Revision a7eb3c8d

View differences:

libavformat/Makefile
15 15
OBJS+=mpeg.o mpegts.o mpegtsenc.o ffm.o crc.o img.o raw.o rm.o \
16 16
      avienc.o avidec.o wav.o swf.o au.o gif.o mov.o mpjpeg.o dv.o \
17 17
      yuv4mpeg.o 4xm.o flvenc.o flvdec.o movenc.o psxstr.o idroq.o ipmovie.o \
18
      nut.o wc3movie.o mp3.o westwood.o segafilm.o idcin.o flic.o
18
      nut.o wc3movie.o mp3.o westwood.o segafilm.o idcin.o flic.o \
19
      sierravmd.o
19 20

  
20 21
ifeq ($(CONFIG_RISKY),yes)
21 22
OBJS+= asf.o
libavformat/allformats.c
70 70
    film_init();
71 71
    idcin_init();
72 72
    flic_init();
73
    vmd_init();
73 74

  
74 75
#if defined(AMR_NB) || defined(AMR_NB_FIXED) || defined(AMR_WB)
75 76
    amr_init();
libavformat/avformat.h
480 480
/* flic.c */
481 481
int flic_init(void);
482 482

  
483
/* sierravmd.c */
484
int vmd_init(void);
485

  
483 486
#include "rtp.h"
484 487

  
485 488
#include "rtsp.h"
libavformat/sierravmd.c
1
/*
2
 * Sierra VMD Format Demuxer
3
 * Copyright (c) 2004 The ffmpeg Project
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 */
19

  
20
/**
21
 * @file sierravmd.c
22
 * Sierra VMD file demuxer
23
 * by Vladimir "VAG" Gneushev (vagsoft at mail.ru)
24
 */
25

  
26
#include "avformat.h"
27

  
28
#define LE_16(x)  ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
29
#define LE_32(x)  ((((uint8_t*)(x))[3] << 24) | \
30
                   (((uint8_t*)(x))[2] << 16) | \
31
                   (((uint8_t*)(x))[1] << 8) | \
32
                    ((uint8_t*)(x))[0])
33

  
34
#define VMD_HEADER_SIZE 0x0330
35
#define BYTES_PER_FRAME_RECORD 16
36

  
37
typedef struct {
38
  int stream_index;
39
  offset_t frame_offset;
40
  unsigned int frame_size;
41
  int64_t pts;
42
  int keyframe;
43
  unsigned char frame_record[BYTES_PER_FRAME_RECORD];
44
} vmd_frame_t;
45

  
46
typedef struct VmdDemuxContext {
47
    int video_stream_index;
48
    int audio_stream_index;
49

  
50
    unsigned int audio_type;
51
    unsigned int audio_samplerate;
52
    unsigned int audio_bits;
53
    unsigned int audio_channels;
54

  
55
    unsigned int frame_count;
56
    vmd_frame_t *frame_table;
57
    unsigned int current_frame;
58

  
59
    unsigned char vmd_header[VMD_HEADER_SIZE];
60
} VmdDemuxContext;
61

  
62
static int vmd_probe(AVProbeData *p)
63
{
64
    if (p->buf_size < 2)
65
        return 0;
66

  
67
    /* check if the first 2 bytes of the file contain the appropriate size
68
     * of a VMD header chunk */
69
    if (LE_16(&p->buf[0]) != VMD_HEADER_SIZE - 2)
70
        return 0;
71

  
72
    /* only return half certainty since this check is a bit sketchy */
73
    return AVPROBE_SCORE_MAX / 2;
74
}
75

  
76
static int vmd_read_header(AVFormatContext *s,
77
                           AVFormatParameters *ap)
78
{
79
    VmdDemuxContext *vmd = (VmdDemuxContext *)s->priv_data;
80
    ByteIOContext *pb = &s->pb;
81
    AVStream *st;
82
    unsigned int toc_offset;
83
    unsigned char *raw_frame_table;
84
    int raw_frame_table_size;
85
    unsigned char *current_frame_record;
86
    offset_t current_offset;
87
    int i;
88
    int sample_rate;
89
    unsigned int total_frames;
90
int video_frame_count = 0;
91

  
92
    /* fetch the main header, including the 2 header length bytes */
93
    url_fseek(pb, 0, SEEK_SET);
94
    if (get_buffer(pb, vmd->vmd_header, VMD_HEADER_SIZE) != VMD_HEADER_SIZE)
95
        return -EIO;
96

  
97
    /* start up the decoders */
98
    st = av_new_stream(s, 0);
99
    if (!st)
100
        return AVERROR_NOMEM;
101
    vmd->video_stream_index = st->index;
102
    st->codec.codec_type = CODEC_TYPE_VIDEO;
103
    st->codec.codec_id = CODEC_ID_VMDVIDEO;
104
    st->codec.codec_tag = 0;  /* no fourcc */
105
    st->codec.width = LE_16(&vmd->vmd_header[12]);
106
    st->codec.height = LE_16(&vmd->vmd_header[14]);
107
    st->codec.extradata_size = VMD_HEADER_SIZE;
108
    st->codec.extradata = av_malloc(VMD_HEADER_SIZE);
109
    memcpy(st->codec.extradata, vmd->vmd_header, VMD_HEADER_SIZE);
110

  
111
    /* if sample rate is 0, assume no audio */
112
    sample_rate = LE_16(&vmd->vmd_header[804]);
113
    if (sample_rate) {
114
        st = av_new_stream(s, 0);
115
        if (!st)
116
            return AVERROR_NOMEM;
117
        vmd->audio_stream_index = st->index;
118
        st->codec.codec_type = CODEC_TYPE_AUDIO;
119
        st->codec.codec_id = CODEC_ID_VMDAUDIO;
120
        st->codec.codec_tag = 0;  /* no codec tag */
121
        st->codec.channels = (vmd->vmd_header[811] & 0x80) ? 2 : 1;
122
        st->codec.sample_rate = sample_rate;
123
        st->codec.bit_rate = st->codec.sample_rate * 
124
            st->codec.bits_per_sample * st->codec.channels;
125
        st->codec.block_align = LE_16(&vmd->vmd_header[806]);
126
        if (st->codec.block_align & 0x8000) {
127
            st->codec.bits_per_sample = 16;
128
            st->codec.block_align = -(st->codec.block_align - 0x10000);
129
        } else
130
            st->codec.bits_per_sample = 8;
131
    }
132

  
133
    /* skip over the offset table and load the table of contents; don't 
134
     * care about the offset table since demuxer will calculate those 
135
     * independently */
136
    toc_offset = LE_32(&vmd->vmd_header[812]);
137
    vmd->frame_count = LE_16(&vmd->vmd_header[6]);
138
    url_fseek(pb, toc_offset + vmd->frame_count * 6, SEEK_SET);
139

  
140
    /* each on-disk VMD frame has an audio part and a video part; demuxer
141
     * accounts them separately */
142
    vmd->frame_count *= 2;
143
    raw_frame_table = NULL;
144
    vmd->frame_table = NULL;
145
    raw_frame_table_size = vmd->frame_count * BYTES_PER_FRAME_RECORD;
146
    raw_frame_table = av_malloc(raw_frame_table_size);
147
    vmd->frame_table = av_malloc(vmd->frame_count * sizeof(vmd_frame_t));
148
    if (!raw_frame_table || !vmd->frame_table) {
149
        av_free(raw_frame_table);
150
        av_free(vmd->frame_table);
151
        return AVERROR_NOMEM;
152
    }
153
    if (get_buffer(pb, raw_frame_table, raw_frame_table_size) != 
154
        raw_frame_table_size) {
155
        av_free(raw_frame_table);
156
        av_free(vmd->frame_table);
157
        return -EIO;
158
    }
159

  
160
    current_offset = LE_32(&vmd->vmd_header[20]);
161
    current_frame_record = raw_frame_table;
162
    total_frames = vmd->frame_count;
163
    i = 0;
164
    while (total_frames--) {
165

  
166
        /* if the frame size is 0, do not count the frame and bring the
167
         * total frame count down */
168
        vmd->frame_table[i].frame_size = LE_32(&current_frame_record[2]);
169

  
170
        /* this logic is present so that 0-length audio chunks are not
171
         * accounted */
172
        if (!vmd->frame_table[i].frame_size) {
173
            vmd->frame_count--;  /* one less frame to count */
174
            current_frame_record += BYTES_PER_FRAME_RECORD;
175
            continue;
176
        }
177

  
178
        if (current_frame_record[0] == 0x02)
179
            vmd->frame_table[i].stream_index = vmd->video_stream_index;
180
        else
181
            vmd->frame_table[i].stream_index = vmd->audio_stream_index;
182
        vmd->frame_table[i].frame_offset = current_offset;
183
        current_offset += vmd->frame_table[i].frame_size;
184
        memcpy(vmd->frame_table[i].frame_record, current_frame_record,
185
            BYTES_PER_FRAME_RECORD);
186

  
187
if (current_frame_record[0] == 0x02) {
188
  /* assume 15 fps for now */
189
  vmd->frame_table[i].pts = video_frame_count++;
190
  vmd->frame_table[i].pts *= 90000;
191
  vmd->frame_table[i].pts /= 15;
192
}
193

  
194
        current_frame_record += BYTES_PER_FRAME_RECORD;
195
        i++;
196
    }
197

  
198
    av_free(raw_frame_table);
199

  
200
    /* set the pts reference at 1 pts = 1/90000 sec */
201
    s->pts_num = 1;
202
    s->pts_den = 90000;
203

  
204
    vmd->current_frame = 0;
205

  
206
    return 0;
207
}
208

  
209
static int vmd_read_packet(AVFormatContext *s,
210
                           AVPacket *pkt)
211
{
212
    VmdDemuxContext *vmd = (VmdDemuxContext *)s->priv_data;
213
    ByteIOContext *pb = &s->pb;
214
    int ret = 0;
215
    vmd_frame_t *frame;
216

  
217
    if (vmd->current_frame >= vmd->frame_count)
218
        return -EIO;
219

  
220
    frame = &vmd->frame_table[vmd->current_frame];
221
    /* position the stream (will probably be there already) */
222
    url_fseek(pb, frame->frame_offset, SEEK_SET);
223

  
224
    if (av_new_packet(pkt, frame->frame_size + BYTES_PER_FRAME_RECORD))
225
        return AVERROR_NOMEM;
226
    memcpy(pkt->data, frame->frame_record, BYTES_PER_FRAME_RECORD);
227
    ret = get_buffer(pb, pkt->data + BYTES_PER_FRAME_RECORD, 
228
        frame->frame_size);
229

  
230
    if (ret != frame->frame_size)
231
        ret = -EIO;
232
    pkt->stream_index = frame->stream_index;
233
    pkt->pts = frame->pts;
234

  
235
    vmd->current_frame++;
236

  
237
    return ret;
238
}
239

  
240
static int vmd_read_close(AVFormatContext *s)
241
{
242
    VmdDemuxContext *vmd = (VmdDemuxContext *)s->priv_data;
243

  
244
    av_free(vmd->frame_table);
245

  
246
    return 0;
247
}
248

  
249
static AVInputFormat vmd_iformat = {
250
    "vmd",
251
    "Sierra VMD format",
252
    sizeof(VmdDemuxContext),
253
    vmd_probe,
254
    vmd_read_header,
255
    vmd_read_packet,
256
    vmd_read_close,
257
};
258

  
259
int vmd_init(void)
260
{
261
    av_register_input_format(&vmd_iformat);
262
    return 0;
263
}

Also available in: Unified diff