/* * IEC 61937 demuxer * Copyright (c) 2010 Anssi Hannula <anssi.hannula at iki.fi> * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * @file * IEC 61937 demuxer, used for compressed data in S/PDIF * @author Anssi Hannula */ #include "avformat.h" #include "spdif.h" #include "libavcodec/ac3.h" #include "libavcodec/aacadtsdec.h" static int spdif_get_offset_and_codec(AVFormatContext *s, enum IEC61937DataType data_type, const char *buf, int *offset, enum CodecID *codec) { AACADTSHeaderInfo aac_hdr; GetBitContext gbc; switch (data_type & 0xff) { case IEC61937_AC3: *offset = AC3_FRAME_SIZE << 2; *codec = CODEC_ID_AC3; break; case IEC61937_MPEG1_LAYER1: *offset = spdif_mpeg_pkt_offset[1][0]; *codec = CODEC_ID_MP1; break; case IEC61937_MPEG1_LAYER23: *offset = spdif_mpeg_pkt_offset[1][0]; *codec = CODEC_ID_MP3; break; case IEC61937_MPEG2_EXT: *offset = 4608; *codec = CODEC_ID_MP3; break; case IEC61937_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 IEC 61937\n"); return AVERROR_INVALIDDATA; } *offset = aac_hdr.samples << 2; *codec = CODEC_ID_AAC; break; case IEC61937_MPEG2_LAYER1_LSF: *offset = spdif_mpeg_pkt_offset[0][0]; *codec = CODEC_ID_MP1; break; case IEC61937_MPEG2_LAYER2_LSF: *offset = spdif_mpeg_pkt_offset[0][1]; *codec = CODEC_ID_MP2; break; case IEC61937_MPEG2_LAYER3_LSF: *offset = spdif_mpeg_pkt_offset[0][2]; *codec = CODEC_ID_MP3; break; case IEC61937_DTS1: *offset = 2048; *codec = CODEC_ID_DTS; break; case IEC61937_DTS2: *offset = 4096; *codec = CODEC_ID_DTS; break; case IEC61937_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 IEC 61937 is", 1); } return AVERROR_PATCHWELCOME; } 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; const uint8_t *probe_end = p->buf + FFMIN(2 * 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 >= 2) 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); /* 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 (sync_codes >= 6) /* good amount of sync codes but with unexpected offsets */ return AVPROBE_SCORE_MAX / 2; /* some sync codes were found */ 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 IEC61937DataType 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_EOF; } ff_spdif_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_missing_feature(s, "codec change in IEC 61937", 0); return AVERROR_PATCHWELCOME; } 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; } AVInputFormat spdif_demuxer = { "spdif", NULL_IF_CONFIG_SMALL("IEC 61937 (compressed data in S/PDIF)"), 0, spdif_probe, spdif_read_header, spdif_read_packet, .flags = AVFMT_GENERIC_INDEX, };