LCOV - code coverage report
Current view: top level - libavformat - tiertexseq.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 131 145 90.3 %
Date: 2017-12-11 04:34:20 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Tiertex Limited SEQ File Demuxer
       3             :  * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net)
       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             : /**
      23             :  * @file
      24             :  * Tiertex Limited SEQ file demuxer
      25             :  */
      26             : 
      27             : #include "libavutil/channel_layout.h"
      28             : #include "avformat.h"
      29             : #include "internal.h"
      30             : 
      31             : #define SEQ_FRAME_SIZE         6144
      32             : #define SEQ_FRAME_W            256
      33             : #define SEQ_FRAME_H            128
      34             : #define SEQ_NUM_FRAME_BUFFERS  30
      35             : #define SEQ_AUDIO_BUFFER_SIZE  882
      36             : #define SEQ_SAMPLE_RATE        22050
      37             : #define SEQ_FRAME_RATE         25
      38             : 
      39             : 
      40             : typedef struct TiertexSeqFrameBuffer {
      41             :     int fill_size;
      42             :     int data_size;
      43             :     unsigned char *data;
      44             : } TiertexSeqFrameBuffer;
      45             : 
      46             : typedef struct SeqDemuxContext {
      47             :     int audio_stream_index;
      48             :     int video_stream_index;
      49             :     int current_frame_pts;
      50             :     int current_frame_offs;
      51             :     TiertexSeqFrameBuffer frame_buffers[SEQ_NUM_FRAME_BUFFERS];
      52             :     int frame_buffers_count;
      53             :     unsigned int current_audio_data_size;
      54             :     unsigned int current_audio_data_offs;
      55             :     unsigned int current_pal_data_size;
      56             :     unsigned int current_pal_data_offs;
      57             :     unsigned int current_video_data_size;
      58             :     unsigned char *current_video_data_ptr;
      59             :     int audio_buffer_full;
      60             : } SeqDemuxContext;
      61             : 
      62             : 
      63        6130 : static int seq_probe(AVProbeData *p)
      64             : {
      65             :     int i;
      66             : 
      67        6130 :     if (p->buf_size < 258)
      68          16 :         return 0;
      69             : 
      70             :     /* there's no real header in a .seq file, the only thing they have in common */
      71             :     /* is the first 256 bytes of the file which are always filled with 0 */
      72       14079 :     for (i = 0; i < 256; i++)
      73       14060 :         if (p->buf[i])
      74        6095 :             return 0;
      75             : 
      76          19 :     if(p->buf[256]==0 && p->buf[257]==0)
      77           9 :         return 0;
      78             : 
      79             :     /* only one fourth of the score since the previous check is too naive */
      80          10 :     return AVPROBE_SCORE_MAX / 4;
      81             : }
      82             : 
      83           1 : static int seq_init_frame_buffers(SeqDemuxContext *seq, AVIOContext *pb)
      84             : {
      85             :     int i, sz;
      86             :     TiertexSeqFrameBuffer *seq_buffer;
      87             : 
      88           1 :     avio_seek(pb, 256, SEEK_SET);
      89             : 
      90           3 :     for (i = 0; i < SEQ_NUM_FRAME_BUFFERS; i++) {
      91           3 :         sz = avio_rl16(pb);
      92           3 :         if (sz == 0)
      93           1 :             break;
      94             :         else {
      95           2 :             seq_buffer = &seq->frame_buffers[i];
      96           2 :             seq_buffer->fill_size = 0;
      97           2 :             seq_buffer->data_size = sz;
      98           2 :             seq_buffer->data = av_malloc(sz);
      99           2 :             if (!seq_buffer->data)
     100           0 :                 return AVERROR(ENOMEM);
     101             :         }
     102             :     }
     103           1 :     seq->frame_buffers_count = i;
     104           1 :     return 0;
     105             : }
     106             : 
     107          58 : static int seq_fill_buffer(SeqDemuxContext *seq, AVIOContext *pb, int buffer_num, unsigned int data_offs, int data_size)
     108             : {
     109             :     TiertexSeqFrameBuffer *seq_buffer;
     110             : 
     111          58 :     if (buffer_num >= SEQ_NUM_FRAME_BUFFERS)
     112           0 :         return AVERROR_INVALIDDATA;
     113             : 
     114          58 :     seq_buffer = &seq->frame_buffers[buffer_num];
     115          58 :     if (seq_buffer->fill_size + data_size > seq_buffer->data_size || data_size <= 0)
     116           0 :         return AVERROR_INVALIDDATA;
     117             : 
     118          58 :     avio_seek(pb, seq->current_frame_offs + data_offs, SEEK_SET);
     119          58 :     if (avio_read(pb, seq_buffer->data + seq_buffer->fill_size, data_size) != data_size)
     120           0 :         return AVERROR(EIO);
     121             : 
     122          58 :     seq_buffer->fill_size += data_size;
     123          58 :     return 0;
     124             : }
     125             : 
     126         178 : static int seq_parse_frame_data(SeqDemuxContext *seq, AVIOContext *pb)
     127             : {
     128             :     unsigned int offset_table[4], buffer_num[4];
     129             :     TiertexSeqFrameBuffer *seq_buffer;
     130             :     int i, e, err;
     131             : 
     132         178 :     seq->current_frame_offs += SEQ_FRAME_SIZE;
     133         178 :     avio_seek(pb, seq->current_frame_offs, SEEK_SET);
     134             : 
     135             :     /* sound data */
     136         178 :     seq->current_audio_data_offs = avio_rl16(pb);
     137         178 :     if (seq->current_audio_data_offs) {
     138          77 :         seq->current_audio_data_size = SEQ_AUDIO_BUFFER_SIZE * 2;
     139             :     } else {
     140         101 :         seq->current_audio_data_size = 0;
     141             :     }
     142             : 
     143             :     /* palette data */
     144         178 :     seq->current_pal_data_offs = avio_rl16(pb);
     145         178 :     if (seq->current_pal_data_offs) {
     146          21 :         seq->current_pal_data_size = 768;
     147             :     } else {
     148         157 :         seq->current_pal_data_size = 0;
     149             :     }
     150             : 
     151             :     /* video data */
     152         890 :     for (i = 0; i < 4; i++)
     153         712 :         buffer_num[i] = avio_r8(pb);
     154             : 
     155         890 :     for (i = 0; i < 4; i++)
     156         712 :         offset_table[i] = avio_rl16(pb);
     157             : 
     158         712 :     for (i = 0; i < 3; i++) {
     159         534 :         if (offset_table[i]) {
     160          58 :             for (e = i + 1; e < 3 && offset_table[e] == 0; e++);
     161          58 :             err = seq_fill_buffer(seq, pb, buffer_num[1 + i],
     162             :               offset_table[i],
     163          58 :               offset_table[e] - offset_table[i]);
     164          58 :             if (err)
     165           0 :                 return err;
     166             :         }
     167             :     }
     168             : 
     169         178 :     if (buffer_num[0] != 255) {
     170          22 :         if (buffer_num[0] >= SEQ_NUM_FRAME_BUFFERS)
     171           0 :             return AVERROR_INVALIDDATA;
     172             : 
     173          22 :         seq_buffer = &seq->frame_buffers[buffer_num[0]];
     174          22 :         seq->current_video_data_size = seq_buffer->fill_size;
     175          22 :         seq->current_video_data_ptr  = seq_buffer->data;
     176          22 :         seq_buffer->fill_size = 0;
     177             :     } else {
     178         156 :         seq->current_video_data_size = 0;
     179         156 :         seq->current_video_data_ptr  = 0;
     180             :     }
     181             : 
     182         178 :     return 0;
     183             : }
     184             : 
     185           1 : static int seq_read_header(AVFormatContext *s)
     186             : {
     187             :     int i, rc;
     188           1 :     SeqDemuxContext *seq = s->priv_data;
     189           1 :     AVIOContext *pb = s->pb;
     190             :     AVStream *st;
     191             : 
     192             :     /* init internal buffers */
     193           1 :     rc = seq_init_frame_buffers(seq, pb);
     194           1 :     if (rc)
     195           0 :         return rc;
     196             : 
     197           1 :     seq->current_frame_offs = 0;
     198             : 
     199             :     /* preload (no audio data, just buffer operations related data) */
     200         101 :     for (i = 1; i <= 100; i++) {
     201         100 :         rc = seq_parse_frame_data(seq, pb);
     202         100 :         if (rc)
     203           0 :             return rc;
     204             :     }
     205             : 
     206           1 :     seq->current_frame_pts = 0;
     207             : 
     208           1 :     seq->audio_buffer_full = 0;
     209             : 
     210             :     /* initialize the video decoder stream */
     211           1 :     st = avformat_new_stream(s, NULL);
     212           1 :     if (!st)
     213           0 :         return AVERROR(ENOMEM);
     214             : 
     215           1 :     avpriv_set_pts_info(st, 32, 1, SEQ_FRAME_RATE);
     216           1 :     seq->video_stream_index = st->index;
     217           1 :     st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
     218           1 :     st->codecpar->codec_id = AV_CODEC_ID_TIERTEXSEQVIDEO;
     219           1 :     st->codecpar->codec_tag = 0;  /* no fourcc */
     220           1 :     st->codecpar->width = SEQ_FRAME_W;
     221           1 :     st->codecpar->height = SEQ_FRAME_H;
     222             : 
     223             :     /* initialize the audio decoder stream */
     224           1 :     st = avformat_new_stream(s, NULL);
     225           1 :     if (!st)
     226           0 :         return AVERROR(ENOMEM);
     227             : 
     228           1 :     st->start_time = 0;
     229           1 :     avpriv_set_pts_info(st, 32, 1, SEQ_SAMPLE_RATE);
     230           1 :     seq->audio_stream_index = st->index;
     231           1 :     st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
     232           1 :     st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
     233           1 :     st->codecpar->codec_tag = 0;  /* no tag */
     234           1 :     st->codecpar->channels = 1;
     235           1 :     st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
     236           1 :     st->codecpar->sample_rate = SEQ_SAMPLE_RATE;
     237           1 :     st->codecpar->bits_per_coded_sample = 16;
     238           1 :     st->codecpar->bit_rate = st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample * st->codecpar->channels;
     239           1 :     st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample / 8;
     240             : 
     241           1 :     return 0;
     242             : }
     243             : 
     244          99 : static int seq_read_packet(AVFormatContext *s, AVPacket *pkt)
     245             : {
     246             :     int rc;
     247          99 :     SeqDemuxContext *seq = s->priv_data;
     248          99 :     AVIOContext *pb = s->pb;
     249             : 
     250          99 :     if (!seq->audio_buffer_full) {
     251          78 :         rc = seq_parse_frame_data(seq, pb);
     252          78 :         if (rc)
     253           0 :             return rc;
     254             : 
     255             :         /* video packet */
     256          78 :         if (seq->current_pal_data_size + seq->current_video_data_size != 0) {
     257          21 :             if (av_new_packet(pkt, 1 + seq->current_pal_data_size + seq->current_video_data_size))
     258           0 :                 return AVERROR(ENOMEM);
     259             : 
     260          21 :             pkt->data[0] = 0;
     261          21 :             if (seq->current_pal_data_size) {
     262          21 :                 pkt->data[0] |= 1;
     263          21 :                 avio_seek(pb, seq->current_frame_offs + seq->current_pal_data_offs, SEEK_SET);
     264          21 :                 if (avio_read(pb, &pkt->data[1], seq->current_pal_data_size) != seq->current_pal_data_size)
     265           0 :                     return AVERROR(EIO);
     266             :             }
     267          21 :             if (seq->current_video_data_size) {
     268          21 :                 pkt->data[0] |= 2;
     269          42 :                 memcpy(&pkt->data[1 + seq->current_pal_data_size],
     270          21 :                   seq->current_video_data_ptr,
     271          21 :                   seq->current_video_data_size);
     272             :             }
     273          21 :             pkt->stream_index = seq->video_stream_index;
     274          21 :             pkt->pts = seq->current_frame_pts;
     275             : 
     276             :             /* sound buffer will be processed on next read_packet() call */
     277          21 :             seq->audio_buffer_full = 1;
     278          21 :             return 0;
     279             :        }
     280             :     }
     281             : 
     282             :     /* audio packet */
     283          78 :     if (seq->current_audio_data_offs == 0) /* end of data reached */
     284           1 :         return AVERROR(EIO);
     285             : 
     286          77 :     avio_seek(pb, seq->current_frame_offs + seq->current_audio_data_offs, SEEK_SET);
     287          77 :     rc = av_get_packet(pb, pkt, seq->current_audio_data_size);
     288          77 :     if (rc < 0)
     289           0 :         return rc;
     290             : 
     291          77 :     pkt->stream_index = seq->audio_stream_index;
     292          77 :     seq->current_frame_pts++;
     293             : 
     294          77 :     seq->audio_buffer_full = 0;
     295          77 :     return 0;
     296             : }
     297             : 
     298           1 : static int seq_read_close(AVFormatContext *s)
     299             : {
     300             :     int i;
     301           1 :     SeqDemuxContext *seq = s->priv_data;
     302             : 
     303          31 :     for (i = 0; i < SEQ_NUM_FRAME_BUFFERS; i++)
     304          30 :         av_freep(&seq->frame_buffers[i].data);
     305             : 
     306           1 :     return 0;
     307             : }
     308             : 
     309             : AVInputFormat ff_tiertexseq_demuxer = {
     310             :     .name           = "tiertexseq",
     311             :     .long_name      = NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ"),
     312             :     .priv_data_size = sizeof(SeqDemuxContext),
     313             :     .read_probe     = seq_probe,
     314             :     .read_header    = seq_read_header,
     315             :     .read_packet    = seq_read_packet,
     316             :     .read_close     = seq_read_close,
     317             : };

Generated by: LCOV version 1.13