3 Copyright (c) 2003-2015 HandBrake Team
4 This file is part of the HandBrake source code
5 Homepage: <http://handbrake.fr/>.
6 It may be used under the terms of the GNU General Public License v2.
7 For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
14 #include "dvdnav/dvdnav.h"
15 #include "dvdread/ifo_read.h"
16 #include "dvdread/ifo_print.h"
17 #include "dvdread/nav_read.h"
19 #define DVD_READ_CACHE 1
21 static char * hb_dvdnav_name( char * path
);
22 static hb_dvd_t
* hb_dvdnav_init( hb_handle_t
* h
, char * path
);
23 static int hb_dvdnav_title_count( hb_dvd_t
* d
);
24 static hb_title_t
* hb_dvdnav_title_scan( hb_dvd_t
* d
, int t
, uint64_t min_duration
);
25 static int hb_dvdnav_start( hb_dvd_t
* d
, hb_title_t
*title
, int chapter
);
26 static void hb_dvdnav_stop( hb_dvd_t
* d
);
27 static int hb_dvdnav_seek( hb_dvd_t
* d
, float f
);
28 static hb_buffer_t
* hb_dvdnav_read( hb_dvd_t
* d
);
29 static int hb_dvdnav_chapter( hb_dvd_t
* d
);
30 static void hb_dvdnav_close( hb_dvd_t
** _d
);
31 static int hb_dvdnav_angle_count( hb_dvd_t
* d
);
32 static void hb_dvdnav_set_angle( hb_dvd_t
* d
, int angle
);
33 static int hb_dvdnav_main_feature( hb_dvd_t
* d
, hb_list_t
* list_title
);
35 hb_dvd_func_t hb_dvdnav_func
=
40 hb_dvdnav_title_count
,
47 hb_dvdnav_angle_count
,
49 hb_dvdnav_main_feature
52 // there can be at most 999 PGCs per title. round that up to the nearest
56 /***********************************************************************
58 **********************************************************************/
59 static void PgcWalkInit( uint32_t pgcn_map
[MAX_PGCN
/32] );
60 static int FindChapterIndex( hb_list_t
* list
, int pgcn
, int pgn
);
61 static int NextPgcn( ifo_handle_t
*ifo
, int pgcn
, uint32_t pgcn_map
[MAX_PGCN
/32] );
62 static int FindNextCell( pgc_t
*pgc
, int cell_cur
);
63 static int dvdtime2msec( dvd_time_t
* );
65 hb_dvd_func_t
* hb_dvdnav_methods( void )
67 return &hb_dvdnav_func
;
70 static char * hb_dvdnav_name( char * path
)
72 static char name
[1024];
73 unsigned char unused
[1024];
74 dvd_reader_t
* reader
;
76 reader
= DVDOpen( path
);
82 if( DVDUDFVolumeInfo( reader
, name
, sizeof( name
),
83 unused
, sizeof( unused
) ) )
93 /***********************************************************************
95 ***********************************************************************
96 * Once dvdnav has entered the 'stopped' state, it can not be revived
97 * dvdnav_reset doesn't work because it doesn't remember the path
98 * So this function re-opens dvdnav
99 **********************************************************************/
100 static int hb_dvdnav_reset( hb_dvdnav_t
* d
)
102 char * path_ccp
= hb_utf8_to_cp( d
->path
);
104 dvdnav_close( d
->dvdnav
);
107 if( dvdnav_open(&d
->dvdnav
, path_ccp
) != DVDNAV_STATUS_OK
)
110 * Not an error, may be a stream - which we'll try in a moment.
112 hb_log( "dvd: not a dvd - trying as a stream/file instead" );
116 if (dvdnav_set_readahead_flag(d
->dvdnav
, DVD_READ_CACHE
) !=
119 hb_error("Error: dvdnav_set_readahead_flag: %s\n",
120 dvdnav_err_to_string(d
->dvdnav
));
125 ** set the PGC positioning flag to have position information
126 ** relatively to the whole feature instead of just relatively to the
129 if (dvdnav_set_PGC_positioning_flag(d
->dvdnav
, 1) != DVDNAV_STATUS_OK
)
131 hb_error("Error: dvdnav_set_PGC_positioning_flag: %s\n",
132 dvdnav_err_to_string(d
->dvdnav
));
141 if( d
->dvdnav
) dvdnav_close( d
->dvdnav
);
146 /***********************************************************************
148 ***********************************************************************
150 **********************************************************************/
151 static hb_dvd_t
* hb_dvdnav_init( hb_handle_t
* h
, char * path
)
158 e
= calloc( sizeof( hb_dvd_t
), 1 );
163 * Convert UTF-8 path to current code page on Windows
164 * hb_utf8_to_cp() is the same as strdup on non-Windows,
165 * so no #ifdef required here
167 path_ccp
= hb_utf8_to_cp( path
);
169 /* Log DVD drive region code */
170 if ( hb_dvd_region( path_ccp
, ®ion_mask
) == 0 )
172 hb_log( "dvd: Region mask 0x%02x", region_mask
);
173 if ( region_mask
== 0xFF )
175 hb_log( "dvd: Warning, DVD device has no region set" );
180 if( dvdnav_open(&d
->dvdnav
, path_ccp
) != DVDNAV_STATUS_OK
)
183 * Not an error, may be a stream - which we'll try in a moment.
185 hb_log( "dvd: not a dvd - trying as a stream/file instead" );
189 if (dvdnav_set_readahead_flag(d
->dvdnav
, DVD_READ_CACHE
) !=
192 hb_error("Error: dvdnav_set_readahead_flag: %s\n",
193 dvdnav_err_to_string(d
->dvdnav
));
198 ** set the PGC positioning flag to have position information
199 ** relatively to the whole feature instead of just relatively to the
202 if (dvdnav_set_PGC_positioning_flag(d
->dvdnav
, 1) != DVDNAV_STATUS_OK
)
204 hb_error("Error: dvdnav_set_PGC_positioning_flag: %s\n",
205 dvdnav_err_to_string(d
->dvdnav
));
210 if( !( d
->reader
= DVDOpen( path_ccp
) ) )
213 * Not an error, may be a stream - which we'll try in a moment.
215 hb_log( "dvd: not a dvd - trying as a stream/file instead" );
220 if( !( d
->vmg
= ifoOpen( d
->reader
, 0 ) ) )
222 hb_error( "dvd: ifoOpen failed" );
226 d
->path
= strdup( path
); /* hb_dvdnav_title_scan assumes UTF-8 path, so not path_ccp here */
232 if( d
->dvdnav
) dvdnav_close( d
->dvdnav
);
233 if( d
->vmg
) ifoClose( d
->vmg
);
234 if( d
->reader
) DVDClose( d
->reader
);
240 /***********************************************************************
241 * hb_dvdnav_title_count
242 **********************************************************************/
243 static int hb_dvdnav_title_count( hb_dvd_t
* e
)
246 hb_dvdnav_t
* d
= &(e
->dvdnav
);
248 dvdnav_get_number_of_titles(d
->dvdnav
, &titles
);
253 PttDuration(ifo_handle_t
*ifo
, int ttn
, int pttn
, int *blocks
, int *last_pgcn
)
257 uint64_t duration
= 0;
258 int cell_start
, cell_end
;
263 // Initialize map of visited pgc's to prevent loops
264 uint32_t pgcn_map
[MAX_PGCN
/32];
265 PgcWalkInit( pgcn_map
);
266 pgcn
= ifo
->vts_ptt_srpt
->title
[ttn
-1].ptt
[pttn
-1].pgcn
;
267 pgn
= ifo
->vts_ptt_srpt
->title
[ttn
-1].ptt
[pttn
-1].pgn
;
268 if ( pgcn
< 1 || pgcn
> ifo
->vts_pgcit
->nr_of_pgci_srp
|| pgcn
>= MAX_PGCN
)
270 hb_log( "invalid PGC ID %d, skipping", pgcn
);
274 if( pgn
<= 0 || pgn
> 99 )
276 hb_log( "scan: pgn %d not valid, skipping", pgn
);
282 pgc
= ifo
->vts_pgcit
->pgci_srp
[pgcn
-1].pgc
;
287 hb_log( "scan: pgc not valid, skipping" );
291 if (pgc
->cell_playback
== NULL
)
295 hb_log("invalid PGC cell_playback table, skipping");
299 if (pgn
> pgc
->nr_of_programs
)
305 duration
+= 90LL * dvdtime2msec( &pgc
->playback_time
);
307 cell_start
= pgc
->program_map
[pgn
-1] - 1;
308 cell_end
= pgc
->nr_of_cells
- 1;
309 for(i
= cell_start
; i
<= cell_end
; i
= FindNextCell(pgc
, i
))
311 *blocks
+= pgc
->cell_playback
[i
].last_sector
+ 1 -
312 pgc
->cell_playback
[i
].first_sector
;
316 } while((pgcn
= NextPgcn(ifo
, pgcn
, pgcn_map
)) != 0);
320 /***********************************************************************
321 * hb_dvdnav_title_scan
322 **********************************************************************/
323 static hb_title_t
* hb_dvdnav_title_scan( hb_dvd_t
* e
, int t
, uint64_t min_duration
)
326 hb_dvdnav_t
* d
= &(e
->dvdnav
);
328 ifo_handle_t
* ifo
= NULL
;
329 int pgcn
, pgn
, pgcn_end
, i
, c
;
333 hb_chapter_t
* chapter
;
335 uint64_t duration
, longest
;
336 int longest_pgcn
, longest_pgn
, longest_pgcn_end
;
338 unsigned char unused
[1024];
339 const char * codec_name
;
341 hb_log( "scan: scanning title %d", t
);
343 title
= hb_title_init( d
->path
, t
);
344 title
->type
= HB_DVD_TYPE
;
345 if (dvdnav_get_title_string(d
->dvdnav
, &name
) == DVDNAV_STATUS_OK
)
347 strncpy( title
->name
, name
, sizeof( title
->name
) );
350 if (strlen(title
->name
) == 0)
352 if( DVDUDFVolumeInfo( d
->reader
, title
->name
, sizeof( title
->name
),
353 unused
, sizeof( unused
) ) )
356 char * p_cur
, * p_last
= d
->path
;
357 for( p_cur
= d
->path
; *p_cur
; p_cur
++ )
359 if( IS_DIR_SEP(p_cur
[0]) && p_cur
[1] )
364 snprintf( title
->name
, sizeof( title
->name
), "%s", p_last
);
365 char *dot_term
= strrchr(title
->name
, '.');
371 /* VTS which our title is in */
372 title
->vts
= d
->vmg
->tt_srpt
->title
[t
-1].title_set_nr
;
376 /* A VTS of 0 means the title wasn't found in the title set */
377 hb_log("Invalid VTS (title set) number: %i", title
->vts
);
381 hb_log( "scan: opening IFO for VTS %d", title
->vts
);
382 if( !( ifo
= ifoOpen( d
->reader
, title
->vts
) ) )
384 hb_log( "scan: ifoOpen failed" );
388 /* ignore titles with bogus cell addresses so we don't abort later
390 for ( i
= 0; i
< ifo
->vts_c_adt
->nr_of_vobs
; ++i
)
392 if( (ifo
->vts_c_adt
->cell_adr_table
[i
].start_sector
& 0xffffff ) ==
395 hb_log( "scan: cell_adr_table[%d].start_sector invalid (0x%x) "
396 "- skipping title", i
,
397 ifo
->vts_c_adt
->cell_adr_table
[i
].start_sector
);
400 if( (ifo
->vts_c_adt
->cell_adr_table
[i
].last_sector
& 0xffffff ) ==
403 hb_log( "scan: cell_adr_table[%d].last_sector invalid (0x%x) "
404 "- skipping title", i
,
405 ifo
->vts_c_adt
->cell_adr_table
[i
].last_sector
);
410 if( global_verbosity_level
== 3 )
412 ifo_print( d
->reader
, title
->vts
);
415 /* Position of the title in the VTS */
416 title
->ttn
= d
->vmg
->tt_srpt
->title
[t
-1].vts_ttn
;
417 if ( title
->ttn
< 1 || title
->ttn
> ifo
->vts_ptt_srpt
->nr_of_srpts
)
419 hb_log( "invalid VTS PTT offset %d for title %d, skipping", title
->ttn
, t
);
426 longest_pgcn_end
= -1;
428 for( i
= 0; i
< ifo
->vts_ptt_srpt
->title
[title
->ttn
-1].nr_of_ptts
; i
++ )
432 duration
= PttDuration(ifo
, title
->ttn
, i
+1, &blocks
, &pgcn_end
);
433 pgcn
= ifo
->vts_ptt_srpt
->title
[title
->ttn
-1].ptt
[i
].pgcn
;
434 pgn
= ifo
->vts_ptt_srpt
->title
[title
->ttn
-1].ptt
[i
].pgn
;
435 if( duration
> longest
)
439 longest_pgcn_end
= pgcn_end
;
441 title
->block_count
= blocks
;
443 else if (pgcn
== longest_pgcn
&& pgn
< longest_pgn
)
446 title
->block_count
= blocks
;
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 );
459 /* ignore titles under 10 seconds because they're often stills or
460 * clips with no audio & our preview code doesn't currently handle
461 * either of these. */
462 if( longest
< min_duration
)
464 hb_log( "scan: ignoring title (too short)" );
469 pgcn_end
= longest_pgcn_end
;
475 if ( pgcn
< 1 || pgcn
> ifo
->vts_pgcit
->nr_of_pgci_srp
|| pgcn
>= MAX_PGCN
)
477 hb_log( "invalid PGC ID %d for title %d, skipping", pgcn
, t
);
481 // Check all pgc's for validity
482 uint32_t pgcn_map
[MAX_PGCN
/32];
483 PgcWalkInit( pgcn_map
);
486 pgc
= ifo
->vts_pgcit
->pgci_srp
[pgcn
-1].pgc
;
488 if( !pgc
|| !pgc
->program_map
)
490 hb_log( "scan: pgc not valid, skipping" );
494 if (pgc
->cell_playback
== NULL
)
496 hb_log( "invalid PGC cell_playback table for title %d, skipping", t
);
499 } while ((pgcn
= NextPgcn(ifo
, pgcn
, pgcn_map
)) != 0);
502 pgc
= ifo
->vts_pgcit
->pgci_srp
[pgcn
-1].pgc
;
504 hb_log("pgc_id: %d, pgn: %d: pgc: %p", pgcn
, pgn
, pgc
);
505 if (pgn
> pgc
->nr_of_programs
)
507 hb_log( "invalid PGN %d for title %d, skipping", pgn
, t
);
512 title
->cell_start
= pgc
->program_map
[pgn
-1] - 1;
513 title
->block_start
= pgc
->cell_playback
[title
->cell_start
].first_sector
;
515 pgc
= ifo
->vts_pgcit
->pgci_srp
[pgcn_end
-1].pgc
;
518 title
->cell_end
= pgc
->nr_of_cells
- 1;
519 title
->block_end
= pgc
->cell_playback
[title
->cell_end
].last_sector
;
521 hb_log( "scan: vts=%d, ttn=%d, cells=%d->%d, blocks=%"PRIu64
"->%"PRIu64
", "
522 "%"PRIu64
" blocks", title
->vts
, title
->ttn
, title
->cell_start
,
523 title
->cell_end
, title
->block_start
, title
->block_end
,
524 title
->block_count
);
526 /* Detect languages */
527 for( i
= 0; i
< ifo
->vtsi_mat
->nr_of_vts_audio_streams
; i
++ )
529 int audio_format
, lang_code
, lang_extension
, audio_control
, position
, j
;
530 hb_audio_t
* audio
, * audio_tmp
;
531 iso639_lang_t
* lang
;
533 hb_log( "scan: checking audio %d", i
+ 1 );
535 audio
= calloc( sizeof( hb_audio_t
), 1 );
537 audio_format
= ifo
->vtsi_mat
->vts_audio_attr
[i
].audio_format
;
538 lang_code
= ifo
->vtsi_mat
->vts_audio_attr
[i
].lang_code
;
539 lang_extension
= ifo
->vtsi_mat
->vts_audio_attr
[i
].code_extension
;
541 ifo
->vts_pgcit
->pgci_srp
[title_pgcn
-1].pgc
->audio_control
[i
];
543 if( !( audio_control
& 0x8000 ) )
545 hb_log( "scan: audio channel is not active" );
550 position
= ( audio_control
& 0x7F00 ) >> 8;
552 switch( audio_format
)
555 audio
->id
= ( ( 0x80 + position
) << 8 ) | 0xbd;
556 audio
->config
.in
.codec
= HB_ACODEC_AC3
;
557 audio
->config
.in
.codec_param
= AV_CODEC_ID_AC3
;
563 audio
->id
= 0xc0 + position
;
564 audio
->config
.in
.codec
= HB_ACODEC_FFMPEG
;
565 audio
->config
.in
.codec_param
= AV_CODEC_ID_MP2
;
570 audio
->id
= ( ( 0xa0 + position
) << 8 ) | 0xbd;
571 audio
->config
.in
.codec
= HB_ACODEC_LPCM
;
576 audio
->id
= ( ( 0x88 + position
) << 8 ) | 0xbd;
577 audio
->config
.in
.codec
= HB_ACODEC_DCA
;
578 audio
->config
.in
.codec_param
= AV_CODEC_ID_DTS
;
584 audio
->config
.in
.codec
= 0;
585 codec_name
= "Unknown";
586 hb_log( "scan: unknown audio codec (%x)",
595 /* Check for duplicate tracks */
597 for( j
= 0; j
< hb_list_count( title
->list_audio
); j
++ )
599 audio_tmp
= hb_list_item( title
->list_audio
, j
);
600 if( audio
->id
== audio_tmp
->id
)
608 hb_log( "scan: duplicate audio track" );
613 lang
= lang_for_code( lang_code
);
615 audio
->config
.lang
.type
= lang_extension
;
617 snprintf( audio
->config
.lang
.simple
,
618 sizeof( audio
->config
.lang
.simple
), "%s",
619 strlen( lang
->native_name
) ? lang
->native_name
: lang
->eng_name
);
620 snprintf( audio
->config
.lang
.iso639_2
,
621 sizeof( audio
->config
.lang
.iso639_2
), "%s", lang
->iso639_2
);
623 hb_log("scan: id=0x%x, lang=%s (%s), 3cc=%s ext=%i", audio
->id
,
624 audio
->config
.lang
.simple
, codec_name
,
625 audio
->config
.lang
.iso639_2
, lang_extension
);
627 audio
->config
.in
.track
= i
;
628 hb_list_add( title
->list_audio
, audio
);
631 /* Check for subtitles */
632 for( i
= 0; i
< ifo
->vtsi_mat
->nr_of_vts_subp_streams
; i
++ )
634 hb_subtitle_t
* subtitle
;
637 iso639_lang_t
* lang
;
638 int lang_extension
= 0;
640 hb_log( "scan: checking subtitle %d", i
+ 1 );
643 ifo
->vts_pgcit
->pgci_srp
[title_pgcn
-1].pgc
->subp_control
[i
];
645 if( !( spu_control
& 0x80000000 ) )
647 hb_log( "scan: subtitle channel is not active" );
651 if( ifo
->vtsi_mat
->vts_video_attr
.display_aspect_ratio
)
653 switch( ifo
->vtsi_mat
->vts_video_attr
.permitted_df
)
656 position
= spu_control
& 0xFF;
659 position
= ( spu_control
>> 8 ) & 0xFF;
662 position
= ( spu_control
>> 16 ) & 0xFF;
667 position
= ( spu_control
>> 24 ) & 0x7F;
670 lang_extension
= ifo
->vtsi_mat
->vts_subp_attr
[i
].code_extension
;
672 lang
= lang_for_code( ifo
->vtsi_mat
->vts_subp_attr
[i
].lang_code
);
674 subtitle
= calloc( sizeof( hb_subtitle_t
), 1 );
676 subtitle
->id
= ( ( 0x20 + position
) << 8 ) | 0xbd;
677 snprintf( subtitle
->lang
, sizeof( subtitle
->lang
), "%s",
678 strlen(lang
->native_name
) ? lang
->native_name
: lang
->eng_name
);
679 snprintf( subtitle
->iso639_2
, sizeof( subtitle
->iso639_2
), "%s",
681 subtitle
->format
= PICTURESUB
;
682 subtitle
->source
= VOBSUB
;
683 subtitle
->config
.dest
= RENDERSUB
; // By default render (burn-in) the VOBSUB.
684 subtitle
->stream_type
= 0xbd;
685 subtitle
->substream_type
= 0x20 + position
;
686 subtitle
->codec
= WORK_DECVOBSUB
;
688 subtitle
->type
= lang_extension
;
690 memcpy( subtitle
->palette
,
691 ifo
->vts_pgcit
->pgci_srp
[title_pgcn
-1].pgc
->palette
,
692 16 * sizeof( uint32_t ) );
693 subtitle
->palette_set
= 1;
695 switch( lang_extension
)
698 strcat( subtitle
->lang
, " (Caption with bigger size character)" );
701 strcat( subtitle
->lang
, " (Caption for Children)" );
704 strcat( subtitle
->lang
, " (Closed Caption)" );
707 strcat( subtitle
->lang
, " (Closed Caption with bigger size character)" );
710 strcat( subtitle
->lang
, " (Closed Caption for Children)" );
713 strcat( subtitle
->lang
, " (Forced Caption)" );
716 strcat( subtitle
->lang
, " (Director's Commentary)" );
719 strcat( subtitle
->lang
, " (Director's Commentary with bigger size character)" );
722 strcat( subtitle
->lang
, " (Director's Commentary for Children)" );
727 hb_log( "scan: id=0x%x, lang=%s, 3cc=%s ext=%i", subtitle
->id
,
728 subtitle
->lang
, subtitle
->iso639_2
, lang_extension
);
730 hb_list_add( title
->list_subtitle
, subtitle
);
734 PgcWalkInit( pgcn_map
);
738 pgc
= ifo
->vts_pgcit
->pgci_srp
[pgcn
-1].pgc
;
740 for (i
= pgn
; i
<= pgc
->nr_of_programs
; i
++)
742 char chapter_title
[80];
743 chapter
= calloc( sizeof( hb_chapter_t
), 1 );
745 chapter
->pgcn
= pgcn
;
747 chapter
->index
= c
+ 1;
748 sprintf( chapter_title
, "Chapter %d", chapter
->index
);
749 hb_chapter_set_title( chapter
, chapter_title
);
751 hb_list_add( title
->list_chapter
, chapter
);
756 } while ((pgcn
= NextPgcn(ifo
, pgcn
, pgcn_map
)) != 0);
758 hb_log( "scan: title %d has %d chapters", t
, c
);
760 count
= hb_list_count( title
->list_chapter
);
761 for (i
= 0; i
< count
; i
++)
763 chapter
= hb_list_item( title
->list_chapter
, i
);
765 pgcn
= chapter
->pgcn
;
767 pgc
= ifo
->vts_pgcit
->pgci_srp
[pgcn
-1].pgc
;
770 chapter
->cell_start
= pgc
->program_map
[pgn
-1] - 1;
771 chapter
->block_start
= pgc
->cell_playback
[chapter
->cell_start
].first_sector
;
772 // if there are no more programs in this pgc, the end cell is the
773 // last cell. Otherwise it's the cell before the start cell of the
775 if ( pgn
== pgc
->nr_of_programs
)
777 chapter
->cell_end
= pgc
->nr_of_cells
- 1;
781 chapter
->cell_end
= pgc
->program_map
[pgn
] - 2;;
783 chapter
->block_end
= pgc
->cell_playback
[chapter
->cell_end
].last_sector
;
785 /* Block count, duration */
786 chapter
->block_count
= 0;
787 chapter
->duration
= 0;
789 cell_cur
= chapter
->cell_start
;
790 while( cell_cur
<= chapter
->cell_end
)
792 #define cp pgc->cell_playback[cell_cur]
793 chapter
->block_count
+= cp
.last_sector
+ 1 - cp
.first_sector
;
794 chapter
->duration
+= 90LL * dvdtime2msec( &cp
.playback_time
);
796 cell_cur
= FindNextCell( pgc
, cell_cur
);
800 for( i
= 0; i
< hb_list_count( title
->list_chapter
); i
++ )
802 chapter
= hb_list_item( title
->list_chapter
, i
);
804 int seconds
= ( chapter
->duration
+ 45000 ) / 90000;
805 chapter
->hours
= ( seconds
/ 3600 );
806 chapter
->minutes
= ( seconds
% 3600 ) / 60;
807 chapter
->seconds
= ( seconds
% 60 );
809 hb_log( "scan: chap %d c=%d->%d, b=%"PRIu64
"->%"PRIu64
" (%"PRIu64
"), %"PRId64
" ms",
810 chapter
->index
, chapter
->cell_start
, chapter
->cell_end
,
811 chapter
->block_start
, chapter
->block_end
,
812 chapter
->block_count
, chapter
->duration
/ 90 );
815 /* Get aspect. We don't get width/height/rate infos here as
816 they tend to be wrong */
817 switch( ifo
->vtsi_mat
->vts_video_attr
.display_aspect_ratio
)
820 title
->container_dar
.num
= 4;
821 title
->container_dar
.den
= 3;
824 title
->container_dar
.num
= 16;
825 title
->container_dar
.den
= 9;
828 hb_log( "scan: unknown aspect" );
832 hb_log("scan: aspect = %d:%d",
833 title
->container_dar
.num
, title
->container_dar
.den
);
835 /* This title is ok so far */
839 hb_title_close( &title
);
842 if( ifo
) ifoClose( ifo
);
847 /***********************************************************************
848 * hb_dvdnav_title_scan
849 **********************************************************************/
850 static int find_title( hb_list_t
* list_title
, int title
)
854 for ( ii
= 0; ii
< hb_list_count( list_title
); ii
++ )
856 hb_title_t
* hbtitle
= hb_list_item( list_title
, ii
);
857 if ( hbtitle
->index
== title
)
863 static int skip_to_menu( dvdnav_t
* dvdnav
, int blocks
)
866 int result
, event
, len
;
867 uint8_t buf
[HB_DVD_READ_BUFFER_SIZE
];
869 for ( ii
= 0; ii
< blocks
; ii
++ )
871 result
= dvdnav_get_next_block( dvdnav
, buf
, &event
, &len
);
872 if ( result
== DVDNAV_STATUS_ERR
)
874 hb_error("dvdnav: Read Error, %s", dvdnav_err_to_string(dvdnav
));
879 case DVDNAV_BLOCK_OK
:
882 case DVDNAV_CELL_CHANGE
:
886 case DVDNAV_STILL_FRAME
:
888 dvdnav_still_event_t
*event
;
889 event
= (dvdnav_still_event_t
*)buf
;
890 dvdnav_still_skip( dvdnav
);
891 if ( event
->length
== 255 )
893 // Infinite still. Can't be the main feature unless
894 // you like watching paint dry.
900 dvdnav_wait_skip( dvdnav
);
906 case DVDNAV_HOP_CHANNEL
:
909 case DVDNAV_NAV_PACKET
:
911 pci_t
*pci
= dvdnav_get_current_nav_pci( dvdnav
);
912 if ( pci
== NULL
) break;
914 int buttons
= pci
->hli
.hl_gi
.btn_ns
;
917 result
= dvdnav_current_title_info( dvdnav
, &title
, &part
);
918 if (result
!= DVDNAV_STATUS_OK
)
920 hb_log("dvdnav title info: %s", dvdnav_err_to_string(dvdnav
));
922 else if ( title
== 0 && buttons
> 0 )
924 // Check button activation duration to see if this
925 // isn't another fake menu.
926 if ( pci
->hli
.hl_gi
.btn_se_e_ptm
- pci
->hli
.hl_gi
.hli_s_ptm
>
929 // Found what appears to be a good menu.
935 case DVDNAV_VTS_CHANGE
:
937 dvdnav_vts_change_event_t
*event
;
938 event
= (dvdnav_vts_change_event_t
*)buf
;
939 // Some discs initialize the vts with the "first play" item
940 // and some don't seem to. So if we see it is uninitialized,
942 if ( event
->new_vtsN
<= 0 )
943 result
= dvdnav_title_play( dvdnav
, 1 );
946 case DVDNAV_HIGHLIGHT
:
949 case DVDNAV_AUDIO_STREAM_CHANGE
:
952 case DVDNAV_SPU_STREAM_CHANGE
:
955 case DVDNAV_SPU_CLUT_CHANGE
:
968 static int try_button( dvdnav_t
* dvdnav
, int button
, hb_list_t
* list_title
)
970 int result
, event
, len
;
971 uint8_t buf
[HB_DVD_READ_BUFFER_SIZE
];
973 int32_t cur_title
= 0, title
, part
;
974 uint64_t longest_duration
= 0;
977 pci_t
*pci
= dvdnav_get_current_nav_pci( dvdnav
);
979 result
= dvdnav_button_select_and_activate( dvdnav
, pci
, button
+ 1 );
980 if (result
!= DVDNAV_STATUS_OK
)
982 hb_log("dvdnav_button_select_and_activate: %s", dvdnav_err_to_string(dvdnav
));
985 result
= dvdnav_current_title_info( dvdnav
, &title
, &part
);
986 if (result
!= DVDNAV_STATUS_OK
)
987 hb_log("dvdnav cur title info: %s", dvdnav_err_to_string(dvdnav
));
991 for (jj
= 0; jj
< 10; jj
++)
993 for (ii
= 0; ii
< 2000; ii
++)
995 result
= dvdnav_get_next_block( dvdnav
, buf
, &event
, &len
);
996 if ( result
== DVDNAV_STATUS_ERR
)
998 hb_error("dvdnav: Read Error, %s", dvdnav_err_to_string(dvdnav
));
1003 case DVDNAV_BLOCK_OK
:
1006 case DVDNAV_CELL_CHANGE
:
1008 result
= dvdnav_current_title_info( dvdnav
, &title
, &part
);
1009 if (result
!= DVDNAV_STATUS_OK
)
1010 hb_log("dvdnav title info: %s", dvdnav_err_to_string(dvdnav
));
1013 // Note, some "fake" titles have long advertised durations
1014 // but then jump to the real title early in playback.
1015 // So keep reading after finding a long title to detect
1019 case DVDNAV_STILL_FRAME
:
1021 dvdnav_still_event_t
*event
;
1022 event
= (dvdnav_still_event_t
*)buf
;
1023 dvdnav_still_skip( dvdnav
);
1024 if ( event
->length
== 255 )
1026 // Infinite still. Can't be the main feature unless
1027 // you like watching paint dry.
1033 dvdnav_wait_skip( dvdnav
);
1039 case DVDNAV_HOP_CHANNEL
:
1042 case DVDNAV_NAV_PACKET
:
1046 case DVDNAV_VTS_CHANGE
:
1048 result
= dvdnav_current_title_info( dvdnav
, &title
, &part
);
1049 if (result
!= DVDNAV_STATUS_OK
)
1050 hb_log("dvdnav title info: %s", dvdnav_err_to_string(dvdnav
));
1053 // Note, some "fake" titles have long advertised durations
1054 // but then jump to the real title early in playback.
1055 // So keep reading after finding a long title to detect
1059 case DVDNAV_HIGHLIGHT
:
1062 case DVDNAV_AUDIO_STREAM_CHANGE
:
1065 case DVDNAV_SPU_STREAM_CHANGE
:
1068 case DVDNAV_SPU_CLUT_CHANGE
:
1078 // Check if the current title is long enough to qualify
1079 // as the main feature.
1080 if ( cur_title
> 0 )
1082 hb_title_t
* hbtitle
;
1084 index
= find_title( list_title
, cur_title
);
1085 hbtitle
= hb_list_item( list_title
, index
);
1086 if ( hbtitle
!= NULL
)
1088 if ( hbtitle
->duration
/ 90000 > 10 * 60 )
1090 hb_deep_log( 3, "dvdnav: Found candidate feature title %d duration %02d:%02d:%02d on button %d",
1091 cur_title
, hbtitle
->hours
, hbtitle
->minutes
,
1092 hbtitle
->seconds
, button
+1 );
1095 if ( hbtitle
->duration
> longest_duration
)
1097 longest_duration
= hbtitle
->duration
;
1101 // Some titles have long lead-ins. Try skipping it.
1102 dvdnav_next_pg_search( dvdnav
);
1107 if ( longest
!= -1 )
1109 hb_title_t
* hbtitle
;
1111 index
= find_title( list_title
, longest
);
1112 hbtitle
= hb_list_item( list_title
, index
);
1113 if ( hbtitle
!= NULL
)
1115 hb_deep_log( 3, "dvdnav: Found candidate feature title %d duration %02d:%02d:%02d on button %d",
1116 longest
, hbtitle
->hours
, hbtitle
->minutes
,
1117 hbtitle
->seconds
, button
+1 );
1123 static int try_menu(
1125 hb_list_t
* list_title
,
1127 uint64_t fallback_duration
)
1129 int result
, event
, len
;
1130 uint8_t buf
[HB_DVD_READ_BUFFER_SIZE
];
1132 int32_t cur_title
, title
, part
;
1133 uint64_t longest_duration
= 0;
1136 // A bit of a hack here. Abusing Escape menu to mean use whatever
1137 // current menu is already set.
1138 if ( menu
!= DVD_MENU_Escape
)
1140 result
= dvdnav_menu_call( d
->dvdnav
, menu
);
1141 if ( result
!= DVDNAV_STATUS_OK
)
1143 // Sometimes the "first play" item doesn't initialize the
1144 // initial VTS. So do it here.
1145 result
= dvdnav_title_play( d
->dvdnav
, 1 );
1146 result
= dvdnav_menu_call( d
->dvdnav
, menu
);
1147 if ( result
!= DVDNAV_STATUS_OK
)
1149 hb_error("dvdnav: Can not set dvd menu, %s", dvdnav_err_to_string(d
->dvdnav
));
1155 result
= dvdnav_current_title_info( d
->dvdnav
, &title
, &part
);
1156 if (result
!= DVDNAV_STATUS_OK
)
1157 hb_log("dvdnav title info: %s", dvdnav_err_to_string(d
->dvdnav
));
1161 for (jj
= 0; jj
< 4; jj
++)
1163 for (ii
= 0; ii
< 4000; ii
++)
1165 result
= dvdnav_get_next_block( d
->dvdnav
, buf
, &event
, &len
);
1166 if ( result
== DVDNAV_STATUS_ERR
)
1168 hb_error("dvdnav: Read Error, %s", dvdnav_err_to_string(d
->dvdnav
));
1173 case DVDNAV_BLOCK_OK
:
1176 case DVDNAV_CELL_CHANGE
:
1178 result
= dvdnav_current_title_info( d
->dvdnav
, &title
, &part
);
1179 if (result
!= DVDNAV_STATUS_OK
)
1180 hb_log("dvdnav title info: %s", dvdnav_err_to_string(d
->dvdnav
));
1184 case DVDNAV_STILL_FRAME
:
1186 dvdnav_still_event_t
*event
;
1187 event
= (dvdnav_still_event_t
*)buf
;
1188 dvdnav_still_skip( d
->dvdnav
);
1189 if ( event
->length
== 255 )
1191 // Infinite still. There won't be any menus after this.
1197 dvdnav_wait_skip( d
->dvdnav
);
1203 case DVDNAV_HOP_CHANNEL
:
1206 case DVDNAV_NAV_PACKET
:
1208 pci_t
*pci
= dvdnav_get_current_nav_pci( d
->dvdnav
);
1211 if ( pci
== NULL
) break;
1213 buttons
= pci
->hli
.hl_gi
.btn_ns
;
1215 // If we are on a menu that has buttons and
1216 // the button activation duration is long enough
1217 // that this isn't another fake menu.
1218 if ( cur_title
== 0 && buttons
> 0 &&
1219 pci
->hli
.hl_gi
.btn_se_e_ptm
- pci
->hli
.hl_gi
.hli_s_ptm
>
1222 for (kk
= 0; kk
< buttons
; kk
++)
1224 dvdnav_t
*dvdnav_copy
;
1226 result
= dvdnav_dup( &dvdnav_copy
, d
->dvdnav
);
1227 if (result
!= DVDNAV_STATUS_OK
)
1229 hb_log("dvdnav dup failed: %s", dvdnav_err_to_string(d
->dvdnav
));
1232 title
= try_button( dvdnav_copy
, kk
, list_title
);
1233 dvdnav_free_dup( dvdnav_copy
);
1237 hb_title_t
* hbtitle
;
1239 index
= find_title( list_title
, title
);
1240 hbtitle
= hb_list_item( list_title
, index
);
1241 if ( hbtitle
!= NULL
)
1243 if ( hbtitle
->duration
> longest_duration
)
1245 longest_duration
= hbtitle
->duration
;
1247 if ((float)fallback_duration
* 0.75 < longest_duration
)
1257 case DVDNAV_VTS_CHANGE
:
1259 result
= dvdnav_current_title_info( d
->dvdnav
, &title
, &part
);
1260 if (result
!= DVDNAV_STATUS_OK
)
1261 hb_log("dvdnav title info: %s", dvdnav_err_to_string(d
->dvdnav
));
1265 case DVDNAV_HIGHLIGHT
:
1268 case DVDNAV_AUDIO_STREAM_CHANGE
:
1271 case DVDNAV_SPU_STREAM_CHANGE
:
1274 case DVDNAV_SPU_CLUT_CHANGE
:
1284 // Sometimes the menu is preceeded by a intro that just
1285 // gets restarted when hitting the menu button. So
1286 // try skipping with the skip forward button. Then
1287 // try hitting the menu again.
1290 dvdnav_next_pg_search( d
->dvdnav
);
1294 result
= dvdnav_menu_call( d
->dvdnav
, menu
);
1302 static int hb_dvdnav_main_feature( hb_dvd_t
* e
, hb_list_t
* list_title
)
1304 hb_dvdnav_t
* d
= &(e
->dvdnav
);
1305 int longest_root
= -1;
1306 int longest_title
= -1;
1307 int longest_fallback
= 0;
1309 uint64_t longest_duration_root
= 0;
1310 uint64_t longest_duration_title
= 0;
1311 uint64_t longest_duration_fallback
= 0;
1312 uint64_t avg_duration
= 0;
1317 hb_deep_log( 2, "dvdnav: Searching menus for main feature" );
1318 for ( ii
= 0; ii
< hb_list_count( list_title
); ii
++ )
1320 title
= hb_list_item( list_title
, ii
);
1321 if ( title
->duration
> longest_duration_fallback
)
1323 longest_duration_fallback
= title
->duration
;
1324 longest_fallback
= title
->index
;
1326 if ( title
->duration
> 90000L * 60 * 30 )
1328 avg_duration
+= title
->duration
;
1333 avg_duration
/= avg_cnt
;
1335 index
= find_title( list_title
, longest_fallback
);
1336 title
= hb_list_item( list_title
, index
);
1339 hb_deep_log( 2, "dvdnav: Longest title %d duration %02d:%02d:%02d",
1340 longest_fallback
, title
->hours
, title
->minutes
,
1344 dvdnav_reset( d
->dvdnav
);
1345 if ( skip_to_menu( d
->dvdnav
, 2000 ) )
1347 longest_root
= try_menu( d
, list_title
, DVD_MENU_Escape
, longest_duration_fallback
);
1348 if ( longest_root
>= 0 )
1350 index
= find_title( list_title
, longest_root
);
1351 title
= hb_list_item( list_title
, index
);
1354 longest_duration_root
= title
->duration
;
1355 hb_deep_log( 2, "dvdnav: Found first-play title %d duration %02d:%02d:%02d",
1356 longest_root
, title
->hours
, title
->minutes
, title
->seconds
);
1361 hb_deep_log( 2, "dvdnav: No first-play menu title found" );
1365 if ( longest_root
< 0 ||
1366 (float)longest_duration_fallback
* 0.7 > longest_duration_root
)
1368 longest_root
= try_menu( d
, list_title
, DVD_MENU_Root
, longest_duration_fallback
);
1369 if ( longest_root
>= 0 )
1371 index
= find_title( list_title
, longest_root
);
1372 title
= hb_list_item( list_title
, index
);
1375 longest_duration_root
= title
->duration
;
1376 hb_deep_log( 2, "dvdnav: Found root title %d duration %02d:%02d:%02d",
1377 longest_root
, title
->hours
, title
->minutes
, title
->seconds
);
1382 hb_deep_log( 2, "dvdnav: No root menu title found" );
1386 if ( longest_root
< 0 ||
1387 (float)longest_duration_fallback
* 0.7 > longest_duration_root
)
1389 longest_title
= try_menu( d
, list_title
, DVD_MENU_Title
, longest_duration_fallback
);
1390 if ( longest_title
>= 0 )
1392 index
= find_title( list_title
, longest_title
);
1393 title
= hb_list_item( list_title
, index
);
1396 longest_duration_title
= title
->duration
;
1397 hb_deep_log( 2, "dvdnav: found title %d duration %02d:%02d:%02d",
1398 longest_title
, title
->hours
, title
->minutes
,
1404 hb_deep_log( 2, "dvdnav: No title menu title found" );
1408 uint64_t longest_duration
;
1411 if ( longest_duration_root
> longest_duration_title
)
1413 longest_duration
= longest_duration_root
;
1414 longest
= longest_root
;
1418 longest_duration
= longest_duration_title
;
1419 longest
= longest_title
;
1421 if ((float)longest_duration_fallback
* 0.7 > longest_duration
&&
1422 longest_duration
< 90000L * 60 * 30 )
1424 float factor
= (float)avg_duration
/ longest_duration
;
1426 factor
= 1 / factor
;
1427 if ( avg_cnt
> 10 && factor
< 0.7 )
1429 longest
= longest_fallback
;
1430 hb_deep_log( 2, "dvdnav: Using longest title %d", longest
);
1436 /***********************************************************************
1438 ***********************************************************************
1439 * Title and chapter start at 1
1440 **********************************************************************/
1441 static int hb_dvdnav_start( hb_dvd_t
* e
, hb_title_t
*title
, int c
)
1443 hb_dvdnav_t
* d
= &(e
->dvdnav
);
1444 int t
= title
->index
;
1445 hb_chapter_t
*chapter
;
1446 dvdnav_status_t result
;
1448 d
->title_block_count
= title
->block_count
;
1449 d
->list_chapter
= title
->list_chapter
;
1451 if ( d
->stopped
&& !hb_dvdnav_reset(d
) )
1455 dvdnav_reset( d
->dvdnav
);
1456 chapter
= hb_list_item( title
->list_chapter
, c
- 1);
1457 if (chapter
!= NULL
)
1458 result
= dvdnav_program_play(d
->dvdnav
, t
, chapter
->pgcn
, chapter
->pgn
);
1460 result
= dvdnav_part_play(d
->dvdnav
, t
, 1);
1461 if (result
!= DVDNAV_STATUS_OK
)
1463 hb_error( "dvd: dvdnav_*_play failed - %s",
1464 dvdnav_err_to_string(d
->dvdnav
) );
1474 /***********************************************************************
1476 ***********************************************************************
1478 **********************************************************************/
1479 static void hb_dvdnav_stop( hb_dvd_t
* e
)
1483 /***********************************************************************
1485 ***********************************************************************
1487 **********************************************************************/
1488 static int hb_dvdnav_seek( hb_dvd_t
* e
, float f
)
1490 hb_dvdnav_t
* d
= &(e
->dvdnav
);
1491 uint64_t sector
= f
* d
->title_block_count
;
1492 int result
, event
, len
;
1493 uint8_t buf
[HB_DVD_READ_BUFFER_SIZE
];
1501 // XXX the current version of libdvdnav can't seek outside the current
1502 // PGC. Check if the place we're seeking to is in a different
1503 // PGC. Position there & adjust the offset if so.
1504 uint64_t pgc_offset
= 0;
1505 uint64_t chap_offset
= 0;
1506 hb_chapter_t
*pgc_change
= hb_list_item(d
->list_chapter
, 0 );
1507 for ( ii
= 0; ii
< hb_list_count( d
->list_chapter
); ++ii
)
1509 hb_chapter_t
*chapter
= hb_list_item( d
->list_chapter
, ii
);
1510 uint64_t chap_len
= chapter
->block_end
- chapter
->block_start
+ 1;
1512 if ( chapter
->pgcn
!= pgc_change
->pgcn
)
1514 // this chapter's in a different pgc from the previous - note the
1515 // change so we can make sector offset's be pgc relative.
1516 pgc_offset
= chap_offset
;
1517 pgc_change
= chapter
;
1519 if ( chap_offset
<= sector
&& sector
< chap_offset
+ chap_len
)
1521 // this chapter contains the sector we want - see if it's in a
1522 // different pgc than the one we're currently in.
1523 int32_t title
, pgcn
, pgn
;
1524 if (dvdnav_current_title_program( d
->dvdnav
, &title
, &pgcn
, &pgn
) != DVDNAV_STATUS_OK
)
1525 hb_log("dvdnav cur pgcn err: %s", dvdnav_err_to_string(d
->dvdnav
));
1526 // If we find ourselves in a new title, it means a title
1527 // transition was made while reading data. Jumping between
1528 // titles can cause the vm to get into a bad state. So
1529 // reset the vm in this case.
1530 if ( d
->title
!= title
)
1531 dvdnav_reset( d
->dvdnav
);
1533 if ( d
->title
!= title
|| chapter
->pgcn
!= pgcn
)
1535 // this chapter is in a different pgc - switch to it.
1536 if (dvdnav_program_play(d
->dvdnav
, d
->title
, chapter
->pgcn
, chapter
->pgn
) != DVDNAV_STATUS_OK
)
1537 hb_log("dvdnav prog play err: %s", dvdnav_err_to_string(d
->dvdnav
));
1539 // seek sectors are pgc-relative so remove the pgc start sector.
1540 sector
-= pgc_offset
;
1543 chap_offset
+= chap_len
;
1546 // dvdnav will not let you seek or poll current position
1547 // till it reaches a certain point in parsing. so we
1548 // have to get blocks until we reach a cell
1549 // Put an arbitrary limit of 100 blocks on how long we search
1550 for (ii
= 0; ii
< 100 && !done
; ii
++)
1552 result
= dvdnav_get_next_block( d
->dvdnav
, buf
, &event
, &len
);
1553 if ( result
== DVDNAV_STATUS_ERR
)
1555 hb_error("dvdnav: Read Error, %s", dvdnav_err_to_string(d
->dvdnav
));
1560 case DVDNAV_BLOCK_OK
:
1561 case DVDNAV_CELL_CHANGE
:
1565 case DVDNAV_STILL_FRAME
:
1566 dvdnav_still_skip( d
->dvdnav
);
1570 dvdnav_wait_skip( d
->dvdnav
);
1574 hb_log("dvdnav: stop encountered during seek");
1578 case DVDNAV_HOP_CHANNEL
:
1579 case DVDNAV_NAV_PACKET
:
1580 case DVDNAV_VTS_CHANGE
:
1581 case DVDNAV_HIGHLIGHT
:
1582 case DVDNAV_AUDIO_STREAM_CHANGE
:
1583 case DVDNAV_SPU_STREAM_CHANGE
:
1584 case DVDNAV_SPU_CLUT_CHANGE
:
1591 if (dvdnav_sector_search(d
->dvdnav
, sector
, SEEK_SET
) != DVDNAV_STATUS_OK
)
1593 hb_error( "dvd: dvdnav_sector_search failed - %s",
1594 dvdnav_err_to_string(d
->dvdnav
) );
1602 /***********************************************************************
1604 ***********************************************************************
1606 **********************************************************************/
1607 static hb_buffer_t
* hb_dvdnav_read( hb_dvd_t
* e
)
1609 hb_dvdnav_t
* d
= &(e
->dvdnav
);
1610 int result
, event
, len
;
1612 int error_count
= 0;
1613 hb_buffer_t
*b
= hb_buffer_init( HB_DVD_READ_BUFFER_SIZE
);
1619 hb_buffer_close( &b
);
1622 result
= dvdnav_get_next_block( d
->dvdnav
, b
->data
, &event
, &len
);
1623 if ( result
== DVDNAV_STATUS_ERR
)
1625 hb_error("dvdnav: Read Error, %s", dvdnav_err_to_string(d
->dvdnav
));
1626 if (dvdnav_sector_search(d
->dvdnav
, 1, SEEK_CUR
) != DVDNAV_STATUS_OK
)
1628 hb_error( "dvd: dvdnav_sector_search failed - %s",
1629 dvdnav_err_to_string(d
->dvdnav
) );
1630 hb_buffer_close( &b
);
1631 hb_set_work_error(d
->h
, HB_ERROR_READ
);
1635 if (error_count
> 500)
1637 hb_error("dvdnav: Error, too many consecutive read errors");
1638 hb_buffer_close( &b
);
1639 hb_set_work_error(d
->h
, HB_ERROR_READ
);
1646 case DVDNAV_BLOCK_OK
:
1647 // We have received a regular block of the currently playing
1650 // The muxers expect to only get chapter 2 and above
1651 // They write chapter 1 when chapter 2 is detected.
1653 b
->s
.new_chap
= chapter
;
1660 * Nothing to do here.
1664 case DVDNAV_STILL_FRAME
:
1666 * We have reached a still frame. A real player application
1667 * would wait the amount of time specified by the still's
1668 * length while still handling user input to make menus and
1669 * other interactive stills work. A length of 0xff means an
1670 * indefinite still which has to be skipped indirectly by some
1673 dvdnav_still_skip( d
->dvdnav
);
1678 * We have reached a point in DVD playback, where timing is
1679 * critical. Player application with internal fifos can
1680 * introduce state inconsistencies, because libdvdnav is
1681 * always the fifo's length ahead in the stream compared to
1682 * what the application sees. Such applications should wait
1683 * until their fifos are empty when they receive this type of
1686 dvdnav_wait_skip( d
->dvdnav
);
1689 case DVDNAV_SPU_CLUT_CHANGE
:
1691 * Player applications should pass the new colour lookup table
1692 * to their SPU decoder
1696 case DVDNAV_SPU_STREAM_CHANGE
:
1698 * Player applications should inform their SPU decoder to
1703 case DVDNAV_AUDIO_STREAM_CHANGE
:
1705 * Player applications should inform their audio decoder to
1710 case DVDNAV_HIGHLIGHT
:
1712 * Player applications should inform their overlay engine to
1713 * highlight the given button
1717 case DVDNAV_VTS_CHANGE
:
1719 * Some status information like video aspect and video scale
1720 * permissions do not change inside a VTS. Therefore this
1721 * event can be used to query such information only when
1722 * necessary and update the decoding/displaying accordingly.
1725 int tt
= 0, pgcn
= 0, pgn
= 0;
1727 dvdnav_current_title_program(d
->dvdnav
, &tt
, &pgcn
, &pgn
);
1730 // Transition to another title signals that we are done.
1731 hb_buffer_close( &b
);
1732 hb_deep_log(2, "dvdnav: vts change, found next title");
1738 case DVDNAV_CELL_CHANGE
:
1740 * Some status information like the current Title and Part
1741 * numbers do not change inside a cell. Therefore this event
1742 * can be used to query such information only when necessary
1743 * and update the decoding/displaying accordingly.
1746 dvdnav_cell_change_event_t
* cell_event
;
1747 int tt
= 0, pgcn
= 0, pgn
= 0, c
;
1749 cell_event
= (dvdnav_cell_change_event_t
*)b
->data
;
1751 dvdnav_current_title_program(d
->dvdnav
, &tt
, &pgcn
, &pgn
);
1754 // Transition to another title signals that we are done.
1755 hb_buffer_close( &b
);
1756 hb_deep_log(2, "dvdnav: cell change, found next title");
1759 c
= FindChapterIndex(d
->list_chapter
, pgcn
, pgn
);
1760 if (c
!= d
->chapter
)
1764 // Some titles end with a 'link' back to the beginning so
1765 // a transition to an earlier chapter means we're done.
1766 hb_buffer_close( &b
);
1767 hb_deep_log(2, "dvdnav: cell change, previous chapter");
1770 chapter
= d
->chapter
= c
;
1772 else if ( cell_event
->cellN
<= d
->cell
)
1774 hb_buffer_close( &b
);
1775 hb_deep_log(2, "dvdnav: cell change, previous cell");
1778 d
->cell
= cell_event
->cellN
;
1782 case DVDNAV_NAV_PACKET
:
1784 * A NAV packet provides PTS discontinuity information, angle
1785 * linking information and button definitions for DVD menus.
1786 * Angles are handled completely inside libdvdnav. For the
1787 * menus to work, the NAV packet information has to be passed
1788 * to the overlay engine of the player so that it knows the
1789 * dimensions of the button areas.
1792 // mpegdemux expects to get these. I don't think it does
1793 // anything useful with them however.
1795 // The muxers expect to only get chapter 2 and above
1796 // They write chapter 1 when chapter 2 is detected.
1798 b
->s
.new_chap
= chapter
;
1804 case DVDNAV_HOP_CHANNEL
:
1806 * This event is issued whenever a non-seamless operation has
1807 * been executed. Applications with fifos should drop the
1808 * fifos content to speed up responsiveness.
1814 * Playback should end here.
1817 hb_buffer_close( &b
);
1818 hb_deep_log(2, "dvdnav: stop");
1825 hb_buffer_close( &b
);
1829 /***********************************************************************
1831 ***********************************************************************
1832 * Returns in which chapter the next block to be read is.
1833 * Chapter numbers start at 1.
1834 **********************************************************************/
1835 static int hb_dvdnav_chapter( hb_dvd_t
* e
)
1837 hb_dvdnav_t
* d
= &(e
->dvdnav
);
1838 int32_t t
, pgcn
, pgn
;
1841 if (dvdnav_current_title_program(d
->dvdnav
, &t
, &pgcn
, &pgn
) != DVDNAV_STATUS_OK
)
1845 c
= FindChapterIndex( d
->list_chapter
, pgcn
, pgn
);
1849 /***********************************************************************
1851 ***********************************************************************
1852 * Closes and frees everything
1853 **********************************************************************/
1854 static void hb_dvdnav_close( hb_dvd_t
** _d
)
1856 hb_dvdnav_t
* d
= &((*_d
)->dvdnav
);
1858 if( d
->dvdnav
) dvdnav_close( d
->dvdnav
);
1859 if( d
->vmg
) ifoClose( d
->vmg
);
1860 if( d
->reader
) DVDClose( d
->reader
);
1868 /***********************************************************************
1869 * hb_dvdnav_angle_count
1870 ***********************************************************************
1871 * Returns the number of angles supported.
1872 **********************************************************************/
1873 static int hb_dvdnav_angle_count( hb_dvd_t
* e
)
1875 hb_dvdnav_t
* d
= &(e
->dvdnav
);
1876 int current
, angle_count
;
1878 if (dvdnav_get_angle_info( d
->dvdnav
, ¤t
, &angle_count
) != DVDNAV_STATUS_OK
)
1880 hb_log("dvdnav_get_angle_info %s", dvdnav_err_to_string(d
->dvdnav
));
1886 /***********************************************************************
1887 * hb_dvdnav_set_angle
1888 ***********************************************************************
1889 * Sets the angle to read
1890 **********************************************************************/
1891 static void hb_dvdnav_set_angle( hb_dvd_t
* e
, int angle
)
1893 hb_dvdnav_t
* d
= &(e
->dvdnav
);
1895 if (dvdnav_angle_change( d
->dvdnav
, angle
) != DVDNAV_STATUS_OK
)
1897 hb_log("dvdnav_angle_change %s", dvdnav_err_to_string(d
->dvdnav
));
1901 /***********************************************************************
1903 ***********************************************************************
1904 * Assumes pgc and cell_cur are correctly set, and sets cell_next to the
1905 * cell to be read when we will be done with cell_cur.
1906 **********************************************************************/
1907 static int FindChapterIndex( hb_list_t
* list
, int pgcn
, int pgn
)
1910 hb_chapter_t
*chapter
;
1912 count
= hb_list_count( list
);
1913 for (ii
= 0; ii
< count
; ii
++)
1915 chapter
= hb_list_item( list
, ii
);
1916 if (chapter
->pgcn
== pgcn
&& chapter
->pgn
== pgn
)
1917 return chapter
->index
;
1922 /***********************************************************************
1924 ***********************************************************************
1925 * Assumes pgc and cell_cur are correctly set, and sets cell_next to the
1926 * cell to be read when we will be done with cell_cur.
1927 **********************************************************************/
1928 static int FindNextCell( pgc_t
*pgc
, int cell_cur
)
1933 if( pgc
->cell_playback
[cell_cur
].block_type
==
1934 BLOCK_TYPE_ANGLE_BLOCK
)
1937 while( pgc
->cell_playback
[cell_cur
+i
].block_mode
!=
1938 BLOCK_MODE_LAST_CELL
)
1942 cell_next
= cell_cur
+ i
+ 1;
1943 hb_log( "dvd: Skipping multi-angle cells %d-%d",
1949 cell_next
= cell_cur
+ 1;
1954 /***********************************************************************
1956 ***********************************************************************
1957 * Assumes pgc and cell_cur are correctly set, and sets cell_next to the
1958 * cell to be read when we will be done with cell_cur.
1959 * Since pg chains can be circularly linked (either from a read error or
1960 * deliberately) pgcn_map tracks program chains we've already seen.
1961 **********************************************************************/
1962 static int NextPgcn( ifo_handle_t
*ifo
, int pgcn
, uint32_t pgcn_map
[MAX_PGCN
/32] )
1967 pgcn_map
[pgcn
>> 5] |= (1 << (pgcn
& 31));
1969 pgc
= ifo
->vts_pgcit
->pgci_srp
[pgcn
-1].pgc
;
1970 next_pgcn
= pgc
->next_pgc_nr
;
1971 if ( next_pgcn
< 1 || next_pgcn
>= MAX_PGCN
|| next_pgcn
> ifo
->vts_pgcit
->nr_of_pgci_srp
)
1974 return pgcn_map
[next_pgcn
>> 5] & (1 << (next_pgcn
& 31))? 0 : next_pgcn
;
1977 /***********************************************************************
1979 ***********************************************************************
1980 * Pgc links can loop. I track which have been visited in a bit vector
1981 * Initialize the bit vector to empty.
1982 **********************************************************************/
1983 static void PgcWalkInit( uint32_t pgcn_map
[MAX_PGCN
/32] )
1985 memset(pgcn_map
, 0, sizeof(uint32_t) * MAX_PGCN
/32);
1988 /***********************************************************************
1990 ***********************************************************************
1992 **********************************************************************/
1993 static int dvdtime2msec(dvd_time_t
* dt
)
1995 double frames_per_s
[4] = {-1.0, 25.00, -1.0, 29.97};
1996 double fps
= frames_per_s
[(dt
->frame_u
& 0xc0) >> 6];
1998 ms
= (((dt
->hour
& 0xf0) >> 3) * 5 + (dt
->hour
& 0x0f)) * 3600000;
1999 ms
+= (((dt
->minute
& 0xf0) >> 3) * 5 + (dt
->minute
& 0x0f)) * 60000;
2000 ms
+= (((dt
->second
& 0xf0) >> 3) * 5 + (dt
->second
& 0x0f)) * 1000;
2004 ms
+= (((dt
->frame_u
& 0x30) >> 3) * 5 +
2005 (dt
->frame_u
& 0x0f)) * 1000.0 / fps
;