From b3aa8755fe07639f22e4104f4932d769d6c9075a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 5 Jan 2014 10:22:37 +0100 Subject: [PATCH] matroskamux: Use the running time for container timestamps, not buffer timestamps Buffer timestamps have no real meaning here, and for selecting the next buffer we already use the running time anyway. --- gst/matroska/matroska-mux.c | 69 ++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c index 7fc51e44c0..884ee36dd9 100644 --- a/gst/matroska/matroska-mux.c +++ b/gst/matroska/matroska-mux.c @@ -3229,6 +3229,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad, GstBuffer *hdr; guint64 blockgroup; gboolean write_duration; + GstClockTime timestamp; gint16 relative_timestamp; gint64 relative_timestamp64; guint64 block_duration; @@ -3268,13 +3269,22 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad, return GST_FLOW_OK; } + timestamp = gst_segment_to_running_time (&collect_pad->collect.segment, + GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf)) + if (!GST_CLOCK_TIME_IS_VALID (timestamp)) { + GST_WARNING_OBJECT (collect_pad->collect.pad, + "Invalid buffer running time; dropping buffer"); + gst_buffer_unref (buf); + return GST_FLOW_OK; + } + /* set the timestamp for outgoing buffers */ - ebml->timestamp = GST_BUFFER_TIMESTAMP (buf); + ebml->timestamp = timestamp; if (collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_VIDEO) { if (!GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) { GST_LOG_OBJECT (mux, "have video keyframe, ts=%" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + GST_TIME_ARGS (timestamp)); is_video_keyframe = TRUE; } else if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DECODE_ONLY) && (!strcmp (collect_pad->track->codec_id, GST_MATROSKA_CODEC_ID_VIDEO_VP8) @@ -3282,7 +3292,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad, GST_MATROSKA_CODEC_ID_VIDEO_VP9))) { GST_LOG_OBJECT (mux, "have VP8 video invisible frame, " "ts=%" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + GST_TIME_ARGS (timestamp)); is_video_invisible = TRUE; } } @@ -3291,7 +3301,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad, /* start a new cluster at every keyframe, at every GstForceKeyUnit event, * or when we may be reaching the limit of the relative timestamp */ if (mux->cluster_time + - mux->max_cluster_duration < GST_BUFFER_TIMESTAMP (buf) + mux->max_cluster_duration < timestamp || is_video_keyframe || mux->force_key_unit_event) { if (!mux->streamable) gst_ebml_write_master_finish (ebml, mux->cluster); @@ -3308,13 +3318,11 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad, mux->cluster = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER); gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE, - gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1, - mux->time_scale)); + gst_util_uint64_scale (timestamp, 1, mux->time_scale)); GST_LOG_OBJECT (mux, "cluster timestamp %" G_GUINT64_FORMAT, - gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1, - mux->time_scale)); - gst_ebml_write_flush_cache (ebml, TRUE, GST_BUFFER_TIMESTAMP (buf)); - mux->cluster_time = GST_BUFFER_TIMESTAMP (buf); + gst_util_uint64_scale (timestamp, 1, mux->time_scale)); + gst_ebml_write_flush_cache (ebml, TRUE, timestamp); + mux->cluster_time = timestamp; gst_ebml_write_uint (ebml, GST_MATROSKA_ID_PREVSIZE, mux->prev_cluster_size); } @@ -3325,14 +3333,21 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad, gst_ebml_write_set_cache (ebml, 0x20); mux->cluster = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER); gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE, - gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1, mux->time_scale)); - gst_ebml_write_flush_cache (ebml, TRUE, GST_BUFFER_TIMESTAMP (buf)); - mux->cluster_time = GST_BUFFER_TIMESTAMP (buf); + gst_util_uint64_scale (timestamp, 1, mux->time_scale)); + gst_ebml_write_flush_cache (ebml, TRUE, timestamp); + mux->cluster_time = timestamp; } /* update duration of this track */ - if (GST_BUFFER_DURATION_IS_VALID (buf)) - collect_pad->duration += GST_BUFFER_DURATION (buf); + if (GST_BUFFER_DURATION_IS_VALID (buf)) { + GstClockTime end_time; + + end_time = gst_segment_to_running_time (&collect_pad->collect.segment, + GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)); + if (GST_CLOCK_TIME_IS_VALID (end_time)) + collect_pad->duration += end_time - timestamp; + } /* We currently write index entries for all video tracks or for the audio * track in a single-track audio file. This could be improved by keeping the @@ -3356,7 +3371,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad, } if (last_idx < 0 || mux->min_index_interval == 0 || - (GST_CLOCK_DIFF (mux->index[last_idx].time, GST_BUFFER_TIMESTAMP (buf)) + (GST_CLOCK_DIFF (mux->index[last_idx].time, timestamp) >= mux->min_index_interval)) { GstMatroskaIndex *idx; @@ -3367,7 +3382,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad, idx = &mux->index[mux->num_indexes++]; idx->pos = mux->cluster_pos; - idx->time = GST_BUFFER_TIMESTAMP (buf); + idx->time = timestamp; idx->track = collect_pad->track->num; } } @@ -3389,7 +3404,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad, /* write the block, for doctype v2 use SimpleBlock if possible * one slice (*breath*). * FIXME: Need to do correct lacing! */ - relative_timestamp64 = GST_BUFFER_TIMESTAMP (buf) - mux->cluster_time; + relative_timestamp64 = timestamp - mux->cluster_time; if (relative_timestamp64 >= 0) { /* round the timestamp */ relative_timestamp64 += gst_util_uint64_scale (mux->time_scale, 1, 2); @@ -3417,7 +3432,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad, gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK, gst_buffer_get_size (buf) + gst_buffer_get_size (hdr)); gst_ebml_write_buffer (ebml, hdr); - gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf)); + gst_ebml_write_flush_cache (ebml, FALSE, timestamp); gst_ebml_write_buffer (ebml, buf); return gst_ebml_last_write_result (ebml); @@ -3436,7 +3451,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad, gst_ebml_write_buffer (ebml, hdr); gst_ebml_write_master_finish_full (ebml, blockgroup, gst_buffer_get_size (buf)); - gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf)); + gst_ebml_write_flush_cache (ebml, FALSE, timestamp); gst_ebml_write_buffer (ebml, buf); return gst_ebml_last_write_result (ebml); @@ -3504,13 +3519,19 @@ gst_matroska_mux_handle_buffer (GstCollectPads * pads, GstCollectData * data, /* make note of first and last encountered timestamps, so we can calculate * the actual duration later when we send an updated header on eos */ if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { - GstClockTime start_ts = GST_BUFFER_TIMESTAMP (buf); - GstClockTime end_ts = start_ts; + GstClockTime start_ts = + gst_segment_to_running_time (&best->collect.segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buf)); + GstClockTime end_ts; if (GST_BUFFER_DURATION_IS_VALID (buf)) - end_ts += GST_BUFFER_DURATION (buf); + end_ts = + gst_segment_to_running_time (&best->collect.segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)); else if (best->track->default_duration) - end_ts += best->track->default_duration; + end_ts = start_ts + best->track->default_duration; + else + end_ts = start_ts; if (!GST_CLOCK_TIME_IS_VALID (best->end_ts) || end_ts > best->end_ts) best->end_ts = end_ts;