diff options
author | Björn Stenberg <bjorn@haxx.se> | 2007-01-08 23:53:00 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2007-01-08 23:53:00 +0000 |
commit | 7039a05147b8bbfc829babea1c65bd436450b505 (patch) | |
tree | 4ba555eb84ed97b72b0575034d5b0530a393713e /songdbj/org/tritonus/lowlevel/pogg/StreamState.java | |
parent | 6d4c19707ef95942e323cbdc89fbbfdbe45e7cc5 (diff) | |
download | rockbox-7039a05147b8bbfc829babea1c65bd436450b505.tar.gz rockbox-7039a05147b8bbfc829babea1c65bd436450b505.zip |
Splitting out songdbj
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11953 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'songdbj/org/tritonus/lowlevel/pogg/StreamState.java')
-rw-r--r-- | songdbj/org/tritonus/lowlevel/pogg/StreamState.java | 703 |
1 files changed, 0 insertions, 703 deletions
diff --git a/songdbj/org/tritonus/lowlevel/pogg/StreamState.java b/songdbj/org/tritonus/lowlevel/pogg/StreamState.java deleted file mode 100644 index 3fde33de8f..0000000000 --- a/songdbj/org/tritonus/lowlevel/pogg/StreamState.java +++ /dev/null | |||
@@ -1,703 +0,0 @@ | |||
1 | /* | ||
2 | * StreamState.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2000 - 2005 by Matthias Pfisterer | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU Library General Public License as published | ||
12 | * by the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU Library General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Library General Public | ||
21 | * License along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | |<--- this code is formatted to fit into 80 columns --->| | ||
27 | */ | ||
28 | |||
29 | package org.tritonus.lowlevel.pogg; | ||
30 | |||
31 | import org.tritonus.share.TDebug; | ||
32 | |||
33 | |||
34 | /** Wrapper for ogg_stream_state. | ||
35 | */ | ||
36 | public class StreamState | ||
37 | { | ||
38 | private static final int INITIAL_BODY_DATA_SIZE = 16 * 1024; | ||
39 | private static final int INITIAL_LACING_VALUES_SIZE = 1024; | ||
40 | |||
41 | /** The serial number of the stream. | ||
42 | This is set by init(). | ||
43 | */ | ||
44 | private int m_nSerialNo; | ||
45 | |||
46 | /** Storage for packet bodies. | ||
47 | */ | ||
48 | private byte[] m_abBodyData; | ||
49 | |||
50 | /** Number of bytes used in te body storage. | ||
51 | */ | ||
52 | private int m_nBodyFill; | ||
53 | |||
54 | /** Number of bytes aready returned (as pages) from the body storage. | ||
55 | */ | ||
56 | private int m_nBodyReturned; | ||
57 | |||
58 | /** Lacing values. Bit 0 to 7 contain the lacing value (mask | ||
59 | 0xFF). Bit 8 is set if the segment belongs to the first | ||
60 | packet of the stream (mask 0x100). Bit 9 is set ig the | ||
61 | segment belongs to the last packet of the stream (mask 0x200). | ||
62 | */ | ||
63 | private int[] m_anLacingValues; | ||
64 | |||
65 | /** Granule values. | ||
66 | */ | ||
67 | private long[] m_alGranuleValues; | ||
68 | |||
69 | /** Number of elements used in m_anLacingValues and m_alGranuleValues. | ||
70 | The elements with the index m_nLacingFill is the first free element. | ||
71 | */ | ||
72 | private int m_nLacingFill; | ||
73 | |||
74 | /** Pointer to the index in m_anLacingValues where the lacing values | ||
75 | of the last decoded packet start (??) | ||
76 | */ | ||
77 | private int m_nLacingPacket; | ||
78 | |||
79 | /** | ||
80 | */ | ||
81 | private int m_nLacingReturned; | ||
82 | |||
83 | private byte[] m_abHeader; | ||
84 | |||
85 | private int m_nHeaderFill; | ||
86 | |||
87 | private boolean m_bBos; | ||
88 | private boolean m_bEos; | ||
89 | private int m_nPageNo; | ||
90 | private long m_lPacketNo; | ||
91 | private long m_lGranulePos; | ||
92 | |||
93 | |||
94 | |||
95 | public StreamState() | ||
96 | { | ||
97 | if (TDebug.TraceOggNative) { TDebug.out("StreamState.<init>(): begin"); } | ||
98 | if (TDebug.TraceOggNative) { TDebug.out("StreamState.<init>(): end"); } | ||
99 | } | ||
100 | |||
101 | |||
102 | |||
103 | public void free() | ||
104 | { | ||
105 | } | ||
106 | |||
107 | |||
108 | |||
109 | /** Calls ogg_stream_init(). | ||
110 | */ | ||
111 | public int init(int nSerialNo) | ||
112 | { | ||
113 | m_nSerialNo = nSerialNo; | ||
114 | m_abBodyData = new byte[INITIAL_BODY_DATA_SIZE]; | ||
115 | m_nBodyFill = 0; | ||
116 | m_nBodyReturned = 0; | ||
117 | m_anLacingValues = new int[INITIAL_LACING_VALUES_SIZE]; | ||
118 | m_alGranuleValues = new long[INITIAL_LACING_VALUES_SIZE]; | ||
119 | m_nLacingFill = 0; | ||
120 | m_nLacingPacket = 0; | ||
121 | m_nLacingReturned = 0; | ||
122 | |||
123 | m_abHeader = new byte[282]; | ||
124 | m_nHeaderFill = 0; | ||
125 | |||
126 | m_bBos = false; | ||
127 | m_bEos = false; | ||
128 | m_nPageNo = 0; | ||
129 | m_lPacketNo = 0; | ||
130 | m_lGranulePos = 0; | ||
131 | |||
132 | // TODO: necessary? | ||
133 | for (int i = 0; i < m_abBodyData.length; i++) | ||
134 | m_abBodyData[i] = 0; | ||
135 | for (int i = 0; i < m_anLacingValues.length; i++) | ||
136 | m_anLacingValues[i] = 0; | ||
137 | for (int i = 0; i < m_alGranuleValues.length; i++) | ||
138 | m_alGranuleValues[i] = 0; | ||
139 | |||
140 | // TODO: remove return value | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | /** Calls ogg_stream_clear(). | ||
145 | */ | ||
146 | public int clear() | ||
147 | { | ||
148 | m_nSerialNo = 0; | ||
149 | m_abBodyData = null; | ||
150 | m_nBodyFill = 0; | ||
151 | m_nBodyReturned = 0; | ||
152 | m_anLacingValues = null; | ||
153 | m_alGranuleValues = null; | ||
154 | m_nLacingFill = 0; | ||
155 | m_nLacingPacket = 0; | ||
156 | m_nLacingReturned = 0; | ||
157 | |||
158 | m_abHeader = null; | ||
159 | m_nHeaderFill = 0; | ||
160 | |||
161 | m_bBos = false; | ||
162 | m_bEos = false; | ||
163 | m_nPageNo = 0; | ||
164 | m_lPacketNo = 0; | ||
165 | m_lGranulePos = 0; | ||
166 | |||
167 | // TODO: remove return value | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | /** Calls ogg_stream_reset(). | ||
172 | */ | ||
173 | public int reset() | ||
174 | { | ||
175 | m_nBodyFill = 0; | ||
176 | m_nBodyReturned = 0; | ||
177 | |||
178 | m_nLacingFill = 0; | ||
179 | m_nLacingPacket = 0; | ||
180 | m_nLacingReturned = 0; | ||
181 | |||
182 | m_nHeaderFill = 0; | ||
183 | |||
184 | m_bBos = false; | ||
185 | m_bEos = false; | ||
186 | m_nPageNo = -1; | ||
187 | m_lPacketNo = 0; | ||
188 | m_lGranulePos = 0; | ||
189 | |||
190 | // TODO: remove return value | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | /** Calls ogg_stream_eos(). | ||
195 | */ | ||
196 | public boolean isEOSReached() | ||
197 | { | ||
198 | return m_bEos; | ||
199 | } | ||
200 | |||
201 | /** Calls ogg_stream_packetin(). | ||
202 | */ | ||
203 | /* submit data to the internal buffer of the framing engine */ | ||
204 | public int packetIn(Packet packet) | ||
205 | { | ||
206 | int i; | ||
207 | byte[] abPacketData = packet.getData(); | ||
208 | int lacing_vals = abPacketData.length / 255 + 1; | ||
209 | |||
210 | if (m_nBodyReturned > 0) | ||
211 | { | ||
212 | /* advance packet data according to the body_returned pointer. We | ||
213 | had to keep it around to return a pointer into the buffer last | ||
214 | call */ | ||
215 | m_nBodyFill -= m_nBodyReturned; | ||
216 | if (m_nBodyFill > 0) | ||
217 | { | ||
218 | System.arraycopy(m_abBodyData, m_nBodyReturned, | ||
219 | m_abBodyData, 0, m_nBodyFill); | ||
220 | } | ||
221 | m_nBodyReturned = 0; | ||
222 | } | ||
223 | |||
224 | /* make sure we have the buffer storage */ | ||
225 | assureBodyDataCapacity(abPacketData.length); | ||
226 | assureLacingValuesCapacity(lacing_vals); | ||
227 | |||
228 | /* Copy in the submitted packet. Yes, the copy is a waste; | ||
229 | this is the liability of overly clean abstraction for the | ||
230 | time being. It will actually be fairly easy to eliminate | ||
231 | the extra copy in the future */ | ||
232 | System.arraycopy(abPacketData, 0, m_abBodyData, m_nBodyFill, | ||
233 | abPacketData.length); | ||
234 | m_nBodyFill += abPacketData.length; | ||
235 | |||
236 | /* Store lacing vals for this packet */ | ||
237 | for (i = 0; i < lacing_vals - 1; i++) | ||
238 | { | ||
239 | m_anLacingValues[m_nLacingFill + i] = 255; | ||
240 | m_alGranuleValues[m_nLacingFill + i] = m_lGranulePos; | ||
241 | } | ||
242 | m_anLacingValues[m_nLacingFill + i] = abPacketData.length % 255; | ||
243 | m_alGranuleValues[m_nLacingFill + i] = packet.getGranulePos(); | ||
244 | m_lGranulePos = packet.getGranulePos(); | ||
245 | |||
246 | /* flag the first segment as the beginning of the packet */ | ||
247 | m_anLacingValues[m_nLacingFill] |= 0x100; | ||
248 | |||
249 | m_nLacingFill += lacing_vals; | ||
250 | |||
251 | /* for the sake of completeness */ | ||
252 | m_lPacketNo++; | ||
253 | |||
254 | if (packet.isEos()) | ||
255 | m_bEos = true; | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | |||
260 | |||
261 | /** Calls ogg_stream_pageout(). | ||
262 | */ | ||
263 | /* This constructs pages from buffered packet segments. The pointers | ||
264 | returned are to static buffers; do not free. The returned buffers are | ||
265 | good only until the next call (using the same ogg_stream_state) */ | ||
266 | public int pageOut(Page page) | ||
267 | { | ||
268 | if ((m_bEos && m_nLacingFill > 0) || /* 'were done, now flush' */ | ||
269 | m_nBodyFill - m_nBodyReturned > 4096 || /* 'page nominal size' */ | ||
270 | m_nLacingFill >= 255 || /* 'segment table full' */ | ||
271 | (m_nLacingFill > 0 && ! m_bBos)) /* 'initial header page' */ | ||
272 | { | ||
273 | return flush(page); | ||
274 | } | ||
275 | /* not enough data to construct a page and not end of stream */ | ||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | |||
280 | |||
281 | /** Calls ogg_stream_flush(). | ||
282 | */ | ||
283 | /* This will flush remaining packets into a page (returning nonzero), | ||
284 | even if there is not enough data to trigger a flush normally | ||
285 | (undersized page). If there are no packets or partial packets to | ||
286 | flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will | ||
287 | try to flush a normal sized page like ogg_stream_pageout; a call to | ||
288 | ogg_stream_flush does not guarantee that all packets have flushed. | ||
289 | Only a return value of 0 from ogg_stream_flush indicates all packet | ||
290 | data is flushed into pages. | ||
291 | |||
292 | since ogg_stream_flush will flush the last page in a stream even if | ||
293 | it's undersized, you almost certainly want to use ogg_stream_pageout | ||
294 | (and *not* ogg_stream_flush) unless you specifically need to flush | ||
295 | an page regardless of size in the middle of a stream. | ||
296 | */ | ||
297 | public int flush(Page page) | ||
298 | { | ||
299 | int i; | ||
300 | int vals = 0; | ||
301 | int maxvals = Math.min(m_nLacingFill, 255); | ||
302 | int bytes = 0; | ||
303 | int acc = 0; | ||
304 | long granule_pos = m_alGranuleValues[0]; | ||
305 | |||
306 | if (maxvals == 0) | ||
307 | { | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | /* construct a page */ | ||
312 | /* decide how many segments to include */ | ||
313 | |||
314 | /* If this is the initial header case, the first page must | ||
315 | only include the initial header packet */ | ||
316 | if (! m_bBos) | ||
317 | { /* 'initial header page' case */ | ||
318 | granule_pos = 0; | ||
319 | for (vals = 0; vals < maxvals; vals++) | ||
320 | { | ||
321 | if ((m_anLacingValues[vals] & 0x0FF) < 255) | ||
322 | { | ||
323 | vals++; | ||
324 | break; | ||
325 | } | ||
326 | } | ||
327 | } | ||
328 | else | ||
329 | { | ||
330 | for (vals = 0; vals < maxvals; vals++) | ||
331 | { | ||
332 | if (acc > 4096) | ||
333 | break; | ||
334 | acc += (m_anLacingValues[vals] & 0x0FF); | ||
335 | granule_pos = m_alGranuleValues[vals]; | ||
336 | } | ||
337 | } | ||
338 | |||
339 | /* construct the header in temp storage */ | ||
340 | m_abHeader[0] = (byte) 'O'; | ||
341 | m_abHeader[1] = (byte) 'g'; | ||
342 | m_abHeader[2] = (byte) 'g'; | ||
343 | m_abHeader[3] = (byte) 'S'; | ||
344 | |||
345 | /* stream structure version */ | ||
346 | m_abHeader[4] = 0; | ||
347 | |||
348 | m_abHeader[5] = 0x00; | ||
349 | /* continued packet flag? */ | ||
350 | if ((m_anLacingValues[0] & 0x100) == 0) | ||
351 | m_abHeader[5] |= 0x01; | ||
352 | /* first page flag? */ | ||
353 | if (! m_bBos) | ||
354 | m_abHeader[5] |= 0x02; | ||
355 | /* last page flag? */ | ||
356 | if (m_bEos && m_nLacingFill == vals) | ||
357 | m_abHeader[5] |= 0x04; | ||
358 | m_bBos = true; | ||
359 | |||
360 | /* 64 bits of PCM position */ | ||
361 | for (i = 6; i < 14; i++) | ||
362 | { | ||
363 | m_abHeader[i] = (byte) (granule_pos & 0xFF); | ||
364 | granule_pos >>>= 8; | ||
365 | } | ||
366 | |||
367 | /* 32 bits of stream serial number */ | ||
368 | int serialno = m_nSerialNo; | ||
369 | for (i = 14; i < 18; i++) | ||
370 | { | ||
371 | m_abHeader[i] = (byte) (serialno & 0xFF); | ||
372 | serialno >>>= 8; | ||
373 | } | ||
374 | |||
375 | /* 32 bits of page counter (we have both counter and page header | ||
376 | because this val can roll over) */ | ||
377 | if (m_nPageNo == -1) | ||
378 | { | ||
379 | m_nPageNo = 0; /* because someone called | ||
380 | stream_reset; this would be a | ||
381 | strange thing to do in an | ||
382 | encode stream, but it has | ||
383 | plausible uses */ | ||
384 | } | ||
385 | int pageno = m_nPageNo++; | ||
386 | for (i = 18; i < 22; i++) | ||
387 | { | ||
388 | m_abHeader[i] = (byte) (pageno & 0xFF); | ||
389 | pageno >>>= 8; | ||
390 | } | ||
391 | |||
392 | /* zero for computation; filled in later */ | ||
393 | m_abHeader[22] = 0; | ||
394 | m_abHeader[23] = 0; | ||
395 | m_abHeader[24] = 0; | ||
396 | m_abHeader[25] = 0; | ||
397 | |||
398 | /* segment table */ | ||
399 | m_abHeader[26] = (byte) (vals & 0xFF); | ||
400 | for (i = 0; i < vals; i++) | ||
401 | { | ||
402 | m_abHeader[i + 27] = (byte) (m_anLacingValues[i] & 0xFF); | ||
403 | bytes += (m_anLacingValues[i] & 0xFF); | ||
404 | } | ||
405 | |||
406 | /* set pointers in the ogg_page struct */ | ||
407 | page.setData(m_abHeader, 0, vals + 27, | ||
408 | m_abBodyData, m_nBodyReturned, bytes); | ||
409 | m_nHeaderFill = vals + 27; | ||
410 | |||
411 | /* advance the lacing data and set the body_returned pointer */ | ||
412 | |||
413 | m_nLacingFill -= vals; | ||
414 | System.arraycopy(m_anLacingValues, vals, m_anLacingValues, 0, | ||
415 | m_nLacingFill); | ||
416 | System.arraycopy(m_alGranuleValues, vals, m_alGranuleValues, 0, | ||
417 | m_nLacingFill); | ||
418 | m_nBodyReturned += bytes; | ||
419 | |||
420 | /* calculate the checksum */ | ||
421 | |||
422 | page.setChecksum(); | ||
423 | |||
424 | /* done */ | ||
425 | return 1; | ||
426 | } | ||
427 | |||
428 | |||
429 | |||
430 | /** add the incoming page to the stream state; we decompose the | ||
431 | page into packet segments here as well. | ||
432 | |||
433 | @return 0 on success, -1 if the stream serial number stored in | ||
434 | the page does not match the one stored in the stream state or | ||
435 | if the protocol version stored in the page is greater than 0. | ||
436 | */ | ||
437 | public int pageIn(Page page) | ||
438 | { | ||
439 | byte[] header = page.getHeader(); | ||
440 | byte[] body = page.getBody(); | ||
441 | int nBodyOffset = 0; | ||
442 | int bodysize = body.length; | ||
443 | int segptr = 0; | ||
444 | |||
445 | int version = page.getVersion(); | ||
446 | boolean continued = page.isContinued(); | ||
447 | boolean bos = page.isBos(); | ||
448 | boolean eos = page.isEos(); | ||
449 | long granulepos = page.getGranulePos(); | ||
450 | int serialno = page.getSerialNo(); | ||
451 | int pageno = page.getPageNo(); | ||
452 | int segments = header[26] & 0xFF; | ||
453 | |||
454 | /* clean up 'returned data' */ | ||
455 | int lr = m_nLacingReturned; | ||
456 | int br = m_nBodyReturned; | ||
457 | |||
458 | /* body data */ | ||
459 | if (br > 0) | ||
460 | { | ||
461 | m_nBodyFill -= br; | ||
462 | if (m_nBodyFill > 0) | ||
463 | { | ||
464 | System.arraycopy(m_abBodyData, br, m_abBodyData, 0, | ||
465 | m_nBodyFill); | ||
466 | } | ||
467 | m_nBodyReturned = 0; | ||
468 | } | ||
469 | |||
470 | if (lr > 0) | ||
471 | { | ||
472 | /* segment table */ | ||
473 | if (m_nLacingFill - lr > 0) | ||
474 | { | ||
475 | System.arraycopy(m_anLacingValues, lr, m_anLacingValues, 0, | ||
476 | m_nLacingFill - lr); | ||
477 | System.arraycopy(m_alGranuleValues, lr, m_alGranuleValues, 0, | ||
478 | m_nLacingFill - lr); | ||
479 | } | ||
480 | m_nLacingFill -= lr; | ||
481 | m_nLacingPacket -= lr; | ||
482 | m_nLacingReturned = 0; | ||
483 | } | ||
484 | |||
485 | /* check the serial number */ | ||
486 | if (serialno != m_nSerialNo) | ||
487 | return -1; | ||
488 | if (version > 0) | ||
489 | return -1; | ||
490 | |||
491 | assureLacingValuesCapacity(segments + 1); | ||
492 | |||
493 | /* are we in sequence? */ | ||
494 | if (pageno != m_nPageNo) | ||
495 | { | ||
496 | int i; | ||
497 | |||
498 | /* unroll previous partial packet (if any) */ | ||
499 | for (i = m_nLacingPacket; i < m_nLacingFill; i++) | ||
500 | m_nBodyFill -= (m_anLacingValues[i] & 0xFF); | ||
501 | m_nLacingFill = m_nLacingPacket; | ||
502 | |||
503 | /* make a note of dropped data in segment table */ | ||
504 | if (m_nPageNo != -1) | ||
505 | { | ||
506 | m_anLacingValues[m_nLacingFill] = 0x400; | ||
507 | m_nLacingFill++; | ||
508 | m_nLacingPacket++; | ||
509 | } | ||
510 | |||
511 | /* are we a 'continued packet' page? If so, we'll need to skip | ||
512 | some segments */ | ||
513 | if (continued) | ||
514 | { | ||
515 | bos = false; | ||
516 | for (; segptr < segments; segptr++) | ||
517 | { | ||
518 | int val = header[27 + segptr] & 0xFF; | ||
519 | nBodyOffset += val; | ||
520 | bodysize -= val; | ||
521 | if (val < 255) | ||
522 | { | ||
523 | segptr++; | ||
524 | break; | ||
525 | } | ||
526 | } | ||
527 | } | ||
528 | } | ||
529 | |||
530 | if (bodysize > 0) | ||
531 | { | ||
532 | assureBodyDataCapacity(bodysize); | ||
533 | System.arraycopy(body, nBodyOffset, m_abBodyData, m_nBodyFill, | ||
534 | bodysize); | ||
535 | m_nBodyFill += bodysize; | ||
536 | } | ||
537 | |||
538 | int saved = -1; | ||
539 | while (segptr < segments) | ||
540 | { | ||
541 | int val = header[27 + segptr] & 0xFF; | ||
542 | m_anLacingValues[m_nLacingFill] = val; | ||
543 | m_alGranuleValues[m_nLacingFill] = -1; | ||
544 | |||
545 | if (bos) | ||
546 | { | ||
547 | m_anLacingValues[m_nLacingFill] |= 0x100; | ||
548 | bos = false; | ||
549 | } | ||
550 | |||
551 | if (val < 255) | ||
552 | saved = m_nLacingFill; | ||
553 | |||
554 | m_nLacingFill++; | ||
555 | segptr++; | ||
556 | |||
557 | if (val < 255) | ||
558 | m_nLacingPacket = m_nLacingFill; | ||
559 | } | ||
560 | |||
561 | /* set the granulepos on the last granuleval of the last full packet */ | ||
562 | if (saved != -1) | ||
563 | { | ||
564 | m_alGranuleValues[saved] = granulepos; | ||
565 | } | ||
566 | |||
567 | if (eos) | ||
568 | { | ||
569 | m_bEos = true; | ||
570 | if (m_nLacingFill > 0) | ||
571 | m_anLacingValues[m_nLacingFill - 1] |= 0x200; | ||
572 | } | ||
573 | |||
574 | m_nPageNo = pageno + 1; | ||
575 | |||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | |||
580 | /** Calls ogg_stream_packetout(). | ||
581 | */ | ||
582 | public int packetOut(Packet packet) | ||
583 | { | ||
584 | return packetOutInternal(packet, true); | ||
585 | } | ||
586 | |||
587 | |||
588 | /** Calls ogg_stream_packetpeek(). | ||
589 | */ | ||
590 | public int packetPeek(Packet packet) | ||
591 | { | ||
592 | return packetOutInternal(packet, false); | ||
593 | } | ||
594 | |||
595 | |||
596 | /** Retrieves a packet from the internal storage for emission. | ||
597 | This method is called by packetOut and packetPeek. | ||
598 | |||
599 | @param packet the Packet object to store the retrieved packet | ||
600 | data in. May be null if bAdvance is false. | ||
601 | |||
602 | @param bAdvance should the internal pointers to the packet | ||
603 | data storage be advanced to the next packet after retrieving | ||
604 | this one? Called with a value of true for ordinary packet out | ||
605 | and with a value of false for packet peek. | ||
606 | |||
607 | @return | ||
608 | */ | ||
609 | private int packetOutInternal(Packet packet, boolean bAdvance) | ||
610 | { | ||
611 | /* The last part of decode. We have the stream broken into | ||
612 | packet segments. Now we need to group them into packets | ||
613 | (or return the out of sync markers) */ | ||
614 | |||
615 | int ptr = m_nLacingReturned; | ||
616 | |||
617 | if (m_nLacingPacket <= ptr) | ||
618 | return 0; | ||
619 | |||
620 | if ((m_anLacingValues[ptr] & 0x400) != 0) | ||
621 | { | ||
622 | /* we need to tell the codec there's a gap; it might need | ||
623 | to handle previous packet dependencies. */ | ||
624 | m_nLacingReturned++; | ||
625 | m_lPacketNo++; | ||
626 | return -1; | ||
627 | } | ||
628 | |||
629 | if (packet == null && ! bAdvance) | ||
630 | return 1; /* just using peek as an inexpensive way | ||
631 | to ask if there's a whole packet | ||
632 | waiting */ | ||
633 | |||
634 | /* Gather the whole packet. We'll have no holes or a partial | ||
635 | * packet */ | ||
636 | int size = m_anLacingValues[ptr] & 0xFF; | ||
637 | int bytes = size; | ||
638 | /* last packet of the stream? */ | ||
639 | boolean eos = (m_anLacingValues[ptr] & 0x200) != 0; | ||
640 | /* first packet of the stream? */ | ||
641 | boolean bos = (m_anLacingValues[ptr] & 0x100) != 0; | ||
642 | |||
643 | while (size == 255) | ||
644 | { | ||
645 | int val = m_anLacingValues[++ptr]; | ||
646 | size = val & 0xff; | ||
647 | if ((val & 0x200) != 0) | ||
648 | eos = true; | ||
649 | bytes += size; | ||
650 | } | ||
651 | |||
652 | if (packet != null) | ||
653 | { | ||
654 | packet.setData(m_abBodyData, m_nBodyReturned, bytes); | ||
655 | packet.setFlags(bos, eos, m_alGranuleValues[ptr], m_lPacketNo); | ||
656 | } | ||
657 | |||
658 | if (bAdvance) | ||
659 | { | ||
660 | m_nBodyReturned += bytes; | ||
661 | m_nLacingReturned = ptr + 1; | ||
662 | m_lPacketNo++; | ||
663 | } | ||
664 | return 1; | ||
665 | } | ||
666 | |||
667 | |||
668 | private void assureBodyDataCapacity(int needed) | ||
669 | { | ||
670 | if (m_abBodyData.length <= m_nBodyFill + needed) | ||
671 | { | ||
672 | int nNewSize = m_abBodyData.length + needed + 1024; | ||
673 | byte[] abNewBodyData = new byte[nNewSize]; | ||
674 | System.arraycopy(m_abBodyData, 0, abNewBodyData, 0, | ||
675 | m_abBodyData.length); | ||
676 | m_abBodyData = abNewBodyData; | ||
677 | } | ||
678 | } | ||
679 | |||
680 | |||
681 | |||
682 | private void assureLacingValuesCapacity(int needed) | ||
683 | { | ||
684 | if (m_anLacingValues.length <= m_nLacingFill + needed) | ||
685 | { | ||
686 | int nNewSize = m_anLacingValues.length + needed + 32; | ||
687 | int[] anNewLacingValues = new int[nNewSize]; | ||
688 | System.arraycopy(m_anLacingValues, 0, anNewLacingValues, 0, | ||
689 | m_anLacingValues.length); | ||
690 | m_anLacingValues = anNewLacingValues; | ||
691 | long[] alNewGranuleValues = new long[nNewSize]; | ||
692 | System.arraycopy(m_alGranuleValues, 0, alNewGranuleValues, 0, | ||
693 | m_alGranuleValues.length); | ||
694 | m_alGranuleValues = alNewGranuleValues; | ||
695 | } | ||
696 | } | ||
697 | } | ||
698 | |||
699 | |||
700 | |||
701 | |||
702 | |||
703 | /*** StreamState.java ***/ | ||