LCOV - code coverage report
Current view: top level - src/libavformat - ape.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 171 213 80.3 %
Date: 2017-06-24 07:01:58 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /*
       2             :  * Monkey's Audio APE demuxer
       3             :  * Copyright (c) 2007 Benjamin Zores <ben@geexbox.org>
       4             :  *  based upon libdemac from Dave Chapman.
       5             :  *
       6             :  * This file is part of FFmpeg.
       7             :  *
       8             :  * FFmpeg is free software; you can redistribute it and/or
       9             :  * modify it under the terms of the GNU Lesser General Public
      10             :  * License as published by the Free Software Foundation; either
      11             :  * version 2.1 of the License, or (at your option) any later version.
      12             :  *
      13             :  * FFmpeg is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :  * Lesser General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public
      19             :  * License along with FFmpeg; if not, write to the Free Software
      20             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      21             :  */
      22             : 
      23             : #include <stdio.h>
      24             : 
      25             : #include "libavutil/intreadwrite.h"
      26             : #include "avformat.h"
      27             : #include "internal.h"
      28             : #include "apetag.h"
      29             : 
      30             : /* The earliest and latest file formats supported by this library */
      31             : #define APE_MIN_VERSION 3800
      32             : #define APE_MAX_VERSION 3990
      33             : 
      34             : #define MAC_FORMAT_FLAG_8_BIT                 1 // is 8-bit [OBSOLETE]
      35             : #define MAC_FORMAT_FLAG_CRC                   2 // uses the new CRC32 error detection [OBSOLETE]
      36             : #define MAC_FORMAT_FLAG_HAS_PEAK_LEVEL        4 // uint32 nPeakLevel after the header [OBSOLETE]
      37             : #define MAC_FORMAT_FLAG_24_BIT                8 // is 24-bit [OBSOLETE]
      38             : #define MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS    16 // has the number of seek elements after the peak level
      39             : #define MAC_FORMAT_FLAG_CREATE_WAV_HEADER    32 // create the wave header on decompression (not stored)
      40             : 
      41             : #define APE_EXTRADATA_SIZE 6
      42             : 
      43             : typedef struct APEFrame {
      44             :     int64_t pos;
      45             :     int nblocks;
      46             :     int size;
      47             :     int skip;
      48             :     int64_t pts;
      49             : } APEFrame;
      50             : 
      51             : typedef struct APEContext {
      52             :     /* Derived fields */
      53             :     uint32_t junklength;
      54             :     uint32_t firstframe;
      55             :     uint32_t totalsamples;
      56             :     int currentframe;
      57             :     APEFrame *frames;
      58             : 
      59             :     /* Info from Descriptor Block */
      60             :     int16_t fileversion;
      61             :     int16_t padding1;
      62             :     uint32_t descriptorlength;
      63             :     uint32_t headerlength;
      64             :     uint32_t seektablelength;
      65             :     uint32_t wavheaderlength;
      66             :     uint32_t audiodatalength;
      67             :     uint32_t audiodatalength_high;
      68             :     uint32_t wavtaillength;
      69             :     uint8_t md5[16];
      70             : 
      71             :     /* Info from Header Block */
      72             :     uint16_t compressiontype;
      73             :     uint16_t formatflags;
      74             :     uint32_t blocksperframe;
      75             :     uint32_t finalframeblocks;
      76             :     uint32_t totalframes;
      77             :     uint16_t bps;
      78             :     uint16_t channels;
      79             :     uint32_t samplerate;
      80             : 
      81             :     /* Seektable */
      82             :     uint32_t *seektable;
      83             :     uint8_t  *bittable;
      84             : } APEContext;
      85             : 
      86        5965 : static int ape_probe(AVProbeData * p)
      87             : {
      88        5965 :     int version = AV_RL16(p->buf+4);
      89        5965 :     if (AV_RL32(p->buf) != MKTAG('M', 'A', 'C', ' '))
      90        5951 :         return 0;
      91             : 
      92          14 :     if (version < APE_MIN_VERSION || version > APE_MAX_VERSION)
      93           0 :         return AVPROBE_SCORE_MAX/4;
      94             : 
      95          14 :     return AVPROBE_SCORE_MAX;
      96             : }
      97             : 
      98          14 : static void ape_dumpinfo(AVFormatContext * s, APEContext * ape_ctx)
      99             : {
     100             : #ifdef DEBUG
     101             :     int i;
     102             : 
     103             :     av_log(s, AV_LOG_DEBUG, "Descriptor Block:\n\n");
     104             :     av_log(s, AV_LOG_DEBUG, "fileversion          = %"PRId16"\n", ape_ctx->fileversion);
     105             :     av_log(s, AV_LOG_DEBUG, "descriptorlength     = %"PRIu32"\n", ape_ctx->descriptorlength);
     106             :     av_log(s, AV_LOG_DEBUG, "headerlength         = %"PRIu32"\n", ape_ctx->headerlength);
     107             :     av_log(s, AV_LOG_DEBUG, "seektablelength      = %"PRIu32"\n", ape_ctx->seektablelength);
     108             :     av_log(s, AV_LOG_DEBUG, "wavheaderlength      = %"PRIu32"\n", ape_ctx->wavheaderlength);
     109             :     av_log(s, AV_LOG_DEBUG, "audiodatalength      = %"PRIu32"\n", ape_ctx->audiodatalength);
     110             :     av_log(s, AV_LOG_DEBUG, "audiodatalength_high = %"PRIu32"\n", ape_ctx->audiodatalength_high);
     111             :     av_log(s, AV_LOG_DEBUG, "wavtaillength        = %"PRIu32"\n", ape_ctx->wavtaillength);
     112             :     av_log(s, AV_LOG_DEBUG, "md5                  = ");
     113             :     for (i = 0; i < 16; i++)
     114             :          av_log(s, AV_LOG_DEBUG, "%02x", ape_ctx->md5[i]);
     115             :     av_log(s, AV_LOG_DEBUG, "\n");
     116             : 
     117             :     av_log(s, AV_LOG_DEBUG, "\nHeader Block:\n\n");
     118             : 
     119             :     av_log(s, AV_LOG_DEBUG, "compressiontype      = %"PRIu16"\n", ape_ctx->compressiontype);
     120             :     av_log(s, AV_LOG_DEBUG, "formatflags          = %"PRIu16"\n", ape_ctx->formatflags);
     121             :     av_log(s, AV_LOG_DEBUG, "blocksperframe       = %"PRIu32"\n", ape_ctx->blocksperframe);
     122             :     av_log(s, AV_LOG_DEBUG, "finalframeblocks     = %"PRIu32"\n", ape_ctx->finalframeblocks);
     123             :     av_log(s, AV_LOG_DEBUG, "totalframes          = %"PRIu32"\n", ape_ctx->totalframes);
     124             :     av_log(s, AV_LOG_DEBUG, "bps                  = %"PRIu16"\n", ape_ctx->bps);
     125             :     av_log(s, AV_LOG_DEBUG, "channels             = %"PRIu16"\n", ape_ctx->channels);
     126             :     av_log(s, AV_LOG_DEBUG, "samplerate           = %"PRIu32"\n", ape_ctx->samplerate);
     127             : 
     128             :     av_log(s, AV_LOG_DEBUG, "\nSeektable\n\n");
     129             :     if ((ape_ctx->seektablelength / sizeof(uint32_t)) != ape_ctx->totalframes) {
     130             :         av_log(s, AV_LOG_DEBUG, "No seektable\n");
     131             :     } else {
     132             :         for (i = 0; i < ape_ctx->seektablelength / sizeof(uint32_t); i++) {
     133             :             if (i < ape_ctx->totalframes - 1) {
     134             :                 av_log(s, AV_LOG_DEBUG, "%8d   %"PRIu32" (%"PRIu32" bytes)",
     135             :                        i, ape_ctx->seektable[i],
     136             :                        ape_ctx->seektable[i + 1] - ape_ctx->seektable[i]);
     137             :                 if (ape_ctx->bittable)
     138             :                     av_log(s, AV_LOG_DEBUG, " + %2d bits\n",
     139             :                            ape_ctx->bittable[i]);
     140             :                 av_log(s, AV_LOG_DEBUG, "\n");
     141             :             } else {
     142             :                 av_log(s, AV_LOG_DEBUG, "%8d   %"PRIu32"\n", i, ape_ctx->seektable[i]);
     143             :             }
     144             :         }
     145             :     }
     146             : 
     147             :     av_log(s, AV_LOG_DEBUG, "\nFrames\n\n");
     148             :     for (i = 0; i < ape_ctx->totalframes; i++)
     149             :         av_log(s, AV_LOG_DEBUG, "%8d   %8"PRId64" %8d (%d samples)\n", i,
     150             :                ape_ctx->frames[i].pos, ape_ctx->frames[i].size,
     151             :                ape_ctx->frames[i].nblocks);
     152             : 
     153             :     av_log(s, AV_LOG_DEBUG, "\nCalculated information:\n\n");
     154             :     av_log(s, AV_LOG_DEBUG, "junklength           = %"PRIu32"\n", ape_ctx->junklength);
     155             :     av_log(s, AV_LOG_DEBUG, "firstframe           = %"PRIu32"\n", ape_ctx->firstframe);
     156             :     av_log(s, AV_LOG_DEBUG, "totalsamples         = %"PRIu32"\n", ape_ctx->totalsamples);
     157             : #endif
     158          14 : }
     159             : 
     160          14 : static int ape_read_header(AVFormatContext * s)
     161             : {
     162          14 :     AVIOContext *pb = s->pb;
     163          14 :     APEContext *ape = s->priv_data;
     164             :     AVStream *st;
     165             :     uint32_t tag;
     166             :     int i;
     167          14 :     int total_blocks, final_size = 0;
     168             :     int64_t pts, file_size;
     169             : 
     170             :     /* Skip any leading junk such as id3v2 tags */
     171          14 :     ape->junklength = avio_tell(pb);
     172             : 
     173          14 :     tag = avio_rl32(pb);
     174          14 :     if (tag != MKTAG('M', 'A', 'C', ' '))
     175           0 :         return AVERROR_INVALIDDATA;
     176             : 
     177          14 :     ape->fileversion = avio_rl16(pb);
     178             : 
     179          14 :     if (ape->fileversion < APE_MIN_VERSION || ape->fileversion > APE_MAX_VERSION) {
     180           0 :         av_log(s, AV_LOG_ERROR, "Unsupported file version - %d.%02d\n",
     181           0 :                ape->fileversion / 1000, (ape->fileversion % 1000) / 10);
     182           0 :         return AVERROR_PATCHWELCOME;
     183             :     }
     184             : 
     185          14 :     if (ape->fileversion >= 3980) {
     186           2 :         ape->padding1             = avio_rl16(pb);
     187           2 :         ape->descriptorlength     = avio_rl32(pb);
     188           2 :         ape->headerlength         = avio_rl32(pb);
     189           2 :         ape->seektablelength      = avio_rl32(pb);
     190           2 :         ape->wavheaderlength      = avio_rl32(pb);
     191           2 :         ape->audiodatalength      = avio_rl32(pb);
     192           2 :         ape->audiodatalength_high = avio_rl32(pb);
     193           2 :         ape->wavtaillength        = avio_rl32(pb);
     194           2 :         avio_read(pb, ape->md5, 16);
     195             : 
     196             :         /* Skip any unknown bytes at the end of the descriptor.
     197             :            This is for future compatibility */
     198           2 :         if (ape->descriptorlength > 52)
     199           0 :             avio_skip(pb, ape->descriptorlength - 52);
     200             : 
     201             :         /* Read header data */
     202           2 :         ape->compressiontype      = avio_rl16(pb);
     203           2 :         ape->formatflags          = avio_rl16(pb);
     204           2 :         ape->blocksperframe       = avio_rl32(pb);
     205           2 :         ape->finalframeblocks     = avio_rl32(pb);
     206           2 :         ape->totalframes          = avio_rl32(pb);
     207           2 :         ape->bps                  = avio_rl16(pb);
     208           2 :         ape->channels             = avio_rl16(pb);
     209           2 :         ape->samplerate           = avio_rl32(pb);
     210             :     } else {
     211          12 :         ape->descriptorlength = 0;
     212          12 :         ape->headerlength = 32;
     213             : 
     214          12 :         ape->compressiontype      = avio_rl16(pb);
     215          12 :         ape->formatflags          = avio_rl16(pb);
     216          12 :         ape->channels             = avio_rl16(pb);
     217          12 :         ape->samplerate           = avio_rl32(pb);
     218          12 :         ape->wavheaderlength      = avio_rl32(pb);
     219          12 :         ape->wavtaillength        = avio_rl32(pb);
     220          12 :         ape->totalframes          = avio_rl32(pb);
     221          12 :         ape->finalframeblocks     = avio_rl32(pb);
     222             : 
     223          12 :         if (ape->formatflags & MAC_FORMAT_FLAG_HAS_PEAK_LEVEL) {
     224          12 :             avio_skip(pb, 4); /* Skip the peak level */
     225          12 :             ape->headerlength += 4;
     226             :         }
     227             : 
     228          12 :         if (ape->formatflags & MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS) {
     229           6 :             ape->seektablelength = avio_rl32(pb);
     230           6 :             ape->headerlength += 4;
     231           6 :             ape->seektablelength *= sizeof(int32_t);
     232             :         } else
     233           6 :             ape->seektablelength = ape->totalframes * sizeof(int32_t);
     234             : 
     235          12 :         if (ape->formatflags & MAC_FORMAT_FLAG_8_BIT)
     236           0 :             ape->bps = 8;
     237          12 :         else if (ape->formatflags & MAC_FORMAT_FLAG_24_BIT)
     238           0 :             ape->bps = 24;
     239             :         else
     240          12 :             ape->bps = 16;
     241             : 
     242          12 :         if (ape->fileversion >= 3950)
     243           0 :             ape->blocksperframe = 73728 * 4;
     244          12 :         else if (ape->fileversion >= 3900 || (ape->fileversion >= 3800  && ape->compressiontype >= 4000))
     245           9 :             ape->blocksperframe = 73728;
     246             :         else
     247           3 :             ape->blocksperframe = 9216;
     248             : 
     249             :         /* Skip any stored wav header */
     250          12 :         if (!(ape->formatflags & MAC_FORMAT_FLAG_CREATE_WAV_HEADER))
     251          12 :             avio_skip(pb, ape->wavheaderlength);
     252             :     }
     253             : 
     254          14 :     if(!ape->totalframes){
     255           0 :         av_log(s, AV_LOG_ERROR, "No frames in the file!\n");
     256           0 :         return AVERROR(EINVAL);
     257             :     }
     258          14 :     if(ape->totalframes > UINT_MAX / sizeof(APEFrame)){
     259           0 :         av_log(s, AV_LOG_ERROR, "Too many frames: %"PRIu32"\n",
     260             :                ape->totalframes);
     261           0 :         return AVERROR_INVALIDDATA;
     262             :     }
     263          14 :     if (ape->seektablelength / sizeof(*ape->seektable) < ape->totalframes) {
     264           0 :         av_log(s, AV_LOG_ERROR,
     265             :                "Number of seek entries is less than number of frames: %"SIZE_SPECIFIER" vs. %"PRIu32"\n",
     266           0 :                ape->seektablelength / sizeof(*ape->seektable), ape->totalframes);
     267           0 :         return AVERROR_INVALIDDATA;
     268             :     }
     269          14 :     ape->frames       = av_malloc_array(ape->totalframes, sizeof(APEFrame));
     270          14 :     if(!ape->frames)
     271           0 :         return AVERROR(ENOMEM);
     272          14 :     ape->firstframe   = ape->junklength + ape->descriptorlength + ape->headerlength + ape->seektablelength + ape->wavheaderlength;
     273          14 :     if (ape->fileversion < 3810)
     274           2 :         ape->firstframe += ape->totalframes;
     275          14 :     ape->currentframe = 0;
     276             : 
     277             : 
     278          14 :     ape->totalsamples = ape->finalframeblocks;
     279          14 :     if (ape->totalframes > 1)
     280          14 :         ape->totalsamples += ape->blocksperframe * (ape->totalframes - 1);
     281             : 
     282          14 :     if (ape->seektablelength > 0) {
     283          14 :         ape->seektable = av_mallocz(ape->seektablelength);
     284          14 :         if (!ape->seektable)
     285           0 :             return AVERROR(ENOMEM);
     286        1291 :         for (i = 0; i < ape->seektablelength / sizeof(uint32_t) && !pb->eof_reached; i++)
     287        1277 :             ape->seektable[i] = avio_rl32(pb);
     288          14 :         if (ape->fileversion < 3810) {
     289           2 :             ape->bittable = av_mallocz(ape->totalframes);
     290           2 :             if (!ape->bittable)
     291           0 :                 return AVERROR(ENOMEM);
     292         329 :             for (i = 0; i < ape->totalframes && !pb->eof_reached; i++)
     293         327 :                 ape->bittable[i] = avio_r8(pb);
     294             :         }
     295          14 :         if (pb->eof_reached)
     296           0 :             av_log(s, AV_LOG_WARNING, "File truncated\n");
     297             :     }
     298             : 
     299          14 :     ape->frames[0].pos     = ape->firstframe;
     300          14 :     ape->frames[0].nblocks = ape->blocksperframe;
     301          14 :     ape->frames[0].skip    = 0;
     302        1277 :     for (i = 1; i < ape->totalframes; i++) {
     303        1263 :         ape->frames[i].pos      = ape->seektable[i] + ape->junklength;
     304        1263 :         ape->frames[i].nblocks  = ape->blocksperframe;
     305        1263 :         ape->frames[i - 1].size = ape->frames[i].pos - ape->frames[i - 1].pos;
     306        1263 :         ape->frames[i].skip     = (ape->frames[i].pos - ape->frames[0].pos) & 3;
     307             :     }
     308          14 :     ape->frames[ape->totalframes - 1].nblocks = ape->finalframeblocks;
     309             :     /* calculate final packet size from total file size, if available */
     310          14 :     file_size = avio_size(pb);
     311          14 :     if (file_size > 0) {
     312          28 :         final_size = file_size - ape->frames[ape->totalframes - 1].pos -
     313          14 :                      ape->wavtaillength;
     314          14 :         final_size -= final_size & 3;
     315             :     }
     316          14 :     if (file_size <= 0 || final_size <= 0)
     317          14 :         final_size = ape->finalframeblocks * 8;
     318          14 :     ape->frames[ape->totalframes - 1].size = final_size;
     319             : 
     320        1291 :     for (i = 0; i < ape->totalframes; i++) {
     321        1277 :         if(ape->frames[i].skip){
     322         689 :             ape->frames[i].pos  -= ape->frames[i].skip;
     323         689 :             ape->frames[i].size += ape->frames[i].skip;
     324             :         }
     325        1277 :         ape->frames[i].size = (ape->frames[i].size + 3) & ~3;
     326             :     }
     327          14 :     if (ape->fileversion < 3810) {
     328         329 :         for (i = 0; i < ape->totalframes; i++) {
     329         327 :             if (i < ape->totalframes - 1 && ape->bittable[i + 1])
     330         317 :                 ape->frames[i].size += 4;
     331         327 :             ape->frames[i].skip <<= 3;
     332         327 :             ape->frames[i].skip  += ape->bittable[i];
     333             :         }
     334             :     }
     335             : 
     336          14 :     ape_dumpinfo(s, ape);
     337             : 
     338          42 :     av_log(s, AV_LOG_VERBOSE, "Decoding file - v%d.%02d, compression level %"PRIu16"\n",
     339          28 :            ape->fileversion / 1000, (ape->fileversion % 1000) / 10,
     340          14 :            ape->compressiontype);
     341             : 
     342             :     /* now we are ready: build format streams */
     343          14 :     st = avformat_new_stream(s, NULL);
     344          14 :     if (!st)
     345           0 :         return AVERROR(ENOMEM);
     346             : 
     347          14 :     total_blocks = (ape->totalframes == 0) ? 0 : ((ape->totalframes - 1) * ape->blocksperframe) + ape->finalframeblocks;
     348             : 
     349          14 :     st->codecpar->codec_type      = AVMEDIA_TYPE_AUDIO;
     350          14 :     st->codecpar->codec_id        = AV_CODEC_ID_APE;
     351          14 :     st->codecpar->codec_tag       = MKTAG('A', 'P', 'E', ' ');
     352          14 :     st->codecpar->channels        = ape->channels;
     353          14 :     st->codecpar->sample_rate     = ape->samplerate;
     354          14 :     st->codecpar->bits_per_coded_sample = ape->bps;
     355             : 
     356          14 :     st->nb_frames = ape->totalframes;
     357          14 :     st->start_time = 0;
     358          14 :     st->duration  = total_blocks;
     359          14 :     avpriv_set_pts_info(st, 64, 1, ape->samplerate);
     360             : 
     361          14 :     if (ff_alloc_extradata(st->codecpar, APE_EXTRADATA_SIZE))
     362           0 :         return AVERROR(ENOMEM);
     363          14 :     AV_WL16(st->codecpar->extradata + 0, ape->fileversion);
     364          14 :     AV_WL16(st->codecpar->extradata + 2, ape->compressiontype);
     365          14 :     AV_WL16(st->codecpar->extradata + 4, ape->formatflags);
     366             : 
     367          14 :     pts = 0;
     368        1291 :     for (i = 0; i < ape->totalframes; i++) {
     369        1277 :         ape->frames[i].pts = pts;
     370        1277 :         av_add_index_entry(st, ape->frames[i].pos, ape->frames[i].pts, 0, 0, AVINDEX_KEYFRAME);
     371        1277 :         pts += ape->blocksperframe;
     372             :     }
     373             : 
     374             :     /* try to read APE tags */
     375          14 :     if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
     376          14 :         ff_ape_parse_tag(s);
     377          14 :         avio_seek(pb, 0, SEEK_SET);
     378             :     }
     379             : 
     380          14 :     return 0;
     381             : }
     382             : 
     383          54 : static int ape_read_packet(AVFormatContext * s, AVPacket * pkt)
     384             : {
     385             :     int ret;
     386             :     int nblocks;
     387          54 :     APEContext *ape = s->priv_data;
     388          54 :     uint32_t extra_size = 8;
     389             : 
     390          54 :     if (avio_feof(s->pb))
     391           2 :         return AVERROR_EOF;
     392          52 :     if (ape->currentframe >= ape->totalframes)
     393           0 :         return AVERROR_EOF;
     394             : 
     395          52 :     if (avio_seek(s->pb, ape->frames[ape->currentframe].pos, SEEK_SET) < 0)
     396           0 :         return AVERROR(EIO);
     397             : 
     398             :     /* Calculate how many blocks there are in this frame */
     399          52 :     if (ape->currentframe == (ape->totalframes - 1))
     400           0 :         nblocks = ape->finalframeblocks;
     401             :     else
     402          52 :         nblocks = ape->blocksperframe;
     403             : 
     404         104 :     if (ape->frames[ape->currentframe].size <= 0 ||
     405          52 :         ape->frames[ape->currentframe].size > INT_MAX - extra_size) {
     406           0 :         av_log(s, AV_LOG_ERROR, "invalid packet size: %d\n",
     407           0 :                ape->frames[ape->currentframe].size);
     408           0 :         ape->currentframe++;
     409           0 :         return AVERROR(EIO);
     410             :     }
     411             : 
     412          52 :     if (av_new_packet(pkt,  ape->frames[ape->currentframe].size + extra_size) < 0)
     413           0 :         return AVERROR(ENOMEM);
     414             : 
     415          52 :     AV_WL32(pkt->data    , nblocks);
     416          52 :     AV_WL32(pkt->data + 4, ape->frames[ape->currentframe].skip);
     417          52 :     ret = avio_read(s->pb, pkt->data + extra_size, ape->frames[ape->currentframe].size);
     418          52 :     if (ret < 0) {
     419           0 :         av_packet_unref(pkt);
     420           0 :         return ret;
     421             :     }
     422             : 
     423          52 :     pkt->pts = ape->frames[ape->currentframe].pts;
     424          52 :     pkt->stream_index = 0;
     425             : 
     426             :     /* note: we need to modify the packet size here to handle the last
     427             :        packet */
     428          52 :     pkt->size = ret + extra_size;
     429             : 
     430          52 :     ape->currentframe++;
     431             : 
     432          52 :     return 0;
     433             : }
     434             : 
     435          14 : static int ape_read_close(AVFormatContext * s)
     436             : {
     437          14 :     APEContext *ape = s->priv_data;
     438             : 
     439          14 :     av_freep(&ape->frames);
     440          14 :     av_freep(&ape->seektable);
     441          14 :     av_freep(&ape->bittable);
     442          14 :     return 0;
     443             : }
     444             : 
     445           0 : static int ape_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
     446             : {
     447           0 :     AVStream *st = s->streams[stream_index];
     448           0 :     APEContext *ape = s->priv_data;
     449           0 :     int index = av_index_search_timestamp(st, timestamp, flags);
     450             : 
     451           0 :     if (index < 0)
     452           0 :         return -1;
     453             : 
     454           0 :     if (avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET) < 0)
     455           0 :         return -1;
     456           0 :     ape->currentframe = index;
     457           0 :     return 0;
     458             : }
     459             : 
     460             : AVInputFormat ff_ape_demuxer = {
     461             :     .name           = "ape",
     462             :     .long_name      = NULL_IF_CONFIG_SMALL("Monkey's Audio"),
     463             :     .priv_data_size = sizeof(APEContext),
     464             :     .read_probe     = ape_probe,
     465             :     .read_header    = ape_read_header,
     466             :     .read_packet    = ape_read_packet,
     467             :     .read_close     = ape_read_close,
     468             :     .read_seek      = ape_read_seek,
     469             :     .extensions     = "ape,apl,mac",
     470             : };

Generated by: LCOV version 1.13