summaryrefslogtreecommitdiffstats
path: root/libhb/stream.c
diff options
context:
space:
mode:
authorjstebbins <[email protected]>2010-06-28 18:10:15 +0000
committerjstebbins <[email protected]>2010-06-28 18:10:15 +0000
commitd6b8fa70071ed9ef8dfa6e7e9675cc2b9b4b01d5 (patch)
tree113dc0a33cd567f368d65fdf681f24d6aea92fe8 /libhb/stream.c
parent007b591efce31dcf65d23c8d3782d054b45717da (diff)
Improve program stream detection
We were getting some false positives on some files. In some cases this would lead to a crash. In all cases it leads to a failure to scan or encode properly. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@3418 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb/stream.c')
-rw-r--r--libhb/stream.c66
1 files changed, 49 insertions, 17 deletions
diff --git a/libhb/stream.c b/libhb/stream.c
index 24093e62a..613651c45 100644
--- a/libhb/stream.c
+++ b/libhb/stream.c
@@ -358,16 +358,54 @@ static int hb_stream_check_for_ts(const uint8_t *buf)
return 0;
}
-static int hb_stream_check_for_ps(const uint8_t *buf)
+static int hb_stream_check_for_ps(hb_stream_t *stream)
{
+ uint8_t buf[2048*4];
+ uint8_t sc_buf[4];
+ int pos;
+ int hits = 0;
+
+ fseek(stream->file_handle, 0, SEEK_SET);
+
// program streams should start with a PACK then some other mpeg start
// code (usually a SYS but that might be missing if we only have a clip).
- int offset = 0;
-
- for ( offset = 0; offset < 8*1024-24; ++offset )
+ while (pos < 512 * 1024)
{
- if ( check_ps_sync( &buf[offset] ) && check_ps_sc( &buf[offset] ) )
- return 1;
+ int offset;
+
+ if ( fread(buf, 1, sizeof(buf), stream->file_handle) != sizeof(buf) )
+ return 0;
+
+ for ( offset = 0; offset < 8*1024-27; ++offset )
+ {
+ if ( check_ps_sync( &buf[offset] ) && check_ps_sc( &buf[offset] ) )
+ {
+ int pes_offset, prev, data_len;
+ uint8_t sid;
+
+ if ( ++hits == 3 )
+ return 1;
+ pes_offset = 14 + (buf[13] & 0x7);
+ sid = buf[pes_offset+3];
+ data_len = (buf[pes_offset+4] << 8) + buf[pes_offset+5];
+ if ( data_len && sid > 0xba && sid < 0xf9 )
+ {
+ prev = ftell( stream->file_handle );
+ pos = pes_offset + 6 + data_len + prev;
+ fseek( stream->file_handle, pos, SEEK_SET );
+ if ( fread(sc_buf, 1, 4, stream->file_handle) != 4 )
+ return 0;
+ if (sc_buf[0] == 0x00 && sc_buf[1] == 0x00 &&
+ sc_buf[2] == 0x01)
+ {
+ return 1;
+ }
+ fseek( stream->file_handle, prev, SEEK_SET );
+ }
+ }
+ }
+ fseek( stream->file_handle, -27, SEEK_CUR );
+ pos = ftell( stream->file_handle );
}
return 0;
}
@@ -383,7 +421,6 @@ static int hb_stream_check_for_dvd_ps(const uint8_t *buf)
static int hb_stream_get_type(hb_stream_t *stream)
{
uint8_t buf[2048*4];
- int i = 64;
if ( fread(buf, 1, sizeof(buf), stream->file_handle) == sizeof(buf) )
{
@@ -409,17 +446,12 @@ static int hb_stream_get_type(hb_stream_t *stream)
stream->hb_stream_type = dvd_program;
return 1;
}
- do
+ if ( hb_stream_check_for_ps(stream) != 0 )
{
- if ( hb_stream_check_for_ps(buf) != 0 )
- {
- hb_log("file is MPEG Program Stream");
- stream->hb_stream_type = program;
- return 1;
- }
- // Seek back to handle start codes that run over end of last buffer
- fseek( stream->file_handle, -28, SEEK_CUR );
- } while ( --i && fread(buf, 1, sizeof(buf), stream->file_handle) == sizeof(buf) );
+ hb_log("file is MPEG Program Stream");
+ stream->hb_stream_type = program;
+ return 1;
+ }
}
return 0;
}