FFmpeg
ipmovie.c
Go to the documentation of this file.
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 
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_DONE 0xFFFC
51 #define CHUNK_NOMEM 0xFFFD
52 #define CHUNK_EOF 0xFFFE
53 #define CHUNK_BAD 0xFFFF
54 
55 #define OPCODE_END_OF_STREAM 0x00
56 #define OPCODE_END_OF_CHUNK 0x01
57 #define OPCODE_CREATE_TIMER 0x02
58 #define OPCODE_INIT_AUDIO_BUFFERS 0x03
59 #define OPCODE_START_STOP_AUDIO 0x04
60 #define OPCODE_INIT_VIDEO_BUFFERS 0x05
61 #define OPCODE_VIDEO_DATA_06 0x06
62 #define OPCODE_SEND_BUFFER 0x07
63 #define OPCODE_AUDIO_FRAME 0x08
64 #define OPCODE_SILENCE_FRAME 0x09
65 #define OPCODE_INIT_VIDEO_MODE 0x0A
66 #define OPCODE_CREATE_GRADIENT 0x0B
67 #define OPCODE_SET_PALETTE 0x0C
68 #define OPCODE_SET_PALETTE_COMPRESSED 0x0D
69 #define OPCODE_SET_SKIP_MAP 0x0E
70 #define OPCODE_SET_DECODING_MAP 0x0F
71 #define OPCODE_VIDEO_DATA_10 0x10
72 #define OPCODE_VIDEO_DATA_11 0x11
73 #define OPCODE_UNKNOWN_12 0x12
74 #define OPCODE_UNKNOWN_13 0x13
75 #define OPCODE_UNKNOWN_14 0x14
76 #define OPCODE_UNKNOWN_15 0x15
77 
78 #define PALETTE_COUNT 256
79 
80 typedef struct IPMVEContext {
82  unsigned char *buf;
83  int buf_size;
84 
85  uint64_t frame_pts_inc;
86 
87  unsigned int video_bpp;
88  unsigned int video_width;
89  unsigned int video_height;
90  int64_t video_pts;
91  uint32_t palette[256];
93  int changed;
96 
97  unsigned int audio_bits;
98  unsigned int audio_channels;
99  unsigned int audio_sample_rate;
101  unsigned int audio_frame_count;
102 
105 
114 
116 
117 } IPMVEContext;
118 
120  AVPacket *pkt) {
121 
122  int chunk_type;
123 
124  if (s->audio_chunk_offset && s->audio_channels && s->audio_bits) {
125  if (s->audio_type == AV_CODEC_ID_NONE) {
126  av_log(s->avf, AV_LOG_ERROR, "Can not read audio packet before"
127  "audio codec is known\n");
128  return CHUNK_BAD;
129  }
130 
131  /* adjust for PCM audio by skipping chunk header */
132  if (s->audio_type != AV_CODEC_ID_INTERPLAY_DPCM) {
133  s->audio_chunk_offset += 6;
134  s->audio_chunk_size -= 6;
135  }
136 
137  avio_seek(pb, s->audio_chunk_offset, SEEK_SET);
138  s->audio_chunk_offset = 0;
139 
140  if (s->audio_chunk_size != av_get_packet(pb, pkt, s->audio_chunk_size))
141  return CHUNK_EOF;
142 
143  pkt->stream_index = s->audio_stream_index;
144  pkt->pts = s->audio_frame_count;
145 
146  /* audio frame maintenance */
147  if (s->audio_type != AV_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) / s->audio_channels;
153 
154  av_log(s->avf, AV_LOG_TRACE, "sending audio frame with pts %"PRId64" (%d audio frames)\n",
155  pkt->pts, s->audio_frame_count);
156 
157  chunk_type = CHUNK_VIDEO;
158 
159  } else if (s->frame_format) {
160 
161  /* send the frame format, decode map, the video data, skip map, and the send_buffer flag together */
162 
163  if (av_new_packet(pkt, 8 + s->decode_map_chunk_size + s->video_chunk_size + s->skip_map_chunk_size))
164  return CHUNK_NOMEM;
165 
166  if (s->has_palette) {
167  uint8_t *pal;
168 
171  if (pal) {
172  memcpy(pal, s->palette, AVPALETTE_SIZE);
173  s->has_palette = 0;
174  }
175  }
176 
177  if (s->changed) {
178  ff_add_param_change(pkt, 0, 0, 0, s->video_width, s->video_height);
179  s->changed = 0;
180  }
181 
182  AV_WL8(pkt->data, s->frame_format);
183  AV_WL8(pkt->data + 1, s->send_buffer);
184  AV_WL16(pkt->data + 2, s->video_chunk_size);
185  AV_WL16(pkt->data + 4, s->decode_map_chunk_size);
186  AV_WL16(pkt->data + 6, s->skip_map_chunk_size);
187 
188  s->frame_format = 0;
189  s->send_buffer = 0;
190 
191  pkt->pos = s->video_chunk_offset;
192  avio_seek(pb, s->video_chunk_offset, SEEK_SET);
193  s->video_chunk_offset = 0;
194 
195  if (avio_read(pb, pkt->data + 8, s->video_chunk_size) !=
196  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) {
209  return CHUNK_EOF;
210  }
211  }
212 
213  if (s->skip_map_chunk_size) {
214  pkt->pos = s->skip_map_chunk_offset;
215  avio_seek(pb, s->skip_map_chunk_offset, SEEK_SET);
216  s->skip_map_chunk_offset = 0;
217 
218  if (avio_read(pb, pkt->data + 8 + s->video_chunk_size + s->decode_map_chunk_size,
219  s->skip_map_chunk_size) != s->skip_map_chunk_size) {
221  return CHUNK_EOF;
222  }
223  }
224 
225  s->video_chunk_size = 0;
226  s->decode_map_chunk_size = 0;
227  s->skip_map_chunk_size = 0;
228 
229  pkt->stream_index = s->video_stream_index;
230  pkt->pts = s->video_pts;
231 
232  av_log(s->avf, AV_LOG_TRACE, "sending video frame with pts %"PRId64"\n", pkt->pts);
233 
234  s->video_pts += s->frame_pts_inc;
235 
236  chunk_type = CHUNK_VIDEO;
237 
238  } else {
239 
240  avio_seek(pb, s->next_chunk_offset, SEEK_SET);
241  chunk_type = CHUNK_DONE;
242 
243  }
244 
245  return chunk_type;
246 }
247 
249 {
250  IPMVEContext *ipmovie = s->priv_data;
252  if (!st)
253  return AVERROR(ENOMEM);
254  avpriv_set_pts_info(st, 32, 1, ipmovie->audio_sample_rate);
255  ipmovie->audio_stream_index = st->index;
257  st->codecpar->codec_id = ipmovie->audio_type;
258  st->codecpar->codec_tag = 0; /* no tag */
259  st->codecpar->channels = ipmovie->audio_channels;
262  st->codecpar->sample_rate = ipmovie->audio_sample_rate;
263  st->codecpar->bits_per_coded_sample = ipmovie->audio_bits;
267  st->codecpar->bit_rate /= 2;
269 
270  return 0;
271 }
272 
273 /* This function loads and processes a single chunk in an IP movie file.
274  * It returns the type of chunk that was processed. */
276  AVPacket *pkt)
277 {
278  unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
279  int chunk_type;
280  int chunk_size;
281  unsigned char opcode_preamble[OPCODE_PREAMBLE_SIZE];
282  unsigned char opcode_type;
283  unsigned char opcode_version;
284  int opcode_size;
285  unsigned char scratch[1024];
286  int i, j;
287  int first_color, last_color;
288  int audio_flags;
289  unsigned char r, g, b;
290  unsigned int width, height;
291 
292  /* see if there are any pending packets */
293  chunk_type = load_ipmovie_packet(s, pb, pkt);
294  if (chunk_type != CHUNK_DONE)
295  return chunk_type;
296 
297  /* read the next chunk, wherever the file happens to be pointing */
298  if (avio_feof(pb))
299  return CHUNK_EOF;
300  if (avio_read(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
302  return CHUNK_BAD;
303  chunk_size = AV_RL16(&chunk_preamble[0]);
304  chunk_type = AV_RL16(&chunk_preamble[2]);
305 
306  av_log(s->avf, AV_LOG_TRACE, "chunk type 0x%04X, 0x%04X bytes: ", chunk_type, chunk_size);
307 
308  switch (chunk_type) {
309 
310  case CHUNK_INIT_AUDIO:
311  av_log(s->avf, AV_LOG_TRACE, "initialize audio\n");
312  break;
313 
314  case CHUNK_AUDIO_ONLY:
315  av_log(s->avf, AV_LOG_TRACE, "audio only\n");
316  break;
317 
318  case CHUNK_INIT_VIDEO:
319  av_log(s->avf, AV_LOG_TRACE, "initialize video\n");
320  break;
321 
322  case CHUNK_VIDEO:
323  av_log(s->avf, AV_LOG_TRACE, "video (and audio)\n");
324  break;
325 
326  case CHUNK_SHUTDOWN:
327  av_log(s->avf, AV_LOG_TRACE, "shutdown\n");
328  break;
329 
330  case CHUNK_END:
331  av_log(s->avf, AV_LOG_TRACE, "end\n");
332  break;
333 
334  default:
335  av_log(s->avf, AV_LOG_TRACE, "invalid chunk\n");
336  chunk_type = CHUNK_BAD;
337  break;
338 
339  }
340 
341  while ((chunk_size > 0) && (chunk_type != CHUNK_BAD)) {
342 
343  /* read the next chunk, wherever the file happens to be pointing */
344  if (avio_feof(pb)) {
345  chunk_type = CHUNK_EOF;
346  break;
347  }
348  if (avio_read(pb, opcode_preamble, CHUNK_PREAMBLE_SIZE) !=
350  chunk_type = CHUNK_BAD;
351  break;
352  }
353 
354  opcode_size = AV_RL16(&opcode_preamble[0]);
355  opcode_type = opcode_preamble[2];
356  opcode_version = opcode_preamble[3];
357 
358  chunk_size -= OPCODE_PREAMBLE_SIZE;
359  chunk_size -= opcode_size;
360  if (chunk_size < 0) {
361  av_log(s->avf, AV_LOG_TRACE, "chunk_size countdown just went negative\n");
362  chunk_type = CHUNK_BAD;
363  break;
364  }
365 
366  av_log(s->avf, AV_LOG_TRACE, " opcode type %02X, version %d, 0x%04X bytes: ",
367  opcode_type, opcode_version, opcode_size);
368  switch (opcode_type) {
369 
371  av_log(s->avf, AV_LOG_TRACE, "end of stream\n");
372  avio_skip(pb, opcode_size);
373  break;
374 
375  case OPCODE_END_OF_CHUNK:
376  av_log(s->avf, AV_LOG_TRACE, "end of chunk\n");
377  avio_skip(pb, opcode_size);
378  break;
379 
380  case OPCODE_CREATE_TIMER:
381  av_log(s->avf, AV_LOG_TRACE, "create timer\n");
382  if ((opcode_version > 0) || (opcode_size != 6)) {
383  av_log(s->avf, AV_LOG_TRACE, "bad create_timer opcode\n");
384  chunk_type = CHUNK_BAD;
385  break;
386  }
387  if (avio_read(pb, scratch, opcode_size) !=
388  opcode_size) {
389  chunk_type = CHUNK_BAD;
390  break;
391  }
392  s->frame_pts_inc = ((uint64_t)AV_RL32(&scratch[0])) * AV_RL16(&scratch[4]);
393  break;
394 
396  av_log(s->avf, AV_LOG_TRACE, "initialize audio buffers\n");
397  if (opcode_version > 1 || opcode_size > 10 || opcode_size < 6) {
398  av_log(s->avf, AV_LOG_TRACE, "bad init_audio_buffers opcode\n");
399  chunk_type = CHUNK_BAD;
400  break;
401  }
402  if (avio_read(pb, scratch, opcode_size) !=
403  opcode_size) {
404  chunk_type = CHUNK_BAD;
405  break;
406  }
407  s->audio_sample_rate = AV_RL16(&scratch[4]);
408  audio_flags = AV_RL16(&scratch[2]);
409  /* bit 0 of the flags: 0 = mono, 1 = stereo */
410  s->audio_channels = (audio_flags & 1) + 1;
411  /* bit 1 of the flags: 0 = 8 bit, 1 = 16 bit */
412  s->audio_bits = (((audio_flags >> 1) & 1) + 1) * 8;
413  /* bit 2 indicates compressed audio in version 1 opcode */
414  if ((opcode_version == 1) && (audio_flags & 0x4))
415  s->audio_type = AV_CODEC_ID_INTERPLAY_DPCM;
416  else if (s->audio_bits == 16)
417  s->audio_type = AV_CODEC_ID_PCM_S16LE;
418  else
419  s->audio_type = AV_CODEC_ID_PCM_U8;
420  av_log(s->avf, AV_LOG_TRACE, "audio: %d bits, %d Hz, %s, %s format\n",
421  s->audio_bits, s->audio_sample_rate,
422  (s->audio_channels == 2) ? "stereo" : "mono",
423  (s->audio_type == AV_CODEC_ID_INTERPLAY_DPCM) ?
424  "Interplay audio" : "PCM");
425  break;
426 
428  av_log(s->avf, AV_LOG_TRACE, "start/stop audio\n");
429  avio_skip(pb, opcode_size);
430  break;
431 
433  av_log(s->avf, AV_LOG_TRACE, "initialize video buffers\n");
434  if ((opcode_version > 2) || (opcode_size > 8) || opcode_size < 4
435  || opcode_version == 2 && opcode_size < 8
436  ) {
437  av_log(s->avf, AV_LOG_TRACE, "bad init_video_buffers opcode\n");
438  chunk_type = CHUNK_BAD;
439  break;
440  }
441  if (avio_read(pb, scratch, opcode_size) !=
442  opcode_size) {
443  chunk_type = CHUNK_BAD;
444  break;
445  }
446  width = AV_RL16(&scratch[0]) * 8;
447  height = AV_RL16(&scratch[2]) * 8;
448  if (width != s->video_width) {
449  s->video_width = width;
450  s->changed++;
451  }
452  if (height != s->video_height) {
453  s->video_height = height;
454  s->changed++;
455  }
456  if (opcode_version < 2 || !AV_RL16(&scratch[6])) {
457  s->video_bpp = 8;
458  } else {
459  s->video_bpp = 16;
460  }
461  av_log(s->avf, AV_LOG_TRACE, "video resolution: %d x %d\n",
462  s->video_width, s->video_height);
463  break;
464 
465  case OPCODE_UNKNOWN_12:
466  case OPCODE_UNKNOWN_13:
467  case OPCODE_UNKNOWN_14:
468  case OPCODE_UNKNOWN_15:
469  av_log(s->avf, AV_LOG_TRACE, "unknown (but documented) opcode %02X\n", opcode_type);
470  avio_skip(pb, opcode_size);
471  break;
472 
473  case OPCODE_SEND_BUFFER:
474  av_log(s->avf, AV_LOG_TRACE, "send buffer\n");
475  avio_skip(pb, opcode_size);
476  s->send_buffer = 1;
477  break;
478 
479  case OPCODE_AUDIO_FRAME:
480  av_log(s->avf, AV_LOG_TRACE, "audio frame\n");
481 
482  /* log position and move on for now */
483  s->audio_chunk_offset = avio_tell(pb);
484  s->audio_chunk_size = opcode_size;
485  avio_skip(pb, opcode_size);
486  break;
487 
489  av_log(s->avf, AV_LOG_TRACE, "silence frame\n");
490  avio_skip(pb, opcode_size);
491  break;
492 
494  av_log(s->avf, AV_LOG_TRACE, "initialize video mode\n");
495  avio_skip(pb, opcode_size);
496  break;
497 
499  av_log(s->avf, AV_LOG_TRACE, "create gradient\n");
500  avio_skip(pb, opcode_size);
501  break;
502 
503  case OPCODE_SET_PALETTE:
504  av_log(s->avf, AV_LOG_TRACE, "set palette\n");
505  /* check for the logical maximum palette size
506  * (3 * 256 + 4 bytes) */
507  if (opcode_size > 0x304 || opcode_size < 4) {
508  av_log(s->avf, AV_LOG_TRACE, "demux_ipmovie: set_palette opcode with invalid size\n");
509  chunk_type = CHUNK_BAD;
510  break;
511  }
512  if (avio_read(pb, scratch, opcode_size) != opcode_size) {
513  chunk_type = CHUNK_BAD;
514  break;
515  }
516 
517  /* load the palette into internal data structure */
518  first_color = AV_RL16(&scratch[0]);
519  last_color = first_color + AV_RL16(&scratch[2]) - 1;
520  /* sanity check (since they are 16 bit values) */
521  if ( (first_color > 0xFF) || (last_color > 0xFF)
522  || (last_color - first_color + 1)*3 + 4 > opcode_size) {
523  av_log(s->avf, AV_LOG_TRACE, "demux_ipmovie: set_palette indexes out of range (%d -> %d)\n",
524  first_color, last_color);
525  chunk_type = CHUNK_BAD;
526  break;
527  }
528  j = 4; /* offset of first palette data */
529  for (i = first_color; i <= last_color; i++) {
530  /* the palette is stored as a 6-bit VGA palette, thus each
531  * component is shifted up to a 8-bit range */
532  r = scratch[j++] * 4;
533  g = scratch[j++] * 4;
534  b = scratch[j++] * 4;
535  s->palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | (b);
536  s->palette[i] |= s->palette[i] >> 6 & 0x30303;
537  }
538  s->has_palette = 1;
539  break;
540 
542  av_log(s->avf, AV_LOG_TRACE, "set palette compressed\n");
543  avio_skip(pb, opcode_size);
544  break;
545 
546  case OPCODE_SET_SKIP_MAP:
547  av_log(s->avf, AV_LOG_TRACE, "set skip map\n");
548 
549  /* log position and move on for now */
550  s->skip_map_chunk_offset = avio_tell(pb);
551  s->skip_map_chunk_size = opcode_size;
552  avio_skip(pb, opcode_size);
553  break;
554 
556  av_log(s->avf, AV_LOG_TRACE, "set decoding map\n");
557 
558  /* log position and move on for now */
559  s->decode_map_chunk_offset = avio_tell(pb);
560  s->decode_map_chunk_size = opcode_size;
561  avio_skip(pb, opcode_size);
562  break;
563 
565  av_log(s->avf, AV_LOG_TRACE, "set video data format 0x06\n");
566  s->frame_format = 0x06;
567 
568  /* log position and move on for now */
569  s->video_chunk_offset = avio_tell(pb);
570  s->video_chunk_size = opcode_size;
571  avio_skip(pb, opcode_size);
572  break;
573 
575  av_log(s->avf, AV_LOG_TRACE, "set video data format 0x10\n");
576  s->frame_format = 0x10;
577 
578  /* log position and move on for now */
579  s->video_chunk_offset = avio_tell(pb);
580  s->video_chunk_size = opcode_size;
581  avio_skip(pb, opcode_size);
582  break;
583 
585  av_log(s->avf, AV_LOG_TRACE, "set video data format 0x11\n");
586  s->frame_format = 0x11;
587 
588  /* log position and move on for now */
589  s->video_chunk_offset = avio_tell(pb);
590  s->video_chunk_size = opcode_size;
591  avio_skip(pb, opcode_size);
592  break;
593 
594  default:
595  av_log(s->avf, AV_LOG_TRACE, "*** unknown opcode type\n");
596  chunk_type = CHUNK_BAD;
597  break;
598 
599  }
600  }
601 
602  if (s->avf->nb_streams == 1 && s->audio_type)
603  init_audio(s->avf);
604 
605  /* make a note of where the stream is sitting */
606  s->next_chunk_offset = avio_tell(pb);
607 
608  /* dispatch the first of any pending packets */
609  if ((chunk_type == CHUNK_VIDEO) || (chunk_type == CHUNK_AUDIO_ONLY))
610  chunk_type = load_ipmovie_packet(s, pb, pkt);
611 
612  return chunk_type;
613 }
614 
615 static const char signature[] = "Interplay MVE File\x1A\0\x1A";
616 
617 static int ipmovie_probe(const AVProbeData *p)
618 {
619  const uint8_t *b = p->buf;
620  const uint8_t *b_end = p->buf + p->buf_size - sizeof(signature);
621  do {
622  if (b[0] == signature[0] && memcmp(b, signature, sizeof(signature)) == 0)
623  return AVPROBE_SCORE_MAX;
624  b++;
625  } while (b < b_end);
626 
627  return 0;
628 }
629 
631 {
632  IPMVEContext *ipmovie = s->priv_data;
633  AVIOContext *pb = s->pb;
634  AVPacket pkt;
635  AVStream *st;
636  unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
637  int chunk_type, i;
638  uint8_t signature_buffer[sizeof(signature)];
639 
640  ipmovie->avf = s;
641 
642  avio_read(pb, signature_buffer, sizeof(signature_buffer));
643  while (memcmp(signature_buffer, signature, sizeof(signature))) {
644  memmove(signature_buffer, signature_buffer + 1, sizeof(signature_buffer) - 1);
645  signature_buffer[sizeof(signature_buffer) - 1] = avio_r8(pb);
646  if (avio_feof(pb))
647  return AVERROR_EOF;
648  }
649  /* initialize private context members */
650  ipmovie->video_pts = ipmovie->audio_frame_count = 0;
651  ipmovie->audio_chunk_offset = ipmovie->video_chunk_offset =
652  ipmovie->decode_map_chunk_offset = ipmovie->skip_map_chunk_offset = 0;
653  ipmovie->decode_map_chunk_size = ipmovie->video_chunk_size =
654  ipmovie->skip_map_chunk_size = 0;
655  ipmovie->send_buffer = ipmovie->frame_format = 0;
656 
657  /* on the first read, this will position the stream at the first chunk */
658  ipmovie->next_chunk_offset = avio_tell(pb) + 4;
659 
660  for (i = 0; i < 256; i++)
661  ipmovie->palette[i] = 0xFFU << 24;
662 
663  /* process the first chunk which should be CHUNK_INIT_VIDEO */
664  if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_VIDEO) {
666  return AVERROR_INVALIDDATA;
667  }
668 
669  /* peek ahead to the next chunk-- if it is an init audio chunk, process
670  * it; if it is the first video chunk, this is a silent file */
671  if (avio_read(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
673  return AVERROR(EIO);
674  chunk_type = AV_RL16(&chunk_preamble[2]);
675  avio_seek(pb, -CHUNK_PREAMBLE_SIZE, SEEK_CUR);
676 
677  if (chunk_type == CHUNK_VIDEO)
678  ipmovie->audio_type = AV_CODEC_ID_NONE; /* no audio */
679  else if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_AUDIO) {
681  return AVERROR_INVALIDDATA;
682  }
683 
684  /* initialize the stream decoders */
685  st = avformat_new_stream(s, NULL);
686  if (!st)
687  return AVERROR(ENOMEM);
688  avpriv_set_pts_info(st, 63, 1, 1000000);
689  ipmovie->video_stream_index = st->index;
692  st->codecpar->codec_tag = 0; /* no fourcc */
693  st->codecpar->width = ipmovie->video_width;
694  st->codecpar->height = ipmovie->video_height;
695  st->codecpar->bits_per_coded_sample = ipmovie->video_bpp;
696 
697  if (ipmovie->audio_type) {
698  return init_audio(s);
699  } else
700  s->ctx_flags |= AVFMTCTX_NOHEADER;
701 
702  return 0;
703 }
704 
706  AVPacket *pkt)
707 {
708  IPMVEContext *ipmovie = s->priv_data;
709  AVIOContext *pb = s->pb;
710  int ret;
711 
712  for (;;) {
713  ret = process_ipmovie_chunk(ipmovie, pb, pkt);
714  if (ret == CHUNK_BAD)
716  else if (ret == CHUNK_EOF)
717  ret = AVERROR(EIO);
718  else if (ret == CHUNK_NOMEM)
719  ret = AVERROR(ENOMEM);
720  else if (ret == CHUNK_END || ret == CHUNK_SHUTDOWN)
721  ret = AVERROR_EOF;
722  else if (ret == CHUNK_VIDEO)
723  ret = 0;
724  else if (ret == CHUNK_INIT_VIDEO || ret == CHUNK_INIT_AUDIO)
725  continue;
726  else
727  continue;
728 
729  return ret;
730  }
731 }
732 
734  .name = "ipmovie",
735  .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE"),
736  .priv_data_size = sizeof(IPMVEContext),
740 };
AV_CODEC_ID_PCM_S16LE
@ AV_CODEC_ID_PCM_S16LE
Definition: codec_id.h:313
OPCODE_CREATE_GRADIENT
#define OPCODE_CREATE_GRADIENT
Definition: ipmovie.c:66
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:634
r
const char * r
Definition: vf_curves.c:116
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4509
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:56
CHUNK_EOF
#define CHUNK_EOF
Definition: ipmovie.c:52
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:55
CHUNK_END
#define CHUNK_END
Definition: ipmovie.c:48
AV_CH_LAYOUT_MONO
#define AV_CH_LAYOUT_MONO
Definition: channel_layout.h:90
OPCODE_UNKNOWN_12
#define OPCODE_UNKNOWN_12
Definition: ipmovie.c:73
CHUNK_BAD
#define CHUNK_BAD
Definition: ipmovie.c:53
AV_WL8
#define AV_WL8(p, d)
Definition: intreadwrite.h:399
AVPacket::data
uint8_t * data
Definition: packet.h:369
b
#define b
Definition: input.c:41
AV_PKT_DATA_PALETTE
@ AV_PKT_DATA_PALETTE
An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE bytes worth of palette.
Definition: packet.h:46
AVCodecParameters::codec_tag
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: codec_par.h:64
IPMVEContext::next_chunk_offset
int64_t next_chunk_offset
Definition: ipmovie.c:115
AVProbeData::buf_size
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:444
OPCODE_SET_PALETTE_COMPRESSED
#define OPCODE_SET_PALETTE_COMPRESSED
Definition: ipmovie.c:68
IPMVEContext::audio_type
enum AVCodecID audio_type
Definition: ipmovie.c:100
OPCODE_INIT_AUDIO_BUFFERS
#define OPCODE_INIT_AUDIO_BUFFERS
Definition: ipmovie.c:58
IPMVEContext::video_stream_index
int video_stream_index
Definition: ipmovie.c:103
AVPROBE_SCORE_MAX
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:453
ipmovie_read_header
static int ipmovie_read_header(AVFormatContext *s)
Definition: ipmovie.c:630
AVCodecParameters::channels
int channels
Audio only.
Definition: codec_par.h:166
IPMVEContext
Definition: ipmovie.c:80
OPCODE_UNKNOWN_14
#define OPCODE_UNKNOWN_14
Definition: ipmovie.c:75
U
#define U(x)
Definition: vp56_arith.h:37
ipmovie_probe
static int ipmovie_probe(const AVProbeData *p)
Definition: ipmovie.c:617
IPMVEContext::audio_chunk_offset
int64_t audio_chunk_offset
Definition: ipmovie.c:106
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
AV_CH_LAYOUT_STEREO
#define AV_CH_LAYOUT_STEREO
Definition: channel_layout.h:91
signature
static const char signature[]
Definition: ipmovie.c:615
IPMVEContext::send_buffer
uint8_t send_buffer
Definition: ipmovie.c:94
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:220
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
OPCODE_VIDEO_DATA_06
#define OPCODE_VIDEO_DATA_06
Definition: ipmovie.c:61
AVInputFormat
Definition: avformat.h:640
IPMVEContext::has_palette
int has_palette
Definition: ipmovie.c:92
width
#define width
IPMVEContext::changed
int changed
Definition: ipmovie.c:93
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:257
av_new_packet
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:99
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:645
g
const char * g
Definition: vf_curves.c:117
AVProbeData::buf
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:443
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
AVCodecParameters::width
int width
Video only.
Definition: codec_par.h:126
OPCODE_START_STOP_AUDIO
#define OPCODE_START_STOP_AUDIO
Definition: ipmovie.c:59
OPCODE_PREAMBLE_SIZE
#define OPCODE_PREAMBLE_SIZE
Definition: ipmovie.c:41
OPCODE_END_OF_STREAM
#define OPCODE_END_OF_STREAM
Definition: ipmovie.c:55
AV_RL16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:94
IPMVEContext::video_height
unsigned int video_height
Definition: ipmovie.c:89
OPCODE_END_OF_CHUNK
#define OPCODE_END_OF_CHUNK
Definition: ipmovie.c:56
IPMVEContext::decode_map_chunk_offset
int64_t decode_map_chunk_offset
Definition: ipmovie.c:112
if
if(ret)
Definition: filter_design.txt:179
AVFormatContext
Format I/O context.
Definition: avformat.h:1232
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1038
read_header
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:527
IPMVEContext::decode_map_chunk_size
int decode_map_chunk_size
Definition: ipmovie.c:113
NULL
#define NULL
Definition: coverity.c:32
AV_CODEC_ID_INTERPLAY_VIDEO
@ AV_CODEC_ID_INTERPLAY_VIDEO
Definition: codec_id.h:88
read_probe
static int read_probe(const AVProbeData *pd)
Definition: jvdec.c:55
AVFMTCTX_NOHEADER
#define AVFMTCTX_NOHEADER
signal that no header is present (streams are added dynamically)
Definition: avformat.h:1177
AV_CODEC_ID_INTERPLAY_DPCM
@ AV_CODEC_ID_INTERPLAY_DPCM
Definition: codec_id.h:415
AVPALETTE_SIZE
#define AVPALETTE_SIZE
Definition: pixfmt.h:32
IPMVEContext::audio_frame_count
unsigned int audio_frame_count
Definition: ipmovie.c:101
IPMVEContext::skip_map_chunk_offset
int64_t skip_map_chunk_offset
Definition: ipmovie.c:110
AVProbeData
This structure contains the data a format has to probe a file.
Definition: avformat.h:441
OPCODE_SET_SKIP_MAP
#define OPCODE_SET_SKIP_MAP
Definition: ipmovie.c:69
IPMVEContext::audio_chunk_size
int audio_chunk_size
Definition: ipmovie.c:107
IPMVEContext::video_chunk_size
int video_chunk_size
Definition: ipmovie.c:109
OPCODE_UNKNOWN_13
#define OPCODE_UNKNOWN_13
Definition: ipmovie.c:74
AVCodecParameters::sample_rate
int sample_rate
Audio only.
Definition: codec_par.h:170
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:46
init_audio
static int init_audio(AVFormatContext *s)
Definition: ipmovie.c:248
AVIOContext
Bytestream IO Context.
Definition: avio.h:161
OPCODE_INIT_VIDEO_BUFFERS
#define OPCODE_INIT_VIDEO_BUFFERS
Definition: ipmovie.c:60
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
CHUNK_INIT_AUDIO
#define CHUNK_INIT_AUDIO
Definition: ipmovie.c:43
avpriv_set_pts_info
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: utils.c:4945
OPCODE_SET_DECODING_MAP
#define OPCODE_SET_DECODING_MAP
Definition: ipmovie.c:70
CHUNK_AUDIO_ONLY
#define CHUNK_AUDIO_ONLY
Definition: ipmovie.c:44
AV_WL16
#define AV_WL16(p, v)
Definition: intreadwrite.h:412
avio_r8
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:624
height
#define height
IPMVEContext::buf
unsigned char * buf
Definition: ipmovie.c:82
OPCODE_INIT_VIDEO_MODE
#define OPCODE_INIT_VIDEO_MODE
Definition: ipmovie.c:65
IPMVEContext::audio_channels
unsigned int audio_channels
Definition: ipmovie.c:98
load_ipmovie_packet
static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, AVPacket *pkt)
Definition: ipmovie.c:119
OPCODE_VIDEO_DATA_10
#define OPCODE_VIDEO_DATA_10
Definition: ipmovie.c:71
CHUNK_SHUTDOWN
#define CHUNK_SHUTDOWN
Definition: ipmovie.c:47
i
int i
Definition: input.c:407
AV_CODEC_ID_NONE
@ AV_CODEC_ID_NONE
Definition: codec_id.h:47
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:362
OPCODE_SILENCE_FRAME
#define OPCODE_SILENCE_FRAME
Definition: ipmovie.c:64
process_ipmovie_chunk
static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, AVPacket *pkt)
Definition: ipmovie.c:275
OPCODE_VIDEO_DATA_11
#define OPCODE_VIDEO_DATA_11
Definition: ipmovie.c:72
AVCodecParameters::height
int height
Definition: codec_par.h:127
AVCodecParameters::block_align
int block_align
Audio only.
Definition: codec_par.h:177
OPCODE_CREATE_TIMER
#define OPCODE_CREATE_TIMER
Definition: ipmovie.c:57
OPCODE_AUDIO_FRAME
#define OPCODE_AUDIO_FRAME
Definition: ipmovie.c:63
uint8_t
uint8_t
Definition: audio_convert.c:194
OPCODE_UNKNOWN_15
#define OPCODE_UNKNOWN_15
Definition: ipmovie.c:76
IPMVEContext::video_pts
int64_t video_pts
Definition: ipmovie.c:90
av_packet_new_side_data
uint8_t * av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, buffer_size_t size)
Definition: avpacket.c:343
ff_add_param_change
int ff_add_param_change(AVPacket *pkt, int32_t channels, uint64_t channel_layout, int32_t sample_rate, int32_t width, int32_t height)
Add side data to a packet for changing parameters to the given values.
Definition: utils.c:5077
av_get_packet
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
Allocate and read the payload of a packet and initialize its fields with default values.
Definition: utils.c:310
ipmovie_read_packet
static int ipmovie_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: ipmovie.c:705
ret
ret
Definition: filter_design.txt:187
read_packet
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
AVStream
Stream structure.
Definition: avformat.h:873
IPMVEContext::avf
AVFormatContext * avf
Definition: ipmovie.c:81
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:253
avformat.h
CHUNK_VIDEO
#define CHUNK_VIDEO
Definition: ipmovie.c:46
IPMVEContext::palette
uint32_t palette[256]
Definition: ipmovie.c:91
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:92
CHUNK_PREAMBLE_SIZE
#define CHUNK_PREAMBLE_SIZE
Definition: ipmovie.c:40
AVStream::index
int index
stream index in AVFormatContext
Definition: avformat.h:874
IPMVEContext::frame_format
uint8_t frame_format
Definition: ipmovie.c:95
channel_layout.h
IPMVEContext::audio_sample_rate
unsigned int audio_sample_rate
Definition: ipmovie.c:99
avio_read
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:633
OPCODE_SET_PALETTE
#define OPCODE_SET_PALETTE
Definition: ipmovie.c:67
AVPacket::stream_index
int stream_index
Definition: packet.h:371
CHUNK_DONE
#define CHUNK_DONE
Definition: ipmovie.c:50
avio_skip
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:337
IPMVEContext::video_chunk_offset
int64_t video_chunk_offset
Definition: ipmovie.c:108
CHUNK_NOMEM
#define CHUNK_NOMEM
Definition: ipmovie.c:51
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
IPMVEContext::audio_stream_index
int audio_stream_index
Definition: ipmovie.c:104
AVCodecParameters::bits_per_coded_sample
int bits_per_coded_sample
The number of bits per sample in the codedwords.
Definition: codec_par.h:102
AV_CODEC_ID_PCM_U8
@ AV_CODEC_ID_PCM_U8
Definition: codec_id.h:318
IPMVEContext::buf_size
int buf_size
Definition: ipmovie.c:83
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
AVPacket
This structure stores compressed data.
Definition: packet.h:346
ff_ipmovie_demuxer
AVInputFormat ff_ipmovie_demuxer
Definition: ipmovie.c:733
IPMVEContext::audio_bits
unsigned int audio_bits
Definition: ipmovie.c:97
AVPacket::pos
int64_t pos
byte position in stream, -1 if unknown
Definition: packet.h:389
AVCodecParameters::channel_layout
uint64_t channel_layout
Audio only.
Definition: codec_par.h:162
AVCodecParameters::bit_rate
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: codec_par.h:89
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
IPMVEContext::video_bpp
unsigned int video_bpp
Definition: ipmovie.c:87
IPMVEContext::skip_map_chunk_size
int skip_map_chunk_size
Definition: ipmovie.c:111
IPMVEContext::video_width
unsigned int video_width
Definition: ipmovie.c:88
IPMVEContext::frame_pts_inc
uint64_t frame_pts_inc
Definition: ipmovie.c:85
OPCODE_SEND_BUFFER
#define OPCODE_SEND_BUFFER
Definition: ipmovie.c:62
avio_feof
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition: aviobuf.c:364
CHUNK_INIT_VIDEO
#define CHUNK_INIT_VIDEO
Definition: ipmovie.c:45