1 /********************************************************************
3 * THIS FILE IS PART OF THE Ogg Reference Library SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * THE Ogg Reference Library SOURCE CODE IS (C) COPYRIGHT 1994-2004 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
11 ********************************************************************
13 function: code raw packets into framed Ogg logical stream and
14 decode Ogg logical streams back into raw packets
17 ********************************************************************/
21 #include "ogginternal.h" /* proper way to suck in ogg/ogg.h from a
24 /* A complete description of Ogg framing exists in docs/framing.html */
26 ogg2_stream_state
*ogg2_stream_create(int serialno
){
27 ogg2_stream_state
*os
=_ogg_calloc(1,sizeof(*os
));
29 os
->serialno
=serialno
;
30 os
->bufferpool
=ogg2_buffer_create();
34 int ogg2_stream_setdiscont(ogg2_stream_state
*os
){
35 /* Discont mode must be known and set before Page 1 is processed */
36 if(os
->pageno
==0||(os
->pageno
==1&&os
->packets
==0)){
43 int ogg2_stream_setfill(ogg2_stream_state
*os
,int watermark
){
45 if(watermark
>65535)watermark
=65535;
46 os
->watermark
=watermark
;
52 /* _clear does not free os, only the non-flat storage within */
53 int ogg2_stream_destroy(ogg2_stream_state
*os
){
56 ogg2_buffer_release(os
->header_tail
);
57 ogg2_buffer_release(os
->body_tail
);
58 ogg2byte_clear(&os
->header_build
);
59 ogg2_buffer_destroy(os
->bufferpool
);
60 memset(os
,0,sizeof(*os
));
66 /* finish building a header then flush the current page header and
67 body to the output buffer */
68 static void _packet_flush(ogg2_stream_state
*os
,int nextcomplete
){
69 ogg2byte_buffer
*obb
=&os
->header_build
;
74 ogg2byte_set1(obb
,'O',0);
75 ogg2byte_set1(obb
,'g',1);
76 ogg2byte_set1(obb
,'g',2);
77 ogg2byte_set1(obb
,'S',3);
79 ogg2byte_set1(obb
,0x00,4); /* stream structure version */
82 if(os
->continued
)ctemp
|=0x01; /* continued packet flag? */
83 os
->continued
=nextcomplete
;
84 if(os
->b_o_s
==0)ctemp
|=0x02; /* first page flag? */
85 if(os
->e_o_s
)ctemp
|=0x04; /* last page flag? */
86 ogg2byte_set1(obb
,ctemp
,5);
88 /* 64 bits of granule position */
90 ogg2byte_set8(obb
,0,6);
92 ogg2byte_set8(obb
,os
->granulepos
,6);
96 /* 32 bits of stream serial number */
97 ogg2byte_set4(obb
,os
->serialno
,14);
99 /* 32 bits of page counter (we have both counter and page header
100 because this val can roll over) */
101 if(os
->pageno
==-1)os
->pageno
=0; /* because someone called
102 stream_reset; this would be a
103 strange thing to do in an
104 encode stream, but it has
106 ogg2byte_set4(obb
,os
->pageno
++,18);
108 /* CRC filled in later */
109 /* segment table size */
110 ogg2byte_set1(obb
,os
->lacing_fill
,26);
112 /* toss the header on the fifo */
114 ogg2_reference
*ret
=ogg2byte_return_and_reset(&os
->header_build
);
115 os
->header_head
=ogg2_buffer_cat(os
->header_head
,ret
);
116 if(nextcomplete
)ogg2byte_init(&os
->header_build
,0,os
->bufferpool
);
118 os
->header_tail
=ogg2byte_return_and_reset(&os
->header_build
);
119 os
->header_head
=ogg2_buffer_walk(os
->header_tail
);
120 if(nextcomplete
)ogg2byte_init(&os
->header_build
,0,os
->bufferpool
);
127 /* submit data to the internal buffer of the framing engine */
128 int ogg2_stream_packetin(ogg2_stream_state
*os
,ogg2_packet
*op
){
130 long bytes
=ogg2_buffer_length(op
->packet
);
131 long lacing_vals
=bytes
/255+1;
132 int remainder
=bytes
%255;
136 ogg2_packet_release(op
);
141 ogg2byte_init(&os
->header_build
, 0, os
->bufferpool
);
143 /* for discontinuous mode */
144 if(os
->discont
&& !os
->packets
) os
->granulepos
=op
->end_granule
;
147 /* concat packet data */
149 os
->body_head
=ogg2_buffer_cat(os
->body_head
,op
->packet
);
151 os
->body_tail
=os
->body_head
=op
->packet
;
153 /* add lacing vals, but finish/flush packet first if we hit a
154 (watermark && not initial page) */
155 for(i
=0;i
<lacing_vals
-1;i
++){ /* handle the 255s first */
157 ogg2byte_set1(&os
->header_build
,255,27+os
->lacing_fill
++);
159 if(os
->body_fill
>=os
->watermark
&& os
->b_o_s
)_packet_flush(os
,1);
160 if(os
->lacing_fill
==255)_packet_flush(os
,1);
163 /* we know we'll finish this packet on this page; propogate
164 granulepos et al and then finish packet lacing */
166 os
->body_fill
+=remainder
;
167 if (!os
->discont
) os
->granulepos
=op
->end_granule
;
168 os
->packetno
++; /* for the sake of completeness */
169 if(op
->e_o_s
)os
->e_o_s
=1;
170 ogg2byte_set1(&os
->header_build
,remainder
,27+os
->lacing_fill
++);
173 os
->body_fill
>=os
->watermark
||
175 os
->lacing_fill
==255)_packet_flush(os
,0);
177 memset(op
,0,sizeof(*op
));
181 /* This constructs pages from buffered packet segments. */
182 int ogg2_stream_pageout(ogg2_stream_state
*os
, ogg2_page
*og
){
188 /* if the incoming page is still valid (and thus unconsumed),
189 release it to prevent a leak */
190 ogg2_page_release(og
);
192 /* is there a page waiting to come back? */
193 if(!os
->header_tail
) return 0;
195 /* get header and body sizes */
196 ogg2byte_init(&ob
,os
->header_tail
,0);
197 header_bytes
=ogg2byte_read1(&ob
,26)+27;
198 for(i
=27;i
<header_bytes
;i
++)
199 body_bytes
+=ogg2byte_read1(&ob
,i
);
201 /* split page references out of the fifos */
203 og
->header
=ogg2_buffer_split(&os
->header_tail
,&os
->header_head
,header_bytes
);
204 og
->header_len
=header_bytes
;
205 og
->body
=ogg2_buffer_split(&os
->body_tail
,&os
->body_head
,body_bytes
);
206 og
->body_len
=body_bytes
;
209 ogg2_page_checksum_set(og
);
211 os
->header_tail
=ogg2_buffer_pretruncate(os
->header_tail
,header_bytes
);
212 os
->body_tail
=ogg2_buffer_pretruncate(os
->body_tail
,body_bytes
);
213 if(!os
->header_tail
)os
->header_head
=0;
214 if(!os
->body_tail
)os
->body_head
=0;
219 /* This will flush remaining packets into a page (returning nonzero),
220 even if there is not enough data to trigger a flush normally
221 (undersized page). If there are no packets or partial packets to
222 flush, ogg2_stream_flush returns 0. Note that ogg2_stream_flush will
223 try to flush a normal sized page like ogg2_stream_pageout; a call to
224 ogg2_stream_flush does not guarantee that all packets have flushed.
225 Only a return value of 0 from ogg2_stream_flush indicates all packet
226 data is flushed into pages.
228 since ogg2_stream_flush will flush the last page in a stream even if
229 it's undersized, you almost certainly want to use ogg2_stream_pageout
230 (and *not* ogg2_stream_flush) unless you specifically need to flush
231 an page regardless of size in the middle of a stream. */
233 int ogg2_stream_flush(ogg2_stream_state
*os
,ogg2_page
*og
){
235 /* If there's no page already waiting for output, flush a partial
236 page... assuming we have one */
237 if(!os
->header_tail
)_packet_flush(os
,0);
238 return ogg2_stream_pageout(os
,og
);
242 int ogg2_stream_eos(ogg2_stream_state
*os
){
246 /* DECODING PRIMITIVES: packet streaming layer **********************/
248 #define FINFLAG 0x80000000UL
249 #define FINMASK 0x7fffffffUL
251 static void _next_lace(ogg2byte_buffer
*ob
,ogg2_stream_state
*os
){
252 /* search ahead one lace */
253 os
->body_fill_next
=0;
254 while(os
->laceptr
<os
->lacing_fill
){
255 int val
=ogg2byte_read1(ob
,27+os
->laceptr
++);
256 os
->body_fill_next
+=val
;
258 os
->body_fill_next
|=FINFLAG
;
265 /* sync and reporting within a logical stream uses a flagging system
266 to improve the utility of the information coming back. There are
267 two basic problems a stream can run into; missing pages (a hole in
268 the page sequence numbering), and malformed pages such that
269 spanning isn't handled properly. Both need to be reported.
271 OGG_EHOLE happens when a page is out of sequence. However, this
272 can be a natural case after seeking or reset and we want to
273 suppress the error in this case. Nor shuld the error be reported
274 redundantly. We need to *set* the hole flag (see below), but we
275 don't want to report it. 0==unset. 1==set, 2==set and report.
277 OGG_ESPAN happens when packet span is indicated but there's no
278 spanning packet data, or there's spanning packet data and no
279 declared span. Naturally, this error should also not be
280 mistriggered due to seek or reset, or reported redundantly. */
282 static void _span_queued_page(ogg2_stream_state
*os
){
283 while( !(os
->body_fill
&FINFLAG
) ){
285 if(!os
->header_tail
)break;
287 /* first flush out preceeding page header (if any). Body is
288 flushed as it's consumed, so that's not done here. */
290 if(os
->lacing_fill
>=0)
291 os
->header_tail
=ogg2_buffer_pretruncate(os
->header_tail
,
298 if(!os
->header_tail
){
303 /* process/prepare next page, if any */
305 ogg2_page og
; /* only for parsing header values */
309 og
.header
=os
->header_tail
; /* only for parsing header values */
310 pageno
=ogg2_page_pageno(&og
);
312 ogg2byte_init(&ob
,os
->header_tail
,0);
313 os
->lacing_fill
=ogg2byte_read1(&ob
,26);
315 /* are we in sequence? */
316 if(pageno
!=os
->pageno
){
317 if(os
->pageno
==-1) /* indicates seek or reset */
318 os
->holeflag
=1; /* set for internal use */
320 os
->holeflag
=2; /* set for external reporting */
322 os
->body_tail
=ogg2_buffer_pretruncate(os
->body_tail
,
324 if(os
->body_tail
==0)os
->body_head
=0;
329 if(ogg2_page_continued(&og
)){
331 if(os
->body_fill
==0){
332 /* continued packet, but no preceeding data to continue */
333 /* dump the first partial packet on the page */
336 ogg2_buffer_pretruncate(os
->body_tail
,os
->body_fill_next
&FINMASK
);
337 if(os
->body_tail
==0)os
->body_head
=0;
339 if(!os
->spanflag
&& !os
->holeflag
)os
->spanflag
=2;
344 /* preceeding data to continue, but not a continued page */
346 os
->body_tail
=ogg2_buffer_pretruncate(os
->body_tail
,
348 if(os
->body_tail
==0)os
->body_head
=0;
352 if(!os
->spanflag
&& !os
->holeflag
)os
->spanflag
=2;
356 if(os
->laceptr
<os
->lacing_fill
){
357 os
->granulepos
=ogg2_page_granulepos(&og
);
359 /* get current packet size & flag */
361 os
->body_fill
+=os
->body_fill_next
; /* addition handles the flag fine;
362 unsigned on purpose */
363 /* ...and next packet size & flag */
369 os
->e_o_s
=ogg2_page_eos(&og
);
370 os
->b_o_s
=ogg2_page_bos(&og
);
376 /* add the incoming page to the stream state; we decompose the page
377 into packet segments here as well. */
379 int ogg2_stream_pagein(ogg2_stream_state
*os
, ogg2_page
*og
){
381 int serialno
=ogg2_page_serialno(og
);
382 int version
=ogg2_page_version(og
);
384 /* check the serial number */
385 if(serialno
!=os
->serialno
){
386 ogg2_page_release(og
);
390 ogg2_page_release(og
);
391 return OGG2_EVERSION
;
396 os
->body_tail
=og
->body
;
397 os
->body_head
=ogg2_buffer_walk(og
->body
);
399 os
->body_head
=ogg2_buffer_cat(os
->body_head
,og
->body
);
401 if(!os
->header_tail
){
402 os
->header_tail
=og
->header
;
403 os
->header_head
=ogg2_buffer_walk(og
->header
);
406 os
->header_head
=ogg2_buffer_cat(os
->header_head
,og
->header
);
409 memset(og
,0,sizeof(*og
));
413 int ogg2_stream_reset(ogg2_stream_state
*os
){
415 ogg2_buffer_release(os
->header_tail
);
416 ogg2_buffer_release(os
->body_tail
);
417 os
->header_tail
=os
->header_head
=0;
418 os
->body_tail
=os
->body_head
=0;
428 ogg2byte_clear(&os
->header_build
);
435 os
->body_fill_next
=0;
440 int ogg2_stream_reset_serialno(ogg2_stream_state
*os
,int serialno
){
441 ogg2_stream_reset(os
);
442 os
->serialno
=serialno
;
446 static int _packetout(ogg2_stream_state
*os
,ogg2_packet
*op
,int adv
){
448 /* if the incoming packet is a valid reference, release it such that
449 we don't leak the memory */
450 ogg2_packet_release(op
);
452 /* buffer packets for return */
453 _span_queued_page(os
);
456 int temp
=os
->holeflag
;
467 int temp
=os
->spanflag
;
478 if(!(os
->body_fill
&FINFLAG
)) return 0;
479 if(!op
&& !adv
)return 1; /* just using peek as an inexpensive way
480 to ask if there's a whole packet
484 if(os
->e_o_s
&& os
->body_fill_next
==0)
490 /* Discontinuous Mode */
492 if(os
->packets
==0)op
->end_granule
=os
->granulepos
;
493 else op
->end_granule
=-1;
495 if(os
->packets
==1)op
->end_granule
=os
->granulepos
;
496 else op
->end_granule
=-1;
499 /* Continuous Mode */
500 if( (os
->body_fill
&FINFLAG
) && !(os
->body_fill_next
&FINFLAG
) )
501 op
->end_granule
=os
->granulepos
;
507 op
->packetno
=os
->packetno
;
512 ogg2byte_init(&ob
,os
->header_tail
,0);
514 /* split the body contents off */
516 op
->packet
=ogg2_buffer_split(&os
->body_tail
,&os
->body_head
,os
->body_fill
&FINMASK
);
517 op
->bytes
=os
->body_fill
&FINMASK
;
519 os
->body_tail
=ogg2_buffer_pretruncate(os
->body_tail
,os
->body_fill
&FINMASK
);
520 if(os
->body_tail
==0)os
->body_head
=0;
523 /* update lacing pointers */
524 os
->body_fill
=os
->body_fill_next
;
528 op
->packet
=ogg2_buffer_sub(os
->body_tail
,0,os
->body_fill
&FINMASK
);
529 op
->bytes
=os
->body_fill
&FINMASK
;
541 int ogg2_stream_packetout(ogg2_stream_state
*os
,ogg2_packet
*op
){
542 return _packetout(os
,op
,1);
545 int ogg2_stream_packetpeek(ogg2_stream_state
*os
,ogg2_packet
*op
){
546 return _packetout(os
,op
,0);
549 int ogg2_packet_release(ogg2_packet
*op
) {
551 ogg2_buffer_release(op
->packet
);
552 memset(op
, 0, sizeof(*op
));
557 int ogg2_page_release(ogg2_page
*og
) {
559 ogg2_buffer_release(og
->header
);
560 ogg2_buffer_release(og
->body
);
561 memset(og
, 0, sizeof(*og
));
569 ogg2_stream_state
*os_en
, *os_de
;
571 ogg2_buffer_state
*bs
;
573 void checkpacket(ogg2_packet
*op
,int len
, int no
, int pos
){
575 static int sequence
=0;
579 if(ogg2_buffer_length(op
->packet
)!=len
){
580 fprintf(stderr
,"incorrect packet length!\n");
583 if(op
->end_granule
!=pos
){
584 fprintf(stderr
,"incorrect packet position!\n");
588 /* packet number just follows sequence/gap; adjust the input number
598 if(op
->packetno
!=sequence
){
599 fprintf(stderr
,"incorrect packet sequence %ld != %d\n",
600 (long)(op
->packetno
),sequence
);
605 ogg2byte_init(&ob
,op
->packet
,0);
606 for(j
=0;j
<ogg2_buffer_length(op
->packet
);j
++)
607 if(ogg2byte_read1(&ob
,j
)!=((j
+no
)&0xff)){
608 fprintf(stderr
,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n",
609 j
,ogg2byte_read1(&ob
,j
),(j
+no
)&0xff);
614 void check_page(unsigned char *data
,const int *header
,ogg2_page
*og
){
618 /* test buffer lengths */
619 long header_len
=header
[26]+27;
622 for(j
=27;j
<header_len
;j
++)
625 if(header_len
!=ogg2_buffer_length(og
->header
)){
626 fprintf(stderr
,"page header length mismatch: %ld correct, buffer is %ld\n",
627 header_len
,ogg2_buffer_length(og
->header
));
630 if(body_len
!=ogg2_buffer_length(og
->body
)){
631 fprintf(stderr
,"page body length mismatch: %ld correct, buffer is %ld\n",
632 body_len
,ogg2_buffer_length(og
->body
));
637 ogg2byte_init(&ob
,og
->body
,0);
638 for(j
=0;j
<ogg2_buffer_length(og
->body
);j
++)
639 if(ogg2byte_read1(&ob
,j
)!=data
[j
]){
640 fprintf(stderr
,"body data mismatch (2) at pos %ld: %x!=%x!\n\n",
641 j
,data
[j
],ogg2byte_read1(&ob
,j
));
646 ogg2byte_init(&ob
,og
->header
,0);
647 for(j
=0;j
<ogg2_buffer_length(og
->header
);j
++){
648 if(ogg2byte_read1(&ob
,j
)!=header
[j
]){
649 fprintf(stderr
,"header content mismatch at pos %ld:\n",j
);
650 for(j
=0;j
<header
[26]+27;j
++)
651 fprintf(stderr
," (%ld)%02x:%02x",j
,header
[j
],ogg2byte_read1(&ob
,j
));
652 fprintf(stderr
,"\n");
656 if(ogg2_buffer_length(og
->header
)!=header
[26]+27){
657 fprintf(stderr
,"header length incorrect! (%ld!=%d)\n",
658 ogg2_buffer_length(og
->header
),header
[26]+27);
663 void print_header(ogg2_page
*og
){
666 ogg2byte_init(&ob
,og
->header
,0);
668 fprintf(stderr
,"\nHEADER:\n");
669 fprintf(stderr
," capture: %c %c %c %c version: %d flags: %x\n",
670 ogg2byte_read1(&ob
,0),ogg2byte_read1(&ob
,1),
671 ogg2byte_read1(&ob
,2),ogg2byte_read1(&ob
,3),
672 (int)ogg2byte_read1(&ob
,4),(int)ogg2byte_read1(&ob
,5));
674 fprintf(stderr
," granulepos: %08x%08x serialno: %x pageno: %ld\n",
675 ogg2byte_read4(&ob
,10),ogg2byte_read4(&ob
,6),
676 ogg2byte_read4(&ob
,14),
677 (long)ogg2byte_read4(&ob
,18));
679 fprintf(stderr
," checksum: %08x\n segments: %d (",
680 ogg2byte_read4(&ob
,22),(int)ogg2byte_read1(&ob
,26));
682 for(j
=27;j
<ogg2_buffer_length(og
->header
);j
++)
683 fprintf(stderr
,"%d ",(int)ogg2byte_read1(&ob
,j
));
684 fprintf(stderr
,")\n\n");
688 fprintf(stderr
,"error!\n");
693 const int head1_0
[] = {0x4f,0x67,0x67,0x53,0,0x06,
694 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
695 0x01,0x02,0x03,0x04,0,0,0,0,
700 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
701 const int head1_1
[] = {0x4f,0x67,0x67,0x53,0,0x02,
702 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
703 0x01,0x02,0x03,0x04,0,0,0,0,
707 const int head2_1
[] = {0x4f,0x67,0x67,0x53,0,0x04,
708 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
709 0x01,0x02,0x03,0x04,1,0,0,0,
712 254,255,0,255,1,255,245,255,255,0,
715 /* nil packets; beginning,middle,end */
716 const int head1_2
[] = {0x4f,0x67,0x67,0x53,0,0x02,
717 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
718 0x01,0x02,0x03,0x04,0,0,0,0,
722 const int head2_2
[] = {0x4f,0x67,0x67,0x53,0,0x04,
723 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
724 0x01,0x02,0x03,0x04,1,0,0,0,
727 17,254,255,0,0,255,1,0,255,245,255,255,0,
730 /* large initial packet */
731 const int head1_3
[] = {0x4f,0x67,0x67,0x53,0,0x02,
732 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
733 0x01,0x02,0x03,0x04,0,0,0,0,
736 255,255,255,255,255,255,255,255,
737 255,255,255,255,255,255,255,255,255,10};
739 const int head2_3
[] = {0x4f,0x67,0x67,0x53,0,0x04,
740 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
741 0x01,0x02,0x03,0x04,1,0,0,0,
747 /* continuing packet test */
748 const int head1_4
[] = {0x4f,0x67,0x67,0x53,0,0x02,
749 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
750 0x01,0x02,0x03,0x04,0,0,0,0,
755 const int head2_4
[] = {0x4f,0x67,0x67,0x53,0,0x00,
756 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
757 0x01,0x02,0x03,0x04,1,0,0,0,
760 255,255,255,255,255,255,255,255,
761 255,255,255,255,255,255,255,255,255};
763 const int head3_4
[] = {0x4f,0x67,0x67,0x53,0,0x05,
764 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
765 0x01,0x02,0x03,0x04,2,0,0,0,
771 /* page with the 255 segment limit */
772 const int head1_5
[] = {0x4f,0x67,0x67,0x53,0,0x02,
773 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
774 0x01,0x02,0x03,0x04,0,0,0,0,
779 const int head2_5
[] = {0x4f,0x67,0x67,0x53,0,0x00,
780 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
781 0x01,0x02,0x03,0x04,1,0,0,0,
784 10,10,10,10,10,10,10,10,
785 10,10,10,10,10,10,10,10,
786 10,10,10,10,10,10,10,10,
787 10,10,10,10,10,10,10,10,
788 10,10,10,10,10,10,10,10,
789 10,10,10,10,10,10,10,10,
790 10,10,10,10,10,10,10,10,
791 10,10,10,10,10,10,10,10,
792 10,10,10,10,10,10,10,10,
793 10,10,10,10,10,10,10,10,
794 10,10,10,10,10,10,10,10,
795 10,10,10,10,10,10,10,10,
796 10,10,10,10,10,10,10,10,
797 10,10,10,10,10,10,10,10,
798 10,10,10,10,10,10,10,10,
799 10,10,10,10,10,10,10,10,
800 10,10,10,10,10,10,10,10,
801 10,10,10,10,10,10,10,10,
802 10,10,10,10,10,10,10,10,
803 10,10,10,10,10,10,10,10,
804 10,10,10,10,10,10,10,10,
805 10,10,10,10,10,10,10,10,
806 10,10,10,10,10,10,10,10,
807 10,10,10,10,10,10,10,10,
808 10,10,10,10,10,10,10,10,
809 10,10,10,10,10,10,10,10,
810 10,10,10,10,10,10,10,10,
811 10,10,10,10,10,10,10,10,
812 10,10,10,10,10,10,10,10,
813 10,10,10,10,10,10,10,10,
814 10,10,10,10,10,10,10,10,
815 10,10,10,10,10,10,10};
817 const int head3_5
[] = {0x4f,0x67,0x67,0x53,0,0x04,
818 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
819 0x01,0x02,0x03,0x04,2,0,0,0,
825 /* packet that overspans over an entire page */
826 const int head1_6
[] = {0x4f,0x67,0x67,0x53,0,0x02,
827 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
828 0x01,0x02,0x03,0x04,0,0,0,0,
833 const int head2_6
[] = {0x4f,0x67,0x67,0x53,0,0x00,
834 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
835 0x01,0x02,0x03,0x04,1,0,0,0,
838 100,255,255,255,255,255,255,255,255,
839 255,255,255,255,255,255,255,255};
841 const int head3_6
[] = {0x4f,0x67,0x67,0x53,0,0x01,
842 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
843 0x01,0x02,0x03,0x04,2,0,0,0,
846 255,255,255,255,255,255,255,255,
847 255,255,255,255,255,255,255,255,255};
849 const int head4_6
[] = {0x4f,0x67,0x67,0x53,0,0x05,
850 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
851 0x01,0x02,0x03,0x04,3,0,0,0,
854 255,255,75,255,4,255,0};
856 /* packet that overspans over an entire page */
857 const int head1_7
[] = {0x4f,0x67,0x67,0x53,0,0x02,
858 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
859 0x01,0x02,0x03,0x04,0,0,0,0,
864 const int head2_7
[] = {0x4f,0x67,0x67,0x53,0,0x00,
865 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
866 0x01,0x02,0x03,0x04,1,0,0,0,
869 100,255,255,255,255,255,255,255,255,
870 255,255,255,255,255,255,255,255};
872 const int head3_7
[] = {0x4f,0x67,0x67,0x53,0,0x05,
873 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
874 0x01,0x02,0x03,0x04,2,0,0,0,
878 void bufcpy(void *data
,ogg2_reference
*or){
880 memcpy(data
,or->buffer
->data
+or->begin
,or->length
);
886 void bufcpy2(void *data
,ogg2_reference
*or,int begin
){
888 if(or->length
-begin
>0){
889 memcpy(data
,or->buffer
->data
+or->begin
+begin
,or->length
-begin
);
890 data
+=or->length
-begin
;
897 int bufcmp(void *data
,ogg2_reference
*or){
899 int ret
=memcmp(data
,or->buffer
->data
+or->begin
,or->length
);
907 void test_pack(const int *pl
, const int **headers
){
908 unsigned char *data
=_ogg_malloc(1024*1024); /* for scripted test cases only */
913 long granulepos
=7,pageno
=0;
914 int i
,j
,packets
,pageout
=0;
918 for(packets
=0;;packets
++)if(pl
[packets
]==-1)break;
920 for(i
=0;i
<packets
;i
++){
921 /* construct a test packet */
922 ogg2_packet op
={0,0,0,0,0,0};
925 op
.packet
=ogg2_buffer_alloc(bs
,len
);
926 op
.e_o_s
=(pl
[i
+1]<0?1:0);
927 op
.granulepos
=granulepos
;
931 for(j
=0;j
<len
;j
++)data
[inptr
+j
]=i
+j
;
932 memcpy(op
.packet
->buffer
->data
,data
+inptr
,len
);
933 op
.packet
->length
=len
;
936 /* submit the test packet */
937 ogg2_stream_packetin(os_en
,&op
);
939 /* retrieve any finished pages */
941 ogg2_page og
={0,0,0,0};
943 while(ogg2_stream_pageout(os_en
,&og
)){
944 /* We have a page. Check it carefully */
946 fprintf(stderr
,"%ld, ",pageno
);
948 if(headers
[pageno
]==NULL
){
949 fprintf(stderr
,"coded too many pages!\n");
953 check_page(data
+outptr
,headers
[pageno
],&og
);
955 outptr
+=ogg2_buffer_length(og
.body
);
958 /* have a complete page; submit it to sync/decode */
961 ogg2_page og_de
={0,0,0,0};
962 ogg2_packet op_de
={0,0,0,0,0,0},op_de2
={0,0,0,0,0,0};
963 int blen
=ogg2_buffer_length(og
.header
)+ogg2_buffer_length(og
.body
);
964 char *buf
=ogg2_sync_bufferin(oy
,blen
);
965 bufcpy(buf
,og
.header
);
966 bufcpy(buf
+ogg2_buffer_length(og
.header
),og
.body
);
967 ogg2_sync_wrote(oy
,blen
);
969 while(ogg2_sync_pageout(oy
,&og_de
)>0){
970 /* got a page. Happy happy. Verify that it's good. */
972 check_page(data
+deptr
,headers
[pageout
],&og_de
);
973 deptr
+=ogg2_buffer_length(og_de
.body
);
976 /* submit it to deconstitution */
977 ogg2_stream_pagein(os_de
,&og_de
);
980 while(ogg2_stream_packetpeek(os_de
,NULL
)>0){
981 ogg2_stream_packetpeek(os_de
,&op_de2
);
982 ogg2_stream_packetout(os_de
,&op_de
); /* just catching them all */
984 /* verify the packets! */
986 if(bufcmp(data
+depacket
,op_de
.packet
)){
987 fprintf(stderr
,"packet data mismatch in decode! pos=%ld\n",
991 if(bufcmp(data
+depacket
,op_de2
.packet
)){
992 fprintf(stderr
,"packet data mismatch in peek! pos=%ld\n",
997 if(bosflag
==0 && op_de
.b_o_s
==0){
998 fprintf(stderr
,"b_o_s flag not set on packet!\n");
1001 if(bosflag
==0 && op_de2
.b_o_s
==0){
1002 fprintf(stderr
,"b_o_s flag not set on peek!\n");
1005 if(bosflag
&& op_de
.b_o_s
){
1006 fprintf(stderr
,"b_o_s flag incorrectly set on packet!\n");
1009 if(bosflag
&& op_de2
.b_o_s
){
1010 fprintf(stderr
,"b_o_s flag incorrectly set on peek!\n");
1014 depacket
+=ogg2_buffer_length(op_de
.packet
);
1016 /* check eos flag */
1018 fprintf(stderr
,"Multiple decoded packets with eos flag!\n");
1022 if(op_de
.e_o_s
)eosflag
=1;
1023 if(op_de
.e_o_s
!=op_de2
.e_o_s
){
1024 fprintf(stderr
,"packet/peek eosflag mismatch!\n");
1027 /* check granulepos flag */
1028 if(op_de
.granulepos
!=-1){
1029 fprintf(stderr
," granule:%ld ",(long)op_de
.granulepos
);
1031 if(op_de
.granulepos
!=op_de2
.granulepos
){
1032 fprintf(stderr
,"packet/peek granpos mismatch!\n");
1036 ogg2_packet_release(&op_de
);
1037 ogg2_packet_release(&op_de2
);
1041 ogg2_page_release(&og
);
1046 if(headers
[pageno
]!=NULL
){
1047 fprintf(stderr
,"did not write last page!\n");
1050 if(headers
[pageout
]!=NULL
){
1051 fprintf(stderr
,"did not decode last page!\n");
1055 fprintf(stderr
,"encoded page data incomplete!\n");
1059 fprintf(stderr
,"decoded page data incomplete!\n");
1062 if(inptr
!=depacket
){
1063 fprintf(stderr
,"decoded packet data incomplete!\n");
1067 fprintf(stderr
,"Never got a packet with EOS set!\n");
1070 fprintf(stderr
,"ok.\n");
1072 ogg2_stream_reset(os_en
);
1073 ogg2_stream_reset(os_de
);
1074 ogg2_sync_reset(oy
);
1080 os_en
=ogg2_stream_create(0x04030201);
1081 os_de
=ogg2_stream_create(0x04030201);
1082 oy
=ogg2_sync_create();
1083 bs
=ogg2_buffer_create();
1085 /* Exercise each code path in the framing code. Also verify that
1086 the checksums are working. */
1090 const int packets
[]={17, -1};
1091 const int *headret
[]={head1_0
,NULL
};
1093 fprintf(stderr
,"testing single page encoding... ");
1094 test_pack(packets
,headret
);
1098 /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1099 const int packets
[]={17, 254, 255, 256, 500, 510, 600, -1};
1100 const int *headret
[]={head1_1
,head2_1
,NULL
};
1102 fprintf(stderr
,"testing basic page encoding... ");
1103 test_pack(packets
,headret
);
1107 /* nil packets; beginning,middle,end */
1108 const int packets
[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
1109 const int *headret
[]={head1_2
,head2_2
,NULL
};
1111 fprintf(stderr
,"testing basic nil packets... ");
1112 test_pack(packets
,headret
);
1116 /* large initial packet */
1117 const int packets
[]={4345,259,255,-1};
1118 const int *headret
[]={head1_3
,head2_3
,NULL
};
1120 fprintf(stderr
,"testing initial-packet lacing > 4k... ");
1121 test_pack(packets
,headret
);
1125 /* continuing packet test */
1126 const int packets
[]={0,4345,259,255,-1};
1127 const int *headret
[]={head1_4
,head2_4
,head3_4
,NULL
};
1129 fprintf(stderr
,"testing single packet page span... ");
1130 test_pack(packets
,headret
);
1133 /* page with the 255 segment limit */
1136 const int packets
[]={0,10,10,10,10,10,10,10,10,
1137 10,10,10,10,10,10,10,10,
1138 10,10,10,10,10,10,10,10,
1139 10,10,10,10,10,10,10,10,
1140 10,10,10,10,10,10,10,10,
1141 10,10,10,10,10,10,10,10,
1142 10,10,10,10,10,10,10,10,
1143 10,10,10,10,10,10,10,10,
1144 10,10,10,10,10,10,10,10,
1145 10,10,10,10,10,10,10,10,
1146 10,10,10,10,10,10,10,10,
1147 10,10,10,10,10,10,10,10,
1148 10,10,10,10,10,10,10,10,
1149 10,10,10,10,10,10,10,10,
1150 10,10,10,10,10,10,10,10,
1151 10,10,10,10,10,10,10,10,
1152 10,10,10,10,10,10,10,10,
1153 10,10,10,10,10,10,10,10,
1154 10,10,10,10,10,10,10,10,
1155 10,10,10,10,10,10,10,10,
1156 10,10,10,10,10,10,10,10,
1157 10,10,10,10,10,10,10,10,
1158 10,10,10,10,10,10,10,10,
1159 10,10,10,10,10,10,10,10,
1160 10,10,10,10,10,10,10,10,
1161 10,10,10,10,10,10,10,10,
1162 10,10,10,10,10,10,10,10,
1163 10,10,10,10,10,10,10,10,
1164 10,10,10,10,10,10,10,10,
1165 10,10,10,10,10,10,10,10,
1166 10,10,10,10,10,10,10,10,
1167 10,10,10,10,10,10,10,50,-1};
1168 const int *headret
[]={head1_5
,head2_5
,head3_5
,NULL
};
1170 fprintf(stderr
,"testing max packet segments... ");
1171 test_pack(packets
,headret
);
1175 /* packet that overspans over an entire page */
1176 const int packets
[]={0,100,9000,259,255,-1};
1177 const int *headret
[]={head1_6
,head2_6
,head3_6
,head4_6
,NULL
};
1179 fprintf(stderr
,"testing very large packets... ");
1180 test_pack(packets
,headret
);
1184 /* term only page. why not? */
1185 const int packets
[]={0,100,4080,-1};
1186 const int *headret
[]={head1_7
,head2_7
,head3_7
,NULL
};
1188 fprintf(stderr
,"testing zero data page (1 nil packet)... ");
1189 test_pack(packets
,headret
);
1195 /* build a bunch of pages for testing */
1196 unsigned char *data
=_ogg_malloc(1024*1024);
1197 int pl
[]={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1};
1200 memset(og
,0,sizeof(og
));
1202 ogg2_stream_reset(os_en
);
1204 for(i
=0;pl
[i
]!=-1;i
++){
1208 op
.packet
=ogg2_buffer_alloc(bs
,len
);
1209 op
.e_o_s
=(pl
[i
+1]<0?1:0);
1210 op
.granulepos
=(i
+1)*1000;
1212 for(j
=0;j
<len
;j
++)data
[inptr
+j
]=i
+j
;
1213 memcpy(op
.packet
->buffer
->data
,data
+inptr
,len
);
1214 op
.packet
->length
=len
;
1216 ogg2_stream_packetin(os_en
,&op
);
1222 /* retrieve finished pages */
1224 if(ogg2_stream_pageout(os_en
,&og
[i
])==0){
1225 fprintf(stderr
,"Too few pages output building sync tests!\n");
1231 if(ogg2_stream_pageout(os_en
,&temp
)>0){
1232 fprintf(stderr
,"Too many pages output building sync tests!\n");
1237 /* Test lost pages on pagein/packetout: no rollback */
1239 ogg2_page temp
={0,0,0,0};
1240 ogg2_packet test
={0,0,0,0,0,0};
1242 fprintf(stderr
,"Testing loss of pages... ");
1244 ogg2_sync_reset(oy
);
1245 ogg2_stream_reset(os_de
);
1247 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[i
].header
)),
1249 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[i
].header
));
1250 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[i
].body
)),
1252 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[i
].body
));
1255 ogg2_sync_pageout(oy
,&temp
);
1256 ogg2_stream_pagein(os_de
,&temp
);
1257 ogg2_sync_pageout(oy
,&temp
);
1258 ogg2_stream_pagein(os_de
,&temp
);
1259 ogg2_sync_pageout(oy
,&temp
);
1260 ogg2_page_release(&temp
);/* skip */
1261 ogg2_sync_pageout(oy
,&temp
);
1262 ogg2_stream_pagein(os_de
,&temp
);
1264 /* do we get the expected results/packets? */
1266 if(ogg2_stream_packetout(os_de
,&test
)!=1)error();
1267 checkpacket(&test
,0,0,0);
1268 ogg2_packet_release(&test
);
1269 if(ogg2_stream_packetout(os_de
,&test
)!=1)error();
1270 checkpacket(&test
,100,1,-1);
1271 ogg2_packet_release(&test
);
1272 if(ogg2_stream_packetout(os_de
,&test
)!=1)error();
1273 checkpacket(&test
,4079,2,3000);
1274 ogg2_packet_release(&test
);
1275 if(ogg2_stream_packetout(os_de
,&test
)!=OGG2_HOLE
){
1276 fprintf(stderr
,"Error: loss of page did not return error\n");
1279 ogg2_packet_release(&test
);
1280 if(ogg2_stream_packetout(os_de
,&test
)!=1)error();
1281 checkpacket(&test
,76,5,-1);
1282 ogg2_packet_release(&test
);
1283 if(ogg2_stream_packetout(os_de
,&test
)!=1)error();
1284 checkpacket(&test
,34,6,-1);
1285 ogg2_packet_release(&test
);
1286 fprintf(stderr
,"ok.\n");
1289 /* Test lost pages on pagein/packetout: rollback with continuation */
1291 ogg2_page temp
={0,0,0,0};
1292 ogg2_packet test
={0,0,0,0,0,0};
1294 fprintf(stderr
,"Testing loss of pages (rollback required)... ");
1296 ogg2_sync_reset(oy
);
1297 ogg2_stream_reset(os_de
);
1299 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[i
].header
)),
1301 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[i
].header
));
1302 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[i
].body
)),
1304 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[i
].body
));
1307 ogg2_sync_pageout(oy
,&temp
);
1308 ogg2_stream_pagein(os_de
,&temp
);
1309 ogg2_sync_pageout(oy
,&temp
);
1310 ogg2_stream_pagein(os_de
,&temp
);
1311 ogg2_sync_pageout(oy
,&temp
);
1312 ogg2_stream_pagein(os_de
,&temp
);
1313 ogg2_sync_pageout(oy
,&temp
);
1314 ogg2_page_release(&temp
);/* skip */
1315 ogg2_sync_pageout(oy
,&temp
);
1316 ogg2_stream_pagein(os_de
,&temp
);
1318 /* do we get the expected results/packets? */
1320 if(ogg2_stream_packetout(os_de
,&test
)!=1)error();
1321 checkpacket(&test
,0,0,0);
1322 ogg2_packet_release(&test
);
1323 if(ogg2_stream_packetout(os_de
,&test
)!=1)error();
1324 checkpacket(&test
,100,1,-1);
1325 ogg2_packet_release(&test
);
1326 if(ogg2_stream_packetout(os_de
,&test
)!=1)error();
1327 checkpacket(&test
,4079,2,3000);
1328 ogg2_packet_release(&test
);
1329 if(ogg2_stream_packetout(os_de
,&test
)!=1)error();
1330 checkpacket(&test
,2956,3,4000);
1331 ogg2_packet_release(&test
);
1332 if(ogg2_stream_packetout(os_de
,&test
)!=OGG2_HOLE
){
1333 fprintf(stderr
,"Error: loss of page did not return error\n");
1336 ogg2_packet_release(&test
);
1337 if(ogg2_stream_packetout(os_de
,&test
)!=1)error();
1338 checkpacket(&test
,300,13,14000);
1339 ogg2_packet_release(&test
);
1340 fprintf(stderr
,"ok.\n");
1343 /* the rest only test sync */
1345 ogg2_page og_de
={0,0,0,0};
1346 /* Test fractional page inputs: incomplete capture */
1347 fprintf(stderr
,"Testing sync on partial inputs... ");
1348 ogg2_sync_reset(oy
);
1349 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].header
)),og
[1].header
);
1350 ogg2_sync_wrote(oy
,3);
1351 if(ogg2_sync_pageout(oy
,&og_de
)>0)error();
1352 ogg2_page_release(&og_de
);
1354 /* Test fractional page inputs: incomplete fixed header */
1355 bufcpy2(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].header
)),og
[1].header
,3);
1356 ogg2_sync_wrote(oy
,20);
1357 if(ogg2_sync_pageout(oy
,&og_de
)>0)error();
1358 ogg2_page_release(&og_de
);
1360 /* Test fractional page inputs: incomplete header */
1361 bufcpy2(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].header
)),og
[1].header
,23);
1362 ogg2_sync_wrote(oy
,5);
1363 if(ogg2_sync_pageout(oy
,&og_de
)>0)error();
1364 ogg2_page_release(&og_de
);
1366 /* Test fractional page inputs: incomplete body */
1368 bufcpy2(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].header
)),og
[1].header
,28);
1369 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[1].header
)-28);
1370 if(ogg2_sync_pageout(oy
,&og_de
)>0)error();
1371 ogg2_page_release(&og_de
);
1373 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].body
)),og
[1].body
);
1374 ogg2_sync_wrote(oy
,1000);
1375 if(ogg2_sync_pageout(oy
,&og_de
)>0)error();
1376 ogg2_page_release(&og_de
);
1378 bufcpy2(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].body
)),og
[1].body
,1000);
1379 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[1].body
)-1000);
1380 if(ogg2_sync_pageout(oy
,&og_de
)<=0)error();
1381 ogg2_page_release(&og_de
);
1383 fprintf(stderr
,"ok.\n");
1386 /* Test fractional page inputs: page + incomplete capture */
1388 ogg2_page og_de
={0,0,0,0};
1389 fprintf(stderr
,"Testing sync on 1+partial inputs... ");
1390 ogg2_sync_reset(oy
);
1392 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].header
)),og
[1].header
);
1393 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[1].header
));
1395 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].body
)),og
[1].body
);
1396 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[1].body
));
1398 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].header
)),og
[1].header
);
1399 ogg2_sync_wrote(oy
,20);
1400 if(ogg2_sync_pageout(oy
,&og_de
)<=0)error();
1401 ogg2_page_release(&og_de
);
1402 if(ogg2_sync_pageout(oy
,&og_de
)>0)error();
1403 ogg2_page_release(&og_de
);
1405 bufcpy2(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].header
)),og
[1].header
,20);
1406 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[1].header
)-20);
1408 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].body
)),og
[1].body
);
1409 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[1].body
));
1411 if(ogg2_sync_pageout(oy
,&og_de
)<=0)error();
1412 ogg2_page_release(&og_de
);
1414 fprintf(stderr
,"ok.\n");
1417 /* Test recapture: garbage + page */
1419 ogg2_page og_de
={0,0,0,0};
1420 fprintf(stderr
,"Testing search for capture... ");
1421 ogg2_sync_reset(oy
);
1424 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].body
)),og
[1].body
);
1425 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[1].body
));
1427 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].header
)),og
[1].header
);
1428 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[1].header
));
1430 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].body
)),og
[1].body
);
1431 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[1].body
));
1433 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[2].header
)),og
[2].header
);
1434 ogg2_sync_wrote(oy
,20);
1436 if(ogg2_sync_pageout(oy
,&og_de
)>0)error();
1437 ogg2_page_release(&og_de
);
1438 if(ogg2_sync_pageout(oy
,&og_de
)<=0)error();
1439 ogg2_page_release(&og_de
);
1440 if(ogg2_sync_pageout(oy
,&og_de
)>0)error();
1441 ogg2_page_release(&og_de
);
1443 bufcpy2(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[2].header
)),og
[2].header
,20);
1444 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[2].header
)-20);
1446 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[2].body
)),og
[2].body
);
1447 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[2].body
));
1448 if(ogg2_sync_pageout(oy
,&og_de
)<=0)error();
1449 ogg2_page_release(&og_de
);
1451 fprintf(stderr
,"ok.\n");
1454 /* Test recapture: page + garbage + page */
1456 ogg2_page og_de
={0,0,0,0};
1457 fprintf(stderr
,"Testing recapture... ");
1458 ogg2_sync_reset(oy
);
1460 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].header
)),og
[1].header
);
1461 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[1].header
));
1463 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[1].body
)),og
[1].body
);
1464 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[1].body
));
1468 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[2].header
)),og
[2].header
);
1469 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[2].header
));
1471 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[2].header
)),og
[2].header
);
1472 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[2].header
));
1474 if(ogg2_sync_pageout(oy
,&og_de
)<=0)error();
1475 ogg2_page_release(&og_de
);
1477 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[2].body
)),og
[2].body
);
1478 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[2].body
)-5);
1480 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[3].header
)),og
[3].header
);
1481 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[3].header
));
1483 bufcpy(ogg2_sync_bufferin(oy
,ogg2_buffer_length(og
[3].body
)),og
[3].body
);
1484 ogg2_sync_wrote(oy
,ogg2_buffer_length(og
[3].body
));
1486 if(ogg2_sync_pageout(oy
,&og_de
)>0)error();
1487 ogg2_page_release(&og_de
);
1488 if(ogg2_sync_pageout(oy
,&og_de
)<=0)error();
1489 ogg2_page_release(&og_de
);
1491 fprintf(stderr
,"ok.\n");
1493 ogg2_stream_destroy(os_en
);
1495 ogg2_page_release(&og
[i
]);
1498 ogg2_stream_destroy(os_de
);
1499 ogg2_sync_destroy(oy
);
1501 ogg2_buffer_destroy(bs
);