LCOV - code coverage report
Current view: top level - media_tools - gpac_ogg.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 323 360 89.7 %
Date: 2021-04-29 23:48:07 Functions: 27 30 90.0 %

          Line data    Source code
       1             : 
       2             : 
       3             : /********************************************************************
       4             :  *                                                                  *
       5             :  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
       6             :  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
       7             :  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
       8             :  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
       9             :  *                                                                  *
      10             :  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
      11             :  * by the Xiph.Org Foundation http://www.xiph.org/                  *
      12             :  *                                                                  *
      13             :  ********************************************************************
      14             : 
      15             :  function: code raw [Vorbis] packets into framed OggSquish stream and
      16             :            decode Ogg streams back into raw packets
      17             : 
      18             :  note: The CRC code is directly derived from public domain code by
      19             :  Ross Williams (ross@guest.adelaide.edu.au).  See docs/framing.html
      20             :  for details.
      21             : 
      22             :  ********************************************************************/
      23             : 
      24             : 
      25             : #include <gpac/internal/ogg.h>
      26             : 
      27             : #ifndef GPAC_DISABLE_OGG
      28             : 
      29             : #define BUFFER_INCREMENT 256
      30             : 
      31             : static u32 mask[]=
      32             : {       0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
      33             :         0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
      34             :         0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
      35             :         0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
      36             :         0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
      37             :         0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
      38             :         0x3fffffff,0x7fffffff,0xffffffff
      39             : };
      40             : 
      41             : 
      42             : #ifdef GPAC_CONFIG_WIN32
      43             : void oggpack_writeinit(oggpack_buffer *b) {
      44             :         memset(b,0,sizeof(*b));
      45             :         b->ptr = b->buffer = (unsigned char *)gf_malloc(BUFFER_INCREMENT);
      46             :         b->buffer[0]='\0';
      47             :         b->storage=BUFFER_INCREMENT;
      48             : }
      49             : #endif
      50             : 
      51             : 
      52             : #if 0 //unused
      53             : static u32 mask8B[] =
      54             : { 0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
      55             : 
      56             : 
      57             : void oggpackB_writeinit(oggpack_buffer *b) {
      58             :         oggpack_writeinit(b);
      59             : }
      60             : #endif
      61             : 
      62             : #ifdef GPAC_CONFIG_WIN32
      63             : 
      64             : void oggpack_writetrunc(oggpack_buffer *b,s32 bits) {
      65             :         s32 bytes=bits>>3;
      66             :         bits-=bytes*8;
      67             :         b->ptr=b->buffer+bytes;
      68             :         b->endbit=bits;
      69             :         b->endbyte=bytes;
      70             :         *b->ptr&=mask[bits];
      71             : }
      72             : #endif
      73             : 
      74             : #if 0//unused
      75             : 
      76             : void oggpackB_writetrunc(oggpack_buffer *b,s32 bits) {
      77             :         s32 bytes=bits>>3;
      78             :         bits-=bytes*8;
      79             :         b->ptr=b->buffer+bytes;
      80             :         b->endbit=bits;
      81             :         b->endbyte=bytes;
      82             :         *b->ptr&=mask8B[bits];
      83             : }
      84             : #endif
      85             : 
      86             : #ifdef GPAC_CONFIG_WIN32
      87             : 
      88             : /* Takes only up to 32 bits. */
      89             : void oggpack_write(oggpack_buffer *b,u32 value,s32 bits) {
      90             :         if(b->endbyte+4>=b->storage) {
      91             :                 b->buffer = (unsigned char *)gf_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
      92             :                 b->storage+=BUFFER_INCREMENT;
      93             :                 b->ptr=b->buffer+b->endbyte;
      94             :         }
      95             : 
      96             :         value&=mask[bits];
      97             :         bits+=b->endbit;
      98             : 
      99             :         b->ptr[0]|=value<<b->endbit;
     100             : 
     101             :         if(bits>=8) {
     102             :                 b->ptr[1]=value>>(8-b->endbit);
     103             :                 if(bits>=16) {
     104             :                         b->ptr[2]=value>>(16-b->endbit);
     105             :                         if(bits>=24) {
     106             :                                 b->ptr[3]=value>>(24-b->endbit);
     107             :                                 if(bits>=32) {
     108             :                                         if(b->endbit)
     109             :                                                 b->ptr[4]=value>>(32-b->endbit);
     110             :                                         else
     111             :                                                 b->ptr[4]=0;
     112             :                                 }
     113             :                         }
     114             :                 }
     115             :         }
     116             : 
     117             :         b->endbyte+=bits/8;
     118             :         b->ptr+=bits/8;
     119             :         b->endbit=bits&7;
     120             : }
     121             : 
     122             : #endif
     123             : 
     124             : #if 0 //unused
     125             : /* Takes only up to 32 bits. */
     126             : void oggpackB_write(oggpack_buffer *b,u32 value,s32 bits) {
     127             :         if(b->endbyte+4>=b->storage) {
     128             :                 b->buffer = (unsigned char *)gf_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
     129             :                 b->storage+=BUFFER_INCREMENT;
     130             :                 b->ptr=b->buffer+b->endbyte;
     131             :         }
     132             : 
     133             :         value=(value&mask[bits])<<(32-bits);
     134             :         bits+=b->endbit;
     135             : 
     136             :         b->ptr[0]|=value>>(24+b->endbit);
     137             : 
     138             :         if(bits>=8) {
     139             :                 b->ptr[1]=value>>(16+b->endbit);
     140             :                 if(bits>=16) {
     141             :                         b->ptr[2]=value>>(8+b->endbit);
     142             :                         if(bits>=24) {
     143             :                                 b->ptr[3]=value>>(b->endbit);
     144             :                                 if(bits>=32) {
     145             :                                         if(b->endbit)
     146             :                                                 b->ptr[4]=value<<(8-b->endbit);
     147             :                                         else
     148             :                                                 b->ptr[4]=0;
     149             :                                 }
     150             :                         }
     151             :                 }
     152             :         }
     153             : 
     154             :         b->endbyte+=bits/8;
     155             :         b->ptr+=bits/8;
     156             :         b->endbit=bits&7;
     157             : }
     158             : 
     159             : void oggpack_writealign(oggpack_buffer *b) {
     160             :         s32 bits=8-b->endbit;
     161             :         if(bits<8)
     162             :                 oggpack_write(b,0,bits);
     163             : }
     164             : 
     165             : void oggpackB_writealign(oggpack_buffer *b) {
     166             :         s32 bits=8-b->endbit;
     167             :         if(bits<8)
     168             :                 oggpackB_write(b,0,bits);
     169             : }
     170             : 
     171             : static void oggpack_writecopy_helper(oggpack_buffer *b,
     172             :                                      void *source,
     173             :                                      s32 bits,
     174             :                                      void (*w)(oggpack_buffer *,
     175             :                                              u32,
     176             :                                              s32),
     177             :                                      s32 msb) {
     178             :         unsigned char *ptr=(unsigned char *)source;
     179             : 
     180             :         s32 bytes=bits/8;
     181             :         bits-=bytes*8;
     182             : 
     183             :         if(b->endbit) {
     184             :                 s32 i;
     185             :                 /* unaligned copy.  Do it the hard way. */
     186             :                 for(i=0; i<bytes; i++)
     187             :                         w(b,(u32)(ptr[i]),8);
     188             :         } else {
     189             :                 /* aligned block copy */
     190             :                 if(b->endbyte+bytes+1>=b->storage) {
     191             :                         b->storage=b->endbyte+bytes+BUFFER_INCREMENT;
     192             :                         b->buffer = (unsigned char *)gf_realloc(b->buffer,b->storage);
     193             :                         b->ptr=b->buffer+b->endbyte;
     194             :                 }
     195             : 
     196             :                 memmove(b->ptr,source,bytes);
     197             :                 b->ptr+=bytes;
     198             :                 b->buffer+=bytes;
     199             :                 *b->ptr=0;
     200             : 
     201             :         }
     202             :         if(bits) {
     203             :                 if(msb)
     204             :                         w(b,(u32)(ptr[bytes]>>(8-bits)),bits);
     205             :                 else
     206             :                         w(b,(u32)(ptr[bytes]),bits);
     207             :         }
     208             : }
     209             : 
     210             : void oggpack_writecopy(oggpack_buffer *b,void *source,s32 bits) {
     211             :         oggpack_writecopy_helper(b,source,bits,oggpack_write,0);
     212             : }
     213             : 
     214             : void oggpackB_writecopy(oggpack_buffer *b,void *source,s32 bits) {
     215             :         oggpack_writecopy_helper(b,source,bits,oggpackB_write,1);
     216             : }
     217             : 
     218             : 
     219             : void oggpackB_reset(oggpack_buffer *b) {
     220             :         oggpack_reset(b);
     221             : }
     222             : #endif
     223             : 
     224             : #ifdef GPAC_CONFIG_WIN32
     225             : void oggpack_reset(oggpack_buffer *b) {
     226             :         b->ptr=b->buffer;
     227             :         b->buffer[0]=0;
     228             :         b->endbit=b->endbyte=0;
     229             : }
     230             : #endif
     231             : 
     232             : #ifdef GPAC_CONFIG_WIN32
     233             : void oggpack_writeclear(oggpack_buffer *b) {
     234             :         gf_free(b->buffer);
     235             :         memset(b,0,sizeof(*b));
     236             : }
     237             : #endif
     238             : 
     239             : #if 0 //unused
     240             : void oggpackB_writeclear(oggpack_buffer *b) {
     241             :         oggpack_writeclear(b);
     242             : }
     243             : #endif
     244             : 
     245             : #ifdef GPAC_CONFIG_WIN32
     246             : 
     247             : /* Read in bits without advancing the bitptr; bits <= 32 */
     248             : s32 oggpack_look(oggpack_buffer *b,s32 bits) {
     249             :         u32 ret;
     250             :         u32 m=mask[bits];
     251             : 
     252             :         bits+=b->endbit;
     253             : 
     254             :         if(b->endbyte+4>=b->storage) {
     255             :                 /* not the main path */
     256             :                 if(b->endbyte*8+bits>b->storage*8)return(-1);
     257             :         }
     258             : 
     259             :         ret=b->ptr[0]>>b->endbit;
     260             :         if(bits>8) {
     261             :                 ret|=b->ptr[1]<<(8-b->endbit);
     262             :                 if(bits>16) {
     263             :                         ret|=b->ptr[2]<<(16-b->endbit);
     264             :                         if(bits>24) {
     265             :                                 ret|=b->ptr[3]<<(24-b->endbit);
     266             :                                 if(bits>32 && b->endbit)
     267             :                                         ret|=b->ptr[4]<<(32-b->endbit);
     268             :                         }
     269             :                 }
     270             :         }
     271             :         return(m&ret);
     272             : }
     273             : #endif
     274             : 
     275             : #if 0 //unused
     276             : /* Read in bits without advancing the bitptr; bits <= 32 */
     277             : s32 oggpackB_look(oggpack_buffer *b,s32 bits) {
     278             :         u32 ret;
     279             :         s32 m=32-bits;
     280             : 
     281             :         bits+=b->endbit;
     282             : 
     283             :         if(b->endbyte+4>=b->storage) {
     284             :                 /* not the main path */
     285             :                 if(b->endbyte*8+bits>b->storage*8)return(-1);
     286             :         }
     287             : 
     288             :         ret=b->ptr[0]<<(24+b->endbit);
     289             :         if(bits>8) {
     290             :                 ret|=b->ptr[1]<<(16+b->endbit);
     291             :                 if(bits>16) {
     292             :                         ret|=b->ptr[2]<<(8+b->endbit);
     293             :                         if(bits>24) {
     294             :                                 ret|=b->ptr[3]<<(b->endbit);
     295             :                                 if(bits>32 && b->endbit)
     296             :                                         ret|=b->ptr[4]>>(8-b->endbit);
     297             :                         }
     298             :                 }
     299             :         }
     300             :         return (ret>>(m>>1))>>((m+1)>>1);
     301             : }
     302             : 
     303             : s32 oggpack_look1(oggpack_buffer *b) {
     304             :         if(b->endbyte>=b->storage)return(-1);
     305             :         return((b->ptr[0]>>b->endbit)&1);
     306             : }
     307             : 
     308             : s32 oggpackB_look1(oggpack_buffer *b) {
     309             :         if(b->endbyte>=b->storage)return(-1);
     310             :         return((b->ptr[0]>>(7-b->endbit))&1);
     311             : }
     312             : 
     313             : #endif //unused
     314             : 
     315       22361 : void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,s32 bytes) {
     316             :         memset(b,0,sizeof(*b));
     317       27481 :         b->buffer=b->ptr=buf;
     318       27481 :         b->storage=bytes;
     319       22361 : }
     320             : 
     321        5120 : void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,s32 bytes) {
     322             :         oggpack_readinit(b,buf,bytes);
     323        5120 : }
     324             : 
     325             : 
     326          22 : void oggpack_adv(oggpack_buffer *b,s32 bits) {
     327          22 :         bits+=b->endbit;
     328          22 :         b->ptr+=bits/8;
     329          22 :         b->endbyte+=bits/8;
     330          22 :         b->endbit=bits&7;
     331          22 : }
     332             : 
     333             : #if 0 //unused
     334             : void oggpackB_adv(oggpack_buffer *b,s32 bits) {
     335             :         oggpack_adv(b,bits);
     336             : }
     337             : 
     338             : void oggpack_adv1(oggpack_buffer *b) {
     339             :         if(++(b->endbit)>7) {
     340             :                 b->endbit=0;
     341             :                 b->ptr++;
     342             :                 b->endbyte++;
     343             :         }
     344             : }
     345             : 
     346             : void oggpackB_adv1(oggpack_buffer *b) {
     347             :         oggpack_adv1(b);
     348             : }
     349             : #endif
     350             : 
     351             : /* bits <= 32 */
     352      117241 : s32 oggpack_read(oggpack_buffer *b,s32 bits) {
     353             :         u32 ret;
     354      117241 :         u32 m=mask[bits];
     355             : 
     356      117241 :         bits+=b->endbit;
     357             : 
     358      117241 :         if(b->endbyte+4>=b->storage) {
     359             :                 /* not the main path */
     360             :                 ret=(u32) (-1);
     361          81 :                 if(b->endbyte*8+bits>b->storage*8)goto overflow;
     362             :         }
     363             : 
     364      117237 :         ret=b->ptr[0]>>b->endbit;
     365      117237 :         if(bits>8) {
     366       26719 :                 ret|=b->ptr[1]<<(8-b->endbit);
     367       26719 :                 if(bits>16) {
     368        1925 :                         ret|=b->ptr[2]<<(16-b->endbit);
     369        1925 :                         if(bits>24) {
     370        1177 :                                 ret |= ((u32)b->ptr[3]) << (24-b->endbit);
     371        1177 :                                 if(bits>32 && b->endbit) {
     372         286 :                                         ret |= ((u32)b->ptr[4]) << (32-b->endbit);
     373             :                                 }
     374             :                         }
     375             :                 }
     376             :         }
     377      117237 :         ret&=m;
     378             : 
     379      117245 : overflow:
     380             : 
     381      117241 :         b->ptr+=bits/8;
     382      117241 :         b->endbyte+=bits/8;
     383      117241 :         b->endbit=bits&7;
     384      117241 :         return(ret);
     385             : }
     386             : 
     387             : /* bits <= 32 */
     388       10236 : s32 oggpackB_read(oggpack_buffer *b,s32 bits) {
     389             :         u32 ret;
     390       10236 :         s32 m=32-bits;
     391             : 
     392       10236 :         bits+=b->endbit;
     393             : 
     394       10236 :         if(b->endbyte+4>=b->storage) {
     395             :                 /* not the main path */
     396             :                 ret=(u32) (-1);
     397           4 :                 if(b->endbyte*8+bits>b->storage*8)goto overflow;
     398             :         }
     399             : 
     400       10232 :         ret = ((u32)b->ptr[0]) << (24+b->endbit);
     401       10232 :         if(bits>8) {
     402           0 :                 ret|=b->ptr[1]<<(16+b->endbit);
     403           0 :                 if(bits>16) {
     404           0 :                         ret|=b->ptr[2]<<(8+b->endbit);
     405           0 :                         if(bits>24) {
     406           0 :                                 ret|=b->ptr[3]<<(b->endbit);
     407           0 :                                 if(bits>32 && b->endbit)
     408           0 :                                         ret|=b->ptr[4]>>(8-b->endbit);
     409             :                         }
     410             :                 }
     411             :         }
     412       10232 :         ret=(ret>>(m>>1))>>((m+1)>>1);
     413             : 
     414       10240 : overflow:
     415             : 
     416       10236 :         b->ptr+=bits/8;
     417       10236 :         b->endbyte+=bits/8;
     418       10236 :         b->endbit=bits&7;
     419       10236 :         return(ret);
     420             : }
     421             : 
     422             : #if 0 //unused
     423             : s32 oggpack_read1(oggpack_buffer *b) {
     424             :         u32 ret;
     425             : 
     426             :         if(b->endbyte>=b->storage) {
     427             :                 /* not the main path */
     428             :                 ret=(u32) (-1);
     429             :                 goto overflow;
     430             :         }
     431             : 
     432             :         ret=(b->ptr[0]>>b->endbit)&1;
     433             : 
     434             : overflow:
     435             : 
     436             :         b->endbit++;
     437             :         if(b->endbit>7) {
     438             :                 b->endbit=0;
     439             :                 b->ptr++;
     440             :                 b->endbyte++;
     441             :         }
     442             :         return(ret);
     443             : }
     444             : 
     445             : s32 oggpackB_read1(oggpack_buffer *b) {
     446             :         u32 ret;
     447             : 
     448             :         if(b->endbyte>=b->storage) {
     449             :                 /* not the main path */
     450             :                 ret=(u32) (-1);
     451             :                 goto overflow;
     452             :         }
     453             : 
     454             :         ret=(b->ptr[0]>>(7-b->endbit))&1;
     455             : 
     456             : overflow:
     457             : 
     458             :         b->endbit++;
     459             :         if(b->endbit>7) {
     460             :                 b->endbit=0;
     461             :                 b->ptr++;
     462             :                 b->endbyte++;
     463             :         }
     464             :         return(ret);
     465             : }
     466             : #endif
     467             : 
     468             : #ifdef GPAC_CONFIG_WIN32
     469             : 
     470             : s32 oggpack_bytes(oggpack_buffer *b) {
     471             :         return(b->endbyte+(b->endbit+7)/8);
     472             : }
     473             : #endif
     474             : 
     475             : #if 0 //unused
     476             : s32 oggpack_bits(oggpack_buffer *b) {
     477             :         return(b->endbyte*8+b->endbit);
     478             : }
     479             : 
     480             : s32 oggpackB_bytes(oggpack_buffer *b) {
     481             :         return oggpack_bytes(b);
     482             : }
     483             : 
     484             : s32 oggpackB_bits(oggpack_buffer *b) {
     485             :         return oggpack_bits(b);
     486             : }
     487             : #endif
     488             : 
     489             : #ifdef GPAC_CONFIG_WIN32
     490             : 
     491             : unsigned char *oggpack_get_buffer(oggpack_buffer *b) {
     492             :         return(b->buffer);
     493             : }
     494             : #endif
     495             : 
     496             : #if 0 //unused
     497             : unsigned char *oggpackB_get_buffer(oggpack_buffer *b) {
     498             :         return oggpack_get_buffer(b);
     499             : }
     500             : 
     501             : #endif //unused
     502             : 
     503             : 
     504             : #undef BUFFER_INCREMENT
     505             : 
     506             : /* A complete description of Ogg framing exists in docs/framing.html */
     507             : 
     508           0 : s32 ogg_page_version(ogg_page *og) {
     509        6857 :         return((s32)(og->header[4]));
     510             : }
     511             : 
     512           0 : s32 ogg_page_continued(ogg_page *og) {
     513        6857 :         return((s32)(og->header[5]&0x01));
     514             : }
     515             : 
     516        4555 : s32 ogg_page_bos(ogg_page *og) {
     517       11412 :         return((s32)(og->header[5]&0x02));
     518             : }
     519             : 
     520       17924 : s32 ogg_page_eos(ogg_page *og) {
     521       17924 :         return((s32)(og->header[5]&0x04));
     522             : }
     523             : 
     524        6857 : s64 ogg_page_granulepos(ogg_page *og) {
     525        6857 :         unsigned char *page=og->header;
     526        6857 :         u64 granulepos=page[13]&(0xff);
     527        6857 :         granulepos= (granulepos<<8)|(page[12]&0xff);
     528        6857 :         granulepos= (granulepos<<8)|(page[11]&0xff);
     529        6857 :         granulepos= (granulepos<<8)|(page[10]&0xff);
     530        6857 :         granulepos= (granulepos<<8)|(page[9]&0xff);
     531        6857 :         granulepos= (granulepos<<8)|(page[8]&0xff);
     532        6857 :         granulepos= (granulepos<<8)|(page[7]&0xff);
     533        6857 :         granulepos= (granulepos<<8)|(page[6]&0xff);
     534        6857 :         return((s64) granulepos);
     535             : }
     536             : 
     537          28 : s32 ogg_page_serialno(ogg_page *og) {
     538       13770 :         return(og->header[14] |
     539       13770 :                ((u32) og->header[15]<<8) |
     540       13770 :                ((u32) og->header[16]<<16) |
     541        6885 :                ((u32) og->header[17]<<24));
     542             : }
     543             : 
     544           0 : s32 ogg_page_pageno(ogg_page *og) {
     545       13714 :         return((u32) og->header[18] |
     546       13714 :                ((u32) og->header[19]<<8) |
     547       13714 :                ((u32) og->header[20]<<16) |
     548        6857 :                ((u32) og->header[21]<<24));
     549             : }
     550             : 
     551             : 
     552             : #if 0 //unused
     553             : 
     554             : /* returns the number of packets that are completed on this page (if
     555             :    the leading packet is begun on a previous page, but ends on this
     556             :    page, it's counted */
     557             : 
     558             : /* NOTE:
     559             : If a page consists of a packet begun on a previous page, and a new
     560             : packet begun (but not completed) on this page, the return will be:
     561             :   ogg_page_packets(page)   ==1,
     562             :   ogg_page_continued(page) !=0
     563             : 
     564             : If a page happens to be a single packet that was begun on a
     565             : previous page, and spans to the next page (in the case of a three or
     566             : more page packet), the return will be:
     567             :   ogg_page_packets(page)   ==0,
     568             :   ogg_page_continued(page) !=0
     569             : */
     570             : 
     571             : s32 ogg_page_packets(ogg_page *og) {
     572             :         s32 i,n=og->header[26],count=0;
     573             :         for(i=0; i<n; i++)
     574             :                 if(og->header[27+i]<255)count++;
     575             :         return(count);
     576             : }
     577             : 
     578             : #endif //unused
     579             : 
     580             : #if 0
     581             : /* helper to initialize lookup for direct-table CRC (illustrative; we
     582             :    use the static init below) */
     583             : 
     584             : static u32 _ogg_crc_entry(u32 index) {
     585             :         s32           i;
     586             :         u32 r;
     587             : 
     588             :         r = index << 24;
     589             :         for (i=0; i<8; i++)
     590             :                 if (r & 0x80000000UL)
     591             :                         r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator
     592             :                                     polynomial, although we use an
     593             :                                     unreflected alg and an init/final
     594             :                                     of 0, not 0xffffffff */
     595             :                 else
     596             :                         r<<=1;
     597             :         return (r & 0xffffffffUL);
     598             : }
     599             : #endif
     600             : 
     601             : static u32 crc_lookup[256]= {
     602             :         0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
     603             :         0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
     604             :         0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
     605             :         0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
     606             :         0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,
     607             :         0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
     608             :         0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,
     609             :         0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
     610             :         0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,
     611             :         0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
     612             :         0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,
     613             :         0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
     614             :         0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,
     615             :         0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
     616             :         0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,
     617             :         0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
     618             :         0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,
     619             :         0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
     620             :         0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,
     621             :         0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
     622             :         0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,
     623             :         0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
     624             :         0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,
     625             :         0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
     626             :         0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,
     627             :         0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
     628             :         0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,
     629             :         0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
     630             :         0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,
     631             :         0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
     632             :         0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,
     633             :         0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
     634             :         0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,
     635             :         0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
     636             :         0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,
     637             :         0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
     638             :         0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,
     639             :         0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
     640             :         0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,
     641             :         0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
     642             :         0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,
     643             :         0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
     644             :         0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,
     645             :         0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
     646             :         0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,
     647             :         0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
     648             :         0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,
     649             :         0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
     650             :         0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,
     651             :         0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
     652             :         0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,
     653             :         0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
     654             :         0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,
     655             :         0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
     656             :         0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,
     657             :         0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
     658             :         0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,
     659             :         0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
     660             :         0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,
     661             :         0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
     662             :         0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,
     663             :         0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
     664             :         0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
     665             :         0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4
     666             : };
     667             : 
     668             : /* init the encode/decode logical stream state */
     669             : 
     670          30 : s32 ogg_stream_init(ogg_stream_state *os,s32 serialno) {
     671          30 :         if(os) {
     672             :                 memset(os,0,sizeof(*os));
     673          30 :                 os->body_storage=16*1024;
     674          30 :                 os->body_data = (unsigned char *)gf_malloc(os->body_storage*sizeof(*os->body_data));
     675             : 
     676          30 :                 os->lacing_storage=1024;
     677          30 :                 os->lacing_vals=(s32 *)gf_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
     678          30 :                 os->granule_vals=(s64*)gf_malloc(os->lacing_storage*sizeof(*os->granule_vals));
     679             : 
     680          30 :                 os->serialno=serialno;
     681             : 
     682          30 :                 return(0);
     683             :         }
     684             :         return(-1);
     685             : }
     686             : 
     687             : /* _clear does not free os, only the non-flat storage within */
     688          30 : s32 ogg_stream_clear(ogg_stream_state *os) {
     689          30 :         if(os) {
     690          30 :                 if(os->body_data)gf_free(os->body_data);
     691          30 :                 if(os->lacing_vals)gf_free(os->lacing_vals);
     692          30 :                 if(os->granule_vals)gf_free(os->granule_vals);
     693             : 
     694             :                 memset(os,0,sizeof(*os));
     695             :         }
     696          30 :         return(0);
     697             : }
     698             : 
     699             : #if 0 //unused
     700             : 
     701             : s32 ogg_stream_destroy(ogg_stream_state *os) {
     702             :         if(os) {
     703             :                 ogg_stream_clear(os);
     704             :                 gf_free(os);
     705             :         }
     706             :         return(0);
     707             : }
     708             : 
     709             : #endif //unused
     710             : 
     711             : /* Helpers for ogg_stream_encode; this keeps the structure and
     712             :    what's happening fairly clear */
     713             : 
     714        6605 : static void _os_body_expand(ogg_stream_state *os,s32 needed) {
     715        6605 :         if(os->body_storage<=os->body_fill+needed) {
     716           6 :                 os->body_storage+=(needed+1024);
     717           6 :                 os->body_data = (unsigned char *)gf_realloc(os->body_data,os->body_storage*sizeof(*os->body_data));
     718             :         }
     719        6605 : }
     720             : 
     721        6613 : static void _os_lacing_expand(ogg_stream_state *os,s32 needed) {
     722        6613 :         if(os->lacing_storage<=os->lacing_fill+needed) {
     723           0 :                 os->lacing_storage+=(needed+32);
     724           0 :                 os->lacing_vals=(s32*)gf_realloc(os->lacing_vals,os->lacing_storage*sizeof(*os->lacing_vals));
     725           0 :                 os->granule_vals=(s64*)gf_realloc(os->granule_vals,os->lacing_storage*sizeof(*os->granule_vals));
     726             :         }
     727        6613 : }
     728             : 
     729             : /* checksum the page */
     730             : /* Direct table CRC; note that this will be faster in the future if we
     731             :    perform the checksum silmultaneously with other copies */
     732             : 
     733        4800 : void ogg_page_checksum_set(ogg_page *og) {
     734        4800 :         if(og) {
     735             :                 u32 crc_reg=0;
     736             :                 s32 i;
     737             : 
     738             :                 /* safety; needed for API behavior, but not framing code */
     739        4800 :                 og->header[22]=0;
     740        4800 :                 og->header[23]=0;
     741        4800 :                 og->header[24]=0;
     742        4800 :                 og->header[25]=0;
     743             : 
     744      254676 :                 for(i=0; i<og->header_len; i++)
     745      249876 :                         crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
     746    25358702 :                 for(i=0; i<og->body_len; i++)
     747    25358702 :                         crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
     748             : 
     749        4800 :                 og->header[22]=crc_reg&0xff;
     750        4800 :                 og->header[23]=(crc_reg>>8)&0xff;
     751        4800 :                 og->header[24]=(crc_reg>>16)&0xff;
     752        4800 :                 og->header[25]=(crc_reg>>24)&0xff;
     753             :         }
     754        4800 : }
     755             : 
     756             : /* submit data to the internal buffer of the framing engine */
     757        3225 : s32 ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op) {
     758        3225 :         s32 lacing_vals=op->bytes/255+1,i;
     759             : 
     760        3225 :         if(os->body_returned) {
     761             :                 /* advance packet data according to the body_returned pointer. We
     762             :                    had to keep it around to return a pointer into the buffer last
     763             :                    call */
     764             : 
     765         239 :                 os->body_fill-=os->body_returned;
     766         239 :                 if(os->body_fill)
     767         163 :                         memmove(os->body_data,os->body_data+os->body_returned,
     768             :                                 os->body_fill);
     769         239 :                 os->body_returned=0;
     770             :         }
     771             : 
     772             :         /* make sure we have the buffer storage */
     773        3225 :         _os_body_expand(os,op->bytes);
     774        3225 :         _os_lacing_expand(os,lacing_vals);
     775             : 
     776             :         /* Copy in the submitted packet.  Yes, the copy is a waste; this is
     777             :            the liability of overly clean abstraction for the time being.  It
     778             :            will actually be fairly easy to eliminate the extra copy in the
     779             :            future */
     780             : 
     781        3225 :         memcpy(os->body_data+os->body_fill,op->packet,op->bytes);
     782        3225 :         os->body_fill+=op->bytes;
     783             : 
     784             :         /* Store lacing vals for this packet */
     785        5998 :         for(i=0; i<lacing_vals-1; i++) {
     786        2773 :                 os->lacing_vals[os->lacing_fill+i]=255;
     787        2773 :                 os->granule_vals[os->lacing_fill+i]=os->granulepos;
     788             :         }
     789        3225 :         os->lacing_vals[os->lacing_fill+i]=(op->bytes)%255;
     790        3225 :         os->granulepos=os->granule_vals[os->lacing_fill+i]=op->granulepos;
     791             : 
     792             :         /* flag the first segment as the beginning of the packet */
     793        3225 :         os->lacing_vals[os->lacing_fill]|= 0x100;
     794             : 
     795        3225 :         os->lacing_fill+=lacing_vals;
     796             : 
     797             :         /* for the sake of completeness */
     798        3225 :         os->packetno++;
     799             : 
     800        3225 :         if(op->e_o_s)os->e_o_s=1;
     801             : 
     802        3225 :         return(0);
     803             : }
     804             : 
     805             : /* This will flush remaining packets into a page (returning nonzero),
     806             :    even if there is not enough data to trigger a flush normally
     807             :    (undersized page). If there are no packets or partial packets to
     808             :    flush, ogg_stream_flush returns 0.  Note that ogg_stream_flush will
     809             :    try to flush a normal sized page like ogg_stream_pageout; a call to
     810             :    ogg_stream_flush does not guarantee that all packets have flushed.
     811             :    Only a return value of 0 from ogg_stream_flush indicates all packet
     812             :    data is flushed into pages.
     813             : 
     814             :    since ogg_stream_flush will flush the last page in a stream even if
     815             :    it's undersized, you almost certainly want to use ogg_stream_pageout
     816             :    (and *not* ogg_stream_flush) unless you specifically need to flush
     817             :    an page regardless of size in the middle of a stream. */
     818             : 
     819         244 : s32 ogg_stream_flush(ogg_stream_state *os,ogg_page *og) {
     820             :         s32 i;
     821             :         s32 vals=0;
     822         244 :         s32 maxvals=(os->lacing_fill>255?255:os->lacing_fill);
     823             :         s32 bytes=0;
     824             :         s32 acc=0;
     825         244 :         s64 granule_pos=os->granule_vals[0];
     826             : 
     827         244 :         if(maxvals==0)return(0);
     828             : 
     829             :         /* construct a page */
     830             :         /* decide how many segments to include */
     831             : 
     832             :         /* If this is the initial header case, the first page must only include
     833             :            the initial header packet */
     834         242 :         if(os->b_o_s==0) { /* 'initial header page' case */
     835             :                 granule_pos=0;
     836           0 :                 for(vals=0; vals<maxvals; vals++) {
     837           2 :                         if((os->lacing_vals[vals]&0x0ff)<255) {
     838           2 :                                 vals++;
     839           2 :                                 break;
     840             :                         }
     841             :                 }
     842             :         } else {
     843        5996 :                 for(vals=0; vals<maxvals; vals++) {
     844        6160 :                         if(acc>4096)break;
     845        5996 :                         acc+=os->lacing_vals[vals]&0x0ff;
     846        5996 :                         granule_pos=os->granule_vals[vals];
     847             :                 }
     848             :         }
     849             : 
     850             :         /* construct the header in temp storage */
     851         242 :         memcpy(os->header,"OggS",4);
     852             : 
     853             :         /* stream structure version */
     854         242 :         os->header[4]=0x00;
     855             : 
     856             :         /* continued packet flag? */
     857         242 :         os->header[5]=0x00;
     858         242 :         if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
     859             :         /* first page flag? */
     860         242 :         if(os->b_o_s==0)os->header[5]|=0x02;
     861             :         /* last page flag? */
     862         242 :         if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
     863         242 :         os->b_o_s=1;
     864             : 
     865             :         /* 64 bits of PCM position */
     866        2178 :         for(i=6; i<14; i++) {
     867        1936 :                 os->header[i]=(u8) (granule_pos&0xff);
     868        1936 :                 granule_pos>>=8;
     869             :         }
     870             : 
     871             :         /* 32 bits of stream serial number */
     872             :         {
     873         242 :                 s32 serialno=os->serialno;
     874        1210 :                 for(i=14; i<18; i++) {
     875         968 :                         os->header[i]=(serialno&0xff);
     876         968 :                         serialno>>=8;
     877             :                 }
     878             :         }
     879             : 
     880             :         /* 32 bits of page counter (we have both counter and page header
     881             :            because this val can roll over) */
     882         242 :         if(os->pageno==-1)os->pageno=0; /* because someone called
     883             :                                      stream_reset; this would be a
     884             :                                      strange thing to do in an
     885             :                                      encode stream, but it has
     886             :                                      plausible uses */
     887             :         {
     888         242 :                 s32 pageno=os->pageno++;
     889        1210 :                 for(i=18; i<22; i++) {
     890         968 :                         os->header[i]=(pageno&0xff);
     891         968 :                         pageno>>=8;
     892             :                 }
     893             :         }
     894             : 
     895             :         /* zero for computation; filled in later */
     896         242 :         os->header[22]=0;
     897         242 :         os->header[23]=0;
     898         242 :         os->header[24]=0;
     899         242 :         os->header[25]=0;
     900             : 
     901             :         /* segment table */
     902         242 :         os->header[26]=vals&0xff;
     903        6240 :         for(i=0; i<vals; i++)
     904        5998 :                 bytes+=os->header[i+27]=(os->lacing_vals[i]&0xff);
     905             : 
     906             :         /* set pointers in the ogg_page struct */
     907         242 :         og->header=os->header;
     908         242 :         og->header_len=os->header_fill=vals+27;
     909         242 :         og->body=os->body_data+os->body_returned;
     910         242 :         og->body_len=bytes;
     911             : 
     912             :         /* advance the lacing data and set the body_returned pointer */
     913             : 
     914         242 :         os->lacing_fill-=vals;
     915         242 :         memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
     916         242 :         memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
     917         242 :         os->body_returned+=bytes;
     918             : 
     919             :         /* calculate the checksum */
     920             : 
     921         242 :         ogg_page_checksum_set(og);
     922             : 
     923             :         /* done */
     924         242 :         return(1);
     925             : }
     926             : 
     927             : 
     928             : /* This constructs pages from buffered packet segments.  The pointers
     929             : returned are to static buffers; do not free. The returned buffers are
     930             : good only until the next call (using the same ogg_stream_state) */
     931             : 
     932        3465 : s32 ogg_stream_pageout(ogg_stream_state *os, ogg_page *og) {
     933             : 
     934        6927 :         if((os->e_o_s&&os->lacing_fill) ||          /* 'were done, now flush' case */
     935        6687 :                 os->body_fill-os->body_returned > 4096 ||/* 'page nominal size' case */
     936        6450 :                 os->lacing_fill>=255 ||                  /* 'segment table full' case */
     937        3148 :                 (os->lacing_fill&&!os->b_o_s)) {         /* 'initial header page' case */
     938             : 
     939         242 :                 return(ogg_stream_flush(os,og));
     940             :         }
     941             : 
     942             :         /* not enough data to construct a page and not end of stream */
     943             :         return(0);
     944             : }
     945             : 
     946             : #if 0 //unused
     947             : s32 ogg_stream_eos(ogg_stream_state *os) {
     948             :         return os->e_o_s;
     949             : }
     950             : #endif
     951             : 
     952             : /* DECODING PRIMITIVES: packet streaming layer **********************/
     953             : 
     954             : /* This has two layers to place more of the multi-serialno and paging
     955             :    control in the application's hands.  First, we expose a data buffer
     956             :    using ogg_sync_buffer().  The app either copies into the
     957             :    buffer, or passes it directly to read(), etc.  We then call
     958             :    ogg_sync_wrote() to tell how many bytes we just added.
     959             : 
     960             :    Pages are returned (pointers into the buffer in ogg_sync_state)
     961             :    by ogg_sync_pageout().  The page is then submitted to
     962             :    ogg_stream_pagein() along with the appropriate
     963             :    ogg_stream_state* (ie, matching serialno).  We then get raw
     964             :    packets out calling ogg_stream_packetout() with a
     965             :    ogg_stream_state.  See the 'frame-prog.txt' docs for details and
     966             :    example code. */
     967             : 
     968             : /* initialize the struct to a known state */
     969          14 : s32 ogg_sync_init(ogg_sync_state *oy) {
     970          14 :         if(oy) {
     971             :                 memset(oy,0,sizeof(*oy));
     972             :         }
     973          14 :         return(0);
     974             : }
     975             : 
     976             : /* clear non-flat storage within */
     977          14 : s32 ogg_sync_clear(ogg_sync_state *oy) {
     978          14 :         if(oy) {
     979          14 :                 if(oy->data)gf_free(oy->data);
     980             :                 ogg_sync_init(oy);
     981             :         }
     982          14 :         return(0);
     983             : }
     984             : 
     985             : #if 0 //unused
     986             : s32 ogg_sync_destroy(ogg_sync_state *oy) {
     987             :         if(oy) {
     988             :                 ogg_sync_clear(oy);
     989             :                 gf_free(oy);
     990             :         }
     991             :         return(0);
     992             : }
     993             : #endif
     994             : 
     995             : 
     996        4037 : u8 *ogg_sync_buffer(ogg_sync_state *oy, s32 size) {
     997             : 
     998             :         /* first, clear out any space that has been previously returned */
     999        4037 :         if(oy->returned) {
    1000        3246 :                 oy->fill-=oy->returned;
    1001        3246 :                 if(oy->fill>0)
    1002        3246 :                         memmove(oy->data,oy->data+oy->returned,oy->fill);
    1003        3246 :                 oy->returned=0;
    1004             :         }
    1005             : 
    1006        4037 :         if(size>oy->storage-oy->fill) {
    1007             :                 /* We need to extend the internal buffer */
    1008          65 :                 s32 newsize=size+oy->fill+4096; /* an extra page to be nice */
    1009             : 
    1010          65 :                 if(oy->data)
    1011          51 :                         oy->data = (unsigned char *)gf_realloc(oy->data,newsize);
    1012             :                 else
    1013          14 :                         oy->data = (unsigned char *)gf_malloc(newsize);
    1014          65 :                 oy->storage=newsize;
    1015             :         }
    1016             : 
    1017             :         /* expose a segment at least as large as requested at the fill mark */
    1018        4037 :         return((char *)oy->data+oy->fill);
    1019             : }
    1020             : 
    1021        4037 : s32 ogg_sync_wrote(ogg_sync_state *oy, s32 bytes) {
    1022        4037 :         if(oy->fill+bytes>oy->storage)
    1023             :                 return(-1);
    1024        4037 :         oy->fill+=bytes;
    1025        4037 :         return(0);
    1026             : }
    1027             : 
    1028             : /* sync the stream.  This is meant to be useful for finding page
    1029             :    boundaries.
    1030             : 
    1031             :    return values for this:
    1032             :   -n) skipped n bytes
    1033             :    0) page not ready; more data (no bytes skipped)
    1034             :    n) page synced at current location; page length n bytes
    1035             : 
    1036             : */
    1037             : 
    1038       11759 : s32 ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og) {
    1039       11759 :         unsigned char *page=oy->data+oy->returned;
    1040             :         unsigned char *next;
    1041       11759 :         s32 bytes=oy->fill-oy->returned;
    1042             : 
    1043       11759 :         if(oy->headerbytes==0) {
    1044             :                 s32 headerbytes,i;
    1045        4659 :                 if(bytes<27)return(0); /* not enough for a header */
    1046             : 
    1047             :                 /* verify capture pattern */
    1048        4617 :                 if(memcmp(page,"OggS",4))goto sync_fail;
    1049             : 
    1050        4617 :                 headerbytes=page[26]+27;
    1051        4617 :                 if(bytes<headerbytes)return(0); /* not enough for header + seg table */
    1052             : 
    1053             :                 /* count up body length in the segment table */
    1054             : 
    1055      114509 :                 for(i=0; i<page[26]; i++)
    1056      114509 :                         oy->bodybytes+=page[27+i];
    1057        4562 :                 oy->headerbytes=headerbytes;
    1058             :         }
    1059             : 
    1060       11662 :         if(oy->bodybytes+oy->headerbytes>bytes)return(0);
    1061             : 
    1062             :         /* The whole test page is buffered.  Verify the checksum */
    1063             :         {
    1064             :                 /* Grab the checksum bytes, set the header field to zero */
    1065             :                 char chksum[4];
    1066             :                 ogg_page log;
    1067             : 
    1068             :                 memcpy(chksum,page+22,4);
    1069        4558 :                 memset(page+22,0,4);
    1070             : 
    1071             :                 /* set up a temp page struct and recompute the checksum */
    1072        4558 :                 log.header=page;
    1073        4558 :                 log.header_len=oy->headerbytes;
    1074        4558 :                 log.body=page+oy->headerbytes;
    1075        4558 :                 log.body_len=oy->bodybytes;
    1076        4558 :                 ogg_page_checksum_set(&log);
    1077             : 
    1078             :                 /* Compare */
    1079        4558 :                 if(memcmp(chksum,page+22,4)) {
    1080             :                         /* D'oh.  Mismatch! Corrupt page (or miscapture and not a page
    1081             :                         at all) */
    1082             :                         /* replace the computed checksum with the one actually read in */
    1083             :                         memcpy(page+22,chksum,4);
    1084             : 
    1085             :                         /* Bad checksum. Lose sync */
    1086           0 :                         goto sync_fail;
    1087             :                 }
    1088             :         }
    1089             : 
    1090             :         /* yes, have a whole page all ready to go */
    1091             :         {
    1092        4558 :                 if(og) {
    1093        4558 :                         og->header=page;
    1094        4558 :                         og->header_len=oy->headerbytes;
    1095        4558 :                         og->body=page+oy->headerbytes;
    1096        4558 :                         og->body_len=oy->bodybytes;
    1097             :                 }
    1098             : 
    1099        4558 :                 oy->unsynced=0;
    1100        4558 :                 oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
    1101        4558 :                 oy->headerbytes=0;
    1102        4558 :                 oy->bodybytes=0;
    1103        4558 :                 return(bytes);
    1104             :         }
    1105             : 
    1106           0 : sync_fail:
    1107             : 
    1108           0 :         oy->headerbytes=0;
    1109           0 :         oy->bodybytes=0;
    1110             : 
    1111             :         /* search for possible capture */
    1112           0 :         next = (unsigned char *)memchr(page+1,'O',bytes-1);
    1113           0 :         if(!next)
    1114           0 :                 next=oy->data+oy->fill;
    1115             : 
    1116           0 :         oy->returned = (s32) (next-oy->data);
    1117           0 :         return (s32) (-(next-page));
    1118             : }
    1119             : 
    1120             : /* sync the stream and get a page.  Keep trying until we find a page.
    1121             :    Supress 'sync errors' after reporting the first.
    1122             : 
    1123             :    return values:
    1124             :    -1) recapture (hole in data)
    1125             :     0) need more data
    1126             :     1) page returned
    1127             : 
    1128             :    Returns pointers into buffered data; invalidated by next call to
    1129             :    _stream, _clear, _init, or _buffer */
    1130             : 
    1131       11759 : s32 ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og) {
    1132             : 
    1133             :         /* all we need to do is verify a page at the head of the stream
    1134             :            buffer.  If it doesn't verify, we look for the next potential
    1135             :            frame */
    1136             : 
    1137             :         while(1) {
    1138       11759 :                 s32 ret=ogg_sync_pageseek(oy,og);
    1139       11759 :                 if(ret>0) {
    1140             :                         /* have a page */
    1141             :                         return(1);
    1142             :                 }
    1143        7201 :                 if(ret==0) {
    1144             :                         /* need more data */
    1145             :                         return(0);
    1146             :                 }
    1147             : 
    1148             :                 /* head did not start a synced page... skipped some bytes */
    1149           0 :                 if(!oy->unsynced) {
    1150           0 :                         oy->unsynced=1;
    1151           0 :                         return(-1);
    1152             :                 }
    1153             : 
    1154             :                 /* loop. keep looking */
    1155             : 
    1156             :         }
    1157             : }
    1158             : 
    1159             : /* add the incoming page to the stream state; we decompose the page
    1160             :    into packet segments here as well. */
    1161             : 
    1162        6857 : s32 ogg_stream_pagein(ogg_stream_state *os, ogg_page *og) {
    1163        6857 :         unsigned char *header=og->header;
    1164        6857 :         unsigned char *body=og->body;
    1165        6857 :         s32           bodysize=og->body_len;
    1166             :         s32            segptr=0;
    1167             : 
    1168             :         s32 version=ogg_page_version(og);
    1169             :         s32 continued=ogg_page_continued(og);
    1170             :         s32 bos=ogg_page_bos(og);
    1171             :         s32 eos=ogg_page_eos(og);
    1172        6857 :         s64 granulepos=ogg_page_granulepos(og);
    1173             :         s32 serialno=ogg_page_serialno(og);
    1174             :         s32 pageno=ogg_page_pageno(og);
    1175        6857 :         s32 segments=header[26];
    1176             : 
    1177             :         /* clean up 'returned data' */
    1178             :         {
    1179        6857 :                 s32 lr=os->lacing_returned;
    1180        6857 :                 s32 br=os->body_returned;
    1181             : 
    1182             :                 /* body data */
    1183        6857 :                 if(br) {
    1184        3287 :                         os->body_fill-=br;
    1185        3287 :                         if(os->body_fill)
    1186        2446 :                                 memmove(os->body_data,os->body_data+br,os->body_fill);
    1187        3287 :                         os->body_returned=0;
    1188             :                 }
    1189             : 
    1190        6857 :                 if(lr) {
    1191             :                         /* segment table */
    1192        3291 :                         if(os->lacing_fill-lr) {
    1193        2446 :                                 memmove(os->lacing_vals,os->lacing_vals+lr,
    1194        2446 :                                         (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
    1195        2446 :                                 memmove(os->granule_vals,os->granule_vals+lr,
    1196        2446 :                                         (os->lacing_fill-lr)*sizeof(*os->granule_vals));
    1197             :                         }
    1198        3291 :                         os->lacing_fill-=lr;
    1199        3291 :                         os->lacing_packet-=lr;
    1200        3291 :                         os->lacing_returned=0;
    1201             :                 }
    1202             :         }
    1203             : 
    1204             :         /* check the serial number */
    1205        6857 :         if(serialno!=os->serialno)return(-1);
    1206        3388 :         if(version>0)return(-1);
    1207             : 
    1208        3388 :         _os_lacing_expand(os,segments+1);
    1209             : 
    1210             :         /* are we in sequence? */
    1211        3388 :         if(pageno!=os->pageno) {
    1212             :                 s32 i;
    1213             : 
    1214             :                 /* unroll previous partial packet (if any) */
    1215           6 :                 for(i=os->lacing_packet; i<os->lacing_fill; i++)
    1216           0 :                         os->body_fill-=os->lacing_vals[i]&0xff;
    1217           6 :                 os->lacing_fill=os->lacing_packet;
    1218             : 
    1219             :                 /* make a note of dropped data in segment table */
    1220           6 :                 if(os->pageno!=-1) {
    1221           6 :                         os->lacing_vals[os->lacing_fill++]=0x400;
    1222           6 :                         os->lacing_packet++;
    1223             :                 }
    1224             : 
    1225             :                 /* are we a 'continued packet' page?  If so, we'll need to skip
    1226             :                    some segments */
    1227           6 :                 if(continued) {
    1228             :                         bos=0;
    1229           0 :                         for(; segptr<segments; segptr++) {
    1230           0 :                                 s32 val=header[27+segptr];
    1231           0 :                                 body+=val;
    1232           0 :                                 bodysize-=val;
    1233           0 :                                 if(val<255) {
    1234           0 :                                         segptr++;
    1235           0 :                                         break;
    1236             :                                 }
    1237             :                         }
    1238             :                 }
    1239             :         }
    1240             : 
    1241        3388 :         if(bodysize) {
    1242        3380 :                 _os_body_expand(os,bodysize);
    1243        3380 :                 memcpy(os->body_data+os->body_fill,body,bodysize);
    1244        3380 :                 os->body_fill+=bodysize;
    1245             :         }
    1246             : 
    1247             :         {
    1248             :                 s32 saved=-1;
    1249       89182 :                 while(segptr<segments) {
    1250       85794 :                         s32 val=header[27+segptr];
    1251       85794 :                         os->lacing_vals[os->lacing_fill]=val;
    1252       85794 :                         os->granule_vals[os->lacing_fill]=-1;
    1253             : 
    1254       85794 :                         if(bos) {
    1255          34 :                                 os->lacing_vals[os->lacing_fill]|=0x100;
    1256             :                                 bos=0;
    1257             :                         }
    1258             : 
    1259       85794 :                         if(val<255)saved=os->lacing_fill;
    1260             : 
    1261       85794 :                         os->lacing_fill++;
    1262       85794 :                         segptr++;
    1263             : 
    1264       85794 :                         if(val<255)os->lacing_packet=os->lacing_fill;
    1265             :                 }
    1266             : 
    1267             :                 /* set the granulepos on the last granuleval of the last full packet */
    1268        3388 :                 if(saved!=-1) {
    1269        3334 :                         os->granule_vals[saved]=granulepos;
    1270             :                 }
    1271             : 
    1272             :         }
    1273             : 
    1274        3388 :         if(eos) {
    1275          12 :                 os->e_o_s=1;
    1276          12 :                 if(os->lacing_fill>0)
    1277          12 :                         os->lacing_vals[os->lacing_fill-1]|=0x200;
    1278             :         }
    1279             : 
    1280        3388 :         os->pageno=pageno+1;
    1281             : 
    1282        3388 :         return(0);
    1283             : }
    1284             : 
    1285             : #if 0 //unused
    1286             : /* clear things to an initial state.  Good to call, eg, before seeking */
    1287             : s32 ogg_sync_reset(ogg_sync_state *oy) {
    1288             :         oy->fill=0;
    1289             :         oy->returned=0;
    1290             :         oy->unsynced=0;
    1291             :         oy->headerbytes=0;
    1292             :         oy->bodybytes=0;
    1293             :         return(0);
    1294             : }
    1295             : 
    1296             : s32 ogg_stream_reset(ogg_stream_state *os) {
    1297             :         os->body_fill=0;
    1298             :         os->body_returned=0;
    1299             : 
    1300             :         os->lacing_fill=0;
    1301             :         os->lacing_packet=0;
    1302             :         os->lacing_returned=0;
    1303             : 
    1304             :         os->header_fill=0;
    1305             : 
    1306             :         os->e_o_s=0;
    1307             :         os->b_o_s=0;
    1308             :         os->pageno=-1;
    1309             :         os->packetno=0;
    1310             :         os->granulepos=0;
    1311             : 
    1312             :         return(0);
    1313             : }
    1314             : 
    1315             : s32 ogg_stream_reset_serialno(ogg_stream_state *os,s32 serialno) {
    1316             :         ogg_stream_reset(os);
    1317             :         os->serialno=serialno;
    1318             :         return(0);
    1319             : }
    1320             : #endif //unused
    1321             : 
    1322       31808 : static s32 _packetout(ogg_stream_state *os,ogg_packet *op,s32 adv) {
    1323             : 
    1324             :         /* The last part of decode. We have the stream broken into packet
    1325             :            segments.  Now we need to group them into packets (or return the
    1326             :            out of sync markers) */
    1327             : 
    1328       31808 :         s32 ptr=os->lacing_returned;
    1329             : 
    1330       31808 :         if(os->lacing_packet<=ptr)return(0);
    1331             : 
    1332       28451 :         if(os->lacing_vals[ptr]&0x400) {
    1333             :                 /* we need to tell the codec there's a gap; it might need to
    1334             :                    handle previous packet dependencies. */
    1335           0 :                 os->lacing_returned++;
    1336           0 :                 os->packetno++;
    1337           0 :                 return(-1);
    1338             :         }
    1339             : 
    1340       28451 :         if(!op && !adv)return(1); /* just using peek as an inexpensive way
    1341             :                                to ask if there's a whole packet
    1342             :                                waiting */
    1343             : 
    1344             :         /* Gather the whole packet. We'll have no holes or a partial packet */
    1345             :         {
    1346       28451 :                 s32 size=os->lacing_vals[ptr]&0xff;
    1347             :                 s32 bytes=size;
    1348       28451 :                 s32 eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
    1349       28451 :                 s32 bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
    1350             : 
    1351      114240 :                 while(size==255) {
    1352       57338 :                         s32 val=os->lacing_vals[++ptr];
    1353       57338 :                         size=val&0xff;
    1354       57338 :                         if(val&0x200)eos=0x200;
    1355       57338 :                         bytes+=size;
    1356             :                 }
    1357             : 
    1358       28451 :                 if(op) {
    1359       28451 :                         op->e_o_s=eos;
    1360       28451 :                         op->b_o_s=bos;
    1361       28451 :                         op->packet=os->body_data+os->body_returned;
    1362       28451 :                         op->packetno=os->packetno;
    1363       28451 :                         op->granulepos=os->granule_vals[ptr];
    1364       28451 :                         op->bytes=bytes;
    1365             :                 }
    1366             : 
    1367       28451 :                 if(adv) {
    1368       28420 :                         os->body_returned+=bytes;
    1369       28420 :                         os->lacing_returned=ptr+1;
    1370       28420 :                         os->packetno++;
    1371             :                 }
    1372             :         }
    1373             :         return(1);
    1374             : }
    1375             : 
    1376       31777 : s32 ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op) {
    1377       31777 :         return _packetout(os,op,1);
    1378             : }
    1379             : 
    1380          31 : s32 ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op) {
    1381          31 :         return _packetout(os,op,0);
    1382             : }
    1383             : 
    1384             : #if 0 //unused
    1385             : void ogg_packet_clear(ogg_packet *op) {
    1386             :         gf_free(op->packet);
    1387             :         memset(op, 0, sizeof(*op));
    1388             : }
    1389             : #endif
    1390             : 
    1391             : 
    1392             : #endif /*GPAC_DISABLE_OGG*/
    1393             : 

Generated by: LCOV version 1.13