| @@ -81,7 +81,7 @@ extern "C" { · 80 unmodified lines |
| 81 | 81 | #endif |
| 82 | 82 | |
| 83 | 83 | /* decode whole buffer block */ |
| 84 | | −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); |
| 84 | +int 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); |
| 85 | 85 | int mp3dec_load_cb(mp3dec_t *dec, mp3dec_io_t *io, uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data); |
| 86 | 86 | /* iterate through frames */ |
| 87 | 87 | size_t mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data); |
| @@ -134,8 +134,9 @@ static void mp3dec_skip_id3v1(const uint8_t *buf, size_t *pbuf_size) · 46 unmodified lines |
| 134 | 134 | |
| 135 | 135 | static size_t mp3dec_skip_id3v2(const uint8_t *buf, size_t buf_size) |
| 136 | 136 | { |
| 137 | +#define MINIMP3_ID3_DETECT_SIZE 10 |
| 137 | 138 | #ifndef MINIMP3_NOSKIP_ID3V2 |
| 138 | | − if (buf_size >= 10 && !memcmp(buf, "ID3", 3) && !((buf[5] & 15) || (buf[6] & 0x80) || (buf[7] & 0x80) || (buf[8] & 0x80) || (buf[9] & 0x80))) |
| 139 | + if (buf_size >= MINIMP3_ID3_DETECT_SIZE && !memcmp(buf, "ID3", 3) && !((buf[5] & 15) || (buf[6] & 0x80) || (buf[7] & 0x80) || (buf[8] & 0x80) || (buf[9] & 0x80))) |
| 139 | 140 | { |
| 140 | 141 | size_t id3v2size = (((buf[6] & 0x7f) << 21) | ((buf[7] & 0x7f) << 14) | ((buf[8] & 0x7f) << 7) | (buf[9] & 0x7f)) + 10; |
| 141 | 142 | if ((buf[5] & 16)) |
| @@ -210,7 +211,12 @@ static int mp3dec_check_vbrtag(const uint8_t *frame, int frame_size, uint32_t *f · 68 unmodified lines |
| 210 | 211 | return 1; |
| 211 | 212 | } |
| 212 | 213 | |
| 213 | | −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) |
| 214 | +int 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) |
| 215 | +{ |
| 216 | + return mp3dec_load_cb(dec, 0, (uint8_t *)buf, buf_size, info, progress_cb, user_data); |
| 217 | +} |
| 218 | + |
| 219 | +int mp3dec_load_cb(mp3dec_t *dec, mp3dec_io_t *io, uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data) |
| 214 | 220 | { |
| 215 | 221 | uint64_t detected_samples = 0; |
| 216 | 222 | size_t orig_buf_size = buf_size; |
| @@ -218,24 +224,64 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 1 unmodified line |
| 218 | 224 | mp3dec_frame_info_t frame_info; |
| 219 | 225 | memset(info, 0, sizeof(*info)); |
| 220 | 226 | memset(&frame_info, 0, sizeof(frame_info)); |
| 227 | + |
| 221 | 228 | /* skip id3 */ |
| 222 | | − mp3dec_skip_id3(&buf, &buf_size); |
| 223 | | − if (!buf_size) |
| 224 | | − return; |
| 229 | + size_t filled, consumed; |
| 230 | + int eof; |
| 231 | + if (io) |
| 232 | + { |
| 233 | + io->seek(0, io->seek_data); |
| 234 | + filled = io->read(buf, MINIMP3_ID3_DETECT_SIZE, io->read_data), consumed = 0, eof = 0; |
| 235 | + if (MINIMP3_ID3_DETECT_SIZE != filled) |
| 236 | + return 0; |
| 237 | + size_t id3v2size = mp3dec_skip_id3v2(buf, filled); |
| 238 | + if (id3v2size) |
| 239 | + { |
| 240 | + io->seek(id3v2size, io->seek_data); |
| 241 | + filled = io->read(buf, buf_size, io->read_data); |
| 242 | + } else |
| 243 | + filled += io->read(buf + MINIMP3_ID3_DETECT_SIZE, buf_size - MINIMP3_ID3_DETECT_SIZE, io->read_data); |
| 244 | + if (filled < MINIMP3_BUF_SIZE) |
| 245 | + mp3dec_skip_id3v1(buf, &filled); |
| 246 | + } else |
| 247 | + { |
| 248 | + mp3dec_skip_id3((const uint8_t **)&buf, &buf_size); |
| 249 | + if (!buf_size) |
| 250 | + return 0; |
| 251 | + } |
| 225 | 252 | /* try to make allocation size assumption by first frame or vbr tag */ |
| 226 | 253 | mp3dec_init(dec); |
| 227 | 254 | int samples; |
| 228 | 255 | do |
| 229 | 256 | { |
| 230 | 257 | uint32_t frames; |
| 231 | | − int delay, padding, free_format_bytes = 0, frame_size = 0; |
| 232 | | − int i = mp3d_find_frame(buf, buf_size, &free_format_bytes, &frame_size); |
| 233 | | − buf += i; |
| 234 | | − buf_size -= i; |
| 258 | + int i, delay, padding, free_format_bytes = 0, frame_size = 0; |
| 259 | + if (io) |
| 260 | + { |
| 261 | + if (!eof && filled - consumed < MINIMP3_BUF_SIZE) |
| 262 | + { /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */ |
| 263 | + memmove(buf, buf + consumed, filled - consumed); |
| 264 | + filled -= consumed; |
| 265 | + consumed = 0; |
| 266 | + size_t readed = io->read(buf + filled, buf_size - filled, io->read_data); |
| 267 | + if (readed != (buf_size - filled)) |
| 268 | + eof = 1; |
| 269 | + filled += readed; |
| 270 | + if (eof) |
| 271 | + mp3dec_skip_id3v1(buf, &filled); |
| 272 | + } |
| 273 | + i = mp3d_find_frame(buf + consumed, filled - consumed, &free_format_bytes, &frame_size); |
| 274 | + consumed += i; |
| 275 | + } else |
| 276 | + { |
| 277 | + i = mp3d_find_frame(buf, buf_size, &free_format_bytes, &frame_size); |
| 278 | + buf += i; |
| 279 | + buf_size -= i; |
| 280 | + } |
| 235 | 281 | if (i && !frame_size) |
| 236 | 282 | continue; |
| 237 | 283 | if (!frame_size) |
| 238 | | − return; |
| 284 | + return 0; |
| 239 | 285 | const uint8_t *hdr = buf; |
| 240 | 286 | frame_info.channels = HDR_IS_MONO(hdr) ? 1 : 2; |
| 241 | 287 | frame_info.hz = hdr_sample_rate_hz(hdr); |
| @@ -253,9 +299,15 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 11 unmodified lines |
| 253 | 299 | if (padding > 0 && detected_samples >= (uint64_t)padding) |
| 254 | 300 | detected_samples -= padding; |
| 255 | 301 | if (!detected_samples) |
| 256 | | − return; |
| 257 | | − buf += frame_size; |
| 258 | | − buf_size -= frame_size; |
| 302 | + return 0; |
| 303 | + if (io) |
| 304 | + { |
| 305 | + consumed += frame_size; |
| 306 | + } else |
| 307 | + { |
| 308 | + buf += frame_size; |
| 309 | + buf_size -= frame_size; |
| 310 | + } |
| 259 | 311 | } |
| 260 | 312 | break; |
| 261 | 313 | } while(1); |
| @@ -266,14 +318,13 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 4 unmodified lines |
| 266 | 318 | allocated += (buf_size/frame_info.frame_bytes)*samples*sizeof(mp3d_sample_t); |
| 267 | 319 | info->buffer = (mp3d_sample_t*)malloc(allocated); |
| 268 | 320 | if (!info->buffer) |
| 269 | | − return; |
| 321 | + return MP3D_E_MEMORY; |
| 270 | 322 | /* save info */ |
| 271 | 323 | info->channels = frame_info.channels; |
| 272 | 324 | info->hz = frame_info.hz; |
| 273 | 325 | info->layer = frame_info.layer; |
| 274 | 326 | /* decode all frames */ |
| 275 | 327 | size_t avg_bitrate_kbps = 0, frames = 0; |
| 276 | | − int frame_bytes; |
| 277 | 328 | do |
| 278 | 329 | { |
| 279 | 330 | if ((allocated - info->samples*sizeof(mp3d_sample_t)) < MINIMP3_MAX_SAMPLES_PER_FRAME*sizeof(mp3d_sample_t)) |
| @@ -281,10 +332,28 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 1 unmodified line |
| 281 | 332 | allocated *= 2; |
| 282 | 333 | info->buffer = (mp3d_sample_t*)realloc(info->buffer, allocated); |
| 283 | 334 | } |
| 284 | | − samples = mp3dec_decode_frame(dec, buf, MINIMP3_MIN(buf_size, (size_t)INT_MAX), info->buffer + info->samples, &frame_info); |
| 285 | | − frame_bytes = frame_info.frame_bytes; |
| 286 | | − buf += frame_bytes; |
| 287 | | − buf_size -= frame_bytes; |
| 335 | + if (io) |
| 336 | + { |
| 337 | + if (!eof && filled - consumed < MINIMP3_BUF_SIZE) |
| 338 | + { /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */ |
| 339 | + memmove(buf, buf + consumed, filled - consumed); |
| 340 | + filled -= consumed; |
| 341 | + consumed = 0; |
| 342 | + size_t readed = io->read(buf + filled, buf_size - filled, io->read_data); |
| 343 | + if (readed != (buf_size - filled)) |
| 344 | + eof = 1; |
| 345 | + filled += readed; |
| 346 | + if (eof) |
| 347 | + mp3dec_skip_id3v1(buf, &filled); |
| 348 | + } |
| 349 | + samples = mp3dec_decode_frame(dec, buf + consumed, filled - consumed, info->buffer + info->samples, &frame_info); |
| 350 | + consumed += frame_info.frame_bytes; |
| 351 | + } else |
| 352 | + { |
| 353 | + samples = mp3dec_decode_frame(dec, buf, MINIMP3_MIN(buf_size, (size_t)INT_MAX), info->buffer + info->samples, &frame_info); |
| 354 | + buf += frame_info.frame_bytes; |
| 355 | + buf_size -= frame_info.frame_bytes; |
| 356 | + } |
| 288 | 357 | if (samples) |
| 289 | 358 | { |
| 290 | 359 | if (info->hz != frame_info.hz || info->layer != frame_info.layer) |
| @@ -309,7 +378,7 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 18 unmodified lines |
| 309 | 378 | if (progress_cb) |
| 310 | 379 | progress_cb(user_data, orig_buf_size, orig_buf_size - buf_size, &frame_info); |
| 311 | 380 | } |
| 312 | | − } while (frame_bytes); |
| 381 | + } while (frame_info.frame_bytes); |
| 313 | 382 | if (detected_samples && info->samples > detected_samples) |
| 314 | 383 | info->samples = detected_samples; /* cut padding */ |
| 315 | 384 | /* reallocate to normal buffer size */ |
| @@ -317,6 +386,7 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 1 unmodified line |
| 317 | 386 | info->buffer = (mp3d_sample_t*)realloc(info->buffer, info->samples*sizeof(mp3d_sample_t)); |
| 318 | 387 | if (frames) |
| 319 | 388 | info->avg_bitrate_kbps = avg_bitrate_kbps/frames; |
| 389 | + return 0; |
| 320 | 390 | } |
| 321 | 391 | |
| 322 | 392 | size_t mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data) |
| @@ -363,11 +433,13 @@ uint64_t mp3dec_iterate_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size, MP3D_ · 40 unmodified lines |
| 363 | 433 | if (buf_size < MINIMP3_BUF_SIZE) |
| 364 | 434 | return 0; |
| 365 | 435 | io->seek(0, io->seek_data); |
| 366 | | − size_t filled = io->read(buf, 10, io->read_data), consumed = 0; |
| 436 | + size_t filled = io->read(buf, MINIMP3_ID3_DETECT_SIZE, io->read_data), consumed = 0; |
| 367 | 437 | uint64_t readed = 0, frames = 0; |
| 368 | 438 | mp3dec_frame_info_t frame_info; |
| 369 | 439 | int eof = 0; |
| 370 | 440 | memset(&frame_info, 0, sizeof(frame_info)); |
| 441 | + if (MINIMP3_ID3_DETECT_SIZE != filled) |
| 442 | + return 0; |
| 371 | 443 | size_t id3v2size = mp3dec_skip_id3v2(buf, filled); |
| 372 | 444 | if (id3v2size) |
| 373 | 445 | { |
| @@ -375,7 +447,7 @@ uint64_t mp3dec_iterate_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size, MP3D_ · 1 unmodified line |
| 375 | 447 | filled = io->read(buf, buf_size, io->read_data); |
| 376 | 448 | readed += id3v2size; |
| 377 | 449 | } else |
| 378 | | − filled += io->read(buf + 10, buf_size - 10, io->read_data); |
| 450 | + filled += io->read(buf + MINIMP3_ID3_DETECT_SIZE, buf_size - MINIMP3_ID3_DETECT_SIZE, io->read_data); |
| 379 | 451 | if (filled < MINIMP3_BUF_SIZE) |
| 380 | 452 | mp3dec_skip_id3v1(buf, &filled); |
| 381 | 453 | do |