summaryrefslogtreecommitdiff
path: root/songdbj/javazoom/jl/decoder/Bitstream.java
diff options
context:
space:
mode:
authorMichiel Van Der Kolk <not.valid@email.address>2005-07-11 15:42:37 +0000
committerMichiel Van Der Kolk <not.valid@email.address>2005-07-11 15:42:37 +0000
commit9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e (patch)
tree4c304cd4151020bd5494d279ee68a105ae3a5a3a /songdbj/javazoom/jl/decoder/Bitstream.java
parentdfa8ecbe609ca8ea194d08560a44fb9a92e94b4b (diff)
downloadrockbox-9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e.tar.gz
rockbox-9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e.zip
Songdb java version, source. only 1.5 compatible
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7101 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'songdbj/javazoom/jl/decoder/Bitstream.java')
-rw-r--r--songdbj/javazoom/jl/decoder/Bitstream.java655
1 files changed, 655 insertions, 0 deletions
diff --git a/songdbj/javazoom/jl/decoder/Bitstream.java b/songdbj/javazoom/jl/decoder/Bitstream.java
new file mode 100644
index 0000000000..cebbd5b03b
--- /dev/null
+++ b/songdbj/javazoom/jl/decoder/Bitstream.java
@@ -0,0 +1,655 @@
1/*
2 * 11/19/04 1.0 moved to LGPL.
3 *
4 * 11/17/04 Uncomplete frames discarded. E.B, javalayer@javazoom.net
5 *
6 * 12/05/03 ID3v2 tag returned. E.B, javalayer@javazoom.net
7 *
8 * 12/12/99 Based on Ibitstream. Exceptions thrown on errors,
9 * Temporary removed seek functionality. mdm@techie.com
10 *
11 * 02/12/99 : Java Conversion by E.B , javalayer@javazoom.net
12 *
13 * 04/14/97 : Added function prototypes for new syncing and seeking
14 * mechanisms. Also made this file portable. Changes made by Jeff Tsay
15 *
16 * @(#) ibitstream.h 1.5, last edit: 6/15/94 16:55:34
17 * @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
18 * @(#) Berlin University of Technology
19 *-----------------------------------------------------------------------
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU Library General Public License as published
22 * by the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU Library General Public License for more details.
29 *
30 * You should have received a copy of the GNU Library General Public
31 * License along with this program; if not, write to the Free Software
32 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 *----------------------------------------------------------------------
34 */
35
36package javazoom.jl.decoder;
37
38import java.io.BufferedInputStream;
39import java.io.ByteArrayInputStream;
40import java.io.IOException;
41import java.io.InputStream;
42import java.io.PushbackInputStream;
43
44
45/**
46 * The <code>Bistream</code> class is responsible for parsing
47 * an MPEG audio bitstream.
48 *
49 * <b>REVIEW:</b> much of the parsing currently occurs in the
50 * various decoders. This should be moved into this class and associated
51 * inner classes.
52 */
53public final class Bitstream implements BitstreamErrors
54{
55 /**
56 * Synchronization control constant for the initial
57 * synchronization to the start of a frame.
58 */
59 static byte INITIAL_SYNC = 0;
60
61 /**
62 * Synchronization control constant for non-initial frame
63 * synchronizations.
64 */
65 static byte STRICT_SYNC = 1;
66
67 // max. 1730 bytes per frame: 144 * 384kbit/s / 32000 Hz + 2 Bytes CRC
68 /**
69 * Maximum size of the frame buffer.
70 */
71 private static final int BUFFER_INT_SIZE = 433;
72
73 /**
74 * The frame buffer that holds the data for the current frame.
75 */
76 private final int[] framebuffer = new int[BUFFER_INT_SIZE];
77
78 /**
79 * Number of valid bytes in the frame buffer.
80 */
81 private int framesize;
82
83 /**
84 * The bytes read from the stream.
85 */
86 private byte[] frame_bytes = new byte[BUFFER_INT_SIZE*4];
87
88 /**
89 * Index into <code>framebuffer</code> where the next bits are
90 * retrieved.
91 */
92 private int wordpointer;
93
94 /**
95 * Number (0-31, from MSB to LSB) of next bit for get_bits()
96 */
97 private int bitindex;
98
99 /**
100 * The current specified syncword
101 */
102 private int syncword;
103
104 /**
105 * Audio header position in stream.
106 */
107 private int header_pos = 0;
108
109 /**
110 *
111 */
112 private boolean single_ch_mode;
113 //private int current_frame_number;
114 //private int last_frame_number;
115
116 private final int bitmask[] = {0, // dummy
117 0x00000001, 0x00000003, 0x00000007, 0x0000000F,
118 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
119 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
120 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
121 0x0001FFFF };
122
123 private final PushbackInputStream source;
124
125 private final Header header = new Header();
126
127 private final byte syncbuf[] = new byte[4];
128
129 private Crc16[] crc = new Crc16[1];
130
131 private byte[] rawid3v2 = null;
132
133 private boolean firstframe = true;
134
135
136 /**
137 * Construct a IBitstream that reads data from a
138 * given InputStream.
139 *
140 * @param in The InputStream to read from.
141 */
142 public Bitstream(InputStream in)
143 {
144 if (in==null) throw new NullPointerException("in");
145 in = new BufferedInputStream(in);
146 loadID3v2(in);
147 firstframe = true;
148 //source = new PushbackInputStream(in, 1024);
149 source = new PushbackInputStream(in, BUFFER_INT_SIZE*4);
150
151 closeFrame();
152 //current_frame_number = -1;
153 //last_frame_number = -1;
154 }
155
156 /**
157 * Return position of the first audio header.
158 * @return size of ID3v2 tag frames.
159 */
160 public int header_pos()
161 {
162 return header_pos;
163 }
164
165 /**
166 * Load ID3v2 frames.
167 * @param in MP3 InputStream.
168 * @author JavaZOOM
169 */
170 private void loadID3v2(InputStream in)
171 {
172 int size = -1;
173 try
174 {
175 // Read ID3v2 header (10 bytes).
176 in.mark(10);
177 size = readID3v2Header(in);
178 header_pos = size;
179 }
180 catch (IOException e)
181 {}
182 finally
183 {
184 try
185 {
186 // Unread ID3v2 header (10 bytes).
187 in.reset();
188 }
189 catch (IOException e)
190 {}
191 }
192 // Load ID3v2 tags.
193 try
194 {
195 if (size > 0)
196 {
197 rawid3v2 = new byte[size];
198 in.read(rawid3v2,0,rawid3v2.length);
199 }
200 }
201 catch (IOException e)
202 {}
203 }
204
205 /**
206 * Parse ID3v2 tag header to find out size of ID3v2 frames.
207 * @param in MP3 InputStream
208 * @return size of ID3v2 frames + header
209 * @throws IOException
210 * @author JavaZOOM
211 */
212 private int readID3v2Header(InputStream in) throws IOException
213 {
214 byte[] id3header = new byte[4];
215 int size = -10;
216 in.read(id3header,0,3);
217 // Look for ID3v2
218 if ( (id3header[0]=='I') && (id3header[1]=='D') && (id3header[2]=='3'))
219 {
220 in.read(id3header,0,3);
221 int majorVersion = id3header[0];
222 int revision = id3header[1];
223 in.read(id3header,0,4);
224 size = (int) (id3header[0] << 21) + (id3header[1] << 14) + (id3header[2] << 7) + (id3header[3]);
225 }
226 return (size+10);
227 }
228
229 /**
230 * Return raw ID3v2 frames + header.
231 * @return ID3v2 InputStream or null if ID3v2 frames are not available.
232 */
233 public InputStream getRawID3v2()
234 {
235 if (rawid3v2 == null) return null;
236 else
237 {
238 ByteArrayInputStream bain = new ByteArrayInputStream(rawid3v2);
239 return bain;
240 }
241 }
242
243 /**
244 * Close the Bitstream.
245 * @throws BitstreamException
246 */
247 public void close() throws BitstreamException
248 {
249 try
250 {
251 source.close();
252 }
253 catch (IOException ex)
254 {
255 throw newBitstreamException(STREAM_ERROR, ex);
256 }
257 }
258
259 /**
260 * Reads and parses the next frame from the input source.
261 * @return the Header describing details of the frame read,
262 * or null if the end of the stream has been reached.
263 */
264 public Header readFrame() throws BitstreamException
265 {
266 Header result = null;
267 try
268 {
269 result = readNextFrame();
270 // E.B, Parse VBR (if any) first frame.
271 if (firstframe == true)
272 {
273 result.parseVBR(frame_bytes);
274 firstframe = false;
275 }
276 }
277 catch (BitstreamException ex)
278 {
279 if ((ex.getErrorCode()==INVALIDFRAME))
280 {
281 // Try to skip this frame.
282 //System.out.println("INVALIDFRAME");
283 try
284 {
285 closeFrame();
286 result = readNextFrame();
287 }
288 catch (BitstreamException e)
289 {
290 if ((e.getErrorCode()!=STREAM_EOF))
291 {
292 // wrap original exception so stack trace is maintained.
293 throw newBitstreamException(e.getErrorCode(), e);
294 }
295 }
296 }
297 else if ((ex.getErrorCode()!=STREAM_EOF))
298 {
299 // wrap original exception so stack trace is maintained.
300 throw newBitstreamException(ex.getErrorCode(), ex);
301 }
302 }
303 return result;
304 }
305
306 /**
307 * Read next MP3 frame.
308 * @return MP3 frame header.
309 * @throws BitstreamException
310 */
311 private Header readNextFrame() throws BitstreamException
312 {
313 if (framesize == -1)
314 {
315 nextFrame();
316 }
317 return header;
318 }
319
320
321 /**
322 * Read next MP3 frame.
323 * @throws BitstreamException
324 */
325 private void nextFrame() throws BitstreamException
326 {
327 // entire frame is read by the header class.
328 header.read_header(this, crc);
329 }
330
331 /**
332 * Unreads the bytes read from the frame.
333 * @throws BitstreamException
334 */
335 // REVIEW: add new error codes for this.
336 public void unreadFrame() throws BitstreamException
337 {
338 if (wordpointer==-1 && bitindex==-1 && (framesize>0))
339 {
340 try
341 {
342 source.unread(frame_bytes, 0, framesize);
343 }
344 catch (IOException ex)
345 {
346 throw newBitstreamException(STREAM_ERROR);
347 }
348 }
349 }
350
351 /**
352 * Close MP3 frame.
353 */
354 public void closeFrame()
355 {
356 framesize = -1;
357 wordpointer = -1;
358 bitindex = -1;
359 }
360
361 /**
362 * Determines if the next 4 bytes of the stream represent a
363 * frame header.
364 */
365 public boolean isSyncCurrentPosition(int syncmode) throws BitstreamException
366 {
367 int read = readBytes(syncbuf, 0, 4);
368 int headerstring = ((syncbuf[0] << 24) & 0xFF000000) | ((syncbuf[1] << 16) & 0x00FF0000) | ((syncbuf[2] << 8) & 0x0000FF00) | ((syncbuf[3] << 0) & 0x000000FF);
369
370 try
371 {
372 source.unread(syncbuf, 0, read);
373 }
374 catch (IOException ex)
375 {
376 }
377
378 boolean sync = false;
379 switch (read)
380 {
381 case 0:
382 sync = true;
383 break;
384 case 4:
385 sync = isSyncMark(headerstring, syncmode, syncword);
386 break;
387 }
388
389 return sync;
390 }
391
392
393 // REVIEW: this class should provide inner classes to
394 // parse the frame contents. Eventually, readBits will
395 // be removed.
396 public int readBits(int n)
397 {
398 return get_bits(n);
399 }
400
401 public int readCheckedBits(int n)
402 {
403 // REVIEW: implement CRC check.
404 return get_bits(n);
405 }
406
407 protected BitstreamException newBitstreamException(int errorcode)
408 {
409 return new BitstreamException(errorcode, null);
410 }
411 protected BitstreamException newBitstreamException(int errorcode, Throwable throwable)
412 {
413 return new BitstreamException(errorcode, throwable);
414 }
415
416 /**
417 * Get next 32 bits from bitstream.
418 * They are stored in the headerstring.
419 * syncmod allows Synchro flag ID
420 * The returned value is False at the end of stream.
421 */
422
423 int syncHeader(byte syncmode) throws BitstreamException
424 {
425 boolean sync;
426 int headerstring;
427 // read additional 2 bytes
428 int bytesRead = readBytes(syncbuf, 0, 3);
429
430 if (bytesRead!=3) throw newBitstreamException(STREAM_EOF, null);
431
432 headerstring = ((syncbuf[0] << 16) & 0x00FF0000) | ((syncbuf[1] << 8) & 0x0000FF00) | ((syncbuf[2] << 0) & 0x000000FF);
433
434 do
435 {
436 headerstring <<= 8;
437
438 if (readBytes(syncbuf, 3, 1)!=1)
439 throw newBitstreamException(STREAM_EOF, null);
440
441 headerstring |= (syncbuf[3] & 0x000000FF);
442
443 sync = isSyncMark(headerstring, syncmode, syncword);
444 }
445 while (!sync);
446
447 //current_frame_number++;
448 //if (last_frame_number < current_frame_number) last_frame_number = current_frame_number;
449
450 return headerstring;
451 }
452
453 public boolean isSyncMark(int headerstring, int syncmode, int word)
454 {
455 boolean sync = false;
456
457 if (syncmode == INITIAL_SYNC)
458 {
459 //sync = ((headerstring & 0xFFF00000) == 0xFFF00000);
460 sync = ((headerstring & 0xFFE00000) == 0xFFE00000); // SZD: MPEG 2.5
461 }
462 else
463 {
464 sync = ((headerstring & 0xFFF80C00) == word) &&
465 (((headerstring & 0x000000C0) == 0x000000C0) == single_ch_mode);
466 }
467
468 // filter out invalid sample rate
469 if (sync)
470 sync = (((headerstring >>> 10) & 3)!=3);
471 // filter out invalid layer
472 if (sync)
473 sync = (((headerstring >>> 17) & 3)!=0);
474 // filter out invalid version
475 if (sync)
476 sync = (((headerstring >>> 19) & 3)!=1);
477
478 return sync;
479 }
480
481 /**
482 * Reads the data for the next frame. The frame is not parsed
483 * until parse frame is called.
484 */
485 int read_frame_data(int bytesize) throws BitstreamException
486 {
487 int numread = 0;
488 numread = readFully(frame_bytes, 0, bytesize);
489 framesize = bytesize;
490 wordpointer = -1;
491 bitindex = -1;
492 return numread;
493 }
494
495 /**
496 * Parses the data previously read with read_frame_data().
497 */
498 void parse_frame() throws BitstreamException
499 {
500 // Convert Bytes read to int
501 int b=0;
502 byte[] byteread = frame_bytes;
503 int bytesize = framesize;
504
505 // Check ID3v1 TAG (True only if last frame).
506 //for (int t=0;t<(byteread.length)-2;t++)
507 //{
508 // if ((byteread[t]=='T') && (byteread[t+1]=='A') && (byteread[t+2]=='G'))
509 // {
510 // System.out.println("ID3v1 detected at offset "+t);
511 // throw newBitstreamException(INVALIDFRAME, null);
512 // }
513 //}
514
515 for (int k=0;k<bytesize;k=k+4)
516 {
517 int convert = 0;
518 byte b0 = 0;
519 byte b1 = 0;
520 byte b2 = 0;
521 byte b3 = 0;
522 b0 = byteread[k];
523 if (k+1<bytesize) b1 = byteread[k+1];
524 if (k+2<bytesize) b2 = byteread[k+2];
525 if (k+3<bytesize) b3 = byteread[k+3];
526 framebuffer[b++] = ((b0 << 24) &0xFF000000) | ((b1 << 16) & 0x00FF0000) | ((b2 << 8) & 0x0000FF00) | (b3 & 0x000000FF);
527 }
528 wordpointer = 0;
529 bitindex = 0;
530 }
531
532 /**
533 * Read bits from buffer into the lower bits of an unsigned int.
534 * The LSB contains the latest read bit of the stream.
535 * (1 <= number_of_bits <= 16)
536 */
537 public int get_bits(int number_of_bits)
538 {
539 int returnvalue = 0;
540 int sum = bitindex + number_of_bits;
541
542 // E.B
543 // There is a problem here, wordpointer could be -1 ?!
544 if (wordpointer < 0) wordpointer = 0;
545 // E.B : End.
546
547 if (sum <= 32)
548 {
549 // all bits contained in *wordpointer
550 returnvalue = (framebuffer[wordpointer] >>> (32 - sum)) & bitmask[number_of_bits];
551 // returnvalue = (wordpointer[0] >> (32 - sum)) & bitmask[number_of_bits];
552 if ((bitindex += number_of_bits) == 32)
553 {
554 bitindex = 0;
555 wordpointer++; // added by me!
556 }
557 return returnvalue;
558 }
559
560 // E.B : Check that ?
561 //((short[])&returnvalue)[0] = ((short[])wordpointer + 1)[0];
562 //wordpointer++; // Added by me!
563 //((short[])&returnvalue + 1)[0] = ((short[])wordpointer)[0];
564 int Right = (framebuffer[wordpointer] & 0x0000FFFF);
565 wordpointer++;
566 int Left = (framebuffer[wordpointer] & 0xFFFF0000);
567 returnvalue = ((Right << 16) & 0xFFFF0000) | ((Left >>> 16)& 0x0000FFFF);
568
569 returnvalue >>>= 48 - sum; // returnvalue >>= 16 - (number_of_bits - (32 - bitindex))
570 returnvalue &= bitmask[number_of_bits];
571 bitindex = sum - 32;
572 return returnvalue;
573}
574
575 /**
576 * Set the word we want to sync the header to.
577 * In Big-Endian byte order
578 */
579 void set_syncword(int syncword0)
580 {
581 syncword = syncword0 & 0xFFFFFF3F;
582 single_ch_mode = ((syncword0 & 0x000000C0) == 0x000000C0);
583 }
584 /**
585 * Reads the exact number of bytes from the source
586 * input stream into a byte array.
587 *
588 * @param b The byte array to read the specified number
589 * of bytes into.
590 * @param offs The index in the array where the first byte
591 * read should be stored.
592 * @param len the number of bytes to read.
593 *
594 * @exception BitstreamException is thrown if the specified
595 * number of bytes could not be read from the stream.
596 */
597 private int readFully(byte[] b, int offs, int len)
598 throws BitstreamException
599 {
600 int nRead = 0;
601 try
602 {
603 while (len > 0)
604 {
605 int bytesread = source.read(b, offs, len);
606 if (bytesread == -1)
607 {
608 while (len-->0)
609 {
610 b[offs++] = 0;
611 }
612 break;
613 //throw newBitstreamException(UNEXPECTED_EOF, new EOFException());
614 }
615 nRead = nRead + bytesread;
616 offs += bytesread;
617 len -= bytesread;
618 }
619 }
620 catch (IOException ex)
621 {
622 throw newBitstreamException(STREAM_ERROR, ex);
623 }
624 return nRead;
625 }
626
627 /**
628 * Simlar to readFully, but doesn't throw exception when
629 * EOF is reached.
630 */
631 private int readBytes(byte[] b, int offs, int len)
632 throws BitstreamException
633 {
634 int totalBytesRead = 0;
635 try
636 {
637 while (len > 0)
638 {
639 int bytesread = source.read(b, offs, len);
640 if (bytesread == -1)
641 {
642 break;
643 }
644 totalBytesRead += bytesread;
645 offs += bytesread;
646 len -= bytesread;
647 }
648 }
649 catch (IOException ex)
650 {
651 throw newBitstreamException(STREAM_ERROR, ex);
652 }
653 return totalBytesRead;
654 }
655}