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 "libavutil/intreadwrite.h" 32#include "avformat.h" 33 34enum BinkAudFlags { 35 BINK_AUD_16BITS = 0x4000, ///< prefer 16-bit output 36 BINK_AUD_STEREO = 0x2000, 37 BINK_AUD_USEDCT = 0x1000, 38}; 39 40#define BINK_EXTRADATA_SIZE 1 41#define BINK_MAX_AUDIO_TRACKS 256 42#define BINK_MAX_WIDTH 7680 43#define BINK_MAX_HEIGHT 4800 44 45typedef struct { 46 uint32_t file_size; 47 48 uint32_t num_audio_tracks; 49 int current_track; ///< audio track to return in next packet 50 int64_t video_pts; 51 int64_t audio_pts[BINK_MAX_AUDIO_TRACKS]; 52 53 uint32_t remain_packet_size; 54} BinkDemuxContext; 55 56static int probe(AVProbeData *p) 57{ 58 const uint8_t *b = p->buf; 59 60 if ( b[0] == 'B' && b[1] == 'I' && b[2] == 'K' && 61 (b[3] == 'b' || b[3] == 'f' || b[3] == 'g' || b[3] == 'h' || b[3] == 'i') && 62 AV_RL32(b+8) > 0 && // num_frames 63 AV_RL32(b+20) > 0 && AV_RL32(b+20) <= BINK_MAX_WIDTH && 64 AV_RL32(b+24) > 0 && AV_RL32(b+24) <= BINK_MAX_HEIGHT && 65 AV_RL32(b+28) > 0 && AV_RL32(b+32) > 0) // fps num,den 66 return AVPROBE_SCORE_MAX; 67 return 0; 68} 69 70static int read_header(AVFormatContext *s, AVFormatParameters *ap) 71{ 72 BinkDemuxContext *bink = s->priv_data; 73 ByteIOContext *pb = s->pb; 74 uint32_t fps_num, fps_den; 75 AVStream *vst, *ast; 76 unsigned int i; 77 uint32_t pos, next_pos; 78 uint16_t flags; 79 int keyframe; 80 81 vst = av_new_stream(s, 0); 82 if (!vst) 83 return AVERROR(ENOMEM); 84 85 vst->codec->codec_tag = get_le32(pb); 86 87 bink->file_size = get_le32(pb) + 8; 88 vst->duration = get_le32(pb); 89 90 if (vst->duration > 1000000) { 91 av_log(s, AV_LOG_ERROR, "invalid header: more than 1000000 frames\n"); 92 return AVERROR(EIO); 93 } 94 95 if (get_le32(pb) > bink->file_size) { 96 av_log(s, AV_LOG_ERROR, 97 "invalid header: largest frame size greater than file size\n"); 98 return AVERROR(EIO); 99 } 100 101 url_fskip(pb, 4); 102 103 vst->codec->width = get_le32(pb); 104 vst->codec->height = get_le32(pb); 105 106 fps_num = get_le32(pb); 107 fps_den = get_le32(pb); 108 if (fps_num == 0 || fps_den == 0) { 109 av_log(s, AV_LOG_ERROR, "invalid header: invalid fps (%d/%d)\n", fps_num, fps_den); 110 return AVERROR(EIO); 111 } 112 av_set_pts_info(vst, 64, fps_den, fps_num); 113 114 vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; 115 vst->codec->codec_id = CODEC_ID_BINKVIDEO; 116 vst->codec->extradata = av_mallocz(4 + FF_INPUT_BUFFER_PADDING_SIZE); 117 vst->codec->extradata_size = 4; 118 get_buffer(pb, vst->codec->extradata, 4); 119 120 bink->num_audio_tracks = get_le32(pb); 121 122 if (bink->num_audio_tracks > BINK_MAX_AUDIO_TRACKS) { 123 av_log(s, AV_LOG_ERROR, 124 "invalid header: more than "AV_STRINGIFY(BINK_MAX_AUDIO_TRACKS)" audio tracks (%d)\n", 125 bink->num_audio_tracks); 126 return AVERROR(EIO); 127 } 128 129 if (bink->num_audio_tracks) { 130 url_fskip(pb, 4 * bink->num_audio_tracks); 131 132 for (i = 0; i < bink->num_audio_tracks; i++) { 133 ast = av_new_stream(s, 1); 134 if (!ast) 135 return AVERROR(ENOMEM); 136 ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; 137 ast->codec->codec_tag = 0; 138 ast->codec->sample_rate = get_le16(pb); 139 av_set_pts_info(ast, 64, 1, ast->codec->sample_rate); 140 flags = get_le16(pb); 141 ast->codec->codec_id = flags & BINK_AUD_USEDCT ? 142 CODEC_ID_BINKAUDIO_DCT : CODEC_ID_BINKAUDIO_RDFT; 143 ast->codec->channels = flags & BINK_AUD_STEREO ? 2 : 1; 144 } 145 146 url_fskip(pb, 4 * bink->num_audio_tracks); 147 } 148 149 /* frame index table */ 150 next_pos = get_le32(pb); 151 for (i = 0; i < vst->duration; i++) { 152 pos = next_pos; 153 if (i == vst->duration - 1) { 154 next_pos = bink->file_size; 155 keyframe = 0; 156 } else { 157 next_pos = get_le32(pb); 158 keyframe = pos & 1; 159 } 160 pos &= ~1; 161 next_pos &= ~1; 162 163 if (next_pos <= pos) { 164 av_log(s, AV_LOG_ERROR, "invalid frame index table\n"); 165 return AVERROR(EIO); 166 } 167 av_add_index_entry(vst, pos, i, next_pos - pos, 0, 168 keyframe ? AVINDEX_KEYFRAME : 0); 169 } 170 171 url_fskip(pb, 4); 172 173 bink->current_track = -1; 174 return 0; 175} 176 177static int read_packet(AVFormatContext *s, AVPacket *pkt) 178{ 179 BinkDemuxContext *bink = s->priv_data; 180 ByteIOContext *pb = s->pb; 181 int ret; 182 183 if (bink->current_track < 0) { 184 int index_entry; 185 AVStream *st = s->streams[0]; // stream 0 is video stream with index 186 187 if (bink->video_pts >= st->duration) 188 return AVERROR(EIO); 189 190 index_entry = av_index_search_timestamp(st, bink->video_pts, 191 AVSEEK_FLAG_ANY); 192 if (index_entry < 0) { 193 av_log(s, AV_LOG_ERROR, 194 "could not find index entry for frame %"PRId64"\n", 195 bink->video_pts); 196 return AVERROR(EIO); 197 } 198 199 bink->remain_packet_size = st->index_entries[index_entry].size; 200 bink->current_track = 0; 201 } 202 203 while (bink->current_track < bink->num_audio_tracks) { 204 uint32_t audio_size = get_le32(pb); 205 if (audio_size > bink->remain_packet_size - 4) { 206 av_log(s, AV_LOG_ERROR, 207 "frame %"PRId64": audio size in header (%u) > size of packet left (%u)\n", 208 bink->video_pts, audio_size, bink->remain_packet_size); 209 return AVERROR(EIO); 210 } 211 bink->remain_packet_size -= 4 + audio_size; 212 bink->current_track++; 213 if (audio_size >= 4) { 214 /* get one audio packet per track */ 215 if ((ret = av_get_packet(pb, pkt, audio_size)) < 0) 216 return ret; 217 pkt->stream_index = bink->current_track; 218 pkt->pts = bink->audio_pts[bink->current_track - 1]; 219 220 /* Each audio packet reports the number of decompressed samples 221 (in bytes). We use this value to calcuate the audio PTS */ 222 if (pkt->size >= 4) 223 bink->audio_pts[bink->current_track -1] += 224 AV_RL32(pkt->data) / (2 * s->streams[bink->current_track]->codec->channels); 225 return 0; 226 } else { 227 url_fseek(pb, audio_size, SEEK_CUR); 228 } 229 } 230 231 /* get video packet */ 232 if ((ret = av_get_packet(pb, pkt, bink->remain_packet_size)) < 0) 233 return ret; 234 pkt->stream_index = 0; 235 pkt->pts = bink->video_pts++; 236 pkt->flags |= AV_PKT_FLAG_KEY; 237 238 /* -1 instructs the next call to read_packet() to read the next frame */ 239 bink->current_track = -1; 240 241 return 0; 242} 243 244static int read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) 245{ 246 BinkDemuxContext *bink = s->priv_data; 247 AVStream *vst = s->streams[0]; 248 249 if (url_is_streamed(s->pb)) 250 return -1; 251 252 /* seek to the first frame */ 253 url_fseek(s->pb, vst->index_entries[0].pos, SEEK_SET); 254 bink->video_pts = 0; 255 memset(bink->audio_pts, 0, sizeof(bink->audio_pts)); 256 bink->current_track = -1; 257 return 0; 258} 259 260AVInputFormat bink_demuxer = { 261 "bink", 262 NULL_IF_CONFIG_SMALL("Bink"), 263 sizeof(BinkDemuxContext), 264 probe, 265 read_header, 266 read_packet, 267 NULL, 268 read_seek, 269}; 270