Windows Media Foundation - 将相机视频捕获为原始RBG32

时间:2014-02-11 20:27:48

标签: c++ ms-media-foundation mft

我正在使用此代码堆叠一周以上:)

我已经更改了Windows SDK(CWavSink)附带的示例代码,这是一个自定义波形接收器,用于将PCM数据记录到wav文件中。

我做了一些更改,将该示例用作视频接收器,以便在Windows 8上记录来自网络摄像头的视频流。

我设法从IMFSample获取视频帧,但我遇到的问题是:

  1. 当将捕获的帧记录到测试文件中时,尝试使用ffmpeg将其转换为avi或任何其他格式,输出颜色错误,视频播放不正常。

  2. 我为宽度和高度设置的内容我总是将帧设置为320X240。

  3. 样本缓冲区总是600kb,包含2帧(我将其设置为一帧作为样本大小)

  4. 我尝试将格式从RGB32更改为H263,但似乎忽略了设置,我总是得到RGB32。

  5. 我很感激你的任何帮助

    这是我的代码

    #include "pch.h"
    #include "VideoSink.h"
    
    #pragma warning( push )
    #pragma warning( disable : 4355 )  // 'this' used in base member initializer list
    
    using namespace VideoRecorder;
    
    const DWORD VIDEO_SINK_STREAM_ID = 1;
    
    
    HRESULT ValidateVideoFormat(const WAVEFORMATEX *pWav, DWORD cbSize);
    
    HRESULT CreateRawVideoType(
        UINT32 frameRate,        // Samples per second
        UINT32 width,     // Bits per sample
        UINT32 hieght,         // Number of channels
        IMFMediaType **ppType     // Receives a pointer to the media type.
        );
    
    
    IFACEMETHODIMP CVideoSink::Initialize()
    {
        IMFByteStream *pStream = nullptr;
    
    
    
        HRESULT hr = S_OK;
    
    
        if (SUCCEEDED(hr))
        {
            hr = this->Initialize(pStream);
        }
    
        return hr;
    }
    
    CVideoSink::CVideoSink() :
        m_nRefCount(1), m_IsShutdown(FALSE), m_pStream(NULL), m_pClock(NULL)
    {
    
    }
    
    CVideoSink::~CVideoSink()
    {
        TRACE((L"~CVideoSink\n"));
        assert(m_IsShutdown);
    }
    
    IFACEMETHODIMP CVideoSink::GetCharacteristics(DWORD *pdwCharacteristics)
    {
        AutoLock lock(m_critSec);
    
        if (pdwCharacteristics == NULL)
        {
            return E_INVALIDARG;
        }
    
        HRESULT hr = CheckShutdown();
    
        if (SUCCEEDED(hr))
        {
            *pdwCharacteristics = MEDIASINK_FIXED_STREAMS | MEDIASINK_RATELESS;
        }
    
        return hr;
    }
    
    
    IFACEMETHODIMP CVideoSink::AddStreamSink( 
        DWORD dwStreamSinkIdentifier,
        IMFMediaType *pMediaType,
        IMFStreamSink **ppStreamSink)
    {
        return MF_E_STREAMSINKS_FIXED;
    }
    
    IFACEMETHODIMP CVideoSink::RemoveStreamSink(DWORD dwStreamSinkIdentifier)
    {
        return MF_E_STREAMSINKS_FIXED;
    }
    
    IFACEMETHODIMP CVideoSink::GetStreamSinkCount(DWORD *pcStreamSinkCount)
    {
        AutoLock lock(m_critSec);
    
        if (pcStreamSinkCount == NULL)
        {
            return E_INVALIDARG;
        }
    
        HRESULT hr = CheckShutdown();
    
        if (SUCCEEDED(hr))
        {
            *pcStreamSinkCount = 1;  // Fixed number of streams.
        }
    
        return hr;
    
    }
    
    IFACEMETHODIMP CVideoSink::GetStreamSinkByIndex( 
        DWORD dwIndex,
        IMFStreamSink **ppStreamSink)
    {
        AutoLock lock(m_critSec);
    
        if (ppStreamSink == NULL)
        {
            return E_INVALIDARG;
        }
    
        // Fixed stream: Index 0. 
        if (dwIndex > 0)
        {
            return MF_E_INVALIDINDEX;
        }
    
        HRESULT hr = CheckShutdown();
    
        if (SUCCEEDED(hr))
        {
            *ppStreamSink = m_pStream;
            (*ppStreamSink)->AddRef();
        }
    
        return hr;
    }
    
    IFACEMETHODIMP CVideoSink::GetStreamSinkById( 
        DWORD dwStreamSinkIdentifier,
        IMFStreamSink **ppStreamSink)
    {
        AutoLock lock(m_critSec);
    
        if (ppStreamSink == NULL)
        {
            return E_INVALIDARG;
        }
    
        // Fixed stream ID.
        if (dwStreamSinkIdentifier != VIDEO_SINK_STREAM_ID)
        {
            return MF_E_INVALIDSTREAMNUMBER;
        }
    
        HRESULT hr = CheckShutdown();
    
        if (SUCCEEDED(hr))
        {
            *ppStreamSink = m_pStream;
            (*ppStreamSink)->AddRef();
        }
    
        return hr;
    
    }
    
    IFACEMETHODIMP CVideoSink::SetPresentationClock(IMFPresentationClock *pPresentationClock)
    {
        AutoLock lock(m_critSec);
    
        HRESULT hr = CheckShutdown();
    
        // If we already have a clock, remove ourselves from that clock's
        // state notifications.
        if (SUCCEEDED(hr))
        {
            if (m_pClock)
            {
                hr = m_pClock->RemoveClockStateSink(this);
            }
        }
    
        // Register ourselves to get state notifications from the new clock.
        if (SUCCEEDED(hr))
        {
            if (pPresentationClock)
            {
                hr = pPresentationClock->AddClockStateSink(this);
            }
        }
    
        if (SUCCEEDED(hr))
        {
            // Release the pointer to the old clock.
            // Store the pointer to the new clock.
    
            SAFE_RELEASE(m_pClock);
            m_pClock = pPresentationClock;
            if (m_pClock)
            {
                m_pClock->AddRef();
            }
        }
    
        return hr;
    }
    
    IFACEMETHODIMP CVideoSink::GetPresentationClock(IMFPresentationClock **ppPresentationClock)
    {
        AutoLock lock(m_critSec);
    
        if (ppPresentationClock == NULL)
        {
            return E_INVALIDARG;
        }
    
        HRESULT hr = CheckShutdown();
    
        if (SUCCEEDED(hr))
        {
            if (m_pClock == NULL)
            {
                hr = MF_E_NO_CLOCK; // There is no presentation clock.
            }
            else
            {
                // Return the pointer to the caller.
                *ppPresentationClock = m_pClock;
                (*ppPresentationClock)->AddRef();
            }
        }
    
    
        return hr;
    }
    
    IFACEMETHODIMP CVideoSink::Shutdown()
    {
        TRACE((L"CVideoSink::Shutdown\n"));
        AutoLock lock(m_critSec);
    
        HRESULT hr = CheckShutdown();
    
        if (SUCCEEDED(hr))
        {
            hr = m_pStream->Shutdown();
    
            SAFE_RELEASE(m_pClock);
            SAFE_RELEASE(m_pStream);
    
            m_IsShutdown = true;
        }
    
        return hr;
    }
    
    IFACEMETHODIMP CVideoSink::BeginFinalize( 
        IMFAsyncCallback *pCallback,
        IUnknown *punkState)
    {
        TRACE((L"CVideoSink::BeginFinalize\n"));
    
        AutoLock lock(m_critSec);
    
        HRESULT hr = CheckShutdown();
    
        // Tell the stream to finalize.
        if (SUCCEEDED(hr))
        {
            hr = m_pStream->Finalize(pCallback, punkState);
        }
        return hr;
    }
    
    IFACEMETHODIMP CVideoSink::EndFinalize(IMFAsyncResult *pResult)
    {
        TRACE((L"CVideoSink::EndFinalize\n"));
    
        HRESULT hr = S_OK;
    
        // Return the status code from the async result.
        if (pResult == NULL)
        {
            hr = E_INVALIDARG;
        }
        else
        {
            hr = pResult->GetStatus();
        }
    
        return hr;
    }
    
    HRESULT CVideoSink::OnClockStart( 
            /* [in] */ MFTIME hnsSystemTime,
            /* [in] */ LONGLONG llClockStartOffset)
    {
        AutoLock lock(m_critSec);
    
        HRESULT hr = CheckShutdown();
    
        if (SUCCEEDED(hr))
        {
            hr = m_pStream->Start(llClockStartOffset);
        }
    
        return hr;
    }    
    
    HRESULT CVideoSink::OnClockStop( 
            /* [in] */ MFTIME hnsSystemTime)
    {
        TRACE((L"CVideoSink::OnClockStop\n"));
        AutoLock lock(m_critSec);
    
        HRESULT hr = CheckShutdown();
    
        if (SUCCEEDED(hr))
        {
            hr = m_pStream->Stop();
        }
    
        return hr;
    }    
    
    HRESULT CVideoSink::OnClockPause( 
            /* [in] */ MFTIME hnsSystemTime)
    {
        AutoLock lock(m_critSec);
    
        HRESULT hr = CheckShutdown();
    
        if (SUCCEEDED(hr))
        {
            hr = m_pStream->Pause();
        }
    
        return hr;
    }
    
    
    HRESULT CVideoSink::OnClockRestart( 
            /* [in] */ MFTIME hnsSystemTime)
    {
        AutoLock lock(m_critSec);
    
        HRESULT hr = CheckShutdown();
    
        if (SUCCEEDED(hr))
        {
            hr = m_pStream->Restart();
        }
    
        return hr;
    }
    
    HRESULT CVideoSink::OnClockSetRate( 
            /* [in] */ MFTIME hnsSystemTime,
            /* [in] */ float flRate)
    {
        return S_OK;
    }
    
    HRESULT CVideoSink::Initialize(IMFByteStream *pByteStream)
    {
        HRESULT hr = S_OK;
    
        m_pStream = new CVideoStream();
        if (m_pStream == NULL)
        {
            hr = E_OUTOFMEMORY;
        }
    
        IMFMediaTypeHandler* typeHandler;
        IMFMediaType* type;
    
    
        // Initialize the stream.
        if (SUCCEEDED(hr))
        {
            hr = m_pStream->Initialize(this, pByteStream);
        }
    
    
        return hr;
    }
    

    我将第二部分添加为另一篇文章(对不起,这是长代码:))

    #不允许:)从这里获取https://github.com/Felixsoft/VideoSink

0 个答案:

没有答案