2015-01-20 21:36:13 +00:00
|
|
|
/*
|
|
|
|
|
* libjingle
|
|
|
|
|
* Copyright 2014 Google Inc.
|
|
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
|
|
|
|
*
|
|
|
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
|
|
|
* this list of conditions and the following disclaimer.
|
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
|
|
|
* and/or other materials provided with the distribution.
|
|
|
|
|
* 3. The name of the author may not be used to endorse or promote products
|
|
|
|
|
* derived from this software without specific prior written permission.
|
|
|
|
|
*
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
|
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
|
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
|
|
|
|
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
|
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
|
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
|
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
|
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
*/
|
2013-07-10 00:45:36 +00:00
|
|
|
|
Move talk/media to webrtc/media
I removed the 'libjingle' target in talk/libjingle.gyp and replaced
all users of it with base/base.gyp:rtc_base. It seems the jsoncpp
and expat dependencies were not used by it's previous references.
The files in talk/media/testdata were uploaded to Google Storage and
added .sha1 files in resources/media instead of simply moving them.
The previously disabled warnings that were inherited from
talk/build/common.gypi are now replaced by target-specific disabling
of only the failing warnings. Additional disabling was needed since the stricter
compilation warnings that applies to code in webrtc/.
License headers will be updated in a follow-up CL in order to not
break Git history.
Other modifications:
* Updated the header guards.
* Sorted the includes using chromium/src/tools/sort-headers.py
except for these files:
talk/app/webrtc/peerconnectionendtoend_unittest.cc
talk/app/webrtc/java/jni/androidmediadecoder_jni.cc
talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
webrtc/media/devices/win32devicemanager.cc.
* Unused GYP reference to libjingle_tests_additional_deps was removed.
* Removed duplicated GYP entries of
webrtc/base/testutils.cc
webrtc/base/testutils.h
The HAVE_WEBRTC_VIDEO and HAVE_WEBRTC_VOICE defines were used by only talk/media,
so they were moved to the media.gyp.
I also checked that none of
EXPAT_RELATIVE_PATH,
FEATURE_ENABLE_VOICEMAIL,
GTEST_RELATIVE_PATH,
JSONCPP_RELATIVE_PATH,
LOGGING=1,
SRTP_RELATIVE_PATH,
FEATURE_ENABLE_SSL,
FEATURE_ENABLE_VOICEMAIL,
FEATURE_ENABLE_PSTN,
HAVE_SCTP,
HAVE_SRTP,
are used by the talk/media code.
For Chromium, the following changes will need to be applied to the roll CL that updates the
DEPS for WebRTC and libjingle: https://codereview.chromium.org/1604303002/
BUG=webrtc:5420
NOPRESUBMIT=True
TBR=tommi@webrtc.org
Review URL: https://codereview.webrtc.org/1587193006
Cr-Commit-Position: refs/heads/master@{#11495}
2016-02-04 23:52:28 -08:00
|
|
|
#ifndef WEBRTC_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_ // NOLINT
|
|
|
|
|
#define WEBRTC_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_
|
2013-07-10 00:45:36 +00:00
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
2014-08-13 17:26:08 +00:00
|
|
|
#include "webrtc/base/bytebuffer.h"
|
|
|
|
|
#include "webrtc/base/gunit.h"
|
|
|
|
|
#include "webrtc/base/timeutils.h"
|
2015-09-15 12:26:33 +02:00
|
|
|
#include "webrtc/call.h"
|
Move talk/media to webrtc/media
I removed the 'libjingle' target in talk/libjingle.gyp and replaced
all users of it with base/base.gyp:rtc_base. It seems the jsoncpp
and expat dependencies were not used by it's previous references.
The files in talk/media/testdata were uploaded to Google Storage and
added .sha1 files in resources/media instead of simply moving them.
The previously disabled warnings that were inherited from
talk/build/common.gypi are now replaced by target-specific disabling
of only the failing warnings. Additional disabling was needed since the stricter
compilation warnings that applies to code in webrtc/.
License headers will be updated in a follow-up CL in order to not
break Git history.
Other modifications:
* Updated the header guards.
* Sorted the includes using chromium/src/tools/sort-headers.py
except for these files:
talk/app/webrtc/peerconnectionendtoend_unittest.cc
talk/app/webrtc/java/jni/androidmediadecoder_jni.cc
talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
webrtc/media/devices/win32devicemanager.cc.
* Unused GYP reference to libjingle_tests_additional_deps was removed.
* Removed duplicated GYP entries of
webrtc/base/testutils.cc
webrtc/base/testutils.h
The HAVE_WEBRTC_VIDEO and HAVE_WEBRTC_VOICE defines were used by only talk/media,
so they were moved to the media.gyp.
I also checked that none of
EXPAT_RELATIVE_PATH,
FEATURE_ENABLE_VOICEMAIL,
GTEST_RELATIVE_PATH,
JSONCPP_RELATIVE_PATH,
LOGGING=1,
SRTP_RELATIVE_PATH,
FEATURE_ENABLE_SSL,
FEATURE_ENABLE_VOICEMAIL,
FEATURE_ENABLE_PSTN,
HAVE_SCTP,
HAVE_SRTP,
are used by the talk/media code.
For Chromium, the following changes will need to be applied to the roll CL that updates the
DEPS for WebRTC and libjingle: https://codereview.chromium.org/1604303002/
BUG=webrtc:5420
NOPRESUBMIT=True
TBR=tommi@webrtc.org
Review URL: https://codereview.webrtc.org/1587193006
Cr-Commit-Position: refs/heads/master@{#11495}
2016-02-04 23:52:28 -08:00
|
|
|
#include "webrtc/media/base/fakenetworkinterface.h"
|
|
|
|
|
#include "webrtc/media/base/fakevideocapturer.h"
|
|
|
|
|
#include "webrtc/media/base/fakevideorenderer.h"
|
|
|
|
|
#include "webrtc/media/base/mediachannel.h"
|
|
|
|
|
#include "webrtc/media/base/streamparams.h"
|
|
|
|
|
#include "webrtc/media/webrtc/fakewebrtccall.h"
|
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};
|
2013-07-10 00:45:36 +00:00
|
|
|
|
|
|
|
|
inline bool IsEqualRes(const cricket::VideoCodec& a, int w, int h, int fps) {
|
|
|
|
|
return a.width == w && a.height == h && a.framerate == fps;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline bool IsEqualCodec(const cricket::VideoCodec& a,
|
|
|
|
|
const cricket::VideoCodec& b) {
|
|
|
|
|
return a.id == b.id && a.name == b.name &&
|
|
|
|
|
IsEqualRes(a, b.width, b.height, b.framerate);
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-05 00:24:06 +00:00
|
|
|
namespace std {
|
2013-07-10 00:45:36 +00:00
|
|
|
inline std::ostream& operator<<(std::ostream& s, const cricket::VideoCodec& c) {
|
|
|
|
|
s << "{" << c.name << "(" << c.id << "), "
|
|
|
|
|
<< c.width << "x" << c.height << "x" << c.framerate << "}";
|
|
|
|
|
return s;
|
|
|
|
|
}
|
2013-12-05 00:24:06 +00:00
|
|
|
} // namespace std
|
2013-07-10 00:45:36 +00:00
|
|
|
|
|
|
|
|
inline int TimeBetweenSend(const cricket::VideoCodec& codec) {
|
2013-07-22 21:07:49 +00:00
|
|
|
return static_cast<int>(
|
2013-07-10 00:45:36 +00:00
|
|
|
cricket::VideoFormat::FpsToInterval(codec.framerate) /
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::kNumNanosecsPerMillisec);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fake video engine that makes it possible to test enabling and disabling
|
|
|
|
|
// capturer (checking that the engine state is updated and that the capturer
|
|
|
|
|
// is indeed capturing) without having to create a channel. It also makes it
|
|
|
|
|
// possible to test that the media processors are indeed being called when
|
|
|
|
|
// registered.
|
|
|
|
|
template<class T>
|
|
|
|
|
class VideoEngineOverride : public T {
|
|
|
|
|
public:
|
2015-09-15 12:26:33 +02:00
|
|
|
VideoEngineOverride() : T() {
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
virtual ~VideoEngineOverride() {
|
|
|
|
|
}
|
|
|
|
|
bool is_camera_on() const { return T::GetVideoCapturer()->IsRunning(); }
|
|
|
|
|
void set_has_senders(bool has_senders) {
|
2013-07-22 21:07:49 +00:00
|
|
|
cricket::VideoCapturer* video_capturer = T::GetVideoCapturer();
|
2013-07-10 00:45:36 +00:00
|
|
|
if (has_senders) {
|
2013-07-22 21:07:49 +00:00
|
|
|
video_capturer->SignalVideoFrame.connect(this,
|
|
|
|
|
&VideoEngineOverride<T>::OnLocalFrame);
|
2013-07-10 00:45:36 +00:00
|
|
|
} else {
|
2013-07-22 21:07:49 +00:00
|
|
|
video_capturer->SignalVideoFrame.disconnect(this);
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void OnLocalFrame(cricket::VideoCapturer*,
|
|
|
|
|
const cricket::VideoFrame*) {
|
|
|
|
|
}
|
|
|
|
|
void OnLocalFrameFormat(cricket::VideoCapturer*,
|
|
|
|
|
const cricket::VideoFormat*) {
|
|
|
|
|
}
|
|
|
|
|
|
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 TriggerMediaFrame(uint32_t ssrc,
|
|
|
|
|
cricket::VideoFrame* frame,
|
|
|
|
|
bool* drop_frame) {
|
2013-07-10 00:45:36 +00:00
|
|
|
T::SignalMediaFrame(ssrc, frame, drop_frame);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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>()
|
|
|
|
|
: call_(webrtc::Call::Create(webrtc::Call::Config())) {}
|
|
|
|
|
|
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() {
|
|
|
|
|
cricket::Device device("test", "device");
|
2015-05-22 09:04:09 +02:00
|
|
|
engine_.Init();
|
2015-09-15 12:26:33 +02:00
|
|
|
channel_.reset(
|
|
|
|
|
engine_.CreateChannel(call_.get(), cricket::VideoOptions()));
|
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,
|
|
|
|
|
cricket::VideoFormat::FpsToInterval(30),
|
|
|
|
|
cricket::FOURCC_I420);
|
|
|
|
|
EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(format));
|
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(kSsrc, 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,
|
|
|
|
|
cricket::VideoFormat::FpsToInterval(30),
|
|
|
|
|
cricket::FOURCC_I420);
|
|
|
|
|
EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(format));
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(kSsrc + 2, video_capturer_2_.get()));
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
virtual void TearDown() {
|
|
|
|
|
channel_.reset();
|
|
|
|
|
}
|
|
|
|
|
bool SetDefaultCodec() {
|
|
|
|
|
return SetOneCodec(DefaultCodec());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SetOneCodec(int pt, const char* name, int w, int h, int fr) {
|
|
|
|
|
return SetOneCodec(cricket::VideoCodec(pt, name, w, h, fr, 0));
|
|
|
|
|
}
|
|
|
|
|
bool SetOneCodec(const cricket::VideoCodec& codec) {
|
2013-07-22 21:07:49 +00:00
|
|
|
cricket::VideoFormat capture_format(codec.width, codec.height,
|
|
|
|
|
cricket::VideoFormat::FpsToInterval(codec.framerate),
|
|
|
|
|
cricket::FOURCC_I420);
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
}
|
2014-07-29 17:36:52 +00:00
|
|
|
const rtc::Buffer* GetRtpPacket(int index) {
|
2013-07-10 00:45:36 +00:00
|
|
|
return network_interface_.GetRtpPacket(index);
|
|
|
|
|
}
|
|
|
|
|
int NumRtcpPackets() {
|
|
|
|
|
return network_interface_.NumRtcpPackets();
|
|
|
|
|
}
|
2014-07-29 17:36:52 +00:00
|
|
|
const rtc::Buffer* GetRtcpPacket(int index) {
|
2013-07-10 00:45:36 +00:00
|
|
|
return network_interface_.GetRtcpPacket(index);
|
|
|
|
|
}
|
2014-07-29 17:36:52 +00:00
|
|
|
static int GetPayloadType(const rtc::Buffer* p) {
|
2013-07-10 00:45:36 +00:00
|
|
|
int pt = -1;
|
|
|
|
|
ParseRtpPacket(p, NULL, &pt, NULL, NULL, NULL, NULL);
|
|
|
|
|
return pt;
|
|
|
|
|
}
|
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 bool ParseRtpPacket(const rtc::Buffer* p,
|
|
|
|
|
bool* x,
|
|
|
|
|
int* pt,
|
|
|
|
|
int* seqnum,
|
|
|
|
|
uint32_t* tstamp,
|
|
|
|
|
uint32_t* ssrc,
|
2013-07-10 00:45:36 +00:00
|
|
|
std::string* payload) {
|
rtc::Buffer improvements
1. Constructors, SetData(), and AppendData() now accept uint8_t*,
int8_t*, and char*. Previously, they accepted void*, meaning that
any kind of pointer was accepted. I think requiring an explicit
cast in cases where the input array isn't already of a byte-sized
type is a better compromise between convenience and safety.
2. data() can now return a uint8_t* instead of a char*, which seems
more appropriate for a byte array, and is harder to mix up with
zero-terminated C strings. data<int8_t>() is also available so
that callers that want that type instead won't have to cast, as
is data<char>() (which remains the default until all existing
callers have been fixed).
3. Constructors, SetData(), and AppendData() now accept arrays
natively, not just decayed to pointers. The advantage of this is
that callers don't have to pass the size separately.
4. There are new constructors that allow setting size and capacity
without initializing the array. Previously, this had to be done
separately after construction.
5. Instead of TransferTo(), Buffer now supports swap(), and move
construction and assignment, and has a Pass() method that works
just like std::move(). (The Pass method is modeled after
scoped_ptr::Pass().)
R=jmarusic@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/42989004
Cr-Commit-Position: refs/heads/master@{#9033}
2015-04-20 14:03:07 +02:00
|
|
|
rtc::ByteBuffer buf(*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
|
|
|
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) {
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_ptr<const rtc::Buffer> p(GetRtcpPacket(i));
|
rtc::Buffer improvements
1. Constructors, SetData(), and AppendData() now accept uint8_t*,
int8_t*, and char*. Previously, they accepted void*, meaning that
any kind of pointer was accepted. I think requiring an explicit
cast in cases where the input array isn't already of a byte-sized
type is a better compromise between convenience and safety.
2. data() can now return a uint8_t* instead of a char*, which seems
more appropriate for a byte array, and is harder to mix up with
zero-terminated C strings. data<int8_t>() is also available so
that callers that want that type instead won't have to cast, as
is data<char>() (which remains the default until all existing
callers have been fixed).
3. Constructors, SetData(), and AppendData() now accept arrays
natively, not just decayed to pointers. The advantage of this is
that callers don't have to pass the size separately.
4. There are new constructors that allow setting size and capacity
without initializing the array. Previously, this had to be done
separately after construction.
5. Instead of TransferTo(), Buffer now supports swap(), and move
construction and assignment, and has a Pass() method that works
just like std::move(). (The Pass method is modeled after
scoped_ptr::Pass().)
R=jmarusic@webrtc.org, tommi@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/42989004
Cr-Commit-Position: refs/heads/master@{#9033}
2015-04-20 14:03:07 +02:00
|
|
|
rtc::ByteBuffer buf(*p);
|
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());
|
2013-07-22 21:07:49 +00:00
|
|
|
EXPECT_TRUE(channel_->SetCapturer(kSsrc, 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);
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_ptr<const rtc::Buffer> 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());
|
|
|
|
|
EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_ptr<const rtc::Buffer> 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));
|
|
|
|
|
EXPECT_FRAME_WAIT(frame + i * fps, codec.width, codec.height, kTimeout);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_ptr<const rtc::Buffer> 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);
|
|
|
|
|
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);
|
2014-03-28 16:22:19 +00:00
|
|
|
EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width);
|
|
|
|
|
EXPECT_EQ(DefaultCodec().height, 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);
|
|
|
|
|
|
|
|
|
|
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]);
|
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);
|
|
|
|
|
EXPECT_EQ(DefaultCodec().width, info.receivers[0].frame_width);
|
|
|
|
|
EXPECT_EQ(DefaultCodec().height, info.receivers[0].frame_height);
|
|
|
|
|
EXPECT_GT(info.receivers[0].framerate_rcvd, 0);
|
|
|
|
|
EXPECT_GT(info.receivers[0].framerate_decoded, 0);
|
|
|
|
|
EXPECT_GT(info.receivers[0].framerate_output, 0);
|
|
|
|
|
}
|
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());
|
2015-11-10 22:34:18 +01:00
|
|
|
parameters.options.conference_mode = rtc::Optional<bool>(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());
|
|
|
|
|
EXPECT_FRAME_ON_RENDERER_WAIT(
|
|
|
|
|
renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
|
|
|
|
|
EXPECT_FRAME_ON_RENDERER_WAIT(
|
|
|
|
|
renderer2, 1, DefaultCodec().width, DefaultCodec().height, 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);
|
|
|
|
|
EXPECT_EQ(DefaultCodec().width, GetSenderStats(0).send_frame_width);
|
|
|
|
|
EXPECT_EQ(DefaultCodec().height, 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);
|
|
|
|
|
EXPECT_EQ(DefaultCodec().width, GetReceiverStats(i).frame_width);
|
|
|
|
|
EXPECT_EQ(DefaultCodec().height, GetReceiverStats(i).frame_height);
|
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());
|
2015-11-10 22:34:18 +01:00
|
|
|
parameters.options.conference_mode = rtc::Optional<bool>(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);
|
|
|
|
|
EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
|
|
|
|
|
|
|
|
|
|
// Add an additional capturer, and hook up a renderer to receive it.
|
2015-02-20 10:24:53 +00:00
|
|
|
cricket::FakeVideoRenderer renderer2;
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_ptr<cricket::FakeVideoCapturer> capturer(
|
2014-08-07 04:47:36 +00:00
|
|
|
CreateFakeVideoCapturer());
|
2013-07-10 00:45:36 +00:00
|
|
|
capturer->SetScreencast(true);
|
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)));
|
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(5678, capturer.get()));
|
|
|
|
|
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]);
|
2014-03-28 16:22:19 +00:00
|
|
|
EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width);
|
|
|
|
|
EXPECT_EQ(DefaultCodec().height, 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.
|
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(5678, NULL));
|
|
|
|
|
}
|
|
|
|
|
|
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;
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_ptr<const rtc::Buffer> 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)));
|
2013-07-22 21:07:49 +00:00
|
|
|
EXPECT_TRUE(channel_->SetCapturer(999u, 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;
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_ptr<const rtc::Buffer> 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
|
|
|
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::Buffer packet1(data1, sizeof(data1));
|
|
|
|
|
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());
|
|
|
|
|
EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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());
|
|
|
|
|
EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, 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;
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_ptr<const rtc::Buffer>
|
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)));
|
2013-07-22 21:07:49 +00:00
|
|
|
EXPECT_TRUE(channel_->SetCapturer(789u, 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());
|
2015-11-10 22:34:18 +01:00
|
|
|
parameters.options.conference_mode = rtc::Optional<bool>(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());
|
|
|
|
|
EXPECT_FRAME_ON_RENDERER_WAIT(
|
|
|
|
|
renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
|
|
|
|
|
EXPECT_FRAME_ON_RENDERER_WAIT(
|
|
|
|
|
renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
|
|
|
|
|
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_ptr<const rtc::Buffer> p(GetRtpPacket(0));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(DefaultCodec().id, GetPayloadType(p.get()));
|
|
|
|
|
EXPECT_EQ(DefaultCodec().width, renderer1.width());
|
|
|
|
|
EXPECT_EQ(DefaultCodec().height, renderer1.height());
|
|
|
|
|
EXPECT_EQ(DefaultCodec().width, renderer2.width());
|
|
|
|
|
EXPECT_EQ(DefaultCodec().height, renderer2.height());
|
|
|
|
|
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();
|
|
|
|
|
codec.width = 320;
|
|
|
|
|
codec.height = 240;
|
2013-07-10 00:45:36 +00:00
|
|
|
const int time_between_send = TimeBetweenSend(codec);
|
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());
|
|
|
|
|
EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_ptr<cricket::FakeVideoCapturer> capturer(
|
2014-08-07 04:47:36 +00:00
|
|
|
CreateFakeVideoCapturer());
|
2013-07-10 00:45:36 +00:00
|
|
|
capturer->SetScreencast(true);
|
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) {
|
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(kSsrc, capturer.get()));
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::Thread::Current()->ProcessMessages(time_between_send);
|
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());
|
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
|
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));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tests that if RemoveCapturer is called without a capturer ever being
|
|
|
|
|
// added, the plugin shouldn't crash (and no black frame should be sent).
|
|
|
|
|
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());
|
|
|
|
|
EXPECT_FRAME_WAIT(1, 640, 400, 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.
|
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
|
2013-12-11 18:25:07 +00:00
|
|
|
// Wait for one black frame for removing the capturer.
|
|
|
|
|
EXPECT_FRAME_WAIT(2, 640, 400, kTimeout);
|
|
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
// No capturer was added, so this RemoveCapturer should
|
|
|
|
|
// fail.
|
|
|
|
|
EXPECT_FALSE(channel_->SetCapturer(kSsrc, NULL));
|
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.
|
2013-12-11 18:25:07 +00:00
|
|
|
EXPECT_EQ(2, 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
|
|
|
|
|
capture_format.interval = cricket::VideoFormat::FpsToInterval(30);
|
|
|
|
|
// 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)));
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_ptr<cricket::FakeVideoCapturer> capturer1(
|
2014-08-07 04:47:36 +00:00
|
|
|
CreateFakeVideoCapturer());
|
2013-07-10 00:45:36 +00:00
|
|
|
capturer1->SetScreencast(true);
|
|
|
|
|
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)));
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_ptr<cricket::FakeVideoCapturer> capturer2(
|
2014-08-07 04:47:36 +00:00
|
|
|
CreateFakeVideoCapturer());
|
2013-07-10 00:45:36 +00:00
|
|
|
capturer2->SetScreencast(true);
|
|
|
|
|
EXPECT_EQ(cricket::CS_RUNNING, capturer2->Start(capture_format));
|
|
|
|
|
// State for all the streams.
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(DefaultCodec()));
|
|
|
|
|
// A limitation in the lmi implementation requires that SetCapturer() is
|
|
|
|
|
// called after SetOneCodec().
|
|
|
|
|
// TODO(hellner): this seems like an unnecessary constraint, fix it.
|
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(1, capturer1.get()));
|
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(2, capturer2.get()));
|
|
|
|
|
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.
|
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
|
|
|
|
|
// Fail to re-remove the capturer.
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_FALSE(channel_->SetCapturer(kSsrc, NULL));
|
|
|
|
|
// The capturers must be unregistered here as it runs out of it's scope
|
|
|
|
|
// next.
|
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(1, NULL));
|
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(2, NULL));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void HighAspectHighHeightCapturer() {
|
|
|
|
|
const int kWidth = 80;
|
|
|
|
|
const int kHeight = 10000;
|
|
|
|
|
const int kScaledWidth = 20;
|
|
|
|
|
const int kScaledHeight = 2500;
|
|
|
|
|
|
|
|
|
|
cricket::VideoCodec codec(DefaultCodec());
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(codec));
|
|
|
|
|
EXPECT_TRUE(SetSend(true));
|
|
|
|
|
|
|
|
|
|
cricket::FakeVideoRenderer renderer;
|
|
|
|
|
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_EQ(0, renderer.num_rendered_frames());
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(SendFrame());
|
2013-12-11 18:25:07 +00:00
|
|
|
EXPECT_GT_FRAME_ON_RENDERER_WAIT(
|
|
|
|
|
renderer, 1, codec.width, codec.height, kTimeout);
|
2013-07-10 00:45:36 +00:00
|
|
|
|
|
|
|
|
// Registering an external capturer is currently the same as screen casting
|
|
|
|
|
// (update the test when this changes).
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_ptr<cricket::FakeVideoCapturer> capturer(
|
2014-08-07 04:47:36 +00:00
|
|
|
CreateFakeVideoCapturer());
|
2013-07-10 00:45:36 +00:00
|
|
|
capturer->SetScreencast(true);
|
|
|
|
|
const std::vector<cricket::VideoFormat>* formats =
|
|
|
|
|
capturer->GetSupportedFormats();
|
|
|
|
|
cricket::VideoFormat capture_format = (*formats)[0];
|
|
|
|
|
EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(capture_format));
|
|
|
|
|
// Capture frame to not get same frame timestamps as previous capturer.
|
|
|
|
|
capturer->CaptureFrame();
|
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(kSsrc, capturer.get()));
|
2014-07-29 17:36:52 +00:00
|
|
|
EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(capturer->CaptureCustomFrame(kWidth, kHeight,
|
|
|
|
|
cricket::FOURCC_ARGB));
|
2013-12-11 18:25:07 +00:00
|
|
|
EXPECT_GT_FRAME_ON_RENDERER_WAIT(
|
|
|
|
|
renderer, 2, kScaledWidth, kScaledHeight, kTimeout);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tests that we can adapt video resolution with 16:10 aspect ratio properly.
|
|
|
|
|
void AdaptResolution16x10() {
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
|
2013-07-10 00:45:36 +00:00
|
|
|
cricket::VideoCodec codec(DefaultCodec());
|
|
|
|
|
codec.width = 640;
|
|
|
|
|
codec.height = 400;
|
|
|
|
|
SendAndReceive(codec);
|
|
|
|
|
codec.width /= 2;
|
|
|
|
|
codec.height /= 2;
|
|
|
|
|
// Adapt the resolution.
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(codec));
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(30));
|
|
|
|
|
EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout);
|
|
|
|
|
}
|
|
|
|
|
// Tests that we can adapt video resolution with 4:3 aspect ratio properly.
|
|
|
|
|
void AdaptResolution4x3() {
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
|
2013-07-10 00:45:36 +00:00
|
|
|
cricket::VideoCodec codec(DefaultCodec());
|
|
|
|
|
codec.width = 640;
|
|
|
|
|
codec.height = 400;
|
|
|
|
|
SendAndReceive(codec);
|
|
|
|
|
codec.width /= 2;
|
|
|
|
|
codec.height /= 2;
|
|
|
|
|
// Adapt the resolution.
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(codec));
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(30));
|
|
|
|
|
EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout);
|
|
|
|
|
}
|
|
|
|
|
// Tests that we can drop all frames properly.
|
|
|
|
|
void AdaptDropAllFrames() {
|
|
|
|
|
// Set the channel codec's resolution to 0, which will require the adapter
|
|
|
|
|
// to drop all frames.
|
|
|
|
|
cricket::VideoCodec codec(DefaultCodec());
|
|
|
|
|
codec.width = codec.height = codec.framerate = 0;
|
|
|
|
|
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());
|
|
|
|
|
EXPECT_TRUE(SendFrame());
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::Thread::Current()->ProcessMessages(500);
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(0, renderer_.num_rendered_frames());
|
|
|
|
|
}
|
|
|
|
|
// Tests that we can reduce the frame rate on demand properly.
|
|
|
|
|
// TODO(fbarchard): This test is flakey on pulse. Fix and re-enable
|
|
|
|
|
void AdaptFramerate() {
|
|
|
|
|
cricket::VideoCodec codec(DefaultCodec());
|
|
|
|
|
int frame_count = 0;
|
|
|
|
|
// The capturer runs at 30 fps. The channel requires 30 fps.
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(codec));
|
|
|
|
|
EXPECT_TRUE(SetSend(true));
|
|
|
|
|
EXPECT_EQ(frame_count, renderer_.num_rendered_frames());
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
|
|
|
|
|
frame_count += 2;
|
|
|
|
|
EXPECT_FRAME_WAIT(frame_count, codec.width, codec.height, kTimeout);
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_ptr<const rtc::Buffer> p(GetRtpPacket(0));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_EQ(codec.id, GetPayloadType(p.get()));
|
|
|
|
|
|
|
|
|
|
// The channel requires 15 fps.
|
|
|
|
|
codec.framerate = 15;
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(codec));
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
|
|
|
|
|
frame_count += 2;
|
|
|
|
|
EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
|
|
|
|
|
|
|
|
|
|
// The channel requires 10 fps.
|
|
|
|
|
codec.framerate = 10;
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(codec));
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
|
|
|
|
|
frame_count += 2;
|
|
|
|
|
EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
|
|
|
|
|
|
|
|
|
|
// The channel requires 8 fps. The adapter adapts to 10 fps, which is the
|
|
|
|
|
// closest factor of 30.
|
|
|
|
|
codec.framerate = 8;
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(codec));
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered.
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped.
|
|
|
|
|
EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered.
|
|
|
|
|
frame_count += 2;
|
|
|
|
|
EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
|
|
|
|
|
}
|
2014-09-03 15:25:49 +00:00
|
|
|
// Tests that adapted frames won't be upscaled to a higher resolution.
|
|
|
|
|
void SendsLowerResolutionOnSmallerFrames() {
|
|
|
|
|
cricket::VideoCodec codec = DefaultCodec();
|
|
|
|
|
codec.width = 320;
|
|
|
|
|
codec.height = 240;
|
|
|
|
|
EXPECT_TRUE(SetOneCodec(codec));
|
|
|
|
|
EXPECT_TRUE(SetSend(true));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
|
2014-09-03 15:25:49 +00:00
|
|
|
EXPECT_EQ(0, renderer_.num_rendered_frames());
|
|
|
|
|
EXPECT_TRUE(SendFrame());
|
|
|
|
|
EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
|
|
|
|
|
|
|
|
|
|
// Check that we send smaller frames at the new resolution.
|
2014-09-03 15:52:02 +00:00
|
|
|
EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(33));
|
2014-09-03 15:25:49 +00:00
|
|
|
EXPECT_TRUE(video_capturer_->CaptureCustomFrame(
|
|
|
|
|
codec.width / 2, codec.height / 2, cricket::FOURCC_I420));
|
|
|
|
|
EXPECT_FRAME_WAIT(2, codec.width / 2, codec.height / 2, kTimeout);
|
|
|
|
|
}
|
2013-07-10 00:45:36 +00:00
|
|
|
|
|
|
|
|
// Tests that we can mute and unmute the channel properly.
|
|
|
|
|
void MuteStream() {
|
|
|
|
|
EXPECT_TRUE(SetDefaultCodec());
|
|
|
|
|
cricket::FakeVideoCapturer video_capturer;
|
|
|
|
|
video_capturer.Start(
|
|
|
|
|
cricket::VideoFormat(
|
|
|
|
|
640, 480,
|
|
|
|
|
cricket::VideoFormat::FpsToInterval(30),
|
|
|
|
|
cricket::FOURCC_I420));
|
|
|
|
|
EXPECT_TRUE(channel_->SetCapturer(kSsrc, &video_capturer));
|
|
|
|
|
EXPECT_TRUE(SetSend(true));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_));
|
2014-07-18 23:31:30 +00:00
|
|
|
EXPECT_EQ(0, renderer_.num_rendered_frames());
|
2013-07-10 00:45:36 +00:00
|
|
|
// Mute the channel and expect black output frame.
|
2014-07-18 23:31:30 +00:00
|
|
|
int frame_count = 0;
|
2015-10-01 02:31:10 -07:00
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(kSsrc, false, nullptr));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(video_capturer.CaptureFrame());
|
|
|
|
|
++frame_count;
|
|
|
|
|
EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
|
|
|
|
|
EXPECT_TRUE(renderer_.black_frame());
|
|
|
|
|
// Unmute the channel and expect non-black output frame.
|
2015-10-01 02:31:10 -07:00
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr));
|
2014-07-29 17:36:52 +00:00
|
|
|
EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(video_capturer.CaptureFrame());
|
|
|
|
|
++frame_count;
|
|
|
|
|
EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
|
|
|
|
|
EXPECT_FALSE(renderer_.black_frame());
|
|
|
|
|
// Test that we can also Mute using the correct send stream SSRC.
|
2015-10-01 02:31:10 -07:00
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(kSsrc, false, nullptr));
|
2014-07-29 17:36:52 +00:00
|
|
|
EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(video_capturer.CaptureFrame());
|
|
|
|
|
++frame_count;
|
|
|
|
|
EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
|
|
|
|
|
EXPECT_TRUE(renderer_.black_frame());
|
2015-10-01 02:31:10 -07:00
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr));
|
2014-07-29 17:36:52 +00:00
|
|
|
EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(video_capturer.CaptureFrame());
|
|
|
|
|
++frame_count;
|
|
|
|
|
EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout);
|
|
|
|
|
EXPECT_FALSE(renderer_.black_frame());
|
2014-08-13 21:36:18 +00:00
|
|
|
// Test that muting an existing stream succeeds even if it's muted.
|
2015-09-10 01:57:14 -07:00
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(kSsrc, false, nullptr));
|
|
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(kSsrc, false, nullptr));
|
2015-10-01 02:31:10 -07:00
|
|
|
// Test that unmuting an existing stream succeeds even if it's not muted.
|
|
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr));
|
|
|
|
|
EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr));
|
2013-07-10 00:45:36 +00:00
|
|
|
// Test that muting an invalid stream fails.
|
2015-10-01 02:31:10 -07:00
|
|
|
EXPECT_FALSE(channel_->SetVideoSend(kSsrc+1, false, nullptr));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
SendAndReceive(codec);
|
|
|
|
|
// 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());
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-25 17:09:47 +00:00
|
|
|
// Set up 2 streams where the first stream uses the default channel.
|
|
|
|
|
// Then disconnect the first stream and verify default channel becomes
|
|
|
|
|
// available.
|
|
|
|
|
// Then add a new stream with |new_ssrc|. The new stream should re-use the
|
|
|
|
|
// default channel.
|
2013-07-10 00:45:36 +00:00
|
|
|
void TwoStreamsReUseFirstStream(const cricket::VideoCodec& codec) {
|
|
|
|
|
SetUpSecondStream();
|
2014-03-25 17:09:47 +00:00
|
|
|
// Default channel used by the first stream.
|
2014-08-13 16:47:12 +00:00
|
|
|
EXPECT_EQ(kSsrc, channel_->GetDefaultSendChannelSsrc());
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(channel_->RemoveRecvStream(kSsrc));
|
|
|
|
|
EXPECT_FALSE(channel_->RemoveRecvStream(kSsrc));
|
2014-03-25 17:09:47 +00:00
|
|
|
EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_FALSE(channel_->RemoveSendStream(kSsrc));
|
2014-03-25 17:09:47 +00:00
|
|
|
// Default channel is no longer used by a stream.
|
2014-08-13 16:47:12 +00:00
|
|
|
EXPECT_EQ(0u, channel_->GetDefaultSendChannelSsrc());
|
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 new_ssrc = kSsrc + 100;
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(channel_->AddSendStream(
|
2014-03-25 17:09:47 +00:00
|
|
|
cricket::StreamParams::CreateLegacy(new_ssrc)));
|
|
|
|
|
// Re-use default channel.
|
2014-08-13 16:47:12 +00:00
|
|
|
EXPECT_EQ(new_ssrc, channel_->GetDefaultSendChannelSsrc());
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_FALSE(channel_->AddSendStream(
|
2014-03-25 17:09:47 +00:00
|
|
|
cricket::StreamParams::CreateLegacy(new_ssrc)));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_TRUE(channel_->AddRecvStream(
|
2014-03-25 17:09:47 +00:00
|
|
|
cricket::StreamParams::CreateLegacy(new_ssrc)));
|
2016-02-04 01:24:52 -08:00
|
|
|
EXPECT_TRUE(channel_->SetSink(new_ssrc, &renderer_));
|
2013-07-10 00:45:36 +00:00
|
|
|
EXPECT_FALSE(channel_->AddRecvStream(
|
2014-03-25 17:09:47 +00:00
|
|
|
cricket::StreamParams::CreateLegacy(new_ssrc)));
|
2013-07-10 00:45:36 +00:00
|
|
|
|
2014-03-25 17:09:47 +00:00
|
|
|
EXPECT_TRUE(channel_->SetCapturer(new_ssrc, video_capturer_.get()));
|
2013-07-22 21:07:49 +00:00
|
|
|
|
2013-07-10 00:45:36 +00:00
|
|
|
SendAndReceive(codec);
|
2014-03-25 17:09:47 +00:00
|
|
|
EXPECT_TRUE(channel_->RemoveSendStream(new_ssrc));
|
2014-08-13 16:47:12 +00:00
|
|
|
EXPECT_EQ(0u, channel_->GetDefaultSendChannelSsrc());
|
2013-07-10 00:45:36 +00:00
|
|
|
}
|
|
|
|
|
|
2015-09-15 12:26:33 +02:00
|
|
|
const rtc::scoped_ptr<webrtc::Call> call_;
|
2013-07-10 00:45:36 +00:00
|
|
|
VideoEngineOverride<E> engine_;
|
2014-07-29 17:36:52 +00:00
|
|
|
rtc::scoped_ptr<cricket::FakeVideoCapturer> video_capturer_;
|
|
|
|
|
rtc::scoped_ptr<cricket::FakeVideoCapturer> video_capturer_2_;
|
|
|
|
|
rtc::scoped_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_;
|
|
|
|
|
};
|
|
|
|
|
|
Move talk/media to webrtc/media
I removed the 'libjingle' target in talk/libjingle.gyp and replaced
all users of it with base/base.gyp:rtc_base. It seems the jsoncpp
and expat dependencies were not used by it's previous references.
The files in talk/media/testdata were uploaded to Google Storage and
added .sha1 files in resources/media instead of simply moving them.
The previously disabled warnings that were inherited from
talk/build/common.gypi are now replaced by target-specific disabling
of only the failing warnings. Additional disabling was needed since the stricter
compilation warnings that applies to code in webrtc/.
License headers will be updated in a follow-up CL in order to not
break Git history.
Other modifications:
* Updated the header guards.
* Sorted the includes using chromium/src/tools/sort-headers.py
except for these files:
talk/app/webrtc/peerconnectionendtoend_unittest.cc
talk/app/webrtc/java/jni/androidmediadecoder_jni.cc
talk/app/webrtc/java/jni/androidmediaencoder_jni.cc
webrtc/media/devices/win32devicemanager.cc.
* Unused GYP reference to libjingle_tests_additional_deps was removed.
* Removed duplicated GYP entries of
webrtc/base/testutils.cc
webrtc/base/testutils.h
The HAVE_WEBRTC_VIDEO and HAVE_WEBRTC_VOICE defines were used by only talk/media,
so they were moved to the media.gyp.
I also checked that none of
EXPAT_RELATIVE_PATH,
FEATURE_ENABLE_VOICEMAIL,
GTEST_RELATIVE_PATH,
JSONCPP_RELATIVE_PATH,
LOGGING=1,
SRTP_RELATIVE_PATH,
FEATURE_ENABLE_SSL,
FEATURE_ENABLE_VOICEMAIL,
FEATURE_ENABLE_PSTN,
HAVE_SCTP,
HAVE_SRTP,
are used by the talk/media code.
For Chromium, the following changes will need to be applied to the roll CL that updates the
DEPS for WebRTC and libjingle: https://codereview.chromium.org/1604303002/
BUG=webrtc:5420
NOPRESUBMIT=True
TBR=tommi@webrtc.org
Review URL: https://codereview.webrtc.org/1587193006
Cr-Commit-Position: refs/heads/master@{#11495}
2016-02-04 23:52:28 -08:00
|
|
|
#endif // WEBRTC_MEDIA_BASE_VIDEOENGINE_UNITTEST_H_ NOLINT
|