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"
22e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
23ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
24ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org#include "webrtc/system_wrappers/interface/event_wrapper.h"
25fa996f226ee327232b854c936d2f706aa71ff090pbos@webrtc.org#include "webrtc/system_wrappers/interface/scoped_ptr.h"
26d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org#include "webrtc/system_wrappers/interface/sleep.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"
37e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org#include "webrtc/test/testsupport/perf_test.h"
38c33d37ce205e22c0e090b0b285ed963686bf24dcpbos@webrtc.org#include "webrtc/video/transport_adapter.h"
39ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
40ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.orgnamespace webrtc {
41ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
4251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.orgstatic unsigned int kDefaultTimeoutMs = 30 * 1000;
4351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.orgstatic unsigned int kLongTimeoutMs = 120 * 1000;
444b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.orgstatic const uint32_t kSendSsrc = 0x654321;
45c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.orgstatic const uint32_t kSendRtxSsrc = 0x424242;
464b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.orgstatic const uint32_t kReceiverLocalSsrc = 0x123456;
474985c7b14f9ec3840d1f49007145abe7d889fd96stefan@webrtc.orgstatic const uint8_t kSendPayloadType = 125;
48c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.orgstatic const uint8_t kSendRtxPayloadType = 126;
49ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.orgstatic const int kRedPayloadType = 118;
50ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.orgstatic const int kUlpfecPayloadType = 119;
5151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
52362e3e55056af7675a4d79dc94f1c30bbbf90569pbos@webrtc.orgclass CallTest : public ::testing::Test {
53ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org public:
5428a116612e93168906d26fc69c43b10afe434c68pbos@webrtc.org  CallTest()
55618a0ec1d2c17d485b7ce51cbfd282e6bae8e019pbos@webrtc.org      : send_stream_(NULL),
56618a0ec1d2c17d485b7ce51cbfd282e6bae8e019pbos@webrtc.org        receive_stream_(NULL),
57618a0ec1d2c17d485b7ce51cbfd282e6bae8e019pbos@webrtc.org        fake_encoder_(Clock::GetRealTimeClock()) {}
58ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
5946f72884ad5c4078fa324626aa69e4860e4d4ae2pbos@webrtc.org  virtual ~CallTest() {
608ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    EXPECT_EQ(NULL, send_stream_);
618ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    EXPECT_EQ(NULL, receive_stream_);
628ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  }
638ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
648ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org protected:
65b5d2d165c78331b337bc372babc3a1a3e62172afpbos@webrtc.org  void CreateCalls(const Call::Config& sender_config,
66b5d2d165c78331b337bc372babc3a1a3e62172afpbos@webrtc.org                   const Call::Config& receiver_config) {
67bf6d5729629fc98dbbf8a4965cec1efe93cad895pbos@webrtc.org    sender_call_.reset(Call::Create(sender_config));
68bf6d5729629fc98dbbf8a4965cec1efe93cad895pbos@webrtc.org    receiver_call_.reset(Call::Create(receiver_config));
698ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  }
70ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
718ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  void CreateTestConfigs() {
728ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    send_config_ = sender_call_->GetDefaultSendConfig();
738ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    receive_config_ = receiver_call_->GetDefaultReceiveConfig();
74ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
754b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org    send_config_.rtp.ssrcs.push_back(kSendSsrc);
76bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    send_config_.encoder_settings.encoder = &fake_encoder_;
77bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    send_config_.encoder_settings.payload_name = "FAKE";
78bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    send_config_.encoder_settings.payload_type = kSendPayloadType;
79bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    video_streams_ = test::CreateVideoStreams(1);
80618a0ec1d2c17d485b7ce51cbfd282e6bae8e019pbos@webrtc.org
81e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    assert(receive_config_.codecs.empty());
82e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    VideoCodec codec =
83e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org        test::CreateDecoderVideoCodec(send_config_.encoder_settings);
84e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    receive_config_.codecs.push_back(codec);
85618a0ec1d2c17d485b7ce51cbfd282e6bae8e019pbos@webrtc.org    ExternalVideoDecoder decoder;
86618a0ec1d2c17d485b7ce51cbfd282e6bae8e019pbos@webrtc.org    decoder.decoder = &fake_decoder_;
87e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    decoder.payload_type = send_config_.encoder_settings.payload_type;
88618a0ec1d2c17d485b7ce51cbfd282e6bae8e019pbos@webrtc.org    receive_config_.external_decoders.push_back(decoder);
894b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org    receive_config_.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
904b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org    receive_config_.rtp.local_ssrc = kReceiverLocalSsrc;
918ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  }
92ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
938ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  void CreateStreams() {
948ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    assert(send_stream_ == NULL);
958ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    assert(receive_stream_ == NULL);
96ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
97bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    send_stream_ =
98bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org        sender_call_->CreateVideoSendStream(send_config_, video_streams_, NULL);
99964d78e5c80ec8e4cbaeece5f119806b1ef9ea22pbos@webrtc.org    receive_stream_ = receiver_call_->CreateVideoReceiveStream(receive_config_);
1008ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  }
101ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
1028ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  void CreateFrameGenerator() {
103bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    frame_generator_capturer_.reset(
104bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org        test::FrameGeneratorCapturer::Create(send_stream_->Input(),
105bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org                                             video_streams_[0].width,
106bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org                                             video_streams_[0].height,
107bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org                                             30,
108bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org                                             Clock::GetRealTimeClock()));
1098ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  }
110ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
1118ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  void StartSending() {
11216a058a180164c32a13f3406d35cc3ef1ad569c4pbos@webrtc.org    receive_stream_->Start();
11316a058a180164c32a13f3406d35cc3ef1ad569c4pbos@webrtc.org    send_stream_->Start();
114c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org    if (frame_generator_capturer_.get() != NULL)
115c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org      frame_generator_capturer_->Start();
1168ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  }
1178ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
1188ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  void StopSending() {
119c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org    if (frame_generator_capturer_.get() != NULL)
120c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org      frame_generator_capturer_->Stop();
1210020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org    if (send_stream_ != NULL)
12216a058a180164c32a13f3406d35cc3ef1ad569c4pbos@webrtc.org      send_stream_->Stop();
1230020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org    if (receive_stream_ != NULL)
12416a058a180164c32a13f3406d35cc3ef1ad569c4pbos@webrtc.org      receive_stream_->Stop();
1258ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  }
1268ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
1278ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  void DestroyStreams() {
1280020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org    if (send_stream_ != NULL)
12912a93e063c94500f8fe0a045fc381a816fdf3c69pbos@webrtc.org      sender_call_->DestroyVideoSendStream(send_stream_);
1300020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org    if (receive_stream_ != NULL)
13112a93e063c94500f8fe0a045fc381a816fdf3c69pbos@webrtc.org      receiver_call_->DestroyVideoReceiveStream(receive_stream_);
132bf6d5729629fc98dbbf8a4965cec1efe93cad895pbos@webrtc.org    send_stream_ = NULL;
1338ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    receive_stream_ = NULL;
1348ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  }
135ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
136c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  void DecodesRetransmittedFrame(bool retransmit_over_rtx);
1378ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  void ReceivesPliAndRecovers(int rtp_history_ms);
13851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
139b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
140ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
141bf6d5729629fc98dbbf8a4965cec1efe93cad895pbos@webrtc.org  scoped_ptr<Call> sender_call_;
142bf6d5729629fc98dbbf8a4965cec1efe93cad895pbos@webrtc.org  scoped_ptr<Call> receiver_call_;
1438ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
144c1797061756f40b9b1f3f3e82fc040ce18ecd43cpbos@webrtc.org  VideoSendStream::Config send_config_;
145bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org  std::vector<VideoStream> video_streams_;
146c1797061756f40b9b1f3f3e82fc040ce18ecd43cpbos@webrtc.org  VideoReceiveStream::Config receive_config_;
1478ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
148c1797061756f40b9b1f3f3e82fc040ce18ecd43cpbos@webrtc.org  VideoSendStream* send_stream_;
149c1797061756f40b9b1f3f3e82fc040ce18ecd43cpbos@webrtc.org  VideoReceiveStream* receive_stream_;
1508ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
1518ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
1528ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
153618a0ec1d2c17d485b7ce51cbfd282e6bae8e019pbos@webrtc.org  test::FakeEncoder fake_encoder_;
154618a0ec1d2c17d485b7ce51cbfd282e6bae8e019pbos@webrtc.org  test::FakeDecoder fake_decoder_;
1558ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org};
1568ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
1578ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.orgclass NackObserver : public test::RtpRtcpObserver {
1585e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org  static const int kNumberOfNacksToObserve = 2;
1595e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org  static const int kLossBurstSize = 2;
1605e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org  static const int kPacketsBetweenLossBursts = 9;
161bf6d5729629fc98dbbf8a4965cec1efe93cad895pbos@webrtc.org
1628ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org public:
163ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org  NackObserver()
16451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      : test::RtpRtcpObserver(kLongTimeoutMs),
165ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org        rtp_parser_(RtpHeaderParser::Create()),
166ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org        sent_rtp_packets_(0),
1675e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org        packets_left_to_drop_(0),
1688ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org        nacks_left_(kNumberOfNacksToObserve) {}
169ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
170ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org private:
1718ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
172ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org    RTPHeader header;
173ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org    EXPECT_TRUE(rtp_parser_->Parse(packet, static_cast<int>(length), &header));
174ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
175ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org    // Never drop retransmitted packets.
176ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org    if (dropped_packets_.find(header.sequenceNumber) !=
177ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org        dropped_packets_.end()) {
178ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org      retransmitted_packets_.insert(header.sequenceNumber);
1795e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org      if (nacks_left_ == 0 &&
1805e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org          retransmitted_packets_.size() == dropped_packets_.size()) {
1815e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org        observation_complete_->Set();
1825e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org      }
1838ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org      return SEND_PACKET;
184ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org    }
185ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
1865e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org    ++sent_rtp_packets_;
1875e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org
188ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org    // Enough NACKs received, stop dropping packets.
1895e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org    if (nacks_left_ == 0)
1908ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org      return SEND_PACKET;
191ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
1925e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org    // Check if it's time for a new loss burst.
1935e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org    if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
1945e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org      packets_left_to_drop_ = kLossBurstSize;
195ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
1965e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org    if (packets_left_to_drop_ > 0) {
1975e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org      --packets_left_to_drop_;
198ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org      dropped_packets_.insert(header.sequenceNumber);
1998ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org      return DROP_PACKET;
200ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org    }
201ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
2028ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    return SEND_PACKET;
2038ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  }
2048ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
2058ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
2068ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    RTCPUtility::RTCPParserV2 parser(packet, length, true);
2078ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    EXPECT_TRUE(parser.IsValid());
2088ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
2098ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
2108ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    while (packet_type != RTCPUtility::kRtcpNotValidCode) {
2115e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org      if (packet_type == RTCPUtility::kRtcpRtpfbNackCode) {
2125e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org        --nacks_left_;
2135e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org        break;
2145e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org      }
2158ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org      packet_type = parser.Iterate();
2168ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    }
2178ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    return SEND_PACKET;
218ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org  }
219ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
2208ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org private:
221ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org  scoped_ptr<RtpHeaderParser> rtp_parser_;
222ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org  std::set<uint16_t> dropped_packets_;
223ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org  std::set<uint16_t> retransmitted_packets_;
224ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org  uint64_t sent_rtp_packets_;
2255e252aced18e522340f8cd5bab35baaf8a57aa66mflodman@webrtc.org  int packets_left_to_drop_;
226ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org  int nacks_left_;
227ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org};
228ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
22975e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.orgTEST_F(CallTest, ReceiverCanBeStartedTwice) {
23075e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  test::NullTransport transport;
23175e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  CreateCalls(Call::Config(&transport), Call::Config(&transport));
23275e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
23375e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  CreateTestConfigs();
23475e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  CreateStreams();
23575e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
23616a058a180164c32a13f3406d35cc3ef1ad569c4pbos@webrtc.org  receive_stream_->Start();
23716a058a180164c32a13f3406d35cc3ef1ad569c4pbos@webrtc.org  receive_stream_->Start();
23875e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
23975e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  DestroyStreams();
24075e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org}
24175e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
24275e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.orgTEST_F(CallTest, ReceiverCanBeStoppedTwice) {
24375e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  test::NullTransport transport;
24475e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  CreateCalls(Call::Config(&transport), Call::Config(&transport));
24575e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
24675e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  CreateTestConfigs();
24775e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  CreateStreams();
24875e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
24916a058a180164c32a13f3406d35cc3ef1ad569c4pbos@webrtc.org  receive_stream_->Stop();
25016a058a180164c32a13f3406d35cc3ef1ad569c4pbos@webrtc.org  receive_stream_->Stop();
25175e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
25275e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org  DestroyStreams();
25375e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org}
25475e7da3a6108c34768fc56cdb932c2919c0dd867pbos@webrtc.org
255d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.orgTEST_F(CallTest, RendersSingleDelayedFrame) {
256d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  static const int kWidth = 320;
257d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  static const int kHeight = 240;
258d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  // This constant is chosen to be higher than the timeout in the video_render
259d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  // module. This makes sure that frames aren't dropped if there are no other
260d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  // frames in the queue.
261d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  static const int kDelayRenderCallbackMs = 1000;
262d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
263d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  class Renderer : public VideoRenderer {
264d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org   public:
265d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    Renderer() : event_(EventWrapper::Create()) {}
266d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
267d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    virtual void RenderFrame(const I420VideoFrame& video_frame,
268d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org                             int /*time_to_render_ms*/) OVERRIDE {
269d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org      event_->Set();
270d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    }
271d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
272d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
273d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
274d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    scoped_ptr<EventWrapper> event_;
275d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  } renderer;
276d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
277d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  class TestFrameCallback : public I420FrameCallback {
278d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org   public:
279d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    TestFrameCallback() : event_(EventWrapper::Create()) {}
280d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
281d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
282d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
283d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org   private:
284c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE {
285d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org      SleepMs(kDelayRenderCallbackMs);
286d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org      event_->Set();
287d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    }
288d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
289d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org    scoped_ptr<EventWrapper> event_;
290d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  };
291d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
292d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  test::DirectTransport sender_transport, receiver_transport;
293d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
294d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  CreateCalls(Call::Config(&sender_transport),
295d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org              Call::Config(&receiver_transport));
296d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
297d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  sender_transport.SetReceiver(receiver_call_->Receiver());
298d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  receiver_transport.SetReceiver(sender_call_->Receiver());
299d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
300d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  CreateTestConfigs();
301d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
302d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  TestFrameCallback pre_render_callback;
303d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  receive_config_.pre_render_callback = &pre_render_callback;
304d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  receive_config_.renderer = &renderer;
305d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
306d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  CreateStreams();
307d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  StartSending();
308d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
309d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  // Create frames that are smaller than the send width/height, this is done to
310d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  // check that the callbacks are done after processing video.
311d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  scoped_ptr<test::FrameGenerator> frame_generator(
312d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org      test::FrameGenerator::Create(kWidth, kHeight));
313d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
314d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
315d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org      << "Timed out while waiting for pre-render callback.";
316d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  EXPECT_EQ(kEventSignaled, renderer.Wait())
317d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org      << "Timed out while waiting for the frame to render.";
318d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
319d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  StopSending();
320d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
321d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  sender_transport.StopSending();
322d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  receiver_transport.StopSending();
323d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
324d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org  DestroyStreams();
325d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org}
326d60137ff1b936534b04396298b7d2f2ebbc1da82pbos@webrtc.org
327c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.orgTEST_F(CallTest, TransmitsFirstFrame) {
328c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  class Renderer : public VideoRenderer {
329c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org   public:
330c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org    Renderer() : event_(EventWrapper::Create()) {}
331c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
332c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org    virtual void RenderFrame(const I420VideoFrame& video_frame,
333c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org                             int /*time_to_render_ms*/) OVERRIDE {
334c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org      event_->Set();
335c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org    }
336c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
337c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
338c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
339c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org    scoped_ptr<EventWrapper> event_;
340c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  } renderer;
341c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
342c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  test::DirectTransport sender_transport, receiver_transport;
343c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
344c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  CreateCalls(Call::Config(&sender_transport),
345c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org              Call::Config(&receiver_transport));
346c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
347c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  sender_transport.SetReceiver(receiver_call_->Receiver());
348c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  receiver_transport.SetReceiver(sender_call_->Receiver());
349c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
350c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  CreateTestConfigs();
351c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  receive_config_.renderer = &renderer;
352c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
353c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  CreateStreams();
354c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  StartSending();
355c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
356c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
357bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org      video_streams_[0].width, video_streams_[0].height));
358c33d37ce205e22c0e090b0b285ed963686bf24dcpbos@webrtc.org  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
359c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
360c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  EXPECT_EQ(kEventSignaled, renderer.Wait())
361c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org      << "Timed out while waiting for the frame to render.";
362c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
363c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  StopSending();
364c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
365c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  sender_transport.StopSending();
366c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  receiver_transport.StopSending();
367c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
368c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org  DestroyStreams();
369c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org}
370c5b5ad1aac76a7379ab0a0a4e6eab0811f5bfc37pbos@webrtc.org
3714b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.orgTEST_F(CallTest, ReceiverUsesLocalSsrc) {
3724b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org  class SyncRtcpObserver : public test::RtpRtcpObserver {
3734b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org   public:
3744b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org    SyncRtcpObserver() : test::RtpRtcpObserver(kDefaultTimeoutMs) {}
3754b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
3764b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org    virtual Action OnReceiveRtcp(const uint8_t* packet,
3774b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org                                 size_t length) OVERRIDE {
3784b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      RTCPUtility::RTCPParserV2 parser(packet, length, true);
3794b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      EXPECT_TRUE(parser.IsValid());
3804b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      uint32_t ssrc = 0;
3814b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      ssrc |= static_cast<uint32_t>(packet[4]) << 24;
3824b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      ssrc |= static_cast<uint32_t>(packet[5]) << 16;
3834b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      ssrc |= static_cast<uint32_t>(packet[6]) << 8;
3844b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      ssrc |= static_cast<uint32_t>(packet[7]) << 0;
3854b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      EXPECT_EQ(kReceiverLocalSsrc, ssrc);
3864b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      observation_complete_->Set();
3874b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
3884b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      return SEND_PACKET;
3894b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org    }
3904b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org  } observer;
3914b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
3924b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org  CreateCalls(Call::Config(observer.SendTransport()),
3934b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org              Call::Config(observer.ReceiveTransport()));
3944b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
3954b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
3964b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
3974b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org  CreateTestConfigs();
3984b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
3994b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org  CreateStreams();
4004b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org  CreateFrameGenerator();
4014b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org  StartSending();
4024b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
4034b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org  EXPECT_EQ(kEventSignaled, observer.Wait())
4044b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org      << "Timed out while waiting for a receiver RTCP packet to be sent.";
4054b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
4064b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org  StopSending();
4074b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
4084b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org  observer.StopSending();
4094b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
4104b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org  DestroyStreams();
4114b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org}
4124b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org
413362e3e55056af7675a4d79dc94f1c30bbbf90569pbos@webrtc.orgTEST_F(CallTest, ReceivesAndRetransmitsNack) {
4148ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  NackObserver observer;
415ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
416b5d2d165c78331b337bc372babc3a1a3e62172afpbos@webrtc.org  CreateCalls(Call::Config(observer.SendTransport()),
417b5d2d165c78331b337bc372babc3a1a3e62172afpbos@webrtc.org              Call::Config(observer.ReceiveTransport()));
418ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
4198ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
4208ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
4218ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  CreateTestConfigs();
4228ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  int rtp_history_ms = 1000;
4238ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
4248ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
425ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
4268ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  CreateStreams();
4278ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  CreateFrameGenerator();
4288ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  StartSending();
429ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
4308ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  // Wait() waits for an event triggered when NACKs have been received, NACKed
4318ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  // packets retransmitted and frames rendered again.
4328ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  EXPECT_EQ(kEventSignaled, observer.Wait());
4338ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
4348ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  StopSending();
4358ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
4368ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  observer.StopSending();
437ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
438ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  DestroyStreams();
439ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org}
440ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
441fb3f14e334ffeeeea5c9f6666b02dfdcdb268375pbos@webrtc.org// TODO(pbos): Flaky, webrtc:3269
442fb3f14e334ffeeeea5c9f6666b02dfdcdb268375pbos@webrtc.orgTEST_F(CallTest, DISABLED_CanReceiveFec) {
443ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  class FecRenderObserver : public test::RtpRtcpObserver, public VideoRenderer {
444ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org   public:
445ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org    FecRenderObserver()
446ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org        : RtpRtcpObserver(kDefaultTimeoutMs),
447ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          state_(kFirstPacket),
448ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          protected_sequence_number_(0),
449ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          protected_frame_timestamp_(0) {}
450ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
451ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org   private:
452c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE
453c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org        EXCLUSIVE_LOCKS_REQUIRED(crit_) {
454ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      RTPHeader header;
455ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
456ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
457ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      EXPECT_EQ(kRedPayloadType, header.payloadType);
458ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      int encapsulated_payload_type =
459ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          static_cast<int>(packet[header.headerLength]);
460ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      if (encapsulated_payload_type != kSendPayloadType)
461ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org        EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
462ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
463ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      switch(state_) {
464ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org        case kFirstPacket:
465ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          state_ = kDropEveryOtherPacketUntilFec;
466ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          break;
467ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org        case kDropEveryOtherPacketUntilFec:
468ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          if (encapsulated_payload_type == kUlpfecPayloadType) {
469ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org            state_ = kDropNextMediaPacket;
470ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org            return SEND_PACKET;
471ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          }
472ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          if (header.sequenceNumber % 2 == 0)
473ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org            return DROP_PACKET;
474ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          break;
475ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org        case kDropNextMediaPacket:
476ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          if (encapsulated_payload_type == kSendPayloadType) {
477ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org            protected_sequence_number_ = header.sequenceNumber;
478ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org            protected_frame_timestamp_ = header.timestamp;
479ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org            state_ = kProtectedPacketDropped;
480ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org            return DROP_PACKET;
481ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          }
482ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          break;
483ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org        case kProtectedPacketDropped:
484ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          EXPECT_NE(header.sequenceNumber, protected_sequence_number_)
485ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org              << "Protected packet retransmitted. Should not happen with FEC.";
486ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          break;
487ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      }
488ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
489ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      return SEND_PACKET;
490ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org    }
491ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
492ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org    virtual void RenderFrame(const I420VideoFrame& video_frame,
493ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org                             int time_to_render_ms) OVERRIDE {
494c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org      CriticalSectionScoped lock(crit_.get());
495ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      // Rendering frame with timestamp associated with dropped packet -> FEC
496ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      // protection worked.
497ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      if (state_ == kProtectedPacketDropped &&
498ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org          video_frame.timestamp() == protected_frame_timestamp_) {
499ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org        observation_complete_->Set();
500ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      }
501ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org    }
502ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
503ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org    enum {
504ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      kFirstPacket,
505ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      kDropEveryOtherPacketUntilFec,
506ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      kDropNextMediaPacket,
507ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org      kProtectedPacketDropped,
508ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org    } state_;
509ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
510c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org    uint32_t protected_sequence_number_ GUARDED_BY(crit_);
511c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org    uint32_t protected_frame_timestamp_ GUARDED_BY(crit_);
512ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  } observer;
513ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
514ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  CreateCalls(Call::Config(observer.SendTransport()),
515ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org              Call::Config(observer.ReceiveTransport()));
516ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
517ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
518ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
519ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  CreateTestConfigs();
520ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
521ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  // int rtp_history_ms = 1000;
522ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  // receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
523ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  // send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
524ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  send_config_.rtp.fec.red_payload_type = kRedPayloadType;
525ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
526ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
527ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  receive_config_.rtp.fec.red_payload_type = kRedPayloadType;
528ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  receive_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
529ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  receive_config_.renderer = &observer;
530ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
531ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  CreateStreams();
532ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  CreateFrameGenerator();
533ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  StartSending();
534ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
535ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  // Wait() waits for an event triggered when NACKs have been received, NACKed
536ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  // packets retransmitted and frames rendered again.
537ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  EXPECT_EQ(kEventSignaled, observer.Wait());
538ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
539ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  StopSending();
540ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org
541ea15f8d77dd35ea068ee01325fb1602e9a0b7771pbos@webrtc.org  observer.StopSending();
542618a0ec1d2c17d485b7ce51cbfd282e6bae8e019pbos@webrtc.org
543618a0ec1d2c17d485b7ce51cbfd282e6bae8e019pbos@webrtc.org  DestroyStreams();
5448ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org}
545ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
546c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org// This test drops second RTP packet with a marker bit set, makes sure it's
547c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org// retransmitted and renders. Retransmission SSRCs are also checked.
548c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.orgvoid CallTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) {
549c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  static const int kDroppedFrameNumber = 2;
550c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  class RetransmissionObserver : public test::RtpRtcpObserver,
551c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org                                 public I420FrameCallback {
552c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org   public:
553c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    RetransmissionObserver(bool expect_rtx)
554c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        : RtpRtcpObserver(kDefaultTimeoutMs),
555c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org          retransmission_ssrc_(expect_rtx ? kSendRtxSsrc : kSendSsrc),
556c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org          retransmission_payload_type_(expect_rtx ? kSendRtxPayloadType
557c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org                                                  : kSendPayloadType),
558c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org          marker_bits_observed_(0),
559c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org          retransmitted_timestamp_(0),
560c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org          frame_retransmitted_(false) {}
561c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
562c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org   private:
563c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
564c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      RTPHeader header;
565c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
566c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
567c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      if (header.timestamp == retransmitted_timestamp_) {
568c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        EXPECT_EQ(retransmission_ssrc_, header.ssrc);
569c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        EXPECT_EQ(retransmission_payload_type_, header.payloadType);
570c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        frame_retransmitted_ = true;
571c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        return SEND_PACKET;
572c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      }
573c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
574c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      EXPECT_EQ(kSendSsrc, header.ssrc);
575c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      EXPECT_EQ(kSendPayloadType, header.payloadType);
576c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
577c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      // Found the second frame's final packet, drop this and expect a
578c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      // retransmission.
579c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
580c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        retransmitted_timestamp_ = header.timestamp;
581c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        return DROP_PACKET;
582c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      }
583c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
584c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      return SEND_PACKET;
585c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    }
586c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
587c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    virtual void FrameCallback(I420VideoFrame* frame) OVERRIDE {
588c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org      CriticalSectionScoped lock(crit_.get());
589c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      if (frame->timestamp() == retransmitted_timestamp_) {
590c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        EXPECT_TRUE(frame_retransmitted_);
591c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        observation_complete_->Set();
592c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      }
593c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    }
594c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
595c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    const uint32_t retransmission_ssrc_;
596c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    const int retransmission_payload_type_;
597c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    int marker_bits_observed_;
598c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    uint32_t retransmitted_timestamp_;
599c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    bool frame_retransmitted_;
600c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  } observer(retransmit_over_rtx);
601c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
602c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  CreateCalls(Call::Config(observer.SendTransport()),
603c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org              Call::Config(observer.ReceiveTransport()));
604c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
605c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
606c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
607c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  CreateTestConfigs();
608c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  send_config_.rtp.nack.rtp_history_ms =
609c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      receive_config_.rtp.nack.rtp_history_ms = 1000;
610c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  if (retransmit_over_rtx) {
611c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrc);
612c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
613e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    int payload_type = send_config_.encoder_settings.payload_type;
614c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    receive_config_.rtp.rtx[payload_type].ssrc = kSendRtxSsrc;
615c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    receive_config_.rtp.rtx[payload_type].payload_type = kSendRtxPayloadType;
616c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  }
617c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  receive_config_.pre_render_callback = &observer;
618c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
619c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  CreateStreams();
620c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  CreateFrameGenerator();
621c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  StartSending();
622c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
623c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  EXPECT_EQ(kEventSignaled, observer.Wait())
624c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org      << "Timed out while waiting for retransmission to render.";
625c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
626c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  StopSending();
627c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  observer.StopSending();
628c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  DestroyStreams();
629c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org}
630c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
631c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.orgTEST_F(CallTest, DecodesRetransmittedFrame) {
632c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  DecodesRetransmittedFrame(false);
633c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org}
634c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
635c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.orgTEST_F(CallTest, DecodesRetransmittedFrameOverRtx) {
636c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  DecodesRetransmittedFrame(true);
637c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org}
638c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
63963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.orgTEST_F(CallTest, UsesFrameCallbacks) {
64063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  static const int kWidth = 320;
64163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  static const int kHeight = 240;
64263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
64363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  class Renderer : public VideoRenderer {
64463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org   public:
64563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    Renderer() : event_(EventWrapper::Create()) {}
64663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
64763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    virtual void RenderFrame(const I420VideoFrame& video_frame,
64863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org                             int /*time_to_render_ms*/) OVERRIDE {
64963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      EXPECT_EQ(0, *video_frame.buffer(kYPlane))
65063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org          << "Rendered frame should have zero luma which is applied by the "
65163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org             "pre-render callback.";
65263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      event_->Set();
65363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    }
65463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
65563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
65663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    scoped_ptr<EventWrapper> event_;
65763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  } renderer;
65863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
65963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  class TestFrameCallback : public I420FrameCallback {
66063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org   public:
66163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    TestFrameCallback(int expected_luma_byte, int next_luma_byte)
66263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org        : event_(EventWrapper::Create()),
66363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org          expected_luma_byte_(expected_luma_byte),
66463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org          next_luma_byte_(next_luma_byte) {}
66563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
66663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
66763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
66863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org   private:
66963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    virtual void FrameCallback(I420VideoFrame* frame) {
67063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      EXPECT_EQ(kWidth, frame->width())
67163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org          << "Width not as expected, callback done before resize?";
67263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      EXPECT_EQ(kHeight, frame->height())
67363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org          << "Height not as expected, callback done before resize?";
67463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
67563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      // Previous luma specified, observed luma should be fairly close.
67663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      if (expected_luma_byte_ != -1) {
67763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org        EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
67863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      }
67963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
68063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      memset(frame->buffer(kYPlane),
68163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org             next_luma_byte_,
68263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org             frame->allocated_size(kYPlane));
68363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
68463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      event_->Set();
68563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    }
68663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
68763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    scoped_ptr<EventWrapper> event_;
68863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    int expected_luma_byte_;
68963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    int next_luma_byte_;
69063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  };
69163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
69263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  TestFrameCallback pre_encode_callback(-1, 255);  // Changes luma to 255.
69363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  TestFrameCallback pre_render_callback(255, 0);  // Changes luma from 255 to 0.
69463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
69563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  test::DirectTransport sender_transport, receiver_transport;
69663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
69763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  CreateCalls(Call::Config(&sender_transport),
69863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org              Call::Config(&receiver_transport));
69963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
70063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  sender_transport.SetReceiver(receiver_call_->Receiver());
70163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  receiver_transport.SetReceiver(sender_call_->Receiver());
70263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
70363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  CreateTestConfigs();
704e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org  scoped_ptr<VP8Encoder> encoder(VP8Encoder::Create());
705e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org  send_config_.encoder_settings.encoder = encoder.get();
706e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org  send_config_.encoder_settings.payload_name = "VP8";
707bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org  ASSERT_EQ(1u, video_streams_.size()) << "Test setup error.";
708bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org  video_streams_[0].width = kWidth;
709bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org  video_streams_[0].height = kHeight;
71063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  send_config_.pre_encode_callback = &pre_encode_callback;
711e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org  receive_config_.codecs.clear();
712e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org  VideoCodec codec =
713e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org      test::CreateDecoderVideoCodec(send_config_.encoder_settings);
714e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org  receive_config_.external_decoders.clear();
715e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org  receive_config_.codecs.push_back(codec);
71663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  receive_config_.pre_render_callback = &pre_render_callback;
71763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  receive_config_.renderer = &renderer;
71863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
71963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  CreateStreams();
72063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  StartSending();
72163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
72263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  // Create frames that are smaller than the send width/height, this is done to
72363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  // check that the callbacks are done after processing video.
72463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  scoped_ptr<test::FrameGenerator> frame_generator(
72563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      test::FrameGenerator::Create(kWidth / 2, kHeight / 2));
726c33d37ce205e22c0e090b0b285ed963686bf24dcpbos@webrtc.org  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
72763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
72863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  EXPECT_EQ(kEventSignaled, pre_encode_callback.Wait())
72963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      << "Timed out while waiting for pre-encode callback.";
73063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
73163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      << "Timed out while waiting for pre-render callback.";
73263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  EXPECT_EQ(kEventSignaled, renderer.Wait())
73363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      << "Timed out while waiting for the frame to render.";
73463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
73563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  StopSending();
73663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
73763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  sender_transport.StopSending();
73863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  receiver_transport.StopSending();
73963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
74063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  DestroyStreams();
74163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org}
74263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
74328a116612e93168906d26fc69c43b10afe434c68pbos@webrtc.orgclass PliObserver : public test::RtpRtcpObserver, public VideoRenderer {
7448ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  static const int kInverseDropProbability = 16;
745bf6d5729629fc98dbbf8a4965cec1efe93cad895pbos@webrtc.org
7468ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org public:
74728a116612e93168906d26fc69c43b10afe434c68pbos@webrtc.org  explicit PliObserver(bool nack_enabled)
74851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      : test::RtpRtcpObserver(kLongTimeoutMs),
7498ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org        nack_enabled_(nack_enabled),
7506c172c5af42b2d10e71b12ef0ed74864dce1ecfdmflodman@webrtc.org        highest_dropped_timestamp_(0),
7516c172c5af42b2d10e71b12ef0ed74864dce1ecfdmflodman@webrtc.org        frames_to_drop_(0),
7528ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org        received_pli_(false) {}
7538ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
7548ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
7558ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    RTPHeader header;
756c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
7578ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
7586c172c5af42b2d10e71b12ef0ed74864dce1ecfdmflodman@webrtc.org    // Drop all retransmitted packets to force a PLI.
7596c172c5af42b2d10e71b12ef0ed74864dce1ecfdmflodman@webrtc.org    if (header.timestamp <= highest_dropped_timestamp_)
7608ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org      return DROP_PACKET;
7618ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
7626c172c5af42b2d10e71b12ef0ed74864dce1ecfdmflodman@webrtc.org    if (frames_to_drop_ > 0) {
7636c172c5af42b2d10e71b12ef0ed74864dce1ecfdmflodman@webrtc.org      highest_dropped_timestamp_ = header.timestamp;
7646c172c5af42b2d10e71b12ef0ed74864dce1ecfdmflodman@webrtc.org      --frames_to_drop_;
7658ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org      return DROP_PACKET;
7668ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    }
7678ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
7688ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    return SEND_PACKET;
769ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org  }
770ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
7718ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
7728ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    RTCPUtility::RTCPParserV2 parser(packet, length, true);
7738ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    EXPECT_TRUE(parser.IsValid());
7748ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
7758ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
7768ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org         packet_type != RTCPUtility::kRtcpNotValidCode;
7778ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org         packet_type = parser.Iterate()) {
7788ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org      if (!nack_enabled_)
7798ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org        EXPECT_NE(packet_type, RTCPUtility::kRtcpRtpfbNackCode);
7808ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
7818ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org      if (packet_type == RTCPUtility::kRtcpPsfbPliCode) {
7828ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org        received_pli_ = true;
7838ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org        break;
7848ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org      }
7858ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    }
7868ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    return SEND_PACKET;
787ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org  }
788ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
78928a116612e93168906d26fc69c43b10afe434c68pbos@webrtc.org  virtual void RenderFrame(const I420VideoFrame& video_frame,
79028a116612e93168906d26fc69c43b10afe434c68pbos@webrtc.org                           int time_to_render_ms) OVERRIDE {
791c476e64d056c5e342bc5b23eecd493abf6d85d7fpbos@webrtc.org    CriticalSectionScoped lock(crit_.get());
7926c172c5af42b2d10e71b12ef0ed74864dce1ecfdmflodman@webrtc.org    if (received_pli_ && video_frame.timestamp() > highest_dropped_timestamp_) {
79328a116612e93168906d26fc69c43b10afe434c68pbos@webrtc.org      observation_complete_->Set();
7948ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org    }
7956c172c5af42b2d10e71b12ef0ed74864dce1ecfdmflodman@webrtc.org    if (!received_pli_)
7966c172c5af42b2d10e71b12ef0ed74864dce1ecfdmflodman@webrtc.org      frames_to_drop_ = kPacketsToDrop;
7978ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  }
798ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
7998ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org private:
8006c172c5af42b2d10e71b12ef0ed74864dce1ecfdmflodman@webrtc.org  static const int kPacketsToDrop = 1;
8016c172c5af42b2d10e71b12ef0ed74864dce1ecfdmflodman@webrtc.org
8028ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  bool nack_enabled_;
8036c172c5af42b2d10e71b12ef0ed74864dce1ecfdmflodman@webrtc.org  uint32_t highest_dropped_timestamp_;
8046c172c5af42b2d10e71b12ef0ed74864dce1ecfdmflodman@webrtc.org  int frames_to_drop_;
8058ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  bool received_pli_;
8068ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org};
807ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
80828a116612e93168906d26fc69c43b10afe434c68pbos@webrtc.orgvoid CallTest::ReceivesPliAndRecovers(int rtp_history_ms) {
8098ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  PliObserver observer(rtp_history_ms > 0);
810ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
811b5d2d165c78331b337bc372babc3a1a3e62172afpbos@webrtc.org  CreateCalls(Call::Config(observer.SendTransport()),
812b5d2d165c78331b337bc372babc3a1a3e62172afpbos@webrtc.org              Call::Config(observer.ReceiveTransport()));
813ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
8148ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
815ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
8168ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  CreateTestConfigs();
8178ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  send_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
8188ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  receive_config_.rtp.nack.rtp_history_ms = rtp_history_ms;
81928a116612e93168906d26fc69c43b10afe434c68pbos@webrtc.org  receive_config_.renderer = &observer;
820ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
8218ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  CreateStreams();
8228ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  CreateFrameGenerator();
8238ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  StartSending();
824ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
8258ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  // Wait() waits for an event triggered when Pli has been received and frames
8268ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  // have been rendered afterwards.
827ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org  EXPECT_EQ(kEventSignaled, observer.Wait());
828ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
8298ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  StopSending();
8308ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
831fe881f62ea79a98b997af7d6fb0346dcb68acccepbos@webrtc.org  observer.StopSending();
832618a0ec1d2c17d485b7ce51cbfd282e6bae8e019pbos@webrtc.org
833618a0ec1d2c17d485b7ce51cbfd282e6bae8e019pbos@webrtc.org  DestroyStreams();
834ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org}
835ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org
836362e3e55056af7675a4d79dc94f1c30bbbf90569pbos@webrtc.orgTEST_F(CallTest, ReceivesPliAndRecoversWithNack) {
8378ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  ReceivesPliAndRecovers(1000);
8388ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org}
8398ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
8408ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org// TODO(pbos): Enable this when 2250 is resolved.
841362e3e55056af7675a4d79dc94f1c30bbbf90569pbos@webrtc.orgTEST_F(CallTest, DISABLED_ReceivesPliAndRecoversWithoutNack) {
8428ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org  ReceivesPliAndRecovers(0);
8438ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org}
8448ce445ecc8a3fbf2a7517f71e778948f6a8e3d2fpbos@webrtc.org
845bc57e0f1a00227c0cec3d429fc58cc442d07b509pbos@webrtc.orgTEST_F(CallTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
8460020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  class PacketInputObserver : public PacketReceiver {
8470020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org   public:
8480020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org    explicit PacketInputObserver(PacketReceiver* receiver)
8490020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org        : receiver_(receiver), delivered_packet_(EventWrapper::Create()) {}
8500020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
85151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    EventTypeWrapper Wait() {
85251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      return delivered_packet_->Wait(kDefaultTimeoutMs);
85351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    }
8540020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8550020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org   private:
856bc57e0f1a00227c0cec3d429fc58cc442d07b509pbos@webrtc.org    virtual DeliveryStatus DeliverPacket(const uint8_t* packet,
857bc57e0f1a00227c0cec3d429fc58cc442d07b509pbos@webrtc.org                                         size_t length) OVERRIDE {
8580020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org      if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length))) {
8590020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org        return receiver_->DeliverPacket(packet, length);
8600020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org      } else {
861bc57e0f1a00227c0cec3d429fc58cc442d07b509pbos@webrtc.org        DeliveryStatus delivery_status =
862bc57e0f1a00227c0cec3d429fc58cc442d07b509pbos@webrtc.org            receiver_->DeliverPacket(packet, length);
863bc57e0f1a00227c0cec3d429fc58cc442d07b509pbos@webrtc.org        EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
8640020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org        delivered_packet_->Set();
865bc57e0f1a00227c0cec3d429fc58cc442d07b509pbos@webrtc.org        return delivery_status;
8660020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org      }
8670020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org    }
8680020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8690020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org    PacketReceiver* receiver_;
8700020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org    scoped_ptr<EventWrapper> delivered_packet_;
8710020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  };
8720020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8730020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  test::DirectTransport send_transport, receive_transport;
8740020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
875b5d2d165c78331b337bc372babc3a1a3e62172afpbos@webrtc.org  CreateCalls(Call::Config(&send_transport), Call::Config(&receive_transport));
8760020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  PacketInputObserver input_observer(receiver_call_->Receiver());
8770020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8780020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  send_transport.SetReceiver(&input_observer);
8790020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  receive_transport.SetReceiver(sender_call_->Receiver());
8800020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8810020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  CreateTestConfigs();
8820020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8830020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  CreateStreams();
8840020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  CreateFrameGenerator();
8850020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  StartSending();
8860020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
88712a93e063c94500f8fe0a045fc381a816fdf3c69pbos@webrtc.org  receiver_call_->DestroyVideoReceiveStream(receive_stream_);
8880020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  receive_stream_ = NULL;
8890020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8900020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  // Wait() waits for a received packet.
8910020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  EXPECT_EQ(kEventSignaled, input_observer.Wait());
8920020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8930020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  StopSending();
8940020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8950020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  DestroyStreams();
8960020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org
8970020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  send_transport.StopSending();
8980020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org  receive_transport.StopSending();
8990020858e503d18322766b76443d83bfa5db4bffbpbos@webrtc.org}
900c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
90151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.orgvoid CallTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) {
90251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  static const int kRtpHistoryMs = 1000;
90351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  static const int kNumCompoundRtcpPacketsToObserve = 10;
90451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  class RtcpModeObserver : public test::RtpRtcpObserver {
90551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org   public:
906d05597a15dd2d01c8e172df86b960b7d4ac9647fpbos@webrtc.org    explicit RtcpModeObserver(newapi::RtcpMode rtcp_mode)
90751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org        : test::RtpRtcpObserver(kDefaultTimeoutMs),
90851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          rtcp_mode_(rtcp_mode),
90951e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          sent_rtp_(0),
91051e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          sent_rtcp_(0) {}
91151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
91251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org   private:
91351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
91451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      if (++sent_rtp_ % 3 == 0)
91551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org        return DROP_PACKET;
91651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
91751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      return SEND_PACKET;
91851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    }
91951e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
92051e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    virtual Action OnReceiveRtcp(const uint8_t* packet,
92151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org                                 size_t length) OVERRIDE {
92251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      ++sent_rtcp_;
92351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      RTCPUtility::RTCPParserV2 parser(packet, length, true);
92451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      EXPECT_TRUE(parser.IsValid());
92551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
92651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
92751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      bool has_report_block = false;
92851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
92951e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org        EXPECT_NE(RTCPUtility::kRtcpSrCode, packet_type);
93051e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org        if (packet_type == RTCPUtility::kRtcpRrCode) {
93151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          has_report_block = true;
93251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          break;
93351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org        }
93451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org        packet_type = parser.Iterate();
93551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      }
93651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
93751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      switch (rtcp_mode_) {
93851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org        case newapi::kRtcpCompound:
93951e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          if (!has_report_block) {
94051e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org            ADD_FAILURE() << "Received RTCP packet without receiver report for "
94151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org                             "kRtcpCompound.";
94251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org            observation_complete_->Set();
94351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          }
94451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
94551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
94651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org            observation_complete_->Set();
94751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
94851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          break;
94951e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org        case newapi::kRtcpReducedSize:
95051e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          if (!has_report_block)
95151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org            observation_complete_->Set();
95251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org          break;
95351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      }
95451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
95551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      return SEND_PACKET;
95651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    }
95751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
95851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    newapi::RtcpMode rtcp_mode_;
95951e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    int sent_rtp_;
96051e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org    int sent_rtcp_;
96151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  } observer(rtcp_mode);
96251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
96351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  CreateCalls(Call::Config(observer.SendTransport()),
96451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org              Call::Config(observer.ReceiveTransport()));
96551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
96651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
96751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
96851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  CreateTestConfigs();
96951e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  send_config_.rtp.nack.rtp_history_ms = kRtpHistoryMs;
97051e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  receive_config_.rtp.nack.rtp_history_ms = kRtpHistoryMs;
97151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  receive_config_.rtp.rtcp_mode = rtcp_mode;
97251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
97351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  CreateStreams();
97451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  CreateFrameGenerator();
97551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  StartSending();
97651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
97751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  EXPECT_EQ(kEventSignaled, observer.Wait())
97851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org      << (rtcp_mode == newapi::kRtcpCompound
97951e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org              ? "Timed out before observing enough compound packets."
98051e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org              : "Timed out before receiving a non-compound RTCP packet.");
98151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
98251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  StopSending();
98351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  observer.StopSending();
98451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  DestroyStreams();
98551e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org}
98651e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
98751e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.orgTEST_F(CallTest, UsesRtcpCompoundMode) {
98851e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  RespectsRtcpMode(newapi::kRtcpCompound);
98951e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org}
99051e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
99151e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.orgTEST_F(CallTest, UsesRtcpReducedSizeMode) {
99251e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org  RespectsRtcpMode(newapi::kRtcpReducedSize);
99351e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org}
99451e010182b9947c9656f9e81a6a12f64a8e21788pbos@webrtc.org
995c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org// Test sets up a Call multiple senders with different resolutions and SSRCs.
996c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org// Another is set up to receive all three of these with different renderers.
997c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org// Each renderer verifies that it receives the expected resolution, and as soon
998c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org// as every renderer has received a frame, the test finishes.
999c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.orgTEST_F(CallTest, SendsAndReceivesMultipleStreams) {
1000c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  static const size_t kNumStreams = 3;
1001c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1002c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  class VideoOutputObserver : public VideoRenderer {
1003c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org   public:
10044383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org    VideoOutputObserver(test::FrameGeneratorCapturer** capturer,
10054383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org                        int width,
10064383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org                        int height)
10074383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org        : capturer_(capturer),
10084383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org          width_(width),
10094383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org          height_(height),
10104383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org          done_(EventWrapper::Create()) {}
1011c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1012c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    virtual void RenderFrame(const I420VideoFrame& video_frame,
1013c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org                             int time_to_render_ms) OVERRIDE {
1014c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org      EXPECT_EQ(width_, video_frame.width());
1015c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org      EXPECT_EQ(height_, video_frame.height());
10164383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org      (*capturer_)->Stop();
1017c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org      done_->Set();
1018c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    }
1019c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1020e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
1021c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1022c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org   private:
10234383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org    test::FrameGeneratorCapturer** capturer_;
1024c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    int width_;
1025c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    int height_;
1026c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    scoped_ptr<EventWrapper> done_;
1027c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  };
1028c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1029c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  struct {
1030c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    uint32_t ssrc;
1031c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    int width;
1032c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    int height;
1033c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  } codec_settings[kNumStreams] = {{1, 640, 480}, {2, 320, 240}, {3, 240, 160}};
1034c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1035c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  test::DirectTransport sender_transport, receiver_transport;
1036c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  scoped_ptr<Call> sender_call(Call::Create(Call::Config(&sender_transport)));
1037c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  scoped_ptr<Call> receiver_call(
1038c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org      Call::Create(Call::Config(&receiver_transport)));
1039c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  sender_transport.SetReceiver(receiver_call->Receiver());
1040c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  receiver_transport.SetReceiver(sender_call->Receiver());
1041c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1042c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  VideoSendStream* send_streams[kNumStreams];
1043c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  VideoReceiveStream* receive_streams[kNumStreams];
1044c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1045c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  VideoOutputObserver* observers[kNumStreams];
1046c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  test::FrameGeneratorCapturer* frame_generators[kNumStreams];
1047c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1048e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org  scoped_ptr<VP8Encoder> encoders[kNumStreams];
1049e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org  for (size_t i = 0; i < kNumStreams; ++i)
1050e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    encoders[i].reset(VP8Encoder::Create());
1051e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org
1052c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  for (size_t i = 0; i < kNumStreams; ++i) {
1053c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    uint32_t ssrc = codec_settings[i].ssrc;
1054c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    int width = codec_settings[i].width;
1055c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    int height = codec_settings[i].height;
10564383539b27ae877337679901c1cc9120f3a83fefpbos@webrtc.org    observers[i] = new VideoOutputObserver(&frame_generators[i], width, height);
1057c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1058e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    VideoSendStream::Config send_config = sender_call->GetDefaultSendConfig();
1059e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    send_config.rtp.ssrcs.push_back(ssrc);
1060bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    send_config.encoder_settings.encoder = encoders[i].get();
1061bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    send_config.encoder_settings.payload_name = "VP8";
1062bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    send_config.encoder_settings.payload_type = 124;
1063bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    std::vector<VideoStream> video_streams = test::CreateVideoStreams(1);
1064bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    VideoStream* stream = &video_streams[0];
1065e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    stream->width = width;
1066e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    stream->height = height;
1067e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    stream->max_framerate = 5;
1068e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    stream->min_bitrate_bps = stream->target_bitrate_bps =
1069e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org        stream->max_bitrate_bps = 100000;
1070bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org    send_streams[i] =
1071bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org        sender_call->CreateVideoSendStream(send_config, video_streams, NULL);
107216a058a180164c32a13f3406d35cc3ef1ad569c4pbos@webrtc.org    send_streams[i]->Start();
1073e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org
1074c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    VideoReceiveStream::Config receive_config =
1075c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org        receiver_call->GetDefaultReceiveConfig();
1076c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    receive_config.renderer = observers[i];
10774b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org    receive_config.rtp.remote_ssrc = ssrc;
10784b50db1f8ce21cc7faf4f7c80b6a492dffb2a1d5pbos@webrtc.org    receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
1079e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    VideoCodec codec =
1080e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org        test::CreateDecoderVideoCodec(send_config.encoder_settings);
1081e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    receive_config.codecs.push_back(codec);
1082964d78e5c80ec8e4cbaeece5f119806b1ef9ea22pbos@webrtc.org    receive_streams[i] =
1083964d78e5c80ec8e4cbaeece5f119806b1ef9ea22pbos@webrtc.org        receiver_call->CreateVideoReceiveStream(receive_config);
108416a058a180164c32a13f3406d35cc3ef1ad569c4pbos@webrtc.org    receive_streams[i]->Start();
1085c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1086c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    frame_generators[i] = test::FrameGeneratorCapturer::Create(
1087c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org        send_streams[i]->Input(), width, height, 30, Clock::GetRealTimeClock());
1088c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    frame_generators[i]->Start();
1089c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  }
1090c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1091c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  for (size_t i = 0; i < kNumStreams; ++i) {
1092e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org    EXPECT_EQ(kEventSignaled, observers[i]->Wait())
1093e2a7a77646b23fb3704d267e6079e04bde493543pbos@webrtc.org        << "Timed out while waiting for observer " << i << " to render.";
1094c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  }
1095c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1096c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  for (size_t i = 0; i < kNumStreams; ++i) {
1097c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    frame_generators[i]->Stop();
109812a93e063c94500f8fe0a045fc381a816fdf3c69pbos@webrtc.org    sender_call->DestroyVideoSendStream(send_streams[i]);
109912a93e063c94500f8fe0a045fc381a816fdf3c69pbos@webrtc.org    receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1100471354f94ed73da7195e2f8e72c5a2239b9a9afbpbos@webrtc.org    delete frame_generators[i];
1101c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org    delete observers[i];
1102c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  }
1103c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org
1104c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  sender_transport.StopSending();
1105c5080a993e1be0ee14292f5fe8cd7a5b30033f5fpbos@webrtc.org  receiver_transport.StopSending();
110646f72884ad5c4078fa324626aa69e4860e4d4ae2pbos@webrtc.org};
1107e028410838cd976c75e379b3c2e2eb0ac52b3c99stefan@webrtc.org
11082e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.orgTEST_F(CallTest, ObserversEncodedFrames) {
11092e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  class EncodedFrameTestObserver : public EncodedFrameObserver {
11102e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org   public:
1111c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    EncodedFrameTestObserver()
1112c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        : length_(0),
1113c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org          frame_type_(kFrameEmpty),
1114c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org          called_(EventWrapper::Create()) {}
11152e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    virtual ~EncodedFrameTestObserver() {}
11162e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11172e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
11182e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      frame_type_ = encoded_frame.frame_type_;
11192e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      length_ = encoded_frame.length_;
11202e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      buffer_.reset(new uint8_t[length_]);
11212e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      memcpy(buffer_.get(), encoded_frame.data_, length_);
11222e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      called_->Set();
11232e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    }
11242e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
1125c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org    EventTypeWrapper Wait() { return called_->Wait(kDefaultTimeoutMs); }
11262e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11272e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
11282e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      ASSERT_EQ(length_, observer.length_)
11292e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org          << "Observed frames are of different lengths.";
11302e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      EXPECT_EQ(frame_type_, observer.frame_type_)
11312e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org          << "Observed frames have different frame types.";
11322e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
11332e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org          << "Observed encoded frames have different content.";
11342e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    }
11352e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11362e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org   private:
11372e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    scoped_ptr<uint8_t[]> buffer_;
11382e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    size_t length_;
11392e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    FrameType frame_type_;
11402e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org    scoped_ptr<EventWrapper> called_;
11412e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  };
11422e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11432e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  EncodedFrameTestObserver post_encode_observer;
11442e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  EncodedFrameTestObserver pre_decode_observer;
11452e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11462e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  test::DirectTransport sender_transport, receiver_transport;
11472e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11482e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  CreateCalls(Call::Config(&sender_transport),
11492e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org              Call::Config(&receiver_transport));
11502e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11512e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  sender_transport.SetReceiver(receiver_call_->Receiver());
11522e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  receiver_transport.SetReceiver(sender_call_->Receiver());
11532e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11542e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  CreateTestConfigs();
11552e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  send_config_.post_encode_callback = &post_encode_observer;
11562e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  receive_config_.pre_decode_callback = &pre_decode_observer;
11572e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11582e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  CreateStreams();
11592e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  StartSending();
11602e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11612e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
1162bdfcddf7091e92134143e9a2d9ccce908e43979epbos@webrtc.org      video_streams_[0].width, video_streams_[0].height));
1163c33d37ce205e22c0e090b0b285ed963686bf24dcpbos@webrtc.org  send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
11642e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11652e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  EXPECT_EQ(kEventSignaled, post_encode_observer.Wait())
11662e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      << "Timed out while waiting for send-side encoded-frame callback.";
11672e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11682e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  EXPECT_EQ(kEventSignaled, pre_decode_observer.Wait())
11692e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      << "Timed out while waiting for pre-decode encoded-frame callback.";
11702e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11712e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  post_encode_observer.ExpectEqualFrames(pre_decode_observer);
11722e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11732e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  StopSending();
11742e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11752e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  sender_transport.StopSending();
11762e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  receiver_transport.StopSending();
11772e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
11782e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  DestroyStreams();
11792e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org}
11807ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org
11817ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.orgTEST_F(CallTest, ReceiveStreamSendsRemb) {
11827ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org  class RembObserver : public test::RtpRtcpObserver {
11837ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org   public:
11847ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org    RembObserver() : test::RtpRtcpObserver(kDefaultTimeoutMs) {}
11857ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org
11867ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org    virtual Action OnReceiveRtcp(const uint8_t* packet,
11877ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org                                 size_t length) OVERRIDE {
11887ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      RTCPUtility::RTCPParserV2 parser(packet, length, true);
11897ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      EXPECT_TRUE(parser.IsValid());
11907ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org
11917ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      bool received_psfb = false;
11927ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      bool received_remb = false;
11937ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
11947ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
11957ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org        if (packet_type == RTCPUtility::kRtcpPsfbRembCode) {
11967ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org          const RTCPUtility::RTCPPacket& packet = parser.Packet();
11977ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org          EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalSsrc);
11987ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org          received_psfb = true;
11997ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org        } else if (packet_type == RTCPUtility::kRtcpPsfbRembItemCode) {
12007ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org          const RTCPUtility::RTCPPacket& packet = parser.Packet();
12017ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org          EXPECT_GT(packet.REMBItem.BitRate, 0u);
12027ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org          EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
12037ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org          EXPECT_EQ(packet.REMBItem.SSRCs[0], kSendSsrc);
12047ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org          received_remb = true;
12057ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org        }
12067ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org        packet_type = parser.Iterate();
12077ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      }
12087ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      if (received_psfb && received_remb)
12097ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org        observation_complete_->Set();
12107ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      return SEND_PACKET;
12117ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org    }
12127ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org  } observer;
12137ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org
12147ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org  CreateCalls(Call::Config(observer.SendTransport()),
12157ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org              Call::Config(observer.ReceiveTransport()));
12167ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
12177ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org  CreateTestConfigs();
12187ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org  CreateStreams();
12197ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org  CreateFrameGenerator();
12207ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org  StartSending();
12217ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org
12227ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org  EXPECT_EQ(kEventSignaled, observer.Wait())
12237ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org      << "Timed out while waiting for a receiver RTCP REMB packet to be sent.";
12247ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org
12257ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org  StopSending();
12267ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org  observer.StopSending();
12277ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org  DestroyStreams();
12287ff4089bfcce71ba2a5d21d5adc0467782a914a0mflodman@webrtc.org}
1229b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
1230b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.orgvoid CallTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
1231b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  static const int kNumRtcpReportPacketsToObserve = 5;
1232b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  class RtcpXrObserver : public test::RtpRtcpObserver {
1233b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org   public:
1234b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    explicit RtcpXrObserver(bool enable_rrtr)
1235b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        : test::RtpRtcpObserver(kDefaultTimeoutMs),
1236b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          enable_rrtr_(enable_rrtr),
1237b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          sent_rtcp_sr_(0),
1238b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          sent_rtcp_rr_(0),
1239b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          sent_rtcp_rrtr_(0),
1240b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          sent_rtcp_dlrr_(0) {}
1241c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org
1242b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org   private:
1243b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    // Receive stream should send RR packets (and RRTR packets if enabled).
1244b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    virtual Action OnReceiveRtcp(const uint8_t* packet,
1245b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org                                 size_t length) OVERRIDE {
1246b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      RTCPUtility::RTCPParserV2 parser(packet, length, true);
1247b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      EXPECT_TRUE(parser.IsValid());
1248b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
1249b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1250b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
1251b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        if (packet_type == RTCPUtility::kRtcpRrCode) {
1252b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          ++sent_rtcp_rr_;
1253c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org        } else if (packet_type ==
1254c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org                   RTCPUtility::kRtcpXrReceiverReferenceTimeCode) {
1255b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          ++sent_rtcp_rrtr_;
1256b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        }
1257b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        EXPECT_NE(packet_type, RTCPUtility::kRtcpSrCode);
1258b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        EXPECT_NE(packet_type, RTCPUtility::kRtcpXrDlrrReportBlockItemCode);
1259b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        packet_type = parser.Iterate();
1260b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      }
1261b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      return SEND_PACKET;
1262b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    }
1263b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    // Send stream should send SR packets (and DLRR packets if enabled).
1264b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
1265b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      RTCPUtility::RTCPParserV2 parser(packet, length, true);
1266b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      EXPECT_TRUE(parser.IsValid());
1267b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
1268b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1269b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      while (packet_type != RTCPUtility::kRtcpNotValidCode) {
1270b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        if (packet_type == RTCPUtility::kRtcpSrCode) {
1271b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          ++sent_rtcp_sr_;
1272b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        } else if (packet_type == RTCPUtility::kRtcpXrDlrrReportBlockItemCode) {
1273b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          ++sent_rtcp_dlrr_;
1274b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        }
1275b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        EXPECT_NE(packet_type, RTCPUtility::kRtcpXrReceiverReferenceTimeCode);
1276b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        packet_type = parser.Iterate();
1277b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      }
1278b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
1279b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
1280b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        if (enable_rrtr_) {
1281b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          EXPECT_GT(sent_rtcp_rrtr_, 0);
1282b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          EXPECT_GT(sent_rtcp_dlrr_, 0);
1283b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        } else {
1284b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          EXPECT_EQ(0, sent_rtcp_rrtr_);
1285b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org          EXPECT_EQ(0, sent_rtcp_dlrr_);
1286b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        }
1287b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org        observation_complete_->Set();
1288b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      }
1289b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      return SEND_PACKET;
1290b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    }
1291b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    bool enable_rrtr_;
1292b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    int sent_rtcp_sr_;
1293b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    int sent_rtcp_rr_;
1294b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    int sent_rtcp_rrtr_;
1295b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org    int sent_rtcp_dlrr_;
1296b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  } observer(enable_rrtr);
1297b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
1298b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  CreateCalls(Call::Config(observer.SendTransport()),
1299b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org              Call::Config(observer.ReceiveTransport()));
1300c71929dce136f9bc59fcc7ceb172cf74fc507ea9pbos@webrtc.org  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
1301b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
1302b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  CreateTestConfigs();
1303b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  receive_config_.rtp.rtcp_mode = newapi::kRtcpReducedSize;
1304b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  receive_config_.rtp.rtcp_xr.receiver_reference_time_report = enable_rrtr;
1305b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
1306b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  CreateStreams();
1307b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  CreateFrameGenerator();
1308b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  StartSending();
1309b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
1310b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  EXPECT_EQ(kEventSignaled, observer.Wait())
1311b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org      << "Timed out while waiting for RTCP SR/RR packets to be sent.";
1312b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
1313b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  StopSending();
1314b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  observer.StopSending();
1315b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  DestroyStreams();
1316b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org}
1317b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
1318c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.orgclass StatsObserver : public test::RtpRtcpObserver, public I420FrameCallback {
1319c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org public:
1320c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  StatsObserver()
1321c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      : test::RtpRtcpObserver(kLongTimeoutMs),
1322c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        receive_stream_(NULL),
1323c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        send_stream_(NULL),
1324c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        expected_receive_ssrc_(),
1325c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        expected_send_ssrcs_(),
1326c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        check_stats_event_(EventWrapper::Create()) {}
1327c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1328c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  void SetExpectedReceiveSsrc(uint32_t ssrc) { expected_receive_ssrc_ = ssrc; }
1329c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1330c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  void SetExpectedSendSsrcs(const std::vector<uint32_t>& ssrcs) {
1331c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    for (std::vector<uint32_t>::const_iterator it = ssrcs.begin();
1332c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org         it != ssrcs.end();
1333c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org         ++it) {
1334c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      expected_send_ssrcs_.insert(*it);
1335c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    }
1336c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  }
1337c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1338c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  void SetExpectedCName(std::string cname) { expected_cname_ = cname; }
1339c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1340c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  void SetReceiveStream(VideoReceiveStream* stream) {
1341c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    receive_stream_ = stream;
1342c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  }
1343c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1344c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  void SetSendStream(VideoSendStream* stream) { send_stream_ = stream; }
1345c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1346c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  void WaitForFilledStats() {
1347c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    Clock* clock = Clock::GetRealTimeClock();
1348c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    int64_t now = clock->TimeInMilliseconds();
1349c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    int64_t stop_time = now + kLongTimeoutMs;
1350c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    bool receive_ok = false;
1351c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    bool send_ok = false;
1352c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1353c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    while (now < stop_time) {
1354c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      if (!receive_ok)
1355c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        receive_ok = CheckReceiveStats();
1356c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      if (!send_ok)
1357c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        send_ok = CheckSendStats();
1358c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1359c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      if (receive_ok && send_ok)
1360c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        return;
1361c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1362c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      int64_t time_until_timout_ = stop_time - now;
1363c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      if (time_until_timout_ > 0)
1364c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        check_stats_event_->Wait(time_until_timout_);
1365c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      now = clock->TimeInMilliseconds();
1366c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    }
1367c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1368c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    ADD_FAILURE() << "Timed out waiting for filled stats.";
1369c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    for (std::map<std::string, bool>::const_iterator it =
1370c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org             receive_stats_filled_.begin();
1371c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org         it != receive_stats_filled_.end();
1372c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org         ++it) {
1373c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      if (!it->second) {
1374c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        ADD_FAILURE() << "Missing receive stats: " << it->first;
1375c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      }
1376c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    }
1377c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1378c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    for (std::map<std::string, bool>::const_iterator it =
1379c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org             send_stats_filled_.begin();
1380c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org         it != send_stats_filled_.end();
1381c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org         ++it) {
1382c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      if (!it->second) {
1383c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        ADD_FAILURE() << "Missing send stats: " << it->first;
1384c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      }
1385c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    }
1386c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  }
1387c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1388c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org private:
1389c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
1390c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    check_stats_event_->Set();
1391c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    return SEND_PACKET;
1392c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  }
1393c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1394c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
1395c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    check_stats_event_->Set();
1396c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    return SEND_PACKET;
1397c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  }
1398c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1399c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  virtual Action OnReceiveRtp(const uint8_t* packet, size_t length) OVERRIDE {
1400c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    check_stats_event_->Set();
1401c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    return SEND_PACKET;
1402c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  }
1403c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1404c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) OVERRIDE {
1405c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    check_stats_event_->Set();
1406c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    return SEND_PACKET;
1407c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  }
1408c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1409c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  virtual void FrameCallback(I420VideoFrame* video_frame) OVERRIDE {
1410c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    // Ensure that we have at least 5ms send side delay.
1411c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    int64_t render_time = video_frame->render_time_ms();
1412c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    if (render_time > 0)
1413c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      video_frame->set_render_time_ms(render_time - 5);
1414c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  }
1415c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1416c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  bool CheckReceiveStats() {
1417c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    assert(receive_stream_ != NULL);
1418c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    VideoReceiveStream::Stats stats = receive_stream_->GetStats();
1419c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    EXPECT_EQ(expected_receive_ssrc_, stats.ssrc);
1420c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1421c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    // Make sure all fields have been populated.
1422c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1423c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    receive_stats_filled_["IncomingRate"] |=
1424c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        stats.network_frame_rate != 0 || stats.bitrate_bps != 0;
1425c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1426c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
1427c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1428c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
1429c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1430c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    receive_stats_filled_["StatisticsUpdated"] |=
1431c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        stats.rtcp_stats.cumulative_lost != 0 ||
1432c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        stats.rtcp_stats.extended_max_sequence_number != 0 ||
1433c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
1434c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1435c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    receive_stats_filled_["DataCountersUpdated"] |=
1436c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        stats.rtp_stats.bytes != 0 || stats.rtp_stats.fec_packets != 0 ||
1437c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        stats.rtp_stats.header_bytes != 0 || stats.rtp_stats.packets != 0 ||
1438c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        stats.rtp_stats.padding_bytes != 0 ||
1439c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        stats.rtp_stats.retransmitted_packets != 0;
1440c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1441c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    receive_stats_filled_["CodecStats"] |=
1442c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        stats.avg_delay_ms != 0 || stats.discarded_packets != 0 ||
1443c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        stats.key_frames != 0 || stats.delta_frames != 0;
1444c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1445c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    receive_stats_filled_["CName"] |= stats.c_name == expected_cname_;
1446c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1447c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    return AllStatsFilled(receive_stats_filled_);
1448c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  }
1449c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1450c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  bool CheckSendStats() {
1451c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    assert(send_stream_ != NULL);
1452c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    VideoSendStream::Stats stats = send_stream_->GetStats();
1453c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1454c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    send_stats_filled_["NumStreams"] |=
1455c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        stats.substreams.size() == expected_send_ssrcs_.size();
1456c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1457c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    send_stats_filled_["Delay"] |=
1458c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        stats.avg_delay_ms != 0 || stats.max_delay_ms != 0;
1459c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1460c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    receive_stats_filled_["CName"] |= stats.c_name == expected_cname_;
1461c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1462c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    for (std::map<uint32_t, StreamStats>::const_iterator it =
1463c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org             stats.substreams.begin();
1464c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org         it != stats.substreams.end();
1465c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org         ++it) {
1466c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
1467c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org                  expected_send_ssrcs_.end());
1468c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1469c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      send_stats_filled_[CompoundKey("IncomingRate", it->first)] |=
1470c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org          stats.input_frame_rate != 0;
1471c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1472c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      const StreamStats& stream_stats = it->second;
1473c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1474c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
1475c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org          stream_stats.rtcp_stats.cumulative_lost != 0 ||
1476c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org          stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
1477c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org          stream_stats.rtcp_stats.fraction_lost != 0;
1478c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1479c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
1480c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org          stream_stats.rtp_stats.fec_packets != 0 ||
1481c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org          stream_stats.rtp_stats.padding_bytes != 0 ||
1482c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org          stream_stats.rtp_stats.retransmitted_packets != 0 ||
1483c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org          stream_stats.rtp_stats.packets != 0;
1484c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1485c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      send_stats_filled_[CompoundKey("BitrateStatisticsObserver", it->first)] |=
1486c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org          stream_stats.bitrate_bps != 0;
1487c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1488c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
1489c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org          stream_stats.delta_frames != 0 || stream_stats.key_frames != 0;
1490c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1491c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
1492c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org          stats.encode_frame_rate != 0;
1493c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    }
1494c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1495c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    return AllStatsFilled(send_stats_filled_);
1496c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  }
1497c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1498c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  std::string CompoundKey(const char* name, uint32_t ssrc) {
1499c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    std::ostringstream oss;
1500c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    oss << name << "_" << ssrc;
1501c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    return oss.str();
1502c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  }
1503c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1504c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
1505c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
1506c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org         it != stats_map.end();
1507c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org         ++it) {
1508c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org      if (!it->second)
1509c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org        return false;
1510c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    }
1511c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org    return true;
1512c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  }
1513c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1514c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  VideoReceiveStream* receive_stream_;
1515c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  std::map<std::string, bool> receive_stats_filled_;
1516c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1517c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  VideoSendStream* send_stream_;
1518c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  std::map<std::string, bool> send_stats_filled_;
1519c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1520c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  uint32_t expected_receive_ssrc_;
1521c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  std::set<uint32_t> expected_send_ssrcs_;
1522c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  std::string expected_cname_;
1523c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1524c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  scoped_ptr<EventWrapper> check_stats_event_;
1525c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org};
1526c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1527c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.orgTEST_F(CallTest, GetStats) {
1528c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  StatsObserver observer;
1529c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1530c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  CreateCalls(Call::Config(observer.SendTransport()),
1531c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org              Call::Config(observer.ReceiveTransport()));
1532c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1533c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
1534c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1535c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  CreateTestConfigs();
1536c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  send_config_.pre_encode_callback = &observer;  // Used to inject delay.
1537c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  send_config_.rtp.c_name = "SomeCName";
1538c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1539c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  observer.SetExpectedReceiveSsrc(receive_config_.rtp.local_ssrc);
1540c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  observer.SetExpectedSendSsrcs(send_config_.rtp.ssrcs);
1541c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  observer.SetExpectedCName(send_config_.rtp.c_name);
1542c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1543c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  CreateStreams();
1544c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  observer.SetReceiveStream(receive_stream_);
1545c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  observer.SetSendStream(send_stream_);
1546c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  CreateFrameGenerator();
1547c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  StartSending();
1548c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1549c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  observer.WaitForFilledStats();
1550c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1551c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  StopSending();
1552c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  observer.StopSending();
1553c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org  DestroyStreams();
1554c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org}
1555c8ab7215c005f95e375f6e07f2a08ab6c7431f51sprang@webrtc.org
1556b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.orgTEST_F(CallTest, ReceiverReferenceTimeReportEnabled) {
1557b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  TestXrReceiverReferenceTimeReport(true);
1558b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org}
1559b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org
1560b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.orgTEST_F(CallTest, ReceiverReferenceTimeReportDisabled) {
1561b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org  TestXrReceiverReferenceTimeReport(false);
1562b4263e09399b251e5cf306b2ade0d0f768d3cb61asapersson@webrtc.org}
15633f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org
156499153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.orgTEST_F(CallTest, TestReceivedRtpPacketStats) {
156599153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  static const size_t kNumRtpPacketsToSend = 5;
156699153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  class ReceivedRtpStatsObserver : public test::RtpRtcpObserver {
156799153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org   public:
156899153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org    ReceivedRtpStatsObserver()
156999153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org        : test::RtpRtcpObserver(kDefaultTimeoutMs),
157099153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org          receive_stream_(NULL),
157199153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org          sent_rtp_(0) {}
157299153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org
157399153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org    void SetReceiveStream(VideoReceiveStream* stream) {
157499153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org      receive_stream_ = stream;
157599153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org    }
157699153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org
157799153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org   private:
157899153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
157999153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org      if (sent_rtp_ >= kNumRtpPacketsToSend) {
158099153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org        VideoReceiveStream::Stats stats = receive_stream_->GetStats();
158199153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org        if (kNumRtpPacketsToSend == stats.rtp_stats.packets) {
158299153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org          observation_complete_->Set();
158399153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org        }
158499153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org        return DROP_PACKET;
158599153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org      }
158699153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org      ++sent_rtp_;
158799153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org      return SEND_PACKET;
158899153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org    }
158999153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org
159099153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org    VideoReceiveStream* receive_stream_;
159199153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org    uint32_t sent_rtp_;
159299153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  } observer;
159399153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org
159499153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  CreateCalls(Call::Config(observer.SendTransport()),
159599153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org              Call::Config(observer.ReceiveTransport()));
159699153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  observer.SetReceivers(receiver_call_->Receiver(), sender_call_->Receiver());
159799153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org
159899153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  CreateTestConfigs();
159999153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  CreateStreams();
160099153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  observer.SetReceiveStream(receive_stream_);
160199153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  CreateFrameGenerator();
160299153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  StartSending();
160399153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org
160499153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  EXPECT_EQ(kEventSignaled, observer.Wait())
160599153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org      << "Timed out while verifying number of received RTP packets.";
160699153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org
160799153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  StopSending();
160899153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  observer.StopSending();
160999153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org  DestroyStreams();
161099153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org}
161199153baa13d2a844373be5fa45eeb5be492b3445asapersson@webrtc.org
1612ce8510901416e37afabb0a54c6e10bec6db63a42pbos@webrtc.org}  // namespace webrtc
1613