summaryrefslogtreecommitdiffstats
path: root/libhb/dvd.c
diff options
context:
space:
mode:
Diffstat (limited to 'libhb/dvd.c')
-rw-r--r--libhb/dvd.c805
1 files changed, 0 insertions, 805 deletions
diff --git a/libhb/dvd.c b/libhb/dvd.c
deleted file mode 100644
index 4082a18d3..000000000
--- a/libhb/dvd.c
+++ /dev/null
@@ -1,805 +0,0 @@
-/* $Id: dvd.c,v 1.12 2005/11/25 15:05:25 titer Exp $
-
- This file is part of the HandBrake source code.
- Homepage: <http://handbrake.m0k.org/>.
- It may be used under the terms of the GNU General Public License. */
-
-#include "hb.h"
-#include "lang.h"
-
-#include "dvdread/ifo_read.h"
-#include "dvdread/nav_read.h"
-
-struct hb_dvd_s
-{
- char * path;
-
- dvd_reader_t * reader;
- ifo_handle_t * vmg;
-
- int vts;
- int ttn;
- ifo_handle_t * ifo;
- dvd_file_t * file;
-
- pgc_t * pgc;
- int cell_start;
- int cell_end;
- int title_start;
- int title_end;
- int title_block_count;
- int cell_cur;
- int cell_next;
- int block;
- int pack_len;
- int next_vobu;
-};
-
-/***********************************************************************
- * Local prototypes
- **********************************************************************/
-static void FindNextCell( hb_dvd_t * );
-static int dvdtime2msec( dvd_time_t * );
-
-char * hb_dvd_name( char * path )
-{
- static char name[1024];
- unsigned char unused[1024];
- dvd_reader_t * reader;
-
- reader = DVDOpen( path );
- if( !reader )
- {
- return NULL;
- }
-
- if( DVDUDFVolumeInfo( reader, name, sizeof( name ),
- unused, sizeof( unused ) ) )
- {
- DVDClose( reader );
- return NULL;
- }
-
- DVDClose( reader );
- return name;
-}
-
-/***********************************************************************
- * hb_dvd_init
- ***********************************************************************
- *
- **********************************************************************/
-hb_dvd_t * hb_dvd_init( char * path )
-{
- hb_dvd_t * d;
-
- d = calloc( sizeof( hb_dvd_t ), 1 );
-
- /* Open device */
- if( !( d->reader = DVDOpen( path ) ) )
- {
- hb_log( "dvd: DVDOpen failed (%s)", path );
- goto fail;
- }
-
- /* Open main IFO */
- if( !( d->vmg = ifoOpen( d->reader, 0 ) ) )
- {
- hb_log( "dvd: ifoOpen failed" );
- goto fail;
- }
-
- d->path = strdup( path );
-
- return d;
-
-fail:
- if( d->vmg ) ifoClose( d->vmg );
- if( d->reader ) DVDClose( d->reader );
- free( d );
- return NULL;
-}
-
-/***********************************************************************
- * hb_dvd_title_count
- **********************************************************************/
-int hb_dvd_title_count( hb_dvd_t * d )
-{
- return d->vmg->tt_srpt->nr_of_srpts;
-}
-
-/***********************************************************************
- * hb_dvd_title_scan
- **********************************************************************/
-hb_title_t * hb_dvd_title_scan( hb_dvd_t * d, int t )
-{
-
- hb_title_t * title;
- ifo_handle_t * vts = NULL;
- int pgc_id, pgn, i;
- hb_chapter_t * chapter, * chapter_old;
- int c;
- uint64_t duration;
- float duration_correction;
- unsigned char unused[1024];
-
- hb_log( "scan: scanning title %d", t );
-
- title = hb_title_init( d->path, t );
- if( DVDUDFVolumeInfo( d->reader, title->name, sizeof( title->name ),
- unused, sizeof( unused ) ) )
- {
- char * p_cur, * p_last = d->path;
- for( p_cur = d->path; *p_cur; p_cur++ )
- {
- if( p_cur[0] == '/' && p_cur[1] )
- {
- p_last = &p_cur[1];
- }
- }
- snprintf( title->name, sizeof( title->name ), "%s", p_last );
- }
-
- /* VTS which our title is in */
- title->vts = d->vmg->tt_srpt->title[t-1].title_set_nr;
-
- hb_log( "scan: opening IFO for VTS %d", title->vts );
- if( !( vts = ifoOpen( d->reader, title->vts ) ) )
- {
- hb_log( "scan: ifoOpen failed" );
- goto fail;
- }
-
- /* Position of the title in the VTS */
- title->ttn = d->vmg->tt_srpt->title[t-1].vts_ttn;
-
- /* Get pgc */
- pgc_id = vts->vts_ptt_srpt->title[title->ttn-1].ptt[0].pgcn;
- pgn = vts->vts_ptt_srpt->title[title->ttn-1].ptt[0].pgn;
- d->pgc = vts->vts_pgcit->pgci_srp[pgc_id-1].pgc;
-
- /* Start cell */
- title->cell_start = d->pgc->program_map[pgn-1] - 1;
- title->block_start = d->pgc->cell_playback[title->cell_start].first_sector;
-
- /* End cell */
- title->cell_end = d->pgc->nr_of_cells - 1;
- title->block_end = d->pgc->cell_playback[title->cell_end].last_sector;
-
- /* Block count */
- title->block_count = 0;
- d->cell_cur = title->cell_start;
- while( d->cell_cur <= title->cell_end )
- {
-#define cp d->pgc->cell_playback[d->cell_cur]
- title->block_count += cp.last_sector + 1 - cp.first_sector;
-#undef cp
- FindNextCell( d );
- d->cell_cur = d->cell_next;
- }
-
- hb_log( "scan: vts=%d, ttn=%d, cells=%d->%d, blocks=%d->%d, "
- "%d blocks", title->vts, title->ttn, title->cell_start,
- title->cell_end, title->block_start, title->block_end,
- title->block_count );
-
- if( title->block_count < 2048 )
- {
- hb_log( "scan: title too short (%d blocks), ignoring",
- title->block_count );
- goto fail;
- }
-
-
- /* Get duration */
- title->duration = 90LL * dvdtime2msec( &d->pgc->playback_time );
- title->hours = title->duration / 90000 / 3600;
- title->minutes = ( ( title->duration / 90000 ) % 3600 ) / 60;
- title->seconds = ( title->duration / 90000 ) % 60;
- hb_log( "scan: duration is %02d:%02d:%02d (%lld ms)",
- title->hours, title->minutes, title->seconds,
- title->duration / 90 );
-
- /* Discard titles under 10 seconds */
- if( !( title->hours | title->minutes ) && title->seconds < 10 )
- {
- hb_log( "scan: ignoring title (too short)" );
- goto fail;
- }
-
- /* Detect languages */
- for( i = 0; i < vts->vtsi_mat->nr_of_vts_audio_streams; i++ )
- {
- hb_audio_t * audio, * audio_tmp;
- int audio_format, lang_code, audio_control,
- position, j;
-
- hb_log( "scan: checking audio %d", i + 1 );
-
- audio = calloc( sizeof( hb_audio_t ), 1 );
-
- audio_format = vts->vtsi_mat->vts_audio_attr[i].audio_format;
- lang_code = vts->vtsi_mat->vts_audio_attr[i].lang_code;
- audio_control =
- vts->vts_pgcit->pgci_srp[pgc_id-1].pgc->audio_control[i];
-
- if( !( audio_control & 0x8000 ) )
- {
- hb_log( "scan: audio channel is not active" );
- free( audio );
- continue;
- }
-
- position = ( audio_control & 0x7F00 ) >> 8;
-
- switch( audio_format )
- {
- case 0x00:
- audio->id = ( ( 0x80 + position ) << 8 ) | 0xbd;
- audio->codec = HB_ACODEC_AC3;
- break;
-
- case 0x02:
- case 0x03:
- audio->id = 0xc0 + position;
- audio->codec = HB_ACODEC_MPGA;
- break;
-
- case 0x04:
- audio->id = ( ( 0xa0 + position ) << 8 ) | 0xbd;
- audio->codec = HB_ACODEC_LPCM;
- break;
-
- default:
- audio->id = 0;
- audio->codec = 0;
- hb_log( "scan: unknown audio codec (%x)",
- audio_format );
- break;
- }
- if( !audio->id )
- {
- continue;
- }
-
- /* Check for duplicate tracks */
- audio_tmp = NULL;
- for( j = 0; j < hb_list_count( title->list_audio ); j++ )
- {
- audio_tmp = hb_list_item( title->list_audio, j );
- if( audio->id == audio_tmp->id )
- {
- break;
- }
- audio_tmp = NULL;
- }
- if( audio_tmp )
- {
- hb_log( "scan: duplicate audio track" );
- free( audio );
- continue;
- }
-
- snprintf( audio->lang, sizeof( audio->lang ), "%s (%s)",
- lang_for_code( vts->vtsi_mat->vts_audio_attr[i].lang_code ),
- audio->codec == HB_ACODEC_AC3 ? "AC3" : ( audio->codec ==
- HB_ACODEC_MPGA ? "MPEG" : "LPCM" ) );
- snprintf( audio->lang_simple, sizeof( audio->lang_simple ), "%s",
- lang_for_code( vts->vtsi_mat->vts_audio_attr[i].lang_code ) );
-
- hb_log( "scan: id=%x, lang=%s", audio->id,
- audio->lang );
-
- hb_list_add( title->list_audio, audio );
- }
-
- if( !hb_list_count( title->list_audio ) )
- {
- hb_log( "scan: ignoring title (no audio track)" );
- goto fail;
- }
-
- memcpy( title->palette,
- vts->vts_pgcit->pgci_srp[pgc_id-1].pgc->palette,
- 16 * sizeof( uint32_t ) );
-
- /* Check for subtitles */
- for( i = 0; i < vts->vtsi_mat->nr_of_vts_subp_streams; i++ )
- {
- hb_subtitle_t * subtitle;
- int spu_control;
- int position;
-
- hb_log( "scan: checking subtitle %d", i + 1 );
-
- spu_control =
- vts->vts_pgcit->pgci_srp[pgc_id-1].pgc->subp_control[i];
-
- if( !( spu_control & 0x80000000 ) )
- {
- hb_log( "scan: subtitle channel is not active" );
- continue;
- }
-
- if( vts->vtsi_mat->vts_video_attr.display_aspect_ratio )
- {
- switch( vts->vtsi_mat->vts_video_attr.permitted_df )
- {
- case 1:
- position = spu_control & 0xFF;
- break;
- case 2:
- position = ( spu_control >> 8 ) & 0xFF;
- break;
- default:
- position = ( spu_control >> 16 ) & 0xFF;
- }
- }
- else
- {
- position = ( spu_control >> 24 ) & 0x7F;
- }
-
- subtitle = calloc( sizeof( hb_subtitle_t ), 1 );
- subtitle->id = ( ( 0x20 + position ) << 8 ) | 0xbd;
- snprintf( subtitle->lang, sizeof( subtitle->lang ), "%s",
- lang_for_code( vts->vtsi_mat->vts_subp_attr[i].lang_code ) );
-
- hb_log( "scan: id=%x, lang=%s", subtitle->id,
- subtitle->lang );
-
- hb_list_add( title->list_subtitle, subtitle );
- }
-
- /* Chapters */
- hb_log( "scan: title %d has %d chapters", t,
- vts->vts_ptt_srpt->title[title->ttn-1].nr_of_ptts );
- for( i = 0, c = 1;
- i < vts->vts_ptt_srpt->title[title->ttn-1].nr_of_ptts; i++ )
- {
- int pgc_id_next, pgn_next;
- pgc_t * pgc_next;
-
- chapter = calloc( sizeof( hb_chapter_t ), 1 );
- chapter->index = c;
-
- pgc_id = vts->vts_ptt_srpt->title[title->ttn-1].ptt[i].pgcn;
- pgn = vts->vts_ptt_srpt->title[title->ttn-1].ptt[i].pgn;
- d->pgc = vts->vts_pgcit->pgci_srp[pgc_id-1].pgc;
-
- /* Start cell */
- chapter->cell_start = d->pgc->program_map[pgn-1] - 1;
- chapter->block_start =
- d->pgc->cell_playback[chapter->cell_start].first_sector;
-
- /* End cell */
- if( i != vts->vts_ptt_srpt->title[title->ttn-1].nr_of_ptts - 1 )
- {
- /* The cell before the starting cell of the next chapter,
- or... */
- pgc_id_next = vts->vts_ptt_srpt->title[title->ttn-1].ptt[i+1].pgcn;
- pgn_next = vts->vts_ptt_srpt->title[title->ttn-1].ptt[i+1].pgn;
- pgc_next = vts->vts_pgcit->pgci_srp[pgc_id_next-1].pgc;
- chapter->cell_end = pgc_next->program_map[pgn_next-1] - 2;
- if( chapter->cell_end < 0 )
- {
- /* Huh? */
- free( chapter );
- continue;
- }
- }
- else
- {
- /* ... the last cell of the title */
- chapter->cell_end = title->cell_end;
- }
- chapter->block_end =
- d->pgc->cell_playback[chapter->cell_end].last_sector;
-
- /* Block count, duration */
- pgc_id = vts->vts_ptt_srpt->title[title->ttn-1].ptt[0].pgcn;
- pgn = vts->vts_ptt_srpt->title[title->ttn-1].ptt[0].pgn;
- d->pgc = vts->vts_pgcit->pgci_srp[pgc_id-1].pgc;
- chapter->block_count = 0;
- chapter->duration = 0;
-
- d->cell_cur = chapter->cell_start;
- while( d->cell_cur <= chapter->cell_end )
- {
-#define cp d->pgc->cell_playback[d->cell_cur]
- chapter->block_count += cp.last_sector + 1 - cp.first_sector;
- chapter->duration += 90LL * dvdtime2msec( &cp.playback_time );
-#undef cp
- FindNextCell( d );
- d->cell_cur = d->cell_next;
- }
-
- if( chapter->block_count < 2048 && chapter->index > 1 )
- {
- hb_log( "scan: chapter %d too short (%d blocks, "
- "cells=%d->%d), merging", chapter->index,
- chapter->block_count, chapter->cell_start,
- chapter->cell_end );
- chapter_old = hb_list_item( title->list_chapter,
- chapter->index - 2 );
- chapter_old->cell_end = chapter->cell_end;
- chapter_old->block_end = chapter->block_end;
- chapter_old->block_count += chapter->block_count;
- free( chapter );
- chapter = chapter_old;
- }
- else
- {
- hb_list_add( title->list_chapter, chapter );
- c++;
- }
- }
-
- /* The durations we get for chapters aren't precise. Scale them so
- the total matches the title duration */
- duration = 0;
- for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
- {
- chapter = hb_list_item( title->list_chapter, i );
- duration += chapter->duration;
- }
- duration_correction = (float) title->duration / (float) duration;
- for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
- {
- int seconds;
- chapter = hb_list_item( title->list_chapter, i );
- chapter->duration = duration_correction * chapter->duration;
- seconds = ( chapter->duration + 45000 ) / 90000;
- chapter->hours = seconds / 3600;
- chapter->minutes = ( seconds % 3600 ) / 60;
- chapter->seconds = seconds % 60;
-
- hb_log( "scan: chap %d c=%d->%d, b=%d->%d (%d), %lld ms",
- chapter->index, chapter->cell_start, chapter->cell_end,
- chapter->block_start, chapter->block_end,
- chapter->block_count, chapter->duration / 90 );
- }
-
- /* Get aspect. We don't get width/height/rate infos here as
- they tend to be wrong */
- switch( vts->vtsi_mat->vts_video_attr.display_aspect_ratio )
- {
- case 0:
- title->aspect = HB_ASPECT_BASE * 4 / 3;
- break;
- case 3:
- title->aspect = HB_ASPECT_BASE * 16 / 9;
- break;
- default:
- hb_log( "scan: unknown aspect" );
- goto fail;
- }
-
- hb_log( "scan: aspect = %d", title->aspect );
-
- /* This title is ok so far */
- goto cleanup;
-
-fail:
- hb_list_close( &title->list_audio );
- free( title );
- title = NULL;
-
-cleanup:
- if( vts ) ifoClose( vts );
-
- return title;
-}
-
-/***********************************************************************
- * hb_dvd_start
- ***********************************************************************
- * Title and chapter start at 1
- **********************************************************************/
-int hb_dvd_start( hb_dvd_t * d, int title, int chapter )
-{
- int pgc_id, pgn;
- int i;
-
- /* Open the IFO and the VOBs for this title */
- d->vts = d->vmg->tt_srpt->title[title-1].title_set_nr;
- d->ttn = d->vmg->tt_srpt->title[title-1].vts_ttn;
- if( !( d->ifo = ifoOpen( d->reader, d->vts ) ) )
- {
- hb_log( "dvd: ifoOpen failed for VTS %d", d->vts );
- return 0;
- }
- if( !( d->file = DVDOpenFile( d->reader, d->vts,
- DVD_READ_TITLE_VOBS ) ) )
- {
- hb_log( "dvd: DVDOpenFile failed for VTS %d", d->vts );
- return 0;
- }
-
- /* Get title first and last blocks */
- pgc_id = d->ifo->vts_ptt_srpt->title[d->ttn-1].ptt[0].pgcn;
- pgn = d->ifo->vts_ptt_srpt->title[d->ttn-1].ptt[0].pgn;
- d->pgc = d->ifo->vts_pgcit->pgci_srp[pgc_id-1].pgc;
- d->cell_start = d->pgc->program_map[pgn - 1] - 1;
- d->cell_end = d->pgc->nr_of_cells - 1;
- d->title_start = d->pgc->cell_playback[d->cell_start].first_sector;
- d->title_end = d->pgc->cell_playback[d->cell_end].last_sector;
-
- /* Block count */
- d->title_block_count = 0;
- for( i = d->cell_start; i <= d->cell_end; i++ )
- {
- d->title_block_count += d->pgc->cell_playback[i].last_sector + 1 -
- d->pgc->cell_playback[i].first_sector;
- }
-
- /* Get pgc for the current chapter */
- pgc_id = d->ifo->vts_ptt_srpt->title[d->ttn-1].ptt[chapter-1].pgcn;
- pgn = d->ifo->vts_ptt_srpt->title[d->ttn-1].ptt[chapter-1].pgn;
- d->pgc = d->ifo->vts_pgcit->pgci_srp[pgc_id-1].pgc;
-
- /* Get the two first cells */
- d->cell_cur = d->pgc->program_map[pgn-1] - 1;
- FindNextCell( d );
-
- d->block = d->pgc->cell_playback[d->cell_cur].first_sector;
- d->next_vobu = d->block;
- d->pack_len = 0;
-
- return 1;
-}
-
-/***********************************************************************
- * hb_dvd_stop
- ***********************************************************************
- *
- **********************************************************************/
-void hb_dvd_stop( hb_dvd_t * d )
-{
- if( d->ifo )
- {
- ifoClose( d->ifo );
- d->ifo = NULL;
- }
- if( d->file )
- {
- DVDCloseFile( d->file );
- d->file = NULL;
- }
-}
-
-/***********************************************************************
- * hb_dvd_seek
- ***********************************************************************
- *
- **********************************************************************/
-int hb_dvd_seek( hb_dvd_t * d, float f )
-{
- int count, sizeCell;
- int i;
-
- count = f * d->title_block_count;
-
- for( i = d->cell_start; i <= d->cell_end; i++ )
- {
- sizeCell = d->pgc->cell_playback[i].last_sector + 1 -
- d->pgc->cell_playback[i].first_sector;
-
- if( count < sizeCell )
- {
- d->cell_cur = i;
- FindNextCell( d );
-
- /* Now let hb_dvd_read find the next VOBU */
- d->next_vobu = d->pgc->cell_playback[i].first_sector + count;
- d->pack_len = 0;
- break;
- }
-
- count -= sizeCell;
- }
-
- if( i > d->cell_end )
- {
- return 0;
- }
-
- return 1;
-}
-
-/***********************************************************************
- * hb_dvd_read
- ***********************************************************************
- *
- **********************************************************************/
-int hb_dvd_read( hb_dvd_t * d, hb_buffer_t * b )
-{
- if( !d->pack_len )
- {
- /* New pack */
- dsi_t dsi_pack;
- int error;
-
- error = 0;
-
- for( ;; )
- {
- int block, pack_len, next_vobu;
-
- if( DVDReadBlocks( d->file, d->next_vobu, 1, b->data ) != 1 )
- {
- hb_log( "dvd: DVDReadBlocks failed (%d)", d->next_vobu );
- return 0;
- }
-
- navRead_DSI( &dsi_pack, &b->data[DSI_START_BYTE] );
-
- block = dsi_pack.dsi_gi.nv_pck_lbn;
- pack_len = dsi_pack.dsi_gi.vobu_ea;
- next_vobu = block + ( dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
-
- if( pack_len > 0 &&
- pack_len < 1024 &&
- block >= d->next_vobu &&
- ( block <= d->title_start + d->title_block_count ||
- block <= d->title_end ) )
- {
- /* XXX
- This looks like a valid VOBU, but actually we are
- just hoping */
- if( error )
- {
-#if 0
- hb_log( "dvd: found VOBU at %d (b %d, l %d, n %d)",
- d->next_vobu, block, pack_len, next_vobu );
-#endif
- }
- d->block = block;
- d->pack_len = pack_len;
- d->next_vobu = next_vobu;
- break;
- }
-
- /* Wasn't a valid VOBU, try next block */
- if( !error )
- {
-#if 0
- hb_log( "dvd: looking for a VOBU (%d)", d->next_vobu );
-#endif
- }
-
- if( ++error > 1024 )
- {
- hb_log( "dvd: couldn't find a VOBU after 1024 blocks" );
- return 0;
- }
-
- (d->next_vobu)++;
- }
-
- if( dsi_pack.vobu_sri.next_vobu == SRI_END_OF_CELL )
- {
- d->cell_cur = d->cell_next;
- d->next_vobu = d->pgc->cell_playback[d->cell_cur].first_sector;
- FindNextCell( d );
- }
- }
- else
- {
- if( DVDReadBlocks( d->file, d->block, 1, b->data ) != 1 )
- {
- hb_log( "reader: DVDReadBlocks failed (%d)", d->block );
- return 0;
- }
- d->pack_len--;
- }
-
- d->block++;
-
- return 1;
-}
-
-/***********************************************************************
- * hb_dvd_chapter
- ***********************************************************************
- * Returns in which chapter the next block to be read is.
- * Chapter numbers start at 1.
- **********************************************************************/
-int hb_dvd_chapter( hb_dvd_t * d )
-{
- int i;
- int pgc_id, pgn;
- pgc_t * pgc;
-
- for( i = 0;
- i < d->ifo->vts_ptt_srpt->title[d->ttn-1].nr_of_ptts;
- i++ )
- {
- /* Get pgc for chapter (i+1) */
- pgc_id = d->ifo->vts_ptt_srpt->title[d->ttn-1].ptt[i].pgcn;
- pgn = d->ifo->vts_ptt_srpt->title[d->ttn-1].ptt[i].pgn;
- pgc = d->ifo->vts_pgcit->pgci_srp[pgc_id-1].pgc;
-
- if( d->cell_cur >= pgc->program_map[pgn-1] - 1 &&
- d->cell_cur <= pgc->nr_of_cells - 1 )
- {
- /* We are in this chapter */
- return i + 1;
- }
- }
-
- /* End of title */
- return -1;
-}
-
-/***********************************************************************
- * hb_dvd_close
- ***********************************************************************
- * Closes and frees everything
- **********************************************************************/
-void hb_dvd_close( hb_dvd_t ** _d )
-{
- hb_dvd_t * d = *_d;
-
- if( d->vmg )
- {
- ifoClose( d->vmg );
- }
- if( d->reader )
- {
- DVDClose( d->reader );
- }
-
- free( d );
- *_d = NULL;
-}
-
-/***********************************************************************
- * FindNextCell
- ***********************************************************************
- * Assumes pgc and cell_cur are correctly set, and sets cell_next to the
- * cell to be read when we will be done with cell_cur.
- **********************************************************************/
-static void FindNextCell( hb_dvd_t * d )
-{
- int i = 0;
-
- if( d->pgc->cell_playback[d->cell_cur].block_type ==
- BLOCK_TYPE_ANGLE_BLOCK )
- {
-
- while( d->pgc->cell_playback[d->cell_cur+i].block_mode !=
- BLOCK_MODE_LAST_CELL )
- {
- i++;
- }
- d->cell_next = d->cell_cur + i + 1;
- }
- else
- {
- d->cell_next = d->cell_cur + 1;
- }
-}
-
-/***********************************************************************
- * dvdtime2msec
- ***********************************************************************
- * From lsdvd
- **********************************************************************/
-static int dvdtime2msec(dvd_time_t * dt)
-{
- double frames_per_s[4] = {-1.0, 25.00, -1.0, 29.97};
- double fps = frames_per_s[(dt->frame_u & 0xc0) >> 6];
- long ms;
- ms = (((dt->hour & 0xf0) >> 3) * 5 + (dt->hour & 0x0f)) * 3600000;
- ms += (((dt->minute & 0xf0) >> 3) * 5 + (dt->minute & 0x0f)) * 60000;
- ms += (((dt->second & 0xf0) >> 3) * 5 + (dt->second & 0x0f)) * 1000;
-
- if( fps > 0 )
- {
- ms += ((dt->frame_u & 0x30) >> 3) * 5 +
- (dt->frame_u & 0x0f) * 1000.0 / fps;
- }
-
- return ms;
-}