/* 
  Vcodec.java
  This is to entry point of a video coder decoder.
  This same class is used in Chapter 11, 12, and 13.
  Though different Encoder and Decoder classes are used,
  other classes remain the same. 
  Examples of usage:
  To encode: java Vcodec ../data/jvideo.avi t.fjv
             Reads uncompressed data from "jvideo.avi"; compressed data saved in "t.fjv".
  To decode: java Vcodec -d t.fjv
             Reads compressed data from "t.fjv"; decodes and renders data on screen. 
*/

import java.io.*;
import ij.plugin.AVI_Reader;

public class Vcodec {
  
  static AVI_Reader avi;  

  static void print_block( short X[][] )
  {
    for ( int i = 0; i < 8; ++i ){
      System.out.printf("\n");
      for ( int j = 0; j < 8; ++j ) {
        System.out.printf("%4d, ", X[i][j] );
      }
    }
  }

  public static void main(String[] args) throws InterruptedException
  {
    if (args.length < 1) {
      System.out.println("Usage for encoding: java " + "Vcodec" +
        " AVI_input_filename [fjv_output_filename]" );
      System.out.println("    e.g. java Vcodec ../data/jvideo.avi t.fjv");
      System.out.println("Usage for decoding: java " + "Vcodec -d" +
        " fjv_filename" );
      System.out.println("    e.g. java Vcodec -d  t.fjv");
      System.exit(-1);
    }
  
    Vheader header;
  
    if ( args[0].equals ( "-d" ) ) {
      System.out.println("Decoding..");
      if (args.length < 2) {
        System.out.println("Usage: java " + "Vcodec" +
        " -d fjv_input_filename " );
        System.exit(-1);
      }
      try {
        File f = new File ( args[1] );
        InputStream ins = new FileInputStream( f );
        header = new Vheader();
        header.readHeader( ins );
        BitInputStream bitin = new BitInputStream ( ins );
        CircularQueue sharedQueue = new CircularQueue( 4, header.width, header.height );
        Display display = new Display ( sharedQueue, header.width, header.height );
        Decoder decoder = new Decoder ( sharedQueue, bitin, display );
        decoder.start();
        while ( !sharedQueue.quit ) {
          Thread.sleep ( 5 );
        } 
        display.close_window();     
      } catch (IOException e) {}
      
      return;
    }
      
    System.out.println("Encoding..");
    String outfilename;
    if (args.length < 2) 
       outfilename = args[0].substring(0, args[0].length()-3 ) + "fjv";
    else
       outfilename = args[1]; 
    avi = new AVI_Reader();
    //read images from AVI file to virtual stack
    avi.makeStack ( args[0], 0, 0, true, false, false  );

    int vsize = avi.getSize();     //number of images in the virtual stack
    int width = avi.getWidth();    //image width
    int height = avi.getHeight();  //image height
    System.out.printf("total frames=%d, width=%d, height=%d \n",
                                                  vsize, width, height );
    header = new Vheader ( (short) width, (short) height, (short) 20, vsize );
 
    try {
      File f = new File ( outfilename );
      OutputStream outs = new FileOutputStream( f );
      header.writeHeader( outs );
      BitOutputStream bitout = new BitOutputStream ( outs );
      CircularQueue sharedQueue = new CircularQueue( 4, width, height );
      AviFrameProducer p =  new AviFrameProducer ( avi, sharedQueue );
      p.start();
      Display display = new Display ( sharedQueue, width, height );
      Encoder c = new Encoder ( sharedQueue, bitout, display );
      c.start();
      while ( !sharedQueue.quit || !sharedQueue.bufferEmpty() ) {
        Thread.sleep ( 5 );
      } 
      display.close_window();     
      bitout.close();
    } catch (IOException e) {}
  }
}
