aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoranssih <anssih@svn>2010-08-26 22:29:25 +0000
committeranssih <anssih@svn>2010-08-26 22:29:25 +0000
commit0dc21668a41e0de03e99c895a4823b8a5188d1e6 (patch)
treead5af6c53b4bf41b8bf0016907c401f5c863d844
parent62091ce9b91c433a835229349f7010fab6874e04 (diff)
add spdif demuxer patch to ffmpeg patchset
(cherry picked from commit 33c97443302cd593f5d0c21611de7d5451b71b32) git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/branches/Dharma@33187 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
-rw-r--r--xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0033-added-ffmpeg-spdif-demuxer-fixes-ac3-in-wav.patch312
1 files changed, 312 insertions, 0 deletions
diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0033-added-ffmpeg-spdif-demuxer-fixes-ac3-in-wav.patch b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0033-added-ffmpeg-spdif-demuxer-fixes-ac3-in-wav.patch
new file mode 100644
index 0000000000..5572de1b40
--- /dev/null
+++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/patches/0033-added-ffmpeg-spdif-demuxer-fixes-ac3-in-wav.patch
@@ -0,0 +1,312 @@
+From 9ce6f874f085c318a88d73f89c2d3804dd064ce6 Mon Sep 17 00:00:00 2001
+From: Anssi Hannula <anssi.hannula@iki.fi>
+Date: Thu, 26 Aug 2010 21:49:03 +0300
+Subject: [PATCH] added: ffmpeg spdif demuxer (fixes ac3-in-wav)
+
+This is a patch on its way to ffmpeg upstream after some cleanups, but
+it does work already.
+---
+ .../cores/dvdplayer/Codecs/ffmpeg/doc/general.texi | 2 +-
+ .../dvdplayer/Codecs/ffmpeg/libavformat/Makefile | 1 +
+ .../Codecs/ffmpeg/libavformat/allformats.c | 2 +-
+ .../dvdplayer/Codecs/ffmpeg/libavformat/spdif.c | 229 +++++++++++++++++++-
+ 4 files changed, 231 insertions(+), 3 deletions(-)
+
+diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/doc/general.texi b/xbmc/cores/dvdplayer/Codecs/ffmpeg/doc/general.texi
+index d7f85e8..0154b79 100644
+--- a/xbmc/cores/dvdplayer/Codecs/ffmpeg/doc/general.texi
++++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/doc/general.texi
+@@ -102,7 +102,7 @@ library:
+ @item id Quake II CIN video @tab @tab X
+ @item id RoQ @tab X @tab X
+ @tab Used in Quake III, Jedi Knight 2, other computer games.
+-@item IEC61937 encapsulation @tab X @tab
++@item IEC61937 encapsulation @tab X @tab X
+ @item IFF @tab @tab X
+ @tab Interchange File Format
+ @item Interplay MVE @tab @tab X
+diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavformat/Makefile b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavformat/Makefile
+index 36669bd..489c9ce 100644
+--- a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavformat/Makefile
++++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavformat/Makefile
+@@ -238,6 +238,7 @@ OBJS-$(CONFIG_SMACKER_DEMUXER) += smacker.o
+ OBJS-$(CONFIG_SOL_DEMUXER) += sol.o raw.o
+ OBJS-$(CONFIG_SOX_DEMUXER) += soxdec.o raw.o
+ OBJS-$(CONFIG_SOX_MUXER) += soxenc.o
++OBJS-$(CONFIG_SPDIF_DEMUXER) += spdif.o
+ OBJS-$(CONFIG_SPDIF_MUXER) += spdif.o
+ OBJS-$(CONFIG_STR_DEMUXER) += psxstr.o
+ OBJS-$(CONFIG_SWF_DEMUXER) += swfdec.o
+diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavformat/allformats.c b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavformat/allformats.c
+index 94ab78c..30469f4 100644
+--- a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavformat/allformats.c
++++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavformat/allformats.c
+@@ -187,7 +187,7 @@ void av_register_all(void)
+ REGISTER_DEMUXER (SMACKER, smacker);
+ REGISTER_DEMUXER (SOL, sol);
+ REGISTER_MUXDEMUX (SOX, sox);
+- REGISTER_MUXER (SPDIF, spdif);
++ REGISTER_MUXDEMUX (SPDIF, spdif);
+ REGISTER_DEMUXER (STR, str);
+ REGISTER_MUXDEMUX (SWF, swf);
+ REGISTER_MUXER (TG2, tg2);
+diff --git a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavformat/spdif.c b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavformat/spdif.c
+index 473e325..98184d6 100644
+--- a/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavformat/spdif.c
++++ b/xbmc/cores/dvdplayer/Codecs/ffmpeg/libavformat/spdif.c
+@@ -1,6 +1,7 @@
+ /*
+- * IEC958 muxer
++ * IEC958 muxer and demuxer
+ * Copyright (c) 2009 Bartlomiej Wolowiec
++ * Copyright (c) 2010 Anssi Hannula <anssi.hannula@iki.fi>
+ *
+ * This file is part of FFmpeg.
+ *
+@@ -23,6 +24,7 @@
+ * @file
+ * IEC-61937 encapsulation of various formats, used by S/PDIF
+ * @author Bartlomiej Wolowiec
++ * @author Anssi Hannula
+ */
+
+ /*
+@@ -303,6 +305,7 @@ static int spdif_write_packet(struct AVFormatContext *s, AVPacket *pkt)
+ return 0;
+ }
+
++#if CONFIG_SPDIF_MUXER
+ AVOutputFormat spdif_muxer = {
+ "spdif",
+ NULL_IF_CONFIG_SMALL("IEC958 - S/PDIF (IEC-61937)"),
+@@ -315,3 +318,227 @@ AVOutputFormat spdif_muxer = {
+ spdif_write_packet,
+ spdif_write_trailer,
+ };
++#endif
++
++
++static int spdif_get_offset_and_codec(AVFormatContext *s,
++ enum IEC958DataType data_type,
++ const char *buf, int *offset,
++ enum CodecID *codec)
++{
++ AACADTSHeaderInfo aac_hdr;
++ GetBitContext gbc;
++
++ switch (data_type & 0xff) {
++ case IEC958_AC3:
++ *offset = AC3_FRAME_SIZE << 2;
++ *codec = CODEC_ID_AC3;
++ break;
++ case IEC958_MPEG1_LAYER1:
++ *offset = mpeg_pkt_offset[1][0];
++ *codec = CODEC_ID_MP1;
++ break;
++ case IEC958_MPEG1_LAYER23:
++ *offset = mpeg_pkt_offset[1][0];
++ *codec = CODEC_ID_MP3;
++ break;
++ case IEC958_MPEG2_EXT:
++ *offset = 4608;
++ *codec = CODEC_ID_MP3;
++ break;
++ case IEC958_MPEG2_AAC:
++ init_get_bits(&gbc, buf, AAC_ADTS_HEADER_SIZE * 8);
++ if (ff_aac_parse_header(&gbc, &aac_hdr)) {
++ if (s) /* be silent during a probe */
++ av_log(s, AV_LOG_ERROR, "Invalid AAC packet in S/PDIF\n");
++ return AVERROR(EINVAL);
++ }
++ *offset = aac_hdr.samples << 2;
++ *codec = CODEC_ID_AAC;
++ break;
++ case IEC958_MPEG2_LAYER1_LSF:
++ *offset = mpeg_pkt_offset[0][0];
++ *codec = CODEC_ID_MP1;
++ break;
++ case IEC958_MPEG2_LAYER2_LSF:
++ *offset = mpeg_pkt_offset[0][1];
++ *codec = CODEC_ID_MP2;
++ break;
++ case IEC958_MPEG2_LAYER3_LSF:
++ *offset = mpeg_pkt_offset[0][2];
++ *codec = CODEC_ID_MP3;
++ break;
++ case IEC958_DTS1:
++ *offset = 2048;
++ *codec = CODEC_ID_DTS;
++ break;
++ case IEC958_DTS2:
++ *offset = 4096;
++ *codec = CODEC_ID_DTS;
++ break;
++ case IEC958_DTS3:
++ *offset = 8192;
++ *codec = CODEC_ID_DTS;
++ break;
++ default:
++ if (s) { /* be silent during a probe */
++ av_log(s, AV_LOG_WARNING, "Data type 0x%04x", data_type);
++ av_log_missing_feature(s, " in S/PDIF is", 1);
++ }
++ return AVERROR(ENOSYS);
++ }
++ return 0;
++}
++
++/* Largest offset between bursts we currently handle, i.e. AAC with
++ aac_hdr.samples = 4096 */
++#define SPDIF_MAX_OFFSET 16384
++
++static int spdif_probe(AVProbeData *p)
++{
++ const uint8_t *buf = p->buf;
++ /* probe for 64 bytes to find initial sync word */
++ const uint8_t *probe_end = p->buf + FFMIN(SPDIF_MAX_OFFSET, p->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 CodecID codec;
++
++ for (; buf < probe_end; buf++) {
++ state = (state << 8) | *buf;
++
++ if (state == (AV_BSWAP16C(SYNCWORD1) << 16 | AV_BSWAP16C(SYNCWORD2))
++ && buf[1] < 0x37) {
++ sync_codes++;
++
++ if (buf == expected_code) {
++ if (++consecutive_codes >= 3)
++ return AVPROBE_SCORE_MAX;
++ } else
++ consecutive_codes = 0;
++
++ if (buf + 4 + AAC_ADTS_HEADER_SIZE > p->buf + p->buf_size)
++ break;
++
++ /* continue probing to find more sync codes */
++ probe_end = FFMIN(buf + SPDIF_MAX_OFFSET, p->buf + p->buf_size - 1);
++
++ /* try to 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)
++ break;
++ expected_code = buf + offset;
++ buf = expected_code - 7;
++ }
++ }
++ }
++
++ if (!sync_codes)
++ return 0;
++
++ if (p->buf_size / sync_codes > SPDIF_MAX_OFFSET)
++ return 1; /* unusually few sync codes were found */
++
++ if (sync_codes >= 6)
++ /* expected amount of sync codes but with unexpected offsets */
++ return AVPROBE_SCORE_MAX / 2;
++
++ if (sync_codes == consecutive_codes + 1 &&
++ !memcmp(p->buf + 8, "WAVE", 4) && !memcmp(p->buf, "RIFF", 4))
++ /* all sync codes (except first one as it was only after WAV headers)
++ were consecutive, but the buffer was too small;
++ also, this looks like a WAV file, so we need to delay wav demuxer
++ from grabbing this file until we get a big enough buffer to see if
++ there are more consecutive codes (we want to be selected for
++ (ac3-in-)spdif-in-wav as chained demuxers are not yet supported),
++ therefore return the same score as wav demuxer to make it a tie */
++ return AVPROBE_SCORE_MAX - 1;
++
++ /* sync codes were found but the buffer was too small */
++ return AVPROBE_SCORE_MAX / 8;
++}
++
++static int spdif_read_header(AVFormatContext *s, AVFormatParameters *ap)
++{
++ s->ctx_flags |= AVFMTCTX_NOHEADER;
++ return 0;
++}
++
++static int spdif_read_packet(AVFormatContext *s, AVPacket *pkt)
++{
++ ByteIOContext *pb = s->pb;
++ enum IEC958DataType data_type;
++ enum CodecID codec_id;
++ uint32_t state = 0;
++ int pkt_size_bits, offset, ret;
++
++ while (state != (AV_BSWAP16C(SYNCWORD1) << 16 | AV_BSWAP16C(SYNCWORD2))) {
++ state = (state << 8) | get_byte(pb);
++ if (url_feof(pb))
++ return AVERROR_EOF;
++ }
++
++ data_type = get_le16(pb);
++ pkt_size_bits = get_le16(pb);
++
++ if (pkt_size_bits % 16)
++ av_log_ask_for_sample(s, "Packet does not end to a 16-bit boundary.");
++
++ ret = av_new_packet(pkt, FFALIGN(pkt_size_bits, 16) >> 3);
++ if (ret)
++ return ret;
++
++ pkt->pos = url_ftell(pb) - BURST_HEADER_SIZE;
++
++ if (get_buffer(pb, pkt->data, pkt->size) < pkt->size) {
++ av_free_packet(pkt);
++ return AVERROR(EIO);
++ }
++ bswap_buf16((uint16_t *)pkt->data, (uint16_t *)pkt->data, pkt->size >> 1);
++
++ ret = spdif_get_offset_and_codec(s, data_type, pkt->data,
++ &offset, &codec_id);
++ if (ret) {
++ av_free_packet(pkt);
++ return ret;
++ }
++
++ /* skip over the padding to the beginning of the next frame */
++ url_fskip(pb, offset - pkt->size - BURST_HEADER_SIZE);
++
++ if (!s->nb_streams) {
++ /* first packet, create a stream */
++ AVStream *st = av_new_stream(s, 0);
++ if (!st) {
++ av_free_packet(pkt);
++ return AVERROR(ENOMEM);
++ }
++ st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
++ st->codec->codec_id = codec_id;
++ } else if (codec_id != s->streams[0]->codec->codec_id) {
++ av_log_ask_for_sample(s, "Codec changed in S/PDIF stream.");
++ return AVERROR(ENOSYS);
++ }
++
++ if (!s->bit_rate && s->streams[0]->codec->sample_rate)
++ /* stream bitrate matches 16-bit stereo PCM bitrate for currently
++ supported codecs */
++ s->bit_rate = 2 * 16 * s->streams[0]->codec->sample_rate;
++
++ return 0;
++}
++
++#if CONFIG_SPDIF_DEMUXER
++AVInputFormat spdif_demuxer = {
++ "spdif",
++ NULL_IF_CONFIG_SMALL("IEC958 - S/PDIF (IEC-61937)"),
++ 0,
++ spdif_probe,
++ spdif_read_header,
++ spdif_read_packet,
++ .flags = AVFMT_GENERIC_INDEX,
++};
++#endif
+--
+1.7.2
+