mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
matroska: Add an helper method to get buffer timestamps
... and replace GST_BUFFER_TIMESTAMP that always return PTS with this method that return PTS or DTS based on stream type. https://bugzilla.gnome.org/show_bug.cgi?id=745192
This commit is contained in:
parent
8984e18ef7
commit
f727762c1f
4 changed files with 46 additions and 32 deletions
|
@ -3090,6 +3090,7 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
|
||||||
gint flags = 0;
|
gint flags = 0;
|
||||||
gint64 referenceblock = 0;
|
gint64 referenceblock = 0;
|
||||||
gint64 offset;
|
gint64 offset;
|
||||||
|
GstClockTime buffer_timestamp;
|
||||||
|
|
||||||
offset = gst_ebml_read_get_offset (ebml);
|
offset = gst_ebml_read_get_offset (ebml);
|
||||||
|
|
||||||
|
@ -3468,6 +3469,8 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
|
||||||
goto next_lace;
|
goto next_lace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buffer_timestamp = gst_matroska_track_get_buffer_timestamp (stream, sub);
|
||||||
|
|
||||||
if (!stream->dts_only)
|
if (!stream->dts_only)
|
||||||
GST_BUFFER_PTS (sub) = lace_time;
|
GST_BUFFER_PTS (sub) = lace_time;
|
||||||
else
|
else
|
||||||
|
@ -3580,7 +3583,7 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
|
||||||
"Pushing lace %d, data of size %" G_GSIZE_FORMAT
|
"Pushing lace %d, data of size %" G_GSIZE_FORMAT
|
||||||
" for stream %d, time=%" GST_TIME_FORMAT " and duration=%"
|
" for stream %d, time=%" GST_TIME_FORMAT " and duration=%"
|
||||||
GST_TIME_FORMAT, n, gst_buffer_get_size (sub), stream_num,
|
GST_TIME_FORMAT, n, gst_buffer_get_size (sub), stream_num,
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)),
|
GST_TIME_ARGS (buffer_timestamp),
|
||||||
GST_TIME_ARGS (GST_BUFFER_DURATION (sub)));
|
GST_TIME_ARGS (GST_BUFFER_DURATION (sub)));
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -3591,13 +3594,13 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux,
|
||||||
|
|
||||||
GST_LOG_OBJECT (demux, "adding association %" GST_TIME_FORMAT "-> %"
|
GST_LOG_OBJECT (demux, "adding association %" GST_TIME_FORMAT "-> %"
|
||||||
G_GUINT64_FORMAT " for writer id %d",
|
G_GUINT64_FORMAT " for writer id %d",
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)), cluster_offset,
|
GST_TIME_ARGS (buffer_timestamp), cluster_offset,
|
||||||
stream->index_writer_id);
|
stream->index_writer_id);
|
||||||
gst_index_add_association (demux->common.element_index,
|
gst_index_add_association (demux->common.element_index,
|
||||||
stream->index_writer_id, GST_BUFFER_FLAG_IS_SET (sub,
|
stream->index_writer_id, GST_BUFFER_FLAG_IS_SET (sub,
|
||||||
GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : GST_ASSOCIATION_FLAG_KEY_UNIT,
|
GST_BUFFER_FLAG_DELTA_UNIT) ? 0 : GST_ASSOCIATION_FLAG_KEY_UNIT,
|
||||||
GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (sub), GST_FORMAT_BYTES,
|
GST_FORMAT_TIME, buffer_timestamp, GST_FORMAT_BYTES, cluster_offset,
|
||||||
cluster_offset, NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -297,6 +297,17 @@ gst_matroska_parse_flac_stream_headers (gpointer codec_data,
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GstClockTime
|
||||||
|
gst_matroska_track_get_buffer_timestamp (GstMatroskaTrackContext * track,
|
||||||
|
GstBuffer * buf)
|
||||||
|
{
|
||||||
|
if (track->dts_only) {
|
||||||
|
return GST_BUFFER_DTS (buf);
|
||||||
|
} else {
|
||||||
|
return GST_BUFFER_PTS (buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gst_matroska_track_free (GstMatroskaTrackContext * track)
|
gst_matroska_track_free (GstMatroskaTrackContext * track)
|
||||||
{
|
{
|
||||||
|
|
|
@ -650,5 +650,6 @@ GstBufferList * gst_matroska_parse_opus_stream_headers (gpointer codec_data,
|
||||||
GstBufferList * gst_matroska_parse_flac_stream_headers (gpointer codec_data,
|
GstBufferList * gst_matroska_parse_flac_stream_headers (gpointer codec_data,
|
||||||
gsize codec_data_size);
|
gsize codec_data_size);
|
||||||
void gst_matroska_track_free (GstMatroskaTrackContext * track);
|
void gst_matroska_track_free (GstMatroskaTrackContext * track);
|
||||||
|
GstClockTime gst_matroska_track_get_buffer_timestamp (GstMatroskaTrackContext * track, GstBuffer *buf);
|
||||||
|
|
||||||
#endif /* __GST_MATROSKA_IDS_H__ */
|
#endif /* __GST_MATROSKA_IDS_H__ */
|
||||||
|
|
|
@ -3369,6 +3369,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
|
||||||
gboolean is_video_invisible = FALSE;
|
gboolean is_video_invisible = FALSE;
|
||||||
GstMatroskamuxPad *pad;
|
GstMatroskamuxPad *pad;
|
||||||
gint flags = 0;
|
gint flags = 0;
|
||||||
|
GstClockTime buffer_timestamp;
|
||||||
|
|
||||||
/* write data */
|
/* write data */
|
||||||
pad = GST_MATROSKAMUX_PAD_CAST (collect_pad->collect.pad);
|
pad = GST_MATROSKAMUX_PAD_CAST (collect_pad->collect.pad);
|
||||||
|
@ -3390,12 +3391,14 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buffer_timestamp =
|
||||||
|
gst_matroska_track_get_buffer_timestamp (collect_pad->track, buf);
|
||||||
|
|
||||||
/* hm, invalid timestamp (due to --to be fixed--- element upstream);
|
/* hm, invalid timestamp (due to --to be fixed--- element upstream);
|
||||||
* this would wreak havoc with time stored in matroska file */
|
* this would wreak havoc with time stored in matroska file */
|
||||||
/* TODO: maybe calculate a timestamp by using the previous timestamp
|
/* TODO: maybe calculate a timestamp by using the previous timestamp
|
||||||
* and default duration */
|
* and default duration */
|
||||||
if ((!GST_BUFFER_PTS_IS_VALID (buf) && !collect_pad->track->dts_only)
|
if (!GST_CLOCK_TIME_IS_VALID (buffer_timestamp)) {
|
||||||
|| (!GST_BUFFER_DTS_IS_VALID (buf) && collect_pad->track->dts_only)) {
|
|
||||||
GST_WARNING_OBJECT (collect_pad->collect.pad,
|
GST_WARNING_OBJECT (collect_pad->collect.pad,
|
||||||
"Invalid buffer timestamp; dropping buffer");
|
"Invalid buffer timestamp; dropping buffer");
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
|
@ -3403,16 +3406,12 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the timestamp for outgoing buffers */
|
/* set the timestamp for outgoing buffers */
|
||||||
if (collect_pad->track->dts_only) {
|
ebml->timestamp = buffer_timestamp;
|
||||||
ebml->timestamp = GST_BUFFER_DTS (buf);
|
|
||||||
} else {
|
|
||||||
ebml->timestamp = GST_BUFFER_PTS (buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
|
if (collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_VIDEO) {
|
||||||
if (!GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
|
if (!GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
|
||||||
GST_LOG_OBJECT (mux, "have video keyframe, ts=%" GST_TIME_FORMAT,
|
GST_LOG_OBJECT (mux, "have video keyframe, ts=%" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
|
GST_TIME_ARGS (buffer_timestamp));
|
||||||
is_video_keyframe = TRUE;
|
is_video_keyframe = TRUE;
|
||||||
} else if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DECODE_ONLY) &&
|
} 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)
|
(!strcmp (collect_pad->track->codec_id, GST_MATROSKA_CODEC_ID_VIDEO_VP8)
|
||||||
|
@ -3420,7 +3419,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
|
||||||
GST_MATROSKA_CODEC_ID_VIDEO_VP9))) {
|
GST_MATROSKA_CODEC_ID_VIDEO_VP9))) {
|
||||||
GST_LOG_OBJECT (mux,
|
GST_LOG_OBJECT (mux,
|
||||||
"have VP8 video invisible frame, " "ts=%" GST_TIME_FORMAT,
|
"have VP8 video invisible frame, " "ts=%" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
|
GST_TIME_ARGS (buffer_timestamp));
|
||||||
is_video_invisible = TRUE;
|
is_video_invisible = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3429,7 +3428,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
|
||||||
/* start a new cluster at every keyframe, at every GstForceKeyUnit event,
|
/* start a new cluster at every keyframe, at every GstForceKeyUnit event,
|
||||||
* or when we may be reaching the limit of the relative timestamp */
|
* or when we may be reaching the limit of the relative timestamp */
|
||||||
if (mux->cluster_time +
|
if (mux->cluster_time +
|
||||||
mux->max_cluster_duration < GST_BUFFER_TIMESTAMP (buf)
|
mux->max_cluster_duration < buffer_timestamp
|
||||||
|| is_video_keyframe || mux->force_key_unit_event) {
|
|| is_video_keyframe || mux->force_key_unit_event) {
|
||||||
if (!mux->streamable)
|
if (!mux->streamable)
|
||||||
gst_ebml_write_master_finish (ebml, mux->cluster);
|
gst_ebml_write_master_finish (ebml, mux->cluster);
|
||||||
|
@ -3446,13 +3445,11 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
|
||||||
mux->cluster =
|
mux->cluster =
|
||||||
gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
|
gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
|
||||||
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
|
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
|
||||||
gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1,
|
gst_util_uint64_scale (buffer_timestamp, 1, mux->time_scale));
|
||||||
mux->time_scale));
|
|
||||||
GST_LOG_OBJECT (mux, "cluster timestamp %" G_GUINT64_FORMAT,
|
GST_LOG_OBJECT (mux, "cluster timestamp %" G_GUINT64_FORMAT,
|
||||||
gst_util_uint64_scale (GST_BUFFER_TIMESTAMP (buf), 1,
|
gst_util_uint64_scale (buffer_timestamp, 1, mux->time_scale));
|
||||||
mux->time_scale));
|
gst_ebml_write_flush_cache (ebml, TRUE, buffer_timestamp);
|
||||||
gst_ebml_write_flush_cache (ebml, TRUE, GST_BUFFER_TIMESTAMP (buf));
|
mux->cluster_time = buffer_timestamp;
|
||||||
mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
|
|
||||||
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_PREVSIZE,
|
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_PREVSIZE,
|
||||||
mux->prev_cluster_size);
|
mux->prev_cluster_size);
|
||||||
}
|
}
|
||||||
|
@ -3463,9 +3460,9 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
|
||||||
gst_ebml_write_set_cache (ebml, 0x20);
|
gst_ebml_write_set_cache (ebml, 0x20);
|
||||||
mux->cluster = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
|
mux->cluster = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
|
||||||
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
|
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 (buffer_timestamp, 1, mux->time_scale));
|
||||||
gst_ebml_write_flush_cache (ebml, TRUE, GST_BUFFER_TIMESTAMP (buf));
|
gst_ebml_write_flush_cache (ebml, TRUE, buffer_timestamp);
|
||||||
mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
|
mux->cluster_time = buffer_timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update duration of this track */
|
/* update duration of this track */
|
||||||
|
@ -3494,7 +3491,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_idx < 0 || mux->min_index_interval == 0 ||
|
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, buffer_timestamp)
|
||||||
>= mux->min_index_interval)) {
|
>= mux->min_index_interval)) {
|
||||||
GstMatroskaIndex *idx;
|
GstMatroskaIndex *idx;
|
||||||
|
|
||||||
|
@ -3505,7 +3502,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
|
||||||
idx = &mux->index[mux->num_indexes++];
|
idx = &mux->index[mux->num_indexes++];
|
||||||
|
|
||||||
idx->pos = mux->cluster_pos;
|
idx->pos = mux->cluster_pos;
|
||||||
idx->time = GST_BUFFER_TIMESTAMP (buf);
|
idx->time = buffer_timestamp;
|
||||||
idx->track = collect_pad->track->num;
|
idx->track = collect_pad->track->num;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3527,7 +3524,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
|
||||||
/* write the block, for doctype v2 use SimpleBlock if possible
|
/* write the block, for doctype v2 use SimpleBlock if possible
|
||||||
* one slice (*breath*).
|
* one slice (*breath*).
|
||||||
* FIXME: Need to do correct lacing! */
|
* FIXME: Need to do correct lacing! */
|
||||||
relative_timestamp64 = GST_BUFFER_TIMESTAMP (buf) - mux->cluster_time;
|
relative_timestamp64 = buffer_timestamp - mux->cluster_time;
|
||||||
if (relative_timestamp64 >= 0) {
|
if (relative_timestamp64 >= 0) {
|
||||||
/* round the timestamp */
|
/* round the timestamp */
|
||||||
relative_timestamp64 += gst_util_uint64_scale (mux->time_scale, 1, 2);
|
relative_timestamp64 += gst_util_uint64_scale (mux->time_scale, 1, 2);
|
||||||
|
@ -3555,7 +3552,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
|
||||||
gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK,
|
gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK,
|
||||||
gst_buffer_get_size (buf) + gst_buffer_get_size (hdr));
|
gst_buffer_get_size (buf) + gst_buffer_get_size (hdr));
|
||||||
gst_ebml_write_buffer (ebml, 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, buffer_timestamp);
|
||||||
gst_ebml_write_buffer (ebml, buf);
|
gst_ebml_write_buffer (ebml, buf);
|
||||||
|
|
||||||
return gst_ebml_last_write_result (ebml);
|
return gst_ebml_last_write_result (ebml);
|
||||||
|
@ -3574,7 +3571,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad,
|
||||||
gst_ebml_write_buffer (ebml, hdr);
|
gst_ebml_write_buffer (ebml, hdr);
|
||||||
gst_ebml_write_master_finish_full (ebml, blockgroup,
|
gst_ebml_write_master_finish_full (ebml, blockgroup,
|
||||||
gst_buffer_get_size (buf));
|
gst_buffer_get_size (buf));
|
||||||
gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf));
|
gst_ebml_write_flush_cache (ebml, FALSE, buffer_timestamp);
|
||||||
gst_ebml_write_buffer (ebml, buf);
|
gst_ebml_write_buffer (ebml, buf);
|
||||||
|
|
||||||
return gst_ebml_last_write_result (ebml);
|
return gst_ebml_last_write_result (ebml);
|
||||||
|
@ -3594,11 +3591,11 @@ static GstFlowReturn
|
||||||
gst_matroska_mux_handle_buffer (GstCollectPads * pads, GstCollectData * data,
|
gst_matroska_mux_handle_buffer (GstCollectPads * pads, GstCollectData * data,
|
||||||
GstBuffer * buf, gpointer user_data)
|
GstBuffer * buf, gpointer user_data)
|
||||||
{
|
{
|
||||||
|
GstClockTime buffer_timestamp;
|
||||||
GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
|
GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
|
||||||
GstEbmlWrite *ebml = mux->ebml_write;
|
GstEbmlWrite *ebml = mux->ebml_write;
|
||||||
GstMatroskaPad *best;
|
GstMatroskaPad *best;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (mux, "Collected pads");
|
GST_DEBUG_OBJECT (mux, "Collected pads");
|
||||||
|
|
||||||
/* start with a header */
|
/* start with a header */
|
||||||
|
@ -3634,15 +3631,17 @@ gst_matroska_mux_handle_buffer (GstCollectPads * pads, GstCollectData * data,
|
||||||
/* if we have a best stream, should also have a buffer */
|
/* if we have a best stream, should also have a buffer */
|
||||||
g_assert (buf);
|
g_assert (buf);
|
||||||
|
|
||||||
|
buffer_timestamp = gst_matroska_track_get_buffer_timestamp (best->track, buf);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (best->collect.pad, "best pad - buffer ts %"
|
GST_DEBUG_OBJECT (best->collect.pad, "best pad - buffer ts %"
|
||||||
GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
|
GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
|
GST_TIME_ARGS (buffer_timestamp),
|
||||||
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
|
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
|
||||||
|
|
||||||
/* make note of first and last encountered timestamps, so we can calculate
|
/* make note of first and last encountered timestamps, so we can calculate
|
||||||
* the actual duration later when we send an updated header on eos */
|
* the actual duration later when we send an updated header on eos */
|
||||||
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
|
if (GST_CLOCK_TIME_IS_VALID (buffer_timestamp)) {
|
||||||
GstClockTime start_ts = GST_BUFFER_TIMESTAMP (buf);
|
GstClockTime start_ts = buffer_timestamp;
|
||||||
GstClockTime end_ts = start_ts;
|
GstClockTime end_ts = start_ts;
|
||||||
|
|
||||||
if (GST_BUFFER_DURATION_IS_VALID (buf))
|
if (GST_BUFFER_DURATION_IS_VALID (buf))
|
||||||
|
|
Loading…
Reference in a new issue