From 6afdb5d6c2a5949fcd956afbd0a2f8f2699587ed Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sun, 10 Jan 2016 14:02:40 +0100 Subject: [PATCH] Make a separate shutdown from the destructor for the H.264 encoder. --- h264encode.cpp | 54 ++++++++++++++++++++++++++++++++++---------------- h264encode.h | 1 + 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/h264encode.cpp b/h264encode.cpp index 6998e75..d5c9e8c 100644 --- a/h264encode.cpp +++ b/h264encode.cpp @@ -113,6 +113,7 @@ public: 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 vector &input_frames); + void shutdown(); private: struct storage_task { @@ -155,6 +156,8 @@ private: void update_ReferenceFrames(int frame_type); int update_RefPicList(int frame_type); + bool is_shutdown = false; + thread encode_thread, storage_thread; mutex storage_task_queue_mutex; @@ -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; @@ -1891,4 +1906,9 @@ void H264Encoder::end_frame(RefCountedGLsync fence, int64_t pts, const vectorend_frame(fence, pts, input_frames); } +void H264Encoder::shutdown() +{ + impl->shutdown(); +} + // Real class. diff --git a/h264encode.h b/h264encode.h index caf33af..adf9578 100644 --- a/h264encode.h +++ b/h264encode.h @@ -50,6 +50,7 @@ public: void add_audio(int64_t pts, std::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 shutdown(); // Blocking. private: std::unique_ptr impl; -- 2.39.2