Bug#762571: Debdiff

Martin Steghöfer martin at steghoefer.eu
Wed Oct 1 11:02:41 UTC 2014


Petter Reinholdtsen wrote:
> Do you have a working patch you can append to this bug? 

Here you go, that's what fixed the issue for me (attached debdiff).

Disclaimer: Not sure, if I did the debdiff 100% correct, libvorbis uses 
source format 1.0 and I've never worked with non-quilt packages before. 
I haven't done much testing of the patched library, either (I'm not a 
regular user of libvorbis).

Cheers,
Martin

-------------- next part --------------
diff -u libvorbis-1.3.2/debian/changelog libvorbis-1.3.2/debian/changelog
--- libvorbis-1.3.2/debian/changelog
+++ libvorbis-1.3.2/debian/changelog
@@ -1,3 +1,11 @@
+libvorbis (1.3.2-1.5) UNRELEASED; urgency=medium
+
+  * Non-maintainer upload.
+  * Fix problems with seeking to PCM 0 by backporting r19159 of
+    upstream SVN, authored by Chris Montgomery. (Closes: #762571)
+
+ -- Martin Steghöfer <martin at steghoefer.eu>  Wed, 01 Oct 2014 12:36:56 +0200
+
 libvorbis (1.3.2-1.4) unstable; urgency=low
 
   * Non-maintainer upload.
only in patch2:
unchanged:
--- libvorbis-1.3.2.orig/lib/vorbisfile.c
+++ libvorbis-1.3.2/lib/vorbisfile.c
@@ -1417,22 +1417,28 @@
     if(pos>=total)break;
   }
 
-  /* search within the logical bitstream for the page with the highest
-     pcm_pos preceding (or equal to) pos.  There is a danger here;
-     missing pages or incorrect frame number information in the
-     bitstream could make our task impossible.  Account for that (it
-     would be an error condition) */
+  /* Search within the logical bitstream for the page with the highest
+     pcm_pos preceding pos.  If we're looking for a position on the
+     first page, bisection will halt without finding our position as
+     it's before the first explicit granulepos fencepost. That case is
+     handled separately below.
+
+     There is a danger here; missing pages or incorrect frame number
+     information in the bitstream could make our task impossible.
+     Account for that (it would be an error condition) */
+
+  /* new search algorithm originally by HB (Nicholas Vinen) */
 
-  /* new search algorithm by HB (Nicholas Vinen) */
   {
     ogg_int64_t end=vf->offsets[link+1];
-    ogg_int64_t begin=vf->offsets[link];
+    ogg_int64_t begin=vf->dataoffsets[link];
     ogg_int64_t begintime = vf->pcmlengths[link*2];
     ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
     ogg_int64_t target=pos-total+begintime;
-    ogg_int64_t best=begin;
+    ogg_int64_t best=-1;
 
     ogg_page og;
+    /* bisection loop */
     while(begin<end){
       ogg_int64_t bisect;
 
@@ -1447,51 +1453,82 @@
           bisect=begin;
       }
 
+      /* only seek if the file position isn't already there */
       if(bisect!=vf->offset){
         result=_seek_helper(vf,bisect);
         if(result) goto seek_error;
       }
 
+      /* read loop within the bisection loop */
       while(begin<end){
         result=_get_next_page(vf,&og,end-vf->offset);
         if(result==OV_EREAD) goto seek_error;
         if(result<0){
+          /* there is no next page! */
           if(bisect<=begin+1)
-            end=begin; /* found it */
+              /* No bisection left to perform.  We've either found the
+                 best candidate already or failed. Exit loop. */
+            end=begin;
           else{
+            /* We tried to load a fraction of the last page; back up a
+               bit and try to get the whole last page */
             if(bisect==0) goto seek_error;
             bisect-=CHUNKSIZE;
+
+            /* don't repeat/loop on a read we've already performed */
             if(bisect<=begin)bisect=begin+1;
+
+            /* seek and cntinue bisection */
             result=_seek_helper(vf,bisect);
             if(result) goto seek_error;
           }
         }else{
           ogg_int64_t granulepos;
 
+          /* got a page. analyze it */
+          /* only consider pages from primary vorbis stream */
           if(ogg_page_serialno(&og)!=vf->serialnos[link])
             continue;
 
+          /* only consider pages with the granulepos set */
           granulepos=ogg_page_granulepos(&og);
           if(granulepos==-1)continue;
 
           if(granulepos<target){
+            /* this page is a successful candidate! Set state */
+
             best=result;  /* raw offset of packet with granulepos */
             begin=vf->offset; /* raw offset of next page */
             begintime=granulepos;
 
+            /* if we're before our target but within a short distance,
+               don't bisect; read forward */
             if(target-begintime>44100)break;
-            bisect=begin; /* *not* begin + 1 */
+
+            bisect=begin; /* *not* begin + 1 as above */
           }else{
-            if(bisect<=begin+1)
-              end=begin;  /* found it */
-            else{
-              if(end==vf->offset){ /* we're pretty close - we'd be stuck in */
+
+            /* This is one of our pages, but the granpos is
+               post-target; it is not a bisection return
+               candidate. (The only way we'd use it is if it's the
+               first page in the stream; we handle that case later
+               outside the bisection) */
+            if(bisect<=begin+1){
+              /* No bisection left to perform.  We've either found the
+                 best candidate already or failed. Exit loop. */
+              end=begin;
+            }else{
+              if(end==vf->offset){
+                /* bisection read to the end; use the known page
+                   boundary (result) to update bisection, back up a
+                   little bit, and try again */
                 end=result;
-                bisect-=CHUNKSIZE; /* an endless loop otherwise. */
+                bisect-=CHUNKSIZE;
                 if(bisect<=begin)bisect=begin+1;
                 result=_seek_helper(vf,bisect);
                 if(result) goto seek_error;
               }else{
+                /* Normal bisection */
                 end=bisect;
                 endtime=granulepos;
                 break;
@@ -1502,9 +1539,46 @@
       }
     }
 
-    /* found our page. seek to it, update pcm offset. Easier case than
-       raw_seek, don't keep packets preceding granulepos. */
-    {
+    /* Out of bisection: did it 'fail?' */
+    if(best == -1){
+
+      /* Check the 'looking for data in first page' special case;
+         bisection would 'fail' because our search target was before the
+         first PCM granule position fencepost. */
+
+      if(begin == vf->dataoffsets[link] &&
+         ogg_page_serialno(&og)==vf->serialnos[link]){
+
+        /* Yes, this is the beginning-of-stream case. We already have
+           our page, right at the beginning of PCM data.  Set state
+           and return. */
+
+        vf->offset=result;
+        vf->pcm_offset=total;
+
+        if(link!=vf->current_link){
+          /* Different link; dump entire decode machine */
+          _decode_clear(vf);
+
+          vf->current_link=link;
+          vf->current_serialno=vf->serialnos[link];
+          vf->ready_state=STREAMSET;
+
+        }else{
+          vorbis_synthesis_restart(&vf->vd);
+        }
+
+        ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
+        ogg_stream_pagein(&vf->os,&og);
+
+      }else
+        goto seek_error;
+
+    }else{
+
+      /* Bisection found our page. seek to it, update pcm offset. Easier case than
+         raw_seek, don't keep packets preceding granulepos. */
+
       ogg_page og;
       ogg_packet op;
 
@@ -1534,15 +1608,19 @@
       while(1){
         result=ogg_stream_packetpeek(&vf->os,&op);
         if(result==0){
-          /* !!! the packet finishing this page originated on a
-             preceding page. Keep fetching previous pages until we
-             get one with a granulepos or without the 'continued' flag
-             set.  Then just use raw_seek for simplicity. */
+          /* No packet returned; we exited the bisection with 'best'
+             pointing to a page with a granule position, so the packet
+             finishing this page ('best') originated on a preceding
+             page. Keep fetching previous pages until we get one with
+             a granulepos or without the 'continued' flag set.  Then
+             just use raw_seek for simplicity. */
 
           result=_seek_helper(vf,best);
           if(result<0) goto seek_error;
 
-          while(1){
+          /* Do not rewind past the beginning of link data; if we do,
+             it's either a bug or a broken stream */
+          while(result>vf->dataoffsets[link]){
             result=_get_prev_page(vf,&og);
             if(result<0) goto seek_error;
             if(ogg_page_serialno(&og)==vf->current_serialno &&


More information about the pkg-xiph-maint mailing list