mirror of
				https://github.com/kunkundi/crossdesk.git
				synced 2025-10-26 20:25:34 +08:00 
			
		
		
		
	Update linux capture module
This commit is contained in:
		| @@ -1,26 +0,0 @@ | ||||
| #include "screen_capture_wgc.h" | ||||
|  | ||||
| #include <iostream> | ||||
|  | ||||
| ScreenCaptureWgc::ScreenCaptureWgc() {} | ||||
|  | ||||
| ScreenCaptureWgc::~ScreenCaptureWgc() {} | ||||
|  | ||||
| bool ScreenCaptureWgc::IsWgcSupported() { return false; } | ||||
|  | ||||
| int ScreenCaptureWgc::Init(const RECORD_DESKTOP_RECT &rect, const int fps, | ||||
|                            cb_desktop_data cb) { | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int ScreenCaptureWgc::Start() { return 0; } | ||||
|  | ||||
| int ScreenCaptureWgc::Pause() { return 0; } | ||||
|  | ||||
| int ScreenCaptureWgc::Resume() { return 0; } | ||||
|  | ||||
| int ScreenCaptureWgc::Stop() { return 0; } | ||||
|  | ||||
| void ScreenCaptureWgc::OnFrame() {} | ||||
|  | ||||
| void ScreenCaptureWgc::CleanUp() {} | ||||
| @@ -1,56 +0,0 @@ | ||||
| #ifndef _SCREEN_CAPTURE_WGC_H_ | ||||
| #define _SCREEN_CAPTURE_WGC_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: | ||||
|   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(); | ||||
|  | ||||
|  protected: | ||||
|   void CleanUp(); | ||||
|  | ||||
|  private: | ||||
|   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; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,123 @@ | ||||
| #include "screen_capture_x11.h" | ||||
|  | ||||
| #include <iostream> | ||||
|  | ||||
| #define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2 | ||||
| unsigned char nv12_buffer_[NV12_BUFFER_SIZE]; | ||||
|  | ||||
| ScreenCaptureX11::ScreenCaptureX11() {} | ||||
|  | ||||
| ScreenCaptureX11::~ScreenCaptureX11() {} | ||||
|  | ||||
| int ScreenCaptureX11::Init(const RECORD_DESKTOP_RECT &rect, const int fps, | ||||
|                            cb_desktop_data cb) { | ||||
|   pFormatCtx_ = avformat_alloc_context(); | ||||
|  | ||||
|   avdevice_register_all(); | ||||
|  | ||||
|   // grabbing frame rate | ||||
|   av_dict_set(&options_, "framerate", "5", 0); | ||||
|   // Make the grabbed area follow the mouse | ||||
|   av_dict_set(&options_, "follow_mouse", "centered", 0); | ||||
|   // 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("x11grab"); | ||||
|   if (!ifmt_) { | ||||
|     printf("Couldn't find_input_format\n"); | ||||
|   } | ||||
|  | ||||
|   // Grab at position 10,20 | ||||
|   if (avformat_open_input(&pFormatCtx_, ":0.0", ifmt_, &options_) != 0) { | ||||
|     printf("Couldn't open input stream.\n"); | ||||
|     return -1; | ||||
|   } | ||||
|  | ||||
|   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) { | ||||
|       videoindex_ = i_; | ||||
|       break; | ||||
|     } | ||||
|   if (videoindex_ == -1) { | ||||
|     printf("Didn't find a video stream.\n"); | ||||
|     return -1; | ||||
|   } | ||||
|  | ||||
|   pCodecParam_ = pFormatCtx_->streams[videoindex_]->codecpar; | ||||
|  | ||||
|   pCodecCtx_ = avcodec_alloc_context3(NULL); | ||||
|   avcodec_parameters_to_context(pCodecCtx_, pCodecParam_); | ||||
|  | ||||
|   // pCodec_ = const_cast<AVCodec *>(avcodec_find_decoder(AV_CODEC_ID_H264)); | ||||
|   pCodec_ = const_cast<AVCodec *>(avcodec_find_decoder(pCodecCtx_->codec_id)); | ||||
|   if (pCodec_ == NULL) { | ||||
|     printf("Codec not found.\n"); | ||||
|     return -1; | ||||
|   } | ||||
|   if (avcodec_open2(pCodecCtx_, pCodec_, NULL) < 0) { | ||||
|     printf("Could not open codec.\n"); | ||||
|     return -1; | ||||
|   } | ||||
|  | ||||
|   pFrame_ = av_frame_alloc(); | ||||
|   pFrameNV12_ = av_frame_alloc(); | ||||
|  | ||||
|   const int pixel_w = 1280, pixel_h = 720; | ||||
|   int screen_w = 1280, screen_h = 720; | ||||
|  | ||||
|   screen_w = 1280; | ||||
|   screen_h = 720; | ||||
|  | ||||
|   packet_ = (AVPacket *)av_malloc(sizeof(AVPacket)); | ||||
|  | ||||
|   img_convert_ctx_ = | ||||
|       sws_getContext(pCodecCtx_->width, pCodecCtx_->height, pCodecCtx_->pix_fmt, | ||||
|                      pCodecCtx_->width, pCodecCtx_->height, AV_PIX_FMT_NV12, | ||||
|                      SWS_BICUBIC, NULL, NULL, NULL); | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int ScreenCaptureX11::Start() { | ||||
|   capture_thread_.reset(new std::thread([this]() { | ||||
|     while (1) { | ||||
|       if (av_read_frame(pFormatCtx_, packet_) >= 0) { | ||||
|         printf("111111444444\n"); | ||||
|         if (packet_->stream_index == videoindex_) { | ||||
|           printf("11111155555\n"); | ||||
|           avcodec_send_packet(pCodecCtx_, packet_); | ||||
|           got_picture_ = avcodec_receive_frame(pCodecCtx_, pFrame_); | ||||
|           printf("33333333\n"); | ||||
|           if (!got_picture_) { | ||||
|             printf("44444444444\n"); | ||||
|  | ||||
|             av_image_fill_arrays(pFrameNV12_->data, pFrameNV12_->linesize, | ||||
|                                  nv12_buffer_, AV_PIX_FMT_NV12, pFrame_->width, | ||||
|                                  pFrame_->height, 1); | ||||
|  | ||||
|             sws_scale(img_convert_ctx_, pFrame_->data, pFrame_->linesize, 0, | ||||
|                       pFrame_->height, pFrameNV12_->data, | ||||
|                       pFrameNV12_->linesize); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   })); | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int ScreenCaptureX11::Pause() { return 0; } | ||||
|  | ||||
| int ScreenCaptureX11::Resume() { return 0; } | ||||
|  | ||||
| int ScreenCaptureX11::Stop() { return 0; } | ||||
|  | ||||
| void ScreenCaptureX11::OnFrame() {} | ||||
|  | ||||
| void ScreenCaptureX11::CleanUp() {} | ||||
| @@ -0,0 +1,85 @@ | ||||
| #ifndef _SCREEN_CAPTURE_X11_H_ | ||||
| #define _SCREEN_CAPTURE_X11_H_ | ||||
|  | ||||
| #include <atomic> | ||||
| #include <functional> | ||||
| #include <string> | ||||
| #include <thread> | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| #include <libavcodec/avcodec.h> | ||||
| #include <libavdevice/avdevice.h> | ||||
| #include <libavformat/avformat.h> | ||||
| #include <libavutil/imgutils.h> | ||||
| #include <libswscale/swscale.h> | ||||
| #ifdef __cplusplus | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| 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 ScreenCaptureX11 { | ||||
|  public: | ||||
|   ScreenCaptureX11(); | ||||
|   ~ScreenCaptureX11(); | ||||
|  | ||||
|  public: | ||||
|   int Init(const RECORD_DESKTOP_RECT &rect, const int fps, cb_desktop_data cb); | ||||
|  | ||||
|   int Start(); | ||||
|   int Pause(); | ||||
|   int Resume(); | ||||
|   int Stop(); | ||||
|  | ||||
|   void OnFrame(); | ||||
|  | ||||
|  protected: | ||||
|   void CleanUp(); | ||||
|  | ||||
|  private: | ||||
|   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; | ||||
|  | ||||
|  private: | ||||
|   int i_ = 0; | ||||
|   int videoindex_ = 0; | ||||
|   int got_picture_ = 0; | ||||
|   // ffmpeg | ||||
|   AVFormatContext *pFormatCtx_ = nullptr; | ||||
|   AVCodecContext *pCodecCtx_ = nullptr; | ||||
|   AVCodec *pCodec_ = nullptr; | ||||
|   AVCodecParameters *pCodecParam_ = nullptr; | ||||
|   AVDictionary *options_ = nullptr; | ||||
|   AVInputFormat *ifmt_ = nullptr; | ||||
|   AVFrame *pFrame_ = nullptr; | ||||
|   AVFrame *pFrameNV12_ = nullptr; | ||||
|   AVPacket *packet_ = nullptr; | ||||
|   struct SwsContext *img_convert_ctx_ = nullptr; | ||||
|  | ||||
|   // thread | ||||
|   std::unique_ptr<std::thread> capture_thread_ = nullptr; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										37
									
								
								application/remote_desk/screen_capture/linux/x11_session.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								application/remote_desk/screen_capture/linux/x11_session.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| #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 | ||||
| @@ -0,0 +1,51 @@ | ||||
| #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() {} | ||||
|  | ||||
| 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() {} | ||||
|  | ||||
| int X11SessionImpl::Resume() {} | ||||
|  | ||||
| void X11SessionImpl::OnFrame() {} | ||||
|  | ||||
| void X11SessionImpl::OnClosed() {} | ||||
|  | ||||
| int X11SessionImpl::Initialize() { return 0; } | ||||
|  | ||||
| void X11SessionImpl::CleanUp() {} | ||||
| @@ -0,0 +1,45 @@ | ||||
| #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(); | ||||
|  | ||||
|   int Initialize(); | ||||
|   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 | ||||
| @@ -117,7 +117,7 @@ int main(int argc, char *argv[]) { | ||||
|   // Make the grabbed area follow the mouse | ||||
|   av_dict_set(&options, "follow_mouse", "centered", 0); | ||||
|   // Video frame size. The default is to capture the full screen | ||||
|   // av_dict_set(&options, "video_size", "1280x720", 0); | ||||
|   av_dict_set(&options, "video_size", "1280x720", 0); | ||||
|   AVInputFormat *ifmt = (AVInputFormat *)av_find_input_format("x11grab"); | ||||
|   if (!ifmt) { | ||||
|     printf("Couldn't find_input_format\n"); | ||||
|   | ||||
| @@ -232,4 +232,4 @@ target("linux_capture") | ||||
|     set_kind("binary") | ||||
|     add_packages("vcpkg::ffmpeg", "sdl2", "asound") | ||||
|     add_files("tests/peerconnection/linux_capture.cpp") | ||||
|     add_ldflags("-lasound", "-lX11", "-lXext", "-lxcb", "-lsndio", "-lpostproc", "-lXv") | ||||
|     add_ldflags("-lasound", "-lX11", "-lXext", "-lxcb", "-lsndio", "-lpostproc", "-ldl", {force = true}) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user