| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Bink demuxer | 2 * Bink demuxer |
| 3 * Copyright (c) 2008-2010 Peter Ross (pross@xvid.org) | 3 * Copyright (c) 2008-2010 Peter Ross (pross@xvid.org) |
| 4 * Copyright (c) 2009 Daniel Verkamp (daniel@drv.nu) | 4 * Copyright (c) 2009 Daniel Verkamp (daniel@drv.nu) |
| 5 * | 5 * |
| 6 * This file is part of FFmpeg. | 6 * This file is part of FFmpeg. |
| 7 * | 7 * |
| 8 * FFmpeg is free software; you can redistribute it and/or | 8 * FFmpeg is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Lesser General Public | 9 * modify it under the terms of the GNU Lesser General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 BINK_AUD_USEDCT = 0x1000, | 37 BINK_AUD_USEDCT = 0x1000, |
| 38 }; | 38 }; |
| 39 | 39 |
| 40 #define BINK_EXTRADATA_SIZE 1 | 40 #define BINK_EXTRADATA_SIZE 1 |
| 41 #define BINK_MAX_AUDIO_TRACKS 256 | 41 #define BINK_MAX_AUDIO_TRACKS 256 |
| 42 #define BINK_MAX_WIDTH 7680 | 42 #define BINK_MAX_WIDTH 7680 |
| 43 #define BINK_MAX_HEIGHT 4800 | 43 #define BINK_MAX_HEIGHT 4800 |
| 44 | 44 |
| 45 typedef struct { | 45 typedef struct { |
| 46 uint32_t file_size; | 46 uint32_t file_size; |
| 47 uint32_t total_frames; | |
| 48 | 47 |
| 49 uint32_t num_audio_tracks; | 48 uint32_t num_audio_tracks; |
| 50 int current_track; ///< audio track to return in next packet | 49 int current_track; ///< audio track to return in next packet |
| 51 int64_t video_pts; | 50 int64_t video_pts; |
| 52 int64_t audio_pts[BINK_MAX_AUDIO_TRACKS]; | 51 int64_t audio_pts[BINK_MAX_AUDIO_TRACKS]; |
| 53 | 52 |
| 54 uint32_t remain_packet_size; | 53 uint32_t remain_packet_size; |
| 55 } BinkDemuxContext; | 54 } BinkDemuxContext; |
| 56 | 55 |
| 57 static int probe(AVProbeData *p) | 56 static int probe(AVProbeData *p) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 68 return 0; | 67 return 0; |
| 69 } | 68 } |
| 70 | 69 |
| 71 static int read_header(AVFormatContext *s, AVFormatParameters *ap) | 70 static int read_header(AVFormatContext *s, AVFormatParameters *ap) |
| 72 { | 71 { |
| 73 BinkDemuxContext *bink = s->priv_data; | 72 BinkDemuxContext *bink = s->priv_data; |
| 74 ByteIOContext *pb = s->pb; | 73 ByteIOContext *pb = s->pb; |
| 75 uint32_t fps_num, fps_den; | 74 uint32_t fps_num, fps_den; |
| 76 AVStream *vst, *ast; | 75 AVStream *vst, *ast; |
| 77 unsigned int i; | 76 unsigned int i; |
| 78 uint32_t pos, prev_pos; | 77 uint32_t pos, next_pos; |
| 79 uint16_t flags; | 78 uint16_t flags; |
| 80 int keyframe; | 79 int keyframe; |
| 81 | 80 |
| 82 vst = av_new_stream(s, 0); | 81 vst = av_new_stream(s, 0); |
| 83 if (!vst) | 82 if (!vst) |
| 84 return AVERROR(ENOMEM); | 83 return AVERROR(ENOMEM); |
| 85 | 84 |
| 86 vst->codec->codec_tag = get_le32(pb); | 85 vst->codec->codec_tag = get_le32(pb); |
| 87 | 86 |
| 88 bink->file_size = get_le32(pb) + 8; | 87 bink->file_size = get_le32(pb) + 8; |
| 89 bink->total_frames = get_le32(pb); | 88 vst->duration = get_le32(pb); |
| 90 | 89 |
| 91 if (bink->total_frames > 1000000) { | 90 if (vst->duration > 1000000) { |
| 92 av_log(s, AV_LOG_ERROR, "invalid header: more than 1000000 frames\n"); | 91 av_log(s, AV_LOG_ERROR, "invalid header: more than 1000000 frames\n"); |
| 93 return AVERROR(EIO); | 92 return AVERROR(EIO); |
| 94 } | 93 } |
| 95 | 94 |
| 96 if (get_le32(pb) > bink->file_size) { | 95 if (get_le32(pb) > bink->file_size) { |
| 97 av_log(s, AV_LOG_ERROR, | 96 av_log(s, AV_LOG_ERROR, |
| 98 "invalid header: largest frame size greater than file size\n"); | 97 "invalid header: largest frame size greater than file size\n"); |
| 99 return AVERROR(EIO); | 98 return AVERROR(EIO); |
| 100 } | 99 } |
| 101 | 100 |
| 102 url_fskip(pb, 4); | 101 url_fskip(pb, 4); |
| 103 | 102 |
| 104 vst->codec->width = get_le32(pb); | 103 vst->codec->width = get_le32(pb); |
| 105 vst->codec->height = get_le32(pb); | 104 vst->codec->height = get_le32(pb); |
| 106 | 105 |
| 107 fps_num = get_le32(pb); | 106 fps_num = get_le32(pb); |
| 108 fps_den = get_le32(pb); | 107 fps_den = get_le32(pb); |
| 109 if (fps_num == 0 || fps_den == 0) { | 108 if (fps_num == 0 || fps_den == 0) { |
| 110 av_log(s, AV_LOG_ERROR, "invalid header: invalid fps (%d/%d)\n", fps_num
, fps_den); | 109 av_log(s, AV_LOG_ERROR, "invalid header: invalid fps (%d/%d)\n", fps_num
, fps_den); |
| 111 return AVERROR(EIO); | 110 return AVERROR(EIO); |
| 112 } | 111 } |
| 113 av_set_pts_info(vst, 64, fps_den, fps_num); | 112 av_set_pts_info(vst, 64, fps_den, fps_num); |
| 114 | 113 |
| 115 url_fskip(pb, 4); | |
| 116 | |
| 117 vst->codec->codec_type = CODEC_TYPE_VIDEO; | 114 vst->codec->codec_type = CODEC_TYPE_VIDEO; |
| 118 vst->codec->codec_id = CODEC_ID_BINKVIDEO; | 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 |
| 119 bink->num_audio_tracks = get_le32(pb); | 120 bink->num_audio_tracks = get_le32(pb); |
| 120 | 121 |
| 121 if (bink->num_audio_tracks > BINK_MAX_AUDIO_TRACKS) { | 122 if (bink->num_audio_tracks > BINK_MAX_AUDIO_TRACKS) { |
| 122 av_log(s, AV_LOG_ERROR, | 123 av_log(s, AV_LOG_ERROR, |
| 123 "invalid header: more than "AV_STRINGIFY(BINK_MAX_AUDIO_TRACKS)"
audio tracks (%d)\n", | 124 "invalid header: more than "AV_STRINGIFY(BINK_MAX_AUDIO_TRACKS)"
audio tracks (%d)\n", |
| 124 bink->num_audio_tracks); | 125 bink->num_audio_tracks); |
| 125 return AVERROR(EIO); | 126 return AVERROR(EIO); |
| 126 } | 127 } |
| 127 | 128 |
| 128 if (bink->num_audio_tracks) { | 129 if (bink->num_audio_tracks) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 139 flags = get_le16(pb); | 140 flags = get_le16(pb); |
| 140 ast->codec->codec_id = flags & BINK_AUD_USEDCT ? | 141 ast->codec->codec_id = flags & BINK_AUD_USEDCT ? |
| 141 CODEC_ID_BINKAUDIO_DCT : CODEC_ID_BINKAUDIO_R
DFT; | 142 CODEC_ID_BINKAUDIO_DCT : CODEC_ID_BINKAUDIO_R
DFT; |
| 142 ast->codec->channels = flags & BINK_AUD_STEREO ? 2 : 1; | 143 ast->codec->channels = flags & BINK_AUD_STEREO ? 2 : 1; |
| 143 } | 144 } |
| 144 | 145 |
| 145 url_fskip(pb, 4 * bink->num_audio_tracks); | 146 url_fskip(pb, 4 * bink->num_audio_tracks); |
| 146 } | 147 } |
| 147 | 148 |
| 148 /* frame index table */ | 149 /* frame index table */ |
| 149 pos = get_le32(pb) & ~1; | 150 next_pos = get_le32(pb); |
| 150 for (i = 0; i < bink->total_frames; i++) { | 151 for (i = 0; i < vst->duration; i++) { |
| 151 prev_pos = pos; | 152 pos = next_pos; |
| 152 if (i == bink->total_frames - 1) { | 153 if (i == vst->duration - 1) { |
| 153 pos = bink->file_size; | 154 next_pos = bink->file_size; |
| 154 keyframe = 0; | 155 keyframe = 0; |
| 155 } else { | 156 } else { |
| 156 pos = get_le32(pb); | 157 next_pos = get_le32(pb); |
| 157 keyframe = pos & 1; | 158 keyframe = pos & 1; |
| 158 pos &= ~1; | |
| 159 } | 159 } |
| 160 if (pos <= prev_pos) { | 160 pos &= ~1; |
| 161 next_pos &= ~1; |
| 162 |
| 163 if (next_pos <= pos) { |
| 161 av_log(s, AV_LOG_ERROR, "invalid frame index table\n"); | 164 av_log(s, AV_LOG_ERROR, "invalid frame index table\n"); |
| 162 return AVERROR(EIO); | 165 return AVERROR(EIO); |
| 163 } | 166 } |
| 164 av_add_index_entry(vst, pos, i, pos - prev_pos, 0, | 167 av_add_index_entry(vst, pos, i, next_pos - pos, 0, |
| 165 keyframe ? AVINDEX_KEYFRAME : 0); | 168 keyframe ? AVINDEX_KEYFRAME : 0); |
| 166 } | 169 } |
| 167 | 170 |
| 168 url_fskip(pb, 4); | 171 url_fskip(pb, 4); |
| 169 | 172 |
| 170 bink->current_track = -1; | 173 bink->current_track = -1; |
| 171 return 0; | 174 return 0; |
| 172 } | 175 } |
| 173 | 176 |
| 174 static int read_packet(AVFormatContext *s, AVPacket *pkt) | 177 static int read_packet(AVFormatContext *s, AVPacket *pkt) |
| 175 { | 178 { |
| 176 BinkDemuxContext *bink = s->priv_data; | 179 BinkDemuxContext *bink = s->priv_data; |
| 177 ByteIOContext *pb = s->pb; | 180 ByteIOContext *pb = s->pb; |
| 178 int ret; | 181 int ret; |
| 179 | 182 |
| 180 if (bink->current_track < 0) { | 183 if (bink->current_track < 0) { |
| 181 int index_entry; | 184 int index_entry; |
| 182 AVStream *st = s->streams[0]; // stream 0 is video stream with index | 185 AVStream *st = s->streams[0]; // stream 0 is video stream with index |
| 183 | 186 |
| 184 if (bink->video_pts >= bink->total_frames) | 187 if (bink->video_pts >= st->duration) |
| 185 return AVERROR(EIO); | 188 return AVERROR(EIO); |
| 186 | 189 |
| 187 index_entry = av_index_search_timestamp(st, bink->video_pts, | 190 index_entry = av_index_search_timestamp(st, bink->video_pts, |
| 188 AVSEEK_FLAG_ANY); | 191 AVSEEK_FLAG_ANY); |
| 189 if (index_entry < 0) { | 192 if (index_entry < 0) { |
| 190 av_log(s, AV_LOG_ERROR, | 193 av_log(s, AV_LOG_ERROR, |
| 191 "could not find index entry for frame %"PRId64"\n", | 194 "could not find index entry for frame %"PRId64"\n", |
| 192 bink->video_pts); | 195 bink->video_pts); |
| 193 return AVERROR(EIO); | 196 return AVERROR(EIO); |
| 194 } | 197 } |
| 195 | 198 |
| 196 bink->remain_packet_size = st->index_entries[index_entry].size; | 199 bink->remain_packet_size = st->index_entries[index_entry].size; |
| 197 bink->current_track = 0; | 200 bink->current_track = 0; |
| 198 } | 201 } |
| 199 | 202 |
| 200 if (bink->current_track < bink->num_audio_tracks) { | 203 while (bink->current_track < bink->num_audio_tracks) { |
| 201 uint32_t audio_size = get_le32(pb); | 204 uint32_t audio_size = get_le32(pb); |
| 202 if (audio_size > bink->remain_packet_size - 4) { | 205 if (audio_size > bink->remain_packet_size - 4) { |
| 203 av_log(s, AV_LOG_ERROR, | 206 av_log(s, AV_LOG_ERROR, |
| 204 "frame %"PRId64": audio size in header (%u) > size of packet
left (%u)\n", | 207 "frame %"PRId64": audio size in header (%u) > size of packet
left (%u)\n", |
| 205 bink->video_pts, audio_size, bink->remain_packet_size); | 208 bink->video_pts, audio_size, bink->remain_packet_size); |
| 206 return AVERROR(EIO); | 209 return AVERROR(EIO); |
| 207 } | 210 } |
| 208 bink->remain_packet_size -= 4 + audio_size; | 211 bink->remain_packet_size -= 4 + audio_size; |
| 209 bink->current_track++; | 212 bink->current_track++; |
| 210 if (audio_size > 0) { | 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 |
| 211 /* Each audio packet reports the number of decompressed samples | 220 /* Each audio packet reports the number of decompressed samples |
| 212 (in bytes). We use this value to calcuate the audio PTS */ | 221 (in bytes). We use this value to calcuate the audio PTS */ |
| 213 int reported_size = get_le32(pb) / (2 * s->streams[bink->current_tra
ck]->codec->channels); | 222 bink->audio_pts[bink->current_track -1] += |
| 214 url_fseek(pb, -4, SEEK_CUR); | 223 AV_RL32(pkt->data) / (2 * s->streams[bink->current_track]->codec
->channels); |
| 215 | |
| 216 /* get one audio packet per track */ | |
| 217 if ((ret = av_get_packet(pb, pkt, audio_size)) | |
| 218 != audio_size) | |
| 219 return ret; | |
| 220 pkt->stream_index = bink->current_track; | |
| 221 pkt->pts = bink->audio_pts[bink->current_track - 1] += reported_size
; | |
| 222 return 0; | 224 return 0; |
| 225 } else { |
| 226 url_fseek(pb, audio_size, SEEK_CUR); |
| 223 } | 227 } |
| 224 } | 228 } |
| 225 | 229 |
| 226 /* get video packet */ | 230 /* get video packet */ |
| 227 if ((ret = av_get_packet(pb, pkt, bink->remain_packet_size)) | 231 if ((ret = av_get_packet(pb, pkt, bink->remain_packet_size)) |
| 228 != bink->remain_packet_size) | 232 != bink->remain_packet_size) |
| 229 return ret; | 233 return ret; |
| 230 pkt->stream_index = 0; | 234 pkt->stream_index = 0; |
| 231 pkt->pts = bink->video_pts++; | 235 pkt->pts = bink->video_pts++; |
| 232 pkt->flags |= PKT_FLAG_KEY; | 236 pkt->flags |= PKT_FLAG_KEY; |
| 233 | 237 |
| 234 /* -1 instructs the next call to read_packet() to read the next frame */ | 238 /* -1 instructs the next call to read_packet() to read the next frame */ |
| 235 bink->current_track = -1; | 239 bink->current_track = -1; |
| 236 | 240 |
| 237 return 0; | 241 return 0; |
| 238 } | 242 } |
| 239 | 243 |
| 244 static int read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, in
t 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 |
| 240 AVInputFormat bink_demuxer = { | 260 AVInputFormat bink_demuxer = { |
| 241 "bink", | 261 "bink", |
| 242 NULL_IF_CONFIG_SMALL("Bink"), | 262 NULL_IF_CONFIG_SMALL("Bink"), |
| 243 sizeof(BinkDemuxContext), | 263 sizeof(BinkDemuxContext), |
| 244 probe, | 264 probe, |
| 245 read_header, | 265 read_header, |
| 246 read_packet, | 266 read_packet, |
| 267 NULL, |
| 268 read_seek, |
| 247 }; | 269 }; |
| OLD | NEW |