Commit 1ae9d282 authored by Carl Eugen Hoyos's avatar Carl Eugen Hoyos

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.
parent 9ff92cf1
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#define AVFORMAT_SPDIF_H #define AVFORMAT_SPDIF_H
#include <stdint.h> #include <stdint.h>
#include "avformat.h"
#define SYNCWORD1 0xF872 #define SYNCWORD1 0xF872
#define SYNCWORD2 0x4E1F #define SYNCWORD2 0x4E1F
...@@ -58,5 +59,7 @@ static const uint16_t spdif_mpeg_pkt_offset[2][3] = { ...@@ -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); 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 */ #endif /* AVFORMAT_SPDIF_H */
...@@ -105,14 +105,19 @@ static int spdif_get_offset_and_codec(AVFormatContext *s, ...@@ -105,14 +105,19 @@ static int spdif_get_offset_and_codec(AVFormatContext *s,
static int spdif_probe(AVProbeData *p) static int spdif_probe(AVProbeData *p)
{ {
const uint8_t *buf = p->buf; enum AVCodecID codec;
const uint8_t *probe_end = p->buf + FFMIN(2 * SPDIF_MAX_OFFSET, p->buf_size - 1); 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; const uint8_t *expected_code = buf + 7;
uint32_t state = 0; uint32_t state = 0;
int sync_codes = 0; int sync_codes = 0;
int consecutive_codes = 0; int consecutive_codes = 0;
int offset; int offset;
enum AVCodecID codec;
for (; buf < probe_end; buf++) { for (; buf < probe_end; buf++) {
state = (state << 8) | *buf; state = (state << 8) | *buf;
...@@ -127,16 +132,16 @@ static int spdif_probe(AVProbeData *p) ...@@ -127,16 +132,16 @@ static int spdif_probe(AVProbeData *p)
} else } else
consecutive_codes = 0; 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; break;
/* continue probing to find more sync codes */ /* 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 */ /* skip directly to the next sync code */
if (!spdif_get_offset_and_codec(NULL, (buf[2] << 8) | buf[1], if (!spdif_get_offset_and_codec(NULL, (buf[2] << 8) | buf[1],
&buf[5], &offset, &codec)) { &buf[5], &offset, codec)) {
if (buf + offset >= p->buf + p->buf_size) if (buf + offset >= p_buf + buf_size)
break; break;
expected_code = buf + offset; expected_code = buf + offset;
buf = expected_code - 7; buf = expected_code - 7;
...@@ -161,7 +166,7 @@ static int spdif_read_header(AVFormatContext *s) ...@@ -161,7 +166,7 @@ static int spdif_read_header(AVFormatContext *s)
return 0; return 0;
} }
static int spdif_read_packet(AVFormatContext *s, AVPacket *pkt) int ff_spdif_read_packet(AVFormatContext *s, AVPacket *pkt)
{ {
AVIOContext *pb = s->pb; AVIOContext *pb = s->pb;
enum IEC61937DataType data_type; enum IEC61937DataType data_type;
...@@ -230,6 +235,6 @@ AVInputFormat ff_spdif_demuxer = { ...@@ -230,6 +235,6 @@ AVInputFormat ff_spdif_demuxer = {
.long_name = NULL_IF_CONFIG_SMALL("IEC 61937 (compressed data in S/PDIF)"), .long_name = NULL_IF_CONFIG_SMALL("IEC 61937 (compressed data in S/PDIF)"),
.read_probe = spdif_probe, .read_probe = spdif_probe,
.read_header = spdif_read_header, .read_header = spdif_read_header,
.read_packet = spdif_read_packet, .read_packet = ff_spdif_read_packet,
.flags = AVFMT_GENERIC_INDEX, .flags = AVFMT_GENERIC_INDEX,
}; };
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#define LIBAVFORMAT_VERSION_MAJOR 54 #define LIBAVFORMAT_VERSION_MAJOR 54
#define LIBAVFORMAT_VERSION_MINOR 59 #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, \ #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \ LIBAVFORMAT_VERSION_MINOR, \
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "w64.h" #include "w64.h"
#include "avio.h" #include "avio.h"
#include "metadata.h" #include "metadata.h"
#include "spdif.h"
typedef struct WAVDemuxContext { typedef struct WAVDemuxContext {
const AVClass *class; const AVClass *class;
...@@ -49,6 +50,7 @@ typedef struct WAVDemuxContext { ...@@ -49,6 +50,7 @@ typedef struct WAVDemuxContext {
int smv_eof; int smv_eof;
int audio_eof; int audio_eof;
int ignore_length; int ignore_length;
int spdif;
} WAVDemuxContext; } WAVDemuxContext;
...@@ -407,6 +409,21 @@ static int wav_read_packet(AVFormatContext *s, ...@@ -407,6 +409,21 @@ static int wav_read_packet(AVFormatContext *s,
AVStream *st; AVStream *st;
WAVDemuxContext *wav = s->priv_data; 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) { if (wav->smv_data_ofs > 0) {
int64_t audio_dts, video_dts; int64_t audio_dts, video_dts;
smv_retry: smv_retry:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment