国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 開發(fā) > 綜合 > 正文

在C#中用DirectShow做的媒體播放機(jī)

2024-07-21 02:26:44
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

在c#中用directshow做的媒體播放機(jī)

 

概述:
我的這個(gè)程序僅僅只是告訴大家如何用directshow 在c#中做一個(gè)播放機(jī),世上并不能
有太多的功能.也許你只要花上五分種就可以解決問(wèn)題.是的如果你用的是ide,我感保證
一切都只是用你的鼠標(biāo)在你的設(shè)計(jì)器中點(diǎn)點(diǎn)屬性設(shè)置一些東西就可以簡(jiǎn)單的完成了.當(dāng)然
了還是要那么一點(diǎn)點(diǎn)編碼的.至少是關(guān)于directshow 接口的.例如,視屏和聲音.

程序中的小問(wèn)題:
1.如何從你的磁盤上打開媒體文件
2.如何讓工具條上的按鈕起用和禁用
3.如何設(shè)置狀態(tài)欄的顯示文字
4.如何控制時(shí)間
5.如何使用時(shí)間控件的事件
6.如何用directshow來(lái)播放媒體文件
7.如何確定播放狀態(tài)等等...
...

用戶界面如下圖:
很簡(jiǎn)單是嗎?是的,我說(shuō)了是個(gè)簡(jiǎn)單的程序,我只是讓它具備了基本功能而已.工具欄上
的三個(gè)button控制播放,停止和暫停.一個(gè)文件菜單用來(lái)打開媒體文件和關(guān)閉程序.當(dāng)然
還有一個(gè)介紹程序的info毫無(wú)疑問(wèn)這是最基本的界面配置.

 

 

 

下面介紹directshow 接口

播放視屏和聲音文件我們要用到diectx為我們提供的directshow組件.使用這個(gè)接口
可以讓你方便的播放那些共用的影像和聲音文件.你要做的僅僅只是安裝directshow接口
和使用它的功能函數(shù)和配置正確的接口參數(shù)而已.

 


不幸的是.net并不正式支持directx.是的也許你聽說(shuō)directx9支持是嗎?是的,不過(guò)在
最終版敲定的那一天還沒來(lái),我們都得不到最好的效果.但無(wú)論如何我們還是要用的不是嗎?
要不這篇文章得作廢了.是的,也許你用過(guò)vb,對(duì)了,就是它,我們正是要用到那個(gè).

好了,在此之前我們還必須要做件事情.我想你已經(jīng)猜到了,引用對(duì)嗎?還記得xcopy嗎?是的
.net的優(yōu)勢(shì).來(lái)吧,快點(diǎn)把這個(gè)"interop.quartztypelib.dll"dll引用進(jìn)來(lái),就象這樣
看見下面的圖示了嗎?很簡(jiǎn)單.

 

最后別忘了看看你的代碼中是否有那么一句
using quartztypelib;
有是嗎?編譯器為你加的,如果沒有自己加上好了.

準(zhǔn)備工作結(jié)束了,該是代碼部分了,這可是程序員無(wú)法推卸的責(zé)任.否則我們都得下崗了.

程序?qū)崿F(xiàn)部分:

如何打開你想要媒體文件?

還記得嗎?"file -> open..." 是的幾乎每個(gè)使用windows的人都會(huì)這樣操作.如何實(shí)現(xiàn)?
很簡(jiǎn)單看看下面的代碼:


openfiledialog openfiledialog = new openfiledialog();

openfiledialog.filter = "media files|*.mpg;*.avi;*.wma;*.mov;*.wav;*.mp2;*.mp3|all files|*.*";

if (dialogresult.ok == openfiledialog.showdialog())
{
    .
    .
    .
看吧很簡(jiǎn)單是嗎?記得寫一個(gè)函數(shù)把它放進(jìn)去.當(dāng)你點(diǎn)擊ok按鈕的時(shí)候.directshow接口就會(huì)
得到你想要播放的文件.
看下面的圖你就知道它是如何工作的.


directshow為多媒體流回放提供最基本的服務(wù),這些多媒體流可以是本地文件,還可以是服務(wù)器傳輸過(guò)來(lái)的。特別的,directshow可以支持視頻回放,支持以不同的文件和流格式壓縮視頻內(nèi)容,包括windows media、mpeg、avi和wav。

在directshow的核心處,服務(wù)是組件的模塊化集合,稱為過(guò)濾器,可以根據(jù)媒體類型排列成過(guò)濾器圖。過(guò)濾器可以操作數(shù)據(jù)流,如讀入、分析、解碼、格式化或渲染。

過(guò)濾器以樹型進(jìn)行排列,這棵樹稱為過(guò)濾器樹,通過(guò)過(guò)濾器樹管理器(filter graph manager,簡(jiǎn)稱fgm)進(jìn)行管理。使用fgm應(yīng)用程序可以通過(guò)使用microsoft windows media player控件間接控制過(guò)濾器樹,還可以通過(guò)調(diào)用com接口方法直接控制。directshow過(guò)濾器樹(參閱圖1)由從源到目標(biāo)渲染器的有向過(guò)濾器序列組成,所有這些通過(guò)輸入和輸出過(guò)濾器引腳連接。過(guò)濾器引腳協(xié)商它們將支持哪些媒體類型。fgm控制樹過(guò)濾器之間的多媒體數(shù)據(jù)流。因?yàn)閐irectshow有一個(gè)靈活的、可重配置的過(guò)濾器樹體系結(jié)構(gòu),因此directshow可以使用同樣的軟件成分支持多種媒體類型的回放和分流。開發(fā)人員還可以通過(guò)編寫自己的過(guò)濾器擴(kuò)展directshow多媒體支持。


圖1. directshow過(guò)濾器樹


過(guò)濾器
過(guò)濾器是注冊(cè)的directshow類,它執(zhí)行許多媒體信息處理任務(wù)。這些任務(wù)包括:

獲得源信息(例如,獲得媒體流)
分析(例如,在流上執(zhí)行包讀入、分離和格式化)
轉(zhuǎn)換(例如,解碼wma和mpeg-4音頻和視頻流)
渲染(例如,在適當(dāng)?shù)臅r(shí)候產(chǎn)生音頻pcm或者視頻rgb/yuv輸出,將數(shù)據(jù)傳給directsound和directdraw)
過(guò)濾器使用幾種類型的接口,例如引腳、計(jì)數(shù)器、傳送器和時(shí)鐘接口,來(lái)執(zhí)行它們的任務(wù)。過(guò)濾器實(shí)現(xiàn)和開放了許多接口。fgm可以使用這些接口創(chuàng)建、連接和控制樹。過(guò)濾器經(jīng)常實(shí)現(xiàn)包含下列方法的ibasefilter接口:

運(yùn)行、停止和暫停過(guò)濾器狀態(tài)。
恢復(fù)過(guò)濾器和廠商信息。
得到和設(shè)置參考時(shí)鐘。
恢復(fù)過(guò)濾器狀態(tài)信息。
枚舉過(guò)濾器引線。
重建過(guò)濾器樹時(shí)定位引腳

好了介紹了這么多,你的手也許已經(jīng)閑不住了.看看下面的代碼是如何實(shí)現(xiàn)的


cleanup();

m_objfiltergraph = new filgraphmanager();
m_objfiltergraph.renderfile(openfiledialog.filename);

m_objbasicaudio = m_objfiltergraph as ibasicaudio;

try
{
 m_objvideowindow = m_objfiltergraph as ivideowindow;
 m_objvideowindow.owner = (int) panel1.handle;
 m_objvideowindow.windowstyle = ws_child | ws_clipchildren;
 m_objvideowindow.setwindowposition(panel1.clientrectangle.left,
  panel1.clientrectangle.top,
  panel1.clientrectangle.width,
  panel1.clientrectangle.height);
}
catch (exception ex)
{
 m_objvideowindow = null;
}

m_objmediaevent = m_objfiltergraph as imediaevent;

m_objmediaeventex = m_objfiltergraph as imediaeventex;
m_objmediaeventex.setnotifywindow((int) this.handle, wm_graphnotify, 0);

m_objmediaposition = m_objfiltergraph as imediaposition;

m_objmediacontrol = m_objfiltergraph as imediacontrol;


//


如何來(lái)播放,暫停,停止?
簡(jiǎn)單這些函數(shù)看字面也知道.

m_objmediacontrol.run();//播放

m_objmediacontrol.pause();//暫停

m_objmediacontrol.stop();//停止

 

ok,在來(lái)看我們是如何控制時(shí)間進(jìn)度的?
//
private void timer1_tick(object sender, system.eventargs e)
{
    if (m_currentstatus == mediastatus.running)
    {
        updatestatusbar();
    }
}

看見上面那個(gè) updatestatusbar();這里是讓它沒100ms更新一次狀態(tài)欄.
代碼如下:
private void updatestatusbar()
{
    switch (m_currentstatus)
    {
        case mediastatus.none   : statusbarpanel1.text = "stopped"; break;
        case mediastatus.paused : statusbarpanel1.text = "paused "; break;
        case mediastatus.running: statusbarpanel1.text = "running"; break;
        case mediastatus.stopped: statusbarpanel1.text = "stopped"; break;
    }

    if (m_objmediaposition != null)
    {
        int s = (int) m_objmediaposition.duration;
        int h = s / 3600;
        int m = (s  - (h * 3600)) / 60;
        s = s - (h * 3600 + m * 60);

        statusbarpanel2.text = string.format("{0:d2}:{1:d2}:{2:d2}", h, m, s);

        s = (int) m_objmediaposition.currentposition;
        h = s / 3600;
        m = (s  - (h * 3600)) / 60;
        s = s - (h * 3600 + m * 60);

        statusbarpanel3.text = string.format("{0:d2}:{1:d2}:{2:d2}", h, m, s);
    }
    else
    {
        statusbarpanel2.text = "00:00:00";
        statusbarpanel3.text = "00:00:00";
    }
}

還有一個(gè)問(wèn)題程序怎么能夠知道它播放完了????
這會(huì)有點(diǎn)麻煩了.好了,想想看有什么辦法呢?對(duì)了,windows是消息驅(qū)動(dòng)的.那找找看有什么消息
好了.有的就ec_complete 這個(gè).還記得"wndproc" 它嗎??是的,我的老朋友.這次我們必須
要改寫它來(lái)捕獲ec_complete消息.這個(gè)消息是directshow通知父窗體,播放結(jié)束了.

protected override void wndproc(ref message m)
{
    if (m.msg == wm_graphnotify)
    {
        int leventcode;
        int lparam1, lparam2;

        while (true)
        {
            try
            {
                m_objmediaeventex.getevent(out leventcode,
                    out lparam1,
                    out lparam2,
                    0);

                m_objmediaeventex.freeeventparams(leventcode, lparam1, lparam2);

                if (leventcode == ec_complete)
                {
                    m_objmediacontrol.stop();
                    m_objmediaposition.currentposition = 0;
                    m_currentstatus = mediastatus.stopped;
                    updatestatusbar();
                    updatetoolbar();
                }
            }
            catch (exception)
            {
                break;
            }
        }
    }

    base.wndproc(ref m);
}
好了,一切都結(jié)束了,現(xiàn)在要做的事就是做些來(lái)找一部影片來(lái)享受一下自己的成果了.


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 仁化县| 古蔺县| 朝阳区| 阿克| 贺兰县| 改则县| 嵩明县| 东辽县| 伽师县| 新沂市| 蒙阴县| 南川市| 筠连县| 益阳市| 邵阳县| 廉江市| 碌曲县| 息烽县| 黄山市| 阜新| 诸城市| 习水县| 山西省| 自贡市| 美姑县| 麟游县| 仁寿县| 体育| 房产| 台中县| 古浪县| 青龙| 台前县| 宜黄县| 东丽区| 凤凰县| 霸州市| 徐水县| 湘阴县| 卢氏县| 磐石市|