Mercurial > audlegacy-plugins
comparison src/madplug/decoder.c @ 980:6ba4a4bfd127 trunk
[svn] - fix overflow when calculates bitrate with non-fast scan on a huge sized file.
- make file info dialog always do non-fast scan. user can easily add TLEN tag of correct play time length to a VBR encoded file which does not go along with fast scan.
- tweak debug output.
| author | yaz |
|---|---|
| date | Thu, 26 Apr 2007 02:06:12 -0700 |
| parents | b2fbf53360cf |
| children | e46b98155d5d |
comparison
equal
deleted
inserted
replaced
| 979:e31c4566feb6 | 980:6ba4a4bfd127 |
|---|---|
| 177 unsigned char buffer[BUFFER_SIZE]; | 177 unsigned char buffer[BUFFER_SIZE]; |
| 178 struct mad_frame frame; /* to read xing data */ | 178 struct mad_frame frame; /* to read xing data */ |
| 179 gboolean has_xing = FALSE; | 179 gboolean has_xing = FALSE; |
| 180 int bitrate_frames = 0; | 180 int bitrate_frames = 0; |
| 181 guint xing_bitrate = 0; | 181 guint xing_bitrate = 0; |
| 182 double accum_bitrate = 0.0; | |
| 182 | 183 |
| 183 mad_stream_init(&stream); | 184 mad_stream_init(&stream); |
| 185 mad_stream_options(&stream, 0); // check CRC | |
| 184 mad_header_init(&header); | 186 mad_header_init(&header); |
| 185 mad_frame_init(&frame); | 187 mad_frame_init(&frame); |
| 186 xing_init(&info->xing); | 188 xing_init(&info->xing); |
| 187 | 189 |
| 188 info->bitrate = 0; | 190 info->bitrate = 0; |
| 208 len = input_get_data(info, buffer + remainder, | 210 len = input_get_data(info, buffer + remainder, |
| 209 BUFFER_SIZE - remainder); | 211 BUFFER_SIZE - remainder); |
| 210 | 212 |
| 211 if (len <= 0) { | 213 if (len <= 0) { |
| 212 #ifdef DEBUG | 214 #ifdef DEBUG |
| 213 g_message("scan_file: len <= 0! len = %d", len); | 215 g_message("scan_file: len <= 0 len = %d", len); |
| 214 #endif | 216 #endif |
| 215 break; | 217 break; |
| 216 } | 218 } |
| 217 | 219 |
| 218 mad_stream_buffer(&stream, buffer, len + remainder); | 220 mad_stream_buffer(&stream, buffer, len + remainder); |
| 254 } | 256 } |
| 255 info->frames++; | 257 info->frames++; |
| 256 | 258 |
| 257 #ifdef DEBUG | 259 #ifdef DEBUG |
| 258 #ifdef DEBUG_INTENSIVELY | 260 #ifdef DEBUG_INTENSIVELY |
| 259 g_message("duration = %lu", | 261 g_message("header bitrate = %ld", header.bitrate); |
| 262 g_message("duration = %ul", | |
| 260 mad_timer_count(header.duration, | 263 mad_timer_count(header.duration, |
| 261 MAD_UNITS_MILLISECONDS)); | 264 MAD_UNITS_MILLISECONDS)); |
| 262 g_message("size = %d", stream.next_frame - stream.this_frame); | 265 g_message("size = %d", stream.next_frame - stream.this_frame); |
| 263 #endif | 266 #endif |
| 264 #endif | 267 #endif |
| 283 #ifdef DEBUG | 286 #ifdef DEBUG |
| 284 g_message("xing frame decode failed"); | 287 g_message("xing frame decode failed"); |
| 285 #endif | 288 #endif |
| 286 goto no_xing; | 289 goto no_xing; |
| 287 } | 290 } |
| 288 if (xing_parse | 291 if (xing_parse(&info->xing, stream.anc_ptr, stream.anc_bitlen) == 0) { |
| 289 (&info->xing, stream.anc_ptr, | 292 #ifdef DEBUG |
| 290 stream.anc_bitlen) == 0) { | 293 g_message("xing header found "); |
| 291 #ifdef DEBUG | |
| 292 g_message("found xing header"); | |
| 293 #endif /* DEBUG */ | 294 #endif /* DEBUG */ |
| 294 has_xing = TRUE; | 295 has_xing = TRUE; |
| 295 info->vbr = TRUE; /* otherwise xing header would have been 'Info' */ | 296 info->vbr = TRUE; /* otherwise xing header would have been 'Info' */ |
| 296 info->frames = info->xing.frames; | 297 info->frames = info->xing.frames; |
| 297 if(info->tuple->length == -1) | 298 if(info->tuple->length == -1) |
| 298 mad_timer_multiply(&info->duration, info->frames); | 299 mad_timer_multiply(&info->duration, info->frames); |
| 299 else { | 300 else { |
| 300 info->duration.seconds = info->tuple->length / 1000; | 301 info->duration.seconds = info->tuple->length / 1000; |
| 301 info->duration.fraction = info->tuple->length % 1000; | 302 info->duration.fraction = info->tuple->length % 1000; |
| 302 } | 303 } |
| 304 | |
| 305 g_message("xing: bytes = %ld frames = %ld", info->xing.bytes, info->xing.frames); | |
| 306 g_message("info->duration = %ld", info->duration.seconds); | |
| 307 g_message("mad_timer_count = %ld", mad_timer_count(info->duration, MAD_UNITS_SECONDS)); | |
| 303 xing_bitrate = | 308 xing_bitrate = |
| 304 8.0 * info->xing.bytes / | 309 8.0 * info->xing.bytes / |
| 305 mad_timer_count(info->duration, | 310 mad_timer_count(info->duration, MAD_UNITS_SECONDS); |
| 306 MAD_UNITS_SECONDS); | 311 #ifdef DEBUG |
| 307 #ifdef DEBUG | 312 g_message("xing bitrate = %d", xing_bitrate); |
| 308 g_message("xing: bitrate = %d", xing_bitrate); | |
| 309 #endif | 313 #endif |
| 310 continue; | 314 continue; |
| 311 } | 315 } |
| 312 } | 316 #ifdef DEBUG |
| 317 else { | |
| 318 g_message("xing header parsing failed"); | |
| 319 continue; | |
| 320 } | |
| 321 | |
| 322 #endif | |
| 323 } /* xing */ | |
| 313 | 324 |
| 314 } | 325 } |
| 315 else { | 326 else { |
| 316 /* perhaps we have a VRB file */ | 327 /* perhaps we have a VBR file */ |
| 317 if (info->bitrate != header.bitrate) | 328 if (info->bitrate != header.bitrate) |
| 318 info->vbr = TRUE; | 329 info->vbr = TRUE; |
| 319 if (info->vbr) { | 330 if (info->vbr) { |
| 320 info->bitrate += header.bitrate; | 331 accum_bitrate += (double)header.bitrate; |
| 321 bitrate_frames++; | 332 bitrate_frames++; |
| 322 } | 333 } |
| 323 /* check for changin layer/samplerate/channels */ | 334 /* check for changin layer/samplerate/channels */ |
| 324 if (info->mpeg_layer != header.layer) | 335 if (info->mpeg_layer != header.layer) |
| 325 g_warning("layer varies!!"); | 336 g_warning("layer varies!!"); |
| 330 } | 341 } |
| 331 no_xing: | 342 no_xing: |
| 332 if (fast && info->frames >= N_AVERAGE_FRAMES) { | 343 if (fast && info->frames >= N_AVERAGE_FRAMES) { |
| 333 float frame_size = ((double) data_used) / N_AVERAGE_FRAMES; | 344 float frame_size = ((double) data_used) / N_AVERAGE_FRAMES; |
| 334 #ifdef DEBUG | 345 #ifdef DEBUG |
| 335 g_message("info->frames = %d info->size = %d tagsize = %d frame_size = %lf", | 346 g_message("bitrate = %ld samplerate = %d", header.bitrate, header.samplerate); |
| 336 info->frames, info->size, tagsize, frame_size); | 347 g_message("data_used = %d info->frames = %d info->size = %d tagsize = %d frame_size = %lf", |
| 348 data_used, info->frames, info->size, tagsize, frame_size); | |
| 337 #endif | 349 #endif |
| 338 if(info->size != 0) | 350 if(info->size != 0) |
| 339 info->frames = (info->size - tagsize) / frame_size; | 351 info->frames = (info->size - tagsize) / frame_size; |
| 340 #ifdef DEBUG | 352 #ifdef DEBUG |
| 341 g_message("info->frames = %d", info->frames); | 353 g_message("info->frames = %d", info->frames); |
| 355 data_used, tagsize, frame_size); | 367 data_used, tagsize, frame_size); |
| 356 g_message("frames = %d, frequency = %d, channels = %d", | 368 g_message("frames = %d, frequency = %d, channels = %d", |
| 357 info->frames, info->freq, info->channels); | 369 info->frames, info->freq, info->channels); |
| 358 long millis = mad_timer_count(info->duration, | 370 long millis = mad_timer_count(info->duration, |
| 359 MAD_UNITS_MILLISECONDS); | 371 MAD_UNITS_MILLISECONDS); |
| 360 g_message("duration = %lu:%lu", millis / 1000 / 60, | 372 g_message("duration = %ld:%02ld", millis / 1000 / 60, (millis / 1000) % 60); |
| 361 (millis / 1000) % 60); | |
| 362 #endif /* DEBUG */ | 373 #endif /* DEBUG */ |
| 363 break; | 374 break; |
| 364 } | 375 } |
| 365 } | 376 } /* while */ |
| 366 if (stream.error != MAD_ERROR_BUFLEN) | 377 if (stream.error != MAD_ERROR_BUFLEN) |
| 367 break; | 378 break; |
| 368 } | 379 } |
| 369 | 380 |
| 370 if (info->vbr && xing_bitrate == 0) { | 381 if (info->vbr && xing_bitrate != 0) { |
| 371 info->bitrate = info->bitrate / bitrate_frames; | 382 info->bitrate = xing_bitrate; |
| 372 #ifdef DEBUG | 383 } |
| 373 g_message("info->bitrate = %d", info->bitrate); | 384 else if (info->vbr && xing_bitrate == 0 && bitrate_frames != 0) { |
| 374 #endif | 385 info->bitrate = accum_bitrate / bitrate_frames; |
| 375 } | 386 } |
| 376 | 387 |
| 377 mad_frame_finish(&frame); | 388 mad_frame_finish(&frame); |
| 378 mad_header_finish(&header); | 389 mad_header_finish(&header); |
| 379 mad_stream_finish(&stream); | 390 mad_stream_finish(&stream); |
| 384 g_message("e: scan_file"); | 395 g_message("e: scan_file"); |
| 385 #endif /* DEBUG */ | 396 #endif /* DEBUG */ |
| 386 return (info->frames != 0 || info->remote == TRUE); | 397 return (info->frames != 0 || info->remote == TRUE); |
| 387 } | 398 } |
| 388 | 399 |
| 389 // sanity check for audio open parameters | 400 /* sanity check for audio open parameters */ |
| 390 static gboolean check_audio_param(struct mad_info_t *info) | 401 static gboolean check_audio_param(struct mad_info_t *info) |
| 391 { | 402 { |
| 392 if(info->fmt < FMT_U8 || info->fmt > FMT_S16_NE) | 403 if(info->fmt < FMT_U8 || info->fmt > FMT_S16_NE) |
| 393 return FALSE; | 404 return FALSE; |
| 394 if(info->freq < 0) // not sure about maximum frequency. --yaz | 405 if(info->freq < 0) // not sure about maximum frequency. --yaz |
