Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * @(#)AVIReader.java  1.0  2011-08-24
   * 
   * Copyright (c) 2011 Werner Randelshofer, Goldau, Switzerland.
   * All rights reserved.
   * 
   * You may not use, copy or modify this file, except in compliance with the
   * license agreement you entered into with Werner Randelshofer.
   * For details see accompanying license terms.
  */
 package org.monte.media.avi;
 
 import java.io.File;
 import static java.lang.Math.*;
 import static org.monte.media.FormatKeys.*;
 import static org.monte.media.AudioFormatKeys.*;
 import static org.monte.media.VideoFormatKeys.*;
 import static org.monte.media.BufferFlag.*;

Provides high-level support for decoding and reading audio and video samples from an AVI 1.0 file.

Author(s):
Werner Randelshofer
Version:
1.0 2011-08-24 Created.
 
 public class AVIReader extends AVIInputStream implements MovieReader {
 
     public final static Format AVI = new Format(.);
     private Rational movieDuration = null;
 
     public AVIReader(ImageInputStream inthrows IOException {
         super(in);
     }
 
     public AVIReader(File filethrows IOException {
         super(file);
     }
 
     @Override
     public Format getFileFormat() throws IOException {
         return ;
     }
 
     @Override
     public Format getFormat(int trackthrows IOException {
         ensureRealized();
         return .get(track).;
     }

    
Reads a chunk of media data from the specified track.

If the track is a video track with palette change "..PC" chunks, then the body of the palette change chunk can be found in the buffer.header.

Parameters:
track The track number.
buffer The buffer for the media data.
Throws:
java.io.IOException
 
     @Override
     public void read(int trackBuffer bufferthrows IOException {
         ensureRealized();
         Track tr = .get(track);
         if (tr.readIndex >= tr.samples.size()) {
             buffer.setFlagsTo();
             buffer.length = 0;
             return;
         }
 
         Sample s = tr.samples.get((inttr.readIndex);
         .seek(s.offset);
         {
             byte[] b;
             if (buffer.data instanceof byte[]) {
                 b = (byte[]) buffer.data;
                 if (b.length < s.length) {
                     buffer.data = b = new byte[(((ints.length + 1023) / 1024) * 1024];
                 }
             } else {
                 buffer.data = b = new byte[(((ints.length + 1023) / 1024) * 1024];
             }
             .readFully(b, 0, (ints.length);
         }
         buffer.offset = 0;
         buffer.length = (ints.length;
 
        if (s.header != null) {
        {
            byte[] b;
            if (buffer.header instanceof byte[]) {
                b = (byte[]) buffer.data;
                if (b.length != s.header.length) {
                    buffer.header = b = new byte[(((ints.header.length + 1023) / 1024) * 1024];
                }
            } else {
                buffer.header = b = new byte[(((ints.header.length + 1023) / 1024) * 1024];
            }
            .readFully(b, 0, (ints.header.length);
        }
        } else {
            buffer.header = null;
        }
        switch (tr.mediaType) {
            case : {
                Format af = tr.format;
                buffer.sampleCount = buffer.length / af.get();
            }
            break;
            case : {
                buffer.sampleCount = 1;
            }
            break;
            case :
            case :
            default:
                throw new UnsupportedOperationException("Unsupported media type " + tr.mediaType);
        }
        buffer.format = tr.format;
        buffer.track = track;
        buffer.sampleDuration = new Rational(tr.scaletr.rate);
        buffer.timeStamp = new Rational((s.timeStamp + tr.startTime) * tr.scaletr.rate);
        buffer.flags = s.isKeyframe ? EnumSet.of() : EnumSet.noneOf(BufferFlag.class);
        tr.readIndex++;
    }

    
Decodes the PC palette change chunk.
    private void decodePC(byte[] pcint offsetint lengthbyte[] rbyte[] gbyte[] b) {
        offset += 4; // FIXME - Parse firstEntry, numEntries and flags from PC
        for (int i = 0; i < 256; i++) {
            r[i] = pc[offset + i * 4];
            g[i] = pc[offset + i * 4 + 1];
            b[i] = pc[offset + i * 4 + 2];
        }
    }

    
Reads an image.

Parameters:
track The track number
img An image that can be reused if it fits the media format of the track. Pass null to create a new image on each read.
Returns:
An image or null if the end of the media has been reached.
Throws:
java.io.IOException
    public BufferedImage read(int trackBufferedImage imgthrows IOException {
        Track tr = .get(track);
        if (tr.inputBuffer == null) {
            tr.inputBuffer = new Buffer();
        }
        if (tr.codec == null) {
            createCodec(tr);
        }
        Buffer buf = new Buffer();
        buf.data = img;
        do {
            read(tracktr.inputBuffer);
            // FIXME - We assume a one-step codec here!
            tr.codec.process(tr.inputBufferbuf);
        } while (buf.isFlag() && !buf.isFlag());
        if (tr.inputBuffer.isFlag()) {
            return null;
        }
        return (BufferedImagebuf.data;
    }
    private void createCodec(Track tr) {
        Format fmt = tr.format;
        Codec codec = createCodec(fmt);
        String enc = fmt.get();
        if (codec == null) {
            throw new UnsupportedOperationException("Track " + tr + " no codec found for format " + fmt);
        } else {
            if (fmt.get() == .) {
                if (null == codec.setInputFormat(fmt)) {
                    throw new UnsupportedOperationException("Track " + tr + " codec does not support input format " + fmt + ". codec=" + codec);
                }
                Format outFormat = fmt.prepend(.,//
                        ,
                        BufferedImage.class);
                if (null == codec.setOutputFormat(outFormat)) {
                    throw new UnsupportedOperationException("Track " + tr + " codec does not support output format " + outFormat + ". codec=" + codec);
                }
            }
        }
        tr.codec = codec;
    }
    private Codec createCodec(Format fmt) {
        Codec[] codecs = Registry.getInstance().getDecoders(fmt.prepend());
        return codecs.length == 0 ? null : codecs[0];
    }
    @Override
    public Rational getReadTime(int trackthrows IOException {
        Track tr = .get(track);
        if (tr.samples.size() > tr.readIndex) {
            Sample s = tr.samples.get((inttr.readIndex);
            return new Rational((s.timeStamp + tr.startTime) * tr.scaletr.rate);
        }
        return new Rational(0, 1);
    }
    @Override
    public int nextTrack() throws IOException {
        ensureRealized();
        Rational ts = new Rational(., 1);
        int nextTrack = -1;
        for (int i = 0, n = .size(); i < ni++) {
            Track tr = .get(i);
            if (tr.samples.isEmpty()) {
                continue;
            }
            Sample currentSample = tr.readIndex < tr.samples.size() ? tr.samples.get((inttr.readIndex) : tr.samples.get(tr.samples.size() - 1);
            long readTimeStamp = currentSample.timeStamp;
            if (tr.readIndex >= tr.samples.size()) {
                readTimeStamp += currentSample.duration;
            }
            Rational trts = new Rational((readTimeStamp + tr.startTime) * tr.scaletr.rate);
            if (trts.compareTo(ts) < 0 && tr.readIndex < tr.samples.size()) {
                ts = trts;
                nextTrack = i;
            }
        }
        return nextTrack;
    }
    @Override
    public Rational getDuration() {
        try {
            ensureRealized();
        } catch (IOException ex) {
            ex.printStackTrace();
            return new Rational(0, 1);
        }
        if ( == null) {
            Rational maxDuration = new Rational(0, 1);
            for (Track tr : ) {
                Rational trackDuration = new Rational((tr.length * tr.scale + tr.startTime), tr.rate);
                if (maxDuration.compareTo(trackDuration) < 0) {
                    maxDuration = trackDuration;
                }
            }
             = maxDuration;
        }
        return ;
    }
    @Override
    public Rational getDuration(int track) {
        Track tr = .get(track);
        Rational trackDuration = new Rational((tr.length * tr.scale + tr.startTime), tr.rate);
        return trackDuration;
    }
    @Override
    public long getTimeScale(int track) {
        return .get(track).;
    }
    @Override
    public long timeToSample(int trackRational time) {
        Track tr = .get(track);
        // This only works, if all samples contain only one sample!
        // FIXME - We foolishly assume that only audio tracks have more than one
        // sample in a frame.
        // FIXME - We foolishly assume that all samples have a sampleDuration != 0.
        long index = time.getNumerator() * tr.rate / time.getDenominator() / tr.scale - tr.startTime;
        if (tr.mediaType == .) {
            int count = 0;
            // FIXME This is very inefficient, perform binary search with sample.timestamp
            // this will work for all media types!
            for (int i = 0, n = tr.samples.size(); i < ni++) {
                long d = tr.samples.get(i). * tr.scale// foolishly assume that sampleDuration = sample count
                if (count + d > index) {
                    index = i;
                    break;
                }
                count += d;
            }
        }
        return max(0, min(indextr.samples.size()));
    }
    @Override
    public Rational sampleToTime(int tracklong sampleIndexthrows IOException {
        ensureRealized();
        Track tr = .get(track);
        Sample sample = tr.samples.get((intmax(0, min(tr.samples.size() - 1, sampleIndex)));
        long time = (tr.startTime + sample.timeStamp) * tr.scale;//
        if (sampleIndex >= tr.samples.size()) {
            time += sample.duration * tr.scale;
        }
        return new Rational(timetr.rate);
    }
    @Override
    public void setMovieReadTime(Rational newValuethrows IOException {
        ensureRealized();
        for (int t = 0, n = .size(); t < nt++) {
            Track tr = .get(t);
            int sample = (intmin(timeToSample(tnewValue), tr.samples.size() - 1);
            if (tr.readIndex > sample) {
                tr.readIndex = 0;
            }
            for (; sample >= 0 && sample > tr.readIndex && !tr.samples.get(sample).sample--);
            tr.readIndex = sample;
        }
    }
    @Override
    public int findTrack(int fromTrackFormat formatthrows IOException {
        for (int i = fromTrackn = getTrackCount(); i < ni++) {
            if (getFormat(i).matches(format)) {
                return i;
            }
        }
        return -1;
    }
New to GrepCode? Check out our FAQ X