[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