msdkdec: fix assertion 'frame->ref_count > 0' failed

Can happen if the oldest frame is the current frame
and if gst_video_decoder_finish_frame failed in which
case the current is unref and then drop instead of
just drop.
This patch also removes some assumptions, it was strange
to call unref and finish_frame in gst_msdkdec_finish_task.
In principle when owning a frame, the code should either
unref, or drop or finish.
This commit is contained in:
Julien Isorce 2019-12-06 08:50:05 -08:00 committed by Julien Isorce
parent 5bf10d8781
commit 3bae199863

View file

@ -660,11 +660,12 @@ gst_msdkdec_finish_task (GstMsdkDec * thiz, MsdkDecTask * task)
if (!frame)
return GST_FLOW_FLUSHING;
gst_video_codec_frame_unref (frame);
if (decode_only)
GST_VIDEO_CODEC_FRAME_SET_DECODE_ONLY (frame);
flow = gst_video_decoder_finish_frame (decoder, frame);
if (flow == GST_FLOW_ERROR)
GST_ERROR_OBJECT (thiz, "Failed to finish frame");
return flow;
}
return GST_FLOW_OK;
@ -1001,12 +1002,6 @@ gst_msdkdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame)
if (thiz->force_reset_on_res_change)
hard_reset = TRUE;
/* Config changed dynamically and we are going to do a full reset,
* this will unref the input frame which has the new configuration.
* Keep a ref to the input_frame to keep it alive */
if (thiz->initialized && thiz->do_renego)
gst_video_codec_frame_ref (frame);
if (!gst_msdkdec_negotiate (thiz, hard_reset)) {
GST_ELEMENT_ERROR (thiz, CORE, NEGOTIATION,
("Could not negotiate the stream"), (NULL));
@ -1015,13 +1010,21 @@ gst_msdkdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame)
}
}
/* gst_msdkdec_handle_frame owns one ref on input argument |frame|. At this
* point this frame is not used so just unref it right away.
* gst_msdkdec_finish_task is fetching the frames itself. */
gst_video_codec_frame_unref (frame);
frame = NULL;
for (;;) {
if (thiz->postpone_free_surface)
gst_msdkdec_free_unlocked_msdk_surfaces (thiz, surface);
task = &g_array_index (thiz->tasks, MsdkDecTask, thiz->next_task);
flow = gst_msdkdec_finish_task (thiz, task);
if (flow != GST_FLOW_OK)
if (flow != GST_FLOW_OK) {
if (flow == GST_FLOW_ERROR)
GST_ERROR_OBJECT (thiz, "Failed to finish a task");
goto error;
}
if (!surface) {
flow = allocate_output_buffer (thiz, &buffer);
if (flow == GST_FLOW_CUSTOM_SUCCESS) {
@ -1165,6 +1168,7 @@ error:
gst_buffer_unmap (input_buffer, &map_info);
gst_buffer_unref (input_buffer);
}
if (frame)
gst_video_decoder_drop_frame (decoder, frame);
return flow;