codecs: vp8decoder: Sync up with h264decoder implementation

Pass GstVideoCodecFrame with GstVp8Picture to new_picture() and
output_picture() methods for subclass to be able to reference
it directly.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1458>
This commit is contained in:
Seungha Yang 2020-07-23 17:45:03 +09:00 committed by Nicolas Dufresne
parent c78fe6bfb0
commit deaa29bd96
4 changed files with 63 additions and 61 deletions

View file

@ -332,7 +332,7 @@ gst_vp8_decoder_handle_frame (GstVideoDecoder * decoder,
picture->system_frame_number = frame->system_frame_number; picture->system_frame_number = frame->system_frame_number;
if (klass->new_picture) { 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"); GST_ERROR_OBJECT (self, "subclass cannot handle new picture");
goto unmap_and_error; goto unmap_and_error;
} }
@ -361,15 +361,10 @@ gst_vp8_decoder_handle_frame (GstVideoDecoder * decoder,
gst_buffer_unmap (in_buf, &map); gst_buffer_unmap (in_buf, &map);
gst_video_codec_frame_set_user_data (frame, gst_vp8_picture_ref (picture), gst_vp8_decoder_update_reference (self, 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);
g_assert (klass->output_picture); g_assert (klass->output_picture);
return klass->output_picture (self, picture); return klass->output_picture (self, frame, picture);
unmap_and_error: unmap_and_error:
{ {

View file

@ -91,7 +91,14 @@ struct _GstVp8DecoderClass
gboolean (*new_sequence) (GstVp8Decoder * decoder, gboolean (*new_sequence) (GstVp8Decoder * decoder,
const GstVp8FrameHdr * frame_hdr); 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, gboolean (*new_picture) (GstVp8Decoder * decoder,
GstVideoCodecFrame * frame,
GstVp8Picture * picture); GstVp8Picture * picture);
gboolean (*start_picture) (GstVp8Decoder * decoder, gboolean (*start_picture) (GstVp8Decoder * decoder,
@ -104,7 +111,14 @@ struct _GstVp8DecoderClass
gboolean (*end_picture) (GstVp8Decoder * decoder, gboolean (*end_picture) (GstVp8Decoder * decoder,
GstVp8Picture * picture); GstVp8Picture * picture);
/**
* GstVp8Decoder:output_picture:
* @decoder: a #GstVp8Decoder
* @frame: (transfer full): a #GstVideoCodecFrame
* @picture: (transfer full): a #GstVp8Picture
*/
GstFlowReturn (*output_picture) (GstVp8Decoder * decoder, GstFlowReturn (*output_picture) (GstVp8Decoder * decoder,
GstVideoCodecFrame * frame,
GstVp8Picture * picture); GstVp8Picture * picture);
/*< private >*/ /*< private >*/

View file

@ -99,9 +99,9 @@ static gboolean gst_d3d11_vp8_dec_src_query (GstVideoDecoder * decoder,
static gboolean gst_d3d11_vp8_dec_new_sequence (GstVp8Decoder * decoder, static gboolean gst_d3d11_vp8_dec_new_sequence (GstVp8Decoder * decoder,
const GstVp8FrameHdr * frame_hdr); const GstVp8FrameHdr * frame_hdr);
static gboolean gst_d3d11_vp8_dec_new_picture (GstVp8Decoder * decoder, 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 * 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, static gboolean gst_d3d11_vp8_dec_start_picture (GstVp8Decoder * decoder,
GstVp8Picture * picture); GstVp8Picture * picture);
static gboolean gst_d3d11_vp8_dec_decode_picture (GstVp8Decoder * decoder, static gboolean gst_d3d11_vp8_dec_decode_picture (GstVp8Decoder * decoder,
@ -335,7 +335,8 @@ gst_d3d11_vp8_dec_new_sequence (GstVp8Decoder * decoder,
} }
static gboolean 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); GstD3D11Vp8Dec *self = GST_D3D11_VP8_DEC (decoder);
GstBuffer *view_buffer; GstBuffer *view_buffer;
@ -362,10 +363,10 @@ gst_d3d11_vp8_dec_new_picture (GstVp8Decoder * decoder, GstVp8Picture * picture)
static GstFlowReturn static GstFlowReturn
gst_d3d11_vp8_dec_output_picture (GstVp8Decoder * decoder, gst_d3d11_vp8_dec_output_picture (GstVp8Decoder * decoder,
GstVp8Picture * picture) GstVideoCodecFrame * frame, GstVp8Picture * picture)
{ {
GstD3D11Vp8Dec *self = GST_D3D11_VP8_DEC (decoder); GstD3D11Vp8Dec *self = GST_D3D11_VP8_DEC (decoder);
GstVideoCodecFrame *frame = NULL; GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
GstBuffer *output_buffer = NULL; GstBuffer *output_buffer = NULL;
GstBuffer *view_buffer; GstBuffer *view_buffer;
@ -375,25 +376,16 @@ gst_d3d11_vp8_dec_output_picture (GstVp8Decoder * decoder,
if (!view_buffer) { if (!view_buffer) {
GST_ERROR_OBJECT (self, "Could not get output view"); GST_ERROR_OBJECT (self, "Could not get output view");
return GST_FLOW_ERROR; goto 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;
} }
if (!picture->frame_hdr.show_frame) { if (!picture->frame_hdr.show_frame) {
GST_LOG_OBJECT (self, "Decode only picture %p", picture); GST_LOG_OBJECT (self, "Decode only picture %p", picture);
GST_VIDEO_CODEC_FRAME_SET_DECODE_ONLY (frame); 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, /* 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 */ * up to gop size but our dpb pool cannot be increased */
if (self->use_d3d11_output && if (self->use_d3d11_output &&
gst_d3d11_decoder_supports_direct_rendering (self->d3d11_decoder) && gst_d3d11_decoder_supports_direct_rendering (self->d3d11_decoder) &&
GST_VIDEO_DECODER (self)->input_segment.rate > 0) { vdec->input_segment.rate > 0) {
GstMemory *mem; GstMemory *mem;
output_buffer = gst_buffer_ref (view_buffer); output_buffer = gst_buffer_ref (view_buffer);
mem = gst_buffer_peek_memory (output_buffer, 0); mem = gst_buffer_peek_memory (output_buffer, 0);
GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD); GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD);
} else { } else {
output_buffer = output_buffer = gst_video_decoder_allocate_output_buffer (vdec);
gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self));
} }
if (!output_buffer) { if (!output_buffer) {
GST_ERROR_OBJECT (self, "Couldn't allocate output buffer"); GST_ERROR_OBJECT (self, "Couldn't allocate output buffer");
return GST_FLOW_ERROR; goto error;
} }
frame->output_buffer = output_buffer; 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, picture->frame_hdr.width, picture->frame_hdr.height,
view_buffer, output_buffer)) { view_buffer, output_buffer)) {
GST_ERROR_OBJECT (self, "Failed to copy buffer"); GST_ERROR_OBJECT (self, "Failed to copy buffer");
gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame); goto error;
return GST_FLOW_ERROR;
} }
GST_LOG_OBJECT (self, "Finish frame %" GST_TIME_FORMAT, GST_LOG_OBJECT (self, "Finish frame %" GST_TIME_FORMAT,
GST_TIME_ARGS (GST_BUFFER_PTS (output_buffer))); 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 * static GstD3D11DecoderOutputView *

View file

@ -657,18 +657,17 @@ fail:
static GstFlowReturn static GstFlowReturn
gst_v4l2_codec_vp8_dec_output_picture (GstVp8Decoder * decoder, gst_v4l2_codec_vp8_dec_output_picture (GstVp8Decoder * decoder,
GstVp8Picture * picture) GstVideoCodecFrame * frame, GstVp8Picture * picture)
{ {
GstV4l2CodecVp8Dec *self = GST_V4L2_CODEC_VP8_DEC (decoder); GstV4l2CodecVp8Dec *self = GST_V4L2_CODEC_VP8_DEC (decoder);
GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
GstV4l2Request *request = gst_vp8_picture_get_user_data (picture); GstV4l2Request *request = gst_vp8_picture_get_user_data (picture);
gint ret; gint ret;
guint32 frame_num; guint32 frame_num;
GstVideoCodecFrame *frame, *other_frame;
GstVp8Picture *other_pic;
GstV4l2Request *other_request;
GST_DEBUG_OBJECT (self, "Output picture %u", picture->system_frame_number); 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)) if (gst_v4l2_request_is_done (request))
goto finish_frame; goto finish_frame;
@ -676,38 +675,27 @@ gst_v4l2_codec_vp8_dec_output_picture (GstVp8Decoder * decoder,
if (ret == 0) { if (ret == 0) {
GST_ELEMENT_ERROR (self, STREAM, DECODE, GST_ELEMENT_ERROR (self, STREAM, DECODE,
("Decoding frame took too long"), (NULL)); ("Decoding frame took too long"), (NULL));
return GST_FLOW_ERROR; goto error;
} else if (ret < 0) { } else if (ret < 0) {
GST_ELEMENT_ERROR (self, STREAM, DECODE, GST_ELEMENT_ERROR (self, STREAM, DECODE,
("Decoding request failed: %s", g_strerror (errno)), (NULL)); ("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)) {
if (!gst_v4l2_decoder_dequeue_src (self->decoder, &frame_num)) { GST_ELEMENT_ERROR (self, STREAM, DECODE,
GST_ELEMENT_ERROR (self, STREAM, DECODE, ("Decoder did not produce a frame"), (NULL));
("Decoder did not produce a frame"), (NULL)); goto error;
return GST_FLOW_ERROR; }
}
if (frame_num == picture->system_frame_number) if (frame_num != picture->system_frame_number) {
break; GST_ELEMENT_ERROR (self, STREAM, DECODE,
("Decoder produced out of order frame"), (NULL));
other_frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (self), goto error;
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);
} }
finish_frame: finish_frame:
gst_v4l2_request_set_done (request); 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); g_return_val_if_fail (frame->output_buffer, GST_FLOW_ERROR);
/* Hold on reference buffers for the rest of the picture lifetime */ /* Hold on reference buffers for the rest of the picture lifetime */
@ -717,7 +705,15 @@ finish_frame:
if (self->copy_frames) if (self->copy_frames)
gst_v4l2_codec_vp8_dec_copy_output_buffer (self, frame); 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 static void