#include <windows.h>
#include <wchar.h>

#include "kbmf_player.h"
#include "kbmov_config.h"
#include "../../../kpi_decoder/kbwma/source/kpifile_stream.h"

#pragma comment(lib, "mfplat.lib")
#pragma comment(lib, "mf.lib")
#pragma comment(lib, "evr.lib")
#pragma comment(lib, "strmiids.lib")
#pragma comment(lib, "mfuuid.lib")

//
//Windows XP で動作するようにするため MFPlat.dll と MF.dll を遅延ロードする
//(「リンカー」->「入力」->「DLL の遅延読み込み」)
//使用する API が増えると遅延ロードすべき DLL が増える可能性あり
//
///////////////////////////////////////////////////////////////////////////////
bool KbMFPlayer::s_bInitialized = false;
///////////////////////////////////////////////////////////////////////////////
bool __fastcall KbMFPlayer::Initialize(void)
{//XP で Media Foundation の API を呼ばないように OS チェック
    if (!s_bInitialized) {
        if(CheckVistaOrLater()){
            MFStartup(MF_VERSION);
            s_bInitialized = true;
        }
    }
    return s_bInitialized;
}
///////////////////////////////////////////////////////////////////////////////
void __fastcall KbMFPlayer::Uninitialize(void)
{
    if (s_bInitialized) {
        MFShutdown();
        s_bInitialized = false;
    }
}
///////////////////////////////////////////////////////////////////////////////
KbMFPlayer::KbMFPlayer(void)
    :KbMovPlayerBase()
{
    m_pMediaSession = NULL;
    m_pMediaSource = NULL;
    m_pTopology = NULL;
    m_pVideoDisplayControl = NULL;
    m_pPresentationClock = NULL;
    m_hMFEvent = NULL;
}
///////////////////////////////////////////////////////////////////////////////
KbMFPlayer::~KbMFPlayer(void)
{
    if (m_hThread) {
        SendCommand(COMMAND_QUIT, 0, 0);
        WaitForSingleObject(m_hThread, INFINITE);
        CloseHandle(m_hThread);
        m_hThread = NULL;
    }
    if(m_hMFEvent)CloseHandle(m_hMFEvent);
}
///////////////////////////////////////////////////////////////////////////////
DWORD __fastcall KbMFPlayer::Open(IKpiConfig *pConfig, IKpiFile *pFile, IKpiFolder *pFolder)
{
    if (!Initialize()) {//XP では MF 使用不可
        return 0;
    }
    m_hMFEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    return KbMovPlayerBase::Open(pConfig, pFile, pFolder);
}
/////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK KbMFPlayer::VideoWindowProcInternal(HWND hWnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam)
{
    if(hWnd == m_hWndDraw){
        if(message != WM_PAINT){
            return KbMovPlayerBase::VideoWindowProcInternal(hWnd, message, wParam, lParam);
        }
    }
    switch (message) {
    case WM_SIZE:{
        if (m_pVideoDisplayControl) {
            double ratio = (double)m_MediaInfo.dwVideoWidth / (double)m_MediaInfo.dwVideoHeight;
            int cx = LOWORD(lParam);
            int cy = HIWORD(lParam);
            int new_cx = cx;
            int new_cy = (double)cx / ratio;
            if (new_cy > cy) {
                new_cy = cy;
                new_cx = (double)cy * ratio;
            }
            RECT rc;
            rc.left = (cx - new_cx) / 2;
            rc.top = (cy - new_cy) / 2;
            rc.right = rc.left + new_cx;
            rc.bottom = rc.top + new_cy;
            MoveWindow(m_hWndDraw, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, false/*TRUE*/);
            rc.left = rc.top = 0;
            rc.right = new_cx;
            rc.bottom = new_cy;
            m_pVideoDisplayControl->SetVideoPosition(NULL, &rc);
        }
        break;
    }
    case WM_PAINT:{
        if(m_pVideoDisplayControl){
            m_pVideoDisplayControl->RepaintVideo();
        }
        break;
    }
    default:
        break;
    }
    return KbMovPlayerBase::VideoWindowProcInternal(hWnd, message, wParam, lParam);
}
/////////////////////////////////////////////////////////////////////////
void  __fastcall KbMFPlayer::ThreadProc(void)
{//DirectShow 関係のオブジェクトの作成・メソッド呼び出し・破棄は
 //全てこのスレッド内で行うようにする

    IKpiFile* pFile = m_pFile;
    IKpiConfig* pConfig = m_pConfig;

    KbMov_Settings settings;
    kbmov_GetSettings(pConfig, &settings);
    m_bFullScreen = settings.bFullScreen;
    IMFSourceResolver *pSourceResolver = NULL;
    do {
        HRESULT hr = MFCreateMediaSession(NULL, &m_pMediaSession);
        if(!m_pMediaSession)break;
        hr = m_pMediaSession->BeginGetEvent(this, NULL);
        MFCreateSourceResolver(&pSourceResolver);
        if(!pSourceResolver)break;
        MF_OBJECT_TYPE object_type = MF_OBJECT_INVALID;

        IUnknown* pObj = NULL;
        if(1){
            KbKpiFileStream* pStream = new KbKpiFileStream(pFile);
            IMFByteStream *pByteStream = NULL;
            MFCreateMFByteStreamOnStream(pStream, &pByteStream);
            pStream->Release();
            if (!pByteStream) {
                break;
            }
            wchar_t szFileName[MAX_PATH];
            pFile->GetFileName(szFileName, sizeof(szFileName));
            //CreateObjectFromByteStream の第2引数にファイル名を渡す(拡張子を渡す)
            pSourceResolver->CreateObjectFromByteStream(pByteStream, szFileName, MF_RESOLUTION_MEDIASOURCE,
                NULL,
                &object_type,
                &pObj);
            pByteStream->Release();
        }
        /*else{
            const wchar_t *cszFileName = NULL;
            pFile->GetRealFileW(&cszFileName);
            hr = pSourceResolver->CreateObjectFromURL(
                cszFileName,
                MF_RESOLUTION_MEDIASOURCE,
                NULL,
                &object_type,
                &pObj);
        }*/
        if(!pObj){
            break;
        }
        pObj->QueryInterface(IID_IMFMediaSource, (void**)&m_pMediaSource);
        pObj->Release();
        pSourceResolver->Release();
        if(!m_pMediaSource){
            break;
        }
        MFCreateTopology(&m_pTopology);
        if (!m_pTopology)break;
        IMFPresentationDescriptor *pPresentationDescriptor = NULL;
        m_pMediaSource->CreatePresentationDescriptor(&pPresentationDescriptor);
        if(!pPresentationDescriptor)break;
        {
            IMFClock *pClock = NULL;
            m_pMediaSession->GetClock(&pClock);
            if (pClock) {
                pClock->QueryInterface(IID_IMFPresentationClock, (void**)&m_pPresentationClock);
                pClock->Release();
            }
        }
        DWORD dwStreamCount = 0;
        pPresentationDescriptor->GetStreamDescriptorCount(&dwStreamCount);
        // 各ストリームごとに、ノードを作成する
        for (DWORD i = 0; i < dwStreamCount; i++) {
            IMFStreamDescriptor *pStreamDescriptor = NULL;
            BOOL bSelected = FALSE;
            hr = pPresentationDescriptor->GetStreamDescriptorByIndex(i, &bSelected, &pStreamDescriptor);
            if (bSelected) {
                IMFActivate *pSinkActivate = NULL;
                hr = CreateMediaSinkActivate(pStreamDescriptor, &pSinkActivate);
                if (SUCCEEDED(hr)) {
                    IMFTopologyNode *pSourceNode = NULL;
                    IMFTopologyNode *pOutputNode = NULL;
                    AddSourceNode(pPresentationDescriptor, pStreamDescriptor, &pSourceNode);
                    AddOutputNode(pSinkActivate, &pOutputNode);
                    if(pSourceNode && pOutputNode)pSourceNode->ConnectOutput(0, pOutputNode, 0);
                    if(pOutputNode)pOutputNode->Release();
                    if(pSourceNode)pSourceNode->Release();
                }
                if(pSinkActivate)pSinkActivate->Release();
            }
            if(pStreamDescriptor)pStreamDescriptor->Release();
        }
        ResetEvent(m_hMFEvent);
        m_pMediaSession->SetTopology(0, m_pTopology);
        WaitForSingleObject(m_hMFEvent, INFINITE);
        UINT64 qwDuration = 0;
        pPresentationDescriptor->GetUINT64(MF_PD_DURATION, &qwDuration);//曲長
        pPresentationDescriptor->Release();
        m_MediaInfo.dwSampleRate = 0;
        m_MediaInfo.dwChannels = 0;
        m_MediaInfo.nBitsPerSample = 0;
        m_MediaInfo.dwSeekableFlags = KPI_MEDIAINFO::SEEK_FLAGS_ROUGH;
        m_MediaInfo.dwUnitSample = 0;
        m_MediaInfo.qwLength = qwDuration;
        m_MediaInfo.dwCount = 1;
        MessageLoop();
        //後始末
        //作成も破棄もこのスレッド内で行う
        if(m_pPresentationClock){
            m_pPresentationClock->Release(); m_pPresentationClock = NULL;
        }
        if(m_pVideoDisplayControl){
            m_pVideoDisplayControl->Release(); m_pVideoDisplayControl = NULL;
        }
        if(m_pTopology){
            m_pTopology->Release(); m_pTopology = NULL;
        }
        if(m_pMediaSource) {
            m_pMediaSource->Release(); m_pMediaSource = NULL;
        }
        if(m_pMediaSession) {
            m_pMediaSession->Release(); m_pMediaSession = NULL;
        }
        if(m_hWnd) {
            DestroyWindow(m_hWnd);m_hWnd = NULL;
        }
        return;
    } while (0);
    if (m_pPresentationClock) {
        m_pPresentationClock->Release(); m_pPresentationClock = NULL;
    }
    if (m_pVideoDisplayControl) {
        m_pVideoDisplayControl->Release(); m_pVideoDisplayControl = NULL;
    }
    if (m_pTopology) {
        m_pTopology->Release(); m_pTopology = NULL;
    }
    if (m_pMediaSource) {
        m_pMediaSource->Release(); m_pMediaSource = NULL;
    }
    if (m_pMediaSession) {
        m_pMediaSession->Release(); m_pMediaSession = NULL;
    }
    kpi_InitMediaInfo(&m_MediaInfo);
}
/////////////////////////////////////////////////////////////////////////
void __fastcall KbMFPlayer::MessageLoop(void)
{
    HANDLE hHandles[] = {m_hEvent};
    DWORD dwWait;
    MSG msg;
    PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
    SetEvent(m_hEventDone);
    while(1){
        if (m_hWnd) {
            dwWait = MsgWaitForMultipleObjects(1, hHandles, FALSE, INFINITE, QS_ALLINPUT);
            if (dwWait == WAIT_OBJECT_0 + 1) {
                if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                    if (msg.message == WM_QUIT) {
                        break;
                    }
                }
                continue;
            }
        }
        else {
            dwWait = WaitForSingleObject(m_hEvent, INFINITE);
        }
        switch (m_Command.nCommand) {
        case COMMAND_CREATEWINDOW: {
            if (m_hWnd) {
                if(!m_pVideoDisplayControl){
                    MFGetService(m_pMediaSession, MR_VIDEO_RENDER_SERVICE,
                        __uuidof(IMFVideoDisplayControl), (void**)&m_pVideoDisplayControl);
                    if (m_pVideoDisplayControl) {
                        m_pVideoDisplayControl->SetVideoWindow(m_hWndDraw);
                        m_pVideoDisplayControl->SetAspectRatioMode(MFVideoARMode_PreservePicture);
                    }
                }
            }
            SetEvent(m_hEventDone);
            break;
        }//COMMAND_CREATEWINDOW
        case COMMAND_STOP: {
            if(m_nStatus != KPI_STATUS_STOP){
                ResetEvent(m_hMFEvent);
                m_pMediaSession->Stop();
                m_pMediaSession->BeginGetEvent(this, NULL);
                WaitForSingleObject(m_hMFEvent, INFINITE);
            }
            SetEvent(m_hEventDone);
            break;
        }
        case COMMAND_PAUSE: {
            ResetEvent(m_hMFEvent);
            m_pMediaSession->Pause();
            WaitForSingleObject(m_hMFEvent, INFINITE);
            //m_nStatus = KPI_STATUS_PAUSE;
            SetEvent(m_hEventDone);
            break;
        }
        case COMMAND_RESTART: {
            PROPVARIANT varStart = {0};
            varStart.vt = VT_EMPTY;
            ResetEvent(m_hMFEvent);
            m_pMediaSession->Start(NULL, &varStart);
            WaitForSingleObject(m_hMFEvent, INFINITE);
            //m_nStatus = KPI_STATUS_PLAYING;
            SetEvent(m_hEventDone);
            break;
        }
        case COMMAND_RUN: {
            DWORD dwStartPos = m_Command.wParam;
            BOOL bVisible = m_Command.lParam && m_MediaInfo.dwVideoWidth > 0 && m_MediaInfo.dwVideoHeight > 0;
            SetVisible(bVisible);
            m_nStatus = KPI_STATUS_PLAYING;
            PROPVARIANT varStart = {0};
            varStart.vt = VT_I8;
            varStart.hVal.QuadPart = (INT64)dwStartPos * 10000;
            ResetEvent(m_hMFEvent);
            m_pMediaSession->Start(NULL, &varStart);
            m_pMediaSession->BeginGetEvent(this, NULL);
            WaitForSingleObject(m_hMFEvent, INFINITE);
            SetEvent(m_hEventDone);
            break;
        }//run
        case COMMAND_QUIT: {
            if(m_pMediaSession){
                ResetEvent(m_hMFEvent);
                if(!FAILED(m_pMediaSession->Close())){
                    WaitForSingleObject(m_hMFEvent, INFINITE);
                }
                m_pMediaSource->Shutdown();
                m_pMediaSession->Shutdown();
            }
            if (m_hWnd) {
                SendMessage(m_hWnd, WM_CLOSE, 0, 0);
                if (m_pVideoDisplayControl) {
                    m_pVideoDisplayControl->SetVideoWindow(NULL);
                    m_pVideoDisplayControl->Release();
                    m_pVideoDisplayControl = NULL;
                }
                DestroyWindow(m_hWndDraw); m_hWndDraw = NULL;
                DestroyWindow(m_hWnd); m_hWnd = NULL;
            }
            return;
            //PostQuitMessage(0);
            break;
        }//quit
#if 0
        case COMMAND_GET_STATUS: {//必要なし
            if (m_pPresentationClock) {
                MFCLOCK_STATE state;
                m_pPresentationClock->GetState(0, &state);
                switch(state){
                    case MFCLOCK_STATE_RUNNING: m_nStatus = KPI_STATUS_PLAYING;break;
                    case MFCLOCK_STATE_STOPPED: m_nStatus = KPI_STATUS_STOP; break;
                    case MFCLOCK_STATE_PAUSED: m_nStatus = KPI_STATUS_PAUSE; break;
                    default:break;
                }
            }            
            SetEvent(m_hEventDone);
            break;
        }
#endif
        case COMMAND_GET_POSITION: {
            DWORD* pdwPos = (DWORD*)m_Command.wParam;
            DWORD dwPos = 0;
            if(m_pPresentationClock){
                MFTIME mftime = 0;
                m_pPresentationClock->GetTime(&mftime);
                dwPos = mftime / 10000;
            }
            *pdwPos = dwPos;
            SetEvent(m_hEventDone);
            break;
        }
        case COMMAND_GET_VIDEOPOS: {
            RECT* prc = (RECT*)m_Command.wParam;
            int nLeft, nTop, nWidth, nHeight;
            GetVideoPos(&nLeft, &nTop, &nWidth, &nHeight);
            prc->left = nLeft;
            prc->top = nTop;
            prc->right = nLeft + nWidth;
            prc->bottom = nTop + nHeight;
            SetEvent(m_hEventDone);
            break;
        };
        case COMMAND_SET_VIDEOPOS: {
            RECT* prc = (RECT*)m_Command.wParam;
            bool bTopMost = m_Command.lParam != 0;
            int nLeft = prc->left;
            int nTop = prc->top;
            int nWidth = prc->right - prc->left;
            int nHeight = prc->bottom - prc->top;
            UpdateWindowPosition(nLeft, nTop, nWidth, nHeight, bTopMost);
            SetEvent(m_hEventDone);
            break;
        }
        case COMMAND_SET_TOPMOST: {
            BOOL bTopMost = m_Command.wParam;
            SetTopMost(bTopMost);
            SetEvent(m_hEventDone);
            break;
        }
        case COMMAND_SET_VOLUME: {
            int nVolume = m_Command.wParam;
            IMFGetService        *pGetService = NULL;
            IMFAudioStreamVolume *pVolume = NULL;
            do{
                m_pMediaSession->QueryInterface(IID_IMFGetService, (void**)&pGetService);
                if(!pGetService)break;
                pGetService->GetService(MR_STREAM_VOLUME_SERVICE, IID_IMFAudioStreamVolume, (void**)&pVolume);
                if(!pVolume)break;
                UINT32 uChannels = 0;
                pVolume->GetChannelCount(&uChannels);
                float *pfVolumes = (float*)malloc(sizeof(float) * uChannels);
                for(int i = 0; i < uChannels; i++){
                    pfVolumes[i] = nVolume / 100.0;
                }
                pVolume->SetAllVolumes(uChannels, pfVolumes);
                free(pfVolumes);
            }while(0);
            if(pVolume)pVolume->Release();
            if(pGetService)pGetService->Release();
            SetEvent(m_hEventDone);
            break;
        }
        case COMMAND_SET_TEMPO: {
            int nTempo = m_Command.wParam;
            double dTempo = (double)nTempo / 100.0;
            IMFGetService  *pGetService = NULL;
            IMFRateSupport *pRateSupport = NULL;
            IMFRateControl *pRateControl = NULL;
            do{
                m_pMediaSession->QueryInterface(IID_IMFGetService, (void**)&pGetService);
                if(!pGetService)break;
                pGetService->GetService(MF_RATE_CONTROL_SERVICE, IID_IMFRateSupport, (void**)&pRateSupport);
                //m_pMediaSession->QueryInterface(IID_IMFRateSupport, (void**)&pRateSupport);
                if(!pRateSupport)break;
                float flNearestSupportedRate = dTempo;
                HRESULT hr = pRateSupport->IsRateSupported(FALSE, dTempo, &flNearestSupportedRate);
                if(FAILED(hr)){
                    dTempo = flNearestSupportedRate;
                }
                pGetService->GetService(MF_RATE_CONTROL_SERVICE, IID_IMFRateControl, (void**)&pRateControl);
                //m_pMediaSession->QueryInterface(IID_IMFRateControl, (void**)&pRateControl);
                if(!pRateControl)break;
                pRateControl->SetRate(FALSE, dTempo);
            }while(0);
            if(pRateControl)pRateControl->Release();
            if(pRateSupport)pRateSupport->Release();
            if(pGetService)pGetService->Release();
            SetEvent(m_hEventDone);
            break;
        }
        case COMMAND_SET_VISIBLE:{
            BOOL bVisible = m_Command.wParam && m_MediaInfo.dwVideoWidth > 0 && m_MediaInfo.dwVideoHeight > 0;
            SetVisible(bVisible);
            SetEvent(m_hEventDone);
            break;
        }
        default:
            break;
        }
    }
}
/////////////////////////////////////////////////////////////////////////
HRESULT KbMFPlayer::CreateMediaSinkActivate(IMFStreamDescriptor* stream_desc,
                                            IMFActivate** activate)
{
    IMFMediaTypeHandler* handler = NULL;
    GUID guidMajorType = GUID_NULL;
    HRESULT hr;
    hr = stream_desc->GetMediaTypeHandler(&handler);
    if(!handler){
        return hr;
    }
    hr = handler->GetMajorType(&guidMajorType);
    if (guidMajorType == MFMediaType_Audio) {
        hr = MFCreateAudioRendererActivate(activate);
    }
    else if (guidMajorType == MFMediaType_Video) {
        KbMov_Settings settings;
        kbmov_GetSettings(m_pConfig, &settings);
        if (settings.bVideo){
            if(!m_hWnd){
                wchar_t szCaption[MAX_PATH];
                m_pFile->GetFileName(szCaption, sizeof(szCaption));
                wcsncat_s(szCaption, L"(MF)", _TRUNCATE);
                KbMovPlayerBase::CreateVideoWindow(0, 0, 0, 0);
                SetWindowText(m_hWnd, szCaption);
                IMFMediaType *pMediaType = NULL;
                handler->GetCurrentMediaType(&pMediaType);
                if(pMediaType){
                    MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, 
                                (UINT32*)&m_MediaInfo.dwVideoWidth, (UINT32*)&m_MediaInfo.dwVideoHeight);
                    pMediaType->Release();
                }
            }
            hr = MFCreateVideoRendererActivate(m_hWndDraw, activate);
        }
        else{
            hr = MF_E_INVALIDMEDIATYPE;
        }
    }
    else {
        hr = MF_E_INVALIDMEDIATYPE;
    }
    handler->Release();
    return hr;
}
/////////////////////////////////////////////////////////////////////////
void KbMFPlayer::AddSourceNode(IMFPresentationDescriptor* pres_desc,
    IMFStreamDescriptor* stream_desc, IMFTopologyNode** ppNode)
{
    IMFTopologyNode *pNode = NULL;
    MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &pNode);
    if(pNode){
        pNode->SetUnknown(MF_TOPONODE_SOURCE, m_pMediaSource);
        pNode->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, pres_desc);
        pNode->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, stream_desc);
        m_pTopology->AddNode(pNode);
    }
    *ppNode = pNode;
}
/////////////////////////////////////////////////////////////////////////
void KbMFPlayer::AddOutputNode(IMFActivate* activate, IMFTopologyNode** ppNode)
{
    IMFTopologyNode* pNode = NULL;
    MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &pNode);
    if(pNode){
        pNode->SetObject(activate);
        pNode->SetUINT32(MF_TOPONODE_STREAMID, 0);
        m_pTopology->AddNode(pNode);
    }
    *ppNode = pNode;
}
/////////////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE  KbMFPlayer::Invoke(IMFAsyncResult* pAsyncResult)
{
    HRESULT hr; 
    MediaEventType me_type = MEUnknown;
    IMFMediaEvent *media_event = NULL; 
    hr = m_pMediaSession->EndGetEvent(pAsyncResult, &media_event);
    if(!media_event){
        if(WaitForSingleObject(m_hMFEvent, 0) == WAIT_TIMEOUT){
            SetEvent(m_hMFEvent);
        }
        return hr;
    }
    hr = media_event->GetType(&me_type);
    if (me_type == MESessionClosed) {
        m_nStatus = KPI_STATUS_STOP;
        SetEvent(m_hMFEvent);
        media_event->Release();
        return hr;
    }
    media_event->GetStatus(&hr);
    if(FAILED(hr)){
        m_nStatus = KPI_STATUS_STOP;
        if (WaitForSingleObject(m_hMFEvent, 0) == WAIT_TIMEOUT) {
            SetEvent(m_hMFEvent);
        }
        //return hr;
    }
    else if(me_type == MESessionStarted){
        m_nStatus = KPI_STATUS_PLAYING;
        SetEvent(m_hMFEvent);
    }
    else if (me_type == MESessionPaused) {
        m_nStatus = KPI_STATUS_PAUSE;
        SetEvent(m_hMFEvent);
    }
    else if (me_type == MESessionStopped) {
        m_nStatus = KPI_STATUS_STOP;
        SetEvent(m_hMFEvent);
    }
    else if(me_type == MESessionEnded){
        m_nStatus = KPI_STATUS_STOP;
    }
    else if (me_type == MESessionTopologyStatus) {
        MF_TOPOSTATUS topo_status = MF_TOPOSTATUS_INVALID;
        media_event->GetUINT32(MF_EVENT_TOPOLOGY_STATUS, (UINT32*)&topo_status);
        if (topo_status == MF_TOPOSTATUS_READY) {
            SetEvent(m_hMFEvent);
        }
        //if (topo_status == MF_TOPOSTATUS_STARTED_SOURCE) {//MESessionStarted より先に呼ばれる
        //  int t = 0;
        //}
    }
    media_event->Release();
    hr = m_pMediaSession->BeginGetEvent(this, NULL);
    return hr;
}

