mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-26 20:25:34 +08:00
Fix screen capture on MacOS
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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() {}
|
||||
@@ -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);
|
||||
@@ -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
|
||||
@@ -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() {}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user