X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=h264encode.cpp;h=78e34474b80e07a397c41dbaf3a0cf70d1807a3d;hb=f245cb0d0453e0e8bd5c7d40720bd0a5b50454ee;hp=6998e7503c4bbf061a6005843f85f46b15cacbf1;hpb=6db9385e3864fef2b4b8b292f25bca68d657164a;p=nageru diff --git a/h264encode.cpp b/h264encode.cpp index 6998e75..78e3447 100644 --- a/h264encode.cpp +++ b/h264encode.cpp @@ -110,9 +110,10 @@ class H264EncoderImpl { public: H264EncoderImpl(QSurface *surface, int width, int height, HTTPD *httpd); ~H264EncoderImpl(); - void add_audio(int64_t pts, vector audio); // Needs to come before end_frame() of same pts. + void add_audio(int64_t pts, vector audio); 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. @@ -291,7 +293,11 @@ bitstream_put_ui(bitstream *bs, unsigned int val, int size_in_bits) bs->buffer[pos] = (bs->buffer[pos] << size_in_bits | val); } else { size_in_bits -= bit_left; - bs->buffer[pos] = (bs->buffer[pos] << bit_left) | (val >> size_in_bits); + if (bit_left >= 32) { + bs->buffer[pos] = (val >> size_in_bits); + } else { + bs->buffer[pos] = (bs->buffer[pos] << bit_left) | (val >> size_in_bits); + } bs->buffer[pos] = va_swap32(bs->buffer[pos]); if (pos + 1 == bs->max_size_in_dword) { @@ -1438,7 +1444,7 @@ void H264EncoderImpl::save_codeddata(storage_task task) string data; - const int64_t global_delay = (ip_period - 1) * (TIMEBASE / MAX_FPS); // So we never get negative dts. + const int64_t global_delay = int64_t(ip_period - 1) * (TIMEBASE / MAX_FPS); // So we never get negative dts. va_status = vaMapBuffer(va_dpy, gl_surfaces[task.display_order % SURFACE_NUM].coded_buf, (void **)(&buf_list)); CHECK_VASTATUS(va_status, "vaMapBuffer"); @@ -1650,26 +1656,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 +1726,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 +1736,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 +1745,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 +1910,9 @@ void H264Encoder::end_frame(RefCountedGLsync fence, int64_t pts, const vectorend_frame(fence, pts, input_frames); } +void H264Encoder::shutdown() +{ + impl->shutdown(); +} + // Real class.