videodecoder: improve PTS and DTS handling
Also keep track of the DTS and use it to set PTS on keyframes. Set DTS on outgoing buffers.
This commit is contained in:
parent
b27c649a48
commit
9f591a0bd1
@ -1427,7 +1427,8 @@ typedef struct _Timestamp Timestamp;
|
|||||||
struct _Timestamp
|
struct _Timestamp
|
||||||
{
|
{
|
||||||
guint64 offset;
|
guint64 offset;
|
||||||
GstClockTime timestamp;
|
GstClockTime pts;
|
||||||
|
GstClockTime dts;
|
||||||
GstClockTime duration;
|
GstClockTime duration;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1440,11 +1441,14 @@ gst_video_decoder_add_timestamp (GstVideoDecoder * decoder, GstBuffer * buffer)
|
|||||||
ts = g_malloc (sizeof (Timestamp));
|
ts = g_malloc (sizeof (Timestamp));
|
||||||
|
|
||||||
GST_LOG_OBJECT (decoder,
|
GST_LOG_OBJECT (decoder,
|
||||||
"adding timestamp %" GST_TIME_FORMAT " (offset:%" G_GUINT64_FORMAT ")",
|
"adding PTS %" GST_TIME_FORMAT " DTS %" GST_TIME_FORMAT
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), priv->input_offset);
|
" (offset:%" G_GUINT64_FORMAT ")",
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_PTS (buffer)),
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_DTS (buffer)), priv->input_offset);
|
||||||
|
|
||||||
ts->offset = priv->input_offset;
|
ts->offset = priv->input_offset;
|
||||||
ts->timestamp = GST_BUFFER_TIMESTAMP (buffer);
|
ts->pts = GST_BUFFER_PTS (buffer);
|
||||||
|
ts->dts = GST_BUFFER_DTS (buffer);
|
||||||
ts->duration = GST_BUFFER_DURATION (buffer);
|
ts->duration = GST_BUFFER_DURATION (buffer);
|
||||||
|
|
||||||
priv->timestamps = g_list_append (priv->timestamps, ts);
|
priv->timestamps = g_list_append (priv->timestamps, ts);
|
||||||
@ -1452,7 +1456,8 @@ gst_video_decoder_add_timestamp (GstVideoDecoder * decoder, GstBuffer * buffer)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
gst_video_decoder_get_timestamp_at_offset (GstVideoDecoder *
|
gst_video_decoder_get_timestamp_at_offset (GstVideoDecoder *
|
||||||
decoder, guint64 offset, GstClockTime * timestamp, GstClockTime * duration)
|
decoder, guint64 offset, GstClockTime * pts, GstClockTime * dts,
|
||||||
|
GstClockTime * duration)
|
||||||
{
|
{
|
||||||
#ifndef GST_DISABLE_GST_DEBUG
|
#ifndef GST_DISABLE_GST_DEBUG
|
||||||
guint64 got_offset = 0;
|
guint64 got_offset = 0;
|
||||||
@ -1460,7 +1465,8 @@ gst_video_decoder_get_timestamp_at_offset (GstVideoDecoder *
|
|||||||
Timestamp *ts;
|
Timestamp *ts;
|
||||||
GList *g;
|
GList *g;
|
||||||
|
|
||||||
*timestamp = GST_CLOCK_TIME_NONE;
|
*pts = GST_CLOCK_TIME_NONE;
|
||||||
|
*dts = GST_CLOCK_TIME_NONE;
|
||||||
*duration = GST_CLOCK_TIME_NONE;
|
*duration = GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
g = decoder->priv->timestamps;
|
g = decoder->priv->timestamps;
|
||||||
@ -1470,7 +1476,8 @@ gst_video_decoder_get_timestamp_at_offset (GstVideoDecoder *
|
|||||||
#ifndef GST_DISABLE_GST_DEBUG
|
#ifndef GST_DISABLE_GST_DEBUG
|
||||||
got_offset = ts->offset;
|
got_offset = ts->offset;
|
||||||
#endif
|
#endif
|
||||||
*timestamp = ts->timestamp;
|
*pts = ts->pts;
|
||||||
|
*dts = ts->dts;
|
||||||
*duration = ts->duration;
|
*duration = ts->duration;
|
||||||
g_free (ts);
|
g_free (ts);
|
||||||
g = g->next;
|
g = g->next;
|
||||||
@ -1481,9 +1488,9 @@ gst_video_decoder_get_timestamp_at_offset (GstVideoDecoder *
|
|||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (decoder,
|
GST_LOG_OBJECT (decoder,
|
||||||
"got timestamp %" GST_TIME_FORMAT " @ offs %" G_GUINT64_FORMAT
|
"got PTS %" GST_TIME_FORMAT " DTS %" GST_TIME_FORMAT " @ offs %"
|
||||||
" (wanted offset:%" G_GUINT64_FORMAT ")", GST_TIME_ARGS (*timestamp),
|
G_GUINT64_FORMAT " (wanted offset:%" G_GUINT64_FORMAT ")",
|
||||||
got_offset, offset);
|
GST_TIME_ARGS (*pts), GST_TIME_ARGS (*dts), got_offset, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1590,7 +1597,7 @@ gst_video_decoder_chain_forward (GstVideoDecoder * decoder,
|
|||||||
if (priv->current_frame == NULL)
|
if (priv->current_frame == NULL)
|
||||||
priv->current_frame = gst_video_decoder_new_frame (decoder);
|
priv->current_frame = gst_video_decoder_new_frame (decoder);
|
||||||
|
|
||||||
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
|
if (GST_BUFFER_PTS_IS_VALID (buf)) {
|
||||||
gst_video_decoder_add_timestamp (decoder, buf);
|
gst_video_decoder_add_timestamp (decoder, buf);
|
||||||
}
|
}
|
||||||
priv->input_offset += gst_buffer_get_size (buf);
|
priv->input_offset += gst_buffer_get_size (buf);
|
||||||
@ -1647,8 +1654,10 @@ gst_video_decoder_flush_decode (GstVideoDecoder * dec)
|
|||||||
GstVideoCodecFrame *frame = (GstVideoCodecFrame *) (walk->data);
|
GstVideoCodecFrame *frame = (GstVideoCodecFrame *) (walk->data);
|
||||||
GstBuffer *buf = frame->input_buffer;
|
GstBuffer *buf = frame->input_buffer;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (dec, "decoding frame %p buffer %p, ts %" GST_TIME_FORMAT,
|
GST_DEBUG_OBJECT (dec, "decoding frame %p buffer %p, PTS %" GST_TIME_FORMAT
|
||||||
frame, buf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
|
", DTS %" GST_TIME_FORMAT, frame, buf,
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_DTS (buf)));
|
||||||
|
|
||||||
next = walk->next;
|
next = walk->next;
|
||||||
|
|
||||||
@ -1695,8 +1704,9 @@ gst_video_decoder_flush_parse (GstVideoDecoder * dec, gboolean at_eos)
|
|||||||
GstBuffer *buf = GST_BUFFER_CAST (walk->data);
|
GstBuffer *buf = GST_BUFFER_CAST (walk->data);
|
||||||
GList *next = walk->next;
|
GList *next = walk->next;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (dec, "parsing buffer %p, ts %" GST_TIME_FORMAT,
|
GST_DEBUG_OBJECT (dec, "parsing buffer %p, PTS %" GST_TIME_FORMAT
|
||||||
buf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
|
", DTS %" GST_TIME_FORMAT, buf, GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_DTS (buf)));
|
||||||
|
|
||||||
/* parse buffer, resulting frames prepended to parse_gather queue */
|
/* parse buffer, resulting frames prepended to parse_gather queue */
|
||||||
gst_buffer_ref (buf);
|
gst_buffer_ref (buf);
|
||||||
@ -1730,8 +1740,10 @@ gst_video_decoder_flush_parse (GstVideoDecoder * dec, gboolean at_eos)
|
|||||||
|
|
||||||
/* if we copied a keyframe, flush and decode the decode queue */
|
/* if we copied a keyframe, flush and decode the decode queue */
|
||||||
if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) {
|
if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) {
|
||||||
GST_DEBUG_OBJECT (dec, "found keyframe %p with PTS %" GST_TIME_FORMAT,
|
GST_DEBUG_OBJECT (dec, "found keyframe %p with PTS %" GST_TIME_FORMAT
|
||||||
frame, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (frame->input_buffer)));
|
", DTS %" GST_TIME_FORMAT, frame,
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_PTS (frame->input_buffer)),
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_DTS (frame->input_buffer)));
|
||||||
res = gst_video_decoder_flush_decode (dec);
|
res = gst_video_decoder_flush_decode (dec);
|
||||||
if (res != GST_FLOW_OK)
|
if (res != GST_FLOW_OK)
|
||||||
goto done;
|
goto done;
|
||||||
@ -1794,8 +1806,10 @@ gst_video_decoder_chain_reverse (GstVideoDecoder * dec, GstBuffer * buf)
|
|||||||
|
|
||||||
if (G_LIKELY (buf)) {
|
if (G_LIKELY (buf)) {
|
||||||
GST_DEBUG_OBJECT (dec, "gathering buffer %p of size %" G_GSIZE_FORMAT ", "
|
GST_DEBUG_OBJECT (dec, "gathering buffer %p of size %" G_GSIZE_FORMAT ", "
|
||||||
"time %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT, buf,
|
"PTS %" GST_TIME_FORMAT ", DTS %" GST_TIME_FORMAT ", dur %"
|
||||||
gst_buffer_get_size (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
|
GST_TIME_FORMAT, buf, gst_buffer_get_size (buf),
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
|
||||||
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
|
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
|
||||||
|
|
||||||
/* add buffer to gather queue */
|
/* add buffer to gather queue */
|
||||||
@ -1814,8 +1828,10 @@ gst_video_decoder_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
|||||||
decoder = GST_VIDEO_DECODER (parent);
|
decoder = GST_VIDEO_DECODER (parent);
|
||||||
|
|
||||||
GST_LOG_OBJECT (decoder,
|
GST_LOG_OBJECT (decoder,
|
||||||
"chain %" GST_TIME_FORMAT " duration %" GST_TIME_FORMAT " size %"
|
"chain PTS %" GST_TIME_FORMAT ", DTS %" GST_TIME_FORMAT " duration %"
|
||||||
G_GSIZE_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
|
GST_TIME_FORMAT " size %" G_GSIZE_FORMAT,
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
|
||||||
|
GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
|
||||||
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), gst_buffer_get_size (buf));
|
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), gst_buffer_get_size (buf));
|
||||||
|
|
||||||
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
|
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
|
||||||
@ -1973,7 +1989,7 @@ gst_video_decoder_prepare_finish_frame (GstVideoDecoder *
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
GST_LOG_OBJECT (decoder,
|
GST_LOG_OBJECT (decoder,
|
||||||
"finish frame %p (#%d) sync:%d pts:%" GST_TIME_FORMAT " dts:%"
|
"finish frame %p (#%d) sync:%d PTS:%" GST_TIME_FORMAT " DTS:%"
|
||||||
GST_TIME_FORMAT,
|
GST_TIME_FORMAT,
|
||||||
frame, frame->system_frame_number,
|
frame, frame->system_frame_number,
|
||||||
GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame), GST_TIME_ARGS (frame->pts),
|
GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame), GST_TIME_ARGS (frame->pts),
|
||||||
@ -2182,7 +2198,9 @@ gst_video_decoder_finish_frame (GstVideoDecoder * decoder,
|
|||||||
|
|
||||||
GST_BUFFER_FLAG_UNSET (output_buffer, GST_BUFFER_FLAG_DELTA_UNIT);
|
GST_BUFFER_FLAG_UNSET (output_buffer, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (output_buffer) = frame->pts;
|
/* set PTS and DTS to both the PTS for decoded frames */
|
||||||
|
GST_BUFFER_PTS (output_buffer) = frame->pts;
|
||||||
|
GST_BUFFER_DTS (output_buffer) = frame->pts;
|
||||||
GST_BUFFER_DURATION (output_buffer) = frame->duration;
|
GST_BUFFER_DURATION (output_buffer) = frame->duration;
|
||||||
|
|
||||||
GST_BUFFER_OFFSET (output_buffer) = GST_BUFFER_OFFSET_NONE;
|
GST_BUFFER_OFFSET (output_buffer) = GST_BUFFER_OFFSET_NONE;
|
||||||
@ -2219,7 +2237,7 @@ gst_video_decoder_clip_and_push_buf (GstVideoDecoder * decoder, GstBuffer * buf)
|
|||||||
GstClockTime duration;
|
GstClockTime duration;
|
||||||
|
|
||||||
/* Check for clipping */
|
/* Check for clipping */
|
||||||
start = GST_BUFFER_TIMESTAMP (buf);
|
start = GST_BUFFER_PTS (buf);
|
||||||
duration = GST_BUFFER_DURATION (buf);
|
duration = GST_BUFFER_DURATION (buf);
|
||||||
|
|
||||||
stop = GST_CLOCK_TIME_NONE;
|
stop = GST_CLOCK_TIME_NONE;
|
||||||
@ -2231,7 +2249,7 @@ gst_video_decoder_clip_and_push_buf (GstVideoDecoder * decoder, GstBuffer * buf)
|
|||||||
segment = &decoder->output_segment;
|
segment = &decoder->output_segment;
|
||||||
if (gst_segment_clip (segment, GST_FORMAT_TIME, start, stop, &cstart, &cstop)) {
|
if (gst_segment_clip (segment, GST_FORMAT_TIME, start, stop, &cstart, &cstop)) {
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (buf) = cstart;
|
GST_BUFFER_PTS (buf) = cstart;
|
||||||
|
|
||||||
if (stop != GST_CLOCK_TIME_NONE)
|
if (stop != GST_CLOCK_TIME_NONE)
|
||||||
GST_BUFFER_DURATION (buf) = cstop - cstart;
|
GST_BUFFER_DURATION (buf) = cstop - cstart;
|
||||||
@ -2240,8 +2258,8 @@ gst_video_decoder_clip_and_push_buf (GstVideoDecoder * decoder, GstBuffer * buf)
|
|||||||
"accepting buffer inside segment: %" GST_TIME_FORMAT " %"
|
"accepting buffer inside segment: %" GST_TIME_FORMAT " %"
|
||||||
GST_TIME_FORMAT " seg %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT
|
GST_TIME_FORMAT " seg %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT
|
||||||
" time %" GST_TIME_FORMAT,
|
" time %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
|
GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) +
|
GST_TIME_ARGS (GST_BUFFER_PTS (buf) +
|
||||||
GST_BUFFER_DURATION (buf)),
|
GST_BUFFER_DURATION (buf)),
|
||||||
GST_TIME_ARGS (segment->start), GST_TIME_ARGS (segment->stop),
|
GST_TIME_ARGS (segment->start), GST_TIME_ARGS (segment->stop),
|
||||||
GST_TIME_ARGS (segment->time));
|
GST_TIME_ARGS (segment->time));
|
||||||
@ -2271,9 +2289,9 @@ gst_video_decoder_clip_and_push_buf (GstVideoDecoder * decoder, GstBuffer * buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (decoder, "pushing buffer %p of size %" G_GSIZE_FORMAT ", "
|
GST_DEBUG_OBJECT (decoder, "pushing buffer %p of size %" G_GSIZE_FORMAT ", "
|
||||||
"time %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT, buf,
|
"PTS %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT, buf,
|
||||||
gst_buffer_get_size (buf),
|
gst_buffer_get_size (buf),
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
|
GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
|
||||||
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
|
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
|
||||||
|
|
||||||
/* we got data, so note things are looking up again, reduce
|
/* we got data, so note things are looking up again, reduce
|
||||||
@ -2353,8 +2371,7 @@ gst_video_decoder_have_frame (GstVideoDecoder * decoder)
|
|||||||
GstVideoDecoderPrivate *priv = decoder->priv;
|
GstVideoDecoderPrivate *priv = decoder->priv;
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
int n_available;
|
int n_available;
|
||||||
GstClockTime timestamp;
|
GstClockTime pts, dts, duration;
|
||||||
GstClockTime duration;
|
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
GST_LOG_OBJECT (decoder, "have_frame");
|
GST_LOG_OBJECT (decoder, "have_frame");
|
||||||
@ -2371,14 +2388,16 @@ gst_video_decoder_have_frame (GstVideoDecoder * decoder)
|
|||||||
priv->current_frame->input_buffer = buffer;
|
priv->current_frame->input_buffer = buffer;
|
||||||
|
|
||||||
gst_video_decoder_get_timestamp_at_offset (decoder,
|
gst_video_decoder_get_timestamp_at_offset (decoder,
|
||||||
priv->frame_offset, ×tamp, &duration);
|
priv->frame_offset, &pts, &dts, &duration);
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (buffer) = timestamp;
|
GST_BUFFER_PTS (buffer) = pts;
|
||||||
|
GST_BUFFER_DTS (buffer) = dts;
|
||||||
GST_BUFFER_DURATION (buffer) = duration;
|
GST_BUFFER_DURATION (buffer) = duration;
|
||||||
|
|
||||||
GST_LOG_OBJECT (decoder, "collected frame size %d, "
|
GST_LOG_OBJECT (decoder, "collected frame size %d, "
|
||||||
"ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT,
|
"PTS %" GST_TIME_FORMAT ", DTS %" GST_TIME_FORMAT ", dur %"
|
||||||
n_available, GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration));
|
GST_TIME_FORMAT, n_available, GST_TIME_ARGS (pts), GST_TIME_ARGS (dts),
|
||||||
|
GST_TIME_ARGS (duration));
|
||||||
|
|
||||||
/* In reverse playback, just capture and queue frames for later processing */
|
/* In reverse playback, just capture and queue frames for later processing */
|
||||||
if (decoder->output_segment.rate < 0.0) {
|
if (decoder->output_segment.rate < 0.0) {
|
||||||
@ -2415,15 +2434,18 @@ gst_video_decoder_decode_frame (GstVideoDecoder * decoder,
|
|||||||
|
|
||||||
frame->distance_from_sync = priv->distance_from_sync;
|
frame->distance_from_sync = priv->distance_from_sync;
|
||||||
priv->distance_from_sync++;
|
priv->distance_from_sync++;
|
||||||
frame->pts = GST_BUFFER_TIMESTAMP (frame->input_buffer);
|
frame->pts = GST_BUFFER_PTS (frame->input_buffer);
|
||||||
|
frame->dts = GST_BUFFER_DTS (frame->input_buffer);
|
||||||
frame->duration = GST_BUFFER_DURATION (frame->input_buffer);
|
frame->duration = GST_BUFFER_DURATION (frame->input_buffer);
|
||||||
|
|
||||||
/* For keyframes, DTS = PTS */
|
/* For keyframes, PTS = DTS */
|
||||||
if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame))
|
if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) {
|
||||||
frame->dts = frame->pts;
|
if (!GST_CLOCK_TIME_IS_VALID (frame->pts))
|
||||||
|
frame->pts = frame->dts;
|
||||||
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (decoder, "pts %" GST_TIME_FORMAT, GST_TIME_ARGS (frame->pts));
|
GST_LOG_OBJECT (decoder, "PTS %" GST_TIME_FORMAT ", DTS %" GST_TIME_FORMAT,
|
||||||
GST_LOG_OBJECT (decoder, "dts %" GST_TIME_FORMAT, GST_TIME_ARGS (frame->dts));
|
GST_TIME_ARGS (frame->pts), GST_TIME_ARGS (frame->dts));
|
||||||
GST_LOG_OBJECT (decoder, "dist %d", frame->distance_from_sync);
|
GST_LOG_OBJECT (decoder, "dist %d", frame->distance_from_sync);
|
||||||
priv->frames = g_list_append (priv->frames, frame);
|
priv->frames = g_list_append (priv->frames, frame);
|
||||||
frame->deadline =
|
frame->deadline =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user