[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