下面将以实现一个音频通话功能为示例详细介绍VoiceEngine的使用,在文末将附上相应源码的下载地址。这里参考的是voiceengine\voe_cmd_test。
第一步是创建VoiceEngine和相关的sub-apis
- //
- // Create VoiceEngine related instance
- //
- webrtc::VoiceEngine* ptrVoE = NULL;
- ptrVoE = webrtc::VoiceEngine::Create();
- webrtc::VoEBase* ptrVoEBase = NULL;
- ptrVoEBase = webrtc::VoEBase::GetInterface(ptrVoE);
- webrtc::VoECodec* ptrVoECodec = NULL;
- ptrVoECodec = webrtc::VoECodec::GetInterface(ptrVoE);
- webrtc::VoEAudioProcessing* ptrVoEAp = NULL;
- ptrVoEAp = webrtc::VoEAudioProcessing::GetInterface(ptrVoE);
- webrtc::VoEVolumeControl* ptrVoEVolume = NULL;
- ptrVoEVolume = webrtc::VoEVolumeControl::GetInterface(ptrVoE);
- webrtc::VoENetwork* ptrVoENetwork = NULL;
- ptrVoENetwork = webrtc::VoENetwork::GetInterface(ptrVoE);
- webrtc::VoEFile* ptrVoEFile = NULL;
- ptrVoEFile = webrtc::VoEFile::GetInterface(ptrVoE);
- webrtc::VoEHardware* ptrVoEHardware = NULL;
- ptrVoEHardware = webrtc::VoEHardware::GetInterface(ptrVoE);
- //
- //Set Trace File and Record File
- //
- const std::string trace_filename = "webrtc_trace.txt";
- VoiceEngine::SetTraceFilter(kTraceAll);
- error = VoiceEngine::SetTraceFile(trace_filename.c_str());
- if (error != 0)
- {
- printf("ERROR in VoiceEngine::SetTraceFile\n");
- return error;
- }
- error = VoiceEngine::SetTraceCallback(NULL);
- if (error != 0)
- {
- printf("ERROR in VoiceEngine::SetTraceCallback\n");
- return error;
- }
- const std::string play_filename = "recorded_playout.wav";
- const std::string mic_filename = "recorded_mic.wav";
- //
- //Init
- //
- error = ptrVoEBase->Init();
- if (error != 0)
- {
- printf("ERROR in VoEBase::Init\n");
- return error;
- }
- error = ptrVoEBase->RegisterVoiceEngineObserver(my_observer);
- if (error != 0)
- {
- printf("ERROR in VoEBase:;RegisterVoiceEngineObserver\n");
- return error;
- }
- printf("Version\n");
- char tmp[1024];
- error = ptrVoEBase->GetVersion(tmp);
- if (error != 0)
- {
- printf("ERROR in VoEBase::GetVersion\n");
- return error;
- }
- printf("%s\n", tmp);
- class MyObserver : public VoiceEngineObserver {
- public:
- virtual void CallbackOnError(int channel, int err_code);
- };
- void MyObserver::CallbackOnError(int channel, int err_code) {
- // Add printf for other error codes here
- if (err_code == VE_TYPING_NOISE_WARNING) {
- printf(" TYPING NOISE DETECTED \n");
- }
- else if (err_code == VE_TYPING_NOISE_OFF_WARNING) {
- printf(" TYPING NOISE OFF DETECTED \n");
- }
- else if (err_code == VE_RECEIVE_PACKET_TIMEOUT) {
- printf(" RECEIVE PACKET TIMEOUT \n");
- }
- else if (err_code == VE_PACKET_RECEIPT_RESTARTED) {
- printf(" PACKET RECEIPT RESTARTED \n");
- }
- else if (err_code == VE_RUNTIME_PLAY_WARNING) {
- printf(" RUNTIME PLAY WARNING \n");
- }
- else if (err_code == VE_RUNTIME_REC_WARNING) {
- printf(" RUNTIME RECORD WARNING \n");
- }
- else if (err_code == VE_SATURATION_WARNING) {
- printf(" SATURATION WARNING \n");
- }
- else if (err_code == VE_RUNTIME_PLAY_ERROR) {
- printf(" RUNTIME PLAY ERROR \n");
- }
- else if (err_code == VE_RUNTIME_REC_ERROR) {
- printf(" RUNTIME RECORD ERROR \n");
- }
- else if (err_code == VE_REC_DEVICE_REMOVED) {
- printf(" RECORD DEVICE REMOVED \n");
- }
- }
- //
- //Network Settings
- //
- int audiochannel;
- audiochannel = ptrVoEBase->CreateChannel();
- if (audiochannel < 0)
- {
- printf("ERROR in VoEBase::CreateChannel\n");
- return audiochannel;
- }
- VoiceChannelTransport* voice_channel_transport = new VoiceChannelTransport(ptrVoENetwork, audiochannel);
- char ip[64] = "127.0.0.1";
- int rPort = 800;//remote port
- int lPort = 800;//local port
- error = voice_channel_transport->SetSendDestination(ip, rPort);
- if (error != 0)
- {
- printf("ERROR in set send ip and port\n");
- return error;
- }
- error = voice_channel_transport->SetLocalReceiver(lPort);
- if (error != 0)
- {
- printf("ERROR in set receiver and port\n");
- return error;
- }
- // Helper class for VoiceEngine tests.
- class VoiceChannelTransport : public webrtc::test::UdpTransportData {
- public:
- VoiceChannelTransport(VoENetwork* voe_network, int channel);
- virtual ~VoiceChannelTransport();
- // Start implementation of UdpTransportData.
- void IncomingRTPPacket(const int8_t* incoming_rtp_packet,
- const size_t packet_length,
- const char* /*from_ip*/,
- const uint16_t /*from_port*/) override;
- void IncomingRTCPPacket(const int8_t* incoming_rtcp_packet,
- const size_t packet_length,
- const char* /*from_ip*/,
- const uint16_t /*from_port*/) override;
- // End implementation of UdpTransportData.
- // Specifies the ports to receive RTP packets on.
- int SetLocalReceiver(uint16_t rtp_port);
- // Specifies the destination port and IP address for a specified channel.
- int SetSendDestination(const char* ip_address, uint16_t rtp_port);
- private:
- int channel_;
- VoENetwork* voe_network_;
- webrtc::test::UdpTransport* socket_transport_;
- };
- VoiceChannelTransport::VoiceChannelTransport(VoENetwork* voe_network,
- int channel)
- : channel_(channel),
- voe_network_(voe_network) {
- uint8_t socket_threads = 1;
- socket_transport_ = webrtc::test::UdpTransport::Create(channel, socket_threads);
- int registered = voe_network_->RegisterExternalTransport(channel,
- *socket_transport_);
- #if !defined(WEBRTC_ANDROID) && !defined(WEBRTC_IOS)
- if (registered != 0)
- return;
- #else
- assert(registered == 0);
- #endif
- }
- VoiceChannelTransport::~VoiceChannelTransport() {
- voe_network_->DeRegisterExternalTransport(channel_);
- webrtc::test::UdpTransport::Destroy(socket_transport_);
- }
- void VoiceChannelTransport::IncomingRTPPacket(
- const int8_t* incoming_rtp_packet,
- const size_t packet_length,
- const char* /*from_ip*/,
- const uint16_t /*from_port*/) {
- voe_network_->ReceivedRTPPacket(
- channel_, incoming_rtp_packet, packet_length, PacketTime());
- }
- void VoiceChannelTransport::IncomingRTCPPacket(
- const int8_t* incoming_rtcp_packet,
- const size_t packet_length,
- const char* /*from_ip*/,
- const uint16_t /*from_port*/) {
- voe_network_->ReceivedRTCPPacket(channel_, incoming_rtcp_packet,
- packet_length);
- }
- int VoiceChannelTransport::SetLocalReceiver(uint16_t rtp_port) {
- static const int kNumReceiveSocketBuffers = 500;
- int return_value = socket_transport_->InitializeReceiveSockets(this,
- rtp_port);
- if (return_value == 0) {
- return socket_transport_->StartReceiving(kNumReceiveSocketBuffers);
- }
- return return_value;
- }
- int VoiceChannelTransport::SetSendDestination(const char* ip_address,
- uint16_t rtp_port) {
- return socket_transport_->InitializeSendSockets(ip_address, rtp_port);
- }
- //
- //Setup Codecs
- //
- CodecInst codec_params;
- CodecInst cinst;
- for (int i = 0; i < ptrVoECodec->NumOfCodecs(); ++i) {
- int error = ptrVoECodec->GetCodec(i, codec_params);
- if (error != 0)
- {
- printf("ERROR in VoECodec::GetCodec\n");
- return error;
- }
- printf("%2d. %3d %s/%d/%d \n", i, codec_params.pltype, codec_params.plname,
- codec_params.plfreq, codec_params.channels);
- }
- printf("Select send codec: ");
- int codec_selection;
- scanf("%i", &codec_selection);
- ptrVoECodec->GetCodec(codec_selection, cinst);
- error = ptrVoECodec->SetSendCodec(audiochannel, cinst);
- if (error != 0)
- {
- printf("ERROR in VoECodec::SetSendCodec\n");
- return error;
- }
- //
- //Setup Devices
- //
- int rd(-1), pd(-1);
- error = ptrVoEHardware->GetNumOfRecordingDevices(rd);
- if (error != 0)
- {
- printf("ERROR in VoEHardware::GetNumOfRecordingDevices\n");
- return error;
- }
- error = ptrVoEHardware->GetNumOfPlayoutDevices(pd);
- if (error != 0)
- {
- printf("ERROR in VoEHardware::GetNumOfPlayoutDevices\n");
- return error;
- }
- char dn[128] = { 0 };
- char guid[128] = { 0 };
- printf("\nPlayout devices (%d): \n", pd);
- for (int j = 0; j < pd; ++j) {
- error = ptrVoEHardware->GetPlayoutDeviceName(j, dn, guid);
- if (error != 0)
- {
- printf("ERROR in VoEHardware::GetPlayoutDeviceName\n");
- return error;
- }
- printf(" %d: %s \n", j, dn);
- }
- printf("Recording devices (%d): \n", rd);
- for (int j = 0; j < rd; ++j) {
- error = ptrVoEHardware->GetRecordingDeviceName(j, dn, guid);
- if (error != 0)
- {
- printf("ERROR in VoEHardware::GetRecordingDeviceName\n");
- return error;
- }
- printf(" %d: %s \n", j, dn);
- }
- printf("Select playout device: ");
- scanf("%d", &pd);
- error = ptrVoEHardware->SetPlayoutDevice(pd);
- if (error != 0)
- {
- printf("ERROR in VoEHardware::SetPlayoutDevice\n");
- return error;
- }
- printf("Select recording device: ");
- scanf("%d", &rd);
- getchar();
- error = ptrVoEHardware->SetRecordingDevice(rd);
- if (error != 0)
- {
- printf("ERROR in VoEHardware::SetRecordingDevice\n");
- return error;
- }
- //
- //Audio Processing
- //
- error = ptrVoECodec->SetVADStatus(0, 1);//FIX:why not use audio channel
- if (error != 0)
- {
- printf("ERROR in VoECodec::SetVADStatus\n");
- return error;
- }
- error = ptrVoEAp->SetAgcStatus(1);
- if (error != 0)
- {
- printf("ERROR in VoEAudioProcess::SetAgcStatus\n");
- return error;
- }
- error = ptrVoEAp->SetEcStatus(1);
- if (error != 0)
- {
- printf("ERROR in VoEAudioProcess::SetEcStatus\n");
- return error;
- }
- error = ptrVoEAp->SetNsStatus(1);
- if (error != 0)
- {
- printf("ERROR in VoEAudioProcess::SetNsStatus\n");
- return error;
- }
- error = ptrVoEAp->SetRxAgcStatus(audiochannel, 1);
- if (error != 0)
- {
- printf("ERROR in VoEAudioProcess::SetRxAgcStatus\n");
- return error;
- }
- error = ptrVoEAp->SetRxNsStatus(audiochannel, 1);
- if (error != 0)
- {
- printf("ERROR in VoEAudioProcess::SetRxNsStatus\n");
- return error;
- }
- //Start Receive
- error = ptrVoEBase->StartReceive(audiochannel);
- if (error != 0)
- {
- printf("ERROR in VoEBase::StartReceive\n");
- return error;
- }
- //Start Playout
- error = ptrVoEBase->StartPlayout(audiochannel);
- if (error != 0)
- {
- printf("ERROR in VoEBase::StartPlayout\n");
- return error;
- }
- //Start Send
- error = ptrVoEBase->StartSend(audiochannel);
- if (error != 0)
- {
- printf("ERROR in VoEBase::StartSend\n");
- return error;
- }
- //Start Record
- error = ptrVoEFile->StartRecordingMicrophone(mic_filename.c_str());
- if (error != 0)
- {
- printf("ERROR in VoEFile::StartRecordingMicrophone\n");
- return error;
- }
- error = ptrVoEFile->StartRecordingPlayout(audiochannel, play_filename.c_str());
- if (error != 0)
- {
- printf("ERROR in VoEFile::StartRecordingPlayout\n");
- return error;
- }
在通话结束之后,还需要进行相应的stop\release
- //Stop Record
- error = ptrVoEFile->StopRecordingMicrophone();
- if (error != 0)
- {
- printf("ERROR in VoEFile::StopRecordingMicrophone\n");
- return error;
- }
- error = ptrVoEFile->StopRecordingPlayout(audiochannel);
- if (error != 0)
- {
- printf("ERROR in VoEFile::StopRecordingPlayout\n");
- return error;
- }
- //Stop Receive
- error = ptrVoEBase->StopReceive(audiochannel);
- if (error != 0)
- {
- printf("ERROR in VoEBase::StopReceive\n");
- return error;
- }
- //Stop Send
- error = ptrVoEBase->StopSend(audiochannel);
- if (error != 0)
- {
- printf("ERROR in VoEBase::StopSend\n");
- return error;
- }
- //Stop Playout
- error = ptrVoEBase->StopPlayout(audiochannel);
- if (error != 0)
- {
- printf("ERROR in VoEBase::StopPlayout\n");
- return error;
- }
- //Delete Channel
- error = ptrVoEBase->DeleteChannel(audiochannel);
- if (error != 0)
- {
- printf("ERROR in VoEBase::DeleteChannel\n");
- return error;
- }
- delete voice_channel_transport;
- ptrVoEBase->DeRegisterVoiceEngineObserver();
- error = ptrVoEBase->Terminate();
- if (error != 0)
- {
- printf("ERROR in VoEBase::Terminate\n");
- return error;
- }
- int remainingInterfaces = 0;
- remainingInterfaces += ptrVoEBase->Release();
- remainingInterfaces = ptrVoECodec->Release();
- remainingInterfaces += ptrVoEVolume->Release();
- remainingInterfaces += ptrVoEFile->Release();
- remainingInterfaces += ptrVoEAp->Release();
- remainingInterfaces += ptrVoEHardware->Release();
- remainingInterfaces += ptrVoENetwork->Release();
- /*if (remainingInterfaces > 0)
- {
- printf("ERROR: Could not release all interfaces\n");
- return -1;
- }*/
- bool deleted = webrtc::VoiceEngine::Delete(ptrVoE);
- if (deleted == false)
- {
- printf("ERROR in VoiceEngine::Delete\n");
- return -1;
- }
至此,就实现了一个音频通话的功能。