Fix screen capture on MacOS

This commit is contained in:
dijunkun
2023-12-01 17:16:38 +08:00
parent 5febe99bc2
commit 47a2dc85f9
7 changed files with 65 additions and 171 deletions

View File

@@ -49,6 +49,8 @@ extern "C" {
#include "screen_capture_wgc.h"
#elif __linux__
#include "screen_capture_x11.h"
#elif __APPLE__
#include "screen_capture_avf.h"
#endif
#include "../../thirdparty/projectx/src/interface/x.h"
@@ -157,6 +159,8 @@ static bool done = false;
ScreenCaptureWgc *screen_capture = nullptr;
#elif __linux__
ScreenCaptureX11 *screen_capture = nullptr;
#elif __APPLE__
ScreenCaptureAvf *screen_capture = nullptr;
#endif
char *nv12_buffer = nullptr;
@@ -824,6 +828,31 @@ int main() {
rect.right = 0;
rect.bottom = 0;
last_frame_time_ = std::chrono::high_resolution_clock::now();
screen_capture->Init(
rect, 60,
[](unsigned char *data, int size, int width, int height) -> void {
auto now_time = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> duration =
now_time - last_frame_time_;
auto tc = duration.count() * 1000;
if (tc >= 0) {
SendData(peer_server, DATA_TYPE::VIDEO, (const char *)data,
NV12_BUFFER_SIZE);
last_frame_time_ = now_time;
}
});
screen_capture->Start();
#elif __APPLE__
screen_capture = new ScreenCaptureAvf();
RECORD_DESKTOP_RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = 0;
rect.bottom = 0;
last_frame_time_ = std::chrono::high_resolution_clock::now();
screen_capture->Init(
rect, 60,

View File

@@ -1,4 +1,4 @@
#include "screen_capture_x11.h"
#include "screen_capture_avf.h"
#include <iostream>
@@ -7,21 +7,17 @@
#define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2
unsigned char nv12_buffer_[NV12_BUFFER_SIZE];
ScreenCaptureX11::ScreenCaptureX11() {}
ScreenCaptureAvf::ScreenCaptureAvf() {}
ScreenCaptureX11::~ScreenCaptureX11()
{
if (capture_thread_->joinable())
{
ScreenCaptureAvf::~ScreenCaptureAvf() {
if (capture_thread_->joinable()) {
capture_thread_->join();
}
}
int ScreenCaptureX11::Init(const RECORD_DESKTOP_RECT &rect, const int fps,
cb_desktop_data cb)
{
if (cb)
{
int ScreenCaptureAvf::Init(const RECORD_DESKTOP_RECT &rect, const int fps,
cb_desktop_data cb) {
if (cb) {
_on_data = cb;
}
@@ -37,33 +33,29 @@ int ScreenCaptureX11::Init(const RECORD_DESKTOP_RECT &rect, const int fps,
// Video frame size. The default is to capture the full screen
// av_dict_set(&options_, "video_size", "1280x720", 0);
ifmt_ = (AVInputFormat *)av_find_input_format("avfoundation");
if (!ifmt_)
{
if (!ifmt_) {
printf("Couldn't find_input_format\n");
}
// Grab at position 10,20
if (avformat_open_input(&pFormatCtx_, "Capture screen 0", ifmt_, &options_) != 0)
{
if (avformat_open_input(&pFormatCtx_, "Capture screen 0", ifmt_, &options_) !=
0) {
printf("Couldn't open input stream.\n");
return -1;
}
if (avformat_find_stream_info(pFormatCtx_, NULL) < 0)
{
if (avformat_find_stream_info(pFormatCtx_, NULL) < 0) {
printf("Couldn't find stream information.\n");
return -1;
}
videoindex_ = -1;
for (i_ = 0; i_ < pFormatCtx_->nb_streams; i_++)
if (pFormatCtx_->streams[i_]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
if (pFormatCtx_->streams[i_]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoindex_ = i_;
break;
}
if (videoindex_ == -1)
{
if (videoindex_ == -1) {
printf("Didn't find a video stream.\n");
return -1;
}
@@ -74,13 +66,11 @@ int ScreenCaptureX11::Init(const RECORD_DESKTOP_RECT &rect, const int fps,
avcodec_parameters_to_context(pCodecCtx_, pCodecParam_);
pCodec_ = const_cast<AVCodec *>(avcodec_find_decoder(pCodecCtx_->codec_id));
if (pCodec_ == NULL)
{
if (pCodec_ == NULL) {
printf("Codec not found.\n");
return -1;
}
if (avcodec_open2(pCodecCtx_, pCodec_, NULL) < 0)
{
if (avcodec_open2(pCodecCtx_, pCodec_, NULL) < 0) {
printf("Could not open codec.\n");
return -1;
}
@@ -105,10 +95,8 @@ int ScreenCaptureX11::Init(const RECORD_DESKTOP_RECT &rect, const int fps,
return 0;
}
int ScreenCaptureX11::Start()
{
capture_thread_.reset(new std::thread([this]()
{
int ScreenCaptureAvf::Start() {
capture_thread_.reset(new std::thread([this]() {
while (1) {
if (av_read_frame(pFormatCtx_, packet_) >= 0) {
if (packet_->stream_index == videoindex_) {
@@ -131,17 +119,18 @@ int ScreenCaptureX11::Start()
}
}
}
} }));
}
}));
return 0;
}
int ScreenCaptureX11::Pause() { return 0; }
int ScreenCaptureAvf::Pause() { return 0; }
int ScreenCaptureX11::Resume() { return 0; }
int ScreenCaptureAvf::Resume() { return 0; }
int ScreenCaptureX11::Stop() { return 0; }
int ScreenCaptureAvf::Stop() { return 0; }
void ScreenCaptureX11::OnFrame() {}
void ScreenCaptureAvf::OnFrame() {}
void ScreenCaptureX11::CleanUp() {}
void ScreenCaptureAvf::CleanUp() {}

View File

@@ -1,5 +1,11 @@
#ifndef _SCREEN_CAPTURE_X11_H_
#define _SCREEN_CAPTURE_X11_H_
/*
* @Author: DI JUNKUN
* @Date: 2023-12-01
* Copyright (c) 2023 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _SCREEN_CAPTURE_AVF_H_
#define _SCREEN_CAPTURE_AVF_H_
#include <atomic>
#include <functional>
@@ -28,10 +34,10 @@ typedef struct {
typedef std::function<void(unsigned char *, int, int, int)> cb_desktop_data;
typedef std::function<void(int)> cb_desktop_error;
class ScreenCaptureX11 {
class ScreenCaptureAvf {
public:
ScreenCaptureX11();
~ScreenCaptureX11();
ScreenCaptureAvf();
~ScreenCaptureAvf();
public:
int Init(const RECORD_DESKTOP_RECT &rect, const int fps, cb_desktop_data cb);

View File

@@ -1,37 +0,0 @@
#ifndef _X11_SESSION_H_
#define _X11_SESSION_H_
class X11Session {
public:
struct x11_session_frame {
unsigned int width;
unsigned int height;
unsigned int row_pitch;
const unsigned char *data;
};
class x11_session_observer {
public:
virtual ~x11_session_observer() {}
virtual void OnFrame(const x11_session_frame &frame) = 0;
};
public:
virtual void Release() = 0;
virtual int Initialize() = 0;
virtual void RegisterObserver(x11_session_observer *observer) = 0;
virtual int Start() = 0;
virtual int Stop() = 0;
virtual int Pause() = 0;
virtual int Resume() = 0;
protected:
virtual ~X11Session(){};
};
#endif

View File

@@ -1,49 +0,0 @@
#include "x11_session_impl.h"
#include <atomic>
#include <functional>
#include <iostream>
#include <memory>
#define CHECK_INIT \
if (!is_initialized_) { \
std::cout << "AE_NEED_INIT" << std::endl; \
return 4; \
}
X11SessionImpl::X11SessionImpl() {}
X11SessionImpl::~X11SessionImpl() {
Stop();
CleanUp();
}
void X11SessionImpl::Release() { delete this; }
int X11SessionImpl::Initialize() { return 0; }
void X11SessionImpl::RegisterObserver(x11_session_observer *observer) {
observer_ = observer;
}
int X11SessionImpl::Start() {
if (is_running_) return 0;
int error = 1;
CHECK_INIT;
return error;
}
int X11SessionImpl::Stop() { return 0; }
int X11SessionImpl::Pause() { return 0; }
int X11SessionImpl::Resume() { return 0; }
void X11SessionImpl::OnFrame() {}
void X11SessionImpl::OnClosed() {}
void X11SessionImpl::CleanUp() {}

View File

@@ -1,44 +0,0 @@
#ifndef _WGC_SESSION_IMPL_H_
#define _WGC_SESSION_IMPL_H_
#include <mutex>
#include <thread>
#include "x11_session.h"
class X11SessionImpl : public X11Session {
public:
X11SessionImpl();
~X11SessionImpl() override;
public:
void Release() override;
int Initialize() override;
void RegisterObserver(x11_session_observer *observer) override;
int Start() override;
int Stop() override;
int Pause() override;
int Resume() override;
private:
void OnFrame();
void OnClosed();
void CleanUp();
// void message_func();
private:
std::mutex lock_;
bool is_initialized_ = false;
bool is_running_ = false;
bool is_paused_ = false;
x11_session_observer *observer_ = nullptr;
};
#endif