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