首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 開發視訊聊天軟體:VFW (Video for Windows) 影像擷取 + UDP 傳輸

     編輯:Delphi

技術架構

  • 影像擷取:Microsoft VFW (AVICAP32.DLL),建立捕捉視窗、連接裝置、設定參數、啟用預覽、註冊幀回呼函數逐幀取得畫面。
  • 壓縮編碼:每幀繪製至 TBitmap,轉 TJpegImage 壓縮 (品質 10~100),存入 TMemoryStream。
  • 網路傳輸:Indy TIdUDPClient 廣播 (192.168.0.255:9001) 或單播發送 JPEG 位元組流;接收端 TIdUDPServer 讀取 Stream 載入 JPEG 顯示於 TImage。

伺服器端 (擷取/發送) 關鍵程式碼

uses VFW, Jpeg, IdUDPClient, Classes;

var
  CapWnd: THandle; CapParms: TCaptureParms; BmpInfo: TBitmapInfo;

procedure TFormServer.StartCapture;
begin
  // 1. 建立捕捉視窗
  CapWnd := capCreateCaptureWindow('MyCap', WS_CHILD or WS_VISIBLE,
    0, 0, PanelVideo.Width, PanelVideo.Height, PanelVideo.Handle, 0);
  if CapWnd = 0 then Exit;

  // 2. 註冊幀回呼
  capSetCallbackOnFrame(CapWnd, @FrameCallback);

  // 3. 設定捕捉參數
  FillChar(CapParms, SizeOf(CapParms), 0);
  CapParms.dwRequestMicroSecPerFrame := 33333; // ~30 fps
  CapParms.fYield := True;
  CapParms.vKeyAbort := VK_ESCAPE;
  capCaptureSetSetup(CapWnd, @CapParms, SizeOf(CapParms));

  // 4. 連接裝置 (索引 0)
  capDriverConnect(CapWnd, 0);
  capGetVideoFormat(CapWnd, @BmpInfo, SizeOf(BmpInfo));

  // 5. 啟用預覽 (Overlay 模式較省資源)
  capPreviewScale(CapWnd, True);
  capOverlay(CapWnd, True);
  capPreview(CapWnd, True);

  // 6. 開始串流捕捉 (不存檔)
  capCaptureSequenceNoFile(CapWnd);
end;

// 幀回呼函數 (VFW 執行緒呼叫,需執行緒安全)
function FrameCallback(hWnd: HWND; lpVHdr: PVideoHdr): LongInt; stdcall;
var
  HDC: HDC; Bmp: TBitmap; Jpg: TJpegImage; MS: TMemoryStream; DrawHandle: HDC;
begin
  Result := 1; // 繼續捕捉
  Bmp := TBitmap.Create;
  Jpg := TJpegImage.Create;
  MS := TMemoryStream.Create;
  try
    Bmp.Width := BmpInfo.bmiHeader.biWidth;
    Bmp.Height := BmpInfo.bmiHeader.biHeight;

    // VFW 畫面繪製至 Bitmap
    DrawHandle := DrawDibOpen;
    DrawDibDraw(DrawHandle, Bmp.Canvas.Handle, 0, 0,
      BmpInfo.bmiHeader.biWidth, BmpInfo.bmiHeader.biHeight,
      @BmpInfo.bmiHeader, lpVHdr.lpData, 0, 0,
      BmpInfo.bmiHeader.biWidth, BmpInfo.bmiHeader.biHeight, 0);
    DrawDibClose(DrawHandle);

    // JPEG 壓縮
    Jpg.Assign(Bmp);
    Jpg.CompressionQuality := 20; // 平衡品質/大小
    Jpg.Compress;
    Jpg.SaveToStream(MS);

    // UDP 廣播發送 (注意 MTU 限制,大封包需分片)
    if MS.Size > IdUDPClient1.BufferSize then
      IdUDPClient1.SendBuffer('192.168.0.255', 9001, MS.Memory^, IdUDPClient1.BufferSize)
    else
      IdUDPClient1.SendBuffer('192.168.0.255', 9001, MS.Memory^, MS.Size);
  finally
    MS.Free; Jpg.Free; Bmp.Free;
  end;
end;

procedure TFormServer.StopCapture;
begin
  capCaptureAbort(CapWnd);
  capDriverDisconnect(CapWnd);
end;

客戶端 (接收/顯示) 關鍵程式碼

procedure TFormClient.IdUDPServer1UDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
var
  Jpg: TJpegImage;
begin
  Jpg := TJpegImage.Create;
  try
    Jpg.LoadFromStream(AData);
    ImageVideo.Picture.Bitmap.Assign(Jpg);
  finally
    Jpg.Free;
  end;
end;

關鍵技術難點與改進方向

現代化建議

新專案強烈建議採用 **WebRTC** (DataChannel/VideoTrack) 或 **gRPC + Protobuf** 傳輸編碼後的 H.264/VP8/HEVC 影流,Delphi 可透過 libwebrtc 封裝或 sgcWebSockets (支援 WebRTC) 整合,跨平台、穿透 NAT、硬體加速、低延遲。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
問題原因改進方案
UDP 封包大小限制 (MTU ~1500 bytes)JPEG 若超過 BufferSize 會被截斷,畫面破碎啟用分片重組、或改用 H.264 硬體編碼 + RTP over UDP、或改 TCP 可靠傳輸
VFW 過時、不支援現代攝像頭 (UVC)、無硬體加速VFW 為 1990s 技術改用 DirectShow、Media Foundation、OpenCV、FFmpeg (Delphi wrapper)
無音訊支援範例僅處理影像同步捕捉 WaveIn 音訊、Opus/AAC 編碼、RTP 多工傳輸
廣播僅限同網段,跨路由需組播/中繼伺服器UDP 廣播不穿透路由引入 STUN/TURN/ICE (WebRTC) 實現 NAT 穿透
幀回呼在 VFW 執行緒,VCL 操作需同步直接操作 UI 會導致死結用 TThread.Queue 送回主執行緒更新預覽