HRESULT HDMediaSource::Start(IMFPresentationDescriptor *pPresentationDescriptor,const GUID *pguidTimeFormat,const PROPVARIANT *pvarStartPosition) { DbgLogPrintf(L"%s::Start...",L"HDMediaSource"); if (pPresentationDescriptor == nullptr || pvarStartPosition == nullptr) return E_INVALIDARG; if ((pguidTimeFormat != nullptr) && (*pguidTimeFormat != GUID_NULL)) return MF_E_UNSUPPORTED_TIME_FORMAT; //只支持100ns if (pvarStartPosition->vt != VT_I8 && pvarStartPosition->vt != VT_EMPTY) return MF_E_UNSUPPORTED_TIME_FORMAT; CritSec::AutoLock lock(_cs); HRESULT hr = CheckShutdown(); if (FAILED(hr)) return hr; hr = IsInitialized(); if (FAILED(hr)) return hr; hr = ValidatePresentationDescriptor(pPresentationDescriptor); if (FAILED(hr)) return hr; if (_state == STATE_STARTED) DbgLogPrintf(L"%s::was already started.",L"HDMediaSource"); ComPtr<SourceOperation> op; hr = SourceOperation::CreateStartOperation( pPresentationDescriptor, _start_op_seek_time, op.GetAddressOf()); if (FAILED(hr)) return hr; _start_op_seek_time = PACKET_NO_PTS; hr = op->SetData(*pvarStartPosition); if (FAILED(hr)) return hr; DbgLogPrintf(L"%s::Start OK.",L"HDMediaSource"); _enterReadPacketFlag = false; _network_buffering = false; return QueueOperation(op.Get()); }
HRESULT WavSource::Start( IMFPresentationDescriptor* pPresentationDescriptor, const GUID* pguidTimeFormat, const PROPVARIANT* pvarStartPosition ) { HRESULT hr = S_OK; LONGLONG llStartOffset = 0; BOOL bIsSeek = FALSE; BOOL bIsRestartFromCurrentPosition = FALSE; BOOL bQueuedStartEvent = FALSE; IMFMediaEvent *pEvent = NULL; PROPVARIANT var; PropVariantInit(&var); // Check parameters. // Start position and presentation descriptor cannot be NULL. if (pvarStartPosition == NULL || pPresentationDescriptor == NULL) { return E_INVALIDARG; } // Check the time format. Must be "reference time" units. if ((pguidTimeFormat != NULL) && (*pguidTimeFormat != GUID_NULL)) { // Unrecognized time format GUID. return MF_E_UNSUPPORTED_TIME_FORMAT; } EnterCriticalSection(&m_critSec); // Fail if the source is shut down. hr = CheckShutdown(); if (FAILED(hr)) { goto done; } // Check the start position. if (pvarStartPosition->vt == VT_I8) { // Start position is given in pvarStartPosition in 100-ns units. llStartOffset = pvarStartPosition->hVal.QuadPart; if (m_state != STATE_STOPPED) { // Source is running or paused, so this is a seek. bIsSeek = TRUE; } } else if (pvarStartPosition->vt == VT_EMPTY) { // Start position is "current position". // For stopped, that means 0. Otherwise, use the current position. if (m_state == STATE_STOPPED) { llStartOffset = 0; } else { llStartOffset = GetCurrentPosition(); bIsRestartFromCurrentPosition = TRUE; } } else { // We don't support this time format. hr = MF_E_UNSUPPORTED_TIME_FORMAT; goto done; } // Validate the caller's presentation descriptor. hr = ValidatePresentationDescriptor(pPresentationDescriptor); if (FAILED(hr)) { goto done; } // Sends the MENewStream or MEUpdatedStream event. hr = QueueNewStreamEvent(pPresentationDescriptor); if (FAILED(hr)) { goto done; } // Notify the stream of the new start time. hr = m_pStream->SetPosition(llStartOffset); if (FAILED(hr)) { goto done; } // Send Started or Seeked events. var.vt = VT_I8; var.hVal.QuadPart = llStartOffset; // Send the source event. if (bIsSeek) { hr = QueueEvent(MESourceSeeked, GUID_NULL, hr, &var); if (FAILED(hr)) { goto done; } } else { // For starting, if we are RESTARTING from the current position and our // previous state was running/paused, then we need to add the // MF_EVENT_SOURCE_ACTUAL_START attribute to the event. This requires // creating the event object first. // Create the event. hr = MFCreateMediaEvent(MESourceStarted, GUID_NULL, hr, &var, &pEvent); if (FAILED(hr)) { goto done; } // For restarts, set the actual start time as an attribute. if (bIsRestartFromCurrentPosition) { hr = pEvent->SetUINT64(MF_EVENT_SOURCE_ACTUAL_START, llStartOffset); if (FAILED(hr)) { goto done; } } // Now queue the event. hr = m_pEventQueue->QueueEvent(pEvent); if (FAILED(hr)) { goto done; } } bQueuedStartEvent = TRUE; // Send the stream event. if (m_pStream) { if (bIsSeek) { hr = m_pStream->QueueEvent(MEStreamSeeked, GUID_NULL, hr, &var); } else { hr = m_pStream->QueueEvent(MEStreamStarted, GUID_NULL, hr, &var); } if (FAILED(hr)) { goto done; } } if (bIsSeek) { // For seek requests, flush any queued samples. hr = m_pStream->Flush(); } else { // Otherwise, deliver any queued samples. hr = m_pStream->DeliverQueuedSamples(); } if (FAILED(hr)) { goto done; } m_state = STATE_STARTED; done: // If a failure occurred and we have not sent the // MESourceStarted/MESourceSeeked event yet, then it is // OK just to return an error code from Start(). // If a failure occurred and we have already sent the // event (with a success code), then we need to raise an // MEError event. if (FAILED(hr) && bQueuedStartEvent) { hr = QueueEvent(MEError, GUID_NULL, hr, &var); } PropVariantClear(&var); SafeRelease(&pEvent); LeaveCriticalSection(&m_critSec); return hr; }
IFACEMETHODIMP CGeometricMediaSource::Start( IMFPresentationDescriptor *pPresentationDescriptor, const GUID *pguidTimeFormat, const PROPVARIANT *pvarStartPos ) { HRESULT hr = S_OK; // Check parameters. // Start position and presentation descriptor cannot be nullptr. if (pvarStartPos == nullptr || pPresentationDescriptor == nullptr) { return E_INVALIDARG; } // Check the time format. if ((pguidTimeFormat != nullptr) && (*pguidTimeFormat != GUID_NULL)) { // Unrecognized time format GUID. return MF_E_UNSUPPORTED_TIME_FORMAT; } // Check the data type of the start position. if (pvarStartPos->vt != VT_EMPTY && pvarStartPos->vt != VT_I8) { return MF_E_UNSUPPORTED_TIME_FORMAT; } AutoLock lock(_critSec); ComPtr<CStartOperation> spStartOp; if (_eSourceState != SourceState_Stopped && _eSourceState != SourceState_Started) { hr = MF_E_INVALIDREQUEST; } if (SUCCEEDED(hr)) { // Check if the presentation description is valid. hr = ValidatePresentationDescriptor(pPresentationDescriptor); } if (SUCCEEDED(hr)) { // Prepare asynchronous operation attributes spStartOp = new(std::nothrow) CStartOperation(pPresentationDescriptor); if (!spStartOp) { hr = E_OUTOFMEMORY; } if (SUCCEEDED(hr)) { hr = spStartOp->SetData(*pvarStartPos); } } if (SUCCEEDED(hr)) { // Queue asynchronous operation hr = QueueOperation(spStartOp.Get()); } return hr; }