mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 03:00:35 +00:00
matroska-mux: Fix incorrect rounding of timestamps
Previously we saved the buffer_timestamp straight into mux->cluster_time. Since the cluster time saved into the file does not have as high precision as GstClockTime depending on the timecodescale the rounding of relative_timestamp was invalid as mux->cluster_time which it was calculated relative to was not equal to the cluster time written to the matroska file. Example of "mkvinfo -v" of how it looks before and after this change in an scenario where previously timestamps got out of order because of this issue. Notice the timestamp of the SimpleBlock right before and right after the Cluster now being in order. The consequence of this however is that the cluster timestamp is not necessarily the same as the timestamp of the first buffer in the cluster however (in case it's rounded up). Before | + SimpleBlock (track number 1, 1 frame(s), timecode 126.922s = 00:02:06.922) | + Frame with size 432 | + SimpleBlock (track number 2, 1 frame(s), timecode 126.933s = 00:02:06.933) | + Frame with size 329 | + SimpleBlock (track number 2, 1 frame(s), timecode 126.955s = 00:02:06.955) | + Frame with size 333 |+ Cluster | + Cluster timecode: 126.954s | + Cluster previous size: 97344 | + SimpleBlock (key, track number 1, 1 frame(s), timecode 126.954s = 00:02:06.954) | + Frame with size 61239 | + SimpleBlock (track number 2, 1 frame(s), timecode 126.975s = 00:02:06.975) | + Frame with size 338 After | + SimpleBlock (track number 1, 1 frame(s), timecode 135.456s = 00:02:15.456) | + Frame with size 2260 | + SimpleBlock (track number 2, 1 frame(s), timecode 135.468s = 00:02:15.468) | + Frame with size 332 | + SimpleBlock (track number 2, 1 frame(s), timecode 135.490s = 00:02:15.490) | + Frame with size 335 |+ Cluster | + Cluster timecode: 135.489s | + Cluster previous size: 158758 | + SimpleBlock (key, track number 1, 1 frame(s), timecode 135.490s = 00:02:15.490) | + Frame with size 88070 | + SimpleBlock (track number 2, 1 frame(s), timecode 135.511s = 00:02:15.511) | + Frame with size 336
This commit is contained in:
parent
2ffb52499f
commit
ce802f033c
1 changed files with 27 additions and 5 deletions
|
@ -3798,6 +3798,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
|
|||
GstBuffer *hdr;
|
||||
guint64 blockgroup;
|
||||
gboolean write_duration;
|
||||
guint64 cluster_time_scaled;
|
||||
gint16 relative_timestamp;
|
||||
gint64 relative_timestamp64;
|
||||
guint64 block_duration, duration_diff = 0;
|
||||
|
@ -3910,6 +3911,8 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
|
|||
gst_pad_push_event (mux->srcpad, mux->force_key_unit_event);
|
||||
mux->force_key_unit_event = NULL;
|
||||
}
|
||||
cluster_time_scaled =
|
||||
gst_util_uint64_scale (buffer_timestamp, 1, mux->time_scale);
|
||||
|
||||
mux->prev_cluster_size = ebml->pos - mux->cluster_pos;
|
||||
mux->cluster_pos = ebml->pos;
|
||||
|
@ -3917,25 +3920,44 @@ 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 (buffer_timestamp, 1, mux->time_scale));
|
||||
cluster_time_scaled);
|
||||
GST_LOG_OBJECT (mux, "cluster timestamp %" G_GUINT64_FORMAT,
|
||||
gst_util_uint64_scale (buffer_timestamp, 1, mux->time_scale));
|
||||
gst_ebml_write_flush_cache (ebml, is_video_keyframe
|
||||
|| is_audio_only, buffer_timestamp);
|
||||
mux->cluster_time = buffer_timestamp;
|
||||
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_PREVSIZE,
|
||||
mux->prev_cluster_size);
|
||||
/* cluster_time needs to be identical in value to what's stored in the
|
||||
* matroska so we need to have it with the same precision as what's
|
||||
* possible with the set timecodescale rather than just using the
|
||||
* buffer_timestamp.
|
||||
* If this is not done the rounding of relative_timestamp will be
|
||||
* incorrect and possibly making the timestamps get out of order if tw
|
||||
* buffers arrive at the same millisecond (assuming default timecodescale
|
||||
* of 1ms) */
|
||||
mux->cluster_time =
|
||||
gst_util_uint64_scale (cluster_time_scaled, mux->time_scale, 1);
|
||||
}
|
||||
} else {
|
||||
/* first cluster */
|
||||
|
||||
cluster_time_scaled =
|
||||
gst_util_uint64_scale (buffer_timestamp, 1, mux->time_scale);
|
||||
mux->cluster_pos = ebml->pos;
|
||||
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 (buffer_timestamp, 1, mux->time_scale));
|
||||
cluster_time_scaled);
|
||||
gst_ebml_write_flush_cache (ebml, TRUE, buffer_timestamp);
|
||||
mux->cluster_time = buffer_timestamp;
|
||||
/* cluster_time needs to be identical in value to what's stored in the
|
||||
* matroska so we need to have it with the same precision as what's
|
||||
* possible with the set timecodescale rather than just using the
|
||||
* buffer_timestamp.
|
||||
* If this is not done the rounding of relative_timestamp will be
|
||||
* incorrect and possibly making the timestamps get out of order if tw
|
||||
* buffers arrive at the same millisecond (assuming default timecodescale
|
||||
* of 1ms) */
|
||||
mux->cluster_time =
|
||||
gst_util_uint64_scale (cluster_time_scaled, mux->time_scale, 1);
|
||||
}
|
||||
|
||||
/* We currently write index entries for all video tracks or for the audio
|
||||
|
|
Loading…
Reference in a new issue