]> git.sesse.net Git - nageru/blobdiff - h264encode.cpp
Hook up the exit menu item.
[nageru] / h264encode.cpp
index 7024fdec81f3ebdad1f71038285319e362b797d5..02ada023b182879a0f0bf3fea15d3302dcad541b 100644 (file)
@@ -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<float> audio);  // Needs to come before end_frame() of same pts.
+       void add_audio(int64_t pts, vector<float> audio);
        bool begin_frame(GLuint *y_tex, GLuint *cbcr_tex);
-       void end_frame(RefCountedGLsync fence, int64_t pts, const std::vector<RefCountedFrame> &input_frames);
+       void end_frame(RefCountedGLsync fence, int64_t pts, const vector<RefCountedFrame> &input_frames);
+       void shutdown();
 
 private:
        struct storage_task {
                unsigned long long display_order;
                int frame_type;
-               std::vector<float> audio;
+               vector<float> audio;
                int64_t pts, dts;
        };
        struct PendingFrame {
                RefCountedGLsync fence;
-               std::vector<RefCountedFrame> input_frames;
+               vector<RefCountedFrame> 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> storage_task_queue;  // protected by storage_task_queue_mutex
+       queue<storage_task> 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<int, PendingFrame> pending_video_frames;  // under frame_queue_mutex
-       std::map<int64_t, std::vector<float>> pending_audio_frames;  // under frame_queue_mutex
+       map<int, PendingFrame> pending_video_frames;  // under frame_queue_mutex
+       map<int64_t, vector<float>> 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<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);
@@ -1734,6 +1722,7 @@ bool H264EncoderImpl::begin_frame(GLuint *y_tex, GLuint *cbcr_tex)
 
 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);
@@ -1743,6 +1732,7 @@ void H264EncoderImpl::add_audio(int64_t pts, vector<float> 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 };
@@ -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<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;
@@ -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<float> audio)
+void H264Encoder::add_audio(int64_t pts, vector<float> 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<RefCountedFrame> &input_frames)
+void H264Encoder::end_frame(RefCountedGLsync fence, int64_t pts, const vector<RefCountedFrame> &input_frames)
 {
        impl->end_frame(fence, pts, input_frames);
 }
 
+void H264Encoder::shutdown()
+{
+       impl->shutdown();
+}
+
 // Real class.