webrtc学习--webrtc桌面采集
推荐一个零声学院免费教程,个人觉得老师讲得不错,分享给大家fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,在音视频中,主要包含音视频的采集、编码、传输、解码和渲染。这些,在webrtc中都有涉及。下面借鉴webrtc中的桌面采集来进行学习。.........
·
前言
在音视频中,主要包含音视频的采集、编码、传输、解码和渲染。这些,在webrtc中都有涉及。下面借鉴webrtc中的桌面采集来进行学习。
准备
- 需要下载webrtc源码
- m98 版本webrtc代码 https://pan.baidu.com/s/11_4_sAX9GibQHdvuIOTtNQ 提取码: vyfk
webrtc采集
webrtc 采集主要参考《PeerConnectionClient Demo 视频源为window抓屏》
webrtc实现采集接口很简单
下面通过api简单的说明下webrtc采集部分:
屏幕采集
- webrtc::DesktopCapturer::CreateScreenCapturer 创建一个屏幕采集类
此方法为静态方法,创建一个屏幕采集
// static
std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateScreenCapturer(
const DesktopCaptureOptions& options) {
#if defined(RTC_ENABLE_WIN_WGC)
if (options.allow_wgc_capturer() && IsWgcSupported(CaptureType::kScreen)) {
return WgcCapturerWin::CreateRawScreenCapturer(options);
}
#endif // defined(RTC_ENABLE_WIN_WGC)
std::unique_ptr<DesktopCapturer> capturer = CreateRawScreenCapturer(options);
if (capturer && options.detect_updated_region()) {
capturer.reset(new DesktopCapturerDifferWrapper(std::move(capturer)));
}
return capturer;
}
窗口采集
- webrtc::DesktopCapturer::CreateWindowCapturer 创建一个窗口采集类
和上面一样,此方法为静态方法,创建一个窗口采集
// static
std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateWindowCapturer(
const DesktopCaptureOptions& options) {
#if defined(RTC_ENABLE_WIN_WGC)
if (options.allow_wgc_capturer() && IsWgcSupported(CaptureType::kWindow)) {
return WgcCapturerWin::CreateRawWindowCapturer(options);
}
#endif // defined(RTC_ENABLE_WIN_WGC)
#if defined(WEBRTC_WIN)
if (options.allow_cropping_window_capturer()) {
return CroppingWindowCapturer::CreateCapturer(options);
}
#endif // defined(WEBRTC_WIN)
std::unique_ptr<DesktopCapturer> capturer = CreateRawWindowCapturer(options);
if (capturer && options.detect_updated_region()) {
capturer.reset(new DesktopCapturerDifferWrapper(std::move(capturer)));
}
return capturer;
}
webrtc采集数据回调类
- webrtc创建好对应的屏幕(窗口)采集类,只需要设置对应的回调类,即可将采集到的数据进行回调出来。
// Interface that must be implemented by the DesktopCapturer consumers.
class Callback {
public:
// Called after a frame has been captured. `frame` is not nullptr if and
// only if `result` is SUCCESS.
virtual void OnCaptureResult(Result result,
std::unique_ptr<DesktopFrame> frame) = 0;
protected:
virtual ~Callback() {}
};
- Callback 回调类,通过webrtc::DesktopCapturer::CreateScreenCapturer 创建的对象的start方法,设置回调对象。
void DesktopCapturerDifferWrapper::Start(DesktopCapturer::Callback* callback) {
callback_ = callback;
base_capturer_->Start(this);
}
···
webrtc::WindowCapturerTest callback;
capturer_->Start(&callback);
webrtc采集代码
#include <stdio.h>
#include <memory>
#include <string>
#include <utility>
#include <Windows.h>
#include "modules/desktop_capture/desktop_capture_options.h"
#include "modules/desktop_capture/desktop_capturer.h"
#include "modules/desktop_capture/desktop_frame.h"
#include "modules/desktop_capture/desktop_geometry.h"
#include "rtc_base/checks.h"
#include <api/video/i420_buffer.h>
#include <third_party/libyuv/include/libyuv.h>
#include <api/video/video_frame.h>
namespace webrtc {
rtc::scoped_refptr<webrtc::I420Buffer> i420_buffer_;
class WindowCapturerTest: public DesktopCapturer::Callback {
public:
// DesktopCapturer::Callback interface
void OnCaptureResult(DesktopCapturer::Result result,
std::unique_ptr<DesktopFrame> frame) override {
if (result != webrtc::DesktopCapturer::Result::SUCCESS)
return;
int width = frame->size().width();
int height = frame->size().height();
if (!i420_buffer_.get() ||
i420_buffer_->width() * i420_buffer_->height() != width * height) {
i420_buffer_ = webrtc::I420Buffer::Create(width, height);
}
libyuv::ConvertToI420(frame->data(), 0, i420_buffer_->MutableDataY(),
i420_buffer_->StrideY(), i420_buffer_->MutableDataU(),
i420_buffer_->StrideU(), i420_buffer_->MutableDataV(),
i420_buffer_->StrideV(), 0, 0, width, height, width,
height, libyuv::kRotate0, libyuv::FOURCC_ARGB);
webrtc::VideoFrame video_frame(webrtc::VideoFrame(i420_buffer_, 0, 0, webrtc::kVideoRotation_0));
if (NULL == m_pFile)
{
if (m_nCount == 0) {
char szMsg[256];
sprintf(szMsg, ".\\test_%dx%d.yuv", width, height);
printf(szMsg);
printf("\r\n");
m_pFile = fopen(szMsg, "wb");
}
}
rtc::scoped_refptr<webrtc::VideoFrameBuffer> vfb = video_frame.video_frame_buffer();
if (++m_nCount < 100) {
if (m_pFile != NULL) {
fwrite(vfb.get()->GetI420()->DataY(), 1, height * width, m_pFile);
fwrite(vfb.get()->GetI420()->DataU(), 1, height * width / 4, m_pFile);
fwrite(vfb.get()->GetI420()->DataV(), 1, height * width / 4, m_pFile);
//fflush(m_pFile);
}
} else {
if (m_pFile != NULL) {
fflush(m_pFile);
fclose(m_pFile);
m_pFile = NULL;
}
}
i420_buffer_.release();
frame.reset();
//OnFrame(webrtc::VideoFrame(i420_buffer_, 0, 0, webrtc::kVideoRotation_0));
}
~WindowCapturerTest() {
if (m_pFile != NULL) {
fflush(m_pFile);
fclose(m_pFile);
m_pFile = NULL;
}
}
protected:
std::unique_ptr<DesktopCapturer> capturer_;
std::unique_ptr<DesktopFrame> frame_;
int m_nCount = 0;
FILE* m_pFile = NULL;
};
}// namespace webrtc
std::unique_ptr<webrtc::DesktopCapturer> capturer_;
void startCapturer() {
auto options = webrtc::DesktopCaptureOptions::CreateDefault();
options.set_allow_directx_capturer(true);
capturer_ = webrtc::DesktopCapturer::CreateScreenCapturer(options);//屏幕
//capturer_ = webrtc::DesktopCapturer::CreateWindowCapturer(options);
//capturer_ = webrtc::DesktopCapturer::CreateWindowCapturer(webrtc::DesktopCaptureOptions::CreateDefault());//窗口
if (!capturer_.get())
return;
webrtc::WindowCapturerTest callback;
capturer_->Start(&callback);
webrtc::DesktopCapturer::SourceList sources;
capturer_->GetSourceList(&sources);
for (auto it = sources.begin(); it != sources.end(); ++it) {
char szMsg[256];
sprintf(szMsg, "it->id = 0x%x it->title=%s\r\n", it->id, it->title.c_str());
printf(szMsg);
}
capturer_->SelectSource(sources[0].id);
while (1)
{
//开始循环抓图
capturer_->CaptureFrame();
Sleep(40);
}
}
int main()
{
startCapturer();
getchar();
return 0;
}
webrtc 代码
CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.8)
IF(WIN32)
CMAKE_POLICY(SET CMP0020 NEW)
ENDIF(WIN32)
SET(PRJ_NAME libwebrtc)
PROJECT(${PRJ_NAME})
ADD_DEFINITIONS(-D_LIB)
ADD_DEFINITIONS(-DWIN32)
ADD_DEFINITIONS(-DNOMINMAX)
ADD_DEFINITIONS(-DWEBRTC_WIN)
ADD_DEFINITIONS(-DWEBRTC_USE_H264)
ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_FILES)
SET(INCLUDE_PATHS
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/third_party
${CMAKE_CURRENT_SOURCE_DIR}/third_party/libyuv/include
)
INCLUDE_DIRECTORIES(${3DRLIB_INCLUDE_DIR} ${INCLUDE_PATHS})
LINK_DIRECTORIES(${3DRLIB_INCLUDE_DIR})
#FILE(GLOB INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
#FILE(GLOB SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
SET(THIS_SOURCE_FILES ${INCLUDE_FILES} ${SOURCE_FILES} ${SRC_FILES})
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
#FIND_PACKAGE(Qt5 COMPONENTS Core Gui Widgets Network REQUIRED)
#SET(MOC_FILES )
#QT5_WRAP_CPP(THIS_SOURCE_FILES ${MOC_FILES})
# 添加筛选器
SET(API_TASK_QUEUE
api/task_queue/task_queue_base.cc
api/task_queue/task_queue_base.h
)
SET(API_VIDEO
api/video/color_space.cc
api/video/color_space.h
api/video/i420_buffer.cc
api/video/i420_buffer.h
#api/video/i422_buffer.cc
#api/video/i444_buffer.cc
#api/video/nv12_buffer.cc
#api/video/nv12_buffer.h
api/video/video_frame.cc
api/video/video_frame.h
api/video/video_frame_buffer.cc
api/video/video_frame_buffer.h
api/video/video_source_interface.cc
api/video/video_source_interface.h
)
SET(MEDIA_BASE
media/base/adapted_video_track_source.cc
media/base/video_adapter.cc
media/base/video_broadcaster.cc
media/base/video_common.cc
media/base/video_source_base.cc
)
SET(MODULES_DESKTOP_CAPTURE
modules/desktop_capture/blank_detector_desktop_capturer_wrapper.cc
modules/desktop_capture/cropped_desktop_frame.cc
modules/desktop_capture/cropping_window_capturer.cc
modules/desktop_capture/cropping_window_capturer_win.cc
modules/desktop_capture/desktop_and_cursor_composer.cc
modules/desktop_capture/desktop_capture_metrics_helper.cc
modules/desktop_capture/desktop_capturer.cc
modules/desktop_capture/desktop_capturer_differ_wrapper.cc
modules/desktop_capture/desktop_capturer_wrapper.cc
modules/desktop_capture/desktop_capture_options.cc
modules/desktop_capture/desktop_frame.cc
modules/desktop_capture/desktop_frame_rotation.cc
modules/desktop_capture/desktop_frame_win.cc
modules/desktop_capture/desktop_geometry.cc
modules/desktop_capture/desktop_region.cc
modules/desktop_capture/differ_block.cc
modules/desktop_capture/differ_vector_sse2.cc
modules/desktop_capture/fallback_desktop_capturer_wrapper.cc
modules/desktop_capture/full_screen_application_handler.cc
modules/desktop_capture/full_screen_window_detector.cc
modules/desktop_capture/mouse_cursor.cc
modules/desktop_capture/mouse_cursor_monitor_win.cc
modules/desktop_capture/resolution_tracker.cc
modules/desktop_capture/rgba_color.cc
modules/desktop_capture/screen_capturer_win.cc
modules/desktop_capture/screen_drawer.cc
modules/desktop_capture/screen_drawer_win.cc
modules/desktop_capture/shared_desktop_frame.cc
modules/desktop_capture/shared_memory.cc
modules/desktop_capture/window_capturer_win.cc
modules/desktop_capture/window_finder.cc
modules/desktop_capture/window_finder_win.cc
)
SET(MODULES_DESKTOP_CAPTURE_WIN
modules/desktop_capture/win/cursor.cc
modules/desktop_capture/win/d3d_device.cc
modules/desktop_capture/win/desktop.cc
modules/desktop_capture/win/display_configuration_monitor.cc
modules/desktop_capture/win/dxgi_adapter_duplicator.cc
modules/desktop_capture/win/dxgi_context.cc
modules/desktop_capture/win/dxgi_duplicator_controller.cc
modules/desktop_capture/win/dxgi_frame.cc
modules/desktop_capture/win/dxgi_output_duplicator.cc
modules/desktop_capture/win/dxgi_texture.cc
modules/desktop_capture/win/dxgi_texture_mapping.cc
modules/desktop_capture/win/dxgi_texture_staging.cc
modules/desktop_capture/win/full_screen_win_application_handler.cc
modules/desktop_capture/win/scoped_thread_desktop.cc
modules/desktop_capture/win/screen_capturer_win_directx.cc
modules/desktop_capture/win/screen_capturer_win_gdi.cc
modules/desktop_capture/win/screen_capturer_win_magnifier.cc
modules/desktop_capture/win/screen_capture_utils.cc
modules/desktop_capture/win/selected_window_context.cc
modules/desktop_capture/win/window_capture_utils.cc
modules/desktop_capture/win/desktop_capture_utils.cc
modules/desktop_capture/win/window_capturer_win_gdi.cc
)
SET(RTC_BASE
rtc_base/async_resolver_interface.cc
rtc_base/async_socket.cc
rtc_base/checks.cc
rtc_base/critical_section.cc
rtc_base/event.cc
rtc_base/event_tracer.cc
rtc_base/ip_address.cc
rtc_base/location.cc
rtc_base/logging.cc
rtc_base/message_handler.cc
rtc_base/net_helpers.cc
rtc_base/null_socket_server.cc
rtc_base/physical_socket_server.cc
rtc_base/platform_thread.cc
rtc_base/platform_thread_types.cc
rtc_base/signal_thread.cc
rtc_base/socket_address.cc
rtc_base/string_encode.cc
rtc_base/string_to_number.cc
rtc_base/string_utils.cc
rtc_base/thread.cc
rtc_base/time_utils.cc
rtc_base/system_time.cc
rtc_base/win32.cc
rtc_base/win/windows_version.cc
)
SET(RTC_BASE_NUMERICS
rtc_base/numerics/histogram_percentile_counter.cc
)
SET(RTC_BASE_MEMORY
rtc_base/memory/aligned_malloc.cc
)
SET(RTC_BASE_STRINGS
rtc_base/strings/string_builder.cc
)
SET(RTC_BASE_SYNCHRONIZATION
rtc_base/synchronization/sequence_checker.cc
rtc_base/synchronization/sequence_checker_internal.cc
rtc_base/synchronization/yield_policy.cc
)
SET(SYSTEM_WRAPPERS
system_wrappers/source/cpu_features.cc
system_wrappers/source/cpu_info.cc
system_wrappers/source/field_trial.cc
system_wrappers/source/metrics.cc
system_wrappers/source/sleep.cc
)
SET(THIRD_PARTY_ABSL
third_party/absl/base/internal/throw_delegate.cc
third_party/absl/strings/ascii.cc
third_party/absl/strings/internal/memutil.cc
third_party/absl/strings/string_view.cc
)
SET(THIRD_PARTY_LIBYUV
third_party/libyuv/source/compare.cc
third_party/libyuv/source/compare_common.cc
third_party/libyuv/source/compare_gcc.cc
third_party/libyuv/source/compare_neon.cc
third_party/libyuv/source/compare_neon64.cc
third_party/libyuv/source/compare_win.cc
third_party/libyuv/source/convert.cc
third_party/libyuv/source/convert_argb.cc
third_party/libyuv/source/convert_from.cc
third_party/libyuv/source/convert_from_argb.cc
third_party/libyuv/source/convert_jpeg.cc
third_party/libyuv/source/convert_to_argb.cc
third_party/libyuv/source/convert_to_i420.cc
third_party/libyuv/source/cpu_id.cc
third_party/libyuv/source/mjpeg_decoder.cc
third_party/libyuv/source/mjpeg_validate.cc
third_party/libyuv/source/planar_functions.cc
third_party/libyuv/source/rotate.cc
third_party/libyuv/source/rotate_argb.cc
third_party/libyuv/source/rotate_mips.cc
third_party/libyuv/source/rotate_neon.cc
third_party/libyuv/source/rotate_neon64.cc
third_party/libyuv/source/row_any.cc
third_party/libyuv/source/row_common.cc
third_party/libyuv/source/row_gcc.cc
third_party/libyuv/source/row_mips.cc
third_party/libyuv/source/row_neon.cc
third_party/libyuv/source/row_neon64.cc
third_party/libyuv/source/row_win.cc
third_party/libyuv/source/scale.cc
third_party/libyuv/source/scale_any.cc
third_party/libyuv/source/scale_argb.cc
third_party/libyuv/source/scale_common.cc
third_party/libyuv/source/scale_gcc.cc
third_party/libyuv/source/scale_mips.cc
third_party/libyuv/source/scale_neon.cc
third_party/libyuv/source/scale_neon64.cc
third_party/libyuv/source/scale_win.cc
third_party/libyuv/source/video_common.cc
)
SOURCE_GROUP(api/task/queue FILES ${API_TASK_QUEUE})
SOURCE_GROUP(api/video FILES ${API_VIDEO})
SOURCE_GROUP(media/base FILES ${MEDIA_BASE})
SOURCE_GROUP(modules/desktop/capture FILES ${MODULES_DESKTOP_CAPTURE})
SOURCE_GROUP(modules/desktop/capture/win FILES ${MODULES_DESKTOP_CAPTURE_WIN})
SOURCE_GROUP(rtc_base FILES ${RTC_BASE})
SOURCE_GROUP(rtc_base/memory FILES ${RTC_BASE_MEMORY})
SOURCE_GROUP(rtc_base/strings ${RTC_BASE_STRINGS})
SOURCE_GROUP(rtc_base/synchronization FILES ${RTC_BASE_SYNCHRONIZATION})
SOURCE_GROUP(rtc_base/numerics FILES ${RTC_BASE_NUMERICS})
SOURCE_GROUP(system_wrappers FILES ${SYSTEM_WRAPPERS})
SOURCE_GROUP(third_party/absl FILES ${THIRD_PARTY_ABSL})
SOURCE_GROUP(third_party/libyuv FILES ${THIRD_PARTY_LIBYUV})
FILE(GLOB CPP_FILES
${API_TASK_QUEUE}
${API_VIDEO}
${MEDIA_BASE}
${MODULES_DESKTOP_CAPTURE}
${MODULES_DESKTOP_CAPTURE_WIN}
${RTC_BASE}
${RTC_BASE_MEMORY}
${RTC_BASE_NUMERICS}
${RTC_BASE_STRINGS}
${RTC_BASE_SYNCHRONIZATION}
${SYSTEM_WRAPPERS}
${THIRD_PARTY_ABSL}
${THIRD_PARTY_LIBYUV}
)
ADD_LIBRARY(${PRJ_NAME} STATIC ${CPP_FILES})
#TARGET_LINK_LIBRARIES(${PRJ_NAME} Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Network)
IF(WIN32)
SET_TARGET_PROPERTIES(${PRJ_NAME} PROPERTIES DEBUG_POSTFIX _d)
SET_TARGET_PROPERTIES(${PRJ_NAME} PROPERTIES LINK_FLAGS "/OPT:NOREF /OPT:NOICF")
ENDIF(WIN32)
webrtc代码说明
上面是抽取webrtc中的代码,通过webrtc来采集屏幕(窗口),API使用比较简单。通过cmake管理,方便进行
跨平台。同时,前期把这些代码抽取出来,方便后面进行集成。应用到其他工程中。同时,学习之余记录下来。
参考链接
windows下提取webrtc的录制窗口demo程序
PeerConnectionClient Demo 视频源为window抓屏
更多推荐
已为社区贡献7条内容
所有评论(0)