FileDocCategorySizeDatePackage
StreamChunkReader.javaAPI DocJaudiotagger 2.0.47086Wed Mar 30 16:11:50 BST 2011org.jaudiotagger.audio.asf.io

StreamChunkReader

public class StreamChunkReader extends Object implements ChunkReader
Reads and interprets the data of the audio or video stream information chunk.
author
Christian Laireiter

Fields Summary
private static final GUID[]
APPLYING
The GUID this reader {@linkplain #getApplyingIds() applies to}
Constructors Summary
protected StreamChunkReader()
Shouldn't be used for now.


              
      
        // Nothing to do
    
Methods Summary
public booleancanFail()
{@inheritDoc}

        return true;
    
public GUID[]getApplyingIds()
{@inheritDoc}

        return APPLYING.clone();
    
public Chunkread(GUID guid, java.io.InputStream stream, long chunkStart)
{@inheritDoc}

        StreamChunk result = null;
        final BigInteger chunkLength = Utils.readBig64(stream);
        // Now comes GUID indicating whether stream content type is audio or
        // video
        final GUID streamTypeGUID = Utils.readGUID(stream);
        if (GUID.GUID_AUDIOSTREAM.equals(streamTypeGUID)
                || GUID.GUID_VIDEOSTREAM.equals(streamTypeGUID)) {

            // A GUID is indicating whether the stream is error
            // concealed
            final GUID errorConcealment = Utils.readGUID(stream);
            /*
             * Read the Time Offset
             */
            final long timeOffset = Utils.readUINT64(stream);

            final long typeSpecificDataSize = Utils.readUINT32(stream);
            final long streamSpecificDataSize = Utils.readUINT32(stream);

            /*
             * Read a bit field. (Contains stream number, and whether the stream
             * content is encrypted.)
             */
            final int mask = Utils.readUINT16(stream);
            final int streamNumber = mask & 127;
            final boolean contentEncrypted = (mask & 0x8000) != 0;

            /*
             * Skip a reserved field
             */
            stream.skip(4);

            /*
             * very important to set for every stream type. The size of bytes
             * read by the specific stream type, in order to skip the remaining
             * unread bytes of the stream chunk.
             */
            long streamSpecificBytes;

            if (GUID.GUID_AUDIOSTREAM.equals(streamTypeGUID)) {
                /*
                 * Reading audio specific information
                 */
                final AudioStreamChunk audioStreamChunk = new AudioStreamChunk(
                        chunkLength);
                result = audioStreamChunk;

                /*
                 * read WAVEFORMATEX and format extension.
                 */
                final long compressionFormat = Utils.readUINT16(stream);
                final long channelCount = Utils.readUINT16(stream);
                final long samplingRate = Utils.readUINT32(stream);
                final long avgBytesPerSec = Utils.readUINT32(stream);
                final long blockAlignment = Utils.readUINT16(stream);
                final int bitsPerSample = Utils.readUINT16(stream);
                final int codecSpecificDataSize = Utils.readUINT16(stream);
                final byte[] codecSpecificData = new byte[codecSpecificDataSize];
                stream.read(codecSpecificData);

                audioStreamChunk.setCompressionFormat(compressionFormat);
                audioStreamChunk.setChannelCount(channelCount);
                audioStreamChunk.setSamplingRate(samplingRate);
                audioStreamChunk.setAverageBytesPerSec(avgBytesPerSec);
                audioStreamChunk.setErrorConcealment(errorConcealment);
                audioStreamChunk.setBlockAlignment(blockAlignment);
                audioStreamChunk.setBitsPerSample(bitsPerSample);
                audioStreamChunk.setCodecData(codecSpecificData);

                streamSpecificBytes = 18 + codecSpecificData.length;
            } else {
                /*
                 * Reading video specific information
                 */
                final VideoStreamChunk videoStreamChunk = new VideoStreamChunk(
                        chunkLength);
                result = videoStreamChunk;

                final long pictureWidth = Utils.readUINT32(stream);
                final long pictureHeight = Utils.readUINT32(stream);

                // Skip unknown field
                stream.skip(1);

                /*
                 * Now read the format specific data
                 */
                // Size of the data section (formatDataSize)
                stream.skip(2);

                stream.skip(16);
                final byte[] fourCC = new byte[4];
                stream.read(fourCC);

                videoStreamChunk.setPictureWidth(pictureWidth);
                videoStreamChunk.setPictureHeight(pictureHeight);
                videoStreamChunk.setCodecId(fourCC);

                streamSpecificBytes = 31;
            }

            /*
             * Setting common values for audio and video
             */
            result.setStreamNumber(streamNumber);
            result.setStreamSpecificDataSize(streamSpecificDataSize);
            result.setTypeSpecificDataSize(typeSpecificDataSize);
            result.setTimeOffset(timeOffset);
            result.setContentEncrypted(contentEncrypted);
            result.setPosition(chunkStart);
            /*
             * Now skip remainder of chunks bytes. chunk-length - 24 (size of
             * GUID and chunklen) - streamSpecificBytes(stream type specific
             * data) - 54 (common data)
             */
            stream
                    .skip(chunkLength.longValue() - 24 - streamSpecificBytes
                            - 54);
        }
        return result;