/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media.cts;

import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * Writes an IVF file.
 *
 * IVF format is a simple container format for VP8 encoded frames defined at
 * http://wiki.multimedia.cx/index.php?title=IVF.
 */

public class IvfWriter {
    private static final byte HEADER_END = 32;
    private RandomAccessFile mOutputFile;
    private int mWidth;
    private int mHeight;
    private int mScale;
    private int mRate;
    private int mFrameCount;

    /**
     * Initializes the IVF file writer.
     *
     * Timebase fraction is in format scale/rate, e.g. 1/1000
     * Timestamp values supplied while writing frames should be in accordance
     * with this timebase value.
     *
     * @param filename   name of the IVF file
     * @param width      frame width
     * @param height     frame height
     * @param scale      timebase scale (or numerator of the timebase fraction)
     * @param rate       timebase rate (or denominator of the timebase fraction)
     */
    public IvfWriter(String filename,
                     int width, int height,
                     int scale, int rate) throws IOException {
        mOutputFile = new RandomAccessFile(filename, "rw");
        mWidth = width;
        mHeight = height;
        mScale = scale;
        mRate = rate;
        mFrameCount = 0;
        mOutputFile.setLength(0);
        mOutputFile.seek(HEADER_END);  // Skip the header for now, as framecount is unknown
    }

    /**
     * Initializes the IVF file writer with a microsecond timebase.
     *
     * Microsecond timebase is default for OMX thus stagefright.
     *
     * @param filename   name of the IVF file
     * @param width      frame width
     * @param height     frame height
     */
    public IvfWriter(String filename, int width, int height) throws IOException {
        this(filename, width, height, 1, 1000000);
    }

    /**
     * Finalizes the IVF header and closes the file.
     */
    public void close() throws IOException{
        // Write header now
        mOutputFile.seek(0);
        mOutputFile.write(makeIvfHeader(mFrameCount, mWidth, mHeight, mScale, mRate));
        mOutputFile.close();
    }

    /**
     * Writes a single encoded VP8 frame with its frame header.
     *
     * @param frame     actual contents of the encoded frame data
     * @param timeStamp timestamp of the frame (in accordance to specified timebase)
     */
    public void writeFrame(byte[] frame, long timeStamp) throws IOException {
        mOutputFile.write(makeIvfFrameHeader(frame.length, timeStamp));
        mOutputFile.write(frame);
        mFrameCount++;
    }

    /**
     * Makes a 32 byte file header for IVF format.
     *
     * Timebase fraction is in format scale/rate, e.g. 1/1000
     *
     * @param frameCount total number of frames file contains
     * @param width      frame width
     * @param height     frame height
     * @param scale      timebase scale (or numerator of the timebase fraction)
     * @param rate       timebase rate (or denominator of the timebase fraction)
     */
    private static byte[] makeIvfHeader(int frameCount, int width, int height, int scale, int rate){
        byte[] ivfHeader = new byte[32];
        ivfHeader[0] = 'D';
        ivfHeader[1] = 'K';
        ivfHeader[2] = 'I';
        ivfHeader[3] = 'F';
        lay16Bits(ivfHeader, 4, 0);  // version
        lay16Bits(ivfHeader, 6, 32);  // header size
        ivfHeader[8] = 'V';  // fourcc
        ivfHeader[9] = 'P';
        ivfHeader[10] = '8';
        ivfHeader[11] = '0';
        lay16Bits(ivfHeader, 12, width);
        lay16Bits(ivfHeader, 14, height);
        lay32Bits(ivfHeader, 16, rate);  // scale/rate
        lay32Bits(ivfHeader, 20, scale);
        lay32Bits(ivfHeader, 24, frameCount);
        lay32Bits(ivfHeader, 28, 0);  // unused
        return ivfHeader;
    }

    /**
     * Makes a 12 byte header for an encoded frame.
     *
     * @param size      frame size
     * @param timestamp presentation timestamp of the frame
     */
    private static byte[] makeIvfFrameHeader(int size, long timestamp){
        byte[] frameHeader = new byte[12];
        lay32Bits(frameHeader, 0, size);
        lay64bits(frameHeader, 4, timestamp);
        return frameHeader;
    }


    /**
     * Lays least significant 16 bits of an int into 2 items of a byte array.
     *
     * Note that ordering is little-endian.
     *
     * @param array     the array to be modified
     * @param index     index of the array to start laying down
     * @param value     the integer to use least significant 16 bits
     */
    private static void lay16Bits(byte[] array, int index, int value){
        array[index] = (byte) (value);
        array[index + 1] = (byte) (value >> 8);
    }

    /**
     * Lays an int into 4 items of a byte array.
     *
     * Note that ordering is little-endian.
     *
     * @param array     the array to be modified
     * @param index     index of the array to start laying down
     * @param value     the integer to use
     */
    private static void lay32Bits(byte[] array, int index, int value){
        for (int i = 0; i < 4; i++){
            array[index + i] = (byte) (value >> (i * 8));
        }
    }

    /**
     * Lays a long int into 8 items of a byte array.
     *
     * Note that ordering is little-endian.
     *
     * @param array     the array to be modified
     * @param index     index of the array to start laying down
     * @param value     the integer to use
     */
    private static void lay64bits(byte[] array, int index, long value){
        for (int i = 0; i < 8; i++){
            array[index + i] = (byte) (value >> (i * 8));
        }
    }
}
