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