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

Generated by: LCOV version 1.13