yading@11: /* yading@11: * IEC 61937 demuxer yading@11: * Copyright (c) 2010 Anssi Hannula yading@11: * yading@11: * This file is part of FFmpeg. yading@11: * yading@11: * FFmpeg is free software; you can redistribute it and/or yading@11: * modify it under the terms of the GNU Lesser General Public yading@11: * License as published by the Free Software Foundation; either yading@11: * version 2.1 of the License, or (at your option) any later version. yading@11: * yading@11: * FFmpeg is distributed in the hope that it will be useful, yading@11: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@11: * Lesser General Public License for more details. yading@11: * yading@11: * You should have received a copy of the GNU Lesser General Public yading@11: * License along with FFmpeg; if not, write to the Free Software yading@11: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@11: */ yading@11: yading@11: /** yading@11: * @file yading@11: * IEC 61937 demuxer, used for compressed data in S/PDIF yading@11: * @author Anssi Hannula yading@11: */ yading@11: yading@11: #include "avformat.h" yading@11: #include "spdif.h" yading@11: #include "libavcodec/ac3.h" yading@11: #include "libavcodec/aacadtsdec.h" yading@11: yading@11: static int spdif_get_offset_and_codec(AVFormatContext *s, yading@11: enum IEC61937DataType data_type, yading@11: const char *buf, int *offset, yading@11: enum AVCodecID *codec) yading@11: { yading@11: AACADTSHeaderInfo aac_hdr; yading@11: GetBitContext gbc; yading@11: yading@11: switch (data_type & 0xff) { yading@11: case IEC61937_AC3: yading@11: *offset = AC3_FRAME_SIZE << 2; yading@11: *codec = AV_CODEC_ID_AC3; yading@11: break; yading@11: case IEC61937_MPEG1_LAYER1: yading@11: *offset = spdif_mpeg_pkt_offset[1][0]; yading@11: *codec = AV_CODEC_ID_MP1; yading@11: break; yading@11: case IEC61937_MPEG1_LAYER23: yading@11: *offset = spdif_mpeg_pkt_offset[1][0]; yading@11: *codec = AV_CODEC_ID_MP3; yading@11: break; yading@11: case IEC61937_MPEG2_EXT: yading@11: *offset = 4608; yading@11: *codec = AV_CODEC_ID_MP3; yading@11: break; yading@11: case IEC61937_MPEG2_AAC: yading@11: init_get_bits(&gbc, buf, AAC_ADTS_HEADER_SIZE * 8); yading@11: if (avpriv_aac_parse_header(&gbc, &aac_hdr)) { yading@11: if (s) /* be silent during a probe */ yading@11: av_log(s, AV_LOG_ERROR, "Invalid AAC packet in IEC 61937\n"); yading@11: return AVERROR_INVALIDDATA; yading@11: } yading@11: *offset = aac_hdr.samples << 2; yading@11: *codec = AV_CODEC_ID_AAC; yading@11: break; yading@11: case IEC61937_MPEG2_LAYER1_LSF: yading@11: *offset = spdif_mpeg_pkt_offset[0][0]; yading@11: *codec = AV_CODEC_ID_MP1; yading@11: break; yading@11: case IEC61937_MPEG2_LAYER2_LSF: yading@11: *offset = spdif_mpeg_pkt_offset[0][1]; yading@11: *codec = AV_CODEC_ID_MP2; yading@11: break; yading@11: case IEC61937_MPEG2_LAYER3_LSF: yading@11: *offset = spdif_mpeg_pkt_offset[0][2]; yading@11: *codec = AV_CODEC_ID_MP3; yading@11: break; yading@11: case IEC61937_DTS1: yading@11: *offset = 2048; yading@11: *codec = AV_CODEC_ID_DTS; yading@11: break; yading@11: case IEC61937_DTS2: yading@11: *offset = 4096; yading@11: *codec = AV_CODEC_ID_DTS; yading@11: break; yading@11: case IEC61937_DTS3: yading@11: *offset = 8192; yading@11: *codec = AV_CODEC_ID_DTS; yading@11: break; yading@11: default: yading@11: if (s) { /* be silent during a probe */ yading@11: avpriv_request_sample(s, "Data type 0x%04x in IEC 61937", yading@11: data_type); yading@11: } yading@11: return AVERROR_PATCHWELCOME; yading@11: } yading@11: return 0; yading@11: } yading@11: yading@11: /* Largest offset between bursts we currently handle, i.e. AAC with yading@11: aac_hdr.samples = 4096 */ yading@11: #define SPDIF_MAX_OFFSET 16384 yading@11: yading@11: static int spdif_probe(AVProbeData *p) yading@11: { yading@11: enum AVCodecID codec; yading@11: return ff_spdif_probe (p->buf, p->buf_size, &codec); yading@11: } yading@11: yading@11: int ff_spdif_probe(const uint8_t *p_buf, int buf_size, enum AVCodecID *codec) yading@11: { yading@11: const uint8_t *buf = p_buf; yading@11: const uint8_t *probe_end = p_buf + FFMIN(2 * SPDIF_MAX_OFFSET, buf_size - 1); yading@11: const uint8_t *expected_code = buf + 7; yading@11: uint32_t state = 0; yading@11: int sync_codes = 0; yading@11: int consecutive_codes = 0; yading@11: int offset; yading@11: yading@11: for (; buf < probe_end; buf++) { yading@11: state = (state << 8) | *buf; yading@11: yading@11: if (state == (AV_BSWAP16C(SYNCWORD1) << 16 | AV_BSWAP16C(SYNCWORD2)) yading@11: && buf[1] < 0x37) { yading@11: sync_codes++; yading@11: yading@11: if (buf == expected_code) { yading@11: if (++consecutive_codes >= 2) yading@11: return AVPROBE_SCORE_MAX; yading@11: } else yading@11: consecutive_codes = 0; yading@11: yading@11: if (buf + 4 + AAC_ADTS_HEADER_SIZE > p_buf + buf_size) yading@11: break; yading@11: yading@11: /* continue probing to find more sync codes */ yading@11: probe_end = FFMIN(buf + SPDIF_MAX_OFFSET, p_buf + buf_size - 1); yading@11: yading@11: /* skip directly to the next sync code */ yading@11: if (!spdif_get_offset_and_codec(NULL, (buf[2] << 8) | buf[1], yading@11: &buf[5], &offset, codec)) { yading@11: if (buf + offset >= p_buf + buf_size) yading@11: break; yading@11: expected_code = buf + offset; yading@11: buf = expected_code - 7; yading@11: } yading@11: } yading@11: } yading@11: yading@11: if (!sync_codes) yading@11: return 0; yading@11: yading@11: if (sync_codes >= 6) yading@11: /* good amount of sync codes but with unexpected offsets */ yading@11: return AVPROBE_SCORE_MAX / 2; yading@11: yading@11: /* some sync codes were found */ yading@11: return AVPROBE_SCORE_MAX / 8; yading@11: } yading@11: yading@11: static int spdif_read_header(AVFormatContext *s) yading@11: { yading@11: s->ctx_flags |= AVFMTCTX_NOHEADER; yading@11: return 0; yading@11: } yading@11: yading@11: int ff_spdif_read_packet(AVFormatContext *s, AVPacket *pkt) yading@11: { yading@11: AVIOContext *pb = s->pb; yading@11: enum IEC61937DataType data_type; yading@11: enum AVCodecID codec_id; yading@11: uint32_t state = 0; yading@11: int pkt_size_bits, offset, ret; yading@11: yading@11: while (state != (AV_BSWAP16C(SYNCWORD1) << 16 | AV_BSWAP16C(SYNCWORD2))) { yading@11: state = (state << 8) | avio_r8(pb); yading@11: if (url_feof(pb)) yading@11: return AVERROR_EOF; yading@11: } yading@11: yading@11: data_type = avio_rl16(pb); yading@11: pkt_size_bits = avio_rl16(pb); yading@11: yading@11: if (pkt_size_bits % 16) yading@11: avpriv_request_sample(s, "Packet not ending at a 16-bit boundary"); yading@11: yading@11: ret = av_new_packet(pkt, FFALIGN(pkt_size_bits, 16) >> 3); yading@11: if (ret) yading@11: return ret; yading@11: yading@11: pkt->pos = avio_tell(pb) - BURST_HEADER_SIZE; yading@11: yading@11: if (avio_read(pb, pkt->data, pkt->size) < pkt->size) { yading@11: av_free_packet(pkt); yading@11: return AVERROR_EOF; yading@11: } yading@11: ff_spdif_bswap_buf16((uint16_t *)pkt->data, (uint16_t *)pkt->data, pkt->size >> 1); yading@11: yading@11: ret = spdif_get_offset_and_codec(s, data_type, pkt->data, yading@11: &offset, &codec_id); yading@11: if (ret) { yading@11: av_free_packet(pkt); yading@11: return ret; yading@11: } yading@11: yading@11: /* skip over the padding to the beginning of the next frame */ yading@11: avio_skip(pb, offset - pkt->size - BURST_HEADER_SIZE); yading@11: yading@11: if (!s->nb_streams) { yading@11: /* first packet, create a stream */ yading@11: AVStream *st = avformat_new_stream(s, NULL); yading@11: if (!st) { yading@11: av_free_packet(pkt); yading@11: return AVERROR(ENOMEM); yading@11: } yading@11: st->codec->codec_type = AVMEDIA_TYPE_AUDIO; yading@11: st->codec->codec_id = codec_id; yading@11: } else if (codec_id != s->streams[0]->codec->codec_id) { yading@11: avpriv_report_missing_feature(s, "Codec change in IEC 61937"); yading@11: return AVERROR_PATCHWELCOME; yading@11: } yading@11: yading@11: if (!s->bit_rate && s->streams[0]->codec->sample_rate) yading@11: /* stream bitrate matches 16-bit stereo PCM bitrate for currently yading@11: supported codecs */ yading@11: s->bit_rate = 2 * 16 * s->streams[0]->codec->sample_rate; yading@11: yading@11: return 0; yading@11: } yading@11: yading@11: AVInputFormat ff_spdif_demuxer = { yading@11: .name = "spdif", yading@11: .long_name = NULL_IF_CONFIG_SMALL("IEC 61937 (compressed data in S/PDIF)"), yading@11: .read_probe = spdif_probe, yading@11: .read_header = spdif_read_header, yading@11: .read_packet = ff_spdif_read_packet, yading@11: .flags = AVFMT_GENERIC_INDEX, yading@11: };