Directshow 中的濾鏡概念_filter

來源:互聯網
上載者:User

Directshow的中filter (濾鏡) 其實可以看作是一個功能模組,它規定了標準的介面,用於不同的濾鏡直接傳遞媒體資料。各個濾鏡也不用知道其他濾鏡具體是怎麼樣工作的,他只要知道傳過來的 是什麼樣格式的媒體資料就行了,然後他自己又由什麼樣的格式傳出去給下個濾鏡。

一個典型的在播放器中播放mp3檔案的filter出來大概是這樣子到;

檔案源濾鏡(File source filter)-》 mp3 解碼filter -》音頻渲染filter

 

上面這個是加上dsp 音效處理的。

最開始的叫做 “源濾鏡” ,最後的叫做“renderer filter” ,每個播放流程,這兩種類型的濾鏡都是一定存在的,中間 到按照功能等分類,還可以分為“transfer filter”(變換濾鏡)、“分離濾鏡(把音視頻資料分離)”等等各種類型。有的還能夠一個接受介面,輸出多個介面。

濾鏡和濾鏡的串連還可以分為推模式(push filter)和拉模式(pull filter)兩種。

推模式的特點就是資料由上遊的濾鏡決定,就是上遊的濾鏡一有資料了可以推給下遊的去處理。

拉模式的呢就是下遊什麼時候處理資料完了,才通過介面像上遊濾鏡要資料。

兩種的不同就是資料的傳遞方法不同,所以中間的快取資料策略也不一樣,具體可以去查看msdn。

總的來說拉模式的適合用來播放檔案,而推模式適合用來網路傳輸即時媒體。因為對即時性要求比較高的,我在自己的源濾鏡中收到資料,就馬上要求播放這 個資料了呀,推模式呢就可以馬上在這個源濾鏡中把資料傳給下遊濾鏡,要求播放。如果是拉模式就不一樣咯,下遊濾鏡決定了播放的話語權,我什麼時候播放完 了,我再什麼時候找你源濾鏡要資料,這樣有可能慢吞吞的在放,而源濾鏡那有可能已經累積了很多資料在那了來不及播放,這樣即時性就不好。

我在寫語音交談的時候,也是試了這兩種濾鏡的,採用push filter到時候,即時性確實要好些的。

關於學習,可以參考directshow sdk內建的兩個例子

memfile(pull filter到)

ball (push filter的)

仔細看一些,稍稍修改就可以工作了。

=================

pull filter的

下遊需要資料時會調用這個函數向上遊filter要資料

HRESULT Read(PBYTE pbBuffer,
                 DWORD dwBytesToRead,
                 BOOL bAlign,                  LPDWORD pdwBytesRead)    

 

 

在這個函數可以設定我們推薦的緩衝的大小,可以在這裡改一下把資料大小改一下,緩衝越小延時就,不過這裡是有要求的,不能亂改,亂改了,決定權在下 遊filter,他就會拒接串連,網上那些人說是要是32768 乘以6的大小,我測試的時候,播放mp3檔案時這裡最小可以調到4096 *48 。
// we need to return an addrefed allocator, even if it is the preferred
// one, since he doesn't know whether it is the preferred one or not.
STDMETHODIMP
CAsyncOutputPin::RequestAllocator(
    IMemAllocator* pPreferred,
    ALLOCATOR_PROPERTIES* pProps,
    IMemAllocator ** ppActual)
{
    CheckPointer(pPreferred,E_POINTER);
    CheckPointer(pProps,E_POINTER);
    CheckPointer(ppActual,E_POINTER);
    ASSERT(m_pIo);

    // we care about alignment but nothing else
    if(!pProps->cbAlign || !m_pIo->IsAligned(pProps->cbAlign))
    {
        m_pIo->Alignment(&pProps->cbAlign);
    }

    ALLOCATOR_PROPERTIES Actual;
    HRESULT hr;
/////// 設定IMediaSample的長度更小一點,可以使語音的延時小一點。
///預設值為 32768 ,可能延時太大了
    pProps->cbBuffer = 4096 ; /////4096 *48 可以成功  
    pProps->cBuffers = 48;    
    if(pPreferred)
    {
        hr = pPreferred->SetProperties(pProps, &Actual);

        if(SUCCEEDED(hr) && m_pIo->IsAligned(Actual.cbAlign))
        {
            pPreferred->AddRef();
            *ppActual = pPreferred;
            return S_OK;
        }
    }

    // create our own allocator
    IMemAllocator* pAlloc;
    hr = InitAllocator(&pAlloc);
    if(FAILED(hr))
    {
        return hr;
    }

    //...and see if we can make it suitable
    hr = pAlloc->SetProperties(pProps, &Actual);
    if(SUCCEEDED(hr) && m_pIo->IsAligned(Actual.cbAlign))
    {
        // we need to release our refcount on pAlloc, and addref
        // it to pass a refcount to the caller - this is a net nothing.
        *ppActual = pAlloc;
        return S_OK;
    }

    // failed to find a suitable allocator
    pAlloc->Release();

    // if we failed because of the IsAligned test, the error code will
    // not be failure
    if(SUCCEEDED(hr))
    {
        hr = VFW_E_BADALIGN;
    }
    return hr;
}

--------------

push模式時,

他會在後台啟動一個進程不停調用FillBuffer函數,我們只要在源濾鏡中有資料來時,把資料傳下去就可以了。在這個函數裡面我們可以用鎖來等 待資料的到來,一來了馬上push就行了。

 

 

===================

寫filter的時候,還需要注意設定filter的可以接受的和輸出的 媒體類型,CMediaType 這個類的設定很關鍵 。設定好了,各個filter才能連的起來,雖然directshow是會進行一些智能串連嘗試的。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.