| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * IEC 61937 demuxer | ||
| 3 | * Copyright (c) 2010 Anssi Hannula <anssi.hannula at iki.fi> | ||
| 4 | * | ||
| 5 | * This file is part of FFmpeg. | ||
| 6 | * | ||
| 7 | * FFmpeg is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with FFmpeg; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | /** | ||
| 23 | * @file | ||
| 24 | * IEC 61937 demuxer, used for compressed data in S/PDIF | ||
| 25 | * @author Anssi Hannula | ||
| 26 | */ | ||
| 27 | |||
| 28 | #include "libavutil/bswap.h" | ||
| 29 | |||
| 30 | #include "libavcodec/ac3defs.h" | ||
| 31 | #include "libavcodec/adts_parser.h" | ||
| 32 | |||
| 33 | #include "avformat.h" | ||
| 34 | #include "demux.h" | ||
| 35 | #include "internal.h" | ||
| 36 | #include "spdif.h" | ||
| 37 | |||
| 38 | 2194 | static int spdif_get_offset_and_codec(AVFormatContext *s, | |
| 39 | enum IEC61937DataType data_type, | ||
| 40 | const char *buf, int *offset, | ||
| 41 | enum AVCodecID *codec) | ||
| 42 | { | ||
| 43 | uint32_t samples; | ||
| 44 | uint8_t frames; | ||
| 45 | int ret; | ||
| 46 | |||
| 47 |
6/13✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 114 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 102 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1189 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 662 times.
✓ Branch 12 taken 20 times.
|
2194 | switch (data_type & 0xff) { |
| 48 | 107 | case IEC61937_AC3: | |
| 49 | 107 | *offset = AC3_FRAME_SIZE << 2; | |
| 50 | 107 | *codec = AV_CODEC_ID_AC3; | |
| 51 | 107 | break; | |
| 52 | ✗ | case IEC61937_MPEG1_LAYER1: | |
| 53 | ✗ | *offset = spdif_mpeg_pkt_offset[1][0]; | |
| 54 | ✗ | *codec = AV_CODEC_ID_MP1; | |
| 55 | ✗ | break; | |
| 56 | 114 | case IEC61937_MPEG1_LAYER23: | |
| 57 | 114 | *offset = spdif_mpeg_pkt_offset[1][0]; | |
| 58 | 114 | *codec = AV_CODEC_ID_MP3; | |
| 59 | 114 | break; | |
| 60 | ✗ | case IEC61937_MPEG2_EXT: | |
| 61 | ✗ | *offset = 4608; | |
| 62 | ✗ | *codec = AV_CODEC_ID_MP3; | |
| 63 | ✗ | break; | |
| 64 | 102 | case IEC61937_MPEG2_AAC: | |
| 65 | 102 | ret = av_adts_header_parse(buf, &samples, &frames); | |
| 66 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 86 times.
|
102 | if (ret < 0) { |
| 67 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if (s) /* be silent during a probe */ |
| 68 | ✗ | av_log(s, AV_LOG_ERROR, "Invalid AAC packet in IEC 61937\n"); | |
| 69 | 16 | return ret; | |
| 70 | } | ||
| 71 | 86 | *offset = samples << 2; | |
| 72 | 86 | *codec = AV_CODEC_ID_AAC; | |
| 73 | 86 | break; | |
| 74 | ✗ | case IEC61937_MPEG2_LAYER1_LSF: | |
| 75 | ✗ | *offset = spdif_mpeg_pkt_offset[0][0]; | |
| 76 | ✗ | *codec = AV_CODEC_ID_MP1; | |
| 77 | ✗ | break; | |
| 78 | ✗ | case IEC61937_MPEG2_LAYER2_LSF: | |
| 79 | ✗ | *offset = spdif_mpeg_pkt_offset[0][1]; | |
| 80 | ✗ | *codec = AV_CODEC_ID_MP2; | |
| 81 | ✗ | break; | |
| 82 | ✗ | case IEC61937_MPEG2_LAYER3_LSF: | |
| 83 | ✗ | *offset = spdif_mpeg_pkt_offset[0][2]; | |
| 84 | ✗ | *codec = AV_CODEC_ID_MP3; | |
| 85 | ✗ | break; | |
| 86 | 1189 | case IEC61937_DTS1: | |
| 87 | 1189 | *offset = 2048; | |
| 88 | 1189 | *codec = AV_CODEC_ID_DTS; | |
| 89 | 1189 | break; | |
| 90 | ✗ | case IEC61937_DTS2: | |
| 91 | ✗ | *offset = 4096; | |
| 92 | ✗ | *codec = AV_CODEC_ID_DTS; | |
| 93 | ✗ | break; | |
| 94 | ✗ | case IEC61937_DTS3: | |
| 95 | ✗ | *offset = 8192; | |
| 96 | ✗ | *codec = AV_CODEC_ID_DTS; | |
| 97 | ✗ | break; | |
| 98 | 662 | case IEC61937_EAC3: | |
| 99 | 662 | *offset = 24576; | |
| 100 | 662 | *codec = AV_CODEC_ID_EAC3; | |
| 101 | 662 | break; | |
| 102 | 20 | default: | |
| 103 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
20 | if (s) { /* be silent during a probe */ |
| 104 | ✗ | avpriv_request_sample(s, "Data type 0x%04x in IEC 61937", | |
| 105 | data_type); | ||
| 106 | } | ||
| 107 | 20 | return AVERROR_PATCHWELCOME; | |
| 108 | } | ||
| 109 | 2158 | return 0; | |
| 110 | } | ||
| 111 | |||
| 112 | /* Largest offset between bursts we currently handle, i.e. AAC with | ||
| 113 | samples = 4096 */ | ||
| 114 | #define SPDIF_MAX_OFFSET 16384 | ||
| 115 | |||
| 116 | 7467 | static int spdif_probe(const AVProbeData *p) | |
| 117 | { | ||
| 118 | enum AVCodecID codec; | ||
| 119 | 7467 | return ff_spdif_probe (p->buf, p->buf_size, &codec); | |
| 120 | } | ||
| 121 | |||
| 122 | 8005 | int ff_spdif_probe(const uint8_t *p_buf, int buf_size, enum AVCodecID *codec) | |
| 123 | { | ||
| 124 | 8005 | const uint8_t *buf = p_buf; | |
| 125 |
2/2✓ Branch 0 taken 6031 times.
✓ Branch 1 taken 1974 times.
|
8005 | const uint8_t *probe_end = p_buf + FFMIN(2 * SPDIF_MAX_OFFSET, buf_size - 1); |
| 126 | 8005 | const uint8_t *expected_code = buf + 7; | |
| 127 | 8005 | uint32_t state = 0; | |
| 128 | 8005 | int sync_codes = 0; | |
| 129 | 8005 | int consecutive_codes = 0; | |
| 130 | int offset; | ||
| 131 | |||
| 132 |
2/2✓ Branch 0 taken 105352695 times.
✓ Branch 1 taken 7987 times.
|
105360682 | for (; buf < probe_end; buf++) { |
| 133 | 105352695 | state = (state << 8) | *buf; | |
| 134 | |||
| 135 |
2/2✓ Branch 0 taken 101 times.
✓ Branch 1 taken 105352594 times.
|
105352695 | if (state == (AV_BSWAP16C(SYNCWORD1) << 16 | AV_BSWAP16C(SYNCWORD2)) |
| 136 |
1/2✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
|
101 | && buf[1] < 0x37) { |
| 137 | 101 | sync_codes++; | |
| 138 | |||
| 139 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 90 times.
|
101 | if (buf == expected_code) { |
| 140 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
|
11 | if (++consecutive_codes >= 2) |
| 141 | 4 | return AVPROBE_SCORE_MAX; | |
| 142 | } else | ||
| 143 | 90 | consecutive_codes = 0; | |
| 144 | |||
| 145 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
|
97 | if (buf + 4 + AV_AAC_ADTS_HEADER_SIZE > p_buf + buf_size) |
| 146 | ✗ | break; | |
| 147 | |||
| 148 | /* continue probing to find more sync codes */ | ||
| 149 | 97 | probe_end = FFMIN(buf + SPDIF_MAX_OFFSET, p_buf + buf_size - 1); | |
| 150 | |||
| 151 | /* skip directly to the next sync code */ | ||
| 152 |
2/2✓ Branch 0 taken 61 times.
✓ Branch 1 taken 36 times.
|
97 | if (!spdif_get_offset_and_codec(NULL, (buf[2] << 8) | buf[1], |
| 153 | 97 | &buf[5], &offset, codec)) { | |
| 154 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 47 times.
|
61 | if (buf + offset >= p_buf + buf_size) |
| 155 | 14 | break; | |
| 156 | 47 | expected_code = buf + offset; | |
| 157 | 47 | buf = expected_code - 7; | |
| 158 | } | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 |
2/2✓ Branch 0 taken 7958 times.
✓ Branch 1 taken 43 times.
|
8001 | if (!sync_codes) |
| 163 | 7958 | return 0; | |
| 164 | |||
| 165 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 40 times.
|
43 | if (sync_codes >= 6) |
| 166 | /* good amount of sync codes but with unexpected offsets */ | ||
| 167 | 3 | return AVPROBE_SCORE_EXTENSION; | |
| 168 | |||
| 169 | /* some sync codes were found */ | ||
| 170 | 40 | return AVPROBE_SCORE_EXTENSION / 4; | |
| 171 | } | ||
| 172 | |||
| 173 | 7 | static int spdif_read_header(AVFormatContext *s) | |
| 174 | { | ||
| 175 | 7 | s->ctx_flags |= AVFMTCTX_NOHEADER; | |
| 176 | 7 | return 0; | |
| 177 | } | ||
| 178 | |||
| 179 | 2097 | static int spdif_get_pkt_size_bits(int type, int code) | |
| 180 | { | ||
| 181 |
2/2✓ Branch 0 taken 652 times.
✓ Branch 1 taken 1445 times.
|
2097 | switch (type & 0xff) { |
| 182 | 652 | case IEC61937_EAC3: | |
| 183 | 652 | return code << 3; | |
| 184 | 1445 | default: | |
| 185 | 1445 | return code; | |
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | 2113 | int ff_spdif_read_packet(AVFormatContext *s, AVPacket *pkt) | |
| 190 | { | ||
| 191 | 2113 | AVIOContext *pb = s->pb; | |
| 192 | enum IEC61937DataType data_type; | ||
| 193 | enum AVCodecID codec_id; | ||
| 194 | 2113 | uint32_t state = 0; | |
| 195 | int pkt_size_bits, offset, ret; | ||
| 196 | |||
| 197 |
2/2✓ Branch 0 taken 260308 times.
✓ Branch 1 taken 2097 times.
|
262405 | while (state != (AV_BSWAP16C(SYNCWORD1) << 16 | AV_BSWAP16C(SYNCWORD2))) { |
| 198 | 260308 | state = (state << 8) | avio_r8(pb); | |
| 199 |
2/2✓ Branch 1 taken 16 times.
✓ Branch 2 taken 260292 times.
|
260308 | if (avio_feof(pb)) |
| 200 | 16 | return AVERROR_EOF; | |
| 201 | } | ||
| 202 | |||
| 203 | 2097 | data_type = avio_rl16(pb); | |
| 204 | 2097 | pkt_size_bits = spdif_get_pkt_size_bits(data_type, avio_rl16(pb)); | |
| 205 | |||
| 206 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2097 times.
|
2097 | if (pkt_size_bits % 16) |
| 207 | ✗ | avpriv_request_sample(s, "Packet not ending at a 16-bit boundary"); | |
| 208 | |||
| 209 | 2097 | ret = av_new_packet(pkt, FFALIGN(pkt_size_bits, 16) >> 3); | |
| 210 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2097 times.
|
2097 | if (ret) |
| 211 | ✗ | return ret; | |
| 212 | |||
| 213 | 2097 | pkt->pos = avio_tell(pb) - BURST_HEADER_SIZE; | |
| 214 | |||
| 215 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2097 times.
|
2097 | if (avio_read(pb, pkt->data, pkt->size) < pkt->size) { |
| 216 | ✗ | return AVERROR_EOF; | |
| 217 | } | ||
| 218 | 2097 | ff_spdif_bswap_buf16((uint16_t *)pkt->data, (uint16_t *)pkt->data, pkt->size >> 1); | |
| 219 | |||
| 220 | 2097 | ret = spdif_get_offset_and_codec(s, data_type, pkt->data, | |
| 221 | &offset, &codec_id); | ||
| 222 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2097 times.
|
2097 | if (ret < 0) { |
| 223 | ✗ | return ret; | |
| 224 | } | ||
| 225 | |||
| 226 | /* skip over the padding to the beginning of the next frame */ | ||
| 227 | 2097 | avio_skip(pb, offset - pkt->size - BURST_HEADER_SIZE); | |
| 228 | |||
| 229 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2090 times.
|
2097 | if (!s->nb_streams) { |
| 230 | /* first packet, create a stream */ | ||
| 231 | 7 | AVStream *st = avformat_new_stream(s, NULL); | |
| 232 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (!st) { |
| 233 | ✗ | return AVERROR(ENOMEM); | |
| 234 | } | ||
| 235 | 7 | st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; | |
| 236 | 7 | st->codecpar->codec_id = codec_id; | |
| 237 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
|
7 | if (codec_id == AV_CODEC_ID_EAC3) |
| 238 | 1 | ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL; | |
| 239 | else | ||
| 240 | 6 | ffstream(st)->need_parsing = AVSTREAM_PARSE_HEADERS; | |
| 241 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2090 times.
|
2090 | } else if (codec_id != s->streams[0]->codecpar->codec_id) { |
| 242 | ✗ | avpriv_report_missing_feature(s, "Codec change in IEC 61937"); | |
| 243 | ✗ | return AVERROR_PATCHWELCOME; | |
| 244 | } | ||
| 245 | |||
| 246 |
4/4✓ Branch 0 taken 19 times.
✓ Branch 1 taken 2078 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 11 times.
|
2097 | if (!s->bit_rate && s->streams[0]->codecpar->sample_rate) |
| 247 | /* stream bitrate matches 16-bit stereo PCM bitrate for currently | ||
| 248 | supported codecs */ | ||
| 249 | 8 | s->bit_rate = 2 * 16LL * s->streams[0]->codecpar->sample_rate; | |
| 250 | |||
| 251 | 2097 | return 0; | |
| 252 | } | ||
| 253 | |||
| 254 | const FFInputFormat ff_spdif_demuxer = { | ||
| 255 | .p.name = "spdif", | ||
| 256 | .p.long_name = NULL_IF_CONFIG_SMALL("IEC 61937 (compressed data in S/PDIF)"), | ||
| 257 | .p.flags = AVFMT_GENERIC_INDEX, | ||
| 258 | .read_probe = spdif_probe, | ||
| 259 | .read_header = spdif_read_header, | ||
| 260 | .read_packet = ff_spdif_read_packet, | ||
| 261 | }; | ||
| 262 |