[FFmpeg-devel] [PATCH] DCA-in-WAV detection
Anssi Hannula
anssi.hannula
Wed Jan 26 17:37:39 CET 2011
On 23.01.2011 18:46, Vitor Sessak wrote:
> On 05/11/2007 05:04 AM, Kostya wrote:
>> On Fri, May 04, 2007 at 09:40:01AM +0300, Kostya wrote:
>>> Here is my attempt on patch discussed on Febryary 2006
>>> Thread called "[PATCH] Fix DTS in WAV file playback."
>>
>> ping
>
> Git-friendly patch attached. Hope that patchwork will catch it up.
>
> -Vitor
>
> From 5a24ffec96f58c1af68b7c87f65e29d9d8477507 Mon Sep 17 00:00:00 2001
> From: Kostya Shishkov <kostya.shishkov at gmail.com>
> Date: Sun, 23 Jan 2011 17:43:37 +0100
> Subject: [PATCH] DCA-in-WAV detection
>
> ---
> 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
In libavcodec/dca.h.
> +#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
For the record, they are probably intentionally broken so that
non-DTS-aware equipment/software can handle them before the stream is
fed to a DTS-capable receiver (think e.g. burning the .wav to an audio
disc).
> + 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 */
s/big/little/
> + if (state == DCA_MARKER_14B_LE) {
> + if ((get_be16(pb) & 0xF0FF) == 0xF007)
> + found = 1;
> + else
> + url_fseek(pb, -2, SEEK_CUR);
> + }
> + }
BTW, I don't think that any PCM_S16LE-declaring wav files contain
big-endian DTS stream. The stream is little-endian so that when the wav
file (or an audio disc track) is transmitted into S/PDIF and the byte
order of the assumed-PCM_S16LE samples is reversed (as S/PDIF is
big-endian), it becomes big-endian bitstream which is understood by the
receivers (while little-endian may not be).
I'm not against handling big-endian here just-in-case, though.
> + /* 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
--
Anssi Hannula
More information about the ffmpeg-devel
mailing list