FFmpeg
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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 "avio_internal.h"
39 #include "demux.h"
40 #include "internal.h"
41 
42 #define CHUNK_PREAMBLE_SIZE 4
43 #define OPCODE_PREAMBLE_SIZE 4
44 
45 #define CHUNK_INIT_AUDIO 0x0000
46 #define CHUNK_AUDIO_ONLY 0x0001
47 #define CHUNK_INIT_VIDEO 0x0002
48 #define CHUNK_VIDEO 0x0003
49 #define CHUNK_SHUTDOWN 0x0004
50 #define CHUNK_END 0x0005
51 /* these last types are used internally */
52 #define CHUNK_HAVE_PACKET 0xFFFB
53 #define CHUNK_DONE 0xFFFC
54 #define CHUNK_NOMEM 0xFFFD
55 #define CHUNK_EOF 0xFFFE
56 #define CHUNK_BAD 0xFFFF
57 
58 #define OPCODE_END_OF_STREAM 0x00
59 #define OPCODE_END_OF_CHUNK 0x01
60 #define OPCODE_CREATE_TIMER 0x02
61 #define OPCODE_INIT_AUDIO_BUFFERS 0x03
62 #define OPCODE_START_STOP_AUDIO 0x04
63 #define OPCODE_INIT_VIDEO_BUFFERS 0x05
64 #define OPCODE_VIDEO_DATA_06 0x06
65 #define OPCODE_SEND_BUFFER 0x07
66 #define OPCODE_AUDIO_FRAME 0x08
67 #define OPCODE_SILENCE_FRAME 0x09
68 #define OPCODE_INIT_VIDEO_MODE 0x0A
69 #define OPCODE_CREATE_GRADIENT 0x0B
70 #define OPCODE_SET_PALETTE 0x0C
71 #define OPCODE_SET_PALETTE_COMPRESSED 0x0D
72 #define OPCODE_SET_SKIP_MAP 0x0E
73 #define OPCODE_SET_DECODING_MAP 0x0F
74 #define OPCODE_VIDEO_DATA_10 0x10
75 #define OPCODE_VIDEO_DATA_11 0x11
76 #define OPCODE_UNKNOWN_12 0x12
77 #define OPCODE_UNKNOWN_13 0x13
78 #define OPCODE_UNKNOWN_14 0x14
79 #define OPCODE_UNKNOWN_15 0x15
80 
81 #define PALETTE_COUNT 256
82 
83 typedef struct IPMVEContext {
85  unsigned char *buf;
86  int buf_size;
87 
88  uint64_t frame_pts_inc;
89 
90  unsigned int video_bpp;
91  unsigned int video_width;
92  unsigned int video_height;
94  uint32_t palette[256];
96  int changed;
97  uint8_t send_buffer;
98  uint8_t frame_format;
99 
100  unsigned int audio_bits;
101  unsigned int audio_channels;
102  unsigned int audio_sample_rate;
104  unsigned int audio_frame_count;
105 
108 
117 
119 
120 } IPMVEContext;
121 
123  AVPacket *pkt) {
124 
125  int chunk_type;
126 
127  if (s->audio_chunk_offset && s->audio_channels && s->audio_bits) {
128  if (s->audio_type == AV_CODEC_ID_NONE) {
129  av_log(s->avf, AV_LOG_ERROR, "Can not read audio packet before"
130  "audio codec is known\n");
131  return CHUNK_BAD;
132  }
133 
134  /* adjust for PCM audio by skipping chunk header */
135  if (s->audio_type != AV_CODEC_ID_INTERPLAY_DPCM) {
136  s->audio_chunk_offset += 6;
137  s->audio_chunk_size -= 6;
138  }
139 
140  avio_seek(pb, s->audio_chunk_offset, SEEK_SET);
141  s->audio_chunk_offset = 0;
142 
143  if (s->audio_chunk_size != av_get_packet(pb, pkt, s->audio_chunk_size))
144  return CHUNK_EOF;
145 
146  pkt->stream_index = s->audio_stream_index;
147  pkt->pts = s->audio_frame_count;
148 
149  /* audio frame maintenance */
150  if (s->audio_type != AV_CODEC_ID_INTERPLAY_DPCM)
151  s->audio_frame_count +=
152  (s->audio_chunk_size / s->audio_channels / (s->audio_bits / 8));
153  else
154  s->audio_frame_count +=
155  (s->audio_chunk_size - 6 - s->audio_channels) / s->audio_channels;
156 
157  av_log(s->avf, AV_LOG_TRACE, "sending audio frame with pts %"PRId64" (%d audio frames)\n",
158  pkt->pts, s->audio_frame_count);
159 
160  chunk_type = CHUNK_HAVE_PACKET;
161 
162  } else if (s->frame_format) {
163 
164  /* send the frame format, decode map, the video data, skip map, and the send_buffer flag together */
165 
166  if (av_new_packet(pkt, 8 + s->decode_map_chunk_size + s->video_chunk_size + s->skip_map_chunk_size))
167  return CHUNK_NOMEM;
168 
169  if (s->has_palette) {
170  uint8_t *pal;
171 
174  if (pal) {
175  memcpy(pal, s->palette, AVPALETTE_SIZE);
176  s->has_palette = 0;
177  }
178  }
179 
180  if (s->changed) {
181  ff_add_param_change(pkt, 0, 0, 0, s->video_width, s->video_height);
182  s->changed = 0;
183  }
184 
185  AV_WL8(pkt->data, s->frame_format);
186  AV_WL8(pkt->data + 1, s->send_buffer);
187  AV_WL16(pkt->data + 2, s->video_chunk_size);
188  AV_WL16(pkt->data + 4, s->decode_map_chunk_size);
189  AV_WL16(pkt->data + 6, s->skip_map_chunk_size);
190 
191  s->frame_format = 0;
192  s->send_buffer = 0;
193 
194  pkt->pos = s->video_chunk_offset;
195  avio_seek(pb, s->video_chunk_offset, SEEK_SET);
196  s->video_chunk_offset = 0;
197 
198  if (avio_read(pb, pkt->data + 8, s->video_chunk_size) !=
199  s->video_chunk_size) {
200  return CHUNK_EOF;
201  }
202 
203  if (s->decode_map_chunk_size) {
204  pkt->pos = s->decode_map_chunk_offset;
205  avio_seek(pb, s->decode_map_chunk_offset, SEEK_SET);
206  s->decode_map_chunk_offset = 0;
207 
208  if (avio_read(pb, pkt->data + 8 + s->video_chunk_size,
209  s->decode_map_chunk_size) != s->decode_map_chunk_size) {
210  return CHUNK_EOF;
211  }
212  }
213 
214  if (s->skip_map_chunk_size) {
215  pkt->pos = s->skip_map_chunk_offset;
216  avio_seek(pb, s->skip_map_chunk_offset, SEEK_SET);
217  s->skip_map_chunk_offset = 0;
218 
219  if (avio_read(pb, pkt->data + 8 + s->video_chunk_size + s->decode_map_chunk_size,
220  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_HAVE_PACKET;
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 */
260  st->codecpar->sample_rate = ipmovie->audio_sample_rate;
261  st->codecpar->bits_per_coded_sample = ipmovie->audio_bits;
262  st->codecpar->bit_rate = ipmovie->audio_channels * st->codecpar->sample_rate *
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  int ret;
616 
617  ipmovie->avf = s;
618 
619  ret = ffio_read_size(pb, signature_buffer, sizeof(signature_buffer));
620  if (ret < 0)
621  return ret;
622  while (memcmp(signature_buffer, signature, sizeof(signature))) {
623  memmove(signature_buffer, signature_buffer + 1, sizeof(signature_buffer) - 1);
624  signature_buffer[sizeof(signature_buffer) - 1] = avio_r8(pb);
625  if (avio_feof(pb))
626  return AVERROR_EOF;
627  }
628 
629  /* on the first read, this will position the stream at the first chunk */
630  ipmovie->next_chunk_offset = avio_tell(pb) + 4;
631 
632  for (i = 0; i < 256; i++)
633  ipmovie->palette[i] = 0xFFU << 24;
634 
635  /* process the first chunk which should be CHUNK_INIT_VIDEO */
636  if (process_ipmovie_chunk(ipmovie, pb, NULL) != CHUNK_INIT_VIDEO) {
637  return AVERROR_INVALIDDATA;
638  }
639 
640  /* peek ahead to the next chunk-- if it is an init audio chunk, process
641  * it; if it is the first video chunk, this is a silent file */
642  if (avio_read(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
644  return AVERROR(EIO);
645  chunk_type = AV_RL16(&chunk_preamble[2]);
646  avio_seek(pb, -CHUNK_PREAMBLE_SIZE, SEEK_CUR);
647 
648  if (chunk_type == CHUNK_VIDEO)
649  ipmovie->audio_type = AV_CODEC_ID_NONE; /* no audio */
650  else if (process_ipmovie_chunk(ipmovie, pb, ffformatcontext(s)->parse_pkt) != CHUNK_INIT_AUDIO) {
651  return AVERROR_INVALIDDATA;
652  }
653 
654  /* initialize the stream decoders */
655  st = avformat_new_stream(s, NULL);
656  if (!st)
657  return AVERROR(ENOMEM);
658  avpriv_set_pts_info(st, 63, 1, 1000000);
659  ipmovie->video_stream_index = st->index;
662  st->codecpar->codec_tag = 0; /* no fourcc */
663  st->codecpar->width = ipmovie->video_width;
664  st->codecpar->height = ipmovie->video_height;
665  st->codecpar->bits_per_coded_sample = ipmovie->video_bpp;
666 
667  if (ipmovie->audio_type) {
668  return init_audio(s);
669  } else
670  s->ctx_flags |= AVFMTCTX_NOHEADER;
671 
672  return 0;
673 }
674 
676  AVPacket *pkt)
677 {
678  IPMVEContext *ipmovie = s->priv_data;
679  AVIOContext *pb = s->pb;
680  int ret;
681 
682  for (;;) {
683  ret = process_ipmovie_chunk(ipmovie, pb, pkt);
684  /* dispatch the first of any pending packets */
685  if ((ret == CHUNK_VIDEO) || (ret == CHUNK_AUDIO_ONLY))
686  ret = load_ipmovie_packet(ipmovie, pb, pkt);
687 
688  if (ret == CHUNK_BAD)
690  else if (ret == CHUNK_EOF)
691  ret = AVERROR(EIO);
692  else if (ret == CHUNK_NOMEM)
693  ret = AVERROR(ENOMEM);
694  else if (ret == CHUNK_END || ret == CHUNK_SHUTDOWN)
695  ret = AVERROR_EOF;
696  else if (ret == CHUNK_HAVE_PACKET)
697  ret = 0;
698  else if (ret == CHUNK_INIT_VIDEO || ret == CHUNK_INIT_AUDIO)
699  continue;
700  else
701  continue;
702 
703  return ret;
704  }
705 }
706 
708  .p.name = "ipmovie",
709  .p.long_name = NULL_IF_CONFIG_SMALL("Interplay MVE"),
710  .priv_data_size = sizeof(IPMVEContext),
714 };
AV_CODEC_ID_PCM_S16LE
@ AV_CODEC_ID_PCM_S16LE
Definition: codec_id.h:336
OPCODE_CREATE_GRADIENT
#define OPCODE_CREATE_GRADIENT
Definition: ipmovie.c:69
r
const char * r
Definition: vf_curves.c:127
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:55
ffformatcontext
static av_always_inline FFFormatContext * ffformatcontext(AVFormatContext *s)
Definition: internal.h:123
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:50
OPCODE_UNKNOWN_12
#define OPCODE_UNKNOWN_12
Definition: ipmovie.c:76
CHUNK_BAD
#define CHUNK_BAD
Definition: ipmovie.c:56
AV_WL8
#define AV_WL8(p, d)
Definition: intreadwrite.h:395
int64_t
long long int64_t
Definition: coverity.c:34
AVPacket::data
uint8_t * data
Definition: packet.h:535
b
#define b
Definition: input.c:42
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:118
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:71
IPMVEContext::audio_type
enum AVCodecID audio_type
Definition: ipmovie.c:103
OPCODE_INIT_AUDIO_BUFFERS
#define OPCODE_INIT_AUDIO_BUFFERS
Definition: ipmovie.c:61
IPMVEContext::video_stream_index
int video_stream_index
Definition: ipmovie.c:106
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:607
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:777
IPMVEContext
Definition: ipmovie.c:83
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:78
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:109
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:592
IPMVEContext::send_buffer
uint8_t send_buffer
Definition: ipmovie.c:97
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:236
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
OPCODE_VIDEO_DATA_06
#define OPCODE_VIDEO_DATA_06
Definition: ipmovie.c:64
IPMVEContext::has_palette
int has_palette
Definition: ipmovie.c:95
read_packet
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_read_callback.c:42
IPMVEContext::changed
int changed
Definition: ipmovie.c:96
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: packet.c:99
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:550
g
const char * g
Definition: vf_curves.c:128
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:201
AVCodecParameters::width
int width
Video only.
Definition: codec_par.h:134
OPCODE_START_STOP_AUDIO
#define OPCODE_START_STOP_AUDIO
Definition: ipmovie.c:62
OPCODE_PREAMBLE_SIZE
#define OPCODE_PREAMBLE_SIZE
Definition: ipmovie.c:43
OPCODE_END_OF_STREAM
#define OPCODE_END_OF_STREAM
Definition: ipmovie.c:58
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:92
OPCODE_END_OF_CHUNK
#define OPCODE_END_OF_CHUNK
Definition: ipmovie.c:59
IPMVEContext::decode_map_chunk_offset
int64_t decode_map_chunk_offset
Definition: ipmovie.c:115
if
if(ret)
Definition: filter_design.txt:179
AVFormatContext
Format I/O context.
Definition: avformat.h:1265
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:768
IPMVEContext::decode_map_chunk_size
int decode_map_chunk_size
Definition: ipmovie.c:116
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:1216
AV_CODEC_ID_INTERPLAY_DPCM
@ AV_CODEC_ID_INTERPLAY_DPCM
Definition: codec_id.h:439
AVPALETTE_SIZE
#define AVPALETTE_SIZE
Definition: pixfmt.h:32
IPMVEContext::audio_frame_count
unsigned int audio_frame_count
Definition: ipmovie.c:104
IPMVEContext::skip_map_chunk_offset
int64_t skip_map_chunk_offset
Definition: ipmovie.c:113
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:72
IPMVEContext::audio_chunk_size
int audio_chunk_size
Definition: ipmovie.c:110
IPMVEContext::video_chunk_size
int video_chunk_size
Definition: ipmovie.c:112
AVCodecParameters::ch_layout
AVChannelLayout ch_layout
Audio only.
Definition: codec_par.h:180
OPCODE_UNKNOWN_13
#define OPCODE_UNKNOWN_13
Definition: ipmovie.c:77
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:248
AVIOContext
Bytestream IO Context.
Definition: avio.h:160
OPCODE_INIT_VIDEO_BUFFERS
#define OPCODE_INIT_VIDEO_BUFFERS
Definition: ipmovie.c:63
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:94
height
#define height
Definition: dsp.h:89
CHUNK_INIT_AUDIO
#define CHUNK_INIT_AUDIO
Definition: ipmovie.c:45
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:142
FFInputFormat::p
AVInputFormat p
The public AVInputFormat.
Definition: demux.h:46
OPCODE_SET_DECODING_MAP
#define OPCODE_SET_DECODING_MAP
Definition: ipmovie.c:73
CHUNK_AUDIO_ONLY
#define CHUNK_AUDIO_ONLY
Definition: ipmovie.c:46
AV_WL16
#define AV_WL16(p, v)
Definition: intreadwrite.h:408
avio_r8
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:603
read_header
static int read_header(FFV1Context *f, RangeCoder *c)
Definition: ffv1dec.c:489
IPMVEContext::buf
unsigned char * buf
Definition: ipmovie.c:85
OPCODE_INIT_VIDEO_MODE
#define OPCODE_INIT_VIDEO_MODE
Definition: ipmovie.c:68
IPMVEContext::audio_channels
unsigned int audio_channels
Definition: ipmovie.c:101
load_ipmovie_packet
static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, AVPacket *pkt)
Definition: ipmovie.c:122
OPCODE_VIDEO_DATA_10
#define OPCODE_VIDEO_DATA_10
Definition: ipmovie.c:74
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:839
CHUNK_SHUTDOWN
#define CHUNK_SHUTDOWN
Definition: ipmovie.c:49
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:256
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:528
avio_internal.h
OPCODE_SILENCE_FRAME
#define OPCODE_SILENCE_FRAME
Definition: ipmovie.c:67
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:75
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:60
OPCODE_AUDIO_FRAME
#define OPCODE_AUDIO_FRAME
Definition: ipmovie.c:66
OPCODE_UNKNOWN_15
#define OPCODE_UNKNOWN_15
Definition: ipmovie.c:79
IPMVEContext::video_pts
int64_t video_pts
Definition: ipmovie.c:93
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:94
ipmovie_read_packet
static int ipmovie_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: ipmovie.c:675
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:745
IPMVEContext::avf
AVFormatContext * avf
Definition: ipmovie.c:84
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:231
avformat.h
CHUNK_VIDEO
#define CHUNK_VIDEO
Definition: ipmovie.c:48
IPMVEContext::palette
uint32_t palette[256]
Definition: ipmovie.c:94
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:42
AVStream::index
int index
stream index in AVFormatContext
Definition: avformat.h:751
IPMVEContext::frame_format
uint8_t frame_format
Definition: ipmovie.c:98
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: packet.c:232
IPMVEContext::audio_sample_rate
unsigned int audio_sample_rate
Definition: ipmovie.c:102
avio_read
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:612
CHUNK_HAVE_PACKET
#define CHUNK_HAVE_PACKET
Definition: ipmovie.c:52
OPCODE_SET_PALETTE
#define OPCODE_SET_PALETTE
Definition: ipmovie.c:70
AVPacket::stream_index
int stream_index
Definition: packet.h:537
CHUNK_DONE
#define CHUNK_DONE
Definition: ipmovie.c:53
avio_skip
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:318
ff_ipmovie_demuxer
const FFInputFormat ff_ipmovie_demuxer
Definition: ipmovie.c:707
IPMVEContext::video_chunk_offset
int64_t video_chunk_offset
Definition: ipmovie.c:111
CHUNK_NOMEM
#define CHUNK_NOMEM
Definition: ipmovie.c:54
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:200
read_probe
static int read_probe(const AVProbeData *p)
Definition: cdg.c:30
IPMVEContext::audio_stream_index
int audio_stream_index
Definition: ipmovie.c:107
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:341
IPMVEContext::buf_size
int buf_size
Definition: ipmovie.c:86
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:512
IPMVEContext::audio_bits
unsigned int audio_bits
Definition: ipmovie.c:100
AVPacket::pos
int64_t pos
byte position in stream, -1 if unknown
Definition: packet.h:555
FFInputFormat
Definition: demux.h:42
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:90
ffio_read_size
int ffio_read_size(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:662
IPMVEContext::skip_map_chunk_size
int skip_map_chunk_size
Definition: ipmovie.c:114
width
#define width
Definition: dsp.h:89
IPMVEContext::video_width
unsigned int video_width
Definition: ipmovie.c:91
IPMVEContext::frame_pts_inc
uint64_t frame_pts_inc
Definition: ipmovie.c:88
OPCODE_SEND_BUFFER
#define OPCODE_SEND_BUFFER
Definition: ipmovie.c:65
avio_feof
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition: aviobuf.c:346
CHUNK_INIT_VIDEO
#define CHUNK_INIT_VIDEO
Definition: ipmovie.c:47