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

org.monte.media.quicktime.DataAtomOutputStream Maven / Gradle / Ivy

There is a newer version: 1.1
Show newest version
/**
 * @(#)DataAtomOutputStream.java 
 *
 * Copyright (c) 2008-2012 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.quicktime;

import java.io.*;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.imageio.stream.ImageOutputStreamImpl;

/**
 * This output stream filter supports common data types used inside
 * of a QuickTime Data Atom.
 *
 * @author Werner Randelshofer
 * @version $Id: DataAtomOutputStream.java 299 2013-01-03 07:40:18Z werner $
 */
public class DataAtomOutputStream extends FilterOutputStream {

    ImageOutputStreamImpl impl;
    protected static final long MAC_TIMESTAMP_EPOCH = new GregorianCalendar(1904, GregorianCalendar.JANUARY, 1).getTimeInMillis();
    /**
     * The number of bytes written to the data output stream so far. 
     * If this counter overflows, it will be wrapped to Integer.MAX_VALUE.
     */
    protected long written;

    public DataAtomOutputStream(OutputStream out) {
        super(out);
    }

    /**
     * Writes an Atom Type identifier (4 bytes).
     * @param s A string with a length of 4 characters.
     */
    public void writeType(String s) throws IOException {
        if (s.length() != 4) {
            throw new IllegalArgumentException("type string must have 4 characters");
        }

        try {
            out.write(s.getBytes("ASCII"), 0, 4);
            incCount(4);
        } catch (UnsupportedEncodingException e) {
            throw new InternalError(e.toString());
        }
    }

    /**
     * Writes out a byte to the underlying output stream as 
     * a 1-byte value. If no exception is thrown, the counter 
     * written is incremented by 1.
     *
     * @param      v   a byte value to be written.
     * @exception  java.io.IOException  if an I/O error occurs.
     * @see        java.io.FilterOutputStream#out
     */
    public final void writeByte(int v) throws IOException {
        out.write(v);
        incCount(1);
    }

    /**
     * Writes len bytes from the specified byte array 
     * starting at offset off to the underlying output stream. 
     * If no exception is thrown, the counter written is 
     * incremented by len.
     *
     * @param      b     the data.
     * @param      off   the start offset in the data.
     * @param      len   the number of bytes to write.
     * @exception  java.io.IOException  if an I/O error occurs.
     * @see        java.io.FilterOutputStream#out
     */
    @Override
    public synchronized void write(byte b[], int off, int len)
            throws IOException {
        out.write(b, off, len);
        incCount(len);
    }

    /**
     * Writes the specified byte (the low eight bits of the argument 
     * b) to the underlying output stream. If no exception 
     * is thrown, the counter written is incremented by 
     * 1.
     * 

* Implements the write method of OutputStream. * * @param b the byte to be written. * @exception java.io.IOException if an I/O error occurs. * @see java.io.FilterOutputStream#out */ @Override public synchronized void write(int b) throws IOException { out.write(b); incCount(1); } /** * Writes an int to the underlying output stream as four * bytes, high byte first. If no exception is thrown, the counter * written is incremented by 4. * * @param v an int to be written. * @exception java.io.IOException if an I/O error occurs. * @see java.io.FilterOutputStream#out */ public void writeInt(int v) throws IOException { out.write((v >>> 24) & 0xff); out.write((v >>> 16) & 0xff); out.write((v >>> 8) & 0xff); out.write((v >>> 0) & 0xff); incCount(4); } /** * Writes an unsigned 32 bit integer value. * * @param v The value * @throws java.io.IOException */ public void writeUInt(long v) throws IOException { out.write((int) ((v >>> 24) & 0xff)); out.write((int) ((v >>> 16) & 0xff)); out.write((int) ((v >>> 8) & 0xff)); out.write((int) ((v >>> 0) & 0xff)); incCount(4); } /** * Writes a signed 16 bit integer value. * * @param v The value * @throws java.io.IOException */ public void writeShort(int v) throws IOException { out.write((int) ((v >> 8) & 0xff)); out.write((int) ((v >>> 0) & 0xff)); incCount(2); } /** * Writes a BCD2 to the underlying output stream. * * @param v an int to be written. * @exception java.io.IOException if an I/O error occurs. * @see java.io.FilterOutputStream#out */ public void writeBCD2(int v) throws IOException { out.write(((v % 100 / 10) << 4) | (v % 10)); incCount(1); } /** * Writes a BCD4 to the underlying output stream. * * @param v an int to be written. * @exception java.io.IOException if an I/O error occurs. * @see java.io.FilterOutputStream#out */ public void writeBCD4(int v) throws IOException { out.write(((v % 10000 / 1000) << 4) | (v % 1000 / 100)); out.write(((v % 100 / 10) << 4) | (v % 10)); incCount(2); } /** * Writes a 32-bit Mac timestamp (seconds since 1902). * @param date * @throws java.io.IOException */ public void writeMacTimestamp(Date date) throws IOException { long millis = date.getTime(); long qtMillis = millis - MAC_TIMESTAMP_EPOCH; long qtSeconds = qtMillis / 1000; writeUInt(qtSeconds); } /** * Writes 32-bit fixed-point number divided as 16.16. * * @param f an int to be written. * @exception java.io.IOException if an I/O error occurs. * @see java.io.FilterOutputStream#out */ public void writeFixed16D16(double f) throws IOException { double v = (f >= 0) ? f : -f; int wholePart = (int) Math.floor(v); int fractionPart = (int) ((v - wholePart) * 65536); int t = (wholePart << 16) + fractionPart; if (f < 0) { t = t - 1; } writeInt(t); } /** * Writes 32-bit fixed-point number divided as 2.30. * * @param f an int to be written. * @exception java.io.IOException if an I/O error occurs. * @see java.io.FilterOutputStream#out */ public void writeFixed2D30(double f) throws IOException { double v = (f >= 0) ? f : -f; int wholePart = (int) v; int fractionPart = (int) ((v - wholePart) * 1073741824); int t = (wholePart << 30) + fractionPart; if (f < 0) { t = t - 1; } writeInt(t); } /** * Writes 32-bit fixed-point number divided as 8.8. * * @param f an int to be written. * @exception java.io.IOException if an I/O error occurs. * @see java.io.FilterOutputStream#out */ public void writeFixed8D8(double f) throws IOException { double v = (f >= 0) ? f : -f; int wholePart = (int) v; int fractionPart = (int) ((v - wholePart) * 256); int t = (wholePart << 8) + fractionPart; if (f < 0) { t = t - 1; } writeUShort(t); } /** * Writes a Pascal String. * * @param s * @throws java.io.IOException */ public void writePString(String s) throws IOException { if (s.length() > 0xffff) { throw new IllegalArgumentException("String too long for PString"); } if (s.length() != 0 && s.length() < 256) { out.write(s.length()); } else { out.write(0); writeShort(s.length()); // increments +2 } for (int i = 0; i < s.length(); i++) { out.write(s.charAt(i)); } incCount(1 + s.length()); } /** * Writes a Pascal String padded to the specified fixed size in bytes * * @param s * @param length the fixed size in bytes * @throws java.io.IOException */ public void writePString(String s, int length) throws IOException { if (s.length() > length) { throw new IllegalArgumentException("String too long for PString of length " + length); } if (s.length() != 0 && s.length() < 256) { out.write(s.length()); } else { out.write(0); writeShort(s.length()); // increments +2 } for (int i = 0; i < s.length(); i++) { out.write(s.charAt(i)); } // write pad bytes for (int i = 1 + s.length(); i < length; i++) { out.write(0); } incCount(length); } public void writeLong(long v) throws IOException { out.write((int) (v >>> 56) & 0xff); out.write((int) (v >>> 48) & 0xff); out.write((int) (v >>> 40) & 0xff); out.write((int) (v >>> 32) & 0xff); out.write((int) (v >>> 24) & 0xff); out.write((int) (v >>> 16) & 0xff); out.write((int) (v >>> 8) & 0xff); out.write((int) (v >>> 0) & 0xff); incCount(8); } public void writeUShort(int v) throws IOException { out.write((int) ((v >> 8) & 0xff)); out.write((int) ((v >>> 0) & 0xff)); incCount(2); } /** * Increases the written counter by the specified value * until it reaches Long.MAX_VALUE. */ protected void incCount(int value) { long temp = written + value; if (temp < 0) { temp = Long.MAX_VALUE; } written = temp; } public void writeShorts(short[] s, int off, int len) throws IOException { // Fix 4430357 - if off + len < 0, overflow occurred if (off < 0 || len < 0 || off + len > s.length || off + len < 0) { throw new IndexOutOfBoundsException("off < 0 || len < 0 || off + len > s.length!"); } byte[] b = new byte[len * 2]; int boff = 0; for (int i = 0; i < len; i++) { short v = s[off + i]; b[boff++] = (byte) (v >>> 8); b[boff++] = (byte) (v >>> 0); } write(b, 0, len * 2); } public void writeInts(int[] i, int off, int len) throws IOException { // Fix 4430357 - if off + len < 0, overflow occurred if (off < 0 || len < 0 || off + len > i.length || off + len < 0) { throw new IndexOutOfBoundsException("off < 0 || len < 0 || off + len > i.length!"); } byte[] b = new byte[len * 4]; int boff = 0; for (int j = 0; j < len; j++) { int v = i[off + j]; b[boff++] = (byte) (v >>> 24); b[boff++] = (byte) (v >>> 16); b[boff++] = (byte) (v >>> 8); b[boff++] = (byte) (v >>> 0); } write(b, 0, len * 4); } private byte[] byteBuf = new byte[3]; public void writeInt24(int v) throws IOException { byteBuf[0] = (byte) (v >>> 16); byteBuf[1] = (byte) (v >>> 8); byteBuf[2] = (byte) (v >>> 0); write(byteBuf, 0, 3); } public void writeInts24(int[] i, int off, int len) throws IOException { // Fix 4430357 - if off + len < 0, overflow occurred if (off < 0 || len < 0 || off + len > i.length || off + len < 0) { throw new IndexOutOfBoundsException("off < 0 || len < 0 || off + len > i.length!"); } byte[] b = new byte[len * 3]; int boff = 0; for (int j = 0; j < len; j++) { int v = i[off + j]; //b[boff++] = (byte)(v >>> 24); b[boff++] = (byte) (v >>> 16); b[boff++] = (byte) (v >>> 8); b[boff++] = (byte) (v >>> 0); } write(b, 0, len * 3); } /** * Returns the current value of the counter written, * the number of bytes written to this data output stream so far. * If the counter overflows, it will be wrapped to Integer.MAX_VALUE. * * @return the value of the written field. * @see java.io.DataOutputStream#written */ public final long size() { return written; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy