Bug 493224. Handle non-increasing granule positions in Ogg files. r=doublec

--HG--
extra : rebase_source : d1efb6c38d22467fbb08e8781605c1b4d9552da2
This commit is contained in:
Viktor Gal 2009-05-20 15:52:51 +12:00
parent 5e17d6a960
commit bcfea37cf7
6 changed files with 148 additions and 17 deletions

View File

@ -20,6 +20,8 @@ bug493140: Fix for offsets not being used.
aspect-ratio: Adds oggplay_get_video_aspect_ratio, used for bug 480058.
bug493224.patch: Fix for bug 493224.
seek_to_key_frame.patch: Adds oggplay_seek_to_keyframe(), as per bug 463358.
bug488951: Fix for YUV conversion for odd sized frames. Cherrypicked from

View File

@ -0,0 +1,106 @@
diff --git a/src/liboggplay/oggplay_callback.c b/src/liboggplay/oggplay_callback.c
index f3e2339..39380e7 100644
--- a/src/liboggplay/oggplay_callback.c
+++ b/src/liboggplay/oggplay_callback.c
@@ -109,6 +109,15 @@ oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
int musec;
#endif
+ if ( (granulepos > 0) && (common->last_granulepos > granulepos)) {
+ /*
+ * the granule position is not monotonically increasing,
+ * something wrong with the page!
+ * skipping this page.....
+ */
+ return 0;
+ }
+
/*
* always decode headers
*/
@@ -174,10 +183,19 @@ oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
#endif
if (granulepos != -1) {
+ /*
+ * save last granule position in order to be able to validate
+ * that it's monotonically increasing
+ */
+ common->last_granulepos = granulepos;
+
+ /* calculate the frame number */
granuleshift = oggz_get_granuleshift(oggz, serialno);
frame = (granulepos >> granuleshift);
frame += (granulepos & ((1 << granuleshift) - 1));
- common->current_loc = frame * common->granuleperiod;
+
+ /* calculate the current location in the stream */
+ common->current_loc = frame * common->granuleperiod;
} else {
common->current_loc = -1;
}
diff --git a/src/liboggplay/oggplay_private.h b/src/liboggplay/oggplay_private.h
index fb73f1d..1455c68 100644
--- a/src/liboggplay/oggplay_private.h
+++ b/src/liboggplay/oggplay_private.h
@@ -142,22 +142,22 @@ struct _OggPlayCallbackInfo {
* track
*/
typedef struct {
- long serialno;
- int content_type;
- const char * content_type_name;
- OggPlayDataType decoded_type;
- ogg_int64_t granuleperiod;
- ogg_int64_t last_granulepos;
- ogg_int64_t offset;
- ogg_int64_t current_loc;
- int active;
- ogg_int64_t final_granulepos;
- struct _OggPlay * player;
- OggPlayDataHeader * data_list;
- OggPlayDataHeader * end_of_data_list;
- OggPlayDataHeader * untimed_data_list;
- OggPlayStreamInfo stream_info;
- int preroll;
+ long serialno; /**< identifies the logical bit stream */
+ int content_type;
+ const char * content_type_name;
+ OggPlayDataType decoded_type; /**< type of the track @see OggPlayDataType */
+ ogg_int64_t granuleperiod;
+ ogg_int64_t last_granulepos; /**< last seen granule position */
+ ogg_int64_t offset; /**< */
+ ogg_int64_t current_loc; /**< current location in the stream (in ) */
+ int active; /**< indicates whether the track is active or not */
+ ogg_int64_t final_granulepos; /**< */
+ struct _OggPlay * player; /**< reference to the OggPlay handle */
+ OggPlayDataHeader * data_list;
+ OggPlayDataHeader * end_of_data_list;
+ OggPlayDataHeader * untimed_data_list;
+ OggPlayStreamInfo stream_info; /**< @see OggPlayStreamInfo */
+ int preroll; /**< num. of past content packets to take into account when decoding the current Ogg page */
} OggPlayDecode;
typedef struct {
@@ -190,6 +190,9 @@ typedef struct {
int granuleshift;
} OggPlayCmmlDecode;
+/**
+ * OggPlaySkeletonDecode
+ */
typedef struct {
OggPlayDecode decoder;
ogg_int64_t presentation_time;
diff --git a/src/liboggplay/oggplay_seek.c b/src/liboggplay/oggplay_seek.c
index e74c136..ef150b8 100644
--- a/src/liboggplay/oggplay_seek.c
+++ b/src/liboggplay/oggplay_seek.c
@@ -133,6 +133,7 @@ oggplay_seek_cleanup(OggPlay* me, ogg_int64_t milliseconds)
track->data_list = track->end_of_data_list = NULL;
track->untimed_data_list = NULL;
track->current_loc = -1;
+ track->last_granulepos = -1;
track->stream_info = OGGPLAY_STREAM_JUST_SEEKED;
}

View File

@ -90,6 +90,15 @@ oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
int musec;
#endif
if ( (granulepos > 0) && (common->last_granulepos > granulepos)) {
/*
* the granule position is not monotonically increasing,
* something wrong with the page!
* skipping this page.....
*/
return 0;
}
/*
* always decode headers
*/
@ -160,10 +169,19 @@ oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
#endif
if (granulepos != -1) {
/*
* save last granule position in order to be able to validate
* that it's monotonically increasing
*/
common->last_granulepos = granulepos;
/* calculate the frame number */
granuleshift = oggz_get_granuleshift(oggz, serialno);
frame = (granulepos >> granuleshift);
frame += (granulepos & ((1 << granuleshift) - 1));
common->current_loc = frame * common->granuleperiod;
/* calculate the current location in the stream */
common->current_loc = frame * common->granuleperiod;
} else {
common->current_loc = -1;
}

View File

@ -146,22 +146,22 @@ struct _OggPlayCallbackInfo {
* track
*/
typedef struct {
long serialno;
int content_type;
const char * content_type_name;
OggPlayDataType decoded_type;
ogg_int64_t granuleperiod;
ogg_int64_t last_granulepos;
ogg_int64_t offset;
ogg_int64_t current_loc;
int active;
ogg_int64_t final_granulepos;
struct _OggPlay * player;
OggPlayDataHeader * data_list;
OggPlayDataHeader * end_of_data_list;
OggPlayDataHeader * untimed_data_list;
OggPlayStreamInfo stream_info;
int preroll;
long serialno; /**< identifies the logical bit stream */
int content_type;
const char * content_type_name;
OggPlayDataType decoded_type; /**< type of the track @see OggPlayDataType */
ogg_int64_t granuleperiod;
ogg_int64_t last_granulepos; /**< last seen granule position */
ogg_int64_t offset; /**< */
ogg_int64_t current_loc; /**< current location in the stream (in ) */
int active; /**< indicates whether the track is active or not */
ogg_int64_t final_granulepos; /**< */
struct _OggPlay * player; /**< reference to the OggPlay handle */
OggPlayDataHeader * data_list;
OggPlayDataHeader * end_of_data_list;
OggPlayDataHeader * untimed_data_list;
OggPlayStreamInfo stream_info; /**< @see OggPlayStreamInfo */
int preroll; /**< num. of past content packets to take into account when decoding the current Ogg page */
} OggPlayDecode;
typedef struct {
@ -193,6 +193,9 @@ typedef struct {
int granuleshift;
} OggPlayCmmlDecode;
/**
* OggPlaySkeletonDecode
*/
typedef struct {
OggPlayDecode decoder;
ogg_int64_t presentation_time;

View File

@ -184,6 +184,7 @@ oggplay_seek_cleanup(OggPlay* me, ogg_int64_t milliseconds)
track->data_list = track->end_of_data_list = NULL;
track->untimed_data_list = NULL;
track->current_loc = -1;
track->last_granulepos = -1;
track->stream_info = OGGPLAY_STREAM_JUST_SEEKED;
}

View File

@ -50,6 +50,7 @@ patch -p3 < bug492436.patch
patch -p3 < bug493140.patch
patch -p3 < bug481921.patch
patch -p3 < aspect_ratio.patch
patch -p1 < bug493224.patch
patch -p3 < seek_to_key_frame.patch
patch -p3 < bug488951.patch