codecs: h264decoder: Don't attach extra ref of GstH264Picture to GstVideoCodecFrame

The lifecycle of GstH264Picture is being managed by our DPB
implementation. If it's still required, subclass can do that
by itself in the new_picture() method.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1449>
This commit is contained in:
Seungha Yang 2020-07-20 17:45:12 +09:00
parent 37aeb91d54
commit 7a024a740f
6 changed files with 43 additions and 24 deletions

View file

@ -758,20 +758,19 @@ gst_h264_decoder_parse_slice (GstH264Decoder * self, GstH264NalUnit * nalu,
/* This allows accessing the frame from the picture. */
picture->system_frame_number = priv->current_frame->system_frame_number;
priv->current_picture = picture;
g_assert (priv->current_frame);
if (klass->new_picture)
ret = klass->new_picture (self, picture);
ret = klass->new_picture (self, priv->current_frame, picture);
if (!ret) {
GST_ERROR_OBJECT (self, "subclass does not want accept new picture");
priv->current_picture = NULL;
gst_h264_picture_unref (picture);
return FALSE;
}
priv->current_picture = picture;
gst_video_codec_frame_set_user_data (priv->current_frame,
gst_h264_picture_ref (priv->current_picture),
(GDestroyNotify) gst_h264_picture_unref);
if (!gst_h264_decoder_start_current_picture (self)) {
GST_ERROR_OBJECT (self, "start picture failed");
return FALSE;

View file

@ -90,7 +90,15 @@ struct _GstH264DecoderClass
const GstH264SPS * sps,
gint max_dpb_size);
/**
* GstVideoDecoder:new_picture:
*
* @decoder: a #GstH264Decoder
* @frame: (transfer none): a #GstVideoCodecFrame
* @picture: (transfer none): a #GstH264Picture
*/
gboolean (*new_picture) (GstH264Decoder * decoder,
GstVideoCodecFrame * frame,
GstH264Picture * picture);
gboolean (*start_picture) (GstH264Decoder * decoder,

View file

@ -151,7 +151,7 @@ static gboolean gst_d3d11_h264_dec_src_query (GstVideoDecoder * decoder,
static gboolean gst_d3d11_h264_dec_new_sequence (GstH264Decoder * decoder,
const GstH264SPS * sps, gint max_dpb_size);
static gboolean gst_d3d11_h264_dec_new_picture (GstH264Decoder * decoder,
GstH264Picture * picture);
GstVideoCodecFrame * frame, GstH264Picture * picture);
static GstFlowReturn gst_d3d11_h264_dec_output_picture (GstH264Decoder *
decoder, GstH264Picture * picture);
static gboolean gst_d3d11_h264_dec_start_picture (GstH264Decoder * decoder,
@ -578,7 +578,7 @@ gst_d3d11_h264_dec_start_picture (GstH264Decoder * decoder,
static gboolean
gst_d3d11_h264_dec_new_picture (GstH264Decoder * decoder,
GstH264Picture * picture)
GstVideoCodecFrame * frame, GstH264Picture * picture)
{
GstD3D11H264Dec *self = GST_D3D11_H264_DEC (decoder);
GstBuffer *view_buffer;

View file

@ -146,7 +146,7 @@ static gboolean gst_nv_h264_dec_src_query (GstVideoDecoder * decoder,
static gboolean gst_nv_h264_dec_new_sequence (GstH264Decoder * decoder,
const GstH264SPS * sps, gint max_dpb_size);
static gboolean gst_nv_h264_dec_new_picture (GstH264Decoder * decoder,
GstH264Picture * picture);
GstVideoCodecFrame * frame, GstH264Picture * picture);
static GstFlowReturn gst_nv_h264_dec_output_picture (GstH264Decoder *
decoder, GstH264Picture * picture);
static gboolean gst_nv_h264_dec_start_picture (GstH264Decoder * decoder,
@ -416,21 +416,23 @@ gst_nv_h264_dec_new_sequence (GstH264Decoder * decoder, const GstH264SPS * sps,
}
static gboolean
gst_nv_h264_dec_new_picture (GstH264Decoder * decoder, GstH264Picture * picture)
gst_nv_h264_dec_new_picture (GstH264Decoder * decoder,
GstVideoCodecFrame * frame, GstH264Picture * picture)
{
GstNvH264Dec *self = GST_NV_H264_DEC (decoder);
GstNvDecoderFrame *frame;
GstNvDecoderFrame *nv_frame;
frame = gst_nv_decoder_new_frame (self->decoder);
if (!frame) {
nv_frame = gst_nv_decoder_new_frame (self->decoder);
if (!nv_frame) {
GST_ERROR_OBJECT (self, "No available decoder frame");
return FALSE;
}
GST_LOG_OBJECT (self, "New decoder frame %p (index %d)", frame, frame->index);
GST_LOG_OBJECT (self,
"New decoder frame %p (index %d)", nv_frame, nv_frame->index);
gst_h264_picture_set_user_data (picture,
frame, (GDestroyNotify) gst_nv_decoder_frame_free);
nv_frame, (GDestroyNotify) gst_nv_decoder_frame_free);
return TRUE;
}

View file

@ -544,7 +544,7 @@ gst_v4l2_codec_h264_dec_fill_slice_params (GstV4l2CodecH264Dec * self,
.flags = (slice->header.field_pic_flag ? V4L2_H264_SLICE_FLAG_FIELD_PIC : 0) |
(slice->header.bottom_field_flag ? V4L2_H264_SLICE_FLAG_BOTTOM_FIELD : 0) |
(slice->header.direct_spatial_mv_pred_flag ? V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED : 0) |
(slice->header.sp_for_switch_flag ? V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH : 0),
(slice->header.sp_for_switch_flag ? V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH : 0),
};
/* *INDENT-ON* */
@ -751,6 +751,17 @@ done:
return TRUE;
}
static gboolean
gst_v4l2_codec_h264_dec_new_picture (GstH264Decoder * decoder,
GstVideoCodecFrame * frame, GstH264Picture * picture)
{
/* This user data will be referenced in _output_picture */
gst_video_codec_frame_set_user_data (frame,
gst_h264_picture_ref (picture), (GDestroyNotify) gst_h264_picture_unref);
return TRUE;
}
static gboolean
gst_v4l2_codec_h264_dec_start_picture (GstH264Decoder * decoder,
GstH264Picture * picture, GstH264Slice * slice, GstH264Dpb * dpb)
@ -1249,6 +1260,8 @@ gst_v4l2_codec_h264_dec_subclass_init (GstV4l2CodecH264DecClass * klass,
h264decoder_class->new_sequence =
GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_new_sequence);
h264decoder_class->new_picture =
GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_new_picture);
h264decoder_class->output_picture =
GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_output_picture);
h264decoder_class->start_picture =

View file

@ -518,25 +518,20 @@ fail:
}
static gboolean
gst_va_h264_dec_new_picture (GstH264Decoder * decoder, GstH264Picture * picture)
gst_va_h264_dec_new_picture (GstH264Decoder * decoder,
GstVideoCodecFrame * frame, GstH264Picture * picture)
{
GstVaH264Dec *self = GST_VA_H264_DEC (decoder);
GstVaDecodePicture *pic;
GstVideoCodecFrame *frame;
GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
VASurfaceID surface;
frame = gst_video_decoder_get_frame (vdec, picture->system_frame_number);
if (!frame)
return FALSE; /* something failed before */
self->last_ret = gst_video_decoder_allocate_output_frame (vdec, frame);
if (self->last_ret != GST_FLOW_OK)
goto error;
surface = gst_va_buffer_get_surface (frame->output_buffer, NULL);
gst_video_codec_frame_unref (frame);
pic = gst_va_decoder_new_decode_picture (self->decoder, surface);
gst_h264_picture_set_user_data (picture, pic,
(GDestroyNotify) gst_va_decode_picture_free);
@ -547,7 +542,9 @@ gst_va_h264_dec_new_picture (GstH264Decoder * decoder, GstH264Picture * picture)
error:
{
gst_video_codec_frame_unref (frame);
GST_WARNING_OBJECT (self,
"Failed to allocated output buffer, return %s",
gst_flow_get_name (self->last_ret));
return FALSE;
}
}