1 /* $Id: dvd.c,v 1.12 2005/11/25 15:05:25 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.m0k.org/>.
5 It may be used under the terms of the GNU General Public License. */
10 #include "dvdread/ifo_read.h"
11 #include "dvdread/nav_read.h"
17 dvd_reader_t
* reader
;
30 int title_block_count
;
39 /***********************************************************************
41 **********************************************************************/
42 static void FindNextCell( hb_dvd_t
* );
43 static int dvdtime2msec( dvd_time_t
* );
45 char * hb_dvd_name( char * path
)
47 static char name
[1024];
48 unsigned char unused
[1024];
49 dvd_reader_t
* reader
;
51 reader
= DVDOpen( path
);
57 if( DVDUDFVolumeInfo( reader
, name
, sizeof( name
),
58 unused
, sizeof( unused
) ) )
68 /***********************************************************************
70 ***********************************************************************
72 **********************************************************************/
73 hb_dvd_t
* hb_dvd_init( char * path
)
77 d
= calloc( sizeof( hb_dvd_t
), 1 );
80 if( !( d
->reader
= DVDOpen( path
) ) )
82 hb_log( "dvd: DVDOpen failed (%s)", path
);
87 if( !( d
->vmg
= ifoOpen( d
->reader
, 0 ) ) )
89 hb_log( "dvd: ifoOpen failed" );
93 d
->path
= strdup( path
);
98 if( d
->vmg
) ifoClose( d
->vmg
);
99 if( d
->reader
) DVDClose( d
->reader
);
104 /***********************************************************************
106 **********************************************************************/
107 int hb_dvd_title_count( hb_dvd_t
* d
)
109 return d
->vmg
->tt_srpt
->nr_of_srpts
;
112 /***********************************************************************
114 **********************************************************************/
115 hb_title_t
* hb_dvd_title_scan( hb_dvd_t
* d
, int t
)
119 ifo_handle_t
* vts
= NULL
;
121 hb_chapter_t
* chapter
, * chapter_old
;
124 float duration_correction
;
125 unsigned char unused
[1024];
127 hb_log( "scan: scanning title %d", t
);
129 title
= hb_title_init( d
->path
, t
);
130 if( DVDUDFVolumeInfo( d
->reader
, title
->name
, sizeof( title
->name
),
131 unused
, sizeof( unused
) ) )
133 char * p_cur
, * p_last
= d
->path
;
134 for( p_cur
= d
->path
; *p_cur
; p_cur
++ )
136 if( p_cur
[0] == '/' && p_cur
[1] )
141 snprintf( title
->name
, sizeof( title
->name
), "%s", p_last
);
144 /* VTS which our title is in */
145 title
->vts
= d
->vmg
->tt_srpt
->title
[t
-1].title_set_nr
;
147 hb_log( "scan: opening IFO for VTS %d", title
->vts
);
148 if( !( vts
= ifoOpen( d
->reader
, title
->vts
) ) )
150 hb_log( "scan: ifoOpen failed" );
154 /* Position of the title in the VTS */
155 title
->ttn
= d
->vmg
->tt_srpt
->title
[t
-1].vts_ttn
;
158 pgc_id
= vts
->vts_ptt_srpt
->title
[title
->ttn
-1].ptt
[0].pgcn
;
159 pgn
= vts
->vts_ptt_srpt
->title
[title
->ttn
-1].ptt
[0].pgn
;
160 d
->pgc
= vts
->vts_pgcit
->pgci_srp
[pgc_id
-1].pgc
;
163 title
->cell_start
= d
->pgc
->program_map
[pgn
-1] - 1;
164 title
->block_start
= d
->pgc
->cell_playback
[title
->cell_start
].first_sector
;
167 title
->cell_end
= d
->pgc
->nr_of_cells
- 1;
168 title
->block_end
= d
->pgc
->cell_playback
[title
->cell_end
].last_sector
;
171 title
->block_count
= 0;
172 d
->cell_cur
= title
->cell_start
;
173 while( d
->cell_cur
<= title
->cell_end
)
175 #define cp d->pgc->cell_playback[d->cell_cur]
176 title
->block_count
+= cp
.last_sector
+ 1 - cp
.first_sector
;
179 d
->cell_cur
= d
->cell_next
;
182 hb_log( "scan: vts=%d, ttn=%d, cells=%d->%d, blocks=%d->%d, "
183 "%d blocks", title
->vts
, title
->ttn
, title
->cell_start
,
184 title
->cell_end
, title
->block_start
, title
->block_end
,
185 title
->block_count
);
187 if( title
->block_count
< 2048 )
189 hb_log( "scan: title too short (%d blocks), ignoring",
190 title
->block_count
);
196 title
->duration
= 90LL * dvdtime2msec( &d
->pgc
->playback_time
);
197 title
->hours
= title
->duration
/ 90000 / 3600;
198 title
->minutes
= ( ( title
->duration
/ 90000 ) % 3600 ) / 60;
199 title
->seconds
= ( title
->duration
/ 90000 ) % 60;
200 hb_log( "scan: duration is %02d:%02d:%02d (%lld ms)",
201 title
->hours
, title
->minutes
, title
->seconds
,
202 title
->duration
/ 90 );
204 /* Discard titles under 10 seconds */
205 if( !( title
->hours
| title
->minutes
) && title
->seconds
< 10 )
207 hb_log( "scan: ignoring title (too short)" );
211 /* Detect languages */
212 for( i
= 0; i
< vts
->vtsi_mat
->nr_of_vts_audio_streams
; i
++ )
214 hb_audio_t
* audio
, * audio_tmp
;
215 int audio_format
, lang_code
, audio_control
,
217 iso639_lang_t
* lang
;
219 hb_log( "scan: checking audio %d", i
+ 1 );
221 audio
= calloc( sizeof( hb_audio_t
), 1 );
223 audio_format
= vts
->vtsi_mat
->vts_audio_attr
[i
].audio_format
;
224 lang_code
= vts
->vtsi_mat
->vts_audio_attr
[i
].lang_code
;
226 vts
->vts_pgcit
->pgci_srp
[pgc_id
-1].pgc
->audio_control
[i
];
228 if( !( audio_control
& 0x8000 ) )
230 hb_log( "scan: audio channel is not active" );
235 position
= ( audio_control
& 0x7F00 ) >> 8;
237 switch( audio_format
)
240 audio
->id
= ( ( 0x80 + position
) << 8 ) | 0xbd;
241 audio
->codec
= HB_ACODEC_AC3
;
246 audio
->id
= 0xc0 + position
;
247 audio
->codec
= HB_ACODEC_MPGA
;
251 audio
->id
= ( ( 0xa0 + position
) << 8 ) | 0xbd;
252 audio
->codec
= HB_ACODEC_LPCM
;
256 audio
->id
= ( ( 0x88 + position
) << 8 ) | 0xbd;
257 audio
->codec
= HB_ACODEC_DCA
;
263 hb_log( "scan: unknown audio codec (%x)",
272 /* Check for duplicate tracks */
274 for( j
= 0; j
< hb_list_count( title
->list_audio
); j
++ )
276 audio_tmp
= hb_list_item( title
->list_audio
, j
);
277 if( audio
->id
== audio_tmp
->id
)
285 hb_log( "scan: duplicate audio track" );
290 lang
= lang_for_code( vts
->vtsi_mat
->vts_audio_attr
[i
].lang_code
);
292 snprintf( audio
->lang
, sizeof( audio
->lang
), "%s (%s)",
293 strlen(lang
->native_name
) ? lang
->native_name
: lang
->eng_name
,
294 audio
->codec
== HB_ACODEC_AC3
? "AC3" : ( audio
->codec
==
295 HB_ACODEC_DCA
? "DTS" : ( audio
->codec
==
296 HB_ACODEC_MPGA
? "MPEG" : "LPCM" ) ) );
297 snprintf( audio
->lang_simple
, sizeof( audio
->lang_simple
), "%s",
298 strlen(lang
->native_name
) ? lang
->native_name
: lang
->eng_name
);
299 snprintf( audio
->iso639_2
, sizeof( audio
->iso639_2
), "%s",
302 hb_log( "scan: id=%x, lang=%s, 3cc=%s", audio
->id
,
303 audio
->lang
, audio
->iso639_2
);
305 hb_list_add( title
->list_audio
, audio
);
308 if( !hb_list_count( title
->list_audio
) )
310 hb_log( "scan: ignoring title (no audio track)" );
314 memcpy( title
->palette
,
315 vts
->vts_pgcit
->pgci_srp
[pgc_id
-1].pgc
->palette
,
316 16 * sizeof( uint32_t ) );
318 /* Check for subtitles */
319 for( i
= 0; i
< vts
->vtsi_mat
->nr_of_vts_subp_streams
; i
++ )
321 hb_subtitle_t
* subtitle
;
324 iso639_lang_t
* lang
;
326 hb_log( "scan: checking subtitle %d", i
+ 1 );
329 vts
->vts_pgcit
->pgci_srp
[pgc_id
-1].pgc
->subp_control
[i
];
331 if( !( spu_control
& 0x80000000 ) )
333 hb_log( "scan: subtitle channel is not active" );
337 if( vts
->vtsi_mat
->vts_video_attr
.display_aspect_ratio
)
339 switch( vts
->vtsi_mat
->vts_video_attr
.permitted_df
)
342 position
= spu_control
& 0xFF;
345 position
= ( spu_control
>> 8 ) & 0xFF;
348 position
= ( spu_control
>> 16 ) & 0xFF;
353 position
= ( spu_control
>> 24 ) & 0x7F;
356 lang
= lang_for_code( vts
->vtsi_mat
->vts_subp_attr
[i
].lang_code
);
358 subtitle
= calloc( sizeof( hb_subtitle_t
), 1 );
359 subtitle
->id
= ( ( 0x20 + position
) << 8 ) | 0xbd;
360 snprintf( subtitle
->lang
, sizeof( subtitle
->lang
), "%s",
361 strlen(lang
->native_name
) ? lang
->native_name
: lang
->eng_name
);
362 snprintf( subtitle
->iso639_2
, sizeof( subtitle
->iso639_2
), "%s",
365 hb_log( "scan: id=%x, lang=%s, 3cc=%s", subtitle
->id
,
366 subtitle
->lang
, subtitle
->iso639_2
);
368 hb_list_add( title
->list_subtitle
, subtitle
);
372 hb_log( "scan: title %d has %d chapters", t
,
373 vts
->vts_ptt_srpt
->title
[title
->ttn
-1].nr_of_ptts
);
375 i
< vts
->vts_ptt_srpt
->title
[title
->ttn
-1].nr_of_ptts
; i
++ )
377 int pgc_id_next
, pgn_next
;
380 chapter
= calloc( sizeof( hb_chapter_t
), 1 );
383 pgc_id
= vts
->vts_ptt_srpt
->title
[title
->ttn
-1].ptt
[i
].pgcn
;
384 pgn
= vts
->vts_ptt_srpt
->title
[title
->ttn
-1].ptt
[i
].pgn
;
385 d
->pgc
= vts
->vts_pgcit
->pgci_srp
[pgc_id
-1].pgc
;
388 chapter
->cell_start
= d
->pgc
->program_map
[pgn
-1] - 1;
389 chapter
->block_start
=
390 d
->pgc
->cell_playback
[chapter
->cell_start
].first_sector
;
393 if( i
!= vts
->vts_ptt_srpt
->title
[title
->ttn
-1].nr_of_ptts
- 1 )
395 /* The cell before the starting cell of the next chapter,
397 pgc_id_next
= vts
->vts_ptt_srpt
->title
[title
->ttn
-1].ptt
[i
+1].pgcn
;
398 pgn_next
= vts
->vts_ptt_srpt
->title
[title
->ttn
-1].ptt
[i
+1].pgn
;
399 pgc_next
= vts
->vts_pgcit
->pgci_srp
[pgc_id_next
-1].pgc
;
400 chapter
->cell_end
= pgc_next
->program_map
[pgn_next
-1] - 2;
401 if( chapter
->cell_end
< 0 )
410 /* ... the last cell of the title */
411 chapter
->cell_end
= title
->cell_end
;
414 d
->pgc
->cell_playback
[chapter
->cell_end
].last_sector
;
416 /* Block count, duration */
417 pgc_id
= vts
->vts_ptt_srpt
->title
[title
->ttn
-1].ptt
[0].pgcn
;
418 pgn
= vts
->vts_ptt_srpt
->title
[title
->ttn
-1].ptt
[0].pgn
;
419 d
->pgc
= vts
->vts_pgcit
->pgci_srp
[pgc_id
-1].pgc
;
420 chapter
->block_count
= 0;
421 chapter
->duration
= 0;
423 d
->cell_cur
= chapter
->cell_start
;
424 while( d
->cell_cur
<= chapter
->cell_end
)
426 #define cp d->pgc->cell_playback[d->cell_cur]
427 chapter
->block_count
+= cp
.last_sector
+ 1 - cp
.first_sector
;
428 chapter
->duration
+= 90LL * dvdtime2msec( &cp
.playback_time
);
431 d
->cell_cur
= d
->cell_next
;
434 if( chapter
->block_count
< 2048 && chapter
->index
> 1 )
436 hb_log( "scan: chapter %d too short (%d blocks, "
437 "cells=%d->%d), merging", chapter
->index
,
438 chapter
->block_count
, chapter
->cell_start
,
440 chapter_old
= hb_list_item( title
->list_chapter
,
441 chapter
->index
- 2 );
442 chapter_old
->cell_end
= chapter
->cell_end
;
443 chapter_old
->block_end
= chapter
->block_end
;
444 chapter_old
->block_count
+= chapter
->block_count
;
446 chapter
= chapter_old
;
450 hb_list_add( title
->list_chapter
, chapter
);
455 /* The durations we get for chapters aren't precise. Scale them so
456 the total matches the title duration */
458 for( i
= 0; i
< hb_list_count( title
->list_chapter
); i
++ )
460 chapter
= hb_list_item( title
->list_chapter
, i
);
461 duration
+= chapter
->duration
;
463 duration_correction
= (float) title
->duration
/ (float) duration
;
464 for( i
= 0; i
< hb_list_count( title
->list_chapter
); i
++ )
467 chapter
= hb_list_item( title
->list_chapter
, i
);
468 chapter
->duration
= duration_correction
* chapter
->duration
;
469 seconds
= ( chapter
->duration
+ 45000 ) / 90000;
470 chapter
->hours
= seconds
/ 3600;
471 chapter
->minutes
= ( seconds
% 3600 ) / 60;
472 chapter
->seconds
= seconds
% 60;
474 hb_log( "scan: chap %d c=%d->%d, b=%d->%d (%d), %lld ms",
475 chapter
->index
, chapter
->cell_start
, chapter
->cell_end
,
476 chapter
->block_start
, chapter
->block_end
,
477 chapter
->block_count
, chapter
->duration
/ 90 );
480 /* Get aspect. We don't get width/height/rate infos here as
481 they tend to be wrong */
482 switch( vts
->vtsi_mat
->vts_video_attr
.display_aspect_ratio
)
485 title
->aspect
= HB_ASPECT_BASE
* 4 / 3;
488 title
->aspect
= HB_ASPECT_BASE
* 16 / 9;
491 hb_log( "scan: unknown aspect" );
495 hb_log( "scan: aspect = %d", title
->aspect
);
497 /* This title is ok so far */
501 hb_list_close( &title
->list_audio
);
506 if( vts
) ifoClose( vts
);
511 /***********************************************************************
513 ***********************************************************************
514 * Title and chapter start at 1
515 **********************************************************************/
516 int hb_dvd_start( hb_dvd_t
* d
, int title
, int chapter
)
521 /* Open the IFO and the VOBs for this title */
522 d
->vts
= d
->vmg
->tt_srpt
->title
[title
-1].title_set_nr
;
523 d
->ttn
= d
->vmg
->tt_srpt
->title
[title
-1].vts_ttn
;
524 if( !( d
->ifo
= ifoOpen( d
->reader
, d
->vts
) ) )
526 hb_log( "dvd: ifoOpen failed for VTS %d", d
->vts
);
529 if( !( d
->file
= DVDOpenFile( d
->reader
, d
->vts
,
530 DVD_READ_TITLE_VOBS
) ) )
532 hb_log( "dvd: DVDOpenFile failed for VTS %d", d
->vts
);
536 /* Get title first and last blocks */
537 pgc_id
= d
->ifo
->vts_ptt_srpt
->title
[d
->ttn
-1].ptt
[0].pgcn
;
538 pgn
= d
->ifo
->vts_ptt_srpt
->title
[d
->ttn
-1].ptt
[0].pgn
;
539 d
->pgc
= d
->ifo
->vts_pgcit
->pgci_srp
[pgc_id
-1].pgc
;
540 d
->cell_start
= d
->pgc
->program_map
[pgn
- 1] - 1;
541 d
->cell_end
= d
->pgc
->nr_of_cells
- 1;
542 d
->title_start
= d
->pgc
->cell_playback
[d
->cell_start
].first_sector
;
543 d
->title_end
= d
->pgc
->cell_playback
[d
->cell_end
].last_sector
;
546 d
->title_block_count
= 0;
547 for( i
= d
->cell_start
; i
<= d
->cell_end
; i
++ )
549 d
->title_block_count
+= d
->pgc
->cell_playback
[i
].last_sector
+ 1 -
550 d
->pgc
->cell_playback
[i
].first_sector
;
553 /* Get pgc for the current chapter */
554 pgc_id
= d
->ifo
->vts_ptt_srpt
->title
[d
->ttn
-1].ptt
[chapter
-1].pgcn
;
555 pgn
= d
->ifo
->vts_ptt_srpt
->title
[d
->ttn
-1].ptt
[chapter
-1].pgn
;
556 d
->pgc
= d
->ifo
->vts_pgcit
->pgci_srp
[pgc_id
-1].pgc
;
558 /* Get the two first cells */
559 d
->cell_cur
= d
->pgc
->program_map
[pgn
-1] - 1;
562 d
->block
= d
->pgc
->cell_playback
[d
->cell_cur
].first_sector
;
563 d
->next_vobu
= d
->block
;
570 /***********************************************************************
572 ***********************************************************************
574 **********************************************************************/
575 void hb_dvd_stop( hb_dvd_t
* d
)
584 DVDCloseFile( d
->file
);
589 /***********************************************************************
591 ***********************************************************************
593 **********************************************************************/
594 int hb_dvd_seek( hb_dvd_t
* d
, float f
)
599 count
= f
* d
->title_block_count
;
601 for( i
= d
->cell_start
; i
<= d
->cell_end
; i
++ )
603 sizeCell
= d
->pgc
->cell_playback
[i
].last_sector
+ 1 -
604 d
->pgc
->cell_playback
[i
].first_sector
;
606 if( count
< sizeCell
)
611 /* Now let hb_dvd_read find the next VOBU */
612 d
->next_vobu
= d
->pgc
->cell_playback
[i
].first_sector
+ count
;
620 if( i
> d
->cell_end
)
629 /***********************************************************************
631 ***********************************************************************
632 * Pretty much directly lifted from libdvdread's play_title function.
633 **********************************************************************/
634 int is_nav_pack( unsigned char *buf
)
636 return ( buf
[41] == 0xbf && buf
[1027] == 0xbf );
640 /***********************************************************************
642 ***********************************************************************
644 **********************************************************************/
645 int hb_dvd_read( hb_dvd_t
* d
, hb_buffer_t
* b
)
657 int block
, pack_len
, next_vobu
;
659 if( DVDReadBlocks( d
->file
, d
->next_vobu
, 1, b
->data
) != 1 )
661 hb_log( "dvd: Unrecoverable Read Error from DVD, probable HD or DVD Failure (blk: %d)", d
->next_vobu
);
665 if ( !is_nav_pack( b
->data
) ) {
670 navRead_DSI( &dsi_pack
, &b
->data
[DSI_START_BYTE
] );
672 block
= dsi_pack
.dsi_gi
.nv_pck_lbn
;
673 pack_len
= dsi_pack
.dsi_gi
.vobu_ea
;
674 next_vobu
= block
+ ( dsi_pack
.vobu_sri
.next_vobu
& 0x7fffffff );
678 block
>= d
->next_vobu
&&
679 ( block
<= d
->title_start
+ d
->title_block_count
||
680 block
<= d
->title_end
) )
683 This looks like a valid VOBU, but actually we are
688 hb_log( "dvd: found VOBU at %d (b %d, l %d, n %d)",
689 d
->next_vobu
, block
, pack_len
, next_vobu
);
693 d
->pack_len
= pack_len
;
694 d
->next_vobu
= next_vobu
;
698 /* Wasn't a valid VOBU, try next block */
702 hb_log( "dvd: looking for a VOBU (%d)", d
->next_vobu
);
708 hb_log( "dvd: couldn't find a VOBU after 1024 blocks" );
715 if( dsi_pack
.vobu_sri
.next_vobu
== SRI_END_OF_CELL
)
717 d
->cell_cur
= d
->cell_next
;
718 d
->next_vobu
= d
->pgc
->cell_playback
[d
->cell_cur
].first_sector
;
721 printf("DVD: End of Cell\n");
724 // Revert the cell overlap, and check for a chapter break
725 if( dsi_pack
.vobu_sri
.prev_vobu
== SRI_END_OF_CELL
)
727 printf("DVD: Beginning of Cell\n");
728 if( d
->cell_overlap
)
730 b
->new_chap
= hb_dvd_is_break( d
);
737 if( DVDReadBlocks( d
->file
, d
->block
, 1, b
->data
) != 1 )
739 hb_log( "reader: DVDReadBlocks failed (%d)", d
->block
);
750 /***********************************************************************
752 ***********************************************************************
753 * Returns in which chapter the next block to be read is.
754 * Chapter numbers start at 1.
755 **********************************************************************/
756 int hb_dvd_chapter( hb_dvd_t
* d
)
760 int nr_of_ptts
= d
->ifo
->vts_ptt_srpt
->title
[d
->ttn
-1].nr_of_ptts
;
763 for( i
= nr_of_ptts
- 1;
767 /* Get pgc for chapter (i+1) */
768 pgc_id
= d
->ifo
->vts_ptt_srpt
->title
[d
->ttn
-1].ptt
[i
].pgcn
;
769 pgn
= d
->ifo
->vts_ptt_srpt
->title
[d
->ttn
-1].ptt
[i
].pgn
;
770 pgc
= d
->ifo
->vts_pgcit
->pgci_srp
[pgc_id
-1].pgc
;
772 if( d
->cell_cur
- d
->cell_overlap
>= pgc
->program_map
[pgn
-1] - 1 &&
773 d
->cell_cur
- d
->cell_overlap
<= pgc
->nr_of_cells
- 1 )
775 /* We are in this chapter */
784 /***********************************************************************
786 ***********************************************************************
787 * Returns 1 if the current block is a new chapter start
788 **********************************************************************/
789 int hb_dvd_is_break( hb_dvd_t
* d
)
793 int nr_of_ptts
= d
->ifo
->vts_ptt_srpt
->title
[d
->ttn
-1].nr_of_ptts
;
795 int cell
, chapter_length
, cell_end
;
797 for( i
= nr_of_ptts
- 1;
801 /* Get pgc for chapter (i+1) */
802 pgc_id
= d
->ifo
->vts_ptt_srpt
->title
[d
->ttn
-1].ptt
[i
].pgcn
;
803 pgn
= d
->ifo
->vts_ptt_srpt
->title
[d
->ttn
-1].ptt
[i
].pgn
;
804 pgc
= d
->ifo
->vts_pgcit
->pgci_srp
[pgc_id
-1].pgc
;
805 cell
= pgc
->program_map
[pgn
-1] - 1;
807 if( cell
<= d
->cell_start
)
810 // This must not match against the start cell.
811 if( pgc
->cell_playback
[cell
].first_sector
== d
->block
&& cell
!= d
->cell_start
)
813 /* Check to see if we merged this chapter into the previous one... */
814 /* As a note, merging chapters is probably bad practice for this very reason */
817 if( i
== nr_of_ptts
- 1 )
819 cell_end
= d
->pgc
->nr_of_cells
;
823 cell_end
= pgc
->program_map
[pgn
] - 1;
826 for( j
= cell
; j
< cell_end
; j
++ )
828 chapter_length
+= pgc
->cell_playback
[j
].last_sector
+ 1 -
829 pgc
->cell_playback
[j
].first_sector
;
832 if( chapter_length
>= 2048 )
834 printf("DVD: Chapter Break Cell Found\n");
835 /* We have a chapter break */
840 printf("DVD: Cell Found (%d)\n", chapter_length
);
848 /***********************************************************************
850 ***********************************************************************
851 * Closes and frees everything
852 **********************************************************************/
853 void hb_dvd_close( hb_dvd_t
** _d
)
863 DVDClose( d
->reader
);
870 /***********************************************************************
872 ***********************************************************************
873 * Assumes pgc and cell_cur are correctly set, and sets cell_next to the
874 * cell to be read when we will be done with cell_cur.
875 **********************************************************************/
876 static void FindNextCell( hb_dvd_t
* d
)
880 if( d
->pgc
->cell_playback
[d
->cell_cur
].block_type
==
881 BLOCK_TYPE_ANGLE_BLOCK
)
884 while( d
->pgc
->cell_playback
[d
->cell_cur
+i
].block_mode
!=
885 BLOCK_MODE_LAST_CELL
)
889 d
->cell_next
= d
->cell_cur
+ i
+ 1;
893 d
->cell_next
= d
->cell_cur
+ 1;
897 /***********************************************************************
899 ***********************************************************************
901 **********************************************************************/
902 static int dvdtime2msec(dvd_time_t
* dt
)
904 double frames_per_s
[4] = {-1.0, 25.00, -1.0, 29.97};
905 double fps
= frames_per_s
[(dt
->frame_u
& 0xc0) >> 6];
907 ms
= (((dt
->hour
& 0xf0) >> 3) * 5 + (dt
->hour
& 0x0f)) * 3600000;
908 ms
+= (((dt
->minute
& 0xf0) >> 3) * 5 + (dt
->minute
& 0x0f)) * 60000;
909 ms
+= (((dt
->second
& 0xf0) >> 3) * 5 + (dt
->second
& 0x0f)) * 1000;
913 ms
+= ((dt
->frame_u
& 0x30) >> 3) * 5 +
914 (dt
->frame_u
& 0x0f) * 1000.0 / fps
;