Check if there is enough bytes before reading the buffer in the EA ADPCM
[ffmpeg-lucabe.git] / libavformat / ipmovie.c
blobf992b68782e138c7ce8b51a4975c801969e8f5a1
1 /*
2 * Interplay MVE File Demuxer
3 * Copyright (c) 2003 The ffmpeg Project
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
22 /**
23 * @file libavformat/ipmovie.c
24 * Interplay MVE file demuxer
25 * by Mike Melanson (melanson@pcisys.net)
26 * For more information regarding the Interplay MVE file format, visit:
27 * http://www.pcisys.net/~melanson/codecs/
28 * The aforementioned site also contains a command line utility for parsing
29 * IP MVE files so that you can get a good idea of the typical structure of
30 * such files. This demuxer is not the best example to use if you are trying
31 * to write your own as it uses a rather roundabout approach for splitting
32 * up and sending out the chunks.
35 #include "libavutil/intreadwrite.h"
36 #include "avformat.h"
38 /* debugging support: #define DEBUG_IPMOVIE as non-zero to see extremely
39 * verbose information about the demux process */
40 #define DEBUG_IPMOVIE 0
42 #if DEBUG_IPMOVIE
43 #undef printf
44 #define debug_ipmovie printf
45 #else
46 static inline void debug_ipmovie(const char *format, ...) { }
47 #endif
49 #define IPMOVIE_SIGNATURE "Interplay MVE File\x1A\0"
50 #define IPMOVIE_SIGNATURE_SIZE 20
51 #define CHUNK_PREAMBLE_SIZE 4
52 #define OPCODE_PREAMBLE_SIZE 4
54 #define CHUNK_INIT_AUDIO 0x0000
55 #define CHUNK_AUDIO_ONLY 0x0001
56 #define CHUNK_INIT_VIDEO 0x0002
57 #define CHUNK_VIDEO 0x0003
58 #define CHUNK_SHUTDOWN 0x0004
59 #define CHUNK_END 0x0005
60 /* these last types are used internally */
61 #define CHUNK_DONE 0xFFFC
62 #define CHUNK_NOMEM 0xFFFD
63 #define CHUNK_EOF 0xFFFE
64 #define CHUNK_BAD 0xFFFF
66 #define OPCODE_END_OF_STREAM 0x00
67 #define OPCODE_END_OF_CHUNK 0x01
68 #define OPCODE_CREATE_TIMER 0x02
69 #define OPCODE_INIT_AUDIO_BUFFERS 0x03
70 #define OPCODE_START_STOP_AUDIO 0x04
71 #define OPCODE_INIT_VIDEO_BUFFERS 0x05
72 #define OPCODE_UNKNOWN_06 0x06
73 #define OPCODE_SEND_BUFFER 0x07
74 #define OPCODE_AUDIO_FRAME 0x08
75 #define OPCODE_SILENCE_FRAME 0x09
76 #define OPCODE_INIT_VIDEO_MODE 0x0A
77 #define OPCODE_CREATE_GRADIENT 0x0B
78 #define OPCODE_SET_PALETTE 0x0C
79 #define OPCODE_SET_PALETTE_COMPRESSED 0x0D
80 #define OPCODE_UNKNOWN_0E 0x0E
81 #define OPCODE_SET_DECODING_MAP 0x0F
82 #define OPCODE_UNKNOWN_10 0x10
83 #define OPCODE_VIDEO_DATA 0x11
84 #define OPCODE_UNKNOWN_12 0x12
85 #define OPCODE_UNKNOWN_13 0x13
86 #define OPCODE_UNKNOWN_14 0x14
87 #define OPCODE_UNKNOWN_15 0x15
89 #define PALETTE_COUNT 256
91 typedef struct IPMVEContext {
93 unsigned char *buf;
94 int buf_size;
96 uint64_t frame_pts_inc;
98 unsigned int video_width;
99 unsigned int video_height;
100 int64_t video_pts;
102 unsigned int audio_bits;
103 unsigned int audio_channels;
104 unsigned int audio_sample_rate;
105 enum CodecID audio_type;
106 unsigned int audio_frame_count;
108 int video_stream_index;
109 int audio_stream_index;
111 int64_t audio_chunk_offset;
112 int audio_chunk_size;
113 int64_t video_chunk_offset;
114 int video_chunk_size;
115 int64_t decode_map_chunk_offset;
116 int decode_map_chunk_size;
118 int64_t next_chunk_offset;
120 AVPaletteControl palette_control;
122 } IPMVEContext;
124 static int load_ipmovie_packet(IPMVEContext *s, ByteIOContext *pb,
125 AVPacket *pkt) {
127 int chunk_type;
129 if (s->audio_chunk_offset) {
131 /* adjust for PCM audio by skipping chunk header */
132 if (s->audio_type != CODEC_ID_INTERPLAY_DPCM) {
133 s->audio_chunk_offset += 6;
134 s->audio_chunk_size -= 6;
137 url_fseek(pb, s->audio_chunk_offset, SEEK_SET);
138 s->audio_chunk_offset = 0;
140 if (s->audio_chunk_size != av_get_packet(pb, pkt, s->audio_chunk_size))
141 return CHUNK_EOF;
143 pkt->stream_index = s->audio_stream_index;
144 pkt->pts = s->audio_frame_count;
146 /* audio frame maintenance */
147 if (s->audio_type != CODEC_ID_INTERPLAY_DPCM)
148 s->audio_frame_count +=
149 (s->audio_chunk_size / s->audio_channels / (s->audio_bits / 8));
150 else
151 s->audio_frame_count +=
152 (s->audio_chunk_size - 6) / s->audio_channels;
154 debug_ipmovie("sending audio frame with pts %"PRId64" (%d audio frames)\n",
155 pkt->pts, s->audio_frame_count);
157 chunk_type = CHUNK_VIDEO;
159 } else if (s->decode_map_chunk_offset) {
161 /* send both the decode map and the video data together */
163 if (av_new_packet(pkt, s->decode_map_chunk_size + s->video_chunk_size))
164 return CHUNK_NOMEM;
166 pkt->pos= s->decode_map_chunk_offset;
167 url_fseek(pb, s->decode_map_chunk_offset, SEEK_SET);
168 s->decode_map_chunk_offset = 0;
170 if (get_buffer(pb, pkt->data, s->decode_map_chunk_size) !=
171 s->decode_map_chunk_size) {
172 av_free_packet(pkt);
173 return CHUNK_EOF;
176 url_fseek(pb, s->video_chunk_offset, SEEK_SET);
177 s->video_chunk_offset = 0;
179 if (get_buffer(pb, pkt->data + s->decode_map_chunk_size,
180 s->video_chunk_size) != s->video_chunk_size) {
181 av_free_packet(pkt);
182 return CHUNK_EOF;
185 pkt->stream_index = s->video_stream_index;
186 pkt->pts = s->video_pts;
188 debug_ipmovie("sending video frame with pts %"PRId64"\n",
189 pkt->pts);
191 s->video_pts += s->frame_pts_inc;
193 chunk_type = CHUNK_VIDEO;
195 } else {
197 url_fseek(pb, s->next_chunk_offset, SEEK_SET);
198 chunk_type = CHUNK_DONE;
202 return chunk_type;
205 /* This function loads and processes a single chunk in an IP movie file.
206 * It returns the type of chunk that was processed. */
207 static int process_ipmovie_chunk(IPMVEContext *s, ByteIOContext *pb,
208 AVPacket *pkt)
210 unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
211 int chunk_type;
212 int chunk_size;
213 unsigned char opcode_preamble[OPCODE_PREAMBLE_SIZE];
214 unsigned char opcode_type;
215 unsigned char opcode_version;
216 int opcode_size;
217 unsigned char scratch[1024];
218 int i, j;
219 int first_color, last_color;
220 int audio_flags;
221 unsigned char r, g, b;
223 /* see if there are any pending packets */
224 chunk_type = load_ipmovie_packet(s, pb, pkt);
225 if (chunk_type != CHUNK_DONE)
226 return chunk_type;
228 /* read the next chunk, wherever the file happens to be pointing */
229 if (url_feof(pb))
230 return CHUNK_EOF;
231 if (get_buffer(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
232 CHUNK_PREAMBLE_SIZE)
233 return CHUNK_BAD;
234 chunk_size = AV_RL16(&chunk_preamble[0]);
235 chunk_type = AV_RL16(&chunk_preamble[2]);
237 debug_ipmovie("chunk type 0x%04X, 0x%04X bytes: ", chunk_type, chunk_size);
239 switch (chunk_type) {
241 case CHUNK_INIT_AUDIO:
242 debug_ipmovie("initialize audio\n");
243 break;
245 case CHUNK_AUDIO_ONLY:
246 debug_ipmovie("audio only\n");
247 break;
249 case CHUNK_INIT_VIDEO:
250 debug_ipmovie("initialize video\n");
251 break;
253 case CHUNK_VIDEO:
254 debug_ipmovie("video (and audio)\n");
255 break;
257 case CHUNK_SHUTDOWN:
258 debug_ipmovie("shutdown\n");
259 break;
261 case CHUNK_END:
262 debug_ipmovie("end\n");
263 break;
265 default:
266 debug_ipmovie("invalid chunk\n");
267 chunk_type = CHUNK_BAD;
268 break;
272 while ((chunk_size > 0) && (chunk_type != CHUNK_BAD)) {
274 /* read the next chunk, wherever the file happens to be pointing */
275 if (url_feof(pb)) {
276 chunk_type = CHUNK_EOF;
277 break;
279 if (get_buffer(pb, opcode_preamble, CHUNK_PREAMBLE_SIZE) !=
280 CHUNK_PREAMBLE_SIZE) {
281 chunk_type = CHUNK_BAD;
282 break;
285 opcode_size = AV_RL16(&opcode_preamble[0]);
286 opcode_type = opcode_preamble[2];
287 opcode_version = opcode_preamble[3];
289 chunk_size -= OPCODE_PREAMBLE_SIZE;
290 chunk_size -= opcode_size;
291 if (chunk_size < 0) {
292 debug_ipmovie("chunk_size countdown just went negative\n");
293 chunk_type = CHUNK_BAD;
294 break;
297 debug_ipmovie(" opcode type %02X, version %d, 0x%04X bytes: ",
298 opcode_type, opcode_version, opcode_size);
299 switch (opcode_type) {
301 case OPCODE_END_OF_STREAM:
302 debug_ipmovie("end of stream\n");
303 url_fseek(pb, opcode_size, SEEK_CUR);
304 break;
306 case OPCODE_END_OF_CHUNK:
307 debug_ipmovie("end of chunk\n");
308 url_fseek(pb, opcode_size, SEEK_CUR);
309 break;
311 case OPCODE_CREATE_TIMER:
312 debug_ipmovie("create timer\n");
313 if ((opcode_version > 0) || (opcode_size > 6)) {
314 debug_ipmovie("bad create_timer opcode\n");
315 chunk_type = CHUNK_BAD;
316 break;
318 if (get_buffer(pb, scratch, opcode_size) !=
319 opcode_size) {
320 chunk_type = CHUNK_BAD;
321 break;
323 s->frame_pts_inc = ((uint64_t)AV_RL32(&scratch[0])) * AV_RL16(&scratch[4]);
324 debug_ipmovie(" %.2f frames/second (timer div = %d, subdiv = %d)\n",
325 1000000.0/s->frame_pts_inc, AV_RL32(&scratch[0]), AV_RL16(&scratch[4]));
326 break;
328 case OPCODE_INIT_AUDIO_BUFFERS:
329 debug_ipmovie("initialize audio buffers\n");
330 if ((opcode_version > 1) || (opcode_size > 10)) {
331 debug_ipmovie("bad init_audio_buffers opcode\n");
332 chunk_type = CHUNK_BAD;
333 break;
335 if (get_buffer(pb, scratch, opcode_size) !=
336 opcode_size) {
337 chunk_type = CHUNK_BAD;
338 break;
340 s->audio_sample_rate = AV_RL16(&scratch[4]);
341 audio_flags = AV_RL16(&scratch[2]);
342 /* bit 0 of the flags: 0 = mono, 1 = stereo */
343 s->audio_channels = (audio_flags & 1) + 1;
344 /* bit 1 of the flags: 0 = 8 bit, 1 = 16 bit */
345 s->audio_bits = (((audio_flags >> 1) & 1) + 1) * 8;
346 /* bit 2 indicates compressed audio in version 1 opcode */
347 if ((opcode_version == 1) && (audio_flags & 0x4))
348 s->audio_type = CODEC_ID_INTERPLAY_DPCM;
349 else if (s->audio_bits == 16)
350 s->audio_type = CODEC_ID_PCM_S16LE;
351 else
352 s->audio_type = CODEC_ID_PCM_U8;
353 debug_ipmovie("audio: %d bits, %d Hz, %s, %s format\n",
354 s->audio_bits,
355 s->audio_sample_rate,
356 (s->audio_channels == 2) ? "stereo" : "mono",
357 (s->audio_type == CODEC_ID_INTERPLAY_DPCM) ?
358 "Interplay audio" : "PCM");
359 break;
361 case OPCODE_START_STOP_AUDIO:
362 debug_ipmovie("start/stop audio\n");
363 url_fseek(pb, opcode_size, SEEK_CUR);
364 break;
366 case OPCODE_INIT_VIDEO_BUFFERS:
367 debug_ipmovie("initialize video buffers\n");
368 if ((opcode_version > 2) || (opcode_size > 8)) {
369 debug_ipmovie("bad init_video_buffers opcode\n");
370 chunk_type = CHUNK_BAD;
371 break;
373 if (get_buffer(pb, scratch, opcode_size) !=
374 opcode_size) {
375 chunk_type = CHUNK_BAD;
376 break;
378 s->video_width = AV_RL16(&scratch[0]) * 8;
379 s->video_height = AV_RL16(&scratch[2]) * 8;
380 debug_ipmovie("video resolution: %d x %d\n",
381 s->video_width, s->video_height);
382 break;
384 case OPCODE_UNKNOWN_06:
385 case OPCODE_UNKNOWN_0E:
386 case OPCODE_UNKNOWN_10:
387 case OPCODE_UNKNOWN_12:
388 case OPCODE_UNKNOWN_13:
389 case OPCODE_UNKNOWN_14:
390 case OPCODE_UNKNOWN_15:
391 debug_ipmovie("unknown (but documented) opcode %02X\n", opcode_type);
392 url_fseek(pb, opcode_size, SEEK_CUR);
393 break;
395 case OPCODE_SEND_BUFFER:
396 debug_ipmovie("send buffer\n");
397 url_fseek(pb, opcode_size, SEEK_CUR);
398 break;
400 case OPCODE_AUDIO_FRAME:
401 debug_ipmovie("audio frame\n");
403 /* log position and move on for now */
404 s->audio_chunk_offset = url_ftell(pb);
405 s->audio_chunk_size = opcode_size;
406 url_fseek(pb, opcode_size, SEEK_CUR);
407 break;
409 case OPCODE_SILENCE_FRAME:
410 debug_ipmovie("silence frame\n");
411 url_fseek(pb, opcode_size, SEEK_CUR);
412 break;
414 case OPCODE_INIT_VIDEO_MODE:
415 debug_ipmovie("initialize video mode\n");
416 url_fseek(pb, opcode_size, SEEK_CUR);
417 break;
419 case OPCODE_CREATE_GRADIENT:
420 debug_ipmovie("create gradient\n");
421 url_fseek(pb, opcode_size, SEEK_CUR);
422 break;
424 case OPCODE_SET_PALETTE:
425 debug_ipmovie("set palette\n");
426 /* check for the logical maximum palette size
427 * (3 * 256 + 4 bytes) */
428 if (opcode_size > 0x304) {
429 debug_ipmovie("demux_ipmovie: set_palette opcode too large\n");
430 chunk_type = CHUNK_BAD;
431 break;
433 if (get_buffer(pb, scratch, opcode_size) != opcode_size) {
434 chunk_type = CHUNK_BAD;
435 break;
438 /* load the palette into internal data structure */
439 first_color = AV_RL16(&scratch[0]);
440 last_color = first_color + AV_RL16(&scratch[2]) - 1;
441 /* sanity check (since they are 16 bit values) */
442 if ((first_color > 0xFF) || (last_color > 0xFF)) {
443 debug_ipmovie("demux_ipmovie: set_palette indexes out of range (%d -> %d)\n",
444 first_color, last_color);
445 chunk_type = CHUNK_BAD;
446 break;
448 j = 4; /* offset of first palette data */
449 for (i = first_color; i <= last_color; i++) {
450 /* the palette is stored as a 6-bit VGA palette, thus each
451 * component is shifted up to a 8-bit range */
452 r = scratch[j++] * 4;
453 g = scratch[j++] * 4;
454 b = scratch[j++] * 4;
455 s->palette_control.palette[i] = (r << 16) | (g << 8) | (b);
457 /* indicate a palette change */
458 s->palette_control.palette_changed = 1;
459 break;
461 case OPCODE_SET_PALETTE_COMPRESSED:
462 debug_ipmovie("set palette compressed\n");
463 url_fseek(pb, opcode_size, SEEK_CUR);
464 break;
466 case OPCODE_SET_DECODING_MAP:
467 debug_ipmovie("set decoding map\n");
469 /* log position and move on for now */
470 s->decode_map_chunk_offset = url_ftell(pb);
471 s->decode_map_chunk_size = opcode_size;
472 url_fseek(pb, opcode_size, SEEK_CUR);
473 break;
475 case OPCODE_VIDEO_DATA:
476 debug_ipmovie("set video data\n");
478 /* log position and move on for now */
479 s->video_chunk_offset = url_ftell(pb);
480 s->video_chunk_size = opcode_size;
481 url_fseek(pb, opcode_size, SEEK_CUR);
482 break;
484 default:
485 debug_ipmovie("*** unknown opcode type\n");
486 chunk_type = CHUNK_BAD;
487 break;
492 /* make a note of where the stream is sitting */
493 s->next_chunk_offset = url_ftell(pb);
495 /* dispatch the first of any pending packets */
496 if ((chunk_type == CHUNK_VIDEO) || (chunk_type == CHUNK_AUDIO_ONLY))
497 chunk_type = load_ipmovie_packet(s, pb, pkt);
499 return chunk_type;
502 static int ipmovie_probe(AVProbeData *p)
504 if (strncmp(p->buf, IPMOVIE_SIGNATURE, IPMOVIE_SIGNATURE_SIZE) != 0)
505 return 0;
507 return AVPROBE_SCORE_MAX;
510 static int ipmovie_read_header(AVFormatContext *s,
511 AVFormatParameters *ap)
513 IPMVEContext *ipmovie = s->priv_data;
514 ByteIOContext *pb = s->pb;
515 AVPacket pkt;
516 AVStream *st;
517 unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
518 int chunk_type;
520 /* initialize private context members */
521 ipmovie->video_pts = ipmovie->audio_frame_count = 0;
522 ipmovie->audio_chunk_offset = ipmovie->video_chunk_offset =
523 ipmovie->decode_map_chunk_offset = 0;
525 /* on the first read, this will position the stream at the first chunk */
526 ipmovie->next_chunk_offset = IPMOVIE_SIGNATURE_SIZE + 6;
528 /* process the first chunk which should be CHUNK_INIT_VIDEO */
529 if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_VIDEO)
530 return AVERROR_INVALIDDATA;
532 /* peek ahead to the next chunk-- if it is an init audio chunk, process
533 * it; if it is the first video chunk, this is a silent file */
534 if (get_buffer(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
535 CHUNK_PREAMBLE_SIZE)
536 return AVERROR(EIO);
537 chunk_type = AV_RL16(&chunk_preamble[2]);
538 url_fseek(pb, -CHUNK_PREAMBLE_SIZE, SEEK_CUR);
540 if (chunk_type == CHUNK_VIDEO)
541 ipmovie->audio_type = CODEC_ID_NONE; /* no audio */
542 else if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_AUDIO)
543 return AVERROR_INVALIDDATA;
545 /* initialize the stream decoders */
546 st = av_new_stream(s, 0);
547 if (!st)
548 return AVERROR(ENOMEM);
549 av_set_pts_info(st, 63, 1, 1000000);
550 ipmovie->video_stream_index = st->index;
551 st->codec->codec_type = CODEC_TYPE_VIDEO;
552 st->codec->codec_id = CODEC_ID_INTERPLAY_VIDEO;
553 st->codec->codec_tag = 0; /* no fourcc */
554 st->codec->width = ipmovie->video_width;
555 st->codec->height = ipmovie->video_height;
557 /* palette considerations */
558 st->codec->palctrl = &ipmovie->palette_control;
560 if (ipmovie->audio_type) {
561 st = av_new_stream(s, 0);
562 if (!st)
563 return AVERROR(ENOMEM);
564 av_set_pts_info(st, 32, 1, ipmovie->audio_sample_rate);
565 ipmovie->audio_stream_index = st->index;
566 st->codec->codec_type = CODEC_TYPE_AUDIO;
567 st->codec->codec_id = ipmovie->audio_type;
568 st->codec->codec_tag = 0; /* no tag */
569 st->codec->channels = ipmovie->audio_channels;
570 st->codec->sample_rate = ipmovie->audio_sample_rate;
571 st->codec->bits_per_coded_sample = ipmovie->audio_bits;
572 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
573 st->codec->bits_per_coded_sample;
574 if (st->codec->codec_id == CODEC_ID_INTERPLAY_DPCM)
575 st->codec->bit_rate /= 2;
576 st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
579 return 0;
582 static int ipmovie_read_packet(AVFormatContext *s,
583 AVPacket *pkt)
585 IPMVEContext *ipmovie = s->priv_data;
586 ByteIOContext *pb = s->pb;
587 int ret;
589 ret = process_ipmovie_chunk(ipmovie, pb, pkt);
590 if (ret == CHUNK_BAD)
591 ret = AVERROR_INVALIDDATA;
592 else if (ret == CHUNK_EOF)
593 ret = AVERROR(EIO);
594 else if (ret == CHUNK_NOMEM)
595 ret = AVERROR(ENOMEM);
596 else if (ret == CHUNK_VIDEO)
597 ret = 0;
598 else
599 ret = -1;
601 return ret;
604 AVInputFormat ipmovie_demuxer = {
605 "ipmovie",
606 NULL_IF_CONFIG_SMALL("Interplay MVE format"),
607 sizeof(IPMVEContext),
608 ipmovie_probe,
609 ipmovie_read_header,
610 ipmovie_read_packet,