JMFをWindowsで複数のキャプチャデバイスが接続された環境で使うと、一番はじめに認識したキャプチャデバイスしか認識しないみたいです。実際にうちの環境でも発生しました。
(結構有名な話かもしれないけど。)
これが厄介なのは、カメラ以外のキャプチャデバイス、たとえばテレビキャプチャとか、そういうものとも干渉すること。
回避策はデバイスマネージャでキャプチャデバイスの利用を停止する方法しかないけど、明らかに間違った方法だと思う。
というわけで、なんとかならないものかと解析をしてみました。
解析
JMFRegistryがデバイス認識しない理由が解れば何か解るかな?ということで、ソースコードを探したらありました。Java SE Desktop Technologies - Java Media Framework API (JMF) ここの、JMFRegistry source for JMF 2.1.1. からダウンロード。
Eclipseでコンパイルできるようにして、JMF Registry のCapture DevicesタブでDetect Capture Devicesボタンを押すと呼ばれる関数を探すと、VFWAuto.javaファイルの中で、vfwデバイスを検出してることがわかった。
そのコードは以下の通り。
VFWAuto.java
public class VFWAuto { public VFWAuto() { Vector devices = (Vector) CaptureDeviceManager.getDeviceList(null).clone(); Enumeration enum = devices.elements(); while (enum.hasMoreElements()) { CaptureDeviceInfo cdi = (CaptureDeviceInfo) enum.nextElement(); String name = cdi.getName(); if (name.startsWith("vfw:")) CaptureDeviceManager.removeDevice(cdi); } int nDevices = 0; for (int i = 0; i < 10; i++) { String name = VFWCapture.capGetDriverDescriptionName(i); if (name != null && name.length() > 1) { System.err.println("Found device " + name); System.err.println("Querying device. Please wait..."); com.sun.media.protocol.vfw.VFWSourceStream.autoDetect(i); nDevices++; } } } public static void main(String [] args) { VFWAuto a = new VFWAuto(); System.exit(0); } }
2個以上のデバイスが接続されていても、VFWCapture.capGetDriverDescriptionNameが0番目以降に有効なものを返してこない。うーん、バグかな?
結局、どうにもならなかったorz
DirectShowをJava経由でいじる方法があるので、(arc@dmzさんに教えてもらった)それ用のキャプチャでやろうかな。