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_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 {
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];
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;
102  unsigned int audio_frame_count;
103 
106 
115 
117 
118 } IPMVEContext;
119 
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 
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 
247 {
248  IPMVEContext *ipmovie = s->priv_data;
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;
255  st->codecpar->codec_id = ipmovie->audio_type;
256  st->codecpar->codec_tag = 0; /* no tag */
257  st->codecpar->channels = ipmovie->audio_channels;
260  st->codecpar->sample_rate = ipmovie->audio_sample_rate;
261  st->codecpar->bits_per_coded_sample = ipmovie->audio_bits;
265  st->codecpar->bit_rate /= 2;
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. */
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) !=
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) !=
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 
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 
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 
426  av_log(s->avf, AV_LOG_TRACE, "start/stop audio\n");
427  avio_skip(pb, opcode_size);
428  break;
429 
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 
487  av_log(s->avf, AV_LOG_TRACE, "silence frame\n");
488  avio_skip(pb, opcode_size);
489  break;
490 
492  av_log(s->avf, AV_LOG_TRACE, "initialize video mode\n");
493  avio_skip(pb, opcode_size);
494  break;
495 
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 
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 
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 
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 
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) !=
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;
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 
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)
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 
705  .name = "ipmovie",
706  .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE"),
707  .priv_data_size = sizeof(IPMVEContext),
711 };
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:67
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:4375
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:53
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
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:74
CHUNK_BAD
#define CHUNK_BAD
Definition: ipmovie.c:54
AV_WL8
#define AV_WL8(p, d)
Definition: intreadwrite.h:399
AVPacket::data
uint8_t * data
Definition: packet.h:373
b
#define b
Definition: input.c:40
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:116
AVProbeData::buf_size
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:449
OPCODE_SET_PALETTE_COMPRESSED
#define OPCODE_SET_PALETTE_COMPRESSED
Definition: ipmovie.c:69
IPMVEContext::audio_type
enum AVCodecID audio_type
Definition: ipmovie.c:101
OPCODE_INIT_AUDIO_BUFFERS
#define OPCODE_INIT_AUDIO_BUFFERS
Definition: ipmovie.c:59
IPMVEContext::video_stream_index
int video_stream_index
Definition: ipmovie.c:104
AVPROBE_SCORE_MAX
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:458
ipmovie_read_header
static int ipmovie_read_header(AVFormatContext *s)
Definition: ipmovie.c:607
AVCodecParameters::channels
int channels
Audio only.
Definition: codec_par.h:166
IPMVEContext
Definition: ipmovie.c:81
OPCODE_UNKNOWN_14
#define OPCODE_UNKNOWN_14
Definition: ipmovie.c:76
U
#define U(x)
Definition: vp56_arith.h:37
ipmovie_probe
static int ipmovie_probe(const AVProbeData *p)
Definition: ipmovie.c:594
IPMVEContext::audio_chunk_offset
int64_t audio_chunk_offset
Definition: ipmovie.c:107
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:538
AV_CH_LAYOUT_STEREO
#define AV_CH_LAYOUT_STEREO
Definition: channel_layout.h:91
signature
static const char signature[]
Definition: ipmovie.c:592
IPMVEContext::send_buffer
uint8_t send_buffer
Definition: ipmovie.c:95
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:62
AVInputFormat
Definition: avformat.h:626
IPMVEContext::has_palette
int has_palette
Definition: ipmovie.c:93
width
#define width
IPMVEContext::changed
int changed
Definition: ipmovie.c:94
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:94
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:631
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:448
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:60
OPCODE_PREAMBLE_SIZE
#define OPCODE_PREAMBLE_SIZE
Definition: ipmovie.c:41
OPCODE_END_OF_STREAM
#define OPCODE_END_OF_STREAM
Definition: ipmovie.c:56
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:90
OPCODE_END_OF_CHUNK
#define OPCODE_END_OF_CHUNK
Definition: ipmovie.c:57
IPMVEContext::decode_map_chunk_offset
int64_t decode_map_chunk_offset
Definition: ipmovie.c:113
if
if(ret)
Definition: filter_design.txt:179
AVFormatContext
Format I/O context.
Definition: avformat.h:1107
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:994
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:114
NULL
#define NULL
Definition: coverity.c:32
AV_CODEC_ID_INTERPLAY_VIDEO
@ AV_CODEC_ID_INTERPLAY_VIDEO
Definition: codec_id.h:89
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:1056
AV_CODEC_ID_INTERPLAY_DPCM
@ AV_CODEC_ID_INTERPLAY_DPCM
Definition: codec_id.h:414
AVPALETTE_SIZE
#define AVPALETTE_SIZE
Definition: pixfmt.h:32
IPMVEContext::audio_frame_count
unsigned int audio_frame_count
Definition: ipmovie.c:102
IPMVEContext::skip_map_chunk_offset
int64_t skip_map_chunk_offset
Definition: ipmovie.c:111
AVProbeData
This structure contains the data a format has to probe a file.
Definition: avformat.h:446
OPCODE_SET_SKIP_MAP
#define OPCODE_SET_SKIP_MAP
Definition: ipmovie.c:70
IPMVEContext::audio_chunk_size
int audio_chunk_size
Definition: ipmovie.c:108
IPMVEContext::video_chunk_size
int video_chunk_size
Definition: ipmovie.c:110
OPCODE_UNKNOWN_13
#define OPCODE_UNKNOWN_13
Definition: ipmovie.c:75
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:47
init_audio
static int init_audio(AVFormatContext *s)
Definition: ipmovie.c:246
AVIOContext
Bytestream IO Context.
Definition: avio.h:161
OPCODE_INIT_VIDEO_BUFFERS
#define OPCODE_INIT_VIDEO_BUFFERS
Definition: ipmovie.c:61
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:116
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:4800
OPCODE_SET_DECODING_MAP
#define OPCODE_SET_DECODING_MAP
Definition: ipmovie.c:71
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:607
height
#define height
IPMVEContext::buf
unsigned char * buf
Definition: ipmovie.c:83
ff_ipmovie_demuxer
const AVInputFormat ff_ipmovie_demuxer
Definition: ipmovie.c:704
OPCODE_INIT_VIDEO_MODE
#define OPCODE_INIT_VIDEO_MODE
Definition: ipmovie.c:66
IPMVEContext::audio_channels
unsigned int audio_channels
Definition: ipmovie.c:99
load_ipmovie_packet
static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, AVPacket *pkt)
Definition: ipmovie.c:120
OPCODE_VIDEO_DATA_10
#define OPCODE_VIDEO_DATA_10
Definition: ipmovie.c:72
CHUNK_SHUTDOWN
#define CHUNK_SHUTDOWN
Definition: ipmovie.c:47
i
int i
Definition: input.c:406
AV_CODEC_ID_NONE
@ AV_CODEC_ID_NONE
Definition: codec_id.h:48
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:366
OPCODE_SILENCE_FRAME
#define OPCODE_SILENCE_FRAME
Definition: ipmovie.c:65
process_ipmovie_chunk
static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, AVPacket *pkt)
Definition: ipmovie.c:273
OPCODE_VIDEO_DATA_11
#define OPCODE_VIDEO_DATA_11
Definition: ipmovie.c:73
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:58
OPCODE_AUDIO_FRAME
#define OPCODE_AUDIO_FRAME
Definition: ipmovie.c:64
OPCODE_UNKNOWN_15
#define OPCODE_UNKNOWN_15
Definition: ipmovie.c:77
IPMVEContext::video_pts
int64_t video_pts
Definition: ipmovie.c:91
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:4927
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:282
ipmovie_read_packet
static int ipmovie_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: ipmovie.c:672
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:847
IPMVEContext::avf
AVFormatContext * avf
Definition: ipmovie.c:82
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:243
avformat.h
CHUNK_VIDEO
#define CHUNK_VIDEO
Definition: ipmovie.c:46
IPMVEContext::palette
uint32_t palette[256]
Definition: ipmovie.c:92
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:848
IPMVEContext::frame_format
uint8_t frame_format
Definition: ipmovie.c:96
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:220
IPMVEContext::audio_sample_rate
unsigned int audio_sample_rate
Definition: ipmovie.c:100
avio_read
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:616
CHUNK_HAVE_PACKET
#define CHUNK_HAVE_PACKET
Definition: ipmovie.c:50
OPCODE_SET_PALETTE
#define OPCODE_SET_PALETTE
Definition: ipmovie.c:68
AVPacket::stream_index
int stream_index
Definition: packet.h:375
CHUNK_DONE
#define CHUNK_DONE
Definition: ipmovie.c:51
avio_skip
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:327
IPMVEContext::video_chunk_offset
int64_t video_chunk_offset
Definition: ipmovie.c:109
CHUNK_NOMEM
#define CHUNK_NOMEM
Definition: ipmovie.c:52
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
IPMVEContext::audio_stream_index
int audio_stream_index
Definition: ipmovie.c:105
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:84
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:350
IPMVEContext::audio_bits
unsigned int audio_bits
Definition: ipmovie.c:98
AVPacket::pos
int64_t pos
byte position in stream, -1 if unknown
Definition: packet.h:393
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:61
IPMVEContext::video_bpp
unsigned int video_bpp
Definition: ipmovie.c:88
IPMVEContext::skip_map_chunk_size
int skip_map_chunk_size
Definition: ipmovie.c:112
IPMVEContext::video_width
unsigned int video_width
Definition: ipmovie.c:89
IPMVEContext::frame_pts_inc
uint64_t frame_pts_inc
Definition: ipmovie.c:86
OPCODE_SEND_BUFFER
#define OPCODE_SEND_BUFFER
Definition: ipmovie.c:63
avio_feof
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition: aviobuf.c:354
CHUNK_INIT_VIDEO
#define CHUNK_INIT_VIDEO
Definition: ipmovie.c:45