/*
 * Copyright (C) 2014 Alex Christensen <achristensen@webkit.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "MediaPlayerPrivateMediaFoundation.h"

#include "CachedResourceLoader.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "HWndDC.h"
#include "HostWindow.h"
#include "NotImplemented.h"
#if USE(CAIRO)
#include "CairoOperations.h"
#include "PlatformContextCairo.h"
#include <cairo.h>
#endif

#if USE(MEDIA_FOUNDATION)

#include <wtf/MainThread.h>
#include <wtf/NeverDestroyed.h>

// MFSamplePresenterSampleCounter
// Data type: UINT32
//
// Version number for the video samples. When the presenter increments the version
// number, all samples with the previous version number are stale and should be
// discarded.
static const GUID MFSamplePresenterSampleCounter =
{ 0x869f1f7c, 0x3496, 0x48a9, { 0x88, 0xe3, 0x69, 0x85, 0x79, 0xd0, 0x8c, 0xb6 } };

static const double tenMegahertz = 10000000;

namespace WebCore {

MediaPlayerPrivateMediaFoundation::MediaPlayerPrivateMediaFoundation(MediaPlayer* player) 
    : m_weakThis(makeWeakPtr(this))
    , m_player(player)
    , m_visible(false)
    , m_loadingProgress(false)
    , m_paused(true)
    , m_hasAudio(false)
    , m_hasVideo(false)
    , m_preparingToPlay(false)
    , m_volume(1.0)
    , m_networkState(MediaPlayer::Empty)
    , m_readyState(MediaPlayer::HaveNothing)
{
    createSession();
}

MediaPlayerPrivateMediaFoundation::~MediaPlayerPrivateMediaFoundation()
{
    notifyDeleted();
    endSession();
}

void MediaPlayerPrivateMediaFoundation::registerMediaEngine(MediaEngineRegistrar registrar)
{
    if (isAvailable()) {
        registrar([](MediaPlayer* player) { return makeUnique<MediaPlayerPrivateMediaFoundation>(player); },
            getSupportedTypes, supportsType, 0, 0, 0, 0);
    }
}

bool MediaPlayerPrivateMediaFoundation::isAvailable() 
{
    notImplemented();
    return true;
}

static const HashSet<String, ASCIICaseInsensitiveHash>& mimeTypeCache()
{
    static NeverDestroyed<HashSet<String, ASCIICaseInsensitiveHash>> cachedTypes;

    if (cachedTypes.get().size() > 0)
        return cachedTypes;

    cachedTypes.get().add(String("video/mp4"));

    PROPVARIANT propVarMimeTypeArray;
    PropVariantInit(&propVarMimeTypeArray);

    HRESULT hr = MFGetSupportedMimeTypes(&propVarMimeTypeArray);

    if (SUCCEEDED(hr)) {
        CALPWSTR mimeTypeArray = propVarMimeTypeArray.calpwstr;
        for (unsigned i = 0; i < mimeTypeArray.cElems; i++)
            cachedTypes.get().add(mimeTypeArray.pElems[i]);
    }

    PropVariantClear(&propVarMimeTypeArray);

    return cachedTypes;
}

void MediaPlayerPrivateMediaFoundation::getSupportedTypes(HashSet<String, ASCIICaseInsensitiveHash>& types)
{
    types = mimeTypeCache();
}

MediaPlayer::SupportsType MediaPlayerPrivateMediaFoundation::supportsType(const MediaEngineSupportParameters& parameters)
{
    if (parameters.type.isEmpty())
        return MediaPlayer::IsNotSupported;

    if (mimeTypeCache().contains(parameters.type.containerType()))
        return MediaPlayer::IsSupported;

    return MediaPlayer::IsNotSupported;
}

void MediaPlayerPrivateMediaFoundation::load(const String& url)
{
    {
        LockHolder locker(m_cachedNaturalSizeLock);
        m_cachedNaturalSize = FloatSize();
    }

    startCreateMediaSource(url);

    m_networkState = MediaPlayer::Loading;
    m_player->networkStateChanged();
    m_readyState = MediaPlayer::HaveNothing;
    m_player->readyStateChanged();
}

void MediaPlayerPrivateMediaFoundation::cancelLoad()
{
    notImplemented();
}

void MediaPlayerPrivateMediaFoundation::play()
{
    m_paused = !startSession();

    m_preparingToPlay = false;
}

void MediaPlayerPrivateMediaFoundation::pause()
{
    if (!m_mediaSession)
        return;

    m_paused = SUCCEEDED(m_mediaSession->Pause());
}

bool MediaPlayerPrivateMediaFoundation::supportsFullscreen() const
{
    return true;
}

FloatSize MediaPlayerPrivateMediaFoundation::naturalSize() const
{
    LockHolder locker(m_cachedNaturalSizeLock);
    return m_cachedNaturalSize;
}

bool MediaPlayerPrivateMediaFoundation::hasVideo() const
{
    return m_hasVideo;
}

bool MediaPlayerPrivateMediaFoundation::hasAudio() const
{
    return m_hasAudio;
}

void MediaPlayerPrivateMediaFoundation::setVisible(bool visible)
{
    m_visible = visible;
}

bool MediaPlayerPrivateMediaFoundation::seeking() const
{
    // We assume seeking is immediately complete.
    return false;
}

void MediaPlayerPrivateMediaFoundation::seek(float time)
{
    PROPVARIANT propVariant;
    PropVariantInit(&propVariant);
    propVariant.vt = VT_I8;
    propVariant.hVal.QuadPart = static_cast<__int64>(time * tenMegahertz);
    
    HRESULT hr = m_mediaSession->Start(&GUID_NULL, &propVariant);
    ASSERT_UNUSED(hr, SUCCEEDED(hr));
    PropVariantClear(&propVariant);

    m_player->timeChanged();
}

void MediaPlayerPrivateMediaFoundation::setRate(float rate)
{
    COMPtr<IMFRateControl> rateControl;

    HRESULT hr = MFGetService(m_mediaSession.get(), MF_RATE_CONTROL_SERVICE, IID_IMFRateControl, (void**)&rateControl);

    if (!SUCCEEDED(hr))
        return;

    BOOL reduceSamplesInStream = rate > 2.0;

    rateControl->SetRate(reduceSamplesInStream, rate);
}

float MediaPlayerPrivateMediaFoundation::duration() const
{
    if (!m_mediaSource)
        return 0;

    IMFPresentationDescriptor* descriptor;
    if (!SUCCEEDED(m_mediaSource->CreatePresentationDescriptor(&descriptor)))
        return 0;
    
    UINT64 duration;
    if (!SUCCEEDED(descriptor->GetUINT64(MF_PD_DURATION, &duration)))
        duration = 0;
    descriptor->Release();
    
    return static_cast<float>(duration) / tenMegahertz;
}

float MediaPlayerPrivateMediaFoundation::currentTime() const
{
    if (!m_presenter)
        return 0.0f;

    return m_presenter->currentTime();
}

bool MediaPlayerPrivateMediaFoundation::paused() const
{
    return m_paused;
}

bool MediaPlayerPrivateMediaFoundation::setAllChannelVolumes(float volume)
{
    COMPtr<IMFAudioStreamVolume> audioVolume;
    if (!SUCCEEDED(MFGetService(m_mediaSession.get(), MR_STREAM_VOLUME_SERVICE, __uuidof(IMFAudioStreamVolume), (void **)&audioVolume)))
        return false;

    UINT32 channelsCount;
    HRESULT hr = audioVolume->GetChannelCount(&channelsCount);
    ASSERT_UNUSED(hr, SUCCEEDED(hr));

    Vector<float> volumes(channelsCount, volume);
    return SUCCEEDED(audioVolume->SetAllVolumes(channelsCount, volumes.data()));
}

void MediaPlayerPrivateMediaFoundation::setVolume(float volume)
{
    if (setAllChannelVolumes(volume))
        m_volume = volume;
}

void MediaPlayerPrivateMediaFoundation::setMuted(bool muted)
{
    setAllChannelVolumes(muted ? 0.0 : m_volume);
}

MediaPlayer::NetworkState MediaPlayerPrivateMediaFoundation::networkState() const
{ 
    return m_networkState;
}

MediaPlayer::ReadyState MediaPlayerPrivateMediaFoundation::readyState() const
{
    return m_readyState;
}

float MediaPlayerPrivateMediaFoundation::maxTimeSeekable() const
{
    return durationDouble();
}

std::unique_ptr<PlatformTimeRanges> MediaPlayerPrivateMediaFoundation::buffered() const
{ 
    auto ranges = makeUnique<PlatformTimeRanges>();
    if (m_presenter && m_presenter->maxTimeLoaded() > 0)
        ranges->add(MediaTime::zeroTime(), MediaTime::createWithDouble(m_presenter->maxTimeLoaded()));
    return ranges;
}

bool MediaPlayerPrivateMediaFoundation::didLoadingProgress() const
{
    return m_loadingProgress;
}

void MediaPlayerPrivateMediaFoundation::setSize(const IntSize& size)
{
    m_size = size;

    auto videoDisplay = this->videoDisplay();
    if (!videoDisplay)
        return;

    FrameView* view = nullptr;
    float deviceScaleFactor = 1.0f;
    if (m_player && m_player->cachedResourceLoader() && m_player->cachedResourceLoader()->document()) {
        view = m_player->cachedResourceLoader()->document()->view();
        deviceScaleFactor = m_player->cachedResourceLoader()->document()->deviceScaleFactor();
    }

    int w = m_size.width() * deviceScaleFactor;
    int h = m_size.height() * deviceScaleFactor;

    RECT rc = { 0, 0, w, h };
    videoDisplay->SetVideoPosition(nullptr, &rc);
}

void MediaPlayerPrivateMediaFoundation::paint(GraphicsContext& context, const FloatRect& rect)
{
    if (context.paintingDisabled() || !m_player->visible())
        return;

    if (m_presenter)
        m_presenter->paintCurrentFrame(context, rect);
}

bool MediaPlayerPrivateMediaFoundation::createSession()
{
    if (FAILED(MFStartup(MF_VERSION, MFSTARTUP_FULL)))
        return false;

    if (FAILED(MFCreateMediaSession(nullptr, &m_mediaSession)))
        return false;

    // Get next event.
    AsyncCallback* callback = new AsyncCallback(this, true);
    HRESULT hr = m_mediaSession->BeginGetEvent(callback, nullptr);
    ASSERT_UNUSED(hr, SUCCEEDED(hr));

    return true;
}

bool MediaPlayerPrivateMediaFoundation::startSession()
{
    if (!m_mediaSession)
        return false;

    PROPVARIANT varStart;
    PropVariantInit(&varStart);
    varStart.vt = VT_EMPTY;

    HRESULT hr = m_mediaSession->Start(nullptr, &varStart);
    ASSERT(SUCCEEDED(hr));

    PropVariantClear(&varStart);

    return SUCCEEDED(hr);
}

bool MediaPlayerPrivateMediaFoundation::endSession()
{
    if (m_mediaSession) {
        m_mediaSession->Shutdown();
        m_mediaSession = nullptr;
    }

    HRESULT hr = MFShutdown();
    ASSERT_UNUSED(hr, SUCCEEDED(hr));

    return true;
}

bool MediaPlayerPrivateMediaFoundation::startCreateMediaSource(const String& url)
{
    if (FAILED(MFCreateSourceResolver(&m_sourceResolver)))
        return false;

    COMPtr<IUnknown> cancelCookie;
    Vector<wchar_t> urlSource = url.wideCharacters();

    AsyncCallback* callback = new AsyncCallback(this, false);

    if (FAILED(m_sourceResolver->BeginCreateObjectFromURL(urlSource.data(), MF_RESOLUTION_MEDIASOURCE, nullptr, &cancelCookie, callback, nullptr)))
        return false;

    return true;
}

bool MediaPlayerPrivateMediaFoundation::endCreatedMediaSource(IMFAsyncResult* asyncResult)
{
    MF_OBJECT_TYPE objectType;
    COMPtr<IUnknown> source;

    HRESULT hr = m_sourceResolver->EndCreateObjectFromURL(asyncResult, &objectType, &source);
    if (FAILED(hr))
        return false;

    hr = source->QueryInterface(IID_PPV_ARGS(&m_mediaSource));
    if (FAILED(hr))
        return false;

    hr = asyncResult->GetStatus();
    m_loadingProgress = SUCCEEDED(hr);

    callOnMainThread([weakPtr = m_weakThis] {
        if (!weakPtr)
            return;
        weakPtr->onCreatedMediaSource();
    });

    return true;
}

bool MediaPlayerPrivateMediaFoundation::endGetEvent(IMFAsyncResult* asyncResult)
{
    COMPtr<IMFMediaEvent> event;

    if (!m_mediaSession)
        return false;

    // Get the event from the event queue.
    HRESULT hr = m_mediaSession->EndGetEvent(asyncResult, &event);
    if (FAILED(hr))
        return false;

    // Get the event type.
    MediaEventType mediaEventType;
    hr = event->GetType(&mediaEventType);
    if (FAILED(hr))
        return false;

    switch (mediaEventType) {
    case MESessionTopologySet: {
        callOnMainThread([weakPtr = m_weakThis] {
            if (!weakPtr)
                return;
            weakPtr->onTopologySet();
        });
        break;
    }

    case MESessionStarted: {
        callOnMainThread([weakPtr = m_weakThis] {
            if (!weakPtr)
                return;
            weakPtr->onSessionStarted();
        });
        break;
    }

    case MEBufferingStarted: {
        callOnMainThread([weakPtr = m_weakThis] {
            if (!weakPtr)
                return;
            weakPtr->onBufferingStarted();
        });
        break;
    }

    case MEBufferingStopped: {
        callOnMainThread([weakPtr = m_weakThis] {
            if (!weakPtr)
                return;
            weakPtr->onBufferingStopped();
        });
        break;
    }

    case MESessionEnded: {
        callOnMainThread([weakPtr = m_weakThis] {
            if (!weakPtr)
                return;
            weakPtr->onSessionEnded();
        });
        break;
    }

    case MEMediaSample:
        break;

    case MEError: {
        HRESULT status = S_OK;
        event->GetStatus(&status);
        break;
    }
    }

    if (mediaEventType != MESessionClosed) {
        // For all other events, ask the media session for the
        // next event in the queue.
        AsyncCallback* callback = new AsyncCallback(this, true);

        hr = m_mediaSession->BeginGetEvent(callback, nullptr);
        if (FAILED(hr))
            return false;
    }

    return true;
}

bool MediaPlayerPrivateMediaFoundation::createTopologyFromSource()
{
    // Create a new topology.
    if (FAILED(MFCreateTopology(&m_topology)))
        return false;

    // Create the presentation descriptor for the media source.
    if (FAILED(m_mediaSource->CreatePresentationDescriptor(&m_sourcePD)))
        return false;

    // Get the number of streams in the media source.
    DWORD sourceStreams = 0;
    if (FAILED(m_sourcePD->GetStreamDescriptorCount(&sourceStreams)))
        return false;

    // For each stream, create the topology nodes and add them to the topology.
    for (DWORD i = 0; i < sourceStreams; i++) {
        if (!addBranchToPartialTopology(i))
            return false;
    }

    return true;
}

bool MediaPlayerPrivateMediaFoundation::addBranchToPartialTopology(int stream)
{
    // Get the stream descriptor for this stream.
    COMPtr<IMFStreamDescriptor> sourceSD;
    BOOL selected = FALSE;
    if (FAILED(m_sourcePD->GetStreamDescriptorByIndex(stream, &selected, &sourceSD)))
        return false;

    // Create the topology branch only if the stream is selected.
    // Otherwise, do nothing.
    if (!selected)
        return true;

    // Create a source node for this stream.
    COMPtr<IMFTopologyNode> sourceNode;
    if (!createSourceStreamNode(sourceSD, sourceNode))
        return false;

    COMPtr<IMFTopologyNode> outputNode;
    if (!createOutputNode(sourceSD, outputNode))
        return false;

    // Add both nodes to the topology.
    if (FAILED(m_topology->AddNode(sourceNode.get())))
        return false;

    if (FAILED(m_topology->AddNode(outputNode.get())))
        return false;

    // Connect the source node to the output node.
    if (FAILED(sourceNode->ConnectOutput(0, outputNode.get(), 0)))
        return false;

    return true;
}

HWND MediaPlayerPrivateMediaFoundation::hostWindow()
{
    if (m_player && m_player->cachedResourceLoader() && !m_player->cachedResourceLoader()->document()) {
        auto* view = m_player->cachedResourceLoader()->document()->view();
        if (view && view->hostWindow() && view->hostWindow()->platformPageClient())
            return view->hostWindow()->platformPageClient();
    }
    return GetDesktopWindow();
}

void MediaPlayerPrivateMediaFoundation::invalidateFrameView()
{
    FrameView* view = nullptr;
    if (!m_player || !m_player->cachedResourceLoader() || !m_player->cachedResourceLoader()->document())
        return;
    view = m_player->cachedResourceLoader()->document()->view();
    if (!view)
        return;

    view->invalidate();
}

void MediaPlayerPrivateMediaFoundation::addListener(MediaPlayerListener* listener)
{
    LockHolder locker(m_mutexListeners);

    m_listeners.add(listener);
}

void MediaPlayerPrivateMediaFoundation::removeListener(MediaPlayerListener* listener)
{
    LockHolder locker(m_mutexListeners);

    m_listeners.remove(listener);
}

void MediaPlayerPrivateMediaFoundation::notifyDeleted()
{
    LockHolder locker(m_mutexListeners);

    for (HashSet<MediaPlayerListener*>::const_iterator it = m_listeners.begin(); it != m_listeners.end(); ++it)
        (*it)->onMediaPlayerDeleted();
}

void MediaPlayerPrivateMediaFoundation::setNaturalSize(const FloatSize& size)
{
    LockHolder locker(m_cachedNaturalSizeLock);
    m_cachedNaturalSize = size;
}

bool MediaPlayerPrivateMediaFoundation::createOutputNode(COMPtr<IMFStreamDescriptor> sourceSD, COMPtr<IMFTopologyNode>& node)
{
    if (!sourceSD)
        return false;

#ifndef NDEBUG
    // Get the stream ID.
    DWORD streamID = 0;
    sourceSD->GetStreamIdentifier(&streamID); // Just for debugging, ignore any failures.
#endif

    COMPtr<IMFMediaTypeHandler> handler;
    if (FAILED(sourceSD->GetMediaTypeHandler(&handler)))
        return false;

    GUID guidMajorType = GUID_NULL;
    if (FAILED(handler->GetMajorType(&guidMajorType)))
        return false;

    // Create a downstream node.
    if (FAILED(MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node)))
        return false;

    // Create an IMFActivate object for the renderer, based on the media type.
    COMPtr<IMFActivate> rendererActivate;
    if (MFMediaType_Audio == guidMajorType) {
        // Create the audio renderer.
        if (FAILED(MFCreateAudioRendererActivate(&rendererActivate)))
            return false;
        m_hasAudio = true;
    } else if (MFMediaType_Video == guidMajorType) {
        // Create the video renderer.
        if (FAILED(MFCreateVideoRendererActivate(nullptr, &rendererActivate)))
            return false;

        m_presenter = new CustomVideoPresenter(this);
        m_presenter->SetVideoWindow(hostWindow());
        if (FAILED(rendererActivate->SetUnknown(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE, static_cast<IMFActivate*>(m_presenter.get()))))
            return false;
        m_hasVideo = true;
    } else
        return false;

    // Set the IActivate object on the output node.
    if (FAILED(node->SetObject(rendererActivate.get())))
        return false;

    return true;
}

bool MediaPlayerPrivateMediaFoundation::createSourceStreamNode(COMPtr<IMFStreamDescriptor> sourceSD, COMPtr<IMFTopologyNode>& node)
{
    if (!m_mediaSource || !m_sourcePD || !sourceSD)
        return false;

    // Create the source-stream node.
    HRESULT hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
    if (FAILED(hr))
        return false;

    // Set attribute: Pointer to the media source.
    hr = node->SetUnknown(MF_TOPONODE_SOURCE, m_mediaSource.get());
    if (FAILED(hr))
        return false;

    // Set attribute: Pointer to the presentation descriptor.
    hr = node->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, m_sourcePD.get());
    if (FAILED(hr))
        return false;

    // Set attribute: Pointer to the stream descriptor.
    hr = node->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, sourceSD.get());
    if (FAILED(hr))
        return false;

    return true;
}

void MediaPlayerPrivateMediaFoundation::updateReadyState()
{
    COMPtr<IPropertyStore> prop;

    // Get the property store from the media session.
    HRESULT hr = MFGetService(m_mediaSession.get(), MFNETSOURCE_STATISTICS_SERVICE, IID_PPV_ARGS(&prop));

    if (FAILED(hr))
        return;

    PROPERTYKEY key;
    key.fmtid = MFNETSOURCE_STATISTICS;
    key.pid = MFNETSOURCE_BUFFERPROGRESS_ID;

    PROPVARIANT var;
    hr = prop->GetValue(key, &var);

    const LONG percentageOfPlaybackBufferFilled = var.lVal;

    PropVariantClear(&var);

    if (FAILED(hr))
        return;

    MediaPlayer::ReadyState oldReadyState = m_readyState;
    if (percentageOfPlaybackBufferFilled >= 100) {
        m_readyState = MediaPlayer::HaveEnoughData;
        if (m_preparingToPlay) {
            pause();
            m_preparingToPlay = false;
        }
    } else if (percentageOfPlaybackBufferFilled > 0)
        m_readyState = MediaPlayer::HaveFutureData;
    else
        m_readyState = MediaPlayer::HaveCurrentData;

    if (m_readyState != oldReadyState)
        m_player->readyStateChanged();
}

COMPtr<IMFVideoDisplayControl> MediaPlayerPrivateMediaFoundation::videoDisplay()
{
    if (m_videoDisplay)
        return m_videoDisplay;

    MFGetService(m_mediaSession.get(), MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&m_videoDisplay));

    return m_videoDisplay;
}

void MediaPlayerPrivateMediaFoundation::onCreatedMediaSource()
{
    if (!createTopologyFromSource())
        return;

    // Set the topology on the media session.
    HRESULT hr = m_mediaSession->SetTopology(0, m_topology.get());
    ASSERT_UNUSED(hr, SUCCEEDED(hr));
}

void MediaPlayerPrivateMediaFoundation::onTopologySet()
{
    // This method is called on the main thread as a result of load() being called.

    if (auto videoDisplay = this->videoDisplay()) {
        RECT rc = { 0, 0, m_size.width(), m_size.height() };
        videoDisplay->SetVideoPosition(nullptr, &rc);
    }

    // It is expected that we start buffering data from the network now.
    // We call startSession() to start buffering video data.
    // When we have received enough data, we pause, so that we don't actually start the playback.
    ASSERT(m_paused);
    ASSERT(!m_preparingToPlay);
    m_preparingToPlay = startSession();
}

void MediaPlayerPrivateMediaFoundation::onBufferingStarted()
{
    updateReadyState();
}

void MediaPlayerPrivateMediaFoundation::onBufferingStopped()
{
    updateReadyState();
}

void MediaPlayerPrivateMediaFoundation::onSessionStarted()
{
    updateReadyState();
}

void MediaPlayerPrivateMediaFoundation::onSessionEnded()
{
    m_networkState = MediaPlayer::Loaded;
    m_player->networkStateChanged();

    m_paused = true;
    m_player->playbackStateChanged();
}

MediaPlayerPrivateMediaFoundation::AsyncCallback::AsyncCallback(MediaPlayerPrivateMediaFoundation* mediaPlayer, bool event)
    : m_refCount(0)
    , m_mediaPlayer(mediaPlayer)
    , m_event(event)
{
    if (m_mediaPlayer)
        m_mediaPlayer->addListener(this);
}

MediaPlayerPrivateMediaFoundation::AsyncCallback::~AsyncCallback()
{
    if (m_mediaPlayer)
        m_mediaPlayer->removeListener(this);
}

HRESULT MediaPlayerPrivateMediaFoundation::AsyncCallback::QueryInterface(_In_ REFIID riid, __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject)
{
    if (!ppvObject)
        return E_POINTER;
    if (!IsEqualGUID(riid, IID_IMFAsyncCallback)) {
        *ppvObject = nullptr;
        return E_NOINTERFACE;
    }
    *ppvObject = this;
    AddRef();
    return S_OK;
}

ULONG STDMETHODCALLTYPE MediaPlayerPrivateMediaFoundation::AsyncCallback::AddRef()
{
    m_refCount++;
    return m_refCount;
}

ULONG STDMETHODCALLTYPE MediaPlayerPrivateMediaFoundation::AsyncCallback::Release()
{
    m_refCount--;
    ULONG refCount = m_refCount;
    if (!refCount)
        delete this;
    return refCount;
}

HRESULT STDMETHODCALLTYPE MediaPlayerPrivateMediaFoundation::AsyncCallback::GetParameters(__RPC__out DWORD *pdwFlags, __RPC__out DWORD *pdwQueue)
{
    // Returning E_NOTIMPL gives default values.
    return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE MediaPlayerPrivateMediaFoundation::AsyncCallback::Invoke(__RPC__in_opt IMFAsyncResult *pAsyncResult)
{
    LockHolder locker(m_mutex);

    if (!m_mediaPlayer)
        return S_OK;

    if (m_event)
        m_mediaPlayer->endGetEvent(pAsyncResult);
    else
        m_mediaPlayer->endCreatedMediaSource(pAsyncResult);

    return S_OK;
}

void MediaPlayerPrivateMediaFoundation::AsyncCallback::onMediaPlayerDeleted()
{
    LockHolder locker(m_mutex);

    m_mediaPlayer = nullptr;
}

MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::CustomVideoPresenter(MediaPlayerPrivateMediaFoundation* mediaPlayer)
    : m_mediaPlayer(mediaPlayer)
{
    if (m_mediaPlayer)
        m_mediaPlayer->addListener(this);

    m_sourceRect.top = 0;
    m_sourceRect.left = 0;
    m_sourceRect.bottom = 1;
    m_sourceRect.right = 1;

    m_presenterEngine = makeUnique<Direct3DPresenter>();
    if (!m_presenterEngine)
        return;

    m_scheduler.setPresenter(m_presenterEngine.get());
}

MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::~CustomVideoPresenter()
{
    if (m_mediaPlayer)
        m_mediaPlayer->removeListener(this);
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::QueryInterface(REFIID riid, __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject)
{
    *ppvObject = nullptr;
    if (IsEqualGUID(riid, IID_IMFGetService))
        *ppvObject = static_cast<IMFGetService*>(this);
    else if (IsEqualGUID(riid, IID_IMFActivate))
        *ppvObject = static_cast<IMFActivate*>(this);
    else if (IsEqualGUID(riid, IID_IMFVideoDisplayControl))
        *ppvObject = static_cast<IMFVideoDisplayControl*>(this);
    else if (IsEqualGUID(riid, IID_IMFVideoPresenter))
        *ppvObject = static_cast<IMFVideoPresenter*>(this);
    else if (IsEqualGUID(riid, IID_IMFClockStateSink))
        *ppvObject = static_cast<IMFClockStateSink*>(this);
    else if (IsEqualGUID(riid, IID_IMFVideoDeviceID))
        *ppvObject = static_cast<IMFVideoDeviceID*>(this);
    else if (IsEqualGUID(riid, IID_IMFTopologyServiceLookupClient))
        *ppvObject = static_cast<IMFTopologyServiceLookupClient*>(this);
    else if (IsEqualGUID(riid, IID_IUnknown))
        *ppvObject = static_cast<IMFVideoPresenter*>(this);
    else if (IsEqualGUID(riid, IID_IMFAsyncCallback))
        *ppvObject = static_cast<IMFAsyncCallback*>(this);
    else
        return E_NOINTERFACE;

    AddRef();
    return S_OK;
}

ULONG MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::AddRef()
{
    m_refCount++;
    return m_refCount;
}

ULONG MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::Release()
{
    m_refCount--;
    ULONG refCount = m_refCount;
    if (!refCount)
        delete this;
    return refCount;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset)
{
    LockHolder locker(m_lock);

    // After shutdown, we cannot start.
    HRESULT hr = checkShutdown();
    if (FAILED(hr))
        return hr;

    m_renderState = RenderStateStarted;

    if (isActive()) {
        if (llClockStartOffset != PRESENTATION_CURRENT_POSITION) {
            // This is a seek request, flush pending samples.
            flush();
        }
    }

    processOutputLoop();

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::OnClockStop(MFTIME hnsSystemTime)
{
    LockHolder locker(m_lock);

    HRESULT hr = checkShutdown();
    if (FAILED(hr))
        return hr;

    if (m_renderState != RenderStateStopped) {
        m_renderState = RenderStateStopped;
        flush();
    }

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::OnClockPause(MFTIME hnsSystemTime)
{
    LockHolder locker(m_lock);

    // After shutdown, we cannot pause.
    HRESULT hr = checkShutdown();
    if (FAILED(hr))
        return hr;

    m_renderState = RenderStatePaused;

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::OnClockRestart(MFTIME hnsSystemTime)
{
    LockHolder locker(m_lock);

    HRESULT hr = checkShutdown();
    if (FAILED(hr))
        return hr;

    ASSERT(m_renderState == RenderStatePaused);

    m_renderState = RenderStateStarted;

    processOutputLoop();

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::OnClockSetRate(MFTIME hnsSystemTime, float rate)
{
    LockHolder locker(m_lock);

    HRESULT hr = checkShutdown();
    if (FAILED(hr))
        return hr;

    m_rate = rate;

    m_scheduler.setClockRate(rate);

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::ProcessMessage(MFVP_MESSAGE_TYPE eMessage, ULONG_PTR ulParam)
{
    LockHolder locker(m_lock);

    HRESULT hr = checkShutdown();
    if (FAILED(hr))
        return hr;

    switch (eMessage) {
    case MFVP_MESSAGE_FLUSH:
        hr = flush();
        break;

    case MFVP_MESSAGE_INVALIDATEMEDIATYPE:
        hr = renegotiateMediaType();
        break;

    case MFVP_MESSAGE_PROCESSINPUTNOTIFY:
        // A new input sample is available. 
        hr = processInputNotify();
        break;

    case MFVP_MESSAGE_BEGINSTREAMING:
        hr = beginStreaming();
        break;

    case MFVP_MESSAGE_ENDSTREAMING:
        hr = endStreaming();
        break;

    case MFVP_MESSAGE_ENDOFSTREAM:
        m_endStreaming = true;
        hr = checkEndOfStream();
        break;

    default:
        hr = E_INVALIDARG;
        break;
    }

    return hr;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::GetCurrentMediaType(_Outptr_  IMFVideoMediaType **ppMediaType)
{
    LockHolder locker(m_lock);

    if (!ppMediaType)
        return E_POINTER;

    HRESULT hr = checkShutdown();
    if (FAILED(hr))
        return hr;

    if (!m_mediaType)
        return MF_E_NOT_INITIALIZED;

    return m_mediaType->QueryInterface(__uuidof(IMFVideoMediaType), (void**)&ppMediaType);
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::GetDeviceID(IID* pDeviceID)
{
    if (!pDeviceID)
        return E_POINTER;

    *pDeviceID = __uuidof(IDirect3DDevice9);
    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::InitServicePointers(IMFTopologyServiceLookup *pLookup)
{
    if (!pLookup)
        return E_POINTER;

    HRESULT hr = S_OK;

    LockHolder locker(m_lock);

    if (isActive())
        return MF_E_INVALIDREQUEST;

    m_clock = nullptr;
    m_mixer = nullptr;
    m_mediaEventSink = nullptr;

    // Lookup the services.

    DWORD objectCount = 1;
    hr = pLookup->LookupService(MF_SERVICE_LOOKUP_GLOBAL, 0, MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&m_clock), &objectCount);
    // The clock service is optional.

    objectCount = 1;
    hr = pLookup->LookupService(MF_SERVICE_LOOKUP_GLOBAL, 0, MR_VIDEO_MIXER_SERVICE, IID_PPV_ARGS(&m_mixer), &objectCount);
    if (FAILED(hr))
        return hr;

    hr = configureMixer(m_mixer.get());
    if (FAILED(hr))
        return hr;

    objectCount = 1;
    hr = pLookup->LookupService(MF_SERVICE_LOOKUP_GLOBAL, 0, MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&m_mediaEventSink), &objectCount);
    if (FAILED(hr))
        return hr;

    m_renderState = RenderStateStopped;

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::ReleaseServicePointers()
{
    LockHolder locker(m_lock);

    m_renderState = RenderStateShutdown;

    flush();

    setMediaType(nullptr);

    m_clock = nullptr;
    m_mixer = nullptr;
    m_mediaEventSink = nullptr;

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::GetService(REFGUID guidService, REFIID riid, LPVOID* ppvObject)
{
    if (!ppvObject)
        return E_POINTER;

    // We only support MR_VIDEO_RENDER_SERVICE.
    if (guidService != MR_VIDEO_RENDER_SERVICE)
        return MF_E_UNSUPPORTED_SERVICE;

    HRESULT hr = m_presenterEngine->getService(guidService, riid, ppvObject);

    if (FAILED(hr))
        hr = QueryInterface(riid, ppvObject);

    return hr;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::ActivateObject(REFIID riid, void **ppv)
{
    if (!ppv)
        return E_POINTER;

    if (riid == IID_IMFVideoPresenter) {
        *ppv = static_cast<IMFVideoPresenter*>(this);
        AddRef();
        return S_OK;
    }
    return E_FAIL;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::DetachObject()
{
    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::ShutdownObject()
{
    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::SetVideoWindow(HWND hwndVideo)
{
    LockHolder locker(m_lock);

    if (!IsWindow(hwndVideo))
        return E_INVALIDARG;

    HRESULT hr = S_OK;
    HWND oldHwnd = m_presenterEngine->getVideoWindow();

    if (oldHwnd != hwndVideo) {
        // This will create a new Direct3D device.
        hr = m_presenterEngine->setVideoWindow(hwndVideo);

        notifyEvent(EC_DISPLAY_CHANGED, 0, 0);
    }

    return hr;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::GetVideoWindow(HWND* phwndVideo)
{
    LockHolder locker(m_lock);

    if (!phwndVideo)
        return E_POINTER;

    *phwndVideo = m_presenterEngine->getVideoWindow();

    return S_OK;
}

static HRESULT setMixerSourceRect(IMFTransform* mixer, const MFVideoNormalizedRect& sourceRect)
{
    if (!mixer)
        return E_POINTER;

    COMPtr<IMFAttributes> attributes;

    HRESULT hr = mixer->GetAttributes(&attributes);
    if (FAILED(hr))
        return hr;

    return attributes->SetBlob(VIDEO_ZOOM_RECT, (const UINT8*)&sourceRect, sizeof(sourceRect));
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::SetVideoPosition(const MFVideoNormalizedRect* pnrcSource, const LPRECT prcDest)
{
    LockHolder locker(m_lock);

    // First, check that the parameters are valid.

    if (!pnrcSource && !prcDest)
        return E_POINTER;

    if (pnrcSource) {
        if ((pnrcSource->left > pnrcSource->right) || (pnrcSource->top > pnrcSource->bottom))
            return E_INVALIDARG;

        // The source rectangle must be normalized.
        if ((pnrcSource->left < 0) || (pnrcSource->right > 1) || (pnrcSource->top < 0) || (pnrcSource->bottom > 1))
            return E_INVALIDARG;
    }

    if (prcDest) {
        if ((prcDest->left > prcDest->right) || (prcDest->top > prcDest->bottom))
            return E_INVALIDARG;
    }

    HRESULT hr = S_OK;

    // Set the source rectangle.
    if (pnrcSource) {
        m_sourceRect = *pnrcSource;

        if (m_mixer) {
            hr = setMixerSourceRect(m_mixer.get(), m_sourceRect);
            if (FAILED(hr))
                return hr;
        }
    }

    // Set the destination rectangle.
    if (prcDest) {
        RECT rcOldDest = m_presenterEngine->getDestinationRect();

        // If the destination rectangle hasn't changed, we are done.
        if (!EqualRect(&rcOldDest, prcDest)) {
            hr = m_presenterEngine->setDestinationRect(*prcDest);
            if (FAILED(hr))
                return hr;

            // We need to change the media type when the destination rectangle has changed.
            if (m_mixer) {
                hr = renegotiateMediaType();
                if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
                    // This is not a critical failure; the EVR will let us know when
                    // we have to set the mixer media type.
                    hr = S_OK;
                } else {
                    if (FAILED(hr))
                        return hr;

                    // We have successfully changed the media type,
                    // ask for a repaint of the current frame.
                    m_repaint = true;
                    processOutput();
                }
            }
        }
    }

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::GetVideoPosition(MFVideoNormalizedRect* pnrcSource, LPRECT prcDest)
{
    LockHolder locker(m_lock);

    if (!pnrcSource || !prcDest)
        return E_POINTER;

    *pnrcSource = m_sourceRect;
    *prcDest = m_presenterEngine->getDestinationRect();

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::RepaintVideo()
{
    LockHolder locker(m_lock);

    HRESULT hr = checkShutdown();
    if (FAILED(hr))
        return hr;

    // Check that at least one sample has been presented.
    if (m_prerolled) {
        m_repaint = true;
        processOutput();
    }

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::Invoke(IMFAsyncResult* pAsyncResult)
{
    return onSampleFree(pAsyncResult);
}

void MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::onMediaPlayerDeleted()
{
    m_mediaPlayer = nullptr;
}

void MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::paintCurrentFrame(GraphicsContext& context, const FloatRect& r)
{
    if (m_presenterEngine)
        m_presenterEngine->paintCurrentFrame(context, r);
}

float MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::currentTime()
{
    if (!m_clock)
        return 0.0f;

    LONGLONG clockTime;
    MFTIME systemTime;
    HRESULT hr = m_clock->GetCorrelatedTime(0, &clockTime, &systemTime);

    if (FAILED(hr))
        return 0.0f;

    // clockTime is in 100 nanoseconds, we need to convert to seconds.
    float currentTime = clockTime / tenMegahertz;

    if (currentTime > m_maxTimeLoaded)
        m_maxTimeLoaded = currentTime;

    return currentTime;
}

bool MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::isActive() const
{
    return ((m_renderState == RenderStateStarted) || (m_renderState == RenderStatePaused));
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::configureMixer(IMFTransform* mixer)
{
    COMPtr<IMFVideoDeviceID> videoDeviceID;
    HRESULT hr = mixer->QueryInterface(__uuidof(IMFVideoDeviceID), (void**)&videoDeviceID);
    if (FAILED(hr))
        return hr;

    IID deviceID = GUID_NULL;
    hr = videoDeviceID->GetDeviceID(&deviceID);
    if (FAILED(hr))
        return hr;

    // The mixer must have this device ID.
    if (!IsEqualGUID(deviceID, __uuidof(IDirect3DDevice9)))
        return MF_E_INVALIDREQUEST;

    setMixerSourceRect(mixer, m_sourceRect);

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::flush()
{
    m_prerolled = false;

    // Flush the sceduler.
    // This call will block until the scheduler thread has finished flushing.
    m_scheduler.flush();

    if (m_renderState == RenderStateStopped)
        m_presenterEngine->presentSample(nullptr, 0);

    return S_OK;
}

static bool areMediaTypesEqual(IMFMediaType* type1, IMFMediaType* type2)
{
    if (!type1 && !type2)
        return true;
    if (!type1 || !type2)
        return false;

    DWORD flags = 0;
    return S_OK == type1->IsEqual(type2, &flags);
}

static FloatSize calculateNaturalSize(IMFMediaType* mediaType)
{
    UINT32 width = 0, height = 0;
    HRESULT hr = MFGetAttributeSize(mediaType, MF_MT_FRAME_SIZE, &width, &height);
    if (FAILED(hr) || !height)
        return FloatSize();

    UINT32 pixelAspectRatioNumerator = 0;
    UINT32 pixelAspectRatioDenominator = 0;
    hr = MFGetAttributeRatio(mediaType, MF_MT_PIXEL_ASPECT_RATIO, &pixelAspectRatioNumerator, &pixelAspectRatioDenominator);
    if (SUCCEEDED(hr) && pixelAspectRatioNumerator && pixelAspectRatioDenominator)
        return FloatSize(float(width) * pixelAspectRatioNumerator / pixelAspectRatioDenominator, height);

    return FloatSize();
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::setMediaType(IMFMediaType* mediaType)
{
    if (!mediaType) {
        m_mediaType = nullptr;
        releaseResources();
        return S_OK;
    }

    // If we have shut down, we cannot set the media type.
    HRESULT hr = checkShutdown();
    if (FAILED(hr)) {
        releaseResources();
        return hr;
    }

    if (areMediaTypesEqual(m_mediaType.get(), mediaType))
        return S_OK;

    m_mediaType = nullptr;
    releaseResources();

    // Get allocated samples from the presenter.
    VideoSampleList sampleQueue;
    hr = m_presenterEngine->createVideoSamples(mediaType, sampleQueue);
    if (FAILED(hr)) {
        releaseResources();
        return hr;
    }

    // Set the token counter on each sample.
    // This will help us to determine when they are invalid, and can be released.
    for (auto sample : sampleQueue) {
        hr = sample->SetUINT32(MFSamplePresenterSampleCounter, m_tokenCounter);
        if (FAILED(hr)) {
            releaseResources();
            return hr;
        }
    }

    // Add the samples to the sample pool.
    hr = m_samplePool.initialize(sampleQueue);
    if (FAILED(hr)) {
        releaseResources();
        return hr;
    }

    // Set the frame rate. 
    MFRatio fps = { 0, 0 };
    hr = MFGetAttributeRatio(mediaType, MF_MT_FRAME_RATE, (UINT32*)&fps.Numerator, (UINT32*)&fps.Denominator);
    if (SUCCEEDED(hr) && fps.Numerator && fps.Denominator)
        m_scheduler.setFrameRate(fps);
    else {
        // We could not get the frame ret, use default.
        const MFRatio defaultFrameRate = { 30, 1 };
        m_scheduler.setFrameRate(defaultFrameRate);
    }

    // Update natural size
    if (m_mediaPlayer)
        m_mediaPlayer->setNaturalSize(calculateNaturalSize(mediaType));

    ASSERT(mediaType);
    m_mediaType = mediaType;

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::checkShutdown() const
{
    if (m_renderState == RenderStateShutdown)
        return MF_E_SHUTDOWN;
    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::renegotiateMediaType()
{
    HRESULT hr = S_OK;

    if (!m_mixer)
        return MF_E_INVALIDREQUEST;

    // Iterate over the available output types of the mixer.

    DWORD typeIndex = 0;
    bool foundMediaType = false;
    while (!foundMediaType && (hr != MF_E_NO_MORE_TYPES)) {
        // Get the next available media type.
        COMPtr<IMFMediaType> mixerType;
        hr = m_mixer->GetOutputAvailableType(0, typeIndex++, &mixerType);
        if (FAILED(hr))
            break;

        // Do we support this media type?
        hr = isMediaTypeSupported(mixerType.get());
        if (FAILED(hr))
            break;

        // Make adjustments to proposed media type.
        COMPtr<IMFMediaType> optimalType;
        hr = createOptimalVideoType(mixerType.get(), &optimalType);
        if (FAILED(hr))
            break;

        // Test whether the mixer can accept the modified media type
        hr = m_mixer->SetOutputType(0, optimalType.get(), MFT_SET_TYPE_TEST_ONLY);
        if (FAILED(hr))
            break;

        // Try to set the new media type

        hr = setMediaType(optimalType.get());
        if (FAILED(hr))
            break;

        hr = m_mixer->SetOutputType(0, optimalType.get(), 0);

        ASSERT(SUCCEEDED(hr));

        if (FAILED(hr))
            setMediaType(nullptr);
        else
            foundMediaType = true;
    }

    return hr;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::processInputNotify()
{
    // We have a new sample.
    m_sampleNotify = true;

    if (!m_mediaType) {
        // The media type is not valid.
        return MF_E_TRANSFORM_TYPE_NOT_SET;
    } 
    
    // Invalidate the video area
    if (m_mediaPlayer) {
        callOnMainThread([weakPtr = m_mediaPlayer->m_weakThis] {
            if (weakPtr)
                weakPtr->invalidateFrameView();
        });
    }

    // Process sample
    processOutputLoop();

    return S_OK;
}

static float MFOffsetToFloat(const MFOffset& offset)
{
    const int denominator = std::numeric_limits<WORD>::max() + 1;
    return offset.value + (float(offset.fract) / denominator);
}

static MFOffset MakeOffset(float v)
{
    // v = offset.value + (offset.fract / denominator), where denominator = 65536.0f.
    const int denominator = std::numeric_limits<WORD>::max() + 1;
    MFOffset offset;
    offset.value = short(v);
    offset.fract = WORD(denominator * (v - offset.value));
    return offset;
}

static MFVideoArea MakeArea(float x, float y, DWORD width, DWORD height)
{
    MFVideoArea area;
    area.OffsetX = MakeOffset(x);
    area.OffsetY = MakeOffset(y);
    area.Area.cx = width;
    area.Area.cy = height;
    return area;
}

static HRESULT validateVideoArea(const MFVideoArea& area, UINT32 width, UINT32 height)
{
    float fOffsetX = MFOffsetToFloat(area.OffsetX);
    float fOffsetY = MFOffsetToFloat(area.OffsetY);

    if (((LONG)fOffsetX + area.Area.cx > width) || ((LONG)fOffsetY + area.Area.cy > height))
        return MF_E_INVALIDMEDIATYPE;
    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::beginStreaming()
{
    return m_scheduler.startScheduler(m_clock.get());
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::endStreaming()
{
    return m_scheduler.stopScheduler();
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::checkEndOfStream()
{
    if (!m_endStreaming) {
        // We have not received the end-of-stream message from the EVR.
        return S_OK;
    }

    if (m_sampleNotify) {
        // There is still input samples available for the mixer. 
        return S_OK;
    }

    if (m_samplePool.areSamplesPending()) {
        // There are samples scheduled for rendering.
        return S_OK;
    }

    // We are done, notify the EVR.
    notifyEvent(EC_COMPLETE, (LONG_PTR)S_OK, 0);
    m_endStreaming = false;
    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::isMediaTypeSupported(IMFMediaType* mediaType)
{
    COMPtr<IMFMediaType> proposedVideoType = mediaType;

    // We don't support compressed media types.
    BOOL compressed = FALSE;
    HRESULT hr = proposedVideoType->IsCompressedFormat(&compressed);
    if (FAILED(hr))
        return hr;
    if (compressed)
        return MF_E_INVALIDMEDIATYPE;

    // Validate the format.
    GUID guidSubType = GUID_NULL;
    hr = proposedVideoType->GetGUID(MF_MT_SUBTYPE, &guidSubType);
    if (FAILED(hr))
        return hr;
    D3DFORMAT d3dFormat = (D3DFORMAT)guidSubType.Data1;

    // Check if the format can be used as backbuffer format.
    hr = m_presenterEngine->checkFormat(d3dFormat);
    if (FAILED(hr))
        return hr;

    // Check interlaced formats.
    MFVideoInterlaceMode interlaceMode = MFVideoInterlace_Unknown;
    hr = proposedVideoType->GetUINT32(MF_MT_INTERLACE_MODE, (UINT32*)&interlaceMode);
    if (FAILED(hr))
        return hr;

    if (interlaceMode != MFVideoInterlace_Progressive)
        return MF_E_INVALIDMEDIATYPE;

    UINT32 width = 0, height = 0;
    hr = MFGetAttributeSize(proposedVideoType.get(), MF_MT_FRAME_SIZE, &width, &height);
    if (FAILED(hr))
        return hr;

    // Validate apertures.
    MFVideoArea videoCropArea;
    if (SUCCEEDED(proposedVideoType->GetBlob(MF_MT_PAN_SCAN_APERTURE, (UINT8*)&videoCropArea, sizeof(MFVideoArea), nullptr)))
        validateVideoArea(videoCropArea, width, height);
    if (SUCCEEDED(proposedVideoType->GetBlob(MF_MT_GEOMETRIC_APERTURE, (UINT8*)&videoCropArea, sizeof(MFVideoArea), nullptr)))
        validateVideoArea(videoCropArea, width, height);
    if (SUCCEEDED(proposedVideoType->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE, (UINT8*)&videoCropArea, sizeof(MFVideoArea), nullptr)))
        validateVideoArea(videoCropArea, width, height);
    
    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::createOptimalVideoType(IMFMediaType* proposedType, IMFMediaType** optimalType)
{
    COMPtr<IMFMediaType> optimalVideoType;
    HRESULT hr = MFCreateMediaType(&optimalVideoType);
    if (FAILED(hr))
        return hr;
    hr = optimalVideoType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
    if (FAILED(hr))
        return hr;

    hr = proposedType->CopyAllItems(optimalVideoType.get());
    if (FAILED(hr))
        return hr;

    // We now modify the new media type.

    // We assume that the monitor's pixel aspect ratio is 1:1,
    // and that the pixel aspect ratio is preserved by the presenter.
    hr = MFSetAttributeRatio(optimalVideoType.get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
    if (FAILED(hr))
        return hr;

    // Get the output rectangle.
    RECT rcOutput = m_presenterEngine->getDestinationRect();
    if (IsRectEmpty(&rcOutput)) {
        hr = calculateOutputRectangle(proposedType, rcOutput);
        if (FAILED(hr))
            return hr;
    }

    hr = optimalVideoType->SetUINT32(MF_MT_YUV_MATRIX, MFVideoTransferMatrix_BT709);
    if (FAILED(hr))
        return hr;

    hr = optimalVideoType->SetUINT32(MF_MT_TRANSFER_FUNCTION, MFVideoTransFunc_709);
    if (FAILED(hr))
        return hr;

    hr = optimalVideoType->SetUINT32(MF_MT_VIDEO_PRIMARIES, MFVideoPrimaries_BT709);
    if (FAILED(hr))
        return hr;

    hr = optimalVideoType->SetUINT32(MF_MT_VIDEO_NOMINAL_RANGE, MFNominalRange_16_235);
    if (FAILED(hr))
        return hr;

    hr = optimalVideoType->SetUINT32(MF_MT_VIDEO_LIGHTING, MFVideoLighting_dim);
    if (FAILED(hr))
        return hr;

    hr = MFSetAttributeSize(optimalVideoType.get(), MF_MT_FRAME_SIZE, rcOutput.right, rcOutput.bottom);
    if (FAILED(hr))
        return hr;

    MFVideoArea displayArea = MakeArea(0, 0, rcOutput.right, rcOutput.bottom);

    hr = optimalVideoType->SetUINT32(MF_MT_PAN_SCAN_ENABLED, FALSE);
    if (FAILED(hr))
        return hr;

    hr = optimalVideoType->SetBlob(MF_MT_GEOMETRIC_APERTURE, (UINT8*)&displayArea, sizeof(MFVideoArea));
    if (FAILED(hr))
        return hr;

    hr = optimalVideoType->SetBlob(MF_MT_PAN_SCAN_APERTURE, (UINT8*)&displayArea, sizeof(MFVideoArea));
    if (FAILED(hr))
        return hr;

    hr = optimalVideoType->SetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE, (UINT8*)&displayArea, sizeof(MFVideoArea));
    if (FAILED(hr))
        return hr;

    *optimalType = optimalVideoType.leakRef();

    return S_OK;
}

static RECT correctAspectRatio(const RECT& src, const MFRatio& srcPAR, const MFRatio& destPAR)
{
    RECT rc = { 0, 0, src.right - src.left, src.bottom - src.top };

    if ((srcPAR.Numerator * destPAR.Denominator) != (srcPAR.Denominator * destPAR.Numerator)) {
        // The source and destination aspect ratios are different

        // Transform the source aspect ratio to 1:1
        if (srcPAR.Numerator > srcPAR.Denominator)
            rc.right = MulDiv(rc.right, srcPAR.Numerator, srcPAR.Denominator);
        else if (srcPAR.Numerator < srcPAR.Denominator)
            rc.bottom = MulDiv(rc.bottom, srcPAR.Denominator, srcPAR.Numerator);


        // Transform to destination aspect ratio.
        if (destPAR.Numerator > destPAR.Denominator)
            rc.bottom = MulDiv(rc.bottom, destPAR.Numerator, destPAR.Denominator);
        else if (destPAR.Numerator < destPAR.Denominator)
            rc.right = MulDiv(rc.right, destPAR.Denominator, destPAR.Numerator);

    }

    return rc;
}

static HRESULT GetVideoDisplayArea(IMFMediaType* type, MFVideoArea* area)
{
    if (!type || !area)
        return E_POINTER;

    HRESULT hr = S_OK;
    UINT32 width = 0, height = 0;

    BOOL bPanScan = MFGetAttributeUINT32(type, MF_MT_PAN_SCAN_ENABLED, FALSE);

    if (bPanScan)
        hr = type->GetBlob(MF_MT_PAN_SCAN_APERTURE, (UINT8*)area, sizeof(MFVideoArea), nullptr);

    if (!bPanScan || hr == MF_E_ATTRIBUTENOTFOUND) {
        hr = type->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE, (UINT8*)area, sizeof(MFVideoArea), nullptr);

        if (hr == MF_E_ATTRIBUTENOTFOUND)
            hr = type->GetBlob(MF_MT_GEOMETRIC_APERTURE, (UINT8*)area, sizeof(MFVideoArea), nullptr);

        if (hr == MF_E_ATTRIBUTENOTFOUND) {
            hr = MFGetAttributeSize(type, MF_MT_FRAME_SIZE, &width, &height);
            if (SUCCEEDED(hr))
                *area = MakeArea(0.0, 0.0, width, height);
        }
    }

    return hr;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::calculateOutputRectangle(IMFMediaType* proposedType, RECT& outputRect)
{
    COMPtr<IMFMediaType> proposedVideoType = proposedType;

    UINT32 srcWidth = 0, srcHeight = 0;
    HRESULT hr = MFGetAttributeSize(proposedVideoType.get(), MF_MT_FRAME_SIZE, &srcWidth, &srcHeight);
    if (FAILED(hr))
        return hr;

    MFVideoArea displayArea;
    ZeroMemory(&displayArea, sizeof(displayArea));

    hr = GetVideoDisplayArea(proposedVideoType.get(), &displayArea);
    if (FAILED(hr))
        return hr;

    LONG offsetX = (LONG)MFOffsetToFloat(displayArea.OffsetX);
    LONG offsetY = (LONG)MFOffsetToFloat(displayArea.OffsetY);

    // Check if the display area is valid.
    // If it is valid, we use it. If not, we use the frame dimensions.

    RECT rcOutput;

    if (displayArea.Area.cx != 0
        && displayArea.Area.cy != 0
        && offsetX + displayArea.Area.cx <= srcWidth
        && offsetY + displayArea.Area.cy <= srcHeight) {
        rcOutput.left = offsetX;
        rcOutput.right = offsetX + displayArea.Area.cx;
        rcOutput.top = offsetY;
        rcOutput.bottom = offsetY + displayArea.Area.cy;
    } else {
        rcOutput.left = 0;
        rcOutput.top = 0;
        rcOutput.right = srcWidth;
        rcOutput.bottom = srcHeight;
    }

    // Correct aspect ratio.

    MFRatio inputPAR = { 1, 1 };
    MFRatio outputPAR = { 1, 1 }; // We assume the monitor's pixels are square.
    MFGetAttributeRatio(proposedVideoType.get(), MF_MT_PIXEL_ASPECT_RATIO, (UINT32*)&inputPAR.Numerator, (UINT32*)&inputPAR.Denominator);
    outputRect = correctAspectRatio(rcOutput, inputPAR, outputPAR);

    return S_OK;
}

void MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::processOutputLoop()
{
    // Get video frames from the mixer and schedule them for presentation.
    HRESULT hr = S_OK;

    while (hr == S_OK) {
        if (!m_sampleNotify) {
            // Currently no more input samples.
            hr = MF_E_TRANSFORM_NEED_MORE_INPUT;
            break;
        }

        // We break from the loop if we fail to process a sample.
        hr = processOutput();
    }

    if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
        checkEndOfStream();
}

static HRESULT setDesiredSampleTime(IMFSample* sample, const LONGLONG& sampleTime, const LONGLONG& duration)
{
    // To tell the mixer to give us an earlier frame for repainting, we can set the desired sample time.
    // We have to clear the desired sample time before reusing the sample.

    if (!sample)
        return E_POINTER;

    COMPtr<IMFDesiredSample> desired;

    HRESULT hr = sample->QueryInterface(__uuidof(IMFDesiredSample), (void**)&desired);

    if (SUCCEEDED(hr))
        desired->SetDesiredSampleTimeAndDuration(sampleTime, duration);

    return hr;
}

static HRESULT clearDesiredSampleTime(IMFSample* sample)
{
    if (!sample)
        return E_POINTER;

    // We need to retrieve some attributes we have set on the sample before we call 
    // IMFDesiredSample::Clear(), and set them once more, since they are cleared by
    // the Clear() call.

    UINT32 counter = MFGetAttributeUINT32(sample, MFSamplePresenterSampleCounter, (UINT32)-1);

    COMPtr<IMFDesiredSample> desired;
    HRESULT hr = sample->QueryInterface(__uuidof(IMFDesiredSample), (void**)&desired);
    if (SUCCEEDED(hr)) {
        desired->Clear();

        hr = sample->SetUINT32(MFSamplePresenterSampleCounter, counter);
        if (FAILED(hr))
            return hr;
    }

    return hr;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::processOutput()
{
    // This method will try to get a new sample from the mixer.
    // It is called when the mixer has a new sample, or when repainting the last frame.

    ASSERT(m_sampleNotify || m_repaint);

    LONGLONG mixerStartTime = 0, mixerEndTime = 0;
    MFTIME systemTime = 0;
    bool repaint = m_repaint;  

    // If the clock has not started, we only present the first sample. 

    if ((m_renderState != RenderStateStarted) && !m_repaint && m_prerolled)
        return S_FALSE;

    if (!m_mixer)
        return MF_E_INVALIDREQUEST;

    // Get a free sample from the pool.
    COMPtr<IMFSample> sample;
    HRESULT hr = m_samplePool.getSample(sample);
    if (hr == MF_E_SAMPLEALLOCATOR_EMPTY)
        return S_FALSE; // We will try again later when there are free samples

    if (FAILED(hr))
        return hr;

    ASSERT(sample);

    ASSERT(MFGetAttributeUINT32(sample.get(), MFSamplePresenterSampleCounter, (UINT32)-1) == m_tokenCounter);

    if (m_repaint) {
        // Get the most recent sample from the mixer.
        setDesiredSampleTime(sample.get(), m_scheduler.lastSampleTime(), m_scheduler.frameDuration());
        m_repaint = false;
    } else {
        // Clear the desired sample time to get the next sample in the stream.
        clearDesiredSampleTime(sample.get());

        if (m_clock) {
            // Get the starting time of the ProcessOutput call.
            m_clock->GetCorrelatedTime(0, &mixerStartTime, &systemTime);
        }
    }

    // Get a sample from the mixer. 
    MFT_OUTPUT_DATA_BUFFER dataBuffer;
    ZeroMemory(&dataBuffer, sizeof(dataBuffer));

    dataBuffer.dwStreamID = 0;
    dataBuffer.pSample = sample.get();
    dataBuffer.dwStatus = 0;

    DWORD status = 0;
    hr = m_mixer->ProcessOutput(0, 1, &dataBuffer, &status);

    // Release events. There are usually no events returned,
    // but in case there are, we should release them.
    if (dataBuffer.pEvents)
        dataBuffer.pEvents->Release();

    if (FAILED(hr)) {
        HRESULT hr2 = m_samplePool.returnSample(sample.get());
        if (FAILED(hr2))
            return hr2;

        if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) {
            // The media type has not been set, renegotiate.
            hr = renegotiateMediaType();
        } else if (hr == MF_E_TRANSFORM_STREAM_CHANGE) {
            // The media type changed, reset it.
            setMediaType(nullptr);
        } else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
            // The mixer needs more input.
            m_sampleNotify = false;
        }
    } else {
        // We have got a sample from the mixer.

        if (m_clock && !repaint) {
            // Notify the EVR about latency.
            m_clock->GetCorrelatedTime(0, &mixerEndTime, &systemTime);

            LONGLONG latencyTime = mixerEndTime - mixerStartTime;
            notifyEvent(EC_PROCESSING_LATENCY, (LONG_PTR)&latencyTime, 0);
        }

        // Make sure we are notified when the sample is released
        hr = trackSample(sample.get());
        if (FAILED(hr))
            return hr;

        // Deliver the sample for scheduling
        hr = deliverSample(sample.get(), repaint);
        if (FAILED(hr))
            return hr;

        // At least one sample has been presented now.
        m_prerolled = true;
    }

    return hr;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::deliverSample(IMFSample* sample, bool repaint)
{
    if (!sample)
        return E_POINTER;

    Direct3DPresenter::DeviceState state = Direct3DPresenter::DeviceOK;

    // Determine if the sample should be presented immediately.
    bool presentNow = ((m_renderState != RenderStateStarted) || isScrubbing() || repaint);

    HRESULT hr = m_presenterEngine->checkDeviceState(state);

    if (SUCCEEDED(hr))
        hr = m_scheduler.scheduleSample(sample, presentNow);

    if (FAILED(hr)) {
        // Streaming has failed, notify the EVR.
        notifyEvent(EC_ERRORABORT, hr, 0);
    } else if (state == Direct3DPresenter::DeviceReset)
        notifyEvent(EC_DISPLAY_CHANGED, S_OK, 0);

    return hr;
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::trackSample(IMFSample* sample)
{
    if (!sample)
        return E_POINTER;

    COMPtr<IMFTrackedSample> tracked;

    HRESULT hr = sample->QueryInterface(__uuidof(IMFTrackedSample), (void**)&tracked);
    if (FAILED(hr))
        return hr;

    if (!tracked)
        return E_POINTER;

    // Set callback object on which the onSampleFree method is invoked when the sample is no longer used.
    return tracked->SetAllocator(this, nullptr);
}

void MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::releaseResources()
{
    // The token counter is incremented to indicate that existing samples are
    // invalid and can be disposed in the method onSampleFree.
    m_tokenCounter++;

    flush();

    m_samplePool.clear();

    if (m_presenterEngine)
        m_presenterEngine->releaseResources();
}

HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::onSampleFree(IMFAsyncResult* result)
{
    if (!result)
        return E_POINTER;

    COMPtr<IUnknown> object;
    HRESULT hr = result->GetObject(&object);
    if (FAILED(hr)) {
        notifyEvent(EC_ERRORABORT, hr, 0);
        return hr;
    }

    COMPtr<IMFSample> sample;
    hr = object->QueryInterface(__uuidof(IMFSample), (void**)&sample);
    if (FAILED(hr)) {
        notifyEvent(EC_ERRORABORT, hr, 0);
        return hr;
    }

    m_lock.lock();

    if (MFGetAttributeUINT32(sample.get(), MFSamplePresenterSampleCounter, (UINT32)-1) == m_tokenCounter) {
        hr = m_samplePool.returnSample(sample.get());

        // Do more processing, since a free sample is available
        if (SUCCEEDED(hr))
            processOutputLoop();
    }

    m_lock.unlock();

    if (FAILED(hr))
        notifyEvent(EC_ERRORABORT, hr, 0);

    return hr;
}

void MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::notifyEvent(long EventCode, LONG_PTR Param1, LONG_PTR Param2)
{
    if (m_mediaEventSink)
        m_mediaEventSink->Notify(EventCode, Param1, Param2);
}

HRESULT MediaPlayerPrivateMediaFoundation::VideoSamplePool::getSample(COMPtr<IMFSample>& sample)
{
    LockHolder locker(m_lock);

    if (!m_initialized)
        return MF_E_NOT_INITIALIZED;

    if (m_videoSampleQueue.isEmpty())
        return MF_E_SAMPLEALLOCATOR_EMPTY;

    sample = m_videoSampleQueue.takeFirst();

    m_pending++;

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::VideoSamplePool::returnSample(IMFSample* sample)
{
    if (!sample)
        return E_POINTER;

    LockHolder locker(m_lock);

    if (!m_initialized)
        return MF_E_NOT_INITIALIZED;

    m_videoSampleQueue.append(sample);
    m_pending--;
    return S_OK;
}

bool MediaPlayerPrivateMediaFoundation::VideoSamplePool::areSamplesPending()
{
    LockHolder locker(m_lock);

    if (!m_initialized)
        return FALSE;

    return (m_pending > 0);
}

HRESULT MediaPlayerPrivateMediaFoundation::VideoSamplePool::initialize(VideoSampleList& samples)
{
    LockHolder locker(m_lock);

    if (m_initialized)
        return MF_E_INVALIDREQUEST;

    // Copy the samples
    for (auto sample : samples)
        m_videoSampleQueue.append(sample);

    m_initialized = true;
    samples.clear();

    return S_OK;
}

void MediaPlayerPrivateMediaFoundation::VideoSamplePool::clear()
{
    LockHolder locker(m_lock);

    m_videoSampleQueue.clear();
    m_initialized = false;
    m_pending = 0;
}


// Scheduler thread messages.

enum ScheduleEvent {
    EventTerminate = WM_USER,
    EventSchedule,
    EventFlush
};

void MediaPlayerPrivateMediaFoundation::VideoScheduler::setFrameRate(const MFRatio& fps)
{
    UINT64 avgTimePerFrame = 0;
    MFFrameRateToAverageTimePerFrame(fps.Numerator, fps.Denominator, &avgTimePerFrame);

    m_frameDuration = (MFTIME)avgTimePerFrame;
}

HRESULT MediaPlayerPrivateMediaFoundation::VideoScheduler::startScheduler(IMFClock* clock)
{
    if (m_schedulerThread.isValid())
        return E_UNEXPECTED;

    HRESULT hr = S_OK;

    m_clock = clock;

    // Use high timer resolution.
    timeBeginPeriod(1);

    // Create an event to signal that the scheduler thread has started.
    m_threadReadyEvent = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);
    if (!m_threadReadyEvent.isValid())
        return HRESULT_FROM_WIN32(GetLastError());

    // Create an event to signal that the flush has completed.
    m_flushEvent = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);
    if (!m_flushEvent.isValid())
        return HRESULT_FROM_WIN32(GetLastError());

    // Start scheduler thread.
    DWORD threadID = 0;
    m_schedulerThread = ::CreateThread(nullptr, 0, schedulerThreadProc, (LPVOID)this, 0, &threadID);
    if (!m_schedulerThread.isValid())
        return HRESULT_FROM_WIN32(GetLastError());

    HANDLE hObjects[] = { m_threadReadyEvent.get(), m_schedulerThread.get() };

    // Wait for the thread to start
    DWORD result = ::WaitForMultipleObjects(2, hObjects, FALSE, INFINITE);
    if (WAIT_OBJECT_0 != result) {
        // The thread has terminated.
        m_schedulerThread.clear();
        return E_UNEXPECTED;
    }

    m_threadID = threadID;

    return hr;
}

HRESULT MediaPlayerPrivateMediaFoundation::VideoScheduler::stopScheduler()
{
    if (!m_schedulerThread.isValid())
        return S_OK;

    // Terminate the scheduler thread
    stopThread();
    ::PostThreadMessage(m_threadID, EventTerminate, 0, 0);

    // Wait for the scheduler thread to finish.
    ::WaitForSingleObject(m_schedulerThread.get(), INFINITE);

    LockHolder locker(m_lock);

    m_scheduledSamples.clear();
    m_schedulerThread.clear();
    m_flushEvent.clear();

    // Clear previously set timer resolution.
    timeEndPeriod(1);

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::VideoScheduler::flush()
{
    // This method will wait for the flush to finish on the worker thread.

    if (m_schedulerThread.isValid()) {
        ::PostThreadMessage(m_threadID, EventFlush, 0, 0);

        HANDLE objects[] = { m_flushEvent.get(), m_schedulerThread.get() };

        const int schedulerTimeout = 5000;

        // Wait for the flush to finish or the thread to terminate.
        ::WaitForMultipleObjects(2, objects, FALSE, schedulerTimeout);
    }

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::VideoScheduler::scheduleSample(IMFSample* sample, bool presentNow)
{
    if (!sample)
        return E_POINTER;

    if (!m_presenter)
        return MF_E_NOT_INITIALIZED;

    if (!m_schedulerThread.isValid())
        return MF_E_NOT_INITIALIZED;

    DWORD exitCode = 0;
    ::GetExitCodeThread(m_schedulerThread.get(), &exitCode);

    if (exitCode != STILL_ACTIVE)
        return E_FAIL;

    if (presentNow || !m_clock)
        m_presenter->presentSample(sample, 0);
    else {
        // Submit the sample for scheduling.
        LockHolder locker(m_lock);
        m_scheduledSamples.append(sample);

        ::PostThreadMessage(m_threadID, EventSchedule, 0, 0);
    }

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::VideoScheduler::processSamplesInQueue(LONG& nextSleep)
{
    HRESULT hr = S_OK;
    LONG wait = 0;

    // Process samples as long as there are samples in the queue, and they have not arrived too early.

    while (!m_exitThread) {
        COMPtr<IMFSample> sample;

        if (true) {
            LockHolder locker(m_lock);
            if (m_scheduledSamples.isEmpty())
                break;
            sample = m_scheduledSamples.takeFirst();
        }

        // Process the sample.
        // If the sample has arrived too early, wait will be > 0,
        // and the scheduler should go to sleep.
        hr = processSample(sample.get(), wait);

        if (FAILED(hr))
            break;

        if (wait > 0)
            break;
    }

    if (!wait) {
        // The queue is empty. Sleep until the next message arrives.
        wait = INFINITE;
    }

    nextSleep = wait;
    return hr;
}

// MFTimeToMilliseconds: Convert 100-nanosecond time to milliseconds.
static LONG MFTimeToMilliseconds(const LONGLONG& time)
{
    return (time / 10000);
}

HRESULT MediaPlayerPrivateMediaFoundation::VideoScheduler::processSample(IMFSample* sample, LONG& nextSleep)
{
    if (!sample)
        return E_POINTER;

    HRESULT hr = S_OK;

    LONGLONG presentationTime = 0;
    LONGLONG timeNow = 0;
    MFTIME systemTime = 0;

    bool presentNow = true;
    LONG nextSleepTime = 0;

    if (m_clock) {
        // Get the time stamp of the sample.
        // A sample can possibly have no time stamp.
        hr = sample->GetSampleTime(&presentationTime);

        // Get the clock time.
        // If the sample does not have a time stamp, the clock time is not needed.
        if (SUCCEEDED(hr))
            hr = m_clock->GetCorrelatedTime(0, &timeNow, &systemTime);

        // Determine the time until the sample should be presented.
        // Samples arriving late, will have negative values.
        LONGLONG timeDelta = presentationTime - timeNow;
        if (m_playbackRate < 0) {
            // Reverse delta for reverse playback.
            timeDelta = -timeDelta;
        }

        LONGLONG frameDurationOneFourth = m_frameDuration / 4;

        if (timeDelta < -frameDurationOneFourth) {
            // The sample has arrived late. 
            presentNow = true;
        } else if (timeDelta > (3 * frameDurationOneFourth)) {
            // We can sleep, the sample has arrived too early.
            nextSleepTime = MFTimeToMilliseconds(timeDelta - (3 * frameDurationOneFourth));

            // Since sleeping is using the system clock, we need to convert the sleep time
            // from presentation time to system time.
            nextSleepTime = (LONG)(nextSleepTime / fabsf(m_playbackRate));

            presentNow = false;
        }
    }

    if (presentNow)
        hr = m_presenter->presentSample(sample, presentationTime);
    else {
        // Return the sample to the queue, since it is not ready.
        LockHolder locker(m_lock);
        m_scheduledSamples.prepend(sample);
    }

    nextSleep = nextSleepTime;

    return hr;
}

DWORD WINAPI MediaPlayerPrivateMediaFoundation::VideoScheduler::schedulerThreadProc(LPVOID lpParameter)
{
    VideoScheduler* scheduler = reinterpret_cast<VideoScheduler*>(lpParameter);
    if (!scheduler)
        return static_cast<DWORD>(-1);
    return scheduler->schedulerThreadProcPrivate();
}

DWORD MediaPlayerPrivateMediaFoundation::VideoScheduler::schedulerThreadProcPrivate()
{
    HRESULT hr = S_OK;

    // This will force a message queue to be created for the thread.
    MSG msg;
    PeekMessage(&msg, nullptr, WM_USER, WM_USER, PM_NOREMOVE);

    // The thread is ready.
    SetEvent(m_threadReadyEvent.get());

    LONG wait = INFINITE;
    m_exitThread = false;
    while (!m_exitThread) {
        // Wait for messages
        DWORD result = MsgWaitForMultipleObjects(0, nullptr, FALSE, wait, QS_POSTMESSAGE);

        if (result == WAIT_TIMEOUT) {
            hr = processSamplesInQueue(wait);
            if (FAILED(hr))
                m_exitThread = true;
        }

        while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
            bool processSamples = true;

            switch (msg.message) {
            case EventTerminate:
                m_exitThread = true;
                break;

            case EventFlush:
                {
                    LockHolder lock(m_lock);
                    m_scheduledSamples.clear();
                }
                wait = INFINITE;
                SetEvent(m_flushEvent.get());
                break;

            case EventSchedule:
                if (processSamples) {
                    hr = processSamplesInQueue(wait);
                    if (FAILED(hr))
                        m_exitThread = true;
                    processSamples = (wait != INFINITE);
                }
                break;
            }
        }
    }
    return (SUCCEEDED(hr) ? 0 : 1);
}

static HRESULT findAdapter(IDirect3D9* direct3D9, HMONITOR monitor, UINT& adapterID)
{
    HRESULT hr = E_FAIL;

    UINT adapterCount = direct3D9->GetAdapterCount();
    for (UINT i = 0; i < adapterCount; i++) {
        HMONITOR monitorTmp = direct3D9->GetAdapterMonitor(i);

        if (!monitorTmp)
            break;

        if (monitorTmp == monitor) {
            adapterID = i;
            hr = S_OK;
            break;
        }
    }

    return hr;
}

MediaPlayerPrivateMediaFoundation::Direct3DPresenter::Direct3DPresenter()
{
    SetRectEmpty(&m_destRect);

    ZeroMemory(&m_displayMode, sizeof(m_displayMode));

    HRESULT hr = initializeD3D();

    if (FAILED(hr))
        return;

    createD3DDevice();
}

MediaPlayerPrivateMediaFoundation::Direct3DPresenter::~Direct3DPresenter() = default;

HRESULT MediaPlayerPrivateMediaFoundation::Direct3DPresenter::getService(REFGUID guidService, REFIID riid, void** ppv)
{
    ASSERT(ppv);

    HRESULT hr = S_OK;

    if (riid == __uuidof(IDirect3DDeviceManager9)) {
        if (!m_deviceManager)
            hr = MF_E_UNSUPPORTED_SERVICE;
        else {
            *ppv = m_deviceManager.get();
            m_deviceManager->AddRef();
        }
    } else
        hr = MF_E_UNSUPPORTED_SERVICE;

    return hr;
}

HRESULT MediaPlayerPrivateMediaFoundation::Direct3DPresenter::checkFormat(D3DFORMAT format)
{
    HRESULT hr = S_OK;

    UINT adapter = D3DADAPTER_DEFAULT;
    D3DDEVTYPE type = D3DDEVTYPE_HAL;

    if (m_device) {
        D3DDEVICE_CREATION_PARAMETERS params;
        hr = m_device->GetCreationParameters(&params);
        if (FAILED(hr))
            return hr;

        adapter = params.AdapterOrdinal;
        type = params.DeviceType;
    }

    D3DDISPLAYMODE mode;
    hr = m_direct3D9->GetAdapterDisplayMode(adapter, &mode);
    if (FAILED(hr))
        return hr;

    return m_direct3D9->CheckDeviceType(adapter, type, mode.Format, format, TRUE);
}

HRESULT MediaPlayerPrivateMediaFoundation::Direct3DPresenter::setVideoWindow(HWND hwnd)
{
    ASSERT(IsWindow(hwnd));
    ASSERT(hwnd != m_hwnd);

    {
        LockHolder locker(m_lock);
        m_hwnd = hwnd;
    }

    return createD3DDevice();
}

HRESULT MediaPlayerPrivateMediaFoundation::Direct3DPresenter::setDestinationRect(const RECT& rcDest)
{
    if (EqualRect(&rcDest, &m_destRect))
        return S_OK;

    LockHolder locker(m_lock);

    m_destRect = rcDest;

    return S_OK;
}

HRESULT MediaPlayerPrivateMediaFoundation::Direct3DPresenter::createVideoSamples(IMFMediaType* format, VideoSampleList& videoSampleQueue)
{
    // Create video samples matching the supplied format.
    // A swap chain with a single back buffer will be created for each video sample.
    // The mixer will render to the back buffer through a surface kept by the sample.
    // The surface can be rendered to a window by presenting the swap chain.
    // In our case the surface is transferred to system memory, and rendered to a graphics context.

    if (!m_hwnd)
        return MF_E_INVALIDREQUEST;

    if (!format)
        return MF_E_UNEXPECTED;


    LockHolder locker(m_lock);

    releaseResources();

    D3DPRESENT_PARAMETERS presentParameters;
    HRESULT hr = getSwapChainPresentParameters(format, &presentParameters);
    if (FAILED(hr)) {
        releaseResources();
        return hr;
    }

    static const int presenterBufferCount = 3;

    for (int i = 0; i < presenterBufferCount; i++) {
        COMPtr<IDirect3DSwapChain9> swapChain;
        hr = m_device->CreateAdditionalSwapChain(&presentParameters, &swapChain);
        if (FAILED(hr)) {
            releaseResources();
            return hr;
        }

        COMPtr<IMFSample> videoSample;
        hr = createD3DSample(swapChain.get(), videoSample);
        if (FAILED(hr)) {
            releaseResources();
            return hr;
        }

        videoSampleQueue.append(videoSample);
    }

    return hr;
}

void MediaPlayerPrivateMediaFoundation::Direct3DPresenter::releaseResources()
{
    m_surfaceRepaint = nullptr;
}

HRESULT MediaPlayerPrivateMediaFoundation::Direct3DPresenter::checkDeviceState(DeviceState& state)
{
    LockHolder locker(m_lock);

    HRESULT hr = m_device->CheckDeviceState(m_hwnd);

    state = DeviceOK;

    // Not all failure codes are critical.

    switch (hr) {
    case S_OK:
    case S_PRESENT_OCCLUDED:
    case S_PRESENT_MODE_CHANGED:
        hr = S_OK;
        break;

    case D3DERR_DEVICELOST:
    case D3DERR_DEVICEHUNG:
        hr = createD3DDevice();
        if (FAILED(hr))
            return hr;
        state = DeviceReset;
        hr = S_OK;
        break;

    case D3DERR_DEVICEREMOVED:
        state = DeviceRemoved;
        break;

    case E_INVALIDARG:
        // This might happen if the window has been destroyed, or is not valid.
        // A new device will be created if a new window is set.
        hr = S_OK;
    }

    return hr;
}

HRESULT MediaPlayerPrivateMediaFoundation::Direct3DPresenter::presentSample(IMFSample* sample, LONGLONG targetPresentationTime)
{
    HRESULT hr = S_OK;

    LockHolder locker(m_lock);

    COMPtr<IDirect3DSurface9> surface;

    if (sample) {
        COMPtr<IMFMediaBuffer> buffer;
        hr = sample->GetBufferByIndex(0, &buffer);
        hr = MFGetService(buffer.get(), MR_BUFFER_SERVICE, __uuidof(IDirect3DSurface9), (void**)&surface);
    } else if (m_surfaceRepaint) {
        // Use the last surface.
        surface = m_surfaceRepaint;
    }

    if (surface) {
        UINT width = m_destRect.right - m_destRect.left;
        UINT height = m_destRect.bottom - m_destRect.top;

        if (width > 0 && height > 0) {
            if (!m_memSurface || m_width != width || m_height != height) {
                D3DFORMAT format = D3DFMT_A8R8G8B8;
                D3DSURFACE_DESC desc;
                if (SUCCEEDED(surface->GetDesc(&desc)))
                    format = desc.Format;
                m_memSurface.clear();
                hr = m_device->CreateOffscreenPlainSurface(width, height, format, D3DPOOL_SYSTEMMEM, &m_memSurface, nullptr);
                m_width = width;
                m_height = height;
            }
            // Copy data from video memory to system memory
            hr = m_device->GetRenderTargetData(surface.get(), m_memSurface.get());
            if (FAILED(hr)) {
                m_memSurface = nullptr;
                hr = S_OK;
            }
        }

        // Keep the last surface for repaints.
        m_surfaceRepaint = surface;
    }

    if (FAILED(hr)) {
        if (hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET || hr == D3DERR_DEVICEHUNG) {
            // Ignore this error. We have to reset or recreate the device.
            // The presenter will handle this when checking the device state the next time.
            hr = S_OK;
        }
    }
    return hr;
}

void MediaPlayerPrivateMediaFoundation::Direct3DPresenter::paintCurrentFrame(WebCore::GraphicsContext& context, const WebCore::FloatRect& destRect)
{
    UINT width = m_destRect.right - m_destRect.left;
    UINT height = m_destRect.bottom - m_destRect.top;

    if (!width || !height)
        return;

    LockHolder locker(m_lock);

    if (!m_memSurface)
        return;

    D3DLOCKED_RECT lockedRect;
    if (SUCCEEDED(m_memSurface->LockRect(&lockedRect, nullptr, D3DLOCK_READONLY))) {
        void* data = lockedRect.pBits;
        int pitch = lockedRect.Pitch;
#if USE(CAIRO)
        D3DFORMAT format = D3DFMT_UNKNOWN;
        D3DSURFACE_DESC desc;
        if (SUCCEEDED(m_memSurface->GetDesc(&desc)))
            format = desc.Format;

        cairo_format_t cairoFormat = CAIRO_FORMAT_INVALID;

        switch (format) {
        case D3DFMT_A8R8G8B8:
            cairoFormat = CAIRO_FORMAT_ARGB32;
            break;
        case D3DFMT_X8R8G8B8:
            cairoFormat = CAIRO_FORMAT_RGB24;
            break;
        default:
            break;
        }

        ASSERT(cairoFormat != CAIRO_FORMAT_INVALID);

        cairo_surface_t* image = nullptr;
        if (cairoFormat != CAIRO_FORMAT_INVALID)
            image = cairo_image_surface_create_for_data(static_cast<unsigned char*>(data), cairoFormat, width, height, pitch);

        FloatRect srcRect(0, 0, width, height);
        if (image) {
            ASSERT(context.hasPlatformContext());
            auto& state = context.state();
            Cairo::drawSurface(*context.platformContext(), image, destRect, srcRect, state.imageInterpolationQuality, state.alpha, Cairo::ShadowState(state));
            cairo_surface_destroy(image);
        }
#else
#error "Platform needs to implement drawing of Direct3D surface to graphics context!"
#endif
        m_memSurface->UnlockRect();
    }
}

HRESULT MediaPlayerPrivateMediaFoundation::Direct3DPresenter::initializeD3D()
{
    ASSERT(!m_direct3D9);
    ASSERT(!m_deviceManager);

    HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &m_direct3D9);
    if (FAILED(hr))
        return hr;

    return DXVA2CreateDirect3DDeviceManager9(&m_deviceResetToken, &m_deviceManager);
}

HRESULT MediaPlayerPrivateMediaFoundation::Direct3DPresenter::createD3DDevice()
{
    HRESULT hr = S_OK;
    UINT adapterID = D3DADAPTER_DEFAULT;

    LockHolder locker(m_lock);

    if (!m_direct3D9 || !m_deviceManager)
        return MF_E_NOT_INITIALIZED;

    HWND hwnd = GetDesktopWindow();

    // We create additional swap chains to present the video frames,
    // and do not use the implicit swap chain of the device.
    // The size of the back buffer is 1 x 1.

    D3DPRESENT_PARAMETERS pp;
    ZeroMemory(&pp, sizeof(pp));

    pp.BackBufferWidth = 1;
    pp.BackBufferHeight = 1;
    pp.Windowed = TRUE;
    pp.SwapEffect = D3DSWAPEFFECT_COPY;
    pp.BackBufferFormat = D3DFMT_UNKNOWN;
    pp.hDeviceWindow = hwnd;
    pp.Flags = D3DPRESENTFLAG_VIDEO;
    pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;

    if (m_hwnd) {
        HMONITOR monitor = MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTONEAREST);

        hr = findAdapter(m_direct3D9.get(), monitor, adapterID);
        if (FAILED(hr))
            return hr;
    }

    D3DCAPS9 ddCaps;
    ZeroMemory(&ddCaps, sizeof(ddCaps));

    hr = m_direct3D9->GetDeviceCaps(adapterID, D3DDEVTYPE_HAL, &ddCaps);
    if (FAILED(hr))
        return hr;

    DWORD flags = D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE;

    if (ddCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
        flags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
    else
        flags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    COMPtr<IDirect3DDevice9Ex> device;
    hr = m_direct3D9->CreateDeviceEx(adapterID, D3DDEVTYPE_HAL, pp.hDeviceWindow, flags, &pp, nullptr, &device);
    if (FAILED(hr))
        return hr;

    hr = m_direct3D9->GetAdapterDisplayMode(adapterID, &m_displayMode);
    if (FAILED(hr))
        return hr;

    hr = m_deviceManager->ResetDevice(device.get(), m_deviceResetToken);
    if (FAILED(hr))
        return hr;

    m_device = device;

    return hr;
}

HRESULT MediaPlayerPrivateMediaFoundation::Direct3DPresenter::createD3DSample(IDirect3DSwapChain9* swapChain, COMPtr<IMFSample>& videoSample)
{
    COMPtr<IDirect3DSurface9> surface;
    HRESULT hr = swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &surface);
    if (FAILED(hr))
        return hr;

    D3DCOLOR colorBlack = D3DCOLOR_ARGB(0xFF, 0x00, 0x00, 0x00);
    hr = m_device->ColorFill(surface.get(), nullptr, colorBlack);
    if (FAILED(hr))
        return hr;

    return MFCreateVideoSampleFromSurface(surface.get(), &videoSample);
}

HRESULT MediaPlayerPrivateMediaFoundation::Direct3DPresenter::getSwapChainPresentParameters(IMFMediaType* type, D3DPRESENT_PARAMETERS* presentParams)
{
    if (!m_hwnd)
        return MF_E_INVALIDREQUEST;

    COMPtr<IMFMediaType> videoType = type;

    UINT32 width = 0, height = 0;
    HRESULT hr = MFGetAttributeSize(videoType.get(), MF_MT_FRAME_SIZE, &width, &height);
    if (FAILED(hr))
        return hr;

    GUID guidSubType = GUID_NULL;
    hr = videoType->GetGUID(MF_MT_SUBTYPE, &guidSubType);
    if (FAILED(hr))
        return hr;

    DWORD d3dFormat = guidSubType.Data1;

    ZeroMemory(presentParams, sizeof(D3DPRESENT_PARAMETERS));
    presentParams->BackBufferWidth = width;
    presentParams->BackBufferHeight = height;
    presentParams->Windowed = TRUE;
    presentParams->SwapEffect = D3DSWAPEFFECT_COPY;
    presentParams->BackBufferFormat = (D3DFORMAT)d3dFormat;
    presentParams->hDeviceWindow = m_hwnd;
    presentParams->Flags = D3DPRESENTFLAG_VIDEO;
    presentParams->PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;

    D3DDEVICE_CREATION_PARAMETERS params;
    hr = m_device->GetCreationParameters(&params);
    if (FAILED(hr))
        return hr;

    if (params.DeviceType != D3DDEVTYPE_HAL)
        presentParams->Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;

    return S_OK;
}

} // namespace WebCore

#endif
