summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHyunjun Ko <zzoon@igalia.com>2018-03-08 11:39:25 -0900
committerSreerenj Balachandran <sreerenj.balachandran@intel.com>2018-03-08 11:39:25 -0900
commit491843085817ba9c5bc98f8d4087a1cc7ab4fad6 (patch)
treece807a4f8eecb722e43b7b243af46bcc0d4fb806
parent8a3630ffd74b40f089c9f9a36dce229839180e92 (diff)
msdk: enc: fix missing some frames to be encoded
There was not handling the end of encoding sequence in encoder. This patch does drain any remaining internal streams while decoder already does this. Document says: "To mark the end of the encoding sequence, call this function with a NULL surface pointer. Repeat the call to drain any remaining internally cached bitstreams—one frame at a time—until MFX_ERR_MORE_DATA is returned." https://bugzilla.gnome.org/show_bug.cgi?id=793236
-rw-r--r--sys/msdk/gstmsdkenc.c64
-rw-r--r--sys/msdk/gstmsdkenc.h3
2 files changed, 36 insertions, 31 deletions
diff --git a/sys/msdk/gstmsdkenc.c b/sys/msdk/gstmsdkenc.c
index 4ccaf56c9..e23c1532e 100644
--- a/sys/msdk/gstmsdkenc.c
+++ b/sys/msdk/gstmsdkenc.c
@@ -643,39 +643,24 @@ gst_msdkenc_get_free_task (GstMsdkEnc * thiz)
static void
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
gst_msdkenc_finish_frame (GstMsdkEnc * thiz, MsdkEncTask * task,
gboolean discard)
{
- GstVideoCodecFrame *frame = task->input_frame;
+ GstVideoCodecFrame *frame;
- if (task->more_data) {
- GstVideoCodecFrame *frame;
+ if (!task->sync_point)
+ return GST_FLOW_OK;
- 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;
- }
- }
+ frame = gst_video_encoder_get_oldest_frame (GST_VIDEO_ENCODER (thiz));
- if (!task->sync_point) {
- return GST_FLOW_OK;
+ if (!frame) {
+ GST_ERROR_OBJECT (thiz, "failed to get a frame");
+ return GST_FLOW_ERROR;
}
/* Wait for encoding operation to complete */
@@ -705,7 +690,9 @@ gst_msdkenc_finish_frame (GstMsdkEnc * thiz, MsdkEncTask * task,
gst_msdkenc_reset_task (task);
}
+ gst_video_codec_frame_unref (frame);
gst_msdkenc_dequeue_frame (thiz, frame);
+
return gst_video_encoder_finish_frame (GST_VIDEO_ENCODER (thiz), frame);
}
@@ -752,13 +739,9 @@ gst_msdkenc_encode_frame (GstMsdkEnc * thiz, mfxFrameSurface1 * surface,
}
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;
+ gst_msdkenc_dequeue_frame (thiz, input_frame);
}
/* Ensure that next task is available */
@@ -802,11 +785,36 @@ gst_msdkenc_set_latency (GstMsdkEnc * thiz)
static void
gst_msdkenc_flush_frames (GstMsdkEnc * thiz, gboolean discard)
{
- guint i, t = thiz->next_task;
+ mfxStatus status;
+ mfxSession session;
+ MsdkEncTask *task;
+ guint i, t;
if (!thiz->tasks)
return;
+ session = gst_msdk_context_get_session (thiz->context);
+
+ for (;;) {
+ task = thiz->tasks + thiz->next_task;
+ gst_msdkenc_finish_frame (thiz, task, FALSE);
+
+ status = MFXVideoENCODE_EncodeFrameAsync (session, NULL, NULL,
+ &task->output_bitstream, &task->sync_point);
+
+ 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)));
+ }
+
+ if (task->sync_point) {
+ thiz->next_task = ((task - thiz->tasks) + 1) % thiz->num_tasks;
+ } else if (status == MFX_ERR_MORE_DATA) {
+ break;
+ }
+ };
+
+ t = thiz->next_task;
for (i = 0; i < thiz->num_tasks; i++) {
gst_msdkenc_finish_frame (thiz, &thiz->tasks[t], discard);
t = (t + 1) % thiz->num_tasks;
diff --git a/sys/msdk/gstmsdkenc.h b/sys/msdk/gstmsdkenc.h
index db333bd0d..634a54139 100644
--- a/sys/msdk/gstmsdkenc.h
+++ b/sys/msdk/gstmsdkenc.h
@@ -167,11 +167,8 @@ struct _GstMsdkEncClass
struct _MsdkEncTask
{
- GstVideoCodecFrame *input_frame;
mfxSyncPoint sync_point;
mfxBitstream output_bitstream;
- gboolean more_data;
- guint pending_frame_number;
};
GType gst_msdkenc_get_type (void);