michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: michael@0: #ifndef AUDIO_SESSION_H_ michael@0: #define AUDIO_SESSION_H_ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "mozilla/TimeStamp.h" michael@0: #include "nsTArray.h" michael@0: michael@0: #include "MediaConduitInterface.h" michael@0: #include "MediaEngineWrapper.h" michael@0: michael@0: // Audio Engine Includes michael@0: #include "webrtc/common_types.h" michael@0: #include "webrtc/voice_engine/include/voe_base.h" michael@0: #include "webrtc/voice_engine/include/voe_volume_control.h" michael@0: #include "webrtc/voice_engine/include/voe_codec.h" michael@0: #include "webrtc/voice_engine/include/voe_file.h" michael@0: #include "webrtc/voice_engine/include/voe_network.h" michael@0: #include "webrtc/voice_engine/include/voe_external_media.h" michael@0: #include "webrtc/voice_engine/include/voe_audio_processing.h" michael@0: #include "webrtc/voice_engine/include/voe_video_sync.h" michael@0: #include "webrtc/voice_engine/include/voe_rtp_rtcp.h" michael@0: //Some WebRTC types for short notations michael@0: using webrtc::VoEBase; michael@0: using webrtc::VoENetwork; michael@0: using webrtc::VoECodec; michael@0: using webrtc::VoEExternalMedia; michael@0: using webrtc::VoEAudioProcessing; michael@0: using webrtc::VoEVideoSync; michael@0: using webrtc::VoERTP_RTCP; michael@0: /** This file hosts several structures identifying different aspects michael@0: * of a RTP Session. michael@0: */ michael@0: namespace mozilla { michael@0: // Helper function michael@0: michael@0: DOMHighResTimeStamp michael@0: NTPtoDOMHighResTimeStamp(uint32_t ntpHigh, uint32_t ntpLow); michael@0: michael@0: /** michael@0: * Concrete class for Audio session. Hooks up michael@0: * - media-source and target to external transport michael@0: */ michael@0: class WebrtcAudioConduit:public AudioSessionConduit michael@0: ,public webrtc::Transport michael@0: { michael@0: public: michael@0: //VoiceEngine defined constant for Payload Name Size. michael@0: static const unsigned int CODEC_PLNAME_SIZE; michael@0: michael@0: /** michael@0: * APIs used by the registered external transport to this Conduit to michael@0: * feed in received RTP Frames to the VoiceEngine for decoding michael@0: */ michael@0: virtual MediaConduitErrorCode ReceivedRTPPacket(const void *data, int len); michael@0: michael@0: /** michael@0: * APIs used by the registered external transport to this Conduit to michael@0: * feed in received RTCP Frames to the VoiceEngine for decoding michael@0: */ michael@0: virtual MediaConduitErrorCode ReceivedRTCPPacket(const void *data, int len); michael@0: michael@0: /** michael@0: * Function to configure send codec for the audio session michael@0: * @param sendSessionConfig: CodecConfiguration michael@0: * @result: On Success, the audio engine is configured with passed in codec for send michael@0: * On failure, audio engine transmit functionality is disabled. michael@0: * NOTE: This API can be invoked multiple time. Invoking this API may involve restarting michael@0: * transmission sub-system on the engine. michael@0: */ michael@0: virtual MediaConduitErrorCode ConfigureSendMediaCodec(const AudioCodecConfig* codecConfig); michael@0: /** michael@0: * Function to configure list of receive codecs for the audio session michael@0: * @param sendSessionConfig: CodecConfiguration michael@0: * @result: On Success, the audio engine is configured with passed in codec for send michael@0: * Also the playout is enabled. michael@0: * On failure, audio engine transmit functionality is disabled. michael@0: * NOTE: This API can be invoked multiple time. Invoking this API may involve restarting michael@0: * transmission sub-system on the engine. michael@0: */ michael@0: virtual MediaConduitErrorCode ConfigureRecvMediaCodecs( michael@0: const std::vector& codecConfigList); michael@0: /** michael@0: * Function to enable the audio level extension michael@0: * @param enabled: enable extension michael@0: */ michael@0: virtual MediaConduitErrorCode EnableAudioLevelExtension(bool enabled, uint8_t id); michael@0: michael@0: /** michael@0: * Register External Transport to this Conduit. RTP and RTCP frames from the VoiceEngine michael@0: * shall be passed to the registered transport for transporting externally. michael@0: */ michael@0: virtual MediaConduitErrorCode AttachTransport(mozilla::RefPtr aTransport); michael@0: /** michael@0: * Function to deliver externally captured audio sample for encoding and transport michael@0: * @param audioData [in]: Pointer to array containing a frame of audio michael@0: * @param lengthSamples [in]: Length of audio frame in samples in multiple of 10 milliseconds michael@0: * Ex: Frame length is 160, 320, 440 for 16, 32, 44 kHz sampling rates michael@0: respectively. michael@0: audioData[] should be of lengthSamples in size michael@0: say, for 16kz sampling rate, audioData[] should contain 160 michael@0: samples of 16-bits each for a 10m audio frame. michael@0: * @param samplingFreqHz [in]: Frequency/rate of the sampling in Hz ( 16000, 32000 ...) michael@0: * @param capture_delay [in]: Approx Delay from recording until it is delivered to VoiceEngine michael@0: in milliseconds. michael@0: * NOTE: ConfigureSendMediaCodec() SHOULD be called before this function can be invoked michael@0: * This ensures the inserted audio-samples can be transmitted by the conduit michael@0: * michael@0: */ michael@0: virtual MediaConduitErrorCode SendAudioFrame(const int16_t speechData[], michael@0: int32_t lengthSamples, michael@0: int32_t samplingFreqHz, michael@0: int32_t capture_time); michael@0: michael@0: /** michael@0: * Function to grab a decoded audio-sample from the media engine for rendering michael@0: * / playoutof length 10 milliseconds. michael@0: * michael@0: * @param speechData [in]: Pointer to a array to which a 10ms frame of audio will be copied michael@0: * @param samplingFreqHz [in]: Frequency of the sampling for playback in Hertz (16000, 32000,..) michael@0: * @param capture_delay [in]: Estimated Time between reading of the samples to rendering/playback michael@0: * @param lengthSamples [out]: Will contain length of the audio frame in samples at return. michael@0: Ex: A value of 160 implies 160 samples each of 16-bits was copied michael@0: into speechData michael@0: * NOTE: This function should be invoked every 10 milliseconds for the best michael@0: * peformance michael@0: * NOTE: ConfigureRecvMediaCodec() SHOULD be called before this function can be invoked michael@0: * This ensures the decoded samples are ready for reading and playout is enabled. michael@0: * michael@0: */ michael@0: virtual MediaConduitErrorCode GetAudioFrame(int16_t speechData[], michael@0: int32_t samplingFreqHz, michael@0: int32_t capture_delay, michael@0: int& lengthSamples); michael@0: michael@0: michael@0: /** michael@0: * Webrtc transport implementation to send and receive RTP packet. michael@0: * AudioConduit registers itself as ExternalTransport to the VoiceEngine michael@0: */ michael@0: virtual int SendPacket(int channel, const void *data, int len) ; michael@0: michael@0: /** michael@0: * Webrtc transport implementation to send and receive RTCP packet. michael@0: * AudioConduit registers itself as ExternalTransport to the VoiceEngine michael@0: */ michael@0: virtual int SendRTCPPacket(int channel, const void *data, int len) ; michael@0: michael@0: michael@0: michael@0: WebrtcAudioConduit(): michael@0: mOtherDirection(nullptr), michael@0: mShutDown(false), michael@0: mVoiceEngine(nullptr), michael@0: mTransport(nullptr), michael@0: mEngineTransmitting(false), michael@0: mEngineReceiving(false), michael@0: mChannel(-1), michael@0: mCurSendCodecConfig(nullptr), michael@0: mCaptureDelay(150), michael@0: #ifdef MOZILLA_INTERNAL_API michael@0: mLastTimestamp(0), michael@0: #endif // MOZILLA_INTERNAL_API michael@0: mSamples(0), michael@0: mLastSyncLog(0) michael@0: { michael@0: } michael@0: michael@0: virtual ~WebrtcAudioConduit(); michael@0: michael@0: MediaConduitErrorCode Init(WebrtcAudioConduit *other); michael@0: michael@0: int GetChannel() { return mChannel; } michael@0: webrtc::VoiceEngine* GetVoiceEngine() { return mVoiceEngine; } michael@0: bool GetLocalSSRC(unsigned int* ssrc); michael@0: bool GetRemoteSSRC(unsigned int* ssrc); michael@0: bool GetAVStats(int32_t* jitterBufferDelayMs, michael@0: int32_t* playoutBufferDelayMs, michael@0: int32_t* avSyncOffsetMs); michael@0: bool GetRTPStats(unsigned int* jitterMs, unsigned int* cumulativeLost); michael@0: bool GetRTCPReceiverReport(DOMHighResTimeStamp* timestamp, michael@0: uint32_t* jitterMs, michael@0: uint32_t* packetsReceived, michael@0: uint64_t* bytesReceived, michael@0: uint32_t *cumulativeLost, michael@0: int32_t* rttMs); michael@0: bool GetRTCPSenderReport(DOMHighResTimeStamp* timestamp, michael@0: unsigned int* packetsSent, michael@0: uint64_t* bytesSent); michael@0: michael@0: private: michael@0: WebrtcAudioConduit(const WebrtcAudioConduit& other) MOZ_DELETE; michael@0: void operator=(const WebrtcAudioConduit& other) MOZ_DELETE; michael@0: michael@0: //Local database of currently applied receive codecs michael@0: typedef std::vector RecvCodecList; michael@0: michael@0: //Function to convert between WebRTC and Conduit codec structures michael@0: bool CodecConfigToWebRTCCodec(const AudioCodecConfig* codecInfo, michael@0: webrtc::CodecInst& cinst); michael@0: michael@0: //Checks if given sampling frequency is supported michael@0: bool IsSamplingFreqSupported(int freq) const; michael@0: michael@0: //Generate block size in sample lenght for a given sampling frequency michael@0: unsigned int GetNum10msSamplesForFrequency(int samplingFreqHz) const; michael@0: michael@0: // Function to copy a codec structure to Conduit's database michael@0: bool CopyCodecToDB(const AudioCodecConfig* codecInfo); michael@0: michael@0: // Functions to verify if the codec passed is already in michael@0: // conduits database michael@0: bool CheckCodecForMatch(const AudioCodecConfig* codecInfo) const; michael@0: bool CheckCodecsForMatch(const AudioCodecConfig* curCodecConfig, michael@0: const AudioCodecConfig* codecInfo) const; michael@0: //Checks the codec to be applied michael@0: MediaConduitErrorCode ValidateCodecConfig(const AudioCodecConfig* codecInfo, bool send) const; michael@0: michael@0: //Utility function to dump recv codec database michael@0: void DumpCodecDB() const; michael@0: michael@0: // The two sides of a send/receive pair of conduits each keep a pointer to the other. michael@0: // The also share a single VoiceEngine and mChannel. Shutdown must be coordinated michael@0: // carefully to avoid double-freeing or accessing after one frees. michael@0: WebrtcAudioConduit* mOtherDirection; michael@0: // Other side has shut down our channel and related items already michael@0: bool mShutDown; michael@0: michael@0: // These are shared by both directions. They're released by the last michael@0: // conduit to die michael@0: webrtc::VoiceEngine* mVoiceEngine; michael@0: mozilla::RefPtr mTransport; michael@0: ScopedCustomReleasePtr mPtrVoENetwork; michael@0: ScopedCustomReleasePtr mPtrVoEBase; michael@0: ScopedCustomReleasePtr mPtrVoECodec; michael@0: ScopedCustomReleasePtr mPtrVoEXmedia; michael@0: ScopedCustomReleasePtr mPtrVoEProcessing; michael@0: ScopedCustomReleasePtr mPtrVoEVideoSync; michael@0: ScopedCustomReleasePtr mPtrVoERTP_RTCP; michael@0: ScopedCustomReleasePtr mPtrRTP; michael@0: //engine states of our interets michael@0: bool mEngineTransmitting; // If true => VoiceEngine Send-subsystem is up michael@0: bool mEngineReceiving; // If true => VoiceEngine Receive-subsystem is up michael@0: // and playout is enabled michael@0: // Keep track of each inserted RTP block and the time it was inserted michael@0: // so we can estimate the clock time for a specific TimeStamp coming out michael@0: // (for when we send data to MediaStreamTracks). Blocks are aged out as needed. michael@0: struct Processing { michael@0: TimeStamp mTimeStamp; michael@0: uint32_t mRTPTimeStamp; // RTP timestamps received michael@0: }; michael@0: nsAutoTArray mProcessing; michael@0: michael@0: int mChannel; michael@0: RecvCodecList mRecvCodecList; michael@0: AudioCodecConfig* mCurSendCodecConfig; michael@0: michael@0: // Current "capture" delay (really output plus input delay) michael@0: int32_t mCaptureDelay; michael@0: michael@0: #ifdef MOZILLA_INTERNAL_API michael@0: uint32_t mLastTimestamp; michael@0: #endif // MOZILLA_INTERNAL_API michael@0: michael@0: uint32_t mSamples; michael@0: uint32_t mLastSyncLog; michael@0: }; michael@0: michael@0: } // end namespace michael@0: michael@0: #endif