Unified · Split
| @@ -127,10 +127,52 @@ static void mp3dec_skip_id3(const uint8_t **pbuf, size_t *pbuf_size) · 126 unmodified lines | ||
| 127 | 127 | *pbuf_size = buf_size; |
| 128 | 128 | } |
| 129 | 129 | |
| 130 | +static int mp3dec_check_vbrtag(const uint8_t *frame, int frame_size, uint32_t *frames, int *delay, int *padding) | |
| 131 | +{ | |
| 132 | + int i; | |
| 133 | + static const char g_xing_tag[4] = { 'X', 'i', 'n', 'g' }; | |
| 134 | + static const char g_info_tag[4] = { 'I', 'n', 'f', 'o' }; | |
| 135 | +#define FRAMES_FLAG 1 | |
| 136 | +#define BYTES_FLAG 2 | |
| 137 | +#define TOC_FLAG 4 | |
| 138 | +#define VBR_SCALE_FLAG 8 | |
| 139 | + /* TODO: skip side-info? | |
| 140 | + / Side info offsets afrer header: | |
| 141 | + / Mono Stereo | |
| 142 | + / MPEG1 17 32 | |
| 143 | + / MPEG2 & 2.5 9 17*/ | |
| 144 | + for (i = 5; i < frame_size - 36; i++) | |
| 145 | + { | |
| 146 | + const uint8_t *tag = frame + i; | |
| 147 | + if (memcmp(g_xing_tag, tag, 4) && memcmp(g_info_tag, tag, 4)) | |
| 148 | + continue; | |
| 149 | + int flags = tag[7]; | |
| 150 | + if (!((flags & FRAMES_FLAG))) | |
| 151 | + break; | |
| 152 | + tag += 8; | |
| 153 | + (*frames) = (uint32_t)(tag[0] << 24) | (tag[1] << 16) | (tag[2] << 8) | tag[3]; | |
| 154 | + tag += 4; | |
| 155 | + if (flags & BYTES_FLAG) | |
| 156 | + tag += 4; | |
| 157 | + if (flags & TOC_FLAG) | |
| 158 | + tag += 100; | |
| 159 | + if (flags & VBR_SCALE_FLAG) | |
| 160 | + tag += 4; | |
| 161 | + tag += 21; | |
| 162 | + if (tag - frame + 2 >= frame_size) | |
| 163 | + break; | |
| 164 | + *delay = ((tag[0] << 4) | (tag[1] >> 4)) + (528 + 1); | |
| 165 | + *padding = (((tag[1] & 0xF) << 8) | tag[2]) - (528 + 1); | |
| 166 | + return 1; | |
| 167 | + } | |
| 168 | + return 0; | |
| 169 | +} | |
| 170 | + | |
| 130 | 171 | void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data) |
| 131 | 172 | { |
| 173 | + uint64_t detected_samples = 0; | |
| 132 | 174 | size_t orig_buf_size = buf_size; |
| 133 | − mp3d_sample_t pcm[MINIMP3_MAX_SAMPLES_PER_FRAME]; | |
| 175 | + int to_skip = 0; | |
| 134 | 176 | mp3dec_frame_info_t frame_info; |
| 135 | 177 | memset(info, 0, sizeof(*info)); |
| 136 | 178 | memset(&frame_info, 0, sizeof(frame_info)); |
| @@ -138,33 +180,57 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 1 unmodified line | ||
| 138 | 180 | mp3dec_skip_id3(&buf, &buf_size); |
| 139 | 181 | if (!buf_size) |
| 140 | 182 | return; |
| 141 | − /* try to make allocation size assumption by first frame */ | |
| 183 | + /* try to make allocation size assumption by first frame or vbr tag */ | |
| 142 | 184 | mp3dec_init(dec); |
| 143 | 185 | int samples; |
| 144 | 186 | do |
| 145 | 187 | { |
| 146 | − samples = mp3dec_decode_frame(dec, buf, MINIMP3_MIN(buf_size, (size_t)INT_MAX), pcm, &frame_info); | |
| 147 | − buf += frame_info.frame_bytes; | |
| 148 | − buf_size -= frame_info.frame_bytes; | |
| 149 | − if (samples) | |
| 150 | − break; | |
| 151 | − } while (frame_info.frame_bytes); | |
| 152 | − if (!samples) | |
| 153 | − return; | |
| 154 | − samples *= frame_info.channels; | |
| 155 | − size_t allocated = (buf_size/frame_info.frame_bytes)*samples*sizeof(mp3d_sample_t) + MINIMP3_MAX_SAMPLES_PER_FRAME*sizeof(mp3d_sample_t); | |
| 188 | + uint32_t frames; | |
| 189 | + int delay, padding, free_format_bytes = 0, frame_size = 0; | |
| 190 | + int i = mp3d_find_frame(buf, buf_size, &free_format_bytes, &frame_size); | |
| 191 | + buf += i; | |
| 192 | + buf_size -= i; | |
| 193 | + if (i && !frame_size) | |
| 194 | + continue; | |
| 195 | + if (!frame_size) | |
| 196 | + return; | |
| 197 | + const uint8_t *hdr = buf; | |
| 198 | + frame_info.channels = HDR_IS_MONO(hdr) ? 1 : 2; | |
| 199 | + frame_info.hz = hdr_sample_rate_hz(hdr); | |
| 200 | + frame_info.layer = 4 - HDR_GET_LAYER(hdr); | |
| 201 | + frame_info.bitrate_kbps = hdr_bitrate_kbps(hdr); | |
| 202 | + frame_info.frame_bytes = frame_size; | |
| 203 | + samples = hdr_frame_samples(hdr)*frame_info.channels; | |
| 204 | + if (mp3dec_check_vbrtag(hdr, frame_size, &frames, &delay, &padding)) | |
| 205 | + { | |
| 206 | + padding *= frame_info.channels; | |
| 207 | + to_skip = delay*frame_info.channels; | |
| 208 | + detected_samples = samples*(uint64_t)frames; | |
| 209 | + if (detected_samples >= (uint64_t)to_skip) | |
| 210 | + detected_samples -= to_skip; | |
| 211 | + if (padding > 0 && detected_samples >= (uint64_t)padding) | |
| 212 | + detected_samples -= padding; | |
| 213 | + if (!detected_samples) | |
| 214 | + return; | |
| 215 | + buf += frame_size; | |
| 216 | + buf_size -= frame_size; | |
| 217 | + } | |
| 218 | + break; | |
| 219 | + } while(1); | |
| 220 | + size_t allocated = MINIMP3_MAX_SAMPLES_PER_FRAME*sizeof(mp3d_sample_t); | |
| 221 | + if (detected_samples) | |
| 222 | + allocated += detected_samples*sizeof(mp3d_sample_t); | |
| 223 | + else | |
| 224 | + allocated += (buf_size/frame_info.frame_bytes)*samples*sizeof(mp3d_sample_t); | |
| 156 | 225 | info->buffer = (mp3d_sample_t*)malloc(allocated); |
| 157 | 226 | if (!info->buffer) |
| 158 | 227 | return; |
| 159 | − info->samples = samples; | |
| 160 | − memcpy(info->buffer, pcm, info->samples*sizeof(mp3d_sample_t)); | |
| 161 | 228 | /* save info */ |
| 162 | 229 | info->channels = frame_info.channels; |
| 163 | 230 | info->hz = frame_info.hz; |
| 164 | 231 | info->layer = frame_info.layer; |
| 165 | − size_t avg_bitrate_kbps = frame_info.bitrate_kbps; | |
| 166 | − size_t frames = 1; | |
| 167 | − /* decode rest frames */ | |
| 232 | + /* decode all frames */ | |
| 233 | + size_t avg_bitrate_kbps = 0, frames = 0; | |
| 168 | 234 | int frame_bytes; |
| 169 | 235 | do |
| 170 | 236 | { |
| @@ -187,17 +253,28 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 16 unmodified lines | ||
| 187 | 253 | #else |
| 188 | 254 | break; |
| 189 | 255 | #endif |
| 190 | − info->samples += samples*frame_info.channels; | |
| 256 | + samples *= frame_info.channels; | |
| 257 | + if (to_skip) | |
| 258 | + { | |
| 259 | + size_t skip = MINIMP3_MIN(samples, to_skip); | |
| 260 | + to_skip -= skip; | |
| 261 | + samples -= skip; | |
| 262 | + memmove(info->buffer, info->buffer + skip, samples); | |
| 263 | + } | |
| 264 | + info->samples += samples; | |
| 191 | 265 | avg_bitrate_kbps += frame_info.bitrate_kbps; |
| 192 | 266 | frames++; |
| 193 | 267 | if (progress_cb) |
| 194 | 268 | progress_cb(user_data, orig_buf_size, orig_buf_size - buf_size, &frame_info); |
| 195 | 269 | } |
| 196 | 270 | } while (frame_bytes); |
| 271 | + if (detected_samples) | |
| 272 | + info->samples = detected_samples; | |
| 197 | 273 | /* reallocate to normal buffer size */ |
| 198 | 274 | if (allocated != info->samples*sizeof(mp3d_sample_t)) |
| 199 | 275 | info->buffer = (mp3d_sample_t*)realloc(info->buffer, info->samples*sizeof(mp3d_sample_t)); |
| 200 | − info->avg_bitrate_kbps = avg_bitrate_kbps/frames; | |
| 276 | + if (frames) | |
| 277 | + info->avg_bitrate_kbps = avg_bitrate_kbps/frames; | |
| 201 | 278 | } |
| 202 | 279 | |
| 203 | 280 | size_t mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data) |
| @@ -241,61 +318,29 @@ size_t mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB c · 37 unmodified lines | ||
| 241 | 318 | |
| 242 | 319 | static int mp3dec_load_index(void *user_data, const uint8_t *frame, int frame_size, int free_format_bytes, size_t buf_size, size_t offset, mp3dec_frame_info_t *info) |
| 243 | 320 | { |
| 244 | − static const char g_xing_tag[4] = { 'X', 'i', 'n', 'g' }; | |
| 245 | − static const char g_info_tag[4] = { 'I', 'n', 'f', 'o' }; | |
| 246 | 321 | mp3dec_frame_t *idx_frame; |
| 247 | 322 | mp3dec_ex_t *dec = (mp3dec_ex_t *)user_data; |
| 248 | 323 | if (!dec->index.frames && !dec->vbr_tag_found) |
| 249 | 324 | { /* detect VBR tag and try to avoid full scan */ |
| 250 | − int i; | |
| 325 | + uint32_t frames; | |
| 326 | + int delay, padding; | |
| 251 | 327 | dec->info = *info; |
| 252 | 328 | dec->start_offset = dec->offset = offset; |
| 253 | 329 | dec->end_offset = offset + buf_size; |
| 254 | 330 | dec->free_format_bytes = free_format_bytes; /* should not change */ |
| 255 | − /* TODO: skip side-info? | |
| 256 | − / Side info offsets afrer header: | |
| 257 | − / Mono Stereo | |
| 258 | − / MPEG1 17 32 | |
| 259 | − / MPEG2 & 2.5 9 17*/ | |
| 260 | − for (i = 5; i < frame_size - 36; i++) | |
| 331 | + if (mp3dec_check_vbrtag(frame, frame_size, &frames, &delay, &padding)) | |
| 261 | 332 | { |
| 262 | − const uint8_t *tag = frame + i; | |
| 263 | − if (!memcmp(g_xing_tag, tag, 4) || !memcmp(g_info_tag, tag, 4)) | |
| 264 | − { | |
| 265 | −#define FRAMES_FLAG 1 | |
| 266 | −#define BYTES_FLAG 2 | |
| 267 | −#define TOC_FLAG 4 | |
| 268 | −#define VBR_SCALE_FLAG 8 | |
| 269 | − int flags = tag[7], delay, padding; | |
| 270 | − uint32_t frames; | |
| 271 | − if (!((flags & FRAMES_FLAG))) | |
| 272 | − break; | |
| 273 | − tag += 8; | |
| 274 | − frames = (uint32_t)(tag[0] << 24) | (tag[1] << 16) | (tag[2] << 8) | tag[3]; | |
| 275 | − tag += 4; | |
| 276 | − if (flags & BYTES_FLAG) | |
| 277 | − tag += 4; | |
| 278 | − if (flags & TOC_FLAG) | |
| 279 | − tag += 100; | |
| 280 | − if (flags & VBR_SCALE_FLAG) | |
| 281 | − tag += 4; | |
| 282 | − tag += 21; | |
| 283 | − if (tag - frame + 2 >= frame_size) | |
| 284 | − break; | |
| 285 | − delay = (((tag[0] << 4) | (tag[1] >> 4)) + (528 + 1))*info->channels; | |
| 286 | − padding = ((((tag[1] & 0xF) << 8) | tag[2]) - (528 + 1))*info->channels; | |
| 287 | − | |
| 288 | − dec->start_delay = dec->to_skip = delay; | |
| 289 | − dec->samples = hdr_frame_samples(frame)*info->channels*(uint64_t)frames; | |
| 290 | − if (dec->samples >= (uint64_t)dec->start_delay) | |
| 291 | − dec->samples -= dec->start_delay; | |
| 292 | − if (padding > 0 && dec->samples >= (uint64_t)padding) | |
| 293 | − dec->samples -= padding; | |
| 294 | − dec->detected_samples = dec->samples; | |
| 295 | − dec->start_offset = dec->offset = offset + frame_size; | |
| 296 | − dec->vbr_tag_found = 1; | |
| 297 | − return 1; | |
| 298 | − } | |
| 333 | + padding *= info->channels; | |
| 334 | + dec->start_delay = dec->to_skip = delay*info->channels; | |
| 335 | + dec->samples = hdr_frame_samples(frame)*info->channels*(uint64_t)frames; | |
| 336 | + if (dec->samples >= (uint64_t)dec->start_delay) | |
| 337 | + dec->samples -= dec->start_delay; | |
| 338 | + if (padding > 0 && dec->samples >= (uint64_t)padding) | |
| 339 | + dec->samples -= padding; | |
| 340 | + dec->detected_samples = dec->samples; | |
| 341 | + dec->start_offset = dec->offset = offset + frame_size; | |
| 342 | + dec->vbr_tag_found = 1; | |
| 343 | + return 1; | |
| 299 | 344 | } |
| 300 | 345 | } |
| 301 | 346 | if (dec->index.num_frames + 1 > dec->index.capacity) |
| @@ -13,7 +13,7 @@ vectors/l3-sin1k0db.bit vectors/l3-test45.bit vectors/l3-test46.bit vectors/M2L3 · 12 unmodified lines | ||
| 13 | 13 | vectors/M2L3_bitrate_22_all.bit vectors/M2L3_bitrate_24_all.bit vectors/M2L3_compl24.bit vectors/M2L3_noise.bit \ |
| 14 | 14 | vectors/l3-nonstandard-id3v1.bit vectors/l3-nonstandard-id3v2.bit vectors/l1-fl1.bit vectors/l2-fl10.bit" |
| 15 | 15 | if [ "$MODE" = "2" ]; then |
| 16 | −VECTORS+=" vectors/vbrtag/l3-nonstandard-sin1k0db_lame_tag.bit" | |
| 16 | +VECTORS+=" vectors/l3-nonstandard-sin1k0db_lame_vbrtag.bit" | |
| 17 | 17 | fi |
| 18 | 18 | |
| 19 | 19 | set +e |
File renamed without changes.
File renamed without changes.