[PATCH] Detect DTS-in-WAV files as raw DTS

Anssi Hannula anssi.hannula
Wed Aug 18 06:04:30 CEST 2010


Return AVPROBE_SCORE_MAX in raw dts probe if the first 3 DTS markers are
separated with padding that makes the resulting stream have exactly the
same bitrate as the corresponding uncompressed 16 bit stereo stream.

Return AVPROBE_SCORE_MAX / 4 in wav probe if the file is 16 bit stereo
PCM (as used by DTS-in-WAV) and the buffer size is so small that the raw
dts probe may not have gotten a reliable detection yet.
---
 libavformat/raw.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 libavformat/wav.c |   17 +++++++++++++----
 2 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/libavformat/raw.c b/libavformat/raw.c
index dc48c91..b4c3070 100644
--- a/libavformat/raw.c
+++ b/libavformat/raw.c
@@ -538,12 +538,36 @@ static int h261_probe(AVProbeData *p)
 #define DCA_MARKER_14B_LE 0xFF1F00E8
 #define DCA_MARKER_RAW_BE 0x7FFE8001
 #define DCA_MARKER_RAW_LE 0xFE7F0180
+
+static int dts_get_spdif_padding(uint32_t marker, const uint8_t *buf)
+{
+    int blocks;
+    switch (marker) {
+    case DCA_MARKER_RAW_BE:
+        blocks = (AV_RB16(buf) >> 2) & 0x7f;
+        break;
+    case DCA_MARKER_RAW_LE:
+        blocks = (AV_RL16(buf) >> 2) & 0x7f;
+        break;
+    case DCA_MARKER_14B_BE:
+        blocks = ((buf[1] & 0x07) << 4) | ((buf[2] & 0x3f) >> 2);
+        break;
+    case DCA_MARKER_14B_LE:
+        blocks = ((buf[0] & 0x07) << 4) | ((buf[3] & 0x3f) >> 2);
+        break;
+    default:
+        return 0;
+    }
+    return (blocks + 1) << 7;
+}
+
 static int dts_probe(AVProbeData *p)
 {
     const uint8_t *buf, *bufp;
     uint32_t state = -1;
     int markers[3] = {0};
     int sum, max;
+    int spdif_checked = 0;
 
     buf = p->buf;
 
@@ -564,6 +588,26 @@ static int dts_probe(AVProbeData *p)
         if (state == DCA_MARKER_14B_LE)
             if ((bytestream_get_be16(&bufp) & 0xF0FF) == 0xF007)
                 markers[2]++;
+
+        if (!spdif_checked && (markers[0] || markers[1] || markers[2])
+            && buf < p->buf + p->buf_size - 1024) {
+            /* check for dts padded for spdif (without iec61937) */
+            int padding = dts_get_spdif_padding(state, buf + 2);
+            int consecutive_markers = 0;
+            spdif_checked = 1;
+
+            if (!padding)
+                continue;
+
+            for (bufp = buf - 2 + padding; bufp < p->buf + p->buf_size - 4;
+                 bufp += padding) {
+                if (AV_RB32(bufp) == state) {
+                    if (++consecutive_markers == 2)
+                        return AVPROBE_SCORE_MAX;
+                } else
+                    break;
+            }
+        }
     }
     sum = markers[0] + markers[1] + markers[2];
     max = markers[1] > markers[0];
diff --git a/libavformat/wav.c b/libavformat/wav.c
index da08558..0fe70d4 100644
--- a/libavformat/wav.c
+++ b/libavformat/wav.c
@@ -23,6 +23,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 #include "avformat.h"
+#include "libavutil/intreadwrite.h"
 #include "raw.h"
 #include "riff.h"
 
@@ -159,16 +160,24 @@ static int64_t find_tag(ByteIOContext *pb, uint32_t tag1)
 static int wav_probe(AVProbeData *p)
 {
     /* check file header */
-    if (p->buf_size <= 32)
+    if (p->buf_size <= 36)
         return 0;
     if (!memcmp(p->buf + 8, "WAVE", 4)) {
         if (!memcmp(p->buf, "RIFF", 4))
             /*
-              Since ACT demuxer has standard WAV header at top of it's own,
-              returning score is decreased to avoid probe conflict
+              Return a low score for a stereo S16LE PCM file if the buffer is
+              so small that the detection of a possible DTS compression by raw
+              DTS demuxer may not have been possible.
+              Also, since ACT demuxer has standard WAV header at top of its
+              own, returning score is decreased to avoid probe conflict
               between ACT and WAV.
             */
-            return AVPROBE_SCORE_MAX - 1;
+            if (AV_RL32(p->buf + 16) == 16 && AV_RL16(p->buf + 20) == 1
+                && AV_RL16(p->buf + 22) == 2 && AV_RL16(p->buf + 34) == 16
+                && p->buf_size < 32768)
+                return AVPROBE_SCORE_MAX / 4;
+            else
+                return AVPROBE_SCORE_MAX - 1;
         else if (!memcmp(p->buf,      "RF64", 4) &&
                  !memcmp(p->buf + 12, "ds64", 4))
             return AVPROBE_SCORE_MAX;
-- 
1.7.2


--Boundary-00=_q62aM96K/jy6ypr--



More information about the ffmpeg-devel mailing list