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