]> git.sesse.net Git - ffmpeg/blob - libavformat/ipmovie.c
avfilter/vf_scale: store the offset in a local variable before adding it
[ffmpeg] / libavformat / ipmovie.c
1 /*
2  * Interplay MVE File Demuxer
3  * Copyright (c) 2003 The FFmpeg project
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  * 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.
33  */
34
35 #include "libavutil/channel_layout.h"
36 #include "libavutil/intreadwrite.h"
37 #include "avformat.h"
38 #include "internal.h"
39
40 #define CHUNK_PREAMBLE_SIZE 4
41 #define OPCODE_PREAMBLE_SIZE 4
42
43 #define CHUNK_INIT_AUDIO   0x0000
44 #define CHUNK_AUDIO_ONLY   0x0001
45 #define CHUNK_INIT_VIDEO   0x0002
46 #define CHUNK_VIDEO        0x0003
47 #define CHUNK_SHUTDOWN     0x0004
48 #define CHUNK_END          0x0005
49 /* these last types are used internally */
50 #define CHUNK_HAVE_PACKET  0xFFFB
51 #define CHUNK_DONE         0xFFFC
52 #define CHUNK_NOMEM        0xFFFD
53 #define CHUNK_EOF          0xFFFE
54 #define CHUNK_BAD          0xFFFF
55
56 #define OPCODE_END_OF_STREAM           0x00
57 #define OPCODE_END_OF_CHUNK            0x01
58 #define OPCODE_CREATE_TIMER            0x02
59 #define OPCODE_INIT_AUDIO_BUFFERS      0x03
60 #define OPCODE_START_STOP_AUDIO        0x04
61 #define OPCODE_INIT_VIDEO_BUFFERS      0x05
62 #define OPCODE_VIDEO_DATA_06           0x06
63 #define OPCODE_SEND_BUFFER             0x07
64 #define OPCODE_AUDIO_FRAME             0x08
65 #define OPCODE_SILENCE_FRAME           0x09
66 #define OPCODE_INIT_VIDEO_MODE         0x0A
67 #define OPCODE_CREATE_GRADIENT         0x0B
68 #define OPCODE_SET_PALETTE             0x0C
69 #define OPCODE_SET_PALETTE_COMPRESSED  0x0D
70 #define OPCODE_SET_SKIP_MAP            0x0E
71 #define OPCODE_SET_DECODING_MAP        0x0F
72 #define OPCODE_VIDEO_DATA_10           0x10
73 #define OPCODE_VIDEO_DATA_11           0x11
74 #define OPCODE_UNKNOWN_12              0x12
75 #define OPCODE_UNKNOWN_13              0x13
76 #define OPCODE_UNKNOWN_14              0x14
77 #define OPCODE_UNKNOWN_15              0x15
78
79 #define PALETTE_COUNT 256
80
81 typedef struct IPMVEContext {
82     AVFormatContext *avf;
83     unsigned char *buf;
84     int buf_size;
85
86     uint64_t frame_pts_inc;
87
88     unsigned int video_bpp;
89     unsigned int video_width;
90     unsigned int video_height;
91     int64_t video_pts;
92     uint32_t     palette[256];
93     int          has_palette;
94     int          changed;
95     uint8_t      send_buffer;
96     uint8_t      frame_format;
97
98     unsigned int audio_bits;
99     unsigned int audio_channels;
100     unsigned int audio_sample_rate;
101     enum AVCodecID audio_type;
102     unsigned int audio_frame_count;
103
104     int video_stream_index;
105     int audio_stream_index;
106
107     int64_t audio_chunk_offset;
108     int audio_chunk_size;
109     int64_t video_chunk_offset;
110     int video_chunk_size;
111     int64_t skip_map_chunk_offset;
112     int skip_map_chunk_size;
113     int64_t decode_map_chunk_offset;
114     int decode_map_chunk_size;
115
116     int64_t next_chunk_offset;
117
118 } IPMVEContext;
119
120 static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb,
121     AVPacket *pkt) {
122
123     int chunk_type;
124
125     if (s->audio_chunk_offset && s->audio_channels && s->audio_bits) {
126         if (s->audio_type == AV_CODEC_ID_NONE) {
127             av_log(s->avf, AV_LOG_ERROR, "Can not read audio packet before"
128                    "audio codec is known\n");
129                 return CHUNK_BAD;
130         }
131
132         /* adjust for PCM audio by skipping chunk header */
133         if (s->audio_type != AV_CODEC_ID_INTERPLAY_DPCM) {
134             s->audio_chunk_offset += 6;
135             s->audio_chunk_size -= 6;
136         }
137
138         avio_seek(pb, s->audio_chunk_offset, SEEK_SET);
139         s->audio_chunk_offset = 0;
140
141         if (s->audio_chunk_size != av_get_packet(pb, pkt, s->audio_chunk_size))
142             return CHUNK_EOF;
143
144         pkt->stream_index = s->audio_stream_index;
145         pkt->pts = s->audio_frame_count;
146
147         /* audio frame maintenance */
148         if (s->audio_type != AV_CODEC_ID_INTERPLAY_DPCM)
149             s->audio_frame_count +=
150             (s->audio_chunk_size / s->audio_channels / (s->audio_bits / 8));
151         else
152             s->audio_frame_count +=
153                 (s->audio_chunk_size - 6 - s->audio_channels) / s->audio_channels;
154
155         av_log(s->avf, AV_LOG_TRACE, "sending audio frame with pts %"PRId64" (%d audio frames)\n",
156                 pkt->pts, s->audio_frame_count);
157
158         chunk_type = CHUNK_HAVE_PACKET;
159
160     } else if (s->frame_format) {
161
162         /* send the frame format, decode map, the video data, skip map, and the send_buffer flag together */
163
164         if (av_new_packet(pkt, 8 + s->decode_map_chunk_size + s->video_chunk_size + s->skip_map_chunk_size))
165             return CHUNK_NOMEM;
166
167         if (s->has_palette) {
168             uint8_t *pal;
169
170             pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE,
171                                           AVPALETTE_SIZE);
172             if (pal) {
173                 memcpy(pal, s->palette, AVPALETTE_SIZE);
174                 s->has_palette = 0;
175             }
176         }
177
178         if (s->changed) {
179             ff_add_param_change(pkt, 0, 0, 0, s->video_width, s->video_height);
180             s->changed = 0;
181         }
182
183         AV_WL8(pkt->data, s->frame_format);
184         AV_WL8(pkt->data + 1, s->send_buffer);
185         AV_WL16(pkt->data + 2, s->video_chunk_size);
186         AV_WL16(pkt->data + 4, s->decode_map_chunk_size);
187         AV_WL16(pkt->data + 6, s->skip_map_chunk_size);
188
189         s->frame_format = 0;
190         s->send_buffer = 0;
191
192         pkt->pos = s->video_chunk_offset;
193         avio_seek(pb, s->video_chunk_offset, SEEK_SET);
194         s->video_chunk_offset = 0;
195
196         if (avio_read(pb, pkt->data + 8, s->video_chunk_size) !=
197             s->video_chunk_size) {
198             return CHUNK_EOF;
199         }
200
201         if (s->decode_map_chunk_size) {
202             pkt->pos = s->decode_map_chunk_offset;
203             avio_seek(pb, s->decode_map_chunk_offset, SEEK_SET);
204             s->decode_map_chunk_offset = 0;
205
206             if (avio_read(pb, pkt->data + 8 + s->video_chunk_size,
207                 s->decode_map_chunk_size) != s->decode_map_chunk_size) {
208                 return CHUNK_EOF;
209             }
210         }
211
212         if (s->skip_map_chunk_size) {
213             pkt->pos = s->skip_map_chunk_offset;
214             avio_seek(pb, s->skip_map_chunk_offset, SEEK_SET);
215             s->skip_map_chunk_offset = 0;
216
217             if (avio_read(pb, pkt->data + 8 + s->video_chunk_size + s->decode_map_chunk_size,
218                 s->skip_map_chunk_size) != s->skip_map_chunk_size) {
219                 return CHUNK_EOF;
220             }
221         }
222
223         s->video_chunk_size = 0;
224         s->decode_map_chunk_size = 0;
225         s->skip_map_chunk_size = 0;
226
227         pkt->stream_index = s->video_stream_index;
228         pkt->pts = s->video_pts;
229
230         av_log(s->avf, AV_LOG_TRACE, "sending video frame with pts %"PRId64"\n", pkt->pts);
231
232         s->video_pts += s->frame_pts_inc;
233
234         chunk_type = CHUNK_HAVE_PACKET;
235
236     } else {
237
238         avio_seek(pb, s->next_chunk_offset, SEEK_SET);
239         chunk_type = CHUNK_DONE;
240
241     }
242
243     return chunk_type;
244 }
245
246 static int init_audio(AVFormatContext *s)
247 {
248     IPMVEContext *ipmovie = s->priv_data;
249     AVStream *st = avformat_new_stream(s, NULL);
250     if (!st)
251         return AVERROR(ENOMEM);
252     avpriv_set_pts_info(st, 32, 1, ipmovie->audio_sample_rate);
253     ipmovie->audio_stream_index = st->index;
254     st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
255     st->codecpar->codec_id = ipmovie->audio_type;
256     st->codecpar->codec_tag = 0;  /* no tag */
257     st->codecpar->channels = ipmovie->audio_channels;
258     st->codecpar->channel_layout = st->codecpar->channels == 1 ? AV_CH_LAYOUT_MONO :
259                                                             AV_CH_LAYOUT_STEREO;
260     st->codecpar->sample_rate = ipmovie->audio_sample_rate;
261     st->codecpar->bits_per_coded_sample = ipmovie->audio_bits;
262     st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate *
263         st->codecpar->bits_per_coded_sample;
264     if (st->codecpar->codec_id == AV_CODEC_ID_INTERPLAY_DPCM)
265         st->codecpar->bit_rate /= 2;
266     st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample;
267
268     return 0;
269 }
270
271 /* This function loads and processes a single chunk in an IP movie file.
272  * It returns the type of chunk that was processed. */
273 static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb,
274     AVPacket *pkt)
275 {
276     unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
277     int chunk_type;
278     int chunk_size;
279     unsigned char opcode_preamble[OPCODE_PREAMBLE_SIZE];
280     unsigned char opcode_type;
281     unsigned char opcode_version;
282     int opcode_size;
283     unsigned char scratch[1024];
284     int i, j;
285     int first_color, last_color;
286     int audio_flags;
287     unsigned char r, g, b;
288     unsigned int width, height;
289
290     /* see if there are any pending packets */
291     chunk_type = load_ipmovie_packet(s, pb, pkt);
292     if (chunk_type != CHUNK_DONE)
293         return chunk_type;
294
295     /* read the next chunk, wherever the file happens to be pointing */
296     if (avio_feof(pb))
297         return CHUNK_EOF;
298     if (avio_read(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
299         CHUNK_PREAMBLE_SIZE)
300         return CHUNK_BAD;
301     chunk_size = AV_RL16(&chunk_preamble[0]);
302     chunk_type = AV_RL16(&chunk_preamble[2]);
303
304     av_log(s->avf, AV_LOG_TRACE, "chunk type 0x%04X, 0x%04X bytes: ", chunk_type, chunk_size);
305
306     switch (chunk_type) {
307
308     case CHUNK_INIT_AUDIO:
309         av_log(s->avf, AV_LOG_TRACE, "initialize audio\n");
310         break;
311
312     case CHUNK_AUDIO_ONLY:
313         av_log(s->avf, AV_LOG_TRACE, "audio only\n");
314         break;
315
316     case CHUNK_INIT_VIDEO:
317         av_log(s->avf, AV_LOG_TRACE, "initialize video\n");
318         break;
319
320     case CHUNK_VIDEO:
321         av_log(s->avf, AV_LOG_TRACE, "video (and audio)\n");
322         break;
323
324     case CHUNK_SHUTDOWN:
325         av_log(s->avf, AV_LOG_TRACE, "shutdown\n");
326         break;
327
328     case CHUNK_END:
329         av_log(s->avf, AV_LOG_TRACE, "end\n");
330         break;
331
332     default:
333         av_log(s->avf, AV_LOG_TRACE, "invalid chunk\n");
334         chunk_type = CHUNK_BAD;
335         break;
336
337     }
338
339     while ((chunk_size > 0) && (chunk_type != CHUNK_BAD)) {
340
341         /* read the next chunk, wherever the file happens to be pointing */
342         if (avio_feof(pb)) {
343             chunk_type = CHUNK_EOF;
344             break;
345         }
346         if (avio_read(pb, opcode_preamble, CHUNK_PREAMBLE_SIZE) !=
347             CHUNK_PREAMBLE_SIZE) {
348             chunk_type = CHUNK_BAD;
349             break;
350         }
351
352         opcode_size = AV_RL16(&opcode_preamble[0]);
353         opcode_type = opcode_preamble[2];
354         opcode_version = opcode_preamble[3];
355
356         chunk_size -= OPCODE_PREAMBLE_SIZE;
357         chunk_size -= opcode_size;
358         if (chunk_size < 0) {
359             av_log(s->avf, AV_LOG_TRACE, "chunk_size countdown just went negative\n");
360             chunk_type = CHUNK_BAD;
361             break;
362         }
363
364         av_log(s->avf, AV_LOG_TRACE, "  opcode type %02X, version %d, 0x%04X bytes: ",
365                 opcode_type, opcode_version, opcode_size);
366         switch (opcode_type) {
367
368         case OPCODE_END_OF_STREAM:
369             av_log(s->avf, AV_LOG_TRACE, "end of stream\n");
370             avio_skip(pb, opcode_size);
371             break;
372
373         case OPCODE_END_OF_CHUNK:
374             av_log(s->avf, AV_LOG_TRACE, "end of chunk\n");
375             avio_skip(pb, opcode_size);
376             break;
377
378         case OPCODE_CREATE_TIMER:
379             av_log(s->avf, AV_LOG_TRACE, "create timer\n");
380             if ((opcode_version > 0) || (opcode_size != 6)) {
381                 av_log(s->avf, AV_LOG_TRACE, "bad create_timer opcode\n");
382                 chunk_type = CHUNK_BAD;
383                 break;
384             }
385             if (avio_read(pb, scratch, opcode_size) !=
386                 opcode_size) {
387                 chunk_type = CHUNK_BAD;
388                 break;
389             }
390             s->frame_pts_inc = ((uint64_t)AV_RL32(&scratch[0])) * AV_RL16(&scratch[4]);
391             break;
392
393         case OPCODE_INIT_AUDIO_BUFFERS:
394             av_log(s->avf, AV_LOG_TRACE, "initialize audio buffers\n");
395             if (opcode_version > 1 || opcode_size > 10 || opcode_size < 6) {
396                 av_log(s->avf, AV_LOG_TRACE, "bad init_audio_buffers opcode\n");
397                 chunk_type = CHUNK_BAD;
398                 break;
399             }
400             if (avio_read(pb, scratch, opcode_size) !=
401                 opcode_size) {
402                 chunk_type = CHUNK_BAD;
403                 break;
404             }
405             s->audio_sample_rate = AV_RL16(&scratch[4]);
406             audio_flags = AV_RL16(&scratch[2]);
407             /* bit 0 of the flags: 0 = mono, 1 = stereo */
408             s->audio_channels = (audio_flags & 1) + 1;
409             /* bit 1 of the flags: 0 = 8 bit, 1 = 16 bit */
410             s->audio_bits = (((audio_flags >> 1) & 1) + 1) * 8;
411             /* bit 2 indicates compressed audio in version 1 opcode */
412             if ((opcode_version == 1) && (audio_flags & 0x4))
413                 s->audio_type = AV_CODEC_ID_INTERPLAY_DPCM;
414             else if (s->audio_bits == 16)
415                 s->audio_type = AV_CODEC_ID_PCM_S16LE;
416             else
417                 s->audio_type = AV_CODEC_ID_PCM_U8;
418             av_log(s->avf, AV_LOG_TRACE, "audio: %d bits, %d Hz, %s, %s format\n",
419                     s->audio_bits, s->audio_sample_rate,
420                     (s->audio_channels == 2) ? "stereo" : "mono",
421                     (s->audio_type == AV_CODEC_ID_INTERPLAY_DPCM) ?
422                     "Interplay audio" : "PCM");
423             break;
424
425         case OPCODE_START_STOP_AUDIO:
426             av_log(s->avf, AV_LOG_TRACE, "start/stop audio\n");
427             avio_skip(pb, opcode_size);
428             break;
429
430         case OPCODE_INIT_VIDEO_BUFFERS:
431             av_log(s->avf, AV_LOG_TRACE, "initialize video buffers\n");
432             if ((opcode_version > 2) || (opcode_size > 8) || opcode_size < 4
433                 || opcode_version == 2 && opcode_size < 8
434             ) {
435                 av_log(s->avf, AV_LOG_TRACE, "bad init_video_buffers opcode\n");
436                 chunk_type = CHUNK_BAD;
437                 break;
438             }
439             if (avio_read(pb, scratch, opcode_size) !=
440                 opcode_size) {
441                 chunk_type = CHUNK_BAD;
442                 break;
443             }
444             width  = AV_RL16(&scratch[0]) * 8;
445             height = AV_RL16(&scratch[2]) * 8;
446             if (width != s->video_width) {
447                 s->video_width = width;
448                 s->changed++;
449             }
450             if (height != s->video_height) {
451                 s->video_height = height;
452                 s->changed++;
453             }
454             if (opcode_version < 2 || !AV_RL16(&scratch[6])) {
455                 s->video_bpp = 8;
456             } else {
457                 s->video_bpp = 16;
458             }
459             av_log(s->avf, AV_LOG_TRACE, "video resolution: %d x %d\n",
460                     s->video_width, s->video_height);
461             break;
462
463         case OPCODE_UNKNOWN_12:
464         case OPCODE_UNKNOWN_13:
465         case OPCODE_UNKNOWN_14:
466         case OPCODE_UNKNOWN_15:
467             av_log(s->avf, AV_LOG_TRACE, "unknown (but documented) opcode %02X\n", opcode_type);
468             avio_skip(pb, opcode_size);
469             break;
470
471         case OPCODE_SEND_BUFFER:
472             av_log(s->avf, AV_LOG_TRACE, "send buffer\n");
473             avio_skip(pb, opcode_size);
474             s->send_buffer = 1;
475             break;
476
477         case OPCODE_AUDIO_FRAME:
478             av_log(s->avf, AV_LOG_TRACE, "audio frame\n");
479
480             /* log position and move on for now */
481             s->audio_chunk_offset = avio_tell(pb);
482             s->audio_chunk_size = opcode_size;
483             avio_skip(pb, opcode_size);
484             break;
485
486         case OPCODE_SILENCE_FRAME:
487             av_log(s->avf, AV_LOG_TRACE, "silence frame\n");
488             avio_skip(pb, opcode_size);
489             break;
490
491         case OPCODE_INIT_VIDEO_MODE:
492             av_log(s->avf, AV_LOG_TRACE, "initialize video mode\n");
493             avio_skip(pb, opcode_size);
494             break;
495
496         case OPCODE_CREATE_GRADIENT:
497             av_log(s->avf, AV_LOG_TRACE, "create gradient\n");
498             avio_skip(pb, opcode_size);
499             break;
500
501         case OPCODE_SET_PALETTE:
502             av_log(s->avf, AV_LOG_TRACE, "set palette\n");
503             /* check for the logical maximum palette size
504              * (3 * 256 + 4 bytes) */
505             if (opcode_size > 0x304 || opcode_size < 4) {
506                 av_log(s->avf, AV_LOG_TRACE, "demux_ipmovie: set_palette opcode with invalid size\n");
507                 chunk_type = CHUNK_BAD;
508                 break;
509             }
510             if (avio_read(pb, scratch, opcode_size) != opcode_size) {
511                 chunk_type = CHUNK_BAD;
512                 break;
513             }
514
515             /* load the palette into internal data structure */
516             first_color = AV_RL16(&scratch[0]);
517             last_color = first_color + AV_RL16(&scratch[2]) - 1;
518             /* sanity check (since they are 16 bit values) */
519             if (   (first_color > 0xFF) || (last_color > 0xFF)
520                 || (last_color - first_color + 1)*3 + 4 > opcode_size) {
521                 av_log(s->avf, AV_LOG_TRACE, "demux_ipmovie: set_palette indexes out of range (%d -> %d)\n",
522                     first_color, last_color);
523                 chunk_type = CHUNK_BAD;
524                 break;
525             }
526             j = 4;  /* offset of first palette data */
527             for (i = first_color; i <= last_color; i++) {
528                 /* the palette is stored as a 6-bit VGA palette, thus each
529                  * component is shifted up to a 8-bit range */
530                 r = scratch[j++] * 4;
531                 g = scratch[j++] * 4;
532                 b = scratch[j++] * 4;
533                 s->palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | (b);
534                 s->palette[i] |= s->palette[i] >> 6 & 0x30303;
535             }
536             s->has_palette = 1;
537             break;
538
539         case OPCODE_SET_PALETTE_COMPRESSED:
540             av_log(s->avf, AV_LOG_TRACE, "set palette compressed\n");
541             avio_skip(pb, opcode_size);
542             break;
543
544         case OPCODE_SET_SKIP_MAP:
545             av_log(s->avf, AV_LOG_TRACE, "set skip map\n");
546
547             /* log position and move on for now */
548             s->skip_map_chunk_offset = avio_tell(pb);
549             s->skip_map_chunk_size = opcode_size;
550             avio_skip(pb, opcode_size);
551             break;
552
553         case OPCODE_SET_DECODING_MAP:
554             av_log(s->avf, AV_LOG_TRACE, "set decoding map\n");
555
556             /* log position and move on for now */
557             s->decode_map_chunk_offset = avio_tell(pb);
558             s->decode_map_chunk_size = opcode_size;
559             avio_skip(pb, opcode_size);
560             break;
561
562         case OPCODE_VIDEO_DATA_06:
563         case OPCODE_VIDEO_DATA_10:
564         case OPCODE_VIDEO_DATA_11:
565             s->frame_format = opcode_type;
566             av_log(s->avf, AV_LOG_TRACE, "set video data format 0x%02X\n",
567                    opcode_type);
568
569             /* log position and move on for now */
570             s->video_chunk_offset = avio_tell(pb);
571             s->video_chunk_size = opcode_size;
572             avio_skip(pb, opcode_size);
573             break;
574
575         default:
576             av_log(s->avf, AV_LOG_TRACE, "*** unknown opcode type\n");
577             chunk_type = CHUNK_BAD;
578             break;
579
580         }
581     }
582
583     if (s->avf->nb_streams == 1 && s->audio_type)
584         init_audio(s->avf);
585
586     /* make a note of where the stream is sitting */
587     s->next_chunk_offset = avio_tell(pb);
588
589     return chunk_type;
590 }
591
592 static const char signature[] = "Interplay MVE File\x1A\0\x1A";
593
594 static int ipmovie_probe(const AVProbeData *p)
595 {
596     const uint8_t *b = p->buf;
597     const uint8_t *b_end = p->buf + p->buf_size - sizeof(signature);
598     do {
599         if (b[0] == signature[0] && memcmp(b, signature, sizeof(signature)) == 0)
600             return AVPROBE_SCORE_MAX;
601         b++;
602     } while (b < b_end);
603
604     return 0;
605 }
606
607 static int ipmovie_read_header(AVFormatContext *s)
608 {
609     IPMVEContext *ipmovie = s->priv_data;
610     AVIOContext *pb = s->pb;
611     AVStream *st;
612     unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
613     int chunk_type, i;
614     uint8_t signature_buffer[sizeof(signature)];
615
616     ipmovie->avf = s;
617
618     avio_read(pb, signature_buffer, sizeof(signature_buffer));
619     while (memcmp(signature_buffer, signature, sizeof(signature))) {
620         memmove(signature_buffer, signature_buffer + 1, sizeof(signature_buffer) - 1);
621         signature_buffer[sizeof(signature_buffer) - 1] = avio_r8(pb);
622         if (avio_feof(pb))
623             return AVERROR_EOF;
624     }
625
626     /* on the first read, this will position the stream at the first chunk */
627     ipmovie->next_chunk_offset = avio_tell(pb) + 4;
628
629     for (i = 0; i < 256; i++)
630         ipmovie->palette[i] = 0xFFU << 24;
631
632     /* process the first chunk which should be CHUNK_INIT_VIDEO */
633     if (process_ipmovie_chunk(ipmovie, pb, NULL) != CHUNK_INIT_VIDEO) {
634         return AVERROR_INVALIDDATA;
635     }
636
637     /* peek ahead to the next chunk-- if it is an init audio chunk, process
638      * it; if it is the first video chunk, this is a silent file */
639     if (avio_read(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
640         CHUNK_PREAMBLE_SIZE)
641         return AVERROR(EIO);
642     chunk_type = AV_RL16(&chunk_preamble[2]);
643     avio_seek(pb, -CHUNK_PREAMBLE_SIZE, SEEK_CUR);
644
645     if (chunk_type == CHUNK_VIDEO)
646         ipmovie->audio_type = AV_CODEC_ID_NONE;  /* no audio */
647     else if (process_ipmovie_chunk(ipmovie, pb, s->internal->parse_pkt) != CHUNK_INIT_AUDIO) {
648         return AVERROR_INVALIDDATA;
649     }
650
651     /* initialize the stream decoders */
652     st = avformat_new_stream(s, NULL);
653     if (!st)
654         return AVERROR(ENOMEM);
655     avpriv_set_pts_info(st, 63, 1, 1000000);
656     ipmovie->video_stream_index = st->index;
657     st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
658     st->codecpar->codec_id = AV_CODEC_ID_INTERPLAY_VIDEO;
659     st->codecpar->codec_tag = 0;  /* no fourcc */
660     st->codecpar->width = ipmovie->video_width;
661     st->codecpar->height = ipmovie->video_height;
662     st->codecpar->bits_per_coded_sample = ipmovie->video_bpp;
663
664     if (ipmovie->audio_type) {
665         return init_audio(s);
666     } else
667        s->ctx_flags |= AVFMTCTX_NOHEADER;
668
669     return 0;
670 }
671
672 static int ipmovie_read_packet(AVFormatContext *s,
673                                AVPacket *pkt)
674 {
675     IPMVEContext *ipmovie = s->priv_data;
676     AVIOContext *pb = s->pb;
677     int ret;
678
679     for (;;) {
680         ret = process_ipmovie_chunk(ipmovie, pb, pkt);
681         /* dispatch the first of any pending packets */
682         if ((ret == CHUNK_VIDEO) || (ret == CHUNK_AUDIO_ONLY))
683             ret = load_ipmovie_packet(ipmovie, pb, pkt);
684
685         if (ret == CHUNK_BAD)
686             ret = AVERROR_INVALIDDATA;
687         else if (ret == CHUNK_EOF)
688             ret = AVERROR(EIO);
689         else if (ret == CHUNK_NOMEM)
690             ret = AVERROR(ENOMEM);
691         else if (ret == CHUNK_END || ret == CHUNK_SHUTDOWN)
692             ret = AVERROR_EOF;
693         else if (ret == CHUNK_HAVE_PACKET)
694             ret = 0;
695         else if (ret == CHUNK_INIT_VIDEO || ret == CHUNK_INIT_AUDIO)
696             continue;
697         else
698             continue;
699
700         return ret;
701     }
702 }
703
704 const AVInputFormat ff_ipmovie_demuxer = {
705     .name           = "ipmovie",
706     .long_name      = NULL_IF_CONFIG_SMALL("Interplay MVE"),
707     .priv_data_size = sizeof(IPMVEContext),
708     .read_probe     = ipmovie_probe,
709     .read_header    = ipmovie_read_header,
710     .read_packet    = ipmovie_read_packet,
711 };