FFmpeg
ipmovie.c
Go to the documentation of this file.
1 /*
2  * Interplay MVE File Demuxer
3  * Copyright (c) 2003 The FFmpeg project
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * Interplay MVE file demuxer
25  * by Mike Melanson (melanson@pcisys.net)
26  * For more information regarding the Interplay MVE file format, visit:
27  * http://www.pcisys.net/~melanson/codecs/
28  * The aforementioned site also contains a command line utility for parsing
29  * IP MVE files so that you can get a good idea of the typical structure of
30  * such files. This demuxer is not the best example to use if you are trying
31  * to write your own as it uses a rather roundabout approach for splitting
32  * up and sending out the chunks.
33  */
34 
36 #include "libavutil/intreadwrite.h"
37 #include "avformat.h"
38 #include "internal.h"
39 
40 #define CHUNK_PREAMBLE_SIZE 4
41 #define OPCODE_PREAMBLE_SIZE 4
42 
43 #define CHUNK_INIT_AUDIO 0x0000
44 #define CHUNK_AUDIO_ONLY 0x0001
45 #define CHUNK_INIT_VIDEO 0x0002
46 #define CHUNK_VIDEO 0x0003
47 #define CHUNK_SHUTDOWN 0x0004
48 #define CHUNK_END 0x0005
49 /* these last types are used internally */
50 #define CHUNK_DONE 0xFFFC
51 #define CHUNK_NOMEM 0xFFFD
52 #define CHUNK_EOF 0xFFFE
53 #define CHUNK_BAD 0xFFFF
54 
55 #define OPCODE_END_OF_STREAM 0x00
56 #define OPCODE_END_OF_CHUNK 0x01
57 #define OPCODE_CREATE_TIMER 0x02
58 #define OPCODE_INIT_AUDIO_BUFFERS 0x03
59 #define OPCODE_START_STOP_AUDIO 0x04
60 #define OPCODE_INIT_VIDEO_BUFFERS 0x05
61 #define OPCODE_VIDEO_DATA_06 0x06
62 #define OPCODE_SEND_BUFFER 0x07
63 #define OPCODE_AUDIO_FRAME 0x08
64 #define OPCODE_SILENCE_FRAME 0x09
65 #define OPCODE_INIT_VIDEO_MODE 0x0A
66 #define OPCODE_CREATE_GRADIENT 0x0B
67 #define OPCODE_SET_PALETTE 0x0C
68 #define OPCODE_SET_PALETTE_COMPRESSED 0x0D
69 #define OPCODE_SET_SKIP_MAP 0x0E
70 #define OPCODE_SET_DECODING_MAP 0x0F
71 #define OPCODE_VIDEO_DATA_10 0x10
72 #define OPCODE_VIDEO_DATA_11 0x11
73 #define OPCODE_UNKNOWN_12 0x12
74 #define OPCODE_UNKNOWN_13 0x13
75 #define OPCODE_UNKNOWN_14 0x14
76 #define OPCODE_UNKNOWN_15 0x15
77 
78 #define PALETTE_COUNT 256
79 
80 typedef struct IPMVEContext {
82  unsigned char *buf;
83  int buf_size;
84 
85  uint64_t frame_pts_inc;
86 
87  unsigned int video_bpp;
88  unsigned int video_width;
89  unsigned int video_height;
90  int64_t video_pts;
91  uint32_t palette[256];
93  int changed;
96 
97  unsigned int audio_bits;
98  unsigned int audio_channels;
99  unsigned int audio_sample_rate;
101  unsigned int audio_frame_count;
102 
105 
114 
116 
117 } IPMVEContext;
118 
120  AVPacket *pkt) {
121 
122  int chunk_type;
123 
124  if (s->audio_chunk_offset && s->audio_channels && s->audio_bits) {
125  if (s->audio_type == AV_CODEC_ID_NONE) {
126  av_log(s->avf, AV_LOG_ERROR, "Can not read audio packet before"
127  "audio codec is known\n");
128  return CHUNK_BAD;
129  }
130 
131  /* adjust for PCM audio by skipping chunk header */
133  s->audio_chunk_offset += 6;
134  s->audio_chunk_size -= 6;
135  }
136 
137  avio_seek(pb, s->audio_chunk_offset, SEEK_SET);
138  s->audio_chunk_offset = 0;
139 
140  if (s->audio_chunk_size != av_get_packet(pb, pkt, s->audio_chunk_size))
141  return CHUNK_EOF;
142 
144  pkt->pts = s->audio_frame_count;
145 
146  /* audio frame maintenance */
148  s->audio_frame_count +=
149  (s->audio_chunk_size / s->audio_channels / (s->audio_bits / 8));
150  else
151  s->audio_frame_count +=
153 
154  av_log(s->avf, AV_LOG_TRACE, "sending audio frame with pts %"PRId64" (%d audio frames)\n",
155  pkt->pts, s->audio_frame_count);
156 
157  chunk_type = CHUNK_VIDEO;
158 
159  } else if (s->frame_format) {
160 
161  /* send the frame format, decode map, the video data, skip map, and the send_buffer flag together */
162 
164  return CHUNK_NOMEM;
165 
166  if (s->has_palette) {
167  uint8_t *pal;
168 
171  if (pal) {
172  memcpy(pal, s->palette, AVPALETTE_SIZE);
173  s->has_palette = 0;
174  }
175  }
176 
177  if (s->changed) {
178  ff_add_param_change(pkt, 0, 0, 0, s->video_width, s->video_height);
179  s->changed = 0;
180  }
181 
182  AV_WL8(pkt->data, s->frame_format);
183  AV_WL8(pkt->data + 1, s->send_buffer);
184  AV_WL16(pkt->data + 2, s->video_chunk_size);
185  AV_WL16(pkt->data + 4, s->decode_map_chunk_size);
186  AV_WL16(pkt->data + 6, s->skip_map_chunk_size);
187 
188  s->frame_format = 0;
189  s->send_buffer = 0;
190 
191  pkt->pos = s->video_chunk_offset;
192  avio_seek(pb, s->video_chunk_offset, SEEK_SET);
193  s->video_chunk_offset = 0;
194 
195  if (avio_read(pb, pkt->data + 8, s->video_chunk_size) !=
196  s->video_chunk_size) {
197  av_packet_unref(pkt);
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);
205 
206  if (avio_read(pb, pkt->data + 8 + s->video_chunk_size,
208  av_packet_unref(pkt);
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,
220  av_packet_unref(pkt);
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 
230  pkt->pts = s->video_pts;
231 
232  av_log(s->avf, AV_LOG_TRACE, "sending video frame with pts %"PRId64"\n", pkt->pts);
233 
234  s->video_pts += s->frame_pts_inc;
235 
236  chunk_type = CHUNK_VIDEO;
237 
238  } else {
239 
240  avio_seek(pb, s->next_chunk_offset, SEEK_SET);
241  chunk_type = CHUNK_DONE;
242 
243  }
244 
245  return chunk_type;
246 }
247 
249 {
250  IPMVEContext *ipmovie = s->priv_data;
252  if (!st)
253  return AVERROR(ENOMEM);
254  avpriv_set_pts_info(st, 32, 1, ipmovie->audio_sample_rate);
255  ipmovie->audio_stream_index = st->index;
257  st->codecpar->codec_id = ipmovie->audio_type;
258  st->codecpar->codec_tag = 0; /* no tag */
259  st->codecpar->channels = ipmovie->audio_channels;
262  st->codecpar->sample_rate = ipmovie->audio_sample_rate;
263  st->codecpar->bits_per_coded_sample = ipmovie->audio_bits;
267  st->codecpar->bit_rate /= 2;
269 
270  return 0;
271 }
272 
273 /* This function loads and processes a single chunk in an IP movie file.
274  * It returns the type of chunk that was processed. */
276  AVPacket *pkt)
277 {
278  unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
279  int chunk_type;
280  int chunk_size;
281  unsigned char opcode_preamble[OPCODE_PREAMBLE_SIZE];
282  unsigned char opcode_type;
283  unsigned char opcode_version;
284  int opcode_size;
285  unsigned char scratch[1024];
286  int i, j;
287  int first_color, last_color;
288  int audio_flags;
289  unsigned char r, g, b;
290  unsigned int width, height;
291 
292  /* see if there are any pending packets */
293  chunk_type = load_ipmovie_packet(s, pb, pkt);
294  if (chunk_type != CHUNK_DONE)
295  return chunk_type;
296 
297  /* read the next chunk, wherever the file happens to be pointing */
298  if (avio_feof(pb))
299  return CHUNK_EOF;
300  if (avio_read(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
302  return CHUNK_BAD;
303  chunk_size = AV_RL16(&chunk_preamble[0]);
304  chunk_type = AV_RL16(&chunk_preamble[2]);
305 
306  av_log(s->avf, AV_LOG_TRACE, "chunk type 0x%04X, 0x%04X bytes: ", chunk_type, chunk_size);
307 
308  switch (chunk_type) {
309 
310  case CHUNK_INIT_AUDIO:
311  av_log(s->avf, AV_LOG_TRACE, "initialize audio\n");
312  break;
313 
314  case CHUNK_AUDIO_ONLY:
315  av_log(s->avf, AV_LOG_TRACE, "audio only\n");
316  break;
317 
318  case CHUNK_INIT_VIDEO:
319  av_log(s->avf, AV_LOG_TRACE, "initialize video\n");
320  break;
321 
322  case CHUNK_VIDEO:
323  av_log(s->avf, AV_LOG_TRACE, "video (and audio)\n");
324  break;
325 
326  case CHUNK_SHUTDOWN:
327  av_log(s->avf, AV_LOG_TRACE, "shutdown\n");
328  break;
329 
330  case CHUNK_END:
331  av_log(s->avf, AV_LOG_TRACE, "end\n");
332  break;
333 
334  default:
335  av_log(s->avf, AV_LOG_TRACE, "invalid chunk\n");
336  chunk_type = CHUNK_BAD;
337  break;
338 
339  }
340 
341  while ((chunk_size > 0) && (chunk_type != CHUNK_BAD)) {
342 
343  /* read the next chunk, wherever the file happens to be pointing */
344  if (avio_feof(pb)) {
345  chunk_type = CHUNK_EOF;
346  break;
347  }
348  if (avio_read(pb, opcode_preamble, CHUNK_PREAMBLE_SIZE) !=
350  chunk_type = CHUNK_BAD;
351  break;
352  }
353 
354  opcode_size = AV_RL16(&opcode_preamble[0]);
355  opcode_type = opcode_preamble[2];
356  opcode_version = opcode_preamble[3];
357 
358  chunk_size -= OPCODE_PREAMBLE_SIZE;
359  chunk_size -= opcode_size;
360  if (chunk_size < 0) {
361  av_log(s->avf, AV_LOG_TRACE, "chunk_size countdown just went negative\n");
362  chunk_type = CHUNK_BAD;
363  break;
364  }
365 
366  av_log(s->avf, AV_LOG_TRACE, " opcode type %02X, version %d, 0x%04X bytes: ",
367  opcode_type, opcode_version, opcode_size);
368  switch (opcode_type) {
369 
371  av_log(s->avf, AV_LOG_TRACE, "end of stream\n");
372  avio_skip(pb, opcode_size);
373  break;
374 
375  case OPCODE_END_OF_CHUNK:
376  av_log(s->avf, AV_LOG_TRACE, "end of chunk\n");
377  avio_skip(pb, opcode_size);
378  break;
379 
380  case OPCODE_CREATE_TIMER:
381  av_log(s->avf, AV_LOG_TRACE, "create timer\n");
382  if ((opcode_version > 0) || (opcode_size != 6)) {
383  av_log(s->avf, AV_LOG_TRACE, "bad create_timer opcode\n");
384  chunk_type = CHUNK_BAD;
385  break;
386  }
387  if (avio_read(pb, scratch, opcode_size) !=
388  opcode_size) {
389  chunk_type = CHUNK_BAD;
390  break;
391  }
392  s->frame_pts_inc = ((uint64_t)AV_RL32(&scratch[0])) * AV_RL16(&scratch[4]);
393  break;
394 
396  av_log(s->avf, AV_LOG_TRACE, "initialize audio buffers\n");
397  if (opcode_version > 1 || opcode_size > 10 || opcode_size < 6) {
398  av_log(s->avf, AV_LOG_TRACE, "bad init_audio_buffers opcode\n");
399  chunk_type = CHUNK_BAD;
400  break;
401  }
402  if (avio_read(pb, scratch, opcode_size) !=
403  opcode_size) {
404  chunk_type = CHUNK_BAD;
405  break;
406  }
407  s->audio_sample_rate = AV_RL16(&scratch[4]);
408  audio_flags = AV_RL16(&scratch[2]);
409  /* bit 0 of the flags: 0 = mono, 1 = stereo */
410  s->audio_channels = (audio_flags & 1) + 1;
411  /* bit 1 of the flags: 0 = 8 bit, 1 = 16 bit */
412  s->audio_bits = (((audio_flags >> 1) & 1) + 1) * 8;
413  /* bit 2 indicates compressed audio in version 1 opcode */
414  if ((opcode_version == 1) && (audio_flags & 0x4))
416  else if (s->audio_bits == 16)
418  else
420  av_log(s->avf, AV_LOG_TRACE, "audio: %d bits, %d Hz, %s, %s format\n",
422  (s->audio_channels == 2) ? "stereo" : "mono",
424  "Interplay audio" : "PCM");
425  break;
426 
428  av_log(s->avf, AV_LOG_TRACE, "start/stop audio\n");
429  avio_skip(pb, opcode_size);
430  break;
431 
433  av_log(s->avf, AV_LOG_TRACE, "initialize video buffers\n");
434  if ((opcode_version > 2) || (opcode_size > 8) || opcode_size < 4
435  || opcode_version == 2 && opcode_size < 8
436  ) {
437  av_log(s->avf, AV_LOG_TRACE, "bad init_video_buffers opcode\n");
438  chunk_type = CHUNK_BAD;
439  break;
440  }
441  if (avio_read(pb, scratch, opcode_size) !=
442  opcode_size) {
443  chunk_type = CHUNK_BAD;
444  break;
445  }
446  width = AV_RL16(&scratch[0]) * 8;
447  height = AV_RL16(&scratch[2]) * 8;
448  if (width != s->video_width) {
449  s->video_width = width;
450  s->changed++;
451  }
452  if (height != s->video_height) {
453  s->video_height = height;
454  s->changed++;
455  }
456  if (opcode_version < 2 || !AV_RL16(&scratch[6])) {
457  s->video_bpp = 8;
458  } else {
459  s->video_bpp = 16;
460  }
461  av_log(s->avf, AV_LOG_TRACE, "video resolution: %d x %d\n",
462  s->video_width, s->video_height);
463  break;
464 
465  case OPCODE_UNKNOWN_12:
466  case OPCODE_UNKNOWN_13:
467  case OPCODE_UNKNOWN_14:
468  case OPCODE_UNKNOWN_15:
469  av_log(s->avf, AV_LOG_TRACE, "unknown (but documented) opcode %02X\n", opcode_type);
470  avio_skip(pb, opcode_size);
471  break;
472 
473  case OPCODE_SEND_BUFFER:
474  av_log(s->avf, AV_LOG_TRACE, "send buffer\n");
475  avio_skip(pb, opcode_size);
476  s->send_buffer = 1;
477  break;
478 
479  case OPCODE_AUDIO_FRAME:
480  av_log(s->avf, AV_LOG_TRACE, "audio frame\n");
481 
482  /* log position and move on for now */
483  s->audio_chunk_offset = avio_tell(pb);
484  s->audio_chunk_size = opcode_size;
485  avio_skip(pb, opcode_size);
486  break;
487 
489  av_log(s->avf, AV_LOG_TRACE, "silence frame\n");
490  avio_skip(pb, opcode_size);
491  break;
492 
494  av_log(s->avf, AV_LOG_TRACE, "initialize video mode\n");
495  avio_skip(pb, opcode_size);
496  break;
497 
499  av_log(s->avf, AV_LOG_TRACE, "create gradient\n");
500  avio_skip(pb, opcode_size);
501  break;
502 
503  case OPCODE_SET_PALETTE:
504  av_log(s->avf, AV_LOG_TRACE, "set palette\n");
505  /* check for the logical maximum palette size
506  * (3 * 256 + 4 bytes) */
507  if (opcode_size > 0x304 || opcode_size < 4) {
508  av_log(s->avf, AV_LOG_TRACE, "demux_ipmovie: set_palette opcode with invalid size\n");
509  chunk_type = CHUNK_BAD;
510  break;
511  }
512  if (avio_read(pb, scratch, opcode_size) != opcode_size) {
513  chunk_type = CHUNK_BAD;
514  break;
515  }
516 
517  /* load the palette into internal data structure */
518  first_color = AV_RL16(&scratch[0]);
519  last_color = first_color + AV_RL16(&scratch[2]) - 1;
520  /* sanity check (since they are 16 bit values) */
521  if ( (first_color > 0xFF) || (last_color > 0xFF)
522  || (last_color - first_color + 1)*3 + 4 > opcode_size) {
523  av_log(s->avf, AV_LOG_TRACE, "demux_ipmovie: set_palette indexes out of range (%d -> %d)\n",
524  first_color, last_color);
525  chunk_type = CHUNK_BAD;
526  break;
527  }
528  j = 4; /* offset of first palette data */
529  for (i = first_color; i <= last_color; i++) {
530  /* the palette is stored as a 6-bit VGA palette, thus each
531  * component is shifted up to a 8-bit range */
532  r = scratch[j++] * 4;
533  g = scratch[j++] * 4;
534  b = scratch[j++] * 4;
535  s->palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | (b);
536  s->palette[i] |= s->palette[i] >> 6 & 0x30303;
537  }
538  s->has_palette = 1;
539  break;
540 
542  av_log(s->avf, AV_LOG_TRACE, "set palette compressed\n");
543  avio_skip(pb, opcode_size);
544  break;
545 
546  case OPCODE_SET_SKIP_MAP:
547  av_log(s->avf, AV_LOG_TRACE, "set skip map\n");
548 
549  /* log position and move on for now */
551  s->skip_map_chunk_size = opcode_size;
552  avio_skip(pb, opcode_size);
553  break;
554 
556  av_log(s->avf, AV_LOG_TRACE, "set decoding map\n");
557 
558  /* log position and move on for now */
560  s->decode_map_chunk_size = opcode_size;
561  avio_skip(pb, opcode_size);
562  break;
563 
565  av_log(s->avf, AV_LOG_TRACE, "set video data format 0x06\n");
566  s->frame_format = 0x06;
567 
568  /* log position and move on for now */
569  s->video_chunk_offset = avio_tell(pb);
570  s->video_chunk_size = opcode_size;
571  avio_skip(pb, opcode_size);
572  break;
573 
575  av_log(s->avf, AV_LOG_TRACE, "set video data format 0x10\n");
576  s->frame_format = 0x10;
577 
578  /* log position and move on for now */
579  s->video_chunk_offset = avio_tell(pb);
580  s->video_chunk_size = opcode_size;
581  avio_skip(pb, opcode_size);
582  break;
583 
585  av_log(s->avf, AV_LOG_TRACE, "set video data format 0x11\n");
586  s->frame_format = 0x11;
587 
588  /* log position and move on for now */
589  s->video_chunk_offset = avio_tell(pb);
590  s->video_chunk_size = opcode_size;
591  avio_skip(pb, opcode_size);
592  break;
593 
594  default:
595  av_log(s->avf, AV_LOG_TRACE, "*** unknown opcode type\n");
596  chunk_type = CHUNK_BAD;
597  break;
598 
599  }
600  }
601 
602  if (s->avf->nb_streams == 1 && s->audio_type)
603  init_audio(s->avf);
604 
605  /* make a note of where the stream is sitting */
606  s->next_chunk_offset = avio_tell(pb);
607 
608  /* dispatch the first of any pending packets */
609  if ((chunk_type == CHUNK_VIDEO) || (chunk_type == CHUNK_AUDIO_ONLY))
610  chunk_type = load_ipmovie_packet(s, pb, pkt);
611 
612  return chunk_type;
613 }
614 
615 static const char signature[] = "Interplay MVE File\x1A\0\x1A";
616 
617 static int ipmovie_probe(const AVProbeData *p)
618 {
619  const uint8_t *b = p->buf;
620  const uint8_t *b_end = p->buf + p->buf_size - sizeof(signature);
621  do {
622  if (b[0] == signature[0] && memcmp(b, signature, sizeof(signature)) == 0)
623  return AVPROBE_SCORE_MAX;
624  b++;
625  } while (b < b_end);
626 
627  return 0;
628 }
629 
631 {
632  IPMVEContext *ipmovie = s->priv_data;
633  AVIOContext *pb = s->pb;
634  AVPacket pkt;
635  AVStream *st;
636  unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE];
637  int chunk_type, i;
638  uint8_t signature_buffer[sizeof(signature)];
639 
640  ipmovie->avf = s;
641 
642  avio_read(pb, signature_buffer, sizeof(signature_buffer));
643  while (memcmp(signature_buffer, signature, sizeof(signature))) {
644  memmove(signature_buffer, signature_buffer + 1, sizeof(signature_buffer) - 1);
645  signature_buffer[sizeof(signature_buffer) - 1] = avio_r8(pb);
646  if (avio_feof(pb))
647  return AVERROR_EOF;
648  }
649  /* initialize private context members */
650  ipmovie->video_pts = ipmovie->audio_frame_count = 0;
651  ipmovie->audio_chunk_offset = ipmovie->video_chunk_offset =
652  ipmovie->decode_map_chunk_offset = ipmovie->skip_map_chunk_offset = 0;
653  ipmovie->decode_map_chunk_size = ipmovie->video_chunk_size =
654  ipmovie->skip_map_chunk_size = 0;
655  ipmovie->send_buffer = ipmovie->frame_format = 0;
656 
657  /* on the first read, this will position the stream at the first chunk */
658  ipmovie->next_chunk_offset = avio_tell(pb) + 4;
659 
660  for (i = 0; i < 256; i++)
661  ipmovie->palette[i] = 0xFFU << 24;
662 
663  /* process the first chunk which should be CHUNK_INIT_VIDEO */
664  if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_VIDEO)
665  return AVERROR_INVALIDDATA;
666 
667  /* peek ahead to the next chunk-- if it is an init audio chunk, process
668  * it; if it is the first video chunk, this is a silent file */
669  if (avio_read(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) !=
671  return AVERROR(EIO);
672  chunk_type = AV_RL16(&chunk_preamble[2]);
673  avio_seek(pb, -CHUNK_PREAMBLE_SIZE, SEEK_CUR);
674 
675  if (chunk_type == CHUNK_VIDEO)
676  ipmovie->audio_type = AV_CODEC_ID_NONE; /* no audio */
677  else if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_AUDIO)
678  return AVERROR_INVALIDDATA;
679 
680  /* initialize the stream decoders */
681  st = avformat_new_stream(s, NULL);
682  if (!st)
683  return AVERROR(ENOMEM);
684  avpriv_set_pts_info(st, 63, 1, 1000000);
685  ipmovie->video_stream_index = st->index;
688  st->codecpar->codec_tag = 0; /* no fourcc */
689  st->codecpar->width = ipmovie->video_width;
690  st->codecpar->height = ipmovie->video_height;
691  st->codecpar->bits_per_coded_sample = ipmovie->video_bpp;
692 
693  if (ipmovie->audio_type) {
694  return init_audio(s);
695  } else
697 
698  return 0;
699 }
700 
702  AVPacket *pkt)
703 {
704  IPMVEContext *ipmovie = s->priv_data;
705  AVIOContext *pb = s->pb;
706  int ret;
707 
708  for (;;) {
709  ret = process_ipmovie_chunk(ipmovie, pb, pkt);
710  if (ret == CHUNK_BAD)
711  ret = AVERROR_INVALIDDATA;
712  else if (ret == CHUNK_EOF)
713  ret = AVERROR(EIO);
714  else if (ret == CHUNK_NOMEM)
715  ret = AVERROR(ENOMEM);
716  else if (ret == CHUNK_END || ret == CHUNK_SHUTDOWN)
717  ret = AVERROR_EOF;
718  else if (ret == CHUNK_VIDEO)
719  ret = 0;
720  else if (ret == CHUNK_INIT_VIDEO || ret == CHUNK_INIT_AUDIO)
721  continue;
722  else
723  continue;
724 
725  return ret;
726  }
727 }
728 
730  .name = "ipmovie",
731  .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE"),
732  .priv_data_size = sizeof(IPMVEContext),
736 };
#define OPCODE_SET_PALETTE_COMPRESSED
Definition: ipmovie.c:68
int64_t decode_map_chunk_offset
Definition: ipmovie.c:112
#define NULL
Definition: coverity.c:32
#define OPCODE_SEND_BUFFER
Definition: ipmovie.c:62
Bytestream IO Context.
Definition: avio.h:161
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
int64_t skip_map_chunk_offset
Definition: ipmovie.c:110
static int ipmovie_read_header(AVFormatContext *s)
Definition: ipmovie.c:630
int64_t pos
byte position in stream, -1 if unknown
Definition: avcodec.h:1497
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:4882
const char * g
Definition: vf_curves.c:115
int audio_stream_index
Definition: ipmovie.c:104
#define OPCODE_UNKNOWN_14
Definition: ipmovie.c:75
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3953
int index
stream index in AVFormatContext
Definition: avformat.h:882
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:246
#define CHUNK_INIT_VIDEO
Definition: ipmovie.c:45
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:331
static AVPacket pkt
#define AV_CH_LAYOUT_STEREO
int ctx_flags
Flags signalling stream properties.
Definition: avformat.h:1407
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:87
#define OPCODE_CREATE_GRADIENT
Definition: ipmovie.c:66
static int ipmovie_probe(const AVProbeData *p)
Definition: ipmovie.c:617
Format I/O context.
Definition: avformat.h:1358
static const char signature[]
Definition: ipmovie.c:615
#define OPCODE_UNKNOWN_12
Definition: ipmovie.c:73
int64_t audio_chunk_offset
Definition: ipmovie.c:106
#define CHUNK_END
Definition: ipmovie.c:48
uint8_t
int width
Video only.
Definition: avcodec.h:4019
#define AVFMTCTX_NOHEADER
signal that no header is present (streams are added dynamically)
Definition: avformat.h:1302
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:202
unsigned int audio_channels
Definition: ipmovie.c:98
#define AVPALETTE_SIZE
Definition: pixfmt.h:32
#define AV_WL8(p, d)
Definition: intreadwrite.h:399
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4455
#define height
uint8_t * data
Definition: avcodec.h:1477
int decode_map_chunk_size
Definition: ipmovie.c:113
int64_t next_chunk_offset
Definition: ipmovie.c:115
#define AVERROR_EOF
End of file.
Definition: error.h:55
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
Allocate and read the payload of a packet and initialize its fields with default values.
Definition: utils.c:310
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
unsigned int video_bpp
Definition: ipmovie.c:87
uint64_t channel_layout
Audio only.
Definition: avcodec.h:4055
#define av_log(a,...)
unsigned int video_height
Definition: ipmovie.c:89
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:648
AVFormatContext * avf
Definition: ipmovie.c:81
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: avcodec.h:3982
#define U(x)
Definition: vp56_arith.h:37
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:86
#define OPCODE_VIDEO_DATA_06
Definition: ipmovie.c:61
#define OPCODE_INIT_AUDIO_BUFFERS
Definition: ipmovie.c:58
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:260
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: avcodec.h:215
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
An AV_PKT_DATA_PALETTE side data packet contains exactly AVPALETTE_SIZE bytes worth of palette...
Definition: avcodec.h:1190
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
const char * r
Definition: vf_curves.c:114
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3949
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:5014
#define OPCODE_SET_SKIP_MAP
Definition: ipmovie.c:69
int video_chunk_size
Definition: ipmovie.c:109
#define OPCODE_UNKNOWN_13
Definition: ipmovie.c:74
#define OPCODE_SET_DECODING_MAP
Definition: ipmovie.c:70
#define OPCODE_END_OF_CHUNK
Definition: ipmovie.c:56
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:639
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:449
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:448
int buf_size
Definition: ipmovie.c:83
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1414
int block_align
Audio only.
Definition: avcodec.h:4070
#define b
Definition: input.c:41
audio channel layout utility functions
unsigned int audio_bits
Definition: ipmovie.c:97
#define width
#define OPCODE_PREAMBLE_SIZE
Definition: ipmovie.c:41
#define CHUNK_SHUTDOWN
Definition: ipmovie.c:47
#define OPCODE_START_STOP_AUDIO
Definition: ipmovie.c:59
#define s(width, name)
Definition: cbs_vp9.c:257
#define OPCODE_END_OF_STREAM
Definition: ipmovie.c:55
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:530
if(ret)
unsigned char * buf
Definition: ipmovie.c:82
enum AVCodecID audio_type
Definition: ipmovie.c:100
Stream structure.
Definition: avformat.h:881
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
#define OPCODE_INIT_VIDEO_MODE
Definition: ipmovie.c:65
AVIOContext * pb
I/O context.
Definition: avformat.h:1400
#define CHUNK_AUDIO_ONLY
Definition: ipmovie.c:44
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:599
static int init_audio(AVFormatContext *s)
Definition: ipmovie.c:248
static int load_ipmovie_packet(IPMVEContext *s, AVIOContext *pb, AVPacket *pkt)
Definition: ipmovie.c:119
#define OPCODE_INIT_VIDEO_BUFFERS
Definition: ipmovie.c:60
int64_t video_chunk_offset
Definition: ipmovie.c:108
unsigned int video_width
Definition: ipmovie.c:88
int audio_chunk_size
Definition: ipmovie.c:107
uint32_t palette[256]
Definition: ipmovie.c:91
#define CHUNK_INIT_AUDIO
Definition: ipmovie.c:43
This structure contains the data a format has to probe a file.
Definition: avformat.h:446
static int process_ipmovie_chunk(IPMVEContext *s, AVIOContext *pb, AVPacket *pkt)
Definition: ipmovie.c:275
#define OPCODE_AUDIO_FRAME
Definition: ipmovie.c:63
#define OPCODE_VIDEO_DATA_11
Definition: ipmovie.c:72
uint8_t frame_format
Definition: ipmovie.c:95
#define OPCODE_CREATE_TIMER
Definition: ipmovie.c:57
static int read_probe(const AVProbeData *pd)
Definition: jvdec.c:55
int64_t video_pts
Definition: ipmovie.c:90
int sample_rate
Audio only.
Definition: avcodec.h:4063
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:458
#define CHUNK_DONE
Definition: ipmovie.c:50
Main libavformat public API header.
int video_stream_index
Definition: ipmovie.c:103
#define OPCODE_VIDEO_DATA_10
Definition: ipmovie.c:71
#define OPCODE_SILENCE_FRAME
Definition: ipmovie.c:64
#define CHUNK_PREAMBLE_SIZE
Definition: ipmovie.c:40
#define AV_WL16(p, v)
Definition: intreadwrite.h:412
AVInputFormat ff_ipmovie_demuxer
Definition: ipmovie.c:729
#define OPCODE_SET_PALETTE
Definition: ipmovie.c:67
unsigned int audio_frame_count
Definition: ipmovie.c:101
void * priv_data
Format private data.
Definition: avformat.h:1386
#define OPCODE_UNKNOWN_15
Definition: ipmovie.c:76
#define CHUNK_NOMEM
Definition: ipmovie.c:51
uint8_t send_buffer
Definition: ipmovie.c:94
int bits_per_coded_sample
The number of bits per sample in the codedwords.
Definition: avcodec.h:3995
static int ipmovie_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: ipmovie.c:701
int channels
Audio only.
Definition: avcodec.h:4059
#define CHUNK_BAD
Definition: ipmovie.c:53
#define CHUNK_EOF
Definition: ipmovie.c:52
uint64_t frame_pts_inc
Definition: ipmovie.c:85
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:654
int has_palette
Definition: ipmovie.c:92
#define CHUNK_VIDEO
Definition: ipmovie.c:46
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1028
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition: aviobuf.c:358
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: avcodec.h:3957
int changed
Definition: ipmovie.c:93
uint8_t * av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, int size)
Allocate new information of a packet.
Definition: avpacket.c:329
int stream_index
Definition: avcodec.h:1479
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
#define AV_CH_LAYOUT_MONO
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:87
This structure stores compressed data.
Definition: avcodec.h:1454
unsigned int audio_sample_rate
Definition: ipmovie.c:99
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1470
int skip_map_chunk_size
Definition: ipmovie.c:111