Events Windows Media Encoder SDK-确定在本机C++;

Events Windows Media Encoder SDK-确定在本机C++;,events,encoder,wma,Events,Encoder,Wma,我使用Windows Media Encoder SDK将WAV文件转换为WMA格式。 它工作得很好,但我有一个巨大的问题,找出当这个过程完成。。。 有趣的是,我使用了SDK本身的部分代码来获取此通知,但它们似乎不起作用…:( 下面是我的一段代码: class CCallBack : public IDispEventImpl< EVENT_ID, //Thsi is sth I got from the SDK CCallBack, &DIID__IWMEncod

我使用Windows Media Encoder SDK将WAV文件转换为WMA格式。 它工作得很好,但我有一个巨大的问题,找出当这个过程完成。。。 有趣的是,我使用了SDK本身的部分代码来获取此通知,但它们似乎不起作用…:( 下面是我的一段代码:

class CCallBack : public IDispEventImpl< EVENT_ID, //Thsi is sth I got from the SDK
    CCallBack,
    &DIID__IWMEncoderEvents,
    &LIBID_WMEncoderLib,
    LIB_VERMAJOR, 
    LIB_VERMINOR >
{
private:
    WMENC_ENCODER_STATE m_enumState;
    WMENC_SOURCE_STATE  m_enumSrcState;

public:
    // Define the event sink map which determines the events
    // that the application receives.
    BEGIN_SINK_MAP( CCallBack )
        SINK_ENTRY_EX( EVENT_ID, 
        DIID__IWMEncoderEvents,
        DISPID_ENCODEREVENT_STATECHANGE,
        OnStateChange )
        SINK_ENTRY_EX( EVENT_ID,
        DIID__IWMEncoderEvents,
        DISPID_ENCODEREVENT_SRCSTATECHANGE,
        OnSourceStateChange )
    END_SINK_MAP()

    // Implement the event handler for the OnStateChange event.
    STDMETHOD( OnStateChange )( WMENC_ENCODER_STATE enumState )
    {
        m_enumState = enumState;
        return S_OK;
    }

    // Implement the event handler for the OnSourceStateChange event.
    STDMETHOD( OnSourceStateChange )( WMENC_SOURCE_STATE enumState,
        WMENC_SOURCE_TYPE enumType,
        short iIndex,
        BSTR bstrSourceGroup )
    {
        m_enumSrcState = enumState;
        return S_OK;
    }

    // Override the base class virtual function to provide information
    // on the implemented event handlers.
    HRESULT GetFuncInfoFromId( const IID& iid, DISPID dispidMember,
        LCID lcid, _ATL_FUNC_INFO& info )
    {
        if( InlineIsEqualGUID( iid, DIID__IWMEncoderEvents ) )
        {
            info.cc = CC_STDCALL;
            info.vtReturn = VT_ERROR;
            switch( dispidMember )
            {
                // Descibe the parameters of the
                // OnStateChange event handler.
            case DISPID_ENCODEREVENT_STATECHANGE:
                info.nParams = 1;
                info.pVarTypes[0] = VT_I4;
                return S_OK;

                // Describe the parameters of the
                // OnSourceStateChange event handler.
            case DISPID_ENCODEREVENT_SRCSTATECHANGE:
                info.nParams = 4;
                info.pVarTypes[0] = VT_I4;
                info.pVarTypes[1] = VT_I4;
                info.pVarTypes[2] = VT_I2;
                info.pVarTypes[3] = VT_BSTR;
                return S_OK;

            default:
                return E_FAIL;
            }
        }
        return E_FAIL;
    }

    // Link the events to the encoder instance.
    HRESULT CCallBack::Init( IWMEncoder* pEncoder )
    {
        if( pEncoder == NULL )
            return E_FAIL;

        HRESULT hr = DispEventAdvise( pEncoder );
        if( FAILED( hr ) ) 
        {
            // TODO: Handle failure condition.
        }
        return hr;
    }

    // Detach the event sink from the encoder instance.
    HRESULT CCallBack::Shutdown( IWMEncoder* pEncoder )
    {
        if( pEncoder == NULL )
            return E_FAIL;

        HRESULT hr = DispEventUnadvise( pEncoder );
        if( FAILED( hr ) ) 
        {
            // TODO: Handle failure condition.
        }
        return hr;
    }

    // Private member variable access functions.
    WMENC_ENCODER_STATE State() { return m_enumState; }
    WMENC_SOURCE_STATE SrcState() { return m_enumSrcState; }

    CCallBack() { _asm nop }
};

void Do() // This is my code...
{
        // Declare variables.
        HRESULT hr;
        IWMEncoder2* pEncoder = NULL;
        IWMEncSourceGroupCollection* pSrcGrpColl = NULL;
        IWMEncSourceGroup2* pSrcGrp = NULL;
        IWMEncSource* pSrcAud = NULL;
        IWMEncAudioSource* pAudSrc = NULL;
        IWMEncAudienceObj* pAudnc = NULL;
        IWMEncFile2* pFile = NULL;
        IWMEncAttributes* pAttr = NULL;
        IWMEncDisplayInfo* pDispInfo = NULL;
        IErrorInfo* pIErr = NULL;
        IWMEncStatistics* pStatistics = NULL;
        IWMEncFileArchiveStats* pFileArchiveStats = NULL;
        IWMEncOutputStats* pOutputStats = NULL;
        CComBSTR bstrName;
        long lCount = 0;
        CString str;
        CCallBack EventSink;


        // Retrieve a pointer to an IWMEncoder2 interface.
        hr = ::CoCreateInstance(CLSID_WMEncoder, NULL, CLSCTX_INPROC_SERVER, IID_IWMEncoder2, (void**) &pEncoder);
        if ( FAILED( hr ) ) goto ERR;

        hr = EventSink.Init( pEncoder );
        if( FAILED( hr ) ) goto ERR;

// Retrieve the source group collection.
        hr = pEncoder->get_SourceGroupCollection(&pSrcGrpColl);
        if ( FAILED( hr ) ) goto ERR;

        // Add a source group to the collection.
        hr = pSrcGrpColl->Add(CComBSTR("SG_1"), (IWMEncSourceGroup**)&pSrcGrp);
        if ( FAILED( hr ) ) goto ERR;

        hr = pSrcGrp->AddSource(WMENC_AUDIO, (IWMEncSource**)&pAudSrc);
        if ( FAILED( hr ) ) goto ERR;

        if(m_cComboContentType.GetCurSel()==0) hr = pAudSrc->put_ContentMode(WMENC_AUDIOCONTENT_NO_MODE);
        else if(m_cComboContentType.GetCurSel()==1) hr = pAudSrc->put_ContentMode(WMENC_AUDIOCONTENT_SPEECH_MODE);
        else if(m_cComboContentType.GetCurSel()==2) hr = pAudSrc->put_ContentMode(WMENC_AUDIOCONTENT_MIXED_MODE);
        else hr = pAudSrc->put_ContentMode(WMENC_AUDIOCONTENT_NO_MODE);
        if ( FAILED( hr ) ) goto ERR;

        {
            int val = m_cCheckBoxUseTwoPassEnc.GetCheck();
            //int val = ((CButton*)GetDlgItem(IDC_CHECK1))->GetState();
            if(val==BST_CHECKED) hr = pAudSrc->put_PreProcessPass(1);
            else hr = pAudSrc->put_PreProcessPass(0);
            if ( FAILED( hr ) ) goto ERR;
        }

        // Add audio source to the source group.
        hr = pAudSrc->SetInput(CComBSTR("D:\\WAVs\\recording_015.wav"));
        if ( FAILED( hr ) ) goto ERR;

        hr = pEncoder->get_File((IWMEncFile**)&pFile);
        if ( FAILED( hr ) ) goto ERR;

        hr = pFile->put_LocalFileName(CComBSTR("C:\\Users\\Ghost\\Desktop\\OutputFile_+8.wma"));
        if ( FAILED( hr ) ) goto ERR;

        // Set the profile in the source group.
        hr = pSrcGrp->put_Profile(CComVariant(/*(IWMEncProfile*)*/pPro2));
        if ( FAILED( hr ) ) goto ERR;

        hr = pPro2->Validate();
        if ( FAILED( hr ) ) goto ERR;

        // Start the encoding process.
        hr = pEncoder->PrepareToEncode(VARIANT_TRUE);
        if ( FAILED( hr ) ) goto ERR;

        pEncoder->put_AutoStop(VARIANT_TRUE);

        hr = pEncoder->Start();
        if ( FAILED( hr ) ) goto ERR;

        hr = pEncoder->get_Statistics(&pStatistics);
        if ( FAILED( hr ) ) goto ERR;

        WMENC_ENCODER_STATE enumCurState = WMENC_ENCODER_PAUSING;
        WMENC_ENCODER_STATE enumPrvState;
        MSG msg;

        while( TRUE )
        {
            // In order for the events to be triggered correctly,
            // the windows message queue needs to be processed.
            while(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }

            enumPrvState = enumCurState;
            enumCurState = EventSink.State();
            if( EventSink.SrcState() == WMENC_SOURCE_STOP )
                enumCurState = WMENC_ENCODER_STOPPED;

            if( enumCurState != enumPrvState )
            {
                switch ( enumCurState )
                {
                case WMENC_ENCODER_STARTING:
                    // TODO: Handle encoder starting state.
                    break;

                case WMENC_ENCODER_RUNNING:
                    // TODO: Handle encoder running state.
                    break;

                case WMENC_ENCODER_PAUSING:
                    // TODO: Handle encoder pausing state.
                    break;

                case WMENC_ENCODER_PAUSED:
                    // TODO: Handle encoder paused state.
                    break;

                case WMENC_ENCODER_STOPPING:
                    // TODO: Handle encoder stopping state.
                    break;

                case WMENC_ENCODER_STOPPED:
                    // TODO: Handle encoder stopped state.
                    goto EXIT_WAIT;

                case WMENC_ENCODER_END_PREPROCESS:
                    // TODO: Handle encoder end preprocess state.
                    break;
                }
            }
        }
EXIT_WAIT:
        hr = EventSink.Shutdown( pEncoder );
        if ( FAILED( hr ) ) goto ERR;

//      for(;;)
//      {
//          MSG msg;
//          while(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))
//          {
//              TranslateMessage(&msg);
//              DispatchMessage(&msg);
//          }
// 
//          pStatistics->get_StreamOutputStats(WMENC_AUDIO, 0, 1, (IDispatch**)&pOutputStats);
//          if ( FAILED( hr ) ) goto ERR;
//          pStatistics->get_FileArchiveStats((IDispatch**)&pFileArchiveStats);
//          if ( FAILED( hr ) ) goto ERR;
//          WMENC_LONGLONG Dur;
//          pFileArchiveStats->get_FileDuration(&Dur);
//          long Dur2;
//          pAudSrc->get_Duration(&Dur2);
//          if ( FAILED( hr ) ) goto ERR;
//          WMENC_ENCODER_STATE EncState;
//          pEncoder->get_RunState(&EncState);
//          if ( FAILED( hr ) ) goto ERR;
//          WMENC_ARCHIVE_STATE ArchState;
//          pEncoder->get_ArchiveState(WMENC_ARCHIVE_LOCAL, &ArchState);
//          if ( FAILED( hr ) ) goto ERR;
//          if(ArchState == WMENC_ARCHIVE_STOPPED && EncState == WMENC_ENCODER_STOPPED)
//          {
//              break;
//          }
//          Sleep(2000);
//      }

        AfxMessageBox(_T("DONE !"));
        goto END;
ERR:
        ReportError();
END:
        // Release pointers.
        ComFree(pSrcGrpColl)
        ComFree(pSrcGrp)
        ComFree(pStatistics)
        ComFree(pFileArchiveStats)
        ComFree(pAudnc)
        ComFree(pIErr)
        ComFree(pFile)
        ComFree(pSrcAud)
        ComFree(pAttr)
        ComFree(pDispInfo)
        ComFree(pEncoder)
}

我自己从来没有使用过iMenCoder,但是如果你对状态更改的调查没有帮助,难怪你没有收到事件/回调。不管怎样,假设确实有什么东西在路上卡住了,作为安全措施,有没有一个选项,一旦不再产生任何数据,就停止编码?你说“一旦不再产生任何数据,就停止编码".我已经想到了这一点,并尝试以频繁的间隔获取结果文件的持续时间,以检查其是否增长,但我不知道这是否足够可靠…您正在进行文件到文件的操作,因此当进度不再移动时,这是数据结束时的一个非常可靠的指示。我的第一个猜测是IwmenOutputStats.ByteCount只要流程还有一些输入,就必须增加。我只是在想流程不知怎的暂停时的情况(假设用户休眠电脑,并且源文件位于外部硬盘驱动器上。这可能会阻止HD旋转,并且当用户再次登录时,外部HD需要时间重新开始旋转并读取字节)。可能这(以及其他情况)会因延迟数据输入而导致问题(因此输出也是如此)…我确实尝试过类似于你提议的东西(顺便说一句,谢谢)但我一直希望有一些东西可以让我无所畏惧地依靠。我目前面临着同样的问题,除了我6年前编写的代码,它在Win 2003 R2上运行得很好……但在Win 2008 R2上运行得不好。我想我可能会监控CPU的使用情况。如果编码器正在“运行”,但CPU几乎处于空闲状态,然后我假设作业已完成并终止编码作业
pAudSrc->put_PreProcessPass(1);