sierravmd.c
Go to the documentation of this file.
1 /*
2  * Sierra VMD Format Demuxer
3  * Copyright (c) 2004 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  * Sierra VMD file demuxer
25  * by Vladimir "VAG" Gneushev (vagsoft at mail.ru)
26  * for more information on the Sierra VMD file format, visit:
27  * http://www.pcisys.net/~melanson/codecs/
28  */
29 
31 #include "libavutil/intreadwrite.h"
32 #include "avformat.h"
33 #include "internal.h"
34 #include "avio_internal.h"
35 
36 #define VMD_HEADER_SIZE 0x0330
37 #define BYTES_PER_FRAME_RECORD 16
38 
39 typedef struct {
41  int64_t frame_offset;
42  unsigned int frame_size;
43  int64_t pts;
44  int keyframe;
45  unsigned char frame_record[BYTES_PER_FRAME_RECORD];
46 } vmd_frame;
47 
48 typedef struct VmdDemuxContext {
51 
52  unsigned int frame_count;
53  unsigned int frames_per_block;
55  unsigned int current_frame;
56  int is_indeo3;
57 
60  int skiphdr;
61 
62  unsigned char vmd_header[VMD_HEADER_SIZE];
64 
65 static int vmd_probe(AVProbeData *p)
66 {
67  int w, h;
68  if (p->buf_size < 16)
69  return 0;
70  /* check if the first 2 bytes of the file contain the appropriate size
71  * of a VMD header chunk */
72  if (AV_RL16(&p->buf[0]) != VMD_HEADER_SIZE - 2)
73  return 0;
74  w = AV_RL16(&p->buf[12]);
75  h = AV_RL16(&p->buf[14]);
76  if (!w || w > 2048 || !h || h > 2048)
77  return 0;
78 
79  /* only return half certainty since this check is a bit sketchy */
80  return AVPROBE_SCORE_MAX / 2;
81 }
82 
84 {
85  VmdDemuxContext *vmd = s->priv_data;
86  AVIOContext *pb = s->pb;
87  AVStream *st = NULL, *vst;
88  unsigned int toc_offset;
89  unsigned char *raw_frame_table;
90  int raw_frame_table_size;
91  int64_t current_offset;
92  int i, j;
93  unsigned int total_frames;
94  int64_t current_audio_pts = 0;
95  unsigned char chunk[BYTES_PER_FRAME_RECORD];
96  int num, den;
97  int sound_buffers;
98 
99  /* fetch the main header, including the 2 header length bytes */
100  avio_seek(pb, 0, SEEK_SET);
102  return AVERROR(EIO);
103 
104  if(vmd->vmd_header[24] == 'i' && vmd->vmd_header[25] == 'v' && vmd->vmd_header[26] == '3')
105  vmd->is_indeo3 = 1;
106  else
107  vmd->is_indeo3 = 0;
108  /* start up the decoders */
109  vst = avformat_new_stream(s, NULL);
110  if (!vst)
111  return AVERROR(ENOMEM);
112  avpriv_set_pts_info(vst, 33, 1, 10);
113  vmd->video_stream_index = vst->index;
114  vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
115  vst->codec->codec_id = vmd->is_indeo3 ? AV_CODEC_ID_INDEO3 : AV_CODEC_ID_VMDVIDEO;
116  vst->codec->codec_tag = 0; /* no fourcc */
117  vst->codec->width = AV_RL16(&vmd->vmd_header[12]);
118  vst->codec->height = AV_RL16(&vmd->vmd_header[14]);
119  if(vmd->is_indeo3 && vst->codec->width > 320){
120  vst->codec->width >>= 1;
121  vst->codec->height >>= 1;
122  }
123  vst->codec->extradata_size = VMD_HEADER_SIZE;
124  vst->codec->extradata = av_mallocz(VMD_HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
125  memcpy(vst->codec->extradata, vmd->vmd_header, VMD_HEADER_SIZE);
126 
127  /* if sample rate is 0, assume no audio */
128  vmd->sample_rate = AV_RL16(&vmd->vmd_header[804]);
129  if (vmd->sample_rate) {
130  st = avformat_new_stream(s, NULL);
131  if (!st)
132  return AVERROR(ENOMEM);
133  vmd->audio_stream_index = st->index;
136  st->codec->codec_tag = 0; /* no fourcc */
137  if (vmd->vmd_header[811] & 0x80) {
138  st->codec->channels = 2;
140  } else {
141  st->codec->channels = 1;
143  }
144  st->codec->sample_rate = vmd->sample_rate;
145  st->codec->block_align = AV_RL16(&vmd->vmd_header[806]);
146  if (st->codec->block_align & 0x8000) {
147  st->codec->bits_per_coded_sample = 16;
148  st->codec->block_align = -(st->codec->block_align - 0x10000);
149  } else {
150  st->codec->bits_per_coded_sample = 8;
151  }
152  st->codec->bit_rate = st->codec->sample_rate *
154 
155  /* calculate pts */
156  num = st->codec->block_align;
157  den = st->codec->sample_rate * st->codec->channels;
158  av_reduce(&num, &den, num, den, (1UL<<31)-1);
159  avpriv_set_pts_info(vst, 33, num, den);
160  avpriv_set_pts_info(st, 33, num, den);
161  }
162 
163  toc_offset = AV_RL32(&vmd->vmd_header[812]);
164  vmd->frame_count = AV_RL16(&vmd->vmd_header[6]);
165  vmd->frames_per_block = AV_RL16(&vmd->vmd_header[18]);
166  avio_seek(pb, toc_offset, SEEK_SET);
167 
168  raw_frame_table = NULL;
169  vmd->frame_table = NULL;
170  sound_buffers = AV_RL16(&vmd->vmd_header[808]);
171  raw_frame_table_size = vmd->frame_count * 6;
172  if(vmd->frame_count * vmd->frames_per_block >= UINT_MAX / sizeof(vmd_frame) - sound_buffers){
173  av_log(s, AV_LOG_ERROR, "vmd->frame_count * vmd->frames_per_block too large\n");
174  return -1;
175  }
176  raw_frame_table = av_malloc(raw_frame_table_size);
177  vmd->frame_table = av_malloc((vmd->frame_count * vmd->frames_per_block + sound_buffers) * sizeof(vmd_frame));
178  if (!raw_frame_table || !vmd->frame_table) {
179  av_free(raw_frame_table);
180  av_free(vmd->frame_table);
181  return AVERROR(ENOMEM);
182  }
183  if (avio_read(pb, raw_frame_table, raw_frame_table_size) !=
184  raw_frame_table_size) {
185  av_free(raw_frame_table);
186  av_free(vmd->frame_table);
187  return AVERROR(EIO);
188  }
189 
190  total_frames = 0;
191  for (i = 0; i < vmd->frame_count; i++) {
192 
193  current_offset = AV_RL32(&raw_frame_table[6 * i + 2]);
194 
195  /* handle each entry in index block */
196  for (j = 0; j < vmd->frames_per_block; j++) {
197  int type;
198  uint32_t size;
199 
200  avio_read(pb, chunk, BYTES_PER_FRAME_RECORD);
201  type = chunk[0];
202  size = AV_RL32(&chunk[2]);
203  if(!size && type != 1)
204  continue;
205  switch(type) {
206  case 1: /* Audio Chunk */
207  if (!st) break;
208  /* first audio chunk contains several audio buffers */
209  vmd->frame_table[total_frames].frame_offset = current_offset;
210  vmd->frame_table[total_frames].stream_index = vmd->audio_stream_index;
211  vmd->frame_table[total_frames].frame_size = size;
212  memcpy(vmd->frame_table[total_frames].frame_record, chunk, BYTES_PER_FRAME_RECORD);
213  vmd->frame_table[total_frames].pts = current_audio_pts;
214  total_frames++;
215  if(!current_audio_pts)
216  current_audio_pts += sound_buffers - 1;
217  else
218  current_audio_pts++;
219  break;
220  case 2: /* Video Chunk */
221  vmd->frame_table[total_frames].frame_offset = current_offset;
222  vmd->frame_table[total_frames].stream_index = vmd->video_stream_index;
223  vmd->frame_table[total_frames].frame_size = size;
224  memcpy(vmd->frame_table[total_frames].frame_record, chunk, BYTES_PER_FRAME_RECORD);
225  vmd->frame_table[total_frames].pts = i;
226  total_frames++;
227  break;
228  }
229  current_offset += size;
230  }
231  }
232 
233  av_free(raw_frame_table);
234 
235  vmd->current_frame = 0;
236  vmd->frame_count = total_frames;
237 
238  return 0;
239 }
240 
242  AVPacket *pkt)
243 {
244  VmdDemuxContext *vmd = s->priv_data;
245  AVIOContext *pb = s->pb;
246  int ret = 0;
247  vmd_frame *frame;
248 
249  if (vmd->current_frame >= vmd->frame_count)
250  return AVERROR_EOF;
251 
252  frame = &vmd->frame_table[vmd->current_frame];
253  /* position the stream (will probably be there already) */
254  avio_seek(pb, frame->frame_offset, SEEK_SET);
255 
256  if(ffio_limit(pb, frame->frame_size) != frame->frame_size)
257  return AVERROR(EIO);
259  return AVERROR(ENOMEM);
260  pkt->pos= avio_tell(pb);
261  memcpy(pkt->data, frame->frame_record, BYTES_PER_FRAME_RECORD);
262  if(vmd->is_indeo3 && frame->frame_record[0] == 0x02)
263  ret = avio_read(pb, pkt->data, frame->frame_size);
264  else
265  ret = avio_read(pb, pkt->data + BYTES_PER_FRAME_RECORD,
266  frame->frame_size);
267 
268  if (ret != frame->frame_size) {
269  av_free_packet(pkt);
270  ret = AVERROR(EIO);
271  }
272  pkt->stream_index = frame->stream_index;
273  pkt->pts = frame->pts;
274  av_log(s, AV_LOG_DEBUG, " dispatching %s frame with %d bytes and pts %"PRId64"\n",
275  (frame->frame_record[0] == 0x02) ? "video" : "audio",
277  pkt->pts);
278 
279  vmd->current_frame++;
280 
281  return ret;
282 }
283 
285 {
286  VmdDemuxContext *vmd = s->priv_data;
287 
288  av_free(vmd->frame_table);
289 
290  return 0;
291 }
292 
294  .name = "vmd",
295  .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD"),
296  .priv_data_size = sizeof(VmdDemuxContext),
301 };
unsigned int frame_count
Definition: sierravmd.c:52
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:205
const char * s
Definition: avisynth_c.h:668
Bytestream IO Context.
Definition: avio.h:68
void av_free_packet(AVPacket *pkt)
Free a packet.
Definition: avpacket.c:242
int64_t pos
byte position in stream, -1 if unknown
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.
int index
stream index in AVFormatContext
Definition: avformat.h:644
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:199
#define AV_RL16
int64_t audio_sample_counter
Definition: sierravmd.c:59
#define AV_CH_LAYOUT_STEREO
unsigned int frames_per_block
Definition: sierravmd.c:53
int block_align
number of bytes per packet if constant and known or 0 Used by some WAV based audio codecs...
output residual component w
unsigned int current_frame
Definition: sierravmd.c:55
Format I/O context.
Definition: avformat.h:944
static int vmd_read_close(AVFormatContext *s)
Definition: sierravmd.c:284
int audio_stream_index
Definition: sierravmd.c:50
int ffio_limit(AVIOContext *s, int size)
int keyframe
Definition: sierravmd.c:44
static AVPacket pkt
Definition: demuxing.c:56
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
int stream_index
Definition: sierravmd.c:40
uint8_t * data
#define AVERROR_EOF
End of file.
Definition: error.h:55
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:145
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:248
int bits_per_coded_sample
bits per sample/pixel from the demuxer (needed for huffyuv).
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:478
frame
Definition: stft.m:14
struct VmdDemuxContext VmdDemuxContext
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:73
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
int size
uint64_t channel_layout
Audio channel layout.
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
Definition: rational.c:36
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:337
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:336
#define FF_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
int bit_rate
the average bitrate
audio channel layout utility functions
static int read_probe(AVProbeData *pd)
ret
Definition: avfilter.c:821
AVInputFormat ff_vmd_demuxer
Definition: sierravmd.c:293
#define BYTES_PER_FRAME_RECORD
Definition: sierravmd.c:37
#define AV_RL32
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:517
Stream structure.
Definition: avformat.h:643
static int vmd_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: sierravmd.c:241
int video_stream_index
Definition: sierravmd.c:49
NULL
Definition: eval.c:55
enum AVMediaType codec_type
enum AVCodecID codec_id
int sample_rate
samples per second
AVIOContext * pb
I/O context.
Definition: avformat.h:977
vmd_frame * frame_table
Definition: sierravmd.c:54
static int vmd_read_header(AVFormatContext *s)
Definition: sierravmd.c:83
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
unsigned int codec_tag
fourcc (LSB first, so "ABCD" -> (&#39;D&#39;<<24) + (&#39;C&#39;<<16) + (&#39;B&#39;<<8) + &#39;A&#39;).
static int read_packet(AVFormatContext *ctx, AVPacket *pkt)
Definition: libcdio.c:114
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
synthesis window for stochastic i
int64_t pts
Definition: sierravmd.c:43
This structure contains the data a format has to probe a file.
Definition: avformat.h:334
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer 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.Buffer references ownership and permissions
#define type
unsigned char vmd_header[VMD_HEADER_SIZE]
Definition: sierravmd.c:62
int64_t frame_offset
Definition: sierravmd.c:41
#define AVPROBE_SCORE_MAX
maximum score, half of that is used for file-extension-based detection
Definition: avformat.h:340
Main libavformat public API header.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:162
unsigned char frame_record[BYTES_PER_FRAME_RECORD]
Definition: sierravmd.c:45
int channels
number of audio channels
void * priv_data
Format private data.
Definition: avformat.h:964
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:461
unsigned int frame_size
Definition: sierravmd.c:42
#define VMD_HEADER_SIZE
Definition: sierravmd.c:36
static int vmd_probe(AVProbeData *p)
Definition: sierravmd.c:65
#define AV_CH_LAYOUT_MONO
This structure stores compressed data.
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...