Java: CaptureDeviceManager # getDeviceList () пусто? - PullRequest
0 голосов
/ 07 января 2012

Я пытаюсь распечатать все устройства захвата, которые поддерживаются с помощью метода #getDeviceList () в классе CaptureDeviceManager, а возвращаемый вектор имеет размер 0.

Почему это? У меня есть веб-камера, которая работает, поэтому должна быть хотя бы одна. Я использую Mac OS X Lion - использую JMF 2.1.1e.

Спасибо!

Ответы [ 2 ]

1 голос
/ 31 мая 2013

CaptureDeviceManager.getDeviceList (Формат формата) не обнаруживает устройства. Вместо этого он читает из реестра JMF, который является файлом jmf.properties . Он ищет файл jmf.properties в пути к классам.

Если установка JMF прошла успешно, путь к классам был бы настроен на включение всех соответствующих JMF-файлов и каталогов. Установка JMF поставляется с файлом jmf.properties , который находится в папке 'lib' в каталоге установки JMF. Это означает, что jmf.properties будет находиться в JMStudio, и вы обычно увидите, что приложение JMStudio работает правильно. ( Если ваша установка JMF находится в папке «C: \ Program Files», запустите от имени администратора, чтобы обойти UAC )

При создании собственного приложения для обнаружения устройств может возникнуть проблема, описанная выше. Я видел несколько вопросов, связанных с той же проблемой. Это связано с тем, что путь к классу вашего приложения может отличаться и может не включать путь к классу среды. Проверьте свойства вашей IDE здесь. Проблема в том, что CaptureDeviceManager не может найти файл jmf.properties , поскольку его там нет.

Как вы правильно выяснили, вы можете скопировать файл jmf.properties из установочной папки JMF. Он будет содержать правильный список устройств, так как JMF обнаружит его во время установки (проверьте это, чтобы убедиться в этом в любом случае).

Если вы хотите выполнить обнаружение устройства самостоятельно, создайте пустой файл jmf.properties и поместите его где-нибудь в вашем пути к классам (он может изначально вызвать исключение java.io.EOFException во время выполнения, но это правильно обрабатывается классами JMF). Затем используйте следующий код для обнаружения веб-камер ...

import javax.media.*;
import java.util.*;

    public static void main(String[] args) {

    VFWAuto vfwObj = new VFWAuto();

    Vector devices = CaptureDeviceManager.getDeviceList(null);
    Enumeration deviceEnum = devices.elements();

    System.out.println("Device count : " + devices.size());

    while (deviceEnum.hasMoreElements()) {
        CaptureDeviceInfo cdi = (CaptureDeviceInfo) deviceEnum.nextElement();
        System.out.println("Device : " + cdi.getName());
    }

}

Код для класса VFWAuto приведен ниже. Это часть исходного кода JMStudio. Вы можете получить хорошее представление о том, как устройства обнаруживаются и записываются в реестр. Поместите оба класса в один пакет при тестировании. Не обращайте внимания на метод main в классе VFWAuto.

import com.sun.media.protocol.vfw.VFWCapture;
import java.util.*;

import javax.media.*;

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);
}
}

Если вы работаете на платформе Windows и у вас есть работающая веб-камера, этот код должен обнаружить устройство и заполнить файл jmf.properties. При следующем запуске вы также можете закомментировать раздел VFWAuto и его ссылки на объекты, и вы увидите, что CaptureDeviceManager читает из файла jmf.properties.

Класс VFWAuto является частью jmf.jar. Вы также можете увидеть классы DirectSoundAuto и JavaSoundAuto для обнаружения аудиоустройств в примере исходного кода JMStudio. Попробуйте то же самое, что и для VFWAuto.

Моя конфигурация была 64-битная Windows 7 + пакет производительности Windows JMF 2.1.1e + веб-камера.

0 голосов
/ 28 ноября 2013

У меня была та же проблема, и я решил, вызвав flush() на моем ObjectInputStream объекте.

В соответствии с документацией API для конструктора ObjectInputStream:

Заголовок потока, содержащий магический номер и номер версии, считывается из потока и проверяется.Этот метод будет блокироваться до тех пор, пока соответствующий ObjectOutputStream не напишет и не очистит заголовок.Это очень важный момент, о котором следует помнить при попытке отправить объекты в обоих направлениях через сокет, поскольку открытие потоков в неправильном порядке приведет к взаимоблокировке.Рассмотрим, например, что произойдет, если и клиент, и сервер попытаются создать ObjectInputStream из входного потока сокета, перед тем как создать соответствующий ObjectOutputStream.Конструктор ObjectInputStream на клиенте будет блокировать, ожидая магического номера и номера версии, которые будут доставлены через соединение, в то же время конструктор ObjectInputStream на стороне сервера также будет блокироваться по той же причине.Следовательно, тупик.

Из-за этого вы всегда должны практиковать в своем коде, чтобы открывать ObjectOutputStream и сначала очищать его, прежде чем открывать ObjectInputStream.Конструктор ObjectOutputStream не будет блокировать, а вызов flush() заставит магический номер и номер версии перемещаться по проводу.Если вы будете следовать этой практике как на своем клиенте, так и на сервере, у вас не должно возникнуть проблем с тупиком.

Автор кредита Тима Рохали и его объяснения здесь .

...