OSDN Git Service

New cropping algorithm - determine cropping rectangle from a median filter run across...
[handbrake-jp/handbrake-jp-git.git] / libhb / scan.c
1 /* $Id: scan.c,v 1.52 2005/11/25 15:05:25 titer Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.fr/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include "hb.h"
8 #include "a52dec/a52.h"
9 #include "dca.h"
10
11 typedef struct
12 {
13     hb_handle_t * h;
14
15     char        * path;
16     int           title_index;
17     hb_list_t   * list_title;
18
19     hb_dvd_t    * dvd;
20         hb_stream_t * stream;
21
22 } hb_scan_t;
23
24 static void ScanFunc( void * );
25 static int  DecodePreviews( hb_scan_t *, hb_title_t * title );
26 static void LookForAudio( hb_title_t * title, hb_buffer_t * b );
27 static int  AllAudioOK( hb_title_t * title );
28
29 static const char *aspect_to_string( int aspect )
30 {
31     switch ( aspect )
32     {
33         case HB_ASPECT_BASE * 1 / 1:    return "1:1";
34         case HB_ASPECT_BASE * 4 / 3:    return "4:3";
35         case HB_ASPECT_BASE * 16 / 9:   return "16:9";
36         case HB_ASPECT_BASE * 221 / 100:   return "2.21:1";
37     }
38     static char arstr[32];
39     double a = (double)aspect / HB_ASPECT_BASE;
40     sprintf( arstr, aspect >= 1.? "%.2f:1" : "1:%.2f", a );
41     return arstr;
42 }
43
44 hb_thread_t * hb_scan_init( hb_handle_t * handle, const char * path,
45                             int title_index, hb_list_t * list_title )
46 {
47     hb_scan_t * data = calloc( sizeof( hb_scan_t ), 1 );
48
49     data->h            = handle;
50     data->path         = strdup( path );
51     data->title_index  = title_index;
52     data->list_title   = list_title;
53
54     return hb_thread_init( "scan", ScanFunc, data, HB_NORMAL_PRIORITY );
55 }
56
57 static void ScanFunc( void * _data )
58 {
59     hb_scan_t  * data = (hb_scan_t *) _data;
60     hb_title_t * title;
61     int          i;
62
63         data->dvd = NULL;
64         data->stream = NULL;
65
66     /* Try to open the path as a DVD. If it fails, try as a file */
67     hb_log( "scan: trying to open with libdvdread" );
68     if( ( data->dvd = hb_dvd_init( data->path ) ) )
69     {
70         hb_log( "scan: DVD has %d title(s)",
71                 hb_dvd_title_count( data->dvd ) );
72         if( data->title_index )
73         {
74             /* Scan this title only */
75             hb_list_add( data->list_title, hb_dvd_title_scan( data->dvd,
76                             data->title_index ) );
77         }
78         else
79         {
80             /* Scan all titles */
81             for( i = 0; i < hb_dvd_title_count( data->dvd ); i++ )
82             {
83                 hb_list_add( data->list_title,
84                              hb_dvd_title_scan( data->dvd, i + 1 ) );
85             }
86         }
87     }
88     else if ( (data->stream = hb_stream_open( data->path, 0 ) ) != NULL )
89     {
90         hb_list_add( data->list_title, hb_stream_title_scan( data->stream ) );
91     }
92     else
93     {
94         hb_log( "scan: unrecognized file type" );
95         return;
96     }
97
98     for( i = 0; i < hb_list_count( data->list_title ); )
99     {
100         int j;
101         hb_state_t state;
102         hb_audio_t * audio;
103         hb_title_t * title_tmp = NULL;
104
105         title = hb_list_item( data->list_title, i );
106
107         /* I've seen a DVD with strictly identical titles. Check this
108            here and ignore it if redundant */
109         for( j = 0; j < i; j++ )
110         {
111             title_tmp = hb_list_item( data->list_title, j );
112             if( title->vts         == title_tmp->vts &&
113                 title->block_start == title_tmp->block_start &&
114                 title->block_end   == title_tmp->block_end &&
115                 title->block_count == title_tmp->block_count )
116             {
117                 break;
118             }
119             else
120             {
121                 title_tmp = NULL;
122             }
123         }
124         if( title_tmp )
125         {
126             hb_log( "scan: title %d is duplicate with title %d",
127                     title->index, title_tmp->index );
128             hb_list_rem( data->list_title, title );
129             free( title );      /* This _will_ leak! */
130             continue;
131         }
132
133 #define p state.param.scanning
134         /* Update the UI */
135         state.state   = HB_STATE_SCANNING;
136         p.title_cur   = title->index;
137         p.title_count = data->dvd ? hb_dvd_title_count( data->dvd ) : hb_list_count(data->list_title);
138         hb_set_state( data->h, &state );
139 #undef p
140
141         /* Decode previews */
142         /* this will also detect more AC3 / DTS information */
143         if( !DecodePreviews( data, title ) )
144         {
145             /* TODO: free things */
146             hb_list_rem( data->list_title, title );
147             continue;
148         }
149
150         /* Make sure we found audio rates and bitrates */
151         for( j = 0; j < hb_list_count( title->list_audio ); )
152         {
153             audio = hb_list_item( title->list_audio, j );
154             if( !audio->config.in.bitrate )
155             {
156                 hb_log( "scan: removing audio 0x%x because no bitrate found",
157                         audio->id );
158                 hb_list_rem( title->list_audio, audio );
159                 free( audio );
160                 continue;
161             }
162             j++;
163         }
164
165         /* If we don't have any audio streams left, remove the title */
166         if( !hb_list_count( title->list_audio ) )
167         {
168             hb_list_rem( data->list_title, title );
169             free( title );
170             continue;
171         }
172
173         i++;
174     }
175
176     /* Init jobs templates */
177     for( i = 0; i < hb_list_count( data->list_title ); i++ )
178     {
179         hb_job_t * job;
180
181         title      = hb_list_item( data->list_title, i );
182         job        = calloc( sizeof( hb_job_t ), 1 );
183         title->job = job;
184
185         job->title = title;
186
187         /* Set defaults settings */
188         job->chapter_start = 1;
189         job->chapter_end   = hb_list_count( title->list_chapter );
190
191         /* Autocrop by default. Gnark gnark */
192         memcpy( job->crop, title->crop, 4 * sizeof( int ) );
193
194         /* Preserve a source's pixel aspect, if it's available. */
195         if( title->pixel_aspect_width && title->pixel_aspect_height )
196         {
197             job->pixel_aspect_width  = title->pixel_aspect_width;
198             job->pixel_aspect_height = title->pixel_aspect_height;
199         }
200
201         if( title->aspect == 16 && !job->pixel_aspect_width && !job->pixel_aspect_height)
202         {
203             hb_reduce( &job->pixel_aspect_width, &job->pixel_aspect_height,
204                        16 * title->height, 9 * title->width );
205         }
206         else if( !job->pixel_aspect_width && !job->pixel_aspect_height )
207         {
208             hb_reduce( &job->pixel_aspect_width, &job->pixel_aspect_height,
209                        4 * title->height, 3 * title->width );
210         }
211
212         job->width = title->width - job->crop[2] - job->crop[3];
213         hb_fix_aspect( job, HB_KEEP_WIDTH );
214         if( job->height > title->height - job->crop[0] - job->crop[1] )
215         {
216             job->height = title->height - job->crop[0] - job->crop[1];
217             hb_fix_aspect( job, HB_KEEP_HEIGHT );
218         }
219
220         hb_log( "scan: title (%d) job->width:%d, job->height:%d",
221                 i, job->width, job->height );
222
223         job->keep_ratio = 1;
224
225         job->vcodec     = HB_VCODEC_FFMPEG;
226         job->vquality   = -1.0;
227         job->vbitrate   = 1000;
228         job->pass       = 0;
229         job->vrate      = title->rate;
230         job->vrate_base = title->rate_base;
231
232         job->list_audio = hb_list_init();
233
234         job->subtitle = -1;
235
236         job->mux = HB_MUX_MP4;
237     }
238
239     if( data->dvd )
240     {
241         hb_dvd_close( &data->dvd );
242     }
243         if (data->stream)
244         {
245                 hb_stream_close(&data->stream);
246         }
247     free( data->path );
248     free( data );
249     _data = NULL;
250 }
251
252 // -----------------------------------------------
253 // stuff related to cropping
254
255 #define DARK 64
256
257 static int row_all_dark( hb_title_t *title, uint8_t* luma, int row )
258 {
259     int i = title->width;
260     luma += i * row;
261     while ( --i >= 0 )
262     {
263         if ( *luma++ > DARK )
264             return 0;
265     }
266     return 1;
267 }
268
269 static int column_all_dark( hb_title_t *title, uint8_t* luma, int top, int col )
270 {
271     int i = title->height - top;
272     int stride = title->width;
273     luma += stride * top + col;
274     for ( ; --i >= 0; luma += stride )
275     {
276         if ( *luma > DARK )
277             return 0;
278     }
279     return 1;
280 }
281 #undef DARK
282
283 typedef struct {
284     int n;
285     int t[10];
286     int b[10];
287     int l[10];
288     int r[10];
289 } crop_record_t;
290
291 static void record_crop( crop_record_t *crops, int t, int b, int l, int r )
292 {
293     crops->t[crops->n] = t;
294     crops->b[crops->n] = b;
295     crops->l[crops->n] = l;
296     crops->r[crops->n] = r;
297     ++crops->n;
298 }
299
300 static int compare_int( const void *a, const void *b )
301 {
302     return *(const int *)a - *(const int *)b;
303 }
304
305 static void sort_crops( crop_record_t *crops )
306 {
307     qsort( crops->t, crops->n, sizeof(crops->t[0]), compare_int );
308     qsort( crops->b, crops->n, sizeof(crops->t[0]), compare_int );
309     qsort( crops->l, crops->n, sizeof(crops->t[0]), compare_int );
310     qsort( crops->r, crops->n, sizeof(crops->t[0]), compare_int );
311 }
312
313 // -----------------------------------------------
314 // stuff related to title width/height/aspect info
315
316 typedef struct {
317     int count;              /* number of times we've seen this info entry */
318     hb_work_info_t info;    /* copy of info entry */
319 } info_list_t;
320
321 static void remember_info( info_list_t *info_list, hb_work_info_t *info )
322 {
323     for ( ; info_list->count; ++info_list )
324     {
325         if ( memcmp( &info_list->info, info, sizeof(*info) ) == 0 )
326         {
327             // we found a match - bump its count
328             ++info_list->count;
329             return;
330         }
331     }
332     // no match found - add new entry to list (info_list points to
333     // the first free slot). NB - we assume that info_list was allocated
334     // so that it's big enough even if there are no dups. I.e., 10 slots
335     // allocated if there are 10 previews.
336     info_list->count = 1;
337     info_list->info = *info;
338 }
339
340 static void most_common_info( info_list_t *info_list, hb_work_info_t *info )
341 {
342     int i, biggest = 0;
343     for ( i = 1; info_list[i].count; ++i )
344     {
345         if ( info_list[i].count > info_list[biggest].count )
346             biggest = i;
347     }
348     *info = info_list[biggest].info;
349     free( info_list );
350 }
351
352 /***********************************************************************
353  * DecodePreviews
354  ***********************************************************************
355  * Decode 10 pictures for the given title.
356  * It assumes that data->reader and data->vts have successfully been
357  * DVDOpen()ed and ifoOpen()ed.
358  **********************************************************************/
359 static int DecodePreviews( hb_scan_t * data, hb_title_t * title )
360 {
361     int             i, npreviews = 0;
362     hb_buffer_t   * buf_ps, * buf_es;
363     hb_list_t     * list_es;
364     int progressive_count = 0;
365     int interlaced_preview_count = 0;
366     info_list_t * info_list = calloc( 10+1, sizeof(*info_list) );
367     crop_record_t *crops = calloc( 1, sizeof(*crops) );
368
369     buf_ps   = hb_buffer_init( HB_DVD_READ_BUFFER_SIZE );
370     list_es  = hb_list_init();
371
372     hb_log( "scan: decoding previews for title %d", title->index );
373
374     if (data->dvd)
375       hb_dvd_start( data->dvd, title->index, 1 );
376
377     for( i = 0; i < 10; i++ )
378     {
379         int j;
380         FILE * file_preview;
381         char   filename[1024];
382
383         if (data->dvd)
384         {
385           if( !hb_dvd_seek( data->dvd, (float) ( i + 1 ) / 11.0 ) )
386           {
387               continue;
388           }
389         }
390         else if (data->stream)
391         {
392           /* we start reading streams at zero rather than 1/11 because
393            * short streams may have only one sequence header in the entire
394            * file and we need it to decode any previews. */
395           if (!hb_stream_seek(data->stream, (float) i / 11.0 ) )
396           {
397               continue;
398           }
399         }
400
401         hb_log( "scan: preview %d", i + 1 );
402
403         int vcodec = title->video_codec? title->video_codec : WORK_DECMPEG2;
404         hb_work_object_t *vid_decoder = hb_get_work( vcodec );
405         vid_decoder->codec_param = title->video_codec_param;
406         vid_decoder->init( vid_decoder, NULL );
407         hb_buffer_t * vid_buf = NULL;
408
409         for( j = 0; j < 10240 ; j++ )
410         {
411             if (data->dvd)
412             {
413               if( !hb_dvd_read( data->dvd, buf_ps ) )
414               {
415                   hb_log( "Warning: Could not read data for preview %d, skipped", i + 1 );
416                   goto skip_preview;
417               }
418             }
419             else if (data->stream)
420             {
421               if ( !hb_stream_read(data->stream,buf_ps) )
422               {
423                   hb_log( "Warning: Could not read data for preview %d, skipped", i + 1 );
424                   goto skip_preview;
425               }
426             }
427             if ( title->demuxer == HB_NULL_DEMUXER )
428             {
429                 hb_demux_null( buf_ps, list_es, 0 );
430             }
431             else
432             {
433                 hb_demux_ps( buf_ps, list_es, 0 );
434             }
435
436             while( ( buf_es = hb_list_item( list_es, 0 ) ) )
437             {
438                 hb_list_rem( list_es, buf_es );
439                 if( buf_es->id == title->video_id && vid_buf == NULL )
440                 {
441                     vid_decoder->work( vid_decoder, &buf_es, &vid_buf );
442                 }
443                 else if( ! AllAudioOK( title ) )
444                 {
445                     LookForAudio( title, buf_es );
446                 }
447                 if ( buf_es )
448                     hb_buffer_close( &buf_es );
449             }
450
451             if( vid_buf && AllAudioOK( title ) )
452                 break;
453         }
454
455         if( ! vid_buf )
456         {
457             hb_log( "scan: could not get a decoded picture" );
458             continue;
459         }
460
461         /* Get size and rate infos */
462
463         hb_work_info_t vid_info;
464         vid_decoder->info( vid_decoder, &vid_info );
465         vid_decoder->close( vid_decoder );
466         free( vid_decoder );
467
468         remember_info( info_list, &vid_info );
469
470         title->width = vid_info.width;
471         title->height = vid_info.height;
472         title->rate = vid_info.rate;
473         title->rate_base = vid_info.rate_base;
474
475         if( title->rate_base == 1126125 )
476         {
477             /* Frame FPS is 23.976 (meaning it's progressive), so
478                start keeping track of how many are reporting at
479                that speed. When enough show up that way, we want
480                to make that the overall title FPS.
481             */
482             progressive_count++;
483
484             if( progressive_count < 6 )
485             {
486                 /* Not enough frames are reporting as progressive,
487                    which means we should be conservative and use
488                    29.97 as the title's FPS for now.
489                 */
490                 title->rate_base = 900900;
491             }
492             else
493             {
494                 /* A majority of the scan frames are progressive. Make that
495                     the title's FPS, and announce it once to the log.
496                 */
497                 if( progressive_count == 6 )
498                 {
499                     hb_log("Title's mostly NTSC Film, setting fps to 23.976");
500                 }
501                 title->rate_base = 1126125;
502             }
503         }
504         else if( title->rate_base == 900900 && progressive_count >= 6 )
505         {
506             /*
507              * We've already deduced that the frame rate is 23.976, so set it
508              * back again.
509              */
510             title->rate_base = 1126125;
511         }
512
513         while( ( buf_es = hb_list_item( list_es, 0 ) ) )
514         {
515             hb_list_rem( list_es, buf_es );
516             hb_buffer_close( &buf_es );
517         }
518
519         /* Check preview for interlacing artifacts */
520         if( hb_detect_comb( vid_buf, title->width, title->height, 10, 30, 9, 10, 30, 9 ) )
521         {
522             hb_log("Interlacing detected in preview frame %i", i+1);
523             interlaced_preview_count++;
524         }
525
526         hb_get_tempory_filename( data->h, filename, "%x%d",
527                                  (intptr_t)title, i );
528
529         file_preview = fopen( filename, "w" );
530         if( file_preview )
531         {
532             fwrite( vid_buf->data, title->width * title->height * 3 / 2,
533                     1, file_preview );
534             fclose( file_preview );
535         }
536         else
537         {
538             hb_log( "scan: fopen failed (%s)", filename );
539         }
540
541         /* Detect black borders */
542
543 #define Y    vid_buf->data
544         int top, bottom, left, right;
545         int h4 = title->height / 4, w4 = title->width / 4;
546         for ( top = 2; top < h4; ++top )
547         {
548             if ( ! row_all_dark( title, Y, top ) )
549                 break;
550         }
551         if ( top < 4 )
552         {
553             // we started at row two to avoid the "line 19" noise that shows
554             // up on row 0 & 1 of some TV shows. Since we stopped before row 4
555             // check if row 0 & 1 are dark or if we shouldn't crop the top at all.
556             if ( row_all_dark( title, Y, 0 ) )
557             {
558                 top = row_all_dark( title, Y, 1 )? top : 1;
559             }
560             else
561             {
562                 top = 0;
563             }
564         }
565         for ( bottom = 0; bottom < h4; ++bottom )
566         {
567             if ( ! row_all_dark( title, Y, title->height - 1 - bottom ) )
568                 break;
569         }
570         for ( left = 0; left < w4; ++left )
571         {
572             if ( ! column_all_dark( title, Y, top, left ) )
573                 break;
574         }
575         for ( right = 0; right < w4; ++right )
576         {
577             if ( ! column_all_dark( title, Y, top, title->width - 1 - right ) )
578                 break;
579         }
580
581         // only record the result if all the crops are less than a quarter of
582         // the frame otherwise we can get fooled by frames with a lot of black
583         // like titles, credits & fade-thru-black transitions.
584         if ( top < h4 && bottom < h4 && left < w4 && right < w4 )
585         {
586             record_crop( crops, top, bottom, left, right );
587         }
588         ++npreviews;
589
590 skip_preview:
591         if ( vid_buf )
592             hb_buffer_close( &vid_buf );
593     }
594
595     if ( npreviews )
596     {
597         // use the most common frame info for our final title dimensions
598         hb_work_info_t vid_info;
599         most_common_info( info_list, &vid_info );
600
601         title->width = vid_info.width;
602         title->height = vid_info.height;
603         title->pixel_aspect_width = vid_info.pixel_aspect_width;
604         title->pixel_aspect_height = vid_info.pixel_aspect_height;
605
606         // compute the aspect ratio based on the storage dimensions and the
607         // pixel aspect ratio (if supplied) or just storage dimensions if no PAR.
608         title->aspect = ( (double)title->width / (double)title->height + 0.05 ) *
609                         HB_ASPECT_BASE;
610
611         double aspect = (double)title->width / (double)title->height;
612         if( title->pixel_aspect_width && title->pixel_aspect_height )
613         {
614             aspect *= (double)title->pixel_aspect_width /
615                       (double)title->pixel_aspect_height;
616         }
617         title->aspect = ( aspect + 0.05 ) * HB_ASPECT_BASE;
618
619         if ( crops->n )
620         {
621             sort_crops( crops );
622             // The next line selects median cropping - at least
623             // 50% of the frames will have their borders removed.
624             // Other possible choices are loose cropping (i = 0) where 
625             // no non-black pixels will be cropped from any frame and a
626             // tight cropping (i = crops->n - (crops->n >> 2)) where at
627             // least 75% of the frames will have their borders removed.
628             i = crops->n >> 1;
629             title->crop[0] = EVEN( crops->t[i] );
630             title->crop[1] = EVEN( crops->b[i] );
631             title->crop[2] = EVEN( crops->l[i] );
632             title->crop[3] = EVEN( crops->r[i] );
633         }
634         free( crops );
635
636         hb_log( "scan: %d previews, %dx%d, %.3f fps, autocrop = %d/%d/%d/%d, "
637                 "aspect %s, PAR %d:%d",
638                 npreviews, title->width, title->height, (float) title->rate /
639                 (float) title->rate_base,
640                 title->crop[0], title->crop[1], title->crop[2], title->crop[3],
641                 aspect_to_string( title->aspect ), title->pixel_aspect_width,
642                 title->pixel_aspect_height );
643
644         if( interlaced_preview_count >= ( npreviews / 2 ) )
645         {
646             hb_log("Title is likely interlaced or telecined (%i out of %i previews). You should do something about that.",
647                    interlaced_preview_count, npreviews);
648             title->detected_interlacing = 1;
649         }
650         else
651         {
652             title->detected_interlacing = 0;
653         }
654     }
655
656     hb_buffer_close( &buf_ps );
657     while( ( buf_es = hb_list_item( list_es, 0 ) ) )
658     {
659         hb_list_rem( list_es, buf_es );
660         hb_buffer_close( &buf_es );
661     }
662     hb_list_close( &list_es );
663     if (data->dvd)
664       hb_dvd_stop( data->dvd );
665
666     return npreviews;
667 }
668
669 /*
670  * This routine is called for every frame from a non-video elementary stream.
671  * These are a mix of audio & subtitle streams, some of which we want & some
672  * we're ignoring. This routine checks the frame against all our audio streams
673  * to see if it's one we want and haven't identified yet. If yes, it passes the
674  * frame to a codec-specific id routine which is responsible for filling in
675  * the sample rate, bit rate, channels & other audio parameters.
676  *
677  * Since a sample rate is essential for further audio processing, any audio
678  * stream which isn't successfully id'd by is deleted at the end of the scan.
679  * This is necessary to avoid ambiguities where things that might be audio
680  * aren't (e.g., some European DVD Teletext streams use the same IDs as US ATSC
681  * AC-3 audio).
682  */
683 static void LookForAudio( hb_title_t * title, hb_buffer_t * b )
684 {
685     int i;
686
687     hb_audio_t * audio = NULL;
688     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
689     {
690         audio = hb_list_item( title->list_audio, i );
691         /* check if this elementary stream is one we want */
692         if ( audio->id == b->id )
693         {
694             break;
695         }
696         else
697         {
698             audio = NULL;
699         }
700     }
701     if( !audio || audio->config.in.bitrate != 0 )
702     {
703         /* not found or already done */
704         return;
705     }
706
707     hb_work_object_t *w = hb_codec_decoder( audio->config.in.codec );
708
709     if ( w == NULL || w->bsinfo == NULL )
710     {
711         hb_log( "Internal error in scan: unhandled audio type %d for id 0x%x",
712                 audio->config.in.codec, audio->id );
713         goto drop_audio;
714     }
715
716     hb_work_info_t info;
717     w->audio = audio;
718     w->codec_param = audio->config.in.codec_param;
719     int ret = w->bsinfo( w, b, &info );
720     if ( ret < 0 )
721     {
722         hb_log( "no info on audio type %d/0x%x for id 0x%x",
723                 audio->config.in.codec, audio->config.in.codec_param,
724                 audio->id );
725         goto drop_audio;
726     }
727     if ( !info.bitrate )
728     {
729         /* didn't find any info */
730         return;
731     }
732     audio->config.in.samplerate = info.rate;
733     audio->config.in.bitrate = info.bitrate;
734     audio->config.in.channel_layout = info.channel_layout;
735     audio->config.flags.ac3 = info.flags;
736
737     // update the audio description string based on the info we found
738     if ( audio->config.flags.ac3 & AUDIO_F_DOLBY )
739     {
740         strcat( audio->config.lang.description, " (Dolby Surround)" );
741     }
742     else
743     {
744         int layout = audio->config.in.channel_layout;
745         char *desc = audio->config.lang.description +
746                         strlen( audio->config.lang.description );
747         sprintf( desc, " (%d.%d ch)",
748                  HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(layout) +
749                      HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(layout),
750                  HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(layout) );
751     }
752
753     hb_log( "scan: audio 0x%x: %s, rate=%dHz, bitrate=%d %s", audio->id,
754             info.name, audio->config.in.samplerate, audio->config.in.bitrate,
755             audio->config.lang.description );
756  
757     free( w );
758     return;
759
760     // We get here if there's no hope of finding info on an audio bitstream,
761     // either because we don't have a decoder (or a decoder with a bitstream
762     // info proc) or because the decoder's info proc said that the stream
763     // wasn't something it could handle. Delete the item from the title's
764     // audio list so we won't keep reading packets while trying to get its
765     // bitstream info.
766  drop_audio:
767     if ( w )
768         free( w );
769
770     hb_list_rem( title->list_audio, audio );
771 }
772
773 /*
774  * This routine checks to see if we've ID'd all the audio streams associated
775  * with a title. It returns 0 if there are more to ID & 1 if all are done.
776  */
777 static int  AllAudioOK( hb_title_t * title )
778 {
779     int i;
780     hb_audio_t * audio;
781
782     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
783     {
784         audio = hb_list_item( title->list_audio, i );
785         if( audio->config.in.bitrate == 0 )
786         {
787             return 0;
788         }
789     }
790     return 1;
791 }