LCOV - code coverage report
Current view: top level - libavformat - riffdec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 114 164 69.5 %
Date: 2017-12-10 21:22:29 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :  * RIFF demuxing functions and data
       3             :  * Copyright (c) 2000 Fabrice Bellard
       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/dict.h"
      23             : #include "libavutil/error.h"
      24             : #include "libavutil/log.h"
      25             : #include "libavutil/mathematics.h"
      26             : #include "libavcodec/avcodec.h"
      27             : #include "libavcodec/bytestream.h"
      28             : #include "avformat.h"
      29             : #include "avio_internal.h"
      30             : #include "riff.h"
      31             : 
      32        2232 : int ff_get_guid(AVIOContext *s, ff_asf_guid *g)
      33             : {
      34             :     int ret;
      35             :     av_assert0(sizeof(*g) == 16); //compiler will optimize this out
      36        2232 :     ret = avio_read(s, *g, sizeof(*g));
      37        2232 :     if (ret < (int)sizeof(*g)) {
      38          10 :         memset(*g, 0, sizeof(*g));
      39          10 :         return ret < 0 ? ret : AVERROR_INVALIDDATA;
      40             :     }
      41        2222 :     return 0;
      42             : }
      43             : 
      44          10 : enum AVCodecID ff_codec_guid_get_id(const AVCodecGuid *guids, ff_asf_guid guid)
      45             : {
      46             :     int i;
      47          28 :     for (i = 0; guids[i].id != AV_CODEC_ID_NONE; i++)
      48          28 :         if (!ff_guidcmp(guids[i].guid, guid))
      49          10 :             return guids[i].id;
      50           0 :     return AV_CODEC_ID_NONE;
      51             : }
      52             : 
      53             : /* We could be given one of the three possible structures here:
      54             :  * WAVEFORMAT, PCMWAVEFORMAT or WAVEFORMATEX. Each structure
      55             :  * is an expansion of the previous one with the fields added
      56             :  * at the bottom. PCMWAVEFORMAT adds 'WORD wBitsPerSample' and
      57             :  * WAVEFORMATEX adds 'WORD  cbSize' and basically makes itself
      58             :  * an openended structure.
      59             :  */
      60             : 
      61          15 : static void parse_waveformatex(AVIOContext *pb, AVCodecParameters *par)
      62             : {
      63             :     ff_asf_guid subformat;
      64             :     int bps;
      65             : 
      66          15 :     bps = avio_rl16(pb);
      67          15 :     if (bps)
      68          15 :         par->bits_per_coded_sample = bps;
      69          15 :     par->channel_layout        = avio_rl32(pb); /* dwChannelMask */
      70             : 
      71          15 :     ff_get_guid(pb, &subformat);
      72          15 :     if (!memcmp(subformat + 4,
      73          30 :                 (const uint8_t[]){ FF_AMBISONIC_BASE_GUID }, 12) ||
      74          15 :         !memcmp(subformat + 4,
      75          30 :                 (const uint8_t[]){ FF_BROKEN_BASE_GUID }, 12) ||
      76          15 :         !memcmp(subformat + 4,
      77          15 :                 (const uint8_t[]){ FF_MEDIASUBTYPE_BASE_GUID }, 12)) {
      78          15 :         par->codec_tag = AV_RL32(subformat);
      79          15 :         par->codec_id  = ff_wav_codec_get_id(par->codec_tag,
      80             :                                              par->bits_per_coded_sample);
      81             :     } else {
      82           0 :         par->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subformat);
      83           0 :         if (!par->codec_id)
      84           0 :             av_log(pb, AV_LOG_WARNING,
      85             :                    "unknown subformat:"FF_PRI_GUID"\n",
      86           0 :                    FF_ARG_GUID(subformat));
      87             :     }
      88          15 : }
      89             : 
      90             : /* "big_endian" values are needed for RIFX file format */
      91         585 : int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb,
      92             :                       AVCodecParameters *par, int size, int big_endian)
      93             : {
      94             :     int id;
      95         585 :     uint64_t bitrate = 0;
      96             : 
      97         585 :     if (size < 14) {
      98           0 :         avpriv_request_sample(s, "wav header size < 14");
      99           0 :         return AVERROR_INVALIDDATA;
     100             :     }
     101             : 
     102         585 :     par->codec_type  = AVMEDIA_TYPE_AUDIO;
     103         585 :     if (!big_endian) {
     104         585 :         id                 = avio_rl16(pb);
     105         585 :         if (id != 0x0165) {
     106         585 :             par->channels    = avio_rl16(pb);
     107         585 :             par->sample_rate = avio_rl32(pb);
     108         585 :             bitrate            = avio_rl32(pb) * 8LL;
     109         585 :             par->block_align = avio_rl16(pb);
     110             :         }
     111             :     } else {
     112           0 :         id                 = avio_rb16(pb);
     113           0 :         par->channels    = avio_rb16(pb);
     114           0 :         par->sample_rate = avio_rb32(pb);
     115           0 :         bitrate            = avio_rb32(pb) * 8LL;
     116           0 :         par->block_align = avio_rb16(pb);
     117             :     }
     118         585 :     if (size == 14) {  /* We're dealing with plain vanilla WAVEFORMAT */
     119           0 :         par->bits_per_coded_sample = 8;
     120             :     } else {
     121         585 :         if (!big_endian) {
     122         585 :             par->bits_per_coded_sample = avio_rl16(pb);
     123             :         } else {
     124           0 :             par->bits_per_coded_sample = avio_rb16(pb);
     125             :         }
     126             :     }
     127         585 :     if (id == 0xFFFE) {
     128          15 :         par->codec_tag = 0;
     129             :     } else {
     130         570 :         par->codec_tag = id;
     131         570 :         par->codec_id  = ff_wav_codec_get_id(id,
     132             :                                              par->bits_per_coded_sample);
     133             :     }
     134        1139 :     if (size >= 18 && id != 0x0165) {  /* We're obviously dealing with WAVEFORMATEX */
     135         554 :         int cbSize = avio_rl16(pb); /* cbSize */
     136         554 :         if (big_endian) {
     137           0 :             avpriv_report_missing_feature(s, "WAVEFORMATEX support for RIFX files");
     138           0 :             return AVERROR_PATCHWELCOME;
     139             :         }
     140         554 :         size  -= 18;
     141         554 :         cbSize = FFMIN(size, cbSize);
     142         554 :         if (cbSize >= 22 && id == 0xfffe) { /* WAVEFORMATEXTENSIBLE */
     143          15 :             parse_waveformatex(pb, par);
     144          15 :             cbSize -= 22;
     145          15 :             size   -= 22;
     146             :         }
     147         554 :         if (cbSize > 0) {
     148          63 :             av_freep(&par->extradata);
     149          63 :             if (ff_get_extradata(s, par, pb, cbSize) < 0)
     150           0 :                 return AVERROR(ENOMEM);
     151          63 :             size -= cbSize;
     152             :         }
     153             : 
     154             :         /* It is possible for the chunk to contain garbage at the end */
     155         554 :         if (size > 0)
     156           5 :             avio_skip(pb, size);
     157          31 :     } else if (id == 0x0165 && size >= 32) {
     158             :         int nb_streams, i;
     159             : 
     160           0 :         size -= 4;
     161           0 :         av_freep(&par->extradata);
     162           0 :         if (ff_get_extradata(s, par, pb, size) < 0)
     163           0 :             return AVERROR(ENOMEM);
     164           0 :         nb_streams         = AV_RL16(par->extradata + 4);
     165           0 :         par->sample_rate   = AV_RL32(par->extradata + 12);
     166           0 :         par->channels      = 0;
     167           0 :         bitrate            = 0;
     168           0 :         if (size < 8 + nb_streams * 20)
     169           0 :             return AVERROR_INVALIDDATA;
     170           0 :         for (i = 0; i < nb_streams; i++)
     171           0 :             par->channels += par->extradata[8 + i * 20 + 17];
     172             :     }
     173             : 
     174         585 :     par->bit_rate = bitrate;
     175             : 
     176         585 :     if (par->sample_rate <= 0) {
     177           0 :         av_log(s, AV_LOG_ERROR,
     178             :                "Invalid sample rate: %d\n", par->sample_rate);
     179           0 :         return AVERROR_INVALIDDATA;
     180             :     }
     181         585 :     if (par->codec_id == AV_CODEC_ID_AAC_LATM) {
     182             :         /* Channels and sample_rate values are those prior to applying SBR
     183             :          * and/or PS. */
     184           0 :         par->channels    = 0;
     185           0 :         par->sample_rate = 0;
     186             :     }
     187             :     /* override bits_per_coded_sample for G.726 */
     188         585 :     if (par->codec_id == AV_CODEC_ID_ADPCM_G726 && par->sample_rate)
     189           4 :         par->bits_per_coded_sample = par->bit_rate / par->sample_rate;
     190             : 
     191         585 :     return 0;
     192             : }
     193             : 
     194         587 : enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps)
     195             : {
     196             :     enum AVCodecID id;
     197         587 :     id = ff_codec_get_id(ff_codec_wav_tags, tag);
     198         587 :     if (id <= 0)
     199           1 :         return id;
     200             : 
     201         586 :     if (id == AV_CODEC_ID_PCM_S16LE)
     202         502 :         id = ff_get_pcm_codec_id(bps, 0, 0, ~1);
     203          84 :     else if (id == AV_CODEC_ID_PCM_F32LE)
     204           4 :         id = ff_get_pcm_codec_id(bps, 1, 0,  0);
     205             : 
     206         586 :     if (id == AV_CODEC_ID_ADPCM_IMA_WAV && bps == 8)
     207           0 :         id = AV_CODEC_ID_PCM_ZORK;
     208         586 :     return id;
     209             : }
     210             : 
     211         422 : int ff_get_bmp_header(AVIOContext *pb, AVStream *st, uint32_t *size)
     212             : {
     213             :     int tag1;
     214         422 :     uint32_t size_ = avio_rl32(pb);
     215         422 :     if (size)
     216         418 :         *size = size_;
     217         422 :     st->codecpar->width  = avio_rl32(pb);
     218         422 :     st->codecpar->height = (int32_t)avio_rl32(pb);
     219         422 :     avio_rl16(pb); /* planes */
     220         422 :     st->codecpar->bits_per_coded_sample = avio_rl16(pb); /* depth */
     221         422 :     tag1                                = avio_rl32(pb);
     222         422 :     avio_rl32(pb); /* ImageSize */
     223         422 :     avio_rl32(pb); /* XPelsPerMeter */
     224         422 :     avio_rl32(pb); /* YPelsPerMeter */
     225         422 :     avio_rl32(pb); /* ClrUsed */
     226         422 :     avio_rl32(pb); /* ClrImportant */
     227         422 :     return tag1;
     228             : }
     229             : 
     230          72 : int ff_read_riff_info(AVFormatContext *s, int64_t size)
     231             : {
     232             :     int64_t start, end, cur;
     233          72 :     AVIOContext *pb = s->pb;
     234             : 
     235          72 :     start = avio_tell(pb);
     236          72 :     end   = start + size;
     237             : 
     238         388 :     while ((cur = avio_tell(pb)) >= 0 &&
     239         158 :            cur <= end - 8 /* = tag + size */) {
     240             :         uint32_t chunk_code;
     241             :         int64_t chunk_size;
     242          86 :         char key[5] = { 0 };
     243             :         char *value;
     244             : 
     245          86 :         chunk_code = avio_rl32(pb);
     246          86 :         chunk_size = avio_rl32(pb);
     247          86 :         if (avio_feof(pb)) {
     248           0 :             if (chunk_code || chunk_size) {
     249           0 :                 av_log(s, AV_LOG_WARNING, "INFO subchunk truncated\n");
     250           0 :                 return AVERROR_INVALIDDATA;
     251             :             }
     252           0 :             return AVERROR_EOF;
     253             :         }
     254         172 :         if (chunk_size > end ||
     255         172 :             end - chunk_size < cur ||
     256             :             chunk_size == UINT_MAX) {
     257           0 :             avio_seek(pb, -9, SEEK_CUR);
     258           0 :             chunk_code = avio_rl32(pb);
     259           0 :             chunk_size = avio_rl32(pb);
     260           0 :             if (chunk_size > end || end - chunk_size < cur || chunk_size == UINT_MAX) {
     261           0 :                 av_log(s, AV_LOG_WARNING, "too big INFO subchunk\n");
     262           0 :                 return AVERROR_INVALIDDATA;
     263             :             }
     264             :         }
     265             : 
     266          86 :         chunk_size += (chunk_size & 1);
     267             : 
     268          86 :         if (!chunk_code) {
     269           2 :             if (chunk_size)
     270           2 :                 avio_skip(pb, chunk_size);
     271           0 :             else if (pb->eof_reached) {
     272           0 :                 av_log(s, AV_LOG_WARNING, "truncated file\n");
     273           0 :                 return AVERROR_EOF;
     274             :             }
     275           2 :             continue;
     276             :         }
     277             : 
     278          84 :         value = av_mallocz(chunk_size + 1);
     279          84 :         if (!value) {
     280           0 :             av_log(s, AV_LOG_ERROR,
     281             :                    "out of memory, unable to read INFO tag\n");
     282           0 :             return AVERROR(ENOMEM);
     283             :         }
     284             : 
     285          84 :         AV_WL32(key, chunk_code);
     286             :         // Work around VC++ 2015 Update 1 code-gen bug:
     287             :         // https://connect.microsoft.com/VisualStudio/feedback/details/2291638
     288          84 :         key[4] = 0;
     289             : 
     290          84 :         if (avio_read(pb, value, chunk_size) != chunk_size) {
     291           0 :             av_log(s, AV_LOG_WARNING,
     292             :                    "premature end of file while reading INFO tag\n");
     293             :         }
     294             : 
     295          84 :         av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL);
     296             :     }
     297             : 
     298          72 :     return 0;
     299             : }

Generated by: LCOV version 1.13