OSDN Git Service

Adds a log message informing the user of which filters are being applied.
[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.m0k.org/>.
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 LookForAC3AndDCA( hb_title_t * title, hb_buffer_t * b );
27 static int  AllAC3AndDCAOK( 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
74     {
75         if ( hb_stream_is_stream_type(data->path) )
76         {
77           hb_log( "scan: trying to open as MPEG-2 Stream");
78                   data->stream = hb_stream_open (data->path);
79           hb_list_add( data->list_title, hb_stream_title_scan( data->stream ) );
80         }
81         else
82         {
83             hb_log( "scan: unrecognized file type" );
84             return;
85         }
86     }
87
88     for( i = 0; i < hb_list_count( data->list_title ); )
89     {
90         int j;
91         hb_state_t state;
92         hb_audio_t * audio;
93         hb_title_t * title_tmp = NULL;
94
95         title = hb_list_item( data->list_title, i );
96
97         /* I've seen a DVD with strictly identical titles. Check this
98            here and ignore it if redundant */
99         for( j = 0; j < i; j++ )
100         {
101             title_tmp = hb_list_item( data->list_title, j );
102             if( title->vts         == title_tmp->vts &&
103                 title->block_start == title_tmp->block_start &&
104                 title->block_end   == title_tmp->block_end &&
105                 title->block_count == title_tmp->block_count )
106             {
107                 break;
108             }
109             else
110             {
111                 title_tmp = NULL;
112             }
113         }
114         if( title_tmp )
115         {
116             hb_log( "scan: title %d is duplicate with title %d",
117                     title->index, title_tmp->index );
118             hb_list_rem( data->list_title, title );
119             free( title );      /* This _will_ leak! */
120             continue;
121         }
122
123 #define p state.param.scanning
124         /* Update the UI */
125         state.state   = HB_STATE_SCANNING;
126         p.title_cur   = title->index;
127         p.title_count = data->dvd ? hb_dvd_title_count( data->dvd ) : hb_list_count(data->list_title);
128         hb_set_state( data->h, &state );
129 #undef p
130
131         /* Decode previews */
132         /* this will also detect more AC3 / DTS information */
133         if( !DecodePreviews( data, title ) )
134         {
135             /* TODO: free things */
136             hb_list_rem( data->list_title, title );
137             continue;
138         }
139         
140                 if (data->stream)
141                 {
142                         // Stream based processing uses PID's to handle the different audio options for a given title
143                         for( j = 0; j < hb_list_count( title->list_audio ); j++ )
144                         {
145                                 audio = hb_list_item( title->list_audio, j );
146                                 hb_stream_update_audio(data->stream, audio);
147                         }
148                 }
149                 else if (data->dvd)
150                 {
151                         /* Make sure we found AC3 rates and bitrates */
152                         for( j = 0; j < hb_list_count( title->list_audio ); )
153                         {
154                                 audio = hb_list_item( title->list_audio, j );
155                                 if( audio->codec == HB_ACODEC_AC3 &&
156                                         !audio->bitrate )
157                                 {
158                                         hb_list_rem( title->list_audio, audio );
159                                         free( audio );
160                                         continue;
161                                 }
162                                 j++;
163                         }
164                 }
165                 
166         /* Make sure we found AC3 / DCA rates and bitrates */
167         for( j = 0; j < hb_list_count( title->list_audio ); )
168         {
169             audio = hb_list_item( title->list_audio, j );
170             if( ( audio->codec == HB_ACODEC_AC3 || audio->codec == HB_ACODEC_DCA ) &&
171                 !audio->bitrate )
172             {
173                 hb_log( "scan: removing audio with codec of 0x%x because of no bitrate",
174                     audio->codec );
175                 hb_list_rem( title->list_audio, audio );
176                 free( audio );
177                 continue;
178             }
179             j++;
180         }
181
182         /* Do we still have audio */
183         if( !hb_list_count( title->list_audio ) )
184         {
185             hb_list_rem( data->list_title, title );
186             free( title );
187             continue;
188         }
189
190         /* set a default input channel layout of stereo for LPCM or MPEG2 audio */
191         /* AC3 and DCA will already have had their layout set via DecodePreviews above, */
192         /* which calls LookForAC3AndDCA */
193         for( j = 0; j < hb_list_count( title->list_audio ); j++ )
194         {
195             audio = hb_list_item( title->list_audio, j );
196             if( audio->codec == HB_ACODEC_LPCM || audio->codec == HB_ACODEC_MPGA )
197             {
198                 audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
199             }
200         }
201         
202         i++;
203     }
204
205     /* Init jobs templates */
206     for( i = 0; i < hb_list_count( data->list_title ); i++ )
207     {
208         hb_job_t * job;
209
210         title      = hb_list_item( data->list_title, i );
211         job        = calloc( sizeof( hb_job_t ), 1 );
212         title->job = job;
213
214         job->title = title;
215
216         /* Set defaults settings */
217         job->chapter_start = 1;
218         job->chapter_end   = hb_list_count( title->list_chapter );
219
220         /* Autocrop by default. Gnark gnark */
221         memcpy( job->crop, title->crop, 4 * sizeof( int ) );
222
223         if( title->aspect == 16 )
224         {
225             hb_reduce( &job->pixel_aspect_width, &job->pixel_aspect_height,
226                        16 * title->height, 9 * title->width );
227         }
228         else
229         {
230             hb_reduce( &job->pixel_aspect_width, &job->pixel_aspect_height,
231                        4 * title->height, 3 * title->width );
232         }
233
234         job->width = title->width - job->crop[2] - job->crop[3];
235 //        job->height = title->height - job->crop[0] - job->crop[1];
236         hb_fix_aspect( job, HB_KEEP_WIDTH );
237         if( job->height > title->height - job->crop[0] - job->crop[1] )
238         {
239             job->height = title->height - job->crop[0] - job->crop[1];
240             hb_fix_aspect( job, HB_KEEP_HEIGHT );
241         }
242
243     hb_log( "scan: title (%d) job->width:%d, job->height:%d",
244             i,job->width, job->height );
245
246         job->keep_ratio = 1;
247
248         job->vcodec     = HB_VCODEC_FFMPEG;
249         job->vquality   = -1.0;
250         job->vbitrate   = 1000;
251         job->pass       = 0;
252         job->vrate      = title->rate;
253         job->vrate_base = title->rate_base;
254
255         job->audios[0] = 0;
256         job->audios[1] = -1;
257
258         job->acodec   = HB_ACODEC_FAAC;
259         job->abitrate = 128;
260         job->arate    = 44100;
261
262         job->subtitle = -1;
263
264         job->mux = HB_MUX_MP4;
265     }
266
267     if( data->dvd )
268     {
269         hb_dvd_close( &data->dvd );
270     }
271         if (data->stream)
272         {
273                 hb_stream_close(&data->stream);
274         }
275     free( data->path );
276     free( data );
277     _data = NULL;
278 }
279
280 /***********************************************************************
281  * DecodePreviews
282  ***********************************************************************
283  * Decode 10 pictures for the given title.
284  * It assumes that data->reader and data->vts have successfully been
285  * DVDOpen()ed and ifoOpen()ed.
286  **********************************************************************/
287 static int DecodePreviews( hb_scan_t * data, hb_title_t * title )
288 {
289     int             i, ret;
290     hb_buffer_t   * buf_ps, * buf_es, * buf_raw;
291     hb_list_t     * list_es, * list_raw;
292     hb_libmpeg2_t * mpeg2;
293     int progressive_count = 0;
294     
295     buf_ps   = hb_buffer_init( HB_DVD_READ_BUFFER_SIZE );
296     list_es  = hb_list_init();
297     list_raw = hb_list_init();
298
299     hb_log( "scan: decoding previews for title %d", title->index );
300
301     if (data->dvd)
302       hb_dvd_start( data->dvd, title->index, 1 );
303       
304     for( i = 0; i < 10; i++ )
305     {
306         int j, k;
307         FILE * file_preview;
308         char   filename[1024];
309
310         //hb_log("Seeking to: %f", (float) ( i + 1 ) / 11.0 );
311        
312         if (data->dvd)
313         {
314           if( !hb_dvd_seek( data->dvd, (float) ( i + 1 ) / 11.0 ) )
315           {
316               goto error;
317           }
318         }
319         else if (data->stream)
320         {
321           if (!hb_stream_seek(data->stream, (float) ( i + 1 ) / 11.0 ) )
322           {
323             goto error;
324           }
325         }
326         
327         hb_log( "scan: preview %d", i + 1 );
328
329         mpeg2 = hb_libmpeg2_init();
330
331         for( j = 0; j < 10240 ; j++ )
332         {
333             if (data->dvd)
334             {
335               if( !hb_dvd_read( data->dvd, buf_ps ) )
336               {
337                   goto error;
338               }
339             }
340             else if (data->stream)
341             {
342               if ( !hb_stream_read(data->stream,buf_ps) )
343               {
344                 goto error;
345               }
346             }
347             hb_demux_ps( buf_ps, list_es );
348
349             while( ( buf_es = hb_list_item( list_es, 0 ) ) )
350             {
351                 hb_list_rem( list_es, buf_es );
352                 if( buf_es->id == 0xE0 && !hb_list_count( list_raw ) )
353                 {
354                     hb_libmpeg2_decode( mpeg2, buf_es, list_raw );
355                 }
356                 else if( !i )
357                 {
358                     LookForAC3AndDCA( title, buf_es );
359                 }
360                 hb_buffer_close( &buf_es );
361
362                 if( hb_list_count( list_raw ) &&
363                     ( i || AllAC3AndDCAOK( title ) ) )
364                 {
365                     /* We got a picture */
366                     break;
367                 }
368             }
369
370             if( hb_list_count( list_raw ) &&
371                 ( i || AllAC3AndDCAOK( title ) ) )
372             {
373                 break;
374             }
375         }
376
377         if( !hb_list_count( list_raw ) )
378         {
379             hb_log( "scan: could not get a decoded picture" );
380             goto error;
381         }
382
383         /* Get size and rate infos */
384         title->rate = 27000000;
385         int ar;
386         hb_libmpeg2_info( mpeg2, &title->width, &title->height,
387                           &title->rate_base, &ar );
388        
389         if (title->rate_base == 1126125)
390         {
391             /* Frame FPS is 23.976 (meaning it's progressive), so
392                start keeping track of how many are reporting at
393                that speed. When enough show up that way, we want
394                to make that the overall title FPS.
395             */
396             progressive_count++;
397
398             if (progressive_count < 6)
399                 /* Not enough frames are reporting as progressive,
400                    which means we should be conservative and use
401                    29.97 as the title's FPS for now.
402                 */
403                 title->rate_base = 900900;           
404             else
405             {
406                 /* A majority of the scan frames are progressive. Make that
407                     the title's FPS, and announce it once to the log.
408                 */
409                 if (progressive_count == 6)
410                     hb_log("Title's mostly progressive NTSC, setting fps to 23.976");
411                 title->rate_base = 1126125;               
412             }
413         }
414                
415         if( i == 2) // Use the third frame's info, so as to skip opening logos
416         {
417             // The aspect ratio may have already been set by parsing the VOB/IFO details on a DVD, however
418             // if we're working with program/transport streams that data needs to come from within the stream.
419             if (title->aspect <= 0)
420               title->aspect = ar;
421             title->crop[0] = title->crop[1] = title->height / 2;
422             title->crop[2] = title->crop[3] = title->width / 2;
423         }
424
425         hb_libmpeg2_close( &mpeg2 );
426
427         while( ( buf_es = hb_list_item( list_es, 0 ) ) )
428         {
429             hb_list_rem( list_es, buf_es );
430             hb_buffer_close( &buf_es );
431         }
432
433         buf_raw = hb_list_item( list_raw, 0 );
434
435         hb_get_tempory_filename( data->h, filename, "%x%d",
436                                  (intptr_t)title, i );
437
438         file_preview = fopen( filename, "w" );
439         if( file_preview )
440         {
441             fwrite( buf_raw->data, title->width * title->height * 3 / 2,
442                     1, file_preview );
443             fclose( file_preview );
444         }
445         else
446         {
447             hb_log( "scan: fopen failed (%s)", filename );
448         }
449
450 #define Y    buf_raw->data
451 #define DARK 64
452         
453         /* Detect black borders */
454         
455         for( j = 0; j < title->width; j++ )
456         {
457             for( k = 0; k < title->crop[0]; k++ )
458                 if( Y[ k * title->width + j ] > DARK )
459                 {
460                     title->crop[0] = k;
461                     break;
462                 }
463             for( k = 0; k < title->crop[1]; k++ )
464                 if( Y[ ( title->height - k - 1 ) *
465                        title->width + j ] > DARK )
466                 {
467                     title->crop[1] = k;
468                     break;
469                 }
470         }
471         for( j = 0; j < title->height; j++ )
472         {
473             for( k = 0; k < title->crop[2]; k++ ) 
474                 if( Y[ j * title->width + k ] > DARK )
475                 {
476                     title->crop[2] = k;
477                     break;
478                 }
479             for( k = 0; k < title->crop[3]; k++ )
480                 if( Y[ j * title->width +
481                         title->width - k - 1 ] > DARK )
482                 {
483                     title->crop[3] = k;
484                     break;
485                 }
486         }
487
488         while( ( buf_raw = hb_list_item( list_raw, 0 ) ) )
489         {
490             hb_list_rem( list_raw, buf_raw );
491             hb_buffer_close( &buf_raw );
492         }
493     }
494
495     title->crop[0] = EVEN( title->crop[0] );
496     title->crop[1] = EVEN( title->crop[1] );
497     title->crop[2] = EVEN( title->crop[2] );
498     title->crop[3] = EVEN( title->crop[3] );
499
500     hb_log( "scan: %dx%d, %.3f fps, autocrop = %d/%d/%d/%d",
501             title->width, title->height, (float) title->rate /
502             (float) title->rate_base, title->crop[0], title->crop[1],
503             title->crop[2], title->crop[3] );
504
505     ret = 1;
506     goto cleanup;
507
508 error:
509     ret = 0;
510
511 cleanup:
512     hb_buffer_close( &buf_ps );
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     hb_list_close( &list_es );
519     while( ( buf_raw = hb_list_item( list_raw, 0 ) ) )
520     {
521         hb_list_rem( list_raw, buf_raw );
522         hb_buffer_close( &buf_raw );
523     }
524     hb_list_close( &list_raw );
525     if (data->dvd)
526       hb_dvd_stop( data->dvd );
527
528     return ret;
529 }
530
531 static void LookForAC3AndDCA( hb_title_t * title, hb_buffer_t * b ) 
532 {
533     int i;
534     int flags;
535     int rate;
536     int bitrate;
537     int frame_length;
538     dca_state_t * state;
539
540     /* Figure out if this is a AC3 or DCA buffer for a known track */
541     hb_audio_t * audio = NULL;
542     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
543     {
544         audio = hb_list_item( title->list_audio, i );
545         /* check if we have an AC3 or DCA which we recognise */
546         if( ( audio->codec == HB_ACODEC_AC3 || audio->codec == HB_ACODEC_DCA ) &&
547             audio->id    == b->id )
548         {
549             break;
550         }
551         else
552         {
553             audio = NULL;
554         }
555     }
556     if( !audio )
557     {
558         return;
559     }
560
561     if( audio->bitrate )
562     {
563         /* Already done for this track */
564         return;
565     }
566
567     for( i = 0; i < b->size - 7; i++ )
568     {
569
570         if ( audio->codec == HB_ACODEC_AC3 )
571         {
572
573             /* check for a52 */
574             if( a52_syncinfo( &b->data[i], &flags, &rate, &bitrate ) )
575             {
576                 hb_log( "scan: AC3, rate=%dHz, bitrate=%d", rate, bitrate );
577                 audio->rate    = rate;
578                 audio->bitrate = bitrate;
579                 switch( flags & A52_CHANNEL_MASK )
580                 {
581                     /* mono sources */
582                     case A52_MONO:
583                     case A52_CHANNEL1:
584                     case A52_CHANNEL2:
585                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_MONO;
586                         break;
587                     /* stereo input */
588                     case A52_CHANNEL:
589                     case A52_STEREO:
590                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
591                         break;
592                     /* dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input */
593                     case A52_DOLBY:
594                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_DOLBY;
595                         break;
596                     /* 3F/2R input */
597                     case A52_3F2R:
598                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F2R;
599                         break;
600                     /* 3F/1R input */
601                     case A52_3F1R:
602                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F1R;
603                         break;
604                     /* other inputs */
605                     case A52_3F:
606                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F;
607                         break;
608                     case A52_2F1R:
609                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F1R;
610                         break;
611                     case A52_2F2R:
612                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F2R;
613                         break;
614                     /* unknown */
615                     default:
616                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
617                 }
618                 
619                 /* add in our own LFE flag if the source has LFE */
620                 if (flags & A52_LFE)
621                 {
622                     audio->input_channel_layout = audio->input_channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE;
623                 }
624
625                 /* store the AC3 flags for future reference
626                 This enables us to find out if we had a stereo or Dolby source later on */
627                 audio->config.a52.ac3flags = flags;
628
629                 /* store the ac3 flags in the public ac3flags property too, so we can access it from the GUI */
630                 audio->ac3flags = audio->config.a52.ac3flags;
631
632                 /* XXX */
633                 if ( (flags & A52_CHANNEL_MASK) == A52_DOLBY ) {
634                     sprintf( audio->lang + strlen( audio->lang ),
635                          " (Dolby Surround)" );
636                 } else {
637                     sprintf( audio->lang + strlen( audio->lang ),
638                          " (%d.%d ch)",
639                         HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->input_channel_layout) +
640                         HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->input_channel_layout),
641                         HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->input_channel_layout));
642                 }
643
644                 break;
645             
646             }
647
648         }
649         else if ( audio->codec == HB_ACODEC_DCA )
650         {
651
652             hb_log( "scan: checking for DCA syncinfo" );
653
654             /* check for dca */
655             state = dca_init( 0 );
656             if( dca_syncinfo( state, &b->data[i], &flags, &rate, &bitrate, &frame_length ) )
657             {
658                 hb_log( "scan: DCA, rate=%dHz, bitrate=%d", rate, bitrate );
659                 audio->rate    = rate;
660                 audio->bitrate = bitrate;
661                 switch( flags & DCA_CHANNEL_MASK )
662                 {
663                     /* mono sources */
664                     case DCA_MONO:
665                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_MONO;
666                         break;
667                     /* stereo input */
668                     case DCA_CHANNEL:
669                     case DCA_STEREO:
670                     case DCA_STEREO_SUMDIFF:
671                     case DCA_STEREO_TOTAL:
672                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
673                         break;
674                     /* 3F/2R input */
675                     case DCA_3F2R:
676                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F2R;
677                         break;
678                     /* 3F/1R input */
679                     case DCA_3F1R:
680                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F1R;
681                         break;
682                     /* other inputs */
683                     case DCA_3F:
684                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F;
685                         break;
686                     case DCA_2F1R:
687                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F1R;
688                         break;
689                     case DCA_2F2R:
690                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F2R;
691                         break;
692                     case DCA_4F2R:
693                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_4F2R;
694                         break;
695                     /* unknown */
696                     default:
697                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
698                 }
699
700                 /* add in our own LFE flag if the source has LFE */
701                 if (flags & DCA_LFE)
702                 {
703                     audio->input_channel_layout = audio->input_channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE;
704                 }
705
706                 /* store the DCA flags for future reference
707                 This enables us to find out if we had a stereo or Dolby source later on */
708                 audio->config.dca.dcaflags = flags;
709
710                 /* store the dca flags in the public dcaflags property too, so we can access it from the GUI */
711                 audio->dcaflags = audio->config.dca.dcaflags;
712
713                 /* XXX */
714                 if ( (flags & DCA_CHANNEL_MASK) == DCA_DOLBY ) {
715                     sprintf( audio->lang + strlen( audio->lang ),
716                          " (Dolby Surround)" );
717                 } else {
718                     sprintf( audio->lang + strlen( audio->lang ),
719                          " (%d.%d ch)",
720                         HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->input_channel_layout) +
721                         HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->input_channel_layout),
722                         HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->input_channel_layout));
723                 }
724
725                 break;
726             }
727         }
728     }
729
730 }
731
732 static int  AllAC3AndDCAOK( hb_title_t * title )
733 {
734     int i;
735     hb_audio_t * audio;
736
737     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
738     {
739         audio = hb_list_item( title->list_audio, i );
740         if( ( audio->codec == HB_ACODEC_AC3 || audio->codec == HB_ACODEC_DCA ) &&
741             !audio->bitrate )
742         {
743             return 0;
744         }
745     }
746
747     return 1;
748 }