2 * Tiertex Limited SEQ File Demuxer
3 * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net)
5 * This file is part of FFmpeg.
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.
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.
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
24 * Tiertex Limited SEQ file demuxer
27 #include "libavutil/channel_layout.h"
28 #include "libavutil/mem.h"
30 #include "avio_internal.h"
34 #define SEQ_FRAME_SIZE 6144
35 #define SEQ_FRAME_W 256
36 #define SEQ_FRAME_H 128
37 #define SEQ_NUM_FRAME_BUFFERS 30
38 #define SEQ_AUDIO_BUFFER_SIZE 882
39 #define SEQ_SAMPLE_RATE 22050
40 #define SEQ_FRAME_RATE 25
43 typedef struct TiertexSeqFrameBuffer
{
47 } TiertexSeqFrameBuffer
;
49 typedef struct SeqDemuxContext
{
50 int audio_stream_index
;
51 int video_stream_index
;
52 int current_frame_pts
;
53 int current_frame_offs
;
54 TiertexSeqFrameBuffer frame_buffers
[SEQ_NUM_FRAME_BUFFERS
];
55 int frame_buffers_count
;
56 unsigned int current_audio_data_size
;
57 unsigned int current_audio_data_offs
;
58 unsigned int current_pal_data_size
;
59 unsigned int current_pal_data_offs
;
60 unsigned int current_video_data_size
;
61 unsigned char *current_video_data_ptr
;
62 int audio_buffer_full
;
66 static int seq_probe(const AVProbeData
*p
)
70 if (p
->buf_size
< 258)
73 /* there's no real header in a .seq file, the only thing they have in common */
74 /* is the first 256 bytes of the file which are always filled with 0 */
75 for (i
= 0; i
< 256; i
++)
79 if(p
->buf
[256]==0 && p
->buf
[257]==0)
82 /* only one fourth of the score since the previous check is too naive */
83 return AVPROBE_SCORE_MAX
/ 4;
86 static int seq_init_frame_buffers(SeqDemuxContext
*seq
, AVIOContext
*pb
)
89 TiertexSeqFrameBuffer
*seq_buffer
;
91 avio_seek(pb
, 256, SEEK_SET
);
93 for (i
= 0; i
< SEQ_NUM_FRAME_BUFFERS
; i
++) {
98 seq_buffer
= &seq
->frame_buffers
[i
];
99 seq_buffer
->fill_size
= 0;
100 seq_buffer
->data_size
= sz
;
101 seq_buffer
->data
= av_malloc(sz
);
102 if (!seq_buffer
->data
)
103 return AVERROR(ENOMEM
);
106 seq
->frame_buffers_count
= i
;
110 static int seq_fill_buffer(SeqDemuxContext
*seq
, AVIOContext
*pb
, int buffer_num
, unsigned int data_offs
, int data_size
)
112 TiertexSeqFrameBuffer
*seq_buffer
;
115 if (buffer_num
>= SEQ_NUM_FRAME_BUFFERS
)
116 return AVERROR_INVALIDDATA
;
118 seq_buffer
= &seq
->frame_buffers
[buffer_num
];
119 if (seq_buffer
->fill_size
+ data_size
> seq_buffer
->data_size
|| data_size
<= 0)
120 return AVERROR_INVALIDDATA
;
122 avio_seek(pb
, seq
->current_frame_offs
+ data_offs
, SEEK_SET
);
123 if ((ret
= ffio_read_size(pb
, seq_buffer
->data
+ seq_buffer
->fill_size
, data_size
)) < 0)
126 seq_buffer
->fill_size
+= data_size
;
130 static int seq_parse_frame_data(SeqDemuxContext
*seq
, AVIOContext
*pb
)
132 unsigned int offset_table
[4], buffer_num
[4];
133 TiertexSeqFrameBuffer
*seq_buffer
;
136 seq
->current_frame_offs
+= SEQ_FRAME_SIZE
;
137 avio_seek(pb
, seq
->current_frame_offs
, SEEK_SET
);
140 seq
->current_audio_data_offs
= avio_rl16(pb
);
141 if (seq
->current_audio_data_offs
) {
142 seq
->current_audio_data_size
= SEQ_AUDIO_BUFFER_SIZE
* 2;
144 seq
->current_audio_data_size
= 0;
148 seq
->current_pal_data_offs
= avio_rl16(pb
);
149 if (seq
->current_pal_data_offs
) {
150 seq
->current_pal_data_size
= 768;
152 seq
->current_pal_data_size
= 0;
156 for (i
= 0; i
< 4; i
++)
157 buffer_num
[i
] = avio_r8(pb
);
159 for (i
= 0; i
< 4; i
++)
160 offset_table
[i
] = avio_rl16(pb
);
162 for (i
= 0; i
< 3; i
++) {
163 if (offset_table
[i
]) {
164 for (e
= i
+ 1; e
< 3 && offset_table
[e
] == 0; e
++);
165 err
= seq_fill_buffer(seq
, pb
, buffer_num
[1 + i
],
167 offset_table
[e
] - offset_table
[i
]);
173 if (buffer_num
[0] != 255) {
174 if (buffer_num
[0] >= SEQ_NUM_FRAME_BUFFERS
)
175 return AVERROR_INVALIDDATA
;
177 seq_buffer
= &seq
->frame_buffers
[buffer_num
[0]];
178 seq
->current_video_data_size
= seq_buffer
->fill_size
;
179 seq
->current_video_data_ptr
= seq_buffer
->data
;
180 seq_buffer
->fill_size
= 0;
182 seq
->current_video_data_size
= 0;
183 seq
->current_video_data_ptr
= 0;
189 static int seq_read_close(AVFormatContext
*s
)
192 SeqDemuxContext
*seq
= s
->priv_data
;
194 for (i
= 0; i
< SEQ_NUM_FRAME_BUFFERS
; i
++)
195 av_freep(&seq
->frame_buffers
[i
].data
);
200 static int seq_read_header(AVFormatContext
*s
)
203 SeqDemuxContext
*seq
= s
->priv_data
;
204 AVIOContext
*pb
= s
->pb
;
207 /* init internal buffers */
208 rc
= seq_init_frame_buffers(seq
, pb
);
212 seq
->current_frame_offs
= 0;
214 /* preload (no audio data, just buffer operations related data) */
215 for (i
= 1; i
<= 100; i
++) {
216 rc
= seq_parse_frame_data(seq
, pb
);
221 seq
->current_frame_pts
= 0;
223 seq
->audio_buffer_full
= 0;
225 /* initialize the video decoder stream */
226 st
= avformat_new_stream(s
, NULL
);
228 return AVERROR(ENOMEM
);
230 avpriv_set_pts_info(st
, 32, 1, SEQ_FRAME_RATE
);
231 seq
->video_stream_index
= st
->index
;
232 st
->codecpar
->codec_type
= AVMEDIA_TYPE_VIDEO
;
233 st
->codecpar
->codec_id
= AV_CODEC_ID_TIERTEXSEQVIDEO
;
234 st
->codecpar
->codec_tag
= 0; /* no fourcc */
235 st
->codecpar
->width
= SEQ_FRAME_W
;
236 st
->codecpar
->height
= SEQ_FRAME_H
;
238 /* initialize the audio decoder stream */
239 st
= avformat_new_stream(s
, NULL
);
241 return AVERROR(ENOMEM
);
244 avpriv_set_pts_info(st
, 32, 1, SEQ_SAMPLE_RATE
);
245 seq
->audio_stream_index
= st
->index
;
246 st
->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
247 st
->codecpar
->codec_id
= AV_CODEC_ID_PCM_S16BE
;
248 st
->codecpar
->codec_tag
= 0; /* no tag */
249 st
->codecpar
->ch_layout
= (AVChannelLayout
)AV_CHANNEL_LAYOUT_MONO
;
250 st
->codecpar
->sample_rate
= SEQ_SAMPLE_RATE
;
251 st
->codecpar
->bits_per_coded_sample
= 16;
252 st
->codecpar
->bit_rate
= st
->codecpar
->sample_rate
* st
->codecpar
->bits_per_coded_sample
* st
->codecpar
->ch_layout
.nb_channels
;
253 st
->codecpar
->block_align
= st
->codecpar
->ch_layout
.nb_channels
* st
->codecpar
->bits_per_coded_sample
/ 8;
258 static int seq_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
261 SeqDemuxContext
*seq
= s
->priv_data
;
262 AVIOContext
*pb
= s
->pb
;
264 if (!seq
->audio_buffer_full
) {
265 rc
= seq_parse_frame_data(seq
, pb
);
270 if (seq
->current_pal_data_size
+ seq
->current_video_data_size
!= 0) {
271 rc
= av_new_packet(pkt
, 1 + seq
->current_pal_data_size
272 + seq
->current_video_data_size
);
277 if (seq
->current_pal_data_size
) {
280 avio_seek(pb
, seq
->current_frame_offs
+ seq
->current_pal_data_offs
, SEEK_SET
);
281 if ((ret
= ffio_read_size(pb
, &pkt
->data
[1], seq
->current_pal_data_size
)) < 0)
284 if (seq
->current_video_data_size
) {
286 memcpy(&pkt
->data
[1 + seq
->current_pal_data_size
],
287 seq
->current_video_data_ptr
,
288 seq
->current_video_data_size
);
290 pkt
->stream_index
= seq
->video_stream_index
;
291 pkt
->pts
= seq
->current_frame_pts
;
293 /* sound buffer will be processed on next read_packet() call */
294 seq
->audio_buffer_full
= 1;
300 if (seq
->current_audio_data_offs
== 0) /* end of data reached */
303 avio_seek(pb
, seq
->current_frame_offs
+ seq
->current_audio_data_offs
, SEEK_SET
);
304 rc
= av_get_packet(pb
, pkt
, seq
->current_audio_data_size
);
308 pkt
->stream_index
= seq
->audio_stream_index
;
309 seq
->current_frame_pts
++;
311 seq
->audio_buffer_full
= 0;
315 const FFInputFormat ff_tiertexseq_demuxer
= {
316 .p
.name
= "tiertexseq",
317 .p
.long_name
= NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ"),
318 .priv_data_size
= sizeof(SeqDemuxContext
),
319 .flags_internal
= FF_INFMT_FLAG_INIT_CLEANUP
,
320 .read_probe
= seq_probe
,
321 .read_header
= seq_read_header
,
322 .read_packet
= seq_read_packet
,
323 .read_close
= seq_read_close
,