"Fossies" - the Fresh Open Source Software Archive

Member "ffmpeg-4.0.1/libavformat/3dostr.c" (13 Apr 2018, 5082 Bytes) of package /linux/misc/ffmpeg-4.0.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "3dostr.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * 3DO STR demuxer
    3  * Copyright (c) 2015 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 "avformat.h"
   23 #include "internal.h"
   24 
   25 static int threedostr_probe(AVProbeData *p)
   26 {
   27     if (memcmp(p->buf, "CTRL", 4) &&
   28         memcmp(p->buf, "SHDR", 4) &&
   29         memcmp(p->buf, "SNDS", 4))
   30         return 0;
   31 
   32     return AVPROBE_SCORE_MAX / 3 * 2;
   33 }
   34 
   35 static int threedostr_read_header(AVFormatContext *s)
   36 {
   37     unsigned chunk, codec = 0, size, ctrl_size = -1, found_shdr = 0;
   38     AVStream *st;
   39 
   40     while (!avio_feof(s->pb) && !found_shdr) {
   41         chunk = avio_rl32(s->pb);
   42         size  = avio_rb32(s->pb);
   43 
   44         if (size < 8)
   45             return AVERROR_INVALIDDATA;
   46         size -= 8;
   47 
   48         switch (chunk) {
   49         case MKTAG('C','T','R','L'):
   50             ctrl_size = size;
   51             break;
   52         case MKTAG('S','N','D','S'):
   53             if (size < 56)
   54                 return AVERROR_INVALIDDATA;
   55             avio_skip(s->pb, 8);
   56             if (avio_rl32(s->pb) != MKTAG('S','H','D','R'))
   57                 return AVERROR_INVALIDDATA;
   58             avio_skip(s->pb, 24);
   59 
   60             st = avformat_new_stream(s, NULL);
   61             if (!st)
   62                 return AVERROR(ENOMEM);
   63 
   64             st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
   65             st->codecpar->sample_rate = avio_rb32(s->pb);
   66             st->codecpar->channels    = avio_rb32(s->pb);
   67             if (st->codecpar->channels <= 0)
   68                 return AVERROR_INVALIDDATA;
   69             codec                  = avio_rl32(s->pb);
   70             avio_skip(s->pb, 4);
   71             if (ctrl_size == 20 || ctrl_size == 3 || ctrl_size == -1)
   72                 st->duration       = (avio_rb32(s->pb) - 1) / st->codecpar->channels;
   73             else
   74                 st->duration       = avio_rb32(s->pb) * 16 / st->codecpar->channels;
   75             size -= 56;
   76             found_shdr = 1;
   77             break;
   78         case MKTAG('S','H','D','R'):
   79             if (size >  0x78) {
   80                 avio_skip(s->pb, 0x74);
   81                 size -= 0x78;
   82                 if (avio_rl32(s->pb) == MKTAG('C','T','R','L') && size > 4) {
   83                     ctrl_size = avio_rb32(s->pb);
   84                     size -= 4;
   85                 }
   86             }
   87             break;
   88         default:
   89             av_log(s, AV_LOG_DEBUG, "skipping unknown chunk: %X\n", chunk);
   90             break;
   91         }
   92 
   93         avio_skip(s->pb, size);
   94     }
   95 
   96     switch (codec) {
   97     case MKTAG('S','D','X','2'):
   98         st->codecpar->codec_id    = AV_CODEC_ID_SDX2_DPCM;
   99         st->codecpar->block_align = 1 * st->codecpar->channels;
  100         break;
  101     default:
  102         avpriv_request_sample(s, "codec %X", codec);
  103         return AVERROR_PATCHWELCOME;
  104     }
  105 
  106     avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
  107 
  108     return 0;
  109 }
  110 
  111 static int threedostr_read_packet(AVFormatContext *s, AVPacket *pkt)
  112 {
  113     unsigned chunk, size, found_ssmp = 0;
  114     AVStream *st = s->streams[0];
  115     int64_t pos;
  116     int ret = 0;
  117 
  118     while (!found_ssmp) {
  119         if (avio_feof(s->pb))
  120             return AVERROR_EOF;
  121 
  122         pos   = avio_tell(s->pb);
  123         chunk = avio_rl32(s->pb);
  124         size  = avio_rb32(s->pb);
  125 
  126         if (!size)
  127             continue;
  128 
  129         if (size < 8)
  130             return AVERROR_INVALIDDATA;
  131         size -= 8;
  132 
  133         switch (chunk) {
  134         case MKTAG('S','N','D','S'):
  135             if (size <= 16)
  136                 return AVERROR_INVALIDDATA;
  137             avio_skip(s->pb, 8);
  138             if (avio_rl32(s->pb) != MKTAG('S','S','M','P'))
  139                 return AVERROR_INVALIDDATA;
  140             avio_skip(s->pb, 4);
  141             size -= 16;
  142             ret = av_get_packet(s->pb, pkt, size);
  143             pkt->pos = pos;
  144             pkt->stream_index = 0;
  145             pkt->duration = size / st->codecpar->channels;
  146             size = 0;
  147             found_ssmp = 1;
  148             break;
  149         default:
  150             av_log(s, AV_LOG_DEBUG, "skipping unknown chunk: %X\n", chunk);
  151             break;
  152         }
  153 
  154         avio_skip(s->pb, size);
  155     }
  156 
  157     return ret;
  158 }
  159 
  160 AVInputFormat ff_threedostr_demuxer = {
  161     .name           = "3dostr",
  162     .long_name      = NULL_IF_CONFIG_SMALL("3DO STR"),
  163     .read_probe     = threedostr_probe,
  164     .read_header    = threedostr_read_header,
  165     .read_packet    = threedostr_read_packet,
  166     .extensions     = "str",
  167     .flags          = AVFMT_GENERIC_INDEX,
  168 };