yading@11
|
1 /*
|
yading@11
|
2 * Bink demuxer
|
yading@11
|
3 * Copyright (c) 2008-2010 Peter Ross (pross@xvid.org)
|
yading@11
|
4 * Copyright (c) 2009 Daniel Verkamp (daniel@drv.nu)
|
yading@11
|
5 *
|
yading@11
|
6 * This file is part of FFmpeg.
|
yading@11
|
7 *
|
yading@11
|
8 * FFmpeg is free software; you can redistribute it and/or
|
yading@11
|
9 * modify it under the terms of the GNU Lesser General Public
|
yading@11
|
10 * License as published by the Free Software Foundation; either
|
yading@11
|
11 * version 2.1 of the License, or (at your option) any later version.
|
yading@11
|
12 *
|
yading@11
|
13 * FFmpeg is distributed in the hope that it will be useful,
|
yading@11
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@11
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@11
|
16 * Lesser General Public License for more details.
|
yading@11
|
17 *
|
yading@11
|
18 * You should have received a copy of the GNU Lesser General Public
|
yading@11
|
19 * License along with FFmpeg; if not, write to the Free Software
|
yading@11
|
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@11
|
21 */
|
yading@11
|
22
|
yading@11
|
23 /**
|
yading@11
|
24 * @file
|
yading@11
|
25 * Bink demuxer
|
yading@11
|
26 *
|
yading@11
|
27 * Technical details here:
|
yading@11
|
28 * http://wiki.multimedia.cx/index.php?title=Bink_Container
|
yading@11
|
29 */
|
yading@11
|
30
|
yading@11
|
31 #include "libavutil/channel_layout.h"
|
yading@11
|
32 #include "libavutil/intreadwrite.h"
|
yading@11
|
33 #include "avformat.h"
|
yading@11
|
34 #include "internal.h"
|
yading@11
|
35
|
yading@11
|
36 enum BinkAudFlags {
|
yading@11
|
37 BINK_AUD_16BITS = 0x4000, ///< prefer 16-bit output
|
yading@11
|
38 BINK_AUD_STEREO = 0x2000,
|
yading@11
|
39 BINK_AUD_USEDCT = 0x1000,
|
yading@11
|
40 };
|
yading@11
|
41
|
yading@11
|
42 #define BINK_EXTRADATA_SIZE 1
|
yading@11
|
43 #define BINK_MAX_AUDIO_TRACKS 256
|
yading@11
|
44 #define BINK_MAX_WIDTH 7680
|
yading@11
|
45 #define BINK_MAX_HEIGHT 4800
|
yading@11
|
46
|
yading@11
|
47 typedef struct {
|
yading@11
|
48 uint32_t file_size;
|
yading@11
|
49
|
yading@11
|
50 uint32_t num_audio_tracks;
|
yading@11
|
51 int current_track; ///< audio track to return in next packet
|
yading@11
|
52 int64_t video_pts;
|
yading@11
|
53 int64_t audio_pts[BINK_MAX_AUDIO_TRACKS];
|
yading@11
|
54
|
yading@11
|
55 uint32_t remain_packet_size;
|
yading@11
|
56 } BinkDemuxContext;
|
yading@11
|
57
|
yading@11
|
58 static int probe(AVProbeData *p)
|
yading@11
|
59 {
|
yading@11
|
60 const uint8_t *b = p->buf;
|
yading@11
|
61
|
yading@11
|
62 if ( b[0] == 'B' && b[1] == 'I' && b[2] == 'K' &&
|
yading@11
|
63 (b[3] == 'b' || b[3] == 'f' || b[3] == 'g' || b[3] == 'h' || b[3] == 'i') &&
|
yading@11
|
64 AV_RL32(b+8) > 0 && // num_frames
|
yading@11
|
65 AV_RL32(b+20) > 0 && AV_RL32(b+20) <= BINK_MAX_WIDTH &&
|
yading@11
|
66 AV_RL32(b+24) > 0 && AV_RL32(b+24) <= BINK_MAX_HEIGHT &&
|
yading@11
|
67 AV_RL32(b+28) > 0 && AV_RL32(b+32) > 0) // fps num,den
|
yading@11
|
68 return AVPROBE_SCORE_MAX;
|
yading@11
|
69 return 0;
|
yading@11
|
70 }
|
yading@11
|
71
|
yading@11
|
72 static int read_header(AVFormatContext *s)
|
yading@11
|
73 {
|
yading@11
|
74 BinkDemuxContext *bink = s->priv_data;
|
yading@11
|
75 AVIOContext *pb = s->pb;
|
yading@11
|
76 uint32_t fps_num, fps_den;
|
yading@11
|
77 AVStream *vst, *ast;
|
yading@11
|
78 unsigned int i;
|
yading@11
|
79 uint32_t pos, next_pos;
|
yading@11
|
80 uint16_t flags;
|
yading@11
|
81 int keyframe;
|
yading@11
|
82
|
yading@11
|
83 vst = avformat_new_stream(s, NULL);
|
yading@11
|
84 if (!vst)
|
yading@11
|
85 return AVERROR(ENOMEM);
|
yading@11
|
86
|
yading@11
|
87 vst->codec->codec_tag = avio_rl32(pb);
|
yading@11
|
88
|
yading@11
|
89 bink->file_size = avio_rl32(pb) + 8;
|
yading@11
|
90 vst->duration = avio_rl32(pb);
|
yading@11
|
91
|
yading@11
|
92 if (vst->duration > 1000000) {
|
yading@11
|
93 av_log(s, AV_LOG_ERROR, "invalid header: more than 1000000 frames\n");
|
yading@11
|
94 return AVERROR(EIO);
|
yading@11
|
95 }
|
yading@11
|
96
|
yading@11
|
97 if (avio_rl32(pb) > bink->file_size) {
|
yading@11
|
98 av_log(s, AV_LOG_ERROR,
|
yading@11
|
99 "invalid header: largest frame size greater than file size\n");
|
yading@11
|
100 return AVERROR(EIO);
|
yading@11
|
101 }
|
yading@11
|
102
|
yading@11
|
103 avio_skip(pb, 4);
|
yading@11
|
104
|
yading@11
|
105 vst->codec->width = avio_rl32(pb);
|
yading@11
|
106 vst->codec->height = avio_rl32(pb);
|
yading@11
|
107
|
yading@11
|
108 fps_num = avio_rl32(pb);
|
yading@11
|
109 fps_den = avio_rl32(pb);
|
yading@11
|
110 if (fps_num == 0 || fps_den == 0) {
|
yading@11
|
111 av_log(s, AV_LOG_ERROR, "invalid header: invalid fps (%d/%d)\n", fps_num, fps_den);
|
yading@11
|
112 return AVERROR(EIO);
|
yading@11
|
113 }
|
yading@11
|
114 avpriv_set_pts_info(vst, 64, fps_den, fps_num);
|
yading@11
|
115 vst->avg_frame_rate = av_inv_q(vst->time_base);
|
yading@11
|
116
|
yading@11
|
117 vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
yading@11
|
118 vst->codec->codec_id = AV_CODEC_ID_BINKVIDEO;
|
yading@11
|
119 vst->codec->extradata = av_mallocz(4 + FF_INPUT_BUFFER_PADDING_SIZE);
|
yading@11
|
120 if (!vst->codec->extradata)
|
yading@11
|
121 return AVERROR(ENOMEM);
|
yading@11
|
122 vst->codec->extradata_size = 4;
|
yading@11
|
123 avio_read(pb, vst->codec->extradata, 4);
|
yading@11
|
124
|
yading@11
|
125 bink->num_audio_tracks = avio_rl32(pb);
|
yading@11
|
126
|
yading@11
|
127 if (bink->num_audio_tracks > BINK_MAX_AUDIO_TRACKS) {
|
yading@11
|
128 av_log(s, AV_LOG_ERROR,
|
yading@11
|
129 "invalid header: more than "AV_STRINGIFY(BINK_MAX_AUDIO_TRACKS)" audio tracks (%d)\n",
|
yading@11
|
130 bink->num_audio_tracks);
|
yading@11
|
131 return AVERROR(EIO);
|
yading@11
|
132 }
|
yading@11
|
133
|
yading@11
|
134 if (bink->num_audio_tracks) {
|
yading@11
|
135 avio_skip(pb, 4 * bink->num_audio_tracks);
|
yading@11
|
136
|
yading@11
|
137 for (i = 0; i < bink->num_audio_tracks; i++) {
|
yading@11
|
138 ast = avformat_new_stream(s, NULL);
|
yading@11
|
139 if (!ast)
|
yading@11
|
140 return AVERROR(ENOMEM);
|
yading@11
|
141 ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
yading@11
|
142 ast->codec->codec_tag = 0;
|
yading@11
|
143 ast->codec->sample_rate = avio_rl16(pb);
|
yading@11
|
144 avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
|
yading@11
|
145 flags = avio_rl16(pb);
|
yading@11
|
146 ast->codec->codec_id = flags & BINK_AUD_USEDCT ?
|
yading@11
|
147 AV_CODEC_ID_BINKAUDIO_DCT : AV_CODEC_ID_BINKAUDIO_RDFT;
|
yading@11
|
148 if (flags & BINK_AUD_STEREO) {
|
yading@11
|
149 ast->codec->channels = 2;
|
yading@11
|
150 ast->codec->channel_layout = AV_CH_LAYOUT_STEREO;
|
yading@11
|
151 } else {
|
yading@11
|
152 ast->codec->channels = 1;
|
yading@11
|
153 ast->codec->channel_layout = AV_CH_LAYOUT_MONO;
|
yading@11
|
154 }
|
yading@11
|
155 ast->codec->extradata = av_mallocz(4 + FF_INPUT_BUFFER_PADDING_SIZE);
|
yading@11
|
156 if (!ast->codec->extradata)
|
yading@11
|
157 return AVERROR(ENOMEM);
|
yading@11
|
158 ast->codec->extradata_size = 4;
|
yading@11
|
159 AV_WL32(ast->codec->extradata, vst->codec->codec_tag);
|
yading@11
|
160 }
|
yading@11
|
161
|
yading@11
|
162 for (i = 0; i < bink->num_audio_tracks; i++)
|
yading@11
|
163 s->streams[i + 1]->id = avio_rl32(pb);
|
yading@11
|
164 }
|
yading@11
|
165
|
yading@11
|
166 /* frame index table */
|
yading@11
|
167 next_pos = avio_rl32(pb);
|
yading@11
|
168 for (i = 0; i < vst->duration; i++) {
|
yading@11
|
169 pos = next_pos;
|
yading@11
|
170 if (i == vst->duration - 1) {
|
yading@11
|
171 next_pos = bink->file_size;
|
yading@11
|
172 keyframe = 0;
|
yading@11
|
173 } else {
|
yading@11
|
174 next_pos = avio_rl32(pb);
|
yading@11
|
175 keyframe = pos & 1;
|
yading@11
|
176 }
|
yading@11
|
177 pos &= ~1;
|
yading@11
|
178 next_pos &= ~1;
|
yading@11
|
179
|
yading@11
|
180 if (next_pos <= pos) {
|
yading@11
|
181 av_log(s, AV_LOG_ERROR, "invalid frame index table\n");
|
yading@11
|
182 return AVERROR(EIO);
|
yading@11
|
183 }
|
yading@11
|
184 av_add_index_entry(vst, pos, i, next_pos - pos, 0,
|
yading@11
|
185 keyframe ? AVINDEX_KEYFRAME : 0);
|
yading@11
|
186 }
|
yading@11
|
187
|
yading@11
|
188 avio_skip(pb, 4);
|
yading@11
|
189
|
yading@11
|
190 bink->current_track = -1;
|
yading@11
|
191 return 0;
|
yading@11
|
192 }
|
yading@11
|
193
|
yading@11
|
194 static int read_packet(AVFormatContext *s, AVPacket *pkt)
|
yading@11
|
195 {
|
yading@11
|
196 BinkDemuxContext *bink = s->priv_data;
|
yading@11
|
197 AVIOContext *pb = s->pb;
|
yading@11
|
198 int ret;
|
yading@11
|
199
|
yading@11
|
200 if (bink->current_track < 0) {
|
yading@11
|
201 int index_entry;
|
yading@11
|
202 AVStream *st = s->streams[0]; // stream 0 is video stream with index
|
yading@11
|
203
|
yading@11
|
204 if (bink->video_pts >= st->duration)
|
yading@11
|
205 return AVERROR_EOF;
|
yading@11
|
206
|
yading@11
|
207 index_entry = av_index_search_timestamp(st, bink->video_pts,
|
yading@11
|
208 AVSEEK_FLAG_ANY);
|
yading@11
|
209 if (index_entry < 0) {
|
yading@11
|
210 av_log(s, AV_LOG_ERROR,
|
yading@11
|
211 "could not find index entry for frame %"PRId64"\n",
|
yading@11
|
212 bink->video_pts);
|
yading@11
|
213 return AVERROR(EIO);
|
yading@11
|
214 }
|
yading@11
|
215
|
yading@11
|
216 bink->remain_packet_size = st->index_entries[index_entry].size;
|
yading@11
|
217 bink->current_track = 0;
|
yading@11
|
218 }
|
yading@11
|
219
|
yading@11
|
220 while (bink->current_track < bink->num_audio_tracks) {
|
yading@11
|
221 uint32_t audio_size = avio_rl32(pb);
|
yading@11
|
222 if (audio_size > bink->remain_packet_size - 4) {
|
yading@11
|
223 av_log(s, AV_LOG_ERROR,
|
yading@11
|
224 "frame %"PRId64": audio size in header (%u) > size of packet left (%u)\n",
|
yading@11
|
225 bink->video_pts, audio_size, bink->remain_packet_size);
|
yading@11
|
226 return AVERROR(EIO);
|
yading@11
|
227 }
|
yading@11
|
228 bink->remain_packet_size -= 4 + audio_size;
|
yading@11
|
229 bink->current_track++;
|
yading@11
|
230 if (audio_size >= 4) {
|
yading@11
|
231 /* get one audio packet per track */
|
yading@11
|
232 if ((ret = av_get_packet(pb, pkt, audio_size)) < 0)
|
yading@11
|
233 return ret;
|
yading@11
|
234 pkt->stream_index = bink->current_track;
|
yading@11
|
235 pkt->pts = bink->audio_pts[bink->current_track - 1];
|
yading@11
|
236
|
yading@11
|
237 /* Each audio packet reports the number of decompressed samples
|
yading@11
|
238 (in bytes). We use this value to calcuate the audio PTS */
|
yading@11
|
239 if (pkt->size >= 4)
|
yading@11
|
240 bink->audio_pts[bink->current_track -1] +=
|
yading@11
|
241 AV_RL32(pkt->data) / (2 * s->streams[bink->current_track]->codec->channels);
|
yading@11
|
242 return 0;
|
yading@11
|
243 } else {
|
yading@11
|
244 avio_skip(pb, audio_size);
|
yading@11
|
245 }
|
yading@11
|
246 }
|
yading@11
|
247
|
yading@11
|
248 /* get video packet */
|
yading@11
|
249 if ((ret = av_get_packet(pb, pkt, bink->remain_packet_size)) < 0)
|
yading@11
|
250 return ret;
|
yading@11
|
251 pkt->stream_index = 0;
|
yading@11
|
252 pkt->pts = bink->video_pts++;
|
yading@11
|
253 pkt->flags |= AV_PKT_FLAG_KEY;
|
yading@11
|
254
|
yading@11
|
255 /* -1 instructs the next call to read_packet() to read the next frame */
|
yading@11
|
256 bink->current_track = -1;
|
yading@11
|
257
|
yading@11
|
258 return 0;
|
yading@11
|
259 }
|
yading@11
|
260
|
yading@11
|
261 static int read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
|
yading@11
|
262 {
|
yading@11
|
263 BinkDemuxContext *bink = s->priv_data;
|
yading@11
|
264 AVStream *vst = s->streams[0];
|
yading@11
|
265
|
yading@11
|
266 if (!s->pb->seekable)
|
yading@11
|
267 return -1;
|
yading@11
|
268
|
yading@11
|
269 /* seek to the first frame */
|
yading@11
|
270 if (avio_seek(s->pb, vst->index_entries[0].pos, SEEK_SET) < 0)
|
yading@11
|
271 return -1;
|
yading@11
|
272
|
yading@11
|
273 bink->video_pts = 0;
|
yading@11
|
274 memset(bink->audio_pts, 0, sizeof(bink->audio_pts));
|
yading@11
|
275 bink->current_track = -1;
|
yading@11
|
276 return 0;
|
yading@11
|
277 }
|
yading@11
|
278
|
yading@11
|
279 AVInputFormat ff_bink_demuxer = {
|
yading@11
|
280 .name = "bink",
|
yading@11
|
281 .long_name = NULL_IF_CONFIG_SMALL("Bink"),
|
yading@11
|
282 .priv_data_size = sizeof(BinkDemuxContext),
|
yading@11
|
283 .read_probe = probe,
|
yading@11
|
284 .read_header = read_header,
|
yading@11
|
285 .read_packet = read_packet,
|
yading@11
|
286 .read_seek = read_seek,
|
yading@11
|
287 };
|