locked
Seeking is so slowly RRS feed

  • Question

  • Hi all

    I have wirte an audio MF source and MF decoder, now the problem is that after seek audio it will be wait for about 4 seconds and continue playback.

    this is my code:

    HRESULT MySource::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
        {
            // 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
        {
            hr = m_pStream->DeliverQueuedSamples();
        }
        if (FAILED(hr)) { goto done; }
        m_state = STATE_STARTED;
    
    done:
        if (FAILED(hr) && bQueuedStartEvent)
        {
            hr = QueueEvent(MEError, GUID_NULL, hr, &var);
        }
        PropVariantClear(&var);
        SafeRelease(&pEvent);
        LeaveCriticalSection(&m_critSec);
    
        return hr;
    }

    Tuesday, May 29, 2012 5:32 PM

All replies

  • Your code for the Start function looks okay and the session starts eventually, so I do not think there are problems there.  Some starting points for investigation:

    (1) How soon after Start is called do you receive the first sample request?  This should happen fairly quickly (<100ms).

    (2) How quickly is your source able to fulfill that first sample request?

    (3) What are the timestamps on the samples that you start to provide?  MF will trim samples before the seek time, so if there is a timestamp issue it could result in a lot of samples getting dropped.

    (4) The MFTrace tool might provide some hints on where the delay is coming from.

    Friday, July 27, 2012 9:31 PM