LCOV - code coverage report
Current view: top level - libavformat - mpc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 78 115 67.8 %
Date: 2017-12-14 19:11:59 Functions: 4 5 80.0 %

          Line data    Source code
       1             : /*
       2             :  * Musepack demuxer
       3             :  * Copyright (c) 2006 Konstantin Shishkov
       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             : 
      24             : #include "avformat.h"
      25             : #include "internal.h"
      26             : #include "apetag.h"
      27             : #include "id3v1.h"
      28             : #include "libavutil/dict.h"
      29             : 
      30             : #define MPC_FRAMESIZE  1152
      31             : #define DELAY_FRAMES   32
      32             : 
      33             : static const int mpc_rate[4] = { 44100, 48000, 37800, 32000 };
      34             : typedef struct MPCFrame {
      35             :     int64_t pos;
      36             :     int size, skip;
      37             : }MPCFrame;
      38             : 
      39             : typedef struct MPCContext {
      40             :     int ver;
      41             :     uint32_t curframe, lastframe;
      42             :     uint32_t fcount;
      43             :     MPCFrame *frames;
      44             :     int curbits;
      45             :     int frames_noted;
      46             : } MPCContext;
      47             : 
      48        6130 : static int mpc_probe(AVProbeData *p)
      49             : {
      50        6130 :     const uint8_t *d = p->buf;
      51        6130 :     if (d[0] == 'M' && d[1] == 'P' && d[2] == '+' && (d[3] == 0x17 || d[3] == 0x7))
      52           2 :         return AVPROBE_SCORE_MAX;
      53        6128 :     return 0;
      54             : }
      55             : 
      56           2 : static int mpc_read_header(AVFormatContext *s)
      57             : {
      58           2 :     MPCContext *c = s->priv_data;
      59             :     AVStream *st;
      60             : 
      61           2 :     if(avio_rl24(s->pb) != MKTAG('M', 'P', '+', 0)){
      62           0 :         av_log(s, AV_LOG_ERROR, "Not a Musepack file\n");
      63           0 :         return AVERROR_INVALIDDATA;
      64             :     }
      65           2 :     c->ver = avio_r8(s->pb);
      66           2 :     if(c->ver != 0x07 && c->ver != 0x17){
      67           0 :         av_log(s, AV_LOG_ERROR, "Can demux Musepack SV7, got version %02X\n", c->ver);
      68           0 :         return AVERROR_INVALIDDATA;
      69             :     }
      70           2 :     c->fcount = avio_rl32(s->pb);
      71           2 :     if((int64_t)c->fcount * sizeof(MPCFrame) >= UINT_MAX){
      72           0 :         av_log(s, AV_LOG_ERROR, "Too many frames, seeking is not possible\n");
      73           0 :         return AVERROR_INVALIDDATA;
      74             :     }
      75           2 :     if(c->fcount){
      76           2 :         c->frames = av_malloc(c->fcount * sizeof(MPCFrame));
      77           2 :         if(!c->frames){
      78           0 :             av_log(s, AV_LOG_ERROR, "Cannot allocate seektable\n");
      79           0 :             return AVERROR(ENOMEM);
      80             :         }
      81             :     }else{
      82           0 :         av_log(s, AV_LOG_WARNING, "Container reports no frames\n");
      83             :     }
      84           2 :     c->curframe = 0;
      85           2 :     c->lastframe = -1;
      86           2 :     c->curbits = 8;
      87           2 :     c->frames_noted = 0;
      88             : 
      89           2 :     st = avformat_new_stream(s, NULL);
      90           2 :     if (!st)
      91           0 :         return AVERROR(ENOMEM);
      92           2 :     st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
      93           2 :     st->codecpar->codec_id = AV_CODEC_ID_MUSEPACK7;
      94           2 :     st->codecpar->channels = 2;
      95           2 :     st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
      96           2 :     st->codecpar->bits_per_coded_sample = 16;
      97             : 
      98           2 :     if (ff_get_extradata(s, st->codecpar, s->pb, 16) < 0)
      99           0 :         return AVERROR(ENOMEM);
     100           2 :     st->codecpar->sample_rate = mpc_rate[st->codecpar->extradata[2] & 3];
     101           2 :     avpriv_set_pts_info(st, 32, MPC_FRAMESIZE, st->codecpar->sample_rate);
     102             :     /* scan for seekpoints */
     103           2 :     st->start_time = 0;
     104           2 :     st->duration = c->fcount;
     105             : 
     106             :     /* try to read APE tags */
     107           2 :     if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) {
     108           2 :         int64_t pos = avio_tell(s->pb);
     109           2 :         ff_ape_parse_tag(s);
     110           2 :         if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX))
     111           0 :             ff_id3v1_read(s);
     112           2 :         avio_seek(s->pb, pos, SEEK_SET);
     113             :     }
     114             : 
     115           2 :     return 0;
     116             : }
     117             : 
     118         914 : static int mpc_read_packet(AVFormatContext *s, AVPacket *pkt)
     119             : {
     120         914 :     MPCContext *c = s->priv_data;
     121         914 :     int ret, size, size2, curbits, cur = c->curframe;
     122             :     unsigned tmp;
     123             :     int64_t pos;
     124             : 
     125         914 :     if (c->curframe >= c->fcount && c->fcount)
     126           2 :         return AVERROR_EOF;
     127             : 
     128         912 :     if(c->curframe != c->lastframe + 1){
     129           0 :         avio_seek(s->pb, c->frames[c->curframe].pos, SEEK_SET);
     130           0 :         c->curbits = c->frames[c->curframe].skip;
     131             :     }
     132         912 :     c->lastframe = c->curframe;
     133         912 :     c->curframe++;
     134         912 :     curbits = c->curbits;
     135         912 :     pos = avio_tell(s->pb);
     136         912 :     tmp = avio_rl32(s->pb);
     137         912 :     if(curbits <= 12){
     138         368 :         size2 = (tmp >> (12 - curbits)) & 0xFFFFF;
     139             :     }else{
     140         544 :         size2 = (tmp << (curbits - 12) | avio_rl32(s->pb) >> (44 - curbits)) & 0xFFFFF;
     141             :     }
     142         912 :     curbits += 20;
     143         912 :     avio_seek(s->pb, pos, SEEK_SET);
     144             : 
     145         912 :     size = ((size2 + curbits + 31) & ~31) >> 3;
     146         912 :     if(cur == c->frames_noted && c->fcount){
     147         912 :         c->frames[cur].pos = pos;
     148         912 :         c->frames[cur].size = size;
     149         912 :         c->frames[cur].skip = curbits - 20;
     150         912 :         av_add_index_entry(s->streams[0], cur, cur, size, 0, AVINDEX_KEYFRAME);
     151         912 :         c->frames_noted++;
     152             :     }
     153         912 :     c->curbits = (curbits + size2) & 0x1F;
     154             : 
     155         912 :     if ((ret = av_new_packet(pkt, size + 4)) < 0)
     156           0 :         return ret;
     157             : 
     158         912 :     pkt->data[0] = curbits;
     159         912 :     pkt->data[1] = (c->curframe > c->fcount) && c->fcount;
     160         912 :     pkt->data[2] = 0;
     161         912 :     pkt->data[3] = 0;
     162             : 
     163         912 :     pkt->stream_index = 0;
     164         912 :     pkt->pts = cur;
     165         912 :     ret = avio_read(s->pb, pkt->data + 4, size);
     166         912 :     if(c->curbits)
     167         888 :         avio_seek(s->pb, -4, SEEK_CUR);
     168         912 :     if(ret < size){
     169           0 :         av_packet_unref(pkt);
     170           0 :         return ret < 0 ? ret : AVERROR(EIO);
     171             :     }
     172         912 :     pkt->size = ret + 4;
     173             : 
     174         912 :     return 0;
     175             : }
     176             : 
     177           2 : static int mpc_read_close(AVFormatContext *s)
     178             : {
     179           2 :     MPCContext *c = s->priv_data;
     180             : 
     181           2 :     av_freep(&c->frames);
     182           2 :     return 0;
     183             : }
     184             : 
     185             : /**
     186             :  * Seek to the given position
     187             :  * If position is unknown but is within the limits of file
     188             :  * then packets are skipped unless desired position is reached
     189             :  *
     190             :  * Also this function makes use of the fact that timestamp == frameno
     191             :  */
     192           0 : static int mpc_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
     193             : {
     194           0 :     AVStream *st = s->streams[stream_index];
     195           0 :     MPCContext *c = s->priv_data;
     196           0 :     AVPacket pkt1, *pkt = &pkt1;
     197             :     int ret;
     198           0 :     int index = av_index_search_timestamp(st, FFMAX(timestamp - DELAY_FRAMES, 0), flags);
     199             :     uint32_t lastframe;
     200             : 
     201             :     /* if found, seek there */
     202           0 :     if (index >= 0 && st->index_entries[st->nb_index_entries-1].timestamp >= timestamp - DELAY_FRAMES){
     203           0 :         c->curframe = st->index_entries[index].pos;
     204           0 :         return 0;
     205             :     }
     206             :     /* if timestamp is out of bounds, return error */
     207           0 :     if(timestamp < 0 || timestamp >= c->fcount)
     208           0 :         return -1;
     209           0 :     timestamp -= DELAY_FRAMES;
     210             :     /* seek to the furthest known position and read packets until
     211             :        we reach desired position */
     212           0 :     lastframe = c->curframe;
     213           0 :     if(c->frames_noted) c->curframe = c->frames_noted - 1;
     214           0 :     while(c->curframe < timestamp){
     215           0 :         ret = av_read_frame(s, pkt);
     216           0 :         if (ret < 0){
     217           0 :             c->curframe = lastframe;
     218           0 :             return ret;
     219             :         }
     220           0 :         av_packet_unref(pkt);
     221             :     }
     222           0 :     return 0;
     223             : }
     224             : 
     225             : 
     226             : AVInputFormat ff_mpc_demuxer = {
     227             :     .name           = "mpc",
     228             :     .long_name      = NULL_IF_CONFIG_SMALL("Musepack"),
     229             :     .priv_data_size = sizeof(MPCContext),
     230             :     .read_probe     = mpc_probe,
     231             :     .read_header    = mpc_read_header,
     232             :     .read_packet    = mpc_read_packet,
     233             :     .read_close     = mpc_read_close,
     234             :     .read_seek      = mpc_read_seek,
     235             :     .extensions     = "mpc",
     236             : };

Generated by: LCOV version 1.13