Add musepack decoder.
authorRonald S. Bultje <rbultje@ronald.bitfreak.net>
Sun, 7 Nov 2004 18:30:07 +0000 (18:30 +0000)
committerRonald S. Bultje <rbultje@ronald.bitfreak.net>
Sun, 7 Nov 2004 18:30:07 +0000 (18:30 +0000)
Original commit message from CVS:
* configure.ac:
* ext/Makefile.am:
* ext/musepack/Makefile.am:
* ext/musepack/gstmusepackdec.cpp:
* ext/musepack/gstmusepackdec.h:
* ext/musepack/gstmusepackreader.cpp:
* ext/musepack/gstmusepackreader.h:
Add musepack decoder.
* ext/faad/gstfaad.c: (gst_faad_base_init):
Make pad templates static.
* gst/typefind/gsttypefindfunctions.c: (mp3_type_find),
(plugin_init):
Add musepack typefinder, make mp3 typefinding work halfway stream,
which doesn't actually work yet because id3demux doesn't implement
_get_length().

ChangeLog
configure.ac
ext/Makefile.am
gst/typefind/gsttypefindfunctions.c

index d2ecf69..5d1de38 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
 2004-11-07  Ronald S. Bultje  <rbultje@ronald.bitfreak.net>
 
+       * configure.ac:
+       * ext/Makefile.am:
+       * ext/musepack/Makefile.am:
+       * ext/musepack/gstmusepackdec.cpp:
+       * ext/musepack/gstmusepackdec.h:
+       * ext/musepack/gstmusepackreader.cpp:
+       * ext/musepack/gstmusepackreader.h:
+         Add musepack decoder.
+       * ext/faad/gstfaad.c: (gst_faad_base_init):
+         Make pad templates static.
+       * gst/typefind/gsttypefindfunctions.c: (mp3_type_find),
+       (plugin_init):
+         Add musepack typefinder, make mp3 typefinding work halfway stream,
+         which doesn't actually work yet because id3demux doesn't implement
+         _get_length().
+
+2004-11-07  Ronald S. Bultje  <rbultje@ronald.bitfreak.net>
+
        * ext/ogg/gstoggmux.c: (gst_ogg_mux_next_buffer),
        (gst_ogg_mux_queue_pads), (gst_ogg_mux_loop):
          Fix interrupt event handling (#144436).
index 11b17ff..a69a2bc 100644 (file)
@@ -1359,6 +1359,23 @@ main (int   argc,
   fi
 ])
 
+dnl *** musepack ***
+translit(dnm, m, l) AM_CONDITIONAL(USE_MUSEPACK, true)
+GST_CHECK_FEATURE(MUSEPACK, [musepackdec], musepack, [
+  AC_LANG_CPLUSPLUS
+  OLD_CPPFLAGS="$CPPFLAGS"
+  CPPFLAGS="-I/usr/include/musepack $CPPFLAGS"
+  AC_CHECK_HEADER(mpc_dec.h, [
+    HAVE_MUSEPACK="yes"
+    MUSEPACK_LIBS="-lmusepack"
+    MUSEPACK_CFLAGS="-I/usr/include/musepack"
+    AC_SUBST(MUSEPACK_CFLAGS)
+    AC_SUBST(MUSEPACK_LIBS)
+    ], [HAVE_MUSEPACK="no"])
+  CPPFLAGS="$OLD_CPPFLAGS"
+  AC_LANG_C
+])
+
 dnl *** musicbrainz ***
 dnl libmusicbrainz <= 2.0.2 has symbol clashes with ffmpeg
 dnl however, our ffmpeg patch was accepted upstream
@@ -1948,6 +1965,7 @@ ext/mikmod/Makefile
 ext/mpeg2dec/Makefile
 ext/mpeg2enc/Makefile
 ext/mplex/Makefile
+ext/musepack/Makefile
 ext/musicbrainz/Makefile
 ext/nas/Makefile
 ext/ogg/Makefile
index cd9c5ac..311a320 100644 (file)
@@ -238,6 +238,12 @@ endif
 #MAS_DIR=
 #endif
 
+if USE_MUSEPACK
+MUSEPACK_DIR=musepack
+else
+MUSEPACK_DIR=
+endif
+
 if USE_MUSICBRAINZ
 MUSICBRAINZ_DIR=musicbrainz
 else
@@ -399,6 +405,7 @@ SUBDIRS=\
        $(MPEG2DEC_DIR) \
        $(MPEG2ENC_DIR) \
        $(MPLEX_DIR) \
+       $(MUSEPACK_DIR) \
        $(MUSICBRAINZ_DIR) \
        $(OGG_DIR) \
        $(PANGO_DIR) \
@@ -458,6 +465,7 @@ DIST_SUBDIRS=\
        mpeg2dec \
        mpeg2enc \
        mplex \
+       musepack \
        musicbrainz \
        nas \
        ogg \
index 3709f81..b8f86d2 100644 (file)
@@ -367,105 +367,117 @@ static GstStaticCaps mp3_caps = GST_STATIC_CAPS ("audio/mpeg, "
 static void
 mp3_type_find (GstTypeFind * tf, gpointer unused)
 {
+  guint64 length = gst_type_find_get_length (tf);
+  gint try;
   guint8 *data = NULL;
-  guint size = 0;
-  guint64 skipped = 0;
+  guint size;
+  guint64 skipped;
 
-  while (skipped < GST_MP3_TYPEFIND_TRY_SYNC) {
-    if (size <= 0) {
-      size = GST_MP3_TYPEFIND_SYNC_SIZE * 2;
-      do {
-        size /= 2;
-        data = gst_type_find_peek (tf, skipped, size);
-      } while (size > 10 && !data);
-      if (!data)
-        break;
-    }
-    if (*data == 0xFF) {
-      guint8 *head_data = NULL;
-      guint layer, bitrate, samplerate, channels;
-      guint found = 0;          /* number of valid headers found */
-      guint64 offset = skipped;
+  for (try = 0; try < 2; try++) {
+    guint64 start_off = (try == 0) ? 0 : length / 2;
 
-      while (found < GST_MP3_TYPEFIND_TRY_HEADERS) {
-        guint32 head;
-        guint length;
-        guint prev_layer = 0, prev_bitrate = 0,
-            prev_channels = 0, prev_samplerate = 0;
+    if (try != 0 && start_off == 0)
+      return;
 
-        if (offset + 4 <= skipped + size) {
-          head_data = data + offset - skipped;
-        } else {
-          head_data = gst_type_find_peek (tf, offset, 4);
-        }
-        if (!head_data)
-          break;
-        head = GST_READ_UINT32_BE (head_data);
-        if (!(length = mp3_type_frame_length_from_header (head, &layer,
-                    &channels, &bitrate, &samplerate))) {
-          GST_LOG ("%d. header at offset %" G_GUINT64_FORMAT
-              " (0x%X) was not an mp3 header", found + 1, offset,
-              (guint) offset);
+    size = 0;
+    skipped = 0;
+    while (skipped < GST_MP3_TYPEFIND_TRY_SYNC) {
+      if (size <= 0) {
+        size = GST_MP3_TYPEFIND_SYNC_SIZE * 2;
+        do {
+          size /= 2;
+          data = gst_type_find_peek (tf, skipped + start_off, size);
+        } while (size > 10 && !data);
+        if (!data)
           break;
-        }
-        if ((prev_layer && prev_layer != layer) ||
-            /* (prev_bitrate && prev_bitrate != bitrate) || <-- VBR */
-            (prev_samplerate && prev_samplerate != samplerate) ||
-            (prev_channels && prev_channels != channels)) {
-          /* this means an invalid property, or a change, which might mean
-           * that this is not a mp3 but just a random bytestream. It could
-           * be a freaking funky encoded mp3 though. We'll just not count
-           * this header*/
-          prev_layer = layer;
-          prev_bitrate = bitrate;
-          prev_channels = channels;
-          prev_samplerate = samplerate;
-        } else {
-          found++;
-          GST_LOG ("found %d. header at offset %" G_GUINT64_FORMAT " (0x%X)",
-              found, offset, (guint) offset);
-        }
-        offset += length;
       }
-      g_assert (found <= GST_MP3_TYPEFIND_TRY_HEADERS);
-      if (found == GST_MP3_TYPEFIND_TRY_HEADERS ||
-          (found >= GST_MP3_TYPEFIND_MIN_HEADERS && head_data == NULL)) {
-        /* we can make a valid guess */
-        guint probability = found * GST_TYPE_FIND_MAXIMUM *
-            (GST_MP3_TYPEFIND_TRY_SYNC - skipped) /
-            GST_MP3_TYPEFIND_TRY_HEADERS / GST_MP3_TYPEFIND_TRY_SYNC;
-
-        if (probability < GST_TYPE_FIND_MINIMUM)
-          probability = GST_TYPE_FIND_MINIMUM;
-        GST_INFO
-            ("audio/mpeg calculated %u  =  %u  *  %u / %u  *  (%u - %u) / %u",
-            probability, GST_TYPE_FIND_MAXIMUM, found,
-            GST_MP3_TYPEFIND_TRY_HEADERS, GST_MP3_TYPEFIND_TRY_SYNC, skipped,
-            GST_MP3_TYPEFIND_TRY_SYNC);
-        /* make sure we're not id3 tagged */
-        head_data = gst_type_find_peek (tf, -128, 3);
-        if (!head_data) {
-          probability = probability * 4 / 5;
-        } else if (memcmp (head_data, "TAG", 3) == 0) {
-          probability = 0;
+      if (*data == 0xFF) {
+        guint8 *head_data = NULL;
+        guint layer, bitrate, samplerate, channels;
+        guint found = 0;        /* number of valid headers found */
+        guint64 offset = skipped;
+
+        while (found < GST_MP3_TYPEFIND_TRY_HEADERS) {
+          guint32 head;
+          guint length;
+          guint prev_layer = 0, prev_bitrate = 0,
+              prev_channels = 0, prev_samplerate = 0;
+
+          if (offset + 4 <= skipped + size) {
+            head_data = data + offset - skipped;
+          } else {
+            head_data = gst_type_find_peek (tf, offset + start_off, 4);
+          }
+          if (!head_data)
+            break;
+          head = GST_READ_UINT32_BE (head_data);
+          if (!(length = mp3_type_frame_length_from_header (head, &layer,
+                      &channels, &bitrate, &samplerate))) {
+            GST_LOG ("%d. header at offset %" G_GUINT64_FORMAT
+                " (0x%X) was not an mp3 header", found + 1, offset,
+                (guint) offset);
+            break;
+          }
+          if ((prev_layer && prev_layer != layer) ||
+              /* (prev_bitrate && prev_bitrate != bitrate) || <-- VBR */
+              (prev_samplerate && prev_samplerate != samplerate) ||
+              (prev_channels && prev_channels != channels)) {
+            /* this means an invalid property, or a change, which might mean
+             * that this is not a mp3 but just a random bytestream. It could
+             * be a freaking funky encoded mp3 though. We'll just not count
+             * this header*/
+            prev_layer = layer;
+            prev_bitrate = bitrate;
+            prev_channels = channels;
+            prev_samplerate = samplerate;
+          } else {
+            found++;
+            GST_LOG ("found %d. header at offset %" G_GUINT64_FORMAT " (0x%X)",
+                found, offset, (guint) offset);
+          }
+          offset += length;
         }
-        g_assert (probability <= GST_TYPE_FIND_MAXIMUM);
-        if (probability > 0) {
-          GstCaps *caps;
-
-          g_assert (layer > 0);
-          caps = gst_caps_copy (MP3_CAPS);
-          gst_structure_set (gst_caps_get_structure (caps, 0), "layer",
-              G_TYPE_INT, layer, 0);
-          gst_type_find_suggest (tf, probability, caps);
-          gst_caps_free (caps);
+        g_assert (found <= GST_MP3_TYPEFIND_TRY_HEADERS);
+        if (found == GST_MP3_TYPEFIND_TRY_HEADERS ||
+            (found >= GST_MP3_TYPEFIND_MIN_HEADERS && head_data == NULL)) {
+          /* we can make a valid guess */
+          guint probability = found * GST_TYPE_FIND_MAXIMUM *
+              (GST_MP3_TYPEFIND_TRY_SYNC - skipped) /
+              GST_MP3_TYPEFIND_TRY_HEADERS / GST_MP3_TYPEFIND_TRY_SYNC;
+
+          if (probability < GST_TYPE_FIND_MINIMUM)
+            probability = GST_TYPE_FIND_MINIMUM;
+          probability /= (try + 1);
+          GST_INFO
+              ("audio/mpeg calculated %u  =  %u  *  %u / %u  *  (%u - %u) / %u",
+              probability, GST_TYPE_FIND_MAXIMUM, found,
+              GST_MP3_TYPEFIND_TRY_HEADERS, GST_MP3_TYPEFIND_TRY_SYNC, skipped,
+              GST_MP3_TYPEFIND_TRY_SYNC);
+          /* make sure we're not id3 tagged */
+          head_data = gst_type_find_peek (tf, -128, 3);
+          if (!head_data) {
+            probability = probability * 4 / 5;
+          } else if (memcmp (head_data, "TAG", 3) == 0) {
+            probability = 0;
+          }
+          g_assert (probability <= GST_TYPE_FIND_MAXIMUM);
+          if (probability > 0) {
+            GstCaps *caps;
+
+            g_assert (layer > 0);
+            caps = gst_caps_copy (MP3_CAPS);
+            gst_structure_set (gst_caps_get_structure (caps, 0), "layer",
+                G_TYPE_INT, layer, 0);
+            gst_type_find_suggest (tf, probability, caps);
+            gst_caps_free (caps);
+          }
+          return;
         }
-        return;
       }
+      data++;
+      skipped++;
+      size--;
     }
-    data++;
-    skipped++;
-    size--;
   }
 }
 
@@ -1399,6 +1411,7 @@ plugin_init (GstPlugin * plugin)
   };
   static gchar *mp3_exts[] = { "mp3", "mp2", "mp1", "mpga", NULL };
   static gchar *ac3_exts[] = { "ac3", NULL };
+  static gchar *musepack_exts[] = { "mpc", NULL };
   static gchar *mpeg_sys_exts[] = { "mpe", "mpeg", "mpg", NULL };
   static gchar *mpeg_video_exts[] = { "mpv", "mpeg", "mpg", NULL };
   static gchar *ogg_exts[] = { "ogg", "ogm", NULL };
@@ -1439,6 +1452,8 @@ plugin_init (GstPlugin * plugin)
       asf_exts,
       "\060\046\262\165\216\146\317\021\246\331\000\252\000\142\316\154", 16,
       GST_TYPE_FIND_MAXIMUM);
+  TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-musepack", GST_RANK_PRIMARY,
+      musepack_exts, "MP+", 3, GST_TYPE_FIND_MAXIMUM);
   TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-au", GST_RANK_MARGINAL,
       au_exts, ".snd", 4, GST_TYPE_FIND_MAXIMUM);
   TYPE_FIND_REGISTER_RIFF (plugin, "video/x-msvideo", GST_RANK_PRIMARY,