Browse code

S/PDIF demuxer

Patch by Anssi Hannula, anssi d hannula a iki d fi

Originally committed as revision 25804 to svn://svn.ffmpeg.org/ffmpeg/trunk

Anssi Hannula authored on 2010/11/23 07:09:26
Showing 6 changed files
... ...
@@ -58,6 +58,7 @@ version <next>:
58 58
 - IEC 61937 encapsulation for E-AC3 (for HDMI passthrough)
59 59
 - overlay filter added
60 60
 - rename aspect filter to setdar, and pixelaspect to setsar
61
+- IEC 61937 demuxer
61 62
 
62 63
 
63 64
 version 0.6:
... ...
@@ -103,7 +103,7 @@ library:
103 103
 @item id Quake II CIN video     @tab   @tab X
104 104
 @item id RoQ                    @tab X @tab X
105 105
     @tab Used in Quake III, Jedi Knight 2, other computer games.
106
-@item IEC61937 encapsulation @tab X @tab
106
+@item IEC61937 encapsulation @tab X @tab X
107 107
 @item IFF                       @tab   @tab X
108 108
     @tab Interchange File Format
109 109
 @item Interplay MVE             @tab   @tab X
... ...
@@ -256,6 +256,7 @@ OBJS-$(CONFIG_SMACKER_DEMUXER)           += smacker.o
256 256
 OBJS-$(CONFIG_SOL_DEMUXER)               += sol.o pcm.o
257 257
 OBJS-$(CONFIG_SOX_DEMUXER)               += soxdec.o pcm.o
258 258
 OBJS-$(CONFIG_SOX_MUXER)                 += soxenc.o
259
+OBJS-$(CONFIG_SPDIF_DEMUXER)             += spdif.o spdifdec.o
259 260
 OBJS-$(CONFIG_SPDIF_MUXER)               += spdif.o spdifenc.o
260 261
 OBJS-$(CONFIG_SRT_DEMUXER)               += srtdec.o
261 262
 OBJS-$(CONFIG_SRT_MUXER)                 += rawenc.o
... ...
@@ -193,7 +193,7 @@ void av_register_all(void)
193 193
     REGISTER_DEMUXER  (SMACKER, smacker);
194 194
     REGISTER_DEMUXER  (SOL, sol);
195 195
     REGISTER_MUXDEMUX (SOX, sox);
196
-    REGISTER_MUXER    (SPDIF, spdif);
196
+    REGISTER_MUXDEMUX (SPDIF, spdif);
197 197
     REGISTER_MUXDEMUX (SRT, srt);
198 198
     REGISTER_DEMUXER  (STR, str);
199 199
     REGISTER_MUXDEMUX (SWF, swf);
... ...
@@ -22,7 +22,7 @@
22 22
 #define AVFORMAT_AVFORMAT_H
23 23
 
24 24
 #define LIBAVFORMAT_VERSION_MAJOR 52
25
-#define LIBAVFORMAT_VERSION_MINOR 85
25
+#define LIBAVFORMAT_VERSION_MINOR 86
26 26
 #define LIBAVFORMAT_VERSION_MICRO  0
27 27
 
28 28
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
29 29
new file mode 100644
... ...
@@ -0,0 +1,236 @@
0
+/*
1
+ * IEC 61937 demuxer
2
+ * Copyright (c) 2010 Anssi Hannula <anssi.hannula at iki.fi>
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+/**
22
+ * @file
23
+ * IEC 61937 demuxer, used for compressed data in S/PDIF
24
+ * @author Anssi Hannula
25
+ */
26
+
27
+#include "avformat.h"
28
+#include "spdif.h"
29
+#include "libavcodec/ac3.h"
30
+#include "libavcodec/aacadtsdec.h"
31
+
32
+static int spdif_get_offset_and_codec(AVFormatContext *s,
33
+                                      enum IEC958DataType data_type,
34
+                                      const char *buf, int *offset,
35
+                                      enum CodecID *codec)
36
+{
37
+    AACADTSHeaderInfo aac_hdr;
38
+    GetBitContext gbc;
39
+
40
+    switch (data_type & 0xff) {
41
+    case IEC958_AC3:
42
+        *offset = AC3_FRAME_SIZE << 2;
43
+        *codec = CODEC_ID_AC3;
44
+        break;
45
+    case IEC958_MPEG1_LAYER1:
46
+        *offset = spdif_mpeg_pkt_offset[1][0];
47
+        *codec = CODEC_ID_MP1;
48
+        break;
49
+    case IEC958_MPEG1_LAYER23:
50
+        *offset = spdif_mpeg_pkt_offset[1][0];
51
+        *codec = CODEC_ID_MP3;
52
+        break;
53
+    case IEC958_MPEG2_EXT:
54
+        *offset = 4608;
55
+        *codec = CODEC_ID_MP3;
56
+        break;
57
+    case IEC958_MPEG2_AAC:
58
+        init_get_bits(&gbc, buf, AAC_ADTS_HEADER_SIZE * 8);
59
+        if (ff_aac_parse_header(&gbc, &aac_hdr)) {
60
+            if (s) /* be silent during a probe */
61
+                av_log(s, AV_LOG_ERROR, "Invalid AAC packet in IEC 61937\n");
62
+            return AVERROR_INVALIDDATA;
63
+        }
64
+        *offset = aac_hdr.samples << 2;
65
+        *codec = CODEC_ID_AAC;
66
+        break;
67
+    case IEC958_MPEG2_LAYER1_LSF:
68
+        *offset = spdif_mpeg_pkt_offset[0][0];
69
+        *codec = CODEC_ID_MP1;
70
+        break;
71
+    case IEC958_MPEG2_LAYER2_LSF:
72
+        *offset = spdif_mpeg_pkt_offset[0][1];
73
+        *codec = CODEC_ID_MP2;
74
+        break;
75
+    case IEC958_MPEG2_LAYER3_LSF:
76
+        *offset = spdif_mpeg_pkt_offset[0][2];
77
+        *codec = CODEC_ID_MP3;
78
+        break;
79
+    case IEC958_DTS1:
80
+        *offset = 2048;
81
+        *codec = CODEC_ID_DTS;
82
+        break;
83
+    case IEC958_DTS2:
84
+        *offset = 4096;
85
+        *codec = CODEC_ID_DTS;
86
+        break;
87
+    case IEC958_DTS3:
88
+        *offset = 8192;
89
+        *codec = CODEC_ID_DTS;
90
+        break;
91
+    default:
92
+        if (s) { /* be silent during a probe */
93
+            av_log(s, AV_LOG_WARNING, "Data type 0x%04x", data_type);
94
+            av_log_missing_feature(s, " in IEC 61937 is", 1);
95
+        }
96
+        return AVERROR_PATCHWELCOME;
97
+    }
98
+    return 0;
99
+}
100
+
101
+/* Largest offset between bursts we currently handle, i.e. AAC with
102
+   aac_hdr.samples = 4096 */
103
+#define SPDIF_MAX_OFFSET 16384
104
+
105
+static int spdif_probe(AVProbeData *p)
106
+{
107
+    const uint8_t *buf = p->buf;
108
+    const uint8_t *probe_end = p->buf + FFMIN(2 * SPDIF_MAX_OFFSET, p->buf_size - 1);
109
+    const uint8_t *expected_code = buf + 7;
110
+    uint32_t state = 0;
111
+    int sync_codes = 0;
112
+    int consecutive_codes = 0;
113
+    int offset;
114
+    enum CodecID codec;
115
+
116
+    for (; buf < probe_end; buf++) {
117
+        state = (state << 8) | *buf;
118
+
119
+        if (state == (AV_BSWAP16C(SYNCWORD1) << 16 | AV_BSWAP16C(SYNCWORD2))
120
+                && buf[1] < 0x37) {
121
+            sync_codes++;
122
+
123
+            if (buf == expected_code) {
124
+                if (++consecutive_codes >= 2)
125
+                    return AVPROBE_SCORE_MAX;
126
+            } else
127
+                consecutive_codes = 0;
128
+
129
+            if (buf + 4 + AAC_ADTS_HEADER_SIZE > p->buf + p->buf_size)
130
+                break;
131
+
132
+            /* continue probing to find more sync codes */
133
+            probe_end = FFMIN(buf + SPDIF_MAX_OFFSET, p->buf + p->buf_size - 1);
134
+
135
+            /* skip directly to the next sync code */
136
+            if (!spdif_get_offset_and_codec(NULL, (buf[2] << 8) | buf[1],
137
+                                            &buf[5], &offset, &codec)) {
138
+                if (buf + offset >= p->buf + p->buf_size)
139
+                    break;
140
+                expected_code = buf + offset;
141
+                buf = expected_code - 7;
142
+            }
143
+        }
144
+    }
145
+
146
+    if (!sync_codes)
147
+        return 0;
148
+
149
+    if (sync_codes >= 6)
150
+        /* good amount of sync codes but with unexpected offsets */
151
+        return AVPROBE_SCORE_MAX / 2;
152
+
153
+    /* some sync codes were found */
154
+    return AVPROBE_SCORE_MAX / 8;
155
+}
156
+
157
+static int spdif_read_header(AVFormatContext *s, AVFormatParameters *ap)
158
+{
159
+    s->ctx_flags |= AVFMTCTX_NOHEADER;
160
+    return 0;
161
+}
162
+
163
+static int spdif_read_packet(AVFormatContext *s, AVPacket *pkt)
164
+{
165
+    ByteIOContext *pb = s->pb;
166
+    enum IEC958DataType data_type;
167
+    enum CodecID codec_id;
168
+    uint32_t state = 0;
169
+    int pkt_size_bits, offset, ret;
170
+
171
+    while (state != (AV_BSWAP16C(SYNCWORD1) << 16 | AV_BSWAP16C(SYNCWORD2))) {
172
+        state = (state << 8) | get_byte(pb);
173
+        if (url_feof(pb))
174
+            return AVERROR_EOF;
175
+    }
176
+
177
+    data_type = get_le16(pb);
178
+    pkt_size_bits = get_le16(pb);
179
+
180
+    if (pkt_size_bits % 16)
181
+        av_log_ask_for_sample(s, "Packet does not end to a 16-bit boundary.");
182
+
183
+    ret = av_new_packet(pkt, FFALIGN(pkt_size_bits, 16) >> 3);
184
+    if (ret)
185
+        return ret;
186
+
187
+    pkt->pos = url_ftell(pb) - BURST_HEADER_SIZE;
188
+
189
+    if (get_buffer(pb, pkt->data, pkt->size) < pkt->size) {
190
+        av_free_packet(pkt);
191
+        return AVERROR_EOF;
192
+    }
193
+    ff_spdif_bswap_buf16((uint16_t *)pkt->data, (uint16_t *)pkt->data, pkt->size >> 1);
194
+
195
+    ret = spdif_get_offset_and_codec(s, data_type, pkt->data,
196
+                                     &offset, &codec_id);
197
+    if (ret) {
198
+        av_free_packet(pkt);
199
+        return ret;
200
+    }
201
+
202
+    /* skip over the padding to the beginning of the next frame */
203
+    url_fskip(pb, offset - pkt->size - BURST_HEADER_SIZE);
204
+
205
+    if (!s->nb_streams) {
206
+        /* first packet, create a stream */
207
+        AVStream *st = av_new_stream(s, 0);
208
+        if (!st) {
209
+            av_free_packet(pkt);
210
+            return AVERROR(ENOMEM);
211
+        }
212
+        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
213
+        st->codec->codec_id = codec_id;
214
+    } else if (codec_id != s->streams[0]->codec->codec_id) {
215
+        av_log_missing_feature(s, "codec change in IEC 61937", 0);
216
+        return AVERROR_PATCHWELCOME;
217
+    }
218
+
219
+    if (!s->bit_rate && s->streams[0]->codec->sample_rate)
220
+        /* stream bitrate matches 16-bit stereo PCM bitrate for currently
221
+           supported codecs */
222
+        s->bit_rate = 2 * 16 * s->streams[0]->codec->sample_rate;
223
+
224
+    return 0;
225
+}
226
+
227
+AVInputFormat spdif_demuxer = {
228
+    "spdif",
229
+    NULL_IF_CONFIG_SMALL("IEC 61937 (compressed data in S/PDIF)"),
230
+    0,
231
+    spdif_probe,
232
+    spdif_read_header,
233
+    spdif_read_packet,
234
+    .flags = AVFMT_GENERIC_INDEX,
235
+};