changes.
[IRC.git] / Robust / src / Tests / ssJava / mp3decoder / Bitstream.java
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
36 /**
37  * The <code>Bistream</code> class is responsible for parsing an MPEG audio
38  * bitstream.
39  * 
40  * <b>REVIEW:</b> much of the parsing currently occurs in the various decoders.
41  * This should be moved into this class and associated inner classes.
42  */
43 @LATTICE("FB<F,FF<F,WP<BI,FF*,WP*,BI*")
44 @METHODDEFAULT("OUT<THIS,THIS<VAR,VAR<IN,VAR*,THISLOC=THIS,GLOBALLOC=IN")
45 public final class Bitstream implements BitstreamErrors {
46   /**
47    * Synchronization control constant for the initial synchronization to the
48    * start of a frame.
49    */
50   @LOC("F")
51   static byte INITIAL_SYNC = 0;
52
53   /**
54    * Synchronization control constant for non-initial frame synchronizations.
55    */
56
57   @LOC("F")
58   static byte STRICT_SYNC = 1;
59
60   // max. 1730 bytes per frame: 144 * 384kbit/s / 32000 Hz + 2 Bytes CRC
61   /**
62    * Maximum size of the frame buffer.
63    */
64   @LOC("F")
65   private static final int BUFFER_INT_SIZE = 433;
66
67   /**
68    * The frame buffer that holds the data for the current frame.
69    */
70   @LOC("FB")
71   private final int[] framebuffer = new int[BUFFER_INT_SIZE];
72
73   /**
74    * Number of valid bytes in the frame buffer.
75    */
76   @LOC("F")
77   private int framesize;
78
79   /**
80    * The bytes read from the stream.
81    */
82   @LOC("FB")
83   private byte[] frame_bytes = new byte[BUFFER_INT_SIZE * 4];
84
85   /**
86    * Index into <code>framebuffer</code> where the next bits are retrieved.
87    */
88   @LOC("WP")
89   private int wordpointer;
90
91   /**
92    * Number (0-31, from MSB to LSB) of next bit for get_bits()
93    */
94   @LOC("BI")
95   private int bitindex;
96
97   /**
98    * The current specified syncword
99    */
100   @LOC("F")
101   private int syncword;
102
103   /**
104    * Audio header position in stream.
105    */
106   @LOC("F")
107   private int header_pos = 0;
108
109   /**
110          *
111          */
112   @LOC("F")
113   private boolean single_ch_mode;
114   // private int current_frame_number;
115   // private int last_frame_number;
116
117   @LOC("F")
118   private final int bitmask[] = {
119       0, // dummy
120       0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F,
121       0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, 0x00001FFF, 0x00003FFF,
122       0x00007FFF, 0x0000FFFF, 0x0001FFFF };
123
124   @LOC("F")
125   private final PushbackInputStream source;
126
127   @LOC("F")
128   private final Header header = new Header();
129
130   @LOC("F")
131   private final byte syncbuf[] = new byte[4];
132
133   @LOC("F")
134   private Crc16[] crc = new Crc16[1];
135
136   @LOC("F")
137   private byte[] rawid3v2 = null;
138
139   @LOC("FF")
140   private boolean firstframe = true;
141
142   /**
143    * Construct a IBitstream that reads data from a given InputStream.
144    * 
145    * @param in
146    *          The InputStream to read from.
147    */
148   public Bitstream(InputStream in) {
149     if (in == null)
150       throw new NullPointerException("in");
151     in = new BufferedInputStream(in);
152     loadID3v2(in);
153     firstframe = true;
154     // source = new PushbackInputStream(in, 1024);
155     source = new PushbackInputStream(in, BUFFER_INT_SIZE * 4);
156
157     closeFrame();
158     // current_frame_number = -1;
159     // last_frame_number = -1;
160   }
161
162   /**
163    * Return position of the first audio header.
164    * 
165    * @return size of ID3v2 tag frames.
166    */
167   public int header_pos() {
168     return header_pos;
169   }
170
171   /**
172    * Load ID3v2 frames.
173    * 
174    * @param in
175    *          MP3 InputStream.
176    * @author JavaZOOM
177    */
178   private void loadID3v2(InputStream in) {
179     int size = -1;
180     try {
181       // Read ID3v2 header (10 bytes).
182       in.mark(10);
183       size = readID3v2Header(in);
184       header_pos = size;
185     } catch (IOException e) {
186     } finally {
187       try {
188         // Unread ID3v2 header (10 bytes).
189         in.reset();
190       } catch (IOException e) {
191       }
192     }
193     // Load ID3v2 tags.
194     try {
195       if (size > 0) {
196         rawid3v2 = new byte[size];
197         in.read(rawid3v2, 0, rawid3v2.length);
198       }
199     } catch (IOException e) {
200     }
201   }
202
203   /**
204    * Parse ID3v2 tag header to find out size of ID3v2 frames.
205    * 
206    * @param in
207    *          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     byte[] id3header = new byte[4];
214     int size = -10;
215     in.read(id3header, 0, 3);
216     // Look for ID3v2
217     if ((id3header[0] == 'I') && (id3header[1] == 'D') && (id3header[2] == '3')) {
218       in.read(id3header, 0, 3);
219       int majorVersion = id3header[0];
220       int revision = id3header[1];
221       in.read(id3header, 0, 4);
222       size =
223           (int) (id3header[0] << 21) + (id3header[1] << 14) + (id3header[2] << 7) + (id3header[3]);
224     }
225     return (size + 10);
226   }
227
228   /**
229    * Return raw ID3v2 frames + header.
230    * 
231    * @return ID3v2 InputStream or null if ID3v2 frames are not available.
232    */
233   public InputStream getRawID3v2() {
234     if (rawid3v2 == null)
235       return null;
236     else {
237       ByteArrayInputStream bain = new ByteArrayInputStream(rawid3v2);
238       return bain;
239     }
240   }
241
242   /**
243    * Close the Bitstream.
244    * 
245    * @throws BitstreamException
246    */
247   public void close() throws BitstreamException {
248     try {
249       source.close();
250     } catch (IOException ex) {
251       throw newBitstreamException(STREAM_ERROR, ex);
252     }
253   }
254
255   /**
256    * Reads and parses the next frame from the input source.
257    * 
258    * @return the Header describing details of the frame read, or null if the end
259    *         of the stream has been reached.
260    */
261   public Header readFrame() throws BitstreamException {
262     Header result = null;
263     try {
264       result = readNextFrame();
265       // E.B, Parse VBR (if any) first frame.
266       if (firstframe == true) {
267         result.parseVBR(frame_bytes);
268         firstframe = false;
269       }
270     } catch (BitstreamException ex) {
271       if ((ex.getErrorCode() == INVALIDFRAME)) {
272         // Try to skip this frame.
273         // System.out.println("INVALIDFRAME");
274         try {
275           closeFrame();
276           result = readNextFrame();
277         } catch (BitstreamException e) {
278           if ((e.getErrorCode() != STREAM_EOF)) {
279             // wrap original exception so stack trace is maintained.
280             throw newBitstreamException(e.getErrorCode(), e);
281           }
282         }
283       } else if ((ex.getErrorCode() != STREAM_EOF)) {
284         // wrap original exception so stack trace is maintained.
285         throw newBitstreamException(ex.getErrorCode(), ex);
286       }
287     }
288     return result;
289   }
290
291   /**
292    * Read next MP3 frame.
293    * 
294    * @return MP3 frame header.
295    * @throws BitstreamException
296    */
297   private Header readNextFrame() throws BitstreamException {
298     if (framesize == -1) {
299       nextFrame();
300     }
301     return header;
302   }
303
304   /**
305    * Read next MP3 frame.
306    * 
307    * @throws BitstreamException
308    */
309   private void nextFrame() throws BitstreamException {
310     // entire frame is read by the header class.
311     header.read_header(this, crc);
312   }
313
314   /**
315    * Unreads the bytes read from the frame.
316    * 
317    * @throws BitstreamException
318    */
319   // REVIEW: add new error codes for this.
320   public void unreadFrame() throws BitstreamException {
321     if (wordpointer == -1 && bitindex == -1 && (framesize > 0)) {
322       try {
323         source.unread(frame_bytes, 0, framesize);
324       } catch (IOException ex) {
325         throw newBitstreamException(STREAM_ERROR);
326       }
327     }
328   }
329
330   /**
331    * Close MP3 frame.
332    */
333   public void closeFrame() {
334     framesize = -1;
335     wordpointer = -1;
336     bitindex = -1;
337   }
338
339   /**
340    * Determines if the next 4 bytes of the stream represent a frame header.
341    */
342   public boolean isSyncCurrentPosition(int syncmode) throws BitstreamException {
343     int read = readBytes(syncbuf, 0, 4);
344     int headerstring =
345         ((syncbuf[0] << 24) & 0xFF000000) | ((syncbuf[1] << 16) & 0x00FF0000)
346             | ((syncbuf[2] << 8) & 0x0000FF00) | ((syncbuf[3] << 0) & 0x000000FF);
347
348     try {
349       source.unread(syncbuf, 0, read);
350     } catch (IOException ex) {
351     }
352
353     boolean sync = false;
354     switch (read) {
355     case 0:
356       sync = true;
357       break;
358     case 4:
359       sync = isSyncMark(headerstring, syncmode, syncword);
360       break;
361     }
362
363     return sync;
364   }
365
366   // REVIEW: this class should provide inner classes to
367   // parse the frame contents. Eventually, readBits will
368   // be removed.
369   public int readBits(int n) {
370     return get_bits(n);
371   }
372
373   public int readCheckedBits(int n) {
374     // REVIEW: implement CRC check.
375     return get_bits(n);
376   }
377
378   protected BitstreamException newBitstreamException(int errorcode) {
379     return new BitstreamException(errorcode, null);
380   }
381
382   protected BitstreamException newBitstreamException(int errorcode, Throwable throwable) {
383     return new BitstreamException(errorcode, throwable);
384   }
385
386   /**
387    * Get next 32 bits from bitstream. They are stored in the headerstring.
388    * syncmod allows Synchro flag ID The returned value is False at the end of
389    * stream.
390    */
391
392   int syncHeader(byte syncmode) throws BitstreamException {
393     boolean sync;
394     int headerstring;
395     // read additional 2 bytes
396     int bytesRead = readBytes(syncbuf, 0, 3);
397
398     if (bytesRead != 3)
399       throw newBitstreamException(STREAM_EOF, null);
400
401     headerstring =
402         ((syncbuf[0] << 16) & 0x00FF0000) | ((syncbuf[1] << 8) & 0x0000FF00)
403             | ((syncbuf[2] << 0) & 0x000000FF);
404
405     do {
406       headerstring <<= 8;
407
408       if (readBytes(syncbuf, 3, 1) != 1)
409         throw newBitstreamException(STREAM_EOF, null);
410
411       headerstring |= (syncbuf[3] & 0x000000FF);
412
413       sync = isSyncMark(headerstring, syncmode, syncword);
414     } while (!sync);
415
416     // current_frame_number++;
417     // if (last_frame_number < current_frame_number) last_frame_number =
418     // current_frame_number;
419
420     return headerstring;
421   }
422
423   public boolean isSyncMark(int headerstring, int syncmode, int word) {
424     boolean sync = false;
425
426     if (syncmode == INITIAL_SYNC) {
427       // sync = ((headerstring & 0xFFF00000) == 0xFFF00000);
428       sync = ((headerstring & 0xFFE00000) == 0xFFE00000); // SZD: MPEG 2.5
429     } else {
430       sync =
431           ((headerstring & 0xFFF80C00) == word)
432               && (((headerstring & 0x000000C0) == 0x000000C0) == single_ch_mode);
433     }
434
435     // filter out invalid sample rate
436     if (sync)
437       sync = (((headerstring >>> 10) & 3) != 3);
438     // filter out invalid layer
439     if (sync)
440       sync = (((headerstring >>> 17) & 3) != 0);
441     // filter out invalid version
442     if (sync)
443       sync = (((headerstring >>> 19) & 3) != 1);
444
445     return sync;
446   }
447
448   /**
449    * Reads the data for the next frame. The frame is not parsed until parse
450    * frame is called.
451    */
452   int read_frame_data(int bytesize) throws BitstreamException {
453     int numread = 0;
454     numread = readFully(frame_bytes, 0, bytesize);
455     framesize = bytesize;
456     wordpointer = -1;
457     bitindex = -1;
458     return numread;
459   }
460
461   /**
462    * Parses the data previously read with read_frame_data().
463    */
464   @LATTICE("GLOBAL<B,B<BNUM,BNUM<K,K<BYTE,BYTE<THIS,B*,K*,THISLOC=THIS,GLOBALLOC=GLOBAL")
465   void parse_frame() throws BitstreamException {
466     // Convert Bytes read to int
467     @LOC("B") int b = 0;
468     @LOC("BYTE") byte[] byteread = frame_bytes;
469     @LOC("BYTE") int bytesize = framesize;
470
471     // Check ID3v1 TAG (True only if last frame).
472     // for (int t=0;t<(byteread.length)-2;t++)
473     // {
474     // if ((byteread[t]=='T') && (byteread[t+1]=='A') && (byteread[t+2]=='G'))
475     // {
476     // System.out.println("ID3v1 detected at offset "+t);
477     // throw newBitstreamException(INVALIDFRAME, null);
478     // }
479     // }
480
481     for (@LOC("K") int k = 0; k < bytesize; k = k + 4) {
482       @LOC("BYTE") int convert = 0;
483       @LOC("BNUM") byte b0 = 0;
484       @LOC("BNUM") byte b1 = 0;
485       @LOC("BNUM") byte b2 = 0;
486       @LOC("BNUM") byte b3 = 0;
487       b0 = byteread[k];
488       if (k + 1 < bytesize)
489         b1 = byteread[k + 1];
490       if (k + 2 < bytesize)
491         b2 = byteread[k + 2];
492       if (k + 3 < bytesize)
493         b3 = byteread[k + 3];
494       framebuffer[b++] =
495           ((b0 << 24) & 0xFF000000) | ((b1 << 16) & 0x00FF0000) | ((b2 << 8) & 0x0000FF00)
496               | (b3 & 0x000000FF);
497     }
498     wordpointer = 0;
499     bitindex = 0;
500   }
501
502   /**
503    * Read bits from buffer into the lower bits of an unsigned int. The LSB
504    * contains the latest read bit of the stream. (1 <= number_of_bits <= 16)
505    */
506   @LATTICE("OUT<RL,RL<THIS,THIS<IN,OUT*,THISLOC=THIS,RETURNLOC=OUT")
507   public int get_bits(@LOC("IN") int number_of_bits) {
508     
509     @LOC("OUT") int returnvalue = 0;
510     @LOC("THIS,Bitstream.BI") int sum = bitindex + number_of_bits;
511
512     // E.B
513     // There is a problem here, wordpointer could be -1 ?!
514     if (wordpointer < 0)
515       wordpointer = 0;
516     // E.B : End.
517
518     if (sum <= 32) {
519       // all bits contained in *wordpointer
520       returnvalue = (framebuffer[wordpointer] >>> (32 - sum)) & bitmask[number_of_bits];
521       // returnvalue = (wordpointer[0] >> (32 - sum)) & bitmask[number_of_bits];
522       if ((bitindex += number_of_bits) == 32) {
523         bitindex = 0;
524         wordpointer++; // added by me!
525       }
526       return returnvalue;
527     }
528
529     // E.B : Check that ?
530     // ((short[])&returnvalue)[0] = ((short[])wordpointer + 1)[0];
531     // wordpointer++; // Added by me!
532     // ((short[])&returnvalue + 1)[0] = ((short[])wordpointer)[0];
533     @LOC("RL") int Right = (framebuffer[wordpointer] & 0x0000FFFF);
534     wordpointer++;
535     @LOC("RL") int Left = (framebuffer[wordpointer] & 0xFFFF0000);
536     returnvalue = ((Right << 16) & 0xFFFF0000) | ((Left >>> 16) & 0x0000FFFF);
537
538     returnvalue >>>= 48 - sum; // returnvalue >>= 16 - (number_of_bits - (32 -
539                                // bitindex))
540     returnvalue &= bitmask[number_of_bits];
541     bitindex = sum - 32;
542     return returnvalue;
543   }
544
545   /**
546    * Set the word we want to sync the header to. In Big-Endian byte order
547    */
548   void set_syncword(@LOC("IN") int syncword0) {
549     syncword = syncword0 & 0xFFFFFF3F;
550     single_ch_mode = ((syncword0 & 0x000000C0) == 0x000000C0);
551   }
552
553   /**
554    * Reads the exact number of bytes from the source input stream into a byte
555    * array.
556    * 
557    * @param b
558    *          The byte array to read the specified number of bytes into.
559    * @param offs
560    *          The index in the array where the first byte read should be stored.
561    * @param len
562    *          the number of bytes to read.
563    * 
564    * @exception BitstreamException
565    *              is thrown if the specified number of bytes could not be read
566    *              from the stream.
567    */
568   @LATTICE("OUT<VAR,VAR<THIS,THIS<IN,IN*,VAR*,THISLOC=THIS")
569   @RETURNLOC("OUT")
570   private int readFully(@LOC("OUT") byte[] b, @LOC("IN") int offs, @LOC("IN") int len)
571       throws BitstreamException {
572     @LOC("VAR") int nRead = 0;
573     try {
574       while (len > 0) {
575         @LOC("IN") int bytesread = source.read(b, offs, len);
576         if (bytesread == -1) {
577           while (len-- > 0) {
578             b[offs++] = 0;
579           }
580           break;
581           // throw newBitstreamException(UNEXPECTED_EOF, new EOFException());
582         }
583         nRead = nRead + bytesread;
584         offs += bytesread;
585         len -= bytesread;
586       }
587     } catch (IOException ex) {
588       throw newBitstreamException(STREAM_ERROR, ex);
589     }
590     return nRead;
591   }
592
593   /**
594    * Simlar to readFully, but doesn't throw exception when EOF is reached.
595    */
596   @LATTICE("OUT<VAR,VAR<THIS,THIS<IN,IN*,VAR*,THISLOC=THIS")
597   @RETURNLOC("OUT")
598   private int readBytes(@LOC("OUT") byte[] b, @LOC("IN") int offs, @LOC("IN") int len)
599       throws BitstreamException {
600     @LOC("VAR") int totalBytesRead = 0;
601     try {
602       while (len > 0) {
603         @LOC("IN") int bytesread = source.read(b, offs, len);
604         if (bytesread == -1) {
605           break;
606         }
607         totalBytesRead += bytesread;
608         offs += bytesread;
609         len -= bytesread;
610       }
611     } catch (IOException ex) {
612       throw newBitstreamException(STREAM_ERROR, ex);
613     }
614     return totalBytesRead;
615   }
616 }