00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "avformat.h"
00028 #include "internal.h"
00029
00030 #define SEQ_FRAME_SIZE 6144
00031 #define SEQ_FRAME_W 256
00032 #define SEQ_FRAME_H 128
00033 #define SEQ_NUM_FRAME_BUFFERS 30
00034 #define SEQ_AUDIO_BUFFER_SIZE 882
00035 #define SEQ_SAMPLE_RATE 22050
00036 #define SEQ_FRAME_RATE 25
00037
00038
00039 typedef struct TiertexSeqFrameBuffer {
00040 int fill_size;
00041 int data_size;
00042 unsigned char *data;
00043 } TiertexSeqFrameBuffer;
00044
00045 typedef struct SeqDemuxContext {
00046 int audio_stream_index;
00047 int video_stream_index;
00048 int current_frame_pts;
00049 int current_frame_offs;
00050 TiertexSeqFrameBuffer frame_buffers[SEQ_NUM_FRAME_BUFFERS];
00051 int frame_buffers_count;
00052 unsigned int current_audio_data_size;
00053 unsigned int current_audio_data_offs;
00054 unsigned int current_pal_data_size;
00055 unsigned int current_pal_data_offs;
00056 unsigned int current_video_data_size;
00057 unsigned char *current_video_data_ptr;
00058 int audio_buffer_full;
00059 } SeqDemuxContext;
00060
00061
00062 static int seq_probe(AVProbeData *p)
00063 {
00064 int i;
00065
00066 if (p->buf_size < 258)
00067 return 0;
00068
00069
00070
00071 for (i = 0; i < 256; i++)
00072 if (p->buf[i])
00073 return 0;
00074
00075 if(p->buf[256]==0 && p->buf[257]==0)
00076 return 0;
00077
00078
00079 return AVPROBE_SCORE_MAX / 4;
00080 }
00081
00082 static int seq_init_frame_buffers(SeqDemuxContext *seq, AVIOContext *pb)
00083 {
00084 int i, sz;
00085 TiertexSeqFrameBuffer *seq_buffer;
00086
00087 avio_seek(pb, 256, SEEK_SET);
00088
00089 for (i = 0; i < SEQ_NUM_FRAME_BUFFERS; i++) {
00090 sz = avio_rl16(pb);
00091 if (sz == 0)
00092 break;
00093 else {
00094 seq_buffer = &seq->frame_buffers[i];
00095 seq_buffer->fill_size = 0;
00096 seq_buffer->data_size = sz;
00097 seq_buffer->data = av_malloc(sz);
00098 if (!seq_buffer->data)
00099 return AVERROR(ENOMEM);
00100 }
00101 }
00102 seq->frame_buffers_count = i;
00103 return 0;
00104 }
00105
00106 static int seq_fill_buffer(SeqDemuxContext *seq, AVIOContext *pb, int buffer_num, unsigned int data_offs, int data_size)
00107 {
00108 TiertexSeqFrameBuffer *seq_buffer;
00109
00110 if (buffer_num >= SEQ_NUM_FRAME_BUFFERS)
00111 return AVERROR_INVALIDDATA;
00112
00113 seq_buffer = &seq->frame_buffers[buffer_num];
00114 if (seq_buffer->fill_size + data_size > seq_buffer->data_size || data_size <= 0)
00115 return AVERROR_INVALIDDATA;
00116
00117 avio_seek(pb, seq->current_frame_offs + data_offs, SEEK_SET);
00118 if (avio_read(pb, seq_buffer->data + seq_buffer->fill_size, data_size) != data_size)
00119 return AVERROR(EIO);
00120
00121 seq_buffer->fill_size += data_size;
00122 return 0;
00123 }
00124
00125 static int seq_parse_frame_data(SeqDemuxContext *seq, AVIOContext *pb)
00126 {
00127 unsigned int offset_table[4], buffer_num[4];
00128 TiertexSeqFrameBuffer *seq_buffer;
00129 int i, e, err;
00130
00131 seq->current_frame_offs += SEQ_FRAME_SIZE;
00132 avio_seek(pb, seq->current_frame_offs, SEEK_SET);
00133
00134
00135 seq->current_audio_data_offs = avio_rl16(pb);
00136 if (seq->current_audio_data_offs) {
00137 seq->current_audio_data_size = SEQ_AUDIO_BUFFER_SIZE * 2;
00138 } else {
00139 seq->current_audio_data_size = 0;
00140 }
00141
00142
00143 seq->current_pal_data_offs = avio_rl16(pb);
00144 if (seq->current_pal_data_offs) {
00145 seq->current_pal_data_size = 768;
00146 } else {
00147 seq->current_pal_data_size = 0;
00148 }
00149
00150
00151 for (i = 0; i < 4; i++)
00152 buffer_num[i] = avio_r8(pb);
00153
00154 for (i = 0; i < 4; i++)
00155 offset_table[i] = avio_rl16(pb);
00156
00157 for (i = 0; i < 3; i++) {
00158 if (offset_table[i]) {
00159 for (e = i + 1; e < 3 && offset_table[e] == 0; e++);
00160 err = seq_fill_buffer(seq, pb, buffer_num[1 + i],
00161 offset_table[i],
00162 offset_table[e] - offset_table[i]);
00163 if (err)
00164 return err;
00165 }
00166 }
00167
00168 if (buffer_num[0] != 255) {
00169 if (buffer_num[0] >= SEQ_NUM_FRAME_BUFFERS)
00170 return AVERROR_INVALIDDATA;
00171
00172 seq_buffer = &seq->frame_buffers[buffer_num[0]];
00173 seq->current_video_data_size = seq_buffer->fill_size;
00174 seq->current_video_data_ptr = seq_buffer->data;
00175 seq_buffer->fill_size = 0;
00176 } else {
00177 seq->current_video_data_size = 0;
00178 seq->current_video_data_ptr = 0;
00179 }
00180
00181 return 0;
00182 }
00183
00184 static int seq_read_header(AVFormatContext *s)
00185 {
00186 int i, rc;
00187 SeqDemuxContext *seq = s->priv_data;
00188 AVIOContext *pb = s->pb;
00189 AVStream *st;
00190
00191
00192 rc = seq_init_frame_buffers(seq, pb);
00193 if (rc)
00194 return rc;
00195
00196 seq->current_frame_offs = 0;
00197
00198
00199 for (i = 1; i <= 100; i++) {
00200 rc = seq_parse_frame_data(seq, pb);
00201 if (rc)
00202 return rc;
00203 }
00204
00205 seq->current_frame_pts = 0;
00206
00207 seq->audio_buffer_full = 0;
00208
00209
00210 st = avformat_new_stream(s, NULL);
00211 if (!st)
00212 return AVERROR(ENOMEM);
00213
00214 avpriv_set_pts_info(st, 32, 1, SEQ_FRAME_RATE);
00215 seq->video_stream_index = st->index;
00216 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00217 st->codec->codec_id = AV_CODEC_ID_TIERTEXSEQVIDEO;
00218 st->codec->codec_tag = 0;
00219 st->codec->width = SEQ_FRAME_W;
00220 st->codec->height = SEQ_FRAME_H;
00221
00222
00223 st = avformat_new_stream(s, NULL);
00224 if (!st)
00225 return AVERROR(ENOMEM);
00226
00227 st->start_time = 0;
00228 avpriv_set_pts_info(st, 32, 1, SEQ_SAMPLE_RATE);
00229 seq->audio_stream_index = st->index;
00230 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00231 st->codec->codec_id = AV_CODEC_ID_PCM_S16BE;
00232 st->codec->codec_tag = 0;
00233 st->codec->channels = 1;
00234 st->codec->sample_rate = SEQ_SAMPLE_RATE;
00235 st->codec->bits_per_coded_sample = 16;
00236 st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_coded_sample * st->codec->channels;
00237 st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample / 8;
00238
00239 return 0;
00240 }
00241
00242 static int seq_read_packet(AVFormatContext *s, AVPacket *pkt)
00243 {
00244 int rc;
00245 SeqDemuxContext *seq = s->priv_data;
00246 AVIOContext *pb = s->pb;
00247
00248 if (!seq->audio_buffer_full) {
00249 rc = seq_parse_frame_data(seq, pb);
00250 if (rc)
00251 return rc;
00252
00253
00254 if (seq->current_pal_data_size + seq->current_video_data_size != 0) {
00255 if (av_new_packet(pkt, 1 + seq->current_pal_data_size + seq->current_video_data_size))
00256 return AVERROR(ENOMEM);
00257
00258 pkt->data[0] = 0;
00259 if (seq->current_pal_data_size) {
00260 pkt->data[0] |= 1;
00261 avio_seek(pb, seq->current_frame_offs + seq->current_pal_data_offs, SEEK_SET);
00262 if (avio_read(pb, &pkt->data[1], seq->current_pal_data_size) != seq->current_pal_data_size)
00263 return AVERROR(EIO);
00264 }
00265 if (seq->current_video_data_size) {
00266 pkt->data[0] |= 2;
00267 memcpy(&pkt->data[1 + seq->current_pal_data_size],
00268 seq->current_video_data_ptr,
00269 seq->current_video_data_size);
00270 }
00271 pkt->stream_index = seq->video_stream_index;
00272 pkt->pts = seq->current_frame_pts;
00273
00274
00275 seq->audio_buffer_full = 1;
00276 return 0;
00277 }
00278 }
00279
00280
00281 if (seq->current_audio_data_offs == 0)
00282 return AVERROR(EIO);
00283
00284 avio_seek(pb, seq->current_frame_offs + seq->current_audio_data_offs, SEEK_SET);
00285 rc = av_get_packet(pb, pkt, seq->current_audio_data_size);
00286 if (rc < 0)
00287 return rc;
00288
00289 pkt->stream_index = seq->audio_stream_index;
00290 seq->current_frame_pts++;
00291
00292 seq->audio_buffer_full = 0;
00293 return 0;
00294 }
00295
00296 static int seq_read_close(AVFormatContext *s)
00297 {
00298 int i;
00299 SeqDemuxContext *seq = s->priv_data;
00300
00301 for (i = 0; i < SEQ_NUM_FRAME_BUFFERS; i++)
00302 av_free(seq->frame_buffers[i].data);
00303
00304 return 0;
00305 }
00306
00307 AVInputFormat ff_tiertexseq_demuxer = {
00308 .name = "tiertexseq",
00309 .long_name = NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ"),
00310 .priv_data_size = sizeof(SeqDemuxContext),
00311 .read_probe = seq_probe,
00312 .read_header = seq_read_header,
00313 .read_packet = seq_read_packet,
00314 .read_close = seq_read_close,
00315 };