mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 18:05:37 +00:00
codecs: Keep track of non-decoding-essential input state change
In theory, input caps can be updated anytime at non-keyframe or sequence boundary, such as HDR10 metadata, framerate, aspect-ratio or so. Those information update might not trigger ::new_sequence() or subclass may ignore the changes. By this commit, input state change will be tracked by baseclass and subclass will be able to know the non-decoding-essential update by checking the codec specific picture struct on ::output_picture() Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3328>
This commit is contained in:
parent
a40842545f
commit
2ede4011bf
18 changed files with 188 additions and 0 deletions
|
@ -48,6 +48,8 @@ struct _GstAV1DecoderPrivate
|
|||
guint preferred_output_delay;
|
||||
GstQueueArray *output_queue;
|
||||
gboolean is_live;
|
||||
|
||||
gboolean input_state_changed;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
@ -83,6 +85,7 @@ static gboolean gst_av1_decoder_start (GstVideoDecoder * decoder);
|
|||
static gboolean gst_av1_decoder_stop (GstVideoDecoder * decoder);
|
||||
static gboolean gst_av1_decoder_set_format (GstVideoDecoder * decoder,
|
||||
GstVideoCodecState * state);
|
||||
static gboolean gst_av1_decoder_negotiate (GstVideoDecoder * decoder);
|
||||
static GstFlowReturn gst_av1_decoder_finish (GstVideoDecoder * decoder);
|
||||
static gboolean gst_av1_decoder_flush (GstVideoDecoder * decoder);
|
||||
static GstFlowReturn gst_av1_decoder_drain (GstVideoDecoder * decoder);
|
||||
|
@ -102,6 +105,7 @@ gst_av1_decoder_class_init (GstAV1DecoderClass * klass)
|
|||
decoder_class->start = GST_DEBUG_FUNCPTR (gst_av1_decoder_start);
|
||||
decoder_class->stop = GST_DEBUG_FUNCPTR (gst_av1_decoder_stop);
|
||||
decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_av1_decoder_set_format);
|
||||
decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_av1_decoder_negotiate);
|
||||
decoder_class->finish = GST_DEBUG_FUNCPTR (gst_av1_decoder_finish);
|
||||
decoder_class->flush = GST_DEBUG_FUNCPTR (gst_av1_decoder_flush);
|
||||
decoder_class->drain = GST_DEBUG_FUNCPTR (gst_av1_decoder_drain);
|
||||
|
@ -210,6 +214,8 @@ gst_av1_decoder_set_format (GstVideoDecoder * decoder,
|
|||
|
||||
GST_DEBUG_OBJECT (decoder, "Set format");
|
||||
|
||||
priv->input_state_changed = TRUE;
|
||||
|
||||
if (self->input_state)
|
||||
gst_video_codec_state_unref (self->input_state);
|
||||
|
||||
|
@ -227,6 +233,17 @@ gst_av1_decoder_set_format (GstVideoDecoder * decoder,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_av1_decoder_negotiate (GstVideoDecoder * decoder)
|
||||
{
|
||||
GstAV1Decoder *self = GST_AV1_DECODER (decoder);
|
||||
|
||||
/* output state must be updated by subclass using new input state already */
|
||||
self->priv->input_state_changed = FALSE;
|
||||
|
||||
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_av1_decoder_drain_output_queue (GstAV1Decoder * self,
|
||||
guint num, GstFlowReturn * ret)
|
||||
|
@ -731,6 +748,14 @@ out:
|
|||
} else {
|
||||
GstAV1DecoderOutputFrame output_frame;
|
||||
|
||||
/* If subclass didn't update output state at this point,
|
||||
* marking this picture as a discont and stores current input state */
|
||||
if (priv->input_state_changed) {
|
||||
priv->current_picture->discont_state =
|
||||
gst_video_codec_state_ref (self->input_state);
|
||||
priv->input_state_changed = FALSE;
|
||||
}
|
||||
|
||||
output_frame.frame = frame;
|
||||
output_frame.picture = priv->current_picture;
|
||||
output_frame.self = self;
|
||||
|
|
|
@ -36,6 +36,9 @@ _gst_av1_picture_free (GstAV1Picture * picture)
|
|||
if (picture->notify)
|
||||
picture->notify (picture->user_data);
|
||||
|
||||
if (picture->discont_state)
|
||||
gst_video_codec_state_unref (picture->discont_state);
|
||||
|
||||
g_free (picture);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <gst/codecs/codecs-prelude.h>
|
||||
#include <gst/codecparsers/gstav1parser.h>
|
||||
#include <gst/video/video.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -84,6 +85,9 @@ struct _GstAV1Picture
|
|||
gboolean showable_frame;
|
||||
gboolean apply_grain;
|
||||
|
||||
/* decoder input state if this picture is discont point */
|
||||
GstVideoCodecState *discont_state;
|
||||
|
||||
gpointer user_data;
|
||||
GDestroyNotify notify;
|
||||
};
|
||||
|
|
|
@ -150,6 +150,8 @@ struct _GstH264DecoderPrivate
|
|||
|
||||
/* For delayed output */
|
||||
GstQueueArray *output_queue;
|
||||
|
||||
gboolean input_state_changed;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
@ -179,6 +181,7 @@ static gboolean gst_h264_decoder_start (GstVideoDecoder * decoder);
|
|||
static gboolean gst_h264_decoder_stop (GstVideoDecoder * decoder);
|
||||
static gboolean gst_h264_decoder_set_format (GstVideoDecoder * decoder,
|
||||
GstVideoCodecState * state);
|
||||
static gboolean gst_h264_decoder_negotiate (GstVideoDecoder * decoder);
|
||||
static GstFlowReturn gst_h264_decoder_finish (GstVideoDecoder * decoder);
|
||||
static gboolean gst_h264_decoder_flush (GstVideoDecoder * decoder);
|
||||
static GstFlowReturn gst_h264_decoder_drain (GstVideoDecoder * decoder);
|
||||
|
@ -307,6 +310,7 @@ gst_h264_decoder_class_init (GstH264DecoderClass * klass)
|
|||
decoder_class->start = GST_DEBUG_FUNCPTR (gst_h264_decoder_start);
|
||||
decoder_class->stop = GST_DEBUG_FUNCPTR (gst_h264_decoder_stop);
|
||||
decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_h264_decoder_set_format);
|
||||
decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_h264_decoder_negotiate);
|
||||
decoder_class->finish = GST_DEBUG_FUNCPTR (gst_h264_decoder_finish);
|
||||
decoder_class->flush = GST_DEBUG_FUNCPTR (gst_h264_decoder_flush);
|
||||
decoder_class->drain = GST_DEBUG_FUNCPTR (gst_h264_decoder_drain);
|
||||
|
@ -1023,6 +1027,14 @@ gst_h264_decoder_start_current_picture (GstH264Decoder * self)
|
|||
g_assert (priv->active_sps != NULL);
|
||||
g_assert (priv->active_pps != NULL);
|
||||
|
||||
/* If subclass didn't update output state at this point,
|
||||
* marking this picture as a discont and stores current input state */
|
||||
if (priv->input_state_changed) {
|
||||
priv->current_picture->discont_state =
|
||||
gst_video_codec_state_ref (self->input_state);
|
||||
priv->input_state_changed = FALSE;
|
||||
}
|
||||
|
||||
sps = priv->active_sps;
|
||||
|
||||
priv->max_frame_num = sps->max_frame_num;
|
||||
|
@ -1369,6 +1381,8 @@ gst_h264_decoder_set_format (GstVideoDecoder * decoder,
|
|||
|
||||
GST_DEBUG_OBJECT (decoder, "Set format");
|
||||
|
||||
priv->input_state_changed = TRUE;
|
||||
|
||||
if (self->input_state)
|
||||
gst_video_codec_state_unref (self->input_state);
|
||||
|
||||
|
@ -1441,6 +1455,17 @@ gst_h264_decoder_set_format (GstVideoDecoder * decoder,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_h264_decoder_negotiate (GstVideoDecoder * decoder)
|
||||
{
|
||||
GstH264Decoder *self = GST_H264_DECODER (decoder);
|
||||
|
||||
/* output state must be updated by subclass using new input state already */
|
||||
self->priv->input_state_changed = FALSE;
|
||||
|
||||
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_h264_decoder_fill_picture_from_slice (GstH264Decoder * self,
|
||||
const GstH264Slice * slice, GstH264Picture * picture)
|
||||
|
|
|
@ -35,6 +35,9 @@ _gst_h264_picture_free (GstH264Picture * picture)
|
|||
if (picture->notify)
|
||||
picture->notify (picture->user_data);
|
||||
|
||||
if (picture->discont_state)
|
||||
gst_video_codec_state_unref (picture->discont_state);
|
||||
|
||||
g_free (picture);
|
||||
}
|
||||
|
||||
|
|
|
@ -161,6 +161,9 @@ struct _GstH264Picture
|
|||
|
||||
GstVideoBufferFlags buffer_flags;
|
||||
|
||||
/* decoder input state if this picture is discont point */
|
||||
GstVideoCodecState *discont_state;
|
||||
|
||||
gpointer user_data;
|
||||
GDestroyNotify notify;
|
||||
};
|
||||
|
|
|
@ -134,6 +134,8 @@ struct _GstH265DecoderPrivate
|
|||
guint preferred_output_delay;
|
||||
gboolean is_live;
|
||||
GstQueueArray *output_queue;
|
||||
|
||||
gboolean input_state_changed;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
@ -173,6 +175,7 @@ static gboolean gst_h265_decoder_start (GstVideoDecoder * decoder);
|
|||
static gboolean gst_h265_decoder_stop (GstVideoDecoder * decoder);
|
||||
static gboolean gst_h265_decoder_set_format (GstVideoDecoder * decoder,
|
||||
GstVideoCodecState * state);
|
||||
static gboolean gst_h265_decoder_negotiate (GstVideoDecoder * decoder);
|
||||
static GstFlowReturn gst_h265_decoder_finish (GstVideoDecoder * decoder);
|
||||
static gboolean gst_h265_decoder_flush (GstVideoDecoder * decoder);
|
||||
static GstFlowReturn gst_h265_decoder_drain (GstVideoDecoder * decoder);
|
||||
|
@ -201,6 +204,7 @@ gst_h265_decoder_class_init (GstH265DecoderClass * klass)
|
|||
decoder_class->start = GST_DEBUG_FUNCPTR (gst_h265_decoder_start);
|
||||
decoder_class->stop = GST_DEBUG_FUNCPTR (gst_h265_decoder_stop);
|
||||
decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_h265_decoder_set_format);
|
||||
decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_h265_decoder_negotiate);
|
||||
decoder_class->finish = GST_DEBUG_FUNCPTR (gst_h265_decoder_finish);
|
||||
decoder_class->flush = GST_DEBUG_FUNCPTR (gst_h265_decoder_flush);
|
||||
decoder_class->drain = GST_DEBUG_FUNCPTR (gst_h265_decoder_drain);
|
||||
|
@ -1083,6 +1087,8 @@ gst_h265_decoder_set_format (GstVideoDecoder * decoder,
|
|||
|
||||
GST_DEBUG_OBJECT (decoder, "Set format");
|
||||
|
||||
priv->input_state_changed = TRUE;
|
||||
|
||||
if (self->input_state)
|
||||
gst_video_codec_state_unref (self->input_state);
|
||||
|
||||
|
@ -1151,6 +1157,17 @@ gst_h265_decoder_set_format (GstVideoDecoder * decoder,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_h265_decoder_negotiate (GstVideoDecoder * decoder)
|
||||
{
|
||||
GstH265Decoder *self = GST_H265_DECODER (decoder);
|
||||
|
||||
/* output state must be updated by subclass using new input state already */
|
||||
self->priv->input_state_changed = FALSE;
|
||||
|
||||
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_h265_decoder_flush (GstVideoDecoder * decoder)
|
||||
{
|
||||
|
@ -1785,6 +1802,14 @@ gst_h265_decoder_start_current_picture (GstH265Decoder * self)
|
|||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
/* If subclass didn't update output state at this point,
|
||||
* marking this picture as a discont and stores current input state */
|
||||
if (priv->input_state_changed) {
|
||||
priv->current_picture->discont_state =
|
||||
gst_video_codec_state_ref (self->input_state);
|
||||
priv->input_state_changed = FALSE;
|
||||
}
|
||||
|
||||
gst_h265_decoder_prepare_rps (self, &priv->current_slice,
|
||||
priv->current_picture);
|
||||
|
||||
|
|
|
@ -34,6 +34,9 @@ _gst_h265_picture_free (GstH265Picture * picture)
|
|||
if (picture->notify)
|
||||
picture->notify (picture->user_data);
|
||||
|
||||
if (picture->discont_state)
|
||||
gst_video_codec_state_unref (picture->discont_state);
|
||||
|
||||
g_free (picture);
|
||||
}
|
||||
|
||||
|
|
|
@ -90,6 +90,9 @@ struct _GstH265Picture
|
|||
|
||||
GstVideoBufferFlags buffer_flags;
|
||||
|
||||
/* decoder input state if this picture is discont point */
|
||||
GstVideoCodecState *discont_state;
|
||||
|
||||
gpointer user_data;
|
||||
GDestroyNotify notify;
|
||||
};
|
||||
|
|
|
@ -267,6 +267,8 @@ struct _GstMpeg2DecoderPrivate
|
|||
GstQueueArray *output_queue;
|
||||
/* used for low-latency vs. high throughput mode decision */
|
||||
gboolean is_live;
|
||||
|
||||
gboolean input_state_changed;
|
||||
};
|
||||
|
||||
#define UPDATE_FLOW_RETURN(ret,new_ret) G_STMT_START { \
|
||||
|
@ -293,6 +295,7 @@ static gboolean gst_mpeg2_decoder_start (GstVideoDecoder * decoder);
|
|||
static gboolean gst_mpeg2_decoder_stop (GstVideoDecoder * decoder);
|
||||
static gboolean gst_mpeg2_decoder_set_format (GstVideoDecoder * decoder,
|
||||
GstVideoCodecState * state);
|
||||
static gboolean gst_mpeg2_decoder_negotiate (GstVideoDecoder * decoder);
|
||||
static GstFlowReturn gst_mpeg2_decoder_finish (GstVideoDecoder * decoder);
|
||||
static gboolean gst_mpeg2_decoder_flush (GstVideoDecoder * decoder);
|
||||
static GstFlowReturn gst_mpeg2_decoder_drain (GstVideoDecoder * decoder);
|
||||
|
@ -314,6 +317,7 @@ gst_mpeg2_decoder_class_init (GstMpeg2DecoderClass * klass)
|
|||
decoder_class->start = GST_DEBUG_FUNCPTR (gst_mpeg2_decoder_start);
|
||||
decoder_class->stop = GST_DEBUG_FUNCPTR (gst_mpeg2_decoder_stop);
|
||||
decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_mpeg2_decoder_set_format);
|
||||
decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_mpeg2_decoder_negotiate);
|
||||
decoder_class->finish = GST_DEBUG_FUNCPTR (gst_mpeg2_decoder_finish);
|
||||
decoder_class->flush = GST_DEBUG_FUNCPTR (gst_mpeg2_decoder_flush);
|
||||
decoder_class->drain = GST_DEBUG_FUNCPTR (gst_mpeg2_decoder_drain);
|
||||
|
@ -379,6 +383,8 @@ gst_mpeg2_decoder_set_format (GstVideoDecoder * decoder,
|
|||
|
||||
GST_DEBUG_OBJECT (decoder, "Set format");
|
||||
|
||||
priv->input_state_changed = TRUE;
|
||||
|
||||
if (self->input_state)
|
||||
gst_video_codec_state_unref (self->input_state);
|
||||
|
||||
|
@ -395,6 +401,17 @@ gst_mpeg2_decoder_set_format (GstVideoDecoder * decoder,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_mpeg2_decoder_negotiate (GstVideoDecoder * decoder)
|
||||
{
|
||||
GstMpeg2Decoder *self = GST_MPEG2_DECODER (decoder);
|
||||
|
||||
/* output state must be updated by subclass using new input state already */
|
||||
self->priv->input_state_changed = FALSE;
|
||||
|
||||
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_mpeg2_decoder_drain (GstVideoDecoder * decoder)
|
||||
{
|
||||
|
@ -817,6 +834,14 @@ gst_mpeg2_decoder_start_current_picture (GstMpeg2Decoder * decoder,
|
|||
GstMpeg2Picture *prev_picture, *next_picture;
|
||||
GstFlowReturn ret;
|
||||
|
||||
/* If subclass didn't update output state at this point,
|
||||
* marking this picture as a discont and stores current input state */
|
||||
if (priv->input_state_changed) {
|
||||
priv->current_picture->discont_state =
|
||||
gst_video_codec_state_ref (decoder->input_state);
|
||||
priv->input_state_changed = FALSE;
|
||||
}
|
||||
|
||||
if (!klass->start_picture)
|
||||
return GST_FLOW_OK;
|
||||
|
||||
|
|
|
@ -40,6 +40,9 @@ _gst_mpeg2_picture_free (GstMpeg2Picture * picture)
|
|||
if (picture->notify)
|
||||
picture->notify (picture->user_data);
|
||||
|
||||
if (picture->discont_state)
|
||||
gst_video_codec_state_unref (picture->discont_state);
|
||||
|
||||
g_free (picture);
|
||||
}
|
||||
|
||||
|
|
|
@ -94,6 +94,9 @@ struct _GstMpeg2Picture
|
|||
GstMpegVideoPictureStructure structure;
|
||||
GstMpegVideoPictureType type;
|
||||
|
||||
/* decoder input state if this picture is discont point */
|
||||
GstVideoCodecState *discont_state;
|
||||
|
||||
gpointer user_data;
|
||||
GDestroyNotify notify;
|
||||
};
|
||||
|
|
|
@ -47,6 +47,8 @@ struct _GstVp8DecoderPrivate
|
|||
/* for delayed output */
|
||||
GstQueueArray *output_queue;
|
||||
gboolean is_live;
|
||||
|
||||
gboolean input_state_changed;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
@ -67,6 +69,7 @@ static gboolean gst_vp8_decoder_start (GstVideoDecoder * decoder);
|
|||
static gboolean gst_vp8_decoder_stop (GstVideoDecoder * decoder);
|
||||
static gboolean gst_vp8_decoder_set_format (GstVideoDecoder * decoder,
|
||||
GstVideoCodecState * state);
|
||||
static gboolean gst_vp8_decoder_negotiate (GstVideoDecoder * decoder);
|
||||
static GstFlowReturn gst_vp8_decoder_finish (GstVideoDecoder * decoder);
|
||||
static gboolean gst_vp8_decoder_flush (GstVideoDecoder * decoder);
|
||||
static GstFlowReturn gst_vp8_decoder_drain (GstVideoDecoder * decoder);
|
||||
|
@ -87,6 +90,7 @@ gst_vp8_decoder_class_init (GstVp8DecoderClass * klass)
|
|||
decoder_class->start = GST_DEBUG_FUNCPTR (gst_vp8_decoder_start);
|
||||
decoder_class->stop = GST_DEBUG_FUNCPTR (gst_vp8_decoder_stop);
|
||||
decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_vp8_decoder_set_format);
|
||||
decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_vp8_decoder_negotiate);
|
||||
decoder_class->finish = GST_DEBUG_FUNCPTR (gst_vp8_decoder_finish);
|
||||
decoder_class->flush = GST_DEBUG_FUNCPTR (gst_vp8_decoder_flush);
|
||||
decoder_class->drain = GST_DEBUG_FUNCPTR (gst_vp8_decoder_drain);
|
||||
|
@ -205,6 +209,8 @@ gst_vp8_decoder_set_format (GstVideoDecoder * decoder,
|
|||
|
||||
GST_DEBUG_OBJECT (decoder, "Set format");
|
||||
|
||||
priv->input_state_changed = TRUE;
|
||||
|
||||
if (self->input_state)
|
||||
gst_video_codec_state_unref (self->input_state);
|
||||
|
||||
|
@ -221,6 +227,17 @@ gst_vp8_decoder_set_format (GstVideoDecoder * decoder,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_vp8_decoder_negotiate (GstVideoDecoder * decoder)
|
||||
{
|
||||
GstVp8Decoder *self = GST_VP8_DECODER (decoder);
|
||||
|
||||
/* output state must be updated by subclass using new input state already */
|
||||
self->priv->input_state_changed = FALSE;
|
||||
|
||||
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_vp8_decoder_update_reference (GstVp8Decoder * self, GstVp8Picture * picture)
|
||||
{
|
||||
|
@ -452,6 +469,13 @@ gst_vp8_decoder_handle_frame (GstVideoDecoder * decoder,
|
|||
|
||||
ret = gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
|
||||
} else {
|
||||
/* If subclass didn't update output state at this point,
|
||||
* marking this picture as a discont and stores current input state */
|
||||
if (priv->input_state_changed) {
|
||||
picture->discont_state = gst_video_codec_state_ref (self->input_state);
|
||||
priv->input_state_changed = FALSE;
|
||||
}
|
||||
|
||||
output_frame.frame = frame;
|
||||
output_frame.picture = picture;
|
||||
output_frame.self = self;
|
||||
|
|
|
@ -36,6 +36,9 @@ _gst_vp8_picture_free (GstVp8Picture * picture)
|
|||
if (picture->notify)
|
||||
picture->notify (picture->user_data);
|
||||
|
||||
if (picture->discont_state)
|
||||
gst_video_codec_state_unref (picture->discont_state);
|
||||
|
||||
g_free (picture);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <gst/codecs/codecs-prelude.h>
|
||||
#include <gst/codecparsers/gstvp8parser.h>
|
||||
#include <gst/video/video.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -34,6 +35,7 @@ typedef struct _GstVp8Picture GstVp8Picture;
|
|||
|
||||
struct _GstVp8Picture
|
||||
{
|
||||
/*< private >*/
|
||||
GstMiniObject parent;
|
||||
|
||||
GstClockTime pts;
|
||||
|
@ -46,6 +48,9 @@ struct _GstVp8Picture
|
|||
const guint8 * data;
|
||||
gsize size;
|
||||
|
||||
/* decoder input state if this picture is discont point */
|
||||
GstVideoCodecState *discont_state;
|
||||
|
||||
gpointer user_data;
|
||||
GDestroyNotify notify;
|
||||
};
|
||||
|
|
|
@ -84,6 +84,8 @@ struct _GstVp9DecoderPrivate
|
|||
guint preferred_output_delay;
|
||||
GstQueueArray *output_queue;
|
||||
gboolean is_live;
|
||||
|
||||
gboolean input_state_changed;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
@ -104,6 +106,7 @@ static gboolean gst_vp9_decoder_start (GstVideoDecoder * decoder);
|
|||
static gboolean gst_vp9_decoder_stop (GstVideoDecoder * decoder);
|
||||
static gboolean gst_vp9_decoder_set_format (GstVideoDecoder * decoder,
|
||||
GstVideoCodecState * state);
|
||||
static gboolean gst_vp9_decoder_negotiate (GstVideoDecoder * decoder);
|
||||
static GstFlowReturn gst_vp9_decoder_finish (GstVideoDecoder * decoder);
|
||||
static gboolean gst_vp9_decoder_flush (GstVideoDecoder * decoder);
|
||||
static GstFlowReturn gst_vp9_decoder_drain (GstVideoDecoder * decoder);
|
||||
|
@ -125,6 +128,7 @@ gst_vp9_decoder_class_init (GstVp9DecoderClass * klass)
|
|||
decoder_class->start = GST_DEBUG_FUNCPTR (gst_vp9_decoder_start);
|
||||
decoder_class->stop = GST_DEBUG_FUNCPTR (gst_vp9_decoder_stop);
|
||||
decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_vp9_decoder_set_format);
|
||||
decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_vp9_decoder_negotiate);
|
||||
decoder_class->finish = GST_DEBUG_FUNCPTR (gst_vp9_decoder_finish);
|
||||
decoder_class->flush = GST_DEBUG_FUNCPTR (gst_vp9_decoder_flush);
|
||||
decoder_class->drain = GST_DEBUG_FUNCPTR (gst_vp9_decoder_drain);
|
||||
|
@ -264,6 +268,8 @@ gst_vp9_decoder_set_format (GstVideoDecoder * decoder,
|
|||
|
||||
GST_DEBUG_OBJECT (decoder, "Set format");
|
||||
|
||||
priv->input_state_changed = TRUE;
|
||||
|
||||
if (self->input_state)
|
||||
gst_video_codec_state_unref (self->input_state);
|
||||
|
||||
|
@ -277,6 +283,17 @@ gst_vp9_decoder_set_format (GstVideoDecoder * decoder,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_vp9_decoder_negotiate (GstVideoDecoder * decoder)
|
||||
{
|
||||
GstVp9Decoder *self = GST_VP9_DECODER (decoder);
|
||||
|
||||
/* output state must be updated by subclass using new input state already */
|
||||
self->priv->input_state_changed = FALSE;
|
||||
|
||||
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_vp9_decoder_reset (GstVp9Decoder * self)
|
||||
{
|
||||
|
@ -529,6 +546,13 @@ gst_vp9_decoder_handle_frame (GstVideoDecoder * decoder,
|
|||
|
||||
ret = gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
|
||||
} else {
|
||||
/* If subclass didn't update output state at this point,
|
||||
* marking this picture as a discont and stores current input state */
|
||||
if (priv->input_state_changed) {
|
||||
picture->discont_state = gst_video_codec_state_ref (self->input_state);
|
||||
priv->input_state_changed = FALSE;
|
||||
}
|
||||
|
||||
output_frame.frame = frame;
|
||||
output_frame.picture = picture;
|
||||
output_frame.self = self;
|
||||
|
|
|
@ -36,6 +36,9 @@ _gst_vp9_picture_free (GstVp9Picture * picture)
|
|||
if (picture->notify)
|
||||
picture->notify (picture->user_data);
|
||||
|
||||
if (picture->discont_state)
|
||||
gst_video_codec_state_unref (picture->discont_state);
|
||||
|
||||
g_free (picture);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <gst/codecs/codecs-prelude.h>
|
||||
#include <gst/codecs/gstvp9statefulparser.h>
|
||||
#include <gst/video/video.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -46,6 +47,9 @@ struct _GstVp9Picture
|
|||
const guint8 * data;
|
||||
gsize size;
|
||||
|
||||
/* decoder input state if this picture is discont point */
|
||||
GstVideoCodecState *discont_state;
|
||||
|
||||
gpointer user_data;
|
||||
GDestroyNotify notify;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue