v4l2slh264dec: Improve end_picture() robustness

Use a goto to ensure that for all cases we cleanup the current picture state.
And move the src buffer allocation higher, so we don't queue a bitstream
buffer if we don't have a picture buffer to decode into.
This commit is contained in:
Nicolas Dufresne 2020-03-18 17:00:37 -04:00
parent bd7db13412
commit ee26c9c9a1

View file

@ -608,6 +608,8 @@ gst_v4l2_codec_h264_dec_output_picture (GstH264Decoder * decoder,
GstH264Picture *other_pic; GstH264Picture *other_pic;
GstV4l2Request *other_request; GstV4l2Request *other_request;
GST_DEBUG_OBJECT (self, "Output picture %u", picture->system_frame_number);
if (gst_v4l2_request_is_done (request)) if (gst_v4l2_request_is_done (request))
goto finish_frame; goto finish_frame;
@ -718,17 +720,33 @@ gst_v4l2_codec_h264_dec_end_picture (GstH264Decoder * decoder,
if (!request) { if (!request) {
GST_ELEMENT_ERROR (decoder, RESOURCE, NO_SPACE_LEFT, GST_ELEMENT_ERROR (decoder, RESOURCE, NO_SPACE_LEFT,
("Failed to allocate a media request object."), (NULL)); ("Failed to allocate a media request object."), (NULL));
return FALSE; goto fail;
} }
gst_h264_picture_set_user_data (picture, request, gst_h264_picture_set_user_data (picture, request,
(GDestroyNotify) gst_v4l2_request_free); (GDestroyNotify) gst_v4l2_request_free);
flow_ret = gst_buffer_pool_acquire_buffer (GST_BUFFER_POOL (self->src_pool),
&buffer, NULL);
if (flow_ret != GST_FLOW_OK) {
/* FIXME our pool does not wait */
GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE,
("No more picture buffer available."), (NULL));
goto fail;
}
frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self),
picture->system_frame_number);
g_return_val_if_fail (frame, FALSE);
g_warn_if_fail (frame->output_buffer == NULL);
frame->output_buffer = buffer;
gst_video_codec_frame_unref (frame);
if (!gst_v4l2_decoder_set_controls (self->decoder, request, control, if (!gst_v4l2_decoder_set_controls (self->decoder, request, control,
G_N_ELEMENTS (control))) { G_N_ELEMENTS (control))) {
GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE, GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE,
("Driver did not accept the bitstream parameters."), (NULL)); ("Driver did not accept the bitstream parameters."), (NULL));
return FALSE; goto fail;
} }
bytesused = self->bitstream_map.size; bytesused = self->bitstream_map.size;
@ -739,41 +757,29 @@ gst_v4l2_codec_h264_dec_end_picture (GstH264Decoder * decoder,
picture->system_frame_number, bytesused)) { picture->system_frame_number, bytesused)) {
GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE, GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE,
("Driver did not accept the bitstream data."), (NULL)); ("Driver did not accept the bitstream data."), (NULL));
return FALSE; goto fail;
} }
flow_ret = gst_buffer_pool_acquire_buffer (GST_BUFFER_POOL (self->src_pool),
&buffer, NULL);
if (flow_ret != GST_FLOW_OK) {
/* FIXME our pool does not wait */
GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE,
("No more picture buffer available."), (NULL));
gst_v4l2_codec_h264_dec_reset_picture (self);
return FALSE;
}
frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self),
picture->system_frame_number);
g_return_val_if_fail (frame, FALSE);
g_warn_if_fail (frame->output_buffer == NULL);
frame->output_buffer = buffer;
gst_video_codec_frame_unref (frame);
if (!gst_v4l2_decoder_queue_src_buffer (self->decoder, buffer, if (!gst_v4l2_decoder_queue_src_buffer (self->decoder, buffer,
picture->system_frame_number)) { picture->system_frame_number)) {
GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE, GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE,
("Driver did not accept the picture buffer."), (NULL)); ("Driver did not accept the picture buffer."), (NULL));
return FALSE; goto fail;
} }
if (!gst_v4l2_request_queue (request)) { if (!gst_v4l2_request_queue (request)) {
GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE, GST_ELEMENT_ERROR (decoder, RESOURCE, WRITE,
("Driver did not accept the decode request."), (NULL)); ("Driver did not accept the decode request."), (NULL));
return FALSE; goto fail;
} }
gst_v4l2_codec_h264_dec_reset_picture (self); gst_v4l2_codec_h264_dec_reset_picture (self);
return TRUE; return TRUE;
fail:
gst_v4l2_codec_h264_dec_reset_picture (self);
return FALSE;
} }
static gboolean static gboolean