Je développe une application de bureau de streaming de caméra USB en utilisant la technique MediaFoundation SourceReader. L'appareil photo prend en charge USB3.0 et donne 60fps pour la résolution de format vidéo MJPG 1080p.MFT asynchrone n'envoie pas MFTransformHaveOutput Événement (Intel MFT MJPEG Decoder MFT)
J'ai utilisé le logiciel MJPEG Decoder MFT pour convertir MJPG en trames YUY2, puis converti dans la trame RGB32 pour dessiner sur la fenêtre. Au lieu de 60fps, je suis en mesure de rendre seulement 30fps sur la fenêtre lors de l'utilisation de ce décodeur logiciel. J'ai posté une question sur ce site et j'ai eu une suggestion d'utiliser Intel Hardware MJPEG Decoder MFT pour résoudre le problème de chute de trame.
Pour utiliser ce décodeur matériel MJPEG, j'ai adressé un modèle de traitement MFT asynchrone et configuré un rappel asynchrone pour IMFMediaEventGenerator via l'interface IMFTransform.
Après avoir appelé MFT_MESSAGE_NOTIFY_START_OF_STREAM en utilisant la méthode ProcessMessage, j'ai reçu deux fois l'événement MFTransfromNeedInput mais je n'ai pas reçu l'événement MFTransformHaveOutput de MFT.
J'ai partagé mon code ici pour référence: méthode
IMFTransform* m_pTransform = NULL;
HRESULT EnumDecoderMFT()
{
HRESULT hr;
IMFActivate** ppActivate;
UINT32 numDecodersMJPG = 0;
LPWSTR lpMFTName = 0;
MFT_REGISTER_TYPE_INFO inputFilter = {MFMediaType_Video,MFVideoFormat_MJPG};
MFT_REGISTER_TYPE_INFO outputFilter = {MFMediaType_Video,MFVideoFormat_YUY2};
UINT32 unFlags = MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_HARDWARE | MFT_ENUM_FLAG_SORTANDFILTER;
hr = MFTEnumEx(MFT_CATEGORY_VIDEO_DECODER, unFlags, &inputFilter, &outputFilter, &ppActivate, &numDecodersMJPG);
if (FAILED(hr)) return hr;
hr = ppActivate[0]->GetAllocatedString(MFT_FRIENDLY_NAME_Attribute,&lpMFTName,0);
if (FAILED(hr)) return hr;
// Activate transform
hr = ppActivate[0]->ActivateObject(__uuidof(IMFTransform), (void**)&m_pTransform);
if (FAILED(hr)) return hr;
hr = hr = m_pTransform->GetAttributes(&pAttributes);
if (SUCCEEDED(hr))
{
hr = pAttributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
if(FAILED(hr)) return hr;
hr = pAttributes->SetUINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE,TRUE);
if(FAILED(hr)) return hr;
hr = pAttributes->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE);
if(FAILED(hr)) return hr;
hr = m_pTransform->QueryInterface(IID_IMFMediaEventGenerator,(void**)&m_pEventGenerator);
if(FAILED(hr)) return hr;
hr = m_pEventGenerator->BeginGetEvent((IMFAsyncCallback*)this,NULL);
if(FAILED(hr)) return hr;
pAttributes->Release();
}
SafeRelease(&ppActivate[0]);
CoTaskMemFree(ppActivate);
return hr;
}
HRESULT Invoke(IMFAsyncResult *pResult)
{
HRESULT hr = S_OK,hrStatus;
MediaEventType meType = MEUnknown; // Event type
IMFMediaEvent *pEvent = NULL;
// Get the event from the event queue.
hr = m_pEventGenerator->EndGetEvent(pResult, &pEvent); //Completes an asynchronous request for the next event in the queue.
if(FAILED(hr)) return hr;
// Get the event type.
hr = pEvent->GetType(&meType);
if(FAILED(hr)) return hr;
hr = pEvent->GetStatus(&hrStatus);
if(FAILED(hr)) return hr;
if(SUCCEEDED(hrStatus))
{
if(meType == METransformNeedInput)
{
SetEvent(m_hNeedInputEvent);
}
else if(meType == METransformHaveOutput)
{
SetEvent(m_hHaveOutputEvent);
}
else if(meType == METransformDrainComplete)
{
hr = m_pTransform->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH,0);
if(FAILED(hr)) return hr;
}
else if(meType == MEError)
{
PROPVARIANT pValue;
hr = pEvent->GetValue(&pValue);
if(FAILED(hr)) return hr;
}
hr = m_pEventGenerator->BeginGetEvent((IMFAsyncCallback*)this,NULL);
if(FAILED(hr)) return hr;
}
done:
SafeRelease(&pEvent);
return S_OK;
}
HRESULT CMFSourceReader::OnReadSample(
HRESULT hrStatus,
DWORD dwStreamIndex ,
DWORD dwStreamFlags ,
LONGLONG llTimestamp ,
IMFSample *pSample // Can be NULL
)
{
HRESULT hr = S_OK;
IMFMediaBuffer *pBuffer = NULL;
DWORD dwcbTotLen = 0;
IMFSample *mftOutSample = NULL;
EnterCriticalSection(&m_critsec);
if (FAILED(hrStatus))
{
hr = hrStatus;
}
if (SUCCEEDED(hr))
{
if (pSample != NULL)
{
if(dwStreamIndex == 0) //VideoStream
{
if(m_pTransform)
{
hr = m_pTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0);
if(FAILED(hr)) return hr;
m_dwWaitObj = WaitForSingleObject(m_hNeedInputEvent,INFINITE);
if(m_dwWaitObj == WAIT_OBJECT_0)
{
hr = ProcessInputSample(pSample);
if(FAILED(hr)) return hr;
}
m_dwWaitObj = WaitForSingleObject(m_hHaveOutputEvent,INFINITE);
if(m_dwWaitObj == WAIT_OBJECT_0)
{
hr = ProcessOutputSample(&mftOutSample);
if(FAILED(hr)) return hr;
}
}
}
}
}
if(SUCCEEDED(hr))
{
if(m_pReader != NULL)
{
hr = m_pReader->ReadSample(
(DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,
0,
NULL, // actual
NULL, // flags
NULL, // timestamp
NULL // sample
);
if(FAILED(hr)) return hr;
}
}
SafeRelease(&mftOutSample);
LeaveCriticalSection(&m_critsec);
return hr;
}
HRESULT ProcessOutputSample(IMFSample **pOutSample)
{
HRESULT hr = S_OK;
MFT_OUTPUT_DATA_BUFFER outputDataBuffer;
DWORD processOutputStatus = 0,mftOutFlags = 0;
MFT_OUTPUT_STREAM_INFO StreamInfo;
IMFSample *mftOutSample = NULL;
IMFMediaBuffer *pOutBuffer = NULL;
if(m_pTransform != NULL)
{
hr = m_pTransform->GetOutputStreamInfo(0, &StreamInfo);
if(FAILED(hr)) return hr;
DWORD status = 0;
hr = m_pTransform->GetOutputStatus(&status);
if (FAILED(hr)) return hr;
hr = MFCreateSample(&mftOutSample);
if(FAILED(hr)) return hr;
hr = MFCreateMemoryBuffer(StreamInfo.cbSize, &pOutBuffer);
if(FAILED(hr)) return hr;
hr = mftOutSample->AddBuffer(pOutBuffer);
if(FAILED(hr)) return hr;
outputDataBuffer.dwStreamID = 0;
outputDataBuffer.dwStatus = 0;
outputDataBuffer.pEvents = NULL;
outputDataBuffer.pSample = mftOutSample;
hr = m_pTransform->ProcessOutput(0, 1, &outputDataBuffer, &processOutputStatus);
if(FAILED(hr)) return hr;
hr = m_pTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0);
if (FAILED(hr)) return hr;
hr = m_pTransform->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, 0);
if (FAILED(hr)) return hr;
if(mftOutSample)
{
*pOutSample = mftOutSample;
(*pOutSample)->AddRef();
}
ResetEvent(m_hHaveOutputEvent);
}
SafeRelease(&mftOutSample);
SafeRelease(&pOutBuffer);
return hr;
}
HRESULT ProcessInputSample(IMFSample *pInputSample)
{
HRESULT hr;
if(m_pTransform != NULL)
{
hr = m_pTransform->ProcessInput(0, pInputSample, 0);
if(FAILED(hr)) return hr;
hr = m_pTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM,0);
if(FAILED(hr)) return hr;
ResetEvent(m_hNeedInputEvent);
}
return hr;
}
J'ai commenté de ProcessOutputSample() dans mon code et vérifié, MFT envoyer en continu type d'événement MFTransformNeedInput. Après l'exemple ProcessInput, j'ai la méthode ProcessOutput mais elle a renvoyé une erreur E_UNEXPECTED. J'ai lu à propos de cette erreur dans MSDN, ils ont mentionné que je ne devrais pas appeler la méthode IMFTransform :: ProcessOutput sans recevoir l'événement MFTransformHaveOutput.
Puis-je utiliser Intel Hardware MJPEG Decoder MFT dans MediaFoundation? Quelqu'un fournit un échantillon pour utiliser ce décodeur? Les 4 derniers jours, je suis aux prises avec ce problème.
Merci d'avance.
Quelle webcam est-ce? (juste curieux) – YePhIcK
J'utilise l'appareil photo qui est mentionné dans ce lien: https://www.e-consystems.com/13mp-autofocus-usb-camera.asp – Abi