[PATCH] DCA-in-WAV detection

Kostya Shishkov kostya.shishkov
Sun Jan 23 17:43:37 CET 2011


---
 libavformat/wav.c |   56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 56 insertions(+), 0 deletions(-)

diff --git a/libavformat/wav.c b/libavformat/wav.c
index a6db698..90eb583 100644
--- a/libavformat/wav.c
+++ b/libavformat/wav.c
@@ -150,6 +150,58 @@ static int wav_probe(AVProbeData *p)
         return 0;
 }
 
+#define DCA_MARKER_RAW_BE 0x7FFE8001
+#define DCA_MARKER_RAW_LE 0xFE7F0180
+#define DCA_MARKER_14B_BE 0x1FFFE800
+#define DCA_MARKER_14B_LE 0xFF1F00E8
+
+#define DCA_PROBE_SIZE 16384
+
+/* Most WAV files with DTS audio are broken and use 0x01 (PCM) as format
+   ID instead of 0x2001 (DTS). If the format found is 0x01, check the first
+   bytes after 'data' for a valid DTS header. */
+static void find_dts_header (ByteIOContext *pb, AVCodecContext *codec)
+{
+    uint32_t state = -1, marker;
+    unsigned int i;
+    offset_t pos;
+    int found = 0;
+
+    pos = url_ftell(pb);
+    for (i = 0; i < DCA_PROBE_SIZE && !url_feof(pb) && !found; i += 2) {
+        state = (state << 16) | get_be16(pb);
+        /* raw stream markers */
+        if (state == DCA_MARKER_RAW_BE || state == DCA_MARKER_RAW_LE)
+            found = 1;
+        /* 14 bits and big endian bitstream */
+        if (state == DCA_MARKER_14B_BE) {
+            if ((get_be16(pb) & 0xFFF0) == 0x07F0)
+                found = 1;
+            else
+                url_fseek(pb, -2, SEEK_CUR);
+        }
+        /* 14 bits and big endian bitstream */
+        if (state == DCA_MARKER_14B_LE) {
+            if ((get_be16(pb) & 0xF0FF) == 0xF007)
+                found = 1;
+            else
+                url_fseek(pb, -2, SEEK_CUR);
+        }
+    }
+    /* if marker is found then test stream for more markers to appear */
+    if(found){
+        marker = state;
+        for (i = 0; i < DCA_PROBE_SIZE*3 && !url_feof(pb) && found < 4; i++) {
+            state = (state << 8) | get_byte(pb);
+            if(state == marker)
+                found++;
+        }
+    }
+    if(found == 4)
+        codec->codec_id = CODEC_ID_DTS;
+    url_fseek(pb, pos, SEEK_SET);
+}
+
 /* wav input */
 static int wav_read_header(AVFormatContext *s,
                            AVFormatParameters *ap)
@@ -186,6 +238,10 @@ static int wav_read_header(AVFormatContext *s,
     size = find_tag(pb, MKTAG('d', 'a', 't', 'a'));
     if (size < 0)
         return -1;
+
+    /* check if it's really PCM or hidden DTS */
+    if (codec_get_id (codec_wav_tags, st->codec->codec_tag) == CODEC_ID_PCM_S16LE)
+        find_dts_header (pb, st->codec);
     wav->data_end= url_ftell(pb) + size;
     return 0;
 }
-- 
1.7.1


--------------010708080704020304060508--



More information about the ffmpeg-devel mailing list