/src/ffmpeg/libavformat/idcin.c
Line | Count | Source |
1 | | /* |
2 | | * id Quake II CIN 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 | | * id Quake II CIN file demuxer by Mike Melanson (melanson@pcisys.net) |
25 | | * For more information about the id CIN format, visit: |
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 | | * Probabilistically, 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 | | * |
56 | | * Finally, not all id CIN creation tools agree on the resolution of the |
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 | | |
71 | | #include "libavutil/channel_layout.h" |
72 | | #include "libavutil/imgutils.h" |
73 | | #include "libavutil/intreadwrite.h" |
74 | | #include "avformat.h" |
75 | | #include "demux.h" |
76 | | #include "internal.h" |
77 | | |
78 | 944k | #define HUFFMAN_TABLE_SIZE (64 * 1024) |
79 | 1.55k | #define IDCIN_FPS 14 |
80 | | |
81 | | typedef struct IdcinDemuxContext { |
82 | | int video_stream_index; |
83 | | int audio_stream_index; |
84 | | int audio_chunk_size1; |
85 | | int audio_chunk_size2; |
86 | | int block_align; |
87 | | |
88 | | /* demux state variables */ |
89 | | int current_audio_chunk; |
90 | | int next_chunk_is_video; |
91 | | int audio_present; |
92 | | int64_t first_pkt_pos; |
93 | | } IdcinDemuxContext; |
94 | | |
95 | | static int idcin_probe(const AVProbeData *p) |
96 | 942k | { |
97 | 942k | unsigned int number, sample_rate; |
98 | 942k | unsigned int w, h; |
99 | 942k | int i; |
100 | | |
101 | | /* |
102 | | * This is what you could call a "probabilistic" file check: id CIN |
103 | | * files don't have a definite file signature. In lieu of such a marker, |
104 | | * perform sanity checks on the 5 32-bit header fields: |
105 | | * width, height: greater than 0, less than or equal to 1024 |
106 | | * audio sample rate: greater than or equal to 8000, less than or |
107 | | * equal to 48000, or 0 for no audio |
108 | | * audio sample width (bytes/sample): 0 for no audio, or 1 or 2 |
109 | | * audio channels: 0 for no audio, or 1 or 2 |
110 | | */ |
111 | | |
112 | | /* check we have enough data to do all checks, otherwise the |
113 | | 0-padding may cause a wrong recognition */ |
114 | 942k | if (p->buf_size < 20 + HUFFMAN_TABLE_SIZE + 12) |
115 | 931k | return 0; |
116 | | |
117 | | /* check the video width */ |
118 | 11.1k | w = AV_RL32(&p->buf[0]); |
119 | 11.1k | if ((w == 0) || (w > 1024)) |
120 | 9.93k | return 0; |
121 | | |
122 | | /* check the video height */ |
123 | 1.24k | h = AV_RL32(&p->buf[4]); |
124 | 1.24k | if ((h == 0) || (h > 1024)) |
125 | 412 | return 0; |
126 | | |
127 | | /* check the audio sample rate */ |
128 | 831 | sample_rate = AV_RL32(&p->buf[8]); |
129 | 831 | if (sample_rate && (sample_rate < 8000 || sample_rate > 48000)) |
130 | 213 | return 0; |
131 | | |
132 | | /* check the audio bytes/sample */ |
133 | 618 | number = AV_RL32(&p->buf[12]); |
134 | 618 | if (number > 2 || sample_rate && !number) |
135 | 168 | return 0; |
136 | | |
137 | | /* check the audio channels */ |
138 | 450 | number = AV_RL32(&p->buf[16]); |
139 | 450 | if (number > 2 || sample_rate && !number) |
140 | 130 | return 0; |
141 | | |
142 | 320 | i = 20 + HUFFMAN_TABLE_SIZE; |
143 | 320 | if (AV_RL32(&p->buf[i]) == 1) |
144 | 82 | i += 768; |
145 | | |
146 | 320 | if (i+12 > p->buf_size || AV_RL32(&p->buf[i+8]) != w*h) |
147 | 305 | return 1; |
148 | | |
149 | | /* return half certainty since this check is a bit sketchy */ |
150 | 15 | return AVPROBE_SCORE_EXTENSION; |
151 | 320 | } |
152 | | |
153 | | static int idcin_read_header(AVFormatContext *s) |
154 | 1.97k | { |
155 | 1.97k | AVIOContext *pb = s->pb; |
156 | 1.97k | IdcinDemuxContext *idcin = s->priv_data; |
157 | 1.97k | AVStream *st; |
158 | 1.97k | unsigned int width, height; |
159 | 1.97k | unsigned int sample_rate, bytes_per_sample, channels; |
160 | 1.97k | int ret; |
161 | | |
162 | | /* get the 5 header parameters */ |
163 | 1.97k | width = avio_rl32(pb); |
164 | 1.97k | height = avio_rl32(pb); |
165 | 1.97k | sample_rate = avio_rl32(pb); |
166 | 1.97k | bytes_per_sample = avio_rl32(pb); |
167 | 1.97k | channels = avio_rl32(pb); |
168 | | |
169 | 1.97k | if (s->pb->eof_reached) { |
170 | 140 | av_log(s, AV_LOG_ERROR, "incomplete header\n"); |
171 | 140 | return s->pb->error ? s->pb->error : AVERROR_EOF; |
172 | 140 | } |
173 | | |
174 | 1.83k | if (av_image_check_size(width, height, 0, s) < 0) |
175 | 154 | return AVERROR_INVALIDDATA; |
176 | 1.68k | if (sample_rate > 0) { |
177 | 1.35k | if (sample_rate < 14 || sample_rate > INT_MAX) { |
178 | 36 | av_log(s, AV_LOG_ERROR, "invalid sample rate: %u\n", sample_rate); |
179 | 36 | return AVERROR_INVALIDDATA; |
180 | 36 | } |
181 | 1.31k | if (bytes_per_sample < 1 || bytes_per_sample > 2) { |
182 | 52 | av_log(s, AV_LOG_ERROR, "invalid bytes per sample: %u\n", |
183 | 52 | bytes_per_sample); |
184 | 52 | return AVERROR_INVALIDDATA; |
185 | 52 | } |
186 | 1.26k | if (channels < 1 || channels > 2) { |
187 | 43 | av_log(s, AV_LOG_ERROR, "invalid channels: %u\n", channels); |
188 | 43 | return AVERROR_INVALIDDATA; |
189 | 43 | } |
190 | 1.22k | idcin->audio_present = 1; |
191 | 1.22k | } else { |
192 | | /* if sample rate is 0, assume no audio */ |
193 | 330 | idcin->audio_present = 0; |
194 | 330 | } |
195 | | |
196 | 1.55k | st = avformat_new_stream(s, NULL); |
197 | 1.55k | if (!st) |
198 | 0 | return AVERROR(ENOMEM); |
199 | 1.55k | avpriv_set_pts_info(st, 33, 1, IDCIN_FPS); |
200 | 1.55k | st->start_time = 0; |
201 | 1.55k | idcin->video_stream_index = st->index; |
202 | 1.55k | st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; |
203 | 1.55k | st->codecpar->codec_id = AV_CODEC_ID_IDCIN; |
204 | 1.55k | st->codecpar->codec_tag = 0; /* no fourcc */ |
205 | 1.55k | st->codecpar->width = width; |
206 | 1.55k | st->codecpar->height = height; |
207 | | |
208 | | /* load up the Huffman tables into extradata */ |
209 | 1.55k | if ((ret = ff_get_extradata(s, st->codecpar, pb, HUFFMAN_TABLE_SIZE)) < 0) |
210 | 82 | return ret; |
211 | | |
212 | 1.47k | if (idcin->audio_present) { |
213 | 1.17k | idcin->audio_present = 1; |
214 | 1.17k | st = avformat_new_stream(s, NULL); |
215 | 1.17k | if (!st) |
216 | 0 | return AVERROR(ENOMEM); |
217 | 1.17k | avpriv_set_pts_info(st, 63, 1, sample_rate); |
218 | 1.17k | st->start_time = 0; |
219 | 1.17k | idcin->audio_stream_index = st->index; |
220 | 1.17k | st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; |
221 | 1.17k | st->codecpar->codec_tag = 1; |
222 | 1.17k | av_channel_layout_default(&st->codecpar->ch_layout, channels); |
223 | 1.17k | st->codecpar->sample_rate = sample_rate; |
224 | 1.17k | st->codecpar->bits_per_coded_sample = bytes_per_sample * 8; |
225 | 1.17k | st->codecpar->bit_rate = sample_rate * bytes_per_sample * 8 * channels; |
226 | 1.17k | st->codecpar->block_align = idcin->block_align = bytes_per_sample * channels; |
227 | 1.17k | if (bytes_per_sample == 1) |
228 | 553 | st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; |
229 | 618 | else |
230 | 618 | st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; |
231 | | |
232 | 1.17k | if (sample_rate % 14 != 0) { |
233 | 934 | idcin->audio_chunk_size1 = (sample_rate / 14) * |
234 | 934 | bytes_per_sample * channels; |
235 | 934 | idcin->audio_chunk_size2 = (sample_rate / 14 + 1) * |
236 | 934 | bytes_per_sample * channels; |
237 | 934 | } else { |
238 | 237 | idcin->audio_chunk_size1 = idcin->audio_chunk_size2 = |
239 | 237 | (sample_rate / 14) * bytes_per_sample * channels; |
240 | 237 | } |
241 | 1.17k | idcin->current_audio_chunk = 0; |
242 | 1.17k | } |
243 | | |
244 | 1.47k | idcin->next_chunk_is_video = 1; |
245 | 1.47k | idcin->first_pkt_pos = avio_tell(s->pb); |
246 | | |
247 | 1.47k | return 0; |
248 | 1.47k | } |
249 | | |
250 | | static int idcin_read_packet(AVFormatContext *s, |
251 | | AVPacket *pkt) |
252 | 15.5k | { |
253 | 15.5k | int ret; |
254 | 15.5k | unsigned int command; |
255 | 15.5k | unsigned int chunk_size; |
256 | 15.5k | IdcinDemuxContext *idcin = s->priv_data; |
257 | 15.5k | AVIOContext *pb = s->pb; |
258 | 15.5k | int i; |
259 | 15.5k | int palette_scale; |
260 | 15.5k | unsigned char r, g, b; |
261 | 15.5k | unsigned char palette_buffer[768]; |
262 | 15.5k | uint32_t palette[256]; |
263 | | |
264 | 15.5k | if (avio_feof(s->pb)) |
265 | 809 | return s->pb->error ? s->pb->error : AVERROR_EOF; |
266 | | |
267 | 14.7k | if (idcin->next_chunk_is_video) { |
268 | 13.7k | command = avio_rl32(pb); |
269 | 13.7k | if (command == 2) { |
270 | 11 | return AVERROR_INVALIDDATA; |
271 | 13.7k | } else if (command == 1) { |
272 | | /* trigger a palette change */ |
273 | 94 | ret = avio_read(pb, palette_buffer, 768); |
274 | 94 | if (ret < 0) { |
275 | 6 | return ret; |
276 | 88 | } else if (ret != 768) { |
277 | 17 | av_log(s, AV_LOG_ERROR, "incomplete packet\n"); |
278 | 17 | return AVERROR_INVALIDDATA; |
279 | 17 | } |
280 | | /* scale the palette as necessary */ |
281 | 71 | palette_scale = 2; |
282 | 10.5k | for (i = 0; i < 768; i++) |
283 | 10.5k | if (palette_buffer[i] > 63) { |
284 | 60 | palette_scale = 0; |
285 | 60 | break; |
286 | 60 | } |
287 | | |
288 | 18.2k | for (i = 0; i < 256; i++) { |
289 | 18.1k | r = palette_buffer[i * 3 ] << palette_scale; |
290 | 18.1k | g = palette_buffer[i * 3 + 1] << palette_scale; |
291 | 18.1k | b = palette_buffer[i * 3 + 2] << palette_scale; |
292 | 18.1k | palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | (b); |
293 | 18.1k | if (palette_scale == 2) |
294 | 2.81k | palette[i] |= palette[i] >> 6 & 0x30303; |
295 | 18.1k | } |
296 | 71 | } |
297 | | |
298 | 13.7k | if (s->pb->eof_reached) { |
299 | 368 | av_log(s, AV_LOG_ERROR, "incomplete packet\n"); |
300 | 368 | return s->pb->error ? s->pb->error : AVERROR_EOF; |
301 | 368 | } |
302 | 13.3k | chunk_size = avio_rl32(pb); |
303 | 13.3k | if (chunk_size < 4 || chunk_size > INT_MAX - 4) { |
304 | 451 | av_log(s, AV_LOG_ERROR, "invalid chunk size: %u\n", chunk_size); |
305 | 451 | return AVERROR_INVALIDDATA; |
306 | 451 | } |
307 | | /* skip the number of decoded bytes (always equal to width * height) */ |
308 | 12.9k | avio_skip(pb, 4); |
309 | 12.9k | chunk_size -= 4; |
310 | 12.9k | ret= av_get_packet(pb, pkt, chunk_size); |
311 | 12.9k | if (ret < 0) |
312 | 319 | return ret; |
313 | 12.6k | else if (ret != chunk_size) { |
314 | 510 | av_log(s, AV_LOG_ERROR, "incomplete packet\n"); |
315 | 510 | return AVERROR_INVALIDDATA; |
316 | 510 | } |
317 | 12.0k | if (command == 1) { |
318 | 34 | uint8_t *pal; |
319 | | |
320 | 34 | pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, |
321 | 34 | AVPALETTE_SIZE); |
322 | 34 | if (!pal) { |
323 | 0 | return AVERROR(ENOMEM); |
324 | 0 | } |
325 | 34 | memcpy(pal, palette, AVPALETTE_SIZE); |
326 | 34 | pkt->flags |= AV_PKT_FLAG_KEY; |
327 | 34 | } |
328 | 12.0k | pkt->stream_index = idcin->video_stream_index; |
329 | 12.0k | pkt->duration = 1; |
330 | 12.0k | } else { |
331 | | /* send out the audio chunk */ |
332 | 934 | if (idcin->current_audio_chunk) |
333 | 384 | chunk_size = idcin->audio_chunk_size2; |
334 | 550 | else |
335 | 550 | chunk_size = idcin->audio_chunk_size1; |
336 | 934 | ret= av_get_packet(pb, pkt, chunk_size); |
337 | 934 | if (ret < 0) |
338 | 8 | return ret; |
339 | 926 | pkt->stream_index = idcin->audio_stream_index; |
340 | 926 | pkt->duration = chunk_size / idcin->block_align; |
341 | | |
342 | 926 | idcin->current_audio_chunk ^= 1; |
343 | 926 | } |
344 | | |
345 | 13.0k | if (idcin->audio_present) |
346 | 1.86k | idcin->next_chunk_is_video ^= 1; |
347 | | |
348 | 13.0k | return 0; |
349 | 14.7k | } |
350 | | |
351 | | static int idcin_read_seek(AVFormatContext *s, int stream_index, |
352 | | int64_t timestamp, int flags) |
353 | 0 | { |
354 | 0 | IdcinDemuxContext *idcin = s->priv_data; |
355 | |
|
356 | 0 | if (idcin->first_pkt_pos > 0) { |
357 | 0 | int64_t ret = avio_seek(s->pb, idcin->first_pkt_pos, SEEK_SET); |
358 | 0 | if (ret < 0) |
359 | 0 | return ret; |
360 | 0 | avpriv_update_cur_dts(s, s->streams[idcin->video_stream_index], 0); |
361 | 0 | idcin->next_chunk_is_video = 1; |
362 | 0 | idcin->current_audio_chunk = 0; |
363 | 0 | return 0; |
364 | 0 | } |
365 | 0 | return -1; |
366 | 0 | } |
367 | | |
368 | | const FFInputFormat ff_idcin_demuxer = { |
369 | | .p.name = "idcin", |
370 | | .p.long_name = NULL_IF_CONFIG_SMALL("id Cinematic"), |
371 | | .p.flags = AVFMT_NO_BYTE_SEEK, |
372 | | .priv_data_size = sizeof(IdcinDemuxContext), |
373 | | .read_probe = idcin_probe, |
374 | | .read_header = idcin_read_header, |
375 | | .read_packet = idcin_read_packet, |
376 | | .read_seek = idcin_read_seek, |
377 | | }; |