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

VC 開發實戰:使用 DirectShow 實現全螢幕視訊播放

     編輯:VC++

DirectShow 全螢幕播放核心步驟

開發遊戲時常需播放片頭動畫。媒體播放控件雖簡單但功能受限;VFW 等多媒體庫又過於複雜。微軟提供的 DirectX Media SDK(含 DirectShow)結合 DirectX 高效能,支援多種格式(甚至 MPEG-2),是最佳選擇。

必要標頭檔與介面

#include <ddraw.h>
#include <mmstream.h>
#include <amstream.h>
#include <ddstream.h>

核心介面:IMultiMediaStream(最高層多媒體串流物件,可包含音訊、視訊等多種串流)。

三大核心步驟

  1. 建立 DirectDraw 表面
  2. 從檔案擷取視訊/音訊串流
  3. 在 DirectDraw 表面播放視訊串流

關鍵變數宣告

DDSURFACEDESC ddsd;
IDirectDraw *pDD;
IDirectDrawSurface *pPrimarySurface;
IMultiMediaStream *pMMStream;

初始化與釋放流程

HRESULT Init() {
    pDD = NULL; pPrimarySurface = NULL; pMMStream = NULL;
    ZeroMemory(&ddsd, sizeof(ddsd));
    CoInitialize(NULL); // COM 初始化
    return InitDDraw();
}

void Uninit() {
    if (pMMStream) pMMStream->Release();
    if (pPrimarySurface) pPrimarySurface->Release();
    if (pDD) pDD->Release();
    CoUninitialize();
}

DirectDraw 初始化與表面建立

HRESULT InitDDraw() {
    HRESULT r;
    if (FAILED(r = DirectDrawCreate(NULL, &pDD, NULL))) return r;
    if (FAILED(r = pDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN))) return r;
    if (FAILED(r = pDD->SetDisplayMode(640, 480, 16))) return r; // 解析度設定

    ddsd.dwSize = sizeof(ddsd);
    ddsd.dwFlags = DDSD_CAPS;
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
    if (FAILED(pDD->CreateSurface(&ddsd, &pPrimarySurface, NULL))) return r;
    return S_OK;
}

從檔案載入多媒體串流

HRESULT LoadFromFile(const char *szFileName, IMultiMediaStream **ppMMStream, IDirectDraw *pDD) {
    HRESULT r;
    IAMMultiMediaStream *pAMStream;
    if (FAILED(r = CoCreateInstance(CLSID_AMMultiMediaStream, NULL, CLSCTX_INPROC_SERVER,
        IID_IAMMultiMediaStream, (void **)&pAMStream))) return r;

    WCHAR wPath[MAX_PATH];
    MultiByteToWideChar(CP_ACP, 0, szFileName, -1, wPath, MAX_PATH);

    if (FAILED(r = pAMStream->Initialize(STREAMTYPE_READ, AMMSF_NOGRAPHTHREAD, NULL))) return r;
    if (FAILED(r = pAMStream->AddMediaStream(pDD, &MSPID_PrimaryVideo, 0, NULL))) return r;
    if (FAILED(r = pAMStream->AddMediaStream(NULL, &MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NULL))) return r;
    if (FAILED(r = pAMStream->OpenFile(wPath, 0))) return r;

    *ppMMStream = pAMStream;
    return S_OK;
}

關鍵點:IAMMultiMediaStream 功能強大,此處用於建立視訊/音訊串流並從檔案開啟。

播放實作

HRESULT Play(IDirectDrawSurface *pSurface, IMultiMediaStream *pMMStream) {
    IMediaStream *pPrimaryVidStream;
    IDirectDrawMediaStream *pDDStream;
    IDirectDrawStreamSample *pSample;
    RECT rect; DDSURFACEDESC ddsd;

    pMMStream->GetMediaStream(MSPID_PrimaryVideo, &pPrimaryVidStream);
    pPrimaryVidStream->QueryInterface(IID_IDirectDrawMediaStream, (void **)&pDDStream);
    ddsd.dwSize = sizeof(ddsd);
    pDDStream->GetFormat(&ddsd, NULL, NULL, NULL);

    rect.top = 100; rect.left = 150;
    rect.bottom = ddsd.dwHeight + 100;
    rect.right = ddsd.dwWidth + 150;

    pDDStream->CreateSample(pSurface, &rect, 0, &pSample);
    pMMStream->SetState(STREAMSTATE_RUN);

    while (pSample->Update(0, NULL, NULL, NULL) == S_OK); // 影格更新迴圈

    pMMStream->SetState(STREAMSTATE_STOP);
    pSample->Release(); pDDStream->Release(); pPrimaryVidStream->Release();
}

播放核心:取得視訊串流 → 查詢 DirectDraw 串流介面 → 取得格式建立樣本 → 關聯表面 → 設定狀態為 RUN → 迴圈更新樣本 → 停止釋放。

完整範例碼可至 作者網站 下載。歡迎指正交流!

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