From 1b7b0e099d2a342ffa3ad636190c30ef37993b91 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Mon, 20 Sep 2004 12:40:40 +0000 Subject: [PATCH] ext/mad/gstmad.c: Allow for mp3 rate/channels changes. However, only very conservatively. Reason that we *have* to en... Original commit message from CVS: * ext/mad/gstmad.c: (gst_mad_check_caps_reset), (gst_mad_change_state): Allow for mp3 rate/channels changes. However, only very conservatively. Reason that we *have* to enable this is smiply because the mad find_sync() function is not good enough, it will regularly sync on random data as valid frames and therefore make us provide random caps as *final* caps of the stream. The best fix I could think of is to simply require several of the same stream changes in a row before we change caps. The actual testcase that works now is # * ext/ogg/Makefile.am: * ext/ogg/gstogg.c: (plugin_init): * ext/ogg/gstogmparse.c: OGM support (video only for now; I need an audio sample file). * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_base_init), (gst_asf_demux_process_stream), (gst_asf_demux_video_caps), (gst_asf_demux_add_video_stream): WMV extradata. * gst/playback/gstplaybasebin.c: (unknown_type): Don't error out on single unknown-types after all. It's wrong. If we found type of video and audio but not of a subtitle stream, it will still error out (which is unwanted). Will find a better fix later on. * gst/typefind/gsttypefindfunctions.c: (ogmvideo_type_find), (ogmaudio_type_find), (plugin_init): OGM support. --- ChangeLog | 29 ++++++++++++++++++++++++++++ ext/mad/gstmad.c | 17 +++++++++++++--- gst/asfdemux/gstasfdemux.c | 48 ++++++++++++++++++++++++++-------------------- 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5e54b77..a9cd506 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2004-09-20 Ronald S. Bultje + + * ext/mad/gstmad.c: (gst_mad_check_caps_reset), + (gst_mad_change_state): + Allow for mp3 rate/channels changes. However, only very + conservatively. Reason that we *have* to enable this is smiply + because the mad find_sync() function is not good enough, it will + regularly sync on random data as valid frames and therefore make + us provide random caps as *final* caps of the stream. The best fix + I could think of is to simply require several of the same stream + changes in a row before we change caps. + The actual testcase that works now is # + * ext/ogg/Makefile.am: + * ext/ogg/gstogg.c: (plugin_init): + * ext/ogg/gstogmparse.c: + OGM support (video only for now; I need an audio sample file). + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_base_init), + (gst_asf_demux_process_stream), (gst_asf_demux_video_caps), + (gst_asf_demux_add_video_stream): + WMV extradata. + * gst/playback/gstplaybasebin.c: (unknown_type): + Don't error out on single unknown-types after all. It's wrong. + If we found type of video and audio but not of a subtitle stream, + it will still error out (which is unwanted). Will find a better fix + later on. + * gst/typefind/gsttypefindfunctions.c: (ogmvideo_type_find), + (ogmaudio_type_find), (plugin_init): + OGM support. + 2004-09-20 Johan Dahlin * ext/jpeg/gstjpegdec.c (gst_jpegdec_chain): Allocate the buffer diff --git a/ext/mad/gstmad.c b/ext/mad/gstmad.c index 43d0544..d8871be 100644 --- a/ext/mad/gstmad.c +++ b/ext/mad/gstmad.c @@ -74,8 +74,9 @@ struct _GstMad GstTagList *tags; /* negotiated format */ - gint rate; - gint channels; + gint rate, pending_rate; + gint channels, pending_channels; + gint times_pending; gboolean caps_set; /* used to keep track of whether to change/update caps */ GstIndex *index; @@ -1153,7 +1154,16 @@ gst_mad_check_caps_reset (GstMad * mad) GST_DEBUG ("Header changed from %d Hz/%d ch to %d Hz/%d ch, failed sync after seek ?", mad->rate, mad->channels, rate, nchannels); - return; + /* we're conservative on stream changes. However, our *initial* caps + * might have been wrong as well - mad ain't perfect in syncing. So, + * we count caps changes and change if we pass a limit treshold (3). */ + if (nchannels != mad->pending_channels || rate != mad->pending_rate) { + mad->times_pending = 0; + mad->pending_channels = nchannels; + mad->pending_rate = rate; + } + if (++mad->times_pending < 3) + return; } } gst_mad_update_info (mad); @@ -1493,6 +1503,7 @@ gst_mad_change_state (GstElement * element) mad->rate = 0; mad->channels = 0; mad->caps_set = FALSE; + mad->times_pending = mad->pending_rate = mad->pending_channels = 0; mad->vbr_average = 0; mad->segment_start = 0; mad->new_header = TRUE; diff --git a/gst/asfdemux/gstasfdemux.c b/gst/asfdemux/gstasfdemux.c index cc12a7a..6f0ff8a 100644 --- a/gst/asfdemux/gstasfdemux.c +++ b/gst/asfdemux/gstasfdemux.c @@ -70,7 +70,7 @@ static gboolean gst_asf_demux_setup_pad (GstASFDemux * asf_demux, static GstElementStateReturn gst_asf_demux_change_state (GstElement * element); static GstCaps *gst_asf_demux_video_caps (guint32 codec_fcc, - asf_stream_video_format * video, char **codec_name); + asf_stream_video_format * video, guint8 * extradata, char **codec_name); static GstCaps *gst_asf_demux_audio_caps (guint16 codec_id, asf_stream_audio * audio, guint8 * extradata, char **codec_name); @@ -154,7 +154,7 @@ gst_asf_demux_base_init (gpointer g_class) vidcaps = gst_caps_new_empty (); for (i = 0; vid_list[i] != 0; i++) { - temp = gst_asf_demux_video_caps (vid_list[i], NULL, NULL); + temp = gst_asf_demux_video_caps (vid_list[i], NULL, NULL, NULL); gst_caps_append (vidcaps, temp); } @@ -942,8 +942,6 @@ gst_asf_demux_process_stream (GstASFDemux * asf_demux, guint64 * obj_size) asf_stream_video video_object; asf_stream_video_format video_format_object; guint16 size; - GstBuffer *buf; - guint32 got_bytes; guint16 id; /* Get the rest of the header's header */ @@ -1018,21 +1016,6 @@ gst_asf_demux_process_stream (GstASFDemux * asf_demux, guint64 * obj_size) if (!gst_asf_demux_add_video_stream (asf_demux, &video_format_object, id)) return FALSE; - - /* Read any additional information */ - if (size) { - got_bytes = gst_bytestream_read (asf_demux->bs, &buf, size); - /* There is additional data */ - while (got_bytes < size) { - guint32 remaining; - GstEvent *event; - - gst_bytestream_get_status (asf_demux->bs, &remaining, &event); - gst_event_unref (event); - - got_bytes = gst_bytestream_read (asf_demux->bs, &buf, size); - } - } break; default: GST_ELEMENT_ERROR (asf_demux, STREAM, WRONG_TYPE, (NULL), @@ -1743,7 +1726,7 @@ gst_asf_demux_add_audio_stream (GstASFDemux * asf_demux, static GstCaps * gst_asf_demux_video_caps (guint32 codec_fcc, - asf_stream_video_format * video, char **codec_name) + asf_stream_video_format * video, guint8 * extradata, char **codec_name) { GstCaps *caps = NULL; gint width = 0, height = 0; @@ -1864,6 +1847,17 @@ gst_asf_demux_video_caps (guint32 codec_fcc, "width", G_TYPE_INT, video->width, "height", G_TYPE_INT, video->height, "framerate", G_TYPE_DOUBLE, (double) 25, NULL); + + if (extradata) { + GstBuffer *buffer; + + buffer = gst_buffer_new_and_alloc (video->size); + memcpy (GST_BUFFER_DATA (buffer), extradata, video->size); + /* gst_util_dump_mem (GST_BUFFER_DATA (buffer), video->size); */ + + gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buffer, NULL); + gst_data_unref (GST_DATA (buffer)); + } } else { gst_caps_set_simple (caps, "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, @@ -1883,6 +1877,7 @@ gst_asf_demux_add_video_stream (GstASFDemux * asf_demux, gchar *name = NULL; char *codec_name = NULL; GstTagList *list = gst_tag_list_new (); + gint size_left = video->size - 40; /* Create the audio pad */ name = g_strdup_printf ("video_%02d", asf_demux->num_video_streams); @@ -1890,7 +1885,18 @@ gst_asf_demux_add_video_stream (GstASFDemux * asf_demux, g_free (name); /* Now try some gstreamer formatted MIME types (from gst_avi_demux_strf_vids) */ - caps = gst_asf_demux_video_caps (video->tag, video, &codec_name); + if (size_left) { + guint8 *extradata; + + GST_WARNING_OBJECT (asf_demux, + "asfdemux: Video header contains %d bytes of codec specific data", + size_left); + gst_bytestream_peek_bytes (asf_demux->bs, &extradata, size_left); + caps = gst_asf_demux_video_caps (video->tag, video, extradata, &codec_name); + gst_bytestream_flush (asf_demux->bs, size_left); + } else { + caps = gst_asf_demux_video_caps (video->tag, video, NULL, &codec_name); + } gst_tag_list_add (list, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC, codec_name, NULL); gst_element_found_tags (GST_ELEMENT (asf_demux), list); -- 2.7.4