summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc/libwebrtcglue/AudioConduit.h
blob: b3673c6cee85f89d474e4cdb38fd0ff581c57a32 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef AUDIO_SESSION_H_
#define AUDIO_SESSION_H_

#include "mozilla/Attributes.h"
#include "mozilla/ReentrantMonitor.h"
#include "mozilla/TimeStamp.h"
#include "nsTArray.h"

#include "MediaConduitInterface.h"
#include "common/MediaEngineWrapper.h"
#include "RtpSourceObserver.h"
#include "RtpPacketQueue.h"

// Audio Engine Includes
#include "webrtc/common_types.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_packet_observer.h"
#include "webrtc/modules/audio_device/include/fake_audio_device.h"
#include "webrtc/voice_engine/include/voe_base.h"
#include "webrtc/voice_engine/channel_proxy.h"

/** This file hosts several structures identifying different aspects
 * of a RTP Session.
 */
namespace mozilla {
// Helper function

DOMHighResTimeStamp NTPtoDOMHighResTimeStamp(uint32_t ntpHigh, uint32_t ntpLow);

/**
 * Concrete class for Audio session. Hooks up
 *  - media-source and target to external transport
 */
class WebrtcAudioConduit : public AudioSessionConduit,
                           public webrtc::Transport,
                           public webrtc::RtcpEventObserver,
                           public webrtc::RtpPacketObserver {
 public:
  // VoiceEngine defined constant for Payload Name Size.
  static const unsigned int CODEC_PLNAME_SIZE;

  /**
   * APIs used by the registered external transport to this Conduit to
   * feed in received RTP Frames to the VoiceEngine for decoding
   */
  MediaConduitErrorCode ReceivedRTPPacket(const void* data, int len,
                                          webrtc::RTPHeader& header) override;

  /**
   * APIs used by the registered external transport to this Conduit to
   * feed in received RTCP Frames to the VoiceEngine for decoding
   */
  MediaConduitErrorCode ReceivedRTCPPacket(const void* data, int len) override;
  Maybe<DOMHighResTimeStamp> LastRtcpReceived() const override;
  DOMHighResTimeStamp GetNow() const override { return mCall->GetNow(); }

  MediaConduitErrorCode StopTransmitting() override;
  MediaConduitErrorCode StartTransmitting() override;
  MediaConduitErrorCode StopReceiving() override;
  MediaConduitErrorCode StartReceiving() override;

  MediaConduitErrorCode StopTransmittingLocked();
  MediaConduitErrorCode StartTransmittingLocked();
  MediaConduitErrorCode StopReceivingLocked();
  MediaConduitErrorCode StartReceivingLocked();

  /**
   * Function to configure send codec for the audio session
   * @param sendSessionConfig: CodecConfiguration
   * @result: On Success, the audio engine is configured with passed in codec
   * for send On failure, audio engine transmit functionality is disabled. NOTE:
   * This API can be invoked multiple time. Invoking this API may involve
   * restarting transmission sub-system on the engine.
   */
  MediaConduitErrorCode ConfigureSendMediaCodec(
      const AudioCodecConfig* codecConfig) override;
  /**
   * Function to configure list of receive codecs for the audio session
   * @param sendSessionConfig: CodecConfiguration
   * @result: On Success, the audio engine is configured with passed in codec
   * for send Also the playout is enabled. On failure, audio engine transmit
   * functionality is disabled. NOTE: This API can be invoked multiple time.
   * Invoking this API may involve restarting transmission sub-system on the
   * engine.
   */
  MediaConduitErrorCode ConfigureRecvMediaCodecs(
      const std::vector<UniquePtr<AudioCodecConfig>>& codecConfigList) override;

  MediaConduitErrorCode SetLocalRTPExtensions(
      MediaSessionConduitLocalDirection aDirection,
      const RtpExtList& extensions) override;

  /**
   * Register External Transport to this Conduit. RTP and RTCP frames from the
   * VoiceEngine shall be passed to the registered transport for transporting
   * externally.
   */
  MediaConduitErrorCode SetTransmitterTransport(
      RefPtr<TransportInterface> aTransport) override;

  MediaConduitErrorCode SetReceiverTransport(
      RefPtr<TransportInterface> aTransport) override;

  /**
   * Function to deliver externally captured audio sample for encoding and
   * transport
   * @param audioData [in]: Pointer to array containing a frame of audio
   * @param lengthSamples [in]: Length of audio frame in samples in multiple of
   *                             10 milliseconds
   *                             Ex: Frame length is 160, 320, 440 for 16, 32,
   *                             44 kHz sampling rates respectively.
   *                             audioData[] should be of lengthSamples in
   *                             size say, for 16kz sampling rate,
   *                             audioData[] should contain 160 samples of
   *                             16-bits each for a 10m audio frame.
   * @param samplingFreqHz [in]: Frequency/rate of the sampling in Hz
   *                             ( 16000, 32000 ...)
   * @param capture_delay [in]:  Approx Delay from recording until it is
   *                             delivered to VoiceEngine in milliseconds.
   * NOTE: ConfigureSendMediaCodec() SHOULD be called before this function can
   * be invoked. This ensures the inserted audio-samples can be transmitted by
   * the conduit
   */
  MediaConduitErrorCode SendAudioFrame(const int16_t speechData[],
                                       int32_t lengthSamples,
                                       int32_t samplingFreqHz,
                                       uint32_t channels,
                                       int32_t capture_time) override;

  /**
   * Function to grab a decoded audio-sample from the media engine for
   * rendering / playoutof length 10 milliseconds.
   *
   * @param speechData [in]: Pointer to a array to which a 10ms frame of audio
   *                         will be copied
   * @param samplingFreqHz [in]: Frequency of the sampling for playback in
   *                             Hertz (16000, 32000,..)
   * @param capture_delay [in]: Estimated Time between reading of the samples
   *                            to rendering/playback
   * @param lengthSamples [in]: Contain maximum length of speechData array.
   * @param numChannels [out]: Number of channels in the audio frame,
   *                           guaranteed to be non-zero.
   * @param lengthSamples [out]: Will contain length of the audio frame in
   *                             samples at return.
   *                             Ex: A value of 160 implies 160 samples each of
   *                             16-bits was copied into speechData
   * NOTE: This function should be invoked every 10 milliseconds for the best
   * peformance
   * NOTE: ConfigureRecvMediaCodec() SHOULD be called before this function can
   * be invoked
   * This ensures the decoded samples are ready for reading and playout is
   * enabled.
   */
  MediaConduitErrorCode GetAudioFrame(int16_t speechData[],
                                      int32_t samplingFreqHz,
                                      int32_t capture_delay,
                                      size_t& numChannels,
                                      size_t& lengthSamples) override;

  /**
   * Webrtc transport implementation to send and receive RTP packet.
   * AudioConduit registers itself as ExternalTransport to the VoiceEngine
   */
  bool SendRtp(const uint8_t* data, size_t len,
               const webrtc::PacketOptions& options) override;

  /**
   * Webrtc transport implementation to send and receive RTCP packet.
   * AudioConduit registers itself as ExternalTransport to the VoiceEngine
   */
  bool SendRtcp(const uint8_t* data, size_t len) override;

  uint64_t CodecPluginID() override { return 0; }
  void SetPCHandle(const std::string& aPCHandle) override {}
  MediaConduitErrorCode DeliverPacket(const void* data, int len) override;

  void DeleteStreams() override {}

  WebrtcAudioConduit(RefPtr<WebRtcCallWrapper> aCall,
                     nsCOMPtr<nsISerialEventTarget> aStsThread)
      : mTransportMonitor("WebrtcAudioConduit"),
        mTransmitterTransport(nullptr),
        mReceiverTransport(nullptr),
        mCall(aCall),
        mRecvStreamConfig(),
        mRecvStream(nullptr),
        mSendStreamConfig(
            this)  // 'this' is stored but not  dereferenced in the constructor.
        ,
        mSendStream(nullptr),
        mRecvSSRC(0),
        mEngineTransmitting(false),
        mEngineReceiving(false),
        mRecvChannel(-1),
        mSendChannel(-1),
        mDtmfEnabled(false),
        mMutex("WebrtcAudioConduit::mMutex"),
        mRtpSourceObserver(new RtpSourceObserver(mCall->GetTimestampMaker())),
        mStsThread(aStsThread) {}

  virtual ~WebrtcAudioConduit();

  virtual MediaConduitErrorCode Init();

  int GetRecvChannel() { return mRecvChannel; }
  webrtc::VoiceEngine* GetVoiceEngine() {
    return mCall->Call()->voice_engine();
  }

  /* Set Local SSRC list.
   * Note: Until the refactor of the VoE into the call API is complete
   *   this list should contain only a single ssrc.
   */
  bool SetLocalSSRCs(const std::vector<uint32_t>& aSSRCs,
                     const std::vector<uint32_t>& aRtxSSRCs) override;
  std::vector<uint32_t> GetLocalSSRCs() override;
  bool SetRemoteSSRC(uint32_t ssrc, uint32_t rtxSsrc) override;
  bool UnsetRemoteSSRC(uint32_t ssrc) override { return true; }
  bool GetRemoteSSRC(uint32_t* ssrc) override;
  bool SetLocalCNAME(const char* cname) override;
  bool SetLocalMID(const std::string& mid) override;

  void SetSyncGroup(const std::string& group) override;

  bool GetSendPacketTypeStats(
      webrtc::RtcpPacketTypeCounter* aPacketCounts) override;

  bool GetRecvPacketTypeStats(
      webrtc::RtcpPacketTypeCounter* aPacketCounts) override;

  bool GetRTPReceiverStats(unsigned int* jitterMs,
                           unsigned int* cumulativeLost) override;
  bool GetRTCPReceiverReport(uint32_t* jitterMs, uint32_t* packetsReceived,
                             uint64_t* bytesReceived, uint32_t* cumulativeLost,
                             Maybe<double>* aOutRttSec) override;
  bool GetRTCPSenderReport(unsigned int* packetsSent, uint64_t* bytesSent,
                           DOMHighResTimeStamp* aRemoteTimestamp) override;
  Maybe<mozilla::dom::RTCBandwidthEstimationInternal> GetBandwidthEstimation()
      override;

  bool SetDtmfPayloadType(unsigned char type, int freq) override;

  bool InsertDTMFTone(int channel, int eventCode, bool outOfBand, int lengthMs,
                      int attenuationDb) override;

  void GetRtpSources(nsTArray<dom::RTCRtpSourceEntry>& outSources) override;

  void OnRtpPacket(const webrtc::RTPHeader& aRtpHeader,
                   const int64_t aTimestamp, const uint32_t aJitter) override;

  void OnRtcpBye() override;
  void OnRtcpTimeout() override;

  void SetRtcpEventObserver(mozilla::RtcpEventObserver* observer) override;

  // test-only: inserts fake CSRCs and audio level data
  void InsertAudioLevelForContributingSource(const uint32_t aCsrcSource,
                                             const int64_t aTimestamp,
                                             const uint32_t aRtpTimestamp,
                                             const bool aHasAudioLevel,
                                             const uint8_t aAudioLevel);

  bool IsSamplingFreqSupported(int freq) const override;

 protected:
  // These are protected so they can be accessed by unit tests

  // Written only on main thread. Accessed from audio thread.
  // Accessed from mStsThread during stats calls.
  // This is safe, provided audio and stats calls stop before we
  // destroy the AudioConduit.
  std::unique_ptr<webrtc::voe::ChannelProxy> mRecvChannelProxy = nullptr;

  // Written only on main thread. Accessed from mStsThread during stats calls.
  // This is safe, provided stats calls stop before we destroy the
  // AudioConduit.
  std::unique_ptr<webrtc::voe::ChannelProxy> mSendChannelProxy = nullptr;

 private:
  WebrtcAudioConduit(const WebrtcAudioConduit& other) = delete;
  void operator=(const WebrtcAudioConduit& other) = delete;

  // Function to convert between WebRTC and Conduit codec structures
  bool CodecConfigToWebRTCCodec(const AudioCodecConfig* codecInfo,
                                webrtc::AudioSendStream::Config& config);

  // Generate block size in sample lenght for a given sampling frequency
  unsigned int GetNum10msSamplesForFrequency(int samplingFreqHz) const;

  // Checks the codec to be applied
  MediaConduitErrorCode ValidateCodecConfig(const AudioCodecConfig* codecInfo,
                                            bool send);

  MediaConduitErrorCode CreateSendStream();
  void DeleteSendStream();
  MediaConduitErrorCode CreateRecvStream();
  void DeleteRecvStream();

  bool RecreateSendStreamIfExists();
  bool RecreateRecvStreamIfExists();

  MediaConduitErrorCode CreateChannels();
  virtual void DeleteChannels();

  mozilla::ReentrantMonitor mTransportMonitor;

  // Accessed on any thread under mTransportMonitor.
  RefPtr<TransportInterface> mTransmitterTransport;

  // Accessed on any thread under mTransportMonitor.
  RefPtr<TransportInterface> mReceiverTransport;

  // Accessed from main thread and audio threads. Used to create and destroy
  // channels and to send audio data. Access to channels is protected by
  // locking in channel.cc.
  ScopedCustomReleasePtr<webrtc::VoEBase> mPtrVoEBase;

  // Const so can be accessed on any thread. Most methods are called on
  // main thread.
  const RefPtr<WebRtcCallWrapper> mCall;

  // Written only on main thread. Guarded by mMutex, except for reads on main.
  webrtc::AudioReceiveStream::Config mRecvStreamConfig;

  // Written only on main thread. Guarded by mMutex, except for reads on main.
  webrtc::AudioReceiveStream* mRecvStream;

  // Written only on main thread. Guarded by mMutex, except for reads on main.
  webrtc::AudioSendStream::Config mSendStreamConfig;

  // Written only on main thread. Guarded by mMutex, except for reads on main.
  webrtc::AudioSendStream* mSendStream;

  // accessed on creation, and when receiving packets
  Atomic<uint32_t> mRecvSSRC;  // this can change during a stream!

  // Accessed only on mStsThread.
  RtpPacketQueue mRtpPacketQueue;

  // engine states of our interets
  mozilla::Atomic<bool>
      mEngineTransmitting;  // If true => VoiceEngine Send-subsystem is up
  mozilla::Atomic<bool>
      mEngineReceiving;  // If true => VoiceEngine Receive-subsystem is up
                         // and playout is enabled

  // Accessed only on main thread.
  int mRecvChannel;

  // Accessed on main thread and from audio thread.
  int mSendChannel;

  // Accessed only on main thread.
  bool mDtmfEnabled;

  Mutex mMutex;

  // Accessed from audio thread.
  webrtc::AudioFrame mAudioFrame;  // for output pulls

  // Accessed from both main and mStsThread. Uses locks internally.
  RefPtr<RtpSourceObserver> mRtpSourceObserver;

  // Socket transport service thread. Any thread.
  const nsCOMPtr<nsISerialEventTarget> mStsThread;

  // Accessed from mStsThread. Last successfully polled RTT
  Maybe<DOMHighResTimeStamp> mRttSec;

  // Accessed only on mStsThread
  Maybe<DOMHighResTimeStamp> mLastRtcpReceived;

  // Accessed only on main thread.
  mozilla::RtcpEventObserver* mRtcpEventObserver = nullptr;
};

}  // namespace mozilla

#endif