From fcd464ea306af49f48793107774ae10f3511e29e Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Wed, 3 May 2006 14:51:50 +0000 Subject: [PATCH] gst/matroska/matroska-mux.c: Don't misinterpret GST_CLOCK_TIME_NONE as very high timestamp value and then dead-lock w... Original commit message from CVS: Patch by: Mark Nauwelaerts * gst/matroska/matroska-mux.c: (gst_matroska_mux_best_pad), (gst_matroska_mux_stream_is_vorbis_header), (gst_matroska_mux_write_data): Don't misinterpret GST_CLOCK_TIME_NONE as very high timestamp value and then dead-lock when muxing vorbis audio streams (the three vorbis header buffers carry no timestamp, and it would try to mux these after all video buffers). Fixes #340346. Improve clustering: start a new cluster also whenever we get a keyframe. --- ChangeLog | 15 +++++++++++ gst/matroska/matroska-mux.c | 54 +++++++++++++++++++++++++++++++++---- 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index c4da8ba21b..252f92d068 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2006-05-03 Tim-Philipp Müller + + Patch by: Mark Nauwelaerts + + * gst/matroska/matroska-mux.c: (gst_matroska_mux_best_pad), + (gst_matroska_mux_stream_is_vorbis_header), + (gst_matroska_mux_write_data): + Don't misinterpret GST_CLOCK_TIME_NONE as very high timestamp + value and then dead-lock when muxing vorbis audio streams + (the three vorbis header buffers carry no timestamp, and it + would try to mux these after all video buffers). Fixes #340346. + + Improve clustering: start a new cluster also whenever we get + a keyframe. + 2006-05-03 Thomas Vander Stichele * win32/common/config.h: diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c index 6e17588ac2..20d5cfafd2 100644 --- a/gst/matroska/matroska-mux.c +++ b/gst/matroska/matroska-mux.c @@ -1292,9 +1292,10 @@ gst_matroska_mux_best_pad (GstMatroskaMux * mux, gboolean * popped) /* if we have a buffer check if it is better then the current best one */ if (collect_pad->buffer != NULL) { - if (best == NULL - || GST_BUFFER_TIMESTAMP (collect_pad->buffer) < - GST_BUFFER_TIMESTAMP (best->buffer)) { + if (best == NULL || !GST_BUFFER_TIMESTAMP_IS_VALID (collect_pad->buffer) + || (GST_BUFFER_TIMESTAMP_IS_VALID (best->buffer) + && GST_BUFFER_TIMESTAMP (collect_pad->buffer) < + GST_BUFFER_TIMESTAMP (best->buffer))) { best = collect_pad; } } @@ -1303,6 +1304,33 @@ gst_matroska_mux_best_pad (GstMatroskaMux * mux, gboolean * popped) return best; } +static gboolean +gst_matroska_mux_stream_is_vorbis_header (GstMatroskaMux * mux, + GstMatroskaPad * collect_pad) +{ + GstMatroskaTrackAudioContext *audio_ctx; + + audio_ctx = (GstMatroskaTrackAudioContext *) collect_pad->track; + + if (collect_pad->track->type != GST_MATROSKA_TRACK_TYPE_AUDIO) + return FALSE; + + if (audio_ctx->first_frame != FALSE) + return FALSE; + + if (strcmp (collect_pad->track->codec_id, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS)) + return FALSE; + + /* HACK: three frame headers are counted using pos */ + if (++collect_pad->track->pos <= 3) + return TRUE; + + /* 4th vorbis packet => skipped all headers */ + collect_pad->track->pos = 0; + audio_ctx->first_frame = TRUE; + return FALSE; +} + /** * gst_matroska_mux_buffer_header: @@ -1356,12 +1384,28 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad) buf = collect_pad->buffer; collect_pad->buffer = NULL; + /* vorbis header are retrieved from caps and placed in CodecPrivate */ + if (gst_matroska_mux_stream_is_vorbis_header (mux, collect_pad)) { + gst_buffer_unref (buf); + return GST_FLOW_OK; + } + + /* hm, invalid timestamp (due to --to be fixed--- element upstream); + * this would wreak havoc with time stored in matroska file */ + if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { + GST_WARNING_OBJECT (collect_pad->collect.pad, + "Invalid buffer timestamp; dropping buffer"); + gst_buffer_unref (buf); + return GST_FLOW_OK; + } + /* set the timestamp for outgoing buffers */ ebml->timestamp = GST_BUFFER_TIMESTAMP (buf); if (mux->cluster) { - /* start a new cluster every two seconds */ - if (mux->cluster_time + GST_SECOND * 2 < GST_BUFFER_TIMESTAMP (buf)) { + /* start a new cluster every two seconds or at keyframe */ + if (mux->cluster_time + GST_SECOND * 2 < GST_BUFFER_TIMESTAMP (buf) + || !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) { GstMatroskaMetaSeekIndex *idx; gst_ebml_write_master_finish (ebml, mux->cluster);