OSDN Git Service

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