[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