]> Joshua Wise's Git repositories - patchfork.git/blame - jorbis/src/com/jcraft/jogg/SyncState.java
initial import from pitchfork-0.5.5
[patchfork.git] / jorbis / src / com / jcraft / jogg / SyncState.java
CommitLineData
964dd0bc
JW
1/* JOrbis
2 * Copyright (C) 2000 ymnk, JCraft,Inc.
3 *
4 * Written by: 2000 ymnk<ymnk@jcraft.com>
5 *
6 * Many thanks to
7 * Monty <monty@xiph.org> and
8 * The XIPHOPHORUS Company http://www.xiph.org/ .
9 * JOrbis has been based on their awesome works, Vorbis codec.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public License
13 * as published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
20 *
21 * You should have received a copy of the GNU Library General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26package com.jcraft.jogg;
27
28// DECODING PRIMITIVES: packet streaming layer
29
30// This has two layers to place more of the multi-serialno and paging
31// control in the application's hands. First, we expose a data buffer
32// using ogg_decode_buffer(). The app either copies into the
33// buffer, or passes it directly to read(), etc. We then call
34// ogg_decode_wrote() to tell how many bytes we just added.
35//
36// Pages are returned (pointers into the buffer in ogg_sync_state)
37// by ogg_decode_stream(). The page is then submitted to
38// ogg_decode_page() along with the appropriate
39// ogg_stream_state* (ie, matching serialno). We then get raw
40// packets out calling ogg_stream_packet() with a
41// ogg_stream_state. See the 'frame-prog.txt' docs for details and
42// example code.
43
44public class SyncState{
45
46 public byte[] data;
47 int storage;
48 int fill;
49 int returned;
50
51 int unsynced;
52 int headerbytes;
53 int bodybytes;
54
55 public int clear(){
56 data=null;
57 return(0);
58 }
59
60// !!!!!!!!!!!!
61// byte[] buffer(int size){
62 public int buffer(int size){
63 // first, clear out any space that has been previously returned
64 if(returned!=0){
65 fill-=returned;
66 if(fill>0){
67 System.arraycopy(data, returned, data, 0, fill);
68 }
69 returned=0;
70 }
71
72 if(size>storage-fill){
73 // We need to extend the internal buffer
74 int newsize=size+fill+4096; // an extra page to be nice
75 if(data!=null){
76 byte[] foo=new byte[newsize];
77 System.arraycopy(data, 0, foo, 0, data.length);
78 data=foo;
79 }
80 else{
81 data=new byte[newsize];
82 }
83 storage=newsize;
84 }
85
86 // expose a segment at least as large as requested at the fill mark
87// return((char *)oy->data+oy->fill);
88// return(data);
89 return(fill);
90 }
91
92 public int wrote(int bytes){
93 if(fill+bytes>storage)return(-1);
94 fill+=bytes;
95 return(0);
96 }
97
98// sync the stream. This is meant to be useful for finding page
99// boundaries.
100//
101// return values for this:
102// -n) skipped n bytes
103// 0) page not ready; more data (no bytes skipped)
104// n) page synced at current location; page length n bytes
105 private Page pageseek=new Page();
106 private byte[] chksum=new byte[4];
107 public int pageseek(Page og){
108 int page=returned;
109 int next;
110 int bytes=fill-returned;
111
112 if(headerbytes==0){
113 int _headerbytes,i;
114 if(bytes<27)return(0); // not enough for a header
115
116 /* verify capture pattern */
117//!!!!!!!!!!!
118 if(data[page]!='O' ||
119 data[page+1]!='g' ||
120 data[page+2]!='g' ||
121 data[page+3]!='S'){
122 headerbytes=0;
123 bodybytes=0;
124
125 // search for possible capture
126 next=0;
127 for(int ii=0; ii<bytes-1; ii++){
128 if(data[page+1+ii]=='O'){next=page+1+ii; break;}
129 }
130 //next=memchr(page+1,'O',bytes-1);
131 if(next==0) next=fill;
132
133 returned=next;
134 return(-(next-page));
135 }
136 _headerbytes=(data[page+26]&0xff)+27;
137 if(bytes<_headerbytes)return(0); // not enough for header + seg table
138
139 // count up body length in the segment table
140
141 for(i=0;i<(data[page+26]&0xff);i++){
142 bodybytes+=(data[page+27+i]&0xff);
143 }
144 headerbytes=_headerbytes;
145 }
146
147 if(bodybytes+headerbytes>bytes)return(0);
148
149 // The whole test page is buffered. Verify the checksum
150 synchronized(chksum){
151 // Grab the checksum bytes, set the header field to zero
152
153 System.arraycopy(data, page+22, chksum, 0, 4);
154 data[page+22]=0;
155 data[page+23]=0;
156 data[page+24]=0;
157 data[page+25]=0;
158
159 // set up a temp page struct and recompute the checksum
160 Page log=pageseek;
161 log.header_base=data;
162 log.header=page;
163 log.header_len=headerbytes;
164
165 log.body_base=data;
166 log.body=page+headerbytes;
167 log.body_len=bodybytes;
168 log.checksum();
169
170 // Compare
171 if(chksum[0]!=data[page+22] ||
172 chksum[1]!=data[page+23] ||
173 chksum[2]!=data[page+24] ||
174 chksum[3]!=data[page+25]){
175 // D'oh. Mismatch! Corrupt page (or miscapture and not a page at all)
176 // replace the computed checksum with the one actually read in
177 System.arraycopy(chksum, 0, data, page+22, 4);
178 // Bad checksum. Lose sync */
179
180 headerbytes=0;
181 bodybytes=0;
182 // search for possible capture
183 next=0;
184 for(int ii=0; ii<bytes-1; ii++){
185 if(data[page+1+ii]=='O'){next=page+1+ii; break;}
186 }
187 //next=memchr(page+1,'O',bytes-1);
188 if(next==0) next=fill;
189 returned=next;
190 return(-(next-page));
191 }
192 }
193
194 // yes, have a whole page all ready to go
195 {
196 page=returned;
197
198 if(og!=null){
199 og.header_base=data;
200 og.header=page;
201 og.header_len=headerbytes;
202 og.body_base=data;
203 og.body=page+headerbytes;
204 og.body_len=bodybytes;
205 }
206
207 unsynced=0;
208 returned+=(bytes=headerbytes+bodybytes);
209 headerbytes=0;
210 bodybytes=0;
211 return(bytes);
212 }
213// headerbytes=0;
214// bodybytes=0;
215// next=0;
216// for(int ii=0; ii<bytes-1; ii++){
217// if(data[page+1+ii]=='O'){next=page+1+ii;}
218// }
219// //next=memchr(page+1,'O',bytes-1);
220// if(next==0) next=fill;
221// returned=next;
222// return(-(next-page));
223 }
224
225
226// sync the stream and get a page. Keep trying until we find a page.
227// Supress 'sync errors' after reporting the first.
228//
229// return values:
230// -1) recapture (hole in data)
231// 0) need more data
232// 1) page returned
233//
234// Returns pointers into buffered data; invalidated by next call to
235// _stream, _clear, _init, or _buffer
236
237 public int pageout(Page og){
238 // all we need to do is verify a page at the head of the stream
239 // buffer. If it doesn't verify, we look for the next potential
240 // frame
241
242 while(true){
243 int ret=pageseek(og);
244 if(ret>0){
245 // have a page
246 return(1);
247 }
248 if(ret==0){
249 // need more data
250 return(0);
251 }
252
253 // head did not start a synced page... skipped some bytes
254 if(unsynced==0){
255 unsynced=1;
256 return(-1);
257 }
258 // loop. keep looking
259 }
260 }
261
262// clear things to an initial state. Good to call, eg, before seeking
263 public int reset(){
264 fill=0;
265 returned=0;
266 unsynced=0;
267 headerbytes=0;
268 bodybytes=0;
269 return(0);
270 }
271 public void init(){}
272
273 public int getDataOffset(){ return returned; }
274 public int getBufferOffset(){ return fill; }
275}
This page took 0.044051 seconds and 4 git commands to generate.