[feat] support dynamic resolution codec

This commit is contained in:
dijunkun
2024-09-05 17:29:27 +08:00
parent 1292018f51
commit 2f72e3957e
7 changed files with 60 additions and 45 deletions

View File

@@ -11,20 +11,13 @@
class ScreenCapturer { class ScreenCapturer {
public: public:
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(unsigned char *, int, int, int)> cb_desktop_data;
public: public:
virtual ~ScreenCapturer() {} virtual ~ScreenCapturer() {}
public: public:
virtual int Init(const RECORD_DESKTOP_RECT &rect, const int fps, virtual int Init(const int fps, cb_desktop_data cb) = 0;
cb_desktop_data cb) = 0;
virtual int Destroy() = 0; virtual int Destroy() = 0;
virtual int Start() = 0; virtual int Start() = 0;

View File

@@ -62,16 +62,12 @@ bool ScreenCapturerWgc::IsWgcSupported() {
} }
} }
int ScreenCapturerWgc::Init(const RECORD_DESKTOP_RECT &rect, const int fps, int ScreenCapturerWgc::Init(const int fps, cb_desktop_data cb) {
cb_desktop_data cb) {
int error = 0; int error = 0;
if (_inited == true) return error; if (_inited == true) return error;
int r = rect.right; // nv12_frame_ = new unsigned char[rect.right * rect.bottom * 3 / 2];
int b = rect.bottom; // nv12_frame_scaled_ = new unsigned char[1280 * 720 * 3 / 2];
nv12_frame_ = new unsigned char[rect.right * rect.bottom * 3 / 2];
nv12_frame_scaled_ = new unsigned char[1280 * 720 * 3 / 2];
_fps = fps; _fps = fps;
@@ -175,22 +171,20 @@ void ConvertBGRAtoABGR(const uint8_t *bgra_data, uint8_t *abgr_data, int width,
void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame &frame) { void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame &frame) {
if (_on_data) { if (_on_data) {
int width = 1280; // int width = 1280;
int height = 720; // int height = 720;
if (!nv12_frame_) {
nv12_frame_ = new unsigned char[frame.width * frame.height * 3 / 2];
}
libyuv::ARGBToNV12((const uint8_t *)frame.data, frame.width * 4, libyuv::ARGBToNV12((const uint8_t *)frame.data, frame.width * 4,
(uint8_t *)nv12_frame_, frame.width, (uint8_t *)nv12_frame_, frame.width,
(uint8_t *)(nv12_frame_ + frame.width * frame.height), (uint8_t *)(nv12_frame_ + frame.width * frame.height),
frame.width, frame.width, frame.height); frame.width, frame.width, frame.height);
libyuv::NV12Scale( _on_data(nv12_frame_, frame.width * frame.height * 3 / 2, frame.width,
(const uint8_t *)nv12_frame_, frame.width, frame.height);
(const uint8_t *)(nv12_frame_ + frame.width * frame.height),
frame.width, frame.width, frame.height, (uint8_t *)nv12_frame_scaled_,
width, (uint8_t *)(nv12_frame_scaled_ + width * height), width, width,
height, libyuv::FilterMode::kFilterLinear);
_on_data(nv12_frame_scaled_, width * height * 3 / 2, width, height);
} }
} }

View File

@@ -19,8 +19,7 @@ class ScreenCapturerWgc : public ScreenCapturer,
public: public:
bool IsWgcSupported(); bool IsWgcSupported();
virtual int Init(const RECORD_DESKTOP_RECT &rect, const int fps, virtual int Init(const int fps, cb_desktop_data cb);
cb_desktop_data cb);
virtual int Destroy(); virtual int Destroy();
virtual int Start(); virtual int Start();
@@ -45,8 +44,6 @@ class ScreenCapturerWgc : public ScreenCapturer,
std::string _device_name; std::string _device_name;
RECORD_DESKTOP_RECT _rect;
int _fps; int _fps;
cb_desktop_data _on_data = nullptr; cb_desktop_data _on_data = nullptr;

View File

@@ -156,25 +156,27 @@ int Render::LoadSettingsFromCacheFile() {
int Render::StartScreenCapture() { int Render::StartScreenCapture() {
screen_capturer_ = (ScreenCapturer *)screen_capturer_factory_->Create(); screen_capturer_ = (ScreenCapturer *)screen_capturer_factory_->Create();
ScreenCapturer::RECORD_DESKTOP_RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = screen_width_;
rect.bottom = screen_height_;
last_frame_time_ = std::chrono::duration_cast<std::chrono::milliseconds>( last_frame_time_ = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch()) std::chrono::steady_clock::now().time_since_epoch())
.count(); .count();
int screen_capturer_init_ret = screen_capturer_->Init( int screen_capturer_init_ret = screen_capturer_->Init(
rect, 60, 60, [this](unsigned char *data, int size, int width, int height) -> void {
[this](unsigned char *data, int size, int width, int height) -> void {
auto now_time = std::chrono::duration_cast<std::chrono::milliseconds>( auto now_time = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch()) std::chrono::steady_clock::now().time_since_epoch())
.count(); .count();
auto duration = now_time - last_frame_time_; auto duration = now_time - last_frame_time_;
if (duration >= 0 && connection_established_) { if (duration >= 0 && connection_established_) {
SendData(peer_, DATA_TYPE::VIDEO, (const char *)data, // SendData(peer_, DATA_TYPE::VIDEO, (const char *)data,
NV12_BUFFER_SIZE); // NV12_BUFFER_SIZE);
XVideoFrame frame;
frame.data = (const char *)data;
frame.size = size;
frame.width = width;
frame.height = height;
SendVideoFrame(peer_, &frame);
last_frame_time_ = now_time; last_frame_time_ = now_time;
} }
}); });
@@ -275,9 +277,12 @@ int Render::CreateConnectionPeer() {
? true ? true
: false; : false;
params_.enable_turn = config_center_.IsEnableTurn(); params_.enable_turn = config_center_.IsEnableTurn();
params_.on_receive_video_buffer = OnReceiveVideoBufferCb; params_.on_receive_video_buffer = nullptr;
params_.on_receive_audio_buffer = OnReceiveAudioBufferCb; params_.on_receive_audio_buffer = OnReceiveAudioBufferCb;
params_.on_receive_data_buffer = OnReceiveDataBufferCb; params_.on_receive_data_buffer = OnReceiveDataBufferCb;
params_.on_receive_video_frame = OnReceiveVideoBufferCb;
params_.on_signal_status = OnSignalStatusCb; params_.on_signal_status = OnSignalStatusCb;
params_.on_connection_status = OnConnectionStatusCb; params_.on_connection_status = OnConnectionStatusCb;
params_.net_status_report = NetStatusReport; params_.net_status_report = NetStatusReport;
@@ -596,7 +601,15 @@ int Render::Run() {
} }
} else if (event.type == REFRESH_EVENT) { } else if (event.type == REFRESH_EVENT) {
if (stream_texture_) if (stream_texture_)
SDL_UpdateTexture(stream_texture_, NULL, dst_buffer_, 1280); if (video_width_ != texture_width_) {
texture_width_ = video_width_;
texture_height_ = video_height_;
stream_texture_ = SDL_CreateTexture(
main_renderer_, stream_pixformat_, SDL_TEXTUREACCESS_STREAMING,
texture_width_, texture_height_);
}
SDL_UpdateTexture(stream_texture_, NULL, dst_buffer_, texture_width_);
} else { } else {
if (connection_established_) { if (connection_established_) {
ProcessMouseKeyEven(event); ProcessMouseKeyEven(event);

View File

@@ -44,7 +44,7 @@ class Render {
int ConnectionStatusWindow(); int ConnectionStatusWindow();
public: public:
static void OnReceiveVideoBufferCb(const char *data, size_t size, static void OnReceiveVideoBufferCb(const XVideoFrame *video_frame,
const char *user_id, size_t user_id_size, const char *user_id, size_t user_id_size,
void *user_data); void *user_data);
@@ -169,6 +169,9 @@ class Render {
int texture_width_ = 1280; int texture_width_ = 1280;
int texture_height_ = 720; int texture_height_ = 720;
int video_width_ = 1280;
int video_height_ = 720;
SDL_Window *main_window_; SDL_Window *main_window_;
SDL_Renderer *main_renderer_ = nullptr; SDL_Renderer *main_renderer_ = nullptr;
@@ -242,7 +245,8 @@ class Render {
unsigned char audio_buffer_[960]; unsigned char audio_buffer_[960];
int audio_len_ = 0; int audio_len_ = 0;
char *nv12_buffer_ = nullptr; char *nv12_buffer_ = nullptr;
unsigned char *dst_buffer_ = new unsigned char[1280 * 720 * 3]; unsigned char *dst_buffer_ = nullptr;
int dst_buffer_capacity_ = 0;
private: private:
ScreenCapturerFactory *screen_capturer_factory_ = nullptr; ScreenCapturerFactory *screen_capturer_factory_ = nullptr;

View File

@@ -115,12 +115,26 @@ void Render::SdlCaptureAudioOut(void *userdata, Uint8 *stream, int len) {
// render->audio_buffer_fresh_ = false; // render->audio_buffer_fresh_ = false;
} }
void Render::OnReceiveVideoBufferCb(const char *data, size_t size, void Render::OnReceiveVideoBufferCb(const XVideoFrame *video_frame,
const char *user_id, size_t user_id_size, const char *user_id, size_t user_id_size,
void *user_data) { void *user_data) {
Render *render = (Render *)user_data; Render *render = (Render *)user_data;
if (render->connection_established_) { if (render->connection_established_) {
memcpy(render->dst_buffer_, data, size); if (!render->dst_buffer_) {
render->dst_buffer_capacity_ = video_frame->size;
render->dst_buffer_ = new unsigned char[video_frame->size];
}
if (render->dst_buffer_capacity_ < video_frame->size) {
delete render->dst_buffer_;
render->dst_buffer_capacity_ = video_frame->size;
render->dst_buffer_ = new unsigned char[video_frame->size];
}
memcpy(render->dst_buffer_, video_frame->data, video_frame->size);
render->video_width_ = video_frame->width;
render->video_height_ = video_frame->height;
SDL_Event event; SDL_Event event;
event.type = REFRESH_EVENT; event.type = REFRESH_EVENT;
SDL_PushEvent(&event); SDL_PushEvent(&event);