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