diff --git a/ext/vpx/gstvp9enc.c b/ext/vpx/gstvp9enc.c index 9bf5efb6e7..c4c2c9d81c 100644 --- a/ext/vpx/gstvp9enc.c +++ b/ext/vpx/gstvp9enc.c @@ -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) {