程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 創建一個基於命令行的簡單的播放器

創建一個基於命令行的簡單的播放器

編輯:關於C語言

1.       概述

這本篇文章給出創建DirectShow程序的一個簡單的示例。DirectShow中使用了大量的COM,確切講DirectShow就是構建在COM基礎上的,但關於COM的基礎知識不在這裡敷述。這個程序是一個簡單的可以播放聲音或者是視頻的控制台程序。這個示例程序只有簡單的幾行,但是卻演示了一個強大的DirectShow的程序。 一個DirectShow應用程序包括以下幾個步驟: 1.       創建一個Filter Graph Manager 的實例; 2.       使用Filter Graph Manager創建一個Filter Graph 3.       運行這個 graph,這樣就會使數據通過這些過濾器(filter)

2.       詳細敘述

首先,調用CoInitialize初始化COM庫: //初始化COM庫.
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
    printf("ERROR - 不能初始化COM庫");
    return 1;
}
  為了使這個示例程序簡單一些,程序中忽略了返回值,但是你可以從任何方法調用中檢查HRESULT的值。 其次,調用CoCreateInstance創建Filter Graph Manager:     //創建過濾器圖像管理器,查詢接口
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,  
  IID_IGraphBuilder, (void **)&pGraph);
    if (FAILED(hr))
    {
        printf("ERROR - 不能夠創建 Filter Graph Manager.");
        return 0;
    }
  如上面的代碼所示,這個類標識符(CLSID)CLSID_FilterGraph。這個Filter Graph Manager由進程中的Dll提供,所以創建時的執行空間上下文是CLSCTX_INPROC_SERVERDirectShow支持自由線程模式,所以你也可以用CoInitializeEx調用COINIT_MULTITHREADED標識符。 調用CoCreateInstance返回IGraphBuilder這個接口,這個接口包含了創建filter graph的大多數方法。另外示例中還需要其余的兩個接口: l  IMediaControl接口控制數據流。這個接口裡面包含了開始和結束播放畫面的方法。 l  IMediaEvent接口包含從Filter Graph Manager中取得的事件。在這個示例裡面,這個接口用來等待視頻播放完成。 這兩個接口都是通過Filter Graph Manager暴露出來的。使用IGraphBuilder指針可以查詢這兩個接口: hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
  現在,你可以創建Filter Graph。這個可以用一個簡單的命令調用。 // 創建graph,此處為要打開的影片
hr = pGraph->RenderFile((LPCWSTR)wText, NULL);
        IGraphBuilder::RenderFile 這個方法用來創建一個Filter Graph 用來播放一個特定的文件。第一個參數是一個文件名,這個文件名為一個Unicode字符串,第二個參數是一個保留字符,一般為NULL。     如果打開的文件不存在,或者是文件格式識別這個返回值HRESULTFAIL。假設這個方法成功了,filter就可以播放了。調用IMediaControl::Run就可以播放視頻了。 //運行graph.
hr = pControl->Run();
    當這個過濾器開始運行後,數據通過filter過濾器後分解成視頻和音頻。系統播放視頻時會創建一個獨立的進程,你可以通過調用IMediaEvent::WaitForCompletion事件方法來監視播放事件當前的狀態。 // 等待影片播放完成
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);     這個事件阻塞到文件完成播放時,或者是到這個線程分配到的時間片丟失掉的時候。INFINITE這個值意味著應用程序阻塞到整個影片播放完成。 當應用程序完成了整個影片的播放,釋放這些接口的指針,然後關閉這些COM組件庫。 pControl->Release();
pEvent->Release();
pGraph->Release();
//卸載COM組件
CoUninitialize();

3. 源程序

3.1. 說明

程序中用到了DirectShow示例文件中的基本類庫,在編譯之前先編譯DX安裝目錄\Samples\C++\DirectShow \BaseClasses  下面的工程,進行以下設置菜單Project->Setting 添加strmbase.lib  

3.2.       源碼

1.        /******************************************************************** 2.               created: 2008/05/15 3.               created: 15:5:2008   13:39 4.               file base:       FirstDX 5.               file ext:  cpp 6.               author:          ZJY 7.               8.               purpose: 這個小程序主要是為了演示DirectShow的最基本的一個步驟 9.        *********************************************************************/ 10.    #include "stdafx.h" 11.    #include <dshow.h> 12.    #include <iostream> 13.      14.    int main(int argc,char *argv[]) 15.    { 16.           char strAviName[256]; 17.           if (argc == 1) 18.           { 19.                  std::cout << "沒有輸出影片,請添加要播放的影片..." <<std::endl; 20.                  return 1; 21.           } 22.           else if (argc == 2) 23.           { 24.                  strcpy(strAviName,argv[1]); 25.           } 26.           else 27.           { 28.                  std::cout <<"參數傳遞錯誤..." <<std::endl; 29.                  return 1; 30.           } 31.      32.        IGraphBuilder *pGraph = NULL; 33.        IMediaControl *pControl = NULL; 34.        IMediaEvent   *pEvent = NULL; 35.           36.        //初始化COM庫. 37.        HRESULT hr = CoInitialize(NULL); 38.        if (FAILED(hr)) 39.        { 40.            printf("ERROR - 不能初始化COM庫"); 41.            return 1; 42.        } 43.           44.           //創建過濾器圖像管理器,查詢接口 45.        hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 46.                  IID_IGraphBuilder, (void **)&pGraph); 47.        if (FAILED(hr)) 48.        { 49.            printf("ERROR - 不能夠創建 Filter Graph Manager."); 50.            return 0; 51.        } 52.           53.        hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl); 54.        hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent); 55.           56.           //由於DirectShow主要是Unicode格式,我們使用Windows自帶函數 57.           //轉換文件名char數組為Unicode格式 58.           int len = strlen(strAviName)+1; 59.           wchar_t *wText = new wchar_t[len]; 60.           if ( wText == NULL) 61.           { 62.                  std::cout <<"ERROR - 文件打開錯誤..."<<std::endl; 63.                  return 1; 64.           } 65.           memset(wText,0,len); 66.           ::MultiByteToWideChar( CP_ACP, NULL,strAviName, -1, wText,len ); 67.      68.           // 創建graph,此處為要打開的影片 69.           hr = pGraph->RenderFile((LPCWSTR)wText, NULL); 70.      71.        if (SUCCEEDED(hr)) 72.        { 73.            //運行graph. 74.            hr = pControl->Run(); 75.            if (SUCCEEDED(hr)) 76.            { 77.                // 等待影片播放完成 78.                long evCode; 79.                pEvent->WaitForCompletion(INFINITE, &evCode); 80.                         //注意:不要在真實的程序中使用INFINITE,因為這樣會永久阻塞應用程序 81.            } 82.        } 83.           else 84.                  std::cout << "ERROR - 影片不存在或格式不支持..." <<std::endl; 85.        pControl->Release(); 86.        pEvent->Release(); 87.        pGraph->Release(); 88.           //卸載COM組件 89.        CoUninitialize(); 90.           return 0; 91.    }

本文出自 “持之以恆,刨根問底” 博客,請務必保留此出處http://zjyzjy.blog.51cto.com/329429/77136

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved