LCOV - code coverage report
Current view: top level - libavformat - mmf.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 139 160 86.9 %
Date: 2017-12-14 19:11:59 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Yamaha SMAF format
       3             :  * Copyright (c) 2005 Vidar Madsen
       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             : #include "libavutil/channel_layout.h"
      23             : #include "avformat.h"
      24             : #include "avio_internal.h"
      25             : #include "internal.h"
      26             : #include "pcm.h"
      27             : #include "rawenc.h"
      28             : #include "riff.h"
      29             : 
      30             : typedef struct MMFContext {
      31             :     int64_t atrpos, atsqpos, awapos;
      32             :     int64_t data_end;
      33             :     int stereo;
      34             : } MMFContext;
      35             : 
      36             : static const int mmf_rates[] = { 4000, 8000, 11025, 22050, 44100 };
      37             : 
      38           2 : static int mmf_rate(int code)
      39             : {
      40           2 :     if ((code < 0) || (code > 4))
      41           0 :         return -1;
      42           2 :     return mmf_rates[code];
      43             : }
      44             : 
      45             : #if CONFIG_MMF_MUXER
      46           1 : static int mmf_rate_code(int rate)
      47             : {
      48             :     int i;
      49           5 :     for (i = 0; i < 5; i++)
      50           5 :         if (mmf_rates[i] == rate)
      51           1 :             return i;
      52           0 :     return -1;
      53             : }
      54             : 
      55             : /* Copy of end_tag() from avienc.c, but for big-endian chunk size */
      56           5 : static void end_tag_be(AVIOContext *pb, int64_t start)
      57             : {
      58             :     int64_t pos;
      59             : 
      60           5 :     pos = avio_tell(pb);
      61           5 :     avio_seek(pb, start - 4, SEEK_SET);
      62           5 :     avio_wb32(pb, (uint32_t)(pos - start));
      63           5 :     avio_seek(pb, pos, SEEK_SET);
      64           5 : }
      65             : 
      66           1 : static int mmf_write_header(AVFormatContext *s)
      67             : {
      68           1 :     MMFContext *mmf = s->priv_data;
      69           1 :     AVIOContext *pb = s->pb;
      70             :     int64_t pos;
      71             :     int rate;
      72           2 :     const char *version = s->flags & AVFMT_FLAG_BITEXACT ?
      73           1 :                           "VN:Lavf," :
      74             :                           "VN:"LIBAVFORMAT_IDENT",";
      75             : 
      76           1 :     rate = mmf_rate_code(s->streams[0]->codecpar->sample_rate);
      77           1 :     if (rate < 0) {
      78           0 :         av_log(s, AV_LOG_ERROR, "Unsupported sample rate %d, supported are 4000, 8000, 11025, 22050 and 44100\n",
      79           0 :                s->streams[0]->codecpar->sample_rate);
      80           0 :         return AVERROR(EINVAL);
      81             :     }
      82             : 
      83           1 :     mmf->stereo = s->streams[0]->codecpar->channels > 1;
      84           1 :     if (mmf->stereo &&
      85           0 :         s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
      86           0 :         av_log(s, AV_LOG_ERROR, "Yamaha SMAF stereo is experimental, "
      87             :                "add '-strict %d' if you want to use it.\n",
      88             :                FF_COMPLIANCE_EXPERIMENTAL);
      89           0 :         return AVERROR(EINVAL);
      90             :     }
      91             : 
      92           1 :     ffio_wfourcc(pb, "MMMD");
      93           1 :     avio_wb32(pb, 0);
      94           1 :     pos = ff_start_tag(pb, "CNTI");
      95           1 :     avio_w8(pb, 0); /* class */
      96           1 :     avio_w8(pb, 1); /* type */
      97           1 :     avio_w8(pb, 1); /* code type */
      98           1 :     avio_w8(pb, 0); /* status */
      99           1 :     avio_w8(pb, 0); /* counts */
     100           1 :     end_tag_be(pb, pos);
     101             : 
     102           1 :     pos = ff_start_tag(pb, "OPDA");
     103           1 :     avio_write(pb, version, strlen(version)); /* metadata ("ST:songtitle,VN:version,...") */
     104           1 :     end_tag_be(pb, pos);
     105             : 
     106           1 :     avio_write(pb, "ATR\x00", 4);
     107           1 :     avio_wb32(pb, 0);
     108           1 :     mmf->atrpos = avio_tell(pb);
     109           1 :     avio_w8(pb, 0); /* format type */
     110           1 :     avio_w8(pb, 0); /* sequence type */
     111           1 :     avio_w8(pb, (mmf->stereo << 7) | (1 << 4) | rate); /* (channel << 7) | (format << 4) | rate */
     112           1 :     avio_w8(pb, 0); /* wave base bit */
     113           1 :     avio_w8(pb, 2); /* time base d */
     114           1 :     avio_w8(pb, 2); /* time base g */
     115             : 
     116           1 :     ffio_wfourcc(pb, "Atsq");
     117           1 :     avio_wb32(pb, 16);
     118           1 :     mmf->atsqpos = avio_tell(pb);
     119             :     /* Will be filled on close */
     120           1 :     avio_write(pb, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16);
     121             : 
     122           1 :     mmf->awapos = ff_start_tag(pb, "Awa\x01");
     123             : 
     124           1 :     avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codecpar->sample_rate);
     125             : 
     126           1 :     avio_flush(pb);
     127             : 
     128           1 :     return 0;
     129             : }
     130             : 
     131             : /* Write a variable-length symbol */
     132           2 : static void put_varlength(AVIOContext *pb, int val)
     133             : {
     134           2 :     if (val < 128)
     135           0 :         avio_w8(pb, val);
     136             :     else {
     137           2 :         val -= 128;
     138           2 :         avio_w8(pb, 0x80 | val >> 7);
     139           2 :         avio_w8(pb, 0x7f & val);
     140             :     }
     141           2 : }
     142             : 
     143           1 : static int mmf_write_trailer(AVFormatContext *s)
     144             : {
     145           1 :     AVIOContext *pb = s->pb;
     146           1 :     MMFContext *mmf = s->priv_data;
     147             :     int64_t pos, size;
     148             :     int gatetime;
     149             : 
     150           1 :     if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) {
     151             :         /* Fill in length fields */
     152           1 :         end_tag_be(pb, mmf->awapos);
     153           1 :         end_tag_be(pb, mmf->atrpos);
     154           1 :         end_tag_be(pb, 8);
     155             : 
     156           1 :         pos  = avio_tell(pb);
     157           1 :         size = pos - mmf->awapos;
     158             : 
     159             :         /* Fill Atsq chunk */
     160           1 :         avio_seek(pb, mmf->atsqpos, SEEK_SET);
     161             : 
     162             :         /* "play wav" */
     163           1 :         avio_w8(pb, 0); /* start time */
     164           1 :         avio_w8(pb, (mmf->stereo << 6) | 1); /* (channel << 6) | wavenum */
     165           1 :         gatetime = size * 500 / s->streams[0]->codecpar->sample_rate;
     166           1 :         put_varlength(pb, gatetime); /* duration */
     167             : 
     168             :         /* "nop" */
     169           1 :         put_varlength(pb, gatetime); /* start time */
     170           1 :         avio_write(pb, "\xff\x00", 2); /* nop */
     171             : 
     172             :         /* "end of sequence" */
     173           1 :         avio_write(pb, "\x00\x00\x00\x00", 4);
     174             : 
     175           1 :         avio_seek(pb, pos, SEEK_SET);
     176             : 
     177           1 :         avio_flush(pb);
     178             :     }
     179           1 :     return 0;
     180             : }
     181             : #endif /* CONFIG_MMF_MUXER */
     182             : 
     183        6130 : static int mmf_probe(AVProbeData *p)
     184             : {
     185             :     /* check file header */
     186        6134 :     if (p->buf[0] == 'M' && p->buf[1] == 'M' &&
     187           8 :         p->buf[2] == 'M' && p->buf[3] == 'D' &&
     188           6 :         p->buf[8] == 'C' && p->buf[9] == 'N' &&
     189           4 :         p->buf[10] == 'T' && p->buf[11] == 'I')
     190           2 :         return AVPROBE_SCORE_MAX;
     191             :     else
     192        6128 :         return 0;
     193             : }
     194             : 
     195             : /* mmf input */
     196           2 : static int mmf_read_header(AVFormatContext *s)
     197             : {
     198           2 :     MMFContext *mmf = s->priv_data;
     199             :     unsigned int tag;
     200           2 :     AVIOContext *pb = s->pb;
     201             :     AVStream *st;
     202             :     int64_t size;
     203             :     int rate, params;
     204             : 
     205           2 :     tag = avio_rl32(pb);
     206           2 :     if (tag != MKTAG('M', 'M', 'M', 'D'))
     207           0 :         return AVERROR_INVALIDDATA;
     208           2 :     avio_skip(pb, 4); /* file_size */
     209             : 
     210             :     /* Skip some unused chunks that may or may not be present */
     211           4 :     for (;; avio_skip(pb, size)) {
     212          10 :         tag  = avio_rl32(pb);
     213           6 :         size = avio_rb32(pb);
     214           6 :         if (tag == MKTAG('C', 'N', 'T', 'I'))
     215           2 :             continue;
     216           4 :         if (tag == MKTAG('O', 'P', 'D', 'A'))
     217           2 :             continue;
     218           2 :         break;
     219             :     }
     220             : 
     221             :     /* Tag = "ATRx", where "x" = track number */
     222           2 :     if ((tag & 0xffffff) == MKTAG('M', 'T', 'R', 0)) {
     223           0 :         av_log(s, AV_LOG_ERROR, "MIDI like format found, unsupported\n");
     224           0 :         return AVERROR_PATCHWELCOME;
     225             :     }
     226           2 :     if ((tag & 0xffffff) != MKTAG('A', 'T', 'R', 0)) {
     227           0 :         av_log(s, AV_LOG_ERROR, "Unsupported SMAF chunk %08x\n", tag);
     228           0 :         return AVERROR_PATCHWELCOME;
     229             :     }
     230             : 
     231           2 :     avio_r8(pb); /* format type */
     232           2 :     avio_r8(pb); /* sequence type */
     233           2 :     params = avio_r8(pb); /* (channel << 7) | (format << 4) | rate */
     234           2 :     rate   = mmf_rate(params & 0x0f);
     235           2 :     if (rate < 0) {
     236           0 :         av_log(s, AV_LOG_ERROR, "Invalid sample rate\n");
     237           0 :         return AVERROR_INVALIDDATA;
     238             :     }
     239           2 :     avio_r8(pb); /* wave base bit */
     240           2 :     avio_r8(pb); /* time base d */
     241           2 :     avio_r8(pb); /* time base g */
     242             : 
     243             :     /* Skip some unused chunks that may or may not be present */
     244           2 :     for (;; avio_skip(pb, size)) {
     245           6 :         tag  = avio_rl32(pb);
     246           4 :         size = avio_rb32(pb);
     247           4 :         if (tag == MKTAG('A', 't', 's', 'q'))
     248           2 :             continue;
     249           2 :         if (tag == MKTAG('A', 's', 'p', 'I'))
     250           0 :             continue;
     251           2 :         break;
     252             :     }
     253             : 
     254             :     /* Make sure it's followed by an Awa chunk, aka wave data */
     255           2 :     if ((tag & 0xffffff) != MKTAG('A', 'w', 'a', 0)) {
     256           0 :         av_log(s, AV_LOG_ERROR, "Unexpected SMAF chunk %08x\n", tag);
     257           0 :         return AVERROR_INVALIDDATA;
     258             :     }
     259           2 :     mmf->data_end = avio_tell(pb) + size;
     260             : 
     261           2 :     st = avformat_new_stream(s, NULL);
     262           2 :     if (!st)
     263           0 :         return AVERROR(ENOMEM);
     264             : 
     265           2 :     st->codecpar->codec_type            = AVMEDIA_TYPE_AUDIO;
     266           2 :     st->codecpar->codec_id              = AV_CODEC_ID_ADPCM_YAMAHA;
     267           2 :     st->codecpar->sample_rate           = rate;
     268           2 :     st->codecpar->channels              = (params >> 7) + 1;
     269           2 :     st->codecpar->channel_layout        = params >> 7 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
     270           2 :     st->codecpar->bits_per_coded_sample = 4;
     271           4 :     st->codecpar->bit_rate              = st->codecpar->sample_rate *
     272           2 :                                           st->codecpar->bits_per_coded_sample;
     273             : 
     274           2 :     avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     275             : 
     276           2 :     return 0;
     277             : }
     278             : 
     279             : #define MAX_SIZE 4096
     280             : 
     281          58 : static int mmf_read_packet(AVFormatContext *s, AVPacket *pkt)
     282             : {
     283          58 :     MMFContext *mmf = s->priv_data;
     284             :     int64_t left, size;
     285             :     int ret;
     286             : 
     287          58 :     left = mmf->data_end - avio_tell(s->pb);
     288          58 :     size = FFMIN(left, MAX_SIZE);
     289          58 :     if (avio_feof(s->pb) || size <= 0)
     290          15 :         return AVERROR_EOF;
     291             : 
     292          43 :     ret = av_get_packet(s->pb, pkt, size);
     293          43 :     if (ret < 0)
     294           0 :         return ret;
     295             : 
     296          43 :     pkt->stream_index = 0;
     297             : 
     298          43 :     return ret;
     299             : }
     300             : 
     301             : #if CONFIG_MMF_DEMUXER
     302             : AVInputFormat ff_mmf_demuxer = {
     303             :     .name           = "mmf",
     304             :     .long_name      = NULL_IF_CONFIG_SMALL("Yamaha SMAF"),
     305             :     .priv_data_size = sizeof(MMFContext),
     306             :     .read_probe     = mmf_probe,
     307             :     .read_header    = mmf_read_header,
     308             :     .read_packet    = mmf_read_packet,
     309             :     .flags          = AVFMT_GENERIC_INDEX,
     310             : };
     311             : #endif
     312             : 
     313             : #if CONFIG_MMF_MUXER
     314             : AVOutputFormat ff_mmf_muxer = {
     315             :     .name           = "mmf",
     316             :     .long_name      = NULL_IF_CONFIG_SMALL("Yamaha SMAF"),
     317             :     .mime_type      = "application/vnd.smaf",
     318             :     .extensions     = "mmf",
     319             :     .priv_data_size = sizeof(MMFContext),
     320             :     .audio_codec    = AV_CODEC_ID_ADPCM_YAMAHA,
     321             :     .video_codec    = AV_CODEC_ID_NONE,
     322             :     .write_header   = mmf_write_header,
     323             :     .write_packet   = ff_raw_write_packet,
     324             :     .write_trailer  = mmf_write_trailer,
     325             : };
     326             : #endif

Generated by: LCOV version 1.13