LCOV - code coverage report
Current view: top level - libavformat - xwma.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 78 120 65.0 %
Date: 2017-12-17 04:34:43 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :  * xWMA demuxer
       3             :  * Copyright (c) 2011 Max Horn
       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 <inttypes.h>
      23             : #include <stdint.h>
      24             : 
      25             : #include "avformat.h"
      26             : #include "internal.h"
      27             : #include "riff.h"
      28             : 
      29             : /*
      30             :  * Demuxer for xWMA, a Microsoft audio container used by XAudio 2.
      31             :  */
      32             : 
      33             : typedef struct XWMAContext {
      34             :     int64_t data_end;
      35             : } XWMAContext;
      36             : 
      37        6130 : static int xwma_probe(AVProbeData *p)
      38             : {
      39        6130 :     if (!memcmp(p->buf, "RIFF", 4) && !memcmp(p->buf + 8, "XWMA", 4))
      40           1 :         return AVPROBE_SCORE_MAX;
      41        6129 :     return 0;
      42             : }
      43             : 
      44           1 : static int xwma_read_header(AVFormatContext *s)
      45             : {
      46             :     int64_t size;
      47           1 :     int ret = 0;
      48           1 :     uint32_t dpds_table_size = 0;
      49           1 :     uint32_t *dpds_table = NULL;
      50             :     unsigned int tag;
      51           1 :     AVIOContext *pb = s->pb;
      52             :     AVStream *st;
      53           1 :     XWMAContext *xwma = s->priv_data;
      54             :     int i;
      55             : 
      56             :     /* The following code is mostly copied from wav.c, with some
      57             :      * minor alterations.
      58             :      */
      59             : 
      60             :     /* check RIFF header */
      61           1 :     tag = avio_rl32(pb);
      62           1 :     if (tag != MKTAG('R', 'I', 'F', 'F'))
      63           0 :         return -1;
      64           1 :     avio_rl32(pb); /* file size */
      65           1 :     tag = avio_rl32(pb);
      66           1 :     if (tag != MKTAG('X', 'W', 'M', 'A'))
      67           0 :         return -1;
      68             : 
      69             :     /* parse fmt header */
      70           1 :     tag = avio_rl32(pb);
      71           1 :     if (tag != MKTAG('f', 'm', 't', ' '))
      72           0 :         return -1;
      73           1 :     size = avio_rl32(pb);
      74           1 :     st = avformat_new_stream(s, NULL);
      75           1 :     if (!st)
      76           0 :         return AVERROR(ENOMEM);
      77             : 
      78           1 :     ret = ff_get_wav_header(s, pb, st->codecpar, size, 0);
      79           1 :     if (ret < 0)
      80           0 :         return ret;
      81           1 :     st->need_parsing = AVSTREAM_PARSE_NONE;
      82             : 
      83             :     /* All xWMA files I have seen contained WMAv2 data. If there are files
      84             :      * using WMA Pro or some other codec, then we need to figure out the right
      85             :      * extradata for that. Thus, ask the user for feedback, but try to go on
      86             :      * anyway.
      87             :      */
      88           1 :     if (st->codecpar->codec_id != AV_CODEC_ID_WMAV2 &&
      89           0 :         st->codecpar->codec_id != AV_CODEC_ID_WMAPRO) {
      90           0 :         avpriv_request_sample(s, "Unexpected codec (tag %s; id %d)",
      91           0 :                               av_fourcc2str(st->codecpar->codec_tag),
      92           0 :                               st->codecpar->codec_id);
      93             :     } else {
      94             :         /* In all xWMA files I have seen, there is no extradata. But the WMA
      95             :          * codecs require extradata, so we provide our own fake extradata.
      96             :          *
      97             :          * First, check that there really was no extradata in the header. If
      98             :          * there was, then try to use it, after asking the user to provide a
      99             :          * sample of this unusual file.
     100             :          */
     101           1 :         if (st->codecpar->extradata_size != 0) {
     102             :             /* Surprise, surprise: We *did* get some extradata. No idea
     103             :              * if it will work, but just go on and try it, after asking
     104             :              * the user for a sample.
     105             :              */
     106           0 :             avpriv_request_sample(s, "Unexpected extradata (%d bytes)",
     107           0 :                                   st->codecpar->extradata_size);
     108           1 :         } else if (st->codecpar->codec_id == AV_CODEC_ID_WMAPRO) {
     109           0 :             if (ff_alloc_extradata(st->codecpar, 18))
     110           0 :                 return AVERROR(ENOMEM);
     111             : 
     112           0 :             memset(st->codecpar->extradata, 0, st->codecpar->extradata_size);
     113           0 :             st->codecpar->extradata[ 0] = st->codecpar->bits_per_coded_sample;
     114           0 :             st->codecpar->extradata[14] = 224;
     115             :         } else {
     116           1 :             if (ff_alloc_extradata(st->codecpar, 6))
     117           0 :                 return AVERROR(ENOMEM);
     118             : 
     119           1 :             memset(st->codecpar->extradata, 0, st->codecpar->extradata_size);
     120             :             /* setup extradata with our experimentally obtained value */
     121           1 :             st->codecpar->extradata[4] = 31;
     122             :         }
     123             :     }
     124             : 
     125           1 :     if (!st->codecpar->channels) {
     126           0 :         av_log(s, AV_LOG_WARNING, "Invalid channel count: %d\n",
     127           0 :                st->codecpar->channels);
     128           0 :         return AVERROR_INVALIDDATA;
     129             :     }
     130           1 :     if (!st->codecpar->bits_per_coded_sample) {
     131           0 :         av_log(s, AV_LOG_WARNING, "Invalid bits_per_coded_sample: %d\n",
     132           0 :                st->codecpar->bits_per_coded_sample);
     133           0 :         return AVERROR_INVALIDDATA;
     134             :     }
     135             : 
     136             :     /* set the sample rate */
     137           1 :     avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     138             : 
     139             :     /* parse the remaining RIFF chunks */
     140             :     for (;;) {
     141           3 :         if (pb->eof_reached) {
     142           0 :             ret = AVERROR_EOF;
     143           0 :             goto fail;
     144             :         }
     145             :         /* read next chunk tag */
     146           2 :         tag = avio_rl32(pb);
     147           2 :         size = avio_rl32(pb);
     148           2 :         if (tag == MKTAG('d', 'a', 't', 'a')) {
     149             :             /* We assume that the data chunk comes last. */
     150           1 :             break;
     151           1 :         } else if (tag == MKTAG('d','p','d','s')) {
     152             :             /* Quoting the MSDN xWMA docs on the dpds chunk: "Contains the
     153             :              * decoded packet cumulative data size array, each element is the
     154             :              * number of bytes accumulated after the corresponding xWMA packet
     155             :              * is decoded in order."
     156             :              *
     157             :              * Each packet has size equal to st->codecpar->block_align, which in
     158             :              * all cases I saw so far was always 2230. Thus, we can use the
     159             :              * dpds data to compute a seeking index.
     160             :              */
     161             : 
     162             :             /* Error out if there is more than one dpds chunk. */
     163           1 :             if (dpds_table) {
     164           0 :                 av_log(s, AV_LOG_ERROR, "two dpds chunks present\n");
     165           0 :                 ret = AVERROR_INVALIDDATA;
     166           0 :                 goto fail;
     167             :             }
     168             : 
     169             :             /* Compute the number of entries in the dpds chunk. */
     170           1 :             if (size & 3) {  /* Size should be divisible by four */
     171           0 :                 av_log(s, AV_LOG_WARNING,
     172             :                        "dpds chunk size %"PRId64" not divisible by 4\n", size);
     173             :             }
     174           1 :             dpds_table_size = size / 4;
     175           1 :             if (dpds_table_size == 0 || dpds_table_size >= INT_MAX / 4) {
     176           0 :                 av_log(s, AV_LOG_ERROR,
     177             :                        "dpds chunk size %"PRId64" invalid\n", size);
     178           0 :                 return AVERROR_INVALIDDATA;
     179             :             }
     180             : 
     181             :             /* Allocate some temporary storage to keep the dpds data around.
     182             :              * for processing later on.
     183             :              */
     184           1 :             dpds_table = av_malloc_array(dpds_table_size, sizeof(uint32_t));
     185           1 :             if (!dpds_table) {
     186           0 :                 return AVERROR(ENOMEM);
     187             :             }
     188             : 
     189         159 :             for (i = 0; i < dpds_table_size; ++i) {
     190         158 :                 dpds_table[i] = avio_rl32(pb);
     191         158 :                 size -= 4;
     192             :             }
     193             :         }
     194           1 :         avio_skip(pb, size);
     195             :     }
     196             : 
     197             :     /* Determine overall data length */
     198           1 :     if (size < 0) {
     199           0 :         ret = AVERROR_INVALIDDATA;
     200           0 :         goto fail;
     201             :     }
     202           1 :     if (!size) {
     203           0 :         xwma->data_end = INT64_MAX;
     204             :     } else
     205           1 :         xwma->data_end = avio_tell(pb) + size;
     206             : 
     207             : 
     208           2 :     if (dpds_table && dpds_table_size) {
     209             :         int64_t cur_pos;
     210           1 :         const uint32_t bytes_per_sample
     211           1 :                 = (st->codecpar->channels * st->codecpar->bits_per_coded_sample) >> 3;
     212             : 
     213             :         /* Estimate the duration from the total number of output bytes. */
     214           1 :         const uint64_t total_decoded_bytes = dpds_table[dpds_table_size - 1];
     215             : 
     216           1 :         if (!bytes_per_sample) {
     217           0 :             av_log(s, AV_LOG_ERROR,
     218             :                    "Invalid bits_per_coded_sample %d for %d channels\n",
     219           0 :                    st->codecpar->bits_per_coded_sample, st->codecpar->channels);
     220           0 :             ret = AVERROR_INVALIDDATA;
     221           0 :             goto fail;
     222             :         }
     223             : 
     224           1 :         st->duration = total_decoded_bytes / bytes_per_sample;
     225             : 
     226             :         /* Use the dpds data to build a seek table.  We can only do this after
     227             :          * we know the offset to the data chunk, as we need that to determine
     228             :          * the actual offset to each input block.
     229             :          * Note: If we allowed ourselves to assume that the data chunk always
     230             :          * follows immediately after the dpds block, we could of course guess
     231             :          * the data block's start offset already while reading the dpds chunk.
     232             :          * I decided against that, just in case other chunks ever are
     233             :          * discovered.
     234             :          */
     235           1 :         cur_pos = avio_tell(pb);
     236         159 :         for (i = 0; i < dpds_table_size; ++i) {
     237             :             /* From the number of output bytes that would accumulate in the
     238             :              * output buffer after decoding the first (i+1) packets, we compute
     239             :              * an offset / timestamp pair.
     240             :              */
     241         474 :             av_add_index_entry(st,
     242         158 :                                cur_pos + (i+1) * st->codecpar->block_align, /* pos */
     243         158 :                                dpds_table[i] / bytes_per_sample,            /* timestamp */
     244         158 :                                st->codecpar->block_align,                   /* size */
     245             :                                0,                                           /* duration */
     246             :                                AVINDEX_KEYFRAME);
     247             :         }
     248           0 :     } else if (st->codecpar->bit_rate) {
     249             :         /* No dpds chunk was present (or only an empty one), so estimate
     250             :          * the total duration using the average bits per sample and the
     251             :          * total data length.
     252             :          */
     253           0 :         st->duration = (size<<3) * st->codecpar->sample_rate / st->codecpar->bit_rate;
     254             :     }
     255             : 
     256           1 : fail:
     257           1 :     av_free(dpds_table);
     258             : 
     259           1 :     return ret;
     260             : }
     261             : 
     262         159 : static int xwma_read_packet(AVFormatContext *s, AVPacket *pkt)
     263             : {
     264             :     int ret, size;
     265             :     int64_t left;
     266             :     AVStream *st;
     267         159 :     XWMAContext *xwma = s->priv_data;
     268             : 
     269         159 :     st = s->streams[0];
     270             : 
     271         159 :     left = xwma->data_end - avio_tell(s->pb);
     272         159 :     if (left <= 0) {
     273           1 :         return AVERROR_EOF;
     274             :     }
     275             : 
     276             :     /* read a single block; the default block size is 2230. */
     277         158 :     size = (st->codecpar->block_align > 1) ? st->codecpar->block_align : 2230;
     278         158 :     size = FFMIN(size, left);
     279             : 
     280         158 :     ret  = av_get_packet(s->pb, pkt, size);
     281         158 :     if (ret < 0)
     282           0 :         return ret;
     283             : 
     284         158 :     pkt->stream_index = 0;
     285         158 :     return ret;
     286             : }
     287             : 
     288             : AVInputFormat ff_xwma_demuxer = {
     289             :     .name           = "xwma",
     290             :     .long_name      = NULL_IF_CONFIG_SMALL("Microsoft xWMA"),
     291             :     .priv_data_size = sizeof(XWMAContext),
     292             :     .read_probe     = xwma_probe,
     293             :     .read_header    = xwma_read_header,
     294             :     .read_packet    = xwma_read_packet,
     295             : };

Generated by: LCOV version 1.13