OSDN Git Service

Saearch & Replace domain names to move from .m0k.org to handbrake.fr. Only covers...
[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 hb_thread_t * hb_scan_init( hb_handle_t * handle, const char * path,
30                             int title_index, hb_list_t * list_title )
31 {
32     hb_scan_t * data = calloc( sizeof( hb_scan_t ), 1 );
33
34     data->h            = handle;
35     data->path         = strdup( path );
36     data->title_index  = title_index;
37     data->list_title   = list_title;
38
39     return hb_thread_init( "scan", ScanFunc, data, HB_NORMAL_PRIORITY );
40 }
41
42 static void ScanFunc( void * _data )
43 {
44     hb_scan_t  * data = (hb_scan_t *) _data;
45     hb_title_t * title;
46     int          i;
47
48         data->dvd = NULL;
49         data->stream = NULL;
50
51     /* Try to open the path as a DVD. If it fails, try as a file */
52     hb_log( "scan: trying to open with libdvdread" );
53     if( ( data->dvd = hb_dvd_init( data->path ) ) )
54     {
55         hb_log( "scan: DVD has %d title(s)",
56                 hb_dvd_title_count( data->dvd ) );
57         if( data->title_index )
58         {
59             /* Scan this title only */
60             hb_list_add( data->list_title, hb_dvd_title_scan( data->dvd,
61                             data->title_index ) );
62         }
63         else
64         {
65             /* Scan all titles */
66             for( i = 0; i < hb_dvd_title_count( data->dvd ); i++ )
67             {
68                 hb_list_add( data->list_title,
69                              hb_dvd_title_scan( data->dvd, i + 1 ) );
70             }
71         }
72     }
73     else if ( (data->stream = hb_stream_open( data->path, 0 ) ) != NULL )
74     {
75         hb_list_add( data->list_title, hb_stream_title_scan( data->stream ) );
76     }
77     else
78     {
79         hb_log( "scan: unrecognized file type" );
80         return;
81     }
82
83     for( i = 0; i < hb_list_count( data->list_title ); )
84     {
85         int j;
86         hb_state_t state;
87         hb_audio_t * audio;
88         hb_title_t * title_tmp = NULL;
89
90         title = hb_list_item( data->list_title, i );
91
92         /* I've seen a DVD with strictly identical titles. Check this
93            here and ignore it if redundant */
94         for( j = 0; j < i; j++ )
95         {
96             title_tmp = hb_list_item( data->list_title, j );
97             if( title->vts         == title_tmp->vts &&
98                 title->block_start == title_tmp->block_start &&
99                 title->block_end   == title_tmp->block_end &&
100                 title->block_count == title_tmp->block_count )
101             {
102                 break;
103             }
104             else
105             {
106                 title_tmp = NULL;
107             }
108         }
109         if( title_tmp )
110         {
111             hb_log( "scan: title %d is duplicate with title %d",
112                     title->index, title_tmp->index );
113             hb_list_rem( data->list_title, title );
114             free( title );      /* This _will_ leak! */
115             continue;
116         }
117
118 #define p state.param.scanning
119         /* Update the UI */
120         state.state   = HB_STATE_SCANNING;
121         p.title_cur   = title->index;
122         p.title_count = data->dvd ? hb_dvd_title_count( data->dvd ) : hb_list_count(data->list_title);
123         hb_set_state( data->h, &state );
124 #undef p
125
126         /* Decode previews */
127         /* this will also detect more AC3 / DTS information */
128         if( !DecodePreviews( data, title ) )
129         {
130             /* TODO: free things */
131             hb_list_rem( data->list_title, title );
132             continue;
133         }
134
135         /* Make sure we found audio rates and bitrates */
136         for( j = 0; j < hb_list_count( title->list_audio ); )
137         {
138             audio = hb_list_item( title->list_audio, j );
139             if( !audio->config.in.bitrate )
140             {
141                 hb_log( "scan: removing audio 0x%x because no bitrate found",
142                         audio->id );
143                 hb_list_rem( title->list_audio, audio );
144                 free( audio );
145                 continue;
146             }
147             j++;
148         }
149
150         /* If we don't have any audio streams left, remove the title */
151         if( !hb_list_count( title->list_audio ) )
152         {
153             hb_list_rem( data->list_title, title );
154             free( title );
155             continue;
156         }
157
158         i++;
159     }
160
161     /* Init jobs templates */
162     for( i = 0; i < hb_list_count( data->list_title ); i++ )
163     {
164         hb_job_t * job;
165
166         title      = hb_list_item( data->list_title, i );
167         job        = calloc( sizeof( hb_job_t ), 1 );
168         title->job = job;
169
170         job->title = title;
171
172         /* Set defaults settings */
173         job->chapter_start = 1;
174         job->chapter_end   = hb_list_count( title->list_chapter );
175
176         /* Autocrop by default. Gnark gnark */
177         memcpy( job->crop, title->crop, 4 * sizeof( int ) );
178
179         if( title->aspect == 16 )
180         {
181             hb_reduce( &job->pixel_aspect_width, &job->pixel_aspect_height,
182                        16 * title->height, 9 * title->width );
183         }
184         else
185         {
186             hb_reduce( &job->pixel_aspect_width, &job->pixel_aspect_height,
187                        4 * title->height, 3 * title->width );
188         }
189
190         job->width = title->width - job->crop[2] - job->crop[3];
191         hb_fix_aspect( job, HB_KEEP_WIDTH );
192         if( job->height > title->height - job->crop[0] - job->crop[1] )
193         {
194             job->height = title->height - job->crop[0] - job->crop[1];
195             hb_fix_aspect( job, HB_KEEP_HEIGHT );
196         }
197
198         hb_log( "scan: title (%d) job->width:%d, job->height:%d",
199                 i, job->width, job->height );
200
201         job->keep_ratio = 1;
202
203         job->vcodec     = HB_VCODEC_FFMPEG;
204         job->vquality   = -1.0;
205         job->vbitrate   = 1000;
206         job->pass       = 0;
207         job->vrate      = title->rate;
208         job->vrate_base = title->rate_base;
209
210         job->list_audio = hb_list_init();
211
212         job->subtitle = -1;
213
214         job->mux = HB_MUX_MP4;
215     }
216
217     if( data->dvd )
218     {
219         hb_dvd_close( &data->dvd );
220     }
221         if (data->stream)
222         {
223                 hb_stream_close(&data->stream);
224         }
225     free( data->path );
226     free( data );
227     _data = NULL;
228 }
229
230 /***********************************************************************
231  * DecodePreviews
232  ***********************************************************************
233  * Decode 10 pictures for the given title.
234  * It assumes that data->reader and data->vts have successfully been
235  * DVDOpen()ed and ifoOpen()ed.
236  **********************************************************************/
237 static int DecodePreviews( hb_scan_t * data, hb_title_t * title )
238 {
239     int             i, npreviews = 0;
240     hb_buffer_t   * buf_ps, * buf_es, * buf_raw;
241     hb_list_t     * list_es, * list_raw;
242     hb_libmpeg2_t * mpeg2;
243     int progressive_count = 0;
244     int interlaced_preview_count = 0;
245     int last_ar = 0, ar16_count = 0, ar4_count = 0;
246
247     buf_ps   = hb_buffer_init( HB_DVD_READ_BUFFER_SIZE );
248     list_es  = hb_list_init();
249     list_raw = hb_list_init();
250
251     hb_log( "scan: decoding previews for title %d", title->index );
252
253     if (data->dvd)
254       hb_dvd_start( data->dvd, title->index, 1 );
255
256     for( i = 0; i < 10; i++ )
257     {
258         int j, k;
259         FILE * file_preview;
260         char   filename[1024];
261
262         if (data->dvd)
263         {
264           if( !hb_dvd_seek( data->dvd, (float) ( i + 1 ) / 11.0 ) )
265           {
266               goto error;
267           }
268         }
269         else if (data->stream)
270         {
271           /* we start reading streams at zero rather than 1/11 because
272            * short streams may have only one sequence header in the entire
273            * file and we need it to decode any previews. */
274           if (!hb_stream_seek(data->stream, (float) i / 11.0 ) )
275           {
276             goto error;
277           }
278         }
279
280         hb_log( "scan: preview %d", i + 1 );
281
282         mpeg2 = hb_libmpeg2_init();
283
284         for( j = 0; j < 10240 ; j++ )
285         {
286             if (data->dvd)
287             {
288               if( !hb_dvd_read( data->dvd, buf_ps ) )
289               {
290                   hb_log( "Warning: Could not read data for preview %d, skipped", i + 1 );
291                   goto skip_preview;
292               }
293             }
294             else if (data->stream)
295             {
296               if ( !hb_stream_read(data->stream,buf_ps) )
297               {
298                   hb_log( "Warning: Could not read data for preview %d, skipped", i + 1 );
299                   goto skip_preview;
300               }
301             }
302             hb_demux_ps( buf_ps, list_es );
303
304             while( ( buf_es = hb_list_item( list_es, 0 ) ) )
305             {
306                 hb_list_rem( list_es, buf_es );
307                 if( buf_es->id == 0xE0 && !hb_list_count( list_raw ) )
308                 {
309                     hb_libmpeg2_decode( mpeg2, buf_es, list_raw );
310                     int ar = hb_libmpeg2_clear_aspect_ratio( mpeg2 );
311                     if ( ar != 0 )
312                     {
313                         if ( ar != last_ar && last_ar != 0 )
314                         {
315                             hb_log( "aspect ratio changed from %d to %d",
316                                     last_ar, ar );
317                         }
318                         switch ( ar )
319                         {
320                             case HB_ASPECT_BASE * 4 / 3:
321                                 ++ar4_count;
322                                 break;
323                             case HB_ASPECT_BASE * 16 / 9:
324                                 ++ar16_count;
325                                 break;
326                             default:
327                                 hb_log( "unknown aspect ratio %d", ar );
328                                 /* if the aspect is closer to 4:3 use that
329                                  * otherwise use 16:9 */
330                                 if ( ar < HB_ASPECT_BASE * 14 / 9 )
331                                 {
332                                     ++ar4_count;
333                                 }
334                                 else
335                                 {
336                                     ++ar16_count;
337                                 }
338                                 break;
339                         }
340                     }
341                     last_ar = ar;
342                 }
343                 else if( ! AllAudioOK( title ) )
344                 {
345                     LookForAudio( title, buf_es );
346                 }
347                 hb_buffer_close( &buf_es );
348
349                 if( hb_list_count( list_raw ) && AllAudioOK( title ) )
350                 {
351                     /* We got a picture */
352                     break;
353                 }
354             }
355
356             if( hb_list_count( list_raw ) && AllAudioOK( title ) )
357             {
358                 break;
359             }
360         }
361
362         if( !hb_list_count( list_raw ) )
363         {
364             hb_log( "scan: could not get a decoded picture" );
365             continue;
366         }
367
368         /* Get size and rate infos */
369         title->rate = 27000000;
370         int ar;
371         hb_libmpeg2_info( mpeg2, &title->width, &title->height,
372                           &title->rate_base, &ar );
373
374         /* if we found mostly 4:3 previews use that as the aspect ratio otherwise
375            use 16:9 */
376         title->aspect = ar4_count > ar16_count ?
377                             HB_ASPECT_BASE * 4 / 3 : HB_ASPECT_BASE * 16 / 9;
378
379         if( title->rate_base == 1126125 )
380         {
381             /* Frame FPS is 23.976 (meaning it's progressive), so
382                start keeping track of how many are reporting at
383                that speed. When enough show up that way, we want
384                to make that the overall title FPS.
385             */
386             progressive_count++;
387
388             if( progressive_count < 6 )
389             {
390                 /* Not enough frames are reporting as progressive,
391                    which means we should be conservative and use
392                    29.97 as the title's FPS for now.
393                 */
394                 title->rate_base = 900900;
395             }
396             else
397             {
398                 /* A majority of the scan frames are progressive. Make that
399                     the title's FPS, and announce it once to the log.
400                 */
401                 if( progressive_count == 6 )
402                 {
403                     hb_log("Title's mostly NTSC Film, setting fps to 23.976");
404                 }
405                 title->rate_base = 1126125;
406             }
407         }
408         else if( title->rate_base == 900900 && progressive_count >= 6 )
409         {
410             /*
411              * We've already deduced that the frame rate is 23.976, so set it
412              * back again.
413              */
414             title->rate_base = 1126125;
415         }
416
417         // start from third frame to skip opening logos
418         if( i == 2)
419         {
420             title->crop[0] = title->crop[1] = title->height / 2;
421             title->crop[2] = title->crop[3] = title->width / 2;
422         }
423
424         hb_libmpeg2_close( &mpeg2 );
425
426         while( ( buf_es = hb_list_item( list_es, 0 ) ) )
427         {
428             hb_list_rem( list_es, buf_es );
429             hb_buffer_close( &buf_es );
430         }
431
432         buf_raw = hb_list_item( list_raw, 0 );
433
434         /* Check preview for interlacing artifacts */
435         if( hb_detect_comb( buf_raw, title->width, title->height, 10, 30, 9 ) )
436         {
437             hb_log("Interlacing detected in preview frame %i", i);
438             interlaced_preview_count++;
439         }
440
441         hb_get_tempory_filename( data->h, filename, "%x%d",
442                                  (intptr_t)title, i );
443
444         file_preview = fopen( filename, "w" );
445         if( file_preview )
446         {
447             fwrite( buf_raw->data, title->width * title->height * 3 / 2,
448                     1, file_preview );
449             fclose( file_preview );
450         }
451         else
452         {
453             hb_log( "scan: fopen failed (%s)", filename );
454         }
455
456 #define Y    buf_raw->data
457 #define DARK 64
458
459         /* Detect black borders */
460
461         for( j = 0; j < title->width; j++ )
462         {
463             for( k = 0; k < title->crop[0]; k++ )
464                 if( Y[ k * title->width + j ] > DARK )
465                 {
466                     title->crop[0] = k;
467                     break;
468                 }
469             for( k = 0; k < title->crop[1]; k++ )
470                 if( Y[ ( title->height - k - 1 ) *
471                        title->width + j ] > DARK )
472                 {
473                     title->crop[1] = k;
474                     break;
475                 }
476         }
477         for( j = 0; j < title->height; j++ )
478         {
479             for( k = 0; k < title->crop[2]; k++ )
480                 if( Y[ j * title->width + k ] > DARK )
481                 {
482                     title->crop[2] = k;
483                     break;
484                 }
485             for( k = 0; k < title->crop[3]; k++ )
486                 if( Y[ j * title->width +
487                         title->width - k - 1 ] > DARK )
488                 {
489                     title->crop[3] = k;
490                     break;
491                 }
492         }
493         ++npreviews;
494
495 skip_preview:
496         while( ( buf_raw = hb_list_item( list_raw, 0 ) ) )
497         {
498             hb_list_rem( list_raw, buf_raw );
499             hb_buffer_close( &buf_raw );
500         }
501     }
502
503     title->crop[0] = EVEN( title->crop[0] );
504     title->crop[1] = EVEN( title->crop[1] );
505     title->crop[2] = EVEN( title->crop[2] );
506     title->crop[3] = EVEN( title->crop[3] );
507
508     hb_log( "scan: %d previews, %dx%d, %.3f fps, autocrop = %d/%d/%d/%d, aspect %s",
509             npreviews, title->width, title->height, (float) title->rate /
510             (float) title->rate_base, title->crop[0], title->crop[1],
511             title->crop[2], title->crop[3],
512             title->aspect == HB_ASPECT_BASE * 16 / 9 ? "16:9" :
513                 title->aspect == HB_ASPECT_BASE * 4 / 3 ? "4:3" : "none" );
514
515     if( interlaced_preview_count >= ( npreviews / 2 ) )
516     {
517         hb_log("Title is likely interlaced or telecined (%i out of %i previews). You should do something about that.",
518                interlaced_preview_count, npreviews);
519         title->detected_interlacing = 1;
520     }
521     else
522     {
523         title->detected_interlacing = 0;
524     }
525
526     goto cleanup;
527
528 error:
529     npreviews = 0;
530
531 cleanup:
532     hb_buffer_close( &buf_ps );
533     while( ( buf_es = hb_list_item( list_es, 0 ) ) )
534     {
535         hb_list_rem( list_es, buf_es );
536         hb_buffer_close( &buf_es );
537     }
538     hb_list_close( &list_es );
539     while( ( buf_raw = hb_list_item( list_raw, 0 ) ) )
540     {
541         hb_list_rem( list_raw, buf_raw );
542         hb_buffer_close( &buf_raw );
543     }
544     hb_list_close( &list_raw );
545     if (data->dvd)
546       hb_dvd_stop( data->dvd );
547
548     return npreviews;
549 }
550
551 static void update_audio_description( const char *codec, hb_audio_t *audio,
552                                       int is_dolby )
553 {
554     hb_log( "scan: %s, rate=%dHz, bitrate=%d", codec, audio->config.in.samplerate,
555             audio->config.in.bitrate );
556
557     /* XXX */
558     if ( is_dolby )
559     {
560         strcat( audio->config.lang.description, " (Dolby Surround)" );
561         return;
562     }
563
564     char *desc = audio->config.lang.description +
565                     strlen( audio->config.lang.description );
566     sprintf( desc, " (%d.%d ch)",
567        HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->config.in.channel_layout) +
568        HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->config.in.channel_layout),
569        HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->config.in.channel_layout));
570 }
571
572 static int hb_setup_a52_audio( hb_audio_t *audio, hb_buffer_t *b )
573 {
574     int i, rate, bitrate, flags;
575
576     /* since AC3 frames don't line up with MPEG ES frames scan the
577      * entire frame for an AC3 sync pattern.  */
578     for ( i = 0; i < b->size - 7; ++i )
579     {
580         if( a52_syncinfo( &b->data[i], &flags, &rate, &bitrate ) != 0 )
581         {
582             break;
583         }
584     }
585     if ( i >= b->size - 7 )
586     {
587         /* didn't find AC3 sync */
588         return 0;
589     }
590
591     audio->config.in.samplerate = rate;
592     audio->config.in.bitrate = bitrate;
593
594     switch( flags & A52_CHANNEL_MASK )
595     {
596         /* mono sources */
597         case A52_MONO:
598         case A52_CHANNEL1:
599         case A52_CHANNEL2:
600             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_MONO;
601             break;
602         /* stereo input */
603         case A52_CHANNEL:
604         case A52_STEREO:
605             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
606             break;
607         /* dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input */
608         case A52_DOLBY:
609             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_DOLBY;
610             break;
611         /* 3F/2R input */
612         case A52_3F2R:
613             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F2R;
614             break;
615         /* 3F/1R input */
616         case A52_3F1R:
617             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F1R;
618             break;
619         /* other inputs */
620         case A52_3F:
621             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F;
622             break;
623         case A52_2F1R:
624             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F1R;
625             break;
626         case A52_2F2R:
627             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F2R;
628             break;
629         /* unknown */
630         default:
631             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
632     }
633
634     if (flags & A52_LFE)
635     {
636         audio->config.in.channel_layout |= HB_INPUT_CH_LAYOUT_HAS_LFE;
637     }
638
639     /* store the AC3 flags for future reference
640      * This enables us to find out if we had a stereo or Dolby source later on
641      * Store the ac3 flags in the public ac3flags property too, so we can access
642      * it from the GUI
643      */
644     audio->config.flags.ac3 = audio->priv.config.a52.ac3flags = flags;
645     update_audio_description( "AC3", audio, (flags & A52_CHANNEL_MASK) == A52_DOLBY );
646     return 1;
647 }
648
649 static int hb_setup_dca_audio( hb_audio_t *audio, hb_buffer_t *b )
650 {
651     int i, flags, rate, bitrate, frame_length;
652     dca_state_t * state = dca_init( 0 );
653
654     /* since DCA frames don't line up with MPEG ES frames scan the
655      * entire frame for an DCA sync pattern.  */
656     for ( i = 0; i < b->size - 7; ++i )
657     {
658         if( dca_syncinfo( state, &b->data[i], &flags, &rate, &bitrate,
659                           &frame_length ) )
660         {
661             break;
662         }
663     }
664     if ( i >= b->size - 7 )
665     {
666         /* didn't find DCA sync */
667         return 0;
668     }
669
670     audio->config.in.samplerate = rate;
671     audio->config.in.bitrate = bitrate;
672     switch( flags & DCA_CHANNEL_MASK )
673     {
674         /* mono sources */
675         case DCA_MONO:
676             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_MONO;
677             break;
678         /* stereo input */
679         case DCA_CHANNEL:
680         case DCA_STEREO:
681         case DCA_STEREO_SUMDIFF:
682         case DCA_STEREO_TOTAL:
683             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
684             break;
685         /* 3F/2R input */
686         case DCA_3F2R:
687             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F2R;
688             break;
689         /* 3F/1R input */
690         case DCA_3F1R:
691             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F1R;
692             break;
693         /* other inputs */
694         case DCA_3F:
695             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_3F;
696             break;
697         case DCA_2F1R:
698             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F1R;
699             break;
700         case DCA_2F2R:
701             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_2F2R;
702             break;
703         case DCA_4F2R:
704             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_4F2R;
705             break;
706         /* unknown */
707         default:
708             audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
709     }
710
711     if (flags & DCA_LFE)
712     {
713         audio->config.in.channel_layout |= HB_INPUT_CH_LAYOUT_HAS_LFE;
714     }
715
716     /* store the DCA flags for future reference
717      * This enables us to find out if we had a stereo or Dolby source later on
718      * store the dca flags in the public dcaflags property too, so we can access
719      * it from the GUI
720      */
721     audio->config.flags.dca = audio->priv.config.dca.dcaflags = flags;
722     update_audio_description( "DCA", audio, (flags & DCA_CHANNEL_MASK) == DCA_DOLBY );
723     return 1;
724 }
725
726 static int hb_setup_pcm_audio( hb_audio_t *audio, hb_buffer_t *b )
727 {
728     // LPCM doesn't have a sync pattern like AC3 or DCA but every
729     // LPCM elementary stream packet starts with a 7 byte header
730     // giving the characteristics of the stream.
731     // See libhb/declpcm.c for a description of the LPCM header.
732
733     static const int hdr2samplerate[] = { 48000, 96000, 44100, 32000 };
734     static const int hdr2samplesize[] = { 16, 20, 24, 16 };
735     static const int hdr2layout[] = {
736             HB_INPUT_CH_LAYOUT_MONO,   HB_INPUT_CH_LAYOUT_STEREO,
737             HB_INPUT_CH_LAYOUT_2F1R,   HB_INPUT_CH_LAYOUT_2F2R,
738             HB_INPUT_CH_LAYOUT_3F2R,   HB_INPUT_CH_LAYOUT_4F2R,
739             HB_INPUT_CH_LAYOUT_STEREO, HB_INPUT_CH_LAYOUT_STEREO,
740     };
741
742     int nchannels  = ( b->data[4] & 7 ) + 1;
743     int sample_size = hdr2samplesize[b->data[4] >> 6];
744
745     int rate = hdr2samplerate[ ( b->data[4] >> 4 ) & 0x3 ];
746     int bitrate = rate * sample_size * nchannels;
747
748     audio->config.in.samplerate = rate;
749     audio->config.in.bitrate = bitrate;
750     audio->config.in.channel_layout = hdr2layout[nchannels - 1];
751     update_audio_description( "LPCM", audio, 0 );
752     return 1;
753 }
754
755 static int hb_setup_mpg_audio( hb_audio_t *audio, hb_buffer_t *b )
756 {
757     /* XXX
758      * This is a placeholder to get the audio sample rate set.
759      * It should be replaced by something that extracts the correct info from
760      * the mpeg audio bitstream.
761      */
762     audio->config.in.samplerate = 48000;
763     audio->config.in.bitrate = 384000;
764     audio->config.in.channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
765     update_audio_description( "MPGA", audio, 0 );
766     return 1;
767 }
768
769 /*
770  * This routine is called for every frame from a non-video elementary stream.
771  * These are a mix of audio & subtitle streams, some of which we want & some
772  * we're ignoring. This routine checks the frame against all our audio streams
773  * to see if it's one we want and haven't identified yet. If yes, it passes the
774  * frame to a codec-specific id routine which is responsible for filling in
775  * the sample rate, bit rate, channels & other audio parameters.
776  *
777  * Since a sample rate is essential for further audio processing, any audio
778  * stream which isn't successfully id'd by is deleted at the end of the scan.
779  * This is necessary to avoid ambiguities where things that might be audio
780  * aren't (e.g., some European DVD Teletext streams use the same IDs as US ATSC
781  * AC-3 audio).
782  */
783 static void LookForAudio( hb_title_t * title, hb_buffer_t * b )
784 {
785     int i;
786
787     hb_audio_t * audio = NULL;
788     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
789     {
790         audio = hb_list_item( title->list_audio, i );
791         /* check if this elementary stream is one we want */
792         if ( audio->id == b->id )
793         {
794             break;
795         }
796         else
797         {
798             audio = NULL;
799         }
800     }
801     if( !audio || audio->config.in.bitrate != 0 )
802     {
803         /* not found or already done */
804         return;
805     }
806
807     switch ( audio->config.in.codec )
808     {
809         case HB_ACODEC_AC3:
810             hb_setup_a52_audio( audio, b );
811             break;
812
813         case HB_ACODEC_DCA:
814             hb_setup_dca_audio( audio, b );
815             break;
816
817         case HB_ACODEC_LPCM:
818             hb_setup_pcm_audio( audio, b );
819             break;
820
821         case HB_ACODEC_MPGA:
822             hb_setup_mpg_audio( audio, b );
823             break;
824
825         default:
826             hb_log( "Internal error in scan: unhandled audio type %d for 0x%x",
827                     audio->config.in.codec, audio->id );
828             break;
829     }
830 }
831
832 /*
833  * This routine checks to see if we've ID'd all the audio streams associated
834  * with a title. It returns 0 if there are more to ID & 1 if all are done.
835  */
836 static int  AllAudioOK( hb_title_t * title )
837 {
838     int i;
839     hb_audio_t * audio;
840
841     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
842     {
843         audio = hb_list_item( title->list_audio, i );
844         if( audio->config.in.bitrate == 0 )
845         {
846             return 0;
847         }
848     }
849     return 1;
850 }