summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Eugen Hoyos <cehoyos@ag.or.at>2013-01-06 18:48:51 +0100
committerCarl Eugen Hoyos <cehoyos@ag.or.at>2013-01-06 18:48:51 +0100
commit1ae9d2820e1181a1109c230d4f1e717443dcce2d (patch)
treef84cc0408b71350c81dbb784eb8c94cab1756006
parent9ff92cf1953d90e0e4f87f76f3f2f6439205a139 (diff)
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.
-rw-r--r--libavformat/spdif.h3
-rw-r--r--libavformat/spdifdec.c23
-rw-r--r--libavformat/version.h2
-rw-r--r--libavformat/wavdec.c17
4 files changed, 35 insertions, 10 deletions
diff --git a/libavformat/spdif.h b/libavformat/spdif.h
index 4b11de20d1..0a0d962ba4 100644
--- a/libavformat/spdif.h
+++ b/libavformat/spdif.h
@@ -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 */
diff --git a/libavformat/spdifdec.c b/libavformat/spdifdec.c
index 94cfe8443d..e1329cc6d3 100644
--- a/libavformat/spdifdec.c
+++ b/libavformat/spdifdec.c
@@ -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,
};
diff --git a/libavformat/version.h b/libavformat/version.h
index f6901dd8f1..49cd01a9d8 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -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, \
diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c
index f8a36e9d6c..451187739f 100644
--- a/libavformat/wavdec.c
+++ b/libavformat/wavdec.c
@@ -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: