1ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org/*
2ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org *
4ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org *  Use of this source code is governed by a BSD-style license
5ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org *  that can be found in the LICENSE file in the root of the source
6ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org *  tree. An additional intellectual property rights grant can be found
7ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org *  in the file PATENTS.  All contributing project authors may
8ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org */
108ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org#include <assert.h>
118ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
12e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org#include <algorithm>
13ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org#include <map>
14e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org#include <sstream>
15e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org#include <string>
16ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
17ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org#include "testing/gtest/include/gtest/gtest.h"
18ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
1924e2089750e9e51228b82d6c7ebf4fa064c797bapbos@webrtc.org#include "webrtc/call.h"
202e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org#include "webrtc/frame_callback.h"
21ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
22ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
23ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org#include "webrtc/system_wrappers/interface/event_wrapper.h"
24fa996f226ee327232b854c936d2f706aa71ff090pbos@webrtc.org#include "webrtc/system_wrappers/interface/scoped_ptr.h"
25d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org#include "webrtc/system_wrappers/interface/sleep.h"
26eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org#include "webrtc/test/call_test.h"
2724e2089750e9e51228b82d6c7ebf4fa064c797bapbos@webrtc.org#include "webrtc/test/direct_transport.h"
28e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org#include "webrtc/test/encoder_settings.h"
29e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org#include "webrtc/test/fake_audio_device.h"
3024e2089750e9e51228b82d6c7ebf4fa064c797bapbos@webrtc.org#include "webrtc/test/fake_decoder.h"
3124e2089750e9e51228b82d6c7ebf4fa064c797bapbos@webrtc.org#include "webrtc/test/fake_encoder.h"
32c33d37ce205e22c0e090b0b285ed963686bf24dcpbos@webrtc.org#include "webrtc/test/frame_generator.h"
3324e2089750e9e51228b82d6c7ebf4fa064c797bapbos@webrtc.org#include "webrtc/test/frame_generator_capturer.h"
3475e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org#include "webrtc/test/null_transport.h"
3524e2089750e9e51228b82d6c7ebf4fa064c797bapbos@webrtc.org#include "webrtc/test/rtp_rtcp_observer.h"
363adf058e962fa6f313d0fa4e6b8981407369924dpbos@webrtc.org#include "webrtc/test/testsupport/fileutils.h"
370ab271b4001169347867b4eeac3035e3442026f9andresp@webrtc.org#include "webrtc/test/testsupport/gtest_disable.h"
38e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org#include "webrtc/test/testsupport/perf_test.h"
39c33d37ce205e22c0e090b0b285ed963686bf24dcpbos@webrtc.org#include "webrtc/video/transport_adapter.h"
401c655450cf12d21bfa5b2ff277f337335149186apbos@webrtc.org#include "webrtc/video_encoder.h"
41ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
42ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.orgnamespace webrtc {
43ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
449b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.orgstatic const unsigned long kSilenceTimeoutMs = 2000;
4551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
46eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgclass EndToEndTest : public test::CallTest {
47ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org public:
48eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  EndToEndTest() {}
49ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
50eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  virtual ~EndToEndTest() {
518ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    EXPECT_EQ(NULL, send_stream_);
5288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    EXPECT_TRUE(receive_streams_.empty());
538ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  }
548ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
558ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org protected:
569b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  class UnusedTransport : public newapi::Transport {
579b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org   private:
589b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    virtual bool SendRtp(const uint8_t* packet, size_t length) OVERRIDE {
599b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      ADD_FAILURE() << "Unexpected RTP sent.";
609b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      return false;
619b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    }
629b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
639b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    virtual bool SendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
649b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      ADD_FAILURE() << "Unexpected RTCP sent.";
659b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      return false;
669b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    }
679b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  };
689b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
69c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  void DecodesRetransmittedFrame(bool retransmit_over_rtx);
708ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  void ReceivesPliAndRecovers(int rtp_history_ms);
7151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
72b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
7388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
742fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  void TestRtpStatePreservation(bool use_rtx);
75ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org};
76ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
77eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
7875e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  test::NullTransport transport;
7975e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  CreateCalls(Call::Config(&transport), Call::Config(&transport));
8075e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
81eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  CreateSendConfig(1);
82eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  CreateMatchingReceiveConfigs();
83eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
8475e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  CreateStreams();
8575e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
8688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  receive_streams_[0]->Start();
8788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  receive_streams_[0]->Start();
8875e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
8975e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  DestroyStreams();
9075e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org}
9175e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
92eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
9375e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  test::NullTransport transport;
9475e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  CreateCalls(Call::Config(&transport), Call::Config(&transport));
9575e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
96eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  CreateSendConfig(1);
97eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  CreateMatchingReceiveConfigs();
98eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
9975e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  CreateStreams();
10075e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
10188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  receive_streams_[0]->Stop();
10288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  receive_streams_[0]->Stop();
10375e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
10475e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  DestroyStreams();
10575e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org}
10675e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
107eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, RendersSingleDelayedFrame) {
108d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  static const int kWidth = 320;
109d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  static const int kHeight = 240;
110d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  // This constant is chosen to be higher than the timeout in the video_render
111d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  // module. This makes sure that frames aren't dropped if there are no other
112d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  // frames in the queue.
113d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  static const int kDelayRenderCallbackMs = 1000;
114d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
115d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  class Renderer : public VideoRenderer {
116d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org   public:
117d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    Renderer() : event_(EventWrapper::Create()) {}
118d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
119d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    virtual void RenderFrame(const I420VideoFrame& video_frame,
120d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org                             int /*time_to_render_ms*/) OVERRIDE {
121d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org      event_->Set();
122d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    }
123d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
124d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
125d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
126d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    scoped_ptr<EventWrapper> event_;
127d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  } renderer;
128d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
129d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  class TestFrameCallback : public I420FrameCallback {
130d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org   public:
131d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    TestFrameCallback() : event_(EventWrapper::Create()) {}
132d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
133d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
134d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
135d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org   private:
136c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE {
137d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org      SleepMs(kDelayRenderCallbackMs);
138d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org      event_->Set();
139d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    }
140d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
141d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    scoped_ptr<EventWrapper> event_;
142d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  };
143d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
144d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  test::DirectTransport sender_transport, receiver_transport;
145d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
146d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  CreateCalls(Call::Config(&sender_transport),
147d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org              Call::Config(&receiver_transport));
148d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
149d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  sender_transport.SetReceiver(receiver_call_->Receiver());
150d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  receiver_transport.SetReceiver(sender_call_->Receiver());
151d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
152eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  CreateSendConfig(1);
153eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  CreateMatchingReceiveConfigs();
154d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
155d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  TestFrameCallback pre_render_callback;
15688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  receive_configs_[0].pre_render_callback = &pre_render_callback;
15788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  receive_configs_[0].renderer = &renderer;
158d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
159d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  CreateStreams();
16088b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  Start();
161d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
162d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  // Create frames that are smaller than the send width/height, this is done to
163d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  // check that the callbacks are done after processing video.
164d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  scoped_ptr<test::FrameGenerator> frame_generator(
165d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org      test::FrameGenerator::Create(kWidth, kHeight));
166d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
167d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
168d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org      << "Timed out while waiting for pre-render callback.";
169d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  EXPECT_EQ(kEventSignaled, renderer.Wait())
170d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org      << "Timed out while waiting for the frame to render.";
171d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
17288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  Stop();
173d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
174d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  sender_transport.StopSending();
175d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  receiver_transport.StopSending();
176d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
177d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  DestroyStreams();
178d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org}
179d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
180eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, TransmitsFirstFrame) {
181c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  class Renderer : public VideoRenderer {
182c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org   public:
183c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org    Renderer() : event_(EventWrapper::Create()) {}
184c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
185c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org    virtual void RenderFrame(const I420VideoFrame& video_frame,
186c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org                             int /*time_to_render_ms*/) OVERRIDE {
187c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org      event_->Set();
188c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org    }
189c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
190c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
191c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
192c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org    scoped_ptr<EventWrapper> event_;
193c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  } renderer;
194c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
195c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  test::DirectTransport sender_transport, receiver_transport;
196c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
197c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  CreateCalls(Call::Config(&sender_transport),
198c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org              Call::Config(&receiver_transport));
199c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
200c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  sender_transport.SetReceiver(receiver_call_->Receiver());
201c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  receiver_transport.SetReceiver(sender_call_->Receiver());
202c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
203eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  CreateSendConfig(1);
204eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  CreateMatchingReceiveConfigs();
20588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  receive_configs_[0].renderer = &renderer;
206c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
207c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  CreateStreams();
20888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  Start();
209c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
210c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
21158b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org      encoder_config_.streams[0].width, encoder_config_.streams[0].height));
212c33d37ce205e22c0e090b0b285ed963686bf24dcpbos@webrtc.org  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
213c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
214c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  EXPECT_EQ(kEventSignaled, renderer.Wait())
215c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org      << "Timed out while waiting for the frame to render.";
216c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
21788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  Stop();
218c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
219c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  sender_transport.StopSending();
220c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  receiver_transport.StopSending();
221c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
222c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  DestroyStreams();
223c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org}
224c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
225617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.orgTEST_F(EndToEndTest, SendsAndReceivesH264) {
226617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org  class H264Observer : public test::EndToEndTest, public VideoRenderer {
227617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org   public:
228617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org    H264Observer()
229617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org        : EndToEndTest(2 * kDefaultTimeoutMs),
230617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org          fake_encoder_(Clock::GetRealTimeClock()),
231617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org          frame_counter_(0) {}
232617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org
233617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org    virtual void PerformTest() OVERRIDE {
234617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org      EXPECT_EQ(kEventSignaled, Wait())
235617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org          << "Timed out while waiting for enough frames to be decoded.";
236617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org    }
237617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org
238617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org    virtual void ModifyConfigs(
239617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org        VideoSendStream::Config* send_config,
240617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org        std::vector<VideoReceiveStream::Config>* receive_configs,
24158b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        VideoEncoderConfig* encoder_config) OVERRIDE {
242617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org      send_config->encoder_settings.encoder = &fake_encoder_;
243617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org      send_config->encoder_settings.payload_name = "H264";
244617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org      send_config->encoder_settings.payload_type = kFakeSendPayloadType;
24558b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org      encoder_config->streams[0].min_bitrate_bps = 50000;
24658b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org      encoder_config->streams[0].target_bitrate_bps =
24758b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org          encoder_config->streams[0].max_bitrate_bps = 2000000;
248617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org
249617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org      (*receive_configs)[0].renderer = this;
250617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org      VideoCodec codec =
251617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org          test::CreateDecoderVideoCodec(send_config->encoder_settings);
252617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org      (*receive_configs)[0].codecs.resize(1);
253617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org      (*receive_configs)[0].codecs[0] = codec;
254617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org      (*receive_configs)[0].external_decoders.resize(1);
255617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org      (*receive_configs)[0].external_decoders[0].payload_type =
256617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org          send_config->encoder_settings.payload_type;
257617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org      (*receive_configs)[0].external_decoders[0].decoder = &fake_decoder_;
258617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org    }
259617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org
260617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org    virtual void RenderFrame(const I420VideoFrame& video_frame,
261617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org                             int time_to_render_ms) OVERRIDE {
262617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org      const int kRequiredFrames = 500;
263617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org      if (++frame_counter_ == kRequiredFrames)
264617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org        observation_complete_->Set();
265617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org    }
266617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org
267617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org   private:
268617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org    test::FakeH264Decoder fake_decoder_;
269617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org    test::FakeH264Encoder fake_encoder_;
270617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org    int frame_counter_;
271617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org  } test;
272617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org
273617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org  RunBaseTest(&test);
274617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org}
275617e272fea14f31c0b32aa6c47afc81dbb65697bstefan@webrtc.org
276eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
277eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  class SyncRtcpObserver : public test::EndToEndTest {
2784b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org   public:
279eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
2804b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
2814b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org    virtual Action OnReceiveRtcp(const uint8_t* packet,
2824b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org                                 size_t length) OVERRIDE {
2834b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      RTCPUtility::RTCPParserV2 parser(packet, length, true);
2844b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      EXPECT_TRUE(parser.IsValid());
2854b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      uint32_t ssrc = 0;
2864b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      ssrc |= static_cast<uint32_t>(packet[4]) << 24;
2874b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      ssrc |= static_cast<uint32_t>(packet[5]) << 16;
2884b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      ssrc |= static_cast<uint32_t>(packet[6]) << 8;
2894b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      ssrc |= static_cast<uint32_t>(packet[7]) << 0;
2904b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      EXPECT_EQ(kReceiverLocalSsrc, ssrc);
2914b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      observation_complete_->Set();
2924b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
2934b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      return SEND_PACKET;
2944b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org    }
2954b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
296eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void PerformTest() OVERRIDE {
297eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      EXPECT_EQ(kEventSignaled, Wait())
298eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          << "Timed out while waiting for a receiver RTCP packet to be sent.";
299eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
300eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  } test;
3014b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
302eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  RunBaseTest(&test);
303eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org}
3044b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
305eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
306eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  static const int kNumberOfNacksToObserve = 2;
307eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  static const int kLossBurstSize = 2;
308eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  static const int kPacketsBetweenLossBursts = 9;
309eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  class NackObserver : public test::EndToEndTest {
310eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org   public:
311eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    NackObserver()
312eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        : EndToEndTest(kLongTimeoutMs),
313eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          rtp_parser_(RtpHeaderParser::Create()),
314eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          sent_rtp_packets_(0),
315eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          packets_left_to_drop_(0),
316eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          nacks_left_(kNumberOfNacksToObserve) {}
3174b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
318eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org   private:
319eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
320eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      RTPHeader header;
3216aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      EXPECT_TRUE(rtp_parser_->Parse(packet, length, &header));
322eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
323eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      // Never drop retransmitted packets.
324eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      if (dropped_packets_.find(header.sequenceNumber) !=
325eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          dropped_packets_.end()) {
326eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        retransmitted_packets_.insert(header.sequenceNumber);
327eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        if (nacks_left_ == 0 &&
328eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org            retransmitted_packets_.size() == dropped_packets_.size()) {
329eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          observation_complete_->Set();
330eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        }
331eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        return SEND_PACKET;
332eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      }
3334b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
334eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      ++sent_rtp_packets_;
3354b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
336eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      // Enough NACKs received, stop dropping packets.
337eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      if (nacks_left_ == 0)
338eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        return SEND_PACKET;
3394b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
340eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      // Check if it's time for a new loss burst.
341eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
342eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        packets_left_to_drop_ = kLossBurstSize;
343ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
344eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      if (packets_left_to_drop_ > 0) {
345eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        --packets_left_to_drop_;
346eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        dropped_packets_.insert(header.sequenceNumber);
347eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        return DROP_PACKET;
348eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      }
349ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
350eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      return SEND_PACKET;
351eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
3528ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
353eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual Action OnReceiveRtcp(const uint8_t* packet,
354eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org                                 size_t length) OVERRIDE {
355eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      RTCPUtility::RTCPParserV2 parser(packet, length, true);
356eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      EXPECT_TRUE(parser.IsValid());
357ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
358eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
359eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
360eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        if (packet_type == RTCPUtility::kRtcpRtpfbNackCode) {
361eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          --nacks_left_;
362eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          break;
363eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        }
364eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        packet_type = parser.Iterate();
365eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      }
366eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      return SEND_PACKET;
367eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
368ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
369eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void ModifyConfigs(
370eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        VideoSendStream::Config* send_config,
37188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        std::vector<VideoReceiveStream::Config>* receive_configs,
37258b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        VideoEncoderConfig* encoder_config) OVERRIDE {
373eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
37488b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
375eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
3768ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
377eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void PerformTest() OVERRIDE {
378eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      EXPECT_EQ(kEventSignaled, Wait())
379eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          << "Timed out waiting for packets to be NACKed, retransmitted and "
380eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org             "rendered.";
381eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
3828ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
383eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    scoped_ptr<RtpHeaderParser> rtp_parser_;
384eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    std::set<uint16_t> dropped_packets_;
385eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    std::set<uint16_t> retransmitted_packets_;
386eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    uint64_t sent_rtp_packets_;
387eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    int packets_left_to_drop_;
388eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    int nacks_left_;
389eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  } test;
390ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
391eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  RunBaseTest(&test);
392ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org}
393ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
394fb3f14e334ffeeeea5c9f6666b02dfdcdb268375pbos@webrtc.org// TODO(pbos): Flaky, webrtc:3269
395eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, DISABLED_CanReceiveFec) {
396eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  class FecRenderObserver : public test::EndToEndTest, public VideoRenderer {
397ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org   public:
398ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org    FecRenderObserver()
399eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        : EndToEndTest(kDefaultTimeoutMs),
400ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          state_(kFirstPacket),
401ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          protected_sequence_number_(0),
402ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          protected_frame_timestamp_(0) {}
403ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
404ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org   private:
405c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE
406c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org        EXCLUSIVE_LOCKS_REQUIRED(crit_) {
407ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      RTPHeader header;
4086aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      EXPECT_TRUE(parser_->Parse(packet, length, &header));
409ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
410ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      EXPECT_EQ(kRedPayloadType, header.payloadType);
411ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      int encapsulated_payload_type =
412ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          static_cast<int>(packet[header.headerLength]);
413eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      if (encapsulated_payload_type != kFakeSendPayloadType)
414ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org        EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
415ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
416eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      switch (state_) {
417ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org        case kFirstPacket:
418ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          state_ = kDropEveryOtherPacketUntilFec;
419ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          break;
420ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org        case kDropEveryOtherPacketUntilFec:
421ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          if (encapsulated_payload_type == kUlpfecPayloadType) {
422ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org            state_ = kDropNextMediaPacket;
423ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org            return SEND_PACKET;
424ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          }
425ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          if (header.sequenceNumber % 2 == 0)
426ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org            return DROP_PACKET;
427ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          break;
428ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org        case kDropNextMediaPacket:
429eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          if (encapsulated_payload_type == kFakeSendPayloadType) {
430ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org            protected_sequence_number_ = header.sequenceNumber;
431ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org            protected_frame_timestamp_ = header.timestamp;
432ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org            state_ = kProtectedPacketDropped;
433ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org            return DROP_PACKET;
434ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          }
435ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          break;
436ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org        case kProtectedPacketDropped:
437ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          EXPECT_NE(header.sequenceNumber, protected_sequence_number_)
438ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org              << "Protected packet retransmitted. Should not happen with FEC.";
439ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          break;
440ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      }
441ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
442ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      return SEND_PACKET;
443ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org    }
444ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
445ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org    virtual void RenderFrame(const I420VideoFrame& video_frame,
446ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org                             int time_to_render_ms) OVERRIDE {
447c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org      CriticalSectionScoped lock(crit_.get());
448ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      // Rendering frame with timestamp associated with dropped packet -> FEC
449ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      // protection worked.
450ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      if (state_ == kProtectedPacketDropped &&
451ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          video_frame.timestamp() == protected_frame_timestamp_) {
452ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org        observation_complete_->Set();
453ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      }
454ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org    }
455ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
456ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org    enum {
457ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      kFirstPacket,
458ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      kDropEveryOtherPacketUntilFec,
459ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      kDropNextMediaPacket,
460ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      kProtectedPacketDropped,
461ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org    } state_;
462ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
463eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void ModifyConfigs(
464eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        VideoSendStream::Config* send_config,
46588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        std::vector<VideoReceiveStream::Config>* receive_configs,
46658b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        VideoEncoderConfig* encoder_config) OVERRIDE {
467eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
468eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      // int rtp_history_ms = 1000;
46988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
470eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
471eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      send_config->rtp.fec.red_payload_type = kRedPayloadType;
472eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
473eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
47488b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
47588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
47688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      (*receive_configs)[0].renderer = this;
477eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
478ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
479eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void PerformTest() OVERRIDE {
480eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      EXPECT_EQ(kEventSignaled, Wait())
481eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          << "Timed out while waiting for retransmitted NACKed frames to be "
482eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org             "rendered again.";
483eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
484ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
485eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    uint32_t protected_sequence_number_ GUARDED_BY(crit_);
486eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    uint32_t protected_frame_timestamp_ GUARDED_BY(crit_);
487eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  } test;
488618a0ec1d2c17d485b7ce51cbfd282e6bae8e019pbos@webrtc.org
489eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  RunBaseTest(&test);
4908ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org}
491ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
492c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org// This test drops second RTP packet with a marker bit set, makes sure it's
493c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org// retransmitted and renders. Retransmission SSRCs are also checked.
494eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgvoid EndToEndTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) {
495c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  static const int kDroppedFrameNumber = 2;
496eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  class RetransmissionObserver : public test::EndToEndTest,
497c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org                                 public I420FrameCallback {
498c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org   public:
499eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    explicit RetransmissionObserver(bool expect_rtx)
500eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        : EndToEndTest(kDefaultTimeoutMs),
5012fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org          retransmission_ssrc_(expect_rtx ? kSendRtxSsrcs[0] : kSendSsrcs[0]),
502c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org          retransmission_payload_type_(expect_rtx ? kSendRtxPayloadType
503eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org                                                  : kFakeSendPayloadType),
504c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org          marker_bits_observed_(0),
505c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org          retransmitted_timestamp_(0),
506c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org          frame_retransmitted_(false) {}
507c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
508c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org   private:
509c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
510c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      RTPHeader header;
5116aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      EXPECT_TRUE(parser_->Parse(packet, length, &header));
512c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
513c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      if (header.timestamp == retransmitted_timestamp_) {
514c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        EXPECT_EQ(retransmission_ssrc_, header.ssrc);
515c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        EXPECT_EQ(retransmission_payload_type_, header.payloadType);
516c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        frame_retransmitted_ = true;
517c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        return SEND_PACKET;
518c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      }
519c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
520eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      EXPECT_EQ(kSendSsrcs[0], header.ssrc);
521eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      EXPECT_EQ(kFakeSendPayloadType, header.payloadType);
522c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
523c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      // Found the second frame's final packet, drop this and expect a
524c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      // retransmission.
525c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
526c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        retransmitted_timestamp_ = header.timestamp;
527c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        return DROP_PACKET;
528c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      }
529c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
530c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      return SEND_PACKET;
531c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    }
532c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
533c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE {
534c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org      CriticalSectionScoped lock(crit_.get());
535c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      if (frame->timestamp() == retransmitted_timestamp_) {
536c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        EXPECT_TRUE(frame_retransmitted_);
537c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        observation_complete_->Set();
538c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      }
539c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    }
540c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
541eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void ModifyConfigs(
542eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        VideoSendStream::Config* send_config,
54388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        std::vector<VideoReceiveStream::Config>* receive_configs,
54458b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        VideoEncoderConfig* encoder_config) OVERRIDE {
545eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
54688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      (*receive_configs)[0].pre_render_callback = this;
54788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
5482fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
5492fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
550eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
5512fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        (*receive_configs)[0].rtp.rtx[kSendRtxPayloadType].ssrc =
5522fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org            kSendRtxSsrcs[0];
55388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        (*receive_configs)[0].rtp.rtx[kSendRtxPayloadType].payload_type =
554eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org            kSendRtxPayloadType;
555eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      }
556eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
557eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
558eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void PerformTest() OVERRIDE {
559eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      EXPECT_EQ(kEventSignaled, Wait())
560eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          << "Timed out while waiting for retransmission to render.";
561eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
562eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
563c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    const uint32_t retransmission_ssrc_;
564c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    const int retransmission_payload_type_;
565c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    int marker_bits_observed_;
566c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    uint32_t retransmitted_timestamp_;
567c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    bool frame_retransmitted_;
568eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  } test(retransmit_over_rtx);
569c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
570eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  RunBaseTest(&test);
571c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org}
572c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
573eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, DecodesRetransmittedFrame) {
574c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  DecodesRetransmittedFrame(false);
575c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org}
576c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
577eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
578c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  DecodesRetransmittedFrame(true);
579c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org}
580c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
58129c4d870efc8877b99ee583e8904cfba3d654b10andresp@webrtc.orgTEST_F(EndToEndTest, UsesFrameCallbacks) {
58263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  static const int kWidth = 320;
58363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  static const int kHeight = 240;
58463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
58563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  class Renderer : public VideoRenderer {
58663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org   public:
58763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    Renderer() : event_(EventWrapper::Create()) {}
58863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
58963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    virtual void RenderFrame(const I420VideoFrame& video_frame,
59063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org                             int /*time_to_render_ms*/) OVERRIDE {
59163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      EXPECT_EQ(0, *video_frame.buffer(kYPlane))
59263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org          << "Rendered frame should have zero luma which is applied by the "
59363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org             "pre-render callback.";
59463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      event_->Set();
59563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    }
59663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
59763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
59863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    scoped_ptr<EventWrapper> event_;
59963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  } renderer;
60063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
60163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  class TestFrameCallback : public I420FrameCallback {
60263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org   public:
60363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    TestFrameCallback(int expected_luma_byte, int next_luma_byte)
60463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org        : event_(EventWrapper::Create()),
60563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org          expected_luma_byte_(expected_luma_byte),
60663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org          next_luma_byte_(next_luma_byte) {}
60763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
60863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
60963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
61063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org   private:
61163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    virtual void FrameCallback(I420VideoFrame* frame) {
61263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      EXPECT_EQ(kWidth, frame->width())
61363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org          << "Width not as expected, callback done before resize?";
61463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      EXPECT_EQ(kHeight, frame->height())
61563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org          << "Height not as expected, callback done before resize?";
61663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
61763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      // Previous luma specified, observed luma should be fairly close.
61863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      if (expected_luma_byte_ != -1) {
61963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org        EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
62063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      }
62163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
62263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      memset(frame->buffer(kYPlane),
62363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org             next_luma_byte_,
62463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org             frame->allocated_size(kYPlane));
62563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
62663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      event_->Set();
62763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    }
62863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
62963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    scoped_ptr<EventWrapper> event_;
63063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    int expected_luma_byte_;
63163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    int next_luma_byte_;
63263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  };
63363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
63463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  TestFrameCallback pre_encode_callback(-1, 255);  // Changes luma to 255.
63563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  TestFrameCallback pre_render_callback(255, 0);  // Changes luma from 255 to 0.
63663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
63763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  test::DirectTransport sender_transport, receiver_transport;
63863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
63963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  CreateCalls(Call::Config(&sender_transport),
64063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org              Call::Config(&receiver_transport));
64163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
64263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  sender_transport.SetReceiver(receiver_call_->Receiver());
64363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  receiver_transport.SetReceiver(sender_call_->Receiver());
64463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
645eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  CreateSendConfig(1);
6461c655450cf12d21bfa5b2ff277f337335149186apbos@webrtc.org  scoped_ptr<VideoEncoder> encoder(
6471c655450cf12d21bfa5b2ff277f337335149186apbos@webrtc.org      VideoEncoder::Create(VideoEncoder::kVp8));
648e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org  send_config_.encoder_settings.encoder = encoder.get();
649e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org  send_config_.encoder_settings.payload_name = "VP8";
65058b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org  ASSERT_EQ(1u, encoder_config_.streams.size()) << "Test setup error.";
65158b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org  encoder_config_.streams[0].width = kWidth;
65258b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org  encoder_config_.streams[0].height = kHeight;
65363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  send_config_.pre_encode_callback = &pre_encode_callback;
654eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
655eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  CreateMatchingReceiveConfigs();
65688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  receive_configs_[0].pre_render_callback = &pre_render_callback;
65788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  receive_configs_[0].renderer = &renderer;
65863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
65963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  CreateStreams();
66088b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  Start();
66163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
66263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  // Create frames that are smaller than the send width/height, this is done to
66363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  // check that the callbacks are done after processing video.
66463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  scoped_ptr<test::FrameGenerator> frame_generator(
66563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      test::FrameGenerator::Create(kWidth / 2, kHeight / 2));
666c33d37ce205e22c0e090b0b285ed963686bf24dcpbos@webrtc.org  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
66763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
66863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  EXPECT_EQ(kEventSignaled, pre_encode_callback.Wait())
66963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      << "Timed out while waiting for pre-encode callback.";
67063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
67163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      << "Timed out while waiting for pre-render callback.";
67263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  EXPECT_EQ(kEventSignaled, renderer.Wait())
67363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      << "Timed out while waiting for the frame to render.";
67463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
67588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  Stop();
67663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
67763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  sender_transport.StopSending();
67863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  receiver_transport.StopSending();
67963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
68063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  DestroyStreams();
68163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org}
68263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
683eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgvoid EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
684eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  static const int kPacketsToDrop = 1;
6858ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
686eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  class PliObserver : public test::EndToEndTest, public VideoRenderer {
687eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org   public:
688eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    explicit PliObserver(int rtp_history_ms)
689eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        : EndToEndTest(kLongTimeoutMs),
690eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          rtp_history_ms_(rtp_history_ms),
691eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          nack_enabled_(rtp_history_ms > 0),
692eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          highest_dropped_timestamp_(0),
693eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          frames_to_drop_(0),
694eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          received_pli_(false) {}
695ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
696eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org   private:
697eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
698eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      RTPHeader header;
6996aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      EXPECT_TRUE(parser_->Parse(packet, length, &header));
7008ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
701eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      // Drop all retransmitted packets to force a PLI.
702eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      if (header.timestamp <= highest_dropped_timestamp_)
703eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        return DROP_PACKET;
7048ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
705eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      if (frames_to_drop_ > 0) {
706eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        highest_dropped_timestamp_ = header.timestamp;
707eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        --frames_to_drop_;
708eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        return DROP_PACKET;
7098ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org      }
710ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
711eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      return SEND_PACKET;
7128ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    }
7136c172c5af42b2d10e71b12ef0ed74864dce1ecfdmflodman@webrtc.org
714eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual Action OnReceiveRtcp(const uint8_t* packet,
715eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org                                 size_t length) OVERRIDE {
716eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      RTCPUtility::RTCPParserV2 parser(packet, length, true);
717eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      EXPECT_TRUE(parser.IsValid());
718ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
719eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
720eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org           packet_type != RTCPUtility::kRtcpNotValidCode;
721eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org           packet_type = parser.Iterate()) {
722eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        if (!nack_enabled_)
723eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          EXPECT_NE(packet_type, RTCPUtility::kRtcpRtpfbNackCode);
724ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
725eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        if (packet_type == RTCPUtility::kRtcpPsfbPliCode) {
726eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          received_pli_ = true;
727eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          break;
728eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        }
729eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      }
730eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      return SEND_PACKET;
731eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
732ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
733eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void RenderFrame(const I420VideoFrame& video_frame,
734eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org                             int time_to_render_ms) OVERRIDE {
735eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      CriticalSectionScoped lock(crit_.get());
736eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      if (received_pli_ &&
737eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          video_frame.timestamp() > highest_dropped_timestamp_) {
738eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        observation_complete_->Set();
739eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      }
740eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      if (!received_pli_)
741eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        frames_to_drop_ = kPacketsToDrop;
742eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
743ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
744eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void ModifyConfigs(
745eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        VideoSendStream::Config* send_config,
74688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        std::vector<VideoReceiveStream::Config>* receive_configs,
74758b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        VideoEncoderConfig* encoder_config) OVERRIDE {
748eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
74988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
75088b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      (*receive_configs)[0].renderer = this;
751eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
752ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
753eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void PerformTest() OVERRIDE {
754eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      EXPECT_EQ(kEventSignaled, Wait()) << "Timed out waiting for PLI to be "
755eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org                                           "received and a frame to be "
756eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org                                           "rendered afterwards.";
757eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
7588ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
759eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    int rtp_history_ms_;
760eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    bool nack_enabled_;
761eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    uint32_t highest_dropped_timestamp_;
762eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    int frames_to_drop_;
763eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    bool received_pli_;
764eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  } test(rtp_history_ms);
765618a0ec1d2c17d485b7ce51cbfd282e6bae8e019pbos@webrtc.org
766eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  RunBaseTest(&test);
767ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org}
768ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
769eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
7708ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  ReceivesPliAndRecovers(1000);
7718ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org}
7728ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
7738ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org// TODO(pbos): Enable this when 2250 is resolved.
774eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, DISABLED_ReceivesPliAndRecoversWithoutNack) {
7758ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  ReceivesPliAndRecovers(0);
7768ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org}
7778ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
778eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
7790020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  class PacketInputObserver : public PacketReceiver {
7800020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org   public:
7810020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org    explicit PacketInputObserver(PacketReceiver* receiver)
7820020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org        : receiver_(receiver), delivered_packet_(EventWrapper::Create()) {}
7830020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
78451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    EventTypeWrapper Wait() {
78551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      return delivered_packet_->Wait(kDefaultTimeoutMs);
78651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    }
7870020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
7880020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org   private:
789bc57e0f1a00227c0cec3d429fc58cc442d07b509pbos@webrtc.org    virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
790bc57e0f1a00227c0cec3d429fc58cc442d07b509pbos@webrtc.org                                         size_t length) OVERRIDE {
7916aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      if (RtpHeaderParser::IsRtcp(packet, length)) {
7920020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org        return receiver_->DeliverPacket(packet, length);
7930020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org      } else {
794bc57e0f1a00227c0cec3d429fc58cc442d07b509pbos@webrtc.org        DeliveryStatus delivery_status =
795bc57e0f1a00227c0cec3d429fc58cc442d07b509pbos@webrtc.org            receiver_->DeliverPacket(packet, length);
796bc57e0f1a00227c0cec3d429fc58cc442d07b509pbos@webrtc.org        EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
7970020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org        delivered_packet_->Set();
798bc57e0f1a00227c0cec3d429fc58cc442d07b509pbos@webrtc.org        return delivery_status;
7990020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org      }
8000020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org    }
8010020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8020020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org    PacketReceiver* receiver_;
8030020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org    scoped_ptr<EventWrapper> delivered_packet_;
8040020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  };
8050020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8060020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  test::DirectTransport send_transport, receive_transport;
8070020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
808b5d2d165c78331b337bc372babc3a1a3e62172afpbos@webrtc.org  CreateCalls(Call::Config(&send_transport), Call::Config(&receive_transport));
8090020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  PacketInputObserver input_observer(receiver_call_->Receiver());
8100020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8110020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  send_transport.SetReceiver(&input_observer);
8120020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  receive_transport.SetReceiver(sender_call_->Receiver());
8130020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
814eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  CreateSendConfig(1);
815eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  CreateMatchingReceiveConfigs();
8160020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8170020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  CreateStreams();
81888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  CreateFrameGeneratorCapturer();
81988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  Start();
8200020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
82188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  receiver_call_->DestroyVideoReceiveStream(receive_streams_[0]);
82288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  receive_streams_.clear();
8230020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8240020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  // Wait() waits for a received packet.
8250020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  EXPECT_EQ(kEventSignaled, input_observer.Wait());
8260020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
82788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  Stop();
8280020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8290020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  DestroyStreams();
8300020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8310020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  send_transport.StopSending();
8320020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  receive_transport.StopSending();
8330020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org}
834c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
835eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgvoid EndToEndTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) {
83651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  static const int kNumCompoundRtcpPacketsToObserve = 10;
837eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  class RtcpModeObserver : public test::EndToEndTest {
83851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org   public:
839d05597a15dd2d01c8e172df86b960b7d4ac9647fpbos@webrtc.org    explicit RtcpModeObserver(newapi::RtcpMode rtcp_mode)
840eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        : EndToEndTest(kDefaultTimeoutMs),
84151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          rtcp_mode_(rtcp_mode),
84251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          sent_rtp_(0),
84351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          sent_rtcp_(0) {}
84451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
84551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org   private:
84651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
84751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      if (++sent_rtp_ % 3 == 0)
84851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org        return DROP_PACKET;
84951e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
85051e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      return SEND_PACKET;
85151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    }
85251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
85351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    virtual Action OnReceiveRtcp(const uint8_t* packet,
85451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org                                 size_t length) OVERRIDE {
85551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      ++sent_rtcp_;
85651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      RTCPUtility::RTCPParserV2 parser(packet, length, true);
85751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      EXPECT_TRUE(parser.IsValid());
85851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
85951e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
86051e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      bool has_report_block = false;
86151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
86251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org        EXPECT_NE(RTCPUtility::kRtcpSrCode, packet_type);
86351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org        if (packet_type == RTCPUtility::kRtcpRrCode) {
86451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          has_report_block = true;
86551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          break;
86651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org        }
86751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org        packet_type = parser.Iterate();
86851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      }
86951e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
87051e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      switch (rtcp_mode_) {
87151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org        case newapi::kRtcpCompound:
87251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          if (!has_report_block) {
87351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org            ADD_FAILURE() << "Received RTCP packet without receiver report for "
87451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org                             "kRtcpCompound.";
87551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org            observation_complete_->Set();
87651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          }
87751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
87851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
87951e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org            observation_complete_->Set();
88051e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
88151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          break;
88251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org        case newapi::kRtcpReducedSize:
88351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          if (!has_report_block)
88451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org            observation_complete_->Set();
88551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          break;
88651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      }
88751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
88851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      return SEND_PACKET;
88951e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    }
89051e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
891eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void ModifyConfigs(
892eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        VideoSendStream::Config* send_config,
89388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        std::vector<VideoReceiveStream::Config>* receive_configs,
89458b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        VideoEncoderConfig* encoder_config) OVERRIDE {
895eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
89688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
89788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
898eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
899eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
900eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void PerformTest() OVERRIDE {
901eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      EXPECT_EQ(kEventSignaled, Wait())
902eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          << (rtcp_mode_ == newapi::kRtcpCompound
903eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org                  ? "Timed out before observing enough compound packets."
904eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org                  : "Timed out before receiving a non-compound RTCP packet.");
905eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
906eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
90751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    newapi::RtcpMode rtcp_mode_;
90851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    int sent_rtp_;
90951e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    int sent_rtcp_;
910eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  } test(rtcp_mode);
91151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
912eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  RunBaseTest(&test);
91351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org}
91451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
915eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, UsesRtcpCompoundMode) {
91651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  RespectsRtcpMode(newapi::kRtcpCompound);
91751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org}
91851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
919eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
92051e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  RespectsRtcpMode(newapi::kRtcpReducedSize);
92151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org}
92251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
923c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org// Test sets up a Call multiple senders with different resolutions and SSRCs.
924c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org// Another is set up to receive all three of these with different renderers.
925c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org// Each renderer verifies that it receives the expected resolution, and as soon
926c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org// as every renderer has received a frame, the test finishes.
92729c4d870efc8877b99ee583e8904cfba3d654b10andresp@webrtc.orgTEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
928c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  static const size_t kNumStreams = 3;
929c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
930c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  class VideoOutputObserver : public VideoRenderer {
931c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org   public:
9324383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org    VideoOutputObserver(test::FrameGeneratorCapturer** capturer,
9334383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org                        int width,
9344383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org                        int height)
9354383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org        : capturer_(capturer),
9364383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org          width_(width),
9374383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org          height_(height),
9384383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org          done_(EventWrapper::Create()) {}
939c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
940c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    virtual void RenderFrame(const I420VideoFrame& video_frame,
941c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org                             int time_to_render_ms) OVERRIDE {
942c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org      EXPECT_EQ(width_, video_frame.width());
943c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org      EXPECT_EQ(height_, video_frame.height());
9444383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org      (*capturer_)->Stop();
945c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org      done_->Set();
946c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    }
947c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
948e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
949c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
950c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org   private:
9514383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org    test::FrameGeneratorCapturer** capturer_;
952c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    int width_;
953c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    int height_;
954c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    scoped_ptr<EventWrapper> done_;
955c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  };
956c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
957c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  struct {
958c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    uint32_t ssrc;
959c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    int width;
960c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    int height;
961c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  } codec_settings[kNumStreams] = {{1, 640, 480}, {2, 320, 240}, {3, 240, 160}};
962c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
963c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  test::DirectTransport sender_transport, receiver_transport;
964c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  scoped_ptr<Call> sender_call(Call::Create(Call::Config(&sender_transport)));
965c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  scoped_ptr<Call> receiver_call(
966c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org      Call::Create(Call::Config(&receiver_transport)));
967c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  sender_transport.SetReceiver(receiver_call->Receiver());
968c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  receiver_transport.SetReceiver(sender_call->Receiver());
969c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
970c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  VideoSendStream* send_streams[kNumStreams];
971c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  VideoReceiveStream* receive_streams[kNumStreams];
972c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
973c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  VideoOutputObserver* observers[kNumStreams];
974c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  test::FrameGeneratorCapturer* frame_generators[kNumStreams];
975c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
9761c655450cf12d21bfa5b2ff277f337335149186apbos@webrtc.org  scoped_ptr<VideoEncoder> encoders[kNumStreams];
977e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org  for (size_t i = 0; i < kNumStreams; ++i)
9781c655450cf12d21bfa5b2ff277f337335149186apbos@webrtc.org    encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
979e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org
980c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  for (size_t i = 0; i < kNumStreams; ++i) {
981c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    uint32_t ssrc = codec_settings[i].ssrc;
982c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    int width = codec_settings[i].width;
983c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    int height = codec_settings[i].height;
9844383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org    observers[i] = new VideoOutputObserver(&frame_generators[i], width, height);
985c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
9867f0b309745ae589ded2bec817c390249fdb10ad3pbos@webrtc.org    VideoSendStream::Config send_config;
987e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    send_config.rtp.ssrcs.push_back(ssrc);
988bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    send_config.encoder_settings.encoder = encoders[i].get();
989bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    send_config.encoder_settings.payload_name = "VP8";
990bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    send_config.encoder_settings.payload_type = 124;
99158b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org    VideoEncoderConfig encoder_config;
99258b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org    encoder_config.streams = test::CreateVideoStreams(1);
99358b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org    VideoStream* stream = &encoder_config.streams[0];
994e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    stream->width = width;
995e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    stream->height = height;
996e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    stream->max_framerate = 5;
997e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    stream->min_bitrate_bps = stream->target_bitrate_bps =
998e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org        stream->max_bitrate_bps = 100000;
999bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    send_streams[i] =
100058b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        sender_call->CreateVideoSendStream(send_config, encoder_config);
100116a058a180164c32a13f3406d35cc3ef1ad569c4pbos@webrtc.org    send_streams[i]->Start();
1002e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org
10037f0b309745ae589ded2bec817c390249fdb10ad3pbos@webrtc.org    VideoReceiveStream::Config receive_config;
1004c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    receive_config.renderer = observers[i];
10054b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org    receive_config.rtp.remote_ssrc = ssrc;
10064b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org    receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
1007e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    VideoCodec codec =
1008e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org        test::CreateDecoderVideoCodec(send_config.encoder_settings);
1009e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    receive_config.codecs.push_back(codec);
1010964d78e5c80ec8e4cbaeece5f119806b1ef9ea22pbos@webrtc.org    receive_streams[i] =
1011964d78e5c80ec8e4cbaeece5f119806b1ef9ea22pbos@webrtc.org        receiver_call->CreateVideoReceiveStream(receive_config);
101216a058a180164c32a13f3406d35cc3ef1ad569c4pbos@webrtc.org    receive_streams[i]->Start();
1013c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1014c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    frame_generators[i] = test::FrameGeneratorCapturer::Create(
1015c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org        send_streams[i]->Input(), width, height, 30, Clock::GetRealTimeClock());
1016c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    frame_generators[i]->Start();
1017c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  }
1018c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1019c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  for (size_t i = 0; i < kNumStreams; ++i) {
1020e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    EXPECT_EQ(kEventSignaled, observers[i]->Wait())
1021e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org        << "Timed out while waiting for observer " << i << " to render.";
1022c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  }
1023c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1024c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  for (size_t i = 0; i < kNumStreams; ++i) {
1025c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    frame_generators[i]->Stop();
102612a93e063c94500f8fe0a045fc381a816fdf3c69pbos@webrtc.org    sender_call->DestroyVideoSendStream(send_streams[i]);
102712a93e063c94500f8fe0a045fc381a816fdf3c69pbos@webrtc.org    receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1028471354f94ed73da7195e2f8e72c5a2239b9a9afbpbos@webrtc.org    delete frame_generators[i];
1029c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    delete observers[i];
1030c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  }
1031c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1032c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  sender_transport.StopSending();
1033c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  receiver_transport.StopSending();
1034eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org}
1035e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org
1036eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, ObserversEncodedFrames) {
10372e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  class EncodedFrameTestObserver : public EncodedFrameObserver {
10382e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org   public:
1039c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    EncodedFrameTestObserver()
1040c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        : length_(0),
1041c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org          frame_type_(kFrameEmpty),
1042c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org          called_(EventWrapper::Create()) {}
10432e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    virtual ~EncodedFrameTestObserver() {}
10442e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
10452e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
10462e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      frame_type_ = encoded_frame.frame_type_;
10472e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      length_ = encoded_frame.length_;
10482e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      buffer_.reset(new uint8_t[length_]);
10492e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      memcpy(buffer_.get(), encoded_frame.data_, length_);
10502e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      called_->Set();
10512e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    }
10522e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
1053c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    EventTypeWrapper Wait() { return called_->Wait(kDefaultTimeoutMs); }
10542e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
10552e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
10562e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      ASSERT_EQ(length_, observer.length_)
10572e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org          << "Observed frames are of different lengths.";
10582e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      EXPECT_EQ(frame_type_, observer.frame_type_)
10592e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org          << "Observed frames have different frame types.";
10602e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
10612e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org          << "Observed encoded frames have different content.";
10622e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    }
10632e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
10642e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org   private:
10652e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    scoped_ptr<uint8_t[]> buffer_;
10662e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    size_t length_;
10672e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    FrameType frame_type_;
10682e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    scoped_ptr<EventWrapper> called_;
10692e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  };
10702e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
10712e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  EncodedFrameTestObserver post_encode_observer;
10722e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  EncodedFrameTestObserver pre_decode_observer;
10732e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
10742e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  test::DirectTransport sender_transport, receiver_transport;
10752e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
10762e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  CreateCalls(Call::Config(&sender_transport),
10772e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org              Call::Config(&receiver_transport));
10782e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
10792e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  sender_transport.SetReceiver(receiver_call_->Receiver());
10802e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  receiver_transport.SetReceiver(sender_call_->Receiver());
10812e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
1082eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  CreateSendConfig(1);
1083eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  CreateMatchingReceiveConfigs();
10842e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  send_config_.post_encode_callback = &post_encode_observer;
108588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  receive_configs_[0].pre_decode_callback = &pre_decode_observer;
10862e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
10872e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  CreateStreams();
108888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  Start();
10892e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
10902e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
109158b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org      encoder_config_.streams[0].width, encoder_config_.streams[0].height));
1092c33d37ce205e22c0e090b0b285ed963686bf24dcpbos@webrtc.org  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
10932e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
10942e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  EXPECT_EQ(kEventSignaled, post_encode_observer.Wait())
10952e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      << "Timed out while waiting for send-side encoded-frame callback.";
10962e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
10972e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  EXPECT_EQ(kEventSignaled, pre_decode_observer.Wait())
10982e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      << "Timed out while waiting for pre-decode encoded-frame callback.";
10992e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11002e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  post_encode_observer.ExpectEqualFrames(pre_decode_observer);
11012e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
110288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  Stop();
11032e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11042e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  sender_transport.StopSending();
11052e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  receiver_transport.StopSending();
11062e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11072e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  DestroyStreams();
11082e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org}
11097ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org
1110eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1111eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  class RembObserver : public test::EndToEndTest {
11127ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org   public:
1113eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
11147ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org
11157ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org    virtual Action OnReceiveRtcp(const uint8_t* packet,
11167ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org                                 size_t length) OVERRIDE {
11177ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      RTCPUtility::RTCPParserV2 parser(packet, length, true);
11187ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      EXPECT_TRUE(parser.IsValid());
11197ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org
11207ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      bool received_psfb = false;
11217ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      bool received_remb = false;
11227ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
11237ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
11247ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org        if (packet_type == RTCPUtility::kRtcpPsfbRembCode) {
11257ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org          const RTCPUtility::RTCPPacket& packet = parser.Packet();
11267ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org          EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalSsrc);
11277ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org          received_psfb = true;
11287ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org        } else if (packet_type == RTCPUtility::kRtcpPsfbRembItemCode) {
11297ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org          const RTCPUtility::RTCPPacket& packet = parser.Packet();
11307ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org          EXPECT_GT(packet.REMBItem.BitRate, 0u);
11317ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org          EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
1132eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          EXPECT_EQ(packet.REMBItem.SSRCs[0], kSendSsrcs[0]);
11337ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org          received_remb = true;
11347ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org        }
11357ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org        packet_type = parser.Iterate();
11367ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      }
11377ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      if (received_psfb && received_remb)
11387ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org        observation_complete_->Set();
11397ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      return SEND_PACKET;
11407ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org    }
1141eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void PerformTest() OVERRIDE {
1142eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for a "
1143eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org                                           "receiver RTCP REMB packet to be "
1144eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org                                           "sent.";
1145eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
1146eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  } test;
11477ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org
1148eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  RunBaseTest(&test);
11497ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org}
1150b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
1151eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgvoid EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
1152b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  static const int kNumRtcpReportPacketsToObserve = 5;
1153eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  class RtcpXrObserver : public test::EndToEndTest {
1154b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org   public:
1155b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    explicit RtcpXrObserver(bool enable_rrtr)
1156eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        : EndToEndTest(kDefaultTimeoutMs),
1157b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          enable_rrtr_(enable_rrtr),
1158b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          sent_rtcp_sr_(0),
1159b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          sent_rtcp_rr_(0),
1160b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          sent_rtcp_rrtr_(0),
1161b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          sent_rtcp_dlrr_(0) {}
1162c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
1163b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org   private:
1164b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    // Receive stream should send RR packets (and RRTR packets if enabled).
1165b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    virtual Action OnReceiveRtcp(const uint8_t* packet,
1166b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org                                 size_t length) OVERRIDE {
1167b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      RTCPUtility::RTCPParserV2 parser(packet, length, true);
1168b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      EXPECT_TRUE(parser.IsValid());
1169b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
1170b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1171b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
1172b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        if (packet_type == RTCPUtility::kRtcpRrCode) {
1173b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          ++sent_rtcp_rr_;
1174c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        } else if (packet_type ==
1175c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org                   RTCPUtility::kRtcpXrReceiverReferenceTimeCode) {
1176b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          ++sent_rtcp_rrtr_;
1177b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        }
1178b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        EXPECT_NE(packet_type, RTCPUtility::kRtcpSrCode);
1179b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        EXPECT_NE(packet_type, RTCPUtility::kRtcpXrDlrrReportBlockItemCode);
1180b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        packet_type = parser.Iterate();
1181b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      }
1182b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      return SEND_PACKET;
1183b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    }
1184b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    // Send stream should send SR packets (and DLRR packets if enabled).
1185b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
1186b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      RTCPUtility::RTCPParserV2 parser(packet, length, true);
1187b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      EXPECT_TRUE(parser.IsValid());
1188b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
1189b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1190b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
1191b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        if (packet_type == RTCPUtility::kRtcpSrCode) {
1192b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          ++sent_rtcp_sr_;
1193b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        } else if (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
1194b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          ++sent_rtcp_dlrr_;
1195b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        }
1196b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        EXPECT_NE(packet_type, RTCPUtility::kRtcpXrReceiverReferenceTimeCode);
1197b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        packet_type = parser.Iterate();
1198b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      }
1199b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
1200b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
1201b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        if (enable_rrtr_) {
1202b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          EXPECT_GT(sent_rtcp_rrtr_, 0);
1203b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          EXPECT_GT(sent_rtcp_dlrr_, 0);
1204b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        } else {
1205b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          EXPECT_EQ(0, sent_rtcp_rrtr_);
1206b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          EXPECT_EQ(0, sent_rtcp_dlrr_);
1207b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        }
1208b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        observation_complete_->Set();
1209b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      }
1210b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      return SEND_PACKET;
1211b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    }
1212eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
1213eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void ModifyConfigs(
1214eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        VideoSendStream::Config* send_config,
121588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        std::vector<VideoReceiveStream::Config>* receive_configs,
121658b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        VideoEncoderConfig* encoder_config) OVERRIDE {
121788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      (*receive_configs)[0].rtp.rtcp_mode = newapi::kRtcpReducedSize;
121888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
121988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org          enable_rrtr_;
1220eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
1221eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
1222eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void PerformTest() OVERRIDE {
1223eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      EXPECT_EQ(kEventSignaled, Wait())
1224eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          << "Timed out while waiting for RTCP SR/RR packets to be sent.";
1225eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
1226eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
1227b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    bool enable_rrtr_;
1228b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    int sent_rtcp_sr_;
1229b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    int sent_rtcp_rr_;
1230b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    int sent_rtcp_rrtr_;
1231b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    int sent_rtcp_dlrr_;
1232eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  } test(enable_rrtr);
1233b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
1234eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  RunBaseTest(&test);
1235b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org}
1236b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
123788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.orgvoid EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
123888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org                                     bool send_single_ssrc_first) {
123988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  class SendsSetSsrcs : public test::EndToEndTest {
124088b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org   public:
124188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    SendsSetSsrcs(const uint32_t* ssrcs,
124288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org                  size_t num_ssrcs,
124388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org                  bool send_single_ssrc_first)
124488b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        : EndToEndTest(kDefaultTimeoutMs),
124588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org          num_ssrcs_(num_ssrcs),
124688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org          send_single_ssrc_first_(send_single_ssrc_first),
124788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org          ssrcs_to_observe_(num_ssrcs),
124888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org          expect_single_ssrc_(send_single_ssrc_first) {
124988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      for (size_t i = 0; i < num_ssrcs; ++i)
125088b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        valid_ssrcs_[ssrcs[i]] = true;
125188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    }
125288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
125388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org   private:
125488b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
125588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      RTPHeader header;
12566aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      EXPECT_TRUE(parser_->Parse(packet, length, &header));
125788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
125888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      EXPECT_TRUE(valid_ssrcs_[header.ssrc])
125988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org          << "Received unknown SSRC: " << header.ssrc;
126088b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
126188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      if (!valid_ssrcs_[header.ssrc])
126288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        observation_complete_->Set();
126388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
126488b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      if (!is_observed_[header.ssrc]) {
126588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        is_observed_[header.ssrc] = true;
126688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        --ssrcs_to_observe_;
126788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        if (expect_single_ssrc_) {
126888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org          expect_single_ssrc_ = false;
126988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org          observation_complete_->Set();
127088b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        }
127188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      }
127288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
127388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      if (ssrcs_to_observe_ == 0)
127488b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        observation_complete_->Set();
127588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
127688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      return SEND_PACKET;
127788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    }
127888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
127988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    virtual size_t GetNumStreams() const OVERRIDE { return num_ssrcs_; }
128088b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
128188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    virtual void ModifyConfigs(
128288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        VideoSendStream::Config* send_config,
128388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        std::vector<VideoReceiveStream::Config>* receive_configs,
128458b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        VideoEncoderConfig* encoder_config) OVERRIDE {
128588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      if (num_ssrcs_ > 1) {
128688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
128758b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
128858b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org          encoder_config->streams[i].min_bitrate_bps = 10000;
128958b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org          encoder_config->streams[i].target_bitrate_bps = 15000;
129058b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org          encoder_config->streams[i].max_bitrate_bps = 20000;
129188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        }
129288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      }
129388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
129458b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org      encoder_config_all_streams_ = *encoder_config;
129588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      if (send_single_ssrc_first_)
129658b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        encoder_config->streams.resize(1);
129788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    }
129888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
129988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    virtual void OnStreamsCreated(
130088b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        VideoSendStream* send_stream,
130188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
130288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      send_stream_ = send_stream;
130388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    }
130488b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
130588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    virtual void PerformTest() OVERRIDE {
130688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      EXPECT_EQ(kEventSignaled, Wait())
130788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org          << "Timed out while waiting for "
130888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org          << (send_single_ssrc_first_ ? "first SSRC." : "SSRCs.");
130988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
131088b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      if (send_single_ssrc_first_) {
131188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        // Set full simulcast and continue with the rest of the SSRCs.
131258b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        send_stream_->ReconfigureVideoEncoder(encoder_config_all_streams_);
131388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        EXPECT_EQ(kEventSignaled, Wait())
131488b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org            << "Timed out while waiting on additional SSRCs.";
131588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      }
131688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    }
131788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
131888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org   private:
131988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    std::map<uint32_t, bool> valid_ssrcs_;
132088b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    std::map<uint32_t, bool> is_observed_;
132188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
132288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    const size_t num_ssrcs_;
132388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    const bool send_single_ssrc_first_;
132488b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
132588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    size_t ssrcs_to_observe_;
132688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    bool expect_single_ssrc_;
132788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
132888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    VideoSendStream* send_stream_;
132958b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org    VideoEncoderConfig encoder_config_all_streams_;
133088b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  } test(kSendSsrcs, num_ssrcs, send_single_ssrc_first);
133188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
133288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  RunBaseTest(&test);
133388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org}
133488b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
1335eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, GetStats) {
1336eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
1337eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org   public:
1338eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    StatsObserver()
1339eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        : EndToEndTest(kLongTimeoutMs),
1340eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          receive_stream_(NULL),
1341eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          send_stream_(NULL),
1342eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          expected_receive_ssrc_(),
1343eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          expected_send_ssrcs_(),
1344eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          check_stats_event_(EventWrapper::Create()) {}
1345c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1346eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org   private:
1347eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
1348eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      check_stats_event_->Set();
1349eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      return SEND_PACKET;
1350c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    }
1351c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1352eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
1353eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      check_stats_event_->Set();
1354eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      return SEND_PACKET;
1355c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    }
1356c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1357eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual Action OnReceiveRtp(const uint8_t* packet, size_t length) OVERRIDE {
1358eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      check_stats_event_->Set();
1359eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      return SEND_PACKET;
1360c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    }
1361c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1362eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual Action OnReceiveRtcp(const uint8_t* packet,
1363eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org                                 size_t length) OVERRIDE {
1364eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      check_stats_event_->Set();
1365eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      return SEND_PACKET;
1366eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
1367c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1368eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void FrameCallback(I420VideoFrame* video_frame) OVERRIDE {
1369eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      // Ensure that we have at least 5ms send side delay.
1370eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      int64_t render_time = video_frame->render_time_ms();
1371eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      if (render_time > 0)
1372eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        video_frame->set_render_time_ms(render_time - 5);
1373eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
1374c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1375eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    bool CheckReceiveStats() {
1376eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      assert(receive_stream_ != NULL);
1377eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      VideoReceiveStream::Stats stats = receive_stream_->GetStats();
1378eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      EXPECT_EQ(expected_receive_ssrc_, stats.ssrc);
1379c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1380eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      // Make sure all fields have been populated.
1381c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1382eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      receive_stats_filled_["IncomingRate"] |=
1383eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          stats.network_frame_rate != 0 || stats.bitrate_bps != 0;
1384c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1385eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
1386c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1387eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
1388c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1389eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      receive_stats_filled_["StatisticsUpdated"] |=
1390eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          stats.rtcp_stats.cumulative_lost != 0 ||
1391eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          stats.rtcp_stats.extended_max_sequence_number != 0 ||
1392eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
1393c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1394eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      receive_stats_filled_["DataCountersUpdated"] |=
1395eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          stats.rtp_stats.bytes != 0 || stats.rtp_stats.fec_packets != 0 ||
1396eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          stats.rtp_stats.header_bytes != 0 || stats.rtp_stats.packets != 0 ||
1397eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          stats.rtp_stats.padding_bytes != 0 ||
1398eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          stats.rtp_stats.retransmitted_packets != 0;
1399c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1400eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      receive_stats_filled_["CodecStats"] |=
1401eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          stats.avg_delay_ms != 0 || stats.discarded_packets != 0 ||
1402eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          stats.key_frames != 0 || stats.delta_frames != 0;
1403c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1404eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      return AllStatsFilled(receive_stats_filled_);
1405eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
1406c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1407eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    bool CheckSendStats() {
1408eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      assert(send_stream_ != NULL);
1409eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      VideoSendStream::Stats stats = send_stream_->GetStats();
1410c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1411eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      send_stats_filled_["NumStreams"] |=
1412eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          stats.substreams.size() == expected_send_ssrcs_.size();
1413c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1414eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      for (std::map<uint32_t, StreamStats>::const_iterator it =
1415eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org               stats.substreams.begin();
1416eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org           it != stats.substreams.end();
1417eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org           ++it) {
1418eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
1419eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org                    expected_send_ssrcs_.end());
1420c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1421eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        send_stats_filled_[CompoundKey("IncomingRate", it->first)] |=
1422eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org            stats.input_frame_rate != 0;
1423c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1424eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        const StreamStats& stream_stats = it->second;
1425c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1426eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
1427eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org            stream_stats.rtcp_stats.cumulative_lost != 0 ||
1428eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org            stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
1429eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org            stream_stats.rtcp_stats.fraction_lost != 0;
1430c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1431eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
1432eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org            stream_stats.rtp_stats.fec_packets != 0 ||
1433eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org            stream_stats.rtp_stats.padding_bytes != 0 ||
1434eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org            stream_stats.rtp_stats.retransmitted_packets != 0 ||
1435eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org            stream_stats.rtp_stats.packets != 0;
1436c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1437eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
1438eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org                                       it->first)] |=
1439eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org            stream_stats.bitrate_bps != 0;
1440c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1441eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
1442eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org            stream_stats.delta_frames != 0 || stream_stats.key_frames != 0;
1443c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1444eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
1445eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org            stats.encode_frame_rate != 0;
144655b0f2e500fac8fc0932ea5b60359d268371f8c5stefan@webrtc.org
144755b0f2e500fac8fc0932ea5b60359d268371f8c5stefan@webrtc.org        send_stats_filled_[CompoundKey("Delay", it->first)] |=
144855b0f2e500fac8fc0932ea5b60359d268371f8c5stefan@webrtc.org            stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
1449eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      }
1450c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1451eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      return AllStatsFilled(send_stats_filled_);
1452c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    }
1453c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1454eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    std::string CompoundKey(const char* name, uint32_t ssrc) {
1455eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      std::ostringstream oss;
1456eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      oss << name << "_" << ssrc;
1457eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      return oss.str();
1458eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
1459c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1460eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
1461eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
1462eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org           it != stats_map.end();
1463eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org           ++it) {
1464eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        if (!it->second)
1465eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          return false;
1466eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      }
1467eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      return true;
1468c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    }
1469c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1470eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void ModifyConfigs(
1471eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        VideoSendStream::Config* send_config,
147288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        std::vector<VideoReceiveStream::Config>* receive_configs,
147358b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        VideoEncoderConfig* encoder_config) OVERRIDE {
1474eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      send_config->pre_encode_callback = this;  // Used to inject delay.
1475eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      send_config->rtp.c_name = "SomeCName";
1476c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
147788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      expected_receive_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
1478eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
1479eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      for (size_t i = 0; i < ssrcs.size(); ++i)
1480eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        expected_send_ssrcs_.insert(ssrcs[i]);
1481c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1482eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      expected_cname_ = send_config->rtp.c_name;
1483eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
1484c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
148588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    virtual void OnStreamsCreated(
148688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        VideoSendStream* send_stream,
148788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
1488eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      send_stream_ = send_stream;
148988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      receive_stream_ = receive_streams[0];
1490eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
1491c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1492eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void PerformTest() OVERRIDE {
1493eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      Clock* clock = Clock::GetRealTimeClock();
1494eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      int64_t now = clock->TimeInMilliseconds();
1495eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
1496eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      bool receive_ok = false;
1497eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      bool send_ok = false;
1498eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
1499eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      while (now < stop_time) {
1500eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        if (!receive_ok)
1501eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          receive_ok = CheckReceiveStats();
1502eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        if (!send_ok)
1503eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          send_ok = CheckSendStats();
1504eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
1505eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        if (receive_ok && send_ok)
1506eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          return;
1507eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
1508eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        int64_t time_until_timout_ = stop_time - now;
1509eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        if (time_until_timout_ > 0)
1510eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          check_stats_event_->Wait(time_until_timout_);
1511eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        now = clock->TimeInMilliseconds();
1512eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      }
1513c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1514eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      ADD_FAILURE() << "Timed out waiting for filled stats.";
1515eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      for (std::map<std::string, bool>::const_iterator it =
1516eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org               receive_stats_filled_.begin();
1517eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org           it != receive_stats_filled_.end();
1518eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org           ++it) {
1519eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        if (!it->second) {
1520eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          ADD_FAILURE() << "Missing receive stats: " << it->first;
1521eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        }
1522eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      }
1523c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1524eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      for (std::map<std::string, bool>::const_iterator it =
1525eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org               send_stats_filled_.begin();
1526eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org           it != send_stats_filled_.end();
1527eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org           ++it) {
1528eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        if (!it->second) {
1529eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          ADD_FAILURE() << "Missing send stats: " << it->first;
1530eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        }
1531eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      }
1532eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
1533c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1534eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    VideoReceiveStream* receive_stream_;
1535eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    std::map<std::string, bool> receive_stats_filled_;
1536c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1537eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    VideoSendStream* send_stream_;
1538eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    std::map<std::string, bool> send_stats_filled_;
1539c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1540eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    uint32_t expected_receive_ssrc_;
1541eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    std::set<uint32_t> expected_send_ssrcs_;
1542eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    std::string expected_cname_;
1543c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1544eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    scoped_ptr<EventWrapper> check_stats_event_;
1545eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  } test;
1546c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1547eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  RunBaseTest(&test);
1548c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org}
1549c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1550eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
1551b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  TestXrReceiverReferenceTimeReport(true);
1552b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org}
1553b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
1554eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
1555b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  TestXrReceiverReferenceTimeReport(false);
1556b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org}
15573f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org
1558eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.orgTEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
155999153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  static const size_t kNumRtpPacketsToSend = 5;
1560eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  class ReceivedRtpStatsObserver : public test::EndToEndTest {
156199153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org   public:
156299153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org    ReceivedRtpStatsObserver()
1563eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org        : EndToEndTest(kDefaultTimeoutMs),
156499153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org          receive_stream_(NULL),
156599153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org          sent_rtp_(0) {}
156699153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org
1567eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org   private:
156888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org    virtual void OnStreamsCreated(
156988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        VideoSendStream* send_stream,
157088b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org        const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
157188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org      receive_stream_ = receive_streams[0];
157299153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org    }
157399153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org
157499153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
157599153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org      if (sent_rtp_ >= kNumRtpPacketsToSend) {
157699153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org        VideoReceiveStream::Stats stats = receive_stream_->GetStats();
157799153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org        if (kNumRtpPacketsToSend == stats.rtp_stats.packets) {
157899153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org          observation_complete_->Set();
157999153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org        }
158099153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org        return DROP_PACKET;
158199153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org      }
158299153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org      ++sent_rtp_;
158399153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org      return SEND_PACKET;
158499153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org    }
158599153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org
1586eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    virtual void PerformTest() OVERRIDE {
1587eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org      EXPECT_EQ(kEventSignaled, Wait())
1588eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org          << "Timed out while verifying number of received RTP packets.";
1589eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org    }
1590eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org
159199153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org    VideoReceiveStream* receive_stream_;
159299153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org    uint32_t sent_rtp_;
1593eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  } test;
159499153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org
1595eb67a6be101fe1ac8f2a4c062dbe6250f2e36bc0pbos@webrtc.org  RunBaseTest(&test);
159699153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org}
159799153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org
159888b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.orgTEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
159988b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
160088b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.orgTEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
160188b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  TestSendsSetSsrcs(kNumSsrcs, false);
160288b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org}
160388b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
160488b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.orgTEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
160588b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org  TestSendsSetSsrcs(kNumSsrcs, true);
160688b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org}
160788b558febb8e8f42df6c7482efe76795c3fed399pbos@webrtc.org
16084a1b3e3a69d349b0d3e91f607f24e02d8b975688mflodman@webrtc.orgTEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
160965afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org  class ObserveRedundantPayloads: public test::EndToEndTest {
161065afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org   public:
161165afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org    ObserveRedundantPayloads()
161265afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org        : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
16136c0337de402c181603ef7d499b2102ccb260ca80pbos@webrtc.org          for (size_t i = 0; i < kNumSsrcs; ++i) {
161465afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org            registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
161565afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org          }
161665afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org        }
161765afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org
161865afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org   private:
161965afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
162065afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      RTPHeader header;
16216aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      EXPECT_TRUE(parser_->Parse(packet, length, &header));
162265afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org
162365afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      if (!registered_rtx_ssrc_[header.ssrc])
162465afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org        return SEND_PACKET;
162565afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org
162665afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      EXPECT_LE(static_cast<size_t>(header.headerLength + header.paddingLength),
162765afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org                length);
162865afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      const bool packet_is_redundant_payload =
162965afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org          static_cast<size_t>(header.headerLength + header.paddingLength) <
163065afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org          length;
163165afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org
163265afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      if (!packet_is_redundant_payload)
163365afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org        return SEND_PACKET;
163465afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org
163565afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      if (!observed_redundant_retransmission_[header.ssrc]) {
163665afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org        observed_redundant_retransmission_[header.ssrc] = true;
163765afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org        if (--ssrcs_to_observe_ == 0)
163865afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org          observation_complete_->Set();
163965afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      }
164065afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org
164165afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      return SEND_PACKET;
164265afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org    }
164365afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org
164465afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org    virtual size_t GetNumStreams() const OVERRIDE { return kNumSsrcs; }
164565afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org
164665afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org    virtual void ModifyConfigs(
164765afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org        VideoSendStream::Config* send_config,
164865afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org        std::vector<VideoReceiveStream::Config>* receive_configs,
164958b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        VideoEncoderConfig* encoder_config) OVERRIDE {
165065afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
165158b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org      for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
165258b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        encoder_config->streams[i].min_bitrate_bps = 10000;
165358b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        encoder_config->streams[i].target_bitrate_bps = 15000;
165458b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        encoder_config->streams[i].max_bitrate_bps = 20000;
165565afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      }
165665afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      // Significantly higher than max bitrates for all video streams -> forcing
165765afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      // padding to trigger redundant padding on all RTX SSRCs.
165865afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      send_config->rtp.min_transmit_bitrate_bps = 100000;
165965afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org
166065afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
166165afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      send_config->rtp.rtx.pad_with_redundant_payloads = true;
166265afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org
166365afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      for (size_t i = 0; i < kNumSsrcs; ++i)
166465afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org        send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
166565afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org    }
166665afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org
166765afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org    virtual void PerformTest() OVERRIDE {
166865afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org      EXPECT_EQ(kEventSignaled, Wait())
166965afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org          << "Timed out while waiting for redundant payloads on all SSRCs.";
167065afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org    }
167165afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org
167265afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org   private:
167365afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org    size_t ssrcs_to_observe_;
167465afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org    std::map<uint32_t, bool> observed_redundant_retransmission_;
167565afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org    std::map<uint32_t, bool> registered_rtx_ssrc_;
167665afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org  } test;
167765afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org
167865afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org  RunBaseTest(&test);
167965afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org}
168065afbf3e1da598f94f47eb0c11fe2b668e4f30f4pbos@webrtc.org
16812fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.orgvoid EndToEndTest::TestRtpStatePreservation(bool use_rtx) {
16822fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  static const uint32_t kMaxSequenceNumberGap = 100;
16832fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  static const uint64_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
16842fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  class RtpSequenceObserver : public test::RtpRtcpObserver {
16852fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org   public:
16866c0337de402c181603ef7d499b2102ccb260ca80pbos@webrtc.org    explicit RtpSequenceObserver(bool use_rtx)
16872fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        : test::RtpRtcpObserver(kDefaultTimeoutMs),
16882fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org          crit_(CriticalSectionWrapper::CreateCriticalSection()),
16892fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org          ssrcs_to_observe_(kNumSsrcs) {
16902fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      for (size_t i = 0; i < kNumSsrcs; ++i) {
16912fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        configured_ssrcs_[kSendSsrcs[i]] = true;
16922fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        if (use_rtx)
16932fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org          configured_ssrcs_[kSendRtxSsrcs[i]] = true;
16942fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      }
16952fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    }
16962fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
16972fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
16982fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      CriticalSectionScoped lock(crit_.get());
16992fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      ssrc_observed_.clear();
17002fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      ssrcs_to_observe_ = num_expected_ssrcs;
17012fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    }
17022fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
17032fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org   private:
17042fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
17052fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      RTPHeader header;
17066aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org      EXPECT_TRUE(parser_->Parse(packet, length, &header));
17072fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      const uint32_t ssrc = header.ssrc;
17082fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      const uint16_t sequence_number = header.sequenceNumber;
17092fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      const uint32_t timestamp = header.timestamp;
17102fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      const bool only_padding =
17112fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org          static_cast<size_t>(header.headerLength + header.paddingLength) ==
17122fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org          length;
17132fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
17142fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      EXPECT_TRUE(configured_ssrcs_[ssrc])
17152fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org          << "Received SSRC that wasn't configured: " << ssrc;
17162fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
17172fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      std::map<uint32_t, uint16_t>::iterator it =
17182fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org          last_observed_sequence_number_.find(header.ssrc);
17192fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      if (it == last_observed_sequence_number_.end()) {
17202fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        last_observed_sequence_number_[ssrc] = sequence_number;
17212fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        last_observed_timestamp_[ssrc] = timestamp;
17222fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      } else {
17232fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        // Verify sequence numbers are reasonably close.
17242fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        uint32_t extended_sequence_number = sequence_number;
17252fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        // Check for roll-over.
17262fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        if (sequence_number < last_observed_sequence_number_[ssrc])
17272fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org          extended_sequence_number += 0xFFFFu + 1;
17282fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        EXPECT_LE(
17292fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org            extended_sequence_number - last_observed_sequence_number_[ssrc],
17302fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org            kMaxSequenceNumberGap)
17312fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org            << "Gap in sequence numbers ("
17322fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org            << last_observed_sequence_number_[ssrc] << " -> " << sequence_number
17332fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org            << ") too large for SSRC: " << ssrc << ".";
17342fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        last_observed_sequence_number_[ssrc] = sequence_number;
17352fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
17362fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        // TODO(pbos): Remove this check if we ever have monotonically
17372fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        // increasing timestamps. Right now padding packets add a delta which
17382fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        // can cause reordering between padding packets and regular packets,
17392fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        // hence we drop padding-only packets to not flake.
17402fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        if (only_padding) {
17412fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org          // Verify that timestamps are reasonably close.
17422fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org          uint64_t extended_timestamp = timestamp;
17432fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org          // Check for roll-over.
17442fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org          if (timestamp < last_observed_timestamp_[ssrc])
17452fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org            extended_timestamp += static_cast<uint64_t>(0xFFFFFFFFu) + 1;
17462fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org          EXPECT_LE(extended_timestamp - last_observed_timestamp_[ssrc],
17472fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org                    kMaxTimestampGap)
17482fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org              << "Gap in timestamps (" << last_observed_timestamp_[ssrc]
17492fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org              << " -> " << timestamp << ") too large for SSRC: " << ssrc << ".";
17502fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        }
17512fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        last_observed_timestamp_[ssrc] = timestamp;
17522fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      }
17532fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
17542fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      CriticalSectionScoped lock(crit_.get());
17552fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      // Wait for media packets on all ssrcs.
17562fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      if (!ssrc_observed_[ssrc] && !only_padding) {
17572fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        ssrc_observed_[ssrc] = true;
17582fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        if (--ssrcs_to_observe_ == 0)
17592fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org          observation_complete_->Set();
17602fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      }
17612fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
17622fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      return SEND_PACKET;
17632fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    }
17642fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
17652fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    std::map<uint32_t, uint16_t> last_observed_sequence_number_;
17662fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    std::map<uint32_t, uint32_t> last_observed_timestamp_;
17672fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    std::map<uint32_t, bool> configured_ssrcs_;
17682fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
17692fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    scoped_ptr<CriticalSectionWrapper> crit_;
17702fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    size_t ssrcs_to_observe_ GUARDED_BY(crit_);
17712fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
17722fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  } observer(use_rtx);
17732fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
17742fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  CreateCalls(Call::Config(observer.SendTransport()),
17752fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org              Call::Config(observer.ReceiveTransport()));
17762fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  observer.SetReceivers(sender_call_->Receiver(), NULL);
17772fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
17782fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  CreateSendConfig(kNumSsrcs);
17792fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
17802fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  if (use_rtx) {
17812fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    for (size_t i = 0; i < kNumSsrcs; ++i) {
17822fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
17832fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    }
17842fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
17852fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  }
17862fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
17872fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  // Lower bitrates so that all streams send initially.
178858b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org  for (size_t i = 0; i < encoder_config_.streams.size(); ++i) {
178958b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org    encoder_config_.streams[i].min_bitrate_bps = 10000;
179058b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org    encoder_config_.streams[i].target_bitrate_bps = 15000;
179158b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org    encoder_config_.streams[i].max_bitrate_bps = 20000;
17922fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  }
17932fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
17942fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  CreateMatchingReceiveConfigs();
17952fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
17962fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  CreateStreams();
17972fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  CreateFrameGeneratorCapturer();
17982fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
17992fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  Start();
18002fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  EXPECT_EQ(kEventSignaled, observer.Wait())
18012fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org      << "Timed out waiting for all SSRCs to send packets.";
18022fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
18032fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  // Test stream resetting more than once to make sure that the state doesn't
18042fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  // get set once (this could be due to using std::map::insert for instance).
18052fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  for (size_t i = 0; i < 3; ++i) {
18062fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    frame_generator_capturer_->Stop();
18072fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    sender_call_->DestroyVideoSendStream(send_stream_);
18082fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
18092fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    // Re-create VideoSendStream with only one stream.
181058b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org    VideoEncoderConfig one_stream = encoder_config_;
181158b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org    one_stream.streams.resize(1);
18122fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    send_stream_ =
181358b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        sender_call_->CreateVideoSendStream(send_config_, one_stream);
18142fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    send_stream_->Start();
18152fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    CreateFrameGeneratorCapturer();
18162fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    frame_generator_capturer_->Start();
18172fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
18182fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    observer.ResetExpectedSsrcs(1);
18192fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    EXPECT_EQ(kEventSignaled, observer.Wait())
18202fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        << "Timed out waiting for single RTP packet.";
18212fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
18222fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    // Reconfigure back to use all streams.
182358b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org    send_stream_->ReconfigureVideoEncoder(encoder_config_);
18242fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    observer.ResetExpectedSsrcs(kNumSsrcs);
18252fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    EXPECT_EQ(kEventSignaled, observer.Wait())
18262fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        << "Timed out waiting for all SSRCs to send packets.";
18272fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
18282fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    // Reconfigure down to one stream.
182958b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org    send_stream_->ReconfigureVideoEncoder(one_stream);
18302fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    observer.ResetExpectedSsrcs(1);
18312fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    EXPECT_EQ(kEventSignaled, observer.Wait())
18322fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        << "Timed out waiting for single RTP packet.";
18332fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
18342fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    // Reconfigure back to use all streams.
183558b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org    send_stream_->ReconfigureVideoEncoder(encoder_config_);
18362fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    observer.ResetExpectedSsrcs(kNumSsrcs);
18372fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org    EXPECT_EQ(kEventSignaled, observer.Wait())
18382fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org        << "Timed out waiting for all SSRCs to send packets.";
18392fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  }
18402fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
18412fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  observer.StopSending();
18422fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
18432fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  Stop();
18442fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  DestroyStreams();
18452fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org}
18462fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
1847cd35c434c6c9358f87893d0116a3ee528203a975aluebs@webrtc.orgTEST_F(EndToEndTest, DISABLED_RestartingSendStreamPreservesRtpState) {
18482fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  TestRtpStatePreservation(false);
18492fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org}
18502fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
18512fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.orgTEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
18522fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org  TestRtpStatePreservation(true);
18532fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org}
18542fd91bd35094b909b4b3cce636454426fc893ac2pbos@webrtc.org
18559b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.orgTEST_F(EndToEndTest, RespectsNetworkState) {
18569b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  // TODO(pbos): Remove accepted downtime packets etc. when signaling network
18579b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  // down blocks until no more packets will be sent.
18589b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
18599b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  // Pacer will send from its packet list and then send required padding before
18609b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  // checking paused_ again. This should be enough for one round of pacing,
18619b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  // otherwise increase.
18629b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  static const int kNumAcceptedDowntimeRtp = 5;
18639b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  // A single RTCP may be in the pipeline.
18649b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  static const int kNumAcceptedDowntimeRtcp = 1;
18659b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
18669b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org   public:
18679b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    NetworkStateTest()
18689b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        : EndToEndTest(kDefaultTimeoutMs),
18699b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          FakeEncoder(Clock::GetRealTimeClock()),
18709b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          test_crit_(CriticalSectionWrapper::CreateCriticalSection()),
18719b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          encoded_frames_(EventWrapper::Create()),
18729b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          sender_packets_(EventWrapper::Create()),
18739b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          receiver_packets_(EventWrapper::Create()),
18749b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          sender_state_(Call::kNetworkUp),
18759b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          down_sender_rtp_(0),
18769b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          down_sender_rtcp_(0),
18779b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          receiver_state_(Call::kNetworkUp),
18789b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          down_receiver_rtcp_(0),
18799b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          down_frames_(0) {}
18809b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
18819b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
18829b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      CriticalSectionScoped lock(test_crit_.get());
18839b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      if (sender_state_ == Call::kNetworkDown) {
18849b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        ++down_sender_rtp_;
18859b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        EXPECT_LE(down_sender_rtp_, kNumAcceptedDowntimeRtp)
18869b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org            << "RTP sent during sender-side downtime.";
18879b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        if (down_sender_rtp_> kNumAcceptedDowntimeRtp)
18889b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          sender_packets_->Set();
18899b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      } else {
18909b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        sender_packets_->Set();
18919b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      }
18929b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      return SEND_PACKET;
18939b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    }
18949b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
18959b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
18969b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      CriticalSectionScoped lock(test_crit_.get());
18979b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      if (sender_state_ == Call::kNetworkDown) {
18989b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        ++down_sender_rtcp_;
18999b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        EXPECT_LE(down_sender_rtcp_, kNumAcceptedDowntimeRtcp)
19009b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org            << "RTCP sent during sender-side downtime.";
19019b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        if (down_sender_rtcp_ > kNumAcceptedDowntimeRtcp)
19029b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          sender_packets_->Set();
19039b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      } else {
19049b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        sender_packets_->Set();
19059b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      }
19069b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      return SEND_PACKET;
19079b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    }
19089b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
19099b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    virtual Action OnReceiveRtp(const uint8_t* packet, size_t length) OVERRIDE {
19109b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
19119b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      return SEND_PACKET;
19129b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    }
19139b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
19149b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    virtual Action OnReceiveRtcp(const uint8_t* packet,
19159b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org                                 size_t length) OVERRIDE {
19169b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      CriticalSectionScoped lock(test_crit_.get());
19179b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      if (receiver_state_ == Call::kNetworkDown) {
19189b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        ++down_receiver_rtcp_;
19199b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        EXPECT_LE(down_receiver_rtcp_, kNumAcceptedDowntimeRtcp)
19209b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org            << "RTCP sent during receiver-side downtime.";
19219b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        if (down_receiver_rtcp_ > kNumAcceptedDowntimeRtcp)
19229b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          receiver_packets_->Set();
19239b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      } else {
19249b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        receiver_packets_->Set();
19259b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      }
19269b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      return SEND_PACKET;
19279b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    }
19289b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
19299b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    virtual void OnCallsCreated(Call* sender_call,
19309b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org                                Call* receiver_call) OVERRIDE {
19319b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      sender_call_ = sender_call;
19329b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      receiver_call_ = receiver_call;
19339b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    }
19349b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
19359b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    virtual void ModifyConfigs(
19369b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        VideoSendStream::Config* send_config,
19379b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        std::vector<VideoReceiveStream::Config>* receive_configs,
193858b5140b7535ae66c618cc64b0a955b8d47cc86cpbos@webrtc.org        VideoEncoderConfig* encoder_config) OVERRIDE {
19399b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      send_config->encoder_settings.encoder = this;
19409b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    }
19419b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
19429b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    virtual void PerformTest() OVERRIDE {
19439b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      EXPECT_EQ(kEventSignaled, encoded_frames_->Wait(kDefaultTimeoutMs))
19449b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          << "No frames received by the encoder.";
19459b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      EXPECT_EQ(kEventSignaled, sender_packets_->Wait(kDefaultTimeoutMs))
19469b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          << "Timed out waiting for send-side packets.";
19479b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      EXPECT_EQ(kEventSignaled, receiver_packets_->Wait(kDefaultTimeoutMs))
19489b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          << "Timed out waiting for receiver-side packets.";
19499b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
19509b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      // Sender-side network down.
19519b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      sender_call_->SignalNetworkState(Call::kNetworkDown);
19529b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      {
19539b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        CriticalSectionScoped lock(test_crit_.get());
19549b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        sender_packets_->Reset();  // Earlier packets should not count.
19559b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        sender_state_ = Call::kNetworkDown;
19569b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      }
19579b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      EXPECT_EQ(kEventTimeout, sender_packets_->Wait(kSilenceTimeoutMs))
19589b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          << "Packets sent during sender-network downtime.";
19599b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      EXPECT_EQ(kEventSignaled, receiver_packets_->Wait(kDefaultTimeoutMs))
19609b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          << "Timed out waiting for receiver-side packets.";
19619b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      // Receiver-side network down.
19629b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      receiver_call_->SignalNetworkState(Call::kNetworkDown);
19639b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      {
19649b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        CriticalSectionScoped lock(test_crit_.get());
19659b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        receiver_packets_->Reset();  // Earlier packets should not count.
19669b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        receiver_state_ = Call::kNetworkDown;
19679b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      }
19689b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      EXPECT_EQ(kEventTimeout, receiver_packets_->Wait(kSilenceTimeoutMs))
19699b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          << "Packets sent during receiver-network downtime.";
19709b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
19719b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      // Network back up again for both.
19729b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      {
19739b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        CriticalSectionScoped lock(test_crit_.get());
19749b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        sender_packets_->Reset();  // Earlier packets should not count.
19759b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        receiver_packets_->Reset();  // Earlier packets should not count.
19769b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        sender_state_ = receiver_state_ = Call::kNetworkUp;
19779b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      }
19789b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      sender_call_->SignalNetworkState(Call::kNetworkUp);
19799b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      receiver_call_->SignalNetworkState(Call::kNetworkUp);
19809b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      EXPECT_EQ(kEventSignaled, sender_packets_->Wait(kDefaultTimeoutMs))
19819b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          << "Timed out waiting for send-side packets.";
19829b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      EXPECT_EQ(kEventSignaled, receiver_packets_->Wait(kDefaultTimeoutMs))
19839b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          << "Timed out waiting for receiver-side packets.";
19849b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    }
19859b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
19869b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    virtual int32_t Encode(const I420VideoFrame& input_image,
19879b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org                           const CodecSpecificInfo* codec_specific_info,
19889b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org                           const std::vector<VideoFrameType>* frame_types)
19899b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        OVERRIDE {
19909b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      {
19919b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        CriticalSectionScoped lock(test_crit_.get());
19929b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        if (sender_state_ == Call::kNetworkDown) {
19939b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          ++down_frames_;
19949b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          EXPECT_LE(down_frames_, 1)
19959b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org              << "Encoding more than one frame while network is down.";
19969b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          if (down_frames_ > 1)
19979b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org            encoded_frames_->Set();
19989b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        } else {
19999b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          encoded_frames_->Set();
20009b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        }
20019b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      }
20029b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      return test::FakeEncoder::Encode(
20039b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          input_image, codec_specific_info, frame_types);
20049b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    }
20059b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
20069b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org   private:
20079b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    const scoped_ptr<CriticalSectionWrapper> test_crit_;
20089b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    scoped_ptr<EventWrapper> encoded_frames_;
20099b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    scoped_ptr<EventWrapper> sender_packets_;
20109b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    scoped_ptr<EventWrapper> receiver_packets_;
20119b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    Call* sender_call_;
20129b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    Call* receiver_call_;
20139b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    Call::NetworkState sender_state_ GUARDED_BY(test_crit_);
20149b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    int down_sender_rtp_ GUARDED_BY(test_crit_);
20159b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    int down_sender_rtcp_ GUARDED_BY(test_crit_);
20169b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    Call::NetworkState receiver_state_ GUARDED_BY(test_crit_);
20179b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    int down_receiver_rtcp_ GUARDED_BY(test_crit_);
20189b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    int down_frames_ GUARDED_BY(test_crit_);
20199b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  } test;
20209b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
20219b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  RunBaseTest(&test);
20229b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org}
20239b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
20249b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.orgTEST_F(EndToEndTest, NewSendStreamsRespectNetworkDown) {
20259b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  class UnusedEncoder : public test::FakeEncoder {
20269b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    public:
20279b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org     UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
20289b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    virtual int32_t Encode(const I420VideoFrame& input_image,
20299b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org                           const CodecSpecificInfo* codec_specific_info,
20309b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org                           const std::vector<VideoFrameType>* frame_types)
20319b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org        OVERRIDE {
20329b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      ADD_FAILURE() << "Unexpected frame encode.";
20339b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org      return test::FakeEncoder::Encode(
20349b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org          input_image, codec_specific_info, frame_types);
20359b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org    }
20369b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  };
20379b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
20389b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  UnusedTransport transport;
20399b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  CreateSenderCall(Call::Config(&transport));
20409b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  sender_call_->SignalNetworkState(Call::kNetworkDown);
20419b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
20429b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  CreateSendConfig(1);
20439b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  UnusedEncoder unused_encoder;
20449b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  send_config_.encoder_settings.encoder = &unused_encoder;
20459b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  CreateStreams();
20469b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  CreateFrameGeneratorCapturer();
20479b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
20489b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  Start();
20499b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  SleepMs(kSilenceTimeoutMs);
20509b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  Stop();
20519b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
20529b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  DestroyStreams();
20539b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org}
20549b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
20559b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.orgTEST_F(EndToEndTest, NewReceiveStreamsRespectNetworkDown) {
20569b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  test::DirectTransport sender_transport;
20579b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  CreateSenderCall(Call::Config(&sender_transport));
20589b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  UnusedTransport transport;
20599b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  CreateReceiverCall(Call::Config(&transport));
20609b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  sender_transport.SetReceiver(receiver_call_->Receiver());
20619b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
20629b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  receiver_call_->SignalNetworkState(Call::kNetworkDown);
20639b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
20649b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  CreateSendConfig(1);
20659b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  CreateMatchingReceiveConfigs();
20669b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  CreateStreams();
20679b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  CreateFrameGeneratorCapturer();
20689b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
20699b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  Start();
20709b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  SleepMs(kSilenceTimeoutMs);
20719b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  Stop();
20729b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
20739b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  sender_transport.StopSending();
20749b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org
20759b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org  DestroyStreams();
20769b707ca664bd22f7a8bfad14a06f9ffdc6129d3dpbos@webrtc.org}
2077ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org}  // namespace webrtc
2078