

import javax.media.*;
import javax.media.renderer.VideoRenderer;
import javax.media.control.*;
import javax.media.Format;
import javax.media.format.VideoFormat;
import javax.media.format.RGBFormat;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.util.Vector;
import java.util.Random;
import java.awt.geom.*;
// java3d packages
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.Box;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.geometry.Cylinder;

import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.behaviors.mouse.*;

/*
 * This is a JMF renderer plugin. It texure maps the incoming
 * video frame to a 3D surface, making use of Java 3D 
 *
 */

class JMFTexture2D extends Texture2D implements VideoRenderer {
    Processor p;  
    protected RGBFormat inputFormat; 
    protected RGBFormat supportedRGB;
    protected Format [] supportedFormats;
    BufferedImage bi;
    ImageComponent2D ic;
    Random r;
    byte[] byteData; 
   
    private static final String name = "JMFTexture2D";
    protected int       inWidth = 0;
    protected int       inHeight = 0;
    protected int count = 0;
    protected int imHeight = 256;
    protected int imWidth = 256;
    int jj=0;
    protected Component component = null;
    protected Rectangle reqBounds = null;
    protected Rectangle bounds = new Rectangle();
    protected boolean started = false;
    protected Object lastData = null;
    Canvas3D c;
    boolean firstFrame = true;
    MediaLocator ml;
    
    
    public JMFTexture2D(Canvas3D c) {
           //super(Texture2D.BASE_LEVEL,Texture2D.RGB,256,256);
            super(Texture2D.BASE_LEVEL,Texture2D.RGB,256,256);

           this.c = c;
           this.setCapability(Texture2D.ALLOW_IMAGE_WRITE);
           this.setCapability(Texture2D.ALLOW_IMAGE_READ);
           
           supportedRGB =  new RGBFormat(null,
                                         Format.NOT_SPECIFIED,
                                         Format.byteArray,
                                         Format.NOT_SPECIFIED,
                                         24,
                                         3, 2, 1,
                                         3, Format.NOT_SPECIFIED,
                                         Format.TRUE,
                                         Format.NOT_SPECIFIED);
        
          supportedFormats = new VideoFormat[] {supportedRGB };
          firstFrame = true;
                   
          String os = System.getProperty("os.name");
          System.out.println("running on " + os);

          bi = new BufferedImage(256, 256, BufferedImage.TYPE_3BYTE_BGR);
          byteData = ((DataBufferByte)bi.getRaster().getDataBuffer()).getData();
    //bi = new BufferedImage(imgwidth,imgheight,BufferedImage.TYPE_INT_RGB);           
    
    //instantiate a new ImageComponent; choose byRef and yUp  
      ic = new ImageComponent2D(ImageComponent2D.FORMAT_RGB,
                                               imHeight, imWidth,true,true);
      //set bi as ImageComponenet object
      ic.set(bi);
        
        /*
      if ( os.startsWith("W") || os.startsWith("w")) {
            bi = new BufferedImage(256,
                                   256, 
                                   BufferedImage.TYPE_3BYTE_BGR); 
            
            super(ImageComponent.FORMAT_RGB,
                                      bi,
                                      true,
                                      true);
     //bi = new BufferedIma
        }else if (os.startsWith("S") || os.startsWith("s")){
            bi = new BufferedImage(256,
                                   256, 
                                   BufferedImage.TYPE_4BYTE_ABGR);  

            super(ImageComponent.FORMAT_RGBA,
                                      bi,
                                      true,
                                      true);            
        } else {
            bi = new BufferedImage(256,
                                   256, 
                                   BufferedImage.TYPE_3BYTE_BGR);   
         
            super(ImageComponent.FORMAT_RGB,
                                      bi,
                                      false,
                                      true);
        }
 */
        
      
        this.setImage(0, ic);
      
        this.start();
           System.out.println("JMFTexture2D constructor");
        // Prepare supported input formats and preferred format
             
    }
    
    

    
   public void setMedia(MediaLocator ml) {
     this.ml = ml;
   }

   public boolean openMedia() {
        try {
            p = Manager.createProcessor(ml);
        } catch (Exception ex) {
          System.out.println("failed to create a processor for movie " + ml);
         //printUsuage();
          return false;
        }

        //p.addControllerListener(c);
        
        p.configure();
        

        
        // use processor as a player
        

        // obtain the track control
        TrackControl[] tc = p.getTrackControls();

        if ( tc == null ) {
            System.out.println("Failed to get the track control from processor");
            return false;
        }

        TrackControl vtc = null;
        
        for ( int i =0; i < tc.length; i++ ) {
            if (tc[i].getFormat() instanceof VideoFormat ) {
                vtc = tc[i];
                break;
            }
            
        }

        if ( vtc == null ) {
            System.out.println("can't find video track");
            return false;
        }
        
        try {
            vtc.setRenderer(this);
        } catch ( Exception ex) {
            ex.printStackTrace();
            System.out.println("the processor does not support effect");
            return false;
        }
        p.setContentDescriptor(null);
        
        // prefetch
        p.prefetch();


        return true;
    }

    public void init() {
    
        p.start();
        System.out.println("p start");

    }

    
  public int process(Buffer buffer) {
        //System.out.println("process...");
        //rawData is the video buffer raw data
      jj++;
        byte[] rawData =(byte[])(buffer.getData());
        if ( buffer.getLength() <= 0 ) 
            return BUFFER_PROCESSED_OK;

        if ( count < 0 ) {
            count ++;
            try {
                Thread.currentThread().sleep(50);
            } catch ( Exception ex) {
                ex.printStackTrace();
            }

            return BUFFER_PROCESSED_OK;
        }

        count = 0;
        
  
      
        //BufferedImage bimg = new BufferedImage(SS,SS, btype);
        
       int nbytes=3;
       int pixeln=0;
       int npixels=256*256;
       
       for (int ii=0;ii<npixels;ii++) {
          pixeln=ii*nbytes;
          byteData[pixeln] = (byte)jj;
          byteData[pixeln+1]=(byte)(npixels/(jj+1));
          byteData[pixeln+2]=(byte)0;
          // System.out.println("ii: " + ii);
          pixeln=pixeln+3;
        }
        //
        
        
        ic = new ImageComponent2D (ImageComponent.FORMAT_RGB,
                                                     bi,
                                                     true,
                                                     true);
        
        this.setImage(0, ic);
        return BUFFER_PROCESSED_OK;
    }
  
  //the following methods must be implemented
    
      public java.lang.Object[] getControls() {
        // No controls
        return (Object[]) new Control[0];
    }

    /**
     * Return the control based on a control type for the PlugIn.
     */
    public Object getControl(String controlType) {
       try {
          Class  cls = Class.forName(controlType);
          Object cs[] = getControls();
          for (int i = 0; i < cs.length; i++) {
             if (cls.isInstance(cs[i]))
                return cs[i];
          }
          return null;
       } catch (Exception e) {   // no such controlType or such control
         return null;
       }
    }

    /*************************************************************************
     * PlugIn implementation
     *************************************************************************/

    public java.lang.String getName() {
        return name;
    }
    
       public java.awt.Rectangle getBounds() {
        return reqBounds;
    }
    
     public javax.media.Format[] getSupportedInputFormats() {
        return supportedFormats;
    }
    
 
   public boolean setComponent(java.awt.Component comp) {
        component = comp;
        return true;
    }
  
  public void open() throws javax.media.ResourceUnavailableException {
      //openMedia(ml);
  }
  
  public Format setInputFormat(Format format) {
        if ( format != null && format instanceof RGBFormat &&
             format.matches(supportedRGB)) {
            
            inputFormat = (RGBFormat) format;
            Dimension size = inputFormat.getSize();
            inWidth = size.width;
            inHeight = size.height;
            // System.out.println("in setInputFormat = " + format);
            return format;
        } else
            return null;
    }

  public void setBounds(java.awt.Rectangle rectangle) {
  }
  public synchronized void close() {
  }
    
 public java.awt.Component getComponent() {
        return c;
    }   
 public void reset() {
        // Nothing to do
    }
  public void start() {
      System.out.println("start called");
  }
  
  public void stop() {
      System.out.println("stop called");
  }

  
}