ImageToMovie.java
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, AIST, the University of Tokyo and General Robotix Inc.
00003  * All rights reserved. This program is made available under the terms of the
00004  * Eclipse Public License v1.0 which accompanies this distribution, and is
00005  * available at http://www.eclipse.org/legal/epl-v10.html
00006  * Contributors:
00007  * General Robotix Inc.
00008  * National Institute of Advanced Industrial Science and Technology (AIST) 
00009  */
00010 package com.generalrobotix.ui.view.tdview;
00011 
00012 import java.io.*;
00013 import java.util.*;
00014 import java.awt.*;
00015 
00016 import javax.media.*;
00017 import javax.media.control.*;
00018 import javax.media.protocol.*;
00019 import javax.media.datasink.*;
00020 import javax.media.format.*;
00021 import javax.media.util.ImageToBuffer;
00022 
00023 import org.eclipse.jface.dialogs.MessageDialog;
00024 import org.eclipse.swt.widgets.Display;
00025 
00026 import com.generalrobotix.ui.grxui.GrxUIPerspectiveFactory;
00027 import com.generalrobotix.ui.util.MessageBundle;
00028 
00029 
00030 //======================================================================
00031 //ImageToMovie
00032 //
00033 //フィールド
00034 //    public static String QUICKTIME
00035 //      .mov形式
00036 //    public static String MSVIDEO
00037 //      .avi形式
00038 //
00039 //コンストラクタ
00040 //    public ImageToMovie (int width, int height, float frameRate,String outputUrl,String fileType){
00041 //      引数の説明
00042 //          width,height    ムービーサイズ
00043 //          frameRate       フレームレート[1/s]
00044 //          outputUrl       ファイル名
00045 //          fileType        ファイルタイプ
00046 //                              QUICKTIME or MSVIDEO
00047 //
00048 //メソッド
00049 //    public Format[] getSupportedFormats()
00050 //      出力可能なFormatを配列として返す。
00051 //
00052 //    public void setFormat(Format format)
00053 //      出力形式を設定する。
00054 //
00055 //    public void startProcess()
00056 //      処理を開始する。
00057 //
00058 //    public void pushImage(Image image){
00059 //      ムービーの一コマのイメージを追加する
00060 //
00061 //    public int getImageStackSize(){
00062 //      現在バッファにスタックされているイメージ数を返す
00063 //
00064 //    public void endProcess(){
00065 //      ムービー作成のが終了する。
00066 //      (バッファにたまっている画像を出力して終わる。ファイルが閉じられれるまでwaitする事に注意)
00067 //
00068 //======================================================================
00069 
00070 
00071 public class ImageToMovie implements ControllerListener, DataSinkListener {
00072     //ファイル形式用定数
00073     public static String QUICKTIME=FileTypeDescriptor.QUICKTIME;
00074     public static String MSVIDEO=FileTypeDescriptor.MSVIDEO;
00075     
00076     private ImageDataSource ids_;//カスタムデータソース
00077     private Processor p_;//プロセッサ
00078     private DataSink dsink_;//データシンク
00079     private MediaLocator outML_;//出力ファイル
00080 
00081     private final boolean debugFlag_ = false;//デバッグ用
00082 
00083     //待ち用
00084     private Object waitSync_ = new Object();
00085     private boolean stateTransitionOK_ = true;
00086     private Object waitFileSync_ = new Object();
00087     private boolean fileDone_ = false;
00088     private boolean fileSuccess_ = true;
00089 
00090 
00091     // Create a media locator from the given string.
00092     static MediaLocator createMediaLocator(String url) {
00093 
00094         MediaLocator ml;
00095 
00096         if (url.indexOf(":") > 0 && (ml = new MediaLocator(url)) != null)
00097             return ml;
00098 
00099         if (url.startsWith(File.separator)) {
00100             if ((ml = new MediaLocator("file:" + url)) != null)
00101             return ml;
00102         } else {
00103             String file =
00104                 "file:" + System.getProperty("user.dir") + File.separator + url;
00105             if ((ml = new MediaLocator(file)) != null) return ml;
00106         }
00107 
00108         return null;
00109     }
00110 
00111     //コンストラクタ
00112     //出力用MediaLocatorとプロセッサとデータソースを作りファイル作成の準備までする
00113     public ImageToMovie (
00114         int width,
00115         int height,
00116         float frameRate,
00117         String outputUrl,
00118         String fileType
00119     ){
00120         //出力用MediaLocator生成
00121         outML_ = createMediaLocator(outputUrl);
00122         if (debugFlag_) System.out.println("create:"+outML_);
00123         
00124         
00125         //データソース生成
00126         ids_ = new ImageDataSource(width, height, frameRate);
00127 
00128         //プロセッサ生成
00129         try {
00130             if (debugFlag_) {
00131                 System.err.println(
00132                     "- create processor for the image datasource ..."
00133                 );
00134             }
00135             p_ = Manager.createProcessor(ids_);
00136         } catch (Exception e) {
00137             System.err.println(
00138                 "Yikes!  Cannot create a processor from the data source."
00139             );
00140             return;
00141         }
00142 
00143         
00144         p_.addControllerListener(this);
00145 
00146         // Put the Processor into configured state so we can set
00147         // some processing options on the processor.
00148         p_.configure();
00149         if (!_waitForState(p_, Processor.Configured)) {
00150             System.err.println("Failed to configure the processor.");
00151             return ;
00152         }
00153 
00154         // Set the output content descriptor to. 
00155         p_.setContentDescriptor(new ContentDescriptor(fileType));
00156     }
00157     
00158     //使用可能な形式を返す
00159     public Format[] getSupportedFormats(){
00160         TrackControl tcs[] = p_.getTrackControls();
00161         return tcs[0].getSupportedFormats();
00162     }
00163 
00164     //形式を設定
00165     public void setFormat(Format format){
00166         TrackControl tcs[] = p_.getTrackControls();
00167         tcs[0].setFormat(format);
00168     }
00169     
00170     //ムービー処理開始
00171     public boolean startProcess() {
00172         p_.realize();
00173         if (!_waitForState(p_, Controller.Realized)) {
00174             System.err.println("Failed to realize the processor.");
00175             return false;
00176         }
00177         // Now, we'll need to create a DataSink.
00178         if ((dsink_ = _createDataSink(p_, outML_)) == null) {
00179             System.err.println(
00180                 "Failed to create a DataSink for the given output " +
00181                 "MediaLocator: " + outML_
00182             );
00183             return false;
00184         }
00185         dsink_.addDataSinkListener(this);
00186         fileDone_ = false;
00187         
00188         if (debugFlag_) System.err.println("start processing...");
00189 
00190         // OK, we can now start the actual transcoding.
00191         try {
00192             p_.start();
00193             dsink_.start();
00194         } catch (IOException e) {
00195             System.err.println("IO error during processing");
00196             return false;
00197         }
00198         return true;
00199     }
00200     
00201     
00202     //イメージセットメソッド
00203     public void pushImage(Image image){
00204          ids_.pushImage(image);
00205     }
00206 
00207     //現在バッファにスタックされているイメージ数を返す
00208     public int getImageStackSize(){
00209          return ids_.getImageStackSize();
00210     }
00211 
00212     //終了させる
00213     public void endProcess(){
00214         ids_.endImage();
00215         
00216         _waitForFileDone();
00217 
00218         // Cleanup.
00219         try {
00220             dsink_.close();
00221         } catch (Exception ex) {}
00222         p_.removeControllerListener(this);
00223 
00224         if (debugFlag_) System.err.println("...done processing.");
00225              
00226     }
00227 
00228 
00229     //DataSinkを作成する下請け関数
00230     private DataSink _createDataSink(Processor p, MediaLocator outML) {
00231 
00232         DataSource ds;
00233 
00234         if ((ds = p.getDataOutput()) == null) {
00235             System.err.println(
00236                 "Something is really wrong: the processor does not have " +
00237                 "an output DataSource"
00238             );
00239             return null;
00240         }
00241 
00242         DataSink dsink;
00243 
00244         try {
00245             if (debugFlag_) {
00246                 System.err.println("- create DataSink for: " + outML);
00247             }
00248             dsink = Manager.createDataSink(ds, outML);
00249             dsink.open();
00250         } catch (Exception e) {
00251             System.err.println("Cannot create the DataSink: " + e);
00252             Display display = Display.getDefault();
00253             if (display != null && !display.isDisposed()) {
00254                 display.syncExec(new Runnable(){
00255                                 public void run(){
00256                                         MessageDialog.openError( GrxUIPerspectiveFactory.getCurrentShell(), MessageBundle.get("Grx3DView.dialog.title.error"), MessageBundle.get("Grx3DView.dialog.message.recFileError")); //$NON-NLS-1$ //$NON-NLS-2$
00257                                 }
00258                         });
00259             }
00260             return null;
00261         }
00262 
00263         return dsink;
00264     }
00265 
00266 
00267      //* Block until the processor has transitioned to the given state.
00268      //* Return false if the transition failed.
00269     boolean _waitForState(Processor p, int state) {
00270         synchronized (waitSync_) {
00271             try {
00272             while (p.getState() < state && stateTransitionOK_)
00273                 waitSync_.wait();
00274             } catch (Exception e) {}
00275         }
00276         return stateTransitionOK_;
00277     }
00278 
00279 
00280      //* Controller Listener.
00281     public void controllerUpdate(ControllerEvent evt) {
00282 
00283         if (evt instanceof ConfigureCompleteEvent ||
00284             evt instanceof RealizeCompleteEvent ||
00285             evt instanceof PrefetchCompleteEvent) {
00286             synchronized (waitSync_) {
00287             stateTransitionOK_ = true;
00288             waitSync_.notifyAll();
00289             }
00290         } else if (evt instanceof ResourceUnavailableEvent) {
00291             synchronized (waitSync_) {
00292             stateTransitionOK_ = false;
00293             waitSync_.notifyAll();
00294             }
00295         } else if (evt instanceof EndOfMediaEvent) {
00296             evt.getSourceController().stop();
00297             evt.getSourceController().close();
00298         }
00299     }
00300 
00301 
00302 
00303 
00304     // Block until file writing is done. 
00305     boolean _waitForFileDone() {
00306         synchronized (waitFileSync_) {
00307             try {
00308             while (!fileDone_)
00309                 waitFileSync_.wait();
00310             } catch (Exception e) {}
00311         }
00312         return fileSuccess_;
00313     }
00314 
00315 
00316     //Event handler for the file writer.
00317     public void dataSinkUpdate(DataSinkEvent evt) {
00318 
00319         if (evt instanceof EndOfStreamEvent) {
00320             synchronized (waitFileSync_) {
00321             fileDone_ = true;
00322             waitFileSync_.notifyAll();
00323             }
00324         } else if (evt instanceof DataSinkErrorEvent) {
00325             synchronized (waitFileSync_) {
00326             fileDone_ = true;
00327             fileSuccess_ = false;
00328             waitFileSync_.notifyAll();
00329             }
00330         }
00331     }
00332     
00333     
00335     // Inner classes.
00337     class ImageDataSource extends PullBufferDataSource {
00338 
00339         ImageSourceStream streams_[];
00340 
00341         ImageDataSource(int width, int height, float frameRate) {
00342             streams_ = new ImageSourceStream[1];
00343             streams_[0] = new ImageSourceStream(width, height, frameRate);
00344         }
00345         //イメージセットメソッド
00346         public void pushImage(Image image){
00347              streams_[0].pushImage(image);
00348         }
00349 
00350         //現在バッファにスタックされているイメージ数を返す
00351         public int getImageStackSize(){
00352              return streams_[0].getImageStackSize();
00353         }
00354 
00355         //終了させる
00356         public void endImage(){
00357             streams_[0].endImage();
00358         }
00359 
00360         public void setLocator(MediaLocator source) {
00361         }
00362 
00363         public MediaLocator getLocator() {
00364             return null;
00365         }
00366 
00367         //Content type is of RAW since we are sending buffers of video
00368         // frames without a container format.
00369         public String getContentType() {
00370             return ContentDescriptor.RAW;
00371         }
00372 
00373         public void connect() {
00374         }
00375 
00376         public void disconnect() {
00377         }
00378 
00379         public void start() {
00380         }
00381 
00382         public void stop() {
00383         }
00384 
00385         public PullBufferStream[] getStreams() {
00386             return streams_;
00387         }
00388 
00389         public javax.media.Time getDuration() {
00390             return DURATION_UNKNOWN;
00391         }
00392 
00393         public Object[] getControls() {
00394             return new Object[0];
00395         }
00396 
00397         public Object getControl(String type) {
00398             return null;
00399         }
00400     }
00401 
00402 
00403     // The source stream to go along with ImageDataSource.
00404     class ImageSourceStream implements PullBufferStream {
00405 
00406         int width_, height_;
00407         float frameRate_;
00408         VideoFormat format_;
00409         //Format format_;
00410         Vector<Buffer> imageStack_; //イメージを貯えておくスタック
00411         boolean ending_ = false;//終了の要請あり
00412         boolean ended_ = false;//終了した
00413 
00414         public ImageSourceStream(int width, int height, float frameRate) {
00415             this.width_ = width;
00416             this.height_ = height;
00417             frameRate_=frameRate;
00418             
00419             imageStack_= new Vector<Buffer>();
00420 
00421             format_ =
00422                 new RGBFormat(
00423                    new Dimension(width, height),
00424                    Format.NOT_SPECIFIED,
00425                    Format.intArray,
00426                    (float)frameRate,
00427                    32,
00428                    0xff0000,
00429                    0x00ff00,
00430                    0x0000ff
00431                );
00432         }
00433 
00434         //イメージセットメソッド
00435         public void pushImage(Image image){
00436             imageStack_.add(ImageToBuffer.createBuffer(image, frameRate_));
00437         }
00438 
00439         //終了させる
00440         public void endImage(){
00441             ending_=true;
00442         }
00443 
00444         //現在バッファにスタックされているイメージ数を返す
00445         public int getImageStackSize(){
00446              return imageStack_.size();
00447         }
00448 
00449         //イメージがセットされていればブロック解除
00450         //作者注:特に動作していないようです
00451         public boolean willReadBlock() {
00452             //System.out.println("willReadBlock");
00453             return (ending_==false && imageStack_.isEmpty());
00454             //return false;
00455         }
00456 
00457         // This is called from the Processor to read a frame worth
00458         // of video data.
00459         public void read(Buffer buf) throws IOException {
00460 
00461             // 終了の知らせあり
00462             if (ending_ && imageStack_.isEmpty()) {
00463                 // We are done.  Set EndOfMedia.
00464                 System.err.println("Done reading all images.");
00465                 buf.setEOM(true);
00466                 buf.setOffset(0);
00467                 buf.setLength(0);
00468                 ended_=true;
00469 
00470             //通常の処理
00471             } else if (!(imageStack_.isEmpty())){ //スタックにデータあり
00472                 //スタックからイメージデータを取り出しbufに入れる
00473                 buf.copy((Buffer)imageStack_.remove(0));
00474                 buf.setFlags(buf.getFlags() | Buffer.FLAG_KEY_FRAME);
00475                 buf.setFormat(format_);
00476                 if (debugFlag_) {
00477                     /*
00478                     System.out.println(
00479                         "flag = " + buf.getFlags() +
00480                         " format = " + buf.getFormat() +
00481                         " data = " + buf.getData()
00482                     );
00483                     */
00484                     //System.out.println("writing image to file.");
00485                 }
00486             } else { //スタックにはデータなし
00487                 //System.err.println("una aho na!.");
00488                 buf.setFlags(Buffer.FLAG_DISCARD );//ダミーを示すフラグをセット
00489             }
00490 
00491         }
00492         public Format getFormat() {
00493             return format_;
00494         }
00495 
00496         public ContentDescriptor getContentDescriptor() {
00497             return new ContentDescriptor(ContentDescriptor.RAW);
00498         }
00499 
00500         public long getContentLength() {
00501             return 0;
00502         }
00503 
00504         public boolean endOfStream() {
00505             return ended_;
00506         }
00507 
00508         public Object[] getControls() {
00509             return new Object[0];
00510         }
00511 
00512         public Object getControl(String type) {
00513             return null;
00514         }
00515         //
00516         //class StackEx extends Stack{
00517         //    public StackEx(){
00518         //        super();
00519         //    }
00520         //    public Object popFromEnd(){
00521         //        if (this.empty()){
00522         //            return null;
00523         //        }else{
00524         //            return this.remove(0);
00525         //        }
00526         //    }
00527         //}
00528     }
00529 
00530 }


openhrp3
Author(s): AIST, General Robotix Inc., Nakamura Lab of Dept. of Mechano Informatics at University of Tokyo
autogenerated on Thu Apr 11 2019 03:30:17