OSDN Git Service

[更新]NyARToolkit forJava
[nyartoolkit-and/nyartoolkit-and.git] / trunk / src.utils / jmf / jp / nyatla / nyartoolkit / jmf / utils / JmfCaptureDevice.java
1 package jp.nyatla.nyartoolkit.jmf.utils;\r
2 \r
3 import java.awt.Dimension;\r
4 \r
5 import javax.media.*;\r
6 import javax.media.control.*;\r
7 import javax.media.format.*;\r
8 import javax.media.protocol.*;\r
9 import jp.nyatla.nyartoolkit.*;\r
10 \r
11 public class JmfCaptureDevice\r
12 {\r
13         private JmfCaptureListener _capture_listener;\r
14         private MonitorStream _jmf_monitor_stream;\r
15         private Processor _jmf_processor;\r
16         private CaptureDeviceInfo _info;\r
17         private VideoFormat _capture_format;\r
18         private static final String[] _enc_str={"RGB","YUV"};   \r
19         public static final int PIXEL_FORMAT_RGB =0;// "RGB";\r
20         public static final int PIXEL_FORMAT_YUV =1;// "YUV";\r
21         public JmfCaptureDevice(CaptureDeviceInfo i_capinfo) throws NyARException\r
22         {\r
23                 this._info = i_capinfo;\r
24                 this._capture_format = null;\r
25                 return;\r
26         }\r
27 \r
28         /**\r
29          * サポートしているフォーマットの一覧を返します。\r
30          * @return\r
31          */\r
32         public Format[] getSupportFormats()\r
33         {\r
34                 return this._info.getFormats();\r
35         }\r
36 \r
37         public final VideoFormat getCaptureFormat()\r
38         {\r
39                 return this._capture_format;\r
40         }\r
41 \r
42         /**\r
43          * このキャプチャデバイスの提供する、i_index番目のフォーマットをキャプチャフォーマットに指定します。\r
44          * @param i_index\r
45          */\r
46         public void setCaptureFormat(int i_index)\r
47         {\r
48                 this._capture_format = (VideoFormat)this._info.getFormats()[i_index];\r
49                 return;\r
50         }\r
51         /**\r
52          * キャプチャ画像のフォーマットを指定した形式にしようと試みます。\r
53          * @param i_encode\r
54          * キャプチャする画像フォーマットを指定します。フォーマットはこのクラスに宣言される定数値を使ってください。\r
55          * @param i_size\r
56          * キャプチャ画像サイズを指定します。\r
57          * @param i_rate\r
58          * キャプチャレートをFPS単位で指定します。\r
59          * @return\r
60          * 指定に成功するとTRUEを返します。失敗するとFALSEを返します。\r
61          */     \r
62         protected boolean setCaptureFormat(int i_encode, Dimension i_size, float i_rate) throws NyARException\r
63         {\r
64                 if (this._jmf_processor != null){\r
65                         throw new NyARException();\r
66                 }\r
67                 Format[] formats = this._info.getFormats();\r
68                 VideoFormat f = new VideoFormat(_enc_str[i_encode], i_size, Format.NOT_SPECIFIED, null, i_rate);\r
69                 for (int i = 0; i < formats.length; i++){\r
70                         if (formats[i].matches(f)) {\r
71                                 //[暫定実装]RGBの場合のみ、24bit-BGRAを強制する。他のフォーマットも取りたいときは要改造\r
72                                 //これはMacOSのJMF等で問題が出るかもしれない。問題が出たら教えて下さい。\r
73                                 if(formats[i] instanceof RGBFormat){\r
74                                         RGBFormat fmt_ref=(RGBFormat)formats[i];\r
75                                         if(fmt_ref.getBitsPerPixel()!=24 || fmt_ref.getBlueMask()!=1 || fmt_ref.getGreenMask()!=2 || fmt_ref.getRedMask()!=3){\r
76                                                 continue;\r
77                                         }\r
78                                 }\r
79                                 f =(VideoFormat)formats[i].intersects(f);\r
80                                 this._capture_format = null;\r
81                                 this._capture_format = f;\r
82                                 return true;\r
83                         }\r
84                 }\r
85                 //ない。\r
86                 return false;\r
87         }\r
88         /**\r
89          * キャプチャ画像のエンコード、サイズ、レートを引数とするsetCaptureFormat関数です。\r
90          * @param i_encode\r
91          * PIXEL_FORMAT_XXXで定義される定数値を指定して下さい。\r
92          * @param i_size_x\r
93          * キャプチャする画像の横幅\r
94          * @param i_size_y\r
95          * キャプチャする画像の縦幅\r
96          * @param i_rate\r
97          * フレームレート\r
98          * @return\r
99          * 関数の実行結果を真偽値で返します。\r
100          * @throws NyARException\r
101          */     \r
102         public boolean setCaptureFormat(int i_encode,int i_size_x,int i_size_y, float i_rate) throws NyARException\r
103         {\r
104                 return setCaptureFormat(i_encode,new Dimension(i_size_x,i_size_y),i_rate);\r
105         }\r
106         /**\r
107          * キャプチャ画像のサイズ、レートを引数とするsetCaptureFormat関数です。\r
108          * キャプチャ画像のエンコードは、RGB→YUVの順で検索します。\r
109          * @param i_size_x\r
110          * キャプチャする画像の横幅\r
111          * @param i_size_y\r
112          * キャプチャする画像の縦幅\r
113          * @param i_rate\r
114          * フレームレート\r
115          * @return\r
116          * 関数の実行結果を真偽値で返します。\r
117          * @throws NyARException\r
118          */\r
119         public boolean setCaptureFormat(int i_size_x,int i_size_y, float i_rate) throws NyARException\r
120         {\r
121                 Dimension d=new Dimension(i_size_x,i_size_y);\r
122                 if(setCaptureFormat(PIXEL_FORMAT_RGB,d,i_rate)){\r
123                         return true;\r
124                 }\r
125                 if(setCaptureFormat(PIXEL_FORMAT_YUV,d,i_rate)){\r
126                         return true;\r
127                 }\r
128                 return false;\r
129         }\r
130 \r
131         \r
132         \r
133         /**\r
134          * 画像のキャプチャイベントを受信するリスナクラスを指定します。\r
135          * @param i_listener\r
136          * リスナークラス\r
137          * @throws NyARException\r
138          */\r
139         public void setOnCapture(JmfCaptureListener i_listener) throws NyARException\r
140         {\r
141                 if (this._jmf_processor != null) {\r
142                         throw new NyARException();\r
143                 }\r
144                 this._capture_listener = i_listener;\r
145                 return;\r
146         }\r
147         /**\r
148          * キャプチャーを開始します。stop関数を呼び出すまでの間、setOnCaptureで指定したリスナークラスに、\r
149          * フォーマットで指定したキャプチャ画像が通知されます。\r
150          * @throws NyARException\r
151          */\r
152         public void start() throws NyARException\r
153         {\r
154                 // startしていたらエラー\r
155                 if (this._jmf_processor != null) {\r
156                         throw new NyARException();\r
157                 }\r
158                 DataSource ds;\r
159                 final MediaLocator ml = this._info.getLocator();\r
160                 try {\r
161                         ds = Manager.createDataSource(ml);\r
162                         ds.connect();\r
163                         // ここでフォーマットを作成\r
164                         if (ds instanceof CaptureDevice) {\r
165                                 FormatControl[] fcs = ((CaptureDevice) ds).getFormatControls();\r
166                                 if (fcs.length < 1) {\r
167                                         return;\r
168                                 }\r
169                                 FormatControl fc = fcs[0];\r
170                                 fc.setFormat(this._capture_format);\r
171                         }\r
172                 } catch (Exception e) {\r
173                         throw new NyARException(e);\r
174                 }\r
175                 try{\r
176                         if(ds==null){\r
177                                 //Merge the data sources, if both audio and video are available\r
178                                 ds = Manager.createMergingDataSource(new DataSource[] { null });                                \r
179                         }else{\r
180                                 // Create the monitoring datasource wrapper\r
181                                 ds = new MonitorCDS(ds);                                \r
182                         }\r
183                 }catch(IncompatibleSourceException e){\r
184                         throw new NyARException(e);\r
185                 }\r
186                 \r
187                 // データソース完成\r
188                 try {\r
189                         // Merge the data sources, if both audio and video are available\r
190                         VideoFormat[] formats = new VideoFormat[] { new VideoFormat(null) };\r
191                         ProcessorModel pm = new ProcessorModel(ds, formats, null);// ,\r
192                         Processor processor;\r
193                         processor = Manager.createRealizedProcessor(pm);\r
194                         this._jmf_monitor_stream = (MonitorStream) ds.getControl("jmfsample.MonitorStream");\r
195                         this._jmf_monitor_stream.setCaptureListener(this._capture_listener);\r
196                         this._jmf_processor = processor;\r
197                         this._jmf_processor.start();\r
198                 } catch (Exception e) {\r
199                         ds.disconnect();\r
200                         throw new NyARException(e);\r
201                 }\r
202                 return;\r
203         }\r
204 \r
205         public void stop()\r
206         {\r
207                 this._jmf_processor.stop();\r
208                 this._jmf_processor.close();\r
209                 this._jmf_processor = null;\r
210                 return;\r
211         }\r
212         protected void finalize()\r
213         {\r
214                 if (this._jmf_processor != null) {\r
215                         this._jmf_processor.stop();\r
216                         this._jmf_processor.close();\r
217                         this._jmf_processor = null;\r
218                 }\r
219                 return;\r
220         }\r
221 }