summaryrefslogtreecommitdiff
path: root/songdbj/org/tritonus/lowlevel/pogg/StreamState.java
diff options
context:
space:
mode:
Diffstat (limited to 'songdbj/org/tritonus/lowlevel/pogg/StreamState.java')
-rw-r--r--songdbj/org/tritonus/lowlevel/pogg/StreamState.java703
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
29package org.tritonus.lowlevel.pogg;
30
31import org.tritonus.share.TDebug;
32
33
34/** Wrapper for ogg_stream_state.
35 */
36public 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 ***/