Bug 493224. Handle non-increasing granule positions in Ogg files. r=doublec
authorViktor Gal <wiking@maeth.com>
Wed, 20 May 2009 15:52:51 +1200
changeset 28620 2d3e4849df486b7ef9e22958b55de6ad98e23a5f
parent 28619 96715776a9b844b63ff9f0c97ae58dc5a1f66c57
child 28621 c3bf078aded1033b12e624fceb6c01519bcdd69c
push id7149
push userrocallahan@mozilla.com
push dateWed, 20 May 2009 05:43:24 +0000
treeherdermozilla-central@057648c9f7e1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdoublec
bugs493224
milestone1.9.2a1pre
Bug 493224. Handle non-increasing granule positions in Ogg files. r=doublec
media/liboggplay/README_MOZILLA
media/liboggplay/bug493224.patch
media/liboggplay/src/liboggplay/oggplay_callback.c
media/liboggplay/src/liboggplay/oggplay_private.h
media/liboggplay/src/liboggplay/oggplay_seek.c
media/liboggplay/update.sh
--- 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