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

📄 processing.cpp

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

    hr = pSampleMemoryData->GetInfo(&nBufferSize,
                                    &pnDataBuffer,
                                    &nActualDataSize);


    pSampleMemoryData->Release();
    pSampleMemoryData = NULL;


    if (FAILED(hr))
    {
        LogError("WriteSampleToFile: "
                 "Failed to get to the sample's data");

        return hr;
    }


    //
    // write the data buffer to the avi file
    //

    LogMessage("WriteSampleToFile: received a sample of size %ld bytes",
                nActualDataSize);


    ULONG nBytesWritten = 0;

    hr = pFileWriter->Write(pnDataBuffer,
                            nActualDataSize,
                            &nBytesWritten);

    if (FAILED(hr) || (0 == nBytesWritten))
    {
        LogError("WriteSampleToFile: FileWriter.Write() wrote no data.");

        return E_FAIL;
    }


    return hr;
}


///////////////////////////////////////////////////////////////////////////////
//
// GetSampleID
//
// given the return code fom WaitForMultipleObjects, this function determines
// which sample was signal and returns S_OK and the id of the signaled sample
// or E_FAIL if WaitForMultipleEvents returned an error
//
///////////////////////////////////////////////////////////////////////////////

HRESULT GetSampleID(IN DWORD nWaitCode,         // code from WaitForMultiple...
                    IN DWORD nNumberOfSamples,  // the total number of samples
                    IN OUT DWORD *pnSampleID)   // the calculated id of the 
                                                //          signaled sample
{


    //
    // event abandoned?
    //

    if ( (nWaitCode >= WAIT_ABANDONED_0) && 
         (nWaitCode < WAIT_ABANDONED_0 + nNumberOfSamples) )
    {

        LogError("GetSampleID: event for sample #%lu abandoned.", 
                 nWaitCode - WAIT_ABANDONED_0);

        return E_FAIL;
    }


    //
    // any other error?
    //

    if ( (WAIT_OBJECT_0 > nWaitCode) || 
         (WAIT_OBJECT_0 + nNumberOfSamples <= nWaitCode) )
    {
        LogMessage("GetSampleID: "
                   "waiting for samples failed or timed out. "
                   "WaitForMultipleObjects returned %lu", nWaitCode);

        return E_FAIL;
    }


    //
    // which sample was signaled?
    //

    *pnSampleID = nWaitCode - WAIT_OBJECT_0;

    return S_OK;
}


///////////////////////////////////////////////////////////////////////////////
//
// WriteStreamToFile
//
// extract samples from the terminal's media stream and write them into a file
//
// returns when the call is disconnected (call disconnect causes media streaming
// terminal to abort the samples
//
///////////////////////////////////////////////////////////////////////////////

HRESULT WriteStreamToFile(IN IMediaStream *pTerminalMediaStream)
{

    LogMessage("WriteStreamToFile: started");


    HRESULT hr = E_FAIL;


    //
    // get the number of stream samples we will be using
    //

    DWORD nNumberOfSamples = 0;

    hr = GetNumberOfSamplesOnStream(pTerminalMediaStream, &nNumberOfSamples);

    if (FAILED(hr))
    {
        LogError("WriteStreamToFile: failed to get the number of samples");

        return hr;
    }


    //
    // the number of samples directly corresponds the number of events we will 
    // be waiting on later. WaitForMultipleObjects has a limit of 
    // MAXIMUM_WAIT_OBJECTS events.
    //

    if (nNumberOfSamples > MAXIMUM_WAIT_OBJECTS)
    {

        LogError("WriteStreamToFile: the number of samples [%ld] "
                 "exceeds the number allowed by the design of this "
                 "application [%ld]", 
                 nNumberOfSamples, MAXIMUM_WAIT_OBJECTS);

        return E_FAIL;

    }

   
    //
    // allocate events that will be signaled when each sample is ready to be 
    // saved to a file
    //

    HANDLE *pSampleReadyEvents = NULL;

    pSampleReadyEvents = AllocateEvents(nNumberOfSamples);

    if (NULL == pSampleReadyEvents)
    {
        LogError("WriteStreamToFile: Failed to allocate sample ready events.");
        
        return E_OUTOFMEMORY;
    }


    //
    // allocate array of stream samples
    //
   
    IStreamSample **ppStreamSamples = NULL;

    ppStreamSamples = AllocateStreamSamples(pTerminalMediaStream, 
                                            nNumberOfSamples);

    if (NULL == ppStreamSamples)
    {

        LogError("WriteStreamToFile: Failed to allocate stream sample array");


        //
        // release events we have allocated
        //

        ReleaseEvents(pSampleReadyEvents, nNumberOfSamples);
        pSampleReadyEvents = NULL;

        return E_FAIL;
    }


    //
    // we have the samples, we have the events. 
    // associate events with samples so events get signaled when the 
    // corresponding samples are ready to be written to a file
    // 

    hr = AssociateEventsWithSamples(pSampleReadyEvents,
                                    ppStreamSamples,
                                    nNumberOfSamples);

    if (FAILED(hr))
    {
        LogError("WriteStreamToFile: Failed to associate events with samples");


        //
        // release events and samples we have allocated
        //

        ReleaseEvents(pSampleReadyEvents, nNumberOfSamples);
        pSampleReadyEvents = NULL;

        ReleaseSamples(ppStreamSamples, nNumberOfSamples);
        ppStreamSamples = NULL;

        return E_FAIL;
    }

    
    //
    // get the format of the data delivered by media streaming terminal
    //

    WAVEFORMATEX *pAudioFormat = NULL;

    pAudioFormat = GetAudioFormat(pTerminalMediaStream);

    if (NULL == pAudioFormat)
    {
        LogError("WriteStreamToFile: Failed to get audio format");


        //
        // release events and samples we have allocated
        //

        ReleaseEvents(pSampleReadyEvents, nNumberOfSamples);
        pSampleReadyEvents = NULL;

        ReleaseSamples(ppStreamSamples, nNumberOfSamples);
        ppStreamSamples = NULL;

        return E_FAIL;

    }


    //
    // create a file with the required name and format.
    //
   
    CAVIFileWriter FileWriter;

    hr = FileWriter.Initialize(SZ_OUTPUTFILENAME, *pAudioFormat);


    //
    // no longer need audio format
    //

    FreeMemory(pAudioFormat);
    pAudioFormat = NULL;


    if (FAILED(hr))
    {
        LogError("WriteStreamToFile: open file");


        //
        // release events and samples we have allocated
        //

        ReleaseEvents(pSampleReadyEvents, nNumberOfSamples);
        pSampleReadyEvents = NULL;

        ReleaseSamples(ppStreamSamples, nNumberOfSamples);
        ppStreamSamples = NULL;

        return hr;

    }


    //
    // just for logging, count the number of samples we have recorded
    //

    ULONG nStreamSamplesRecorded = 0;


    while(TRUE)
    {

        //
        // wait for the events associated with the samples
        // when a samples has data, the corresponding event will be 
        // signaled
        //
    
        DWORD nWaitCode = WaitForMultipleObjects(nNumberOfSamples,
                                                 pSampleReadyEvents,
                                                 FALSE,
                                                 INFINITE);

        
        //
        // get the id of the sample that was signaled. fail if Wait returned
        // error
        // 

        DWORD nSampleID = 0;

        hr = GetSampleID(nWaitCode, nNumberOfSamples, &nSampleID);

        if (FAILED(hr))
        {
            LogError("WriteStreamToFile: wait failed");

            break;
        }


        //
        // we filtered out all invalid error codes. so nSampleID has no 
        // choice but be a valid sample index.
        //

        _ASSERTE(nSampleID < nNumberOfSamples);


        //
        // make sure the sample is ready to be read
        //

        hr = ppStreamSamples[nSampleID]->CompletionStatus(COMPSTAT_WAIT, 0);

    
        //
        // check against S_OK explicitly -- not all success codes mean the
        // sample is ready to be used (MS_S_ENDOFSTREAM, etc)
        //

        if (S_OK != hr)
        {

            if (E_ABORT == hr)
            {
        
                //
                // recording was aborted, probably because 
                // the call was disconnected
                //

                LogMessage("WriteStreamToFile: recording aborted");
            }
            else
            {

                LogMessage("WriteStreamToFile: sample is not completed. "
                            "hr = 0x%lx", hr);
            }

            break;
        }

        
        //
        // we have the sample that was signaled and which is now ready to be
        // saved to a file. Record the sample.
        //

        hr = WriteSampleToFile(ppStreamSamples[nSampleID], &FileWriter);

        if (FAILED(hr))
        {
            LogError("WriteStreamToFile: failed to write sample to file");

            break;
        }


        //
        // one more sample was recorded. update the count.
        //

        nStreamSamplesRecorded++;


        //
        // we are done with this sample. return it to the source stream
        // to be refilled with data
        //

        hr = ppStreamSamples[nSampleID]->Update(0,
                                               pSampleReadyEvents[nSampleID],
                                               NULL,
                                               0);

        if (FAILED(hr))
        {
            LogError("WriteStreamToFile: "
                     "Failed to Update the sample recorded. "
                     "hr = 0x%lx", hr);

            break;
        }

    } // sample-writing loop
 

    LogMessage("WriteStreamToFile: wrote the total of %lu samples", 
                nStreamSamplesRecorded);


    //
    // release samples and events
    //

    ReleaseSamples(ppStreamSamples, nNumberOfSamples);
    ppStreamSamples = NULL;

    ReleaseEvents(pSampleReadyEvents, nNumberOfSamples);
    pSampleReadyEvents = NULL;


    //
    // deallocated samples and events. safe to exit.
    //

    LogMessage("WriteStreamToFile: completed, hr = 0x%lx", hr);

 
    return hr;
}


///////////////////////////////////////////////////////////////////////////////
//
// RecordMessage
//
// record the terminal's stream into a file
//
///////////////////////////////////////////////////////////////////////////////

HRESULT RecordMessage(IN ITTerminal *pRecordTerm)
{

    LogMessage("RecordMessage: started");

    HRESULT hr = E_FAIL;


    //
    // get IMediaStream interface on the terminal
    //
    
    IMediaStream *pTerminalMediaStream = NULL;

    hr = pRecordTerm->QueryInterface(IID_IMediaStream, 
                                     (void**)&pTerminalMediaStream);

    if (FAILED(hr))
    {
        LogError("RecordMessage: Failed to qi terminal for IMediaStream.");

        return hr;
    }

    
    //
    // write terminal stream data to a file
    //
    
    hr = WriteStreamToFile(pTerminalMediaStream);

    
    //
    // done with the terminal stream, release.
    //

    pTerminalMediaStream->Release();
    pTerminalMediaStream = NULL;


    LogMessage("RecordMessage: finished");

    return hr;

}


///////////////////////////////////////////////////////////////////////////////
//
// ProcessCallNotificationEvent
//
// processing for TE_CALLNOTIFICATION event
//
///////////////////////////////////////////////////////////////////////////////

HRESULT ProcessCallNotificationEvent(IDispatch *pEvent)
{

    HRESULT hr = E_FAIL;


    //
    // we are being notified of a new call
    //
    // if we own the call and there is not other active call
    // consider this to be the active call
    //
    // wait for CS_OFFERING message before answering the call
    //

    ITCallNotificationEvent *pCallNotificationEvent = NULL;

    hr = pEvent->QueryInterface( IID_ITCallNotificationEvent, 
                                (void **)&pCallNotificationEvent);

    if (FAILED(hr))
    {
        LogError("ProcessCallNotificationEvent: "
                 "Failed to QI event for ITCallNotificationEvent");

        return hr;
    }
   

    //
    // get the call from notification event
    //

    ITCallInfo *pCall = NULL;

    hr = pCallNotificationEvent->get_Call(&pCall);

    //
    // release the ITCallNotificationEvent interface
    //

    pCallNotificationEvent->Release();
    pCallNotificationEvent = NULL;


    if (FAILED(hr))
    {
        LogError("ProcessCallNotificationEvent: "
                 "Failed to get call from Call notification event");


        return hr;
    }

    
    //
    // if we already have an active call, reject the new incoming call
    //

    EnterCriticalSection(&g_CurrentCallCritSection);

    if (NULL != g_pCurrentCall)
    {

        LeaveCriticalSection(&g_CurrentCallCritSection);

⌨️ 快捷键说明

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