X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=h264encode.cpp;h=d5c9e8c9e70a905cb4bef7ee53144e3c1aa91836;hb=6afdb5d6c2a5949fcd956afbd0a2f8f2699587ed;hp=7024fdec81f3ebdad1f71038285319e362b797d5;hpb=607f05fc1c946bae0e436c2e551e07364a49ebcf;p=nageru diff --git a/h264encode.cpp b/h264encode.cpp index 7024fde..d5c9e8c 100644 --- a/h264encode.cpp +++ b/h264encode.cpp @@ -110,20 +110,21 @@ class H264EncoderImpl { public: H264EncoderImpl(QSurface *surface, int width, int height, HTTPD *httpd); ~H264EncoderImpl(); - void add_audio(int64_t pts, std::vector audio); // Needs to come before end_frame() of same pts. + void add_audio(int64_t pts, vector audio); // Needs to come before end_frame() of same pts. bool begin_frame(GLuint *y_tex, GLuint *cbcr_tex); - void end_frame(RefCountedGLsync fence, int64_t pts, const std::vector &input_frames); + void end_frame(RefCountedGLsync fence, int64_t pts, const vector &input_frames); + void shutdown(); private: struct storage_task { unsigned long long display_order; int frame_type; - std::vector audio; + vector audio; int64_t pts, dts; }; struct PendingFrame { RefCountedGLsync fence; - std::vector input_frames; + vector input_frames; int64_t pts; }; @@ -155,22 +156,24 @@ private: void update_ReferenceFrames(int frame_type); int update_RefPicList(int frame_type); - std::thread encode_thread, storage_thread; + bool is_shutdown = false; - std::mutex storage_task_queue_mutex; - std::condition_variable storage_task_queue_changed; + thread encode_thread, storage_thread; + + mutex storage_task_queue_mutex; + condition_variable storage_task_queue_changed; int srcsurface_status[SURFACE_NUM]; // protected by storage_task_queue_mutex - std::queue storage_task_queue; // protected by storage_task_queue_mutex + queue storage_task_queue; // protected by storage_task_queue_mutex bool storage_thread_should_quit = false; // protected by storage_task_queue_mutex - std::mutex frame_queue_mutex; - std::condition_variable frame_queue_nonempty; + mutex frame_queue_mutex; + condition_variable frame_queue_nonempty; bool encode_thread_should_quit = false; // under frame_queue_mutex int current_storage_frame; - std::map pending_video_frames; // under frame_queue_mutex - std::map> pending_audio_frames; // under frame_queue_mutex + map pending_video_frames; // under frame_queue_mutex + map> pending_audio_frames; // under frame_queue_mutex QSurface *surface; AVCodecContext *context_audio; @@ -229,7 +232,6 @@ private: int frame_height_mbaligned; }; - // Supposedly vaRenderPicture() is supposed to destroy the buffer implicitly, // but if we don't delete it here, we get leaks. The GStreamer implementation // does the same. @@ -1650,26 +1652,12 @@ H264EncoderImpl::H264EncoderImpl(QSurface *surface, int width, int height, HTTPD H264EncoderImpl::~H264EncoderImpl() { - { - unique_lock lock(frame_queue_mutex); - encode_thread_should_quit = true; - frame_queue_nonempty.notify_all(); - } - encode_thread.join(); - { - unique_lock lock(storage_task_queue_mutex); - storage_thread_should_quit = true; - frame_queue_nonempty.notify_all(); - storage_task_queue_changed.notify_all(); - } - storage_thread.join(); - - release_encode(); - deinit_va(); + shutdown(); } bool H264EncoderImpl::begin_frame(GLuint *y_tex, GLuint *cbcr_tex) { + assert(!is_shutdown); { // Wait until this frame slot is done encoding. unique_lock lock(storage_task_queue_mutex); @@ -1734,6 +1722,7 @@ bool H264EncoderImpl::begin_frame(GLuint *y_tex, GLuint *cbcr_tex) void H264EncoderImpl::add_audio(int64_t pts, vector audio) { + assert(!is_shutdown); { unique_lock lock(frame_queue_mutex); pending_audio_frames[pts] = move(audio); @@ -1743,6 +1732,7 @@ void H264EncoderImpl::add_audio(int64_t pts, vector audio) void H264EncoderImpl::end_frame(RefCountedGLsync fence, int64_t pts, const vector &input_frames) { + assert(!is_shutdown); { unique_lock lock(frame_queue_mutex); pending_video_frames[current_storage_frame] = PendingFrame{ fence, input_frames, pts }; @@ -1751,6 +1741,31 @@ void H264EncoderImpl::end_frame(RefCountedGLsync fence, int64_t pts, const vecto frame_queue_nonempty.notify_all(); } +void H264EncoderImpl::shutdown() +{ + if (is_shutdown) { + return; + } + + { + unique_lock lock(frame_queue_mutex); + encode_thread_should_quit = true; + frame_queue_nonempty.notify_all(); + } + encode_thread.join(); + { + unique_lock lock(storage_task_queue_mutex); + storage_thread_should_quit = true; + frame_queue_nonempty.notify_all(); + storage_task_queue_changed.notify_all(); + } + storage_thread.join(); + + release_encode(); + deinit_va(); + is_shutdown = true; +} + void H264EncoderImpl::encode_thread_func() { int64_t last_dts = -1; @@ -1876,7 +1891,7 @@ H264Encoder::H264Encoder(QSurface *surface, int width, int height, HTTPD *httpd) // Must be defined here because unique_ptr<> destructor needs to know the impl. H264Encoder::~H264Encoder() {} -void H264Encoder::add_audio(int64_t pts, std::vector audio) +void H264Encoder::add_audio(int64_t pts, vector audio) { impl->add_audio(pts, audio); } @@ -1886,9 +1901,14 @@ bool H264Encoder::begin_frame(GLuint *y_tex, GLuint *cbcr_tex) return impl->begin_frame(y_tex, cbcr_tex); } -void H264Encoder::end_frame(RefCountedGLsync fence, int64_t pts, const std::vector &input_frames) +void H264Encoder::end_frame(RefCountedGLsync fence, int64_t pts, const vector &input_frames) { impl->end_frame(fence, pts, input_frames); } +void H264Encoder::shutdown() +{ + impl->shutdown(); +} + // Real class.