Mercurial > libavformat.hg
annotate bethsoftvid.c @ 6323:4a52e54b7c12 libavformat
Remove duplicate initialiser for cavsvideo_muxer.extensions
The extensions field was initialised first to "cavs", then to "avs".
The name "cavs" is kept since this is used for the format elsewhere
and "avs" is already used for avisynth files.
author | mru |
---|---|
date | Tue, 27 Jul 2010 08:21:23 +0000 |
parents | 178de7695c6c |
children |
rev | line source |
---|---|
1989 | 1 /* |
2 * Bethsoft VID format Demuxer | |
3 * Copyright (c) 2007 Nicholas Tung | |
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 /** | |
5969
178de7695c6c
Remove explicit filename from Doxygen @file commands.
diego
parents:
5910
diff
changeset
|
23 * @file |
1989 | 24 * @brief Bethesda Softworks VID (.vid) file demuxer |
25 * @author Nicholas Tung [ntung (at. ntung com] (2007-03) | |
26 * @sa http://wiki.multimedia.cx/index.php?title=Bethsoft_VID | |
27 * @sa http://www.svatopluk.com/andux/docs/dfvid.html | |
28 */ | |
29 | |
4201
7d2f3f1b68d8
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
3908
diff
changeset
|
30 #include "libavutil/intreadwrite.h" |
1989 | 31 #include "avformat.h" |
3286 | 32 #include "libavcodec/bethsoftvideo.h" |
1989 | 33 |
34 typedef struct BVID_DemuxContext | |
35 { | |
36 int nframes; | |
37 /** delay value between frames, added to individual frame delay. | |
38 * custom units, which will be added to other custom units (~=16ms according | |
39 * to free, unofficial documentation) */ | |
40 int bethsoft_global_delay; | |
41 | |
42 /** video presentation time stamp. | |
43 * delay = 16 milliseconds * (global_delay + per_frame_delay) */ | |
1995
df6bcc29a90c
code claims to use 32bit timestamp, lets make it also use that
michael
parents:
1994
diff
changeset
|
44 int video_pts; |
1989 | 45 |
46 int is_finished; | |
47 | |
48 } BVID_DemuxContext; | |
49 | |
50 static int vid_probe(AVProbeData *p) | |
51 { | |
52 // little endian VID tag, file starts with "VID\0" | |
2001
1a3c9056982a
allocate 32 extra bytes at the end of the probe buffer and remove most probe buf_size checks
michael
parents:
1999
diff
changeset
|
53 if (AV_RL32(p->buf) != MKTAG('V', 'I', 'D', 0)) |
1989 | 54 return 0; |
55 | |
56 return AVPROBE_SCORE_MAX; | |
57 } | |
58 | |
59 static int vid_read_header(AVFormatContext *s, | |
60 AVFormatParameters *ap) | |
61 { | |
1994 | 62 BVID_DemuxContext *vid = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
63 ByteIOContext *pb = s->pb; |
1989 | 64 AVStream *stream; |
65 | |
66 /* load main header. Contents: | |
67 * bytes: 'V' 'I' 'D' | |
68 * int16s: always_512, nframes, width, height, delay, always_14 | |
69 */ | |
70 url_fseek(pb, 5, SEEK_CUR); | |
71 vid->nframes = get_le16(pb); | |
72 | |
73 stream = av_new_stream(s, 0); | |
1991
999e085b50eb
sane indention (no more 3 statements on one line...)
michael
parents:
1989
diff
changeset
|
74 if (!stream) |
2273
7eb456c4ed8a
Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents:
2232
diff
changeset
|
75 return AVERROR(ENOMEM); |
1989 | 76 av_set_pts_info(stream, 32, 1, 60); // 16 ms increments, i.e. 60 fps |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
4331
diff
changeset
|
77 stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; |
1989 | 78 stream->codec->codec_id = CODEC_ID_BETHSOFTVID; |
79 stream->codec->width = get_le16(pb); | |
80 stream->codec->height = get_le16(pb); | |
81 stream->codec->pix_fmt = PIX_FMT_PAL8; | |
82 vid->bethsoft_global_delay = get_le16(pb); | |
83 get_le16(pb); | |
84 | |
85 // done with video codec, set up audio codec | |
86 stream = av_new_stream(s, 0); | |
1991
999e085b50eb
sane indention (no more 3 statements on one line...)
michael
parents:
1989
diff
changeset
|
87 if (!stream) |
2273
7eb456c4ed8a
Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents:
2232
diff
changeset
|
88 return AVERROR(ENOMEM); |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
4331
diff
changeset
|
89 stream->codec->codec_type = AVMEDIA_TYPE_AUDIO; |
1989 | 90 stream->codec->codec_id = CODEC_ID_PCM_U8; |
91 stream->codec->channels = 1; | |
92 stream->codec->sample_rate = 11025; | |
3908
1d3d17de20ba
Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents:
3424
diff
changeset
|
93 stream->codec->bits_per_coded_sample = 8; |
1d3d17de20ba
Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents:
3424
diff
changeset
|
94 stream->codec->bit_rate = stream->codec->channels * stream->codec->sample_rate * stream->codec->bits_per_coded_sample; |
1989 | 95 |
96 return 0; | |
97 } | |
98 | |
99 #define BUFFER_PADDING_SIZE 1000 | |
100 static int read_frame(BVID_DemuxContext *vid, ByteIOContext *pb, AVPacket *pkt, | |
101 uint8_t block_type, AVFormatContext *s, int npixels) | |
102 { | |
103 uint8_t * vidbuf_start = NULL; | |
104 int vidbuf_nbytes = 0; | |
1999 | 105 int code; |
1989 | 106 int bytes_copied = 0; |
107 int position; | |
2232
77ed2f4105b7
bethsoftvid: use correct type for size passed to av_fast_realloc()
mru
parents:
2001
diff
changeset
|
108 unsigned int vidbuf_capacity; |
1989 | 109 |
110 vidbuf_start = av_malloc(vidbuf_capacity = BUFFER_PADDING_SIZE); | |
1991
999e085b50eb
sane indention (no more 3 statements on one line...)
michael
parents:
1989
diff
changeset
|
111 if(!vidbuf_start) |
2273
7eb456c4ed8a
Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents:
2232
diff
changeset
|
112 return AVERROR(ENOMEM); |
1989 | 113 |
114 // save the file position for the packet, include block type | |
115 position = url_ftell(pb) - 1; | |
116 | |
117 vidbuf_start[vidbuf_nbytes++] = block_type; | |
118 | |
119 // get the video delay (next int16), and set the presentation time | |
120 vid->video_pts += vid->bethsoft_global_delay + get_le16(pb); | |
121 | |
122 // set the y offset if it exists (decoder header data should be in data section) | |
1996 | 123 if(block_type == VIDEO_YOFF_P_FRAME){ |
1991
999e085b50eb
sane indention (no more 3 statements on one line...)
michael
parents:
1989
diff
changeset
|
124 if(get_buffer(pb, &vidbuf_start[vidbuf_nbytes], 2) != 2) |
1992
c321bada49c7
memleak (seems ive missed that under the obfuscated indention)
michael
parents:
1991
diff
changeset
|
125 goto fail; |
1989 | 126 vidbuf_nbytes += 2; |
127 } | |
128 | |
1991
999e085b50eb
sane indention (no more 3 statements on one line...)
michael
parents:
1989
diff
changeset
|
129 do{ |
1989 | 130 vidbuf_start = av_fast_realloc(vidbuf_start, &vidbuf_capacity, vidbuf_nbytes + BUFFER_PADDING_SIZE); |
1991
999e085b50eb
sane indention (no more 3 statements on one line...)
michael
parents:
1989
diff
changeset
|
131 if(!vidbuf_start) |
2273
7eb456c4ed8a
Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents:
2232
diff
changeset
|
132 return AVERROR(ENOMEM); |
1989 | 133 |
1999 | 134 code = get_byte(pb); |
135 vidbuf_start[vidbuf_nbytes++] = code; | |
1989 | 136 |
1999 | 137 if(code >= 0x80){ // rle sequence |
1996 | 138 if(block_type == VIDEO_I_FRAME) |
1991
999e085b50eb
sane indention (no more 3 statements on one line...)
michael
parents:
1989
diff
changeset
|
139 vidbuf_start[vidbuf_nbytes++] = get_byte(pb); |
1999 | 140 } else if(code){ // plain sequence |
141 if(get_buffer(pb, &vidbuf_start[vidbuf_nbytes], code) != code) | |
1992
c321bada49c7
memleak (seems ive missed that under the obfuscated indention)
michael
parents:
1991
diff
changeset
|
142 goto fail; |
1999 | 143 vidbuf_nbytes += code; |
1989 | 144 } |
1999 | 145 bytes_copied += code & 0x7F; |
1991
999e085b50eb
sane indention (no more 3 statements on one line...)
michael
parents:
1989
diff
changeset
|
146 if(bytes_copied == npixels){ // sometimes no stop character is given, need to keep track of bytes copied |
1989 | 147 // may contain a 0 byte even if read all pixels |
1991
999e085b50eb
sane indention (no more 3 statements on one line...)
michael
parents:
1989
diff
changeset
|
148 if(get_byte(pb)) |
999e085b50eb
sane indention (no more 3 statements on one line...)
michael
parents:
1989
diff
changeset
|
149 url_fseek(pb, -1, SEEK_CUR); |
1989 | 150 break; |
151 } | |
1991
999e085b50eb
sane indention (no more 3 statements on one line...)
michael
parents:
1989
diff
changeset
|
152 if(bytes_copied > npixels) |
1992
c321bada49c7
memleak (seems ive missed that under the obfuscated indention)
michael
parents:
1991
diff
changeset
|
153 goto fail; |
1999 | 154 } while(code); |
1989 | 155 |
156 // copy data into packet | |
1992
c321bada49c7
memleak (seems ive missed that under the obfuscated indention)
michael
parents:
1991
diff
changeset
|
157 if(av_new_packet(pkt, vidbuf_nbytes) < 0) |
c321bada49c7
memleak (seems ive missed that under the obfuscated indention)
michael
parents:
1991
diff
changeset
|
158 goto fail; |
1989 | 159 memcpy(pkt->data, vidbuf_start, vidbuf_nbytes); |
160 av_free(vidbuf_start); | |
161 | |
162 pkt->pos = position; | |
163 pkt->stream_index = 0; // use the video decoder, which was initialized as the first stream | |
164 pkt->pts = vid->video_pts; | |
165 | |
166 vid->nframes--; // used to check if all the frames were read | |
167 return vidbuf_nbytes; | |
1992
c321bada49c7
memleak (seems ive missed that under the obfuscated indention)
michael
parents:
1991
diff
changeset
|
168 fail: |
c321bada49c7
memleak (seems ive missed that under the obfuscated indention)
michael
parents:
1991
diff
changeset
|
169 av_free(vidbuf_start); |
c321bada49c7
memleak (seems ive missed that under the obfuscated indention)
michael
parents:
1991
diff
changeset
|
170 return -1; |
1989 | 171 } |
172 | |
173 static int vid_read_packet(AVFormatContext *s, | |
174 AVPacket *pkt) | |
175 { | |
1994 | 176 BVID_DemuxContext *vid = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2274
diff
changeset
|
177 ByteIOContext *pb = s->pb; |
1994 | 178 unsigned char block_type; |
1989 | 179 int audio_length; |
180 int ret_value; | |
181 | |
1991
999e085b50eb
sane indention (no more 3 statements on one line...)
michael
parents:
1989
diff
changeset
|
182 if(vid->is_finished || url_feof(pb)) |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2273
diff
changeset
|
183 return AVERROR(EIO); |
1989 | 184 |
185 block_type = get_byte(pb); | |
1991
999e085b50eb
sane indention (no more 3 statements on one line...)
michael
parents:
1989
diff
changeset
|
186 switch(block_type){ |
1989 | 187 case PALETTE_BLOCK: |
188 url_fseek(pb, -1, SEEK_CUR); // include block type | |
1996 | 189 ret_value = av_get_packet(pb, pkt, 3 * 256 + 1); |
190 if(ret_value != 3 * 256 + 1){ | |
1991
999e085b50eb
sane indention (no more 3 statements on one line...)
michael
parents:
1989
diff
changeset
|
191 av_free_packet(pkt); |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2273
diff
changeset
|
192 return AVERROR(EIO); |
1991
999e085b50eb
sane indention (no more 3 statements on one line...)
michael
parents:
1989
diff
changeset
|
193 } |
1989 | 194 pkt->stream_index = 0; |
195 return ret_value; | |
196 | |
197 case FIRST_AUDIO_BLOCK: | |
1994 | 198 get_le16(pb); |
1989 | 199 // soundblaster DAC used for sample rate, as on specification page (link above) |
200 s->streams[1]->codec->sample_rate = 1000000 / (256 - get_byte(pb)); | |
3908
1d3d17de20ba
Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents:
3424
diff
changeset
|
201 s->streams[1]->codec->bit_rate = s->streams[1]->codec->channels * s->streams[1]->codec->sample_rate * s->streams[1]->codec->bits_per_coded_sample; |
1989 | 202 case AUDIO_BLOCK: |
203 audio_length = get_le16(pb); | |
204 ret_value = av_get_packet(pb, pkt, audio_length); | |
205 pkt->stream_index = 1; | |
3278 | 206 return ret_value != audio_length ? AVERROR(EIO) : ret_value; |
1989 | 207 |
1996 | 208 case VIDEO_P_FRAME: |
209 case VIDEO_YOFF_P_FRAME: | |
210 case VIDEO_I_FRAME: | |
1989 | 211 return read_frame(vid, pb, pkt, block_type, s, |
212 s->streams[0]->codec->width * s->streams[0]->codec->height); | |
213 | |
1996 | 214 case EOF_BLOCK: |
1989 | 215 if(vid->nframes != 0) |
216 av_log(s, AV_LOG_VERBOSE, "reached terminating character but not all frames read.\n"); | |
217 vid->is_finished = 1; | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2273
diff
changeset
|
218 return AVERROR(EIO); |
1989 | 219 default: |
220 av_log(s, AV_LOG_ERROR, "unknown block (character = %c, decimal = %d, hex = %x)!!!\n", | |
221 block_type, block_type, block_type); return -1; | |
222 } | |
223 | |
224 return 0; | |
225 } | |
226 | |
227 AVInputFormat bethsoftvid_demuxer = { | |
228 "bethsoftvid", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3286
diff
changeset
|
229 NULL_IF_CONFIG_SMALL("Bethesda Softworks VID format"), |
1989 | 230 sizeof(BVID_DemuxContext), |
231 vid_probe, | |
232 vid_read_header, | |
233 vid_read_packet, | |
234 }; |