Esempio n. 1
0
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;
}
Esempio n. 3
0
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;
}