OSDN Git Service

Native language subtitle scan improvements. Thanks, eddyg!
[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     
294     buf_ps   = hb_buffer_init( HB_DVD_READ_BUFFER_SIZE );
295     list_es  = hb_list_init();
296     list_raw = hb_list_init();
297
298     hb_log( "scan: decoding previews for title %d", title->index );
299
300     if (data->dvd)
301       hb_dvd_start( data->dvd, title->index, 1 );
302       
303     for( i = 0; i < 10; i++ )
304     {
305         int j, k;
306         FILE * file_preview;
307         char   filename[1024];
308
309         if (data->dvd)
310         {
311           if( !hb_dvd_seek( data->dvd, (float) ( i + 1 ) / 11.0 ) )
312           {
313               goto error;
314           }
315         }
316         else if (data->stream)
317         {
318           if (!hb_stream_seek(data->stream, (float) ( i + 1 ) / 11.0 ) )
319           {
320             goto error;
321           }
322         }
323         
324         hb_log( "scan: preview %d", i + 1 );
325
326         mpeg2 = hb_libmpeg2_init();
327
328         for( j = 0; j < 10240 ; j++ )
329         {
330             if (data->dvd)
331             {
332               if( !hb_dvd_read( data->dvd, buf_ps ) )
333               {
334                   goto error;
335               }
336             }
337             else if (data->stream)
338             {
339               if ( !hb_stream_read(data->stream,buf_ps) )
340               {
341                 goto error;
342               }
343             }
344             hb_demux_ps( buf_ps, list_es );
345
346             while( ( buf_es = hb_list_item( list_es, 0 ) ) )
347             {
348                 hb_list_rem( list_es, buf_es );
349                 if( buf_es->id == 0xE0 && !hb_list_count( list_raw ) )
350                 {
351                     hb_libmpeg2_decode( mpeg2, buf_es, list_raw );
352                 }
353                 else if( !i )
354                 {
355                     LookForAC3AndDCA( title, buf_es );
356                 }
357                 hb_buffer_close( &buf_es );
358
359                 if( hb_list_count( list_raw ) &&
360                     ( i || AllAC3AndDCAOK( title ) ) )
361                 {
362                     /* We got a picture */
363                     break;
364                 }
365             }
366
367             if( hb_list_count( list_raw ) &&
368                 ( i || AllAC3AndDCAOK( title ) ) )
369             {
370                 break;
371             }
372         }
373
374         if( !hb_list_count( list_raw ) )
375         {
376             hb_log( "scan: could not get a decoded picture" );
377             goto error;
378         }
379
380         if( !i )
381         {
382             /* Get size and rate infos */
383             title->rate = 27000000;
384             int ar;
385             hb_libmpeg2_info( mpeg2, &title->width, &title->height,
386                               &title->rate_base, &ar );
387             // The aspect ratio may have already been set by parsing the VOB/IFO details on a DVD, however
388             // if we're working with program/transport streams that data needs to come from within the stream.
389             if (title->aspect <= 0)
390               title->aspect = ar;
391             title->crop[0] = title->crop[1] = title->height / 2;
392             title->crop[2] = title->crop[3] = title->width / 2;
393         }
394
395         hb_libmpeg2_close( &mpeg2 );
396
397         while( ( buf_es = hb_list_item( list_es, 0 ) ) )
398         {
399             hb_list_rem( list_es, buf_es );
400             hb_buffer_close( &buf_es );
401         }
402
403         buf_raw = hb_list_item( list_raw, 0 );
404
405         hb_get_tempory_filename( data->h, filename, "%x%d",
406                                  (intptr_t)title, i );
407
408         file_preview = fopen( filename, "w" );
409         if( file_preview )
410         {
411             fwrite( buf_raw->data, title->width * title->height * 3 / 2,
412                     1, file_preview );
413             fclose( file_preview );
414         }
415         else
416         {
417             hb_log( "scan: fopen failed (%s)", filename );
418         }
419
420 #define Y    buf_raw->data
421 #define DARK 64
422         
423         /* Detect black borders */
424         
425         for( j = 0; j < title->width; j++ )
426         {
427             for( k = 0; k < title->crop[0]; k++ )
428                 if( Y[ k * title->width + j ] > DARK )
429                 {
430                     title->crop[0] = k;
431                     break;
432                 }
433             for( k = 0; k < title->crop[1]; k++ )
434                 if( Y[ ( title->height - k - 1 ) *
435                        title->width + j ] > DARK )
436                 {
437                     title->crop[1] = k;
438                     break;
439                 }
440         }
441         for( j = 0; j < title->height; j++ )
442         {
443             for( k = 0; k < title->crop[2]; k++ ) 
444                 if( Y[ j * title->width + k ] > DARK )
445                 {
446                     title->crop[2] = k;
447                     break;
448                 }
449             for( k = 0; k < title->crop[3]; k++ )
450                 if( Y[ j * title->width +
451                         title->width - k - 1 ] > DARK )
452                 {
453                     title->crop[3] = k;
454                     break;
455                 }
456         }
457
458         while( ( buf_raw = hb_list_item( list_raw, 0 ) ) )
459         {
460             hb_list_rem( list_raw, buf_raw );
461             hb_buffer_close( &buf_raw );
462         }
463     }
464
465     title->crop[0] = EVEN( title->crop[0] );
466     title->crop[1] = EVEN( title->crop[1] );
467     title->crop[2] = EVEN( title->crop[2] );
468     title->crop[3] = EVEN( title->crop[3] );
469
470     hb_log( "scan: %dx%d, %.3f fps, autocrop = %d/%d/%d/%d",
471             title->width, title->height, (float) title->rate /
472             (float) title->rate_base, title->crop[0], title->crop[1],
473             title->crop[2], title->crop[3] );
474
475     ret = 1;
476     goto cleanup;
477
478 error:
479     ret = 0;
480
481 cleanup:
482     hb_buffer_close( &buf_ps );
483     while( ( buf_es = hb_list_item( list_es, 0 ) ) )
484     {
485         hb_list_rem( list_es, buf_es );
486         hb_buffer_close( &buf_es );
487     }
488     hb_list_close( &list_es );
489     while( ( buf_raw = hb_list_item( list_raw, 0 ) ) )
490     {
491         hb_list_rem( list_raw, buf_raw );
492         hb_buffer_close( &buf_raw );
493     }
494     hb_list_close( &list_raw );
495     if (data->dvd)
496       hb_dvd_stop( data->dvd );
497
498     return ret;
499 }
500
501 static void LookForAC3AndDCA( hb_title_t * title, hb_buffer_t * b ) 
502 {
503     int i;
504     int flags;
505     int rate;
506     int bitrate;
507     int frame_length;
508     dca_state_t * state;
509
510     /* Figure out if this is a AC3 or DCA buffer for a known track */
511     hb_audio_t * audio = NULL;
512     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
513     {
514         audio = hb_list_item( title->list_audio, i );
515         /* check if we have an AC3 or DCA which we recognise */
516         if( ( audio->codec == HB_ACODEC_AC3 || audio->codec == HB_ACODEC_DCA ) &&
517             audio->id    == b->id )
518         {
519             break;
520         }
521         else
522         {
523             audio = NULL;
524         }
525     }
526     if( !audio )
527     {
528         return;
529     }
530
531     if( audio->bitrate )
532     {
533         /* Already done for this track */
534         return;
535     }
536
537     for( i = 0; i < b->size - 7; i++ )
538     {
539
540         if ( audio->codec == HB_ACODEC_AC3 )
541         {
542
543             /* check for a52 */
544             if( a52_syncinfo( &b->data[i], &flags, &rate, &bitrate ) )
545             {
546                 hb_log( "scan: AC3, rate=%dHz, bitrate=%d", rate, bitrate );
547                 audio->rate    = rate;
548                 audio->bitrate = bitrate;
549                 switch( flags & A52_CHANNEL_MASK )
550                 {
551                     /* mono sources */
552                     case A52_MONO:
553                     case A52_CHANNEL1:
554                     case A52_CHANNEL2:
555                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_MONO;
556                         break;
557                     /* stereo input */
558                     case A52_CHANNEL:
559                     case A52_STEREO:
560                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
561                         break;
562                     /* dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input */
563                     case A52_DOLBY:
564                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_DOLBY;
565                         break;
566                     /* 3F/2R input */
567                     case A52_3F2R:
568                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F2R;
569                         break;
570                     /* 3F/1R input */
571                     case A52_3F1R:
572                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F1R;
573                         break;
574                     /* other inputs */
575                     case A52_3F:
576                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F;
577                         break;
578                     case A52_2F1R:
579                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F1R;
580                         break;
581                     case A52_2F2R:
582                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F2R;
583                         break;
584                     /* unknown */
585                     default:
586                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
587                 }
588                 
589                 /* add in our own LFE flag if the source has LFE */
590                 if (flags & A52_LFE)
591                 {
592                     audio->input_channel_layout = audio->input_channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE;
593                 }
594
595                 /* store the AC3 flags for future reference
596                 This enables us to find out if we had a stereo or Dolby source later on */
597                 audio->config.a52.ac3flags = flags;
598
599                 /* store the ac3 flags in the public ac3flags property too, so we can access it from the GUI */
600                 audio->ac3flags = audio->config.a52.ac3flags;
601
602                 /* XXX */
603                 if ( (flags & A52_CHANNEL_MASK) == A52_DOLBY ) {
604                     sprintf( audio->lang + strlen( audio->lang ),
605                          " (Dolby Surround)" );
606                 } else {
607                     sprintf( audio->lang + strlen( audio->lang ),
608                          " (%d.%d ch)",
609                         HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->input_channel_layout) +
610                         HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->input_channel_layout),
611                         HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->input_channel_layout));
612                 }
613
614                 break;
615             
616             }
617
618         }
619         else if ( audio->codec == HB_ACODEC_DCA )
620         {
621
622             hb_log( "scan: checking for DCA syncinfo" );
623
624             /* check for dca */
625             state = dca_init( 0 );
626             if( dca_syncinfo( state, &b->data[i], &flags, &rate, &bitrate, &frame_length ) )
627             {
628                 hb_log( "scan: DCA, rate=%dHz, bitrate=%d", rate, bitrate );
629                 audio->rate    = rate;
630                 audio->bitrate = bitrate;
631                 switch( flags & DCA_CHANNEL_MASK )
632                 {
633                     /* mono sources */
634                     case DCA_MONO:
635                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_MONO;
636                         break;
637                     /* stereo input */
638                     case DCA_CHANNEL:
639                     case DCA_STEREO:
640                     case DCA_STEREO_SUMDIFF:
641                     case DCA_STEREO_TOTAL:
642                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
643                         break;
644                     /* 3F/2R input */
645                     case DCA_3F2R:
646                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F2R;
647                         break;
648                     /* 3F/1R input */
649                     case DCA_3F1R:
650                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F1R;
651                         break;
652                     /* other inputs */
653                     case DCA_3F:
654                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F;
655                         break;
656                     case DCA_2F1R:
657                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F1R;
658                         break;
659                     case DCA_2F2R:
660                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F2R;
661                         break;
662                     case DCA_4F2R:
663                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_4F2R;
664                         break;
665                     /* unknown */
666                     default:
667                         audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
668                 }
669
670                 /* add in our own LFE flag if the source has LFE */
671                 if (flags & DCA_LFE)
672                 {
673                     audio->input_channel_layout = audio->input_channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE;
674                 }
675
676                 /* store the DCA flags for future reference
677                 This enables us to find out if we had a stereo or Dolby source later on */
678                 audio->config.dca.dcaflags = flags;
679
680                 /* store the dca flags in the public dcaflags property too, so we can access it from the GUI */
681                 audio->dcaflags = audio->config.dca.dcaflags;
682
683                 /* XXX */
684                 if ( (flags & DCA_CHANNEL_MASK) == DCA_DOLBY ) {
685                     sprintf( audio->lang + strlen( audio->lang ),
686                          " (Dolby Surround)" );
687                 } else {
688                     sprintf( audio->lang + strlen( audio->lang ),
689                          " (%d.%d ch)",
690                         HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->input_channel_layout) +
691                         HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->input_channel_layout),
692                         HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->input_channel_layout));
693                 }
694
695                 break;
696             }
697         }
698     }
699
700 }
701
702 static int  AllAC3AndDCAOK( hb_title_t * title )
703 {
704     int i;
705     hb_audio_t * audio;
706
707     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
708     {
709         audio = hb_list_item( title->list_audio, i );
710         if( ( audio->codec == HB_ACODEC_AC3 || audio->codec == HB_ACODEC_DCA ) &&
711             !audio->bitrate )
712         {
713             return 0;
714         }
715     }
716
717     return 1;
718 }