ext/mad/gstmad.c: Allow for mp3 rate/channels changes. However, only very conservativ...
authorRonald S. Bultje <rbultje@ronald.bitfreak.net>
Mon, 20 Sep 2004 12:40:40 +0000 (12:40 +0000)
committerRonald S. Bultje <rbultje@ronald.bitfreak.net>
Mon, 20 Sep 2004 12:40:40 +0000 (12:40 +0000)
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
ext/mad/gstmad.c
gst/asfdemux/gstasfdemux.c

index 5e54b77..a9cd506 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2004-09-20  Ronald S. Bultje  <rbultje@ronald.bitfreak.net>
+
+       * 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  <johan@gnome.org>
 
        * ext/jpeg/gstjpegdec.c (gst_jpegdec_chain): Allocate the buffer
index 43d0544..d8871be 100644 (file)
@@ -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;
index cc12a7a..6f0ff8a 100644 (file)
@@ -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);