Mega Code Archive

 
Categories / Java / 2D Graphics GUI
 

Transfer media from one location to another carrying out the specified

/* Java Media APIs: Cross-Platform Imaging, Media and Visualization Alejandro Terrazas Sams, Published November 2002,  ISBN 0672320940 */ import javax.media.*; import javax.media.datasink.*; import javax.media.protocol.*; /*******************************************************************************  * Transfer media from one location to another carrying out the specified  * transcoding (track formats and content type) at the same time.  * <p>  * Users specify a source and destination location, the Formats (to be realised)  * of the individual tracks, and a ContentDescriptor (content type) for output.  * <p>  * A Processor is created to perform and transcoding and its output DataSource  * is employed to construct a DataSink in order to complete the transfer.  * <p>  * The most important method of the class is transfer() as this opens and starts  * the DataSink. The constructor builds both the Processor (which is starts) and  * the DataSink.  * <p>  * The object keeps track of its own state, which can be queried with the  * getState() method. Defined constants are FAILED, TRANSLATING, TRANSFERRING,  * and FINISHED. The process is asychronous: transcoding largish movies can take  * a long time. The calling code should make allowances for that.  ******************************************************************************/ public class Location2Location implements ControllerListener {   /** Output of the Processor: the transcoded media. */   protected DataSource source;   /** Sink used to "write" out the transcoded media. */   protected DataSink sink;   /** Processor used to transcode the media. */   protected Processor processor;   /**    * Model used in constructing the processor, and which specifies track    * formats and output content type    */   protected ProcessorModel model;   /** State the object is in. */   protected int state;   /** Location that the media will be "written" to. */   protected MediaLocator sinkLocation;   /** The rate of translation. */   protected float translationRate;   /** Process has failed. */   public static final int FAILED = 0;   /**    * Processor is working but not finished. DataSink is yet to start.    */   public static final int TRANSLATING = 1;   /** DataSink has started but not finished. */   public static final int TRANSFERRING = 3;   /** Transcoding and transfer is complete. */   public static final int FINISHED = 4;   /** String names for each of the states. More user friendly */   private static final String[] STATE_NAMES = { "Failed", "Translating",       "<UNUSED>", "Transferring", "Finished" };   /**    * Period (in milliseconds) between checks for the blocking transfer method.    */   public static final int WAIT_PERIOD = 50;   /**    * Wait an "indefinite" period of time for the transfer method to complete.    * i.e., pass to transfer() if the user wishes to block till the process is    * complete, regardless of how long it will take.    */   public static final int INDEFINITE = Integer.MAX_VALUE;   /***************************************************************************    * Construct a transfer/transcode object that transfers media from    * sourceLocation to destinationLocation, transcoding the tracks as    * specified by the outputFormats. The output media is to have a content    * type of outputContainer and the process should (if possible) run at the    * passed rate.    **************************************************************************/   Location2Location(MediaLocator sourceLocation,       MediaLocator destinationLocation, Format[] outputFormats,       ContentDescriptor outputContainer, double rate) {     //////////////////////////////////////////////     // Construct the processor for the transcoding     //////////////////////////////////////////////     state = TRANSLATING;     sinkLocation = destinationLocation;     try {       if (sourceLocation == null)         model = new ProcessorModel(outputFormats, outputContainer);       else         model = new ProcessorModel(sourceLocation, outputFormats,             outputContainer);       processor = Manager.createRealizedProcessor(model);     } catch (Exception e) {       state = FAILED;       return;     }     translationRate = processor.setRate((float) Math.abs(rate));     processor.addControllerListener(this);     ////////////////////////////////////////////////////////////     // Construct the DataSink and employ an anonymous class as     // a DataSink listener in order that the end of transfer     // (completion of task) can be detected.     ///////////////////////////////////////////////////////////     source = processor.getDataOutput();     try {       sink = Manager.createDataSink(source, sinkLocation);     } catch (Exception sinkException) {       state = FAILED;       processor.removeControllerListener(this);       processor.close();       processor = null;       return;     }     sink.addDataSinkListener(new DataSinkListener() {       public void dataSinkUpdate(DataSinkEvent e) {         if (e instanceof EndOfStreamEvent) {           sink.close();           source.disconnect();           if (state != FAILED)             state = FINISHED;         } else if (e instanceof DataSinkErrorEvent) {           if (sink != null)             sink.close();           if (source != null)             source.disconnect();           state = FAILED;         }       }     });     // Start the transcoding     processor.start();   }   /***************************************************************************    * Alternate constructor: source and destination specified as Strings, and    * no rate provided (hence rate of 1.0)    **************************************************************************/   Location2Location(String sourceName, String destinationName,       Format[] outputFormats, ContentDescriptor outputContainer) {     this(new MediaLocator(sourceName), new MediaLocator(destinationName),         outputFormats, outputContainer);   }   /***************************************************************************    * Alternate constructor: No rate specified therefore rate of 1.0    **************************************************************************/   Location2Location(MediaLocator sourceLocation,       MediaLocator destinationLocation, Format[] outputFormats,       ContentDescriptor outputContainer) {     this(sourceLocation, destinationLocation, outputFormats,         outputContainer, 1.0f);   }   /***************************************************************************    * Alternate constructor: source and destination specified as Strings.    **************************************************************************/   Location2Location(String sourceName, String destinationName,       Format[] outputFormats, ContentDescriptor outputContainer,       double rate) {     this(new MediaLocator(sourceName), new MediaLocator(destinationName),         outputFormats, outputContainer, rate);   }   /***************************************************************************    * Respond to events from the Processor performing the transcoding. If its    * task is completed (end of media) close it down. If there is an error    * close it down and mark the process as FAILED.    **************************************************************************/   public synchronized void controllerUpdate(ControllerEvent e) {     if (state == FAILED)       return;     // Transcoding complete.     if (e instanceof StopEvent) {       processor.removeControllerListener(this);       processor.close();       if (state == TRANSLATING)         state = TRANSFERRING;     }     // Transcoding failed.     else if (e instanceof ControllerErrorEvent) {       processor.removeControllerListener(this);       processor.close();       state = FAILED;     }   }   /***************************************************************************    * Initiate the transfer through a DataSink to the destination and wait    * (block) until the process is complete (or failed) or the supplied number    * of milliseconds timeout has passed. The method returns the total amount    * of time it blocked.    **************************************************************************/   public int transfer(int timeOut) {     // Can't initiate: Processor already failed to transcode     ////////////////////////////////////////////////////////     if (state == FAILED)       return -1;     // Start the DataSink     //////////////////////     try {       sink.open();       sink.start();     } catch (Exception e) {       state = FAILED;       return -1;     }     if (state == TRANSLATING)       state = TRANSFERRING;     if (timeOut <= 0)       return timeOut;     // Wait till the process is complete, failed, or the     // prescribed time has passed.     /////////////////////////////////////////////////////     int waited = 0;     while (state != FAILED && state != FINISHED && waited < timeOut) {       try {         Thread.sleep(WAIT_PERIOD);       } catch (InterruptedException ie) {       }       waited += WAIT_PERIOD;     }     return waited;   }   /***************************************************************************    * Initiate the transfer through a DataSink to the destination but return    * immediately to the caller.    **************************************************************************/   public void transfer() {     transfer(-1);   }   /***************************************************************************    * Determine the object's current state. Returns one of the class constants.    **************************************************************************/   public int getState() {     return state;   }   /***************************************************************************    * Returns the object's state as a String. A more user friendly version of    * getState().    **************************************************************************/   public String getStateName() {     return STATE_NAMES[state];   }   /***************************************************************************    * Obtain the rate being used for the process. This is often 1, despite what    * the user may have supplied as Clocks (hence Processors) don't have to    * support any other rate than 1 (and will default to that).    **************************************************************************/   public float getRate() {     return translationRate;   }   /***************************************************************************    * Set the time at which media processing will stop. Specification is in    * media time. This means only the first "when" amount of the media will be    * transferred.    **************************************************************************/   public void setStopTime(Time when) {     if (processor != null)       processor.setStopTime(when);   }   /***************************************************************************    * Stop the processing and hence transfer. This gives user control over the    * duration of a transfer. It could be started with the transfer() call and    * after a specified period stop() could be called.    **************************************************************************/   public void stop() {     if (processor != null)       processor.stop();   } }