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

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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

mercurial