summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gst-libs/gst/video/gstvideodecoder.c48
-rw-r--r--gst-libs/gst/video/gstvideoencoder.c41
-rw-r--r--gst-libs/gst/video/gstvideoutils.h7
3 files changed, 75 insertions, 21 deletions
diff --git a/gst-libs/gst/video/gstvideodecoder.c b/gst-libs/gst/video/gstvideodecoder.c
index c0fb51d79..db67e3106 100644
--- a/gst-libs/gst/video/gstvideodecoder.c
+++ b/gst-libs/gst/video/gstvideodecoder.c
@@ -2147,21 +2147,44 @@ gst_video_decoder_prepare_finish_frame (GstVideoDecoder *
GST_TIME_ARGS (frame->duration));
}
- if (frame->pts == GST_CLOCK_TIME_NONE &&
- GST_CLOCK_TIME_IS_VALID (priv->pts_delta) && priv->frames) {
- GstVideoCodecFrame *oframe = priv->frames->data;
-
- /* valid delta, so we have some reasonable DTS input,
- * then outgoing PTS = smallest DTS = DTS of oldest frame */
- if (GST_CLOCK_TIME_IS_VALID (oframe->dts)) {
- frame->pts = oframe->dts + priv->pts_delta;
- GST_LOG_OBJECT (decoder,
- "Guessing timestamp %" GST_TIME_FORMAT
- " from DTS %" GST_TIME_FORMAT " for frame...",
- GST_TIME_ARGS (frame->pts), GST_TIME_ARGS (oframe->dts));
+ /* PTS is expected montone ascending,
+ * so a good guess is lowest unsent DTS */
+ {
+ GstClockTime min_ts = GST_CLOCK_TIME_NONE;
+ GstVideoCodecFrame *oframe = NULL;
+ gboolean seen_none = FALSE;
+
+ /* some maintenance regardless */
+ for (l = priv->frames; l; l = l->next) {
+ GstVideoCodecFrame *tmp = l->data;
+
+ if (!GST_CLOCK_TIME_IS_VALID (tmp->abidata.ABI.ts)) {
+ seen_none = TRUE;
+ continue;
+ }
+
+ if (!GST_CLOCK_TIME_IS_VALID (min_ts) || tmp->abidata.ABI.ts < min_ts) {
+ min_ts = tmp->abidata.ABI.ts;
+ oframe = tmp;
+ }
+ }
+ /* save a ts if needed */
+ if (oframe && oframe != frame) {
+ oframe->abidata.ABI.ts = frame->abidata.ABI.ts;
+ }
+
+ /* and set if needed;
+ * valid delta means we have reasonable DTS input */
+ if (!GST_CLOCK_TIME_IS_VALID (frame->pts) && !seen_none &&
+ GST_CLOCK_TIME_IS_VALID (priv->pts_delta)) {
+ frame->pts = min_ts + priv->pts_delta;
+ GST_DEBUG_OBJECT (decoder,
+ "no valid PTS, using oldest DTS %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (frame->pts));
}
}
+
if (frame->pts == GST_CLOCK_TIME_NONE) {
/* Last ditch timestamp guess: Just add the duration to the previous
* frame */
@@ -2568,6 +2591,7 @@ gst_video_decoder_decode_frame (GstVideoDecoder * decoder,
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->abidata.ABI.ts = frame->dts;
/* For keyframes, PTS = DTS */
if (GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame)) {
diff --git a/gst-libs/gst/video/gstvideoencoder.c b/gst-libs/gst/video/gstvideoencoder.c
index 63e2d028c..2b0e3de05 100644
--- a/gst-libs/gst/video/gstvideoencoder.c
+++ b/gst-libs/gst/video/gstvideoencoder.c
@@ -1217,6 +1217,7 @@ gst_video_encoder_new_frame (GstVideoEncoder * encoder, GstBuffer * buf,
frame->pts = pts;
frame->dts = dts;
frame->duration = duration;
+ frame->abidata.ABI.ts = pts;
return frame;
}
@@ -1757,15 +1758,39 @@ gst_video_encoder_finish_frame (GstVideoEncoder * encoder,
GST_BUFFER_FLAG_SET (frame->output_buffer, GST_BUFFER_FLAG_DELTA_UNIT);
}
- /* DTS is expected monotone ascending, so a good guess is the lowest PTS
- * of all pending frames, i.e. the oldest frame's PTS (all being OK) */
- if (!GST_CLOCK_TIME_IS_VALID (frame->dts) && encoder->priv->frames) {
- GstVideoCodecFrame *oframe = encoder->priv->frames->data;
+ /* DTS is expected monotone ascending,
+ * so a good guess is the lowest unsent PTS (all being OK) */
+ {
+ GstClockTime min_ts = GST_CLOCK_TIME_NONE;
+ GstVideoCodecFrame *oframe = NULL;
+ gboolean seen_none = FALSE;
- frame->dts = oframe->pts;
- GST_DEBUG_OBJECT (encoder,
- "no valid DTS, using oldest frame's PTS %" GST_TIME_FORMAT,
- GST_TIME_ARGS (frame->pts));
+ /* some maintenance regardless */
+ for (l = priv->frames; l; l = l->next) {
+ GstVideoCodecFrame *tmp = l->data;
+
+ if (!GST_CLOCK_TIME_IS_VALID (tmp->abidata.ABI.ts)) {
+ seen_none = TRUE;
+ continue;
+ }
+
+ if (!GST_CLOCK_TIME_IS_VALID (min_ts) || tmp->abidata.ABI.ts < min_ts) {
+ min_ts = tmp->abidata.ABI.ts;
+ oframe = tmp;
+ }
+ }
+ /* save a ts if needed */
+ if (oframe && oframe != frame) {
+ oframe->abidata.ABI.ts = frame->abidata.ABI.ts;
+ }
+
+ /* and set if needed */
+ if (!GST_CLOCK_TIME_IS_VALID (frame->dts) && !seen_none) {
+ frame->dts = min_ts;
+ GST_DEBUG_OBJECT (encoder,
+ "no valid DTS, using oldest PTS %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (frame->pts));
+ }
}
frame->distance_from_sync = priv->distance_from_sync;
diff --git a/gst-libs/gst/video/gstvideoutils.h b/gst-libs/gst/video/gstvideoutils.h
index 50cb2b56f..a3ff4f9e3 100644
--- a/gst-libs/gst/video/gstvideoutils.h
+++ b/gst-libs/gst/video/gstvideoutils.h
@@ -246,7 +246,12 @@ struct _GstVideoCodecFrame
gpointer user_data;
GDestroyNotify user_data_destroy_notify;
- void *padding[GST_PADDING_LARGE];
+ union {
+ struct {
+ GstClockTime ts;
+ } ABI;
+ void *padding[GST_PADDING_LARGE];
+ } abidata;
};
/* GstVideoCodecState */