Bug 817488 Audio Send and Recv support for PC tests r=ekr
authorSuhas Nandakumar <snandaku@cisco.com>
Wed, 05 Dec 2012 13:37:32 -0800
changeset 115124 77f529436f2b3779ee1071b65f4c8d900f20cb22
parent 115123 c615b961c7b456d8bdfe1f3773f80a77d50aa3c5
child 115125 e71b89c8cc841ac3340a93db57423b1ce4530624
push id23973
push useremorley@mozilla.com
push dateThu, 06 Dec 2012 10:04:18 +0000
treeherdermozilla-central@ddda5400c826 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersekr
bugs817488
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 817488 Audio Send and Recv support for PC tests r=ekr
media/webrtc/signaling/test/FakeMediaStreams.h
media/webrtc/signaling/test/FakeMediaStreamsImpl.h
media/webrtc/signaling/test/signaling_unittests.cpp
--- a/media/webrtc/signaling/test/FakeMediaStreams.h
+++ b/media/webrtc/signaling/test/FakeMediaStreams.h
@@ -90,45 +90,83 @@ protected:
   int mCount;
 };
 
 
 class Fake_SourceMediaStream : public Fake_MediaStream {
  public:
   Fake_SourceMediaStream() : mSegmentsAdded(0),
                              mPullEnabled(false),
+                             mStop(false),
                              mPeriodic(new Fake_MediaPeriodic(this)) {}
 
   void AddTrack(mozilla::TrackID aID, mozilla::TrackRate aRate, mozilla::TrackTicks aStart,
                 mozilla::MediaSegment* aSegment) {}
 
   void AppendToTrack(mozilla::TrackID aID, mozilla::MediaSegment* aSegment) {
-    ++mSegmentsAdded;
+    bool nonZeroSample = false;
+    MOZ_ASSERT(aSegment);
+    if(aSegment->GetType() == mozilla::MediaSegment::AUDIO) {
+      //On audio segment append, we verify for validity
+      //of the audio samples.
+      mozilla::AudioSegment* audio =
+              static_cast<mozilla::AudioSegment*>(aSegment);
+      mozilla::AudioSegment::ChunkIterator iter(*audio);
+      while(!iter.IsEnded()) {
+        mozilla::AudioChunk& chunk = *(iter);
+        MOZ_ASSERT(chunk.mBuffer);
+        const int16_t* buf =
+                static_cast<const int16_t*>(chunk.mBuffer->Data());
+        for(int i=0; i<chunk.mDuration; i++) {
+          if(buf[i]) {
+            //atleast one non-zero sample found.
+            nonZeroSample = true; 
+            break;
+          }
+        }
+        //process next chunk
+        iter.Next();
+      }
+      if(nonZeroSample) {
+          //we increment segments count if
+          //atleast one non-zero samples was found.
+          ++mSegmentsAdded;
+      }
+    } else {
+      //in the case of video segment appended, we just increase the
+      //segment count.
+      ++mSegmentsAdded;
+    }
   }
 
   void AdvanceKnownTracksTime(mozilla::StreamTime aKnownTime) {}
 
   void SetPullEnabled(bool aEnabled) {
     mPullEnabled = aEnabled;
   }
+  //Don't pull anymore data,if mStop is true.
+  void StopStream() {
+   mStop = true;
+  }
 
   virtual Fake_SourceMediaStream *AsSourceStream() { return this; }
 
   virtual nsresult Start();
   virtual nsresult Stop();
 
   virtual void Periodic();
 
   virtual int GetSegmentsAdded() {
     return mSegmentsAdded;
   }
 
  protected:
   int mSegmentsAdded;
   bool mPullEnabled;
+  bool mStop;
   nsRefPtr<Fake_MediaPeriodic> mPeriodic;
   nsCOMPtr<nsITimer> mTimer;
 };
 
 
 class Fake_nsDOMMediaStream : public nsIDOMMediaStream
 {
 public:
@@ -197,19 +235,27 @@ class Fake_MediaStreamBase : public Fake
  private:
   nsCOMPtr<nsITimer> mTimer;
   nsRefPtr<Fake_MediaPeriodic> mPeriodic;
 };
 
 
 class Fake_AudioStreamSource : public Fake_MediaStreamBase {
  public:
-  Fake_AudioStreamSource() : Fake_MediaStreamBase() {}
-
+  Fake_AudioStreamSource() : Fake_MediaStreamBase(),
+                             mCount(0),
+                             mStop(false) {}
+  //Signaling Agent indicates us to stop generating
+  //further audio.
+  void StopStream() {
+    mStop = true;
+  }
   virtual void Periodic();
+  int mCount;
+  bool mStop;
 };
 
 class Fake_VideoStreamSource : public Fake_MediaStreamBase {
  public:
   Fake_VideoStreamSource() : Fake_MediaStreamBase() {}
 };
 
 
--- a/media/webrtc/signaling/test/FakeMediaStreamsImpl.h
+++ b/media/webrtc/signaling/test/FakeMediaStreamsImpl.h
@@ -5,16 +5,19 @@
 #ifndef FAKE_MEDIA_STREAMIMPL_H_
 #define FAKE_MEDIA_STREAMIMPL_H_
 
 #include "FakeMediaStreams.h"
 
 #include "nspr.h"
 #include "nsError.h"
 
+static const int AUDIO_BUFFER_SIZE = 1600;
+static const int NUM_CHANNELS      = 2;
+
 NS_IMPL_THREADSAFE_ISUPPORTS1(Fake_nsDOMMediaStream, nsIDOMMediaStream)
 
 // DOM Media stream
 NS_IMETHODIMP
 Fake_nsDOMMediaStream::GetCurrentTime(double *aCurrentTime)
 {
   PR_ASSERT(PR_FALSE);
 
@@ -37,25 +40,27 @@ nsresult Fake_SourceMediaStream::Start()
 nsresult Fake_SourceMediaStream::Stop() {
   if (mTimer)
     mTimer->Cancel();
   mPeriodic->Detach();
   return NS_OK;
 }
 
 void Fake_SourceMediaStream::Periodic() {
-  if (mPullEnabled) {
+  // Pull more audio-samples iff pulling is enabled
+  // and we are not asked by the signaling agent to stop
+  //pulling data.
+  if (mPullEnabled && !mStop) {
     for (std::set<Fake_MediaStreamListener *>::iterator it =
              mListeners.begin(); it != mListeners.end(); ++it) {
       (*it)->NotifyPull(NULL, mozilla::MillisecondsToMediaTime(10));
     }
   }
 }
 
-
 // Fake_MediaStreamBase
 nsresult Fake_MediaStreamBase::Start() {
   mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
   if (!mTimer) {
     return NS_ERROR_FAILURE;
   }
 
   mTimer->InitWithCallback(mPeriodic, 100, nsITimer::TYPE_REPEATING_SLACK);
@@ -66,21 +71,39 @@ nsresult Fake_MediaStreamBase::Start() {
 nsresult Fake_MediaStreamBase::Stop() {
   mTimer->Cancel();
 
   return NS_OK;
 }
 
 // Fake_AudioStreamSource
 void Fake_AudioStreamSource::Periodic() {
+  //Are we asked to stop pumping audio samples ?
+  if(mStop) {
+    return;
+  }
+  //Generate Signed 16 Bit Audio samples
+  nsRefPtr<mozilla::SharedBuffer> samples =
+    mozilla::SharedBuffer::Create(AUDIO_BUFFER_SIZE * NUM_CHANNELS * sizeof(int16_t));
+  for(int i=0; i<(1600*2); i++) {
+    //saw tooth audio sample
+    reinterpret_cast<int16_t *>(samples->Data())[i] =
+                              ((mCount % 8) * 4000) - (7*4000)/2;
+    mCount++;
+  }
+
   mozilla::AudioSegment segment;
   segment.Init(1);
-  segment.InsertNullDataAtStart(160);
+  segment.AppendFrames(samples.forget(),
+                       AUDIO_BUFFER_SIZE,
+                       0,
+                       AUDIO_BUFFER_SIZE,
+                       mozilla::AUDIO_FORMAT_S16);
 
-  for (std::set<Fake_MediaStreamListener *>::iterator it = mListeners.begin();
+  for(std::set<Fake_MediaStreamListener *>::iterator it = mListeners.begin();
        it != mListeners.end(); ++it) {
     (*it)->NotifyQueuedTrackChanges(NULL, // Graph
                                     0, // TrackID
                                     16000, // Rate (hz)
                                     0, // Offset TODO(ekr@rtfm.com) fix
                                     0, // ???
                                     segment);
   }
--- a/media/webrtc/signaling/test/signaling_unittests.cpp
+++ b/media/webrtc/signaling/test/signaling_unittests.cpp
@@ -672,16 +672,32 @@ void CreateAnswer(sipcc::MediaConstraint
     return streams[stream]->GetStream()->AsSourceStream()->GetSegmentsAdded();
   }
 
   int GetPacketsSent(int stream) {
     return static_cast<Fake_MediaStreamBase *>(
         domMediaStream_->GetStream())->GetSegmentsAdded();
   }
 
+  //Stops generating new audio data for transmission.
+  //Should be called before Cleanup of the peer connection.
+  void CloseSendStreams() {
+    static_cast<Fake_AudioStreamSource*>(
+        domMediaStream_->GetStream())->StopStream();
+  }
+
+  //Stops pulling audio data off the receivers.
+  //Should be called before Cleanup of the peer connection.
+  void CloseReceiveStreams() {
+    std::vector<nsDOMMediaStream *> streams =
+                            pObserver->GetStreams();
+    for(int i=0; i < streams.size(); i++) {
+      streams[i]->GetStream()->AsSourceStream()->StopStream();
+    }
+  }
 
 public:
   mozilla::RefPtr<sipcc::PeerConnectionImpl> pc;
   nsRefPtr<TestObserver> pObserver;
   char* offer_;
   char* answer_;
   nsRefPtr<nsDOMMediaStream> domMediaStream_;
 
@@ -1184,41 +1200,47 @@ TEST_F(SignalingTest, OfferAnswerDontAdd
 }
 
 TEST_F(SignalingTest, OfferModifiedAnswer)
 {
   sipcc::MediaConstraints constraints;
   OfferModifiedAnswer(constraints, constraints, SHOULD_SENDRECV_AV,
                       SHOULD_SENDRECV_AV);
   PR_Sleep(kDefaultTimeout * 2); // Wait for completion
+  a1_.CloseSendStreams();
+  a2_.CloseReceiveStreams();
 }
 
 TEST_F(SignalingTest, FullCall)
 {
   sipcc::MediaConstraints constraints;
   OfferAnswer(constraints, constraints, OFFER_AV | ANSWER_AV,
               true, SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV);
 
   PR_Sleep(kDefaultTimeout * 2); // Wait for some data to get written
 
+  a1_.CloseSendStreams();
+  a2_.CloseReceiveStreams();
   // Check that we wrote a bunch of data
   ASSERT_GE(a1_.GetPacketsSent(0), 40);
   //ASSERT_GE(a2_.GetPacketsSent(0), 40);
   //ASSERT_GE(a1_.GetPacketsReceived(0), 40);
   ASSERT_GE(a2_.GetPacketsReceived(0), 40);
 }
 
 TEST_F(SignalingTest, FullCallTrickle)
 {
   sipcc::MediaConstraints constraints;
   OfferAnswerTrickle(constraints, constraints,
                      SHOULD_SENDRECV_AV, SHOULD_SENDRECV_AV);
 
   PR_Sleep(kDefaultTimeout * 2); // Wait for some data to get written
 
+  a1_.CloseSendStreams();
+  a2_.CloseReceiveStreams();
   ASSERT_GE(a1_.GetPacketsSent(0), 40);
   ASSERT_GE(a2_.GetPacketsReceived(0), 40);
 }
 
 // This test comes from Bug 810220
 TEST_F(SignalingTest, AudioOnlyG711Call)
 {
   sipcc::MediaConstraints constraints;