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 |