summaryrefslogtreecommitdiffstats
path: root/libhb/dvd.c
diff options
context:
space:
mode:
authoreddyg <[email protected]>2007-10-11 19:52:16 +0000
committereddyg <[email protected]>2007-10-11 19:52:16 +0000
commit471d4423b3cbf14b134051242afa84a560ebb65d (patch)
treeda1dc7ebb39582fd2c3aae4a3d622543b7c16ee6 /libhb/dvd.c
parent82d12896b6f48d7049aee762ddd59e61499caf9c (diff)
Detect and workaround missing end of cell markers caused by corrupted DVD content, note that any lost DVD content stays lost, but at least it doesn't cause repeated Cells, which are more annoying than a few seconds of lost movie.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1020 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb/dvd.c')
-rw-r--r--libhb/dvd.c92
1 files changed, 83 insertions, 9 deletions
diff --git a/libhb/dvd.c b/libhb/dvd.c
index 6ecaab9e9..449bdd4fb 100644
--- a/libhb/dvd.c
+++ b/libhb/dvd.c
@@ -34,6 +34,8 @@ struct hb_dvd_s
int block;
int pack_len;
int next_vobu;
+ int in_cell;
+ int in_sync;
};
/***********************************************************************
@@ -572,7 +574,9 @@ int hb_dvd_start( hb_dvd_t * d, int title, int chapter )
d->next_vobu = d->block;
d->pack_len = 0;
d->cell_overlap = 0;
-
+ d->in_cell = 0;
+ d->in_sync = 2;
+
return 1;
}
@@ -631,18 +635,56 @@ int hb_dvd_seek( hb_dvd_t * d, float f )
return 0;
}
+ /*
+ * Assume that we are in sync, even if we are not given that it is obvious
+ * that we are out of sync if we have just done a seek.
+ */
+ d->in_sync = 2;
+
return 1;
}
/***********************************************************************
* is_nav_pack
- ***********************************************************************
- * Pretty much directly lifted from libdvdread's play_title function.
- **********************************************************************/
+ ***********************************************************************/
int is_nav_pack( unsigned char *buf )
{
- return ( buf[41] == 0xbf && buf[1027] == 0xbf );
+ /*
+ * The NAV Pack is comprised of the PCI Packet and DSI Packet, both
+ * of these start at known offsets and start with a special identifier.
+ *
+ * NAV = {
+ * PCI = { 00 00 01 bf # private stream header
+ * ?? ?? # length
+ * 00 # substream
+ * ...
+ * }
+ * DSI = { 00 00 01 bf # private stream header
+ * ?? ?? # length
+ * 01 # substream
+ * ...
+ * }
+ *
+ * The PCI starts at offset 0x26 into the sector, and the DSI starts at 0x400
+ *
+ * This information from: http://dvd.sourceforge.net/dvdinfo/
+ */
+ if( ( buf[0x26] == 0x00 && // PCI
+ buf[0x27] == 0x00 &&
+ buf[0x28] == 0x01 &&
+ buf[0x29] == 0xbf &&
+ buf[0x2c] == 0x00 ) &&
+ ( buf[0x400] == 0x00 && // DSI
+ buf[0x401] == 0x00 &&
+ buf[0x402] == 0x01 &&
+ buf[0x403] == 0xbf &&
+ buf[0x406] == 0x01 ) )
+ {
+ return ( 1 );
+ } else {
+ return ( 0 );
+ }
}
@@ -687,6 +729,11 @@ int hb_dvd_read( hb_dvd_t * d, hb_buffer_t * b )
if ( !is_nav_pack( b->data ) ) {
(d->next_vobu)++;
+ if( d->in_sync == 1 ) {
+ hb_log("DVD: Lost sync, searching for NAV pack at blk %d",
+ d->next_vobu);
+ d->in_sync = 0;
+ }
continue;
}
@@ -712,6 +759,7 @@ int hb_dvd_read( hb_dvd_t * d, hb_buffer_t * b )
d->next_vobu, block, pack_len, next_vobu );
#endif
}
+
d->block = block;
d->pack_len = pack_len;
d->next_vobu = next_vobu;
@@ -735,21 +783,44 @@ int hb_dvd_read( hb_dvd_t * d, hb_buffer_t * b )
(d->next_vobu)++;
}
- if( dsi_pack.vobu_sri.next_vobu == SRI_END_OF_CELL )
+ if( d->in_sync == 0 || d->in_sync == 2 )
{
+ if( d->in_sync == 0 )
+ {
+ hb_log( "DVD: In sync with DVD at block %d", d->block );
+ }
+ d->in_sync = 1;
+ }
+
+ if( dsi_pack.vobu_sri.next_vobu == SRI_END_OF_CELL )
+ {
hb_log( "DVD: End of Cell (%d) at block %d", d->cell_cur,
d->block );
d->cell_cur = d->cell_next;
+ d->in_cell = 0;
d->next_vobu = d->pgc->cell_playback[d->cell_cur].first_sector;
FindNextCell( d );
d->cell_overlap = 1;
+
}
-
+
// Revert the cell overlap, and check for a chapter break
if( dsi_pack.vobu_sri.prev_vobu == SRI_END_OF_CELL )
{
hb_log( "DVD: Beginning of Cell (%d) at block %d", d->cell_cur,
d->block );
+ if( d->in_cell )
+ {
+ hb_error( "DVD: Assuming missed End of Cell (%d)", d->cell_cur );
+ d->cell_cur = d->cell_next;
+ d->next_vobu = d->pgc->cell_playback[d->cell_cur].first_sector;
+ FindNextCell( d );
+ d->cell_overlap = 1;
+ d->in_cell = 0;
+ } else {
+ d->in_cell = 1;
+ }
+
if( d->cell_overlap )
{
b->new_chap = hb_dvd_is_break( d );
@@ -782,7 +853,7 @@ int hb_dvd_chapter( hb_dvd_t * d )
{
int i;
int pgc_id, pgn;
- int nr_of_ptts = d->ifo->vts_ptt_srpt->title[d->ttn-1].nr_of_ptts;
+ int nr_of_ptts = d->ifo->vts_ptt_srpt->title[d->ttn-1].nr_of_ptts;
pgc_t * pgc;
for( i = nr_of_ptts - 1;
@@ -862,7 +933,7 @@ int hb_dvd_is_break( hb_dvd_t * d )
}
else
{
- hb_log("DVD: Cell Found (%d)", chapter_length);
+ hb_log("DVD: Cell Found (len=%d)", chapter_length);
}
}
}
@@ -912,6 +983,9 @@ static void FindNextCell( hb_dvd_t * d )
i++;
}
d->cell_next = d->cell_cur + i + 1;
+ hb_log( "DVD: Skipping multi-angle cells %d-%d",
+ d->cell_cur,
+ d->cell_next - 1 );
}
else
{