diff --git a/gst-libs/gst/codecs/gstvp8decoder.c b/gst-libs/gst/codecs/gstvp8decoder.c index b3179e23ca..12c983d48f 100644 --- a/gst-libs/gst/codecs/gstvp8decoder.c +++ b/gst-libs/gst/codecs/gstvp8decoder.c @@ -332,7 +332,7 @@ gst_vp8_decoder_handle_frame (GstVideoDecoder * decoder, picture->system_frame_number = frame->system_frame_number; if (klass->new_picture) { - if (!klass->new_picture (self, picture)) { + if (!klass->new_picture (self, frame, picture)) { GST_ERROR_OBJECT (self, "subclass cannot handle new picture"); goto unmap_and_error; } @@ -361,15 +361,10 @@ gst_vp8_decoder_handle_frame (GstVideoDecoder * decoder, gst_buffer_unmap (in_buf, &map); - gst_video_codec_frame_set_user_data (frame, gst_vp8_picture_ref (picture), - (GDestroyNotify) gst_vp8_picture_unref); - gst_video_codec_frame_unref (frame); - - /* transfer ownership of picture */ - gst_vp8_decoder_update_reference (self, picture); + gst_vp8_decoder_update_reference (self, gst_vp8_picture_ref (picture)); g_assert (klass->output_picture); - return klass->output_picture (self, picture); + return klass->output_picture (self, frame, picture); unmap_and_error: { diff --git a/gst-libs/gst/codecs/gstvp8decoder.h b/gst-libs/gst/codecs/gstvp8decoder.h index c229f4d723..0483af8ba9 100644 --- a/gst-libs/gst/codecs/gstvp8decoder.h +++ b/gst-libs/gst/codecs/gstvp8decoder.h @@ -91,7 +91,14 @@ struct _GstVp8DecoderClass gboolean (*new_sequence) (GstVp8Decoder * decoder, const GstVp8FrameHdr * frame_hdr); + /** + * GstVp8Decoder:new_picture: + * @decoder: a #GstVp8Decoder + * @frame: (transfer none): a #GstVideoCodecFrame + * @picture: (transfer none): a #GstVp8Picture + */ gboolean (*new_picture) (GstVp8Decoder * decoder, + GstVideoCodecFrame * frame, GstVp8Picture * picture); gboolean (*start_picture) (GstVp8Decoder * decoder, @@ -104,7 +111,14 @@ struct _GstVp8DecoderClass gboolean (*end_picture) (GstVp8Decoder * decoder, GstVp8Picture * picture); + /** + * GstVp8Decoder:output_picture: + * @decoder: a #GstVp8Decoder + * @frame: (transfer full): a #GstVideoCodecFrame + * @picture: (transfer full): a #GstVp8Picture + */ GstFlowReturn (*output_picture) (GstVp8Decoder * decoder, + GstVideoCodecFrame * frame, GstVp8Picture * picture); /*< private >*/ diff --git a/sys/d3d11/gstd3d11vp8dec.c b/sys/d3d11/gstd3d11vp8dec.c index 9402bbb8af..b008f8ba2a 100644 --- a/sys/d3d11/gstd3d11vp8dec.c +++ b/sys/d3d11/gstd3d11vp8dec.c @@ -99,9 +99,9 @@ static gboolean gst_d3d11_vp8_dec_src_query (GstVideoDecoder * decoder, static gboolean gst_d3d11_vp8_dec_new_sequence (GstVp8Decoder * decoder, const GstVp8FrameHdr * frame_hdr); static gboolean gst_d3d11_vp8_dec_new_picture (GstVp8Decoder * decoder, - GstVp8Picture * picture); + GstVideoCodecFrame * frame, GstVp8Picture * picture); static GstFlowReturn gst_d3d11_vp8_dec_output_picture (GstVp8Decoder * - decoder, GstVp8Picture * picture); + decoder, GstVideoCodecFrame * frame, GstVp8Picture * picture); static gboolean gst_d3d11_vp8_dec_start_picture (GstVp8Decoder * decoder, GstVp8Picture * picture); static gboolean gst_d3d11_vp8_dec_decode_picture (GstVp8Decoder * decoder, @@ -335,7 +335,8 @@ gst_d3d11_vp8_dec_new_sequence (GstVp8Decoder * decoder, } static gboolean -gst_d3d11_vp8_dec_new_picture (GstVp8Decoder * decoder, GstVp8Picture * picture) +gst_d3d11_vp8_dec_new_picture (GstVp8Decoder * decoder, + GstVideoCodecFrame * frame, GstVp8Picture * picture) { GstD3D11Vp8Dec *self = GST_D3D11_VP8_DEC (decoder); GstBuffer *view_buffer; @@ -362,10 +363,10 @@ gst_d3d11_vp8_dec_new_picture (GstVp8Decoder * decoder, GstVp8Picture * picture) static GstFlowReturn gst_d3d11_vp8_dec_output_picture (GstVp8Decoder * decoder, - GstVp8Picture * picture) + GstVideoCodecFrame * frame, GstVp8Picture * picture) { GstD3D11Vp8Dec *self = GST_D3D11_VP8_DEC (decoder); - GstVideoCodecFrame *frame = NULL; + GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder); GstBuffer *output_buffer = NULL; GstBuffer *view_buffer; @@ -375,25 +376,16 @@ gst_d3d11_vp8_dec_output_picture (GstVp8Decoder * decoder, if (!view_buffer) { GST_ERROR_OBJECT (self, "Could not get output view"); - return GST_FLOW_ERROR; - } - - frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self), - picture->system_frame_number); - - if (!frame) { - GST_ERROR_OBJECT (self, - "No frame corresponding to system frame number %d", - picture->system_frame_number); - - return GST_FLOW_ERROR; + goto error; } if (!picture->frame_hdr.show_frame) { GST_LOG_OBJECT (self, "Decode only picture %p", picture); GST_VIDEO_CODEC_FRAME_SET_DECODE_ONLY (frame); - return gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame); + gst_vp8_picture_unref (picture); + + return gst_video_decoder_finish_frame (vdec, frame); } /* if downstream is d3d11 element and forward playback case, @@ -402,20 +394,19 @@ gst_d3d11_vp8_dec_output_picture (GstVp8Decoder * decoder, * up to gop size but our dpb pool cannot be increased */ if (self->use_d3d11_output && gst_d3d11_decoder_supports_direct_rendering (self->d3d11_decoder) && - GST_VIDEO_DECODER (self)->input_segment.rate > 0) { + vdec->input_segment.rate > 0) { GstMemory *mem; output_buffer = gst_buffer_ref (view_buffer); mem = gst_buffer_peek_memory (output_buffer, 0); GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD); } else { - output_buffer = - gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self)); + output_buffer = gst_video_decoder_allocate_output_buffer (vdec); } if (!output_buffer) { GST_ERROR_OBJECT (self, "Couldn't allocate output buffer"); - return GST_FLOW_ERROR; + goto error; } frame->output_buffer = output_buffer; @@ -425,15 +416,21 @@ gst_d3d11_vp8_dec_output_picture (GstVp8Decoder * decoder, picture->frame_hdr.width, picture->frame_hdr.height, view_buffer, output_buffer)) { GST_ERROR_OBJECT (self, "Failed to copy buffer"); - gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame); - - return GST_FLOW_ERROR; + goto error; } GST_LOG_OBJECT (self, "Finish frame %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (output_buffer))); - return gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame); + gst_vp8_picture_unref (picture); + + return gst_video_decoder_finish_frame (vdec, frame); + +error: + gst_video_decoder_drop_frame (vdec, frame); + gst_vp8_picture_unref (picture); + + return GST_FLOW_ERROR; } static GstD3D11DecoderOutputView * diff --git a/sys/v4l2codecs/gstv4l2codecvp8dec.c b/sys/v4l2codecs/gstv4l2codecvp8dec.c index ae6443012b..f142d56d6a 100644 --- a/sys/v4l2codecs/gstv4l2codecvp8dec.c +++ b/sys/v4l2codecs/gstv4l2codecvp8dec.c @@ -657,18 +657,17 @@ fail: static GstFlowReturn gst_v4l2_codec_vp8_dec_output_picture (GstVp8Decoder * decoder, - GstVp8Picture * picture) + GstVideoCodecFrame * frame, GstVp8Picture * picture) { GstV4l2CodecVp8Dec *self = GST_V4L2_CODEC_VP8_DEC (decoder); + GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder); GstV4l2Request *request = gst_vp8_picture_get_user_data (picture); gint ret; guint32 frame_num; - GstVideoCodecFrame *frame, *other_frame; - GstVp8Picture *other_pic; - GstV4l2Request *other_request; GST_DEBUG_OBJECT (self, "Output picture %u", picture->system_frame_number); + /* Unlikely, but it would not break this decoding flow */ if (gst_v4l2_request_is_done (request)) goto finish_frame; @@ -676,38 +675,27 @@ gst_v4l2_codec_vp8_dec_output_picture (GstVp8Decoder * decoder, if (ret == 0) { GST_ELEMENT_ERROR (self, STREAM, DECODE, ("Decoding frame took too long"), (NULL)); - return GST_FLOW_ERROR; + goto error; } else if (ret < 0) { GST_ELEMENT_ERROR (self, STREAM, DECODE, ("Decoding request failed: %s", g_strerror (errno)), (NULL)); - return GST_FLOW_ERROR; + goto error; } - while (TRUE) { - if (!gst_v4l2_decoder_dequeue_src (self->decoder, &frame_num)) { - GST_ELEMENT_ERROR (self, STREAM, DECODE, - ("Decoder did not produce a frame"), (NULL)); - return GST_FLOW_ERROR; - } + if (!gst_v4l2_decoder_dequeue_src (self->decoder, &frame_num)) { + GST_ELEMENT_ERROR (self, STREAM, DECODE, + ("Decoder did not produce a frame"), (NULL)); + goto error; + } - if (frame_num == picture->system_frame_number) - break; - - other_frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self), - frame_num); - g_return_val_if_fail (other_frame, GST_FLOW_ERROR); - - other_pic = gst_video_codec_frame_get_user_data (other_frame); - other_request = gst_vp8_picture_get_user_data (other_pic); - gst_v4l2_request_set_done (other_request); - gst_video_codec_frame_unref (other_frame); + if (frame_num != picture->system_frame_number) { + GST_ELEMENT_ERROR (self, STREAM, DECODE, + ("Decoder produced out of order frame"), (NULL)); + goto error; } finish_frame: gst_v4l2_request_set_done (request); - frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self), - picture->system_frame_number); - g_return_val_if_fail (frame, GST_FLOW_ERROR); g_return_val_if_fail (frame->output_buffer, GST_FLOW_ERROR); /* Hold on reference buffers for the rest of the picture lifetime */ @@ -717,7 +705,15 @@ finish_frame: if (self->copy_frames) gst_v4l2_codec_vp8_dec_copy_output_buffer (self, frame); - return gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame); + gst_vp8_picture_unref (picture); + + return gst_video_decoder_finish_frame (vdec, frame); + +error: + gst_video_decoder_drop_frame (vdec, frame); + gst_vp8_picture_unref (picture); + + return GST_FLOW_ERROR; } static void