LCOV - code coverage report
Current view: top level - src/libavformat - brstm.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 210 281 74.7 %
Date: 2017-01-24 04:42:20 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /*
       2             :  * BRSTM demuxer
       3             :  * Copyright (c) 2012 Paul B Mahol
       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/intreadwrite.h"
      23             : #include "libavcodec/bytestream.h"
      24             : #include "avformat.h"
      25             : #include "internal.h"
      26             : 
      27             : typedef struct BRSTMDemuxContext {
      28             :     uint32_t    block_size;
      29             :     uint32_t    block_count;
      30             :     uint32_t    current_block;
      31             :     uint32_t    samples_per_block;
      32             :     uint32_t    last_block_used_bytes;
      33             :     uint32_t    last_block_size;
      34             :     uint32_t    last_block_samples;
      35             :     uint32_t    data_start;
      36             :     uint8_t     *table;
      37             :     uint8_t     *adpc;
      38             :     int         little_endian;
      39             : } BRSTMDemuxContext;
      40             : 
      41        5563 : static int probe(AVProbeData *p)
      42             : {
      43        5564 :     if (AV_RL32(p->buf) == MKTAG('R','S','T','M') &&
      44           1 :         (AV_RL16(p->buf + 4) == 0xFFFE ||
      45           0 :          AV_RL16(p->buf + 4) == 0xFEFF))
      46           1 :         return AVPROBE_SCORE_MAX / 3 * 2;
      47        5562 :     return 0;
      48             : }
      49             : 
      50        5563 : static int probe_bfstm(AVProbeData *p)
      51             : {
      52       11125 :     if ((AV_RL32(p->buf) == MKTAG('F','S','T','M') ||
      53        5564 :          AV_RL32(p->buf) == MKTAG('C','S','T','M')) &&
      54           3 :         (AV_RL16(p->buf + 4) == 0xFFFE ||
      55           1 :          AV_RL16(p->buf + 4) == 0xFEFF))
      56           2 :         return AVPROBE_SCORE_MAX / 3 * 2;
      57        5561 :     return 0;
      58             : }
      59             : 
      60           3 : static int read_close(AVFormatContext *s)
      61             : {
      62           3 :     BRSTMDemuxContext *b = s->priv_data;
      63             : 
      64           3 :     av_freep(&b->table);
      65           3 :     av_freep(&b->adpc);
      66             : 
      67           3 :     return 0;
      68             : }
      69             : 
      70          12 : static av_always_inline unsigned int read16(AVFormatContext *s)
      71             : {
      72          12 :     BRSTMDemuxContext *b = s->priv_data;
      73          12 :     if (b->little_endian)
      74           5 :         return avio_rl16(s->pb);
      75             :     else
      76           7 :         return avio_rb16(s->pb);
      77             : }
      78             : 
      79          50 : static av_always_inline unsigned int read32(AVFormatContext *s)
      80             : {
      81          50 :     BRSTMDemuxContext *b = s->priv_data;
      82          50 :     if (b->little_endian)
      83          17 :         return avio_rl32(s->pb);
      84             :     else
      85          33 :         return avio_rb32(s->pb);
      86             : }
      87             : 
      88           3 : static int read_header(AVFormatContext *s)
      89             : {
      90           3 :     BRSTMDemuxContext *b = s->priv_data;
      91             :     int bom, major, minor, codec, chunk;
      92             :     int64_t h1offset, pos, toffset;
      93           3 :     uint32_t size, asize, start = 0;
      94             :     AVStream *st;
      95           3 :     int ret = AVERROR_EOF;
      96           3 :     int loop = 0;
      97           3 :     int bfstm = !strcmp("bfstm", s->iformat->name);
      98             : 
      99           3 :     st = avformat_new_stream(s, NULL);
     100           3 :     if (!st)
     101           0 :         return AVERROR(ENOMEM);
     102           3 :     st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
     103             : 
     104           3 :     avio_skip(s->pb, 4);
     105             : 
     106           3 :     bom = avio_rb16(s->pb);
     107           3 :     if (bom != 0xFEFF && bom != 0xFFFE) {
     108           0 :         av_log(s, AV_LOG_ERROR, "invalid byte order: %X\n", bom);
     109           0 :         return AVERROR_INVALIDDATA;
     110             :     }
     111             : 
     112           3 :     if (bom == 0xFFFE)
     113           1 :         b->little_endian = 1;
     114             : 
     115           3 :     if (!bfstm) {
     116           1 :         major = avio_r8(s->pb);
     117           1 :         minor = avio_r8(s->pb);
     118           1 :         avio_skip(s->pb, 4); // size of file
     119           1 :         size = read16(s);
     120           1 :         if (size < 14)
     121           0 :             return AVERROR_INVALIDDATA;
     122             : 
     123           1 :         avio_skip(s->pb, size - 14);
     124           1 :         pos = avio_tell(s->pb);
     125           1 :         if (avio_rl32(s->pb) != MKTAG('H','E','A','D'))
     126           0 :             return AVERROR_INVALIDDATA;
     127             :     } else {
     128           2 :         uint32_t info_offset = 0;
     129             :         uint16_t section_count, header_size, i;
     130             : 
     131           2 :         header_size = read16(s); // 6
     132             : 
     133           2 :         avio_skip(s->pb, 4); // Unknown constant 0x00030000
     134           2 :         avio_skip(s->pb, 4); // size of file
     135           2 :         section_count = read16(s);
     136           2 :         avio_skip(s->pb, 2); // padding
     137          10 :         for (i = 0; avio_tell(s->pb) < header_size
     138           8 :                     && !(start && info_offset)
     139          12 :                     && i < section_count; i++) {
     140           6 :             uint16_t flag = read16(s);
     141           6 :             avio_skip(s->pb, 2);
     142           6 :             switch (flag) {
     143             :             case 0x4000:
     144           2 :                 info_offset = read32(s);
     145           2 :                 /*info_size =*/ read32(s);
     146           2 :                 break;
     147             :             case 0x4001:
     148           2 :                 avio_skip(s->pb, 4); // seek offset
     149           2 :                 avio_skip(s->pb, 4); // seek size
     150           2 :                 break;
     151             :             case 0x4002:
     152           2 :                 start = read32(s) + 8;
     153           2 :                 avio_skip(s->pb, 4); //data_size = read32(s);
     154           2 :                 break;
     155             :             case 0x4003:
     156           0 :                 avio_skip(s->pb, 4); // REGN offset
     157           0 :                 avio_skip(s->pb, 4); // REGN size
     158           0 :                 break;
     159             :             }
     160             :         }
     161             : 
     162           2 :         if (!info_offset || !start)
     163           0 :             return AVERROR_INVALIDDATA;
     164             : 
     165           2 :         avio_skip(s->pb, info_offset - avio_tell(s->pb));
     166           2 :         pos = avio_tell(s->pb);
     167           2 :         if (avio_rl32(s->pb) != MKTAG('I','N','F','O'))
     168           0 :             return AVERROR_INVALIDDATA;
     169             :     }
     170             : 
     171           3 :     size = read32(s);
     172           3 :     if (size < 40)
     173           0 :         return AVERROR_INVALIDDATA;
     174           3 :     avio_skip(s->pb, 4); // unknown
     175           3 :     h1offset = read32(s);
     176           3 :     if (h1offset > size)
     177           0 :         return AVERROR_INVALIDDATA;
     178           3 :     avio_skip(s->pb, 12);
     179           3 :     toffset = read32(s) + 16LL;
     180           3 :     if (toffset > size)
     181           0 :         return AVERROR_INVALIDDATA;
     182             : 
     183           3 :     avio_skip(s->pb, pos + h1offset + 8 - avio_tell(s->pb));
     184           3 :     codec = avio_r8(s->pb);
     185             : 
     186           3 :     switch (codec) {
     187           0 :     case 0: codec = AV_CODEC_ID_PCM_S8_PLANAR;    break;
     188           0 :     case 1: codec = b->little_endian ?
     189           0 :                     AV_CODEC_ID_PCM_S16LE_PLANAR :
     190           0 :                     AV_CODEC_ID_PCM_S16BE_PLANAR; break;
     191           6 :     case 2: codec = b->little_endian ?
     192           3 :                     AV_CODEC_ID_ADPCM_THP_LE :
     193           3 :                     AV_CODEC_ID_ADPCM_THP;        break;
     194             :     default:
     195           0 :         avpriv_request_sample(s, "codec %d", codec);
     196           0 :         return AVERROR_PATCHWELCOME;
     197             :     }
     198             : 
     199           3 :     loop = avio_r8(s->pb); // loop flag
     200           3 :     st->codecpar->codec_id = codec;
     201           3 :     st->codecpar->channels = avio_r8(s->pb);
     202           3 :     if (!st->codecpar->channels)
     203           0 :         return AVERROR_INVALIDDATA;
     204             : 
     205           3 :     avio_skip(s->pb, 1); // padding
     206             : 
     207           3 :     st->codecpar->sample_rate = bfstm ? read32(s) : read16(s);
     208           3 :     if (st->codecpar->sample_rate <= 0)
     209           0 :         return AVERROR_INVALIDDATA;
     210             : 
     211           3 :     if (!bfstm)
     212           1 :         avio_skip(s->pb, 2); // padding
     213             : 
     214           3 :     if (loop) {
     215           4 :         if (av_dict_set_int(&s->metadata, "loop_start",
     216           2 :                             av_rescale(read32(s), AV_TIME_BASE,
     217           2 :                                        st->codecpar->sample_rate),
     218             :                             0) < 0)
     219           0 :             return AVERROR(ENOMEM);
     220             :     } else {
     221           1 :         avio_skip(s->pb, 4);
     222             :     }
     223             : 
     224           3 :     st->start_time = 0;
     225           3 :     st->duration = read32(s);
     226           3 :     avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     227             : 
     228           3 :     if (!bfstm)
     229           1 :         start = read32(s);
     230           3 :     b->current_block = 0;
     231           3 :     b->block_count = read32(s);
     232           3 :     if (b->block_count > UINT16_MAX) {
     233           0 :         av_log(s, AV_LOG_WARNING, "too many blocks: %u\n", b->block_count);
     234           0 :         return AVERROR_INVALIDDATA;
     235             :     }
     236             : 
     237           3 :     b->block_size = read32(s);
     238           3 :     if (b->block_size > UINT32_MAX / st->codecpar->channels)
     239           0 :         return AVERROR_INVALIDDATA;
     240             : 
     241           3 :     b->samples_per_block = read32(s);
     242           3 :     b->last_block_used_bytes = read32(s);
     243           3 :     b->last_block_samples = read32(s);
     244           3 :     b->last_block_size = read32(s);
     245           3 :     if (b->last_block_size > UINT32_MAX / st->codecpar->channels)
     246           0 :         return AVERROR_INVALIDDATA;
     247           3 :     if (b->last_block_used_bytes > b->last_block_size)
     248           0 :         return AVERROR_INVALIDDATA;
     249             : 
     250             : 
     251           3 :     if (codec == AV_CODEC_ID_ADPCM_THP || codec == AV_CODEC_ID_ADPCM_THP_LE) {
     252             :         int ch;
     253             : 
     254           3 :         avio_skip(s->pb, pos + toffset - avio_tell(s->pb));
     255           3 :         if (!bfstm)
     256           1 :             toffset = read32(s) + 16LL;
     257             :         else
     258           2 :             toffset = toffset + read32(s) + st->codecpar->channels * 8 - 8;
     259           3 :         if (toffset > size)
     260           0 :             return AVERROR_INVALIDDATA;
     261             : 
     262           3 :         avio_skip(s->pb, pos + toffset - avio_tell(s->pb));
     263           3 :         b->table = av_mallocz(32 * st->codecpar->channels);
     264           3 :         if (!b->table)
     265           0 :             return AVERROR(ENOMEM);
     266             : 
     267          12 :         for (ch = 0; ch < st->codecpar->channels; ch++) {
     268           9 :             if (avio_read(s->pb, b->table + ch * 32, 32) != 32) {
     269           0 :                 ret = AVERROR_INVALIDDATA;
     270           0 :                 goto fail;
     271             :             }
     272           9 :             avio_skip(s->pb, bfstm ? 14 : 24);
     273             :         }
     274             :     }
     275             : 
     276           3 :     if (size < (avio_tell(s->pb) - pos)) {
     277           0 :         ret = AVERROR_INVALIDDATA;
     278           0 :         goto fail;
     279             :     }
     280             : 
     281           3 :     avio_skip(s->pb, size - (avio_tell(s->pb) - pos));
     282             : 
     283           9 :     while (!avio_feof(s->pb)) {
     284           6 :         chunk = avio_rl32(s->pb);
     285           6 :         size  = read32(s);
     286           6 :         if (size < 8) {
     287           0 :             ret = AVERROR_INVALIDDATA;
     288           0 :             goto fail;
     289             :         }
     290           6 :         size -= 8;
     291           6 :         switch (chunk) {
     292             :         case MKTAG('S','E','E','K'):
     293             :         case MKTAG('A','D','P','C'):
     294           3 :             if (codec != AV_CODEC_ID_ADPCM_THP &&
     295             :                 codec != AV_CODEC_ID_ADPCM_THP_LE)
     296           0 :                 goto skip;
     297             : 
     298           3 :             asize = b->block_count * st->codecpar->channels * 4;
     299           3 :             if (size < asize) {
     300           0 :                 ret = AVERROR_INVALIDDATA;
     301           0 :                 goto fail;
     302             :             }
     303           3 :             if (b->adpc) {
     304           0 :                 av_log(s, AV_LOG_WARNING, "skipping additional ADPC chunk\n");
     305           0 :                 goto skip;
     306             :             } else {
     307           3 :                 b->adpc = av_mallocz(asize);
     308           3 :                 if (!b->adpc) {
     309           0 :                     ret = AVERROR(ENOMEM);
     310           0 :                     goto fail;
     311             :                 }
     312           4 :                 if (bfstm && codec != AV_CODEC_ID_ADPCM_THP_LE) {
     313             :                     // Big-endian BFSTMs have little-endian SEEK tables
     314             :                     // for some strange reason.
     315             :                     int i;
     316          33 :                     for (i = 0; i < asize; i += 2) {
     317          32 :                         b->adpc[i+1] = avio_r8(s->pb);
     318          32 :                         b->adpc[i]   = avio_r8(s->pb);
     319             :                     }
     320             :                 } else {
     321           2 :                     avio_read(s->pb, b->adpc, asize);
     322             :                 }
     323           3 :                 avio_skip(s->pb, size - asize);
     324             :             }
     325           3 :             break;
     326             :         case MKTAG('D','A','T','A'):
     327           6 :             if ((start < avio_tell(s->pb)) ||
     328           3 :                 (!b->adpc && (codec == AV_CODEC_ID_ADPCM_THP ||
     329             :                               codec == AV_CODEC_ID_ADPCM_THP_LE))) {
     330           0 :                 ret = AVERROR_INVALIDDATA;
     331           0 :                 goto fail;
     332             :             }
     333           3 :             avio_skip(s->pb, start - avio_tell(s->pb));
     334             : 
     335           3 :             if (bfstm && (codec == AV_CODEC_ID_ADPCM_THP ||
     336             :                           codec == AV_CODEC_ID_ADPCM_THP_LE))
     337           2 :                 avio_skip(s->pb, 24);
     338             : 
     339           3 :             b->data_start = avio_tell(s->pb);
     340             : 
     341           3 :             if (!bfstm && (major != 1 || minor))
     342           0 :                 avpriv_request_sample(s, "Version %d.%d", major, minor);
     343             : 
     344           3 :             return 0;
     345             :         default:
     346           0 :             av_log(s, AV_LOG_WARNING, "skipping unknown chunk: %X\n", chunk);
     347             : skip:
     348           0 :             avio_skip(s->pb, size);
     349             :         }
     350             :     }
     351             : 
     352             : fail:
     353           0 :     read_close(s);
     354             : 
     355           0 :     return ret;
     356             : }
     357             : 
     358          30 : static int read_packet(AVFormatContext *s, AVPacket *pkt)
     359             : {
     360          30 :     AVCodecParameters *par = s->streams[0]->codecpar;
     361          30 :     BRSTMDemuxContext *b = s->priv_data;
     362          30 :     uint32_t samples, size, skip = 0;
     363             :     int ret, i;
     364             : 
     365          30 :     if (avio_feof(s->pb))
     366           1 :         return AVERROR_EOF;
     367          29 :     b->current_block++;
     368          29 :     if (b->current_block == b->block_count) {
     369           2 :         size    = b->last_block_used_bytes;
     370           2 :         samples = b->last_block_samples;
     371           2 :         skip    = b->last_block_size - b->last_block_used_bytes;
     372             : 
     373           2 :         if (samples < size * 14 / 8) {
     374           1 :             uint32_t adjusted_size = samples / 14 * 8;
     375           1 :             if (samples % 14)
     376           1 :                 adjusted_size += (samples % 14 + 1) / 2 + 1;
     377             : 
     378           1 :             skip += size - adjusted_size;
     379           1 :             size = adjusted_size;
     380             :         }
     381          27 :     } else if (b->current_block < b->block_count) {
     382          24 :         size    = b->block_size;
     383          24 :         samples = b->samples_per_block;
     384             :     } else {
     385           3 :         return AVERROR_EOF;
     386             :     }
     387             : 
     388          31 :     if (par->codec_id == AV_CODEC_ID_ADPCM_THP ||
     389          31 :         par->codec_id == AV_CODEC_ID_ADPCM_THP_LE) {
     390             :         uint8_t *dst;
     391             : 
     392          26 :         if (!b->adpc) {
     393           0 :             av_log(s, AV_LOG_ERROR, "adpcm_thp requires ADPC chunk, but none was found.\n");
     394           0 :             return AVERROR_INVALIDDATA;
     395             :         }
     396          26 :         if (!b->table) {
     397           0 :             b->table = av_mallocz(32 * par->channels);
     398           0 :             if (!b->table)
     399           0 :                 return AVERROR(ENOMEM);
     400             :         }
     401             : 
     402          52 :         if (size > (INT_MAX - 32 - 4) ||
     403          52 :             (32 + 4 + size) > (INT_MAX / par->channels) ||
     404          26 :             (32 + 4 + size) * par->channels > INT_MAX - 8)
     405           0 :             return AVERROR_INVALIDDATA;
     406          26 :         if (av_new_packet(pkt, 8 + (32 + 4 + size) * par->channels) < 0)
     407           0 :             return AVERROR(ENOMEM);
     408          26 :         dst = pkt->data;
     409          26 :         if (par->codec_id == AV_CODEC_ID_ADPCM_THP_LE) {
     410           5 :             bytestream_put_le32(&dst, size * par->channels);
     411           5 :             bytestream_put_le32(&dst, samples);
     412             :         } else {
     413          21 :             bytestream_put_be32(&dst, size * par->channels);
     414          21 :             bytestream_put_be32(&dst, samples);
     415             :         }
     416          26 :         bytestream_put_buffer(&dst, b->table, 32 * par->channels);
     417          52 :         bytestream_put_buffer(&dst, b->adpc + 4 * par->channels *
     418          52 :                                     (b->current_block - 1), 4 * par->channels);
     419             : 
     420          76 :         for (i = 0; i < par->channels; i++) {
     421          51 :             ret = avio_read(s->pb, dst, size);
     422          51 :             dst += size;
     423          51 :             avio_skip(s->pb, skip);
     424          51 :             if (ret != size) {
     425           1 :                 av_packet_unref(pkt);
     426           1 :                 break;
     427             :             }
     428             :         }
     429          26 :         pkt->duration = samples;
     430             :     } else {
     431           0 :         size *= par->channels;
     432           0 :         ret = av_get_packet(s->pb, pkt, size);
     433             :     }
     434             : 
     435          26 :     pkt->stream_index = 0;
     436             : 
     437          26 :     if (ret != size)
     438           1 :         ret = AVERROR(EIO);
     439             : 
     440          26 :     return ret;
     441             : }
     442             : 
     443           0 : static int read_seek(AVFormatContext *s, int stream_index,
     444             :                      int64_t timestamp, int flags)
     445             : {
     446           0 :     AVStream *st = s->streams[stream_index];
     447           0 :     BRSTMDemuxContext *b = s->priv_data;
     448           0 :     int64_t ret = 0;
     449             : 
     450           0 :     timestamp /= b->samples_per_block;
     451           0 :     ret = avio_seek(s->pb, b->data_start + timestamp * b->block_size *
     452           0 :                            st->codecpar->channels, SEEK_SET);
     453           0 :     if (ret < 0)
     454           0 :         return ret;
     455             : 
     456           0 :     b->current_block = timestamp;
     457           0 :     ff_update_cur_dts(s, st, timestamp * b->samples_per_block);
     458           0 :     return 0;
     459             : }
     460             : 
     461             : AVInputFormat ff_brstm_demuxer = {
     462             :     .name           = "brstm",
     463             :     .long_name      = NULL_IF_CONFIG_SMALL("BRSTM (Binary Revolution Stream)"),
     464             :     .priv_data_size = sizeof(BRSTMDemuxContext),
     465             :     .read_probe     = probe,
     466             :     .read_header    = read_header,
     467             :     .read_packet    = read_packet,
     468             :     .read_close     = read_close,
     469             :     .read_seek      = read_seek,
     470             :     .extensions     = "brstm",
     471             : };
     472             : 
     473             : AVInputFormat ff_bfstm_demuxer = {
     474             :     .name           = "bfstm",
     475             :     .long_name      = NULL_IF_CONFIG_SMALL("BFSTM (Binary Cafe Stream)"),
     476             :     .priv_data_size = sizeof(BRSTMDemuxContext),
     477             :     .read_probe     = probe_bfstm,
     478             :     .read_header    = read_header,
     479             :     .read_packet    = read_packet,
     480             :     .read_close     = read_close,
     481             :     .read_seek      = read_seek,
     482             :     .extensions     = "bfstm,bcstm",
     483             : };

Generated by: LCOV version 1.12