All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.seleniumtests.util.video.avi.AbstractAVIStream Maven / Gradle / Ivy

There is a newer version: 4.23.18
Show newest version
/*
 * @(#)AbstractAVIStream.java  
 * 
 * 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 com.seleniumtests.util.video.avi;

import org.monte.media.riff.RIFFChunk;
import java.util.Map;
import org.monte.media.Buffer;
import org.monte.media.Codec;
import org.monte.media.Format;
import org.monte.media.io.SubImageOutputStream;
import java.awt.Dimension;
import java.awt.image.IndexColorModel;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import javax.imageio.stream.ImageOutputStream;
import static org.monte.media.VideoFormatKeys.*;

/**
 * This is the base class for low-level AVI stream IO.
 *
 * @author Werner Randelshofer
 * @version $Id: AbstractAVIStream.java 299 2013-01-03 07:40:18Z werner $
 */
public abstract class AbstractAVIStream {

    /**
     * Chunk IDs.
     */
    /*
    protected final static int RIFF_ID = 0x46464952;//0x52494646;// "RIFF"
    protected final static int AVI_ID = 0x20495641; //0x41564920;// "AVI "
    protected final static int LIST_ID = 0x5453494c;//0x4c495354;// "LIST"
    protected final static int MOVI_ID = 0x69766f6d;//0x6d6f7669;// "movi"
    protected final static int HDRL_ID = 0x6c726468;//0x6864726c;// "hdrl"
    protected final static int AVIH_ID = 0x68697661;//0x61766968;// "avih"
    protected final static int STRL_ID = 0x6c727473;//0x7374726c;// "strl"
    protected final static int STRH_ID = 0x68727473;//0x73747268;// "strh"
    protected final static int STRN_ID = 0x6e727473;//0x7374726e;// "strn"
    protected final static int STRF_ID = 0x66727473;//0x73747266;// "strf"
    protected final static int STRD_ID = 0x64727473;//0x73747264;// "strd"
    protected final static int IDX1_ID = 0x31786469;//0x69647831;// "idx1"
    protected final static int REC_ID = 0x20636572;//0x72656320;// "rec "
    protected final static int PC_ID = 0x63700000;//0x00007063;// "??pc"
    protected final static int DB_ID = 0x62640000;//0x00006462;// "??db"
    protected final static int DC_ID = 0x63640000;//0x00006463;// "??dc"
    protected final static int WB_ID = 0x62770000;//0x00007762;// "??wb"
    */
    protected final static int RIFF_ID =0x52494646;// "RIFF"
    protected final static int AVI_ID = 0x41564920;// "AVI "
    protected final static int AVIX_ID = 0x41564958;// "AVIX"
    protected final static int LIST_ID = 0x4c495354;// "LIST"
    protected final static int MOVI_ID = 0x6d6f7669;// "movi"
    protected final static int HDRL_ID = 0x6864726c;// "hdrl"
    protected final static int AVIH_ID = 0x61766968;// "avih"
    protected final static int STRL_ID = 0x7374726c;// "strl"
    protected final static int STRH_ID = 0x73747268;// "strh"
    protected final static int STRN_ID = 0x7374726e;// "strn"
    protected final static int STRF_ID = 0x73747266;// "strf"
    protected final static int STRD_ID = 0x73747264;// "strd"
    protected final static int IDX1_ID = 0x69647831;// "idx1"
    protected final static int REC_ID = 0x72656320;// "rec "
    protected final static int CHUNK_SUBTYPE_MASK = 0xffff;// "??xx"
    protected final static int PC_ID = 0x00007063;// "??pc"
    protected final static int DB_ID = 0x00006462;// "??db"
    protected final static int DC_ID = 0x00006463;// "??dc"
    protected final static int WB_ID = 0x00007762;// "??wb"
    
    /**
     * Indicates the AVI file has an index.
     */
    public final static int AVIH_FLAG_HAS_INDEX = 0x00000010;
    /**
     * Indicates that application should use the index, rather than the physical
     * ordering of the chunks in the file, to determine the order of
     * presentation of the data. For example, this flag could be used to create
     * a list of frames for editing.
     */
    public final static int AVIH_FLAG_MUST_USE_INDEX = 0x00000020;
    /**
     * Indicates the AVI file is interleaved.
     */
    public final static int AVIH_FLAG_IS_INTERLEAVED = 0x00000100;
    /**
     * ??
     */
    public final static int AVIH_FLAG_TRUST_CK_TYPE = 0x00000800;
    /**
     * // Indicates the AVI file is a specially allocated file used for
     * capturing real-time video. Applications should warn the user before
     * writing over a file with this flag set because the user probably
     * defragmented this file.
     */
    public final static int AVIH_FLAG_WAS_CAPTURE_FILE = 0x00010000;
    /* Indicates the AVI file contains copyrighted data and 
     * software. When this flag is used, software should not
     * permit the data to be duplicated. */
    public final static int AVIH_FLAG_COPYRIGHTED = 0x00020000;
    /**
     * Indicates this stream should not be enabled by default.
     */
    public final static int STRH_FLAG_DISABLED = 0x00000001;
    /**
     * Indicates this video stream contains palette changes. This flag warns the
     * playback software that it will need to animate the palette.
     */
    public final static int STRH_FLAG_VIDEO_PALETTE_CHANGES = 0x00010000;
    /**
     * Underlying output stream.
     */
    protected ImageOutputStream out;
    /**
     * The offset in the underlying ImageOutputStream. Normally this is 0 unless
     * the underlying stream already contained data when it was passed to the
     * constructor.
     */
    protected long streamOffset;

    /**
     * Supported media types.
     */
    public static enum AVIMediaType {

        AUDIO("auds"),//
        MIDI("mids"),//
        TEXT("txts"),//
        VIDEO("vids")//
        ;
        protected final String fccType;

        @Override
        public String toString() {
            return fccType;
        }

        AVIMediaType(String fourCC) {
            this.fccType = fourCC;
        }
    }
    /**
     * The list of tracks in the file.
     */
    protected ArrayList tracks = new ArrayList();

    /**
     * Gets the position relative to the beginning of the QuickTime stream. 

* Usually this value is equal to the stream position of the underlying * ImageOutputStream, but can be larger if the underlying stream already * contained data. * * @return The relative stream position. * @throws IOException */ protected long getRelativeStreamPosition() throws IOException { return out.getStreamPosition() - streamOffset; } /** * Seeks relative to the beginning of the AVI stream.

Usually this equal * to seeking in the underlying ImageOutputStream, but can be different if * the underlying stream already contained data. * */ protected void seekRelative(long newPosition) throws IOException { out.seek(newPosition + streamOffset); } /** * AVI stores media data in sample chunks. A sample chunk may contain one or * more media samples. A media sample is a single element in a sequence of * time-ordered data. */ protected static class Sample { int chunkType; /** * Offset of the sample chunk relative to the startTime of the AVI file. */ long offset; /** * Data length of the sample chunk. */ long length; /** * The number of media samples in the sample chunk. */ int duration; /** * Whether the sample is a sync-sample. */ boolean isKeyframe; long timeStamp; /** * Palette change sample. */ Sample header; /** * Creates a new sample. * * @param duration The number of media samples contained in the sample * chunk. * @param offset The offset in the AVI stream. * @param length The length in the AVI stream. */ public Sample(int chunkId, int duration, long offset, long length, boolean isSync) { this.chunkType = chunkId; this.duration = duration; this.offset = offset; this.length = length; this.isKeyframe = isSync; } } /** * Represents a track (or "stream") in an AVI file.

A track is defined * by an "strh" chunk, which contains an {@code AVISTREAMHEADER} struct. * Additional chunks can be provided depending on the media type of the * track.

See * http://msdn.microsoft.com/en-us/library/ms779638(VS.85).aspx

*
     * -----------------
     * AVI Stream Header
     * -----------------
     *
     * enum {
     *    audioStream = "auds",
     *   midiStream = "mids",
     *   textStream = "txts",
     *   videoStream = "vids"
     * } aviStrhType;
     *
     * set {
     *    disabled = 0x00000001, // Indicates this stream should not be enabled by default.
     *    videoPaletteChanges = 0x00010000
     *        // Indicates this video stream contains palette changes. This flag
     *        // warns the playback software that it will need to animate the palette.
     *} aviStrhFlags;
     *
     *typedef struct {
     *    Int16 left;
     *    Int16 top;
     *    Int16 right;
     *    Int16 bottom;
     *} aviRectangle;
     *
     *typedef struct {
     *     FOURCC enum aviStrhType type;
     *        // Contains a FOURCC that specifies the type of the data contained in
     *        // the stream. The following standard AVI values for video and audio are
     *        // defined.
     *     FOURCC handler;
     *        // Optionally, contains a FOURCC that identifies a specific data
     *        // handler.
     *        // The data handler is the preferred handler for the stream. For audio
     *        // and video streams, this specifies the codec for decoding the stream.
     *     DWORD  set aviStrhFlags flags;
     *        // Contains any flags for the data stream. The bits in the high-order
     *        // word of these flags are specific to the type of data contained in the
     *        // stream.
     *     WORD   priority;
     *        // Specifies priority of a stream type. For example, in a file with
     *        // multiple audio streams, the one with the highest priority might be
     *        // the default stream.
     *     WORD   language;
     *     DWORD  initialFrames;
     *        // Specifies how far audio data is skewed ahead of the video frames in
     *        // interleaved files. Typically, this is about 0.75 seconds. If you are
     *        // creating interleaved files, specify the number of frames in the file
     *        // prior to the initial frame of the AVI sequence in this member. For
     *        // more information about the contents of this member, see "Special
     *        // Information for Interleaved Files" in the Video for Windows
     *        // Programmer's Guide.
     *     DWORD  scale;
     *        // Used with "rate" to specify the time scale that this stream will use.
     *        // Dividing "rate" by "scale" gives the number of samples per second.
     *        // For video streams, this is the frame rate. For audio streams, this
     *        // rate corresponds to the time needed to play blockAlign bytes of
     *        // audio, which for PCM audio is the just the sample rate.
     *     DWORD  rate;
     *        // See "scale".
     *     DWORD  startTime;
     *        // Specifies the starting time for this stream. The units are defined by
     *        // the "rate" and "scale" members in the main file header. Usually, this
     *        // is zero, but it can specify a delay time for a stream that does not
     *        // startTime concurrently with the file.
     *     DWORD  length;
     *        // Specifies the length of this stream. The units are defined by the
     *        // "rate" and "scale" members of the stream's header.
     *     DWORD  suggestedBufferSize;
     *        // Specifies how large a buffer should be used to read this stream.
     *        // Typically, this contains a value corresponding to the largest chunk
     *        // present in the stream. Using the correct buffer size makes playback
     *        // more efficient. Use zero if you do not know the correct buffer size.
     *     DWORD  quality;
     *        // Specifies an indicator of the quality of the data in the stream.
     *        // Quality is represented as a number between 0 and 10,000. For
     *        // compressed data, this typically represents the value of the quality
     *        // parameter passed to the compression software. If set to �1, drivers
     *        // use the default quality value.
     *     DWORD  sampleSize;
     *        // Specifies the size of a single sample of data. This is set to zero if
     *        // the samples can vary in size. If this number is nonzero, then
     *        // multiple samples of data can be grouped into a single chunk within
     *        // the file. If it is zero, each sample of data (such as a video frame)
     *        // must be in a separate chunk. For video streams, this number is
     *        // typically zero, although it can be nonzero if all video frames are
     *        // the same size. For audio streams, this number should be the same as
     *        // the blockAlign member of the WAVEFORMATEX structure describing the audio.
     *    aviRectangle frame;
     *        // Specifies the destination rectangle for a text or video stream within
     *        // the movie rectangle specified by the "frameWidth" and "frameHeight"
     *        // members of the AVI main header structure. The "frame" member is
     *        // typically used in support of multiple video streams. Set this
     *        // rectangle to the coordinates corresponding to the movie rectangle to
     *        // update the whole movie rectangle. Units for this member are pixels.
     *        // The upper-left corner of the destination rectangle is relative to the
     *        // upper-left corner of the movie rectangle.
     * } AVISTREAMHEADER; * 
*/ protected abstract class Track { /** * The media format. * * FIXME - AbstractAVIStream should have no dependencies to Format. */ protected Format format; // Common metadata /** * The scale of the media in the track.

Used with rate to specify * the time scale that this stream will use. Dividing rate by scale * gives the number of samples per second. For video streams, this is * the frame rate. For audio streams, this rate corresponds to the time * needed to play blockAlign bytes of audio, which for PCM audio is just * the sample rate. */ /** * The rate of the media in scale units.

* * @see scale */ /** * List of samples. */ protected ArrayList samples; /** * Interval between sync samples (keyframes). 0 = automatic. 1 = write * all samples as sync samples. n = sync every n-th sample. */ protected int syncInterval = 30; /** * The twoCC code is used for the ids of the chunks which hold the data * samples. */ protected int twoCC; // // AVISTREAMHEADER structure // ------------------------- /** * {@code mediaType.fccType} contains a FOURCC that specifies the type * of the data contained in the stream. The following standard AVI * values for video and audio are defined. * * FOURCC Description 'auds' Audio stream 'mids' MIDI stream 'txts' Text * stream 'vids' Video stream * */ protected final AVIMediaType mediaType; //protected String fccType; /** * Optionally, contains a FOURCC that identifies a specific data * handler. The data handler is the preferred handler for the stream. * For audio and video streams, this specifies the codec for decoding * the stream. */ protected int fccHandler; /** * Contains any flags for the data stream. The bits in the high-order * word of these flags are specific to the type of data contained in the * stream. The following standard flags are defined. * * Value Description * * AVISF_DISABLED 0x00000001 Indicates this stream should not be enabled * by default. * * AVISF_VIDEO_PALCHANGES 0x00010000 Indicates this video stream * contains palette changes. This flag warns the playback software that * it will need to animate the palette. */ protected int flags; /** * Specifies priority of a stream type. For example, in a file with * multiple audio streams, the one with the highest priority might be * the default stream. */ protected int priority = 0; /** * Language tag. */ protected int language = 0; /** * Specifies how far audio data is skewed ahead of the video frames in * interleaved files. Typically, this is about 0.75 seconds. If you are * creating interleaved files, specify the number of frames in the file * prior to the initial frame of the AVI sequence in this member. For * more information, see the remarks for the initialFrames member of the * AVIMAINHEADER structure. */ protected long initialFrames = 0; /** * Used with rate to specify the time scale that this stream will use. * Dividing rate by scale gives the number of samples per second. For * video streams, this is the frame rate. For audio streams, this rate * corresponds to the time needed to play blockAlign bytes of audio, * which for PCM audio is the just the sample rate. */ protected long scale = 1; /** * The rate of the media in scale units. */ protected long rate = 30; /** * Specifies the starting time for this stream. The units are defined by * the rate and scale members in the main file header. Usually, this is * zero, but it can specify a delay time for a stream that does not * startTime concurrently with the file. */ protected long startTime = 0; /** * Specifies the length of this stream. The units are defined by the * rate and scale members of the stream's header. */ protected long length; /** * Specifies how large a buffer should be used to read this stream. * Typically, this contains a value corresponding to the largest chunk * present in the stream. Using the correct buffer size makes playback * more efficient. Use zero if you do not know the correct buffer size. */ //protected long dwSuggestedBufferSize; => this field is computed from tr.samples /** * Specifies an indicator of the quality of the data in the stream. * Quality is represented as a number between 0 and 10,000. For * compressed data, this typically represents the value of the quality * parameter passed to the compression software. If set to –1, drivers * use the default quality value. */ protected int quality = -1; /** * Specifies the size of a single sample of data. This is set to zero if * the samples can vary in size. If this number is nonzero, then * multiple samples of data can be grouped into a single chunk within * the file. If it is zero, each sample of data (such as a video frame) * must be in a separate chunk. For video streams, this number is * typically zero, although it can be nonzero if all video frames are * the same size. For audio streams, this number should be the same as * the blockAlign member of the WAVEFORMATEX structure describing the * audio. */ //protected long dwSampleSize; => computed from tr.samples /** * Specifies the destination rectangle for a text or video stream within * the movie rectangle specified by the dwWidth and dwHeight members of * the AVI main header structure. The rcFrame member is typically used * in support of multiple video streams. Set this rectangle to the * coordinates corresponding to the movie rectangle to update the whole * movie rectangle. Units for this member are pixels. The upper-left * corner of the destination rectangle is relative to the upper-left * corner of the movie rectangle. */ int frameLeft; int frameTop; int frameRight; int frameBottom; // -------------------------------- // End of AVISTREAMHEADER structure /** * This chunk holds the AVI Stream Header. */ protected FixedSizeDataChunk strhChunk; /** * This chunk holds the AVI Stream Format Header. */ protected FixedSizeDataChunk strfChunk; /** * The optional name of the track. */ protected String name; /** * The codec. */ protected Codec codec; /** * The output buffer is used to store the output of the codec. */ protected Buffer outputBuffer; /** * The input buffer is used when one of the convenience methods without * a Buffer parameter is used. */ protected Buffer inputBuffer; /** * The current chunk index of the reader. */ protected long readIndex = 0; /** * List of additional header chunks. */ protected ArrayList extraHeaders; public Track(int trackIndex, AVIMediaType mediaType, int fourCC) { this.mediaType = mediaType; twoCC = (('0'+trackIndex/10)<<24) | (('0'+trackIndex%10)<<16); this.fccHandler = fourCC; this.samples = new ArrayList(); this.extraHeaders = new ArrayList(); } public abstract long getSTRFChunkSize(); public abstract int getSampleChunkFourCC(boolean isSync); public void addSample(Sample s) { if (!samples.isEmpty()) { s.timeStamp = samples.get(samples.size() - 1).timeStamp + samples.get(samples.size() - 1).duration; } samples.add(s); length++; } } /** * Represents a video track in an AVI file.

The format of a video track * is defined in a "strf" chunk, which contains a {@code BITMAPINFOHEADER} * struct. * *

//---------------------- // AVI Bitmap Info Header // * ---------------------- typedef struct { BYTE blue; BYTE green; BYTE red; * BYTE reserved; } RGBQUAD; * * // Values for this enum taken from: // * http://www.fourcc.org/index.php?http%3A//www.fourcc.org/rgb.php enum { * BI_RGB = 0x00000000, RGB = 0x32424752, // Alias for BI_RGB BI_RLE8 = * 0x01000000, RLE8 = 0x38454C52, // Alias for BI_RLE8 BI_RLE4 = 0x00000002, * RLE4 = 0x34454C52, // Alias for BI_RLE4 BI_BITFIELDS = 0x00000003, raw = * 0x32776173, RGBA = 0x41424752, RGBT = 0x54424752, cvid = "cvid" } * bitmapCompression; * * typedef struct { DWORD structSize; // Specifies the number of bytes * required by the structure. LONG width; // Specifies the width of the * bitmap. // - For RGB formats, the width is specified in pixels. // - The * same is true for YUV formats if the bitdepth is an even power // of 2. // * - For YUV formats where the bitdepth is not an even power of 2, // * however, the width is specified in bytes. // Decoders and video sources * should propose formats where "width" is // the width of the image. If the * video renderer is using DirectDraw, it // modifies the format so that * "width" equals the stride of the surface, // and the "target" member of * the VIDEOINFOHEADER or VIDEOINFOHEADER2 // structure specifies the image * width. Then it proposes the modified // format using IPin::QueryAccept. * // For RGB and even-power-of-2 YUV formats, if the video renderer does // * not specify the stride, then round the width up to the nearst DWORD // * boundary to find the stride. LONG height; // Specifies the height of the * bitmap, in pixels. // - For uncompressed RGB bitmaps, if "height" is * positive, the bitmap // is a bottom-up DIB with the origin at the lower * left corner. If // "height" is negative, the bitmap is a top-down DIB * with the origin // at the upper left corner. // - For YUV bitmaps, the * bitmap is always top-down, regardless of the // sign of "height". * Decoders should offer YUV formats with postive // "height", but for * backward compatibility they should accept YUV // formats with either * positive or negative "height". // - For compressed formats, height must * be positive, regardless of // image orientation. WORD planes; // * Specifies the number of planes for the target device. This value must // * be set to 1. WORD bitCount; // Specifies the number of bits per pixel. * //DWORD enum bitmapCompression compression; FOURCC enum bitmapCompression * compression; // If the bitmap is compressed, this member is a FOURCC the * specifies // the compression. // Value Description // BI_RLE8 A * run-length encoded (RLE) format for bitmaps with 8 // bpp. The * compression format is a 2-byte format // consisting of a count byte * followed by a byte containing a color index. For more information, see * Bitmap Compression. // BI_RLE4 An RLE format for bitmaps with 4 bpp. The * compression // format is a 2-byte format consisting of a count byte // * followed by two word-length color indexes. For more // information, see * Bitmap Compression. // BI_JPEG Windows 98/Me, Windows 2000/XP: Indicates * that the // image is a JPEG image. // BI_PNG Windows 98/Me, Windows * 2000/XP: Indicates that the // image is a PNG image. // For uncompressed * formats, the following values are possible: // Value Description // * BI_RGB Uncompressed RGB. // BI_BITFIELDS Specifies that the bitmap is not * compressed and that // the color table consists of three DWORD color * masks // that specify the red, green, and blue components, // * respectively, of each pixel. This is valid when used // with 16- and * 32-bpp bitmaps. DWORD imageSizeInBytes; // Specifies the size, in bytes, * of the image. This can be set to 0 for // uncompressed RGB bitmaps. LONG * xPelsPerMeter; // Specifies the horizontal resolution, in pixels per * meter, of the // target device for the bitmap. LONG yPelsPerMeter; // * Specifies the vertical resolution, in pixels per meter, of the target // * device for the bitmap. DWORD numberOfColorsUsed; // Specifies the number * of color indices in the color table that are // actually used by the * bitmap DWORD numberOfColorsImportant; // Specifies the number of color * indices that are considered important // for displaying the bitmap. If * this value is zero, all colors are // important. RGBQUAD colors[]; // If * the bitmap is 8-bpp or less, the bitmap uses a color table, which // * immediately follows the BITMAPINFOHEADER. The color table consists of // * an array of RGBQUAD values. The size of the array is given by the // * "clrUsed" member. If "clrUsed" is zero, the array contains the // maximum * number of colors for the given bitdepth; that is, // 2^"bitCount" colors. * } BITMAPINFOHEADER; * */ protected class VideoTrack extends Track { // Video metadata /** * The video compression quality. */ protected float videoQuality = 0.97f; /** * Index color model for RAW_RGB4 and RAW_RGB8 formats. */ protected IndexColorModel palette; protected IndexColorModel previousPalette; /** * Previous frame for delta compression. */ protected Object previousData; //protected Rectangle rcFrame; // BITMAPINFOHEADER structure /** * Specifies the number of bytes required by the structure. This value * does not include the size of the color table or the size of the color * masks, if they are appended to the end of structure. */ //protected long biSize; => computed when writing chukn /** * Specifies the width of the bitmap, in pixels. For information about * calculating the stride of the bitmap. * */ int width; /** * Specifies the height of the bitmap, in pixels. * * For uncompressed RGB bitmaps, if height is positive, the bitmap is a * bottom-up DIB with the origin at the lower left corner. If height is * negative, the bitmap is a top-down DIB with the origin at the upper * left corner. For YUV bitmaps, the bitmap is always top-down, * regardless of the sign of height. Decoders should offer YUV formats * with positive height, but for backward compatibility they should * accept YUV formats with either positive or negative height. For * compressed formats, height must be positive, regardless of image * orientation. */ int height; /** * Specifies the number of planes for the target device. This value must * be set to 1. */ int planes; /** * Specifies the number of bits per pixel (bpp). For uncompressed * formats, this value is the average number of bits per pixel. For * compressed formats, this value is the implied bit depth of the * uncompressed image, after the image has been decoded. */ int bitCount; /** * For compressed video and YUV formats, this member is a FOURCC code, * specified as a DWORD in little-endian order. For example, YUYV video * has the FOURCC 'VYUY' or 0x56595559. * * For uncompressed RGB formats, the following values are possible: * * Value Description * * BI_RGB Uncompressed RGB. * * BI_BITFIELDS Uncompressed RGB with color masks. Valid for 16-bpp and * 32-bpp bitmaps. * * Note that BI_JPG and BI_PNG are not valid video formats. * * For 16-bpp bitmaps, if compression equals BI_RGB, the format is * always RGB 555. If compression equals BI_BITFIELDS, the format is * either RGB 555 or RGB 565. Use the subtype GUID in the AM_MEDIA_TYPE * structure to determine the specific RGB type. */ String compression; /** * Specifies the size, in bytes, of the image. This can be set to 0 for * uncompressed RGB bitmaps. */ long sizeImage; /** * Specifies the horizontal resolution, in pixels per meter, of the * target device for the bitmap. */ long xPelsPerMeter; /** * Specifies the vertical resolution, in pixels per meter, of the target * device for the bitmap. */ long yPelsPerMeter; /** * Specifies the number of color indices in the color table that are * actually used by the bitmap. See Remarks for more information. */ long clrUsed; /** * Specifies the number of color indices that are considered important * for displaying the bitmap. If this value is zero, all colors are * important. */ long clrImportant; private int sampleChunkFourCC; public VideoTrack(int trackIndex, int fourCC, Format videoFormat) { super(trackIndex, AVIMediaType.VIDEO, fourCC); this.format = videoFormat; sampleChunkFourCC = videoFormat != null && videoFormat.get(EncodingKey).equals(ENCODING_AVI_DIB) ? twoCC | DB_ID : twoCC | DC_ID; } @Override public long getSTRFChunkSize() { return palette == null ? 40 : 40 + palette.getMapSize() * 4; } @Override public int getSampleChunkFourCC(boolean isSync) { return sampleChunkFourCC; } } /** *

The format of a video track is defined in a "strf" chunk, which * contains a {@code WAVEFORMATEX} struct. *

     * ----------------------
     * AVI Wave Format Header
     * ----------------------
     * // values for this enum taken from mmreg.h
     * enum {
     *         WAVE_FORMAT_PCM = 0x0001,
     *         //  Microsoft Corporation
     *         WAVE_FORMAT_ADPCM = 0x0002,
     *         //  Microsoft Corporation
     *          *   IEEE754: range (+1, -1]
     *          *  32-bit/64-bit format as defined by
     *          *  MSVC++ float/double type
     *
     *         WAVE_FORMAT_IEEE_FLOAT = 0x0003,
     *         //  IBM Corporation
     *         WAVE_FORMAT_IBM_CVSD = 0x0005,
     *         //  Microsoft Corporation
     *         WAVE_FORMAT_ALAW = 0x0006,
     *         //  Microsoft Corporation
     *         WAVE_FORMAT_MULAW = 0x0007,
     *         //  OKI
     *         WAVE_FORMAT_OKI_ADPCM = 0x0010,
     *         //  Intel Corporation
     *         WAVE_FORMAT_DVI_ADPCM = 0x0011,
     *         //  Intel Corporation
     *         WAVE_FORMAT_IMA_ADPCM = 0x0011,
     *         //  Videologic
     *         WAVE_FORMAT_MEDIASPACE_ADPCM = 0x0012,
     *         //  Sierra Semiconductor Corp
     *         WAVE_FORMAT_SIERRA_ADPCM = 0x0013,
     *         //  Antex Electronics Corporation
     *         WAVE_FORMAT_G723_ADPCM = 0x0014,
     *         //  DSP Solutions, Inc.
     *         WAVE_FORMAT_DIGISTD = 0x0015,
     *         //  DSP Solutions, Inc.
     *         WAVE_FORMAT_DIGIFIX = 0x0016,
     *         //  Dialogic Corporation
     *         WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 0x0017,
     *         //  Media Vision, Inc.
     *         WAVE_FORMAT_MEDIAVISION_ADPCM = 0x0018,
     *         //  Yamaha Corporation of America
     *         WAVE_FORMAT_YAMAHA_ADPCM = 0x0020,
     *         //  Speech Compression
     *         WAVE_FORMAT_SONARC = 0x0021,
     *         //  DSP Group, Inc
     *         WAVE_FORMAT_DSPGROUP_TRUESPEECH = 0x0022,
     *         //  Echo Speech Corporation
     *         WAVE_FORMAT_ECHOSC1 = 0x0023,
     *         //
     *         WAVE_FORMAT_AUDIOFILE_AF36 = 0x0024,
     *         //  Audio Processing Technology
     *         WAVE_FORMAT_APTX = 0x0025,
     *         //
     *         WAVE_FORMAT_AUDIOFILE_AF10 = 0x0026,
     *         //  Dolby Laboratories
     *         WAVE_FORMAT_DOLBY_AC2 = 0x0030,
     *         //  Microsoft Corporation
     *         WAVE_FORMAT_GSM610 = 0x0031,
     *         //  Microsoft Corporation
     *         WAVE_FORMAT_MSNAUDIO = 0x0032,
     *         //  Antex Electronics Corporation
     *         WAVE_FORMAT_ANTEX_ADPCME = 0x0033,
     *         //  Control Resources Limited
     *         WAVE_FORMAT_CONTROL_RES_VQLPC = 0x0034,
     *         //  DSP Solutions, Inc.
     *         WAVE_FORMAT_DIGIREAL = 0x0035,
     *         //  DSP Solutions, Inc.
     *         WAVE_FORMAT_DIGIADPCM = 0x0036,
     *         //  Control Resources Limited
     *         WAVE_FORMAT_CONTROL_RES_CR10 = 0x0037,
     *         //  Natural MicroSystems
     *         WAVE_FORMAT_NMS_VBXADPCM = 0x0038,
     *         // Crystal Semiconductor IMA ADPCM
     *         WAVE_FORMAT_CS_IMAADPCM = 0x0039,
     *         // Echo Speech Corporation
     *         WAVE_FORMAT_ECHOSC3 = 0x003A,
     *         // Rockwell International
     *         WAVE_FORMAT_ROCKWELL_ADPCM = 0x003B,
     *         // Rockwell International
     *         WAVE_FORMAT_ROCKWELL_DIGITALK = 0x003C,
     *         // Xebec Multimedia Solutions Limited
     *         WAVE_FORMAT_XEBEC = 0x003D,
     *         //  Antex Electronics Corporation
     *         WAVE_FORMAT_G721_ADPCM = 0x0040,
     *         //  Antex Electronics Corporation
     *         WAVE_FORMAT_G728_CELP = 0x0041,
     *         //  Microsoft Corporation
     *         WAVE_FORMAT_MPEG = 0x0050,
     *         //  ISO/MPEG Layer3 Format Tag
     *         WAVE_FORMAT_MPEGLAYER3 = 0x0055,
     *         //  Cirrus Logic
     *         WAVE_FORMAT_CIRRUS = 0x0060,
     *         //  ESS Technology
     *         WAVE_FORMAT_ESPCM = 0x0061,
     *         //  Voxware Inc
     *         WAVE_FORMAT_VOXWARE = 0x0062,
     *         //  Canopus, co., Ltd.
     *         WAVE_FORMAT_CANOPUS_ATRAC = 0x0063,
     *         //  APICOM
     *         WAVE_FORMAT_G726_ADPCM = 0x0064,
     *         //  APICOM
     *         WAVE_FORMAT_G722_ADPCM = 0x0065,
     *         //  Microsoft Corporation
     *         WAVE_FORMAT_DSAT = 0x0066,
     *         //  Microsoft Corporation
     *         WAVE_FORMAT_DSAT_DISPLAY = 0x0067,
     *         //  Softsound, Ltd.
     *         WAVE_FORMAT_SOFTSOUND = 0x0080,
     *         //  Rhetorex Inc
     *         WAVE_FORMAT_RHETOREX_ADPCM = 0x0100,
     *         //  Creative Labs, Inc
     *         WAVE_FORMAT_CREATIVE_ADPCM = 0x0200,
     *         //  Creative Labs, Inc
     *         WAVE_FORMAT_CREATIVE_FASTSPEECH8 = 0x0202,
     *         //  Creative Labs, Inc
     *         WAVE_FORMAT_CREATIVE_FASTSPEECH10 = 0x0203,
     *         //  Quarterdeck Corporation
     *         WAVE_FORMAT_QUARTERDECK = 0x0220,
     *         //  Fujitsu Corp.
     *         WAVE_FORMAT_FM_TOWNS_SND = 0x0300,
     *         //  Brooktree Corporation
     *         WAVE_FORMAT_BTV_DIGITAL = 0x0400,
     *         //  Ing C. Olivetti & C., S.p.A.
     *         WAVE_FORMAT_OLIGSM = 0x1000,
     *         //  Ing C. Olivetti & C., S.p.A.
     *         WAVE_FORMAT_OLIADPCM = 0x1001,
     *         //  Ing C. Olivetti & C., S.p.A.
     *         WAVE_FORMAT_OLICELP = 0x1002,
     *         //  Ing C. Olivetti & C., S.p.A.
     *         WAVE_FORMAT_OLISBC = 0x1003,
     *         //  Ing C. Olivetti & C., S.p.A.
     *         WAVE_FORMAT_OLIOPR = 0x1004,
     *         //  Lernout & Hauspie
     *         WAVE_FORMAT_LH_CODEC = 0x1100,
     *         //  Norris Communications, Inc.
     *         WAVE_FORMAT_NORRIS = 0x1400,
     *         //
     *          *  the WAVE_FORMAT_DEVELOPMENT format tag can be used during the
     *          *  development phase of a new wave format.  Before shipping, you MUST
     *          *  acquire an official format tag from Microsoft.
     *
     *         WAVE_FORMAT_DEVELOPMENT = 0xFFFF,
     * } wFormatTagEnum;
     *
     * typedef struct {
     *   WORD enum wFormatTagEnum formatTag;
     *     // Waveform-audio format type. Format tags are registered with Microsoft
     *     // Corporation for many compression algorithms. A complete list of format
     *     // tags can be found in the Mmreg.h header file. For one- or two-channel
     *     // Pulse Code Modulation (PCM) data, this value should be WAVE_FORMAT_PCM.
     *   WORD  numberOfChannels;
     *     // Number of channels in the waveform-audio data. Monaural data uses one
     *     // channel and stereo data uses two channels.
     *   DWORD samplesPerSec;
     *     // Sample rate, in samples per second (hertz). If "formatTag" is
     *     // "WAVE_FORMAT_PCM", then common values for "samplesPerSec" are 8.0 kHz,
     *     // 11.025 kHz, 22.05 kHz, and 44.1 kHz. For non-PCM formats, this member
     *     // must be computed according to the manufacturer's specification of the
     *     // format tag.
     *   DWORD avgBytesPerSec;
     *     // Required average data-transfer rate, in bytes per second, for the format
     *     // tag. If "formatTag" is "WAVE_FORMAT_PCM", "avgBytesPerSec" should be
     *     // equal to the product of "samplesPerSec" and "blockAlignment". For non-PCM
     *     // formats, this member must be computed according to the manufacturer's
     *     // specification of the format tag.
     *   WORD  blockAlignment;
     *     // Block alignment, in bytes. The block alignment is the minimum atomic unit
     *     // of data for the "formatTag" format type. If "formatTag" is
     *     // "WAVE_FORMAT_PCM" or "WAVE_FORMAT_EXTENSIBLE, "blockAlignment" must be equal
     *     // to the product of "numberOfChannels" and "bitsPerSample" divided by 8 (bits per
     *     // byte). For non-PCM formats, this member must be computed according to the
     *     // manufacturer's specification of the format tag.
     *     // Software must process a multiple of "blockAlignment" bytes of data at a
     *     // time. Data written to and read from a device must always start at the
     *     // beginning of a block. For example, it is illegal to start playback of PCM
     *     // data in the middle of a sample (that is, on a non-block-aligned boundary).
     *   WORD  bitsPerSample;
     *     // Bits per sample for the waveFormatTag format type. If "formatTag" is
     *     // "WAVE_FORMAT_PCM", then "bitsPerSample" should be equal to 8 or 16. For
     *     // non-PCM formats, this member must be set according to the manufacturer's
     *     // specification of the format tag. If "formatTag" is
     *     // "WAVE_FORMAT_EXTENSIBLE", this value can be any integer multiple of 8.
     *     // Some compression schemes cannot define a value for "bitsPerSample", so
     *     // this member can be zero.
     *   WORD  cbSize;
     *     // Size, in bytes, of extra format information appended to the end of the
     *     // WAVEFORMATEX structure. This information can be used by non-PCM formats
     *     // to store extra attributes for the "wFormatTag". If no extra information
     *     // is required by the "wFormatTag", this member must be set to zero. For
     *     // WAVE_FORMAT_PCM formats (and only WAVE_FORMAT_PCM formats), this member
     *     // is ignored.
     *   byte[cbSize] extra;
     * } WAVEFORMATEX;
     * 
*/ protected class AudioTrack extends Track { // WAVEFORMATEX Structure /** * Waveform-audio format type. Format tags are registered with Microsoft * Corporation for many compression algorithms. A complete list of * format tags can be found in the Mmreg.h header file. For one- or * two-channel Pulse Code Modulation (PCM) data, this value should be * WAVE_FORMAT_PCM=0x0001. * * If wFormatTag equals WAVE_FORMAT_EXTENSIBLE=0xFFFE, the structure is * interpreted as a WAVEFORMATEXTENSIBLE structure. If wFormatTag equals * WAVE_FORMAT_MPEG, the structure is interpreted as an MPEG1WAVEFORMAT * structure. If wFormatTag equals MPEGLAYER3WAVEFORMAT, the structure * is interpreted as an MPEGLAYER3WAVEFORMAT structure. Before * reinterpreting a WAVEFORMATEX structure as one of these extended * structures, verify that the actual structure size is sufficiently * large and that the cbSize member indicates a valid size. */ protected int wFormatTag; /** * Number of channels in the waveform-audio data. Monaural data uses one * channel and stereo data uses two channels. */ protected int channels; /** * Sample rate, in samples per second (hertz). If wFormatTag is * WAVE_FORMAT_PCM, then common values for samplesPerSec are 8.0 kHz, * 11.025 kHz, 22.05 kHz, and 44.1 kHz. For non-PCM formats, this member * must be computed according to the manufacturer's specification of the * format tag. */ protected long samplesPerSec; /** * Required average data-transfer rate, in bytes per second, for the * format tag. If wFormatTag is WAVE_FORMAT_PCM, avgBytesPerSec should * be equal to the product of samplesPerSec and blockAlign. For non-PCM * formats, this member must be computed according to the manufacturer's * specification of the format tag. */ protected long avgBytesPerSec; /** * Block alignment, in bytes. The block alignment is the minimum atomic * unit of data for the wFormatTag format type. If wFormatTag is * WAVE_FORMAT_PCM or WAVE_FORMAT_EXTENSIBLE, blockAlign must be equal * to the product of channels and bitsPerSample divided by 8 (bits per * byte). For non-PCM formats, this member must be computed according to * the manufacturer's specification of the format tag. * * Software must process a multiple of blockAlign bytes of data at a * time. Data written to and read from a device must always startTime at * the beginning of a block. For example, it is illegal to startTime * playback of PCM data in the middle of a sample (that is, on a * non-block-aligned boundary). */ protected int blockAlign; /** * Bits per sample for the wFormatTag format type. If wFormatTag is * WAVE_FORMAT_PCM, then bitsPerSample should be equal to 8 or 16. For * non-PCM formats, this member must be set according to the * manufacturer's specification of the format tag. If wFormatTag is * WAVE_FORMAT_EXTENSIBLE, this value can be any integer multiple of 8. * Some compression schemes cannot define a value for bitsPerSample, so * this member can be zero. */ protected int bitsPerSample; /** * Size, in bytes, of extra format information appended to the end of * the WAVEFORMATEX structure. This information can be used by non-PCM * formats to store extra attributes for the wFormatTag. If no extra * information is required by the wFormatTag, this member must be set to * zero. For WAVE_FORMAT_PCM formats (and only WAVE_FORMAT_PCM formats), * this member is ignored. */ //int cbSize; => this value is computed // Well known wave format tags /** * Microsoft Corporation */ protected final static int WAVE_FORMAT_PCM = 0x0001; /** * Microsoft Corporation */ protected final static int WAVE_FORMAT_ADPCM = 0x0002; /** * Microsoft Corporation IEEE754: range (+1, -1] 32-bit/64-bit format as * defined by MSVC++ float/double type */ protected final static int WAVE_FORMAT_IEEE_FLOAT = 0x0003; /** * IBM Corporation */ protected final static int WAVE_FORMAT_IBM_CVSD = 0x0005; /** * Microsoft Corporation */ protected final static int WAVE_FORMAT_ALAW = 0x0006; /** * Microsoft Corporation */ protected final static int WAVE_FORMAT_MULAW = 0x0007; /** * OKI */ protected final static int WAVE_FORMAT_OKI_ADPCM = 0x0010; /** * Intel Corporation */ protected final static int WAVE_FORMAT_DVI_ADPCM = 0x0011; /** * Intel Corporation */ protected final static int WAVE_FORMAT_IMA_ADPCM = WAVE_FORMAT_DVI_ADPCM; /** * Videologic */ protected final static int WAVE_FORMAT_MEDIASPACE_ADPCM = 0x0012; /** * Sierra Semiconductor Corp */ protected final static int WAVE_FORMAT_SIERRA_ADPCM = 0x0013; /** * Antex Electronics Corporation */ protected final static int WAVE_FORMAT_G723_ADPCM = 0x0014; /** * DSP Solutions, Inc. */ protected final static int WAVE_FORMAT_DIGISTD = 0x0015; /** * DSP Solutions, Inc. */ protected final static int WAVE_FORMAT_DIGIFIX = 0x0016; /** * Dialogic Corporation */ protected final static int WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 0x0017; /** * Media Vision, Inc. */ protected final static int WAVE_FORMAT_MEDIAVISION_ADPCM = 0x0018; /** * Yamaha Corporation of America */ protected final static int WAVE_FORMAT_YAMAHA_ADPCM = 0x0020; /** * Speech Compression */ protected final static int WAVE_FORMAT_SONARC = 0x0021; /** * DSP Group, Inc */ protected final static int WAVE_FORMAT_DSPGROUP_TRUESPEECH = 0x0022; /** * Echo Speech Corporation */ protected final static int WAVE_FORMAT_ECHOSC1 = 0x0023; /** * */ protected final static int WAVE_FORMAT_AUDIOFILE_AF36 = 0x0024; /** * Audio Processing Technology */ protected final static int WAVE_FORMAT_APTX = 0x0025; /** * */ protected final static int WAVE_FORMAT_AUDIOFILE_AF10 = 0x0026; /** * Dolby Laboratories */ protected final static int WAVE_FORMAT_DOLBY_AC2 = 0x0030; /** * Microsoft Corporation */ protected final static int WAVE_FORMAT_GSM610 = 0x0031; /** * Microsoft Corporation */ protected final static int WAVE_FORMAT_MSNAUDIO = 0x0032; /** * Antex Electronics Corporation */ protected final static int WAVE_FORMAT_ANTEX_ADPCME = 0x0033; /** * Control Resources Limited */ protected final static int WAVE_FORMAT_CONTROL_RES_VQLPC = 0x0034; /** * DSP Solutions, Inc. */ protected final static int WAVE_FORMAT_DIGIREAL = 0x0035; /** * DSP Solutions, Inc. */ protected final static int WAVE_FORMAT_DIGIADPCM = 0x0036; /** * Control Resources Limited */ protected final static int WAVE_FORMAT_CONTROL_RES_CR10 = 0x0037; /** * Natural MicroSystems */ protected final static int WAVE_FORMAT_NMS_VBXADPCM = 0x0038; /** * Crystal Semiconductor IMA ADPCM */ protected final static int WAVE_FORMAT_CS_IMAADPCM = 0x0039; /** * Echo Speech Corporation */ protected final static int WAVE_FORMAT_ECHOSC3 = 0x003A; /** * Rockwell International */ protected final static int WAVE_FORMAT_ROCKWELL_ADPCM = 0x003B; /** * Rockwell International */ protected final static int WAVE_FORMAT_ROCKWELL_DIGITALK = 0x003C; /** * Xebec Multimedia Solutions Limited */ protected final static int WAVE_FORMAT_XEBEC = 0x003D; /** * Antex Electronics Corporation */ protected final static int WAVE_FORMAT_G721_ADPCM = 0x0040; /** * Antex Electronics Corporation */ protected final static int WAVE_FORMAT_G728_CELP = 0x0041; /** * Microsoft Corporation */ protected final static int WAVE_FORMAT_MPEG = 0x0050; /** * ISO/MPEG Layer3 Format Tag */ protected final static int WAVE_FORMAT_MPEGLAYER3 = 0x0055; /** * Cirrus Logic */ protected final static int WAVE_FORMAT_CIRRUS = 0x0060; /** * ESS Technology */ protected final static int WAVE_FORMAT_ESPCM = 0x0061; /** * Voxware Inc */ protected final static int WAVE_FORMAT_VOXWARE = 0x0062; /** * Canopus, co., Ltd. */ protected final static int WAVE_FORMAT_CANOPUS_ATRAC = 0x0063; /** * APICOM */ protected final static int WAVE_FORMAT_G726_ADPCM = 0x0064; /** * APICOM */ protected final static int WAVE_FORMAT_G722_ADPCM = 0x0065; /** * Microsoft Corporation */ protected final static int WAVE_FORMAT_DSAT = 0x0066; /** * Microsoft Corporation */ protected final static int WAVE_FORMAT_DSAT_DISPLAY = 0x0067; /** * Softsound, Ltd. */ protected final static int WAVE_FORMAT_SOFTSOUND = 0x0080; /** * Rhetorex Inc */ protected final static int WAVE_FORMAT_RHETOREX_ADPCM = 0x0100; /** * Creative Labs, Inc */ protected final static int WAVE_FORMAT_CREATIVE_ADPCM = 0x0200; /** * Creative Labs, Inc */ protected final static int WAVE_FORMAT_CREATIVE_FASTSPEECH8 = 0x0202; /** * Creative Labs, Inc */ protected final static int WAVE_FORMAT_CREATIVE_FASTSPEECH10 = 0x0203; /** * Quarterdeck Corporation */ protected final static int WAVE_FORMAT_QUARTERDECK = 0x0220; /** * Fujitsu Corp. */ protected final static int WAVE_FORMAT_FM_TOWNS_SND = 0x0300; /** * Brooktree Corporation */ protected final static int WAVE_FORMAT_BTV_DIGITAL = 0x0400; /** * Ing C. Olivetti & C., S.p.A. */ protected final static int WAVE_FORMAT_OLIGSM = 0x1000; /** * Ing C. Olivetti & C., S.p.A. */ protected final static int WAVE_FORMAT_OLIADPCM = 0x1001; /** * Ing C. Olivetti & C., S.p.A. */ protected final static int WAVE_FORMAT_OLICELP = 0x1002; /** * Ing C. Olivetti & C., S.p.A. */ protected final static int WAVE_FORMAT_OLISBC = 0x1003; /** * Ing C. Olivetti & C., S.p.A. */ protected final static int WAVE_FORMAT_OLIOPR = 0x1004; /** * Lernout & Hauspie */ protected final static int WAVE_FORMAT_LH_CODEC = 0x1100; /** * Norris Communications, Inc. */ protected final static int WAVE_FORMAT_NORRIS = 0x1400; /** * the WAVE_FORMAT_DEVELOPMENT format tag can be used during the * development phase of a new wave format. Before shipping, you MUST * acquire an official format tag from Microsoft. */ protected final static int WAVE_FORMAT_DEVELOPMENT = 0xFFFF; private int sampleChunkFourCC; public AudioTrack(int trackIndex, int fourCC) { super(trackIndex, AVIMediaType.AUDIO, fourCC); sampleChunkFourCC = twoCC | WB_ID; } @Override public long getSTRFChunkSize() { return 18; } @Override public int getSampleChunkFourCC(boolean isSync) { return sampleChunkFourCC; } } /** * Chunk base class. */ protected abstract class Chunk { /** * The chunkType of the chunk. A String with the length of 4 characters. */ protected int chunkType; /** * The offset of the chunk relative to the startTime of the * ImageOutputStream. */ protected long offset; /** * Creates a new Chunk at the current position of the ImageOutputStream. * * @param chunkType The chunkType of the chunk. A string with a length * of 4 characters. */ public Chunk(int chunkType) throws IOException { this.chunkType = chunkType; offset = getRelativeStreamPosition(); } /** * Writes the chunk to the ImageOutputStream and disposes it. */ public abstract void finish() throws IOException; /** * Returns the size of the chunk including the size of the chunk header. * * @return The size of the chunk. */ public abstract long size(); } /** * A CompositeChunk contains an ordered list of Chunks. */ protected class CompositeChunk extends Chunk { /** * The type of the composite. A String with the length of 4 characters. */ protected int compositeType; protected LinkedList children; protected boolean finished; /** * Creates a new CompositeChunk at the current position of the * ImageOutputStream. * * @param compositeType The type of the composite. * @param chunkType The type of the chunk. */ public CompositeChunk(int compositeType, int chunkType) throws IOException { super(chunkType); this.compositeType = compositeType; //out.write out.writeLong(0); // make room for the chunk header out.writeInt(0); // make room for the chunk header children = new LinkedList(); } public void add(Chunk child) throws IOException { if (children.size() > 0) { children.getLast().finish(); } children.add(child); } /** * Writes the chunk and all its children to the ImageOutputStream and * disposes of all resources held by the chunk. * * @throws java.io.IOException */ @Override public void finish() throws IOException { if (!finished) { if (size() > 0xffffffffL) { throw new IOException("CompositeChunk \"" + chunkType + "\" is too large: " + size()); } long pointer = getRelativeStreamPosition(); seekRelative(offset); out.setByteOrder(ByteOrder.BIG_ENDIAN); out.writeInt(compositeType); out.setByteOrder(ByteOrder.LITTLE_ENDIAN); out.writeInt((int) (size() - 8)); out.setByteOrder(ByteOrder.BIG_ENDIAN); out.writeInt(chunkType); out.setByteOrder(ByteOrder.LITTLE_ENDIAN); for (Chunk child : children) { child.finish(); } seekRelative(pointer); if (size() % 2 == 1) { out.writeByte(0); // write pad byte } finished = true; } } @Override public long size() { long length = 12; for (Chunk child : children) { length += child.size() + child.size() % 2; } return length; } } /** * Data Chunk. */ protected class DataChunk extends Chunk { //protected SubImageOutputStream data; protected boolean finished; private long finishedSize; /** * Creates a new DataChunk at the current position of the * ImageOutputStream. * * @param name The name of the chunk. */ public DataChunk(int name) throws IOException { this(name, -1); } /** * Creates a new DataChunk at the current position of the * ImageOutputStream. * * @param name The name of the chunk. * @param dataSize The size of the chunk data, or -1 if not known. */ public DataChunk(int name, long dataSize) throws IOException { super(name); /* data = new SubImageOutputStream(out, ByteOrder.LITTLE_ENDIAN, false); data.writeInt(typeToInt(chunkType)); data.writeInt((int)Math.max(0, dataSize)); */ out.setByteOrder(ByteOrder.BIG_ENDIAN); out.writeInt(chunkType); out.setByteOrder(ByteOrder.LITTLE_ENDIAN); out.writeInt((int) Math.max(0, dataSize)); finishedSize = dataSize == -1 ? -1 : dataSize + 8; } public ImageOutputStream getOutputStream() { if (finished) { throw new IllegalStateException("DataChunk is finished"); } //return data; return out; } /** * Returns the offset of this chunk to the beginning of the random * access file */ public long getOffset() { return offset; } @Override public void finish() throws IOException { if (!finished) { if (finishedSize == -1) { finishedSize = size(); if (finishedSize > 0xffffffffL) { throw new IOException("DataChunk \"" + chunkType + "\" is too large: " + size()); } seekRelative(offset + 4); out.writeInt((int) (finishedSize - 8)); seekRelative(offset + finishedSize); } else { if (size() != finishedSize) { throw new IOException("DataChunk \"" + chunkType + "\" actual size differs from given size: actual size:" + size() + " given size:" + finishedSize); } } if (size() % 2 == 1) { out.writeByte(0); // write pad byte } //data.dispose(); //data = null; finished = true; } } @Override public long size() { if (finished) { return finishedSize; } try { // return data.length(); return out.getStreamPosition() - offset; } catch (IOException ex) { InternalError ie = new InternalError("IOException"); ie.initCause(ex); throw ie; } } } /** * A DataChunk with a fixed size. */ protected class FixedSizeDataChunk extends Chunk { protected boolean finished; protected long fixedSize; /** * Creates a new DataChunk at the current position of the * ImageOutputStream. * * @param chunkType The chunkType of the chunk. */ public FixedSizeDataChunk(int chunkType, long fixedSize) throws IOException { super(chunkType); this.fixedSize = fixedSize; out.setByteOrder(ByteOrder.BIG_ENDIAN); out.writeInt(chunkType); out.setByteOrder(ByteOrder.LITTLE_ENDIAN); out.writeInt((int) fixedSize); // Fill fixed size with nulls byte[] buf = new byte[(int) Math.min(512, fixedSize)]; long written = 0; while (written < fixedSize) { out.write(buf, 0, (int) Math.min(buf.length, fixedSize - written)); written += Math.min(buf.length, fixedSize - written); } if (fixedSize % 2 == 1) { out.writeByte(0); // write pad byte } seekToStartOfData(); } public ImageOutputStream getOutputStream() { /*if (finished) { throw new IllegalStateException("DataChunk is finished"); }*/ return out; } /** * Returns the offset of this chunk to the beginning of the random * access file */ public long getOffset() { return offset; } public void seekToStartOfData() throws IOException { seekRelative(offset + 8); } public void seekToEndOfChunk() throws IOException { seekRelative(offset + 8 + fixedSize + fixedSize % 2); } @Override public void finish() throws IOException { if (!finished) { finished = true; } } @Override public long size() { return 8 + fixedSize; } } protected class MidiTrack extends Track { private static final String NOT_SUPPORTED_YET_ERROR = "Not supported yet."; private final int sampleChunkFourCC; public MidiTrack(int trackIndex, int fourCC) { super(trackIndex, AVIMediaType.MIDI, fourCC); sampleChunkFourCC = twoCC | WB_ID; } @Override public long getSTRFChunkSize() { throw new UnsupportedOperationException(NOT_SUPPORTED_YET_ERROR); } @Override public int getSampleChunkFourCC(boolean isSync) { throw new UnsupportedOperationException(NOT_SUPPORTED_YET_ERROR); } } protected class TextTrack extends Track { private final int sampleChunkFourCC; public TextTrack(int trackIndex, int fourCC) { super(trackIndex, AVIMediaType.TEXT, fourCC); sampleChunkFourCC = twoCC | WB_ID; } @Override public long getSTRFChunkSize() { throw new UnsupportedOperationException("Not supported yet."); } @Override public int getSampleChunkFourCC(boolean isSync) { throw new UnsupportedOperationException("Not supported yet."); } } /** *

Holds information about the entire movie.

* *
     * ---------------
     * AVI Main Header
     * ---------------
     *
     * Set values taken from
     * http://graphics.cs.uni-sb.de/NMM/dist-0.4.0/Docs/Doxygen/html/avifmt_8h.html
     *
     * typedef struct {
     *     DWORD  microSecPerFrame;
     *             // Specifies the number of microseconds between frames.
     *             // This value indicates the overall timing for the file.
     *     DWORD  maxBytesPerSec;
     *             // Specifies the approximate maximum data rate of the file. This
     *             // value indicates the number of bytes per second the system must
     *             // handle to present an AVI sequence as specified by the other
     *             // parameters contained in the main header and stream header chunks.
     *     DWORD  paddingGranularity;
     *             // Specifies the alignment for data, in bytes. Pad the data to
     *             // multiples of this value.
     *     DWORD set avihFlags  flags;
     *             // Contains a bitwise combination of zero or more of the following flags:
     *     DWORD  totalFrames;
     *             // Specifies the total number of frames of data in the file.
     *     DWORD  initialFrames;
     *             // Specifies the initial frame for interleaved files. Noninterleaved
     *             // files should specify zero. If you are creating interleaved files,
     *             // specify the number of frames in the file prior to the initial
     *             // frame of the AVI sequence in this member. For more information
     *             // about the contents of this member, see "Special Information for
     *             // Interleaved Files" in the Video for Windows Programmer's Guide.
     *     DWORD  streams;
     *             // Specifies the number of streams in the file. For example, a file
     *             // with audio and video has two streams.
     *     DWORD  suggestedBufferSize;
     *             // Specifies the suggested buffer size for reading the file.
     *             // Generally, this size should be large enough to contain the
     *             // largest chunk in the file. If set to zero, or if it is too small,
     *             // the playback software will have to reallocate memory during
     *             // playback, which will reduce performance. For an interleaved file,
     *             // the buffer size should be large enough to read an entire record,
     *             // and not just a chunk.
     *     DWORD  width;
     *             // Specifies the width of the AVI file in pixels.
     *     DWORD  height;
     *             // Specifies the height of the AVI file in pixels.
     *     DWORD[]  reserved;
     *             // Reserved. Set this array to zero.
     * } AVIMAINHEADER;
     * 
*/ protected static class MainHeader { /** * Specifies the number of microseconds (=10E-6 seconds) between frames. * This value indicates the overall timing for the file. */ protected long microSecPerFrame; protected long maxBytesPerSec; protected long paddingGranularity; protected int flags; protected long totalFrames; protected long initialFrames; protected long streams; protected long suggestedBufferSize; /** * Width and height of the movie. Null if not specified. */ protected Dimension size; } protected static int typeToInt(String str) { int value = ((str.charAt(0) & 0xff) << 24) | ((str.charAt(1) & 0xff) << 16) | ((str.charAt(2) & 0xff) << 8) | (str.charAt(3) & 0xff); return value; } protected static String intToType(int id) { char[] b=new char[4]; b[0] = (char) ((id >>> 24) & 0xff); b[1] = (char) ((id >>> 16) & 0xff); b[2] = (char) ((id >>> 8) & 0xff); b[3] = (char) (id & 0xff); return String.valueOf(b); } /** * Returns true, if the specified mask is set on the flag. */ protected static boolean isFlagSet(int flag, int mask) { return (flag & mask) == mask; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy