首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JMF 視訊捕獲實戰(二):VFW 架構、裝置識別與格式轉制完整指南

     編輯:Java 相關知識

Java Media Framework (JMF) 進行視訊捕獲的核心在於識別 VFW (Video for Windows) 裝置、取得 MediaLocator、並依據編碼格式(JPEG/H.263)進行解析度轉制,以滿足 RTP 傳輸規格。本文詳解 VFW 架構、JMF 裝置識別代碼、參數屬性檢測與關鍵格式轉制邏輯。

6.1 VFW (Video for Windows) 架構回顧

VFW 為 Microsoft 提供的 Windows 視訊開發工具包,核心模組:

模組功能
AVICAP.DLL視訊捕獲高階介面,處理 AVI I/O 與裝置驅動溝通
MSVIDEO.DLLDrawDib 函數,螢幕視訊繪製
MCIAVI.DRVMCI 命令解譯驅動
AVIFILE.DLLAVI 檔案高階存取
ICM視訊壓縮/解壓縮編解碼器管理
ACM音訊壓縮管理器

Windows 內建 VFW 組件,安裝時自動部署。

6.2 JMF 與 VFW 關聯:裝置字串識別

JMF 透過 CaptureDeviceManager 識別以 vfw: 開頭的裝置字串:

String str1 = "vfw:Logitech USB Video Camera:0";
String str2 = "vfw:Microsoft WDM Image Capture (Win32):0";
CaptureDeviceInfo device = CaptureDeviceManager.getDevice(str2);
MediaLocator locator = device.getLocator();

執行 Detect Capture Devices 後,JMF 控制台將列出所有可用 VFW 裝置。

6.3 自動識別可用 VFW 裝置代碼實現

private MediaLocator autoDetect() {
    MediaLocator ml = null;
    VideoFormat currentFormat = null;
    Format[] videoFormats = null;

    System.out.println("AutoDetect for VFW");
    Vector deviceList = CaptureDeviceManager.getDeviceList(null);
    if (deviceList != null) {
        for (int i = 0; i < deviceList.size(); i++) {
            try {
                CaptureDeviceInfo di = (CaptureDeviceInfo) deviceList.elementAt(i);
                if (di.getName().startsWith("vfw:")) {
                    videoFormats = di.getFormats();
                    for (int j = 0; j < videoFormats.length; j++) {
                        if (videoFormats[j] instanceof RGBFormat) {
                            currentFormat = (RGBFormat) videoFormats[j];
                            break;
                        }
                    }
                    if (currentFormat == null) {
                        System.err.println("Search For RGBFormat Failed");
                        System.exit(-1);
                    }
                    ml = di.getLocator(); // 關鍵:取得 MediaLocator
                }
            } catch (Exception npe) {
                System.err.println("Unable to get Processor for device");
                System.exit(-1);
            }
        }
    } else {
        System.err.println("No Capture Device OK");
        System.exit(-1);
    }
    return ml;
}

6.4 偵測到的視訊裝置參數屬性

屬性包含:裝置名稱、支援格式清單(RGBFormat, YUVFormat 等)、預設幀率、解析度範圍等。

關鍵技術點:視訊格式轉制

RTP 傳輸對解析度有嚴格限制:

  • JPEG:寬、高必須為 8 像素倍數。
  • H.263:僅支援 352×288 (CIF)、176×144 (QCIF)、128×96 (SQCIF) 三種標準解析度。

因此捕獲原始影像必須經過 Processor 的 TrackControl 進行格式轉制:

TrackControl[] tracks = processor.getTrackControls();
for (int i = 0; i < tracks.length; i++) {
    Format supported = tracks[i].getSupportedFormats()[0];
    Format chosen = checkForVideoSizes(tracks[i].getFormat(), supported);
    if (chosen != null) tracks[i].setFormat(chosen);
}

// 轉制核心邏輯
Format checkForVideoSizes(Format original, Format supported) {
    Dimension size = ((VideoFormat) original).getSize();
    Format jpegFmt = new Format(VideoFormat.JPEG_RTP);
    Format h263Fmt = new Format(VideoFormat.H263_RTP);
    int width, height;

    if (supported.matches(jpegFmt)) {
        width  = (size.width  % 8 == 0) ? size.width  : (size.width  / 8) * 8;
        height = (size.height % 8 == 0) ? size.height : (size.height / 8) * 8;
    } else if (supported.matches(h263Fmt)) {
        if (size.width < 128)      { width = 128; height = 96; }
        else if (size.width < 176) { width = 176; height = 144; }
        else                       { width = 352; height = 288; }
    } else {
        return supported; // 非目標格式不處理
    }
    return new VideoFormat(null, new Dimension(width, height),
                           Format.NOT_SPECIFIED, null, Format.NOT_SPECIFIED)
           .intersects(supported);
}

實戰建議

  1. 優先選擇 JPEG_RTP:解析度限制較寬鬆,適應性強。
  2. 檢測裝置支援格式:執行 di.getFormats() 確認目標編碼是否在支援清單中。
  3. 錯誤處理:捕獲 NoProcessorException、IOException,提供使用者友善提示。
  4. 資源釋放:捕獲結束務必呼叫 processor.close()、dataSource.disconnect()。

總結

JMF 視訊捕獲關鍵在於:正確識別 VFW 裝置 → 取得 MediaLocator → 建立 Processor → 依據 RTP 規格對軌道進行格式轉制。掌握 checkForVideoSizes 邏輯,即可確保捕獲影像順利進入後續編碼、傳輸管線。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved