Windows Media Foundation — захват видео с камеры в виде необработанного RBG32

Я собираюсь с этим кодом больше недели 🙂

Я изменил пример кода, включенного в Windows SDK (CWavSink), который является пользовательским приемником волн для записи данных PCM в файл wav.

Я внес некоторые изменения, чтобы использовать этот образец в качестве приемника видео для записи видеопотока с веб-камеры в Windows 8.

Мне удалось получить видеокадры с IMFSample но проблемы у меня есть:

  1. Когда вы записываете захваченные кадры в тестовый файл, попробуйте преобразовать его в avi или любой другой формат, используя ffmpeg, на выходе будут неправильные цвета, и видео не воспроизводится нормально.

  2. Что бы я ни установил для ширины и высоты, я всегда получаю кадры как 320X240.

  3. Буфер выборки всегда 600 КБ, который содержит 2 кадра (я устанавливаю это, чтобы получить один кадр как размер выборки)

  4. Я пытался изменить формат с RGB32 на H263, но кажется, что настройка была проигнорирована, и я всегда получаю RGB32.

Я ценю любую помощь по этому вопросу

Вот мой код

#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

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]