2015-01-20 21:36:13 +00:00
|
|
|
/*
|
2016-02-07 20:46:45 -08:00
|
|
|
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
2015-01-20 21:36:13 +00:00
|
|
|
*
|
2016-02-07 20:46:45 -08:00
|
|
|
* Use of this source code is governed by a BSD-style license
|
|
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
|
|
|
|
* in the file PATENTS. All contributing project authors may
|
|
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
2015-01-20 21:36:13 +00:00
|
|
|
*/
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2017-09-15 06:47:31 +02:00
|
|
|
#ifndef MEDIA_BASE_VIDEOENGINE_UNITTEST_H_ // NOLINT
|
|
|
|
|
#define MEDIA_BASE_VIDEOENGINE_UNITTEST_H_
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2016-02-26 03:00:35 -08:00
|
|
|
#include <memory>
|
2013-07-10 00:45:36 +00:00
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "call/call.h"
|
|
|
|
|
#include "logging/rtc_event_log/rtc_event_log.h"
|
|
|
|
|
#include "media/base/fakenetworkinterface.h"
|
|
|
|
|
#include "media/base/fakevideocapturer.h"
|
|
|
|
|
#include "media/base/fakevideorenderer.h"
|
|
|
|
|
#include "media/base/mediachannel.h"
|
|
|
|
|
#include "media/base/streamparams.h"
|
|
|
|
|
#include "media/engine/fakewebrtccall.h"
|
|
|
|
|
#include "rtc_base/bytebuffer.h"
|
|
|
|
|
#include "rtc_base/gunit.h"
|
|
|
|
|
#include "rtc_base/timeutils.h"
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2017-09-23 17:21:32 +02:00
|
|
|
namespace cricket {
|
|
|
|
|
class WebRtcVideoEncoderFactory;
|
|
|
|
|
class WebRtcVideoDecoderFactory;
|
|
|
|
|
} // namespace cricket
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
#define EXPECT_FRAME_WAIT(c, w, h, t) \
|
|
|
|
|
EXPECT_EQ_WAIT((c), renderer_.num_rendered_frames(), (t)); \
|
|
|
|
|
EXPECT_EQ((w), renderer_.width()); \
|
|
|
|
|
EXPECT_EQ((h), renderer_.height()); \
|
|
|
|
|
EXPECT_EQ(0, renderer_.errors()); \
|
|
|
|
|
|
|
|
|
|
#define EXPECT_FRAME_ON_RENDERER_WAIT(r, c, w, h, t) \
|
|
|
|
|
EXPECT_EQ_WAIT((c), (r).num_rendered_frames(), (t)); \
|
|
|
|
|
EXPECT_EQ((w), (r).width()); \
|
|
|
|
|
EXPECT_EQ((h), (r).height()); \
|
|
|
|
|
EXPECT_EQ(0, (r).errors()); \
|
|
|
|
|
|
2013-12-11 18:25:07 +00:00
|
|
|
#define EXPECT_GT_FRAME_ON_RENDERER_WAIT(r, c, w, h, t) \
|
|
|
|
|
EXPECT_TRUE_WAIT((r).num_rendered_frames() >= (c) && \
|
|
|
|
|
(w) == (r).width() && \
|
|
|
|
|
(h) == (r).height(), (t)); \
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
EXPECT_EQ(0, (r).errors());
|
2013-12-11 18:25:07 +00:00
|
|
|
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
static const uint32_t kTimeout = 5000U;
|
|
|
|
|
static const uint32_t kDefaultReceiveSsrc = 0;
|
|
|
|
|
static const uint32_t kSsrc = 1234u;
|
|
|
|
|
static const uint32_t kRtxSsrc = 4321u;
|
|
|
|
|
static const uint32_t kSsrcs4[] = {1, 2, 3, 4};
|
2016-10-24 01:21:16 -07:00
|
|
|
static const int kVideoWidth = 640;
|
|
|
|
|
static const int kVideoHeight = 360;
|
|
|
|
|
static const int kFramerate = 30;
|
2013-07-10 00:45:36 +00:00
|
|
|
|
|
|
|
|
inline bool IsEqualCodec(const cricket::VideoCodec& a,
|
|
|
|
|
const cricket::VideoCodec& b) {
|
2016-10-24 01:21:16 -07:00
|
|
|
return a.id == b.id && a.name == b.name;
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class E, class C>
|
|
|
|
|
class VideoMediaChannelTest : public testing::Test,
|
|
|
|
|
public sigslot::has_slots<> {
|
|
|
|
|
protected:
|
2015-09-15 12:26:33 +02:00
|
|
|
VideoMediaChannelTest<E, C>()
|
2017-09-12 04:42:15 -07:00
|
|
|
: call_(webrtc::Call::Create(webrtc::Call::Config(&event_log_))),
|
2017-09-23 17:21:32 +02:00
|
|
|
engine_(std::unique_ptr<cricket::WebRtcVideoEncoderFactory>(),
|
|
|
|
|
std::unique_ptr<cricket::WebRtcVideoDecoderFactory>()) {}
|
2015-09-15 12:26:33 +02:00
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
virtual cricket::VideoCodec DefaultCodec() = 0;
|
|
|
|
|
|
|
|
|
|
virtual cricket::StreamParams DefaultSendStreamParams() {
|
|
|
|
|
return cricket::StreamParams::CreateLegacy(kSsrc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void SetUp() {
|
2017-01-17 05:45:40 -08:00
|
|
|
cricket::MediaConfig media_config;
|
|
|
|
|
// Disabling cpu overuse detection actually disables quality scaling too; it
|
|
|
|
|
// implies DegradationPreference kMaintainResolution. Automatic scaling
|
|
|
|
|
// needs to be disabled, otherwise, tests which check the size of received
|
|
|
|
|
// frames become flaky.
|
|
|
|
|
media_config.video.enable_cpu_overuse_detection = false;
|
|
|
|
|
channel_.reset(engine_.CreateChannel(call_.get(), media_config,
|
2016-02-12 02:27:06 -08:00
|
|
|
cricket::VideoOptions()));
|
2016-11-22 16:08:30 -08:00
|
|
|
channel_->OnReadyToSend(true);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(channel_.get() != NULL);
|
|
|
|
|
network_interface_.SetDestination(channel_.get());
|
|
|
|
|
channel_->SetInterface(&network_interface_);
|
|
|
|
|
media_error_ = cricket::VideoMediaChannel::ERROR_NONE;
|
2015-09-17 16:42:56 +02:00
|
|
|
cricket::VideoRecvParameters parameters;
|
|
|
|
|
parameters.codecs = engine_.codecs();
|
|
|
|
|
channel_->SetRecvParameters(parameters);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(channel_->AddSendStream(DefaultSendStreamParams()));
|
2014-08-07 04:47:36 +00:00
|
|
|
video_capturer_.reset(CreateFakeVideoCapturer());
|
2013-07-22 21:07:49 +00:00
|
|
|
cricket::VideoFormat format(640, 480,
|
2016-10-24 01:21:16 -07:00
|
|
|
cricket::VideoFormat::FpsToInterval(kFramerate),
|
2013-07-22 21:07:49 +00:00
|
|
|
cricket::FOURCC_I420);
|
|
|
|
|
EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(format));
|
2016-06-02 16:23:38 -07:00
|
|
|
EXPECT_TRUE(
|
|
|
|
|
channel_->SetVideoSend(kSsrc, true, nullptr, video_capturer_.get()));
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
2014-08-07 04:47:36 +00:00
|
|
|
|
|
|
|
|
virtual cricket::FakeVideoCapturer* CreateFakeVideoCapturer() {
|
|
|
|
|
return new cricket::FakeVideoCapturer();
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-27 17:52:04 +00:00
|
|
|
// Utility method to setup an additional stream to send and receive video.
|
|
|
|
|
// Used to test send and recv between two streams.
|
2013-07-10 00:45:36 +00:00
|
|
|
void SetUpSecondStream() {
|
2014-02-27 17:52:04 +00:00
|
|
|
SetUpSecondStreamWithNoRecv();
|
|
|
|
|
// Setup recv for second stream.
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(channel_->AddRecvStream(
|
2013-07-22 21:07:49 +00:00
|
|
|
cricket::StreamParams::CreateLegacy(kSsrc + 2)));
|
2014-02-27 17:52:04 +00:00
|
|
|
// Make the second renderer available for use by a new stream.
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(kSsrc + 2, &renderer2_));
|
2014-02-27 17:52:04 +00:00
|
|
|
}
|
|
|
|
|
// Setup an additional stream just to send video. Defer add recv stream.
|
|
|
|
|
// This is required if you want to test unsignalled recv of video rtp packets.
|
|
|
|
|
void SetUpSecondStreamWithNoRecv() {
|
2013-07-10 00:45:36 +00:00
|
|
|
// SetUp() already added kSsrc make sure duplicate SSRCs cant be added.
|
2014-02-27 17:52:04 +00:00
|
|
|
EXPECT_TRUE(channel_->AddRecvStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(kSsrc)));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer_));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_FALSE(channel_->AddSendStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(kSsrc)));
|
|
|
|
|
EXPECT_TRUE(channel_->AddSendStream(
|
2013-07-22 21:07:49 +00:00
|
|
|
cricket::StreamParams::CreateLegacy(kSsrc + 2)));
|
2014-02-27 17:52:04 +00:00
|
|
|
// We dont add recv for the second stream.
|
2013-07-22 21:07:49 +00:00
|
|
|
|
2014-02-27 17:52:04 +00:00
|
|
|
// Setup the receive and renderer for second stream after send.
|
2014-08-07 04:47:36 +00:00
|
|
|
video_capturer_2_.reset(CreateFakeVideoCapturer());
|
2013-07-22 21:07:49 +00:00
|
|
|
cricket::VideoFormat format(640, 480,
|
2016-10-24 01:21:16 -07:00
|
|
|
cricket::VideoFormat::FpsToInterval(kFramerate),
|
2013-07-22 21:07:49 +00:00
|
|
|
cricket::FOURCC_I420);
|
|
|
|
|
EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(format));
|
|
|
|
|
|
2016-06-02 16:23:38 -07:00
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(kSsrc + 2, true, nullptr,
|
|
|
|
|
video_capturer_2_.get()));
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
virtual void TearDown() {
|
|
|
|
|
channel_.reset();
|
|
|
|
|
}
|
|
|
|
|
bool SetDefaultCodec() {
|
|
|
|
|
return SetOneCodec(DefaultCodec());
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-24 01:21:16 -07:00
|
|
|
bool SetOneCodec(int pt, const char* name) {
|
|
|
|
|
return SetOneCodec(cricket::VideoCodec(pt, name));
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
bool SetOneCodec(const cricket::VideoCodec& codec) {
|
2016-10-24 01:21:16 -07:00
|
|
|
cricket::VideoFormat capture_format(
|
|
|
|
|
kVideoWidth, kVideoHeight,
|
|
|
|
|
cricket::VideoFormat::FpsToInterval(kFramerate), cricket::FOURCC_I420);
|
2013-07-22 21:07:49 +00:00
|
|
|
|
|
|
|
|
if (video_capturer_) {
|
|
|
|
|
EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(capture_format));
|
|
|
|
|
}
|
|
|
|
|
if (video_capturer_2_) {
|
|
|
|
|
EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(capture_format));
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
bool sending = channel_->sending();
|
|
|
|
|
bool success = SetSend(false);
|
2015-09-17 16:42:56 +02:00
|
|
|
if (success) {
|
|
|
|
|
cricket::VideoSendParameters parameters;
|
|
|
|
|
parameters.codecs.push_back(codec);
|
|
|
|
|
success = channel_->SetSendParameters(parameters);
|
|
|
|
|
}
|
|
|
|
|
if (success) {
|
2013-07-10 00:45:36 +00:00
|
|
|
success = SetSend(sending);
|
2015-09-17 16:42:56 +02:00
|
|
|
}
|
2013-07-10 00:45:36 +00:00
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
bool SetSend(bool send) {
|
|
|
|
|
return channel_->SetSend(send);
|
|
|
|
|
}
|
|
|
|
|
int DrainOutgoingPackets() {
|
|
|
|
|
int packets = 0;
|
|
|
|
|
do {
|
|
|
|
|
packets = NumRtpPackets();
|
|
|
|
|
// 100 ms should be long enough.
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::Thread::Current()->ProcessMessages(100);
|
2013-07-10 00:45:36 +00:00
|
|
|
} while (NumRtpPackets() > packets);
|
|
|
|
|
return NumRtpPackets();
|
|
|
|
|
}
|
|
|
|
|
bool SendFrame() {
|
2013-07-22 21:07:49 +00:00
|
|
|
if (video_capturer_2_) {
|
|
|
|
|
video_capturer_2_->CaptureFrame();
|
|
|
|
|
}
|
2013-07-10 00:45:36 +00:00
|
|
|
return video_capturer_.get() &&
|
|
|
|
|
video_capturer_->CaptureFrame();
|
|
|
|
|
}
|
|
|
|
|
bool WaitAndSendFrame(int wait_ms) {
|
2014-07-29 17:36:52 +00:00
|
|
|
bool ret = rtc::Thread::Current()->ProcessMessages(wait_ms);
|
2013-07-10 00:45:36 +00:00
|
|
|
ret &= SendFrame();
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
// Sends frames and waits for the decoder to be fully initialized.
|
|
|
|
|
// Returns the number of frames that were sent.
|
|
|
|
|
int WaitForDecoder() {
|
|
|
|
|
#if defined(HAVE_OPENMAX)
|
|
|
|
|
// Send enough frames for the OpenMAX decoder to continue processing, and
|
|
|
|
|
// return the number of frames sent.
|
|
|
|
|
// Send frames for a full kTimeout's worth of 15fps video.
|
|
|
|
|
int frame_count = 0;
|
|
|
|
|
while (frame_count < static_cast<int>(kTimeout) / 66) {
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(66));
|
|
|
|
|
++frame_count;
|
|
|
|
|
}
|
|
|
|
|
return frame_count;
|
|
|
|
|
#else
|
|
|
|
|
return 0;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
bool SendCustomVideoFrame(int w, int h) {
|
|
|
|
|
if (!video_capturer_.get()) return false;
|
|
|
|
|
return video_capturer_->CaptureCustomFrame(w, h, cricket::FOURCC_I420);
|
|
|
|
|
}
|
|
|
|
|
int NumRtpBytes() {
|
|
|
|
|
return network_interface_.NumRtpBytes();
|
|
|
|
|
}
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
int NumRtpBytes(uint32_t ssrc) {
|
2013-07-10 00:45:36 +00:00
|
|
|
return network_interface_.NumRtpBytes(ssrc);
|
|
|
|
|
}
|
|
|
|
|
int NumRtpPackets() {
|
|
|
|
|
return network_interface_.NumRtpPackets();
|
|
|
|
|
}
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
int NumRtpPackets(uint32_t ssrc) {
|
2013-07-10 00:45:36 +00:00
|
|
|
return network_interface_.NumRtpPackets(ssrc);
|
|
|
|
|
}
|
|
|
|
|
int NumSentSsrcs() {
|
|
|
|
|
return network_interface_.NumSentSsrcs();
|
|
|
|
|
}
|
2016-03-20 06:15:43 -07:00
|
|
|
const rtc::CopyOnWriteBuffer* GetRtpPacket(int index) {
|
2013-07-10 00:45:36 +00:00
|
|
|
return network_interface_.GetRtpPacket(index);
|
|
|
|
|
}
|
|
|
|
|
int NumRtcpPackets() {
|
|
|
|
|
return network_interface_.NumRtcpPackets();
|
|
|
|
|
}
|
2016-03-20 06:15:43 -07:00
|
|
|
const rtc::CopyOnWriteBuffer* GetRtcpPacket(int index) {
|
2013-07-10 00:45:36 +00:00
|
|
|
return network_interface_.GetRtcpPacket(index);
|
|
|
|
|
}
|
2016-03-20 06:15:43 -07:00
|
|
|
static int GetPayloadType(const rtc::CopyOnWriteBuffer* p) {
|
2013-07-10 00:45:36 +00:00
|
|
|
int pt = -1;
|
|
|
|
|
ParseRtpPacket(p, NULL, &pt, NULL, NULL, NULL, NULL);
|
|
|
|
|
return pt;
|
|
|
|
|
}
|
2016-03-20 06:15:43 -07:00
|
|
|
static bool ParseRtpPacket(const rtc::CopyOnWriteBuffer* p,
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
bool* x,
|
|
|
|
|
int* pt,
|
|
|
|
|
int* seqnum,
|
|
|
|
|
uint32_t* tstamp,
|
|
|
|
|
uint32_t* ssrc,
|
2013-07-10 00:45:36 +00:00
|
|
|
std::string* payload) {
|
2016-03-30 06:43:37 -07:00
|
|
|
rtc::ByteBufferReader buf(p->data<char>(), p->size());
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
uint8_t u08 = 0;
|
|
|
|
|
uint16_t u16 = 0;
|
|
|
|
|
uint32_t u32 = 0;
|
2013-07-10 00:45:36 +00:00
|
|
|
|
|
|
|
|
// Read X and CC fields.
|
|
|
|
|
if (!buf.ReadUInt8(&u08)) return false;
|
|
|
|
|
bool extension = ((u08 & 0x10) != 0);
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
uint8_t cc = (u08 & 0x0F);
|
2013-07-10 00:45:36 +00:00
|
|
|
if (x) *x = extension;
|
|
|
|
|
|
|
|
|
|
// Read PT field.
|
|
|
|
|
if (!buf.ReadUInt8(&u08)) return false;
|
|
|
|
|
if (pt) *pt = (u08 & 0x7F);
|
|
|
|
|
|
|
|
|
|
// Read Sequence Number field.
|
|
|
|
|
if (!buf.ReadUInt16(&u16)) return false;
|
|
|
|
|
if (seqnum) *seqnum = u16;
|
|
|
|
|
|
|
|
|
|
// Read Timestamp field.
|
|
|
|
|
if (!buf.ReadUInt32(&u32)) return false;
|
|
|
|
|
if (tstamp) *tstamp = u32;
|
|
|
|
|
|
|
|
|
|
// Read SSRC field.
|
|
|
|
|
if (!buf.ReadUInt32(&u32)) return false;
|
|
|
|
|
if (ssrc) *ssrc = u32;
|
|
|
|
|
|
|
|
|
|
// Skip CSRCs.
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
for (uint8_t i = 0; i < cc; ++i) {
|
2013-07-10 00:45:36 +00:00
|
|
|
if (!buf.ReadUInt32(&u32)) return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Skip extension header.
|
|
|
|
|
if (extension) {
|
|
|
|
|
// Read Profile-specific extension header ID
|
|
|
|
|
if (!buf.ReadUInt16(&u16)) return false;
|
|
|
|
|
|
|
|
|
|
// Read Extension header length
|
|
|
|
|
if (!buf.ReadUInt16(&u16)) return false;
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
uint16_t ext_header_len = u16;
|
2013-07-10 00:45:36 +00:00
|
|
|
|
|
|
|
|
// Read Extension header
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
for (uint16_t i = 0; i < ext_header_len; ++i) {
|
2013-07-10 00:45:36 +00:00
|
|
|
if (!buf.ReadUInt32(&u32)) return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (payload) {
|
|
|
|
|
return buf.ReadString(payload, buf.Length());
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parse all RTCP packet, from start_index to stop_index, and count how many
|
|
|
|
|
// FIR (PT=206 and FMT=4 according to RFC 5104). If successful, set the count
|
|
|
|
|
// and return true.
|
|
|
|
|
bool CountRtcpFir(int start_index, int stop_index, int* fir_count) {
|
|
|
|
|
int count = 0;
|
|
|
|
|
for (int i = start_index; i < stop_index; ++i) {
|
2016-03-20 06:15:43 -07:00
|
|
|
std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtcpPacket(i));
|
2016-03-30 06:43:37 -07:00
|
|
|
rtc::ByteBufferReader buf(p->data<char>(), p->size());
|
2013-07-10 00:45:36 +00:00
|
|
|
size_t total_len = 0;
|
|
|
|
|
// The packet may be a compound RTCP packet.
|
2015-03-24 09:19:06 +00:00
|
|
|
while (total_len < p->size()) {
|
2013-07-10 00:45:36 +00:00
|
|
|
// Read FMT, type and length.
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
uint8_t fmt = 0;
|
|
|
|
|
uint8_t type = 0;
|
|
|
|
|
uint16_t length = 0;
|
2013-07-10 00:45:36 +00:00
|
|
|
if (!buf.ReadUInt8(&fmt)) return false;
|
|
|
|
|
fmt &= 0x1F;
|
|
|
|
|
if (!buf.ReadUInt8(&type)) return false;
|
|
|
|
|
if (!buf.ReadUInt16(&length)) return false;
|
|
|
|
|
buf.Consume(length * 4); // Skip RTCP data.
|
|
|
|
|
total_len += (length + 1) * 4;
|
|
|
|
|
if ((192 == type) || ((206 == type) && (4 == fmt))) {
|
|
|
|
|
++count;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fir_count) {
|
|
|
|
|
*fir_count = count;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
void OnVideoChannelError(uint32_t ssrc,
|
2013-07-10 00:45:36 +00:00
|
|
|
cricket::VideoMediaChannel::Error error) {
|
|
|
|
|
media_error_ = error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Test that SetSend works.
|
|
|
|
|
void SetSend() {
|
|
|
|
|
EXPECT_FALSE(channel_->sending());
|
2016-06-02 16:23:38 -07:00
|
|
|
EXPECT_TRUE(
|
|
|
|
|
channel_->SetVideoSend(kSsrc, true, nullptr, video_capturer_.get()));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(SetOneCodec(DefaultCodec()));
|
|
|
|
|
EXPECT_FALSE(channel_->sending());
|
|
|
|
|
EXPECT_TRUE(SetSend(true));
|
|
|
|
|
EXPECT_TRUE(channel_->sending());
|
|
|
|
|
EXPECT_TRUE(SendFrame());
|
|
|
|
|
EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
|
|
|
|
|
EXPECT_TRUE(SetSend(false));
|
|
|
|
|
EXPECT_FALSE(channel_->sending());
|
|
|
|
|
}
|
|
|
|
|
// Test that SetSend fails without codecs being set.
|
|
|
|
|
void SetSendWithoutCodecs() {
|
|
|
|
|
EXPECT_FALSE(channel_->sending());
|
|
|
|
|
EXPECT_FALSE(SetSend(true));
|
|
|
|
|
EXPECT_FALSE(channel_->sending());
|
|
|
|
|
}
|
|
|
|
|
// Test that we properly set the send and recv buffer sizes by the time
|
|
|
|
|
// SetSend is called.
|
|
|
|
|
void SetSendSetsTransportBufferSizes() {
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(DefaultCodec()));
|
|
|
|
|
EXPECT_TRUE(SetSend(true));
|
2014-10-28 17:37:17 +00:00
|
|
|
EXPECT_EQ(64 * 1024, network_interface_.sendbuf_size());
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(64 * 1024, network_interface_.recvbuf_size());
|
|
|
|
|
}
|
|
|
|
|
// Tests that we can send frames and the right payload type is used.
|
|
|
|
|
void Send(const cricket::VideoCodec& codec) {
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(codec));
|
|
|
|
|
EXPECT_TRUE(SetSend(true));
|
|
|
|
|
EXPECT_TRUE(SendFrame());
|
|
|
|
|
EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
|
2016-03-20 06:15:43 -07:00
|
|
|
std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(codec.id, GetPayloadType(p.get()));
|
|
|
|
|
}
|
|
|
|
|
// Tests that we can send and receive frames.
|
|
|
|
|
void SendAndReceive(const cricket::VideoCodec& codec) {
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(codec));
|
|
|
|
|
EXPECT_TRUE(SetSend(true));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(0, renderer_.num_rendered_frames());
|
|
|
|
|
EXPECT_TRUE(SendFrame());
|
2016-10-24 01:21:16 -07:00
|
|
|
EXPECT_FRAME_WAIT(1, kVideoWidth, kVideoHeight, kTimeout);
|
2016-03-20 06:15:43 -07:00
|
|
|
std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(codec.id, GetPayloadType(p.get()));
|
|
|
|
|
}
|
2014-06-10 09:39:06 +00:00
|
|
|
void SendReceiveManyAndGetStats(const cricket::VideoCodec& codec,
|
|
|
|
|
int duration_sec, int fps) {
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(codec));
|
|
|
|
|
EXPECT_TRUE(SetSend(true));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
|
2014-06-10 09:39:06 +00:00
|
|
|
EXPECT_EQ(0, renderer_.num_rendered_frames());
|
|
|
|
|
for (int i = 0; i < duration_sec; ++i) {
|
|
|
|
|
for (int frame = 1; frame <= fps; ++frame) {
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(1000 / fps));
|
2016-10-24 01:21:16 -07:00
|
|
|
EXPECT_FRAME_WAIT(frame + i * fps, kVideoWidth, kVideoHeight, kTimeout);
|
2014-06-10 09:39:06 +00:00
|
|
|
}
|
|
|
|
|
}
|
2016-03-20 06:15:43 -07:00
|
|
|
std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
|
2014-06-10 09:39:06 +00:00
|
|
|
EXPECT_EQ(codec.id, GetPayloadType(p.get()));
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
// Test that stats work properly for a 1-1 call.
|
|
|
|
|
void GetStats() {
|
2014-06-10 09:39:06 +00:00
|
|
|
const int kDurationSec = 3;
|
|
|
|
|
const int kFps = 10;
|
|
|
|
|
SendReceiveManyAndGetStats(DefaultCodec(), kDurationSec, kFps);
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
cricket::VideoMediaInfo info;
|
2015-03-04 08:54:32 +00:00
|
|
|
EXPECT_TRUE(channel_->GetStats(&info));
|
2013-07-10 00:45:36 +00:00
|
|
|
|
|
|
|
|
ASSERT_EQ(1U, info.senders.size());
|
|
|
|
|
// TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload?
|
2014-06-10 09:39:06 +00:00
|
|
|
// For webrtc, bytes_sent does not include the RTP header length.
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_GT(info.senders[0].bytes_sent, 0);
|
|
|
|
|
EXPECT_EQ(NumRtpPackets(), info.senders[0].packets_sent);
|
|
|
|
|
EXPECT_EQ(0.0, info.senders[0].fraction_lost);
|
2016-11-14 02:28:16 -08:00
|
|
|
ASSERT_TRUE(info.senders[0].codec_payload_type);
|
|
|
|
|
EXPECT_EQ(DefaultCodec().id, *info.senders[0].codec_payload_type);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(0, info.senders[0].firs_rcvd);
|
2014-02-27 17:52:04 +00:00
|
|
|
EXPECT_EQ(0, info.senders[0].plis_rcvd);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(0, info.senders[0].nacks_rcvd);
|
2016-10-24 01:21:16 -07:00
|
|
|
EXPECT_EQ(kVideoWidth, info.senders[0].send_frame_width);
|
|
|
|
|
EXPECT_EQ(kVideoHeight, info.senders[0].send_frame_height);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_GT(info.senders[0].framerate_input, 0);
|
|
|
|
|
EXPECT_GT(info.senders[0].framerate_sent, 0);
|
|
|
|
|
|
2016-11-14 02:28:16 -08:00
|
|
|
EXPECT_EQ(1U, info.send_codecs.count(DefaultCodec().id));
|
|
|
|
|
EXPECT_EQ(DefaultCodec().ToCodecParameters(),
|
|
|
|
|
info.send_codecs[DefaultCodec().id]);
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
ASSERT_EQ(1U, info.receivers.size());
|
2013-12-05 00:24:06 +00:00
|
|
|
EXPECT_EQ(1U, info.senders[0].ssrcs().size());
|
|
|
|
|
EXPECT_EQ(1U, info.receivers[0].ssrcs().size());
|
|
|
|
|
EXPECT_EQ(info.senders[0].ssrcs()[0], info.receivers[0].ssrcs()[0]);
|
2016-11-14 02:28:16 -08:00
|
|
|
ASSERT_TRUE(info.receivers[0].codec_payload_type);
|
|
|
|
|
EXPECT_EQ(DefaultCodec().id, *info.receivers[0].codec_payload_type);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(NumRtpBytes(), info.receivers[0].bytes_rcvd);
|
|
|
|
|
EXPECT_EQ(NumRtpPackets(), info.receivers[0].packets_rcvd);
|
|
|
|
|
EXPECT_EQ(0.0, info.receivers[0].fraction_lost);
|
|
|
|
|
EXPECT_EQ(0, info.receivers[0].packets_lost);
|
2014-06-10 09:39:06 +00:00
|
|
|
// TODO(asapersson): Not set for webrtc. Handle missing stats.
|
|
|
|
|
// EXPECT_EQ(0, info.receivers[0].packets_concealed);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(0, info.receivers[0].firs_sent);
|
2014-02-27 17:52:04 +00:00
|
|
|
EXPECT_EQ(0, info.receivers[0].plis_sent);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(0, info.receivers[0].nacks_sent);
|
2017-01-17 05:56:53 -08:00
|
|
|
EXPECT_EQ(kVideoWidth, info.receivers[0].frame_width);
|
|
|
|
|
EXPECT_EQ(kVideoHeight, info.receivers[0].frame_height);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_GT(info.receivers[0].framerate_rcvd, 0);
|
|
|
|
|
EXPECT_GT(info.receivers[0].framerate_decoded, 0);
|
|
|
|
|
EXPECT_GT(info.receivers[0].framerate_output, 0);
|
2016-11-14 02:28:16 -08:00
|
|
|
|
|
|
|
|
EXPECT_EQ(1U, info.receive_codecs.count(DefaultCodec().id));
|
|
|
|
|
EXPECT_EQ(DefaultCodec().ToCodecParameters(),
|
|
|
|
|
info.receive_codecs[DefaultCodec().id]);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
2015-09-18 11:14:31 +02:00
|
|
|
|
|
|
|
|
cricket::VideoSenderInfo GetSenderStats(size_t i) {
|
|
|
|
|
cricket::VideoMediaInfo info;
|
|
|
|
|
EXPECT_TRUE(channel_->GetStats(&info));
|
|
|
|
|
return info.senders[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cricket::VideoReceiverInfo GetReceiverStats(size_t i) {
|
|
|
|
|
cricket::VideoMediaInfo info;
|
|
|
|
|
EXPECT_TRUE(channel_->GetStats(&info));
|
|
|
|
|
return info.receivers[i];
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
// Test that stats work properly for a conf call with multiple recv streams.
|
|
|
|
|
void GetStatsMultipleRecvStreams() {
|
|
|
|
|
cricket::FakeVideoRenderer renderer1, renderer2;
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(DefaultCodec()));
|
2015-09-17 16:42:56 +02:00
|
|
|
cricket::VideoSendParameters parameters;
|
|
|
|
|
parameters.codecs.push_back(DefaultCodec());
|
2016-02-17 05:25:36 -08:00
|
|
|
parameters.conference_mode = true;
|
2015-09-17 16:42:56 +02:00
|
|
|
EXPECT_TRUE(channel_->SetSendParameters(parameters));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(SetSend(true));
|
|
|
|
|
EXPECT_TRUE(channel_->AddRecvStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(1)));
|
|
|
|
|
EXPECT_TRUE(channel_->AddRecvStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(2)));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(1, &renderer1));
|
|
|
|
|
EXPECT_TRUE(channel_->SetSink(2, &renderer2));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(0, renderer1.num_rendered_frames());
|
|
|
|
|
EXPECT_EQ(0, renderer2.num_rendered_frames());
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
std::vector<uint32_t> ssrcs;
|
2013-07-10 00:45:36 +00:00
|
|
|
ssrcs.push_back(1);
|
|
|
|
|
ssrcs.push_back(2);
|
|
|
|
|
network_interface_.SetConferenceMode(true, ssrcs);
|
|
|
|
|
EXPECT_TRUE(SendFrame());
|
2016-10-24 01:21:16 -07:00
|
|
|
EXPECT_FRAME_ON_RENDERER_WAIT(renderer1, 1, kVideoWidth, kVideoHeight,
|
|
|
|
|
kTimeout);
|
|
|
|
|
EXPECT_FRAME_ON_RENDERER_WAIT(renderer2, 1, kVideoWidth, kVideoHeight,
|
|
|
|
|
kTimeout);
|
2015-09-18 11:14:31 +02:00
|
|
|
|
|
|
|
|
EXPECT_TRUE(channel_->SetSend(false));
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
cricket::VideoMediaInfo info;
|
2015-03-04 08:54:32 +00:00
|
|
|
EXPECT_TRUE(channel_->GetStats(&info));
|
2013-07-10 00:45:36 +00:00
|
|
|
ASSERT_EQ(1U, info.senders.size());
|
|
|
|
|
// TODO(whyuan): bytes_sent and bytes_rcvd are different. Are both payload?
|
2014-06-10 09:39:06 +00:00
|
|
|
// For webrtc, bytes_sent does not include the RTP header length.
|
2015-09-18 11:14:31 +02:00
|
|
|
EXPECT_GT(GetSenderStats(0).bytes_sent, 0);
|
|
|
|
|
EXPECT_EQ_WAIT(NumRtpPackets(), GetSenderStats(0).packets_sent, kTimeout);
|
2016-10-24 01:21:16 -07:00
|
|
|
EXPECT_EQ(kVideoWidth, GetSenderStats(0).send_frame_width);
|
|
|
|
|
EXPECT_EQ(kVideoHeight, GetSenderStats(0).send_frame_height);
|
2013-07-10 00:45:36 +00:00
|
|
|
|
|
|
|
|
ASSERT_EQ(2U, info.receivers.size());
|
|
|
|
|
for (size_t i = 0; i < info.receivers.size(); ++i) {
|
2015-09-18 11:14:31 +02:00
|
|
|
EXPECT_EQ(1U, GetReceiverStats(i).ssrcs().size());
|
|
|
|
|
EXPECT_EQ(i + 1, GetReceiverStats(i).ssrcs()[0]);
|
|
|
|
|
EXPECT_EQ_WAIT(NumRtpBytes(), GetReceiverStats(i).bytes_rcvd, kTimeout);
|
|
|
|
|
EXPECT_EQ_WAIT(NumRtpPackets(), GetReceiverStats(i).packets_rcvd,
|
|
|
|
|
kTimeout);
|
2016-10-24 01:21:16 -07:00
|
|
|
EXPECT_EQ_WAIT(kVideoWidth, GetReceiverStats(i).frame_width, kTimeout);
|
|
|
|
|
EXPECT_EQ_WAIT(kVideoHeight, GetReceiverStats(i).frame_height, kTimeout);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Test that stats work properly for a conf call with multiple send streams.
|
|
|
|
|
void GetStatsMultipleSendStreams() {
|
|
|
|
|
// Normal setup; note that we set the SSRC explicitly to ensure that
|
|
|
|
|
// it will come first in the senders map.
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(DefaultCodec()));
|
2015-09-17 16:42:56 +02:00
|
|
|
cricket::VideoSendParameters parameters;
|
|
|
|
|
parameters.codecs.push_back(DefaultCodec());
|
2016-02-17 05:25:36 -08:00
|
|
|
parameters.conference_mode = true;
|
2015-09-17 16:42:56 +02:00
|
|
|
EXPECT_TRUE(channel_->SetSendParameters(parameters));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(channel_->AddRecvStream(
|
2014-07-18 23:31:30 +00:00
|
|
|
cricket::StreamParams::CreateLegacy(kSsrc)));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer_));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(SetSend(true));
|
|
|
|
|
EXPECT_TRUE(SendFrame());
|
|
|
|
|
EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
|
2016-10-24 01:21:16 -07:00
|
|
|
EXPECT_FRAME_WAIT(1, kVideoWidth, kVideoHeight, kTimeout);
|
2013-07-10 00:45:36 +00:00
|
|
|
|
|
|
|
|
// Add an additional capturer, and hook up a renderer to receive it.
|
2015-02-20 10:24:53 +00:00
|
|
|
cricket::FakeVideoRenderer renderer2;
|
2016-02-26 03:00:35 -08:00
|
|
|
std::unique_ptr<cricket::FakeVideoCapturer> capturer(
|
2014-08-07 04:47:36 +00:00
|
|
|
CreateFakeVideoCapturer());
|
2014-01-14 10:00:58 +00:00
|
|
|
const int kTestWidth = 160;
|
|
|
|
|
const int kTestHeight = 120;
|
|
|
|
|
cricket::VideoFormat format(kTestWidth, kTestHeight,
|
|
|
|
|
cricket::VideoFormat::FpsToInterval(5),
|
|
|
|
|
cricket::FOURCC_I420);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format));
|
|
|
|
|
EXPECT_TRUE(channel_->AddSendStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(5678)));
|
2016-06-02 16:23:38 -07:00
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(5678, true, nullptr, capturer.get()));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(channel_->AddRecvStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(5678)));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(5678, &renderer2));
|
2014-01-14 10:00:58 +00:00
|
|
|
EXPECT_TRUE(capturer->CaptureCustomFrame(
|
|
|
|
|
kTestWidth, kTestHeight, cricket::FOURCC_I420));
|
|
|
|
|
EXPECT_FRAME_ON_RENDERER_WAIT(
|
2015-02-20 10:24:53 +00:00
|
|
|
renderer2, 1, kTestWidth, kTestHeight, kTimeout);
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2015-02-20 10:24:53 +00:00
|
|
|
// Get stats, and make sure they are correct for two senders. We wait until
|
|
|
|
|
// the number of expected packets have been sent to avoid races where we
|
|
|
|
|
// check stats before it has been updated.
|
2013-07-10 00:45:36 +00:00
|
|
|
cricket::VideoMediaInfo info;
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
for (uint32_t i = 0; i < kTimeout; ++i) {
|
2015-02-20 10:24:53 +00:00
|
|
|
rtc::Thread::Current()->ProcessMessages(1);
|
2015-03-04 08:54:32 +00:00
|
|
|
EXPECT_TRUE(channel_->GetStats(&info));
|
2015-02-20 10:24:53 +00:00
|
|
|
ASSERT_EQ(2U, info.senders.size());
|
|
|
|
|
if (info.senders[0].packets_sent + info.senders[1].packets_sent ==
|
|
|
|
|
NumRtpPackets()) {
|
|
|
|
|
// Stats have been updated for both sent frames, expectations can be
|
|
|
|
|
// checked now.
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(NumRtpPackets(),
|
2015-02-20 10:24:53 +00:00
|
|
|
info.senders[0].packets_sent + info.senders[1].packets_sent)
|
|
|
|
|
<< "Timed out while waiting for packet counts for all sent packets.";
|
2013-12-05 00:24:06 +00:00
|
|
|
EXPECT_EQ(1U, info.senders[0].ssrcs().size());
|
|
|
|
|
EXPECT_EQ(1234U, info.senders[0].ssrcs()[0]);
|
2016-10-24 01:21:16 -07:00
|
|
|
EXPECT_EQ(kVideoWidth, info.senders[0].send_frame_width);
|
|
|
|
|
EXPECT_EQ(kVideoHeight, info.senders[0].send_frame_height);
|
2013-12-05 00:24:06 +00:00
|
|
|
EXPECT_EQ(1U, info.senders[1].ssrcs().size());
|
|
|
|
|
EXPECT_EQ(5678U, info.senders[1].ssrcs()[0]);
|
2014-03-28 16:22:19 +00:00
|
|
|
EXPECT_EQ(kTestWidth, info.senders[1].send_frame_width);
|
|
|
|
|
EXPECT_EQ(kTestHeight, info.senders[1].send_frame_height);
|
2013-07-10 00:45:36 +00:00
|
|
|
// The capturer must be unregistered here as it runs out of it's scope next.
|
2016-06-02 16:23:38 -07:00
|
|
|
channel_->SetVideoSend(5678, true, nullptr, nullptr);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2014-01-15 23:15:54 +00:00
|
|
|
// Test that we can set the bandwidth.
|
2013-07-10 00:45:36 +00:00
|
|
|
void SetSendBandwidth() {
|
2015-09-17 16:42:56 +02:00
|
|
|
cricket::VideoSendParameters parameters;
|
|
|
|
|
parameters.codecs.push_back(DefaultCodec());
|
|
|
|
|
parameters.max_bandwidth_bps = -1; // <= 0 means unlimited.
|
|
|
|
|
EXPECT_TRUE(channel_->SetSendParameters(parameters));
|
|
|
|
|
parameters.max_bandwidth_bps = 128 * 1024;
|
|
|
|
|
EXPECT_TRUE(channel_->SetSendParameters(parameters));
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
// Test that we can set the SSRC for the default send source.
|
|
|
|
|
void SetSendSsrc() {
|
|
|
|
|
EXPECT_TRUE(SetDefaultCodec());
|
|
|
|
|
EXPECT_TRUE(SetSend(true));
|
|
|
|
|
EXPECT_TRUE(SendFrame());
|
|
|
|
|
EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
uint32_t ssrc = 0;
|
2016-03-20 06:15:43 -07:00
|
|
|
std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
|
2013-07-10 00:45:36 +00:00
|
|
|
ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
|
|
|
|
|
EXPECT_EQ(kSsrc, ssrc);
|
2015-11-11 16:19:33 +00:00
|
|
|
// Packets are being paced out, so these can mismatch between the first and
|
|
|
|
|
// second call to NumRtpPackets until pending packets are paced out.
|
|
|
|
|
EXPECT_EQ_WAIT(NumRtpPackets(), NumRtpPackets(ssrc), kTimeout);
|
|
|
|
|
EXPECT_EQ_WAIT(NumRtpBytes(), NumRtpBytes(ssrc), kTimeout);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(1, NumSentSsrcs());
|
|
|
|
|
EXPECT_EQ(0, NumRtpPackets(kSsrc - 1));
|
|
|
|
|
EXPECT_EQ(0, NumRtpBytes(kSsrc - 1));
|
|
|
|
|
}
|
|
|
|
|
// Test that we can set the SSRC even after codecs are set.
|
|
|
|
|
void SetSendSsrcAfterSetCodecs() {
|
|
|
|
|
// Remove stream added in Setup.
|
|
|
|
|
EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
|
|
|
|
|
EXPECT_TRUE(SetDefaultCodec());
|
|
|
|
|
EXPECT_TRUE(channel_->AddSendStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(999)));
|
2016-06-02 16:23:38 -07:00
|
|
|
EXPECT_TRUE(
|
|
|
|
|
channel_->SetVideoSend(999u, true, nullptr, video_capturer_.get()));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(SetSend(true));
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(0));
|
|
|
|
|
EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
uint32_t ssrc = 0;
|
2016-03-20 06:15:43 -07:00
|
|
|
std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
|
2013-07-10 00:45:36 +00:00
|
|
|
ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
|
|
|
|
|
EXPECT_EQ(999u, ssrc);
|
2015-11-11 16:19:33 +00:00
|
|
|
// Packets are being paced out, so these can mismatch between the first and
|
|
|
|
|
// second call to NumRtpPackets until pending packets are paced out.
|
|
|
|
|
EXPECT_EQ_WAIT(NumRtpPackets(), NumRtpPackets(ssrc), kTimeout);
|
|
|
|
|
EXPECT_EQ_WAIT(NumRtpBytes(), NumRtpBytes(ssrc), kTimeout);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(1, NumSentSsrcs());
|
|
|
|
|
EXPECT_EQ(0, NumRtpPackets(kSsrc));
|
|
|
|
|
EXPECT_EQ(0, NumRtpBytes(kSsrc));
|
|
|
|
|
}
|
|
|
|
|
// Test that we can set the default video renderer before and after
|
|
|
|
|
// media is received.
|
2016-02-04 01:24:52 -08:00
|
|
|
void SetSink() {
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
uint8_t data1[] = {
|
|
|
|
|
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2016-03-20 06:15:43 -07:00
|
|
|
rtc::CopyOnWriteBuffer packet1(data1, sizeof(data1));
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::SetBE32(packet1.data() + 8, kSsrc);
|
2016-02-04 01:24:52 -08:00
|
|
|
channel_->SetSink(kDefaultReceiveSsrc, NULL);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(SetDefaultCodec());
|
|
|
|
|
EXPECT_TRUE(SetSend(true));
|
|
|
|
|
EXPECT_EQ(0, renderer_.num_rendered_frames());
|
2014-07-29 17:36:52 +00:00
|
|
|
channel_->OnPacketReceived(&packet1, rtc::PacketTime());
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(SendFrame());
|
2016-10-24 01:21:16 -07:00
|
|
|
EXPECT_FRAME_WAIT(1, kVideoWidth, kVideoHeight, kTimeout);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tests empty StreamParams is rejected.
|
|
|
|
|
void RejectEmptyStreamParams() {
|
|
|
|
|
// Remove the send stream that was added during Setup.
|
|
|
|
|
EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
|
|
|
|
|
|
|
|
|
|
cricket::StreamParams empty;
|
|
|
|
|
EXPECT_FALSE(channel_->AddSendStream(empty));
|
|
|
|
|
EXPECT_TRUE(channel_->AddSendStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(789u)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tests setting up and configuring a send stream.
|
|
|
|
|
void AddRemoveSendStreams() {
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(DefaultCodec()));
|
|
|
|
|
EXPECT_TRUE(SetSend(true));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(SendFrame());
|
2016-10-24 01:21:16 -07:00
|
|
|
EXPECT_FRAME_WAIT(1, kVideoWidth, kVideoHeight, kTimeout);
|
2015-09-18 11:14:31 +02:00
|
|
|
EXPECT_GT(NumRtpPackets(), 0);
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
uint32_t ssrc = 0;
|
2013-07-10 00:45:36 +00:00
|
|
|
size_t last_packet = NumRtpPackets() - 1;
|
2016-03-20 06:15:43 -07:00
|
|
|
std::unique_ptr<const rtc::CopyOnWriteBuffer>
|
2013-12-11 18:25:07 +00:00
|
|
|
p(GetRtpPacket(static_cast<int>(last_packet)));
|
2013-07-10 00:45:36 +00:00
|
|
|
ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
|
|
|
|
|
EXPECT_EQ(kSsrc, ssrc);
|
|
|
|
|
|
|
|
|
|
// Remove the send stream that was added during Setup.
|
|
|
|
|
EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
|
|
|
|
|
int rtp_packets = NumRtpPackets();
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(channel_->AddSendStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(789u)));
|
2016-06-02 16:23:38 -07:00
|
|
|
EXPECT_TRUE(
|
|
|
|
|
channel_->SetVideoSend(789u, true, nullptr, video_capturer_.get()));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(rtp_packets, NumRtpPackets());
|
|
|
|
|
// Wait 30ms to guarantee the engine does not drop the frame.
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(30));
|
|
|
|
|
EXPECT_TRUE_WAIT(NumRtpPackets() > rtp_packets, kTimeout);
|
|
|
|
|
|
|
|
|
|
last_packet = NumRtpPackets() - 1;
|
2013-12-11 18:25:07 +00:00
|
|
|
p.reset(GetRtpPacket(static_cast<int>(last_packet)));
|
2013-07-10 00:45:36 +00:00
|
|
|
ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
|
|
|
|
|
EXPECT_EQ(789u, ssrc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tests the behavior of incoming streams in a conference scenario.
|
|
|
|
|
void SimulateConference() {
|
|
|
|
|
cricket::FakeVideoRenderer renderer1, renderer2;
|
|
|
|
|
EXPECT_TRUE(SetDefaultCodec());
|
2015-09-17 16:42:56 +02:00
|
|
|
cricket::VideoSendParameters parameters;
|
|
|
|
|
parameters.codecs.push_back(DefaultCodec());
|
2016-02-17 05:25:36 -08:00
|
|
|
parameters.conference_mode = true;
|
2015-09-17 16:42:56 +02:00
|
|
|
EXPECT_TRUE(channel_->SetSendParameters(parameters));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(SetSend(true));
|
|
|
|
|
EXPECT_TRUE(channel_->AddRecvStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(1)));
|
|
|
|
|
EXPECT_TRUE(channel_->AddRecvStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(2)));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(1, &renderer1));
|
|
|
|
|
EXPECT_TRUE(channel_->SetSink(2, &renderer2));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(0, renderer1.num_rendered_frames());
|
|
|
|
|
EXPECT_EQ(0, renderer2.num_rendered_frames());
|
Use suffixed {uint,int}{8,16,32,64}_t types.
Removes the use of uint8, etc. in favor of uint8_t.
BUG=webrtc:5024
R=henrik.lundin@webrtc.org, henrikg@webrtc.org, perkj@webrtc.org, solenberg@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org
Review URL: https://codereview.webrtc.org/1362503003 .
Cr-Commit-Position: refs/heads/master@{#10196}
2015-10-07 12:23:21 +02:00
|
|
|
std::vector<uint32_t> ssrcs;
|
2013-07-10 00:45:36 +00:00
|
|
|
ssrcs.push_back(1);
|
|
|
|
|
ssrcs.push_back(2);
|
|
|
|
|
network_interface_.SetConferenceMode(true, ssrcs);
|
|
|
|
|
EXPECT_TRUE(SendFrame());
|
2016-10-24 01:21:16 -07:00
|
|
|
EXPECT_FRAME_ON_RENDERER_WAIT(renderer1, 1, kVideoWidth, kVideoHeight,
|
|
|
|
|
kTimeout);
|
|
|
|
|
EXPECT_FRAME_ON_RENDERER_WAIT(renderer2, 1, kVideoWidth, kVideoHeight,
|
|
|
|
|
kTimeout);
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2016-03-20 06:15:43 -07:00
|
|
|
std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(DefaultCodec().id, GetPayloadType(p.get()));
|
2016-10-24 01:21:16 -07:00
|
|
|
EXPECT_EQ(kVideoWidth, renderer1.width());
|
|
|
|
|
EXPECT_EQ(kVideoHeight, renderer1.height());
|
|
|
|
|
EXPECT_EQ(kVideoWidth, renderer2.width());
|
|
|
|
|
EXPECT_EQ(kVideoHeight, renderer2.height());
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(channel_->RemoveRecvStream(2));
|
|
|
|
|
EXPECT_TRUE(channel_->RemoveRecvStream(1));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tests that we can add and remove capturers and frames are sent out properly
|
|
|
|
|
void AddRemoveCapturer() {
|
2014-01-14 10:00:58 +00:00
|
|
|
cricket::VideoCodec codec = DefaultCodec();
|
2016-10-24 01:21:16 -07:00
|
|
|
const int time_between_send_ms =
|
|
|
|
|
cricket::VideoFormat::FpsToInterval(kFramerate);
|
2014-01-14 10:00:58 +00:00
|
|
|
EXPECT_TRUE(SetOneCodec(codec));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(SetSend(true));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(0, renderer_.num_rendered_frames());
|
|
|
|
|
EXPECT_TRUE(SendFrame());
|
2016-10-24 01:21:16 -07:00
|
|
|
EXPECT_FRAME_WAIT(1, kVideoWidth, kVideoHeight, kTimeout);
|
2016-02-26 03:00:35 -08:00
|
|
|
std::unique_ptr<cricket::FakeVideoCapturer> capturer(
|
2014-08-07 04:47:36 +00:00
|
|
|
CreateFakeVideoCapturer());
|
New flag is_screencast in VideoOptions.
This cl copies the value of cricket::VideoCapturer::IsScreencast into
a flag in VideoOptions. It is passed on via the chain
VideortpSender::SetVideoSend
WebRtcVideoChannel2::SetVideoSend
WebRtcVideoChannel2::SetOptions
WebRtcVideoChannel2::WebRtcVideoSendStream::SetOptions
Where it's used, in
WebRtcVideoChannel2::WebRtcVideoSendStream::OnFrame, we can look it up
in parameters_, instead of calling capturer_->IsScreencast().
Doesn't touch screencast logic related to cpu adaptation, since that
code is in flux in a different cl.
Also drop the is_screencast flag from the Dimensions struct, and drop separate options argument from ConfigureVideoEncoderSettings and SetCodecAndOptions, instead always using the options recorded in VideoSendStreamParameters::options.
In the tests, changed FakeVideoCapturer::is_screencast to be a construction time flag. Generally, unittests of screencast have to both use a capturer configured for screencast, and set the screencast flag using SetSendParameters. Since the automatic connection via VideoSource and VideoRtpSender isn't involved in the unit tests.
Note that using SetSendParameters to set the screencast flag doesn't make sense, since it's not per-stream. SetVideoSend would be more appropriate. That should be fixed if/when we drop VideoOptions from SetSendParameters.
BUG=webrtc:5426
R=pbos@webrtc.org, perkj@webrtc.org, pthatcher@webrtc.org
Review URL: https://codereview.webrtc.org/1711763003 .
Cr-Commit-Position: refs/heads/master@{#11837}
2016-03-02 11:41:36 +01:00
|
|
|
|
|
|
|
|
// TODO(nisse): This testcase fails if we don't configure
|
|
|
|
|
// screencast. It's unclear why, I see nothing obvious in this
|
|
|
|
|
// test which is related to screencast logic.
|
|
|
|
|
cricket::VideoOptions video_options;
|
2017-11-16 11:09:55 +01:00
|
|
|
video_options.is_screencast = true;
|
2016-06-02 16:23:38 -07:00
|
|
|
channel_->SetVideoSend(kSsrc, true, &video_options, nullptr);
|
New flag is_screencast in VideoOptions.
This cl copies the value of cricket::VideoCapturer::IsScreencast into
a flag in VideoOptions. It is passed on via the chain
VideortpSender::SetVideoSend
WebRtcVideoChannel2::SetVideoSend
WebRtcVideoChannel2::SetOptions
WebRtcVideoChannel2::WebRtcVideoSendStream::SetOptions
Where it's used, in
WebRtcVideoChannel2::WebRtcVideoSendStream::OnFrame, we can look it up
in parameters_, instead of calling capturer_->IsScreencast().
Doesn't touch screencast logic related to cpu adaptation, since that
code is in flux in a different cl.
Also drop the is_screencast flag from the Dimensions struct, and drop separate options argument from ConfigureVideoEncoderSettings and SetCodecAndOptions, instead always using the options recorded in VideoSendStreamParameters::options.
In the tests, changed FakeVideoCapturer::is_screencast to be a construction time flag. Generally, unittests of screencast have to both use a capturer configured for screencast, and set the screencast flag using SetSendParameters. Since the automatic connection via VideoSource and VideoRtpSender isn't involved in the unit tests.
Note that using SetSendParameters to set the screencast flag doesn't make sense, since it's not per-stream. SetVideoSend would be more appropriate. That should be fixed if/when we drop VideoOptions from SetSendParameters.
BUG=webrtc:5426
R=pbos@webrtc.org, perkj@webrtc.org, pthatcher@webrtc.org
Review URL: https://codereview.webrtc.org/1711763003 .
Cr-Commit-Position: refs/heads/master@{#11837}
2016-03-02 11:41:36 +01:00
|
|
|
|
2014-01-14 10:00:58 +00:00
|
|
|
cricket::VideoFormat format(480, 360,
|
|
|
|
|
cricket::VideoFormat::FpsToInterval(30),
|
|
|
|
|
cricket::FOURCC_I420);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format));
|
|
|
|
|
// All capturers start generating frames with the same timestamp. ViE does
|
|
|
|
|
// not allow the same timestamp to be used. Capture one frame before
|
|
|
|
|
// associating the capturer with the channel.
|
|
|
|
|
EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
|
|
|
|
|
cricket::FOURCC_I420));
|
|
|
|
|
|
|
|
|
|
int captured_frames = 1;
|
|
|
|
|
for (int iterations = 0; iterations < 2; ++iterations) {
|
2016-06-02 16:23:38 -07:00
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr, capturer.get()));
|
2016-10-24 01:21:16 -07:00
|
|
|
rtc::Thread::Current()->ProcessMessages(time_between_send_ms);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
|
|
|
|
|
cricket::FOURCC_I420));
|
|
|
|
|
++captured_frames;
|
2013-07-22 21:07:49 +00:00
|
|
|
// Wait until frame of right size is captured.
|
|
|
|
|
EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= captured_frames &&
|
|
|
|
|
format.width == renderer_.width() &&
|
2013-07-26 19:17:59 +00:00
|
|
|
format.height == renderer_.height() &&
|
|
|
|
|
!renderer_.black_frame(), kTimeout);
|
2013-07-22 21:07:49 +00:00
|
|
|
EXPECT_GE(renderer_.num_rendered_frames(), captured_frames);
|
|
|
|
|
EXPECT_EQ(format.width, renderer_.width());
|
|
|
|
|
EXPECT_EQ(format.height, renderer_.height());
|
|
|
|
|
captured_frames = renderer_.num_rendered_frames() + 1;
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_FALSE(renderer_.black_frame());
|
2016-06-02 16:23:38 -07:00
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr, nullptr));
|
2013-07-22 21:07:49 +00:00
|
|
|
// Make sure a black frame is generated within the specified timeout.
|
2015-02-18 10:13:09 +00:00
|
|
|
// The black frame should be the resolution of the previous frame to
|
|
|
|
|
// prevent expensive encoder reconfigurations.
|
2013-07-22 21:07:49 +00:00
|
|
|
EXPECT_TRUE_WAIT(renderer_.num_rendered_frames() >= captured_frames &&
|
2015-02-18 10:13:09 +00:00
|
|
|
format.width == renderer_.width() &&
|
|
|
|
|
format.height == renderer_.height() &&
|
2013-07-22 21:07:49 +00:00
|
|
|
renderer_.black_frame(), kTimeout);
|
|
|
|
|
EXPECT_GE(renderer_.num_rendered_frames(), captured_frames);
|
2015-02-18 10:13:09 +00:00
|
|
|
EXPECT_EQ(format.width, renderer_.width());
|
|
|
|
|
EXPECT_EQ(format.height, renderer_.height());
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(renderer_.black_frame());
|
|
|
|
|
|
|
|
|
|
// The black frame has the same timestamp as the next frame since it's
|
|
|
|
|
// timestamp is set to the last frame's timestamp + interval. WebRTC will
|
|
|
|
|
// not render a frame with the same timestamp so capture another frame
|
|
|
|
|
// with the frame capturer to increment the next frame's timestamp.
|
|
|
|
|
EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height,
|
|
|
|
|
cricket::FOURCC_I420));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-02 16:23:38 -07:00
|
|
|
// Tests that if SetVideoSend is called with a NULL capturer after the
|
|
|
|
|
// capturer was already removed, the application doesn't crash (and no black
|
|
|
|
|
// frame is sent).
|
2013-07-10 00:45:36 +00:00
|
|
|
void RemoveCapturerWithoutAdd() {
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(DefaultCodec()));
|
|
|
|
|
EXPECT_TRUE(SetSend(true));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(0, renderer_.num_rendered_frames());
|
|
|
|
|
EXPECT_TRUE(SendFrame());
|
2016-10-24 01:21:16 -07:00
|
|
|
EXPECT_FRAME_WAIT(1, kVideoWidth, kVideoHeight, kTimeout);
|
2014-10-29 15:28:39 +00:00
|
|
|
// Wait for one frame so they don't get dropped because we send frames too
|
|
|
|
|
// tightly.
|
|
|
|
|
rtc::Thread::Current()->ProcessMessages(30);
|
2013-07-22 21:07:49 +00:00
|
|
|
// Remove the capturer.
|
2016-06-02 16:23:38 -07:00
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr, nullptr));
|
2013-12-11 18:25:07 +00:00
|
|
|
|
2016-06-02 16:23:38 -07:00
|
|
|
// No capturer was added, so this SetVideoSend shouldn't do anything.
|
|
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr, nullptr));
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::Thread::Current()->ProcessMessages(300);
|
2013-07-22 21:07:49 +00:00
|
|
|
// Verify no more frames were sent.
|
2017-01-13 05:57:25 -08:00
|
|
|
EXPECT_EQ(1, renderer_.num_rendered_frames());
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tests that we can add and remove capturer as unique sources.
|
|
|
|
|
void AddRemoveCapturerMultipleSources() {
|
|
|
|
|
// WebRTC implementation will drop frames if pushed to quickly. Wait the
|
|
|
|
|
// interval time to avoid that.
|
|
|
|
|
// WebRTC implementation will drop frames if pushed to quickly. Wait the
|
|
|
|
|
// interval time to avoid that.
|
|
|
|
|
// Set up the stream associated with the engine.
|
|
|
|
|
EXPECT_TRUE(channel_->AddRecvStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(kSsrc)));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer_));
|
2013-07-10 00:45:36 +00:00
|
|
|
cricket::VideoFormat capture_format; // default format
|
2016-10-24 01:21:16 -07:00
|
|
|
capture_format.interval = cricket::VideoFormat::FpsToInterval(kFramerate);
|
2013-07-10 00:45:36 +00:00
|
|
|
// Set up additional stream 1.
|
|
|
|
|
cricket::FakeVideoRenderer renderer1;
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_FALSE(channel_->SetSink(1, &renderer1));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(channel_->AddRecvStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(1)));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(1, &renderer1));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(channel_->AddSendStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(1)));
|
2016-02-26 03:00:35 -08:00
|
|
|
std::unique_ptr<cricket::FakeVideoCapturer> capturer1(
|
2014-08-07 04:47:36 +00:00
|
|
|
CreateFakeVideoCapturer());
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(cricket::CS_RUNNING, capturer1->Start(capture_format));
|
|
|
|
|
// Set up additional stream 2.
|
|
|
|
|
cricket::FakeVideoRenderer renderer2;
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_FALSE(channel_->SetSink(2, &renderer2));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(channel_->AddRecvStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(2)));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(2, &renderer2));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(channel_->AddSendStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(2)));
|
2016-02-26 03:00:35 -08:00
|
|
|
std::unique_ptr<cricket::FakeVideoCapturer> capturer2(
|
2014-08-07 04:47:36 +00:00
|
|
|
CreateFakeVideoCapturer());
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(cricket::CS_RUNNING, capturer2->Start(capture_format));
|
|
|
|
|
// State for all the streams.
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(DefaultCodec()));
|
2016-06-02 16:23:38 -07:00
|
|
|
// A limitation in the lmi implementation requires that SetVideoSend() is
|
2013-07-10 00:45:36 +00:00
|
|
|
// called after SetOneCodec().
|
|
|
|
|
// TODO(hellner): this seems like an unnecessary constraint, fix it.
|
2016-06-02 16:23:38 -07:00
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(1, true, nullptr, capturer1.get()));
|
|
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(2, true, nullptr, capturer2.get()));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(SetSend(true));
|
|
|
|
|
// Test capturer associated with engine.
|
2014-01-14 10:00:58 +00:00
|
|
|
const int kTestWidth = 160;
|
|
|
|
|
const int kTestHeight = 120;
|
|
|
|
|
EXPECT_TRUE(capturer1->CaptureCustomFrame(
|
|
|
|
|
kTestWidth, kTestHeight, cricket::FOURCC_I420));
|
|
|
|
|
EXPECT_FRAME_ON_RENDERER_WAIT(
|
|
|
|
|
renderer1, 1, kTestWidth, kTestHeight, kTimeout);
|
2013-07-10 00:45:36 +00:00
|
|
|
// Capture a frame with additional capturer2, frames should be received
|
2014-01-14 10:00:58 +00:00
|
|
|
EXPECT_TRUE(capturer2->CaptureCustomFrame(
|
|
|
|
|
kTestWidth, kTestHeight, cricket::FOURCC_I420));
|
|
|
|
|
EXPECT_FRAME_ON_RENDERER_WAIT(
|
|
|
|
|
renderer2, 1, kTestWidth, kTestHeight, kTimeout);
|
2013-07-22 21:07:49 +00:00
|
|
|
// Successfully remove the capturer.
|
2016-06-02 16:23:38 -07:00
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr, nullptr));
|
2013-07-10 00:45:36 +00:00
|
|
|
// The capturers must be unregistered here as it runs out of it's scope
|
|
|
|
|
// next.
|
2016-06-02 16:23:38 -07:00
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(1, true, nullptr, nullptr));
|
|
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(2, true, nullptr, nullptr));
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Test that multiple send streams can be created and deleted properly.
|
|
|
|
|
void MultipleSendStreams() {
|
|
|
|
|
// Remove stream added in Setup. I.e. remove stream corresponding to default
|
|
|
|
|
// channel.
|
|
|
|
|
EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
|
|
|
|
|
const unsigned int kSsrcsSize = sizeof(kSsrcs4)/sizeof(kSsrcs4[0]);
|
|
|
|
|
for (unsigned int i = 0; i < kSsrcsSize; ++i) {
|
|
|
|
|
EXPECT_TRUE(channel_->AddSendStream(
|
|
|
|
|
cricket::StreamParams::CreateLegacy(kSsrcs4[i])));
|
|
|
|
|
}
|
|
|
|
|
// Delete one of the non default channel streams, let the destructor delete
|
|
|
|
|
// the remaining ones.
|
|
|
|
|
EXPECT_TRUE(channel_->RemoveSendStream(kSsrcs4[kSsrcsSize - 1]));
|
|
|
|
|
// Stream should already be deleted.
|
|
|
|
|
EXPECT_FALSE(channel_->RemoveSendStream(kSsrcs4[kSsrcsSize - 1]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Two streams one channel tests.
|
|
|
|
|
|
|
|
|
|
// Tests that we can send and receive frames.
|
|
|
|
|
void TwoStreamsSendAndReceive(const cricket::VideoCodec& codec) {
|
|
|
|
|
SetUpSecondStream();
|
|
|
|
|
// Test sending and receiving on first stream.
|
2016-04-20 16:31:53 +02:00
|
|
|
SendAndReceive(codec);
|
2013-07-10 00:45:36 +00:00
|
|
|
// Test sending and receiving on second stream.
|
|
|
|
|
EXPECT_EQ_WAIT(1, renderer2_.num_rendered_frames(), kTimeout);
|
2015-09-18 11:14:31 +02:00
|
|
|
EXPECT_GT(NumRtpPackets(), 0);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(1, renderer2_.num_rendered_frames());
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-07 11:53:05 -07:00
|
|
|
webrtc::RtcEventLogNullImpl event_log_;
|
2016-02-26 03:00:35 -08:00
|
|
|
const std::unique_ptr<webrtc::Call> call_;
|
2016-04-08 02:23:55 -07:00
|
|
|
E engine_;
|
2016-02-26 03:00:35 -08:00
|
|
|
std::unique_ptr<cricket::FakeVideoCapturer> video_capturer_;
|
|
|
|
|
std::unique_ptr<cricket::FakeVideoCapturer> video_capturer_2_;
|
|
|
|
|
std::unique_ptr<C> channel_;
|
2013-07-10 00:45:36 +00:00
|
|
|
cricket::FakeNetworkInterface network_interface_;
|
|
|
|
|
cricket::FakeVideoRenderer renderer_;
|
|
|
|
|
cricket::VideoMediaChannel::Error media_error_;
|
|
|
|
|
|
|
|
|
|
// Used by test cases where 2 streams are run on the same channel.
|
|
|
|
|
cricket::FakeVideoRenderer renderer2_;
|
|
|
|
|
};
|
|
|
|
|
|
2017-09-15 06:47:31 +02:00
|
|
|
#endif // MEDIA_BASE_VIDEOENGINE_UNITTEST_H_ NOLINT
|