riff: Manually calculate bitrate of ADPCM streams
authorJulien Moutte <julien@moutte.net>
Tue, 7 May 2013 13:00:05 +0000 (15:00 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 7 May 2013 13:01:05 +0000 (15:01 +0200)
Some ADPCM encoding tools like Oxelon generate WAV files with
wrong format header declaring an invalid bitrate.

As wavparse uses the average bitrate to calculate timestamps
and duration the decoder can be confused by receiving timestamps
completely out of sync with the decoded samples.

ADPCM is a CBR audio codec so we can calculate the average bitrate
instead of trusting the format header.

https://bugzilla.gnome.org/show_bug.cgi?id=636245

gst-libs/gst/riff/riff-media.c

index 008727f..2a0d6ed 100644 (file)
@@ -1217,6 +1217,19 @@ gst_riff_create_audio_caps (guint16 codec_id,
       break;
 
     case GST_RIFF_WAVE_FORMAT_ADPCM:
+      if (strf != NULL) {
+        /* Many encoding tools create a wrong bitrate information in the header,
+         * so either we calculate the bitrate or mark it as invalid as this
+         * would probably confuse timing */
+        strf->av_bps = 0;
+        if (strf->channels != 0 && strf->rate != 0 && strf->blockalign != 0) {
+          int spb = ((strf->blockalign - strf->channels * 7) / 2) * 2;
+          strf->av_bps =
+              gst_util_uint64_scale_int (strf->rate, strf->blockalign, spb);
+          GST_DEBUG ("fixing av_bps to calculated value %d of MS ADPCM",
+              strf->av_bps);
+        }
+      }
       caps = gst_caps_new_simple ("audio/x-adpcm",
           "layout", G_TYPE_STRING, "microsoft", NULL);
       if (codec_name)
@@ -1325,7 +1338,19 @@ gst_riff_create_audio_caps (guint16 codec_id,
       goto unknown;
 
     case GST_RIFF_WAVE_FORMAT_DVI_ADPCM:
-      rate_max = 48000;
+      if (strf != NULL) {
+        /* Many encoding tools create a wrong bitrate information in the
+         * header, so either we calculate the bitrate or mark it as invalid
+         * as this would probably confuse timing */
+        strf->av_bps = 0;
+        if (strf->channels != 0 && strf->rate != 0 && strf->blockalign != 0) {
+          int spb = ((strf->blockalign - strf->channels * 4) / 2) * 2;
+          strf->av_bps =
+              gst_util_uint64_scale_int (strf->rate, strf->blockalign, spb);
+          GST_DEBUG ("fixing av_bps to calculated value %d of IMA DVI ADPCM",
+              strf->av_bps);
+        }
+      }
       caps = gst_caps_new_simple ("audio/x-adpcm",
           "layout", G_TYPE_STRING, "dvi", NULL);
       if (codec_name)