// Handle an event from the capture engine. // NOTE: This method is called from the application's UI thread. HRESULT CaptureManager::OnCaptureEvent(WPARAM wParam, LPARAM lParam) { GUID guidType; HRESULT hrStatus; IMFMediaEvent *pEvent = reinterpret_cast<IMFMediaEvent*>(wParam); HRESULT hr = pEvent->GetStatus(&hrStatus); if (FAILED(hr)) { hrStatus = hr; } hr = pEvent->GetExtendedType(&guidType); if (SUCCEEDED(hr)) { #ifdef _DEBUG LPOLESTR str; if (SUCCEEDED(StringFromCLSID(guidType, &str))) { DBGMSG((L"MF_CAPTURE_ENGINE_EVENT: %s (hr = 0x%X)\n", str, hrStatus)); CoTaskMemFree(str); } #endif if (guidType == MF_CAPTURE_ENGINE_INITIALIZED) { OnCaptureEngineInitialized(hrStatus); SetErrorID(hrStatus, IDS_ERR_INITIALIZE); } else if (guidType == MF_CAPTURE_ENGINE_PREVIEW_STARTED) { OnPreviewStarted(hrStatus); SetErrorID(hrStatus, IDS_ERR_PREVIEW); } else if (guidType == MF_CAPTURE_ENGINE_PREVIEW_STOPPED) { OnPreviewStopped(hrStatus); SetErrorID(hrStatus, IDS_ERR_PREVIEW); } else if (guidType == MF_CAPTURE_ENGINE_RECORD_STARTED) { OnRecordStarted(hrStatus); SetErrorID(hrStatus, IDS_ERR_RECORD); } else if (guidType == MF_CAPTURE_ENGINE_RECORD_STOPPED) { OnRecordStopped(hrStatus); SetErrorID(hrStatus, IDS_ERR_RECORD); } else if (guidType == MF_CAPTURE_ENGINE_PHOTO_TAKEN) { m_bPhotoPending = false; SetErrorID(hrStatus, IDS_ERR_PHOTO); } else if (guidType == MF_CAPTURE_ENGINE_ERROR) { DestroyCaptureEngine(); SetErrorID(hrStatus, IDS_ERR_CAPTURE); } else if (FAILED(hrStatus)) { SetErrorID(hrStatus, IDS_ERR_CAPTURE); } } pEvent->Release(); SetEvent(m_hEvent); return hrStatus; }
// Process any pending output from the decoder (until all output is // processed). // // Thread context: decoder thread bool DecoderMF::DoProcessOutput() { bool ret = false; HRESULT hr; MFT_OUTPUT_DATA_BUFFER mftDataBuffer; DWORD mftStatus; bool moreOutput; if (m_outputSample == NULL) { if (! CreateOutputSample()) return false; } do { // Since we could be looping inside this method for a while, // if a whole stack of frames arrive at once, we want to exit // if the thread has been asked to die. So check on each // iteration of the loop. if (! m_decoderThreadRunning) return true; moreOutput = false; mftDataBuffer.dwStreamID = 0; mftDataBuffer.pSample = m_outputSample; mftDataBuffer.dwStatus = 0; mftDataBuffer.pEvents = NULL; mftStatus = 0; // Looks like we have to reset the sample before use: IMFMediaBuffer* mediaBuffer; hr = m_outputSample->GetBufferByIndex(0, &mediaBuffer); if (FAILED(hr)) goto bail; hr = mediaBuffer->SetCurrentLength(0); if (FAILED(hr)) goto bail; mediaBuffer->Release(); hr = m_h264Decoder->ProcessOutput(0, 1, &mftDataBuffer, &mftStatus); // Check return code if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) break; EnterCriticalSection(&m_criticalSection); if (hr == MF_E_TRANSFORM_STREAM_CHANGE || !m_previewConfigured) { // If the output format has changed, we need to handle // the stream change. This will happen after the first // few packets have been delivered. moreOutput = HandleStreamChange(); LeaveCriticalSection(&m_criticalSection); if (!moreOutput) goto bail; continue; } LeaveCriticalSection(&m_criticalSection); if (FAILED(hr)) goto bail; if (mftDataBuffer.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE) moreOutput = true; // Process each event: if (mftDataBuffer.pEvents != NULL) { DWORD numElements; hr = mftDataBuffer.pEvents->GetElementCount(&numElements); if (SUCCEEDED(hr)) { for (DWORD i = 0; i < numElements; i++) { IUnknown* iunk = NULL; hr = mftDataBuffer.pEvents->GetElement(i, &iunk); if (SUCCEEDED(hr)) { IMFMediaEvent* mediaEvent = NULL; hr = iunk->QueryInterface(IID_IMFMediaEvent, (void**)&mediaEvent); if (SUCCEEDED(hr)) { OutputDebugString(_T("FIXME: process event!\n")); mediaEvent->Release(); } iunk->Release(); } } } mftDataBuffer.pEvents = NULL; } // Process sample: if (mftDataBuffer.pSample != NULL) { IMFMediaBuffer* mediaBuffer; hr = mftDataBuffer.pSample->GetBufferByIndex(0, &mediaBuffer); if (FAILED(hr)) goto bail; EnterCriticalSection(&m_criticalSection); if (m_previewWindow != NULL && m_previewConfigured) m_previewWindow->DrawFrame(mediaBuffer); LeaveCriticalSection(&m_criticalSection); mediaBuffer->Release(); } } while(moreOutput); ret = true; bail: if (ret == false) OutputDebugString(_T("ERROR: failed to process output...\n")); return ret; }
/** Asyncronous callback */ HRESULT FImfVideoPlayer::Invoke( IMFAsyncResult* AsyncResult ) { IMFMediaEvent* Event = NULL; HRESULT HResult = MediaSession->EndGetEvent( AsyncResult, &Event ); if( FAILED( HResult ) ) { Event->Release( ); return S_OK; } MediaEventType EventType = MEUnknown; HResult = Event->GetType( &EventType ); //Moving lower because it is referenced below to GetStatus if there was a problem: Event->Release( ); if( FAILED( HResult ) ) { Event->Release( ); return S_OK; } /* Closed */ if( EventType == MESessionClosed ) { MovieIsFinished.Set( 1 ); CloseIsPosted.Set( 1 ); } else { HResult = MediaSession->BeginGetEvent( this, NULL ); if( FAILED( HResult ) ) { Event->Release( ); return S_OK; } if( MovieIsRunning( ) ) { /* End of clip */ if( EventType == MEEndOfPresentation ) { if( Looping ) StartPlayback( ); else MovieIsFinished.Set( 1 ); } /* Unknown error, dont continue */ else if( EventType == MEError ) { HRESULT HReturnCode = S_OK; Event->GetStatus( &HReturnCode ); /* Log error HResult */ UE_LOG( LogImfVideoPlayer, Log, TEXT( "ImfVideoPlayer error recieved: %i" ), HReturnCode ); MovieIsFinished.Set( 1 ); CloseIsPosted.Set( 1 ); } } /* DEBUG: Displays all event ID's in log */ //UE_LOG( LogImfVideoPlayer, Log, TEXT( "ImfVideoPlayer event id: %i" ), EventType ); } Event->Release( ); return S_OK; }