matroskamux: For audio tracks, take the default duration from the first buffer

... if we don't have any better idea from the caps. This allows writing
SimpleBlocks for a majority of audio streams where the duration of
frames is usually fixed. And as a side effect, allows VLC to play
streams with Opus as it only works with SimpleBlocks currently:
  https://trac.videolan.org/vlc/ticket/18545

https://bugzilla.gnome.org/show_bug.cgi?id=784969
This commit is contained in:
Sebastian Dröge 2017-07-18 10:41:40 +03:00
parent 5a6fe4ed29
commit 317d3380bb

View file

@ -2723,7 +2723,8 @@ gst_matroska_mux_write_chapter_edition (GstMatroskaMux * mux,
* Start a new matroska file (write headers etc...) * Start a new matroska file (write headers etc...)
*/ */
static void static void
gst_matroska_mux_start (GstMatroskaMux * mux) gst_matroska_mux_start (GstMatroskaMux * mux, GstMatroskaPad * first_pad,
GstBuffer * first_pad_buf)
{ {
GstEbmlWrite *ebml = mux->ebml_write; GstEbmlWrite *ebml = mux->ebml_write;
const gchar *doctype; const gchar *doctype;
@ -2893,6 +2894,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
for (collected = mux->collect->data; collected; for (collected = mux->collect->data; collected;
collected = g_slist_next (collected)) { collected = g_slist_next (collected)) {
GstMatroskaPad *collect_pad; GstMatroskaPad *collect_pad;
GstBuffer *buf;
collect_pad = (GstMatroskaPad *) collected->data; collect_pad = (GstMatroskaPad *) collected->data;
@ -2900,6 +2902,23 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
if (collect_pad->track->codec_id == NULL) if (collect_pad->track->codec_id == NULL)
continue; continue;
/* For audio tracks, use the first buffers duration as the default
* duration if we didn't get any better idea from the caps event already
*/
if (collect_pad->track->type == GST_MATROSKA_TRACK_TYPE_AUDIO &&
collect_pad->track->default_duration == 0) {
if (collect_pad == first_pad)
buf = first_pad_buf ? gst_buffer_ref (first_pad_buf) : NULL;
else
buf = gst_collect_pads_peek (mux->collect, collected->data);
if (buf && GST_BUFFER_DURATION_IS_VALID (buf))
collect_pad->track->default_duration =
GST_BUFFER_DURATION (buf) + collect_pad->track->codec_delay;
if (buf)
gst_buffer_unref (buf);
}
collect_pad->track->num = tracknum++; collect_pad->track->num = tracknum++;
child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKENTRY); child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKENTRY);
gst_matroska_mux_track_header (mux, collect_pad->track); gst_matroska_mux_track_header (mux, collect_pad->track);
@ -3814,7 +3833,7 @@ gst_matroska_mux_handle_buffer (GstCollectPads * pads, GstCollectData * data,
GstClockTime buffer_timestamp; 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 = (GstMatroskaPad *) data;
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
GST_DEBUG_OBJECT (mux, "Collected pads"); GST_DEBUG_OBJECT (mux, "Collected pads");
@ -3827,14 +3846,11 @@ gst_matroska_mux_handle_buffer (GstCollectPads * pads, GstCollectData * data,
} }
mux->state = GST_MATROSKA_MUX_STATE_HEADER; mux->state = GST_MATROSKA_MUX_STATE_HEADER;
gst_ebml_start_streamheader (ebml); gst_ebml_start_streamheader (ebml);
gst_matroska_mux_start (mux); gst_matroska_mux_start (mux, best, buf);
gst_matroska_mux_stop_streamheader (mux); gst_matroska_mux_stop_streamheader (mux);
mux->state = GST_MATROSKA_MUX_STATE_DATA; mux->state = GST_MATROSKA_MUX_STATE_DATA;
} }
/* provided with stream to write from */
best = (GstMatroskaPad *) data;
/* if there is no best pad, we have reached EOS */ /* if there is no best pad, we have reached EOS */
if (best == NULL) { if (best == NULL) {
GST_DEBUG_OBJECT (mux, "No best pad. Finishing..."); GST_DEBUG_OBJECT (mux, "No best pad. Finishing...");