mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-26 20:25:34 +08:00
Use sdl2 to display capture screen
This commit is contained in:
@@ -12,9 +12,10 @@
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
#include "pch.h"
|
||||
#include "SimpleCapture.h"
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows;
|
||||
using namespace Windows::Foundation;
|
||||
@@ -107,7 +108,6 @@ void SimpleCapture::OnFrameArrived(
|
||||
auto frameSurface =
|
||||
GetDXGIInterfaceFromObject<ID3D11Texture2D>(frame.Surface());
|
||||
|
||||
|
||||
com_ptr<ID3D11Texture2D> backBuffer;
|
||||
check_hresult(m_swapChain->GetBuffer(0, guid_of<ID3D11Texture2D>(),
|
||||
backBuffer.put_void()));
|
||||
@@ -123,8 +123,7 @@ void SimpleCapture::OnFrameArrived(
|
||||
auto frameSurface =
|
||||
GetDXGIInterfaceFromObject<ID3D11Texture2D>(frame.Surface());
|
||||
|
||||
if (!m_mappedTexture || newSize)
|
||||
CreateMappedTexture(frameSurface);
|
||||
if (!m_mappedTexture || newSize) CreateMappedTexture(frameSurface);
|
||||
|
||||
m_d3dContext->CopyResource(m_mappedTexture.get(), frameSurface.get());
|
||||
|
||||
@@ -136,8 +135,7 @@ void SimpleCapture::OnFrameArrived(
|
||||
#if 1
|
||||
if (mapInfo.pData) {
|
||||
static unsigned char *buffer = nullptr;
|
||||
if (buffer && newSize)
|
||||
delete[] buffer;
|
||||
if (buffer && newSize) delete[] buffer;
|
||||
|
||||
if (!buffer)
|
||||
buffer = new unsigned char[frameContentSize.Width *
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
#ifndef ERROR_DEFINE
|
||||
#define ERROR_DEFINE
|
||||
|
||||
|
||||
enum AM_ERROR{
|
||||
AE_NO = 0,
|
||||
AE_ERROR,
|
||||
AE_UNSUPPORT,
|
||||
AE_INVALID_CONTEXT,
|
||||
AE_NEED_INIT,
|
||||
AE_TIMEOUT,
|
||||
AE_ALLOCATE_FAILED,
|
||||
|
||||
//AE_CO_
|
||||
AE_CO_INITED_FAILED,
|
||||
AE_CO_CREATE_FAILED,
|
||||
AE_CO_GETENDPOINT_FAILED,
|
||||
AE_CO_ACTIVE_DEVICE_FAILED,
|
||||
AE_CO_GET_FORMAT_FAILED,
|
||||
AE_CO_AUDIOCLIENT_INIT_FAILED,
|
||||
AE_CO_GET_CAPTURE_FAILED,
|
||||
AE_CO_CREATE_EVENT_FAILED,
|
||||
AE_CO_SET_EVENT_FAILED,
|
||||
AE_CO_START_FAILED,
|
||||
AE_CO_ENUMENDPOINT_FAILED,
|
||||
AE_CO_GET_ENDPOINT_COUNT_FAILED,
|
||||
AE_CO_GET_ENDPOINT_ID_FAILED,
|
||||
AE_CO_OPEN_PROPERTY_FAILED,
|
||||
AE_CO_GET_VALUE_FAILED,
|
||||
AE_CO_GET_BUFFER_FAILED,
|
||||
AE_CO_RELEASE_BUFFER_FAILED,
|
||||
AE_CO_GET_PACKET_FAILED,
|
||||
AE_CO_PADDING_UNEXPECTED,
|
||||
|
||||
//AE_FFMPEG_
|
||||
AE_FFMPEG_OPEN_INPUT_FAILED,
|
||||
AE_FFMPEG_FIND_STREAM_FAILED,
|
||||
AE_FFMPEG_FIND_DECODER_FAILED,
|
||||
AE_FFMPEG_OPEN_CODEC_FAILED,
|
||||
AE_FFMPEG_READ_FRAME_FAILED,
|
||||
AE_FFMPEG_READ_PACKET_FAILED,
|
||||
AE_FFMPEG_DECODE_FRAME_FAILED,
|
||||
AE_FFMPEG_NEW_SWSCALE_FAILED,
|
||||
AE_FFMPEG_FIND_ENCODER_FAILED,
|
||||
AE_FFMPEG_ALLOC_CONTEXT_FAILED,
|
||||
AE_FFMPEG_ENCODE_FRAME_FAILED,
|
||||
AE_FFMPEG_ALLOC_FRAME_FAILED,
|
||||
AE_FFMPEG_OPEN_IO_FAILED,
|
||||
AE_FFMPEG_CREATE_STREAM_FAILED,
|
||||
AE_FFMPEG_COPY_PARAMS_FAILED,
|
||||
AE_RESAMPLE_INIT_FAILED,
|
||||
AE_FFMPEG_NEW_STREAM_FAILED,
|
||||
AE_FFMPEG_FIND_INPUT_FMT_FAILED,
|
||||
AE_FFMPEG_WRITE_HEADER_FAILED,
|
||||
AE_FFMPEG_WRITE_TRAILER_FAILED,
|
||||
AE_FFMPEG_WRITE_FRAME_FAILED,
|
||||
|
||||
//AE_FILTER_
|
||||
AE_FILTER_ALLOC_GRAPH_FAILED,
|
||||
AE_FILTER_CREATE_FILTER_FAILED,
|
||||
AE_FILTER_PARSE_PTR_FAILED,
|
||||
AE_FILTER_CONFIG_FAILED,
|
||||
AE_FILTER_INVALID_CTX_INDEX,
|
||||
AE_FILTER_ADD_FRAME_FAILED,
|
||||
|
||||
//AE_GDI_
|
||||
AE_GDI_GET_DC_FAILED,
|
||||
AE_GDI_CREATE_DC_FAILED,
|
||||
AE_GDI_CREATE_BMP_FAILED,
|
||||
AE_GDI_BITBLT_FAILED,
|
||||
AE_GDI_GET_DIBITS_FAILED,
|
||||
|
||||
//AE_D3D_
|
||||
AE_D3D_LOAD_FAILED,
|
||||
AE_D3D_GET_PROC_FAILED,
|
||||
AE_D3D_CREATE_DEVICE_FAILED,
|
||||
AE_D3D_QUERYINTERFACE_FAILED,
|
||||
AE_D3D_CREATE_VERTEX_SHADER_FAILED,
|
||||
AE_D3D_CREATE_INLAYOUT_FAILED,
|
||||
AE_D3D_CREATE_PIXEL_SHADER_FAILED,
|
||||
AE_D3D_CREATE_SAMPLERSTATE_FAILED,
|
||||
|
||||
//AE_DXGI_
|
||||
AE_DXGI_GET_PROC_FAILED,
|
||||
AE_DXGI_GET_ADAPTER_FAILED,
|
||||
AE_DXGI_GET_FACTORY_FAILED,
|
||||
AE_DXGI_FOUND_ADAPTER_FAILED,
|
||||
|
||||
//AE_DUP_
|
||||
AE_DUP_ATTATCH_FAILED,
|
||||
AE_DUP_QI_FAILED,
|
||||
AE_DUP_GET_PARENT_FAILED,
|
||||
AE_DUP_ENUM_OUTPUT_FAILED,
|
||||
AE_DUP_DUPLICATE_MAX_FAILED,
|
||||
AE_DUP_DUPLICATE_FAILED,
|
||||
AE_DUP_RELEASE_FRAME_FAILED,
|
||||
AE_DUP_ACQUIRE_FRAME_FAILED,
|
||||
AE_DUP_QI_FRAME_FAILED,
|
||||
AE_DUP_CREATE_TEXTURE_FAILED,
|
||||
AE_DUP_QI_DXGI_FAILED,
|
||||
AE_DUP_MAP_FAILED,
|
||||
AE_DUP_GET_CURSORSHAPE_FAILED,
|
||||
|
||||
//AE_REMUX_
|
||||
AE_REMUX_RUNNING,
|
||||
AE_REMUX_NOT_EXIST,
|
||||
AE_REMUX_INVALID_INOUT,
|
||||
|
||||
// AE_WGC_
|
||||
AE_WGC_CREATE_CAPTURER_FAILED,
|
||||
|
||||
AE_MAX
|
||||
};
|
||||
|
||||
static const char *ERRORS_STR[] = {
|
||||
"no error", //AE_NO
|
||||
"error", //AE_ERROR
|
||||
"not support for now", //AE_UNSUPPORT
|
||||
"invalid context", //AE_INVALID_CONTEXT
|
||||
"need init first", //AE_NEED_INIT
|
||||
"operation timeout", //AE_TIMEOUT
|
||||
"allocate memory failed", //AE_ALLOCATE_FAILED,
|
||||
|
||||
"com init failed", //AE_CO_INITED_FAILED
|
||||
"com create instance failed", //AE_CO_CREATE_FAILED
|
||||
"com get endpoint failed", //AE_CO_GETENDPOINT_FAILED
|
||||
"com active device failed", //AE_CO_ACTIVE_DEVICE_FAILED
|
||||
"com get wave formatex failed", //AE_CO_GET_FORMAT_FAILED
|
||||
"com audio client init failed", //AE_CO_AUDIOCLIENT_INIT_FAILED
|
||||
"com audio get capture failed", //AE_CO_GET_CAPTURE_FAILED
|
||||
"com audio create event failed", //AE_CO_CREATE_EVENT_FAILED
|
||||
"com set ready event failed", //AE_CO_SET_EVENT_FAILED
|
||||
"com start to record failed", //AE_CO_START_FAILED
|
||||
"com enum audio endpoints failed", //AE_CO_ENUMENDPOINT_FAILED
|
||||
"com get endpoints count failed", //AE_CO_GET_ENDPOINT_COUNT_FAILED
|
||||
"com get endpoint id failed", //AE_CO_GET_ENDPOINT_ID_FAILED
|
||||
"com open endpoint property failed", //AE_CO_OPEN_PROPERTY_FAILED
|
||||
"com get property value failed", //AE_CO_GET_VALUE_FAILED
|
||||
"com get buffer failed", //AE_CO_GET_BUFFER_FAILED
|
||||
"com release buffer failed", //AE_CO_RELEASE_BUFFER_FAILED
|
||||
"com get packet size failed", //AE_CO_GET_PACKET_FAILED
|
||||
"com get padding size unexpected", //AE_CO_PADDING_UNEXPECTED
|
||||
|
||||
"ffmpeg open input failed", //AE_FFMPEG_OPEN_INPUT_FAILED
|
||||
"ffmpeg find stream info failed", //AE_FFMPEG_FIND_STREAM_FAILED
|
||||
"ffmpeg find decoder failed", //AE_FFMPEG_FIND_DECODER_FAILED
|
||||
"ffmpeg open codec failed", //AE_FFMPEG_OPEN_CODEC_FAILED
|
||||
"ffmpeg read frame failed", //AE_FFMPEG_READ_FRAME_FAILED
|
||||
"ffmpeg read packet failed", //AE_FFMPEG_READ_PACKET_FAILED
|
||||
"ffmpeg decode frame failed", //AE_FFMPEG_DECODE_FRAME_FAILED
|
||||
"ffmpeg create swscale failed", //AE_FFMPEG_NEW_SWSCALE_FAILED
|
||||
|
||||
"ffmpeg find encoder failed", //AE_FFMPEG_FIND_ENCODER_FAILED
|
||||
"ffmpeg alloc context failed", //AE_FFMPEG_ALLOC_CONTEXT_FAILED
|
||||
"ffmpeg encode frame failed", //AE_FFMPEG_ENCODE_FRAME_FAILED
|
||||
"ffmpeg alloc frame failed", //AE_FFMPEG_ALLOC_FRAME_FAILED
|
||||
|
||||
"ffmpeg open io ctx failed", //AE_FFMPEG_OPEN_IO_FAILED
|
||||
"ffmpeg new stream failed", //AE_FFMPEG_CREATE_STREAM_FAILED
|
||||
"ffmpeg copy parameters failed", //AE_FFMPEG_COPY_PARAMS_FAILED
|
||||
"resampler init failed", //AE_RESAMPLE_INIT_FAILED
|
||||
"ffmpeg new out stream failed", //AE_FFMPEG_NEW_STREAM_FAILED
|
||||
"ffmpeg find input format failed", //AE_FFMPEG_FIND_INPUT_FMT_FAILED
|
||||
"ffmpeg write file header failed", //AE_FFMPEG_WRITE_HEADER_FAILED
|
||||
"ffmpeg write file trailer failed", //AE_FFMPEG_WRITE_TRAILER_FAILED
|
||||
"ffmpeg write frame failed", //AE_FFMPEG_WRITE_FRAME_FAILED
|
||||
|
||||
"avfilter alloc avfilter failed", //AE_FILTER_ALLOC_GRAPH_FAILED
|
||||
"avfilter create graph failed", //AE_FILTER_CREATE_FILTER_FAILED
|
||||
"avfilter parse ptr failed", //AE_FILTER_PARSE_PTR_FAILED
|
||||
"avfilter config graph failed", //AE_FILTER_CONFIG_FAILED
|
||||
"avfilter invalid ctx index", //AE_FILTER_INVALID_CTX_INDEX
|
||||
"avfilter add frame failed", //AE_FILTER_ADD_FRAME_FAILED
|
||||
|
||||
"gdi get dc failed", //AE_GDI_GET_DC_FAILED
|
||||
"gdi create dc failed", //AE_GDI_CREATE_DC_FAILED
|
||||
"gdi create bmp failed", //AE_GDI_CREATE_BMP_FAILED
|
||||
"gdi bitblt failed", //AE_GDI_BITBLT_FAILED
|
||||
"gid geet dibbits failed", //AE_GDI_GET_DIBITS_FAILED
|
||||
|
||||
"d3d11 library load failed", //AE_D3D_LOAD_FAILED
|
||||
"d3d11 proc get failed", //AE_D3D_GET_PROC_FAILED
|
||||
"d3d11 create device failed", //AE_D3D_CREATE_DEVICE_FAILED
|
||||
"d3d11 query interface failed", //AE_D3D_QUERYINTERFACE_FAILED
|
||||
"d3d11 create vertex shader failed",//AE_D3D_CREATE_VERTEX_SHADER_FAILED
|
||||
"d3d11 create input layout failed", //AE_D3D_CREATE_INLAYOUT_FAILED
|
||||
"d3d11 create pixel shader failed", //AE_D3D_CREATE_PIXEL_SHADER_FAILED
|
||||
"d3d11 create sampler state failed",//AE_D3D_CREATE_SAMPLERSTATE_FAILED
|
||||
|
||||
"dxgi get proc address failed", //AE_DXGI_GET_PROC_FAILED
|
||||
"dxgi get adapter failed", //AE_DXGI_GET_ADAPTER_FAILED
|
||||
"dxgi get factory failed", //AE_DXGI_GET_FACTORY_FAILED
|
||||
"dxgi specified adapter not found", //AE_DXGI_FOUND_ADAPTER_FAILED
|
||||
|
||||
"duplication attatch desktop failed", //AE_DUP_ATTATCH_FAILED
|
||||
"duplication query interface failed", //AE_DUP_QI_FAILED
|
||||
"duplication get parent failed", //AE_DUP_GET_PARENT_FAILED
|
||||
"duplication enum ouput failed", //AE_DUP_ENUM_OUTPUT_FAILED
|
||||
"duplication duplicate unavailable", //AE_DUP_DUPLICATE_MAX_FAILED
|
||||
"duplication duplicate failed", //AE_DUP_DUPLICATE_FAILED
|
||||
"duplication release frame failed", //AE_DUP_RELEASE_FRAME_FAILED
|
||||
"duplication acquire frame failed", //AE_DUP_ACQUIRE_FRAME_FAILED
|
||||
"duplication qi frame failed", //AE_DUP_QI_FRAME_FAILED
|
||||
"duplication create texture failed", //AE_DUP_CREATE_TEXTURE_FAILED
|
||||
"duplication dxgi qi failed", //AE_DUP_QI_DXGI_FAILED
|
||||
"duplication map rects failed", //AE_DUP_MAP_FAILED
|
||||
"duplication get cursor shape failed",//AE_DUP_GET_CURSORSHAPE_FAILED
|
||||
|
||||
"remux is already running", //AE_REMUX_RUNNING
|
||||
"remux input file do not exist", //AE_REMUX_NOT_EXIST
|
||||
"remux input or output file invalid", //AE_REMUX_INVALID_INOUT
|
||||
};
|
||||
|
||||
#define err2str(e) e < AE_MAX ? ERRORS_STR[e] : "unknown"
|
||||
|
||||
#define AMERROR_CHECK(err) if(err != AE_NO) return err
|
||||
|
||||
#endif // !ERROR_DEFINE
|
||||
@@ -1,17 +0,0 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include <winrt/Windows.Foundation.Metadata.h>
|
||||
|
||||
bool wgc_is_supported() {
|
||||
try {
|
||||
/* no contract for IGraphicsCaptureItemInterop, verify 10.0.18362.0 */
|
||||
return winrt::Windows::Foundation::Metadata::ApiInformation::
|
||||
IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 8);
|
||||
} catch (const winrt::hresult_error &) {
|
||||
return false;
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
am::wgc_session *wgc_create_session() { return new am::wgc_session_impl(); }
|
||||
@@ -1,50 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#ifdef AMRECORDER_IMPORT
|
||||
#define AMRECORDER_API extern "C" __declspec(dllimport)
|
||||
#else
|
||||
#define AMRECORDER_API extern "C" __declspec(dllexport)
|
||||
#endif
|
||||
|
||||
namespace am {
|
||||
|
||||
class wgc_session {
|
||||
public:
|
||||
struct wgc_session_frame {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int row_pitch;
|
||||
|
||||
const unsigned char *data;
|
||||
};
|
||||
|
||||
class wgc_session_observer {
|
||||
public:
|
||||
virtual ~wgc_session_observer() {}
|
||||
virtual void on_frame(const wgc_session_frame &frame) = 0;
|
||||
};
|
||||
|
||||
public:
|
||||
virtual void release() = 0;
|
||||
|
||||
virtual int initialize(HWND hwnd) = 0;
|
||||
virtual int initialize(HMONITOR hmonitor) = 0;
|
||||
|
||||
virtual void register_observer(wgc_session_observer *observer) = 0;
|
||||
|
||||
virtual int start() = 0;
|
||||
virtual int stop() = 0;
|
||||
|
||||
virtual int pause() = 0;
|
||||
virtual int resume() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~wgc_session(){};
|
||||
};
|
||||
|
||||
} // namespace am
|
||||
|
||||
AMRECORDER_API bool wgc_is_supported();
|
||||
AMRECORDER_API am::wgc_session *wgc_create_session();
|
||||
@@ -1,21 +0,0 @@
|
||||
#ifndef _HEAD_H_
|
||||
#define _HEAD_H_
|
||||
|
||||
#include "record_desktop.h"
|
||||
|
||||
class rd : public am::record_desktop {
|
||||
public:
|
||||
rd(){};
|
||||
virtual ~rd(){};
|
||||
|
||||
int init(const RECORD_DESKTOP_RECT &rect, const int fps) { return 0; };
|
||||
|
||||
int start() { return 0; };
|
||||
int pause() { return 0; };
|
||||
int resume() { return 0; };
|
||||
int stop() { return 0; };
|
||||
|
||||
void clean_up() {}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,19 +1,91 @@
|
||||
|
||||
#define AMRECORDER_IMPORT
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include "export.h"
|
||||
#include "head.h"
|
||||
#include "record_desktop_wgc.h"
|
||||
#include "screen_capture_wgc.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswscale/swscale.h>
|
||||
};
|
||||
|
||||
#define SDL_MAIN_HANDLED
|
||||
#include "SDL2/SDL.h"
|
||||
|
||||
int screen_w = 2560, screen_h = 1440;
|
||||
const int pixel_w = 2560, pixel_h = 1440;
|
||||
|
||||
unsigned char buffer[pixel_w * pixel_h * 3 / 2];
|
||||
unsigned char dst_buffer[pixel_w * pixel_h * 3 / 2];
|
||||
unsigned char rgbData[pixel_w * pixel_h * 4];
|
||||
SDL_Texture *sdlTexture = nullptr;
|
||||
SDL_Renderer *sdlRenderer = nullptr;
|
||||
SDL_Rect sdlRect;
|
||||
|
||||
// Refresh Event
|
||||
#define REFRESH_EVENT (SDL_USEREVENT + 1)
|
||||
|
||||
int thread_exit = 0;
|
||||
|
||||
int refresh_video(void *opaque) {
|
||||
while (thread_exit == 0) {
|
||||
SDL_Event event;
|
||||
event.type = REFRESH_EVENT;
|
||||
SDL_PushEvent(&event);
|
||||
SDL_Delay(10);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int YUV420ToNV12FFmpeg(unsigned char *src_buffer, int width, int height,
|
||||
unsigned char *des_buffer) {
|
||||
AVFrame *Input_pFrame = av_frame_alloc();
|
||||
AVFrame *Output_pFrame = av_frame_alloc();
|
||||
struct SwsContext *img_convert_ctx = sws_getContext(
|
||||
width, height, AV_PIX_FMT_YUV420P, 1280, 720, AV_PIX_FMT_NV12,
|
||||
SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
|
||||
|
||||
av_image_fill_arrays(Input_pFrame->data, Input_pFrame->linesize, src_buffer,
|
||||
AV_PIX_FMT_YUV420P, width, height, 1);
|
||||
av_image_fill_arrays(Output_pFrame->data, Output_pFrame->linesize, des_buffer,
|
||||
AV_PIX_FMT_NV12, 1280, 720, 1);
|
||||
|
||||
sws_scale(img_convert_ctx, (uint8_t const **)Input_pFrame->data,
|
||||
Input_pFrame->linesize, 0, height, Output_pFrame->data,
|
||||
Output_pFrame->linesize);
|
||||
|
||||
if (Input_pFrame) av_free(Input_pFrame);
|
||||
if (Output_pFrame) av_free(Output_pFrame);
|
||||
if (img_convert_ctx) sws_freeContext(img_convert_ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OnFrame(unsigned char *data, int size, int width, int height) {
|
||||
std::cout << "Receive frame: w:" << width << " h:" << height
|
||||
<< " size:" << size << std::endl;
|
||||
// YUV420ToNV12FFmpeg(data, width, height, dst_buffer);
|
||||
|
||||
// SDL_UpdateTexture(sdlTexture, NULL, data, pixel_w);
|
||||
memcpy(rgbData, data, width * height);
|
||||
|
||||
// FIX: If window is resize
|
||||
// sdlRect.x = 0;
|
||||
// sdlRect.y = 0;
|
||||
// sdlRect.w = screen_w;
|
||||
// sdlRect.h = screen_h;
|
||||
|
||||
// SDL_RenderClear(sdlRenderer);
|
||||
// SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect);
|
||||
// SDL_RenderPresent(sdlRenderer);
|
||||
}
|
||||
|
||||
int main() {
|
||||
// bool is_supported = wgc_is_supported();
|
||||
// if (!wgc_is_supported) {
|
||||
// std::cout << "Not support wgc" << std::endl;
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
static am::record_desktop *recorder = new am::record_desktop_wgc();
|
||||
ScreenCaptureWgc *recorder = new ScreenCaptureWgc();
|
||||
|
||||
RECORD_DESKTOP_RECT rect;
|
||||
rect.left = 0;
|
||||
@@ -21,14 +93,50 @@ int main() {
|
||||
rect.right = GetSystemMetrics(SM_CXSCREEN);
|
||||
rect.bottom = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
recorder->init(rect, 10);
|
||||
recorder->Init(rect, 10, OnFrame);
|
||||
|
||||
recorder->start();
|
||||
// int pause() override;
|
||||
// int resume() override;
|
||||
// int stop() override;
|
||||
recorder->Start();
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO)) {
|
||||
printf("Could not initialize SDL - %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_Window *screen;
|
||||
screen = SDL_CreateWindow("RTS Receiver", SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED, screen_w, screen_h,
|
||||
SDL_WINDOW_RESIZABLE);
|
||||
if (!screen) {
|
||||
printf("SDL: could not create window - exiting:%s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
sdlRenderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED);
|
||||
|
||||
Uint32 pixformat = 0;
|
||||
pixformat = SDL_PIXELFORMAT_NV12;
|
||||
|
||||
// sdlTexture = SDL_CreateTexture(sdlRenderer, pixformat,
|
||||
// SDL_TEXTUREACCESS_STREAMING, pixel_w,
|
||||
// pixel_h);
|
||||
|
||||
SDL_Surface *surface =
|
||||
SDL_CreateRGBSurfaceFrom(rgbData, pixel_w, pixel_h, 24, pixel_w * 3,
|
||||
0x000000FF, 0x0000FF00, 0x00FF0000, 0);
|
||||
|
||||
sdlTexture = SDL_CreateTextureFromSurface(sdlRenderer, surface);
|
||||
|
||||
SDL_Thread *refresh_thread = SDL_CreateThread(refresh_video, NULL, NULL);
|
||||
SDL_Event event;
|
||||
while (1) {
|
||||
// Wait
|
||||
SDL_WaitEvent(&event);
|
||||
if (event.type == REFRESH_EVENT) {
|
||||
} else if (event.type == SDL_WINDOWEVENT) {
|
||||
// If Resize
|
||||
SDL_GetWindowSize(screen, &screen_w, &screen_h);
|
||||
} else if (event.type == SDL_QUIT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
#include "pch.h"
|
||||
@@ -1,48 +0,0 @@
|
||||
// pch.h: This is a precompiled header file.
|
||||
// Files listed below are compiled only once, improving build performance for
|
||||
// future builds. This also affects IntelliSense performance, including code
|
||||
// completion and many code browsing features. However, files listed here are
|
||||
// ALL re-compiled if any one of them is updated between builds. Do not add
|
||||
// files here that you will be updating frequently as this negates the
|
||||
// performance advantage.
|
||||
|
||||
#ifndef PCH_H
|
||||
#define PCH_H
|
||||
|
||||
// add headers that you want to pre-compile here
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files
|
||||
|
||||
#include <Unknwn.h>
|
||||
#include <inspectable.h>
|
||||
|
||||
// WinRT
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.System.h>
|
||||
#include <winrt/Windows.Graphics.DirectX.h>
|
||||
#include <winrt/Windows.Graphics.DirectX.Direct3d11.h>
|
||||
#include <winrt/Windows.Graphics.Capture.h>
|
||||
#include <Windows.Graphics.Capture.Interop.h>
|
||||
|
||||
#include <DispatcherQueue.h>
|
||||
|
||||
|
||||
// STL
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
// D3D
|
||||
#include <d3d11_4.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <d2d1_3.h>
|
||||
#include <wincodec.h>
|
||||
|
||||
// windowws
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "error_define.h"
|
||||
#include "export.h"
|
||||
#include "wgc_session_impl.h"
|
||||
|
||||
#endif // PCH_H
|
||||
@@ -1,23 +0,0 @@
|
||||
#include "record_desktop.h"
|
||||
|
||||
am::record_desktop::record_desktop()
|
||||
{
|
||||
_running = false;
|
||||
_paused = false;
|
||||
_inited = false;
|
||||
|
||||
_on_data = nullptr;
|
||||
_on_error = nullptr;
|
||||
|
||||
_device_name = "";
|
||||
_data_type = RECORD_DESKTOP_DATA_TYPES::AT_DESKTOP_BGRA;
|
||||
|
||||
_time_base = { 1,AV_TIME_BASE };
|
||||
_start_time = 0;
|
||||
_pixel_fmt = AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
am::record_desktop::~record_desktop()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
#ifndef RECORD_DESKTOP
|
||||
#define RECORD_DESKTOP
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec\adts_parser.h>
|
||||
#include <libavcodec\avcodec.h>
|
||||
#include <libavdevice\avdevice.h>
|
||||
#include <libavfilter\avfilter.h>
|
||||
#include <libavfilter\buffersink.h>
|
||||
#include <libavfilter\buffersrc.h>
|
||||
#include <libavformat\avformat.h>
|
||||
#include <libavutil\avassert.h>
|
||||
#include <libavutil\channel_layout.h>
|
||||
#include <libavutil\error.h>
|
||||
#include <libavutil\imgutils.h>
|
||||
#include <libavutil\log.h>
|
||||
#include <libavutil\mathematics.h>
|
||||
#include <libavutil\opt.h>
|
||||
#include <libavutil\samplefmt.h>
|
||||
#include <libavutil\time.h>
|
||||
#include <libavutil\timestamp.h>
|
||||
#include <libswresample\swresample.h>
|
||||
#include <libswscale\swscale.h>
|
||||
}
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
typedef enum {
|
||||
DT_DESKTOP_NO = 0,
|
||||
DT_DESKTOP_FFMPEG_GDI,
|
||||
DT_DESKTOP_FFMPEG_DSHOW,
|
||||
DT_DESKTOP_WIN_GDI,
|
||||
DT_DESKTOP_WIN_DUPLICATION,
|
||||
DT_DESKTOP_WIN_WGC,
|
||||
DT_DESKTOP_WIN_MAG
|
||||
} RECORD_DESKTOP_TYPES;
|
||||
|
||||
/*
|
||||
* Record desktop data type
|
||||
*
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
AT_DESKTOP_NO = 0,
|
||||
AT_DESKTOP_RGBA,
|
||||
AT_DESKTOP_BGRA
|
||||
} RECORD_DESKTOP_DATA_TYPES;
|
||||
|
||||
/**
|
||||
* Record desktop rect
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
} RECORD_DESKTOP_RECT;
|
||||
|
||||
namespace am {
|
||||
typedef std::function<void(AVFrame *frame)> cb_desktop_data;
|
||||
typedef std::function<void(int)> cb_desktop_error;
|
||||
|
||||
class record_desktop {
|
||||
public:
|
||||
record_desktop();
|
||||
virtual ~record_desktop();
|
||||
|
||||
virtual int init(const RECORD_DESKTOP_RECT &rect, const int fps) = 0;
|
||||
|
||||
virtual int start() = 0;
|
||||
virtual int pause() = 0;
|
||||
virtual int resume() = 0;
|
||||
virtual int stop() = 0;
|
||||
|
||||
inline const AVRational &get_time_base() { return _time_base; }
|
||||
|
||||
inline int64_t get_start_time() { return _start_time; }
|
||||
|
||||
inline AVPixelFormat get_pixel_fmt() { return _pixel_fmt; }
|
||||
|
||||
public:
|
||||
inline bool is_recording() { return _running; }
|
||||
inline const std::string &get_device_name() { return _device_name; }
|
||||
inline const RECORD_DESKTOP_DATA_TYPES get_data_type() { return _data_type; }
|
||||
inline void registe_cb(cb_desktop_data on_data, cb_desktop_error on_error) {
|
||||
_on_data = on_data;
|
||||
_on_error = on_error;
|
||||
}
|
||||
inline const RECORD_DESKTOP_RECT &get_rect() { return _rect; }
|
||||
|
||||
inline const int get_frame_rate() { return _fps; }
|
||||
|
||||
protected:
|
||||
virtual void clean_up() = 0;
|
||||
|
||||
protected:
|
||||
std::atomic_bool _running;
|
||||
std::atomic_bool _paused;
|
||||
std::atomic_bool _inited;
|
||||
|
||||
std::thread _thread;
|
||||
|
||||
std::string _device_name;
|
||||
|
||||
RECORD_DESKTOP_RECT _rect;
|
||||
RECORD_DESKTOP_DATA_TYPES _data_type;
|
||||
|
||||
int _fps;
|
||||
|
||||
cb_desktop_data _on_data;
|
||||
cb_desktop_error _on_error;
|
||||
|
||||
AVRational _time_base;
|
||||
int64_t _start_time;
|
||||
AVPixelFormat _pixel_fmt;
|
||||
};
|
||||
} // namespace am
|
||||
|
||||
#endif
|
||||
@@ -1,139 +0,0 @@
|
||||
#include "record_desktop_wgc.h"
|
||||
|
||||
#include "error_define.h"
|
||||
|
||||
BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, HDC hdc, LPRECT lprc,
|
||||
LPARAM data) {
|
||||
MONITORINFOEX info_ex;
|
||||
info_ex.cbSize = sizeof(MONITORINFOEX);
|
||||
|
||||
GetMonitorInfo(hmonitor, &info_ex);
|
||||
|
||||
if (info_ex.dwFlags == DISPLAY_DEVICE_MIRRORING_DRIVER) return true;
|
||||
|
||||
if (info_ex.dwFlags & MONITORINFOF_PRIMARY) {
|
||||
*(HMONITOR *)data = hmonitor;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
HMONITOR GetPrimaryMonitor() {
|
||||
HMONITOR hmonitor = nullptr;
|
||||
|
||||
::EnumDisplayMonitors(NULL, NULL, EnumMonitorProc, (LPARAM)&hmonitor);
|
||||
|
||||
return hmonitor;
|
||||
}
|
||||
|
||||
namespace am {
|
||||
|
||||
record_desktop_wgc::record_desktop_wgc() {}
|
||||
|
||||
record_desktop_wgc::~record_desktop_wgc() {
|
||||
stop();
|
||||
clean_up();
|
||||
}
|
||||
|
||||
int record_desktop_wgc::init(const RECORD_DESKTOP_RECT &rect, const int fps) {
|
||||
int error = AE_NO;
|
||||
if (_inited == true) return error;
|
||||
|
||||
_fps = fps;
|
||||
_rect = rect;
|
||||
_start_time = av_gettime_relative();
|
||||
_time_base = {1, AV_TIME_BASE};
|
||||
_pixel_fmt = AV_PIX_FMT_BGRA;
|
||||
|
||||
do {
|
||||
if (!wgc_is_supported()) {
|
||||
error = AE_UNSUPPORT;
|
||||
break;
|
||||
}
|
||||
|
||||
session_ = wgc_create_session();
|
||||
if (!session_) {
|
||||
error = AE_WGC_CREATE_CAPTURER_FAILED;
|
||||
break;
|
||||
}
|
||||
|
||||
session_->register_observer(this);
|
||||
|
||||
error = session_->initialize(GetPrimaryMonitor());
|
||||
|
||||
_inited = true;
|
||||
} while (0);
|
||||
|
||||
if (error != AE_NO) {
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int record_desktop_wgc::start() {
|
||||
if (_running == true) {
|
||||
// al_warn("record desktop duplication is already running");
|
||||
return AE_NO;
|
||||
}
|
||||
|
||||
if (_inited == false) {
|
||||
return AE_NEED_INIT;
|
||||
}
|
||||
|
||||
_running = true;
|
||||
session_->start();
|
||||
|
||||
return AE_NO;
|
||||
}
|
||||
|
||||
int record_desktop_wgc::pause() {
|
||||
_paused = true;
|
||||
if (session_) session_->pause();
|
||||
return AE_NO;
|
||||
}
|
||||
|
||||
int record_desktop_wgc::resume() {
|
||||
_paused = false;
|
||||
if (session_) session_->resume();
|
||||
return AE_NO;
|
||||
}
|
||||
|
||||
int record_desktop_wgc::stop() {
|
||||
_running = false;
|
||||
|
||||
if (session_) session_->stop();
|
||||
|
||||
return AE_NO;
|
||||
}
|
||||
|
||||
void record_desktop_wgc::on_frame(const wgc_session::wgc_session_frame &frame) {
|
||||
// al_debug("wgc on frame");
|
||||
AVFrame *av_frame = av_frame_alloc();
|
||||
|
||||
av_frame->pts = av_gettime_relative();
|
||||
av_frame->pkt_dts = av_frame->pts;
|
||||
// av_frame->pkt_pts = av_frame->pts;
|
||||
|
||||
av_frame->width = frame.width;
|
||||
av_frame->height = frame.height;
|
||||
av_frame->format = AV_PIX_FMT_BGRA;
|
||||
av_frame->pict_type = AV_PICTURE_TYPE_NONE;
|
||||
av_frame->pkt_size = frame.width * frame.height * 4;
|
||||
|
||||
av_image_fill_arrays(av_frame->data, av_frame->linesize, frame.data,
|
||||
AV_PIX_FMT_BGRA, frame.width, frame.height, 1);
|
||||
|
||||
if (_on_data) _on_data(av_frame);
|
||||
|
||||
av_frame_free(&av_frame);
|
||||
}
|
||||
|
||||
void record_desktop_wgc::clean_up() {
|
||||
_inited = false;
|
||||
|
||||
if (session_) session_->release();
|
||||
|
||||
session_ = nullptr;
|
||||
}
|
||||
|
||||
} // namespace am
|
||||
@@ -1,65 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "export.h"
|
||||
#include "record_desktop.h"
|
||||
|
||||
namespace am {
|
||||
class record_desktop_wgc : public record_desktop,
|
||||
public wgc_session::wgc_session_observer {
|
||||
class wgc_session_module {
|
||||
using func_type_is_supported = bool (*)();
|
||||
using func_type_create_session = wgc_session *(*)();
|
||||
|
||||
public:
|
||||
wgc_session_module() {
|
||||
module_ = ::LoadLibraryA("WGC.dll");
|
||||
if (module_) {
|
||||
func_is_supported_ = (func_type_is_supported)::GetProcAddress(
|
||||
module_, "wgc_is_supported");
|
||||
func_create_session_ = (func_type_create_session)::GetProcAddress(
|
||||
module_, "wgc_create_session");
|
||||
}
|
||||
}
|
||||
~wgc_session_module() {
|
||||
if (module_) ::FreeModule(module_);
|
||||
}
|
||||
|
||||
bool is_supported() const {
|
||||
return func_create_session_ && func_is_supported_();
|
||||
}
|
||||
|
||||
wgc_session *create_session() const {
|
||||
if (!func_create_session_) return nullptr;
|
||||
|
||||
return func_create_session_();
|
||||
}
|
||||
|
||||
private:
|
||||
HMODULE module_ = nullptr;
|
||||
func_type_is_supported func_is_supported_ = nullptr;
|
||||
func_type_create_session func_create_session_ = nullptr;
|
||||
};
|
||||
|
||||
public:
|
||||
record_desktop_wgc();
|
||||
~record_desktop_wgc();
|
||||
|
||||
int init(const RECORD_DESKTOP_RECT &rect, const int fps) override;
|
||||
|
||||
int start() override;
|
||||
int pause() override;
|
||||
int resume() override;
|
||||
int stop() override;
|
||||
|
||||
void on_frame(const wgc_session::wgc_session_frame &frame) override;
|
||||
|
||||
protected:
|
||||
void clean_up() override;
|
||||
|
||||
private:
|
||||
wgc_session *session_ = nullptr;
|
||||
wgc_session_module module_;
|
||||
};
|
||||
} // namespace am
|
||||
202
application/remote_desk/dll/screen_capture_wgc.cpp
Normal file
202
application/remote_desk/dll/screen_capture_wgc.cpp
Normal file
@@ -0,0 +1,202 @@
|
||||
#include "screen_capture_wgc.h"
|
||||
|
||||
#include <d3d11_4.h>
|
||||
#include <winrt/Windows.Foundation.Metadata.h>
|
||||
#include <winrt/Windows.Graphics.Capture.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, HDC hdc, LPRECT lprc,
|
||||
LPARAM data) {
|
||||
MONITORINFOEX info_ex;
|
||||
info_ex.cbSize = sizeof(MONITORINFOEX);
|
||||
|
||||
GetMonitorInfo(hmonitor, &info_ex);
|
||||
|
||||
if (info_ex.dwFlags == DISPLAY_DEVICE_MIRRORING_DRIVER) return true;
|
||||
|
||||
if (info_ex.dwFlags & MONITORINFOF_PRIMARY) {
|
||||
*(HMONITOR *)data = hmonitor;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
HMONITOR GetPrimaryMonitor() {
|
||||
HMONITOR hmonitor = nullptr;
|
||||
|
||||
::EnumDisplayMonitors(NULL, NULL, EnumMonitorProc, (LPARAM)&hmonitor);
|
||||
|
||||
return hmonitor;
|
||||
}
|
||||
|
||||
ScreenCaptureWgc::ScreenCaptureWgc() {}
|
||||
|
||||
ScreenCaptureWgc::~ScreenCaptureWgc() {
|
||||
Stop();
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
bool ScreenCaptureWgc::IsWgcSupported() {
|
||||
try {
|
||||
/* no contract for IGraphicsCaptureItemInterop, verify 10.0.18362.0 */
|
||||
return winrt::Windows::Foundation::Metadata::ApiInformation::
|
||||
IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 8);
|
||||
} catch (const winrt::hresult_error &) {
|
||||
return false;
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int ScreenCaptureWgc::Init(const RECORD_DESKTOP_RECT &rect, const int fps,
|
||||
cb_desktop_data cb) {
|
||||
int error = 0;
|
||||
if (_inited == true) return error;
|
||||
|
||||
_fps = fps;
|
||||
_rect = rect;
|
||||
_start_time = av_gettime_relative();
|
||||
_time_base = {1, AV_TIME_BASE};
|
||||
_pixel_fmt = AV_PIX_FMT_BGRA;
|
||||
_on_data = cb;
|
||||
|
||||
do {
|
||||
if (!IsWgcSupported()) {
|
||||
std::cout << "AE_UNSUPPORT" << std::endl;
|
||||
error = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
session_ = new WgcSessionImpl();
|
||||
if (!session_) {
|
||||
error = -1;
|
||||
std::cout << "AE_WGC_CREATE_CAPTURER_FAILED" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
session_->RegisterObserver(this);
|
||||
|
||||
error = session_->Initialize(GetPrimaryMonitor());
|
||||
|
||||
_inited = true;
|
||||
} while (0);
|
||||
|
||||
if (error != 0) {
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ScreenCaptureWgc::Start() {
|
||||
if (_running == true) {
|
||||
std::cout << "record desktop duplication is already running" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_inited == false) {
|
||||
std::cout << "AE_NEED_INIT" << std::endl;
|
||||
return 4;
|
||||
}
|
||||
|
||||
_running = true;
|
||||
session_->Start();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ScreenCaptureWgc::Pause() {
|
||||
_paused = true;
|
||||
if (session_) session_->Pause();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ScreenCaptureWgc::Resume() {
|
||||
_paused = false;
|
||||
if (session_) session_->Resume();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ScreenCaptureWgc::Stop() {
|
||||
_running = false;
|
||||
|
||||
if (session_) session_->Stop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ScreenCaptureWgc::OnFrame(const WgcSession::wgc_session_frame &frame) {
|
||||
std::cout << "onframe" << std::endl;
|
||||
AVFrame *av_frame = av_frame_alloc();
|
||||
|
||||
av_frame->pts = av_gettime_relative();
|
||||
av_frame->pkt_dts = av_frame->pts;
|
||||
// av_frame->pkt_pts = av_frame->pts;
|
||||
|
||||
av_frame->width = frame.width;
|
||||
av_frame->height = frame.height;
|
||||
av_frame->format = AV_PIX_FMT_BGRA;
|
||||
av_frame->pict_type = AV_PICTURE_TYPE_NONE;
|
||||
av_frame->pkt_size = frame.width * frame.height * 4;
|
||||
|
||||
av_image_fill_arrays(av_frame->data, av_frame->linesize, frame.data,
|
||||
AV_PIX_FMT_BGRA, frame.width, frame.height, 1);
|
||||
|
||||
if (_on_data)
|
||||
_on_data((unsigned char *)av_frame->data, av_frame->pkt_size, frame.width,
|
||||
frame.height);
|
||||
|
||||
// av_frame_free(&av_frame);
|
||||
|
||||
// BGRA to YUV
|
||||
// auto swrCtxBGRA2YUV = sws_getContext(
|
||||
// frame.width, frame.height, AV_PIX_FMT_BGRA, frame.width, frame.height,
|
||||
// AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
|
||||
|
||||
// create BGRA
|
||||
// AVFrame *frame_bgra = av_frame;
|
||||
// AVFrame *frame_bgra = av_frame_alloc();
|
||||
// frame_bgra->format = AV_PIX_FMT_BGRA;
|
||||
// frame_bgra->width = frame.width;
|
||||
// frame_bgra->height = frame.height;
|
||||
// if (av_frame_get_buffer(frame_bgra, 32) < 0) {
|
||||
// printf("Failed: av_frame_get_buffer\n");
|
||||
// return;
|
||||
// }
|
||||
// frame_bgra->data[0] = cropImage;
|
||||
|
||||
// YUV
|
||||
// AVFrame *frame_yuv = av_frame_alloc();
|
||||
// frame_yuv->width = frame.width;
|
||||
// frame_yuv->height = frame.height;
|
||||
// frame_yuv->format = AV_PIX_FMT_YUV420P;
|
||||
|
||||
// uint8_t *picture_buf =
|
||||
// (uint8_t *)av_malloc(frame.width * frame.height * 3 / 2);
|
||||
// if (av_image_fill_arrays(frame_yuv->data, frame_yuv->linesize, picture_buf,
|
||||
// AV_PIX_FMT_YUV420P, frame.width, frame.height,
|
||||
// 1) < 0) {
|
||||
// std::cout << "Failed: av_image_fill_arrays" << std::endl;
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (sws_scale(swrCtxBGRA2YUV, frame_bgra->data, frame_bgra->linesize, 0,
|
||||
// frame.height, frame_yuv->data, frame_yuv->linesize) < 0) {
|
||||
// std::cout << "BGRA to YUV failed" << std::endl;
|
||||
// return;
|
||||
// }
|
||||
|
||||
// frame_yuv->pts = av_gettime();
|
||||
|
||||
// if (_on_data)
|
||||
// _on_data((unsigned char *)frame_yuv->data,
|
||||
// frame.width * frame.height * 3 / 2, frame.width, frame.height);
|
||||
}
|
||||
|
||||
void ScreenCaptureWgc::CleanUp() {
|
||||
_inited = false;
|
||||
|
||||
if (session_) session_->Release();
|
||||
|
||||
session_ = nullptr;
|
||||
}
|
||||
76
application/remote_desk/dll/screen_capture_wgc.h
Normal file
76
application/remote_desk/dll/screen_capture_wgc.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#ifndef _SCREEN_CAPTURE_WGC_H_
|
||||
#define _SCREEN_CAPTURE_WGC_H_
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "wgc_session.h"
|
||||
#include "wgc_session_impl.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec\avcodec.h>
|
||||
#include <libavfilter\avfilter.h>
|
||||
#include <libavformat\avformat.h>
|
||||
#include <libavutil\imgutils.h>
|
||||
#include <libavutil\time.h>
|
||||
#include <libswscale/swscale.h>
|
||||
}
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
typedef struct {
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
} RECORD_DESKTOP_RECT;
|
||||
|
||||
typedef std::function<void(unsigned char *, int, int, int)> cb_desktop_data;
|
||||
typedef std::function<void(int)> cb_desktop_error;
|
||||
|
||||
class ScreenCaptureWgc : public WgcSession::wgc_session_observer {
|
||||
public:
|
||||
ScreenCaptureWgc();
|
||||
~ScreenCaptureWgc();
|
||||
|
||||
public:
|
||||
bool IsWgcSupported();
|
||||
|
||||
int Init(const RECORD_DESKTOP_RECT &rect, const int fps, cb_desktop_data cb);
|
||||
|
||||
int Start();
|
||||
int Pause();
|
||||
int Resume();
|
||||
int Stop();
|
||||
|
||||
void OnFrame(const WgcSession::wgc_session_frame &frame);
|
||||
|
||||
protected:
|
||||
void CleanUp();
|
||||
|
||||
private:
|
||||
WgcSession *session_ = nullptr;
|
||||
|
||||
std::atomic_bool _running;
|
||||
std::atomic_bool _paused;
|
||||
std::atomic_bool _inited;
|
||||
|
||||
std::thread _thread;
|
||||
|
||||
std::string _device_name;
|
||||
|
||||
RECORD_DESKTOP_RECT _rect;
|
||||
|
||||
int _fps;
|
||||
|
||||
cb_desktop_data _on_data;
|
||||
cb_desktop_error _on_error;
|
||||
|
||||
AVRational _time_base;
|
||||
int64_t _start_time;
|
||||
AVPixelFormat _pixel_fmt;
|
||||
};
|
||||
|
||||
#endif
|
||||
40
application/remote_desk/dll/wgc_session.h
Normal file
40
application/remote_desk/dll/wgc_session.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef _WGC_SESSION_H_
|
||||
#define _WGC_SESSION_H_
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
class WgcSession {
|
||||
public:
|
||||
struct wgc_session_frame {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int row_pitch;
|
||||
|
||||
const unsigned char *data;
|
||||
};
|
||||
|
||||
class wgc_session_observer {
|
||||
public:
|
||||
virtual ~wgc_session_observer() {}
|
||||
virtual void OnFrame(const wgc_session_frame &frame) = 0;
|
||||
};
|
||||
|
||||
public:
|
||||
virtual void Release() = 0;
|
||||
|
||||
virtual int Initialize(HWND hwnd) = 0;
|
||||
virtual int Initialize(HMONITOR hmonitor) = 0;
|
||||
|
||||
virtual void RegisterObserver(wgc_session_observer *observer) = 0;
|
||||
|
||||
virtual int Start() = 0;
|
||||
virtual int Stop() = 0;
|
||||
|
||||
virtual int Pause() = 0;
|
||||
virtual int Resume() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~WgcSession(){};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,11 +1,17 @@
|
||||
#include "pch.h"
|
||||
#include "wgc_session_impl.h"
|
||||
|
||||
#include <Windows.Graphics.Capture.Interop.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#define CHECK_INIT \
|
||||
if (!is_initialized_) \
|
||||
return AM_ERROR::AE_NEED_INIT
|
||||
if (!is_initialized_) { \
|
||||
std::cout << "AE_NEED_INIT" << std::endl; \
|
||||
return 4; \
|
||||
}
|
||||
|
||||
#define CHECK_CLOSED \
|
||||
if (cleaned_.load() == true) { \
|
||||
@@ -17,45 +23,42 @@ HRESULT __stdcall CreateDirect3D11DeviceFromDXGIDevice(
|
||||
::IDXGIDevice *dxgiDevice, ::IInspectable **graphicsDevice);
|
||||
}
|
||||
|
||||
namespace am {
|
||||
WgcSessionImpl::WgcSessionImpl() {}
|
||||
|
||||
wgc_session_impl::wgc_session_impl() {}
|
||||
|
||||
wgc_session_impl::~wgc_session_impl() {
|
||||
stop();
|
||||
cleanup();
|
||||
WgcSessionImpl::~WgcSessionImpl() {
|
||||
Stop();
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
void wgc_session_impl::release() { delete this; }
|
||||
void WgcSessionImpl::Release() { delete this; }
|
||||
|
||||
int wgc_session_impl::initialize(HWND hwnd) {
|
||||
int WgcSessionImpl::Initialize(HWND hwnd) {
|
||||
std::lock_guard locker(lock_);
|
||||
|
||||
target_.hwnd = hwnd;
|
||||
target_.is_window = true;
|
||||
return initialize();
|
||||
return Initialize();
|
||||
}
|
||||
|
||||
int wgc_session_impl::initialize(HMONITOR hmonitor) {
|
||||
int WgcSessionImpl::Initialize(HMONITOR hmonitor) {
|
||||
std::lock_guard locker(lock_);
|
||||
|
||||
target_.hmonitor = hmonitor;
|
||||
target_.is_window = false;
|
||||
return initialize();
|
||||
return Initialize();
|
||||
}
|
||||
|
||||
void wgc_session_impl::register_observer(wgc_session_observer *observer) {
|
||||
void WgcSessionImpl::RegisterObserver(wgc_session_observer *observer) {
|
||||
std::lock_guard locker(lock_);
|
||||
observer_ = observer;
|
||||
}
|
||||
|
||||
int wgc_session_impl::start() {
|
||||
int WgcSessionImpl::Start() {
|
||||
std::lock_guard locker(lock_);
|
||||
|
||||
if (is_running_)
|
||||
return AM_ERROR::AE_NO;
|
||||
if (is_running_) return 0;
|
||||
|
||||
int error = AM_ERROR::AE_WGC_CREATE_CAPTURER_FAILED;
|
||||
int error = 1;
|
||||
|
||||
CHECK_INIT;
|
||||
try {
|
||||
@@ -70,106 +73,95 @@ int wgc_session_impl::start() {
|
||||
capture_session_ = capture_framepool_.CreateCaptureSession(capture_item_);
|
||||
capture_frame_size_ = current_size;
|
||||
capture_framepool_trigger_ = capture_framepool_.FrameArrived(
|
||||
winrt::auto_revoke, {this, &wgc_session_impl::on_frame});
|
||||
winrt::auto_revoke, {this, &WgcSessionImpl::OnFrame});
|
||||
capture_close_trigger_ = capture_item_.Closed(
|
||||
winrt::auto_revoke, {this, &wgc_session_impl::on_closed});
|
||||
winrt::auto_revoke, {this, &WgcSessionImpl::OnClosed});
|
||||
}
|
||||
|
||||
if (!capture_framepool_)
|
||||
throw std::exception();
|
||||
if (!capture_framepool_) throw std::exception();
|
||||
|
||||
is_running_ = true;
|
||||
|
||||
// we do not need to crate a thread to enter a message loop coz we use
|
||||
// CreateFreeThreaded instead of Create to create a capture frame pool,
|
||||
// we need to test the performance later
|
||||
// loop_ = std::thread(std::bind(&wgc_session_impl::message_func, this));
|
||||
// loop_ = std::thread(std::bind(&WgcSessionImpl::message_func, this));
|
||||
|
||||
capture_session_.StartCapture();
|
||||
|
||||
error = AM_ERROR::AE_NO;
|
||||
error = 0;
|
||||
} catch (winrt::hresult_error) {
|
||||
return AM_ERROR::AE_WGC_CREATE_CAPTURER_FAILED;
|
||||
std::cout << "AE_WGC_CREATE_CAPTURER_FAILED" << std::endl;
|
||||
return 86;
|
||||
} catch (...) {
|
||||
return AM_ERROR::AE_WGC_CREATE_CAPTURER_FAILED;
|
||||
return 86;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int wgc_session_impl::stop() {
|
||||
int WgcSessionImpl::Stop() {
|
||||
std::lock_guard locker(lock_);
|
||||
|
||||
CHECK_INIT;
|
||||
|
||||
is_running_ = false;
|
||||
|
||||
if (loop_.joinable())
|
||||
loop_.join();
|
||||
// if (loop_.joinable()) loop_.join();
|
||||
|
||||
if (capture_framepool_trigger_)
|
||||
capture_framepool_trigger_.revoke();
|
||||
if (capture_framepool_trigger_) capture_framepool_trigger_.revoke();
|
||||
|
||||
if (capture_session_) {
|
||||
capture_session_.Close();
|
||||
capture_session_ = nullptr;
|
||||
}
|
||||
|
||||
return AM_ERROR::AE_NO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wgc_session_impl::pause() {
|
||||
int WgcSessionImpl::Pause() {
|
||||
std::lock_guard locker(lock_);
|
||||
|
||||
CHECK_INIT;
|
||||
return AM_ERROR::AE_NO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wgc_session_impl::resume() {
|
||||
int WgcSessionImpl::Resume() {
|
||||
std::lock_guard locker(lock_);
|
||||
|
||||
CHECK_INIT;
|
||||
return AM_ERROR::AE_NO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto wgc_session_impl::create_d3d11_device() {
|
||||
auto create_d3d_device = [](D3D_DRIVER_TYPE const type,
|
||||
winrt::com_ptr<ID3D11Device> &device) {
|
||||
WINRT_ASSERT(!device);
|
||||
auto WgcSessionImpl::CreateD3D11Device() {
|
||||
winrt::com_ptr<ID3D11Device> d3d_device;
|
||||
HRESULT hr;
|
||||
|
||||
WINRT_ASSERT(!d3d_device);
|
||||
|
||||
D3D_DRIVER_TYPE type = D3D_DRIVER_TYPE_HARDWARE;
|
||||
UINT flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
|
||||
|
||||
//#ifdef _DEBUG
|
||||
// flags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
//#endif
|
||||
|
||||
return ::D3D11CreateDevice(nullptr, type, nullptr, flags, nullptr, 0,
|
||||
D3D11_SDK_VERSION, device.put(), nullptr,
|
||||
nullptr);
|
||||
};
|
||||
auto create_d3d_device_wrapper = [&create_d3d_device]() {
|
||||
winrt::com_ptr<ID3D11Device> device;
|
||||
HRESULT hr = create_d3d_device(D3D_DRIVER_TYPE_HARDWARE, device);
|
||||
hr = D3D11CreateDevice(nullptr, type, nullptr, flags, nullptr, 0,
|
||||
D3D11_SDK_VERSION, d3d_device.put(), nullptr, nullptr);
|
||||
|
||||
if (DXGI_ERROR_UNSUPPORTED == hr) {
|
||||
hr = create_d3d_device(D3D_DRIVER_TYPE_WARP, device);
|
||||
// change D3D_DRIVER_TYPE
|
||||
D3D_DRIVER_TYPE type = D3D_DRIVER_TYPE_WARP;
|
||||
hr = D3D11CreateDevice(nullptr, type, nullptr, flags, nullptr, 0,
|
||||
D3D11_SDK_VERSION, d3d_device.put(), nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
winrt::check_hresult(hr);
|
||||
return device;
|
||||
};
|
||||
|
||||
auto d3d_device = create_d3d_device_wrapper();
|
||||
auto dxgi_device = d3d_device.as<IDXGIDevice>();
|
||||
|
||||
winrt::com_ptr<::IInspectable> d3d11_device;
|
||||
winrt::check_hresult(CreateDirect3D11DeviceFromDXGIDevice(
|
||||
dxgi_device.get(), d3d11_device.put()));
|
||||
d3d_device.as<IDXGIDevice>().get(), d3d11_device.put()));
|
||||
return d3d11_device
|
||||
.as<winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice>();
|
||||
}
|
||||
|
||||
auto wgc_session_impl::create_capture_item(HWND hwnd) {
|
||||
auto WgcSessionImpl::CreateCaptureItemForWindow(HWND hwnd) {
|
||||
auto activation_factory = winrt::get_activation_factory<
|
||||
winrt::Windows::Graphics::Capture::GraphicsCaptureItem>();
|
||||
auto interop_factory = activation_factory.as<IGraphicsCaptureItemInterop>();
|
||||
@@ -181,7 +173,7 @@ auto wgc_session_impl::create_capture_item(HWND hwnd) {
|
||||
return item;
|
||||
}
|
||||
|
||||
auto wgc_session_impl::create_capture_item(HMONITOR hmonitor) {
|
||||
auto WgcSessionImpl::CreateCaptureItemForMonitor(HMONITOR hmonitor) {
|
||||
auto activation_factory = winrt::get_activation_factory<
|
||||
winrt::Windows::Graphics::Capture::GraphicsCaptureItem>();
|
||||
auto interop_factory = activation_factory.as<IGraphicsCaptureItemInterop>();
|
||||
@@ -193,10 +185,9 @@ auto wgc_session_impl::create_capture_item(HMONITOR hmonitor) {
|
||||
return item;
|
||||
}
|
||||
|
||||
HRESULT wgc_session_impl::create_mapped_texture(
|
||||
HRESULT WgcSessionImpl::CreateMappedTexture(
|
||||
winrt::com_ptr<ID3D11Texture2D> src_texture, unsigned int width,
|
||||
unsigned int height) {
|
||||
|
||||
D3D11_TEXTURE2D_DESC src_desc;
|
||||
src_texture->GetDesc(&src_desc);
|
||||
D3D11_TEXTURE2D_DESC map_desc;
|
||||
@@ -211,13 +202,14 @@ HRESULT wgc_session_impl::create_mapped_texture(
|
||||
map_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
map_desc.MiscFlags = 0;
|
||||
|
||||
auto d3dDevice = get_dxgi_interface<ID3D11Device>(d3d11_direct_device_);
|
||||
auto d3dDevice =
|
||||
GetDXGIInterfaceFromObject<ID3D11Device>(d3d11_direct_device_);
|
||||
|
||||
return d3dDevice->CreateTexture2D(&map_desc, nullptr,
|
||||
d3d11_texture_mapped_.put());
|
||||
}
|
||||
|
||||
void wgc_session_impl::on_frame(
|
||||
void WgcSessionImpl::OnFrame(
|
||||
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const &sender,
|
||||
winrt::Windows::Foundation::IInspectable const &args) {
|
||||
std::lock_guard locker(lock_);
|
||||
@@ -240,10 +232,10 @@ void wgc_session_impl::on_frame(
|
||||
// copy to mapped texture
|
||||
{
|
||||
auto frame_captured =
|
||||
get_dxgi_interface<ID3D11Texture2D>(frame.Surface());
|
||||
GetDXGIInterfaceFromObject<ID3D11Texture2D>(frame.Surface());
|
||||
|
||||
if (!d3d11_texture_mapped_ || is_new_size)
|
||||
create_mapped_texture(frame_captured);
|
||||
CreateMappedTexture(frame_captured);
|
||||
|
||||
d3d11_device_context_->CopyResource(d3d11_texture_mapped_.get(),
|
||||
frame_captured.get());
|
||||
@@ -262,61 +254,12 @@ void wgc_session_impl::on_frame(
|
||||
|
||||
// copy data from map_result.pData
|
||||
if (map_result.pData && observer_) {
|
||||
observer_->on_frame(wgc_session_frame{
|
||||
observer_->OnFrame(wgc_session_frame{
|
||||
static_cast<unsigned int>(frame_size.Width),
|
||||
static_cast<unsigned int>(frame_size.Height), map_result.RowPitch,
|
||||
const_cast<const unsigned char *>(
|
||||
(unsigned char *)map_result.pData)});
|
||||
}
|
||||
#if 0
|
||||
if (map_result.pData) {
|
||||
static unsigned char *buffer = nullptr;
|
||||
if (buffer && is_new_size)
|
||||
delete[] buffer;
|
||||
|
||||
if (!buffer)
|
||||
buffer = new unsigned char[frame_size.Width * frame_size.Height * 4];
|
||||
|
||||
int dstRowPitch = frame_size.Width * 4;
|
||||
for (int h = 0; h < frame_size.Height; h++) {
|
||||
memcpy_s(buffer + h * dstRowPitch, dstRowPitch,
|
||||
(BYTE *)map_result.pData + h * map_result.RowPitch,
|
||||
min(map_result.RowPitch, dstRowPitch));
|
||||
}
|
||||
|
||||
BITMAPINFOHEADER bi;
|
||||
|
||||
bi.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bi.biWidth = frame_size.Width;
|
||||
bi.biHeight = frame_size.Height * (-1);
|
||||
bi.biPlanes = 1;
|
||||
bi.biBitCount = 32; // should get from system color bits
|
||||
bi.biCompression = BI_RGB;
|
||||
bi.biSizeImage = 0;
|
||||
bi.biXPelsPerMeter = 0;
|
||||
bi.biYPelsPerMeter = 0;
|
||||
bi.biClrUsed = 0;
|
||||
bi.biClrImportant = 0;
|
||||
|
||||
BITMAPFILEHEADER bf;
|
||||
bf.bfType = 0x4d42;
|
||||
bf.bfReserved1 = 0;
|
||||
bf.bfReserved2 = 0;
|
||||
bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
||||
bf.bfSize = bf.bfOffBits + frame_size.Width * frame_size.Height * 4;
|
||||
|
||||
FILE *fp = nullptr;
|
||||
|
||||
fopen_s(&fp, ".\\save.bmp", "wb+");
|
||||
|
||||
fwrite(&bf, 1, sizeof(bf), fp);
|
||||
fwrite(&bi, 1, sizeof(bi), fp);
|
||||
fwrite(buffer, 1, frame_size.Width * frame_size.Height * 4, fp);
|
||||
|
||||
fflush(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
#endif
|
||||
|
||||
d3d11_device_context_->Unmap(d3d11_texture_mapped_.get(), 0);
|
||||
}
|
||||
@@ -330,41 +273,44 @@ void wgc_session_impl::on_frame(
|
||||
}
|
||||
}
|
||||
|
||||
void wgc_session_impl::on_closed(
|
||||
void WgcSessionImpl::OnClosed(
|
||||
winrt::Windows::Graphics::Capture::GraphicsCaptureItem const &,
|
||||
winrt::Windows::Foundation::IInspectable const &) {
|
||||
OutputDebugStringW(L"wgc_session_impl::on_closed");
|
||||
OutputDebugStringW(L"WgcSessionImpl::OnClosed");
|
||||
}
|
||||
|
||||
int wgc_session_impl::initialize() {
|
||||
if (is_initialized_)
|
||||
return AM_ERROR::AE_NO;
|
||||
int WgcSessionImpl::Initialize() {
|
||||
if (is_initialized_) return 0;
|
||||
|
||||
if (!(d3d11_direct_device_ = create_d3d11_device()))
|
||||
return AM_ERROR::AE_D3D_CREATE_DEVICE_FAILED;
|
||||
if (!(d3d11_direct_device_ = CreateD3D11Device())) {
|
||||
std::cout << "AE_D3D_CREATE_DEVICE_FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
try {
|
||||
if (target_.is_window)
|
||||
capture_item_ = create_capture_item(target_.hwnd);
|
||||
capture_item_ = CreateCaptureItemForWindow(target_.hwnd);
|
||||
else
|
||||
capture_item_ = create_capture_item(target_.hmonitor);
|
||||
capture_item_ = CreateCaptureItemForMonitor(target_.hmonitor);
|
||||
|
||||
// Set up
|
||||
auto d3d11_device = get_dxgi_interface<ID3D11Device>(d3d11_direct_device_);
|
||||
auto d3d11_device =
|
||||
GetDXGIInterfaceFromObject<ID3D11Device>(d3d11_direct_device_);
|
||||
d3d11_device->GetImmediateContext(d3d11_device_context_.put());
|
||||
|
||||
} catch (winrt::hresult_error) {
|
||||
return AM_ERROR::AE_WGC_CREATE_CAPTURER_FAILED;
|
||||
std::cout << "AE_WGC_CREATE_CAPTURER_FAILED" << std::endl;
|
||||
return 86;
|
||||
} catch (...) {
|
||||
return AM_ERROR::AE_WGC_CREATE_CAPTURER_FAILED;
|
||||
return 86;
|
||||
}
|
||||
|
||||
is_initialized_ = true;
|
||||
|
||||
return AM_ERROR::AE_NO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wgc_session_impl::cleanup() {
|
||||
void WgcSessionImpl::CleanUp() {
|
||||
std::lock_guard locker(lock_);
|
||||
|
||||
auto expected = false;
|
||||
@@ -372,11 +318,9 @@ void wgc_session_impl::cleanup() {
|
||||
capture_close_trigger_.revoke();
|
||||
capture_framepool_trigger_.revoke();
|
||||
|
||||
if (capture_framepool_)
|
||||
capture_framepool_.Close();
|
||||
if (capture_framepool_) capture_framepool_.Close();
|
||||
|
||||
if (capture_session_)
|
||||
capture_session_.Close();
|
||||
if (capture_session_) capture_session_.Close();
|
||||
|
||||
capture_framepool_ = nullptr;
|
||||
capture_session_ = nullptr;
|
||||
@@ -391,35 +335,32 @@ LRESULT CALLBACK WindowProc(HWND window, UINT message, WPARAM w_param,
|
||||
return DefWindowProc(window, message, w_param, l_param);
|
||||
}
|
||||
|
||||
void wgc_session_impl::message_func() {
|
||||
const std::wstring kClassName = L"am_fake_window";
|
||||
// void WgcSessionImpl::message_func() {
|
||||
// const std::wstring kClassName = L"am_fake_window";
|
||||
|
||||
WNDCLASS wc = {};
|
||||
// WNDCLASS wc = {};
|
||||
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW);
|
||||
wc.lpszClassName = kClassName.c_str();
|
||||
// wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
// wc.lpfnWndProc = DefWindowProc;
|
||||
// wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
// wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW);
|
||||
// wc.lpszClassName = kClassName.c_str();
|
||||
|
||||
if (!::RegisterClassW(&wc))
|
||||
return;
|
||||
// if (!::RegisterClassW(&wc)) return;
|
||||
|
||||
hwnd_ = ::CreateWindowW(kClassName.c_str(), nullptr, WS_OVERLAPPEDWINDOW, 0,
|
||||
0, 0, 0, nullptr, nullptr, nullptr, nullptr);
|
||||
MSG msg;
|
||||
while (is_running_) {
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
if (!is_running_)
|
||||
break;
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
Sleep(10);
|
||||
}
|
||||
// hwnd_ = ::CreateWindowW(kClassName.c_str(), nullptr, WS_OVERLAPPEDWINDOW,
|
||||
// 0,
|
||||
// 0, 0, 0, nullptr, nullptr, nullptr, nullptr);
|
||||
// MSG msg;
|
||||
// while (is_running_) {
|
||||
// while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
// if (!is_running_) break;
|
||||
// TranslateMessage(&msg);
|
||||
// DispatchMessage(&msg);
|
||||
// }
|
||||
// Sleep(10);
|
||||
// }
|
||||
|
||||
::CloseWindow(hwnd_);
|
||||
::DestroyWindow(hwnd_);
|
||||
}
|
||||
|
||||
} // namespace am
|
||||
// ::CloseWindow(hwnd_);
|
||||
// ::DestroyWindow(hwnd_);
|
||||
// }
|
||||
@@ -1,15 +1,31 @@
|
||||
#pragma once
|
||||
#ifndef _WGC_SESSION_IMPL_H_
|
||||
#define _WGC_SESSION_IMPL_H_
|
||||
|
||||
#include <d3d11_4.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Graphics.Capture.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
namespace am {
|
||||
class wgc_session_impl : public wgc_session {
|
||||
#include "wgc_session.h"
|
||||
|
||||
class WgcSessionImpl : public WgcSession {
|
||||
struct __declspec(uuid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1"))
|
||||
IDirect3DDxgiInterfaceAccess : ::IUnknown {
|
||||
virtual HRESULT __stdcall GetInterface(GUID const &id, void **object) = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline auto GetDXGIInterfaceFromObject(
|
||||
winrt::Windows::Foundation::IInspectable const &object) {
|
||||
auto access = object.as<IDirect3DDxgiInterfaceAccess>();
|
||||
winrt::com_ptr<T> result;
|
||||
winrt::check_hresult(
|
||||
access->GetInterface(winrt::guid_of<T>(), result.put_void()));
|
||||
return result;
|
||||
}
|
||||
|
||||
struct {
|
||||
union {
|
||||
HWND hwnd;
|
||||
@@ -19,44 +35,41 @@ class wgc_session_impl : public wgc_session {
|
||||
} target_{0};
|
||||
|
||||
public:
|
||||
wgc_session_impl();
|
||||
~wgc_session_impl() override;
|
||||
WgcSessionImpl();
|
||||
~WgcSessionImpl() override;
|
||||
|
||||
public:
|
||||
void release() override;
|
||||
void Release() override;
|
||||
|
||||
int initialize(HWND hwnd) override;
|
||||
int initialize(HMONITOR hmonitor) override;
|
||||
int Initialize(HWND hwnd) override;
|
||||
int Initialize(HMONITOR hmonitor) override;
|
||||
|
||||
void register_observer(wgc_session_observer *observer) override;
|
||||
void RegisterObserver(wgc_session_observer *observer) override;
|
||||
|
||||
int start() override;
|
||||
int stop() override;
|
||||
int Start() override;
|
||||
int Stop() override;
|
||||
|
||||
int pause() override;
|
||||
int resume() override;
|
||||
int Pause() override;
|
||||
int Resume() override;
|
||||
|
||||
private:
|
||||
auto create_d3d11_device();
|
||||
auto create_capture_item(HWND hwnd);
|
||||
auto create_capture_item(HMONITOR hmonitor);
|
||||
template <typename T>
|
||||
auto
|
||||
get_dxgi_interface(winrt::Windows::Foundation::IInspectable const &object);
|
||||
HRESULT create_mapped_texture(winrt::com_ptr<ID3D11Texture2D> src_texture,
|
||||
unsigned int width = 0,
|
||||
unsigned int height = 0);
|
||||
void
|
||||
on_frame(winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const
|
||||
auto CreateD3D11Device();
|
||||
auto CreateCaptureItemForWindow(HWND hwnd);
|
||||
auto CreateCaptureItemForMonitor(HMONITOR hmonitor);
|
||||
|
||||
HRESULT CreateMappedTexture(winrt::com_ptr<ID3D11Texture2D> src_texture,
|
||||
unsigned int width = 0, unsigned int height = 0);
|
||||
void OnFrame(
|
||||
winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool const
|
||||
&sender,
|
||||
winrt::Windows::Foundation::IInspectable const &args);
|
||||
void on_closed(winrt::Windows::Graphics::Capture::GraphicsCaptureItem const &,
|
||||
void OnClosed(winrt::Windows::Graphics::Capture::GraphicsCaptureItem const &,
|
||||
winrt::Windows::Foundation::IInspectable const &);
|
||||
|
||||
int initialize();
|
||||
void cleanup();
|
||||
int Initialize();
|
||||
void CleanUp();
|
||||
|
||||
void message_func();
|
||||
// void message_func();
|
||||
|
||||
private:
|
||||
std::mutex lock_;
|
||||
@@ -90,15 +103,14 @@ private:
|
||||
HWND hwnd_ = nullptr;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline auto wgc_session_impl::get_dxgi_interface(
|
||||
winrt::Windows::Foundation::IInspectable const &object) {
|
||||
auto access = object.as<IDirect3DDxgiInterfaceAccess>();
|
||||
winrt::com_ptr<T> result;
|
||||
winrt::check_hresult(
|
||||
access->GetInterface(winrt::guid_of<T>(), result.put_void()));
|
||||
return result;
|
||||
}
|
||||
// template <typename T>
|
||||
// inline auto WgcSessionImpl::GetDXGIInterfaceFromObject(
|
||||
// winrt::Windows::Foundation::IInspectable const &object) {
|
||||
// auto access = object.as<IDirect3DDxgiInterfaceAccess>();
|
||||
// winrt::com_ptr<T> result;
|
||||
// winrt::check_hresult(
|
||||
// access->GetInterface(winrt::guid_of<T>(), result.put_void()));
|
||||
// return result;
|
||||
// }
|
||||
|
||||
|
||||
} // namespace am
|
||||
#endif
|
||||
@@ -11,9 +11,9 @@ add_requires("spdlog 1.11.0", "ffmpeg 5.1.2", {system = false})
|
||||
add_defines("UNICODE")
|
||||
|
||||
if is_os("windows") then
|
||||
-- add_ldflags("/SUBSYSTEM:CONSOLE")
|
||||
add_ldflags("/SUBSYSTEM:CONSOLE")
|
||||
add_links("Shell32", "windowsapp", "dwmapi", "User32", "kernel32")
|
||||
-- add_requires("vcpkg::sdl2")
|
||||
add_requires("vcpkg::sdl2 2.26.4")
|
||||
elseif is_os("linux") then
|
||||
add_links("pthread")
|
||||
set_config("cxxflags", "-fPIC")
|
||||
@@ -34,7 +34,11 @@ target("remote_desk")
|
||||
add_deps("projectx")
|
||||
add_packages("log")
|
||||
add_packages("ffmpeg")
|
||||
add_packages("vcpkg::sdl2")
|
||||
add_links("avfilter", "avdevice", "avformat", "avcodec", "swscale", "swresample", "avutil")
|
||||
add_files("dll/*.cpp")
|
||||
add_includedirs("../../src/interface")
|
||||
-- add_links("SDL2main", "SDL2-static")
|
||||
add_links("SDL2-static", "SDL2main", "Shell32", "gdi32", "winmm",
|
||||
"setupapi", "version", "WindowsApp", "Imm32", "avutil")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user