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