LCOV - code coverage report
Current view: top level - libavformat - spdifdec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 60 128 46.9 %
Date: 2017-12-17 16:07:53 Functions: 4 5 80.0 %

          Line data    Source code
       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/ac3.h"
      31             : #include "libavcodec/adts_parser.h"
      32             : 
      33             : #include "avformat.h"
      34             : #include "spdif.h"
      35             : 
      36          45 : static int spdif_get_offset_and_codec(AVFormatContext *s,
      37             :                                       enum IEC61937DataType data_type,
      38             :                                       const char *buf, int *offset,
      39             :                                       enum AVCodecID *codec)
      40             : {
      41             :     uint32_t samples;
      42             :     uint8_t frames;
      43             :     int ret;
      44             : 
      45          45 :     switch (data_type & 0xff) {
      46          45 :     case IEC61937_AC3:
      47          45 :         *offset = AC3_FRAME_SIZE << 2;
      48          45 :         *codec = AV_CODEC_ID_AC3;
      49          45 :         break;
      50           0 :     case IEC61937_MPEG1_LAYER1:
      51           0 :         *offset = spdif_mpeg_pkt_offset[1][0];
      52           0 :         *codec = AV_CODEC_ID_MP1;
      53           0 :         break;
      54           0 :     case IEC61937_MPEG1_LAYER23:
      55           0 :         *offset = spdif_mpeg_pkt_offset[1][0];
      56           0 :         *codec = AV_CODEC_ID_MP3;
      57           0 :         break;
      58           0 :     case IEC61937_MPEG2_EXT:
      59           0 :         *offset = 4608;
      60           0 :         *codec = AV_CODEC_ID_MP3;
      61           0 :         break;
      62           0 :     case IEC61937_MPEG2_AAC:
      63           0 :         ret = av_adts_header_parse(buf, &samples, &frames);
      64           0 :         if (ret < 0) {
      65           0 :             if (s) /* be silent during a probe */
      66           0 :                 av_log(s, AV_LOG_ERROR, "Invalid AAC packet in IEC 61937\n");
      67           0 :             return ret;
      68             :         }
      69           0 :         *offset = samples << 2;
      70           0 :         *codec = AV_CODEC_ID_AAC;
      71           0 :         break;
      72           0 :     case IEC61937_MPEG2_LAYER1_LSF:
      73           0 :         *offset = spdif_mpeg_pkt_offset[0][0];
      74           0 :         *codec = AV_CODEC_ID_MP1;
      75           0 :         break;
      76           0 :     case IEC61937_MPEG2_LAYER2_LSF:
      77           0 :         *offset = spdif_mpeg_pkt_offset[0][1];
      78           0 :         *codec = AV_CODEC_ID_MP2;
      79           0 :         break;
      80           0 :     case IEC61937_MPEG2_LAYER3_LSF:
      81           0 :         *offset = spdif_mpeg_pkt_offset[0][2];
      82           0 :         *codec = AV_CODEC_ID_MP3;
      83           0 :         break;
      84           0 :     case IEC61937_DTS1:
      85           0 :         *offset = 2048;
      86           0 :         *codec = AV_CODEC_ID_DTS;
      87           0 :         break;
      88           0 :     case IEC61937_DTS2:
      89           0 :         *offset = 4096;
      90           0 :         *codec = AV_CODEC_ID_DTS;
      91           0 :         break;
      92           0 :     case IEC61937_DTS3:
      93           0 :         *offset = 8192;
      94           0 :         *codec = AV_CODEC_ID_DTS;
      95           0 :         break;
      96           0 :     default:
      97           0 :         if (s) { /* be silent during a probe */
      98           0 :             avpriv_request_sample(s, "Data type 0x%04x in IEC 61937",
      99             :                                   data_type);
     100             :         }
     101           0 :         return AVERROR_PATCHWELCOME;
     102             :     }
     103          45 :     return 0;
     104             : }
     105             : 
     106             : /* Largest offset between bursts we currently handle, i.e. AAC with
     107             :    samples = 4096 */
     108             : #define SPDIF_MAX_OFFSET 16384
     109             : 
     110        6130 : static int spdif_probe(AVProbeData *p)
     111             : {
     112             :     enum AVCodecID codec;
     113        6130 :     return ff_spdif_probe (p->buf, p->buf_size, &codec);
     114             : }
     115             : 
     116        6604 : int ff_spdif_probe(const uint8_t *p_buf, int buf_size, enum AVCodecID *codec)
     117             : {
     118        6604 :     const uint8_t *buf = p_buf;
     119        6604 :     const uint8_t *probe_end = p_buf + FFMIN(2 * SPDIF_MAX_OFFSET, buf_size - 1);
     120        6604 :     const uint8_t *expected_code = buf + 7;
     121        6604 :     uint32_t state = 0;
     122        6604 :     int sync_codes = 0;
     123        6604 :     int consecutive_codes = 0;
     124             :     int offset;
     125             : 
     126    82501846 :     for (; buf < probe_end; buf++) {
     127    82495244 :         state = (state << 8) | *buf;
     128             : 
     129    82495244 :         if (state == (AV_BSWAP16C(SYNCWORD1) << 16 | AV_BSWAP16C(SYNCWORD2))
     130           4 :                 && buf[1] < 0x37) {
     131           4 :             sync_codes++;
     132             : 
     133           4 :             if (buf == expected_code) {
     134           2 :                 if (++consecutive_codes >= 2)
     135           1 :                     return AVPROBE_SCORE_MAX;
     136             :             } else
     137           2 :                 consecutive_codes = 0;
     138             : 
     139           3 :             if (buf + 4 + AV_AAC_ADTS_HEADER_SIZE > p_buf + buf_size)
     140           0 :                 break;
     141             : 
     142             :             /* continue probing to find more sync codes */
     143           3 :             probe_end = FFMIN(buf + SPDIF_MAX_OFFSET, p_buf + buf_size - 1);
     144             : 
     145             :             /* skip directly to the next sync code */
     146           3 :             if (!spdif_get_offset_and_codec(NULL, (buf[2] << 8) | buf[1],
     147           3 :                                             &buf[5], &offset, codec)) {
     148           3 :                 if (buf + offset >= p_buf + buf_size)
     149           1 :                     break;
     150           2 :                 expected_code = buf + offset;
     151           2 :                 buf = expected_code - 7;
     152             :             }
     153             :         }
     154             :     }
     155             : 
     156        6603 :     if (!sync_codes)
     157        6602 :         return 0;
     158             : 
     159           1 :     if (sync_codes >= 6)
     160             :         /* good amount of sync codes but with unexpected offsets */
     161           0 :         return AVPROBE_SCORE_EXTENSION;
     162             : 
     163             :     /* some sync codes were found */
     164           1 :     return AVPROBE_SCORE_EXTENSION / 4;
     165             : }
     166             : 
     167           0 : static int spdif_read_header(AVFormatContext *s)
     168             : {
     169           0 :     s->ctx_flags |= AVFMTCTX_NOHEADER;
     170           0 :     return 0;
     171             : }
     172             : 
     173          44 : int ff_spdif_read_packet(AVFormatContext *s, AVPacket *pkt)
     174             : {
     175          44 :     AVIOContext *pb = s->pb;
     176             :     enum IEC61937DataType data_type;
     177             :     enum AVCodecID codec_id;
     178          44 :     uint32_t state = 0;
     179             :     int pkt_size_bits, offset, ret;
     180             : 
     181         256 :     while (state != (AV_BSWAP16C(SYNCWORD1) << 16 | AV_BSWAP16C(SYNCWORD2))) {
     182         170 :         state = (state << 8) | avio_r8(pb);
     183         170 :         if (avio_feof(pb))
     184           2 :             return AVERROR_EOF;
     185             :     }
     186             : 
     187          42 :     data_type = avio_rl16(pb);
     188          42 :     pkt_size_bits = avio_rl16(pb);
     189             : 
     190          42 :     if (pkt_size_bits % 16)
     191           0 :         avpriv_request_sample(s, "Packet not ending at a 16-bit boundary");
     192             : 
     193          42 :     ret = av_new_packet(pkt, FFALIGN(pkt_size_bits, 16) >> 3);
     194          42 :     if (ret)
     195           0 :         return ret;
     196             : 
     197          42 :     pkt->pos = avio_tell(pb) - BURST_HEADER_SIZE;
     198             : 
     199          42 :     if (avio_read(pb, pkt->data, pkt->size) < pkt->size) {
     200           0 :         av_packet_unref(pkt);
     201           0 :         return AVERROR_EOF;
     202             :     }
     203          42 :     ff_spdif_bswap_buf16((uint16_t *)pkt->data, (uint16_t *)pkt->data, pkt->size >> 1);
     204             : 
     205          42 :     ret = spdif_get_offset_and_codec(s, data_type, pkt->data,
     206             :                                      &offset, &codec_id);
     207          42 :     if (ret) {
     208           0 :         av_packet_unref(pkt);
     209           0 :         return ret;
     210             :     }
     211             : 
     212             :     /* skip over the padding to the beginning of the next frame */
     213          42 :     avio_skip(pb, offset - pkt->size - BURST_HEADER_SIZE);
     214             : 
     215          42 :     if (!s->nb_streams) {
     216             :         /* first packet, create a stream */
     217           0 :         AVStream *st = avformat_new_stream(s, NULL);
     218           0 :         if (!st) {
     219           0 :             av_packet_unref(pkt);
     220           0 :             return AVERROR(ENOMEM);
     221             :         }
     222           0 :         st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
     223           0 :         st->codecpar->codec_id = codec_id;
     224          42 :     } else if (codec_id != s->streams[0]->codecpar->codec_id) {
     225           0 :         avpriv_report_missing_feature(s, "Codec change in IEC 61937");
     226           0 :         return AVERROR_PATCHWELCOME;
     227             :     }
     228             : 
     229          42 :     if (!s->bit_rate && s->streams[0]->codecpar->sample_rate)
     230             :         /* stream bitrate matches 16-bit stereo PCM bitrate for currently
     231             :            supported codecs */
     232           1 :         s->bit_rate = 2 * 16 * s->streams[0]->codecpar->sample_rate;
     233             : 
     234          42 :     return 0;
     235             : }
     236             : 
     237             : AVInputFormat ff_spdif_demuxer = {
     238             :     .name           = "spdif",
     239             :     .long_name      = NULL_IF_CONFIG_SMALL("IEC 61937 (compressed data in S/PDIF)"),
     240             :     .read_probe     = spdif_probe,
     241             :     .read_header    = spdif_read_header,
     242             :     .read_packet    = ff_spdif_read_packet,
     243             :     .flags          = AVFMT_GENERIC_INDEX,
     244             : };

Generated by: LCOV version 1.13