Преглед изворни кода

重构整个视频采集流程

zhuizhu пре 9 месеци
родитељ
комит
a00818325c

+ 202 - 10
AvRecorder/capturer/video/DxgiCapturer.cpp

@@ -1,20 +1,213 @@
 #include "DxgiCapturer.h"
+
+#include "basic/basic.h"
+#include "basic/frame.h"
+#include "d3d/buffer_filler.h"
+#include "d3d/convert.h"
+#include "d3d/gen_frame.h"
+#include "../finder.h"
+
 #include <cassert>
+#include <d3d11.h>
+#include <dxgi1_2.h>
 
 namespace avrecorder {
 namespace video {
 
-DxgiCapturer::DxgiCapturer() : d(nullptr) {}
-DxgiCapturer::~DxgiCapturer() { close(); }
+// --- DxgiCapturerPrivate 实现 ---
+bool DxgiCapturerPrivate::Open(int left, int top, int width, int height) {
+    Close();
+    HRESULT hr = S_OK;
+    _isAttached = false;
+    if (_bInit) return false;
+    // Driver types supported
+    D3D_DRIVER_TYPE DriverTypes[] = {
+        D3D_DRIVER_TYPE_HARDWARE,
+        D3D_DRIVER_TYPE_WARP,
+        D3D_DRIVER_TYPE_REFERENCE,
+    };
+    UINT NumDriverTypes = ARRAYSIZE(DriverTypes);
+    // Feature levels supported
+    D3D_FEATURE_LEVEL FeatureLevels[] = {
+        D3D_FEATURE_LEVEL_11_0,
+        D3D_FEATURE_LEVEL_10_1,
+        D3D_FEATURE_LEVEL_10_0,
+        D3D_FEATURE_LEVEL_9_1};
+    UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels);
+    D3D_FEATURE_LEVEL FeatureLevel;
+    // Create D3D device
+    for (UINT DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) {
+        hr = D3D11CreateDevice(nullptr,
+                               DriverTypes[DriverTypeIndex],
+                               nullptr,
+                               0,
+                               FeatureLevels,
+                               NumFeatureLevels,
+                               D3D11_SDK_VERSION,
+                               &_hDevice,
+                               &FeatureLevel,
+                               &_hContext);
+        if (SUCCEEDED(hr)) {
+            break;
+        }
+    }
+    __CheckBool(SUCCEEDED(hr));
+    // Get DXGI device
+    IDXGIDevice* hDxgiDevice = nullptr;
+    __CheckBool(SUCCEEDED(_hDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&hDxgiDevice))));
+    // Get DXGI adapter
+    IDXGIAdapter* hDxgiAdapter = nullptr;
+    hr = hDxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&hDxgiAdapter));
+    Free(hDxgiDevice, [=] { hDxgiDevice->Release(); });
+    __CheckBool(SUCCEEDED(hr));
+    // Get output
+    IDXGIOutput* hDxgiOutput = nullptr;
+    DXGI_OUTPUT_DESC dxgiOutDesc;
+    ZeroMemory(&dxgiOutDesc, sizeof(dxgiOutDesc));
+    for (int idx = 0; SUCCEEDED(hr = hDxgiAdapter->EnumOutputs(idx, &hDxgiOutput)); ++idx) {
+        hDxgiOutput->GetDesc(&dxgiOutDesc);
+        if (dxgiOutDesc.DesktopCoordinates.left == left && dxgiOutDesc.DesktopCoordinates.top == top) {
+            break;
+        }
+    }
+    Free(hDxgiAdapter, [=] { hDxgiAdapter->Release(); });
+    __CheckBool(SUCCEEDED(hr));
+    // QI for Output 1
+    IDXGIOutput1* hDxgiOutput1 = nullptr;
+    hr = hDxgiOutput->QueryInterface(__uuidof(hDxgiOutput1), reinterpret_cast<void**>(&hDxgiOutput1));
+    Free(hDxgiOutput, [=] { hDxgiOutput->Release(); });
+    __CheckBool(SUCCEEDED(hr));
+    // Create desktop duplication
+    hr = hDxgiOutput1->DuplicateOutput(_hDevice, &_hDeskDupl);
+    Free(hDxgiOutput1, [=] { hDxgiOutput1->Release(); });
+    __CheckBool(SUCCEEDED(hr));
+    // Set ColorSpace
+    D3D11_VIDEO_PROCESSOR_COLOR_SPACE inputColorSpace;
+    inputColorSpace.Usage = 1;
+    inputColorSpace.RGB_Range = 0;
+    inputColorSpace.YCbCr_Matrix = 1;
+    inputColorSpace.YCbCr_xvYCC = 0;
+    inputColorSpace.Nominal_Range = D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_0_255;
+    D3D11_VIDEO_PROCESSOR_COLOR_SPACE outputColorSpace;
+    outputColorSpace.Usage = 0;
+    outputColorSpace.RGB_Range = 0;
+    outputColorSpace.YCbCr_Matrix = 1;
+    outputColorSpace.YCbCr_xvYCC = 0;
+    outputColorSpace.Nominal_Range = D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_16_235;
+    _rgbToNv12.Open(_hDevice, _hContext, inputColorSpace, outputColorSpace);
+    _nv12Frame = Frame<MediaType::VIDEO>::Alloc(AV_PIX_FMT_NV12, width, height);
+    _xrgbFrame = Frame<MediaType::VIDEO>::Alloc(AV_PIX_FMT_BGR0, width, height);
+    __CheckBool(_nv12Frame);
+    __CheckBool(_xrgbFrame);
+    _bInit = true;
+    return true;
+}
+
+void DxgiCapturerPrivate::Close() {
+    if (!_bInit) return;
+    _bInit = false;
+    _nv12Buffers.Clear();
+    _xrgbBuffers.Clear();
+    _rgbToNv12.Close();
+    Free(_nv12Frame, [this] { av_frame_free(&_nv12Frame); });
+    Free(_xrgbFrame, [this] { av_frame_free(&_xrgbFrame); });
+    Free(_hDeskDupl, [this] { _hDeskDupl->Release(); });
+    Free(_hDevice, [this] { _hDevice->Release(); });
+    Free(_hContext, [this] { _hContext->Release(); });
+}
+
+AVFrame* DxgiCapturerPrivate::GetFrame() {
+    if (!_bInit) return nullptr;
+    _isCaptureSuccess = false;
+    IDXGIResource* hDesktopResource = nullptr;
+    DXGI_OUTDUPL_FRAME_INFO FrameInfo;
+    HRESULT hr = _hDeskDupl->AcquireNextFrame(0, &FrameInfo, &hDesktopResource);
+    if (FAILED(hr)) {
+        if (hr == DXGI_ERROR_WAIT_TIMEOUT) return nullptr;
+        return nullptr;
+    }
+    // query next frame staging buffer
+    ID3D11Texture2D* srcImage = nullptr;
+    hr = hDesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&srcImage));
+    Free(hDesktopResource, [=] { hDesktopResource->Release(); });
+    __CheckNullptr(SUCCEEDED(hr));
+    srcImage->GetDesc(&_desc);
+    // create a new staging buffer for fill frame image
+    auto desc = _desc;
+    desc.ArraySize = 1;
+    desc.BindFlags = D3D11_BIND_FLAG::D3D11_BIND_RENDER_TARGET;
+    desc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
+    desc.SampleDesc.Count = 1;
+    desc.SampleDesc.Quality = 0;
+    desc.MipLevels = 1;
+    desc.CPUAccessFlags = 0;
+    desc.Usage = D3D11_USAGE_DEFAULT;
+    hr = _hDevice->CreateTexture2D(&desc, nullptr, &_gdiImage);
+    if (FAILED(hr)) {
+        __DebugPrint("Create _gdiImage failed");
+        Free(srcImage, [=] { srcImage->Release(); });
+        Free(_hDeskDupl, [this] { _hDeskDupl->ReleaseFrame(); });
+        return nullptr;
+    }
+    // copy next staging buffer to new staging buffer
+    _hContext->CopyResource(_gdiImage, srcImage);
+    Free(srcImage, [=] { srcImage->Release(); });
+    _hDeskDupl->ReleaseFrame();
+    // create staging buffer for map bits
+    _hStagingSurf = nullptr;
+    hr = _gdiImage->QueryInterface(__uuidof(IDXGISurface), (void**) (&_hStagingSurf));
+    if (FAILED(hr)) {
+        __DebugPrint("_gdiImage->QueryInterface failed");
+        Free(_gdiImage, [this] { _gdiImage->Release(); });
+        return nullptr;
+    }
+    _isCaptureSuccess = true;
+    HDC hdc = nullptr;
+    _hStagingSurf->GetDC(FALSE, &hdc);
+    // 释放 DC 并转换为 AVFrame
+    if (_isCaptureSuccess) {
+        _isCaptureSuccess = false;
+        _hStagingSurf->ReleaseDC(nullptr);
+        // 创建一个临时的纹理
+        ID3D11Texture2D* tmpImage = nullptr;
+        _desc.MiscFlags = 2050;
+        __CheckNullptr(SUCCEEDED(_hDevice->CreateTexture2D(&_desc, nullptr, &tmpImage)));
+        _hContext->CopyResource(tmpImage, _gdiImage);
+        // 首先尝试创建 NV12 纹理
+        AVFrame* frame = nullptr;
+        auto tmpFormat = _desc.Format;
+        _desc.Format = DXGI_FORMAT_NV12;
+        if (GenNv12Frame(_hDevice, _hContext, _desc, tmpImage, _nv12Buffers, _nv12Frame, _rgbToNv12)) {
+            frame = _nv12Frame;
+        } else {
+            _desc.Format = tmpFormat;
+            GenRgbFrame(_hDevice, _hContext, _desc, _gdiImage, _xrgbBuffers, _xrgbFrame);
+            frame = _xrgbFrame;
+        }
+        Free(_hStagingSurf, [this] { _hStagingSurf->Release(); });
+        Free(tmpImage, [&tmpImage] { tmpImage->Release(); });
+        Free(_gdiImage, [this] { _gdiImage->Release(); });
+        return frame;
+    }
+    return nullptr;
+}
+
+// --- DxgiCapturer 实现 ---
+DxgiCapturer::DxgiCapturer() : d(new DxgiCapturerPrivate) {}
+DxgiCapturer::~DxgiCapturer() { close(); delete d; }
 
 bool DxgiCapturer::open(const CaptureTarget& target, int width, int height) {
 #ifdef PLATFORM_WINDOWS
     close();
     if (target.type != CaptureTargetType::Monitor) return false;
-    // 这里只做简单示例,实际应根据 monitorIdx 获取坐标
-    m_left = 0; m_top = 0; m_width = width; m_height = height;
-    // TODO: 初始化 d,创建 D3D 设备等
-    return true;
+    auto monitors = MonitorFinder::GetList();
+    if (target.monitorIdx < 0 || target.monitorIdx >= (int)monitors.size()) return false;
+    auto& monitorInfo = monitors[target.monitorIdx];
+    m_left = monitorInfo.rect.left;
+    m_top = monitorInfo.rect.top;
+    m_width = monitorInfo.rect.right - monitorInfo.rect.left;
+    m_height = monitorInfo.rect.bottom - monitorInfo.rect.top;
+    return d->Open(m_left, m_top, m_width, m_height);
 #else
     return false;
 #endif
@@ -22,18 +215,17 @@ bool DxgiCapturer::open(const CaptureTarget& target, int width, int height) {
 
 void DxgiCapturer::close() {
 #ifdef PLATFORM_WINDOWS
-    // TODO: 释放 d
+    d->Close();
 #endif
 }
 
 AVFrame* DxgiCapturer::getFrame() {
 #ifdef PLATFORM_WINDOWS
-    // TODO: 获取帧
-    return nullptr;
+    return d->GetFrame();
 #else
     return nullptr;
 #endif
 }
 
 } // namespace video
-} // namespace avrecorder 
+} // namespace avrecorder 

+ 28 - 2
AvRecorder/capturer/video/DxgiCapturer.h

@@ -2,12 +2,38 @@
 #define DXGICAPTURER_H
 
 #include "IVideoCapturer.h"
+
+#include "d3d/buffer_filler.h"
+#include "d3d/convert.h"
 #include <d3d11.h>
 #include <dxgi1_2.h>
 
 namespace avrecorder {
 namespace video {
 
+class DxgiCapturerPrivate {
+public:
+    DxgiCapturerPrivate() = default;
+    ~DxgiCapturerPrivate() = default;
+    bool Open(int left, int top, int width, int height);
+    void Close();
+    AVFrame* GetFrame();
+    bool _bInit = false;
+    bool _isCaptureSuccess = false;
+    ID3D11Device* _hDevice = nullptr;
+    ID3D11DeviceContext* _hContext = nullptr;
+    IDXGIOutputDuplication* _hDeskDupl = nullptr;
+    IDXGISurface1* _hStagingSurf = nullptr;
+    ID3D11Texture2D* _gdiImage = nullptr;
+    D3D11_TEXTURE2D_DESC _desc{};
+    bool _isAttached = false;
+    AVFrame* _xrgbFrame = nullptr;
+    AVFrame* _nv12Frame = nullptr;
+    BufferFiller _xrgbBuffers;
+    BufferFiller _nv12Buffers;
+    D3dConverter _rgbToNv12;
+};
+
 class DxgiCapturer : public IVideoCapturer {
 public:
     DxgiCapturer();
@@ -17,7 +43,7 @@ public:
     AVFrame* getFrame() override;
     void setDrawCursor(bool enable) override { m_drawCursor = enable; }
 private:
-    class DxgiCapturerPrivate* d;
+    DxgiCapturerPrivate* d;
     bool m_drawCursor = true;
     int m_left = 0, m_top = 0, m_width = 0, m_height = 0;
 };
@@ -25,4 +51,4 @@ private:
 } // namespace video
 } // namespace avrecorder
 
-#endif // DXGICAPTURER_H 
+#endif // DXGICAPTURER_H

+ 62 - 7
AvRecorder/capturer/video/WgcCapturer.cpp

@@ -1,20 +1,75 @@
 #include "WgcCapturer.h"
-
+#include "qdebug.h"
+#include "qwidget.h"
+#ifdef _WIN32
+#include "wgc/winrt.h"
+#include <capturer/finder.h>
+#include <winrt/base.h>
+#endif
+namespace {
+QWidget* g_widget = nullptr;
+winrt::Windows::System::DispatcherQueueController g_controller{nullptr};
+winrt::Windows::UI::Composition::Compositor g_compositor{nullptr};
+winrt::Windows::UI::Composition::Desktop::DesktopWindowTarget g_target{nullptr};
+winrt::Windows::UI::Composition::ContainerVisual g_root{nullptr};
+} // namespace
 namespace avrecorder {
 namespace video {
-
-WgcCapturer::WgcCapturer() { _app = new App; }
+WgcCapturer::WgcCapturer()
+    : _app(nullptr)
+{
+    // _app = new App;
+}
 WgcCapturer::~WgcCapturer() { close(); if (_app) { delete _app; _app = nullptr; } }
 
+#ifdef _WIN32
+void InitWinRTCapture()
+{
+    // 初始化 COM/WinRT
+    winrt::init_apartment(winrt::apartment_type::single_threaded);
+    // 初始化 DispatcherQueue
+    // 创建调度队列
+    g_controller = CreateDispatcherQueueController();
+
+    // 初始化合成器
+    g_compositor = winrt::Windows::UI::Composition::Compositor();
+    g_widget = new QWidget;
+
+    g_target = CreateDesktopWindowTarget(g_compositor, (HWND) g_widget->winId());
+    g_root = g_compositor.CreateContainerVisual();
+    g_root.RelativeSizeAdjustment({1.0f, 1.0f});
+    g_target.Root(g_root);
+}
+#endif
+
 bool WgcCapturer::open(const CaptureTarget& target, int width, int height) {
 #ifdef PLATFORM_WINDOWS
     close();
-    if (!_app) _app = new App;
+    if (!_app) {
+        _app = new App;
+        _app->Initialize(g_root);
+    }
     if (target.type == CaptureTargetType::Window) {
         return _app->StartCaptureWindow(target.hwnd, width, height);
     } else if (target.type == CaptureTargetType::Monitor) {
-        // 这里只做简单示例,实际应根据 monitorIdx 获取 HMONITOR
-        return _app->StartCaptureMonitor(nullptr, width, height);
+        auto monitors = MonitorFinder::GetList();
+        if (target.monitorIdx < 0 || target.monitorIdx >= (int)monitors.size()) return false;
+        auto monitorInfo = MonitorFinder::GetList()[target.monitorIdx];
+        if (!monitorInfo.monitor) {
+            qDebug() << "monitorInfo.monitor is nullptr!";
+            return false;
+        }
+        if (width <= 0 || height <= 0) {
+            qDebug() << "Invalid width/height:" << width << height;
+            return false;
+        }
+        try {
+            return _app->StartCaptureMonitor(monitorInfo.monitor, width, height);
+        } catch (const winrt::hresult_error& e) {
+            qDebug() << "WGC StartCaptureMonitor exception:"
+                     << QString::fromStdString(winrt::to_string(e.message()));
+            return false;
+        }
     }
     return false;
 #else
@@ -43,4 +98,4 @@ void WgcCapturer::setDrawCursor(bool enable) {
 }
 
 } // namespace video
-} // namespace avrecorder 
+} // namespace avrecorder

+ 2 - 1
AvRecorder/capturer/video/WgcCapturer.h

@@ -16,6 +16,7 @@ public:
     void close() override;
     AVFrame* getFrame() override;
     void setDrawCursor(bool enable) override;
+
 private:
     App* _app = nullptr;
     bool _isAppInit = false;
@@ -24,4 +25,4 @@ private:
 } // namespace video
 } // namespace avrecorder
 
-#endif // WGCCAPTURER_H 
+#endif // WGCCAPTURER_H 

+ 0 - 276
AvRecorder/capturer/video/dxgi_capturer.cpp

@@ -1,276 +0,0 @@
-#include "dxgi_capturer.h"
-#include <windows.h>
-
-#include "basic/basic.h"
-#include "basic/frame.h"
-#include "d3d/buffer_filler.h"
-#include "d3d/convert.h"
-#include "d3d/gen_frame.h"
-#include <d3d11.h>
-#include <dxgi1_2.h>
-
-class DxgiCapturerPrivate
-{
-public:
-    DxgiCapturerPrivate() {}
-
-    bool _bInit = false;
-    bool _isCaptureSuccess = false;
-
-    ID3D11Device* _hDevice = nullptr;
-    ID3D11DeviceContext* _hContext = nullptr;
-    IDXGIOutputDuplication* _hDeskDupl = nullptr;
-    IDXGISurface1* _hStagingSurf = nullptr;
-    ID3D11Texture2D* _gdiImage = nullptr;
-    D3D11_TEXTURE2D_DESC _desc;
-    bool _isAttached = false;
-    AVFrame* _xrgbFrame = nullptr;
-    AVFrame* _nv12Frame = nullptr;
-    BufferFiller _xrgbBuffers;
-    BufferFiller _nv12Buffers;
-    D3dConverter _rgbToNv12;
-};
-
-DxgiCapturer::DxgiCapturer()
-    : d(new DxgiCapturerPrivate)
-{
-    ZeroMemory(&d->_desc, sizeof(d->_desc));
-}
-
-DxgiCapturer::~DxgiCapturer()
-{
-    Close();
-    delete d;
-}
-
-bool DxgiCapturer::Open(int left, int top, int width, int height)
-{
-    Close();
-    HRESULT hr = S_OK;
-    d->_isAttached = false;
-
-    if (d->_bInit) {
-        return false;
-    }
-
-    // Driver types supported
-    D3D_DRIVER_TYPE DriverTypes[] = {
-        D3D_DRIVER_TYPE_HARDWARE,
-        D3D_DRIVER_TYPE_WARP,
-        D3D_DRIVER_TYPE_REFERENCE,
-    };
-    UINT NumDriverTypes = ARRAYSIZE(DriverTypes);
-
-    // Feature levels supported
-    D3D_FEATURE_LEVEL FeatureLevels[] = {
-        D3D_FEATURE_LEVEL_11_0,
-        D3D_FEATURE_LEVEL_10_1,
-        D3D_FEATURE_LEVEL_10_0,
-        D3D_FEATURE_LEVEL_9_1};
-    UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels);
-
-    D3D_FEATURE_LEVEL FeatureLevel;
-
-    // Create D3D device
-    for (UINT DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) {
-        hr = D3D11CreateDevice(nullptr,
-                               DriverTypes[DriverTypeIndex],
-                               nullptr,
-                               0,
-                               FeatureLevels,
-                               NumFeatureLevels,
-                               D3D11_SDK_VERSION,
-                               &d->_hDevice,
-                               &FeatureLevel,
-                               &d->_hContext);
-        if (SUCCEEDED(hr)) {
-            break;
-        }
-    }
-    __CheckBool(SUCCEEDED(hr));
-
-    // Get DXGI device
-    IDXGIDevice* hDxgiDevice = nullptr;
-    __CheckBool(SUCCEEDED(d->_hDevice->QueryInterface(__uuidof(IDXGIDevice),
-                                                      reinterpret_cast<void**>(&hDxgiDevice))));
-
-    // Get DXGI adapter
-    IDXGIAdapter* hDxgiAdapter = nullptr;
-    hr = hDxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&hDxgiAdapter));
-    Free(hDxgiDevice, [=] { hDxgiDevice->Release(); });
-    __CheckBool(SUCCEEDED(hr));
-
-    // Get output
-    INT nOutput = 0;
-    IDXGIOutput* hDxgiOutput = nullptr;
-    DXGI_OUTPUT_DESC dxgiOutDesc;
-    ZeroMemory(&dxgiOutDesc, sizeof(dxgiOutDesc));
-
-    for (int idx = 0; SUCCEEDED(hr = hDxgiAdapter->EnumOutputs(idx, &hDxgiOutput)); ++idx) {
-        // get output description struct
-        hDxgiOutput->GetDesc(&dxgiOutDesc);
-        if (dxgiOutDesc.DesktopCoordinates.left == left
-            && dxgiOutDesc.DesktopCoordinates.top == top) { // 寻找显示器
-            break;
-        }
-    }
-    Free(hDxgiAdapter, [=] { hDxgiAdapter->Release(); });
-    __CheckBool(SUCCEEDED(hr));
-
-    // QI for Output 1
-    IDXGIOutput1* hDxgiOutput1 = nullptr;
-    hr = hDxgiOutput->QueryInterface(__uuidof(hDxgiOutput1), reinterpret_cast<void**>(&hDxgiOutput1));
-    Free(hDxgiOutput, [=] { hDxgiOutput->Release(); });
-    __CheckBool(SUCCEEDED(hr));
-
-    // Create desktop duplication
-    hr = hDxgiOutput1->DuplicateOutput(d->_hDevice, &d->_hDeskDupl);
-    Free(hDxgiOutput1, [=] { hDxgiOutput1->Release(); });
-    __CheckBool(SUCCEEDED(hr));
-
-    // Set ColorSpace
-    D3D11_VIDEO_PROCESSOR_COLOR_SPACE inputColorSpace;
-    inputColorSpace.Usage = 1;
-    inputColorSpace.RGB_Range = 0;
-    inputColorSpace.YCbCr_Matrix = 1;
-    inputColorSpace.YCbCr_xvYCC = 0;
-    inputColorSpace.Nominal_Range = D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_0_255;
-
-    D3D11_VIDEO_PROCESSOR_COLOR_SPACE outputColorSpace;
-    outputColorSpace.Usage = 0;
-    outputColorSpace.RGB_Range = 0;
-    outputColorSpace.YCbCr_Matrix = 1;
-    outputColorSpace.YCbCr_xvYCC = 0;
-    outputColorSpace.Nominal_Range = D3D11_VIDEO_PROCESSOR_NOMINAL_RANGE_16_235;
-    d->_rgbToNv12.Open(d->_hDevice, d->_hContext, inputColorSpace, outputColorSpace);
-    d->_nv12Frame = Frame<MediaType::VIDEO>::Alloc(AV_PIX_FMT_NV12, width, height);
-    d->_xrgbFrame = Frame<MediaType::VIDEO>::Alloc(AV_PIX_FMT_BGR0, width, height);
-    __CheckBool(d->_nv12Frame);
-    __CheckBool(d->_xrgbFrame);
-    // 初始化成功
-    d->_bInit = true;
-    return true;
-}
-void DxgiCapturer::Close()
-{
-    if (!d->_bInit) {
-        return;
-    }
-
-    d->_bInit = false;
-    d->_nv12Buffers.Clear();
-    d->_xrgbBuffers.Clear();
-    d->_rgbToNv12.Close();
-    Free(d->_nv12Frame, [this] { av_frame_free(&d->_nv12Frame); });
-    Free(d->_xrgbFrame, [this] { av_frame_free(&d->_xrgbFrame); });
-    Free(d->_hDeskDupl, [this] { d->_hDeskDupl->Release(); });
-    Free(d->_hDevice, [this] { d->_hDevice->Release(); });
-    Free(d->_hContext, [this] { d->_hContext->Release(); });
-}
-
-HDC DxgiCapturer::GetHdc()
-{
-    d->_isCaptureSuccess = false;
-    if (!d->_bInit) {
-        return nullptr;
-    }
-
-    IDXGIResource* hDesktopResource = nullptr;
-    DXGI_OUTDUPL_FRAME_INFO FrameInfo;
-    HRESULT hr = d->_hDeskDupl->AcquireNextFrame(0, &FrameInfo, &hDesktopResource);
-    if (FAILED(hr)) {
-        if (hr == DXGI_ERROR_WAIT_TIMEOUT) { // 这里是因为当桌面没有动画更新时就会有一个错误值,不进行错误打印
-            return nullptr;
-        }
-        return nullptr;
-    }
-
-    // query next frame staging buffer
-    ID3D11Texture2D* srcImage = nullptr;
-    hr = hDesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&srcImage));
-    Free(hDesktopResource, [=] { hDesktopResource->Release(); });
-    __CheckNullptr(SUCCEEDED(hr));
-
-    srcImage->GetDesc(&d->_desc);
-
-    // create a new staging buffer for fill frame image
-    auto desc = d->_desc;
-    desc.ArraySize = 1;
-    desc.BindFlags = D3D11_BIND_FLAG::D3D11_BIND_RENDER_TARGET;
-    desc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
-    desc.SampleDesc.Count = 1;
-    desc.SampleDesc.Quality = 0;
-    desc.MipLevels = 1;
-    desc.CPUAccessFlags = 0;
-    desc.Usage = D3D11_USAGE_DEFAULT;
-    hr = d->_hDevice->CreateTexture2D(&desc, nullptr, &d->_gdiImage);
-    if (FAILED(hr)) {
-        __DebugPrint("Create _gdiImage failed");
-        Free(srcImage, [=] { srcImage->Release(); });
-        Free(d->_hDeskDupl, [this] { d->_hDeskDupl->ReleaseFrame(); });
-        return nullptr;
-    }
-
-    // copy next staging buffer to new staging buffer
-    d->_hContext->CopyResource(d->_gdiImage, srcImage);
-    Free(srcImage, [=] { srcImage->Release(); });
-    d->_hDeskDupl->ReleaseFrame();
-
-    // create staging buffer for map bits
-    d->_hStagingSurf = nullptr;
-    hr = d->_gdiImage->QueryInterface(__uuidof(IDXGISurface), (void**) (&d->_hStagingSurf));
-    if (FAILED(hr)) {
-        __DebugPrint("_gdiImage->QueryInterface failed");
-        Free(d->_gdiImage, [this] { d->_gdiImage->Release(); });
-        return nullptr;
-    }
-
-    d->_isCaptureSuccess = true;
-    HDC hdc = nullptr;
-    // if GetDc is failed, the hdc is nullptr
-    d->_hStagingSurf->GetDC(FALSE, &hdc);
-    return hdc;
-}
-
-AVFrame* DxgiCapturer::GetFrame()
-{
-    if (!d->_isCaptureSuccess) {
-        return nullptr;
-    }
-    d->_isCaptureSuccess = false;
-    d->_hStagingSurf->ReleaseDC(nullptr);
-
-    // 创建一个临时的纹理
-    ID3D11Texture2D* tmpImage = nullptr;
-    d->_desc.MiscFlags = 2050;
-    __CheckNullptr(SUCCEEDED(d->_hDevice->CreateTexture2D(&d->_desc, nullptr, &tmpImage)));
-    d->_hContext->CopyResource(tmpImage, d->_gdiImage);
-
-    // 首先尝试创建 NV12 纹理
-    AVFrame* frame = nullptr;
-    auto tmpFormat = d->_desc.Format;
-    d->_desc.Format = DXGI_FORMAT_NV12;
-    if (GenNv12Frame(d->_hDevice,
-                     d->_hContext,
-                     d->_desc,
-                     tmpImage,
-                     d->_nv12Buffers,
-                     d->_nv12Frame,
-                     d->_rgbToNv12)) {
-        frame = d->_nv12Frame;
-    } else {
-        d->_desc.Format = tmpFormat;
-        GenRgbFrame(d->_hDevice,
-                    d->_hContext,
-                    d->_desc,
-                    d->_gdiImage,
-                    d->_xrgbBuffers,
-                    d->_xrgbFrame);
-        frame = d->_xrgbFrame;
-    }
-    Free(d->_hStagingSurf, [this] { d->_hStagingSurf->Release(); });
-    Free(tmpImage, [&tmpImage] { tmpImage->Release(); });
-    Free(d->_gdiImage, [this] { d->_gdiImage->Release(); });
-
-    return frame;
-}

+ 0 - 27
AvRecorder/capturer/video/dxgi_capturer.h

@@ -1,27 +0,0 @@
-#ifndef __DXGI_CAPTURER_H__
-#define __DXGI_CAPTURER_H__
-
-#include <d3d11.h>
-#include <dxgi1_2.h>
-
-struct AVFrame;
-
-class DxgiCapturer
-{
-public:
-    DxgiCapturer();
-    ~DxgiCapturer();
-
-public:
-    bool Open(int left, int top, int width, int height);
-    void Close();
-
-public:
-    HDC GetHdc();
-    AVFrame* GetFrame();
-
-private:
-    class DxgiCapturerPrivate* d;
-};
-
-#endif

+ 0 - 56
AvRecorder/capturer/video/gdi_capturer.cpp

@@ -1,56 +0,0 @@
-
-#include "gdi_capturer.h"
-#include "basic/basic.h"
-
-bool GdiCapturer::Open(HWND hwnd, int width, int height)
-{
-    Close();
-    m_width = width;
-    m_height = height;
-    _srcHdc = GetWindowDC(hwnd);
-    _dstHdc = CreateCompatibleDC(_srcHdc);
-    _bitmap = CreateCompatibleBitmap(_srcHdc, width, height);
-    SelectObject(_dstHdc, _bitmap);
-
-    _bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
-    _bitmapInfo.bmiHeader.biPlanes = 1;
-    _bitmapInfo.bmiHeader.biBitCount = 24;
-    _bitmapInfo.bmiHeader.biWidth = width;
-    _bitmapInfo.bmiHeader.biHeight = height;
-    _bitmapInfo.bmiHeader.biCompression = BI_RGB;
-    _bitmapInfo.bmiHeader.biSizeImage = width * height;
-
-    // 创建缓存帧
-    _frame = Frame<MediaType::VIDEO>::Alloc(AV_PIX_FMT_BGR24, width, height);
-    return true;
-}
-
-HDC GdiCapturer::GetHdc(int borderWidth, int borderHeight)
-{
-    __CheckNullptr(
-        BitBlt(_dstHdc, 0, 0, m_width, m_height,
-            _srcHdc, borderWidth / 2, borderHeight - borderWidth / 2, SRCCOPY));
-
-    return _dstHdc;
-}
-
-AVFrame* GdiCapturer::GetFrame()
-{
-    auto linesize = _frame->linesize[0];
-    for (int row = 0; row < m_height; ++row) {
-        __CheckNullptr(GetDIBits(_dstHdc, _bitmap, m_height - 1 - row, 1, _frame->data[0] + row * linesize, &_bitmapInfo, DIB_RGB_COLORS));
-    }
-    return _frame;
-}
-
-void GdiCapturer::Close()
-{
-    Free(_frame, [this] { av_frame_free(&_frame); });
-    Free(_dstHdc, [this] { DeleteObject(_dstHdc); });
-    Free(_bitmap, [this] { DeleteObject(_bitmap); });
-}
-
-GdiCapturer::~GdiCapturer()
-{
-    Close();
-}

+ 0 - 25
AvRecorder/capturer/video/gdi_capturer.h

@@ -1,25 +0,0 @@
-#ifndef __GDI_CAPTURER_H__
-#define __GDI_CAPTURER_H__
-
-#include "basic/frame.h"
-#include <Windows.h>
-
-class GdiCapturer {
-public:
-    bool Open(HWND hwnd, int width, int height);
-    HDC GetHdc(int borderWidth, int borderHeight);
-    AVFrame* GetFrame();
-    void Close();
-    ~GdiCapturer();
-
-private:
-    HDC _srcHdc = nullptr;
-    HDC _dstHdc = nullptr;
-    HBITMAP _bitmap = nullptr;
-    BITMAPINFO _bitmapInfo;
-    int m_width = 0;
-    int m_height = 0;
-    AVFrame* _frame = nullptr;
-};
-
-#endif

+ 0 - 3
AvRecorder/capturer/video/ivideocapturer.cpp

@@ -1,3 +0,0 @@
-#include "ivideocapturer.h"
-
-ivideocapturer::ivideocapturer() {}

+ 0 - 9
AvRecorder/capturer/video/video.pri

@@ -5,9 +5,6 @@ HEADERS += \
     $$PWD/VideoCapturerFactory.h \
     $$PWD/WgcCapturer.h \
     $$PWD/ivideocapturer.h \
-    $$PWD/dxgi_capturer.h \
-    $$PWD/gdi_capturer.h \
-    $$PWD/video_capturer.h \
     $$PWD/wgc/App.h \
     $$PWD/wgc/SimpleCapture.h \
     $$PWD/wgc/capture.interop.h \
@@ -16,19 +13,13 @@ HEADERS += \
     $$PWD/wgc/direct3d11.interop.h \
     $$PWD/wgc/pch.h \
     $$PWD/wgc/winrt.h \
-    $$PWD/wgc_capturer.h
 
 SOURCES += \
     $$PWD/DxgiCapturer.cpp \
     $$PWD/GdiCapturer.cpp \
     $$PWD/VideoCapturerFactory.cpp \
     $$PWD/WgcCapturer.cpp \
-    $$PWD/ivideocapturer.cpp \
-    $$PWD/dxgi_capturer.cpp \
-    $$PWD/gdi_capturer.cpp \
-    $$PWD/video_capturer.cpp \
     $$PWD/wgc/App.cpp \
     $$PWD/wgc/SimpleCapture.cpp \
     $$PWD/wgc/pch.cpp \
     $$PWD/wgc/winrt.cpp \
-    $$PWD/wgc_capturer.cpp

+ 0 - 145
AvRecorder/capturer/video/video_capturer.cpp

@@ -1,145 +0,0 @@
-#include "video_capturer.h"
-#include "capturer/finder.h"
-
-bool VideoCapturer::Open(HWND hwnd, Method method)
-{
-    Close();
-    __CheckBool(hwnd);
-    m_srcHwnd = hwnd;
-    __CheckBool(_GetHwndSize(m_srcHwnd));
-    m_usingMethod = method;
-    m_type = WINDOW;
-    switch (method) {
-    case WGC: {
-        m_wgcCapturer = WgcCapturer::New();
-        __CheckBool(m_wgcCapturer->StartCapturerWindow(hwnd, m_width, m_height));
-        break;
-    }
-
-    default: { // GDI
-        m_gdiCapturer = new GdiCapturer;
-        __CheckBool(m_gdiCapturer->Open(hwnd, m_width, m_height));
-        break;
-    }
-    }
-
-    return true;
-}
-
-bool VideoCapturer::Open(int monitorIdx, Method method)
-{
-    Close();
-    auto&& monitorInfo = MonitorFinder::GetList()[monitorIdx];
-    m_rect = monitorInfo.rect;
-    m_borderHeight = 0;
-    m_borderWidth = 0;
-    m_width = m_rect.right - m_rect.left;
-    m_height = m_rect.bottom - m_rect.top;
-    m_usingMethod = method;
-    m_type = MONITOR;
-    switch (method) {
-    case WGC: {
-        auto monitor = monitorInfo.monitor;
-        m_wgcCapturer = WgcCapturer::New();
-        __CheckBool(m_wgcCapturer->StartCapturerMonitor(monitor, m_width, m_height));
-        break;
-    }
-
-    default: { // DXGI
-        m_dxgiCapturer = new DxgiCapturer;
-        __CheckBool(m_dxgiCapturer->Open(m_rect.left, m_rect.top, m_width, m_height));
-        break;
-    }
-    }
-    return true;
-}
-
-AVFrame* VideoCapturer::GetFrame()
-{
-    switch (m_usingMethod) {
-    case WGC: // 该捕获方式自动就将鼠标画好了,我们不需要再自己画鼠标
-        return m_wgcCapturer->GetFrame();
-    case DXGI: {
-        auto hdc = m_dxgiCapturer->GetHdc();
-        if (m_isDrawCursor && hdc) {
-            _DrawCursor(hdc);
-        }
-        return m_dxgiCapturer->GetFrame();
-    }
-    default: // GDI
-        auto hdc = m_gdiCapturer->GetHdc(m_borderWidth, m_borderHeight);
-        if (m_isDrawCursor && hdc) {
-            _DrawCursor(hdc);
-        }
-        return m_gdiCapturer->GetFrame();
-    }
-}
-
-void VideoCapturer::SetDrawCursor(bool isDrawCursor)
-{
-    m_isDrawCursor = isDrawCursor;
-    if (m_usingMethod == WGC) {
-        m_wgcCapturer->SetDrawCursor(m_isDrawCursor);
-    }
-}
-
-void VideoCapturer::Close()
-{
-    Free(m_dxgiCapturer, [this] { m_dxgiCapturer->Close(); delete m_dxgiCapturer; });
-    Free(m_gdiCapturer, [this] { m_gdiCapturer->Close(); delete m_gdiCapturer; });
-    Free(m_wgcCapturer, [this] { m_wgcCapturer->Close(); });
-}
-
-VideoCapturer::~VideoCapturer()
-{
-    Close();
-}
-
-int VideoCapturer::GetWidth() const
-{
-    return m_width;
-}
-int VideoCapturer::GetHeight() const
-{
-    return m_height;
-}
-
-bool VideoCapturer::_GetHwndSize(HWND hwnd)
-{
-    RECT rect;
-    __CheckBool(GetClientRect(hwnd, &rect));
-    m_rect = rect;
-    m_width = (rect.right - rect.left);
-    m_height = (rect.bottom - rect.top);
-    __CheckBool(GetWindowRect(hwnd, &rect));
-    m_borderHeight = rect.bottom - rect.top - m_height;
-    m_borderWidth = rect.right - rect.left - m_width;
-    if (m_borderHeight < 0) {
-        m_borderHeight = 0;
-    }
-    if (m_borderWidth < 0) {
-        m_borderWidth = 0;
-    }
-    return true;
-}
-
-void VideoCapturer::_DrawCursor(HDC hdc)
-{
-    CURSORINFO ci;
-    ci.cbSize = sizeof(CURSORINFO);
-    __CheckNo(GetCursorInfo(&ci));
-    int cursorX = ci.ptScreenPos.x;
-    int cursorY = ci.ptScreenPos.y;
-
-    if (cursorX > m_rect.right || cursorX < m_rect.left
-        || cursorY > m_rect.bottom || cursorY < m_rect.top) {
-        return; // 超出显示范围
-    }
-
-    if (ci.flags == CURSOR_SHOWING) {
-        // 将光标画到屏幕所在位置
-        int x = cursorX - m_rect.left;
-        int y = cursorY - m_rect.top;
-        __CheckNo(DrawIconEx(hdc, x, y, ci.hCursor, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT));
-    }
-}

+ 0 - 46
AvRecorder/capturer/video/video_capturer.h

@@ -1,46 +0,0 @@
-#ifndef __AV_CAPTURER_H__
-#define __AV_CAPTURER_H__
-
-#include "dxgi_capturer.h"
-#include "gdi_capturer.h"
-#include "wgc_capturer.h"
-
-class VideoCapturer {
-public:
-    enum Method {
-        GDI,
-        DXGI,
-        WGC
-    };
-
-    enum Type {
-        WINDOW,
-        MONITOR
-    };
-    ~VideoCapturer();
-    bool Open(HWND hwnd, Method method);
-    bool Open(int monitorIdx, Method method);
-    AVFrame* GetFrame();
-    void SetDrawCursor(bool isDrawCursor);
-    void Close();
-    int GetWidth() const;
-    int GetHeight() const;
-    Method GetMethod() const { return m_usingMethod; }
-
-private:
-    bool _GetHwndSize(HWND hwnd);
-    void _DrawCursor(HDC hdc);
-    Method m_usingMethod = WGC;
-    RECT m_rect;
-    Type m_type = MONITOR;
-    DxgiCapturer* m_dxgiCapturer = nullptr;
-    GdiCapturer* m_gdiCapturer = nullptr;
-    WgcCapturer* m_wgcCapturer = nullptr;
-    int m_width = 0;
-    int m_height = 0;
-    int m_borderHeight = 0;
-    int m_borderWidth = 0;
-    HWND m_srcHwnd = nullptr;
-    bool m_isDrawCursor = true;
-};
-#endif

+ 2 - 0
AvRecorder/capturer/video/wgc/App.cpp

@@ -9,6 +9,8 @@
 
 #include "basic/frame.h"
 
+#include <QDebug>
+
 using namespace winrt;
 using namespace Windows::System;
 using namespace Windows::Foundation;

+ 22 - 2
AvRecorder/capturer/video/wgc/SimpleCapture.cpp

@@ -6,9 +6,13 @@
 #include <wincodec.h>
 
 #include "pch.h"
+
 #include "SimpleCapture.h"
+
 #include "basic/basic.h"
 
+#include <QDebug>
+
 using namespace winrt;
 using namespace Windows;
 using namespace Windows::Foundation;
@@ -24,6 +28,19 @@ using namespace Windows::UI::Composition;
 #undef min
 #undef max
 
+template<typename T>
+auto GetDXGIInterfaceFromObjectEx(winrt::Windows::Foundation::IInspectable const& object)
+{
+    auto access = object.try_as<IDirect3DDxgiInterfaceAccess>();
+    if (!access) {
+        qDebug() << "Failed to cast to IDirect3DDxgiInterfaceAccess!";
+        throw std::runtime_error("Failed to cast to IDirect3DDxgiInterfaceAccess");
+    }
+    winrt::com_ptr<T> result;
+    winrt::check_hresult(access->GetInterface(winrt::guid_of<T>(), result.put_void()));
+    return result;
+}
+
 SimpleCapture::SimpleCapture(
     IDirect3DDevice const& device,
     GraphicsCaptureItem const& item,
@@ -31,9 +48,12 @@ SimpleCapture::SimpleCapture(
 {
     m_item = item;
     m_device = device;
-
+    if (!m_device) {
+        qDebug() << "m_device is nullptr!";
+        // 这里可以 return 或抛异常
+    }
     // Set up
-    auto d3dDevice = GetDXGIInterfaceFromObject<ID3D11Device>(m_device);
+    auto d3dDevice = GetDXGIInterfaceFromObjectEx<ID3D11Device>(m_device);
     d3dDevice->GetImmediateContext(m_d3dContext.put());
     auto size = m_item.Size();
 

+ 0 - 97
AvRecorder/capturer/video/wgc_capturer.cpp

@@ -1,97 +0,0 @@
-#include "wgc_capturer.h"
-
-#include "wgc/winrt.h"
-
-#include <QWidget>
-
-winrt::Windows::System::DispatcherQueue* WgcCapturer::queuePtr = nullptr;
-winrt::Windows::UI::Composition::ContainerVisual* WgcCapturer::rootPtr = nullptr;
-std::list<WgcCapturer*> WgcCapturer::_capturers;
-// QWidget* __widget = nullptr;
-
-void WgcCapturer::Init()
-{
-    if (queuePtr != nullptr) {
-        return;
-    }
-    // Init COM
-    init_apartment(apartment_type::single_threaded);
-    // Create a DispatcherQueue for our thread
-    static auto controller = CreateDispatcherQueueController();
-    // Initialize Composition
-    static auto compositor = Compositor();
-    // __widget = new QWidget;
-    // __widget->hide();
-    // __widget->resize(800, 600);
-    // __widget->show();
-    // static auto target = CreateDesktopWindowTarget(compositor, (HWND)__widget->winId());
-    static auto root = compositor.CreateContainerVisual();
-    root.RelativeSizeAdjustment({1.0f, 1.0f});
-    // target.Root(root);
-
-    // Enqueue our capture work on the dispatcher
-    static auto queue = controller.DispatcherQueue();
-    queuePtr = &queue;
-    rootPtr = &root;
-    // 首先 New 一个 Capturer 备用
-    New();
-}
-
-void WgcCapturer::Uninit()
-{
-    // delete __widget;
-    while (!_capturers.empty()) {
-        delete *_capturers.begin();
-        _capturers.erase(_capturers.begin());
-    }
-}
-
-WgcCapturer* WgcCapturer::New()
-{
-    // 将上一个 new 好的对象返回,并重新预备一个新的
-    if (_capturers.empty()) {
-        _capturers.push_back(new WgcCapturer);
-    }
-    return *(--_capturers.end());
-}
-
-void WgcCapturer::Delete(WgcCapturer* ptr)
-{
-    // auto iter = std::find(_capturers.begin(), _capturers.end(), ptr);
-    // if (iter == _capturers.end()) {
-    //     return;
-    // }
-    // if (*iter != nullptr) {
-    //     delete *iter;
-    // }
-    // _capturers.erase(iter);
-}
-
-WgcCapturer::WgcCapturer()
-{
-    _app = new App;
-    _isAppInit = false;
-    auto success = queuePtr->TryEnqueue([=]() -> void {
-        _app->Initialize(*rootPtr);
-        _isAppInit = true;
-    });
-    WINRT_VERIFY(success);
-}
-
-WgcCapturer::~WgcCapturer()
-{
-    if (_app) {
-        delete _app;
-        _app = nullptr;
-    }
-}
-
-bool WgcCapturer::StartCapturerMonitor(HMONITOR monitor, int width, int height)
-{
-    return _app->StartCaptureMonitor(monitor, width, height);
-}
-
-bool WgcCapturer::StartCapturerWindow(HWND hwnd, int width, int height)
-{
-    return _app->StartCaptureWindow(hwnd, width, height);
-}

+ 0 - 35
AvRecorder/capturer/video/wgc_capturer.h

@@ -1,35 +0,0 @@
-#ifndef __WGC_CAPTURER_H__
-#define __WGC_CAPTURER_H__
-
-#include "wgc/pch.h"
-
-#include "wgc/App.h"
-#include <list>
-
-class WgcCapturer {
-public:
-    bool StartCapturerWindow(HWND hwnd, int width, int height);
-    bool StartCapturerMonitor(HMONITOR monitor, int width, int height);
-    void SetDrawCursor(bool isDrawCursor) { _app->SetDrawCursor(isDrawCursor); }
-    static void Init();
-    static WgcCapturer* New();
-    static void Delete(WgcCapturer* ptr);
-    static void Uninit();
-    void Close()
-    {
-        if (_app != nullptr) {
-            _app->Close();
-        }
-    }
-    AVFrame* GetFrame() { return _app->GetFrame(); }
-
-private:
-    WgcCapturer();
-    ~WgcCapturer();
-    App* _app = nullptr;
-    bool _isAppInit = false;
-    static std::list<WgcCapturer*> _capturers;
-    static winrt::Windows::System::DispatcherQueue* queuePtr;
-    static winrt::Windows::UI::Composition::ContainerVisual* rootPtr;
-};
-#endif

+ 36 - 32
AvRecorder/recorder/video_recorder.cpp

@@ -1,40 +1,47 @@
 #include "video_recorder.h"
+#include "avrecorder/capturer/video/VideoCaptureManager.h"
+#include <Windows.h>
+#include <capturer/finder.h>
+using namespace avrecorder::video;
 
-bool VideoRecorder::Open(HWND srcHwnd,
-                         Encoder<MediaType::VIDEO>::Param& param,
-                         VideoCapturer::Method type)
-{
-    Close();
-    __CheckBool(_capturer.Open(srcHwnd, type));
-    __CheckBool(_Open(param));
-    return true;
+bool VideoRecorder::Open(HWND srcHwnd, Encoder<MediaType::VIDEO>::Param& param, CaptureMethod method) {
+    CaptureTarget target;
+    target.type = CaptureTargetType::Window;
+    target.hwnd = srcHwnd;
+    RECT clientRect;
+    if (!GetClientRect(srcHwnd, &clientRect)) return false;
+    int width = clientRect.right - clientRect.left;
+    int height = clientRect.bottom - clientRect.top;
+    _capturer.open(target, method, width, height);
+    return _Open(param);
 }
 
-bool VideoRecorder::Open(int monitorIdx,
-                         Encoder<MediaType::VIDEO>::Param& param,
-                         VideoCapturer::Method type)
-{
-    Close();
-    __CheckBool(_capturer.Open(monitorIdx, type));
-    __CheckBool(_Open(param));
-    return true;
+bool VideoRecorder::Open(int monitorIdx, Encoder<MediaType::VIDEO>::Param& param, CaptureMethod method) {
+    CaptureTarget target;
+    target.type = CaptureTargetType::Monitor;
+    target.monitorIdx = monitorIdx;
+    auto monitorInfo = MonitorFinder::GetList()[monitorIdx];
+    RECT rect = monitorInfo.rect;
+    int width = rect.right - rect.left;
+    int height = rect.bottom - rect.top;
+    _capturer.open(target, method, width, height);
+    return _Open(param);
 }
 
 bool VideoRecorder::_Open(Encoder<MediaType::VIDEO>::Param& param)
 {
     __CheckBool(_encodeFrame = Frame<MediaType::VIDEO>::Alloc(AV_PIX_FMT_NV12,
-                                                              _capturer.GetWidth(),
-                                                              _capturer.GetHeight()));
+                                                              _capturer.getFrame() ? _capturer.getFrame()->width : param.width,
+                                                              _capturer.getFrame() ? _capturer.getFrame()->height : param.height));
     {
         std::lock_guard<std::mutex> renderLk(_renderMtx);
         __CheckBool(_renderFrame = Frame<MediaType::VIDEO>::Alloc(AV_PIX_FMT_NV12,
-                                                                  _capturer.GetWidth(),
-                                                                  _capturer.GetHeight()));
+                                                                  _capturer.getFrame() ? _capturer.getFrame()->width : param.width,
+                                                                  _capturer.getFrame() ? _capturer.getFrame()->height : param.height));
     }
-
-    // 开始捕获画面
+    // 捕获定时器和帧获取逻辑
     _captureTimer.Start(param.fps, [this] {
-        auto srcFrame = _capturer.GetFrame();
+        auto srcFrame = _capturer.getFrame();
         if (srcFrame != nullptr) {
             std::lock_guard<std::mutex> muxLk(__mtx);
             if (srcFrame->format != _encodeFrame->format) {
@@ -42,14 +49,14 @@ bool VideoRecorder::_Open(Encoder<MediaType::VIDEO>::Param& param)
                 Free(_encodeFrame, [this] { av_frame_free(&_encodeFrame); });
                 __CheckNo(
                     _encodeFrame = Frame<MediaType::VIDEO>::Alloc(AVPixelFormat(srcFrame->format),
-                                                                  _capturer.GetWidth(),
-                                                                  _capturer.GetHeight()));
+                                                                  srcFrame->width,
+                                                                  srcFrame->height));
             }
             av_frame_copy(_encodeFrame, srcFrame);
         }
     });
-    param.width = _capturer.GetWidth();
-    param.height = _capturer.GetHeight();
+    param.width = _capturer.getFrame() ? _capturer.getFrame()->width : param.width;
+    param.height = _capturer.getFrame() ? _capturer.getFrame()->height : param.height;
     _param = param;
     return true;
 }
@@ -62,10 +69,7 @@ AVFrame* VideoRecorder::GetRenderFrame()
     }
     if (_renderFrame->format != _encodeFrame->format) {
         Free(_renderFrame, [this] { av_frame_free(&_renderFrame); });
-        __CheckNullptr(
-            _renderFrame = Frame<MediaType::VIDEO>::Alloc(AVPixelFormat(_encodeFrame->format),
-                                                          _capturer.GetWidth(),
-                                                          _capturer.GetHeight()));
+        _renderFrame = Frame<MediaType::VIDEO>::Alloc(AVPixelFormat(_encodeFrame->format), _encodeFrame->width, _encodeFrame->height);
     }
     av_frame_copy(_renderFrame, _encodeFrame);
     return _renderFrame;
@@ -110,7 +114,7 @@ void VideoRecorder::Close()
 {
     StopRecord();
     _captureTimer.Stop();
-    _capturer.Close();
+    _capturer.close();
     Free(_encodeFrame, [this] { av_frame_free(&_encodeFrame); });
     Free(_renderFrame, [this] { av_frame_free(&_renderFrame); });
 }

+ 7 - 11
AvRecorder/recorder/video_recorder.h

@@ -2,7 +2,9 @@
 #define __VIDEO_RECORDER_H__
 
 #include "basic/timer.h"
-#include "capturer/video/video_capturer.h"
+#include "avrecorder/capturer/video/VideoCaptureManager.h"
+using namespace avrecorder::video;
+
 #include "muxer/av_muxer.h"
 #include <deque>
 // #include <condition_variable>
@@ -10,26 +12,20 @@
 
 class VideoRecorder {
 public:
-    bool Open(HWND srcHwnd, Encoder<MediaType::VIDEO>::Param& param, VideoCapturer::Method type);
-    bool Open(int monitorIdx, Encoder<MediaType::VIDEO>::Param& param, VideoCapturer::Method type);
+    bool Open(HWND srcHwnd, Encoder<MediaType::VIDEO>::Param& param, CaptureMethod method);
+    bool Open(int monitorIdx, Encoder<MediaType::VIDEO>::Param& param, CaptureMethod method);
     bool LoadMuxer(AvMuxer& muxer);
     bool StartRecord();
     void StopRecord();
-    auto GetCapturerType() { return _capturer.GetMethod(); }
     AVFrame* GetRenderFrame();
-    // 停止录制
     void Close();
-    void SetIsDrawCursor(bool isDraw)
-    {
-        _capturer.SetDrawCursor(isDraw);
-    }
+    void SetIsDrawCursor(bool isDraw) { _capturer.setDrawCursor(isDraw); }
     bool IsCaptureOverload() const { return _captureTimer.IsOverload(); }
-    // 返回滑动窗口丢帧率,窗口未满时返回-1
     double GetLossRate();
 
 private:
     bool _Open(Encoder<MediaType::VIDEO>::Param& param);
-    VideoCapturer _capturer;
+    VideoCaptureManager _capturer;
     AvMuxer* _muxer = nullptr;
     bool _isRecord = false;
     int _streamIndex = -1;

+ 18 - 16
AvRecorder/test/recorder/video_recorder.cpp

@@ -1,23 +1,25 @@
 #include "video_recorder.h"
+#include "avrecorder/capturer/video/VideoCaptureManager.h"
+using namespace avrecorder::video;
 
-bool VideoRecorder::Open(HWND srcHwnd,
-                         Encoder<MediaType::VIDEO>::Param& param,
-                         VideoCapturer::Method type)
-{
-    Close();
-    __CheckBool(_capturer.Open(srcHwnd, type));
-    __CheckBool(_Open(param));
-    return true;
+bool VideoRecorder::Open(HWND srcHwnd, Encoder<MediaType::VIDEO>::Param& param, CaptureMethod method) {
+    VideoCaptureManager capturer;
+    CaptureTarget target;
+    target.type = CaptureTargetType::Window;
+    target.hwnd = srcHwnd;
+    int width = param.width;
+    int height = param.height;
+    return capturer.open(target, method, width, height);
 }
 
-bool VideoRecorder::Open(int monitorIdx,
-                         Encoder<MediaType::VIDEO>::Param& param,
-                         VideoCapturer::Method type)
-{
-    Close();
-    __CheckBool(_capturer.Open(monitorIdx, type));
-    __CheckBool(_Open(param));
-    return true;
+bool VideoRecorder::Open(int monitorIdx, Encoder<MediaType::VIDEO>::Param& param, CaptureMethod method) {
+    VideoCaptureManager capturer;
+    CaptureTarget target;
+    target.type = CaptureTargetType::Monitor;
+    target.monitorIdx = monitorIdx;
+    int width = param.width;
+    int height = param.height;
+    return capturer.open(target, method, width, height);
 }
 
 bool VideoRecorder::_Open(Encoder<MediaType::VIDEO>::Param& param)

+ 4 - 3
AvRecorder/test/recorder/video_recorder.h

@@ -2,15 +2,16 @@
 #define __VIDEO_RECORDER_H__
 
 #include "basic/timer.h"
-#include "capturer/video_capturer.h"
+#include "avrecorder/capturer/video/VideoCaptureManager.h"
+using namespace avrecorder::video;
 #include "muxer/av_muxer.h"
 // #include <condition_variable>
 // #include <queue>
 
 class VideoRecorder {
 public:
-    bool Open(HWND srcHwnd, Encoder<MediaType::VIDEO>::Param& param, VideoCapturer::Method type);
-    bool Open(int monitorIdx, Encoder<MediaType::VIDEO>::Param& param, VideoCapturer::Method type);
+    bool Open(HWND srcHwnd, Encoder<MediaType::VIDEO>::Param& param, CaptureMethod method);
+    bool Open(int monitorIdx, Encoder<MediaType::VIDEO>::Param& param, CaptureMethod method);
     bool LoadMuxer(AvMuxer& muxer);
     bool StartRecord();
     void StopRecord();

+ 31 - 12
AvRecorder/test/ui/av_recorder.cpp

@@ -3,6 +3,8 @@
 #include <QDateTime>
 #include <QStatusBar>
 #include <capturer/finder.h>
+#include "avrecorder/capturer/video/VideoCaptureManager.h"
+using namespace avrecorder::video;
 
 AvRecorder::AvRecorder(QWidget* parent)
     : QWidget(parent)
@@ -18,8 +20,6 @@ AvRecorder::AvRecorder(QWidget* parent)
 
     glWidget = new OpenGLVideoWidget(this);
 
-    WgcCapturer::Init();
-
     auto layout = new QVBoxLayout;
     auto hLayout = new QHBoxLayout;
 
@@ -44,7 +44,7 @@ void AvRecorder::_InitConnect()
         _isLocked = true;
         _StopPreview();
         _StopCapture();
-        _StartCapture(VideoCapturer::WGC);
+        _StartCapture(CaptureMethod::WGC);
         _StartPreview();
         _isLocked = false;
         timer->stop();
@@ -99,7 +99,7 @@ void AvRecorder::_InitConnect()
         _isLocked = true;
         _StopPreview();
         _StopCapture();
-        _StartCapture(VideoCapturer::WGC);
+        _StartCapture(CaptureMethod::WGC);
         _StartPreview();
         _isLocked = false;
     });
@@ -113,11 +113,11 @@ void AvRecorder::_InitConnect()
         _StopPreview();
         _StopCapture();
         if (text == "WGC") {
-            _StartCapture(VideoCapturer::WGC);
+            _StartCapture(CaptureMethod::WGC);
         } else if (text == "DXGI") {
-            _StartCapture(VideoCapturer::DXGI);
+            _StartCapture(CaptureMethod::DXGI);
         } else {
-            _StartCapture(VideoCapturer::GDI);
+            _StartCapture(CaptureMethod::GDI);
         }
         _StartPreview();
     });
@@ -127,7 +127,7 @@ void AvRecorder::_InitConnect()
         _isLocked = true;
         _StopPreview();
         _StopCapture();
-        _StartCapture(VideoCapturer::WGC);
+        _StartCapture(CaptureMethod::WGC);
         _StartPreview();
         _isLocked = false;
     });
@@ -168,10 +168,9 @@ AvRecorder::~AvRecorder()
     _StopStream();
     _StopPreview();
     _StopCapture();
-    WgcCapturer::Uninit();
 }
 
-void AvRecorder::_StartCapture(VideoCapturer::Method method)
+void AvRecorder::_StartCapture(CaptureMethod method)
 {
     if (_isLocked) {
         _captureMethodBox->clear();
@@ -191,7 +190,17 @@ void AvRecorder::_StartCapture(VideoCapturer::Method method)
             _captureMethodBox->addItem("DXGI");
         }
 
-        m_videoRecorder.Open(idx, _settingsParam.videoParam, method);
+        VideoCaptureManager capturer;
+        CaptureTarget target;
+        target.type = CaptureTargetType::Monitor;
+        target.monitorIdx = idx;
+        int width = 1920; // 设置宽度
+        int height = 1080; // 设置高度
+        if (capturer.open(target, method, width, height)) {
+            AVFrame* frame = capturer.getFrame();
+            // ...处理 frame ...
+            capturer.close();
+        }
 
     } else {
         if (_captureMethodBox->count() < 2) {
@@ -199,7 +208,17 @@ void AvRecorder::_StartCapture(VideoCapturer::Method method)
         }
         auto hwnd = WindowFinder::GetList()[idx - monitorCnt].hwnd;
 
-        m_videoRecorder.Open(hwnd, _settingsParam.videoParam, method);
+        VideoCaptureManager capturer;
+        CaptureTarget target;
+        target.type = CaptureTargetType::Window;
+        target.hwnd = hwnd;
+        int width = 1920; // 设置宽度
+        int height = 1080; // 设置高度
+        if (capturer.open(target, method, width, height)) {
+            AVFrame* frame = capturer.getFrame();
+            // ...处理 frame ...
+            capturer.close();
+        }
     }
     _DealCapture();
     _isDrawCursorBox->setEnabled(true);

+ 3 - 1
AvRecorder/test/ui/av_recorder.h

@@ -13,6 +13,8 @@
 #include "recorder/video_recorder.h"
 #include "ui/opengl_video_widget.h"
 #include "ui/settings_page.h"
+#include "avrecorder/capturer/video/VideoCaptureManager.h"
+using namespace avrecorder::video;
 
 class AvRecorder : public QWidget
 {
@@ -54,7 +56,7 @@ private:
     bool _isLocked = false;
     void _InitStatusBarUi();
     void _UpdateCaptureList();
-    void _StartCapture(VideoCapturer::Method method);
+    void _StartCapture(CaptureMethod method);
     void _StopCapture();
     void _StartPreview();
     void _DealCapture();

+ 40 - 29
AvRecorder/ui/av_recorder.cpp

@@ -3,6 +3,8 @@
 #include <QDateTime>
 #include <QStatusBar>
 #include <capturer/finder.h>
+#include "avrecorder/capturer/video/VideoCaptureManager.h"
+using namespace avrecorder::video;
 
 AvRecorder::AvRecorder(QWidget* parent)
     : QWidget(parent)
@@ -178,10 +180,11 @@ void AvRecorder::initConnect()
         m_isLocked = true;
         stopPreview();
         stopCapture();
-        startCapture(VideoCapturer::WGC);
+        startCapture(CaptureMethod::WGC);
         startPreview();
         m_isLocked = false;
     });
+    connect(m_captureComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &AvRecorder::onCaptureSourceChanged);
     connect(m_isDrawCursorBox, &QCheckBox::stateChanged, this, [this] {
         m_videoRecorder.SetIsDrawCursor(m_isDrawCursorBox->isChecked());
     });
@@ -192,11 +195,11 @@ void AvRecorder::initConnect()
         stopPreview();
         stopCapture();
         if (text == "WGC") {
-            startCapture(VideoCapturer::WGC);
+            startCapture(CaptureMethod::WGC);
         } else if (text == "DXGI") {
-            startCapture(VideoCapturer::DXGI);
+            startCapture(CaptureMethod::DXGI);
         } else {
-            startCapture(VideoCapturer::GDI);
+            startCapture(CaptureMethod::GDI);
         }
         startPreview();
     });
@@ -206,7 +209,7 @@ void AvRecorder::initConnect()
         m_isLocked = true;
         stopPreview();
         stopCapture();
-        startCapture(VideoCapturer::WGC);
+        startCapture(CaptureMethod::WGC);
         startPreview();
         m_isLocked = false;
     });
@@ -252,7 +255,6 @@ AvRecorder::~AvRecorder()
     stopStream();
     stopPreview();
     stopCapture();
-    WgcCapturer::Uninit();
 }
 
 bool AvRecorder::start()
@@ -262,7 +264,7 @@ bool AvRecorder::start()
         m_isLocked = true;
         stopPreview();
         stopCapture();
-        startCapture(VideoCapturer::WGC);
+        startCapture(CaptureMethod::WGC);
         startPreview();
         m_isLocked = false;
         timer->stop();
@@ -271,34 +273,25 @@ bool AvRecorder::start()
     return true;
 }
 
-void AvRecorder::startCapture(VideoCapturer::Method method)
+void AvRecorder::startCapture(CaptureMethod method)
 {
-    if (m_isLocked) {
-        m_captureMethodBox->clear();
-        m_captureMethodBox->addItem("WGC");
-    }
     int idx = m_captureComboBox->currentIndex();
-    if (idx < 0) {
-        return;
-    }
-    int monitorCnt = (int) MonitorFinder::GetList().size();
+    if (idx < 0) return;
+    int monitorCnt = (int)MonitorFinder::GetList().size();
     QString type = (idx < monitorCnt) ? "monitor" : "window";
     qintptr ptrHwnd = m_captureComboBox->currentData().value<qintptr>();
+
+    bool ok = false;
     if (idx < monitorCnt) { // 捕获屏幕
-        if (m_captureMethodBox->count() < 2) {
-            m_captureMethodBox->addItem("DXGI");
-        }
-        m_videoRecorder.Open(idx, m_settingsParam.videoParam, method);
-    } else {
-        if (m_captureMethodBox->count() < 2) {
-            m_captureMethodBox->addItem("GDI");
-        }
-        if (type == "window") {
-            if (::IsWindow((HWND) ptrHwnd)) {
-                m_videoRecorder.Open((HWND) ptrHwnd, m_settingsParam.videoParam, method);
-            }
-        }
+        ok = m_videoRecorder.Open(idx, m_settingsParam.videoParam, method);
+    } else if (type == "window" && ::IsWindow((HWND)ptrHwnd)) {
+        ok = m_videoRecorder.Open((HWND)ptrHwnd, m_settingsParam.videoParam, method);
     }
+    if (!ok) {
+        // 可选:弹窗或日志提示
+        return;
+    }
+
     dealCapture();
     m_isDrawCursorBox->setEnabled(true);
     m_recordBtn->setEnabled(true);
@@ -453,3 +446,21 @@ void AvRecorder::initStatusBarUi()
     m_statusBar->addWidget(m_captureTimeLabel);
     m_statusBar->addWidget(m_fpsLabel);
 }
+
+void AvRecorder::updateCaptureMethodBox(bool isMonitor) {
+    m_captureMethodBox->clear();
+    m_captureMethodBox->addItem("WGC");
+    if (isMonitor) {
+        m_captureMethodBox->addItem("DXGI");
+    } else {
+        m_captureMethodBox->addItem("GDI");
+    }
+}
+
+// 捕获源切换时调用
+void AvRecorder::onCaptureSourceChanged() {
+    int idx = m_captureComboBox->currentIndex();
+    int monitorCnt = (int)MonitorFinder::GetList().size();
+    bool isMonitor = (idx >= 0 && idx < monitorCnt);
+    updateCaptureMethodBox(isMonitor);
+}

+ 6 - 1
AvRecorder/ui/av_recorder.h

@@ -14,6 +14,8 @@
 #include "recorder/video_recorder.h"
 #include "ui/opengl_video_widget.h"
 #include "ui/settings_page.h"
+#include "avrecorder/capturer/video/VideoCaptureManager.h"
+using namespace avrecorder::video;
 
 class AvRecorder : public QWidget
 {
@@ -35,7 +37,7 @@ private:
     SettingsPage::Param m_settingsParam;
     void initStatusBarUi();
     void updateCaptureList();
-    void startCapture(VideoCapturer::Method method);
+    void startCapture(CaptureMethod method);
     void stopCapture();
     void startPreview();
     void dealCapture();
@@ -78,4 +80,7 @@ private:
     QTime m_recordTime;
     bool m_isLocked = false;
     QStatusBar* m_statusBar = nullptr;
+
+    void updateCaptureMethodBox(bool isMonitor);
+    void onCaptureSourceChanged();
 };

+ 3 - 4
main.cpp

@@ -15,8 +15,6 @@
 #include <QDateTime>
 #include <QMutex>
 
-#include <AvRecorder/capturer/video/wgc_capturer.h>
-
 QFile g_logFile;
 QTextStream* g_logStream = nullptr;
 QMutex g_logMutex;
@@ -49,7 +47,7 @@ void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const Q
     if (type == QtFatalMsg)
         abort();
 }
-
+namespace avrecorder::video { void InitWinRTCapture(); }
 int main(int argc, char* argv[])
 {
     // 打开日志文件(覆盖模式)
@@ -71,7 +69,8 @@ int main(int argc, char* argv[])
     initRoomType();
 
     // 初始化wgc
-    WgcCapturer::Init();
+
+    avrecorder::video::InitWinRTCapture();
 
     /*
 docker run -itd  --name zlmediakit --restart=always