Support decoding AC-3 in wav.

All known samples are actually ac3-in-spdif-in-wav, so use
the spdif demuxer to get the ac3 frames.
This commit is contained in:
Carl Eugen Hoyos 2013-01-06 18:48:51 +01:00
parent 9ff92cf195
commit 1ae9d2820e
4 changed files with 35 additions and 10 deletions

View File

@ -23,6 +23,7 @@
#define AVFORMAT_SPDIF_H
#include <stdint.h>
#include "avformat.h"
#define SYNCWORD1 0xF872
#define SYNCWORD2 0x4E1F
@ -58,5 +59,7 @@ static const uint16_t spdif_mpeg_pkt_offset[2][3] = {
};
void ff_spdif_bswap_buf16(uint16_t *dst, const uint16_t *src, int w);
int ff_spdif_read_packet(AVFormatContext *s, AVPacket *pkt);
int ff_spdif_probe(const uint8_t *p_buf, int buf_size, enum AVCodecID *codec);
#endif /* AVFORMAT_SPDIF_H */

View File

@ -105,14 +105,19 @@ static int spdif_get_offset_and_codec(AVFormatContext *s,
static int spdif_probe(AVProbeData *p)
{
const uint8_t *buf = p->buf;
const uint8_t *probe_end = p->buf + FFMIN(2 * SPDIF_MAX_OFFSET, p->buf_size - 1);
enum AVCodecID codec;
return ff_spdif_probe (p->buf, p->buf_size, &codec);
}
int ff_spdif_probe(const uint8_t *p_buf, int buf_size, enum AVCodecID *codec)
{
const uint8_t *buf = p_buf;
const uint8_t *probe_end = p_buf + FFMIN(2 * SPDIF_MAX_OFFSET, buf_size - 1);
const uint8_t *expected_code = buf + 7;
uint32_t state = 0;
int sync_codes = 0;
int consecutive_codes = 0;
int offset;
enum AVCodecID codec;
for (; buf < probe_end; buf++) {
state = (state << 8) | *buf;
@ -127,16 +132,16 @@ static int spdif_probe(AVProbeData *p)
} else
consecutive_codes = 0;
if (buf + 4 + AAC_ADTS_HEADER_SIZE > p->buf + p->buf_size)
if (buf + 4 + AAC_ADTS_HEADER_SIZE > p_buf + buf_size)
break;
/* continue probing to find more sync codes */
probe_end = FFMIN(buf + SPDIF_MAX_OFFSET, p->buf + p->buf_size - 1);
probe_end = FFMIN(buf + SPDIF_MAX_OFFSET, p_buf + buf_size - 1);
/* skip directly to the next sync code */
if (!spdif_get_offset_and_codec(NULL, (buf[2] << 8) | buf[1],
&buf[5], &offset, &codec)) {
if (buf + offset >= p->buf + p->buf_size)
&buf[5], &offset, codec)) {
if (buf + offset >= p_buf + buf_size)
break;
expected_code = buf + offset;
buf = expected_code - 7;
@ -161,7 +166,7 @@ static int spdif_read_header(AVFormatContext *s)
return 0;
}
static int spdif_read_packet(AVFormatContext *s, AVPacket *pkt)
int ff_spdif_read_packet(AVFormatContext *s, AVPacket *pkt)
{
AVIOContext *pb = s->pb;
enum IEC61937DataType data_type;
@ -230,6 +235,6 @@ AVInputFormat ff_spdif_demuxer = {
.long_name = NULL_IF_CONFIG_SMALL("IEC 61937 (compressed data in S/PDIF)"),
.read_probe = spdif_probe,
.read_header = spdif_read_header,
.read_packet = spdif_read_packet,
.read_packet = ff_spdif_read_packet,
.flags = AVFMT_GENERIC_INDEX,
};

View File

@ -31,7 +31,7 @@
#define LIBAVFORMAT_VERSION_MAJOR 54
#define LIBAVFORMAT_VERSION_MINOR 59
#define LIBAVFORMAT_VERSION_MICRO 105
#define LIBAVFORMAT_VERSION_MICRO 106
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \

View File

@ -36,6 +36,7 @@
#include "w64.h"
#include "avio.h"
#include "metadata.h"
#include "spdif.h"
typedef struct WAVDemuxContext {
const AVClass *class;
@ -49,6 +50,7 @@ typedef struct WAVDemuxContext {
int smv_eof;
int audio_eof;
int ignore_length;
int spdif;
} WAVDemuxContext;
@ -407,6 +409,21 @@ static int wav_read_packet(AVFormatContext *s,
AVStream *st;
WAVDemuxContext *wav = s->priv_data;
if (CONFIG_SPDIF_DEMUXER && wav->spdif == 0 &&
s->streams[0]->codec->codec_tag == 1) {
enum AVCodecID codec;
ret = ff_spdif_probe(s->pb->buffer, s->pb->buf_end - s->pb->buffer,
&codec);
if (ret > AVPROBE_SCORE_MAX / 2) {
s->streams[0]->codec->codec_id = codec;
wav->spdif = 1;
} else {
wav->spdif = -1;
}
}
if (CONFIG_SPDIF_DEMUXER && wav->spdif == 1)
return ff_spdif_read_packet(s, pkt);
if (wav->smv_data_ofs > 0) {
int64_t audio_dts, video_dts;
smv_retry: