• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavformat/tiertexseq.c

Go to the documentation of this file.
00001 /*
00002  * Tiertex Limited SEQ File Demuxer
00003  * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net)
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00027 #include "avformat.h"
00028 
00029 #define SEQ_FRAME_SIZE         6144
00030 #define SEQ_FRAME_W            256
00031 #define SEQ_FRAME_H            128
00032 #define SEQ_NUM_FRAME_BUFFERS  30
00033 #define SEQ_AUDIO_BUFFER_SIZE  882
00034 #define SEQ_SAMPLE_RATE        22050
00035 #define SEQ_FRAME_RATE         25
00036 
00037 
00038 typedef struct TiertexSeqFrameBuffer {
00039     int fill_size;
00040     int data_size;
00041     unsigned char *data;
00042 } TiertexSeqFrameBuffer;
00043 
00044 typedef struct SeqDemuxContext {
00045     int audio_stream_index;
00046     int video_stream_index;
00047     int current_frame_pts;
00048     int current_frame_offs;
00049     TiertexSeqFrameBuffer frame_buffers[SEQ_NUM_FRAME_BUFFERS];
00050     int frame_buffers_count;
00051     unsigned int current_audio_data_size;
00052     unsigned int current_audio_data_offs;
00053     unsigned int current_pal_data_size;
00054     unsigned int current_pal_data_offs;
00055     unsigned int current_video_data_size;
00056     unsigned char *current_video_data_ptr;
00057     int audio_buffer_full;
00058 } SeqDemuxContext;
00059 
00060 
00061 static int seq_probe(AVProbeData *p)
00062 {
00063     int i;
00064 
00065     if (p->buf_size < 258)
00066         return 0;
00067 
00068     /* there's no real header in a .seq file, the only thing they have in common */
00069     /* is the first 256 bytes of the file which are always filled with 0 */
00070     for (i = 0; i < 256; i++)
00071         if (p->buf[i])
00072             return 0;
00073 
00074     if(p->buf[256]==0 && p->buf[257]==0)
00075         return 0;
00076 
00077     /* only one fourth of the score since the previous check is too naive */
00078     return AVPROBE_SCORE_MAX / 4;
00079 }
00080 
00081 static int seq_init_frame_buffers(SeqDemuxContext *seq, ByteIOContext *pb)
00082 {
00083     int i, sz;
00084     TiertexSeqFrameBuffer *seq_buffer;
00085 
00086     url_fseek(pb, 256, SEEK_SET);
00087 
00088     for (i = 0; i < SEQ_NUM_FRAME_BUFFERS; i++) {
00089         sz = get_le16(pb);
00090         if (sz == 0)
00091             break;
00092         else {
00093             seq_buffer = &seq->frame_buffers[i];
00094             seq_buffer->fill_size = 0;
00095             seq_buffer->data_size = sz;
00096             seq_buffer->data = av_malloc(sz);
00097             if (!seq_buffer->data)
00098                 return AVERROR(ENOMEM);
00099         }
00100     }
00101     seq->frame_buffers_count = i;
00102     return 0;
00103 }
00104 
00105 static int seq_fill_buffer(SeqDemuxContext *seq, ByteIOContext *pb, int buffer_num, unsigned int data_offs, int data_size)
00106 {
00107     TiertexSeqFrameBuffer *seq_buffer;
00108 
00109     if (buffer_num >= SEQ_NUM_FRAME_BUFFERS)
00110         return AVERROR_INVALIDDATA;
00111 
00112     seq_buffer = &seq->frame_buffers[buffer_num];
00113     if (seq_buffer->fill_size + data_size > seq_buffer->data_size || data_size <= 0)
00114         return AVERROR_INVALIDDATA;
00115 
00116     url_fseek(pb, seq->current_frame_offs + data_offs, SEEK_SET);
00117     if (get_buffer(pb, seq_buffer->data + seq_buffer->fill_size, data_size) != data_size)
00118         return AVERROR(EIO);
00119 
00120     seq_buffer->fill_size += data_size;
00121     return 0;
00122 }
00123 
00124 static int seq_parse_frame_data(SeqDemuxContext *seq, ByteIOContext *pb)
00125 {
00126     unsigned int offset_table[4], buffer_num[4];
00127     TiertexSeqFrameBuffer *seq_buffer;
00128     int i, e, err;
00129 
00130     seq->current_frame_offs += SEQ_FRAME_SIZE;
00131     url_fseek(pb, seq->current_frame_offs, SEEK_SET);
00132 
00133     /* sound data */
00134     seq->current_audio_data_offs = get_le16(pb);
00135     if (seq->current_audio_data_offs) {
00136         seq->current_audio_data_size = SEQ_AUDIO_BUFFER_SIZE * 2;
00137     } else {
00138         seq->current_audio_data_size = 0;
00139     }
00140 
00141     /* palette data */
00142     seq->current_pal_data_offs = get_le16(pb);
00143     if (seq->current_pal_data_offs) {
00144         seq->current_pal_data_size = 768;
00145     } else {
00146         seq->current_pal_data_size = 0;
00147     }
00148 
00149     /* video data */
00150     for (i = 0; i < 4; i++)
00151         buffer_num[i] = get_byte(pb);
00152 
00153     for (i = 0; i < 4; i++)
00154         offset_table[i] = get_le16(pb);
00155 
00156     for (i = 0; i < 3; i++) {
00157         if (offset_table[i]) {
00158             for (e = i + 1; e < 3 && offset_table[e] == 0; e++);
00159             err = seq_fill_buffer(seq, pb, buffer_num[1 + i],
00160               offset_table[i],
00161               offset_table[e] - offset_table[i]);
00162             if (err)
00163                 return err;
00164         }
00165     }
00166 
00167     if (buffer_num[0] != 255) {
00168         if (buffer_num[0] >= SEQ_NUM_FRAME_BUFFERS)
00169             return AVERROR_INVALIDDATA;
00170 
00171         seq_buffer = &seq->frame_buffers[buffer_num[0]];
00172         seq->current_video_data_size = seq_buffer->fill_size;
00173         seq->current_video_data_ptr  = seq_buffer->data;
00174         seq_buffer->fill_size = 0;
00175     } else {
00176         seq->current_video_data_size = 0;
00177         seq->current_video_data_ptr  = 0;
00178     }
00179 
00180     return 0;
00181 }
00182 
00183 static int seq_read_header(AVFormatContext *s, AVFormatParameters *ap)
00184 {
00185     int i, rc;
00186     SeqDemuxContext *seq = s->priv_data;
00187     ByteIOContext *pb = s->pb;
00188     AVStream *st;
00189 
00190     /* init internal buffers */
00191     rc = seq_init_frame_buffers(seq, pb);
00192     if (rc)
00193         return rc;
00194 
00195     seq->current_frame_offs = 0;
00196 
00197     /* preload (no audio data, just buffer operations related data) */
00198     for (i = 1; i <= 100; i++) {
00199         rc = seq_parse_frame_data(seq, pb);
00200         if (rc)
00201             return rc;
00202     }
00203 
00204     seq->current_frame_pts = 0;
00205 
00206     seq->audio_buffer_full = 0;
00207 
00208     /* initialize the video decoder stream */
00209     st = av_new_stream(s, 0);
00210     if (!st)
00211         return AVERROR(ENOMEM);
00212 
00213     av_set_pts_info(st, 32, 1, SEQ_FRAME_RATE);
00214     seq->video_stream_index = st->index;
00215     st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00216     st->codec->codec_id = CODEC_ID_TIERTEXSEQVIDEO;
00217     st->codec->codec_tag = 0;  /* no fourcc */
00218     st->codec->width = SEQ_FRAME_W;
00219     st->codec->height = SEQ_FRAME_H;
00220 
00221     /* initialize the audio decoder stream */
00222     st = av_new_stream(s, 0);
00223     if (!st)
00224         return AVERROR(ENOMEM);
00225 
00226     av_set_pts_info(st, 32, 1, SEQ_SAMPLE_RATE);
00227     seq->audio_stream_index = st->index;
00228     st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00229     st->codec->codec_id = CODEC_ID_PCM_S16BE;
00230     st->codec->codec_tag = 0;  /* no tag */
00231     st->codec->channels = 1;
00232     st->codec->sample_rate = SEQ_SAMPLE_RATE;
00233     st->codec->bits_per_coded_sample = 16;
00234     st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_coded_sample * st->codec->channels;
00235     st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
00236 
00237     return 0;
00238 }
00239 
00240 static int seq_read_packet(AVFormatContext *s, AVPacket *pkt)
00241 {
00242     int rc;
00243     SeqDemuxContext *seq = s->priv_data;
00244     ByteIOContext *pb = s->pb;
00245 
00246     if (!seq->audio_buffer_full) {
00247         rc = seq_parse_frame_data(seq, pb);
00248         if (rc)
00249             return rc;
00250 
00251         /* video packet */
00252         if (seq->current_pal_data_size + seq->current_video_data_size != 0) {
00253             if (av_new_packet(pkt, 1 + seq->current_pal_data_size + seq->current_video_data_size))
00254                 return AVERROR(ENOMEM);
00255 
00256             pkt->data[0] = 0;
00257             if (seq->current_pal_data_size) {
00258                 pkt->data[0] |= 1;
00259                 url_fseek(pb, seq->current_frame_offs + seq->current_pal_data_offs, SEEK_SET);
00260                 if (get_buffer(pb, &pkt->data[1], seq->current_pal_data_size) != seq->current_pal_data_size)
00261                     return AVERROR(EIO);
00262             }
00263             if (seq->current_video_data_size) {
00264                 pkt->data[0] |= 2;
00265                 memcpy(&pkt->data[1 + seq->current_pal_data_size],
00266                   seq->current_video_data_ptr,
00267                   seq->current_video_data_size);
00268             }
00269             pkt->stream_index = seq->video_stream_index;
00270             pkt->pts = seq->current_frame_pts;
00271 
00272             /* sound buffer will be processed on next read_packet() call */
00273             seq->audio_buffer_full = 1;
00274             return 0;
00275        }
00276     }
00277 
00278     /* audio packet */
00279     if (seq->current_audio_data_offs == 0) /* end of data reached */
00280         return AVERROR(EIO);
00281 
00282     url_fseek(pb, seq->current_frame_offs + seq->current_audio_data_offs, SEEK_SET);
00283     rc = av_get_packet(pb, pkt, seq->current_audio_data_size);
00284     if (rc < 0)
00285         return rc;
00286 
00287     pkt->stream_index = seq->audio_stream_index;
00288     seq->current_frame_pts++;
00289 
00290     seq->audio_buffer_full = 0;
00291     return 0;
00292 }
00293 
00294 static int seq_read_close(AVFormatContext *s)
00295 {
00296     int i;
00297     SeqDemuxContext *seq = s->priv_data;
00298 
00299     for (i = 0; i < SEQ_NUM_FRAME_BUFFERS; i++)
00300         av_free(seq->frame_buffers[i].data);
00301 
00302     return 0;
00303 }
00304 
00305 AVInputFormat tiertexseq_demuxer = {
00306     "tiertexseq",
00307     NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ format"),
00308     sizeof(SeqDemuxContext),
00309     seq_probe,
00310     seq_read_header,
00311     seq_read_packet,
00312     seq_read_close,
00313 };

Generated on Fri Sep 16 2011 17:17:51 for FFmpeg by  doxygen 1.7.1