Coverage Report - org.jaudiotagger.audio.asf.io.StreamChunkReader
 
Classes in this File Line Coverage Branch Coverage Complexity
StreamChunkReader
78%
47/60
37%
3/8
1.75
 
 1  
 /*
 2  
  * Entagged Audio Tag library
 3  
  * Copyright (c) 2004-2005 Christian Laireiter <liree@web.de>
 4  
  * 
 5  
  * This library is free software; you can redistribute it and/or
 6  
  * modify it under the terms of the GNU Lesser General Public
 7  
  * License as published by the Free Software Foundation; either
 8  
  * version 2.1 of the License, or (at your option) any later version.
 9  
  *  
 10  
  * This library is distributed in the hope that it will be useful,
 11  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
  * Lesser General Public License for more details.
 14  
  * 
 15  
  * You should have received a copy of the GNU Lesser General Public
 16  
  * License along with this library; if not, write to the Free Software
 17  
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 18  
  */
 19  
 package org.jaudiotagger.audio.asf.io;
 20  
 
 21  
 import org.jaudiotagger.audio.asf.data.*;
 22  
 import org.jaudiotagger.audio.asf.util.Utils;
 23  
 
 24  
 import java.io.IOException;
 25  
 import java.io.InputStream;
 26  
 import java.math.BigInteger;
 27  
 
 28  
 /**
 29  
  * Reads and interprets the data of the audio or video stream information chunk. <br>
 30  
  * 
 31  
  * @author Christian Laireiter
 32  
  */
 33  
 public class StreamChunkReader implements ChunkReader {
 34  
 
 35  
     /**
 36  
      * The GUID this reader {@linkplain #getApplyingIds() applies to}
 37  
      */
 38  4
     private final static GUID[] APPLYING = { GUID.GUID_STREAM };
 39  
 
 40  
     /**
 41  
      * Shouldn't be used for now.
 42  
      */
 43  12
     protected StreamChunkReader() {
 44  
         // Nothing to do
 45  12
     }
 46  
 
 47  
     /**
 48  
      * {@inheritDoc}
 49  
      */
 50  
     public boolean canFail() {
 51  278
         return true;
 52  
     }
 53  
 
 54  
     /**
 55  
      * {@inheritDoc}
 56  
      */
 57  
     public GUID[] getApplyingIds() {
 58  12
         return APPLYING.clone();
 59  
     }
 60  
 
 61  
     /**
 62  
      * {@inheritDoc}
 63  
      */
 64  
     public Chunk read(final GUID guid, final InputStream stream,
 65  
             final long chunkStart) throws IOException {
 66  278
         StreamChunk result = null;
 67  278
         final BigInteger chunkLength = Utils.readBig64(stream);
 68  
         // Now comes GUID indicating whether stream content type is audio or
 69  
         // video
 70  278
         final GUID streamTypeGUID = Utils.readGUID(stream);
 71  278
         if (GUID.GUID_AUDIOSTREAM.equals(streamTypeGUID)
 72  
                 || GUID.GUID_VIDEOSTREAM.equals(streamTypeGUID)) {
 73  
 
 74  
             // A GUID is indicating whether the stream is error
 75  
             // concealed
 76  278
             final GUID errorConcealment = Utils.readGUID(stream);
 77  
             /*
 78  
              * Read the Time Offset
 79  
              */
 80  278
             final long timeOffset = Utils.readUINT64(stream);
 81  
 
 82  278
             final long typeSpecificDataSize = Utils.readUINT32(stream);
 83  278
             final long streamSpecificDataSize = Utils.readUINT32(stream);
 84  
 
 85  
             /*
 86  
              * Read a bit field. (Contains stream number, and whether the stream
 87  
              * content is encrypted.)
 88  
              */
 89  278
             final int mask = Utils.readUINT16(stream);
 90  278
             final int streamNumber = mask & 127;
 91  278
             final boolean contentEncrypted = (mask & 0x8000) != 0;
 92  
 
 93  
             /*
 94  
              * Skip a reserved field
 95  
              */
 96  278
             stream.skip(4);
 97  
 
 98  
             /*
 99  
              * very important to set for every stream type. The size of bytes
 100  
              * read by the specific stream type, in order to skip the remaining
 101  
              * unread bytes of the stream chunk.
 102  
              */
 103  
             long streamSpecificBytes;
 104  
 
 105  278
             if (GUID.GUID_AUDIOSTREAM.equals(streamTypeGUID)) {
 106  
                 /*
 107  
                  * Reading audio specific information
 108  
                  */
 109  278
                 final AudioStreamChunk audioStreamChunk = new AudioStreamChunk(
 110  
                         chunkLength);
 111  278
                 result = audioStreamChunk;
 112  
 
 113  
                 /*
 114  
                  * read WAVEFORMATEX and format extension.
 115  
                  */
 116  278
                 final long compressionFormat = Utils.readUINT16(stream);
 117  278
                 final long channelCount = Utils.readUINT16(stream);
 118  278
                 final long samplingRate = Utils.readUINT32(stream);
 119  278
                 final long avgBytesPerSec = Utils.readUINT32(stream);
 120  278
                 final long blockAlignment = Utils.readUINT16(stream);
 121  278
                 final int bitsPerSample = Utils.readUINT16(stream);
 122  278
                 final int codecSpecificDataSize = Utils.readUINT16(stream);
 123  278
                 final byte[] codecSpecificData = new byte[codecSpecificDataSize];
 124  278
                 stream.read(codecSpecificData);
 125  
 
 126  278
                 audioStreamChunk.setCompressionFormat(compressionFormat);
 127  278
                 audioStreamChunk.setChannelCount(channelCount);
 128  278
                 audioStreamChunk.setSamplingRate(samplingRate);
 129  278
                 audioStreamChunk.setAverageBytesPerSec(avgBytesPerSec);
 130  278
                 audioStreamChunk.setErrorConcealment(errorConcealment);
 131  278
                 audioStreamChunk.setBlockAlignment(blockAlignment);
 132  278
                 audioStreamChunk.setBitsPerSample(bitsPerSample);
 133  278
                 audioStreamChunk.setCodecData(codecSpecificData);
 134  
 
 135  278
                 streamSpecificBytes = 18 + codecSpecificData.length;
 136  278
             } else {
 137  
                 /*
 138  
                  * Reading video specific information
 139  
                  */
 140  0
                 final VideoStreamChunk videoStreamChunk = new VideoStreamChunk(
 141  
                         chunkLength);
 142  0
                 result = videoStreamChunk;
 143  
 
 144  0
                 final long pictureWidth = Utils.readUINT32(stream);
 145  0
                 final long pictureHeight = Utils.readUINT32(stream);
 146  
 
 147  
                 // Skip unknown field
 148  0
                 stream.skip(1);
 149  
 
 150  
                 /*
 151  
                  * Now read the format specific data
 152  
                  */
 153  
                 // Size of the data section (formatDataSize)
 154  0
                 stream.skip(2);
 155  
 
 156  0
                 stream.skip(16);
 157  0
                 final byte[] fourCC = new byte[4];
 158  0
                 stream.read(fourCC);
 159  
 
 160  0
                 videoStreamChunk.setPictureWidth(pictureWidth);
 161  0
                 videoStreamChunk.setPictureHeight(pictureHeight);
 162  0
                 videoStreamChunk.setCodecId(fourCC);
 163  
 
 164  0
                 streamSpecificBytes = 31;
 165  
             }
 166  
 
 167  
             /*
 168  
              * Setting common values for audio and video
 169  
              */
 170  278
             result.setStreamNumber(streamNumber);
 171  278
             result.setStreamSpecificDataSize(streamSpecificDataSize);
 172  278
             result.setTypeSpecificDataSize(typeSpecificDataSize);
 173  278
             result.setTimeOffset(timeOffset);
 174  278
             result.setContentEncrypted(contentEncrypted);
 175  278
             result.setPosition(chunkStart);
 176  
             /*
 177  
              * Now skip remainder of chunks bytes. chunk-length - 24 (size of
 178  
              * GUID and chunklen) - streamSpecificBytes(stream type specific
 179  
              * data) - 54 (common data)
 180  
              */
 181  278
             stream
 182  
                     .skip(chunkLength.longValue() - 24 - streamSpecificBytes
 183  
                             - 54);
 184  
         }
 185  278
         return result;
 186  
     }
 187  
 
 188  
 }