void add_audio(int64_t pts, vector<float> 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<RefCountedFrame> &input_frames);
+ void shutdown();
private:
struct storage_task {
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;
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.
H264EncoderImpl::~H264EncoderImpl()
{
- {
- unique_lock<mutex> lock(frame_queue_mutex);
- encode_thread_should_quit = true;
- frame_queue_nonempty.notify_all();
- }
- encode_thread.join();
- {
- unique_lock<mutex> 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<mutex> lock(storage_task_queue_mutex);
void H264EncoderImpl::add_audio(int64_t pts, vector<float> audio)
{
+ assert(!is_shutdown);
{
unique_lock<mutex> lock(frame_queue_mutex);
pending_audio_frames[pts] = move(audio);
void H264EncoderImpl::end_frame(RefCountedGLsync fence, int64_t pts, const vector<RefCountedFrame> &input_frames)
{
+ assert(!is_shutdown);
{
unique_lock<mutex> lock(frame_queue_mutex);
pending_video_frames[current_storage_frame] = PendingFrame{ fence, input_frames, pts };
frame_queue_nonempty.notify_all();
}
+void H264EncoderImpl::shutdown()
+{
+ if (is_shutdown) {
+ return;
+ }
+
+ {
+ unique_lock<mutex> lock(frame_queue_mutex);
+ encode_thread_should_quit = true;
+ frame_queue_nonempty.notify_all();
+ }
+ encode_thread.join();
+ {
+ unique_lock<mutex> 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;
impl->end_frame(fence, pts, input_frames);
}
+void H264Encoder::shutdown()
+{
+ impl->shutdown();
+}
+
// Real class.