Bug 493224. Handle non-increasing granule positions in Ogg files. r=doublec
--- a/media/liboggplay/README_MOZILLA
+++ b/media/liboggplay/README_MOZILLA
@@ -15,15 +15,17 @@ bug481921: fix a crash in oggplay_callba
trac466: Fix for infinite loop in liboggplay when running decoder on its own thread. Cherry picked from liboggplay git commit e6871f.
bug492436: Fix for that bug cherry picked from liboggplay git commit 4b97ad.
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
upstream commits dabde8, 683f23, and 4d7581.
bug488951_fix_yuv: Additional fixes to YUV conversion that have not been
upstreamed yet.
new file mode 100644
--- /dev/null
+++ b/media/liboggplay/bug493224.patch
@@ -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;
+ }
+
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
@@ -85,16 +85,25 @@ oggplay_callback_theora (OGGZ * oggz, og
long frame;
#if TIME_THEORA_DECODE
struct timeval tv;
struct timeval tv2;
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
*/
if (theora_packet_isheader(op)) {
if (theora_decode_header(&(decoder->video_info), &(decoder->video_comment), op) < 0)
return -1;
/*
@@ -155,20 +164,29 @@ oggplay_callback_theora (OGGZ * oggz, og
gettimeofday(&tv2, NULL);
musec = tv2.tv_usec - tv.tv_usec;
if (tv2.tv_sec > tv.tv_sec)
musec += (tv2.tv_sec - tv.tv_sec) * 1000000;
printf("decode took %dus\n", musec);
#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;
}
if
(
(common->current_loc == -1)
||
--- a/media/liboggplay/src/liboggplay/oggplay_private.h
+++ b/media/liboggplay/src/liboggplay/oggplay_private.h
@@ -141,32 +141,32 @@ struct _OggPlayCallbackInfo {
* list gets constructed when a new Ogg file is
* first being read, and gets torn down as soon as
* the first packet with a granulepos is processed
*
* granuleperiod The period between adjacent samples in this
* 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 {
OggPlayDecode decoder;
theora_state video_handle;
theora_info video_info;
theora_comment video_comment;
int remaining_header_packets;
@@ -188,16 +188,19 @@ typedef struct {
FishSoundInfo sound_info;
} OggPlayAudioDecode;
typedef struct {
OggPlayDecode decoder;
int granuleshift;
} OggPlayCmmlDecode;
+/**
+ * OggPlaySkeletonDecode
+ */
typedef struct {
OggPlayDecode decoder;
ogg_int64_t presentation_time;
ogg_int64_t base_time;
} OggPlaySkeletonDecode;
typedef struct {
OggPlayDecode decoder;
--- a/media/liboggplay/src/liboggplay/oggplay_seek.c
+++ b/media/liboggplay/src/liboggplay/oggplay_seek.c
@@ -179,16 +179,17 @@ oggplay_seek_cleanup(OggPlay* me, ogg_in
if (track->data_list != NULL) {
*(end_of_list_p) = track->data_list;
end_of_list_p = &(track->end_of_data_list->next);
oggplay_data_free_list(track->untimed_data_list);
}
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;
}
/*
* we need to notify the tiger renderer that we seeked, so that
* now obsolete events are discarded
*/
#ifdef HAVE_TIGER
--- a/media/liboggplay/update.sh
+++ b/media/liboggplay/update.sh
@@ -45,12 +45,13 @@ sed 's/#include <config.h>/#ifdef WIN32\
rm ./src/liboggplay/oggplay_private.h1
sed s/\#ifdef\ HAVE_INTTYPES_H/\#if\ HAVE_INTTYPES_H/g $1/src/liboggplay/oggplay_data.c >./src/liboggplay/oggplay_data.c
patch -p3 < endian.patch
patch -p3 < trac466.patch
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
patch -p3 < bug488951_yuv_fix.patch