]> granicus.if.org Git - handbrake/commitdiff
dvd: remove dvd specific details from hb_title_t
authorJohn Stebbins <jstebbins.hb@gmail.com>
Fri, 28 Jun 2019 16:44:24 +0000 (09:44 -0700)
committerJohn Stebbins <jstebbins.hb@gmail.com>
Fri, 12 Jul 2019 21:18:37 +0000 (14:18 -0700)
This information isn't needed by the frontends and pollutes the API

libhb/bd.c
libhb/common.h
libhb/dvd.c
libhb/dvd.h
libhb/dvdnav.c
test/test.c

index 39178f6b8f1fca3d38a6f18749aa2658532aef25..7eac359bf80ff412ea194adb88b699b85317c706 100644 (file)
@@ -306,9 +306,6 @@ hb_title_t * hb_bd_title_scan( hb_bd_t * d, int tt, uint64_t min_duration )
             *dot_term = '\0';
     }
 
-    title->vts = 0;
-    title->ttn = 0;
-
     if (tt <= d->title_count)
     {
         ti = d->title_info[tt - 1];
@@ -337,9 +334,6 @@ hb_title_t * hb_bd_title_scan( hb_bd_t * d, int tt, uint64_t min_duration )
     {
         pkt_count += ti->clips[ii].pkt_count;
     }
-    title->block_start = 0;
-    title->block_end = pkt_count;
-    title->block_count = pkt_count;
 
     title->angle_count = ti->angle_count;
 
@@ -572,7 +566,6 @@ hb_title_t * hb_bd_title_scan( hb_bd_t * d, int tt, uint64_t min_duration )
         hb_chapter_set_title( chapter, chapter_title );
 
         chapter->duration = ti->chapters[ii].duration;
-        chapter->block_start = ti->chapters[ii].offset;
 
         // Sanity check chapter duration and start times
         // Have seen some invalid durations in the wild
@@ -610,9 +603,8 @@ hb_title_t * hb_bd_title_scan( hb_bd_t * d, int tt, uint64_t min_duration )
         chapter->minutes = ( seconds % 3600 ) / 60;
         chapter->seconds = ( seconds % 60 );
 
-        hb_log( "bd: chap %d packet=%"PRIu64", %"PRIu64" ms",
+        hb_log( "bd: chap %d, %"PRIu64" ms",
                 chapter->index,
-                chapter->block_start,
                 chapter->duration / 90 );
 
         hb_list_add( title->list_chapter, chapter );
index a5127bc666310e1f08d017da9c9a597a5d986db9..5b77cbed4f6927dd4ed36b3cc3d4689f9f53b533 100644 (file)
@@ -893,13 +893,6 @@ struct hb_audio_s
 struct hb_chapter_s
 {
     int      index;
-    int      pgcn;
-    int      pgn;
-    int      cell_start;
-    int      cell_end;
-    uint64_t block_start;
-    uint64_t block_end;
-    uint64_t block_count;
 
     /* Visual-friendly duration */
     int      hours;
@@ -1052,13 +1045,6 @@ struct hb_title_s
     char            name[1024];
     int             index;
     int             playlist;
-    int             vts;
-    int             ttn;
-    int             cell_start;
-    int             cell_end;
-    uint64_t        block_start;
-    uint64_t        block_end;
-    uint64_t        block_count;
     int             angle_count;
     void          * opaque_priv;
 
index 12611d3977801bfa3fc7bd4b809c3b6ca9a3879a..bc21248c3dcf57d5d2ad27ec5858ef1df12de7b9 100644 (file)
@@ -323,17 +323,17 @@ static hb_title_t * hb_dvdread_title_scan( hb_dvd_t * e, int t, uint64_t min_dur
     }
 
     /* VTS which our title is in */
-    title->vts = d->vmg->tt_srpt->title[t-1].title_set_nr;
+    int title_vts = d->vmg->tt_srpt->title[t-1].title_set_nr;
 
-    if ( !title->vts )
+    if ( !title_vts )
     {
         /* A VTS of 0 means the title wasn't found in the title set */
-        hb_log("Invalid VTS (title set) number: %i", title->vts);
+        hb_log("Invalid VTS (title set) number: %i", title_vts);
         goto fail;
     }
 
-    hb_log( "scan: opening IFO for VTS %d", title->vts );
-    if( !( vts = ifoOpen( d->reader, title->vts ) ) )
+    hb_log( "scan: opening IFO for VTS %d", title_vts );
+    if( !( vts = ifoOpen( d->reader, title_vts ) ) )
     {
         hb_log( "scan: ifoOpen failed" );
         goto fail;
@@ -372,25 +372,25 @@ static hb_title_t * hb_dvdread_title_scan( hb_dvd_t * e, int t, uint64_t min_dur
 
     if( global_verbosity_level == 3 )
     {
-        ifo_print( d->reader, title->vts );
+        ifo_print( d->reader, title_vts );
     }
 
     /* Position of the title in the VTS */
-    title->ttn = d->vmg->tt_srpt->title[t-1].vts_ttn;
-    if ( title->ttn < 1 || title->ttn > vts->vts_ptt_srpt->nr_of_srpts )
+    int title_ttn = d->vmg->tt_srpt->title[t-1].vts_ttn;
+    if ( title_ttn < 1 || title_ttn > vts->vts_ptt_srpt->nr_of_srpts )
     {
-        hb_log( "invalid VTS PTT offset %d for title %d, skipping", title->ttn, t );
+        hb_log( "invalid VTS PTT offset %d for title %d, skipping", title_ttn, t );
         goto fail;
     }
 
     /* Get pgc */
-    pgc_id = vts->vts_ptt_srpt->title[title->ttn-1].ptt[0].pgcn;
+    pgc_id = vts->vts_ptt_srpt->title[title_ttn-1].ptt[0].pgcn;
     if ( pgc_id < 1 || pgc_id > vts->vts_pgcit->nr_of_pgci_srp )
     {
         hb_log( "invalid PGC ID %d for title %d, skipping", pgc_id, t );
         goto fail;
     }
-    pgn    = vts->vts_ptt_srpt->title[title->ttn-1].ptt[0].pgn;
+    pgn    = vts->vts_ptt_srpt->title[title_ttn-1].ptt[0].pgn;
     d->pgc = vts->vts_pgcit->pgci_srp[pgc_id-1].pgc;
 
     hb_log("pgc_id: %d, pgn: %d: pgc: %p", pgc_id, pgn, d->pgc);
@@ -413,31 +413,6 @@ static hb_title_t * hb_dvdread_title_scan( hb_dvd_t * e, int t, uint64_t min_dur
         goto fail;
     }
 
-    /* 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=%"PRIu64"->%"PRIu64", "
-            "%"PRIu64" blocks", title->vts, title->ttn, title->cell_start,
-            title->cell_end, title->block_start, title->block_end,
-            title->block_count );
-
     /* Get duration */
     title->duration = 90LL * dvdtime2msec( &d->pgc->playback_time );
     title->hours    = title->duration / 90000 / 3600;
@@ -651,9 +626,9 @@ static hb_title_t * hb_dvdread_title_scan( hb_dvd_t * e, int t, uint64_t min_dur
 
     /* Chapters */
     hb_log( "scan: title %d has %d chapters", t,
-            vts->vts_ptt_srpt->title[title->ttn-1].nr_of_ptts );
+            vts->vts_ptt_srpt->title[title_ttn-1].nr_of_ptts );
     for( i = 0;
-         i < vts->vts_ptt_srpt->title[title->ttn-1].nr_of_ptts; i++ )
+         i < vts->vts_ptt_srpt->title[title_ttn-1].nr_of_ptts; i++ )
     {
         char chapter_title[80];
         chapter = calloc( sizeof( hb_chapter_t ), 1 );
@@ -663,37 +638,34 @@ static hb_title_t * hb_dvdread_title_scan( hb_dvd_t * e, int t, uint64_t min_dur
         sprintf( chapter_title, "Chapter %d", chapter->index );
         hb_chapter_set_title( chapter, chapter_title );
 
-        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;
+        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;
+        int cell_start, cell_end;
+
+        cell_start = d->pgc->program_map[pgn-1] - 1;
 
         // if there are no more programs in this pgc, the end cell is the
         // last cell. Otherwise it's the cell before the start cell of the
         // next program.
         if ( pgn == d->pgc->nr_of_programs )
         {
-            chapter->cell_end = d->pgc->nr_of_cells - 1;
+            cell_end = d->pgc->nr_of_cells - 1;
         }
         else
         {
-            chapter->cell_end = d->pgc->program_map[pgn] - 2;;
+            cell_end = d->pgc->program_map[pgn] - 2;;
         }
-        chapter->block_end = d->pgc->cell_playback[chapter->cell_end].last_sector;
 
         /* Block count, duration */
-        chapter->block_count = 0;
         chapter->duration = 0;
 
-        d->cell_cur = chapter->cell_start;
-        while( d->cell_cur <= chapter->cell_end )
+        d->cell_cur = cell_start;
+        while( d->cell_cur <= 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 );
@@ -712,10 +684,8 @@ static hb_title_t * hb_dvdread_title_scan( hb_dvd_t * e, int t, uint64_t min_dur
         chapter->minutes  = ( seconds % 3600 ) / 60;
         chapter->seconds  = ( seconds % 60 );
 
-        hb_log( "scan: chap %d c=%d->%d, b=%"PRIu64"->%"PRIu64" (%"PRIu64"), %"PRId64" ms",
-                chapter->index, chapter->cell_start, chapter->cell_end,
-                chapter->block_start, chapter->block_end,
-                chapter->block_count, chapter->duration / 90 );
+        hb_log( "scan: chap %d, %"PRId64" ms",
+                chapter->index, chapter->duration / 90 );
     }
 
     /* Get aspect. We don't get width/height/rate infos here as
@@ -1156,8 +1126,8 @@ static hb_buffer_t * hb_dvdread_read( hb_dvd_t * e )
             {
                 if ( d->block != d->pgc->cell_playback[d->cell_cur].first_sector )
                 {
-                    hb_log( "dvd: beginning of cell %d at block %d", d->cell_cur,
-                           d->block );
+                    hb_deep_log(3, "dvd: beginning of cell %d at block %d", d->cell_cur,
+                           d->block);
                 }
                 if( d->in_cell )
                 {
@@ -1183,8 +1153,8 @@ static hb_buffer_t * hb_dvdread_read( hb_dvd_t * e )
             if ( d->block <= d->pgc->cell_playback[d->cell_cur].first_sector ||
                  d->block > d->pgc->cell_playback[d->cell_cur].last_sector )
             {
-                hb_log( "dvd: end of cell %d at block %d", d->cell_cur,
-                        d->block );
+                hb_deep_log(3, "dvd: end of cell %d at block %d", d->cell_cur,
+                        d->block);
             }
             d->cell_cur  = d->cell_next;
             d->in_cell = 0;
index c5be684a1568add42b60bd34e38cc66f6302c78f..338c8da895b707e0203ac8e9e37014f0380b7b6c 100644 (file)
 #define HB_VOBSUB_STYLE_LETTERBOX  2
 #define HB_VOBSUB_STYLE_PANSCAN    3
 
+struct hb_dvd_chapter_s
+{
+    int     index;
+    int64_t duration;
+    int     pgn;
+    int     pgcn;
+    int     block_start;
+    int     block_end;
+};
+
 struct hb_dvdread_s
 {
     char         * path;
@@ -62,11 +72,18 @@ struct hb_dvdnav_s
     int            title_block_count;
     int            chapter;
     int            cell;
-    hb_list_t    * list_chapter;
     int            stopped;
     hb_handle_t  * h;
+
+    ifo_handle_t * ifo;
+    int            vts;
+    int            pgcn;
+    int            pgn;
+    int64_t        duration;
+    hb_list_t    * list_dvd_chapter;
 };
 
+typedef struct hb_dvd_chapter_s hb_dvd_chapter_t;
 typedef struct hb_dvdnav_s hb_dvdnav_t;
 typedef struct hb_dvdread_s hb_dvdread_t;
 
index 6e165024b4a9e98481a928a36fc99f75e227d6b6..03a86e9063afdc17728c54a970211e61e3a25575 100644 (file)
@@ -61,6 +61,8 @@ static int FindChapterIndex( hb_list_t * list, int pgcn, int pgn );
 static int NextPgcn( ifo_handle_t *ifo, int pgcn, uint32_t pgcn_map[MAX_PGCN/32] );
 static int FindNextCell( pgc_t *pgc, int cell_cur );
 static int dvdtime2msec( dvd_time_t * );
+static int TitleOpenIfo(hb_dvdnav_t * d, int t);
+static void TitleCloseIfo(hb_dvdnav_t * d);
 
 hb_dvd_func_t * hb_dvdnav_methods( void )
 {
@@ -436,20 +438,16 @@ static void add_subtitle( hb_list_t * list_subtitle, int position,
 static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_duration )
 {
 
-    hb_dvdnav_t * d = &(e->dvdnav);
-    hb_title_t   * title;
-    ifo_handle_t * ifo = NULL;
-    int            pgcn, pgn, pgcn_end, i, c;
-    int            title_pgcn;
-    pgc_t        * pgc;
-    int            cell_cur;
-    hb_chapter_t * chapter;
-    int            count;
-    uint64_t       duration, longest;
-    int            longest_pgcn, longest_pgn, longest_pgcn_end;
-    const char   * name;
-    unsigned char  unused[1024];
-    const char   * codec_name;
+    hb_dvdnav_t      * d = &(e->dvdnav);
+    hb_title_t       * title;
+    int                pgcn, i;
+    pgc_t            * pgc;
+    hb_chapter_t     * chapter;
+    hb_dvd_chapter_t * dvd_chapter;
+    int                count;
+    const char       * name;
+    unsigned char      unused[1024];
+    const char       * codec_name;
 
     hb_log( "scan: scanning title %d", t );
 
@@ -482,90 +480,44 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura
         }
     }
 
-    /* VTS which our title is in */
-    title->vts = d->vmg->tt_srpt->title[t-1].title_set_nr;
-
-    if ( !title->vts )
-    {
-        /* A VTS of 0 means the title wasn't found in the title set */
-        hb_log("Invalid VTS (title set) number: %i", title->vts);
-        goto fail;
-    }
-
-    hb_log( "scan: opening IFO for VTS %d", title->vts );
-    if( !( ifo = ifoOpen( d->reader, title->vts ) ) )
+    if (!TitleOpenIfo(d, t))
     {
-        hb_log( "scan: ifoOpen failed" );
         goto fail;
     }
 
     /* ignore titles with bogus cell addresses so we don't abort later
      ** in libdvdread. */
-    for ( i = 0; i < ifo->vts_c_adt->nr_of_vobs; ++i)
+    for ( i = 0; i < d->ifo->vts_c_adt->nr_of_vobs; ++i)
     {
-        if( (ifo->vts_c_adt->cell_adr_table[i].start_sector & 0xffffff ) ==
+        if( (d->ifo->vts_c_adt->cell_adr_table[i].start_sector & 0xffffff ) ==
             0xffffff )
         {
             hb_log( "scan: cell_adr_table[%d].start_sector invalid (0x%x) "
                     "- skipping title", i,
-                    ifo->vts_c_adt->cell_adr_table[i].start_sector );
+                    d->ifo->vts_c_adt->cell_adr_table[i].start_sector );
             goto fail;
         }
-        if( (ifo->vts_c_adt->cell_adr_table[i].last_sector & 0xffffff ) ==
+        if( (d->ifo->vts_c_adt->cell_adr_table[i].last_sector & 0xffffff ) ==
             0xffffff )
         {
             hb_log( "scan: cell_adr_table[%d].last_sector invalid (0x%x) "
                     "- skipping title", i,
-                    ifo->vts_c_adt->cell_adr_table[i].last_sector );
+                    d->ifo->vts_c_adt->cell_adr_table[i].last_sector );
             goto fail;
         }
     }
 
-    if( global_verbosity_level == 3 )
+    if (global_verbosity_level == 4)
     {
-        ifo_print( d->reader, title->vts );
-    }
-
-    /* Position of the title in the VTS */
-    title->ttn = d->vmg->tt_srpt->title[t-1].vts_ttn;
-    if ( title->ttn < 1 || title->ttn > ifo->vts_ptt_srpt->nr_of_srpts )
-    {
-        hb_log( "invalid VTS PTT offset %d for title %d, skipping", title->ttn, t );
-        goto fail;
-    }
-
-    longest = 0LL;
-    longest_pgcn = -1;
-    longest_pgn = 1;
-    longest_pgcn_end = -1;
-    pgcn_end = -1;
-    for( i = 0; i < ifo->vts_ptt_srpt->title[title->ttn-1].nr_of_ptts; i++ )
-    {
-        int blocks = 0;
-
-        duration = PttDuration(ifo, title->ttn, i+1, &blocks, &pgcn_end);
-        pgcn  = ifo->vts_ptt_srpt->title[title->ttn-1].ptt[i].pgcn;
-        pgn   = ifo->vts_ptt_srpt->title[title->ttn-1].ptt[i].pgn;
-        if( duration > longest )
-        {
-            longest_pgcn  = pgcn;
-            longest_pgn   = pgn;
-            longest_pgcn_end   = pgcn_end;
-            longest = duration;
-            title->block_count = blocks;
-        }
-        else if (pgcn == longest_pgcn && pgn < longest_pgn)
-        {
-            longest_pgn   = pgn;
-            title->block_count = blocks;
-        }
+        ifo_print( d->reader, d->vts );
     }
 
     /* Get duration */
-    title->duration = longest;
-    title->hours    = title->duration / 90000 / 3600;
-    title->minutes  = ( ( title->duration / 90000 ) % 3600 ) / 60;
-    title->seconds  = ( title->duration / 90000 ) % 60;
+    title->duration = d->duration;
+    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 (%"PRId64" ms)",
             title->hours, title->minutes, title->seconds,
             title->duration / 90 );
@@ -573,33 +525,30 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura
     /* ignore titles under 10 seconds because they're often stills or
      * clips with no audio & our preview code doesn't currently handle
      * either of these. */
-    if( longest < min_duration )
+    if (title->duration < min_duration)
     {
         hb_log( "scan: ignoring title (too short)" );
         goto fail;
     }
 
-    pgcn       = longest_pgcn;
-    pgcn_end   = longest_pgcn_end;
-    pgn        = longest_pgn;;
-    title_pgcn = pgcn;
-
-
     /* Get pgc */
-    if ( pgcn < 1 || pgcn > ifo->vts_pgcit->nr_of_pgci_srp || pgcn >= MAX_PGCN)
+    if (d->pgcn < 1                                 ||
+        d->pgcn > d->ifo->vts_pgcit->nr_of_pgci_srp ||
+        d->pgcn >= MAX_PGCN)
     {
-        hb_log( "invalid PGC ID %d for title %d, skipping", pgcn, t );
+        hb_log( "invalid PGC ID %d for title %d, skipping", d->pgcn, t );
         goto fail;
     }
 
     // Check all pgc's for validity
     uint32_t pgcn_map[MAX_PGCN/32];
+    pgcn = d->pgcn;
     PgcWalkInit( pgcn_map );
     do
     {
-        pgc = ifo->vts_pgcit->pgci_srp[pgcn-1].pgc;
+        pgc = d->ifo->vts_pgcit->pgci_srp[pgcn-1].pgc;
 
-        if( !pgc || !pgc->program_map )
+        if (!pgc || !pgc->program_map)
         {
             hb_log( "scan: pgc not valid, skipping" );
             goto fail;
@@ -610,35 +559,19 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura
             hb_log( "invalid PGC cell_playback table for title %d, skipping", t );
             goto fail;
         }
-    } while ((pgcn = NextPgcn(ifo, pgcn, pgcn_map)) != 0);
+    } while ((pgcn = NextPgcn(d->ifo, pgcn, pgcn_map)) != 0);
 
-    pgcn       = longest_pgcn;
-    pgc = ifo->vts_pgcit->pgci_srp[pgcn-1].pgc;
+    pgc = d->ifo->vts_pgcit->pgci_srp[d->pgcn-1].pgc;
 
-    hb_log("pgc_id: %d, pgn: %d: pgc: %p", pgcn, pgn, pgc);
-    if (pgn > pgc->nr_of_programs)
+    hb_log("pgc_id: %d, pgn: %d: pgc: %p", d->pgcn, d->pgn, pgc);
+    if (d->pgn > pgc->nr_of_programs)
     {
-        hb_log( "invalid PGN %d for title %d, skipping", pgn, t );
+        hb_log( "invalid PGN %d for title %d, skipping", d->pgn, t );
         goto fail;
     }
 
-    /* Title start */
-    title->cell_start = pgc->program_map[pgn-1] - 1;
-    title->block_start = pgc->cell_playback[title->cell_start].first_sector;
-
-    pgc = ifo->vts_pgcit->pgci_srp[pgcn_end-1].pgc;
-
-    /* Title end */
-    title->cell_end = pgc->nr_of_cells - 1;
-    title->block_end = pgc->cell_playback[title->cell_end].last_sector;
-
-    hb_log( "scan: vts=%d, ttn=%d, cells=%d->%d, blocks=%"PRIu64"->%"PRIu64", "
-            "%"PRIu64" blocks", title->vts, title->ttn, title->cell_start,
-            title->cell_end, title->block_start, title->block_end,
-            title->block_count );
-
     /* Detect languages */
-    for( i = 0; i < ifo->vtsi_mat->nr_of_vts_audio_streams; i++ )
+    for (i = 0; i < d->ifo->vtsi_mat->nr_of_vts_audio_streams; i++)
     {
         int audio_format, lang_code, lang_extension, audio_control, position, j;
         hb_audio_t * audio, * audio_tmp;
@@ -648,13 +581,13 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura
 
         audio = calloc( sizeof( hb_audio_t ), 1 );
 
-        audio_format  ifo->vtsi_mat->vts_audio_attr[i].audio_format;
-        lang_code     ifo->vtsi_mat->vts_audio_attr[i].lang_code;
-        lang_extension = ifo->vtsi_mat->vts_audio_attr[i].code_extension;
-        audio_control =
-            ifo->vts_pgcit->pgci_srp[title_pgcn-1].pgc->audio_control[i];
+        audio_format   = d->ifo->vtsi_mat->vts_audio_attr[i].audio_format;
+        lang_code      = d->ifo->vtsi_mat->vts_audio_attr[i].lang_code;
+        lang_extension = d->ifo->vtsi_mat->vts_audio_attr[i].code_extension;
+        audio_control  =
+            d->ifo->vts_pgcit->pgci_srp[d->pgcn-1].pgc->audio_control[i];
 
-        if( !( audio_control & 0x8000 ) )
+        if (!(audio_control & 0x8000))
         {
             hb_log( "scan: audio channel is not active" );
             free( audio );
@@ -763,7 +696,7 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura
     }
 
     /* Check for subtitles */
-    for( i = 0; i < ifo->vtsi_mat->nr_of_vts_subp_streams; i++ )
+    for( i = 0; i < d->ifo->vtsi_mat->nr_of_vts_subp_streams; i++ )
     {
         int             spu_control, pos, lang_ext = 0;
         iso639_lang_t * lang;
@@ -777,7 +710,7 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura
         // 0x00001f00 - Position mask for Letterbox subtitle track
         // 0x0000001f - Position mask for Pan&Scan subtitle track
         spu_control =
-            ifo->vts_pgcit->pgci_srp[title_pgcn-1].pgc->subp_control[i];
+            d->ifo->vts_pgcit->pgci_srp[d->pgcn-1].pgc->subp_control[i];
 
         if( !( spu_control & 0x80000000 ) )
         {
@@ -785,39 +718,39 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura
             continue;
         }
 
-        lang_ext = ifo->vtsi_mat->vts_subp_attr[i].code_extension;
-        lang     = lang_for_code(ifo->vtsi_mat->vts_subp_attr[i].lang_code);
+        lang_ext = d->ifo->vtsi_mat->vts_subp_attr[i].code_extension;
+        lang     = lang_for_code(d->ifo->vtsi_mat->vts_subp_attr[i].lang_code);
 
         // display_aspect_ratio
         // 0     = 4:3
         // 3     = 16:9
         // other = invalid
-        if (ifo->vtsi_mat->vts_video_attr.display_aspect_ratio)
+        if (d->ifo->vtsi_mat->vts_video_attr.display_aspect_ratio)
         {
             // Add Wide Screen subtitle.
             pos = (spu_control >> 16) & 0x1F;
             add_subtitle(title->list_subtitle, pos, lang, lang_ext,
-                (uint8_t*)ifo->vts_pgcit->pgci_srp[title_pgcn-1].pgc->palette,
+                (uint8_t*)d->ifo->vts_pgcit->pgci_srp[d->pgcn-1].pgc->palette,
                 HB_VOBSUB_STYLE_WIDE);
 
             // permitted_df
             // 1 - Letterbox not permitted
             // 2 - Pan&Scan not permitted
             // 3 - Letterbox and Pan&Scan not permitted
-            if (!(ifo->vtsi_mat->vts_video_attr.permitted_df & 1))
+            if (!(d->ifo->vtsi_mat->vts_video_attr.permitted_df & 1))
             {
                 // Letterbox permitted.  Add Letterbox subtitle.
                 pos = (spu_control >> 8) & 0x1F;
                 add_subtitle(title->list_subtitle, pos, lang, lang_ext,
-                    (uint8_t*)ifo->vts_pgcit->pgci_srp[title_pgcn-1].pgc->palette,
+                    (uint8_t*)d->ifo->vts_pgcit->pgci_srp[d->pgcn-1].pgc->palette,
                     HB_VOBSUB_STYLE_LETTERBOX);
             }
-            if (!(ifo->vtsi_mat->vts_video_attr.permitted_df & 2))
+            if (!(d->ifo->vtsi_mat->vts_video_attr.permitted_df & 2))
             {
                 // Pan&Scan permitted.  Add Pan&Scan subtitle.
                 pos = spu_control & 0x1F;
                 add_subtitle(title->list_subtitle, pos, lang, lang_ext,
-                    (uint8_t*)ifo->vts_pgcit->pgci_srp[title_pgcn-1].pgc->palette,
+                    (uint8_t*)d->ifo->vts_pgcit->pgci_srp[d->pgcn-1].pgc->palette,
                     HB_VOBSUB_STYLE_PANSCAN);
             }
         }
@@ -825,96 +758,40 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura
         {
             pos = (spu_control >> 24) & 0x1F;
             add_subtitle(title->list_subtitle, pos, lang, lang_ext,
-                (uint8_t*)ifo->vts_pgcit->pgci_srp[title_pgcn-1].pgc->palette,
+                (uint8_t*)d->ifo->vts_pgcit->pgci_srp[d->pgcn-1].pgc->palette,
                 HB_VOBSUB_STYLE_4_3);
         }
     }
 
     /* Chapters */
-    PgcWalkInit( pgcn_map );
-    c = 0;
-    do
-    {
-        pgc = ifo->vts_pgcit->pgci_srp[pgcn-1].pgc;
-
-        for (i = pgn; i <= pgc->nr_of_programs; i++)
-        {
-            char chapter_title[80];
-            chapter = calloc( sizeof( hb_chapter_t ), 1 );
-
-            chapter->pgcn = pgcn;
-            chapter->pgn = i;
-            chapter->index = c + 1;
-            sprintf( chapter_title, "Chapter %d", chapter->index );
-            hb_chapter_set_title( chapter, chapter_title );
-
-            hb_list_add( title->list_chapter, chapter );
-            c++;
-        }
-
-        pgn = 1;
-    } while ((pgcn = NextPgcn(ifo, pgcn, pgcn_map)) != 0);
-
-    hb_log( "scan: title %d has %d chapters", t, c );
-
-    count = hb_list_count( title->list_chapter );
+    count = hb_list_count(d->list_dvd_chapter);
+    hb_log( "scan: title %d has %d chapters", t, count );
     for (i = 0; i < count; i++)
     {
-        chapter = hb_list_item( title->list_chapter, i );
-
-        pgcn = chapter->pgcn;
-        pgn = chapter->pgn;
-        pgc = ifo->vts_pgcit->pgci_srp[pgcn-1].pgc;
-
-        /* Start cell */
-        chapter->cell_start  = pgc->program_map[pgn-1] - 1;
-        chapter->block_start = pgc->cell_playback[chapter->cell_start].first_sector;
-        // if there are no more programs in this pgc, the end cell is the
-        // last cell. Otherwise it's the cell before the start cell of the
-        // next program.
-        if ( pgn == pgc->nr_of_programs )
-        {
-            chapter->cell_end = pgc->nr_of_cells - 1;
-        }
-        else
-        {
-            chapter->cell_end = pgc->program_map[pgn] - 2;;
-        }
-        chapter->block_end = pgc->cell_playback[chapter->cell_end].last_sector;
+        char chapter_title[80];
 
-        /* Block count, duration */
-        chapter->block_count = 0;
-        chapter->duration = 0;
+        dvd_chapter       = hb_list_item(d->list_dvd_chapter, i);
+        chapter           = calloc(sizeof( hb_chapter_t ), 1);
+        chapter->index    = i + 1;
+        chapter->duration = dvd_chapter->duration;
 
-        cell_cur = chapter->cell_start;
-        while( cell_cur <= chapter->cell_end )
-        {
-#define cp pgc->cell_playback[cell_cur]
-            chapter->block_count += cp.last_sector + 1 - cp.first_sector;
-            chapter->duration += 90LL * dvdtime2msec( &cp.playback_time );
-#undef cp
-            cell_cur = FindNextCell( pgc, cell_cur );
-        }
-    }
+        sprintf(chapter_title, "Chapter %d", chapter->index);
+        hb_chapter_set_title(chapter, chapter_title);
 
-    for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
-    {
-        chapter           = hb_list_item( title->list_chapter, i );
+        hb_list_add( title->list_chapter, chapter );
 
         int 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=%"PRIu64"->%"PRIu64" (%"PRIu64"), %"PRId64" ms",
-                chapter->index, chapter->cell_start, chapter->cell_end,
-                chapter->block_start, chapter->block_end,
-                chapter->block_count, chapter->duration / 90 );
+        hb_log( "scan: chap %d, %"PRId64" ms",
+                chapter->index, chapter->duration / 90 );
     }
 
     /* Get aspect. We don't get width/height/rate infos here as
        they tend to be wrong */
-    switch( ifo->vtsi_mat->vts_video_attr.display_aspect_ratio )
+    switch (d->ifo->vtsi_mat->vts_video_attr.display_aspect_ratio)
     {
         case 0:
             title->container_dar.num = 4;
@@ -929,7 +806,7 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura
             goto fail;
     }
 
-    switch( ifo->vtsi_mat->vts_video_attr.mpeg_version )
+    switch (d->ifo->vtsi_mat->vts_video_attr.mpeg_version)
     {
         case 0:
             title->video_codec       = WORK_DECAVCODECV;
@@ -941,7 +818,7 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t, uint64_t min_dura
             break;
         default:
             hb_log("scan: unknown/reserved MPEG version %d",
-                    ifo->vtsi_mat->vts_video_attr.mpeg_version);
+                    d->ifo->vtsi_mat->vts_video_attr.mpeg_version);
             title->video_codec       = WORK_DECAVCODECV;
             title->video_codec_param = AV_CODEC_ID_MPEG2VIDEO;
             break;
@@ -957,7 +834,7 @@ fail:
     hb_title_close( &title );
 
 cleanup:
-    if( ifo ) ifoClose( ifo );
+    TitleCloseIfo(d);
 
     return title;
 }
@@ -1560,18 +1437,19 @@ static int hb_dvdnav_start( hb_dvd_t * e, hb_title_t *title, int c )
 {
     hb_dvdnav_t * d = &(e->dvdnav);
     int t = title->index;
-    hb_chapter_t *chapter;
+    hb_dvd_chapter_t *chapter;
     dvdnav_status_t result;
 
-    d->title_block_count = title->block_count;
-    d->list_chapter = title->list_chapter;
-
     if ( d->stopped && !hb_dvdnav_reset(d) )
     {
         return 0;
     }
+    if (!TitleOpenIfo(d, t))
+    {
+        return 0;
+    }
     dvdnav_reset( d->dvdnav );
-    chapter = hb_list_item( title->list_chapter, c - 1);
+    chapter = hb_list_item( d->list_dvd_chapter, c - 1);
     if (chapter != NULL)
         result = dvdnav_program_play(d->dvdnav, t, chapter->pgcn, chapter->pgn);
     else
@@ -1582,7 +1460,6 @@ static int hb_dvdnav_start( hb_dvd_t * e, hb_title_t *title, int c )
                   dvdnav_err_to_string(d->dvdnav) );
         return 0;
     }
-    d->title = t;
     d->stopped = 0;
     d->chapter = 0;
     d->cell = 0;
@@ -1621,10 +1498,10 @@ static int hb_dvdnav_seek( hb_dvd_t * e, float f )
     // PGC. Position there & adjust the offset if so.
     uint64_t pgc_offset = 0;
     uint64_t chap_offset = 0;
-    hb_chapter_t *pgc_change = hb_list_item(d->list_chapter, 0 );
-    for ( ii = 0; ii < hb_list_count( d->list_chapter ); ++ii )
+    hb_dvd_chapter_t *pgc_change = hb_list_item(d->list_dvd_chapter, 0 );
+    for ( ii = 0; ii < hb_list_count( d->list_dvd_chapter ); ++ii )
     {
-        hb_chapter_t *chapter = hb_list_item( d->list_chapter, ii );
+        hb_dvd_chapter_t *chapter = hb_list_item( d->list_dvd_chapter, ii );
         uint64_t chap_len = chapter->block_end - chapter->block_start + 1;
 
         if ( chapter->pgcn != pgc_change->pgcn )
@@ -1870,7 +1747,7 @@ static hb_buffer_t * hb_dvdnav_read( hb_dvd_t * e )
                     hb_deep_log(2, "dvdnav: cell change, found next title");
                     return NULL;
                 }
-                c = FindChapterIndex(d->list_chapter, pgcn, pgn);
+                c = FindChapterIndex(d->list_dvd_chapter, pgcn, pgn);
                 if (c != d->chapter)
                 {
                     if (c < d->chapter)
@@ -1951,7 +1828,7 @@ static int hb_dvdnav_chapter( hb_dvd_t * e )
     {
         return -1;
     }
-    c = FindChapterIndex( d->list_chapter, pgcn, pgn );
+    c = FindChapterIndex( d->list_dvd_chapter, pgcn, pgn );
     return c;
 }
 
@@ -1962,14 +1839,16 @@ static int hb_dvdnav_chapter( hb_dvd_t * e )
  **********************************************************************/
 static void hb_dvdnav_close( hb_dvd_t ** _d )
 {
-    hb_dvdnav_t * d = &((*_d)->dvdnav);
+    hb_dvdnav_t      * d = &((*_d)->dvdnav);
 
-    if( d->dvdnav ) dvdnav_close( d->dvdnav );
-    if( d->vmg ) ifoClose( d->vmg );
-    if( d->reader ) DVDClose( d->reader );
+    if (d->dvdnav) dvdnav_close( d->dvdnav );
+    if (d->vmg)    ifoClose( d->vmg );
+    if (d->reader) DVDClose( d->reader );
 
     free(d->path);
 
+    TitleCloseIfo(d);
+
     free( d );
     *_d = NULL;
 }
@@ -2016,7 +1895,7 @@ static void hb_dvdnav_set_angle( hb_dvd_t * e, int angle )
 static int FindChapterIndex( hb_list_t * list, int pgcn, int pgn )
 {
     int count, ii;
-    hb_chapter_t *chapter;
+    hb_dvd_chapter_t * chapter;
 
     count = hb_list_count( list );
     for (ii = 0; ii < count; ii++)
@@ -2116,3 +1995,152 @@ static int dvdtime2msec(dvd_time_t * dt)
 
     return ms;
 }
+
+static int TitleOpenIfo(hb_dvdnav_t * d, int t)
+{
+    int                pgcn, pgn, pgcn_end, i, c;
+    pgc_t            * pgc;
+    int                cell_cur;
+    hb_dvd_chapter_t * dvd_chapter;
+    uint64_t           duration;
+
+    if (d->title == t && d->ifo != NULL)
+    {
+        // Already opened
+        return 0;
+    }
+
+    // Close previous if open
+    TitleCloseIfo(d);
+
+    /* VTS which our title is in */
+    d->vts = d->vmg->tt_srpt->title[t-1].title_set_nr;
+
+    if (!d->vts)
+    {
+        /* A VTS of 0 means the title wasn't found in the title set */
+        hb_log("Invalid VTS (title set) number: %i", d->vts);
+        goto fail;
+    }
+
+    if(!(d->ifo = ifoOpen(d->reader, d->vts)))
+    {
+        hb_log( "ifoOpen failed" );
+        goto fail;
+    }
+
+    int title_ttn = d->vmg->tt_srpt->title[t-1].vts_ttn;
+    if ( title_ttn < 1 || title_ttn > d->ifo->vts_ptt_srpt->nr_of_srpts )
+    {
+        hb_log( "invalid VTS PTT offset %d for title %d, skipping", title_ttn, t );
+        goto fail;
+    }
+
+    d->duration = 0LL;
+    d->pgcn     = -1;
+    d->pgn      = 1;
+    for (i = 0; i < d->ifo->vts_ptt_srpt->title[title_ttn-1].nr_of_ptts; i++)
+    {
+        int blocks = 0;
+
+        duration = PttDuration(d->ifo, title_ttn, i+1, &blocks, &pgcn_end);
+        pgcn     = d->ifo->vts_ptt_srpt->title[title_ttn-1].ptt[i].pgcn;
+        pgn      = d->ifo->vts_ptt_srpt->title[title_ttn-1].ptt[i].pgn;
+        if (duration > d->duration)
+        {
+            d->pgcn              = pgcn;
+            d->pgn               = pgn;
+            d->duration          = duration;
+            d->title_block_count = blocks;
+        }
+        else if (pgcn == d->pgcn && pgn < d->pgn)
+        {
+            d->pgn               = pgn;
+            d->title_block_count = blocks;
+        }
+    }
+
+
+    /* Chapters */
+    d->list_dvd_chapter = hb_list_init();
+
+    uint32_t pgcn_map[MAX_PGCN/32];
+    PgcWalkInit( pgcn_map );
+    pgcn = d->pgcn;
+    pgn  = d->pgn;
+    c = 0;
+    do
+    {
+        pgc = d->ifo->vts_pgcit->pgci_srp[pgcn-1].pgc;
+
+        for (i = pgn; i <= pgc->nr_of_programs; i++)
+        {
+            int cell_start, cell_end;
+
+            dvd_chapter = calloc(sizeof(hb_dvd_chapter_t), 1);
+
+            dvd_chapter->pgcn  = pgcn;
+            dvd_chapter->pgn   = i;
+            dvd_chapter->index = c + 1;
+
+            cell_start  = pgc->program_map[i-1] - 1;
+            dvd_chapter->block_start = pgc->cell_playback[cell_start].first_sector;
+
+            // if there are no more programs in this pgc, the end cell is the
+            // last cell. Otherwise it's the cell before the start cell of the
+            // next program.
+            if (i == pgc->nr_of_programs)
+            {
+                cell_end = pgc->nr_of_cells - 1;
+            }
+            else
+            {
+                cell_end = pgc->program_map[i] - 2;
+            }
+            dvd_chapter->block_end = pgc->cell_playback[cell_end].last_sector;
+
+            /* duration */
+            dvd_chapter->duration = 0;
+
+            cell_cur = cell_start;
+            while( cell_cur <= cell_end )
+            {
+#define cp pgc->cell_playback[cell_cur]
+                dvd_chapter->duration += 90LL * dvdtime2msec(&cp.playback_time);
+#undef cp
+                cell_cur = FindNextCell( pgc, cell_cur );
+            }
+            hb_list_add(d->list_dvd_chapter, dvd_chapter);
+            c++;
+        }
+        pgn = 1;
+    } while ((pgcn = NextPgcn(d->ifo, pgcn, pgcn_map)) != 0);
+
+    d->title = t;
+    return 1;
+
+fail:
+    TitleCloseIfo(d);
+    return 0;
+}
+
+static void TitleCloseIfo(hb_dvdnav_t * d)
+{
+    hb_dvd_chapter_t * chapter;
+    while ((chapter = hb_list_item(d->list_dvd_chapter, 0)))
+    {
+        hb_list_rem(d->list_dvd_chapter, chapter );
+        free(chapter);
+    }
+    hb_list_close(&d->list_dvd_chapter);
+
+    if (d->ifo)
+    {
+        ifoClose(d->ifo);
+    }
+    d->ifo   = NULL;
+    d->title = 0;
+    d->vts   = 0;
+    d->pgcn  = 0;
+    d->pgn   = 0;
+}
index 443ca3c2e2bb62c3c8fd87e30564dd86804c6719..f9230975803f8f6925d83ac59a25be16409f2849 100644 (file)
@@ -659,9 +659,7 @@ static void PrintTitleInfo( hb_title_t * title, int feature )
     }
     else if ( title->type == HB_DVD_TYPE )
     {
-        fprintf( stderr, "  + vts %d, ttn %d, cells %d->%d (%"PRIu64" blocks)\n",
-                title->vts, title->ttn, title->cell_start, title->cell_end,
-                title->block_count );
+        fprintf( stderr, "  + index %d\n", title->index);
     }
     else if( title->type == HB_BD_TYPE )
     {
@@ -684,10 +682,8 @@ static void PrintTitleInfo( hb_title_t * title, int feature )
     {
         hb_chapter_t  * chapter;
         chapter = hb_list_item( title->list_chapter, i );
-        fprintf( stderr, "    + %d: cells %d->%d, %"PRIu64" blocks, duration "
-                 "%02d:%02d:%02d\n", chapter->index,
-                 chapter->cell_start, chapter->cell_end,
-                 chapter->block_count, chapter->hours, chapter->minutes,
+        fprintf( stderr, "    + %d: duration %02d:%02d:%02d\n",
+                 chapter->index, chapter->hours, chapter->minutes,
                  chapter->seconds );
     }
     fprintf( stderr, "  + audio tracks:\n" );