zhuizhu 9 luni în urmă
părinte
comite
26e324b1a0

+ 39 - 0
AvRecorder/capturer/video/DxgiCapturer.cpp

@@ -0,0 +1,39 @@
+#include "DxgiCapturer.h"
+#include <cassert>
+
+namespace avrecorder {
+namespace video {
+
+DxgiCapturer::DxgiCapturer() : d(nullptr) {}
+DxgiCapturer::~DxgiCapturer() { close(); }
+
+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;
+#else
+    return false;
+#endif
+}
+
+void DxgiCapturer::close() {
+#ifdef PLATFORM_WINDOWS
+    // TODO: 释放 d
+#endif
+}
+
+AVFrame* DxgiCapturer::getFrame() {
+#ifdef PLATFORM_WINDOWS
+    // TODO: 获取帧
+    return nullptr;
+#else
+    return nullptr;
+#endif
+}
+
+} // namespace video
+} // namespace avrecorder 

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

@@ -0,0 +1,28 @@
+#ifndef DXGICAPTURER_H
+#define DXGICAPTURER_H
+
+#include "IVideoCapturer.h"
+#include <d3d11.h>
+#include <dxgi1_2.h>
+
+namespace avrecorder {
+namespace video {
+
+class DxgiCapturer : public IVideoCapturer {
+public:
+    DxgiCapturer();
+    ~DxgiCapturer() override;
+    bool open(const CaptureTarget& target, int width, int height) override;
+    void close() override;
+    AVFrame* getFrame() override;
+    void setDrawCursor(bool enable) override { m_drawCursor = enable; }
+private:
+    class DxgiCapturerPrivate* d;
+    bool m_drawCursor = true;
+    int m_left = 0, m_top = 0, m_width = 0, m_height = 0;
+};
+
+} // namespace video
+} // namespace avrecorder
+
+#endif // DXGICAPTURER_H 

+ 60 - 0
AvRecorder/capturer/video/GdiCapturer.cpp

@@ -0,0 +1,60 @@
+#include "GdiCapturer.h"
+#include <cassert>
+
+namespace avrecorder {
+namespace video {
+
+bool GdiCapturer::open(const CaptureTarget& target, int width, int height) {
+#ifdef PLATFORM_WINDOWS
+    close();
+    if (target.type != CaptureTargetType::Window) return false;
+    m_hwnd = target.hwnd;
+    m_width = width;
+    m_height = height;
+    _srcHdc = GetWindowDC(m_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;
+#else
+    return false;
+#endif
+}
+
+void GdiCapturer::close() {
+#ifdef PLATFORM_WINDOWS
+    if (_frame) { av_frame_free(&_frame); _frame = nullptr; }
+    if (_dstHdc) { DeleteObject(_dstHdc); _dstHdc = nullptr; }
+    if (_bitmap) { DeleteObject(_bitmap); _bitmap = nullptr; }
+    // _srcHdc 由系统管理,无需手动释放
+#endif
+}
+
+AVFrame* GdiCapturer::getFrame() {
+#ifdef PLATFORM_WINDOWS
+    if (!_srcHdc || !_dstHdc || !_frame) return nullptr;
+    BitBlt(_dstHdc, 0, 0, m_width, m_height, _srcHdc, 0, 0, SRCCOPY);
+    auto linesize = _frame->linesize[0];
+    for (int row = 0; row < m_height; ++row) {
+        GetDIBits(_dstHdc, _bitmap, m_height - 1 - row, 1, _frame->data[0] + row * linesize, &_bitmapInfo, DIB_RGB_COLORS);
+    }
+    // 可选:绘制鼠标
+    // ...
+    return _frame;
+#else
+    return nullptr;
+#endif
+}
+
+} // namespace video
+} // namespace avrecorder 

+ 33 - 0
AvRecorder/capturer/video/GdiCapturer.h

@@ -0,0 +1,33 @@
+#ifndef GDICAPTURER_H
+#define GDICAPTURER_H
+
+#include "IVideoCapturer.h"
+#include <Windows.h>
+
+namespace avrecorder {
+namespace video {
+
+class GdiCapturer : public IVideoCapturer {
+public:
+    GdiCapturer() = default;
+    ~GdiCapturer() override { close(); }
+    bool open(const CaptureTarget& target, int width, int height) override;
+    void close() override;
+    AVFrame* getFrame() override;
+    void setDrawCursor(bool enable) override { m_drawCursor = enable; }
+private:
+    HDC _srcHdc = nullptr;
+    HDC _dstHdc = nullptr;
+    HBITMAP _bitmap = nullptr;
+    BITMAPINFO _bitmapInfo;
+    int m_width = 0;
+    int m_height = 0;
+    AVFrame* _frame = nullptr;
+    bool m_drawCursor = true;
+    HWND m_hwnd = nullptr;
+};
+
+} // namespace video
+} // namespace avrecorder
+
+#endif // GDICAPTURER_H 

+ 34 - 0
AvRecorder/capturer/video/VideoCaptureManager.h

@@ -0,0 +1,34 @@
+#ifndef VIDEOCAPTUREMANAGER_H
+#define VIDEOCAPTUREMANAGER_H
+
+#include "IVideoCapturer.h"
+#include "VideoCapturerFactory.h"
+#include <memory>
+
+namespace avrecorder {
+namespace video {
+
+class VideoCaptureManager {
+public:
+    bool open(const CaptureTarget& target, CaptureMethod method, int width, int height) {
+        m_capturer = VideoCapturerFactory::create(method);
+        if (!m_capturer) return false;
+        return m_capturer->open(target, width, height);
+    }
+    void close() {
+        if (m_capturer) m_capturer->close();
+    }
+    AVFrame* getFrame() {
+        return m_capturer ? m_capturer->getFrame() : nullptr;
+    }
+    void setDrawCursor(bool enable) {
+        if (m_capturer) m_capturer->setDrawCursor(enable);
+    }
+private:
+    std::unique_ptr<IVideoCapturer> m_capturer;
+};
+
+} // namespace video
+} // namespace avrecorder
+
+#endif // VIDEOCAPTUREMANAGER_H 

+ 28 - 0
AvRecorder/capturer/video/VideoCapturerFactory.cpp

@@ -0,0 +1,28 @@
+#include "VideoCapturerFactory.h"
+#include "GdiCapturer.h"
+#include "DxgiCapturer.h"
+#include "WgcCapturer.h"
+
+namespace avrecorder {
+namespace video {
+
+std::unique_ptr<IVideoCapturer> VideoCapturerFactory::create(CaptureMethod method) {
+#ifdef PLATFORM_WINDOWS
+    switch (method) {
+    case CaptureMethod::GDI:
+        return std::make_unique<GdiCapturer>();
+    case CaptureMethod::DXGI:
+        return std::make_unique<DxgiCapturer>();
+    case CaptureMethod::WGC:
+        return std::make_unique<WgcCapturer>();
+    default:
+        return nullptr;
+    }
+#else
+    // 其他平台可扩展
+    return nullptr;
+#endif
+}
+
+} // namespace video
+} // namespace avrecorder 

+ 18 - 0
AvRecorder/capturer/video/VideoCapturerFactory.h

@@ -0,0 +1,18 @@
+#ifndef VIDEOCAPTURERFACTORY_H
+#define VIDEOCAPTURERFACTORY_H
+
+#include "IVideoCapturer.h"
+#include <memory>
+
+namespace avrecorder {
+namespace video {
+
+class VideoCapturerFactory {
+public:
+    static std::unique_ptr<IVideoCapturer> create(CaptureMethod method);
+};
+
+} // namespace video
+} // namespace avrecorder
+
+#endif // VIDEOCAPTURERFACTORY_H 

+ 46 - 0
AvRecorder/capturer/video/WgcCapturer.cpp

@@ -0,0 +1,46 @@
+#include "WgcCapturer.h"
+
+namespace avrecorder {
+namespace video {
+
+WgcCapturer::WgcCapturer() { _app = new App; }
+WgcCapturer::~WgcCapturer() { close(); if (_app) { delete _app; _app = nullptr; } }
+
+bool WgcCapturer::open(const CaptureTarget& target, int width, int height) {
+#ifdef PLATFORM_WINDOWS
+    close();
+    if (!_app) _app = new App;
+    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);
+    }
+    return false;
+#else
+    return false;
+#endif
+}
+
+void WgcCapturer::close() {
+#ifdef PLATFORM_WINDOWS
+    if (_app) _app->Close();
+#endif
+}
+
+AVFrame* WgcCapturer::getFrame() {
+#ifdef PLATFORM_WINDOWS
+    return _app ? _app->GetFrame() : nullptr;
+#else
+    return nullptr;
+#endif
+}
+
+void WgcCapturer::setDrawCursor(bool enable) {
+#ifdef PLATFORM_WINDOWS
+    if (_app) _app->SetDrawCursor(enable);
+#endif
+}
+
+} // namespace video
+} // namespace avrecorder 

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

@@ -0,0 +1,27 @@
+#ifndef WGCCAPTURER_H
+#define WGCCAPTURER_H
+
+#include "IVideoCapturer.h"
+#include "wgc/App.h"
+#include <list>
+
+namespace avrecorder {
+namespace video {
+
+class WgcCapturer : public IVideoCapturer {
+public:
+    WgcCapturer();
+    ~WgcCapturer() override;
+    bool open(const CaptureTarget& target, int width, int height) override;
+    void close() override;
+    AVFrame* getFrame() override;
+    void setDrawCursor(bool enable) override;
+private:
+    App* _app = nullptr;
+    bool _isAppInit = false;
+};
+
+} // namespace video
+} // namespace avrecorder
+
+#endif // WGCCAPTURER_H 

+ 66 - 8
AvRecorder/capturer/video/ivideocapturer.h

@@ -1,12 +1,70 @@
-#ifndef IVIDEOCAPTURER_H
-#define IVIDEOCAPTURER_H
+#ifndef IVIDEOCAPURER_H
+#define IVIDEOCAPURER_H
 
-class ivideocapturer
-{
-public:
-    ivideocapturer();
+#include "basic/frame.h"
+
+#include <cstdint>
+#include <memory>
+
+#include "qwindowdefs_win.h"
+
+namespace avrecorder {
+namespace video {
+
+// 平台宏定义
+#if defined(_WIN32)
+    #define PLATFORM_WINDOWS
+#elif defined(__APPLE__)
+    #define PLATFORM_MACOS
+#elif defined(__linux__)
+    #define PLATFORM_LINUX
+#endif
+
+// 捕获目标类型
+enum class CaptureTargetType {
+    Window,
+    Monitor,
+    // 预留更多类型,如 macOS 的 CGWindowID、X11 Window 等
+};
 
-    virtual bool open(int left, int top, int width, int height) = 0;
+// 捕获目标描述
+struct CaptureTarget {
+    CaptureTargetType type;
+    union {
+#ifdef PLATFORM_WINDOWS
+        HWND hwnd;
+        int monitorIdx;
+#endif
+#ifdef PLATFORM_MACOS
+        uint32_t cgWindowId;
+        uint32_t displayId;
+#endif
+#ifdef PLATFORM_LINUX
+        unsigned long x11Window;
+        int x11Screen;
+#endif
+    };
 };
 
-#endif // IVIDEOCAPTURER_H
+// 捕获方式
+enum class CaptureMethod {
+    GDI,
+    DXGI,
+    WGC,
+    // 预留更多方式,如 macOS/Linux
+};
+
+// 统一视频捕获接口
+class IVideoCapturer {
+public:
+    virtual ~IVideoCapturer() = default;
+    virtual bool open(const CaptureTarget& target, int width, int height) = 0;
+    virtual void close() = 0;
+    virtual AVFrame* getFrame() = 0;
+    virtual void setDrawCursor(bool enable) = 0;
+};
+
+} // namespace video
+} // namespace avrecorder
+
+#endif // IVIDEOCAPURER_H

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

@@ -1,4 +1,9 @@
 HEADERS += \
+    $$PWD/DxgiCapturer.h \
+    $$PWD/GdiCapturer.h \
+    $$PWD/VideoCaptureManager.h \
+    $$PWD/VideoCapturerFactory.h \
+    $$PWD/WgcCapturer.h \
     $$PWD/ivideocapturer.h \
     $$PWD/dxgi_capturer.h \
     $$PWD/gdi_capturer.h \
@@ -14,6 +19,10 @@ HEADERS += \
     $$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 \