From: Tim-Philipp Müller Date: Thu, 23 Mar 2006 15:36:27 +0000 (+0000) Subject: gst/wavparse/gstwavparse.*: Delay source pad creation until we have the first chunk... X-Git-Tag: RELEASE-0_10_3~160 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=abb13bdd249c9f6eaa9f6ec8b03f62381625ea49;p=platform%2Fupstream%2Fgst-plugins-good.git gst/wavparse/gstwavparse.*: Delay source pad creation until we have the first chunk of media data, so the we can exam... Original commit message from CVS: * gst/wavparse/gstwavparse.c: (gst_wavparse_perform_seek), (gst_wavparse_stream_headers), (gst_wavparse_add_src_pad), (gst_wavparse_stream_data), (gst_wavparse_loop): * gst/wavparse/gstwavparse.h: Delay source pad creation until we have the first chunk of media data, so the we can examine the data and adjust the caps accordingly if required. This makes playback of .wav files with DTS-declared-as-PCM content work (#313266). --- diff --git a/ChangeLog b/ChangeLog index 308ea82..c5e6a85 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2006-03-23 Tim-Philipp Müller + + * gst/wavparse/gstwavparse.c: (gst_wavparse_perform_seek), + (gst_wavparse_stream_headers), (gst_wavparse_add_src_pad), + (gst_wavparse_stream_data), (gst_wavparse_loop): + * gst/wavparse/gstwavparse.h: + Delay source pad creation until we have the first chunk of + media data, so the we can examine the data and adjust the + caps accordingly if required. This makes playback of .wav + files with DTS-declared-as-PCM content work (#313266). + 2006-03-22 Jan Schmidt * gst/apetag/gsttagdemux.c: (gst_tag_demux_chain): diff --git a/common b/common index f1c7bfd..658b511 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit f1c7bfd24d0fcc4e5113ce3b96b1fac83a9ec560 +Subproject commit 658b51189850df022f032a4310c4ad477a76465f diff --git a/gst/wavparse/gstwavparse.c b/gst/wavparse/gstwavparse.c index 7e57ed3..fcb773e 100644 --- a/gst/wavparse/gstwavparse.c +++ b/gst/wavparse/gstwavparse.c @@ -119,7 +119,7 @@ static GstStaticPadTemplate src_template_factory = "block_align = (int) [ 1, 8192 ], " "rate = (int) [ 8000, 48000 ], " "channels = (int) [ 1, 2 ];" "audio/x-vnd.sony.atrac3;" - "audio/x-wma, " "wmaversion = (int) [ 1, 2 ]") + "audio/x-dts;" "audio/x-wma, " "wmaversion = (int) [ 1, 2 ]") ); @@ -731,6 +731,7 @@ gst_wavparse_perform_seek (GstWavParse * wav, GstEvent * event) { gboolean res; gdouble rate; + GstEvent *newsegment; GstFormat format; GstSeekFlags flags; GstSeekType cur_type, stop_type; @@ -839,10 +840,17 @@ gst_wavparse_perform_seek (GstWavParse * wav, GstEvent * event) GST_DEBUG_OBJECT (wav, "Sending newsegment from %" G_GINT64_FORMAT " to %" G_GINT64_FORMAT, wav->segment.start, stop); - gst_pad_push_event (wav->srcpad, - gst_event_new_new_segment (FALSE, - wav->segment.rate, wav->segment.format, - wav->segment.last_stop, stop, wav->segment.time)); + newsegment = + gst_event_new_new_segment (FALSE, wav->segment.rate, + wav->segment.format, wav->segment.last_stop, stop, wav->segment.time); + + if (wav->srcpad) { + gst_pad_push_event (wav->srcpad, newsegment); + } else { + /* send later when we actually create the source pad */ + g_assert (wav->newsegment == NULL); + wav->newsegment = newsegment; + } wav->segment_running = TRUE; gst_pad_start_task (wav->sinkpad, (GstTaskFunction) gst_wavparse_loop, @@ -917,23 +925,17 @@ gst_wavparse_stream_headers (GstWavParse * wav) if (!caps) goto unknown_format; - gst_wavparse_create_sourcepad (wav); - gst_pad_set_active (wav->srcpad, TRUE); - gst_pad_set_caps (wav->srcpad, caps); - gst_caps_unref (caps); - caps = NULL; - - gst_element_add_pad (GST_ELEMENT (wav), wav->srcpad); - gst_element_no_more_pads (GST_ELEMENT (wav)); + /* create pad later so we can sniff the first few bytes + * of the real data and correct our caps if necessary */ + gst_caps_replace (&wav->caps, caps); + gst_caps_replace (&caps, NULL); if (codec_name) { - GstTagList *tags = gst_tag_list_new (); + wav->tags = gst_tag_list_new (); - gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, + gst_tag_list_add (wav->tags, GST_TAG_MERGE_REPLACE, GST_TAG_AUDIO_CODEC, codec_name, NULL); - gst_element_found_tags_for_pad (GST_ELEMENT (wav), wav->srcpad, tags); - g_free (codec_name); codec_name = NULL; } @@ -1092,10 +1094,46 @@ gst_wavparse_send_event (GstElement * element, GstEvent * event) return res; } +static void +gst_wavparse_add_src_pad (GstWavParse * wav, GstBuffer * buf) +{ + GstStructure *s; + const guint8 dts_marker[] = { 0xFF, 0x1F, 0x00, 0xE8, 0xF1, 0x07 }; + + s = gst_caps_get_structure (wav->caps, 0); + if (gst_structure_has_name (s, "audio/x-raw-int") && + GST_BUFFER_SIZE (buf) > 6 && + memcmp (GST_BUFFER_DATA (buf), dts_marker, 6) == 0) { + + GST_WARNING_OBJECT (wav, "Found DTS marker in file marked as raw PCM"); + gst_caps_unref (wav->caps); + wav->caps = gst_caps_from_string ("audio/x-dts"); + + gst_tag_list_add (wav->tags, GST_TAG_MERGE_REPLACE, + GST_TAG_AUDIO_CODEC, "dts", NULL); + } + + gst_wavparse_create_sourcepad (wav); + gst_pad_set_active (wav->srcpad, TRUE); + gst_pad_set_caps (wav->srcpad, wav->caps); + gst_caps_replace (&wav->caps, NULL); + + gst_element_add_pad (GST_ELEMENT (wav), wav->srcpad); + gst_element_no_more_pads (GST_ELEMENT (wav)); + + gst_pad_push_event (wav->srcpad, wav->newsegment); + wav->newsegment = NULL; + + if (wav->tags) { + gst_element_found_tags_for_pad (GST_ELEMENT (wav), wav->srcpad, wav->tags); + wav->tags = NULL; + } +} + #define MAX_BUFFER_SIZE 4096 static GstFlowReturn -gst_wavparse_stream_data (GstWavParse * wav) +gst_wavparse_stream_data (GstWavParse * wav, gboolean first) { GstBuffer *buf = NULL; GstFlowReturn res = GST_FLOW_OK; @@ -1103,8 +1141,8 @@ gst_wavparse_stream_data (GstWavParse * wav) GstClockTime timestamp, next_timestamp; guint64 pos, nextpos; - GST_DEBUG_OBJECT (wav, "offset : %lld , end : %lld", wav->offset, - wav->end_offset); + GST_LOG_OBJECT (wav, "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT, + wav->offset, wav->end_offset); /* Get the next n bytes and output them */ if (wav->dataleft == 0) @@ -1116,8 +1154,8 @@ gst_wavparse_stream_data (GstWavParse * wav) if (desired >= wav->blockalign && wav->blockalign > 0) desired -= (desired % wav->blockalign); - GST_DEBUG_OBJECT (wav, "Fetching %lld bytes of data from the sinkpad.", - desired); + GST_LOG_OBJECT (wav, "Fetching %" G_GINT64_FORMAT " bytes of data " + "from the sinkpad", desired); if ((res = gst_pad_pull_range (wav->sinkpad, wav->offset, desired, &buf)) != GST_FLOW_OK) @@ -1125,6 +1163,12 @@ gst_wavparse_stream_data (GstWavParse * wav) obtained = GST_BUFFER_SIZE (buf); + /* first chunk of data? create the source pad. We do this only here so + * we can detect broken .wav files with dts disguised as raw PCM (sigh) */ + if (first) { + gst_wavparse_add_src_pad (wav, buf); + } + /* our positions */ pos = wav->offset - wav->datastart; nextpos = pos + obtained; @@ -1214,9 +1258,11 @@ gst_wavparse_loop (GstPad * pad) goto pause; wav->state = GST_WAVPARSE_DATA; - /* fall-through */ + if ((ret = gst_wavparse_stream_data (wav, TRUE)) != GST_FLOW_OK) + goto pause; + break; case GST_WAVPARSE_DATA: - if ((ret = gst_wavparse_stream_data (wav)) != GST_FLOW_OK) + if ((ret = gst_wavparse_stream_data (wav, FALSE)) != GST_FLOW_OK) goto pause; break; default: diff --git a/gst/wavparse/gstwavparse.h b/gst/wavparse/gstwavparse.h index b920314..2d14061 100644 --- a/gst/wavparse/gstwavparse.h +++ b/gst/wavparse/gstwavparse.h @@ -33,10 +33,10 @@ G_BEGIN_DECLS #define GST_WAVPARSE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_WAVPARSE,GstWavParse)) #define GST_WAVPARSE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_WAVPARSE,GstWavParse)) + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_WAVPARSE,GstWavParseClass)) #define GST_IS_WAVPARSE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_WAVPARSE)) -#define GST_IS_WAVPARSE_CLASS(obj) \ +#define GST_IS_WAVPARSE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_WAVPARSE)) typedef enum { @@ -59,6 +59,13 @@ struct _GstWavParse { /* pads */ GstPad *sinkpad,*srcpad; + /* for delayed source pad creation for when + * we have the first chunk of data and know + * the format for sure */ + GstCaps *caps; + GstTagList *tags; + GstEvent *newsegment; + /* WAVE decoding state */ GstWavParseState state;