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