avfilter/avfiltergraph: fix constant string comparision
[ffmpeg.git] / libavformat / tiertexseq.c
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
24 * Tiertex Limited SEQ file demuxer
25 */
26
27 #include "libavutil/channel_layout.h"
28 #include "libavutil/mem.h"
29 #include "avformat.h"
30 #include "avio_internal.h"
31 #include "demux.h"
32 #include "internal.h"
33
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
41
42
43 typedef struct TiertexSeqFrameBuffer {
44 int fill_size;
45 int data_size;
46 unsigned char *data;
47 } TiertexSeqFrameBuffer;
48
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;
63 } SeqDemuxContext;
64
65
66 static int seq_probe(const AVProbeData *p)
67 {
68 int i;
69
70 if (p->buf_size < 258)
71 return 0;
72
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++)
76 if (p->buf[i])
77 return 0;
78
79 if(p->buf[256]==0 && p->buf[257]==0)
80 return 0;
81
82 /* only one fourth of the score since the previous check is too naive */
83 return AVPROBE_SCORE_MAX / 4;
84 }
85
86 static int seq_init_frame_buffers(SeqDemuxContext *seq, AVIOContext *pb)
87 {
88 int i, sz;
89 TiertexSeqFrameBuffer *seq_buffer;
90
91 avio_seek(pb, 256, SEEK_SET);
92
93 for (i = 0; i < SEQ_NUM_FRAME_BUFFERS; i++) {
94 sz = avio_rl16(pb);
95 if (sz == 0)
96 break;
97 else {
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);
104 }
105 }
106 seq->frame_buffers_count = i;
107 return 0;
108 }
109
110 static int seq_fill_buffer(SeqDemuxContext *seq, AVIOContext *pb, int buffer_num, unsigned int data_offs, int data_size)
111 {
112 TiertexSeqFrameBuffer *seq_buffer;
113 int ret;
114
115 if (buffer_num >= SEQ_NUM_FRAME_BUFFERS)
116 return AVERROR_INVALIDDATA;
117
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;
121
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)
124 return ret;
125
126 seq_buffer->fill_size += data_size;
127 return 0;
128 }
129
130 static int seq_parse_frame_data(SeqDemuxContext *seq, AVIOContext *pb)
131 {
132 unsigned int offset_table[4], buffer_num[4];
133 TiertexSeqFrameBuffer *seq_buffer;
134 int i, e, err;
135
136 seq->current_frame_offs += SEQ_FRAME_SIZE;
137 avio_seek(pb, seq->current_frame_offs, SEEK_SET);
138
139 /* sound data */
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;
143 } else {
144 seq->current_audio_data_size = 0;
145 }
146
147 /* palette data */
148 seq->current_pal_data_offs = avio_rl16(pb);
149 if (seq->current_pal_data_offs) {
150 seq->current_pal_data_size = 768;
151 } else {
152 seq->current_pal_data_size = 0;
153 }
154
155 /* video data */
156 for (i = 0; i < 4; i++)
157 buffer_num[i] = avio_r8(pb);
158
159 for (i = 0; i < 4; i++)
160 offset_table[i] = avio_rl16(pb);
161
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],
166 offset_table[i],
167 offset_table[e] - offset_table[i]);
168 if (err)
169 return err;
170 }
171 }
172
173 if (buffer_num[0] != 255) {
174 if (buffer_num[0] >= SEQ_NUM_FRAME_BUFFERS)
175 return AVERROR_INVALIDDATA;
176
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;
181 } else {
182 seq->current_video_data_size = 0;
183 seq->current_video_data_ptr = 0;
184 }
185
186 return 0;
187 }
188
189 static int seq_read_close(AVFormatContext *s)
190 {
191 int i;
192 SeqDemuxContext *seq = s->priv_data;
193
194 for (i = 0; i < SEQ_NUM_FRAME_BUFFERS; i++)
195 av_freep(&seq->frame_buffers[i].data);
196
197 return 0;
198 }
199
200 static int seq_read_header(AVFormatContext *s)
201 {
202 int i, rc;
203 SeqDemuxContext *seq = s->priv_data;
204 AVIOContext *pb = s->pb;
205 AVStream *st;
206
207 /* init internal buffers */
208 rc = seq_init_frame_buffers(seq, pb);
209 if (rc < 0)
210 return rc;
211
212 seq->current_frame_offs = 0;
213
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);
217 if (rc < 0)
218 return rc;
219 }
220
221 seq->current_frame_pts = 0;
222
223 seq->audio_buffer_full = 0;
224
225 /* initialize the video decoder stream */
226 st = avformat_new_stream(s, NULL);
227 if (!st)
228 return AVERROR(ENOMEM);
229
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;
237
238 /* initialize the audio decoder stream */
239 st = avformat_new_stream(s, NULL);
240 if (!st)
241 return AVERROR(ENOMEM);
242
243 st->start_time = 0;
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;
254
255 return 0;
256 }
257
258 static int seq_read_packet(AVFormatContext *s, AVPacket *pkt)
259 {
260 int rc;
261 SeqDemuxContext *seq = s->priv_data;
262 AVIOContext *pb = s->pb;
263
264 if (!seq->audio_buffer_full) {
265 rc = seq_parse_frame_data(seq, pb);
266 if (rc)
267 return rc;
268
269 /* video packet */
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);
273 if (rc < 0)
274 return rc;
275
276 pkt->data[0] = 0;
277 if (seq->current_pal_data_size) {
278 int ret;
279 pkt->data[0] |= 1;
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)
282 return ret;
283 }
284 if (seq->current_video_data_size) {
285 pkt->data[0] |= 2;
286 memcpy(&pkt->data[1 + seq->current_pal_data_size],
287 seq->current_video_data_ptr,
288 seq->current_video_data_size);
289 }
290 pkt->stream_index = seq->video_stream_index;
291 pkt->pts = seq->current_frame_pts;
292
293 /* sound buffer will be processed on next read_packet() call */
294 seq->audio_buffer_full = 1;
295 return 0;
296 }
297 }
298
299 /* audio packet */
300 if (seq->current_audio_data_offs == 0) /* end of data reached */
301 return AVERROR_EOF;
302
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);
305 if (rc < 0)
306 return rc;
307
308 pkt->stream_index = seq->audio_stream_index;
309 seq->current_frame_pts++;
310
311 seq->audio_buffer_full = 0;
312 return 0;
313 }
314
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,
324 };