vp9enc: Allow caps renegotiation
authorSebastian Dröge <sebastian@centricular.com>
Tue, 30 Sep 2014 08:31:43 +0000 (11:31 +0300)
committerSebastian Dröge <sebastian@centricular.com>
Tue, 30 Sep 2014 08:35:42 +0000 (11:35 +0300)
https://bugzilla.gnome.org/show_bug.cgi?id=726329

ext/vpx/gstvp9enc.c

index 9bf5efb..c4c2c9d 100644 (file)
@@ -345,9 +345,10 @@ static gboolean gst_vp9_enc_start (GstVideoEncoder * encoder);
 static gboolean gst_vp9_enc_stop (GstVideoEncoder * encoder);
 static gboolean gst_vp9_enc_set_format (GstVideoEncoder *
     video_encoder, GstVideoCodecState * state);
-static gboolean gst_vp9_enc_finish (GstVideoEncoder * video_encoder);
+static GstFlowReturn gst_vp9_enc_finish (GstVideoEncoder * video_encoder);
 static GstFlowReturn gst_vp9_enc_handle_frame (GstVideoEncoder *
     video_encoder, GstVideoCodecFrame * frame);
+static GstFlowReturn gst_vp9_enc_drain (GstVideoEncoder * video_encoder);
 static gboolean gst_vp9_enc_sink_event (GstVideoEncoder *
     video_encoder, GstEvent * event);
 static gboolean gst_vp9_enc_propose_allocation (GstVideoEncoder * encoder,
@@ -1486,8 +1487,8 @@ gst_vp9_enc_set_format (GstVideoEncoder * video_encoder,
   GST_DEBUG_OBJECT (video_encoder, "set_format");
 
   if (encoder->inited) {
-    GST_DEBUG_OBJECT (video_encoder, "refusing renegotiation");
-    return FALSE;
+    gst_vp9_enc_drain (video_encoder);
+    vpx_codec_destroy (&encoder->encoder);
   }
 
   g_mutex_lock (&encoder->encoder_lock);
@@ -1528,7 +1529,9 @@ gst_vp9_enc_set_format (GstVideoEncoder * video_encoder,
   }
 
   if (encoder->cfg.g_pass == VPX_RC_FIRST_PASS) {
-    encoder->first_pass_cache_content = g_byte_array_sized_new (4096);
+    if (encoder->first_pass_cache_content == NULL) {
+      encoder->first_pass_cache_content = g_byte_array_sized_new (4096);
+    }
   } else if (encoder->cfg.g_pass == VPX_RC_LAST_PASS) {
     GError *err = NULL;
 
@@ -1539,6 +1542,12 @@ gst_vp9_enc_set_format (GstVideoEncoder * video_encoder,
       return FALSE;
     }
 
+    if (encoder->cfg.rc_twopass_stats_in.buf != NULL) {
+      g_free (encoder->cfg.rc_twopass_stats_in.buf);
+      encoder->cfg.rc_twopass_stats_in.buf = NULL;
+      encoder->cfg.rc_twopass_stats_in.sz = 0;
+    }
+
     if (!g_file_get_contents (encoder->multipass_cache_file,
             (gchar **) & encoder->cfg.rc_twopass_stats_in.buf,
             &encoder->cfg.rc_twopass_stats_in.sz, &err)) {
@@ -1805,22 +1814,25 @@ gst_vp9_enc_process (GstVP9Enc * encoder)
   return ret;
 }
 
+/* This function should be called holding then stream lock*/
 static GstFlowReturn
-gst_vp9_enc_finish (GstVideoEncoder * video_encoder)
+gst_vp9_enc_drain (GstVideoEncoder * video_encoder)
 {
   GstVP9Enc *encoder;
   int flags = 0;
   vpx_codec_err_t status;
-
-  GST_DEBUG_OBJECT (video_encoder, "finish");
+  gint64 deadline;
 
   encoder = GST_VP9_ENC (video_encoder);
 
   g_mutex_lock (&encoder->encoder_lock);
+  deadline = encoder->deadline;
+  g_mutex_unlock (&encoder->encoder_lock);
+
   status =
       vpx_codec_encode (&encoder->encoder, NULL, encoder->n_frames, 1, flags,
-      encoder->deadline);
-  g_mutex_unlock (&encoder->encoder_lock);
+      deadline);
+
   if (status != 0) {
     GST_ERROR_OBJECT (encoder, "encode returned %d %s", status,
         gst_vpx_error_name (status));
@@ -1830,6 +1842,7 @@ gst_vp9_enc_finish (GstVideoEncoder * video_encoder)
   /* dispatch remaining frames */
   gst_vp9_enc_process (encoder);
 
+  g_mutex_lock (&encoder->encoder_lock);
   if (encoder->cfg.g_pass == VPX_RC_FIRST_PASS && encoder->multipass_cache_file) {
     GError *err = NULL;
 
@@ -1841,10 +1854,23 @@ gst_vp9_enc_finish (GstVideoEncoder * video_encoder)
       g_error_free (err);
     }
   }
+  g_mutex_unlock (&encoder->encoder_lock);
 
   return GST_FLOW_OK;
 }
 
+static GstFlowReturn
+gst_vp9_enc_finish (GstVideoEncoder * video_encoder)
+{
+  GstFlowReturn ret;
+
+  GST_DEBUG_OBJECT (video_encoder, "finish");
+
+  ret = gst_vp9_enc_drain (video_encoder);
+
+  return ret;
+}
+
 static vpx_image_t *
 gst_vp9_enc_buffer_to_image (GstVP9Enc * enc, GstVideoFrame * frame)
 {