gosu 0.7.45 → 0.7.46

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/COPYING +6 -11
  2. data/Gosu/{ButtonsWin.hpp → Buttons.hpp} +91 -4
  3. data/Gosu/ButtonsMac.hpp +91 -4
  4. data/Gosu/Graphics.hpp +10 -0
  5. data/Gosu/ImageData.hpp +1 -0
  6. data/Gosu/Input.hpp +2 -3
  7. data/Gosu/Version.hpp +2 -2
  8. data/Gosu/Window.hpp +1 -1
  9. data/GosuImpl/Audio/AudioToolboxFile.hpp +4 -0
  10. data/GosuImpl/Graphics/BitmapApple.mm +5 -11
  11. data/GosuImpl/Graphics/ClipRectStack.hpp +2 -2
  12. data/GosuImpl/Graphics/Common.hpp +1 -1
  13. data/GosuImpl/Graphics/DrawOpQueue.hpp +30 -29
  14. data/GosuImpl/Graphics/Graphics.cpp +2 -3
  15. data/GosuImpl/Graphics/TextMac.cpp +9 -5
  16. data/GosuImpl/Graphics/TextTouch.mm +8 -4
  17. data/GosuImpl/Graphics/Texture.cpp +4 -1
  18. data/GosuImpl/InputMac.mm +24 -45
  19. data/GosuImpl/InputX.cpp +25 -39
  20. data/GosuImpl/RubyGosu.swg +11 -0
  21. data/GosuImpl/RubyGosu_wrap.cxx +109 -40
  22. data/GosuImpl/RubyGosu_wrap.h +1 -1
  23. data/GosuImpl/TextInputWin.cpp +1 -1
  24. data/GosuImpl/TextInputX.cpp +3 -1
  25. data/GosuImpl/WinMain.cpp +3 -4
  26. data/GosuImpl/WindowMac.mm +83 -73
  27. data/GosuImpl/WindowWin.cpp +65 -58
  28. data/dependencies/libogg/AUTHORS +4 -0
  29. data/dependencies/libogg/CHANGES +70 -0
  30. data/dependencies/libogg/COPYING +28 -0
  31. data/dependencies/libogg/include/ogg/ogg.h +209 -0
  32. data/dependencies/libogg/include/ogg/os_types.h +147 -0
  33. data/dependencies/libogg/src/bitwise.c +857 -0
  34. data/dependencies/libogg/src/framing.c +2089 -0
  35. data/dependencies/libvorbis/AUTHORS +3 -0
  36. data/dependencies/libvorbis/CHANGES +126 -0
  37. data/dependencies/libvorbis/COPYING +28 -0
  38. data/dependencies/libvorbis/include/vorbis/codec.h +243 -0
  39. data/dependencies/libvorbis/include/vorbis/vorbisenc.h +436 -0
  40. data/dependencies/libvorbis/include/vorbis/vorbisfile.h +206 -0
  41. data/dependencies/libvorbis/lib/analysis.c +120 -0
  42. data/dependencies/libvorbis/lib/backends.h +144 -0
  43. data/dependencies/libvorbis/lib/barkmel.c +64 -0
  44. data/dependencies/libvorbis/lib/bitrate.c +253 -0
  45. data/dependencies/libvorbis/lib/bitrate.h +59 -0
  46. data/dependencies/libvorbis/lib/block.c +1046 -0
  47. data/dependencies/libvorbis/lib/books/coupled/res_books_51.h +12257 -0
  48. data/dependencies/libvorbis/lib/books/coupled/res_books_stereo.h +15783 -0
  49. data/dependencies/libvorbis/lib/books/floor/floor_books.h +1547 -0
  50. data/dependencies/libvorbis/lib/books/uncoupled/res_books_uncoupled.h +7758 -0
  51. data/dependencies/libvorbis/lib/codebook.c +479 -0
  52. data/dependencies/libvorbis/lib/codebook.h +119 -0
  53. data/dependencies/libvorbis/lib/codec_internal.h +167 -0
  54. data/dependencies/libvorbis/lib/envelope.c +375 -0
  55. data/dependencies/libvorbis/lib/envelope.h +80 -0
  56. data/dependencies/libvorbis/lib/floor0.c +222 -0
  57. data/dependencies/libvorbis/lib/floor1.c +1099 -0
  58. data/dependencies/libvorbis/lib/highlevel.h +58 -0
  59. data/dependencies/libvorbis/lib/info.c +664 -0
  60. data/dependencies/libvorbis/lib/lookup.c +94 -0
  61. data/dependencies/libvorbis/lib/lookup.h +32 -0
  62. data/dependencies/libvorbis/lib/lookup_data.h +192 -0
  63. data/dependencies/libvorbis/lib/lpc.c +160 -0
  64. data/dependencies/libvorbis/lib/lpc.h +29 -0
  65. data/dependencies/libvorbis/lib/lsp.c +456 -0
  66. data/dependencies/libvorbis/lib/lsp.h +28 -0
  67. data/dependencies/libvorbis/lib/mapping0.c +816 -0
  68. data/dependencies/libvorbis/lib/masking.h +785 -0
  69. data/dependencies/libvorbis/lib/mdct.c +563 -0
  70. data/dependencies/libvorbis/lib/mdct.h +71 -0
  71. data/dependencies/libvorbis/lib/misc.h +57 -0
  72. data/dependencies/libvorbis/lib/modes/floor_all.h +260 -0
  73. data/dependencies/libvorbis/lib/modes/psych_11.h +51 -0
  74. data/dependencies/libvorbis/lib/modes/psych_16.h +133 -0
  75. data/dependencies/libvorbis/lib/modes/psych_44.h +642 -0
  76. data/dependencies/libvorbis/lib/modes/psych_8.h +101 -0
  77. data/dependencies/libvorbis/lib/modes/residue_16.h +163 -0
  78. data/dependencies/libvorbis/lib/modes/residue_44.h +292 -0
  79. data/dependencies/libvorbis/lib/modes/residue_44p51.h +451 -0
  80. data/dependencies/libvorbis/lib/modes/residue_44u.h +318 -0
  81. data/dependencies/libvorbis/lib/modes/residue_8.h +109 -0
  82. data/dependencies/libvorbis/lib/modes/setup_11.h +143 -0
  83. data/dependencies/libvorbis/lib/modes/setup_16.h +153 -0
  84. data/dependencies/libvorbis/lib/modes/setup_22.h +128 -0
  85. data/dependencies/libvorbis/lib/modes/setup_32.h +132 -0
  86. data/dependencies/libvorbis/lib/modes/setup_44.h +117 -0
  87. data/dependencies/libvorbis/lib/modes/setup_44p51.h +74 -0
  88. data/dependencies/libvorbis/lib/modes/setup_44u.h +74 -0
  89. data/dependencies/libvorbis/lib/modes/setup_8.h +149 -0
  90. data/dependencies/libvorbis/lib/modes/setup_X.h +225 -0
  91. data/dependencies/libvorbis/lib/os.h +186 -0
  92. data/dependencies/libvorbis/lib/psy.c +1203 -0
  93. data/dependencies/libvorbis/lib/psy.h +154 -0
  94. data/dependencies/libvorbis/lib/psytune.c +524 -0
  95. data/dependencies/libvorbis/lib/registry.c +45 -0
  96. data/dependencies/libvorbis/lib/registry.h +32 -0
  97. data/dependencies/libvorbis/lib/res0.c +889 -0
  98. data/dependencies/libvorbis/lib/scales.h +90 -0
  99. data/dependencies/libvorbis/lib/sharedbook.c +579 -0
  100. data/dependencies/libvorbis/lib/smallft.c +1255 -0
  101. data/dependencies/libvorbis/lib/smallft.h +34 -0
  102. data/dependencies/libvorbis/lib/synthesis.c +184 -0
  103. data/dependencies/libvorbis/lib/tone.c +54 -0
  104. data/dependencies/libvorbis/lib/vorbisenc.c +1215 -0
  105. data/dependencies/libvorbis/lib/vorbisfile.c +2337 -0
  106. data/dependencies/libvorbis/lib/window.c +2135 -0
  107. data/dependencies/libvorbis/lib/window.h +26 -0
  108. data/dependencies/ogg_vorbis.license +28 -0
  109. data/lib/gosu/swig_patches.rb +2 -2
  110. data/linux/extconf.rb +17 -3
  111. metadata +96 -17
  112. data/Gosu/ButtonsX.hpp +0 -141
  113. data/GosuImpl/Audio/AudioSDL.cpp +0 -315
@@ -0,0 +1,2089 @@
1
+ /********************************************************************
2
+ * *
3
+ * THIS FILE IS PART OF THE Ogg CONTAINER 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. *
7
+ * *
8
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010 *
9
+ * by the Xiph.Org Foundation http://www.xiph.org/ *
10
+ * *
11
+ ********************************************************************
12
+
13
+ function: code raw packets into framed OggSquish stream and
14
+ decode Ogg streams back into raw packets
15
+ last mod: $Id: framing.c 17592 2010-11-01 20:27:54Z xiphmont $
16
+
17
+ note: The CRC code is directly derived from public domain code by
18
+ Ross Williams (ross@guest.adelaide.edu.au). See docs/framing.html
19
+ for details.
20
+
21
+ ********************************************************************/
22
+
23
+ #include <stdlib.h>
24
+ #include <string.h>
25
+ #include <ogg/ogg.h>
26
+
27
+ /* A complete description of Ogg framing exists in docs/framing.html */
28
+
29
+ int ogg_page_version(const ogg_page *og){
30
+ return((int)(og->header[4]));
31
+ }
32
+
33
+ int ogg_page_continued(const ogg_page *og){
34
+ return((int)(og->header[5]&0x01));
35
+ }
36
+
37
+ int ogg_page_bos(const ogg_page *og){
38
+ return((int)(og->header[5]&0x02));
39
+ }
40
+
41
+ int ogg_page_eos(const ogg_page *og){
42
+ return((int)(og->header[5]&0x04));
43
+ }
44
+
45
+ ogg_int64_t ogg_page_granulepos(const ogg_page *og){
46
+ unsigned char *page=og->header;
47
+ ogg_int64_t granulepos=page[13]&(0xff);
48
+ granulepos= (granulepos<<8)|(page[12]&0xff);
49
+ granulepos= (granulepos<<8)|(page[11]&0xff);
50
+ granulepos= (granulepos<<8)|(page[10]&0xff);
51
+ granulepos= (granulepos<<8)|(page[9]&0xff);
52
+ granulepos= (granulepos<<8)|(page[8]&0xff);
53
+ granulepos= (granulepos<<8)|(page[7]&0xff);
54
+ granulepos= (granulepos<<8)|(page[6]&0xff);
55
+ return(granulepos);
56
+ }
57
+
58
+ int ogg_page_serialno(const ogg_page *og){
59
+ return(og->header[14] |
60
+ (og->header[15]<<8) |
61
+ (og->header[16]<<16) |
62
+ (og->header[17]<<24));
63
+ }
64
+
65
+ long ogg_page_pageno(const ogg_page *og){
66
+ return(og->header[18] |
67
+ (og->header[19]<<8) |
68
+ (og->header[20]<<16) |
69
+ (og->header[21]<<24));
70
+ }
71
+
72
+
73
+
74
+ /* returns the number of packets that are completed on this page (if
75
+ the leading packet is begun on a previous page, but ends on this
76
+ page, it's counted */
77
+
78
+ /* NOTE:
79
+ If a page consists of a packet begun on a previous page, and a new
80
+ packet begun (but not completed) on this page, the return will be:
81
+ ogg_page_packets(page) ==1,
82
+ ogg_page_continued(page) !=0
83
+
84
+ If a page happens to be a single packet that was begun on a
85
+ previous page, and spans to the next page (in the case of a three or
86
+ more page packet), the return will be:
87
+ ogg_page_packets(page) ==0,
88
+ ogg_page_continued(page) !=0
89
+ */
90
+
91
+ int ogg_page_packets(const ogg_page *og){
92
+ int i,n=og->header[26],count=0;
93
+ for(i=0;i<n;i++)
94
+ if(og->header[27+i]<255)count++;
95
+ return(count);
96
+ }
97
+
98
+
99
+ #if 0
100
+ /* helper to initialize lookup for direct-table CRC (illustrative; we
101
+ use the static init below) */
102
+
103
+ static ogg_uint32_t _ogg_crc_entry(unsigned long index){
104
+ int i;
105
+ unsigned long r;
106
+
107
+ r = index << 24;
108
+ for (i=0; i<8; i++)
109
+ if (r & 0x80000000UL)
110
+ r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator
111
+ polynomial, although we use an
112
+ unreflected alg and an init/final
113
+ of 0, not 0xffffffff */
114
+ else
115
+ r<<=1;
116
+ return (r & 0xffffffffUL);
117
+ }
118
+ #endif
119
+
120
+ static const ogg_uint32_t crc_lookup[256]={
121
+ 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
122
+ 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
123
+ 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
124
+ 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
125
+ 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,
126
+ 0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
127
+ 0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,
128
+ 0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
129
+ 0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,
130
+ 0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
131
+ 0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,
132
+ 0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
133
+ 0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,
134
+ 0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
135
+ 0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,
136
+ 0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
137
+ 0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,
138
+ 0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
139
+ 0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,
140
+ 0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
141
+ 0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,
142
+ 0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
143
+ 0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,
144
+ 0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
145
+ 0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,
146
+ 0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
147
+ 0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,
148
+ 0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
149
+ 0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,
150
+ 0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
151
+ 0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,
152
+ 0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
153
+ 0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,
154
+ 0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
155
+ 0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,
156
+ 0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
157
+ 0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,
158
+ 0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
159
+ 0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,
160
+ 0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
161
+ 0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,
162
+ 0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
163
+ 0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,
164
+ 0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
165
+ 0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,
166
+ 0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
167
+ 0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,
168
+ 0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
169
+ 0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,
170
+ 0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
171
+ 0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,
172
+ 0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
173
+ 0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,
174
+ 0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
175
+ 0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,
176
+ 0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
177
+ 0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,
178
+ 0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
179
+ 0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,
180
+ 0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
181
+ 0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,
182
+ 0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
183
+ 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
184
+ 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4};
185
+
186
+ /* init the encode/decode logical stream state */
187
+
188
+ int ogg_stream_init(ogg_stream_state *os,int serialno){
189
+ if(os){
190
+ memset(os,0,sizeof(*os));
191
+ os->body_storage=16*1024;
192
+ os->lacing_storage=1024;
193
+
194
+ os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data));
195
+ os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals));
196
+ os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals));
197
+
198
+ if(!os->body_data || !os->lacing_vals || !os->granule_vals){
199
+ ogg_stream_clear(os);
200
+ return -1;
201
+ }
202
+
203
+ os->serialno=serialno;
204
+
205
+ return(0);
206
+ }
207
+ return(-1);
208
+ }
209
+
210
+ /* async/delayed error detection for the ogg_stream_state */
211
+ int ogg_stream_check(ogg_stream_state *os){
212
+ if(!os || !os->body_data) return -1;
213
+ return 0;
214
+ }
215
+
216
+ /* _clear does not free os, only the non-flat storage within */
217
+ int ogg_stream_clear(ogg_stream_state *os){
218
+ if(os){
219
+ if(os->body_data)_ogg_free(os->body_data);
220
+ if(os->lacing_vals)_ogg_free(os->lacing_vals);
221
+ if(os->granule_vals)_ogg_free(os->granule_vals);
222
+
223
+ memset(os,0,sizeof(*os));
224
+ }
225
+ return(0);
226
+ }
227
+
228
+ int ogg_stream_destroy(ogg_stream_state *os){
229
+ if(os){
230
+ ogg_stream_clear(os);
231
+ _ogg_free(os);
232
+ }
233
+ return(0);
234
+ }
235
+
236
+ /* Helpers for ogg_stream_encode; this keeps the structure and
237
+ what's happening fairly clear */
238
+
239
+ static int _os_body_expand(ogg_stream_state *os,int needed){
240
+ if(os->body_storage<=os->body_fill+needed){
241
+ void *ret;
242
+ ret=_ogg_realloc(os->body_data,(os->body_storage+needed+1024)*
243
+ sizeof(*os->body_data));
244
+ if(!ret){
245
+ ogg_stream_clear(os);
246
+ return -1;
247
+ }
248
+ os->body_storage+=(needed+1024);
249
+ os->body_data=ret;
250
+ }
251
+ return 0;
252
+ }
253
+
254
+ static int _os_lacing_expand(ogg_stream_state *os,int needed){
255
+ if(os->lacing_storage<=os->lacing_fill+needed){
256
+ void *ret;
257
+ ret=_ogg_realloc(os->lacing_vals,(os->lacing_storage+needed+32)*
258
+ sizeof(*os->lacing_vals));
259
+ if(!ret){
260
+ ogg_stream_clear(os);
261
+ return -1;
262
+ }
263
+ os->lacing_vals=ret;
264
+ ret=_ogg_realloc(os->granule_vals,(os->lacing_storage+needed+32)*
265
+ sizeof(*os->granule_vals));
266
+ if(!ret){
267
+ ogg_stream_clear(os);
268
+ return -1;
269
+ }
270
+ os->granule_vals=ret;
271
+ os->lacing_storage+=(needed+32);
272
+ }
273
+ return 0;
274
+ }
275
+
276
+ /* checksum the page */
277
+ /* Direct table CRC; note that this will be faster in the future if we
278
+ perform the checksum simultaneously with other copies */
279
+
280
+ void ogg_page_checksum_set(ogg_page *og){
281
+ if(og){
282
+ ogg_uint32_t crc_reg=0;
283
+ int i;
284
+
285
+ /* safety; needed for API behavior, but not framing code */
286
+ og->header[22]=0;
287
+ og->header[23]=0;
288
+ og->header[24]=0;
289
+ og->header[25]=0;
290
+
291
+ for(i=0;i<og->header_len;i++)
292
+ crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]];
293
+ for(i=0;i<og->body_len;i++)
294
+ crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]];
295
+
296
+ og->header[22]=(unsigned char)(crc_reg&0xff);
297
+ og->header[23]=(unsigned char)((crc_reg>>8)&0xff);
298
+ og->header[24]=(unsigned char)((crc_reg>>16)&0xff);
299
+ og->header[25]=(unsigned char)((crc_reg>>24)&0xff);
300
+ }
301
+ }
302
+
303
+ /* submit data to the internal buffer of the framing engine */
304
+ int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, int count,
305
+ long e_o_s, ogg_int64_t granulepos){
306
+
307
+ int bytes = 0, lacing_vals, i;
308
+
309
+ if(ogg_stream_check(os)) return -1;
310
+ if(!iov) return 0;
311
+
312
+ for (i = 0; i < count; ++i) bytes += (int)iov[i].iov_len;
313
+ lacing_vals=bytes/255+1;
314
+
315
+ if(os->body_returned){
316
+ /* advance packet data according to the body_returned pointer. We
317
+ had to keep it around to return a pointer into the buffer last
318
+ call */
319
+
320
+ os->body_fill-=os->body_returned;
321
+ if(os->body_fill)
322
+ memmove(os->body_data,os->body_data+os->body_returned,
323
+ os->body_fill);
324
+ os->body_returned=0;
325
+ }
326
+
327
+ /* make sure we have the buffer storage */
328
+ if(_os_body_expand(os,bytes) || _os_lacing_expand(os,lacing_vals))
329
+ return -1;
330
+
331
+ /* Copy in the submitted packet. Yes, the copy is a waste; this is
332
+ the liability of overly clean abstraction for the time being. It
333
+ will actually be fairly easy to eliminate the extra copy in the
334
+ future */
335
+
336
+ for (i = 0; i < count; ++i) {
337
+ memcpy(os->body_data+os->body_fill, iov[i].iov_base, iov[i].iov_len);
338
+ os->body_fill += (int)iov[i].iov_len;
339
+ }
340
+
341
+ /* Store lacing vals for this packet */
342
+ for(i=0;i<lacing_vals-1;i++){
343
+ os->lacing_vals[os->lacing_fill+i]=255;
344
+ os->granule_vals[os->lacing_fill+i]=os->granulepos;
345
+ }
346
+ os->lacing_vals[os->lacing_fill+i]=bytes%255;
347
+ os->granulepos=os->granule_vals[os->lacing_fill+i]=granulepos;
348
+
349
+ /* flag the first segment as the beginning of the packet */
350
+ os->lacing_vals[os->lacing_fill]|= 0x100;
351
+
352
+ os->lacing_fill+=lacing_vals;
353
+
354
+ /* for the sake of completeness */
355
+ os->packetno++;
356
+
357
+ if(e_o_s)os->e_o_s=1;
358
+
359
+ return(0);
360
+ }
361
+
362
+ int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){
363
+ ogg_iovec_t iov;
364
+ iov.iov_base = op->packet;
365
+ iov.iov_len = op->bytes;
366
+ return ogg_stream_iovecin(os, &iov, 1, op->e_o_s, op->granulepos);
367
+ }
368
+
369
+ /* Conditionally flush a page; force==0 will only flush nominal-size
370
+ pages, force==1 forces us to flush a page regardless of page size
371
+ so long as there's any data available at all. */
372
+ static int ogg_stream_flush_i(ogg_stream_state *os,ogg_page *og, int force, int nfill){
373
+ int i;
374
+ int vals=0;
375
+ int maxvals=(os->lacing_fill>255?255:os->lacing_fill);
376
+ int bytes=0;
377
+ long acc=0;
378
+ ogg_int64_t granule_pos=-1;
379
+
380
+ if(ogg_stream_check(os)) return(0);
381
+ if(maxvals==0) return(0);
382
+
383
+ /* construct a page */
384
+ /* decide how many segments to include */
385
+
386
+ /* If this is the initial header case, the first page must only include
387
+ the initial header packet */
388
+ if(os->b_o_s==0){ /* 'initial header page' case */
389
+ granule_pos=0;
390
+ for(vals=0;vals<maxvals;vals++){
391
+ if((os->lacing_vals[vals]&0x0ff)<255){
392
+ vals++;
393
+ break;
394
+ }
395
+ }
396
+ }else{
397
+
398
+ /* The extra packets_done, packet_just_done logic here attempts to do two things:
399
+ 1) Don't unneccessarily span pages.
400
+ 2) Unless necessary, don't flush pages if there are less than four packets on
401
+ them; this expands page size to reduce unneccessary overhead if incoming packets
402
+ are large.
403
+ These are not necessary behaviors, just 'always better than naive flushing'
404
+ without requiring an application to explicitly request a specific optimized
405
+ behavior. We'll want an explicit behavior setup pathway eventually as well. */
406
+
407
+ int packets_done=0;
408
+ int packet_just_done=0;
409
+ for(vals=0;vals<maxvals;vals++){
410
+ if(acc>nfill && packet_just_done>=4){
411
+ force=1;
412
+ break;
413
+ }
414
+ acc+=os->lacing_vals[vals]&0x0ff;
415
+ if((os->lacing_vals[vals]&0xff)<255){
416
+ granule_pos=os->granule_vals[vals];
417
+ packet_just_done=++packets_done;
418
+ }else
419
+ packet_just_done=0;
420
+ }
421
+ if(vals==255)force=1;
422
+ }
423
+
424
+ if(!force) return(0);
425
+
426
+ /* construct the header in temp storage */
427
+ memcpy(os->header,"OggS",4);
428
+
429
+ /* stream structure version */
430
+ os->header[4]=0x00;
431
+
432
+ /* continued packet flag? */
433
+ os->header[5]=0x00;
434
+ if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01;
435
+ /* first page flag? */
436
+ if(os->b_o_s==0)os->header[5]|=0x02;
437
+ /* last page flag? */
438
+ if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04;
439
+ os->b_o_s=1;
440
+
441
+ /* 64 bits of PCM position */
442
+ for(i=6;i<14;i++){
443
+ os->header[i]=(unsigned char)(granule_pos&0xff);
444
+ granule_pos>>=8;
445
+ }
446
+
447
+ /* 32 bits of stream serial number */
448
+ {
449
+ long serialno=os->serialno;
450
+ for(i=14;i<18;i++){
451
+ os->header[i]=(unsigned char)(serialno&0xff);
452
+ serialno>>=8;
453
+ }
454
+ }
455
+
456
+ /* 32 bits of page counter (we have both counter and page header
457
+ because this val can roll over) */
458
+ if(os->pageno==-1)os->pageno=0; /* because someone called
459
+ stream_reset; this would be a
460
+ strange thing to do in an
461
+ encode stream, but it has
462
+ plausible uses */
463
+ {
464
+ long pageno=os->pageno++;
465
+ for(i=18;i<22;i++){
466
+ os->header[i]=(unsigned char)(pageno&0xff);
467
+ pageno>>=8;
468
+ }
469
+ }
470
+
471
+ /* zero for computation; filled in later */
472
+ os->header[22]=0;
473
+ os->header[23]=0;
474
+ os->header[24]=0;
475
+ os->header[25]=0;
476
+
477
+ /* segment table */
478
+ os->header[26]=(unsigned char)(vals&0xff);
479
+ for(i=0;i<vals;i++)
480
+ bytes+=os->header[i+27]=(unsigned char)(os->lacing_vals[i]&0xff);
481
+
482
+ /* set pointers in the ogg_page struct */
483
+ og->header=os->header;
484
+ og->header_len=os->header_fill=vals+27;
485
+ og->body=os->body_data+os->body_returned;
486
+ og->body_len=bytes;
487
+
488
+ /* advance the lacing data and set the body_returned pointer */
489
+
490
+ os->lacing_fill-=vals;
491
+ memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals));
492
+ memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals));
493
+ os->body_returned+=bytes;
494
+
495
+ /* calculate the checksum */
496
+
497
+ ogg_page_checksum_set(og);
498
+
499
+ /* done */
500
+ return(1);
501
+ }
502
+
503
+ /* This will flush remaining packets into a page (returning nonzero),
504
+ even if there is not enough data to trigger a flush normally
505
+ (undersized page). If there are no packets or partial packets to
506
+ flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will
507
+ try to flush a normal sized page like ogg_stream_pageout; a call to
508
+ ogg_stream_flush does not guarantee that all packets have flushed.
509
+ Only a return value of 0 from ogg_stream_flush indicates all packet
510
+ data is flushed into pages.
511
+
512
+ since ogg_stream_flush will flush the last page in a stream even if
513
+ it's undersized, you almost certainly want to use ogg_stream_pageout
514
+ (and *not* ogg_stream_flush) unless you specifically need to flush
515
+ an page regardless of size in the middle of a stream. */
516
+
517
+ int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){
518
+ return ogg_stream_flush_i(os,og,1,4096);
519
+ }
520
+
521
+ /* This constructs pages from buffered packet segments. The pointers
522
+ returned are to static buffers; do not free. The returned buffers are
523
+ good only until the next call (using the same ogg_stream_state) */
524
+
525
+ int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){
526
+ int force=0;
527
+ if(ogg_stream_check(os)) return 0;
528
+
529
+ if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
530
+ (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */
531
+ force=1;
532
+
533
+ return(ogg_stream_flush_i(os,og,force,4096));
534
+ }
535
+
536
+ /* Like the above, but an argument is provided to adjust the nominal
537
+ page size for applications which are smart enough to provide their
538
+ own delay based flushing */
539
+
540
+ int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill){
541
+ int force=0;
542
+ if(ogg_stream_check(os)) return 0;
543
+
544
+ if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */
545
+ (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */
546
+ force=1;
547
+
548
+ return(ogg_stream_flush_i(os,og,force,nfill));
549
+ }
550
+
551
+ int ogg_stream_eos(ogg_stream_state *os){
552
+ if(ogg_stream_check(os)) return 1;
553
+ return os->e_o_s;
554
+ }
555
+
556
+ /* DECODING PRIMITIVES: packet streaming layer **********************/
557
+
558
+ /* This has two layers to place more of the multi-serialno and paging
559
+ control in the application's hands. First, we expose a data buffer
560
+ using ogg_sync_buffer(). The app either copies into the
561
+ buffer, or passes it directly to read(), etc. We then call
562
+ ogg_sync_wrote() to tell how many bytes we just added.
563
+
564
+ Pages are returned (pointers into the buffer in ogg_sync_state)
565
+ by ogg_sync_pageout(). The page is then submitted to
566
+ ogg_stream_pagein() along with the appropriate
567
+ ogg_stream_state* (ie, matching serialno). We then get raw
568
+ packets out calling ogg_stream_packetout() with a
569
+ ogg_stream_state. */
570
+
571
+ /* initialize the struct to a known state */
572
+ int ogg_sync_init(ogg_sync_state *oy){
573
+ if(oy){
574
+ oy->storage = -1; /* used as a readiness flag */
575
+ memset(oy,0,sizeof(*oy));
576
+ }
577
+ return(0);
578
+ }
579
+
580
+ /* clear non-flat storage within */
581
+ int ogg_sync_clear(ogg_sync_state *oy){
582
+ if(oy){
583
+ if(oy->data)_ogg_free(oy->data);
584
+ memset(oy,0,sizeof(*oy));
585
+ }
586
+ return(0);
587
+ }
588
+
589
+ int ogg_sync_destroy(ogg_sync_state *oy){
590
+ if(oy){
591
+ ogg_sync_clear(oy);
592
+ _ogg_free(oy);
593
+ }
594
+ return(0);
595
+ }
596
+
597
+ int ogg_sync_check(ogg_sync_state *oy){
598
+ if(oy->storage<0) return -1;
599
+ return 0;
600
+ }
601
+
602
+ char *ogg_sync_buffer(ogg_sync_state *oy, long size){
603
+ if(ogg_sync_check(oy)) return NULL;
604
+
605
+ /* first, clear out any space that has been previously returned */
606
+ if(oy->returned){
607
+ oy->fill-=oy->returned;
608
+ if(oy->fill>0)
609
+ memmove(oy->data,oy->data+oy->returned,oy->fill);
610
+ oy->returned=0;
611
+ }
612
+
613
+ if(size>oy->storage-oy->fill){
614
+ /* We need to extend the internal buffer */
615
+ long newsize=size+oy->fill+4096; /* an extra page to be nice */
616
+ void *ret;
617
+
618
+ if(oy->data)
619
+ ret=_ogg_realloc(oy->data,newsize);
620
+ else
621
+ ret=_ogg_malloc(newsize);
622
+ if(!ret){
623
+ ogg_sync_clear(oy);
624
+ return NULL;
625
+ }
626
+ oy->data=ret;
627
+ oy->storage=newsize;
628
+ }
629
+
630
+ /* expose a segment at least as large as requested at the fill mark */
631
+ return((char *)oy->data+oy->fill);
632
+ }
633
+
634
+ int ogg_sync_wrote(ogg_sync_state *oy, long bytes){
635
+ if(ogg_sync_check(oy))return -1;
636
+ if(oy->fill+bytes>oy->storage)return -1;
637
+ oy->fill+=bytes;
638
+ return(0);
639
+ }
640
+
641
+ /* sync the stream. This is meant to be useful for finding page
642
+ boundaries.
643
+
644
+ return values for this:
645
+ -n) skipped n bytes
646
+ 0) page not ready; more data (no bytes skipped)
647
+ n) page synced at current location; page length n bytes
648
+
649
+ */
650
+
651
+ long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){
652
+ unsigned char *page=oy->data+oy->returned;
653
+ unsigned char *next;
654
+ long bytes=oy->fill-oy->returned;
655
+
656
+ if(ogg_sync_check(oy))return 0;
657
+
658
+ if(oy->headerbytes==0){
659
+ int headerbytes,i;
660
+ if(bytes<27)return(0); /* not enough for a header */
661
+
662
+ /* verify capture pattern */
663
+ if(memcmp(page,"OggS",4))goto sync_fail;
664
+
665
+ headerbytes=page[26]+27;
666
+ if(bytes<headerbytes)return(0); /* not enough for header + seg table */
667
+
668
+ /* count up body length in the segment table */
669
+
670
+ for(i=0;i<page[26];i++)
671
+ oy->bodybytes+=page[27+i];
672
+ oy->headerbytes=headerbytes;
673
+ }
674
+
675
+ if(oy->bodybytes+oy->headerbytes>bytes)return(0);
676
+
677
+ /* The whole test page is buffered. Verify the checksum */
678
+ {
679
+ /* Grab the checksum bytes, set the header field to zero */
680
+ char chksum[4];
681
+ ogg_page log;
682
+
683
+ memcpy(chksum,page+22,4);
684
+ memset(page+22,0,4);
685
+
686
+ /* set up a temp page struct and recompute the checksum */
687
+ log.header=page;
688
+ log.header_len=oy->headerbytes;
689
+ log.body=page+oy->headerbytes;
690
+ log.body_len=oy->bodybytes;
691
+ ogg_page_checksum_set(&log);
692
+
693
+ /* Compare */
694
+ if(memcmp(chksum,page+22,4)){
695
+ /* D'oh. Mismatch! Corrupt page (or miscapture and not a page
696
+ at all) */
697
+ /* replace the computed checksum with the one actually read in */
698
+ memcpy(page+22,chksum,4);
699
+
700
+ /* Bad checksum. Lose sync */
701
+ goto sync_fail;
702
+ }
703
+ }
704
+
705
+ /* yes, have a whole page all ready to go */
706
+ {
707
+ unsigned char *page=oy->data+oy->returned;
708
+ long bytes;
709
+
710
+ if(og){
711
+ og->header=page;
712
+ og->header_len=oy->headerbytes;
713
+ og->body=page+oy->headerbytes;
714
+ og->body_len=oy->bodybytes;
715
+ }
716
+
717
+ oy->unsynced=0;
718
+ oy->returned+=(bytes=oy->headerbytes+oy->bodybytes);
719
+ oy->headerbytes=0;
720
+ oy->bodybytes=0;
721
+ return(bytes);
722
+ }
723
+
724
+ sync_fail:
725
+
726
+ oy->headerbytes=0;
727
+ oy->bodybytes=0;
728
+
729
+ /* search for possible capture */
730
+ next=memchr(page+1,'O',bytes-1);
731
+ if(!next)
732
+ next=oy->data+oy->fill;
733
+
734
+ oy->returned=(int)(next-oy->data);
735
+ return((long)-(next-page));
736
+ }
737
+
738
+ /* sync the stream and get a page. Keep trying until we find a page.
739
+ Suppress 'sync errors' after reporting the first.
740
+
741
+ return values:
742
+ -1) recapture (hole in data)
743
+ 0) need more data
744
+ 1) page returned
745
+
746
+ Returns pointers into buffered data; invalidated by next call to
747
+ _stream, _clear, _init, or _buffer */
748
+
749
+ int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){
750
+
751
+ if(ogg_sync_check(oy))return 0;
752
+
753
+ /* all we need to do is verify a page at the head of the stream
754
+ buffer. If it doesn't verify, we look for the next potential
755
+ frame */
756
+
757
+ for(;;){
758
+ long ret=ogg_sync_pageseek(oy,og);
759
+ if(ret>0){
760
+ /* have a page */
761
+ return(1);
762
+ }
763
+ if(ret==0){
764
+ /* need more data */
765
+ return(0);
766
+ }
767
+
768
+ /* head did not start a synced page... skipped some bytes */
769
+ if(!oy->unsynced){
770
+ oy->unsynced=1;
771
+ return(-1);
772
+ }
773
+
774
+ /* loop. keep looking */
775
+
776
+ }
777
+ }
778
+
779
+ /* add the incoming page to the stream state; we decompose the page
780
+ into packet segments here as well. */
781
+
782
+ int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){
783
+ unsigned char *header=og->header;
784
+ unsigned char *body=og->body;
785
+ long bodysize=og->body_len;
786
+ int segptr=0;
787
+
788
+ int version=ogg_page_version(og);
789
+ int continued=ogg_page_continued(og);
790
+ int bos=ogg_page_bos(og);
791
+ int eos=ogg_page_eos(og);
792
+ ogg_int64_t granulepos=ogg_page_granulepos(og);
793
+ int serialno=ogg_page_serialno(og);
794
+ long pageno=ogg_page_pageno(og);
795
+ int segments=header[26];
796
+
797
+ if(ogg_stream_check(os)) return -1;
798
+
799
+ /* clean up 'returned data' */
800
+ {
801
+ long lr=os->lacing_returned;
802
+ long br=os->body_returned;
803
+
804
+ /* body data */
805
+ if(br){
806
+ os->body_fill-=br;
807
+ if(os->body_fill)
808
+ memmove(os->body_data,os->body_data+br,os->body_fill);
809
+ os->body_returned=0;
810
+ }
811
+
812
+ if(lr){
813
+ /* segment table */
814
+ if(os->lacing_fill-lr){
815
+ memmove(os->lacing_vals,os->lacing_vals+lr,
816
+ (os->lacing_fill-lr)*sizeof(*os->lacing_vals));
817
+ memmove(os->granule_vals,os->granule_vals+lr,
818
+ (os->lacing_fill-lr)*sizeof(*os->granule_vals));
819
+ }
820
+ os->lacing_fill-=lr;
821
+ os->lacing_packet-=lr;
822
+ os->lacing_returned=0;
823
+ }
824
+ }
825
+
826
+ /* check the serial number */
827
+ if(serialno!=os->serialno)return(-1);
828
+ if(version>0)return(-1);
829
+
830
+ if(_os_lacing_expand(os,segments+1)) return -1;
831
+
832
+ /* are we in sequence? */
833
+ if(pageno!=os->pageno){
834
+ int i;
835
+
836
+ /* unroll previous partial packet (if any) */
837
+ for(i=os->lacing_packet;i<os->lacing_fill;i++)
838
+ os->body_fill-=os->lacing_vals[i]&0xff;
839
+ os->lacing_fill=os->lacing_packet;
840
+
841
+ /* make a note of dropped data in segment table */
842
+ if(os->pageno!=-1){
843
+ os->lacing_vals[os->lacing_fill++]=0x400;
844
+ os->lacing_packet++;
845
+ }
846
+ }
847
+
848
+ /* are we a 'continued packet' page? If so, we may need to skip
849
+ some segments */
850
+ if(continued){
851
+ if(os->lacing_fill<1 ||
852
+ os->lacing_vals[os->lacing_fill-1]==0x400){
853
+ bos=0;
854
+ for(;segptr<segments;segptr++){
855
+ int val=header[27+segptr];
856
+ body+=val;
857
+ bodysize-=val;
858
+ if(val<255){
859
+ segptr++;
860
+ break;
861
+ }
862
+ }
863
+ }
864
+ }
865
+
866
+ if(bodysize){
867
+ if(_os_body_expand(os,bodysize)) return -1;
868
+ memcpy(os->body_data+os->body_fill,body,bodysize);
869
+ os->body_fill+=bodysize;
870
+ }
871
+
872
+ {
873
+ int saved=-1;
874
+ while(segptr<segments){
875
+ int val=header[27+segptr];
876
+ os->lacing_vals[os->lacing_fill]=val;
877
+ os->granule_vals[os->lacing_fill]=-1;
878
+
879
+ if(bos){
880
+ os->lacing_vals[os->lacing_fill]|=0x100;
881
+ bos=0;
882
+ }
883
+
884
+ if(val<255)saved=os->lacing_fill;
885
+
886
+ os->lacing_fill++;
887
+ segptr++;
888
+
889
+ if(val<255)os->lacing_packet=os->lacing_fill;
890
+ }
891
+
892
+ /* set the granulepos on the last granuleval of the last full packet */
893
+ if(saved!=-1){
894
+ os->granule_vals[saved]=granulepos;
895
+ }
896
+
897
+ }
898
+
899
+ if(eos){
900
+ os->e_o_s=1;
901
+ if(os->lacing_fill>0)
902
+ os->lacing_vals[os->lacing_fill-1]|=0x200;
903
+ }
904
+
905
+ os->pageno=pageno+1;
906
+
907
+ return(0);
908
+ }
909
+
910
+ /* clear things to an initial state. Good to call, eg, before seeking */
911
+ int ogg_sync_reset(ogg_sync_state *oy){
912
+ if(ogg_sync_check(oy))return -1;
913
+
914
+ oy->fill=0;
915
+ oy->returned=0;
916
+ oy->unsynced=0;
917
+ oy->headerbytes=0;
918
+ oy->bodybytes=0;
919
+ return(0);
920
+ }
921
+
922
+ int ogg_stream_reset(ogg_stream_state *os){
923
+ if(ogg_stream_check(os)) return -1;
924
+
925
+ os->body_fill=0;
926
+ os->body_returned=0;
927
+
928
+ os->lacing_fill=0;
929
+ os->lacing_packet=0;
930
+ os->lacing_returned=0;
931
+
932
+ os->header_fill=0;
933
+
934
+ os->e_o_s=0;
935
+ os->b_o_s=0;
936
+ os->pageno=-1;
937
+ os->packetno=0;
938
+ os->granulepos=0;
939
+
940
+ return(0);
941
+ }
942
+
943
+ int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){
944
+ if(ogg_stream_check(os)) return -1;
945
+ ogg_stream_reset(os);
946
+ os->serialno=serialno;
947
+ return(0);
948
+ }
949
+
950
+ static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){
951
+
952
+ /* The last part of decode. We have the stream broken into packet
953
+ segments. Now we need to group them into packets (or return the
954
+ out of sync markers) */
955
+
956
+ int ptr=os->lacing_returned;
957
+
958
+ if(os->lacing_packet<=ptr)return(0);
959
+
960
+ if(os->lacing_vals[ptr]&0x400){
961
+ /* we need to tell the codec there's a gap; it might need to
962
+ handle previous packet dependencies. */
963
+ os->lacing_returned++;
964
+ os->packetno++;
965
+ return(-1);
966
+ }
967
+
968
+ if(!op && !adv)return(1); /* just using peek as an inexpensive way
969
+ to ask if there's a whole packet
970
+ waiting */
971
+
972
+ /* Gather the whole packet. We'll have no holes or a partial packet */
973
+ {
974
+ int size=os->lacing_vals[ptr]&0xff;
975
+ long bytes=size;
976
+ int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */
977
+ int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */
978
+
979
+ while(size==255){
980
+ int val=os->lacing_vals[++ptr];
981
+ size=val&0xff;
982
+ if(val&0x200)eos=0x200;
983
+ bytes+=size;
984
+ }
985
+
986
+ if(op){
987
+ op->e_o_s=eos;
988
+ op->b_o_s=bos;
989
+ op->packet=os->body_data+os->body_returned;
990
+ op->packetno=os->packetno;
991
+ op->granulepos=os->granule_vals[ptr];
992
+ op->bytes=bytes;
993
+ }
994
+
995
+ if(adv){
996
+ os->body_returned+=bytes;
997
+ os->lacing_returned=ptr+1;
998
+ os->packetno++;
999
+ }
1000
+ }
1001
+ return(1);
1002
+ }
1003
+
1004
+ int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){
1005
+ if(ogg_stream_check(os)) return 0;
1006
+ return _packetout(os,op,1);
1007
+ }
1008
+
1009
+ int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){
1010
+ if(ogg_stream_check(os)) return 0;
1011
+ return _packetout(os,op,0);
1012
+ }
1013
+
1014
+ void ogg_packet_clear(ogg_packet *op) {
1015
+ _ogg_free(op->packet);
1016
+ memset(op, 0, sizeof(*op));
1017
+ }
1018
+
1019
+ #ifdef _V_SELFTEST
1020
+ #include <stdio.h>
1021
+
1022
+ ogg_stream_state os_en, os_de;
1023
+ ogg_sync_state oy;
1024
+
1025
+ void checkpacket(ogg_packet *op,long len, int no, long pos){
1026
+ long j;
1027
+ static int sequence=0;
1028
+ static int lastno=0;
1029
+
1030
+ if(op->bytes!=len){
1031
+ fprintf(stderr,"incorrect packet length (%ld != %ld)!\n",op->bytes,len);
1032
+ exit(1);
1033
+ }
1034
+ if(op->granulepos!=pos){
1035
+ fprintf(stderr,"incorrect packet granpos (%ld != %ld)!\n",(long)op->granulepos,pos);
1036
+ exit(1);
1037
+ }
1038
+
1039
+ /* packet number just follows sequence/gap; adjust the input number
1040
+ for that */
1041
+ if(no==0){
1042
+ sequence=0;
1043
+ }else{
1044
+ sequence++;
1045
+ if(no>lastno+1)
1046
+ sequence++;
1047
+ }
1048
+ lastno=no;
1049
+ if(op->packetno!=sequence){
1050
+ fprintf(stderr,"incorrect packet sequence %ld != %d\n",
1051
+ (long)(op->packetno),sequence);
1052
+ exit(1);
1053
+ }
1054
+
1055
+ /* Test data */
1056
+ for(j=0;j<op->bytes;j++)
1057
+ if(op->packet[j]!=((j+no)&0xff)){
1058
+ fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n",
1059
+ j,op->packet[j],(j+no)&0xff);
1060
+ exit(1);
1061
+ }
1062
+ }
1063
+
1064
+ void check_page(unsigned char *data,const int *header,ogg_page *og){
1065
+ long j;
1066
+ /* Test data */
1067
+ for(j=0;j<og->body_len;j++)
1068
+ if(og->body[j]!=data[j]){
1069
+ fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n",
1070
+ j,data[j],og->body[j]);
1071
+ exit(1);
1072
+ }
1073
+
1074
+ /* Test header */
1075
+ for(j=0;j<og->header_len;j++){
1076
+ if(og->header[j]!=header[j]){
1077
+ fprintf(stderr,"header content mismatch at pos %ld:\n",j);
1078
+ for(j=0;j<header[26]+27;j++)
1079
+ fprintf(stderr," (%ld)%02x:%02x",j,header[j],og->header[j]);
1080
+ fprintf(stderr,"\n");
1081
+ exit(1);
1082
+ }
1083
+ }
1084
+ if(og->header_len!=header[26]+27){
1085
+ fprintf(stderr,"header length incorrect! (%ld!=%d)\n",
1086
+ og->header_len,header[26]+27);
1087
+ exit(1);
1088
+ }
1089
+ }
1090
+
1091
+ void print_header(ogg_page *og){
1092
+ int j;
1093
+ fprintf(stderr,"\nHEADER:\n");
1094
+ fprintf(stderr," capture: %c %c %c %c version: %d flags: %x\n",
1095
+ og->header[0],og->header[1],og->header[2],og->header[3],
1096
+ (int)og->header[4],(int)og->header[5]);
1097
+
1098
+ fprintf(stderr," granulepos: %d serialno: %d pageno: %ld\n",
1099
+ (og->header[9]<<24)|(og->header[8]<<16)|
1100
+ (og->header[7]<<8)|og->header[6],
1101
+ (og->header[17]<<24)|(og->header[16]<<16)|
1102
+ (og->header[15]<<8)|og->header[14],
1103
+ ((long)(og->header[21])<<24)|(og->header[20]<<16)|
1104
+ (og->header[19]<<8)|og->header[18]);
1105
+
1106
+ fprintf(stderr," checksum: %02x:%02x:%02x:%02x\n segments: %d (",
1107
+ (int)og->header[22],(int)og->header[23],
1108
+ (int)og->header[24],(int)og->header[25],
1109
+ (int)og->header[26]);
1110
+
1111
+ for(j=27;j<og->header_len;j++)
1112
+ fprintf(stderr,"%d ",(int)og->header[j]);
1113
+ fprintf(stderr,")\n\n");
1114
+ }
1115
+
1116
+ void copy_page(ogg_page *og){
1117
+ unsigned char *temp=_ogg_malloc(og->header_len);
1118
+ memcpy(temp,og->header,og->header_len);
1119
+ og->header=temp;
1120
+
1121
+ temp=_ogg_malloc(og->body_len);
1122
+ memcpy(temp,og->body,og->body_len);
1123
+ og->body=temp;
1124
+ }
1125
+
1126
+ void free_page(ogg_page *og){
1127
+ _ogg_free (og->header);
1128
+ _ogg_free (og->body);
1129
+ }
1130
+
1131
+ void error(void){
1132
+ fprintf(stderr,"error!\n");
1133
+ exit(1);
1134
+ }
1135
+
1136
+ /* 17 only */
1137
+ const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06,
1138
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1139
+ 0x01,0x02,0x03,0x04,0,0,0,0,
1140
+ 0x15,0xed,0xec,0x91,
1141
+ 1,
1142
+ 17};
1143
+
1144
+ /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1145
+ const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02,
1146
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1147
+ 0x01,0x02,0x03,0x04,0,0,0,0,
1148
+ 0x59,0x10,0x6c,0x2c,
1149
+ 1,
1150
+ 17};
1151
+ const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04,
1152
+ 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
1153
+ 0x01,0x02,0x03,0x04,1,0,0,0,
1154
+ 0x89,0x33,0x85,0xce,
1155
+ 13,
1156
+ 254,255,0,255,1,255,245,255,255,0,
1157
+ 255,255,90};
1158
+
1159
+ /* nil packets; beginning,middle,end */
1160
+ const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02,
1161
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1162
+ 0x01,0x02,0x03,0x04,0,0,0,0,
1163
+ 0xff,0x7b,0x23,0x17,
1164
+ 1,
1165
+ 0};
1166
+ const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04,
1167
+ 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
1168
+ 0x01,0x02,0x03,0x04,1,0,0,0,
1169
+ 0x5c,0x3f,0x66,0xcb,
1170
+ 17,
1171
+ 17,254,255,0,0,255,1,0,255,245,255,255,0,
1172
+ 255,255,90,0};
1173
+
1174
+ /* large initial packet */
1175
+ const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02,
1176
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1177
+ 0x01,0x02,0x03,0x04,0,0,0,0,
1178
+ 0x01,0x27,0x31,0xaa,
1179
+ 18,
1180
+ 255,255,255,255,255,255,255,255,
1181
+ 255,255,255,255,255,255,255,255,255,10};
1182
+
1183
+ const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04,
1184
+ 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1185
+ 0x01,0x02,0x03,0x04,1,0,0,0,
1186
+ 0x7f,0x4e,0x8a,0xd2,
1187
+ 4,
1188
+ 255,4,255,0};
1189
+
1190
+
1191
+ /* continuing packet test */
1192
+ const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02,
1193
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1194
+ 0x01,0x02,0x03,0x04,0,0,0,0,
1195
+ 0xff,0x7b,0x23,0x17,
1196
+ 1,
1197
+ 0};
1198
+
1199
+ const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00,
1200
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1201
+ 0x01,0x02,0x03,0x04,1,0,0,0,
1202
+ 0xf8,0x3c,0x19,0x79,
1203
+ 255,
1204
+ 255,255,255,255,255,255,255,255,
1205
+ 255,255,255,255,255,255,255,255,
1206
+ 255,255,255,255,255,255,255,255,
1207
+ 255,255,255,255,255,255,255,255,
1208
+ 255,255,255,255,255,255,255,255,
1209
+ 255,255,255,255,255,255,255,255,
1210
+ 255,255,255,255,255,255,255,255,
1211
+ 255,255,255,255,255,255,255,255,
1212
+ 255,255,255,255,255,255,255,255,
1213
+ 255,255,255,255,255,255,255,255,
1214
+ 255,255,255,255,255,255,255,255,
1215
+ 255,255,255,255,255,255,255,255,
1216
+ 255,255,255,255,255,255,255,255,
1217
+ 255,255,255,255,255,255,255,255,
1218
+ 255,255,255,255,255,255,255,255,
1219
+ 255,255,255,255,255,255,255,255,
1220
+ 255,255,255,255,255,255,255,255,
1221
+ 255,255,255,255,255,255,255,255,
1222
+ 255,255,255,255,255,255,255,255,
1223
+ 255,255,255,255,255,255,255,255,
1224
+ 255,255,255,255,255,255,255,255,
1225
+ 255,255,255,255,255,255,255,255,
1226
+ 255,255,255,255,255,255,255,255,
1227
+ 255,255,255,255,255,255,255,255,
1228
+ 255,255,255,255,255,255,255,255,
1229
+ 255,255,255,255,255,255,255,255,
1230
+ 255,255,255,255,255,255,255,255,
1231
+ 255,255,255,255,255,255,255,255,
1232
+ 255,255,255,255,255,255,255,255,
1233
+ 255,255,255,255,255,255,255,255,
1234
+ 255,255,255,255,255,255,255,255,
1235
+ 255,255,255,255,255,255,255};
1236
+
1237
+ const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05,
1238
+ 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,
1239
+ 0x01,0x02,0x03,0x04,2,0,0,0,
1240
+ 0x38,0xe6,0xb6,0x28,
1241
+ 6,
1242
+ 255,220,255,4,255,0};
1243
+
1244
+
1245
+ /* spill expansion test */
1246
+ const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02,
1247
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1248
+ 0x01,0x02,0x03,0x04,0,0,0,0,
1249
+ 0xff,0x7b,0x23,0x17,
1250
+ 1,
1251
+ 0};
1252
+
1253
+ const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00,
1254
+ 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1255
+ 0x01,0x02,0x03,0x04,1,0,0,0,
1256
+ 0xce,0x8f,0x17,0x1a,
1257
+ 23,
1258
+ 255,255,255,255,255,255,255,255,
1259
+ 255,255,255,255,255,255,255,255,255,10,255,4,255,0,0};
1260
+
1261
+
1262
+ const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04,
1263
+ 0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,
1264
+ 0x01,0x02,0x03,0x04,2,0,0,0,
1265
+ 0x9b,0xb2,0x50,0xa1,
1266
+ 1,
1267
+ 0};
1268
+
1269
+ /* page with the 255 segment limit */
1270
+ const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02,
1271
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1272
+ 0x01,0x02,0x03,0x04,0,0,0,0,
1273
+ 0xff,0x7b,0x23,0x17,
1274
+ 1,
1275
+ 0};
1276
+
1277
+ const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00,
1278
+ 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00,
1279
+ 0x01,0x02,0x03,0x04,1,0,0,0,
1280
+ 0xed,0x2a,0x2e,0xa7,
1281
+ 255,
1282
+ 10,10,10,10,10,10,10,10,
1283
+ 10,10,10,10,10,10,10,10,
1284
+ 10,10,10,10,10,10,10,10,
1285
+ 10,10,10,10,10,10,10,10,
1286
+ 10,10,10,10,10,10,10,10,
1287
+ 10,10,10,10,10,10,10,10,
1288
+ 10,10,10,10,10,10,10,10,
1289
+ 10,10,10,10,10,10,10,10,
1290
+ 10,10,10,10,10,10,10,10,
1291
+ 10,10,10,10,10,10,10,10,
1292
+ 10,10,10,10,10,10,10,10,
1293
+ 10,10,10,10,10,10,10,10,
1294
+ 10,10,10,10,10,10,10,10,
1295
+ 10,10,10,10,10,10,10,10,
1296
+ 10,10,10,10,10,10,10,10,
1297
+ 10,10,10,10,10,10,10,10,
1298
+ 10,10,10,10,10,10,10,10,
1299
+ 10,10,10,10,10,10,10,10,
1300
+ 10,10,10,10,10,10,10,10,
1301
+ 10,10,10,10,10,10,10,10,
1302
+ 10,10,10,10,10,10,10,10,
1303
+ 10,10,10,10,10,10,10,10,
1304
+ 10,10,10,10,10,10,10,10,
1305
+ 10,10,10,10,10,10,10,10,
1306
+ 10,10,10,10,10,10,10,10,
1307
+ 10,10,10,10,10,10,10,10,
1308
+ 10,10,10,10,10,10,10,10,
1309
+ 10,10,10,10,10,10,10,10,
1310
+ 10,10,10,10,10,10,10,10,
1311
+ 10,10,10,10,10,10,10,10,
1312
+ 10,10,10,10,10,10,10,10,
1313
+ 10,10,10,10,10,10,10};
1314
+
1315
+ const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04,
1316
+ 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
1317
+ 0x01,0x02,0x03,0x04,2,0,0,0,
1318
+ 0x6c,0x3b,0x82,0x3d,
1319
+ 1,
1320
+ 50};
1321
+
1322
+
1323
+ /* packet that overspans over an entire page */
1324
+ const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02,
1325
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1326
+ 0x01,0x02,0x03,0x04,0,0,0,0,
1327
+ 0xff,0x7b,0x23,0x17,
1328
+ 1,
1329
+ 0};
1330
+
1331
+ const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00,
1332
+ 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1333
+ 0x01,0x02,0x03,0x04,1,0,0,0,
1334
+ 0x68,0x22,0x7c,0x3d,
1335
+ 255,
1336
+ 100,
1337
+ 255,255,255,255,255,255,255,255,
1338
+ 255,255,255,255,255,255,255,255,
1339
+ 255,255,255,255,255,255,255,255,
1340
+ 255,255,255,255,255,255,255,255,
1341
+ 255,255,255,255,255,255,255,255,
1342
+ 255,255,255,255,255,255,255,255,
1343
+ 255,255,255,255,255,255,255,255,
1344
+ 255,255,255,255,255,255,255,255,
1345
+ 255,255,255,255,255,255,255,255,
1346
+ 255,255,255,255,255,255,255,255,
1347
+ 255,255,255,255,255,255,255,255,
1348
+ 255,255,255,255,255,255,255,255,
1349
+ 255,255,255,255,255,255,255,255,
1350
+ 255,255,255,255,255,255,255,255,
1351
+ 255,255,255,255,255,255,255,255,
1352
+ 255,255,255,255,255,255,255,255,
1353
+ 255,255,255,255,255,255,255,255,
1354
+ 255,255,255,255,255,255,255,255,
1355
+ 255,255,255,255,255,255,255,255,
1356
+ 255,255,255,255,255,255,255,255,
1357
+ 255,255,255,255,255,255,255,255,
1358
+ 255,255,255,255,255,255,255,255,
1359
+ 255,255,255,255,255,255,255,255,
1360
+ 255,255,255,255,255,255,255,255,
1361
+ 255,255,255,255,255,255,255,255,
1362
+ 255,255,255,255,255,255,255,255,
1363
+ 255,255,255,255,255,255,255,255,
1364
+ 255,255,255,255,255,255,255,255,
1365
+ 255,255,255,255,255,255,255,255,
1366
+ 255,255,255,255,255,255,255,255,
1367
+ 255,255,255,255,255,255,255,255,
1368
+ 255,255,255,255,255,255};
1369
+
1370
+ const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01,
1371
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1372
+ 0x01,0x02,0x03,0x04,2,0,0,0,
1373
+ 0xf4,0x87,0xba,0xf3,
1374
+ 255,
1375
+ 255,255,255,255,255,255,255,255,
1376
+ 255,255,255,255,255,255,255,255,
1377
+ 255,255,255,255,255,255,255,255,
1378
+ 255,255,255,255,255,255,255,255,
1379
+ 255,255,255,255,255,255,255,255,
1380
+ 255,255,255,255,255,255,255,255,
1381
+ 255,255,255,255,255,255,255,255,
1382
+ 255,255,255,255,255,255,255,255,
1383
+ 255,255,255,255,255,255,255,255,
1384
+ 255,255,255,255,255,255,255,255,
1385
+ 255,255,255,255,255,255,255,255,
1386
+ 255,255,255,255,255,255,255,255,
1387
+ 255,255,255,255,255,255,255,255,
1388
+ 255,255,255,255,255,255,255,255,
1389
+ 255,255,255,255,255,255,255,255,
1390
+ 255,255,255,255,255,255,255,255,
1391
+ 255,255,255,255,255,255,255,255,
1392
+ 255,255,255,255,255,255,255,255,
1393
+ 255,255,255,255,255,255,255,255,
1394
+ 255,255,255,255,255,255,255,255,
1395
+ 255,255,255,255,255,255,255,255,
1396
+ 255,255,255,255,255,255,255,255,
1397
+ 255,255,255,255,255,255,255,255,
1398
+ 255,255,255,255,255,255,255,255,
1399
+ 255,255,255,255,255,255,255,255,
1400
+ 255,255,255,255,255,255,255,255,
1401
+ 255,255,255,255,255,255,255,255,
1402
+ 255,255,255,255,255,255,255,255,
1403
+ 255,255,255,255,255,255,255,255,
1404
+ 255,255,255,255,255,255,255,255,
1405
+ 255,255,255,255,255,255,255,255,
1406
+ 255,255,255,255,255,255,255};
1407
+
1408
+ const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05,
1409
+ 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1410
+ 0x01,0x02,0x03,0x04,3,0,0,0,
1411
+ 0xf7,0x2f,0x6c,0x60,
1412
+ 5,
1413
+ 254,255,4,255,0};
1414
+
1415
+ /* packet that overspans over an entire page */
1416
+ const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02,
1417
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1418
+ 0x01,0x02,0x03,0x04,0,0,0,0,
1419
+ 0xff,0x7b,0x23,0x17,
1420
+ 1,
1421
+ 0};
1422
+
1423
+ const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00,
1424
+ 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
1425
+ 0x01,0x02,0x03,0x04,1,0,0,0,
1426
+ 0x68,0x22,0x7c,0x3d,
1427
+ 255,
1428
+ 100,
1429
+ 255,255,255,255,255,255,255,255,
1430
+ 255,255,255,255,255,255,255,255,
1431
+ 255,255,255,255,255,255,255,255,
1432
+ 255,255,255,255,255,255,255,255,
1433
+ 255,255,255,255,255,255,255,255,
1434
+ 255,255,255,255,255,255,255,255,
1435
+ 255,255,255,255,255,255,255,255,
1436
+ 255,255,255,255,255,255,255,255,
1437
+ 255,255,255,255,255,255,255,255,
1438
+ 255,255,255,255,255,255,255,255,
1439
+ 255,255,255,255,255,255,255,255,
1440
+ 255,255,255,255,255,255,255,255,
1441
+ 255,255,255,255,255,255,255,255,
1442
+ 255,255,255,255,255,255,255,255,
1443
+ 255,255,255,255,255,255,255,255,
1444
+ 255,255,255,255,255,255,255,255,
1445
+ 255,255,255,255,255,255,255,255,
1446
+ 255,255,255,255,255,255,255,255,
1447
+ 255,255,255,255,255,255,255,255,
1448
+ 255,255,255,255,255,255,255,255,
1449
+ 255,255,255,255,255,255,255,255,
1450
+ 255,255,255,255,255,255,255,255,
1451
+ 255,255,255,255,255,255,255,255,
1452
+ 255,255,255,255,255,255,255,255,
1453
+ 255,255,255,255,255,255,255,255,
1454
+ 255,255,255,255,255,255,255,255,
1455
+ 255,255,255,255,255,255,255,255,
1456
+ 255,255,255,255,255,255,255,255,
1457
+ 255,255,255,255,255,255,255,255,
1458
+ 255,255,255,255,255,255,255,255,
1459
+ 255,255,255,255,255,255,255,255,
1460
+ 255,255,255,255,255,255};
1461
+
1462
+ const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05,
1463
+ 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
1464
+ 0x01,0x02,0x03,0x04,2,0,0,0,
1465
+ 0xd4,0xe0,0x60,0xe5,
1466
+ 1,
1467
+ 0};
1468
+
1469
+ void test_pack(const int *pl, const int **headers, int byteskip,
1470
+ int pageskip, int packetskip){
1471
+ unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
1472
+ long inptr=0;
1473
+ long outptr=0;
1474
+ long deptr=0;
1475
+ long depacket=0;
1476
+ long granule_pos=7,pageno=0;
1477
+ int i,j,packets,pageout=pageskip;
1478
+ int eosflag=0;
1479
+ int bosflag=0;
1480
+
1481
+ int byteskipcount=0;
1482
+
1483
+ ogg_stream_reset(&os_en);
1484
+ ogg_stream_reset(&os_de);
1485
+ ogg_sync_reset(&oy);
1486
+
1487
+ for(packets=0;packets<packetskip;packets++)
1488
+ depacket+=pl[packets];
1489
+
1490
+ for(packets=0;;packets++)if(pl[packets]==-1)break;
1491
+
1492
+ for(i=0;i<packets;i++){
1493
+ /* construct a test packet */
1494
+ ogg_packet op;
1495
+ int len=pl[i];
1496
+
1497
+ op.packet=data+inptr;
1498
+ op.bytes=len;
1499
+ op.e_o_s=(pl[i+1]<0?1:0);
1500
+ op.granulepos=granule_pos;
1501
+
1502
+ granule_pos+=1024;
1503
+
1504
+ for(j=0;j<len;j++)data[inptr++]=i+j;
1505
+
1506
+ /* submit the test packet */
1507
+ ogg_stream_packetin(&os_en,&op);
1508
+
1509
+ /* retrieve any finished pages */
1510
+ {
1511
+ ogg_page og;
1512
+
1513
+ while(ogg_stream_pageout(&os_en,&og)){
1514
+ /* We have a page. Check it carefully */
1515
+
1516
+ fprintf(stderr,"%ld, ",pageno);
1517
+
1518
+ if(headers[pageno]==NULL){
1519
+ fprintf(stderr,"coded too many pages!\n");
1520
+ exit(1);
1521
+ }
1522
+
1523
+ check_page(data+outptr,headers[pageno],&og);
1524
+
1525
+ outptr+=og.body_len;
1526
+ pageno++;
1527
+ if(pageskip){
1528
+ bosflag=1;
1529
+ pageskip--;
1530
+ deptr+=og.body_len;
1531
+ }
1532
+
1533
+ /* have a complete page; submit it to sync/decode */
1534
+
1535
+ {
1536
+ ogg_page og_de;
1537
+ ogg_packet op_de,op_de2;
1538
+ char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
1539
+ char *next=buf;
1540
+ byteskipcount+=og.header_len;
1541
+ if(byteskipcount>byteskip){
1542
+ memcpy(next,og.header,byteskipcount-byteskip);
1543
+ next+=byteskipcount-byteskip;
1544
+ byteskipcount=byteskip;
1545
+ }
1546
+
1547
+ byteskipcount+=og.body_len;
1548
+ if(byteskipcount>byteskip){
1549
+ memcpy(next,og.body,byteskipcount-byteskip);
1550
+ next+=byteskipcount-byteskip;
1551
+ byteskipcount=byteskip;
1552
+ }
1553
+
1554
+ ogg_sync_wrote(&oy,next-buf);
1555
+
1556
+ while(1){
1557
+ int ret=ogg_sync_pageout(&oy,&og_de);
1558
+ if(ret==0)break;
1559
+ if(ret<0)continue;
1560
+ /* got a page. Happy happy. Verify that it's good. */
1561
+
1562
+ fprintf(stderr,"(%d), ",pageout);
1563
+
1564
+ check_page(data+deptr,headers[pageout],&og_de);
1565
+ deptr+=og_de.body_len;
1566
+ pageout++;
1567
+
1568
+ /* submit it to deconstitution */
1569
+ ogg_stream_pagein(&os_de,&og_de);
1570
+
1571
+ /* packets out? */
1572
+ while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
1573
+ ogg_stream_packetpeek(&os_de,NULL);
1574
+ ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
1575
+
1576
+ /* verify peek and out match */
1577
+ if(memcmp(&op_de,&op_de2,sizeof(op_de))){
1578
+ fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
1579
+ depacket);
1580
+ exit(1);
1581
+ }
1582
+
1583
+ /* verify the packet! */
1584
+ /* check data */
1585
+ if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
1586
+ fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
1587
+ depacket);
1588
+ exit(1);
1589
+ }
1590
+ /* check bos flag */
1591
+ if(bosflag==0 && op_de.b_o_s==0){
1592
+ fprintf(stderr,"b_o_s flag not set on packet!\n");
1593
+ exit(1);
1594
+ }
1595
+ if(bosflag && op_de.b_o_s){
1596
+ fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
1597
+ exit(1);
1598
+ }
1599
+ bosflag=1;
1600
+ depacket+=op_de.bytes;
1601
+
1602
+ /* check eos flag */
1603
+ if(eosflag){
1604
+ fprintf(stderr,"Multiple decoded packets with eos flag!\n");
1605
+ exit(1);
1606
+ }
1607
+
1608
+ if(op_de.e_o_s)eosflag=1;
1609
+
1610
+ /* check granulepos flag */
1611
+ if(op_de.granulepos!=-1){
1612
+ fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
1613
+ }
1614
+ }
1615
+ }
1616
+ }
1617
+ }
1618
+ }
1619
+ }
1620
+ _ogg_free(data);
1621
+ if(headers[pageno]!=NULL){
1622
+ fprintf(stderr,"did not write last page!\n");
1623
+ exit(1);
1624
+ }
1625
+ if(headers[pageout]!=NULL){
1626
+ fprintf(stderr,"did not decode last page!\n");
1627
+ exit(1);
1628
+ }
1629
+ if(inptr!=outptr){
1630
+ fprintf(stderr,"encoded page data incomplete!\n");
1631
+ exit(1);
1632
+ }
1633
+ if(inptr!=deptr){
1634
+ fprintf(stderr,"decoded page data incomplete!\n");
1635
+ exit(1);
1636
+ }
1637
+ if(inptr!=depacket){
1638
+ fprintf(stderr,"decoded packet data incomplete!\n");
1639
+ exit(1);
1640
+ }
1641
+ if(!eosflag){
1642
+ fprintf(stderr,"Never got a packet with EOS set!\n");
1643
+ exit(1);
1644
+ }
1645
+ fprintf(stderr,"ok.\n");
1646
+ }
1647
+
1648
+ int main(void){
1649
+
1650
+ ogg_stream_init(&os_en,0x04030201);
1651
+ ogg_stream_init(&os_de,0x04030201);
1652
+ ogg_sync_init(&oy);
1653
+
1654
+ /* Exercise each code path in the framing code. Also verify that
1655
+ the checksums are working. */
1656
+
1657
+ {
1658
+ /* 17 only */
1659
+ const int packets[]={17, -1};
1660
+ const int *headret[]={head1_0,NULL};
1661
+
1662
+ fprintf(stderr,"testing single page encoding... ");
1663
+ test_pack(packets,headret,0,0,0);
1664
+ }
1665
+
1666
+ {
1667
+ /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
1668
+ const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
1669
+ const int *headret[]={head1_1,head2_1,NULL};
1670
+
1671
+ fprintf(stderr,"testing basic page encoding... ");
1672
+ test_pack(packets,headret,0,0,0);
1673
+ }
1674
+
1675
+ {
1676
+ /* nil packets; beginning,middle,end */
1677
+ const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
1678
+ const int *headret[]={head1_2,head2_2,NULL};
1679
+
1680
+ fprintf(stderr,"testing basic nil packets... ");
1681
+ test_pack(packets,headret,0,0,0);
1682
+ }
1683
+
1684
+ {
1685
+ /* large initial packet */
1686
+ const int packets[]={4345,259,255,-1};
1687
+ const int *headret[]={head1_3,head2_3,NULL};
1688
+
1689
+ fprintf(stderr,"testing initial-packet lacing > 4k... ");
1690
+ test_pack(packets,headret,0,0,0);
1691
+ }
1692
+
1693
+ {
1694
+ /* continuing packet test; with page spill expansion, we have to
1695
+ overflow the lacing table. */
1696
+ const int packets[]={0,65500,259,255,-1};
1697
+ const int *headret[]={head1_4,head2_4,head3_4,NULL};
1698
+
1699
+ fprintf(stderr,"testing single packet page span... ");
1700
+ test_pack(packets,headret,0,0,0);
1701
+ }
1702
+
1703
+ {
1704
+ /* spill expand packet test */
1705
+ const int packets[]={0,4345,259,255,0,0,-1};
1706
+ const int *headret[]={head1_4b,head2_4b,head3_4b,NULL};
1707
+
1708
+ fprintf(stderr,"testing page spill expansion... ");
1709
+ test_pack(packets,headret,0,0,0);
1710
+ }
1711
+
1712
+ /* page with the 255 segment limit */
1713
+ {
1714
+
1715
+ const int packets[]={0,10,10,10,10,10,10,10,10,
1716
+ 10,10,10,10,10,10,10,10,
1717
+ 10,10,10,10,10,10,10,10,
1718
+ 10,10,10,10,10,10,10,10,
1719
+ 10,10,10,10,10,10,10,10,
1720
+ 10,10,10,10,10,10,10,10,
1721
+ 10,10,10,10,10,10,10,10,
1722
+ 10,10,10,10,10,10,10,10,
1723
+ 10,10,10,10,10,10,10,10,
1724
+ 10,10,10,10,10,10,10,10,
1725
+ 10,10,10,10,10,10,10,10,
1726
+ 10,10,10,10,10,10,10,10,
1727
+ 10,10,10,10,10,10,10,10,
1728
+ 10,10,10,10,10,10,10,10,
1729
+ 10,10,10,10,10,10,10,10,
1730
+ 10,10,10,10,10,10,10,10,
1731
+ 10,10,10,10,10,10,10,10,
1732
+ 10,10,10,10,10,10,10,10,
1733
+ 10,10,10,10,10,10,10,10,
1734
+ 10,10,10,10,10,10,10,10,
1735
+ 10,10,10,10,10,10,10,10,
1736
+ 10,10,10,10,10,10,10,10,
1737
+ 10,10,10,10,10,10,10,10,
1738
+ 10,10,10,10,10,10,10,10,
1739
+ 10,10,10,10,10,10,10,10,
1740
+ 10,10,10,10,10,10,10,10,
1741
+ 10,10,10,10,10,10,10,10,
1742
+ 10,10,10,10,10,10,10,10,
1743
+ 10,10,10,10,10,10,10,10,
1744
+ 10,10,10,10,10,10,10,10,
1745
+ 10,10,10,10,10,10,10,10,
1746
+ 10,10,10,10,10,10,10,50,-1};
1747
+ const int *headret[]={head1_5,head2_5,head3_5,NULL};
1748
+
1749
+ fprintf(stderr,"testing max packet segments... ");
1750
+ test_pack(packets,headret,0,0,0);
1751
+ }
1752
+
1753
+ {
1754
+ /* packet that overspans over an entire page */
1755
+ const int packets[]={0,100,130049,259,255,-1};
1756
+ const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1757
+
1758
+ fprintf(stderr,"testing very large packets... ");
1759
+ test_pack(packets,headret,0,0,0);
1760
+ }
1761
+
1762
+ {
1763
+ /* test for the libogg 1.1.1 resync in large continuation bug
1764
+ found by Josh Coalson) */
1765
+ const int packets[]={0,100,130049,259,255,-1};
1766
+ const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
1767
+
1768
+ fprintf(stderr,"testing continuation resync in very large packets... ");
1769
+ test_pack(packets,headret,100,2,3);
1770
+ }
1771
+
1772
+ {
1773
+ /* term only page. why not? */
1774
+ const int packets[]={0,100,64770,-1};
1775
+ const int *headret[]={head1_7,head2_7,head3_7,NULL};
1776
+
1777
+ fprintf(stderr,"testing zero data page (1 nil packet)... ");
1778
+ test_pack(packets,headret,0,0,0);
1779
+ }
1780
+
1781
+
1782
+
1783
+ {
1784
+ /* build a bunch of pages for testing */
1785
+ unsigned char *data=_ogg_malloc(1024*1024);
1786
+ int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1};
1787
+ int inptr=0,i,j;
1788
+ ogg_page og[5];
1789
+
1790
+ ogg_stream_reset(&os_en);
1791
+
1792
+ for(i=0;pl[i]!=-1;i++){
1793
+ ogg_packet op;
1794
+ int len=pl[i];
1795
+
1796
+ op.packet=data+inptr;
1797
+ op.bytes=len;
1798
+ op.e_o_s=(pl[i+1]<0?1:0);
1799
+ op.granulepos=(i+1)*1000;
1800
+
1801
+ for(j=0;j<len;j++)data[inptr++]=i+j;
1802
+ ogg_stream_packetin(&os_en,&op);
1803
+ }
1804
+
1805
+ _ogg_free(data);
1806
+
1807
+ /* retrieve finished pages */
1808
+ for(i=0;i<5;i++){
1809
+ if(ogg_stream_pageout(&os_en,&og[i])==0){
1810
+ fprintf(stderr,"Too few pages output building sync tests!\n");
1811
+ exit(1);
1812
+ }
1813
+ copy_page(&og[i]);
1814
+ }
1815
+
1816
+ /* Test lost pages on pagein/packetout: no rollback */
1817
+ {
1818
+ ogg_page temp;
1819
+ ogg_packet test;
1820
+
1821
+ fprintf(stderr,"Testing loss of pages... ");
1822
+
1823
+ ogg_sync_reset(&oy);
1824
+ ogg_stream_reset(&os_de);
1825
+ for(i=0;i<5;i++){
1826
+ memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1827
+ og[i].header_len);
1828
+ ogg_sync_wrote(&oy,og[i].header_len);
1829
+ memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1830
+ ogg_sync_wrote(&oy,og[i].body_len);
1831
+ }
1832
+
1833
+ ogg_sync_pageout(&oy,&temp);
1834
+ ogg_stream_pagein(&os_de,&temp);
1835
+ ogg_sync_pageout(&oy,&temp);
1836
+ ogg_stream_pagein(&os_de,&temp);
1837
+ ogg_sync_pageout(&oy,&temp);
1838
+ /* skip */
1839
+ ogg_sync_pageout(&oy,&temp);
1840
+ ogg_stream_pagein(&os_de,&temp);
1841
+
1842
+ /* do we get the expected results/packets? */
1843
+
1844
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1845
+ checkpacket(&test,0,0,0);
1846
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1847
+ checkpacket(&test,1,1,-1);
1848
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1849
+ checkpacket(&test,1,2,-1);
1850
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1851
+ checkpacket(&test,98,3,-1);
1852
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1853
+ checkpacket(&test,4079,4,5000);
1854
+ if(ogg_stream_packetout(&os_de,&test)!=-1){
1855
+ fprintf(stderr,"Error: loss of page did not return error\n");
1856
+ exit(1);
1857
+ }
1858
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1859
+ checkpacket(&test,76,9,-1);
1860
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1861
+ checkpacket(&test,34,10,-1);
1862
+ fprintf(stderr,"ok.\n");
1863
+ }
1864
+
1865
+ /* Test lost pages on pagein/packetout: rollback with continuation */
1866
+ {
1867
+ ogg_page temp;
1868
+ ogg_packet test;
1869
+
1870
+ fprintf(stderr,"Testing loss of pages (rollback required)... ");
1871
+
1872
+ ogg_sync_reset(&oy);
1873
+ ogg_stream_reset(&os_de);
1874
+ for(i=0;i<5;i++){
1875
+ memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
1876
+ og[i].header_len);
1877
+ ogg_sync_wrote(&oy,og[i].header_len);
1878
+ memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
1879
+ ogg_sync_wrote(&oy,og[i].body_len);
1880
+ }
1881
+
1882
+ ogg_sync_pageout(&oy,&temp);
1883
+ ogg_stream_pagein(&os_de,&temp);
1884
+ ogg_sync_pageout(&oy,&temp);
1885
+ ogg_stream_pagein(&os_de,&temp);
1886
+ ogg_sync_pageout(&oy,&temp);
1887
+ ogg_stream_pagein(&os_de,&temp);
1888
+ ogg_sync_pageout(&oy,&temp);
1889
+ /* skip */
1890
+ ogg_sync_pageout(&oy,&temp);
1891
+ ogg_stream_pagein(&os_de,&temp);
1892
+
1893
+ /* do we get the expected results/packets? */
1894
+
1895
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1896
+ checkpacket(&test,0,0,0);
1897
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1898
+ checkpacket(&test,1,1,-1);
1899
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1900
+ checkpacket(&test,1,2,-1);
1901
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1902
+ checkpacket(&test,98,3,-1);
1903
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1904
+ checkpacket(&test,4079,4,5000);
1905
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1906
+ checkpacket(&test,1,5,-1);
1907
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1908
+ checkpacket(&test,1,6,-1);
1909
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1910
+ checkpacket(&test,2954,7,-1);
1911
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1912
+ checkpacket(&test,2057,8,9000);
1913
+ if(ogg_stream_packetout(&os_de,&test)!=-1){
1914
+ fprintf(stderr,"Error: loss of page did not return error\n");
1915
+ exit(1);
1916
+ }
1917
+ if(ogg_stream_packetout(&os_de,&test)!=1)error();
1918
+ checkpacket(&test,300,17,18000);
1919
+ fprintf(stderr,"ok.\n");
1920
+ }
1921
+
1922
+ /* the rest only test sync */
1923
+ {
1924
+ ogg_page og_de;
1925
+ /* Test fractional page inputs: incomplete capture */
1926
+ fprintf(stderr,"Testing sync on partial inputs... ");
1927
+ ogg_sync_reset(&oy);
1928
+ memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1929
+ 3);
1930
+ ogg_sync_wrote(&oy,3);
1931
+ if(ogg_sync_pageout(&oy,&og_de)>0)error();
1932
+
1933
+ /* Test fractional page inputs: incomplete fixed header */
1934
+ memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
1935
+ 20);
1936
+ ogg_sync_wrote(&oy,20);
1937
+ if(ogg_sync_pageout(&oy,&og_de)>0)error();
1938
+
1939
+ /* Test fractional page inputs: incomplete header */
1940
+ memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
1941
+ 5);
1942
+ ogg_sync_wrote(&oy,5);
1943
+ if(ogg_sync_pageout(&oy,&og_de)>0)error();
1944
+
1945
+ /* Test fractional page inputs: incomplete body */
1946
+
1947
+ memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
1948
+ og[1].header_len-28);
1949
+ ogg_sync_wrote(&oy,og[1].header_len-28);
1950
+ if(ogg_sync_pageout(&oy,&og_de)>0)error();
1951
+
1952
+ memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
1953
+ ogg_sync_wrote(&oy,1000);
1954
+ if(ogg_sync_pageout(&oy,&og_de)>0)error();
1955
+
1956
+ memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
1957
+ og[1].body_len-1000);
1958
+ ogg_sync_wrote(&oy,og[1].body_len-1000);
1959
+ if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1960
+
1961
+ fprintf(stderr,"ok.\n");
1962
+ }
1963
+
1964
+ /* Test fractional page inputs: page + incomplete capture */
1965
+ {
1966
+ ogg_page og_de;
1967
+ fprintf(stderr,"Testing sync on 1+partial inputs... ");
1968
+ ogg_sync_reset(&oy);
1969
+
1970
+ memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1971
+ og[1].header_len);
1972
+ ogg_sync_wrote(&oy,og[1].header_len);
1973
+
1974
+ memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1975
+ og[1].body_len);
1976
+ ogg_sync_wrote(&oy,og[1].body_len);
1977
+
1978
+ memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
1979
+ 20);
1980
+ ogg_sync_wrote(&oy,20);
1981
+ if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1982
+ if(ogg_sync_pageout(&oy,&og_de)>0)error();
1983
+
1984
+ memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
1985
+ og[1].header_len-20);
1986
+ ogg_sync_wrote(&oy,og[1].header_len-20);
1987
+ memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
1988
+ og[1].body_len);
1989
+ ogg_sync_wrote(&oy,og[1].body_len);
1990
+ if(ogg_sync_pageout(&oy,&og_de)<=0)error();
1991
+
1992
+ fprintf(stderr,"ok.\n");
1993
+ }
1994
+
1995
+ /* Test recapture: garbage + page */
1996
+ {
1997
+ ogg_page og_de;
1998
+ fprintf(stderr,"Testing search for capture... ");
1999
+ ogg_sync_reset(&oy);
2000
+
2001
+ /* 'garbage' */
2002
+ memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2003
+ og[1].body_len);
2004
+ ogg_sync_wrote(&oy,og[1].body_len);
2005
+
2006
+ memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2007
+ og[1].header_len);
2008
+ ogg_sync_wrote(&oy,og[1].header_len);
2009
+
2010
+ memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2011
+ og[1].body_len);
2012
+ ogg_sync_wrote(&oy,og[1].body_len);
2013
+
2014
+ memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2015
+ 20);
2016
+ ogg_sync_wrote(&oy,20);
2017
+ if(ogg_sync_pageout(&oy,&og_de)>0)error();
2018
+ if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2019
+ if(ogg_sync_pageout(&oy,&og_de)>0)error();
2020
+
2021
+ memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
2022
+ og[2].header_len-20);
2023
+ ogg_sync_wrote(&oy,og[2].header_len-20);
2024
+ memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2025
+ og[2].body_len);
2026
+ ogg_sync_wrote(&oy,og[2].body_len);
2027
+ if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2028
+
2029
+ fprintf(stderr,"ok.\n");
2030
+ }
2031
+
2032
+ /* Test recapture: page + garbage + page */
2033
+ {
2034
+ ogg_page og_de;
2035
+ fprintf(stderr,"Testing recapture... ");
2036
+ ogg_sync_reset(&oy);
2037
+
2038
+ memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
2039
+ og[1].header_len);
2040
+ ogg_sync_wrote(&oy,og[1].header_len);
2041
+
2042
+ memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
2043
+ og[1].body_len);
2044
+ ogg_sync_wrote(&oy,og[1].body_len);
2045
+
2046
+ memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2047
+ og[2].header_len);
2048
+ ogg_sync_wrote(&oy,og[2].header_len);
2049
+
2050
+ memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
2051
+ og[2].header_len);
2052
+ ogg_sync_wrote(&oy,og[2].header_len);
2053
+
2054
+ if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2055
+
2056
+ memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
2057
+ og[2].body_len-5);
2058
+ ogg_sync_wrote(&oy,og[2].body_len-5);
2059
+
2060
+ memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
2061
+ og[3].header_len);
2062
+ ogg_sync_wrote(&oy,og[3].header_len);
2063
+
2064
+ memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
2065
+ og[3].body_len);
2066
+ ogg_sync_wrote(&oy,og[3].body_len);
2067
+
2068
+ if(ogg_sync_pageout(&oy,&og_de)>0)error();
2069
+ if(ogg_sync_pageout(&oy,&og_de)<=0)error();
2070
+
2071
+ fprintf(stderr,"ok.\n");
2072
+ }
2073
+
2074
+ /* Free page data that was previously copied */
2075
+ {
2076
+ for(i=0;i<5;i++){
2077
+ free_page(&og[i]);
2078
+ }
2079
+ }
2080
+ }
2081
+
2082
+ return(0);
2083
+ }
2084
+
2085
+ #endif
2086
+
2087
+
2088
+
2089
+