tiertexseq.c
Go to the documentation of this file.
1 /*
2  * Tiertex Limited SEQ File Demuxer
3  * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net)
4  *
5  * This file is part of Libav.
6  *
7  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
27 #include "avformat.h"
28 #include "internal.h"
29 
30 #define SEQ_FRAME_SIZE 6144
31 #define SEQ_FRAME_W 256
32 #define SEQ_FRAME_H 128
33 #define SEQ_NUM_FRAME_BUFFERS 30
34 #define SEQ_AUDIO_BUFFER_SIZE 882
35 #define SEQ_SAMPLE_RATE 22050
36 #define SEQ_FRAME_RATE 25
37 
38 
39 typedef struct TiertexSeqFrameBuffer {
40  int fill_size;
41  int data_size;
42  unsigned char *data;
44 
45 typedef struct SeqDemuxContext {
54  unsigned int current_pal_data_size;
55  unsigned int current_pal_data_offs;
57  unsigned char *current_video_data_ptr;
60 
61 
62 static int seq_probe(AVProbeData *p)
63 {
64  int i;
65 
66  if (p->buf_size < 258)
67  return 0;
68 
69  /* there's no real header in a .seq file, the only thing they have in common */
70  /* is the first 256 bytes of the file which are always filled with 0 */
71  for (i = 0; i < 256; i++)
72  if (p->buf[i])
73  return 0;
74 
75  if(p->buf[256]==0 && p->buf[257]==0)
76  return 0;
77 
78  /* only one fourth of the score since the previous check is too naive */
79  return AVPROBE_SCORE_MAX / 4;
80 }
81 
83 {
84  int i, sz;
85  TiertexSeqFrameBuffer *seq_buffer;
86 
87  avio_seek(pb, 256, SEEK_SET);
88 
89  for (i = 0; i < SEQ_NUM_FRAME_BUFFERS; i++) {
90  sz = avio_rl16(pb);
91  if (sz == 0)
92  break;
93  else {
94  seq_buffer = &seq->frame_buffers[i];
95  seq_buffer->fill_size = 0;
96  seq_buffer->data_size = sz;
97  seq_buffer->data = av_malloc(sz);
98  if (!seq_buffer->data)
99  return AVERROR(ENOMEM);
100  }
101  }
102  seq->frame_buffers_count = i;
103  return 0;
104 }
105 
106 static int seq_fill_buffer(SeqDemuxContext *seq, AVIOContext *pb, int buffer_num, unsigned int data_offs, int data_size)
107 {
108  TiertexSeqFrameBuffer *seq_buffer;
109 
110  if (buffer_num >= SEQ_NUM_FRAME_BUFFERS)
111  return AVERROR_INVALIDDATA;
112 
113  seq_buffer = &seq->frame_buffers[buffer_num];
114  if (seq_buffer->fill_size + data_size > seq_buffer->data_size || data_size <= 0)
115  return AVERROR_INVALIDDATA;
116 
117  avio_seek(pb, seq->current_frame_offs + data_offs, SEEK_SET);
118  if (avio_read(pb, seq_buffer->data + seq_buffer->fill_size, data_size) != data_size)
119  return AVERROR(EIO);
120 
121  seq_buffer->fill_size += data_size;
122  return 0;
123 }
124 
126 {
127  unsigned int offset_table[4], buffer_num[4];
128  TiertexSeqFrameBuffer *seq_buffer;
129  int i, e, err;
130 
132  avio_seek(pb, seq->current_frame_offs, SEEK_SET);
133 
134  /* sound data */
136  if (seq->current_audio_data_offs) {
138  } else {
139  seq->current_audio_data_size = 0;
140  }
141 
142  /* palette data */
143  seq->current_pal_data_offs = avio_rl16(pb);
144  if (seq->current_pal_data_offs) {
145  seq->current_pal_data_size = 768;
146  } else {
147  seq->current_pal_data_size = 0;
148  }
149 
150  /* video data */
151  for (i = 0; i < 4; i++)
152  buffer_num[i] = avio_r8(pb);
153 
154  for (i = 0; i < 4; i++)
155  offset_table[i] = avio_rl16(pb);
156 
157  for (i = 0; i < 3; i++) {
158  if (offset_table[i]) {
159  for (e = i + 1; e < 3 && offset_table[e] == 0; e++);
160  err = seq_fill_buffer(seq, pb, buffer_num[1 + i],
161  offset_table[i],
162  offset_table[e] - offset_table[i]);
163  if (err)
164  return err;
165  }
166  }
167 
168  if (buffer_num[0] != 255) {
169  if (buffer_num[0] >= SEQ_NUM_FRAME_BUFFERS)
170  return AVERROR_INVALIDDATA;
171 
172  seq_buffer = &seq->frame_buffers[buffer_num[0]];
173  seq->current_video_data_size = seq_buffer->fill_size;
174  seq->current_video_data_ptr = seq_buffer->data;
175  seq_buffer->fill_size = 0;
176  } else {
177  seq->current_video_data_size = 0;
178  seq->current_video_data_ptr = 0;
179  }
180 
181  return 0;
182 }
183 
185 {
186  int i, rc;
187  SeqDemuxContext *seq = s->priv_data;
188  AVIOContext *pb = s->pb;
189  AVStream *st;
190 
191  /* init internal buffers */
192  rc = seq_init_frame_buffers(seq, pb);
193  if (rc)
194  return rc;
195 
196  seq->current_frame_offs = 0;
197 
198  /* preload (no audio data, just buffer operations related data) */
199  for (i = 1; i <= 100; i++) {
200  rc = seq_parse_frame_data(seq, pb);
201  if (rc)
202  return rc;
203  }
204 
205  seq->current_frame_pts = 0;
206 
207  seq->audio_buffer_full = 0;
208 
209  /* initialize the video decoder stream */
210  st = avformat_new_stream(s, NULL);
211  if (!st)
212  return AVERROR(ENOMEM);
213 
215  seq->video_stream_index = st->index;
218  st->codec->codec_tag = 0; /* no fourcc */
219  st->codec->width = SEQ_FRAME_W;
220  st->codec->height = SEQ_FRAME_H;
221 
222  /* initialize the audio decoder stream */
223  st = avformat_new_stream(s, NULL);
224  if (!st)
225  return AVERROR(ENOMEM);
226 
228  seq->audio_stream_index = st->index;
231  st->codec->codec_tag = 0; /* no tag */
232  st->codec->channels = 1;
234  st->codec->bits_per_coded_sample = 16;
237 
238  return 0;
239 }
240 
242 {
243  int rc;
244  SeqDemuxContext *seq = s->priv_data;
245  AVIOContext *pb = s->pb;
246 
247  if (!seq->audio_buffer_full) {
248  rc = seq_parse_frame_data(seq, pb);
249  if (rc)
250  return rc;
251 
252  /* video packet */
253  if (seq->current_pal_data_size + seq->current_video_data_size != 0) {
255  return AVERROR(ENOMEM);
256 
257  pkt->data[0] = 0;
258  if (seq->current_pal_data_size) {
259  pkt->data[0] |= 1;
260  avio_seek(pb, seq->current_frame_offs + seq->current_pal_data_offs, SEEK_SET);
261  if (avio_read(pb, &pkt->data[1], seq->current_pal_data_size) != seq->current_pal_data_size)
262  return AVERROR(EIO);
263  }
264  if (seq->current_video_data_size) {
265  pkt->data[0] |= 2;
266  memcpy(&pkt->data[1 + seq->current_pal_data_size],
269  }
270  pkt->stream_index = seq->video_stream_index;
271  pkt->pts = seq->current_frame_pts;
272 
273  /* sound buffer will be processed on next read_packet() call */
274  seq->audio_buffer_full = 1;
275  return 0;
276  }
277  }
278 
279  /* audio packet */
280  if (seq->current_audio_data_offs == 0) /* end of data reached */
281  return AVERROR(EIO);
282 
283  avio_seek(pb, seq->current_frame_offs + seq->current_audio_data_offs, SEEK_SET);
284  rc = av_get_packet(pb, pkt, seq->current_audio_data_size);
285  if (rc < 0)
286  return rc;
287 
288  pkt->stream_index = seq->audio_stream_index;
289  seq->current_frame_pts++;
290 
291  seq->audio_buffer_full = 0;
292  return 0;
293 }
294 
296 {
297  int i;
298  SeqDemuxContext *seq = s->priv_data;
299 
300  for (i = 0; i < SEQ_NUM_FRAME_BUFFERS; i++)
301  av_free(seq->frame_buffers[i].data);
302 
303  return 0;
304 }
305 
307  .name = "tiertexseq",
308  .long_name = NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ format"),
309  .priv_data_size = sizeof(SeqDemuxContext),
314 };