OSDN Git Service

gitattirubes test 2
[handbrake-jp/handbrake-jp.git] / libhb / dvdnav.c
1 /* $Id: dvd.c,v 1.12 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 "lang.h"
9 #include "dvd.h"
10
11 #include "dvdnav/dvdnav.h"
12 #include "dvdread/ifo_read.h"
13 #include "dvdread/ifo_print.h"
14 #include "dvdread/nav_read.h"
15
16 #define DVD_READ_CACHE 1
17
18 static char        * hb_dvdnav_name( char * path );
19 static hb_dvd_t    * hb_dvdnav_init( char * path );
20 static int           hb_dvdnav_title_count( hb_dvd_t * d );
21 static hb_title_t  * hb_dvdnav_title_scan( hb_dvd_t * d, int t );
22 static int           hb_dvdnav_start( hb_dvd_t * d, hb_title_t *title, int chapter );
23 static void          hb_dvdnav_stop( hb_dvd_t * d );
24 static int           hb_dvdnav_seek( hb_dvd_t * d, float f );
25 static int           hb_dvdnav_read( hb_dvd_t * d, hb_buffer_t * b );
26 static int           hb_dvdnav_chapter( hb_dvd_t * d );
27 static void          hb_dvdnav_close( hb_dvd_t ** _d );
28 static int           hb_dvdnav_angle_count( hb_dvd_t * d );
29 static void          hb_dvdnav_set_angle( hb_dvd_t * e, int angle );
30
31 hb_dvd_func_t hb_dvdnav_func =
32 {
33     hb_dvdnav_init,
34     hb_dvdnav_close,
35     hb_dvdnav_name,
36     hb_dvdnav_title_count,
37     hb_dvdnav_title_scan,
38     hb_dvdnav_start,
39     hb_dvdnav_stop,
40     hb_dvdnav_seek,
41     hb_dvdnav_read,
42     hb_dvdnav_chapter,
43     hb_dvdnav_angle_count,
44     hb_dvdnav_set_angle
45 };
46
47 // there can be at most 999 PGCs per title. round that up to the nearest
48 // power of two.
49 #define MAX_PGCN 1024
50
51 /***********************************************************************
52  * Local prototypes
53  **********************************************************************/
54 static void PgcWalkInit( uint32_t pgcn_map[MAX_PGCN/32] );
55 static int FindChapterIndex( hb_list_t * list, int pgcn, int pgn );
56 static int NextPgcn( ifo_handle_t *ifo, int pgcn, uint32_t pgcn_map[MAX_PGCN/32] );
57 static int FindNextCell( pgc_t *pgc, int cell_cur );
58 static int dvdtime2msec( dvd_time_t * );
59
60 hb_dvd_func_t * hb_dvdnav_methods( void )
61 {
62     return &hb_dvdnav_func;
63 }
64
65 static char * hb_dvdnav_name( char * path )
66 {
67     static char name[1024];
68     unsigned char unused[1024];
69     dvd_reader_t * reader;
70
71     reader = DVDOpen( path );
72     if( !reader )
73     {
74         return NULL;
75     }
76
77     if( DVDUDFVolumeInfo( reader, name, sizeof( name ),
78                           unused, sizeof( unused ) ) )
79     {
80         DVDClose( reader );
81         return NULL;
82     }
83
84     DVDClose( reader );
85     return name;
86 }
87
88 /***********************************************************************
89  * hb_dvdnav_reset
90  ***********************************************************************
91  * Once dvdnav has entered the 'stopped' state, it can not be revived
92  * dvdnav_reset doesn't work because it doesn't remember the path
93  * So this function re-opens dvdnav
94  **********************************************************************/
95 static int hb_dvdnav_reset( hb_dvdnav_t * d )
96 {
97     if ( d->dvdnav ) 
98         dvdnav_close( d->dvdnav );
99
100     /* Open device */
101     if( dvdnav_open(&d->dvdnav, d->path) != DVDNAV_STATUS_OK )
102     {
103         /*
104          * Not an error, may be a stream - which we'll try in a moment.
105          */
106         hb_log( "dvd: not a dvd - trying as a stream/file instead" );
107         goto fail;
108     }
109
110     if (dvdnav_set_readahead_flag(d->dvdnav, DVD_READ_CACHE) !=
111         DVDNAV_STATUS_OK)
112     {
113         hb_error("Error: dvdnav_set_readahead_flag: %s\n",
114                  dvdnav_err_to_string(d->dvdnav));
115         goto fail;
116     }
117
118     /*
119      ** set the PGC positioning flag to have position information
120      ** relatively to the whole feature instead of just relatively to the
121      ** current chapter 
122      **/
123     if (dvdnav_set_PGC_positioning_flag(d->dvdnav, 1) != DVDNAV_STATUS_OK)
124     {
125         hb_error("Error: dvdnav_set_PGC_positioning_flag: %s\n",
126                  dvdnav_err_to_string(d->dvdnav));
127         goto fail;
128     }
129     return 1;
130
131 fail:
132     if( d->dvdnav ) dvdnav_close( d->dvdnav );
133     return 0;
134 }
135
136 /***********************************************************************
137  * hb_dvdnav_init
138  ***********************************************************************
139  *
140  **********************************************************************/
141 static hb_dvd_t * hb_dvdnav_init( char * path )
142 {
143     hb_dvd_t * e;
144     hb_dvdnav_t * d;
145     int region_mask;
146
147     e = calloc( sizeof( hb_dvd_t ), 1 );
148     d = &(e->dvdnav);
149
150         /* Log DVD drive region code */
151     if ( hb_dvd_region( path, &region_mask ) == 0 )
152     {
153         hb_log( "dvd: Region mask 0x%02x", region_mask );
154         if ( region_mask == 0xFF )
155         {
156             hb_log( "dvd: Warning, DVD device has no region set" );
157         }
158     }
159
160     /* Open device */
161     if( dvdnav_open(&d->dvdnav, path) != DVDNAV_STATUS_OK )
162     {
163         /*
164          * Not an error, may be a stream - which we'll try in a moment.
165          */
166         hb_log( "dvd: not a dvd - trying as a stream/file instead" );
167         goto fail;
168     }
169
170     if (dvdnav_set_readahead_flag(d->dvdnav, DVD_READ_CACHE) !=
171         DVDNAV_STATUS_OK)
172     {
173         hb_error("Error: dvdnav_set_readahead_flag: %s\n",
174                  dvdnav_err_to_string(d->dvdnav));
175         goto fail;
176     }
177
178     /*
179      ** set the PGC positioning flag to have position information
180      ** relatively to the whole feature instead of just relatively to the
181      ** current chapter 
182      **/
183     if (dvdnav_set_PGC_positioning_flag(d->dvdnav, 1) != DVDNAV_STATUS_OK)
184     {
185         hb_error("Error: dvdnav_set_PGC_positioning_flag: %s\n",
186                  dvdnav_err_to_string(d->dvdnav));
187         goto fail;
188     }
189
190     /* Open device */
191     if( !( d->reader = DVDOpen( path ) ) )
192     {
193         /*
194          * Not an error, may be a stream - which we'll try in a moment.
195          */
196         hb_log( "dvd: not a dvd - trying as a stream/file instead" );
197         goto fail;
198     }
199
200     /* Open main IFO */
201     if( !( d->vmg = ifoOpen( d->reader, 0 ) ) )
202     {
203         hb_error( "dvd: ifoOpen failed" );
204         goto fail;
205     }
206
207     d->path = strdup( path );
208
209     return e;
210
211 fail:
212     if( d->dvdnav ) dvdnav_close( d->dvdnav );
213     if( d->vmg )    ifoClose( d->vmg );
214     if( d->reader ) DVDClose( d->reader );
215     free( e );
216     return NULL;
217 }
218
219 /***********************************************************************
220  * hb_dvdnav_title_count
221  **********************************************************************/
222 static int hb_dvdnav_title_count( hb_dvd_t * e )
223 {
224     int titles = 0;
225     hb_dvdnav_t * d = &(e->dvdnav);
226
227     dvdnav_get_number_of_titles(d->dvdnav, &titles);
228     return titles;
229 }
230
231 static uint64_t
232 PttDuration(ifo_handle_t *ifo, int ttn, int pttn, int *blocks, int *last_pgcn)
233 {
234     int            pgcn, pgn;
235     pgc_t        * pgc;
236     uint64_t       duration = 0;
237     int            cell_start, cell_end;
238     int            i;
239
240     // Initialize map of visited pgc's to prevent loops
241     uint32_t pgcn_map[MAX_PGCN/32];
242     PgcWalkInit( pgcn_map );
243     pgcn   = ifo->vts_ptt_srpt->title[ttn-1].ptt[pttn-1].pgcn;
244     pgn   = ifo->vts_ptt_srpt->title[ttn-1].ptt[pttn-1].pgn;
245     if ( pgcn < 1 || pgcn > ifo->vts_pgcit->nr_of_pgci_srp || pgcn >= MAX_PGCN)
246     {
247         hb_error( "invalid PGC ID %d, skipping", pgcn );
248         return 0;
249     }
250
251     if( pgn <= 0 || pgn > 99 )
252     {
253         hb_error( "scan: pgn %d not valid, skipping", pgn );
254         return 0;
255     }
256
257     *blocks = 0;
258     do
259     {
260         pgc = ifo->vts_pgcit->pgci_srp[pgcn-1].pgc;
261         if (!pgc)
262         {
263             hb_error( "scan: pgc not valid, skipping" );
264             break;
265         }
266         if (pgn > pgc->nr_of_programs)
267         {
268             pgn = 1;
269             continue;
270         }
271
272         duration += 90LL * dvdtime2msec( &pgc->playback_time );
273
274         cell_start = pgc->program_map[pgn-1] - 1;
275         cell_end = pgc->nr_of_cells - 1;
276         for(i = cell_start; i <= cell_end; i = FindNextCell(pgc, i))
277         {
278             *blocks += pgc->cell_playback[i].last_sector + 1 -
279                 pgc->cell_playback[i].first_sector;
280         }
281         *last_pgcn = pgcn;
282         pgn = 1;
283     } while((pgcn = NextPgcn(ifo, pgcn, pgcn_map)) != 0);
284     return duration;
285 }
286
287 /***********************************************************************
288  * hb_dvdnav_title_scan
289  **********************************************************************/
290 static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t )
291 {
292
293     hb_dvdnav_t * d = &(e->dvdnav);
294     hb_title_t   * title;
295     ifo_handle_t * ifo = NULL;
296     int            pgcn, pgn, pgcn_end, i, c;
297     int            title_pgcn;
298     pgc_t        * pgc;
299     int            cell_cur;
300     hb_chapter_t * chapter;
301     int            count;
302     uint64_t       duration, longest;
303     int            longest_pgcn, longest_pgn, longest_pgcn_end;
304     float          duration_correction;
305     const char   * name;
306
307     hb_log( "scan: scanning title %d", t );
308
309     title = hb_title_init( d->path, t );
310     if (dvdnav_get_title_string(d->dvdnav, &name) == DVDNAV_STATUS_OK)
311     {
312         strncpy( title->name, name, sizeof( title->name ) );
313     }
314     else
315     {
316         char * p_cur, * p_last = d->path;
317         for( p_cur = d->path; *p_cur; p_cur++ )
318         {
319             if( p_cur[0] == '/' && p_cur[1] )
320             {
321                 p_last = &p_cur[1];
322             }
323         }
324         snprintf( title->name, sizeof( title->name ), "%s", p_last );
325     }
326
327     /* VTS which our title is in */
328     title->vts = d->vmg->tt_srpt->title[t-1].title_set_nr;
329
330     if ( !title->vts )
331     {
332         /* A VTS of 0 means the title wasn't found in the title set */
333         hb_error("Invalid VTS (title set) number: %i", title->vts);
334         goto fail;
335     }
336
337     hb_log( "scan: opening IFO for VTS %d", title->vts );
338     if( !( ifo = ifoOpen( d->reader, title->vts ) ) )
339     {
340         hb_error( "scan: ifoOpen failed" );
341         goto fail;
342     }
343
344     /* ignore titles with bogus cell addresses so we don't abort later
345      ** in libdvdread. */
346     for ( i = 0; i < ifo->vts_c_adt->nr_of_vobs; ++i)
347     {
348         if( (ifo->vts_c_adt->cell_adr_table[i].start_sector & 0xffffff ) ==
349             0xffffff )
350         {
351             hb_error( "scan: cell_adr_table[%d].start_sector invalid (0x%x) "
352                       "- skipping title", i,
353                       ifo->vts_c_adt->cell_adr_table[i].start_sector );
354             goto fail;
355         }
356         if( (ifo->vts_c_adt->cell_adr_table[i].last_sector & 0xffffff ) ==
357             0xffffff )
358         {
359             hb_error( "scan: cell_adr_table[%d].last_sector invalid (0x%x) "
360                       "- skipping title", i,
361                       ifo->vts_c_adt->cell_adr_table[i].last_sector );
362             goto fail;
363         }
364         if( ifo->vts_c_adt->cell_adr_table[i].start_sector >=
365             ifo->vts_c_adt->cell_adr_table[i].last_sector )
366         {
367             hb_error( "scan: cell_adr_table[%d].start_sector (0x%x) "
368                       "is not before last_sector (0x%x) - skipping title", i,
369                       ifo->vts_c_adt->cell_adr_table[i].start_sector,
370                       ifo->vts_c_adt->cell_adr_table[i].last_sector );
371             goto fail;
372         }
373     }
374
375     if( global_verbosity_level == 3 )
376     {
377         ifo_print( d->reader, title->vts );
378     }
379
380     /* Position of the title in the VTS */
381     title->ttn = d->vmg->tt_srpt->title[t-1].vts_ttn;
382     if ( title->ttn < 1 || title->ttn > ifo->vts_ptt_srpt->nr_of_srpts )
383     {
384         hb_error( "invalid VTS PTT offset %d for title %d, skipping", title->ttn, t );
385         goto fail;
386     }
387
388     longest = 0LL;
389     longest_pgcn = -1;
390     longest_pgn = 1;
391     longest_pgcn_end = -1;
392     pgcn_end = -1;
393     for( i = 0; i < ifo->vts_ptt_srpt->title[title->ttn-1].nr_of_ptts; i++ )
394     {
395         int blocks = 0;
396
397         duration = PttDuration(ifo, title->ttn, i+1, &blocks, &pgcn_end);
398         pgcn  = ifo->vts_ptt_srpt->title[title->ttn-1].ptt[i].pgcn;
399         pgn   = ifo->vts_ptt_srpt->title[title->ttn-1].ptt[i].pgn;
400         if( duration > longest )
401         {
402             longest_pgcn  = pgcn;
403             longest_pgn   = pgn;
404             longest_pgcn_end   = pgcn_end;
405             longest = duration;
406             title->block_count = blocks;
407         }
408         else if (pgcn == longest_pgcn && pgn < longest_pgn)
409         {
410             longest_pgn   = pgn;
411             title->block_count = blocks;
412         }
413     }
414
415     /* ignore titles under 10 seconds because they're often stills or
416      * clips with no audio & our preview code doesn't currently handle
417      * either of these. */
418     if( longest < 900000LL )
419     {
420         hb_log( "scan: ignoring title (too short)" );
421         goto fail;
422     }
423
424     pgcn       = longest_pgcn;
425     pgcn_end   = longest_pgcn_end;
426     pgn        = longest_pgn;;
427     title_pgcn = pgcn;
428
429
430     /* Get pgc */
431     if ( pgcn < 1 || pgcn > ifo->vts_pgcit->nr_of_pgci_srp || pgcn >= MAX_PGCN)
432     {
433         hb_error( "invalid PGC ID %d for title %d, skipping", pgcn, t );
434         goto fail;
435     }
436
437     pgc = ifo->vts_pgcit->pgci_srp[pgcn-1].pgc;
438
439     hb_log("pgc_id: %d, pgn: %d: pgc: %p", pgcn, pgn, pgc);
440     if (pgn > pgc->nr_of_programs)
441     {
442         hb_error( "invalid PGN %d for title %d, skipping", pgn, t );
443         goto fail;
444     }
445
446     /* Title start */
447     title->cell_start = pgc->program_map[pgn-1] - 1;
448     title->block_start = pgc->cell_playback[title->cell_start].first_sector;
449
450     pgc = ifo->vts_pgcit->pgci_srp[pgcn_end-1].pgc;
451
452     /* Title end */
453     title->cell_end = pgc->nr_of_cells - 1;
454     title->block_end = pgc->cell_playback[title->cell_end].last_sector;
455
456     hb_log( "scan: vts=%d, ttn=%d, cells=%d->%d, blocks=%d->%d, "
457             "%d blocks", title->vts, title->ttn, title->cell_start,
458             title->cell_end, title->block_start, title->block_end,
459             title->block_count );
460
461     /* Get duration */
462     title->duration = longest;
463     title->hours    = title->duration / 90000 / 3600;
464     title->minutes  = ( ( title->duration / 90000 ) % 3600 ) / 60;
465     title->seconds  = ( title->duration / 90000 ) % 60;
466     hb_log( "scan: duration is %02d:%02d:%02d (%"PRId64" ms)",
467             title->hours, title->minutes, title->seconds,
468             title->duration / 90 );
469
470     /* Detect languages */
471     for( i = 0; i < ifo->vtsi_mat->nr_of_vts_audio_streams; i++ )
472     {
473         hb_audio_t * audio, * audio_tmp;
474         int          audio_format, lang_code, audio_control,
475                      position, j;
476         iso639_lang_t * lang;
477         int lang_extension = 0;
478
479         hb_log( "scan: checking audio %d", i + 1 );
480
481         audio = calloc( sizeof( hb_audio_t ), 1 );
482
483         audio_format  = ifo->vtsi_mat->vts_audio_attr[i].audio_format;
484         lang_code     = ifo->vtsi_mat->vts_audio_attr[i].lang_code;
485         lang_extension = ifo->vtsi_mat->vts_audio_attr[i].code_extension;
486         audio_control =
487             ifo->vts_pgcit->pgci_srp[title_pgcn-1].pgc->audio_control[i];
488
489         if( !( audio_control & 0x8000 ) )
490         {
491             hb_log( "scan: audio channel is not active" );
492             free( audio );
493             continue;
494         }
495
496         position = ( audio_control & 0x7F00 ) >> 8;
497
498         switch( audio_format )
499         {
500             case 0x00:
501                 audio->id    = ( ( 0x80 + position ) << 8 ) | 0xbd;
502                 audio->config.in.codec = HB_ACODEC_AC3;
503                 break;
504
505             case 0x02:
506             case 0x03:
507                 audio->id    = 0xc0 + position;
508                 audio->config.in.codec = HB_ACODEC_MPGA;
509                 break;
510
511             case 0x04:
512                 audio->id    = ( ( 0xa0 + position ) << 8 ) | 0xbd;
513                 audio->config.in.codec = HB_ACODEC_LPCM;
514                 break;
515
516             case 0x06:
517                 audio->id    = ( ( 0x88 + position ) << 8 ) | 0xbd;
518                 audio->config.in.codec = HB_ACODEC_DCA;
519                 break;
520
521             default:
522                 audio->id    = 0;
523                 audio->config.in.codec = 0;
524                 hb_log( "scan: unknown audio codec (%x)",
525                         audio_format );
526                 break;
527         }
528         if( !audio->id )
529         {
530             continue;
531         }
532
533         /* Check for duplicate tracks */
534         audio_tmp = NULL;
535         for( j = 0; j < hb_list_count( title->list_audio ); j++ )
536         {
537             audio_tmp = hb_list_item( title->list_audio, j );
538             if( audio->id == audio_tmp->id )
539             {
540                 break;
541             }
542             audio_tmp = NULL;
543         }
544         if( audio_tmp )
545         {
546             hb_log( "scan: duplicate audio track" );
547             free( audio );
548             continue;
549         }
550
551         audio->config.lang.type = lang_extension;
552
553         lang = lang_for_code( ifo->vtsi_mat->vts_audio_attr[i].lang_code );
554
555         snprintf( audio->config.lang.description, sizeof( audio->config.lang.description ), "%s (%s)",
556             strlen(lang->native_name) ? lang->native_name : lang->eng_name,
557             audio->config.in.codec == HB_ACODEC_AC3 ? "AC3" : ( audio->config.in.codec ==
558                 HB_ACODEC_DCA ? "DTS" : ( audio->config.in.codec ==
559                 HB_ACODEC_MPGA ? "MPEG" : "LPCM" ) ) );
560         snprintf( audio->config.lang.simple, sizeof( audio->config.lang.simple ), "%s",
561                   strlen(lang->native_name) ? lang->native_name : lang->eng_name );
562         snprintf( audio->config.lang.iso639_2, sizeof( audio->config.lang.iso639_2 ), "%s",
563                   lang->iso639_2);
564
565         switch( lang_extension )
566         {
567         case 0:
568         case 1:
569             break;
570         case 2:
571             strcat( audio->config.lang.description, " (Visually Impaired)" );
572             break;
573         case 3:
574             strcat( audio->config.lang.description, " (Director's Commentary 1)" );
575             break;
576         case 4:
577             strcat( audio->config.lang.description, " (Director's Commentary 2)" );
578             break;
579         default:
580             break;
581         }
582
583         hb_log( "scan: id=%x, lang=%s, 3cc=%s ext=%i", audio->id,
584                 audio->config.lang.description, audio->config.lang.iso639_2,
585                 lang_extension );
586
587         audio->config.in.track = i;
588         hb_list_add( title->list_audio, audio );
589     }
590
591     memcpy( title->palette,
592             ifo->vts_pgcit->pgci_srp[title_pgcn-1].pgc->palette,
593             16 * sizeof( uint32_t ) );
594
595     /* Check for subtitles */
596     for( i = 0; i < ifo->vtsi_mat->nr_of_vts_subp_streams; i++ )
597     {
598         hb_subtitle_t * subtitle;
599         int spu_control;
600         int position;
601         iso639_lang_t * lang;
602         int lang_extension = 0;
603
604         hb_log( "scan: checking subtitle %d", i + 1 );
605
606         spu_control =
607             ifo->vts_pgcit->pgci_srp[title_pgcn-1].pgc->subp_control[i];
608
609         if( !( spu_control & 0x80000000 ) )
610         {
611             hb_log( "scan: subtitle channel is not active" );
612             continue;
613         }
614
615         if( ifo->vtsi_mat->vts_video_attr.display_aspect_ratio )
616         {
617             switch( ifo->vtsi_mat->vts_video_attr.permitted_df )
618             {
619                 case 1:
620                     position = spu_control & 0xFF;
621                     break;
622                 case 2:
623                     position = ( spu_control >> 8 ) & 0xFF;
624                     break;
625                 default:
626                     position = ( spu_control >> 16 ) & 0xFF;
627             }
628         }
629         else
630         {
631             position = ( spu_control >> 24 ) & 0x7F;
632         }
633
634         lang_extension = ifo->vtsi_mat->vts_subp_attr[i].code_extension;
635
636         lang = lang_for_code( ifo->vtsi_mat->vts_subp_attr[i].lang_code );
637
638         subtitle = calloc( sizeof( hb_subtitle_t ), 1 );
639         subtitle->track = i+1;
640         subtitle->id = ( ( 0x20 + position ) << 8 ) | 0xbd;
641         snprintf( subtitle->lang, sizeof( subtitle->lang ), "%s",
642              strlen(lang->native_name) ? lang->native_name : lang->eng_name);
643         snprintf( subtitle->iso639_2, sizeof( subtitle->iso639_2 ), "%s",
644                   lang->iso639_2);
645         subtitle->format = PICTURESUB;
646         subtitle->source = VOBSUB;
647         subtitle->config.dest   = RENDERSUB;  // By default render (burn-in) the VOBSUB.
648
649         subtitle->type = lang_extension;
650
651         switch( lang_extension )
652         {  
653         case 0:
654             break;
655         case 1:
656             break;
657         case 2:
658             strcat( subtitle->lang, " (Caption with bigger size character)");
659             break;
660         case 3: 
661             strcat( subtitle->lang, " (Caption for Children)");
662             break;
663         case 4:
664             break;
665         case 5:
666             strcat( subtitle->lang, " (Closed Caption)");
667             break;
668         case 6:
669             strcat( subtitle->lang, " (Closed Caption with bigger size character)");
670             break;
671         case 7:
672             strcat( subtitle->lang, " (Closed Caption for Children)");
673             break;
674         case 8:
675             break;
676         case 9:
677             strcat( subtitle->lang, " (Forced Caption)");
678             break;
679         case 10:
680             break;
681         case 11:
682             break;
683         case 12:
684             break;
685         case 13:
686             strcat( subtitle->lang, " (Director's Commentary)");
687             break;
688         case 14:
689             strcat( subtitle->lang, " (Director's Commentary with bigger size character)");
690             break;
691         case 15:
692             strcat( subtitle->lang, " (Director's Commentary for Children)");
693         default:
694             break;
695         }
696
697         hb_log( "scan: id=%x, lang=%s, 3cc=%s", subtitle->id,
698                 subtitle->lang, subtitle->iso639_2 );
699
700         hb_list_add( title->list_subtitle, subtitle );
701     }
702
703     /* Chapters */
704     uint32_t pgcn_map[MAX_PGCN/32];
705     PgcWalkInit( pgcn_map );
706     c = 0;
707     do
708     {
709         pgc = ifo->vts_pgcit->pgci_srp[pgcn-1].pgc;
710
711         for (i = pgn; i <= pgc->nr_of_programs; i++)
712         {
713             chapter = calloc( sizeof( hb_chapter_t ), 1 );
714
715             chapter->index = c + 1;
716             chapter->pgcn = pgcn;
717             chapter->pgn = i;
718             hb_list_add( title->list_chapter, chapter );
719             c++;
720         }
721
722         pgn = 1;
723     } while ((pgcn = NextPgcn(ifo, pgcn, pgcn_map)) != 0);
724
725     hb_log( "scan: title %d has %d chapters", t, c );
726
727     duration = 0;
728     count = hb_list_count( title->list_chapter );
729     for (i = 0; i < count; i++)
730     {
731         chapter = hb_list_item( title->list_chapter, i );
732
733         pgcn = chapter->pgcn;
734         pgn = chapter->pgn;
735         pgc = ifo->vts_pgcit->pgci_srp[pgcn-1].pgc;
736
737         /* Start cell */
738         chapter->cell_start  = pgc->program_map[pgn-1] - 1;
739         chapter->block_start = pgc->cell_playback[chapter->cell_start].first_sector;
740         // if there are no more programs in this pgc, the end cell is the
741         // last cell. Otherwise it's the cell before the start cell of the
742         // next program.
743         if ( pgn == pgc->nr_of_programs )
744         {
745             chapter->cell_end = pgc->nr_of_cells - 1;
746         }
747         else
748         {
749             chapter->cell_end = pgc->program_map[pgn] - 2;;
750         }
751         chapter->block_end = pgc->cell_playback[chapter->cell_end].last_sector;
752
753         /* Block count, duration */
754         chapter->block_count = 0;
755         chapter->duration = 0;
756
757         cell_cur = chapter->cell_start;
758         while( cell_cur <= chapter->cell_end )
759         {
760 #define cp pgc->cell_playback[cell_cur]
761             chapter->block_count += cp.last_sector + 1 - cp.first_sector;
762             chapter->duration += 90LL * dvdtime2msec( &cp.playback_time );
763 #undef cp
764             cell_cur = FindNextCell( pgc, cell_cur );
765         }
766         duration += chapter->duration;
767     }
768
769     /* The durations we get for chapters aren't precise. Scale them so
770        the total matches the title duration */
771     duration_correction = (float) title->duration / (float) duration;
772     for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
773     {
774         int seconds;
775         chapter            = hb_list_item( title->list_chapter, i );
776         chapter->duration  = duration_correction * chapter->duration;
777         seconds            = ( chapter->duration + 45000 ) / 90000;
778         chapter->hours     = seconds / 3600;
779         chapter->minutes   = ( seconds % 3600 ) / 60;
780         chapter->seconds   = seconds % 60;
781
782         hb_log( "scan: chap %d c=%d->%d, b=%d->%d (%d), %"PRId64" ms",
783                 chapter->index, chapter->cell_start, chapter->cell_end,
784                 chapter->block_start, chapter->block_end,
785                 chapter->block_count, chapter->duration / 90 );
786     }
787
788     /* Get aspect. We don't get width/height/rate infos here as
789        they tend to be wrong */
790     switch( ifo->vtsi_mat->vts_video_attr.display_aspect_ratio )
791     {
792         case 0:
793             title->container_aspect = 4. / 3.;
794             break;
795         case 3:
796             title->container_aspect = 16. / 9.;
797             break;
798         default:
799             hb_log( "scan: unknown aspect" );
800             goto fail;
801     }
802
803     hb_log( "scan: aspect = %g", title->aspect );
804
805     /* This title is ok so far */
806     goto cleanup;
807
808 fail:
809     hb_list_close( &title->list_audio );
810     free( title );
811     title = NULL;
812
813 cleanup:
814     if( ifo ) ifoClose( ifo );
815
816     return title;
817 }
818
819 /***********************************************************************
820  * hb_dvdnav_start
821  ***********************************************************************
822  * Title and chapter start at 1
823  **********************************************************************/
824 static int hb_dvdnav_start( hb_dvd_t * e, hb_title_t *title, int c )
825 {
826     hb_dvdnav_t * d = &(e->dvdnav);
827     int t = title->index;
828     hb_chapter_t *chapter;
829     dvdnav_status_t result;
830
831     d->title_block_count = title->block_count;
832     d->list_chapter = title->list_chapter;
833
834     if ( d->stopped && !hb_dvdnav_reset(d) )
835     {
836         return 0;
837     }
838     chapter = hb_list_item( title->list_chapter, c - 1);
839     if (chapter != NULL)
840         result = dvdnav_program_play(d->dvdnav, t, chapter->pgcn, chapter->pgn);
841     else
842         result = dvdnav_part_play(d->dvdnav, t, 1);
843     if (result != DVDNAV_STATUS_OK)
844     {
845         hb_error( "dvd: dvdnav_*_play failed - %s", 
846                   dvdnav_err_to_string(d->dvdnav) );
847         return 0;
848     }
849     d->title = t;
850     d->stopped = 0;
851     d->chapter = 0;
852     return 1;
853 }
854
855 /***********************************************************************
856  * hb_dvdnav_stop
857  ***********************************************************************
858  *
859  **********************************************************************/
860 static void hb_dvdnav_stop( hb_dvd_t * e )
861 {
862 }
863
864 /***********************************************************************
865  * hb_dvdnav_seek
866  ***********************************************************************
867  *
868  **********************************************************************/
869 static int hb_dvdnav_seek( hb_dvd_t * e, float f )
870 {
871     hb_dvdnav_t * d = &(e->dvdnav);
872     uint64_t sector = f * d->title_block_count;
873     int result, event, len;
874     uint8_t buf[HB_DVD_READ_BUFFER_SIZE];
875     int done = 0, ii;
876
877     if (d->stopped)
878     {
879         return 0;
880     }
881
882     // XXX the current version of libdvdnav can't seek outside the current
883     // PGC. Check if the place we're seeking to is in a different
884     // PGC. Position there & adjust the offset if so.
885     hb_chapter_t *pgc_change = hb_list_item(d->list_chapter, 0 );
886     for ( ii = 0; ii < hb_list_count( d->list_chapter ); ++ii )
887     {
888         hb_chapter_t *chapter = hb_list_item( d->list_chapter, ii );
889
890         if ( chapter->pgcn != pgc_change->pgcn )
891         {
892             // this chapter's in a different pgc from the previous - note the
893             // change so we can make sector offset's be pgc relative.
894             pgc_change = chapter;
895         }
896         if ( chapter->block_start <= sector && sector <= chapter->block_end )
897         {
898             // this chapter contains the sector we want - see if it's in a
899             // different pgc than the one we're currently in.
900             int32_t title, pgcn, pgn;
901             if (dvdnav_current_title_program( d->dvdnav, &title, &pgcn, &pgn ) != DVDNAV_STATUS_OK)
902                 hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(d->dvdnav));
903             if ( d->title != title || chapter->pgcn != pgcn )
904             {
905                 // this chapter is in a different pgc - switch to it.
906                 if (dvdnav_program_play(d->dvdnav, d->title, chapter->pgcn, chapter->pgn) != DVDNAV_STATUS_OK)
907                     hb_log("dvdnav prog play err: %s", dvdnav_err_to_string(d->dvdnav));
908             }
909             // seek sectors are pgc-relative so remove the pgc start sector.
910             sector -= pgc_change->block_start;
911             break;
912         }
913     }
914
915     // dvdnav will not let you seek or poll current position
916     // till it reaches a certain point in parsing.  so we
917     // have to get blocks until we reach a cell
918     // Put an arbitrary limit of 100 blocks on how long we search
919     for (ii = 0; ii < 100 && !done; ii++)
920     {
921         result = dvdnav_get_next_block( d->dvdnav, buf, &event, &len );
922         if ( result == DVDNAV_STATUS_ERR )
923         {
924             hb_log("dvdnav: Read Error, %s", dvdnav_err_to_string(d->dvdnav));
925             return 0;
926         }
927         switch ( event )
928         {
929         case DVDNAV_BLOCK_OK:
930         case DVDNAV_CELL_CHANGE:
931             done = 1;
932             break;
933
934         case DVDNAV_STILL_FRAME:
935             dvdnav_still_skip( d->dvdnav );
936             break;
937
938         case DVDNAV_WAIT:
939             dvdnav_wait_skip( d->dvdnav );
940             break;
941
942         case DVDNAV_STOP:
943             hb_log("dvdnav: stop encountered during seek");
944             d->stopped = 1;
945             return 0;
946
947         case DVDNAV_HOP_CHANNEL:
948         case DVDNAV_NAV_PACKET:
949         case DVDNAV_VTS_CHANGE:
950         case DVDNAV_HIGHLIGHT:
951         case DVDNAV_AUDIO_STREAM_CHANGE:
952         case DVDNAV_SPU_STREAM_CHANGE:
953         case DVDNAV_SPU_CLUT_CHANGE:
954         case DVDNAV_NOP:
955         default:
956             break;
957         }
958     }
959
960     if (dvdnav_sector_search(d->dvdnav, sector, SEEK_SET) != DVDNAV_STATUS_OK)
961     {
962         hb_error( "dvd: dvdnav_sector_search failed - %s", 
963                   dvdnav_err_to_string(d->dvdnav) );
964         return 0;
965     }
966     return 1;
967 }
968
969 /***********************************************************************
970  * hb_dvdnav_read
971  ***********************************************************************
972  *
973  **********************************************************************/
974 static int hb_dvdnav_read( hb_dvd_t * e, hb_buffer_t * b )
975 {
976     hb_dvdnav_t * d = &(e->dvdnav);
977     int result, event, len;
978     int chapter = 0;
979     int error_count = 0;
980
981     while ( 1 )
982     {
983         if (d->stopped)
984         {
985             return 0;
986         }
987         result = dvdnav_get_next_block( d->dvdnav, b->data, &event, &len );
988         if ( result == DVDNAV_STATUS_ERR )
989         {
990             hb_log("dvdnav: Read Error, %s", dvdnav_err_to_string(d->dvdnav));
991             if (dvdnav_sector_search(d->dvdnav, 1, SEEK_CUR) != DVDNAV_STATUS_OK)
992             {
993                 hb_error( "dvd: dvdnav_sector_search failed - %s",
994                         dvdnav_err_to_string(d->dvdnav) );
995                 return 0;
996             }
997             error_count++;
998             if (error_count > 10)
999             {
1000                 hb_log("dvdnav: Error, too many consecutive read errors");
1001                 return 0;
1002             }
1003             continue;
1004         }
1005         error_count = 0;
1006         switch ( event )
1007         {
1008         case DVDNAV_BLOCK_OK:
1009             // We have received a regular block of the currently playing
1010             // MPEG stream.
1011
1012             // The muxers expect to only get chapter 2 and above
1013             // They write chapter 1 when chapter 2 is detected.
1014             if (chapter > 1)
1015                 b->new_chap = chapter;
1016             chapter = 0;
1017             return 1;
1018
1019         case DVDNAV_NOP:
1020             /*
1021             * Nothing to do here. 
1022             */
1023             break;
1024
1025         case DVDNAV_STILL_FRAME:
1026             /*
1027             * We have reached a still frame. A real player application
1028             * would wait the amount of time specified by the still's
1029             * length while still handling user input to make menus and
1030             * other interactive stills work. A length of 0xff means an
1031             * indefinite still which has to be skipped indirectly by some 
1032             * user interaction. 
1033             */
1034             dvdnav_still_skip( d->dvdnav );
1035             break;
1036
1037         case DVDNAV_WAIT:
1038             /*
1039             * We have reached a point in DVD playback, where timing is
1040             * critical. Player application with internal fifos can
1041             * introduce state inconsistencies, because libdvdnav is
1042             * always the fifo's length ahead in the stream compared to
1043             * what the application sees. Such applications should wait
1044             * until their fifos are empty when they receive this type of
1045             * event. 
1046             */
1047             dvdnav_wait_skip( d->dvdnav );
1048             break;
1049
1050         case DVDNAV_SPU_CLUT_CHANGE:
1051             /*
1052             * Player applications should pass the new colour lookup table 
1053             * to their SPU decoder 
1054             */
1055             break;
1056
1057         case DVDNAV_SPU_STREAM_CHANGE:
1058             /*
1059             * Player applications should inform their SPU decoder to
1060             * switch channels 
1061             */
1062             break;
1063
1064         case DVDNAV_AUDIO_STREAM_CHANGE:
1065             /*
1066             * Player applications should inform their audio decoder to
1067             * switch channels 
1068             */
1069             break;
1070
1071         case DVDNAV_HIGHLIGHT:
1072             /*
1073             * Player applications should inform their overlay engine to
1074             * highlight the given button 
1075             */
1076             break;
1077
1078         case DVDNAV_VTS_CHANGE:
1079             /*
1080             * Some status information like video aspect and video scale
1081             * permissions do not change inside a VTS. Therefore this
1082             * event can be used to query such information only when
1083             * necessary and update the decoding/displaying accordingly. 
1084             */
1085             break;
1086
1087         case DVDNAV_CELL_CHANGE:
1088             /*
1089             * Some status information like the current Title and Part
1090             * numbers do not change inside a cell. Therefore this event
1091             * can be used to query such information only when necessary
1092             * and update the decoding/displaying accordingly. 
1093             */
1094             {
1095                 int tt = 0, pgcn = 0, pgn = 0, c;
1096
1097                 dvdnav_current_title_program(d->dvdnav, &tt, &pgcn, &pgn);
1098                 if (tt != d->title)
1099                 {
1100                     // Transition to another title signals that we are done.
1101                     return 0;
1102                 }
1103                 c = FindChapterIndex(d->list_chapter, pgcn, pgn);
1104                 if (c != d->chapter)
1105                 {
1106                     if (c < d->chapter)
1107                     {
1108                         // Some titles end with a 'link' back to the beginning so
1109                         // a transition to an earlier chapter means we're done.
1110                         return 0;
1111                     }
1112                     chapter = d->chapter = c;
1113                 }
1114             }
1115             break;
1116
1117         case DVDNAV_NAV_PACKET:
1118             /*
1119             * A NAV packet provides PTS discontinuity information, angle
1120             * linking information and button definitions for DVD menus.
1121             * Angles are handled completely inside libdvdnav. For the
1122             * menus to work, the NAV packet information has to be passed
1123             * to the overlay engine of the player so that it knows the
1124             * dimensions of the button areas. 
1125             */
1126
1127             // mpegdemux expects to get these.  I don't think it does
1128             // anything useful with them however.
1129
1130             // The muxers expect to only get chapter 2 and above
1131             // They write chapter 1 when chapter 2 is detected.
1132             if (chapter > 1)
1133                 b->new_chap = chapter;
1134             chapter = 0;
1135             return 1;
1136
1137             break;
1138
1139         case DVDNAV_HOP_CHANNEL:
1140             /*
1141             * This event is issued whenever a non-seamless operation has
1142             * been executed. Applications with fifos should drop the
1143             * fifos content to speed up responsiveness. 
1144             */
1145             break;
1146
1147         case DVDNAV_STOP:
1148             /*
1149             * Playback should end here. 
1150             */
1151             d->stopped = 1;
1152             return 0;
1153
1154         default:
1155             break;
1156         }
1157     }
1158     return 0;
1159 }
1160
1161 /***********************************************************************
1162  * hb_dvdnav_chapter
1163  ***********************************************************************
1164  * Returns in which chapter the next block to be read is.
1165  * Chapter numbers start at 1.
1166  **********************************************************************/
1167 static int hb_dvdnav_chapter( hb_dvd_t * e )
1168 {
1169     hb_dvdnav_t * d = &(e->dvdnav);
1170     int32_t t, pgcn, pgn;
1171     int32_t c;
1172
1173     if (dvdnav_current_title_program(d->dvdnav, &t, &pgcn, &pgn) != DVDNAV_STATUS_OK)
1174     {
1175         return -1;
1176     }
1177     c = FindChapterIndex( d->list_chapter, pgcn, pgn );
1178     return c;
1179 }
1180
1181 /***********************************************************************
1182  * hb_dvdnav_close
1183  ***********************************************************************
1184  * Closes and frees everything
1185  **********************************************************************/
1186 static void hb_dvdnav_close( hb_dvd_t ** _d )
1187 {
1188     hb_dvdnav_t * d = &((*_d)->dvdnav);
1189
1190     if( d->dvdnav ) dvdnav_close( d->dvdnav );
1191     if( d->vmg ) ifoClose( d->vmg );
1192     if( d->reader ) DVDClose( d->reader );
1193
1194     free( d );
1195     *_d = NULL;
1196 }
1197
1198 /***********************************************************************
1199  * hb_dvdnav_angle_count
1200  ***********************************************************************
1201  * Returns the number of angles supported.
1202  **********************************************************************/
1203 static int hb_dvdnav_angle_count( hb_dvd_t * e )
1204 {
1205     hb_dvdnav_t * d = &(e->dvdnav);
1206     int current, angle_count;
1207
1208     if (dvdnav_get_angle_info( d->dvdnav, &current, &angle_count) != DVDNAV_STATUS_OK)
1209     {
1210         hb_log("dvdnav_get_angle_info %s", dvdnav_err_to_string(d->dvdnav));
1211         angle_count = 1;
1212     }
1213     return angle_count;
1214 }
1215
1216 /***********************************************************************
1217  * hb_dvdnav_set_angle
1218  ***********************************************************************
1219  * Sets the angle to read
1220  **********************************************************************/
1221 static void hb_dvdnav_set_angle( hb_dvd_t * e, int angle )
1222 {
1223     hb_dvdnav_t * d = &(e->dvdnav);
1224
1225     if (dvdnav_angle_change( d->dvdnav, angle) != DVDNAV_STATUS_OK)
1226     {
1227         hb_log("dvdnav_angle_change %s", dvdnav_err_to_string(d->dvdnav));
1228     }
1229 }
1230
1231 /***********************************************************************
1232  * FindChapterIndex
1233  ***********************************************************************
1234  * Assumes pgc and cell_cur are correctly set, and sets cell_next to the
1235  * cell to be read when we will be done with cell_cur.
1236  **********************************************************************/
1237 static int FindChapterIndex( hb_list_t * list, int pgcn, int pgn )
1238 {
1239     int count, ii;
1240     hb_chapter_t *chapter;
1241
1242     count = hb_list_count( list );
1243     for (ii = 0; ii < count; ii++)
1244     {
1245         chapter = hb_list_item( list, ii );
1246         if (chapter->pgcn == pgcn && chapter->pgn == pgn)
1247             return chapter->index;
1248     }
1249     return 0;
1250 }
1251
1252 /***********************************************************************
1253  * FindNextCell
1254  ***********************************************************************
1255  * Assumes pgc and cell_cur are correctly set, and sets cell_next to the
1256  * cell to be read when we will be done with cell_cur.
1257  **********************************************************************/
1258 static int FindNextCell( pgc_t *pgc, int cell_cur )
1259 {
1260     int i = 0;
1261     int cell_next;
1262
1263     if( pgc->cell_playback[cell_cur].block_type ==
1264             BLOCK_TYPE_ANGLE_BLOCK )
1265     {
1266
1267         while( pgc->cell_playback[cell_cur+i].block_mode !=
1268                    BLOCK_MODE_LAST_CELL )
1269         {
1270              i++;
1271         }
1272         cell_next = cell_cur + i + 1;
1273         hb_log( "dvd: Skipping multi-angle cells %d-%d",
1274                 cell_cur,
1275                 cell_next - 1 );
1276     }
1277     else
1278     {
1279         cell_next = cell_cur + 1;
1280     }
1281     return cell_next;
1282 }
1283
1284 /***********************************************************************
1285  * NextPgcn
1286  ***********************************************************************
1287  * Assumes pgc and cell_cur are correctly set, and sets cell_next to the
1288  * cell to be read when we will be done with cell_cur.
1289  * Since pg chains can be circularly linked (either from a read error or
1290  * deliberately) pgcn_map tracks program chains we've already seen.
1291  **********************************************************************/
1292 static int NextPgcn( ifo_handle_t *ifo, int pgcn, uint32_t pgcn_map[MAX_PGCN/32] )
1293 {
1294     int next_pgcn;
1295     pgc_t *pgc;
1296
1297     pgcn_map[pgcn >> 5] |= (1 << (pgcn & 31));
1298
1299     pgc = ifo->vts_pgcit->pgci_srp[pgcn-1].pgc;
1300     next_pgcn = pgc->next_pgc_nr;
1301     if ( next_pgcn < 1 || next_pgcn >= MAX_PGCN || next_pgcn > ifo->vts_pgcit->nr_of_pgci_srp )
1302         return 0;
1303
1304     return pgcn_map[next_pgcn >> 5] & (1 << (next_pgcn & 31))? 0 : next_pgcn;
1305 }
1306
1307 /***********************************************************************
1308  * PgcWalkInit
1309  ***********************************************************************
1310  * Pgc links can loop. I track which have been visited in a bit vector
1311  * Initialize the bit vector to empty.
1312  **********************************************************************/
1313 static void PgcWalkInit( uint32_t pgcn_map[MAX_PGCN/32] )
1314 {
1315     memset(pgcn_map, 0, sizeof(pgcn_map) );
1316 }
1317
1318 /***********************************************************************
1319  * dvdtime2msec
1320  ***********************************************************************
1321  * From lsdvd
1322  **********************************************************************/
1323 static int dvdtime2msec(dvd_time_t * dt)
1324 {
1325     double frames_per_s[4] = {-1.0, 25.00, -1.0, 29.97};
1326     double fps = frames_per_s[(dt->frame_u & 0xc0) >> 6];
1327     long   ms;
1328     ms  = (((dt->hour &   0xf0) >> 3) * 5 + (dt->hour   & 0x0f)) * 3600000;
1329     ms += (((dt->minute & 0xf0) >> 3) * 5 + (dt->minute & 0x0f)) * 60000;
1330     ms += (((dt->second & 0xf0) >> 3) * 5 + (dt->second & 0x0f)) * 1000;
1331
1332     if( fps > 0 )
1333     {
1334         ms += ((dt->frame_u & 0x30) >> 3) * 5 +
1335               (dt->frame_u & 0x0f) * 1000.0 / fps;
1336     }
1337
1338     return ms;
1339 }