From ddd9355767b03ed48ff180f9e9ab480afa3cf613 Mon Sep 17 00:00:00 2001 From: Hyunjun Ko Date: Tue, 21 Nov 2017 14:57:03 +0900 Subject: [PATCH] msdkenc: handle the MORE_DATA case If the driver requires more data, just unref the frame at the moment then retreive/finish the frame after encoding is finished. This also fixes a memory leak. https://bugzilla.gnome.org/show_bug.cgi?id=790312 --- sys/msdk/gstmsdkenc.c | 35 ++++++++++++++++++++++++++++++----- sys/msdk/gstmsdkenc.h | 2 ++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/sys/msdk/gstmsdkenc.c b/sys/msdk/gstmsdkenc.c index b0eb85e88a..5d4d361b55 100644 --- a/sys/msdk/gstmsdkenc.c +++ b/sys/msdk/gstmsdkenc.c @@ -630,6 +630,7 @@ gst_msdkenc_reset_task (MsdkEncTask * task) task->input_frame = NULL; task->output_bitstream.DataLength = 0; task->sync_point = NULL; + task->more_data = FALSE; } static GstFlowReturn @@ -638,6 +639,25 @@ gst_msdkenc_finish_frame (GstMsdkEnc * thiz, MsdkEncTask * task, { GstVideoCodecFrame *frame = task->input_frame; + if (task->more_data) { + GstVideoCodecFrame *frame; + + frame = + gst_video_encoder_get_frame (GST_VIDEO_ENCODER_CAST (thiz), + task->pending_frame_number); + if (frame) { + gst_msdkenc_dequeue_frame (thiz, frame); + gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (thiz), frame); + gst_msdkenc_reset_task (task); + return GST_FLOW_OK; + } else { + GST_ERROR_OBJECT (thiz, + "Couldn't find the pending frame %d to be finished", + task->pending_frame_number); + return GST_FLOW_ERROR; + } + } + if (!task->sync_point) { return GST_FLOW_OK; } @@ -699,11 +719,6 @@ gst_msdkenc_encode_frame (GstMsdkEnc * thiz, mfxFrameSurface1 * surface, g_usleep (1000); }; - if (task->sync_point) { - task->input_frame = input_frame; - thiz->next_task = ((task - thiz->tasks) + 1) % thiz->num_tasks; - } - if (status != MFX_ERR_NONE && status != MFX_ERR_MORE_DATA) { GST_ELEMENT_ERROR (thiz, STREAM, ENCODE, ("Encode frame failed."), ("MSDK encode error (%s)", msdk_status_to_string (status))); @@ -712,6 +727,16 @@ gst_msdkenc_encode_frame (GstMsdkEnc * thiz, mfxFrameSurface1 * surface, return GST_FLOW_ERROR; } + if (task->sync_point) { + task->input_frame = input_frame; + thiz->next_task = ((task - thiz->tasks) + 1) % thiz->num_tasks; + } else if (status == MFX_ERR_MORE_DATA) { + task->more_data = TRUE; + task->pending_frame_number = input_frame->system_frame_number; + gst_video_codec_frame_unref (input_frame); + thiz->next_task = ((task - thiz->tasks) + 1) % thiz->num_tasks; + } + /* Ensure that next task is available */ task = thiz->tasks + thiz->next_task; return gst_msdkenc_finish_frame (thiz, task, FALSE); diff --git a/sys/msdk/gstmsdkenc.h b/sys/msdk/gstmsdkenc.h index f3c99da9f2..600f24ef22 100644 --- a/sys/msdk/gstmsdkenc.h +++ b/sys/msdk/gstmsdkenc.h @@ -118,6 +118,8 @@ struct _MsdkEncTask GstVideoCodecFrame *input_frame; mfxSyncPoint sync_point; mfxBitstream output_bitstream; + gboolean more_data; + guint pending_frame_number; }; GType gst_msdkenc_get_type (void);