Commit | Line | Data |
---|---|---|
4120a53a | 1 | /* |
ffa5ed24 | 2 | * id Quake II CIN File Demuxer |
4120a53a MM |
3 | * Copyright (c) 2003 The ffmpeg Project |
4 | * | |
b78e7197 DB |
5 | * This file is part of FFmpeg. |
6 | * | |
7 | * FFmpeg is free software; you can redistribute it and/or | |
4120a53a MM |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either | |
b78e7197 | 10 | * version 2.1 of the License, or (at your option) any later version. |
4120a53a | 11 | * |
b78e7197 | 12 | * FFmpeg is distributed in the hope that it will be useful, |
4120a53a MM |
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 | |
b78e7197 | 18 | * License along with FFmpeg; if not, write to the Free Software |
5509bffa | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
4120a53a MM |
20 | */ |
21 | ||
22 | /** | |
bad5537e | 23 | * @file libavformat/idcin.c |
ffa5ed24 SS |
24 | * id Quake II CIN file demuxer by Mike Melanson (melanson@pcisys.net) |
25 | * For more information about the id CIN format, visit: | |
4120a53a MM |
26 | * http://www.csse.monash.edu.au/~timf/ |
27 | * | |
28 | * CIN is a somewhat quirky and ill-defined format. Here are some notes | |
29 | * for anyone trying to understand the technical details of this format: | |
30 | * | |
31 | * The format has no definite file signature. This is problematic for a | |
32 | * general-purpose media player that wants to automatically detect file | |
33 | * types. However, a CIN file does start with 5 32-bit numbers that | |
34 | * specify audio and video parameters. This demuxer gets around the lack | |
35 | * of file signature by performing sanity checks on those parameters. | |
36 | * Probabalistically, this is a reasonable solution since the number of | |
37 | * valid combinations of the 5 parameters is a very small subset of the | |
38 | * total 160-bit number space. | |
39 | * | |
40 | * Refer to the function idcin_probe() for the precise A/V parameters | |
41 | * that this demuxer allows. | |
42 | * | |
43 | * Next, each audio and video frame has a duration of 1/14 sec. If the | |
44 | * audio sample rate is a multiple of the common frequency 22050 Hz it will | |
45 | * divide evenly by 14. However, if the sample rate is 11025 Hz: | |
46 | * 11025 (samples/sec) / 14 (frames/sec) = 787.5 (samples/frame) | |
47 | * The way the CIN stores audio in this case is by storing 787 sample | |
48 | * frames in the first audio frame and 788 sample frames in the second | |
49 | * audio frame. Therefore, the total number of bytes in an audio frame | |
50 | * is given as: | |
51 | * audio frame #0: 787 * (bytes/sample) * (# channels) bytes in frame | |
52 | * audio frame #1: 788 * (bytes/sample) * (# channels) bytes in frame | |
53 | * audio frame #2: 787 * (bytes/sample) * (# channels) bytes in frame | |
54 | * audio frame #3: 788 * (bytes/sample) * (# channels) bytes in frame | |
55 | * | |
ffa5ed24 | 56 | * Finally, not all id CIN creation tools agree on the resolution of the |
4120a53a MM |
57 | * color palette, apparently. Some creation tools specify red, green, and |
58 | * blue palette components in terms of 6-bit VGA color DAC values which | |
59 | * range from 0..63. Other tools specify the RGB components as full 8-bit | |
60 | * values that range from 0..255. Since there are no markers in the file to | |
61 | * differentiate between the two variants, this demuxer uses the following | |
62 | * heuristic: | |
63 | * - load the 768 palette bytes from disk | |
64 | * - assume that they will need to be shifted left by 2 bits to | |
65 | * transform them from 6-bit values to 8-bit values | |
66 | * - scan through all 768 palette bytes | |
67 | * - if any bytes exceed 63, do not shift the bytes at all before | |
68 | * transmitting them to the video decoder | |
69 | */ | |
70 | ||
6a5d31ac | 71 | #include "libavutil/intreadwrite.h" |
4120a53a MM |
72 | #include "avformat.h" |
73 | ||
4120a53a | 74 | #define HUFFMAN_TABLE_SIZE (64 * 1024) |
40e8e497 | 75 | #define IDCIN_FPS 14 |
4120a53a MM |
76 | |
77 | typedef struct IdcinDemuxContext { | |
78 | int video_stream_index; | |
79 | int audio_stream_index; | |
80 | int audio_chunk_size1; | |
81 | int audio_chunk_size2; | |
82 | ||
83 | /* demux state variables */ | |
84 | int current_audio_chunk; | |
85 | int next_chunk_is_video; | |
86 | int audio_present; | |
87 | ||
88 | int64_t pts; | |
89 | ||
2a2bbcb0 | 90 | AVPaletteControl palctrl; |
4120a53a MM |
91 | } IdcinDemuxContext; |
92 | ||
93 | static int idcin_probe(AVProbeData *p) | |
94 | { | |
95 | unsigned int number; | |
96 | ||
97 | /* | |
ffa5ed24 | 98 | * This is what you could call a "probabilistic" file check: id CIN |
4120a53a MM |
99 | * files don't have a definite file signature. In lieu of such a marker, |
100 | * perform sanity checks on the 5 32-bit header fields: | |
101 | * width, height: greater than 0, less than or equal to 1024 | |
102 | * audio sample rate: greater than or equal to 8000, less than or | |
103 | * equal to 48000, or 0 for no audio | |
104 | * audio sample width (bytes/sample): 0 for no audio, or 1 or 2 | |
105 | * audio channels: 0 for no audio, or 1 or 2 | |
106 | */ | |
107 | ||
8466ab59 RD |
108 | /* check we have enough data to do all checks, otherwise the |
109 | 0-padding may cause a wrong recognition */ | |
110 | if (p->buf_size < 20) | |
111 | return 0; | |
112 | ||
4120a53a | 113 | /* check the video width */ |
fead30d4 | 114 | number = AV_RL32(&p->buf[0]); |
4120a53a MM |
115 | if ((number == 0) || (number > 1024)) |
116 | return 0; | |
117 | ||
118 | /* check the video height */ | |
fead30d4 | 119 | number = AV_RL32(&p->buf[4]); |
4120a53a MM |
120 | if ((number == 0) || (number > 1024)) |
121 | return 0; | |
122 | ||
123 | /* check the audio sample rate */ | |
fead30d4 | 124 | number = AV_RL32(&p->buf[8]); |
4120a53a MM |
125 | if ((number != 0) && ((number < 8000) | (number > 48000))) |
126 | return 0; | |
127 | ||
128 | /* check the audio bytes/sample */ | |
fead30d4 | 129 | number = AV_RL32(&p->buf[12]); |
4120a53a MM |
130 | if (number > 2) |
131 | return 0; | |
132 | ||
133 | /* check the audio channels */ | |
fead30d4 | 134 | number = AV_RL32(&p->buf[16]); |
4120a53a MM |
135 | if (number > 2) |
136 | return 0; | |
137 | ||
138 | /* return half certainly since this check is a bit sketchy */ | |
139 | return AVPROBE_SCORE_MAX / 2; | |
140 | } | |
141 | ||
142 | static int idcin_read_header(AVFormatContext *s, | |
143 | AVFormatParameters *ap) | |
144 | { | |
899681cd | 145 | ByteIOContext *pb = s->pb; |
e4141433 | 146 | IdcinDemuxContext *idcin = s->priv_data; |
4120a53a MM |
147 | AVStream *st; |
148 | unsigned int width, height; | |
149 | unsigned int sample_rate, bytes_per_sample, channels; | |
150 | ||
151 | /* get the 5 header parameters */ | |
152 | width = get_le32(pb); | |
153 | height = get_le32(pb); | |
154 | sample_rate = get_le32(pb); | |
155 | bytes_per_sample = get_le32(pb); | |
156 | channels = get_le32(pb); | |
157 | ||
158 | st = av_new_stream(s, 0); | |
159 | if (!st) | |
769e10f0 | 160 | return AVERROR(ENOMEM); |
40e8e497 | 161 | av_set_pts_info(st, 33, 1, IDCIN_FPS); |
4120a53a | 162 | idcin->video_stream_index = st->index; |
01f4895c MN |
163 | st->codec->codec_type = CODEC_TYPE_VIDEO; |
164 | st->codec->codec_id = CODEC_ID_IDCIN; | |
165 | st->codec->codec_tag = 0; /* no fourcc */ | |
166 | st->codec->width = width; | |
167 | st->codec->height = height; | |
4120a53a MM |
168 | |
169 | /* load up the Huffman tables into extradata */ | |
01f4895c MN |
170 | st->codec->extradata_size = HUFFMAN_TABLE_SIZE; |
171 | st->codec->extradata = av_malloc(HUFFMAN_TABLE_SIZE); | |
172 | if (get_buffer(pb, st->codec->extradata, HUFFMAN_TABLE_SIZE) != | |
4120a53a | 173 | HUFFMAN_TABLE_SIZE) |
6f3e0b21 | 174 | return AVERROR(EIO); |
4120a53a | 175 | /* save a reference in order to transport the palette */ |
01f4895c | 176 | st->codec->palctrl = &idcin->palctrl; |
4120a53a MM |
177 | |
178 | /* if sample rate is 0, assume no audio */ | |
179 | if (sample_rate) { | |
180 | idcin->audio_present = 1; | |
181 | st = av_new_stream(s, 0); | |
182 | if (!st) | |
769e10f0 | 183 | return AVERROR(ENOMEM); |
40e8e497 | 184 | av_set_pts_info(st, 33, 1, IDCIN_FPS); |
4120a53a | 185 | idcin->audio_stream_index = st->index; |
01f4895c MN |
186 | st->codec->codec_type = CODEC_TYPE_AUDIO; |
187 | st->codec->codec_tag = 1; | |
188 | st->codec->channels = channels; | |
189 | st->codec->sample_rate = sample_rate; | |
dd1c8f3e | 190 | st->codec->bits_per_coded_sample = bytes_per_sample * 8; |
01f4895c MN |
191 | st->codec->bit_rate = sample_rate * bytes_per_sample * 8 * channels; |
192 | st->codec->block_align = bytes_per_sample * channels; | |
4120a53a | 193 | if (bytes_per_sample == 1) |
01f4895c | 194 | st->codec->codec_id = CODEC_ID_PCM_U8; |
4120a53a | 195 | else |
01f4895c | 196 | st->codec->codec_id = CODEC_ID_PCM_S16LE; |
4120a53a MM |
197 | |
198 | if (sample_rate % 14 != 0) { | |
199 | idcin->audio_chunk_size1 = (sample_rate / 14) * | |
200 | bytes_per_sample * channels; | |
201 | idcin->audio_chunk_size2 = (sample_rate / 14 + 1) * | |
202 | bytes_per_sample * channels; | |
203 | } else { | |
204 | idcin->audio_chunk_size1 = idcin->audio_chunk_size2 = | |
205 | (sample_rate / 14) * bytes_per_sample * channels; | |
206 | } | |
207 | idcin->current_audio_chunk = 0; | |
208 | } else | |
209 | idcin->audio_present = 1; | |
210 | ||
211 | idcin->next_chunk_is_video = 1; | |
212 | idcin->pts = 0; | |
213 | ||
4120a53a MM |
214 | return 0; |
215 | } | |
216 | ||
217 | static int idcin_read_packet(AVFormatContext *s, | |
218 | AVPacket *pkt) | |
219 | { | |
220 | int ret; | |
221 | unsigned int command; | |
222 | unsigned int chunk_size; | |
e4141433 | 223 | IdcinDemuxContext *idcin = s->priv_data; |
899681cd | 224 | ByteIOContext *pb = s->pb; |
4120a53a MM |
225 | int i; |
226 | int palette_scale; | |
2a2bbcb0 MM |
227 | unsigned char r, g, b; |
228 | unsigned char palette_buffer[768]; | |
4120a53a | 229 | |
899681cd | 230 | if (url_feof(s->pb)) |
6f3e0b21 | 231 | return AVERROR(EIO); |
4120a53a MM |
232 | |
233 | if (idcin->next_chunk_is_video) { | |
234 | command = get_le32(pb); | |
235 | if (command == 2) { | |
6f3e0b21 | 236 | return AVERROR(EIO); |
4120a53a MM |
237 | } else if (command == 1) { |
238 | /* trigger a palette change */ | |
2a2bbcb0 MM |
239 | idcin->palctrl.palette_changed = 1; |
240 | if (get_buffer(pb, palette_buffer, 768) != 768) | |
6f3e0b21 | 241 | return AVERROR(EIO); |
4120a53a MM |
242 | /* scale the palette as necessary */ |
243 | palette_scale = 2; | |
244 | for (i = 0; i < 768; i++) | |
2a2bbcb0 | 245 | if (palette_buffer[i] > 63) { |
4120a53a MM |
246 | palette_scale = 0; |
247 | break; | |
248 | } | |
249 | ||
2a2bbcb0 MM |
250 | for (i = 0; i < 256; i++) { |
251 | r = palette_buffer[i * 3 ] << palette_scale; | |
252 | g = palette_buffer[i * 3 + 1] << palette_scale; | |
253 | b = palette_buffer[i * 3 + 2] << palette_scale; | |
254 | idcin->palctrl.palette[i] = (r << 16) | (g << 8) | (b); | |
255 | } | |
4120a53a MM |
256 | } |
257 | ||
258 | chunk_size = get_le32(pb); | |
259 | /* skip the number of decoded bytes (always equal to width * height) */ | |
260 | url_fseek(pb, 4, SEEK_CUR); | |
261 | chunk_size -= 4; | |
115329f1 | 262 | ret= av_get_packet(pb, pkt, chunk_size); |
044a950d VS |
263 | if (ret < 0) |
264 | return ret; | |
4120a53a MM |
265 | pkt->stream_index = idcin->video_stream_index; |
266 | pkt->pts = idcin->pts; | |
4120a53a MM |
267 | } else { |
268 | /* send out the audio chunk */ | |
269 | if (idcin->current_audio_chunk) | |
270 | chunk_size = idcin->audio_chunk_size2; | |
271 | else | |
272 | chunk_size = idcin->audio_chunk_size1; | |
2692067a | 273 | ret= av_get_packet(pb, pkt, chunk_size); |
044a950d VS |
274 | if (ret < 0) |
275 | return ret; | |
4120a53a MM |
276 | pkt->stream_index = idcin->audio_stream_index; |
277 | pkt->pts = idcin->pts; | |
4120a53a MM |
278 | |
279 | idcin->current_audio_chunk ^= 1; | |
40e8e497 | 280 | idcin->pts++; |
4120a53a MM |
281 | } |
282 | ||
283 | if (idcin->audio_present) | |
284 | idcin->next_chunk_is_video ^= 1; | |
285 | ||
286 | return ret; | |
287 | } | |
288 | ||
ff70e601 | 289 | AVInputFormat idcin_demuxer = { |
4120a53a | 290 | "idcin", |
517ac243 | 291 | NULL_IF_CONFIG_SMALL("id Cinematic format"), |
4120a53a MM |
292 | sizeof(IdcinDemuxContext), |
293 | idcin_probe, | |
294 | idcin_read_header, | |
295 | idcin_read_packet, | |
4120a53a | 296 | }; |