0

ここに画像の説明を入力

こんにちは、みんな、

1 つはカメラから、もう 1 つはファイル ソースからの 2 つの入力を受け取る変換フィルターがあります。変換フィルター内で、2 つのソースからの入力をブレンドしています。

変換フィルターは CTransformFilter から派生します

class CWMTransformFilter : public CTransformFilter

余分なピンは次から派生します: CTransformInputPin (この inturn は CBaseInputPin から派生します)

class CFileInputPin : public CTransformInputPin

私の場合、ファイル ソースが小さい場合 (10 秒と仮定)、カメラからの入力も 10 秒間取得し、その後、カメラは入力ピンへのフレームの送信を停止します。

だから私が今必要としているのは:
1.ソースフィルターが送信を停止した場合でもフレームを送信するようにカメラに通知する方法は?
2. ソース ファイルの再生が停止したときにソース フィルターを再起動するにはどうすればよいですか?
(ループでファイルを再生するようなもの)

アップデート:

STDMETHODIMP CFileInputPin::EndOfStream()
{
    //return CTransformInputPin::EndOfStream();
    return S_OK;
}

STDMETHODIMP CFileInputPin::Receive(IMediaSample* pSample)
{
    HRESULT hr;
    BYTE* pBufferIn;
    long lBufferLength, lBufferSize;
    hr = CBaseInputPin::Receive(pSample);
    if (FAILED(hr))
    {
        printf("Error !!\n");
        return hr;
    }
    hr = pSample->GetPointer(&pBufferIn);
    DWORD stat = WaitForSingleObject(m_pFil->m_QSem,0L);
    BOOL bSem = FALSE;
    if( WAIT_OBJECT_0 == stat )
    {
        BYTE *pBuf = (BYTE *) malloc( Wsize*2 );
        memcpy(pBuf,pBufferIn,Wsize); //lBufferLength);
        sEncodedFrame CurFrame={pBuf,Wsize};
        m_pFil->m_Q.push(CurFrame); //push it onto the queue

        bSem = ReleaseSemaphore(m_pFil->m_QSem,1,NULL);
        if(!bSem)
        {
            printf("ReleaseSemaphore error: %d \n", GetLastError());
        }

        return S_OK;
    }
    else
    {
        printf("Cant Receive frame 0x%x \n",stat);
        return E_FAIL;
    }
    return S_OK;
}

HRESULT CWMTransformFilter::Transform(IMediaSample *pSource, IMediaSample *pDest)
{
    unsigned char r,g,b;
    unsigned char y,u,v;

    BYTE *pBufferIn, *pBufferOut, *pBuf;
    HRESULT hr = pSource->GetPointer(&pBufferIn);
    hr = pDest->GetPointer(&pBufferOut);
    if (FAILED(hr))
    {
        return hr;
    }
    long srclen = pSource->GetActualDataLength();
    long dstlen = pDest->GetActualDataLength();

    LONG pLastCnt;
    BOOL bSem = FALSE;
    //printf("Waiting to fill buffer %d\n",pSource);
    //return S_OK;
    //try
    //{
    while(1)
    {
        //if(1)
        DWORD ret = WaitForSingleObject(m_QSem,0L);
        if(ret != WAIT_OBJECT_0)
        {
            printf("Get error %d \n",GetLastError());
        }
        if( WAIT_OBJECT_0 == ret )
        {
            
            sEncodedFrame Frame;
            if( m_Q.empty() == false )
            {
                Frame = m_Q.front();
                m_Q.pop();
                pBuf = (BYTE*) malloc(dstlen*2);
                pLastCnt = Frame.iValidSize;
                printf("Copy onto queue \n");
                memcpy(pBuf,Frame.pFrame,pLastCnt); //Frame.iValidSize);
                free(Frame.pFrame);
                //delete &Frame;
                bSem = ReleaseSemaphore(m_QSem,1,NULL);
                if(!bSem)
                {
                    printf("ReleaseSemaphore error: %d \n", GetLastError());
                }
                hr = S_OK;
                break;
            }
            else
            {
                bSem = ReleaseSemaphore(m_QSem,1,NULL);
                if(!bSem)
                {
                    printf("ReleaseSemaphore error: %d \n", GetLastError());
                }
                //return S_OK;
                hr = E_FAIL;
            }
        }
        else
        {
            //return S_OK;
            hr = E_FAIL;
        }
    }

    for(i = 0; i < windowWidth*2*windowHeight ; i+=4)
    {
     y = pBufferIn[i];
     u = pBufferIn[i+1];
     v = pBufferIn[i+3];
     r = y + 1.4075 * (v - 128);
     g = y - 0.3455 * (u - 128) - (0.7169 * (v - 128));
     b = y + 1.7790 * (u - 128);

    if(((r > b) &&(g > b)) && (g <= 200) )
    {
        pBufferIn[i] = pBuf[i];
        pBufferIn[i+1] = pBuf[i+1];
        pBufferIn[i+2] = pBuf[i+2];
        pBufferIn[i+3] = pBuf[i+3];
    }
}

    // Process the data.
    memcpy(pBufferOut,pBufferIn,pSource->GetSize()); //after blend

    pDest->SetActualDataLength(pDest->GetSize());
    pDest->SetSyncPoint(TRUE);
    return S_OK;
}

CFileInputPin::Receive は、ファイル入力ピンからサンプルを受け取る場所であり、
CFileInputPin::EndOfStream() は、サンプルが完了したことを通知します。
CWMTransformFilter::Transform() は、サンプルがアウトピンからレンダラーに渡される場所です。

ありがとう、
シャム

4

1 に答える 1

0

質問には多くのトリッキーなことが含まれています。

まず最初に注目したいのは、カスタム デュアル入力フィルターです。入力フィルターが何を行うにせよ、この変換フィルターは除外できます。両方の入力レッグ ストリームを許可するか、またはいずれかをブロックするかは、その実装にのみ依存します。一般的な (典型的な) ルールは、フィルターに 2 つ以上の入力がある場合、次の 2 つのいずれかであるというものです。

  1. ストリームの 1 つがマスターであり、他の入力は意味がある場合は処理に取り込まれるか、破棄されます。
  2. フィルターは入力入力レッグをブロックして、タイムスタンプが一致するデータを取得し続け、内部処理中にストリームをマージします。

入力ストリームは通常、一連のサンプルであり、その後に EOS 通知が続きます。特に、ソースの 1 つが EOS を送信しない場合、または変換フィルターがそれを適切に処理しない場合、フリーズが発生する可能性があります。

2 つ目の大きな問題はシークです。通常、グラフの一部をシークしません。ただし、ここでまさにあなたがやろうとしていることです。独自のシーク インターフェイスを見つけてソース フィルターを個別にシークするか、バッファーを実装して送信するすべてを保持し、ソースが EOS を送信したらこれを無限にループすることができます。これに関するアドバイスはありません。自分のシナリオで何が適切かを判断してください。

別のオプションは、グラフを分割してブリッジし、ソース グラフを通常の方法でシーク/再起動できるようにすることです。

于 2013-07-28T19:09:47.443 に答える