/*
 * Vheader.java
 * This class processes the header information of a .fjv file.
 */

import java.io.*;

class Vheader {
  public byte  id[] = new byte[10]; //I.D. of file, should be ‘‘FORJUNEV"
  public short fps;      //frame per second
  public int   nframes;  //number of frames
  public short width;    //width of video frame
  public short height;   //height of video frame
  public byte  bpp;      //bits per pixel
  public byte  qmethod;  //quantization method
  public byte  ext;      //extension
  public byte  dummy;    //for byte alignment, make header size = 24

  //Constructor
  Vheader ()
  {
    byte src [] = {'F', 'O', 'R', 'J', 'U', 'N', 'E', 'V', 0, 0 };  
    System.arraycopy( src, 0, id, 0, src.length );  //set header I.D.
  }

  //Constructor
  Vheader ( short w, short h, short frameRate, int numVideoFrames )
  {
    this();     //call the other constructor
    //System.out.printf( "%s\n", id );
    fps = frameRate;           //frame per second
    nframes = numVideoFrames;  //number of frames
    width = w;                 //image width
    height = h;                //image height
    bpp = 8;                   //number of bits per pixel
    qmethod = 1;               //quantization method
    ext = 1;                   //file contains compressed data
    dummy = 0;
  }

  //Output lower bytes first, compatible with C/C++
  private void writeBytes ( OutputStream outs, int value, int nbytes )
  { 
    int b;
    int n = 0;
    try {
      for ( int i = 0; i < nbytes; i++ ) {
        b = 0x000000ff & ( value >> n );
        n += 8;            //consider next byte
        outs.write ( b );  //write one byte
      }
    } catch (IOException e) {}
  }
  
  //Input lower bytes first, compatible with C/C++
  private int readBytes ( InputStream ins, int nbytes )
  {
    byte b[] = new byte[4];
    int value = 0, n = 0;
    try {
      ins.read( b, 0, nbytes );
      for ( int i = 0; i < nbytes; i++ ) {
        value |= (0x000000ff & (int) b[i]) << n ;
        n += 8;
      } 
    } catch (IOException e) {}

    return value;
  }

  public void writeHeader( OutputStream outs ) throws IOException
  {
    //Output lower bytes first, compatible with C/C++
    byte bytes[] = new byte[200];
    int k = 0;
    try {
      outs.write ( id );
      writeBytes ( outs, (int) fps, 2 );    //write a short
      writeBytes ( outs, nframes, 4 );      //write an int
      writeBytes ( outs, (int) width, 2 );  //write a short
      writeBytes ( outs, (int) height, 2 ); //write a short
      writeBytes ( outs, (int) bpp, 1 );    //write a byte
      writeBytes ( outs, (int) qmethod, 1); //write a byte
      writeBytes ( outs, (int) ext, 1 );    //write a byte
      writeBytes ( outs, (int) dummy, 1 );  //write a byte
    } catch (IOException e) {}
  }
  
  public void readHeader( InputStream ins ) throws IOException
  {
    byte bytes[] = new byte[200];
    int k = 0;
    try {
      ins.read ( bytes, 0, id.length );
      for ( int i = 0; i < id.length; i++ ){
          if ( bytes[i] != id[i] ){
            System.out.printf("Incorrect header\n");
            System.exit ( -1 );
          }
      }
      fps     = (short) readBytes ( ins, 2 ); //read a short
      nframes = readBytes ( ins, 4 );         //read an int
      width   = (short) readBytes ( ins, 2 ); //read a short
      height  = (short) readBytes ( ins, 2 ); //read a short
      bpp     = (byte) readBytes ( ins, 1 );  //read a byte
      qmethod = (byte) readBytes ( ins, 1 );  //read a byte
      ext     = (byte) readBytes ( ins, 1 );  //read a byte
      dummy   = (byte) readBytes ( ins, 1 );  //read a byte
    } catch (IOException e) {}
  }
}
