⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 processing.cpp

📁 tapi3.0实现
💻 CPP
📖 第 1 页 / 共 5 页
字号:

    //
    // configure the wave format we want
    //

    AM_MEDIA_TYPE MediaType;

    MediaType.majortype            = MEDIATYPE_Audio;
    MediaType.subtype              = MEDIASUBTYPE_PCM;
    MediaType.bFixedSizeSamples    = TRUE;
    MediaType.bTemporalCompression = FALSE;
    MediaType.lSampleSize          = 0;
    MediaType.formattype           = FORMAT_WaveFormatEx;
    MediaType.pUnk                 = NULL;
    MediaType.cbFormat             = sizeof(WAVEFORMATEX);
    MediaType.pbFormat             = (BYTE*)&WaveFormat;


    //
    // log the wave format we are setting on the terminal
    //

    LogMessage("SetAudioFormat: setting wave format on terminal. ");
    LogFormat(&WaveFormat);


    //
    // set the format
    //

    hr = pITMediaFormat->put_MediaFormat(&MediaType);


    if (FAILED(hr))
    {

        //
        // try to see what format the terminal wanted
        //

        LogError("SetAudioFormat: failed to set format");

        AM_MEDIA_TYPE *pMediaFormat = NULL;

        HRESULT hr2 = pITMediaFormat->get_MediaFormat(&pMediaFormat);


        if (SUCCEEDED(hr2))
        {

            if (pMediaFormat->formattype == FORMAT_WaveFormatEx)
            {

                //
                // log the terminal's format
                //

                LogError("SetAudioFormat: terminal's format is");
                LogFormat((WAVEFORMATEX*) pMediaFormat->pbFormat);

            }
            else 
            {

                LogError("SetAudioFormat: "
                         "terminal's format is not WAVEFORMATEX");
            }


            //
            // note: we are responsible for deallocating the format returned by 
            // get_MediaFormat
            //

            DeleteMediaType(pMediaFormat);

        } //  succeeded getting terminal's format
        else
        {

            LogError("SetAudioFormat: failed to get terminal's format");

        }

    }

    pITMediaFormat->Release();
    pITMediaFormat = NULL;


    LogError("SetAudioFormat: completed");

 
    return hr;

}


///////////////////////////////////////////////////////////////////////////////
//
// SetAllocatorProperties
//
// suggest allocator properties to the terminal
//
///////////////////////////////////////////////////////////////////////////////

HRESULT SetAllocatorProperties(IN ITTerminal *pTerminal)
{


    //
    // different buffer sizes may produce different sound quality, depending
    // on the underlying transport that is being used.
    // 
    // this function illustrates how an app can control the number and size of
    // buffers. A multiple of 30 ms (480 bytes at 16-bit 8 KHz PCM) is the most
    // appropriate sample size for IP (especailly G.723.1).
    //
    // However, small buffers can cause poor audio quality on some voice boards.
    //
    // If this method is not called, the allocator properties suggested by the 
    // connecting filter will be used.
    //


    HRESULT hr = E_FAIL;

    
    //
    // get ITAllocator properties interface on the terminal
    //

    ITAllocatorProperties *pITAllocatorProperties = NULL;


    hr = pTerminal->QueryInterface(IID_ITAllocatorProperties,
                                   (void **)&pITAllocatorProperties);


    if (FAILED(hr))
    {
        LogError("SetAllocatorProperties: "
                 "failed to QI terminal for ITAllocatorProperties");

        return hr;
    }

    
    //
    // configure allocator properties
    //
    // suggest the size and number of the samples for MST to pre-allocate. 
    //
    
    ALLOCATOR_PROPERTIES AllocProps;
    
    AllocProps.cBuffers   = 5;    // ask MST to allocate 5 buffers
    AllocProps.cbBuffer   = 4800; // 4800 bytes each
    AllocProps.cbAlign    = 1;    // no need to align buffers
    AllocProps.cbPrefix   = 0;    // no extra memory preceeding the actual data
    
    
    hr = pITAllocatorProperties->SetAllocatorProperties(&AllocProps);

    if (FAILED(hr))
    {
        LogError("SetAllocatorProperties: "
                 "failed to set allocator properties. hr = 0x%lx", hr);

        pITAllocatorProperties->Release();
        pITAllocatorProperties = NULL;

        return hr;
    }

    
    //
    // ask media streaming terminal to allocate buffers for us. 
    // TRUE is the default, so strictly speaking, we didn't have to call 
    // this method.
    //

    hr = pITAllocatorProperties->SetAllocateBuffers(TRUE);


    pITAllocatorProperties->Release();
    pITAllocatorProperties = NULL;

    
    if (FAILED(hr))
    {
        LogError("SetAllocatorProperties: "
                 "failed to SetAllocateBuffers, hr = 0x%lx", hr);

        return hr;
    }


    //
    // succeeded setting allocator properties
    //

    LogMessage("SetAllocatorProperties: succeeded.");


    return S_OK;

}


///////////////////////////////////////////////////////////////////////////////
//
// SelectAndInitializeTerminal
//
//
// Set audio format and allocator properties on the terminal and
// select the terminal on the stream
//
///////////////////////////////////////////////////////////////////////////////

HRESULT SelectAndInitializeTerminal(IN ITTerminal *pRecordTerminal,
                                    IN ITStream *pStream)
{
    
    HRESULT hr = E_FAIL;


    //
    // set audio format on the created terminal
    //

    hr = SetAudioFormat(pRecordTerminal);

    if (FAILED(hr))
    {
     
        //
        // the terminal does not support the wave format we wanted.
        // no big deal for the receiver, we'll just have to create the 
        // file in the format requested by MST.
        //

        LogMessage("CreateAndSelectMST: "
                   "Failed to set audio format on recording terminal. "
                   "Continuing");

    }


    //
    // set allocator properties for this terminal
    //

    hr = SetAllocatorProperties(pRecordTerminal);

    if (FAILED(hr))
    {
     
        //
        // not a fatal error. our allocator props were rejected, 
        // but this does not necessarily mean streaming will fail.
        //

        LogError("CreateAndSelectMST: Failed to set "
                 "allocator properties on recording terminal");
    }


    //
    // select terminal on the stream
    //

    hr = pStream->SelectTerminal(pRecordTerminal);

    if (FAILED(hr))
    {

        LogError("CreateAndSelectMST: Failed to select "
                 "terminal on the stream");
    }

    return hr;

}


///////////////////////////////////////////////////////////////////////////////
//
// IsRenderingStream
//
// returns TRUE if the stream's direction is TD_RENDER
//
///////////////////////////////////////////////////////////////////////////////

BOOL IsRenderingStream(ITStream *pStream)
{

    //
    // check the stream's direction
    //

    TERMINAL_DIRECTION TerminalDirection;

    HRESULT hr = pStream->get_Direction(&TerminalDirection);

    if (FAILED(hr))
    {
        LogError("IsRenderingStream: Failed to get stream direction");
        
        return FALSE;
    }


    if (TD_RENDER == TerminalDirection)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}


///////////////////////////////////////////////////////////////////////////////
//
// IsAudioStream
//
// returns TRUE if the stream's type is TAPIMEDIATYPE_AUDIO 
//
///////////////////////////////////////////////////////////////////////////////

BOOL IsAudioStream(ITStream *pStream)
{
    
    //
    // check the stream's media type 
    //
    
    long nMediaType = 0;

    HRESULT hr = pStream->get_MediaType(&nMediaType);

    if (FAILED(hr))
    {
        LogError("IsAudioStream: Failed to get media type");

        return FALSE;
    }


    //
    // return true if the stream is audio
    //

    if (TAPIMEDIATYPE_AUDIO == nMediaType)
    {
        
        return TRUE;
    }
    else
    {
    
        return FALSE;
    }

}


///////////////////////////////////////////////////////////////////////////////
// 
// CreateAndSelectMST
// 
// check the call's streams. create media streaming terminal on the first
// incoming audio stream
//
// returns:
//
// S_OK if a terminal was created and selected
// S_FALSE if no appropriate stream was found
// error if failed
//
///////////////////////////////////////////////////////////////////////////////

HRESULT CreateAndSelectMST()
{

    LogMessage("CreateAndSelectMST: started");


    //
    // we should already have the call
    //

    if (NULL == g_pCurrentCall) 
    {
        LogError("CreateAndSelectMST: g_pCurrentCall is NULL");

        return E_UNEXPECTED;
    }


    HRESULT hr = E_FAIL;


    //
    // get the ITStreamControl interface for this call
    //

    ITStreamControl *pStreamControl = NULL;

    hr = g_pCurrentCall->QueryInterface(IID_ITStreamControl,
                                        (void**)&pStreamControl);

    if (FAILED(hr))
    {
        LogError("CreateAndSelectMST: failed to QI call for ITStreamControl");

        return hr;
    }


    //
    // enumerate the streams on the call
    //

    IEnumStream *pEnumStreams = NULL;
    
    hr = pStreamControl->EnumerateStreams(&pEnumStreams);
    
    pStreamControl->Release();
    pStreamControl = NULL;

    if (FAILED(hr))
    {
        LogError("CreateAndSelectMST: failed to enumerate streams on call");
        
        return hr;
    }

    
    //
    // walk through the list of streams on the call
    // for the first incoming audio stream, create a media streaming terminal
    // and select it on the stream
    //
  
    BOOL bTerminalCreatedAndSelected = FALSE;

    while (!bTerminalCreatedAndSelected)
    {
        
        ITStream *pStream = NULL;

        hr = pEnumStreams->Next(1, &pStream, NULL);

        if (S_OK != hr)
        {
            //
            // no more streams or error
            //

            LogError("CreateAndSelectMST: didn't find an incoming audio stream."
                     " terminal not selected.");

            break;
        }


        //
        // create and select media streaming terminal on the first incoming
        // audio stream
        //

        if ( IsRenderingStream(pStream) && IsAudioStream(pStream))
        {

            LogMessage("CreateAndSelectMST: creating mst");

            //
            // create media streaming terminal and select it on the stream
            //
            
            ITTerminal *pRecordTerminal = NULL;

            pRecordTerminal = CreateRenderMediaStreamingTerminal(g_pCurrentCall);

            if (NULL != pRecordTerminal)
            {

                hr = SelectAndInitializeTerminal(pRecordTerminal, pStream);

                pRecordTerminal->Release();
                pRecordTerminal = NULL;


                if (SUCCEEDED(hr))
                {
                    //
                    // set the flag, so we can break out of the loop
                    //

                    bTerminalCreatedAndSelected = TRUE;
                }

            } // media streaming terminal created successfully

        } // stream is rendering and audio
        else
        {
            // 
            // the stream is of wrong direction, or type
            //

        }

        pStream->Release();
        pStream = NULL;

    } // while (enumerating streams on the call)


    //
    // done with the stream enumeration. release
    //

    pEnumStreams->Release();
    pEnumStreams = NULL;

    
    if (bTerminalCreatedAndSelected)
    {
        LogMessage("CreateAndSelectMST: terminal selected");

        return S_OK;
    }
    else
    {
        LogMessage("CreateAndSelectMST: no terminal selected");

        return S_FALSE;
    }

}


///////////////////////////////////////////////////////////////////////////////
//
// GetTerminalFromMediaEvent
//
//
// get the terminal selected on the event's stream
//
///////////////////////////////////////////////////////////////////////////////

HRESULT GetTerminalFromMediaEvent(IN ITCallMediaEvent *pCallMediaEvent,
                                  OUT ITTerminal **ppTerminal)
{

    HRESULT hr = E_FAIL;


    //
    // don't return garbage if we fail
    //

    *ppTerminal = NULL;


    //
    // get the stream corresponding to this event
    //

    ITStream *pStream = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -