LCOV - code coverage report
Current view: top level - libavformat - avs.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 101 114 88.6 %
Date: 2017-12-13 18:07:29 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * AVS demuxer.
       3             :  * Copyright (c) 2006  Aurelien Jacobs <aurel@gnuage.org>
       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 "voc.h"
      24             : 
      25             : 
      26             : typedef struct avs_format {
      27             :     VocDecContext voc;
      28             :     AVStream *st_video;
      29             :     AVStream *st_audio;
      30             :     int width;
      31             :     int height;
      32             :     int bits_per_sample;
      33             :     int fps;
      34             :     int nb_frames;
      35             :     int remaining_frame_size;
      36             :     int remaining_audio_size;
      37             : } AvsFormat;
      38             : 
      39             : typedef enum avs_block_type {
      40             :     AVS_NONE      = 0x00,
      41             :     AVS_VIDEO     = 0x01,
      42             :     AVS_AUDIO     = 0x02,
      43             :     AVS_PALETTE   = 0x03,
      44             :     AVS_GAME_DATA = 0x04,
      45             : } AvsBlockType;
      46             : 
      47        6130 : static int avs_probe(AVProbeData * p)
      48             : {
      49             :     const uint8_t *d;
      50             : 
      51        6130 :     d = p->buf;
      52        6130 :     if (d[0] == 'w' && d[1] == 'W' && d[2] == 0x10 && d[3] == 0)
      53             :         /* Ensure the buffer probe scores higher than the extension probe.
      54             :          * This avoids problems with misdetection as AviSynth scripts. */
      55           1 :         return AVPROBE_SCORE_EXTENSION + 5;
      56             : 
      57        6129 :     return 0;
      58             : }
      59             : 
      60           1 : static int avs_read_header(AVFormatContext * s)
      61             : {
      62           1 :     AvsFormat *avs = s->priv_data;
      63             : 
      64           1 :     s->ctx_flags |= AVFMTCTX_NOHEADER;
      65             : 
      66           1 :     avio_skip(s->pb, 4);
      67           1 :     avs->width = avio_rl16(s->pb);
      68           1 :     avs->height = avio_rl16(s->pb);
      69           1 :     avs->bits_per_sample = avio_rl16(s->pb);
      70           1 :     avs->fps = avio_rl16(s->pb);
      71           1 :     avs->nb_frames = avio_rl32(s->pb);
      72           1 :     avs->remaining_frame_size = 0;
      73           1 :     avs->remaining_audio_size = 0;
      74             : 
      75           1 :     avs->st_video = avs->st_audio = NULL;
      76             : 
      77           1 :     if (avs->width != 318 || avs->height != 198)
      78           0 :         av_log(s, AV_LOG_ERROR, "This avs pretend to be %dx%d "
      79             :                "when the avs format is supposed to be 318x198 only.\n",
      80             :                avs->width, avs->height);
      81             : 
      82           1 :     return 0;
      83             : }
      84             : 
      85             : static int
      86          56 : avs_read_video_packet(AVFormatContext * s, AVPacket * pkt,
      87             :                       AvsBlockType type, int sub_type, int size,
      88             :                       uint8_t * palette, int palette_size)
      89             : {
      90          56 :     AvsFormat *avs = s->priv_data;
      91             :     int ret;
      92             : 
      93          56 :     ret = av_new_packet(pkt, size + palette_size);
      94          56 :     if (ret < 0)
      95           0 :         return ret;
      96             : 
      97          56 :     if (palette_size) {
      98           1 :         pkt->data[0] = 0x00;
      99           1 :         pkt->data[1] = 0x03;
     100           1 :         pkt->data[2] = palette_size & 0xFF;
     101           1 :         pkt->data[3] = (palette_size >> 8) & 0xFF;
     102           1 :         memcpy(pkt->data + 4, palette, palette_size - 4);
     103             :     }
     104             : 
     105          56 :     pkt->data[palette_size + 0] = sub_type;
     106          56 :     pkt->data[palette_size + 1] = type;
     107          56 :     pkt->data[palette_size + 2] = size & 0xFF;
     108          56 :     pkt->data[palette_size + 3] = (size >> 8) & 0xFF;
     109          56 :     ret = avio_read(s->pb, pkt->data + palette_size + 4, size - 4) + 4;
     110          56 :     if (ret < size) {
     111           0 :         av_packet_unref(pkt);
     112           0 :         return AVERROR(EIO);
     113             :     }
     114             : 
     115          56 :     pkt->size = ret + palette_size;
     116          56 :     pkt->stream_index = avs->st_video->index;
     117          56 :     if (sub_type == 0)
     118           5 :         pkt->flags |= AV_PKT_FLAG_KEY;
     119             : 
     120          56 :     return 0;
     121             : }
     122             : 
     123          37 : static int avs_read_audio_packet(AVFormatContext * s, AVPacket * pkt)
     124             : {
     125          37 :     AvsFormat *avs = s->priv_data;
     126             :     int ret, size;
     127             : 
     128          37 :     size = avio_tell(s->pb);
     129          37 :     ret = ff_voc_get_packet(s, pkt, avs->st_audio, avs->remaining_audio_size);
     130          37 :     size = avio_tell(s->pb) - size;
     131          37 :     avs->remaining_audio_size -= size;
     132             : 
     133          37 :     if (ret == AVERROR(EIO))
     134           0 :         return 0;    /* this indicate EOS */
     135          37 :     if (ret < 0)
     136           1 :         return ret;
     137             : 
     138          36 :     pkt->stream_index = avs->st_audio->index;
     139          36 :     pkt->flags |= AV_PKT_FLAG_KEY;
     140             : 
     141          36 :     return size;
     142             : }
     143             : 
     144          94 : static int avs_read_packet(AVFormatContext * s, AVPacket * pkt)
     145             : {
     146          94 :     AvsFormat *avs = s->priv_data;
     147          94 :     int sub_type = 0, size = 0;
     148          94 :     AvsBlockType type = AVS_NONE;
     149          94 :     int palette_size = 0;
     150             :     uint8_t palette[4 + 3 * 256];
     151             :     int ret;
     152             : 
     153          94 :     if (avs->remaining_audio_size > 0)
     154          10 :         if (avs_read_audio_packet(s, pkt) > 0)
     155           9 :             return 0;
     156             : 
     157             :     while (1) {
     158          85 :         if (avs->remaining_frame_size <= 0) {
     159          58 :             if (!avio_rl16(s->pb))    /* found EOF */
     160           2 :                 return AVERROR(EIO);
     161          56 :             avs->remaining_frame_size = avio_rl16(s->pb) - 4;
     162             :         }
     163             : 
     164         167 :         while (avs->remaining_frame_size > 0) {
     165          84 :             sub_type = avio_r8(s->pb);
     166          84 :             type = avio_r8(s->pb);
     167          84 :             size = avio_rl16(s->pb);
     168          84 :             if (size < 4)
     169           0 :                 return AVERROR_INVALIDDATA;
     170          84 :             avs->remaining_frame_size -= size;
     171             : 
     172          84 :             switch (type) {
     173           1 :             case AVS_PALETTE:
     174           1 :                 if (size - 4 > sizeof(palette))
     175           0 :                     return AVERROR_INVALIDDATA;
     176           1 :                 ret = avio_read(s->pb, palette, size - 4);
     177           1 :                 if (ret < size - 4)
     178           0 :                     return AVERROR(EIO);
     179           1 :                 palette_size = size;
     180           1 :                 break;
     181             : 
     182          56 :             case AVS_VIDEO:
     183          56 :                 if (!avs->st_video) {
     184           1 :                     avs->st_video = avformat_new_stream(s, NULL);
     185           1 :                     if (!avs->st_video)
     186           0 :                         return AVERROR(ENOMEM);
     187           1 :                     avs->st_video->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
     188           1 :                     avs->st_video->codecpar->codec_id = AV_CODEC_ID_AVS;
     189           1 :                     avs->st_video->codecpar->width = avs->width;
     190           1 :                     avs->st_video->codecpar->height = avs->height;
     191           1 :                     avs->st_video->codecpar->bits_per_coded_sample=avs->bits_per_sample;
     192           1 :                     avs->st_video->nb_frames = avs->nb_frames;
     193             : #if FF_API_R_FRAME_RATE
     194           1 :                     avs->st_video->r_frame_rate =
     195             : #endif
     196           1 :                     avs->st_video->avg_frame_rate = (AVRational){avs->fps, 1};
     197             :                 }
     198          56 :                 return avs_read_video_packet(s, pkt, type, sub_type, size,
     199             :                                              palette, palette_size);
     200             : 
     201          27 :             case AVS_AUDIO:
     202          27 :                 if (!avs->st_audio) {
     203           1 :                     avs->st_audio = avformat_new_stream(s, NULL);
     204           1 :                     if (!avs->st_audio)
     205           0 :                         return AVERROR(ENOMEM);
     206           1 :                     avs->st_audio->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
     207             :                 }
     208          27 :                 avs->remaining_audio_size = size - 4;
     209          27 :                 size = avs_read_audio_packet(s, pkt);
     210          27 :                 if (size != 0)
     211          27 :                     return size;
     212           0 :                 break;
     213             : 
     214           0 :             default:
     215           0 :                 avio_skip(s->pb, size - 4);
     216             :             }
     217             :         }
     218             :     }
     219             : }
     220             : 
     221           1 : static int avs_read_close(AVFormatContext * s)
     222             : {
     223           1 :     return 0;
     224             : }
     225             : 
     226             : AVInputFormat ff_avs_demuxer = {
     227             :     .name           = "avs",
     228             :     .long_name      = NULL_IF_CONFIG_SMALL("AVS"),
     229             :     .priv_data_size = sizeof(AvsFormat),
     230             :     .read_probe     = avs_probe,
     231             :     .read_header    = avs_read_header,
     232             :     .read_packet    = avs_read_packet,
     233             :     .read_close     = avs_read_close,
     234             : };

Generated by: LCOV version 1.13