/src/ffmpeg/libavformat/bink.c
Line | Count | Source |
1 | | /* |
2 | | * Bink demuxer |
3 | | * Copyright (c) 2008-2010 Peter Ross (pross@xvid.org) |
4 | | * Copyright (c) 2009 Daniel Verkamp (daniel@drv.nu) |
5 | | * |
6 | | * This file is part of FFmpeg. |
7 | | * |
8 | | * FFmpeg is free software; you can redistribute it and/or |
9 | | * modify it under the terms of the GNU Lesser General Public |
10 | | * License as published by the Free Software Foundation; either |
11 | | * version 2.1 of the License, or (at your option) any later version. |
12 | | * |
13 | | * FFmpeg is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | | * Lesser General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public |
19 | | * License along with FFmpeg; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | | */ |
22 | | |
23 | | /** |
24 | | * @file |
25 | | * Bink demuxer |
26 | | * |
27 | | * Technical details here: |
28 | | * http://wiki.multimedia.cx/index.php?title=Bink_Container |
29 | | */ |
30 | | |
31 | | #include <inttypes.h> |
32 | | |
33 | | #include "libavutil/channel_layout.h" |
34 | | #include "libavutil/intreadwrite.h" |
35 | | #include "avformat.h" |
36 | | #include "demux.h" |
37 | | #include "internal.h" |
38 | | |
39 | | enum BinkAudFlags { |
40 | | BINK_AUD_16BITS = 0x4000, ///< prefer 16-bit output |
41 | | BINK_AUD_STEREO = 0x2000, |
42 | | BINK_AUD_USEDCT = 0x1000, |
43 | | }; |
44 | | |
45 | | #define BINK_EXTRADATA_SIZE 1 |
46 | 2.13k | #define BINK_MAX_AUDIO_TRACKS 256 |
47 | 982k | #define BINK_MAX_WIDTH 7680 |
48 | 980k | #define BINK_MAX_HEIGHT 4800 |
49 | 990k | #define SMUSH_BLOCK_SIZE 512 |
50 | | |
51 | | typedef struct BinkDemuxContext { |
52 | | uint32_t file_size; |
53 | | |
54 | | uint32_t num_audio_tracks; |
55 | | int current_track; ///< audio track to return in next packet |
56 | | int64_t video_pts; |
57 | | int64_t audio_pts[BINK_MAX_AUDIO_TRACKS]; |
58 | | |
59 | | uint32_t remain_packet_size; |
60 | | int flags; |
61 | | int smush_size; |
62 | | } BinkDemuxContext; |
63 | | |
64 | | static int probe(const AVProbeData *p) |
65 | 964k | { |
66 | 964k | const uint8_t *b = p->buf; |
67 | 964k | int smush = AV_RN32(p->buf) == AV_RN32("SMUS"); |
68 | | |
69 | 979k | do { |
70 | 979k | if (((b[0] == 'B' && b[1] == 'I' && b[2] == 'K' && /* Bink 1 */ |
71 | 2.02k | (b[3] == 'b' || b[3] == 'f' || b[3] == 'g' || b[3] == 'h' || b[3] == 'i' || |
72 | 490 | b[3] == 'k')) || |
73 | 977k | (b[0] == 'K' && b[1] == 'B' && b[2] == '2' && /* Bink 2 */ |
74 | 2.08k | (b[3] == 'a' || b[3] == 'd' || b[3] == 'f' || b[3] == 'g' || b[3] == 'h' || |
75 | 946 | b[3] == 'i' || b[3] == 'j' || b[3] == 'k'))) && |
76 | 3.66k | AV_RL32(b+8) > 0 && // num_frames |
77 | 3.32k | AV_RL32(b+20) > 0 && AV_RL32(b+20) <= BINK_MAX_WIDTH && |
78 | 1.20k | AV_RL32(b+24) > 0 && AV_RL32(b+24) <= BINK_MAX_HEIGHT && |
79 | 581 | AV_RL32(b+28) > 0 && AV_RL32(b+32) > 0) // fps num,den |
80 | 303 | return AVPROBE_SCORE_MAX; |
81 | 978k | b += SMUSH_BLOCK_SIZE; |
82 | 978k | } while (smush && b < p->buf + p->buf_size - 32); |
83 | 964k | return 0; |
84 | 964k | } |
85 | | |
86 | | static int read_header(AVFormatContext *s) |
87 | 2.78k | { |
88 | 2.78k | BinkDemuxContext *bink = s->priv_data; |
89 | 2.78k | AVIOContext *pb = s->pb; |
90 | 2.78k | uint32_t fps_num, fps_den; |
91 | 2.78k | AVStream *const vst = avformat_new_stream(s, NULL); |
92 | 2.78k | FFStream *const vsti = ffstream(vst); |
93 | 2.78k | unsigned int i; |
94 | 2.78k | uint32_t pos, next_pos; |
95 | 2.78k | uint16_t flags; |
96 | 2.78k | int next_keyframe = 1; |
97 | 2.78k | int keyframe; |
98 | 2.78k | int ret; |
99 | 2.78k | uint32_t signature; |
100 | 2.78k | uint8_t revision; |
101 | | |
102 | 2.78k | if (!vst) |
103 | 0 | return AVERROR(ENOMEM); |
104 | | |
105 | 2.78k | vst->codecpar->codec_tag = avio_rl32(pb); |
106 | 2.78k | if (vst->codecpar->codec_tag == AV_RL32("SMUS")) { |
107 | 5.69k | do { |
108 | 5.69k | bink->smush_size += SMUSH_BLOCK_SIZE; |
109 | 5.69k | avio_skip(pb, SMUSH_BLOCK_SIZE - 4); |
110 | 5.69k | vst->codecpar->codec_tag = avio_rl32(pb); |
111 | 5.69k | } while (!avio_feof(pb) && (vst->codecpar->codec_tag & 0xFFFFFF) != AV_RL32("BIK")); |
112 | 92 | if (avio_feof(pb)) { |
113 | 83 | av_log(s, AV_LOG_ERROR, "invalid SMUSH header: BIK not found\n"); |
114 | 83 | return AVERROR_INVALIDDATA; |
115 | 83 | } |
116 | 92 | } |
117 | | |
118 | 2.69k | bink->file_size = avio_rl32(pb) + 8; |
119 | 2.69k | vst->duration = avio_rl32(pb); |
120 | | |
121 | 2.69k | if (vst->duration > 1000000) { |
122 | 43 | av_log(s, AV_LOG_ERROR, "invalid header: more than 1000000 frames\n"); |
123 | 43 | return AVERROR(EIO); |
124 | 43 | } |
125 | | |
126 | 2.65k | if (avio_rl32(pb) > bink->file_size) { |
127 | 6 | av_log(s, AV_LOG_ERROR, |
128 | 6 | "invalid header: largest frame size greater than file size\n"); |
129 | 6 | return AVERROR(EIO); |
130 | 6 | } |
131 | | |
132 | 2.65k | avio_skip(pb, 4); |
133 | | |
134 | 2.65k | vst->codecpar->width = avio_rl32(pb); |
135 | 2.65k | vst->codecpar->height = avio_rl32(pb); |
136 | | |
137 | 2.65k | fps_num = avio_rl32(pb); |
138 | 2.65k | fps_den = avio_rl32(pb); |
139 | 2.65k | if (fps_num == 0 || fps_den == 0) { |
140 | 306 | av_log(s, AV_LOG_ERROR, |
141 | 306 | "invalid header: invalid fps (%"PRIu32"/%"PRIu32")\n", |
142 | 306 | fps_num, fps_den); |
143 | 306 | return AVERROR(EIO); |
144 | 306 | } |
145 | 2.34k | avpriv_set_pts_info(vst, 64, fps_den, fps_num); |
146 | 2.34k | vst->avg_frame_rate = av_inv_q(vst->time_base); |
147 | | |
148 | 2.34k | vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; |
149 | 2.34k | vst->codecpar->codec_id = AV_CODEC_ID_BINKVIDEO; |
150 | | |
151 | 2.34k | if ((vst->codecpar->codec_tag & 0xFFFFFF) == MKTAG('K', 'B', '2', 0)) { |
152 | 71 | av_log(s, AV_LOG_WARNING, "Bink 2 video is not implemented\n"); |
153 | 71 | vst->codecpar->codec_id = AV_CODEC_ID_NONE; |
154 | 71 | } |
155 | | |
156 | 2.34k | if ((ret = ff_get_extradata(s, vst->codecpar, pb, 4)) < 0) |
157 | 210 | return ret; |
158 | | |
159 | 2.13k | bink->num_audio_tracks = avio_rl32(pb); |
160 | | |
161 | 2.13k | if (bink->num_audio_tracks > BINK_MAX_AUDIO_TRACKS) { |
162 | 25 | av_log(s, AV_LOG_ERROR, |
163 | 25 | "invalid header: more than "AV_STRINGIFY(BINK_MAX_AUDIO_TRACKS)" audio tracks (%"PRIu32")\n", |
164 | 25 | bink->num_audio_tracks); |
165 | 25 | return AVERROR(EIO); |
166 | 25 | } |
167 | | |
168 | 2.10k | signature = (vst->codecpar->codec_tag & 0xFFFFFF); |
169 | 2.10k | revision = ((vst->codecpar->codec_tag >> 24) % 0xFF); |
170 | | |
171 | 2.10k | if ((signature == AV_RL32("BIK") && (revision == 'k')) || |
172 | 2.07k | (signature == AV_RL32("KB2") && (revision == 'i' || revision == 'j' || revision == 'k'))) |
173 | 38 | avio_skip(pb, 4); /* unknown new field */ |
174 | | |
175 | 2.10k | if (bink->num_audio_tracks) { |
176 | 915 | avio_skip(pb, 4 * bink->num_audio_tracks); /* max decoded size */ |
177 | | |
178 | 71.4k | for (i = 0; i < bink->num_audio_tracks; i++) { |
179 | 70.5k | AVStream *const ast = avformat_new_stream(s, NULL); |
180 | 70.5k | if (!ast) |
181 | 0 | return AVERROR(ENOMEM); |
182 | 70.5k | ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; |
183 | 70.5k | ast->codecpar->codec_tag = 0; |
184 | 70.5k | ast->codecpar->sample_rate = avio_rl16(pb); |
185 | 70.5k | avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate); |
186 | 70.5k | flags = avio_rl16(pb); |
187 | 70.5k | ast->codecpar->codec_id = flags & BINK_AUD_USEDCT ? |
188 | 65.3k | AV_CODEC_ID_BINKAUDIO_DCT : AV_CODEC_ID_BINKAUDIO_RDFT; |
189 | 70.5k | if (flags & BINK_AUD_STEREO) { |
190 | 5.33k | ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; |
191 | 65.2k | } else { |
192 | 65.2k | ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; |
193 | 65.2k | } |
194 | 70.5k | if ((ret = ff_alloc_extradata(ast->codecpar, 4)) < 0) |
195 | 0 | return ret; |
196 | 70.5k | AV_WL32(ast->codecpar->extradata, vst->codecpar->codec_tag); |
197 | 70.5k | } |
198 | | |
199 | 71.4k | for (i = 0; i < bink->num_audio_tracks; i++) |
200 | 70.5k | s->streams[i + 1]->id = avio_rl32(pb); |
201 | 915 | } |
202 | | |
203 | | /* frame index table */ |
204 | 2.10k | next_pos = avio_rl32(pb); |
205 | 12.2k | for (i = 0; i < vst->duration; i++) { |
206 | 10.2k | pos = next_pos; |
207 | 10.2k | keyframe = next_keyframe; |
208 | 10.2k | if (i == vst->duration - 1) { |
209 | 1.96k | next_pos = bink->file_size; |
210 | 1.96k | next_keyframe = 0; |
211 | 8.31k | } else { |
212 | 8.31k | next_pos = avio_rl32(pb); |
213 | 8.31k | next_keyframe = next_pos & 1; |
214 | 8.31k | } |
215 | 10.2k | pos &= ~1; |
216 | 10.2k | next_pos &= ~1; |
217 | | |
218 | 10.2k | if (next_pos <= pos) { |
219 | 87 | av_log(s, AV_LOG_ERROR, "invalid frame index table\n"); |
220 | 87 | return AVERROR(EIO); |
221 | 87 | } |
222 | 10.1k | if ((ret = av_add_index_entry(vst, pos, i, next_pos - pos, 0, |
223 | 10.1k | keyframe ? AVINDEX_KEYFRAME : 0)) < 0) |
224 | 38 | return ret; |
225 | 10.1k | } |
226 | | |
227 | 1.98k | if (vsti->index_entries) |
228 | 1.94k | avio_seek(pb, vsti->index_entries[0].pos + bink->smush_size, SEEK_SET); |
229 | 41 | else |
230 | 41 | avio_skip(pb, 4); |
231 | | |
232 | 1.98k | bink->current_track = -1; |
233 | 1.98k | return 0; |
234 | 2.10k | } |
235 | | |
236 | | static int read_packet(AVFormatContext *s, AVPacket *pkt) |
237 | 14.0k | { |
238 | 14.0k | BinkDemuxContext *bink = s->priv_data; |
239 | 14.0k | AVIOContext *pb = s->pb; |
240 | 14.0k | int ret; |
241 | | |
242 | 14.0k | if (bink->current_track < 0) { |
243 | 6.87k | int index_entry; |
244 | 6.87k | AVStream *st = s->streams[0]; // stream 0 is video stream with index |
245 | 6.87k | FFStream *const sti = ffstream(st); |
246 | | |
247 | 6.87k | if (bink->video_pts >= st->duration) |
248 | 1.41k | return AVERROR_EOF; |
249 | | |
250 | 5.46k | index_entry = av_index_search_timestamp(st, bink->video_pts, |
251 | 5.46k | AVSEEK_FLAG_ANY); |
252 | 5.46k | if (index_entry < 0) { |
253 | 5 | av_log(s, AV_LOG_ERROR, |
254 | 5 | "could not find index entry for frame %"PRId64"\n", |
255 | 5 | bink->video_pts); |
256 | 5 | return AVERROR(EIO); |
257 | 5 | } |
258 | | |
259 | 5.45k | bink->remain_packet_size = sti->index_entries[index_entry].size; |
260 | 5.45k | bink->flags = sti->index_entries[index_entry].flags; |
261 | 5.45k | bink->current_track = 0; |
262 | 5.45k | } |
263 | | |
264 | 65.4k | while (bink->current_track < bink->num_audio_tracks) { |
265 | 59.3k | uint32_t audio_size = avio_rl32(pb); |
266 | 59.3k | if (audio_size > bink->remain_packet_size - 4) { |
267 | 321 | av_log(s, AV_LOG_ERROR, |
268 | 321 | "frame %"PRId64": audio size in header (%"PRIu32") > size of packet left (%"PRIu32")\n", |
269 | 321 | bink->video_pts, audio_size, bink->remain_packet_size); |
270 | 321 | return AVERROR(EIO); |
271 | 321 | } |
272 | 58.9k | bink->remain_packet_size -= 4 + audio_size; |
273 | 58.9k | bink->current_track++; |
274 | 58.9k | if (audio_size >= 4) { |
275 | | /* get one audio packet per track */ |
276 | 6.18k | if ((ret = av_get_packet(pb, pkt, audio_size)) < 0) |
277 | 80 | return ret; |
278 | 6.10k | pkt->stream_index = bink->current_track; |
279 | 6.10k | pkt->pts = bink->audio_pts[bink->current_track - 1]; |
280 | | |
281 | | /* Each audio packet reports the number of decompressed samples |
282 | | (in bytes). We use this value to calculate the audio PTS */ |
283 | 6.10k | if (pkt->size >= 4) |
284 | 5.98k | bink->audio_pts[bink->current_track -1] += |
285 | 5.98k | AV_RL32(pkt->data) / (2 * s->streams[bink->current_track]->codecpar->ch_layout.nb_channels); |
286 | 6.10k | return 0; |
287 | 52.8k | } else { |
288 | 52.8k | avio_skip(pb, audio_size); |
289 | 52.8k | } |
290 | 58.9k | } |
291 | | |
292 | | /* get video packet */ |
293 | 6.15k | if ((ret = av_get_packet(pb, pkt, bink->remain_packet_size)) < 0) |
294 | 1.84k | return ret; |
295 | 4.30k | pkt->stream_index = 0; |
296 | 4.30k | pkt->pts = bink->video_pts++; |
297 | 4.30k | if (bink->flags & AVINDEX_KEYFRAME) |
298 | 2.17k | pkt->flags |= AV_PKT_FLAG_KEY; |
299 | | |
300 | | /* -1 instructs the next call to read_packet() to read the next frame */ |
301 | 4.30k | bink->current_track = -1; |
302 | | |
303 | 4.30k | return 0; |
304 | 6.15k | } |
305 | | |
306 | | static int read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) |
307 | 0 | { |
308 | 0 | BinkDemuxContext *bink = s->priv_data; |
309 | 0 | AVStream *vst = s->streams[0]; |
310 | 0 | FFStream *const vsti = ffstream(vst); |
311 | 0 | int64_t ret; |
312 | |
|
313 | 0 | if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) |
314 | 0 | return -1; |
315 | | |
316 | | /* seek to the first frame */ |
317 | 0 | ret = avio_seek(s->pb, vsti->index_entries[0].pos + bink->smush_size, SEEK_SET); |
318 | 0 | if (ret < 0) |
319 | 0 | return ret; |
320 | | |
321 | 0 | bink->video_pts = 0; |
322 | 0 | memset(bink->audio_pts, 0, sizeof(bink->audio_pts)); |
323 | 0 | bink->current_track = -1; |
324 | 0 | return 0; |
325 | 0 | } |
326 | | |
327 | | const FFInputFormat ff_bink_demuxer = { |
328 | | .p.name = "bink", |
329 | | .p.long_name = NULL_IF_CONFIG_SMALL("Bink"), |
330 | | .p.flags = AVFMT_SHOW_IDS, |
331 | | .priv_data_size = sizeof(BinkDemuxContext), |
332 | | .read_probe = probe, |
333 | | .read_header = read_header, |
334 | | .read_packet = read_packet, |
335 | | .read_seek = read_seek, |
336 | | }; |