media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #ifndef _PEER_CONNECTION_MEDIA_H_
michael@0 6 #define _PEER_CONNECTION_MEDIA_H_
michael@0 7
michael@0 8 #include <string>
michael@0 9 #include <vector>
michael@0 10 #include <map>
michael@0 11
michael@0 12 #include "nspr.h"
michael@0 13 #include "prlock.h"
michael@0 14
michael@0 15 #include "mozilla/RefPtr.h"
michael@0 16 #include "nsComponentManagerUtils.h"
michael@0 17
michael@0 18 #ifdef USE_FAKE_MEDIA_STREAMS
michael@0 19 #include "FakeMediaStreams.h"
michael@0 20 #else
michael@0 21 #include "DOMMediaStream.h"
michael@0 22 #include "MediaSegment.h"
michael@0 23 #endif
michael@0 24
michael@0 25 #include "AudioSegment.h"
michael@0 26
michael@0 27 #ifdef MOZILLA_INTERNAL_API
michael@0 28 #include "Layers.h"
michael@0 29 #include "VideoUtils.h"
michael@0 30 #include "ImageLayers.h"
michael@0 31 #include "VideoSegment.h"
michael@0 32 #endif
michael@0 33
michael@0 34 namespace mozilla {
michael@0 35 class DataChannel;
michael@0 36 namespace dom {
michael@0 37 class RTCInboundRTPStreamStats;
michael@0 38 class RTCOutboundRTPStreamStats;
michael@0 39 }
michael@0 40 }
michael@0 41
michael@0 42 #include "nricectx.h"
michael@0 43 #include "nriceresolver.h"
michael@0 44 #include "nricemediastream.h"
michael@0 45 #include "MediaPipeline.h"
michael@0 46
michael@0 47 namespace sipcc {
michael@0 48
michael@0 49 class PeerConnectionImpl;
michael@0 50 class PeerConnectionMedia;
michael@0 51
michael@0 52 /* Temporary for providing audio data */
michael@0 53 class Fake_AudioGenerator {
michael@0 54 public:
michael@0 55 typedef mozilla::DOMMediaStream DOMMediaStream;
michael@0 56
michael@0 57 Fake_AudioGenerator(DOMMediaStream* aStream) : mStream(aStream), mCount(0) {
michael@0 58 mTimer = do_CreateInstance("@mozilla.org/timer;1");
michael@0 59 MOZ_ASSERT(mTimer);
michael@0 60
michael@0 61 // Make a track
michael@0 62 mozilla::AudioSegment *segment = new mozilla::AudioSegment();
michael@0 63 mStream->GetStream()->AsSourceStream()->AddTrack(1, 16000, 0, segment);
michael@0 64
michael@0 65 // Set the timer
michael@0 66 mTimer->InitWithFuncCallback(Callback, this, 100, nsITimer::TYPE_REPEATING_PRECISE);
michael@0 67 }
michael@0 68
michael@0 69 static void Callback(nsITimer* timer, void *arg) {
michael@0 70 Fake_AudioGenerator* gen = static_cast<Fake_AudioGenerator*>(arg);
michael@0 71
michael@0 72 nsRefPtr<mozilla::SharedBuffer> samples = mozilla::SharedBuffer::Create(1600 * sizeof(int16_t));
michael@0 73 int16_t* data = static_cast<int16_t*>(samples->Data());
michael@0 74 for (int i=0; i<1600; i++) {
michael@0 75 data[i] = ((gen->mCount % 8) * 4000) - (7*4000)/2;
michael@0 76 ++gen->mCount;
michael@0 77 }
michael@0 78
michael@0 79 mozilla::AudioSegment segment;
michael@0 80 nsAutoTArray<const int16_t*,1> channelData;
michael@0 81 channelData.AppendElement(data);
michael@0 82 segment.AppendFrames(samples.forget(), channelData, 1600);
michael@0 83 gen->mStream->GetStream()->AsSourceStream()->AppendToTrack(1, &segment);
michael@0 84 }
michael@0 85
michael@0 86 private:
michael@0 87 nsCOMPtr<nsITimer> mTimer;
michael@0 88 nsRefPtr<DOMMediaStream> mStream;
michael@0 89 int mCount;
michael@0 90 };
michael@0 91
michael@0 92 /* Temporary for providing video data */
michael@0 93 #ifdef MOZILLA_INTERNAL_API
michael@0 94 class Fake_VideoGenerator {
michael@0 95 public:
michael@0 96 typedef mozilla::DOMMediaStream DOMMediaStream;
michael@0 97 typedef mozilla::gfx::IntSize IntSize;
michael@0 98
michael@0 99 Fake_VideoGenerator(DOMMediaStream* aStream) {
michael@0 100 mStream = aStream;
michael@0 101 mCount = 0;
michael@0 102 mTimer = do_CreateInstance("@mozilla.org/timer;1");
michael@0 103 MOZ_ASSERT(mTimer);
michael@0 104
michael@0 105 // Make a track
michael@0 106 mozilla::VideoSegment *segment = new mozilla::VideoSegment();
michael@0 107 mStream->GetStream()->AsSourceStream()->AddTrack(1, mozilla::USECS_PER_S, 0, segment);
michael@0 108 mStream->GetStream()->AsSourceStream()->AdvanceKnownTracksTime(mozilla::STREAM_TIME_MAX);
michael@0 109
michael@0 110 // Set the timer. Set to 10 fps.
michael@0 111 mTimer->InitWithFuncCallback(Callback, this, 100, nsITimer::TYPE_REPEATING_SLACK);
michael@0 112 }
michael@0 113
michael@0 114 static void Callback(nsITimer* timer, void *arg) {
michael@0 115 Fake_VideoGenerator* gen = static_cast<Fake_VideoGenerator*>(arg);
michael@0 116
michael@0 117 const uint32_t WIDTH = 640;
michael@0 118 const uint32_t HEIGHT = 480;
michael@0 119
michael@0 120 // Allocate a single blank Image
michael@0 121 nsRefPtr<mozilla::layers::ImageContainer> container =
michael@0 122 mozilla::layers::LayerManager::CreateImageContainer();
michael@0 123
michael@0 124 nsRefPtr<mozilla::layers::Image> image =
michael@0 125 container->CreateImage(mozilla::ImageFormat::PLANAR_YCBCR);
michael@0 126
michael@0 127 int len = ((WIDTH * HEIGHT) * 3 / 2);
michael@0 128 mozilla::layers::PlanarYCbCrImage* planar =
michael@0 129 static_cast<mozilla::layers::PlanarYCbCrImage*>(image.get());
michael@0 130 uint8_t* frame = (uint8_t*) PR_Malloc(len);
michael@0 131 ++gen->mCount;
michael@0 132 memset(frame, (gen->mCount / 8) & 0xff, len); // Rotating colors
michael@0 133
michael@0 134 const uint8_t lumaBpp = 8;
michael@0 135 const uint8_t chromaBpp = 4;
michael@0 136
michael@0 137 mozilla::layers::PlanarYCbCrData data;
michael@0 138 data.mYChannel = frame;
michael@0 139 data.mYSize = IntSize(WIDTH, HEIGHT);
michael@0 140 data.mYStride = (int32_t) (WIDTH * lumaBpp / 8.0);
michael@0 141 data.mCbCrStride = (int32_t) (WIDTH * chromaBpp / 8.0);
michael@0 142 data.mCbChannel = frame + HEIGHT * data.mYStride;
michael@0 143 data.mCrChannel = data.mCbChannel + HEIGHT * data.mCbCrStride / 2;
michael@0 144 data.mCbCrSize = IntSize(WIDTH / 2, HEIGHT / 2);
michael@0 145 data.mPicX = 0;
michael@0 146 data.mPicY = 0;
michael@0 147 data.mPicSize = IntSize(WIDTH, HEIGHT);
michael@0 148 data.mStereoMode = mozilla::StereoMode::MONO;
michael@0 149
michael@0 150 // SetData copies data, so we can free the frame
michael@0 151 planar->SetData(data);
michael@0 152 PR_Free(frame);
michael@0 153
michael@0 154 // AddTrack takes ownership of segment
michael@0 155 mozilla::VideoSegment *segment = new mozilla::VideoSegment();
michael@0 156 // 10 fps.
michael@0 157 segment->AppendFrame(image.forget(), mozilla::USECS_PER_S / 10,
michael@0 158 IntSize(WIDTH, HEIGHT));
michael@0 159
michael@0 160 gen->mStream->GetStream()->AsSourceStream()->AppendToTrack(1, segment);
michael@0 161 }
michael@0 162
michael@0 163 private:
michael@0 164 nsCOMPtr<nsITimer> mTimer;
michael@0 165 nsRefPtr<DOMMediaStream> mStream;
michael@0 166 int mCount;
michael@0 167 };
michael@0 168 #endif
michael@0 169
michael@0 170
michael@0 171 class SourceStreamInfo {
michael@0 172 public:
michael@0 173 typedef mozilla::DOMMediaStream DOMMediaStream;
michael@0 174
michael@0 175 SourceStreamInfo(DOMMediaStream* aMediaStream,
michael@0 176 PeerConnectionMedia *aParent)
michael@0 177 : mMediaStream(aMediaStream),
michael@0 178 mParent(aParent) {
michael@0 179 MOZ_ASSERT(mMediaStream);
michael@0 180 }
michael@0 181
michael@0 182 SourceStreamInfo(already_AddRefed<DOMMediaStream>& aMediaStream,
michael@0 183 PeerConnectionMedia *aParent)
michael@0 184 : mMediaStream(aMediaStream),
michael@0 185 mParent(aParent) {
michael@0 186 MOZ_ASSERT(mMediaStream);
michael@0 187 }
michael@0 188
michael@0 189 // This method exists for stats and the unittests.
michael@0 190 // It allows visibility into the pipelines and flows.
michael@0 191 const std::map<mozilla::TrackID, mozilla::RefPtr<mozilla::MediaPipeline>>&
michael@0 192 GetPipelines() const { return mPipelines; }
michael@0 193 mozilla::RefPtr<mozilla::MediaPipeline> GetPipelineByLevel_m(int level);
michael@0 194
michael@0 195 protected:
michael@0 196 std::map<mozilla::TrackID, mozilla::RefPtr<mozilla::MediaPipeline>> mPipelines;
michael@0 197 nsRefPtr<DOMMediaStream> mMediaStream;
michael@0 198 PeerConnectionMedia *mParent;
michael@0 199 };
michael@0 200
michael@0 201 // TODO(ekr@rtfm.com): Refactor {Local,Remote}SourceStreamInfo
michael@0 202 // bug 837539.
michael@0 203 class LocalSourceStreamInfo : public SourceStreamInfo {
michael@0 204 public:
michael@0 205 typedef mozilla::DOMMediaStream DOMMediaStream;
michael@0 206
michael@0 207 LocalSourceStreamInfo(DOMMediaStream *aMediaStream,
michael@0 208 PeerConnectionMedia *aParent)
michael@0 209 : SourceStreamInfo(aMediaStream, aParent) {}
michael@0 210
michael@0 211 ~LocalSourceStreamInfo() {
michael@0 212 mMediaStream = nullptr;
michael@0 213 }
michael@0 214
michael@0 215 DOMMediaStream* GetMediaStream() {
michael@0 216 return mMediaStream;
michael@0 217 }
michael@0 218 void StorePipeline(int aTrack, mozilla::RefPtr<mozilla::MediaPipeline> aPipeline);
michael@0 219
michael@0 220 void ExpectAudio(const mozilla::TrackID);
michael@0 221 void ExpectVideo(const mozilla::TrackID);
michael@0 222 unsigned AudioTrackCount();
michael@0 223 unsigned VideoTrackCount();
michael@0 224 void DetachTransport_s();
michael@0 225 void DetachMedia_m();
michael@0 226
michael@0 227 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(LocalSourceStreamInfo)
michael@0 228 private:
michael@0 229 nsTArray<mozilla::TrackID> mAudioTracks;
michael@0 230 nsTArray<mozilla::TrackID> mVideoTracks;
michael@0 231 };
michael@0 232
michael@0 233 class RemoteSourceStreamInfo : public SourceStreamInfo {
michael@0 234 public:
michael@0 235 typedef mozilla::DOMMediaStream DOMMediaStream;
michael@0 236
michael@0 237 RemoteSourceStreamInfo(already_AddRefed<DOMMediaStream> aMediaStream,
michael@0 238 PeerConnectionMedia *aParent)
michael@0 239 : SourceStreamInfo(aMediaStream, aParent),
michael@0 240 mTrackTypeHints(0) {}
michael@0 241
michael@0 242 DOMMediaStream* GetMediaStream() {
michael@0 243 return mMediaStream;
michael@0 244 }
michael@0 245 void StorePipeline(int aTrack, bool aIsVideo,
michael@0 246 mozilla::RefPtr<mozilla::MediaPipeline> aPipeline);
michael@0 247
michael@0 248 bool SetUsingBundle_m(int aLevel, bool decision);
michael@0 249
michael@0 250 void DetachTransport_s();
michael@0 251 void DetachMedia_m();
michael@0 252
michael@0 253 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteSourceStreamInfo)
michael@0 254
michael@0 255 public:
michael@0 256 DOMMediaStream::TrackTypeHints mTrackTypeHints;
michael@0 257 private:
michael@0 258 std::map<int, bool> mTypes;
michael@0 259 };
michael@0 260
michael@0 261 class PeerConnectionMedia : public sigslot::has_slots<> {
michael@0 262 public:
michael@0 263 PeerConnectionMedia(PeerConnectionImpl *parent);
michael@0 264 ~PeerConnectionMedia() {}
michael@0 265
michael@0 266 nsresult Init(const std::vector<mozilla::NrIceStunServer>& stun_servers,
michael@0 267 const std::vector<mozilla::NrIceTurnServer>& turn_servers);
michael@0 268 // WARNING: This destroys the object!
michael@0 269 void SelfDestruct();
michael@0 270
michael@0 271 mozilla::RefPtr<mozilla::NrIceCtx> ice_ctx() const { return mIceCtx; }
michael@0 272
michael@0 273 mozilla::RefPtr<mozilla::NrIceMediaStream> ice_media_stream(size_t i) const {
michael@0 274 // TODO(ekr@rtfm.com): If someone asks for a value that doesn't exist,
michael@0 275 // make one.
michael@0 276 if (i >= mIceStreams.size()) {
michael@0 277 return nullptr;
michael@0 278 }
michael@0 279 return mIceStreams[i];
michael@0 280 }
michael@0 281
michael@0 282 size_t num_ice_media_streams() const {
michael@0 283 return mIceStreams.size();
michael@0 284 }
michael@0 285
michael@0 286 // Add a stream
michael@0 287 nsresult AddStream(nsIDOMMediaStream* aMediaStream, uint32_t *stream_id);
michael@0 288
michael@0 289 // Remove a stream
michael@0 290 nsresult RemoveStream(nsIDOMMediaStream* aMediaStream, uint32_t *stream_id);
michael@0 291
michael@0 292 // Get a specific local stream
michael@0 293 uint32_t LocalStreamsLength()
michael@0 294 {
michael@0 295 return mLocalSourceStreams.Length();
michael@0 296 }
michael@0 297 LocalSourceStreamInfo* GetLocalStream(int index);
michael@0 298
michael@0 299 // Get a specific remote stream
michael@0 300 uint32_t RemoteStreamsLength()
michael@0 301 {
michael@0 302 return mRemoteSourceStreams.Length();
michael@0 303 }
michael@0 304 RemoteSourceStreamInfo* GetRemoteStream(int index);
michael@0 305
michael@0 306 bool SetUsingBundle_m(int level, bool decision);
michael@0 307 bool UpdateFilterFromRemoteDescription_m(
michael@0 308 int level,
michael@0 309 nsAutoPtr<mozilla::MediaPipelineFilter> filter);
michael@0 310
michael@0 311 // Add a remote stream. Returns the index in index
michael@0 312 nsresult AddRemoteStream(nsRefPtr<RemoteSourceStreamInfo> aInfo, int *aIndex);
michael@0 313 nsresult AddRemoteStreamHint(int aIndex, bool aIsVideo);
michael@0 314
michael@0 315 const nsCOMPtr<nsIThread>& GetMainThread() const { return mMainThread; }
michael@0 316 const nsCOMPtr<nsIEventTarget>& GetSTSThread() const { return mSTSThread; }
michael@0 317
michael@0 318 // Get a transport flow either RTP/RTCP for a particular stream
michael@0 319 // A stream can be of audio/video/datachannel/budled(?) types
michael@0 320 mozilla::RefPtr<mozilla::TransportFlow> GetTransportFlow(int aStreamIndex,
michael@0 321 bool aIsRtcp) {
michael@0 322 int index_inner = aStreamIndex * 2 + (aIsRtcp ? 1 : 0);
michael@0 323
michael@0 324 if (mTransportFlows.find(index_inner) == mTransportFlows.end())
michael@0 325 return nullptr;
michael@0 326
michael@0 327 return mTransportFlows[index_inner];
michael@0 328 }
michael@0 329
michael@0 330 // Add a transport flow
michael@0 331 void AddTransportFlow(int aIndex, bool aRtcp,
michael@0 332 const mozilla::RefPtr<mozilla::TransportFlow> &aFlow) {
michael@0 333 int index_inner = aIndex * 2 + (aRtcp ? 1 : 0);
michael@0 334
michael@0 335 MOZ_ASSERT(!mTransportFlows[index_inner]);
michael@0 336 mTransportFlows[index_inner] = aFlow;
michael@0 337 }
michael@0 338
michael@0 339 mozilla::RefPtr<mozilla::MediaSessionConduit> GetConduit(int aStreamIndex, bool aReceive) {
michael@0 340 int index_inner = aStreamIndex * 2 + (aReceive ? 0 : 1);
michael@0 341
michael@0 342 if (mConduits.find(index_inner) == mConduits.end())
michael@0 343 return nullptr;
michael@0 344
michael@0 345 return mConduits[index_inner];
michael@0 346 }
michael@0 347
michael@0 348 // Add a conduit
michael@0 349 void AddConduit(int aIndex, bool aReceive,
michael@0 350 const mozilla::RefPtr<mozilla::MediaSessionConduit> &aConduit) {
michael@0 351 int index_inner = aIndex * 2 + (aReceive ? 0 : 1);
michael@0 352
michael@0 353 MOZ_ASSERT(!mConduits[index_inner]);
michael@0 354 mConduits[index_inner] = aConduit;
michael@0 355 }
michael@0 356
michael@0 357 // ICE state signals
michael@0 358 sigslot::signal2<mozilla::NrIceCtx*, mozilla::NrIceCtx::GatheringState>
michael@0 359 SignalIceGatheringStateChange;
michael@0 360 sigslot::signal2<mozilla::NrIceCtx*, mozilla::NrIceCtx::ConnectionState>
michael@0 361 SignalIceConnectionStateChange;
michael@0 362
michael@0 363 private:
michael@0 364 // Shutdown media transport. Must be called on STS thread.
michael@0 365 void ShutdownMediaTransport_s();
michael@0 366
michael@0 367 // Final destruction of the media stream. Must be called on the main
michael@0 368 // thread.
michael@0 369 void SelfDestruct_m();
michael@0 370
michael@0 371 // ICE events
michael@0 372 void IceGatheringStateChange_s(mozilla::NrIceCtx* ctx,
michael@0 373 mozilla::NrIceCtx::GatheringState state);
michael@0 374 void IceConnectionStateChange_s(mozilla::NrIceCtx* ctx,
michael@0 375 mozilla::NrIceCtx::ConnectionState state);
michael@0 376 void IceStreamReady(mozilla::NrIceMediaStream *aStream);
michael@0 377
michael@0 378 void IceGatheringStateChange_m(mozilla::NrIceCtx* ctx,
michael@0 379 mozilla::NrIceCtx::GatheringState state);
michael@0 380 void IceConnectionStateChange_m(mozilla::NrIceCtx* ctx,
michael@0 381 mozilla::NrIceCtx::ConnectionState state);
michael@0 382
michael@0 383 // The parent PC
michael@0 384 PeerConnectionImpl *mParent;
michael@0 385
michael@0 386 // A list of streams returned from GetUserMedia
michael@0 387 mozilla::Mutex mLocalSourceStreamsLock;
michael@0 388 nsTArray<nsRefPtr<LocalSourceStreamInfo> > mLocalSourceStreams;
michael@0 389
michael@0 390 // A list of streams provided by the other side
michael@0 391 nsTArray<nsRefPtr<RemoteSourceStreamInfo> > mRemoteSourceStreams;
michael@0 392
michael@0 393 // ICE objects
michael@0 394 mozilla::RefPtr<mozilla::NrIceCtx> mIceCtx;
michael@0 395 std::vector<mozilla::RefPtr<mozilla::NrIceMediaStream> > mIceStreams;
michael@0 396
michael@0 397 // DNS
michael@0 398 nsRefPtr<mozilla::NrIceResolver> mDNSResolver;
michael@0 399
michael@0 400 // Transport flows: even is RTP, odd is RTCP
michael@0 401 std::map<int, mozilla::RefPtr<mozilla::TransportFlow> > mTransportFlows;
michael@0 402
michael@0 403 // Conduits: even is receive, odd is transmit (for easier correlation with
michael@0 404 // flows)
michael@0 405 std::map<int, mozilla::RefPtr<mozilla::MediaSessionConduit> > mConduits;
michael@0 406
michael@0 407 // The main thread.
michael@0 408 nsCOMPtr<nsIThread> mMainThread;
michael@0 409
michael@0 410 // The STS thread.
michael@0 411 nsCOMPtr<nsIEventTarget> mSTSThread;
michael@0 412
michael@0 413 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PeerConnectionMedia)
michael@0 414 };
michael@0 415
michael@0 416 } // namespace sipcc
michael@0 417 #endif

mercurial