Restart VideoReceiveStreams in WebRtcVideoEngine2.

Puts VideoReceiveStreams in a wrapper, WebRtcVideoReceiveStream that
contain their state (configs). WebRtcVideoRenderer (the wrapper between
webrtc::VideoRenderer and cricket::VideoRenderer) has also been merged
into WebRtcVideoReceiveStream.

Implements and tests setting codecs with new FEC settings as well as RTP
header extensions on already existing receive streams.

BUG=1788
R=pthatcher@webrtc.org, wu@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/14879004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6727 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
pbos@webrtc.org
2014-07-18 09:35:58 +00:00
parent c31651d847
commit d1ea06b3d5
3 changed files with 284 additions and 183 deletions

View File

@@ -638,50 +638,6 @@ class WebRtcVideoRenderFrame : public VideoFrame {
const webrtc::I420VideoFrame* const frame_;
};
WebRtcVideoRenderer::WebRtcVideoRenderer()
: last_width_(-1), last_height_(-1), renderer_(NULL) {}
void WebRtcVideoRenderer::RenderFrame(const webrtc::I420VideoFrame& frame,
int time_to_render_ms) {
talk_base::CritScope crit(&lock_);
if (renderer_ == NULL) {
LOG(LS_WARNING) << "VideoReceiveStream not connected to a VideoRenderer.";
return;
}
if (frame.width() != last_width_ || frame.height() != last_height_) {
SetSize(frame.width(), frame.height());
}
LOG(LS_VERBOSE) << "RenderFrame: (" << frame.width() << "x" << frame.height()
<< ")";
const WebRtcVideoRenderFrame render_frame(&frame);
renderer_->RenderFrame(&render_frame);
}
void WebRtcVideoRenderer::SetRenderer(cricket::VideoRenderer* renderer) {
talk_base::CritScope crit(&lock_);
renderer_ = renderer;
if (renderer_ != NULL && last_width_ != -1) {
SetSize(last_width_, last_height_);
}
}
VideoRenderer* WebRtcVideoRenderer::GetRenderer() {
talk_base::CritScope crit(&lock_);
return renderer_;
}
void WebRtcVideoRenderer::SetSize(int width, int height) {
talk_base::CritScope crit(&lock_);
if (!renderer_->SetSize(width, height, 0)) {
LOG(LS_ERROR) << "Could not set renderer size.";
}
last_width_ = width;
last_height_ = height;
}
// WebRtcVideoChannel2
WebRtcVideoChannel2::WebRtcVideoChannel2(
@@ -720,18 +676,10 @@ WebRtcVideoChannel2::~WebRtcVideoChannel2() {
delete it->second;
}
for (std::map<uint32, webrtc::VideoReceiveStream*>::iterator it =
for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
receive_streams_.begin();
it != receive_streams_.end();
++it) {
assert(it->second != NULL);
call_->DestroyVideoReceiveStream(it->second);
}
for (std::map<uint32, WebRtcVideoRenderer*>::iterator it = renderers_.begin();
it != renderers_.end();
++it) {
assert(it->second != NULL);
delete it->second;
}
}
@@ -812,6 +760,14 @@ bool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) {
}
recv_codecs_ = mapped_codecs;
for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
receive_streams_.begin();
it != receive_streams_.end();
++it) {
it->second->SetRecvCodecs(recv_codecs_);
}
return true;
}
@@ -832,7 +788,13 @@ bool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
send_codec_.Set(supported_codecs.front());
LOG(LS_INFO) << "Using codec: " << supported_codecs.front().codec.ToString();
SetCodecForAllSendStreams(supported_codecs.front());
for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
send_streams_.begin();
it != send_streams_.end();
++it) {
assert(it->second != NULL);
it->second->SetCodec(supported_codecs.front());
}
return true;
}
@@ -974,87 +936,52 @@ bool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp) {
}
webrtc::VideoReceiveStream::Config config;
config.rtp.remote_ssrc = ssrc;
config.rtp.local_ssrc = rtcp_receiver_report_ssrc_;
ConfigureReceiverRtp(&config, sp);
receive_streams_[ssrc] =
new WebRtcVideoReceiveStream(call_.get(), config, recv_codecs_);
return true;
}
void WebRtcVideoChannel2::ConfigureReceiverRtp(
webrtc::VideoReceiveStream::Config* config,
const StreamParams& sp) const {
uint32 ssrc = sp.first_ssrc();
config->rtp.remote_ssrc = ssrc;
config->rtp.local_ssrc = rtcp_receiver_report_ssrc_;
if (IsNackEnabled(recv_codecs_.begin()->codec)) {
config.rtp.nack.rtp_history_ms = kNackHistoryMs;
config->rtp.nack.rtp_history_ms = kNackHistoryMs;
}
config.rtp.remb = true;
config.rtp.extensions = recv_rtp_extensions_;
config->rtp.remb = true;
config->rtp.extensions = recv_rtp_extensions_;
// TODO(pbos): This protection is against setting the same local ssrc as
// remote which is not permitted by the lower-level API. RTCP requires a
// corresponding sender SSRC. Figure out what to do when we don't have
// (receive-only) or know a good local SSRC.
if (config.rtp.remote_ssrc == config.rtp.local_ssrc) {
if (config.rtp.local_ssrc != kDefaultRtcpReceiverReportSsrc) {
config.rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc;
if (config->rtp.remote_ssrc == config->rtp.local_ssrc) {
if (config->rtp.local_ssrc != kDefaultRtcpReceiverReportSsrc) {
config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc;
} else {
config.rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc + 1;
config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc + 1;
}
}
bool default_renderer_used = false;
for (std::map<uint32, WebRtcVideoRenderer*>::iterator it = renderers_.begin();
it != renderers_.end();
++it) {
if (it->second->GetRenderer() == default_renderer_) {
default_renderer_used = true;
for (size_t i = 0; i < recv_codecs_.size(); ++i) {
if (recv_codecs_[i].codec.id == kDefaultVideoCodecPref.payload_type) {
config->rtp.fec = recv_codecs_[i].fec;
uint32 rtx_ssrc;
if (recv_codecs_[i].rtx_payload_type != -1 &&
sp.GetFidSsrc(ssrc, &rtx_ssrc)) {
config->rtp.rtx[kDefaultVideoCodecPref.payload_type].ssrc = rtx_ssrc;
config->rtp.rtx[kDefaultVideoCodecPref.payload_type].payload_type =
recv_codecs_[i].rtx_payload_type;
}
break;
}
}
assert(renderers_[ssrc] == NULL);
renderers_[ssrc] = new WebRtcVideoRenderer();
if (!default_renderer_used) {
renderers_[ssrc]->SetRenderer(default_renderer_);
}
config.renderer = renderers_[ssrc];
{
// TODO(pbos): Base receive codecs off recv_codecs_ and set up using a
// DecoderFactory similar to send side. Pending webrtc:2854.
// Also set up default codecs if there's nothing in recv_codecs_.
webrtc::VideoCodec codec;
memset(&codec, 0, sizeof(codec));
codec.plType = kDefaultVideoCodecPref.payload_type;
talk_base::strcpyn(codec.plName, ARRAY_SIZE(codec.plName),
kDefaultVideoCodecPref.name);
codec.codecType = webrtc::kVideoCodecVP8;
codec.codecSpecific.VP8.resilience = webrtc::kResilientStream;
codec.codecSpecific.VP8.numberOfTemporalLayers = 1;
codec.codecSpecific.VP8.denoisingOn = true;
codec.codecSpecific.VP8.errorConcealmentOn = false;
codec.codecSpecific.VP8.automaticResizeOn = false;
codec.codecSpecific.VP8.frameDroppingOn = true;
codec.codecSpecific.VP8.keyFrameInterval = 3000;
// Bitrates don't matter and are ignored for the receiver. This is put in to
// have the current underlying implementation accept the VideoCodec.
codec.minBitrate = codec.startBitrate = codec.maxBitrate = 300;
config.codecs.push_back(codec);
for (size_t i = 0; i < recv_codecs_.size(); ++i) {
if (recv_codecs_[i].codec.id == codec.plType) {
config.rtp.fec = recv_codecs_[i].fec;
uint32 rtx_ssrc;
if (recv_codecs_[i].rtx_payload_type != -1 &&
sp.GetFidSsrc(ssrc, &rtx_ssrc)) {
config.rtp.rtx[codec.plType].ssrc = rtx_ssrc;
config.rtp.rtx[codec.plType].payload_type =
recv_codecs_[i].rtx_payload_type;
}
break;
}
}
}
webrtc::VideoReceiveStream* receive_stream =
call_->CreateVideoReceiveStream(config);
assert(receive_stream != NULL);
receive_streams_[ssrc] = receive_stream;
receive_stream->Start();
return true;
}
bool WebRtcVideoChannel2::RemoveRecvStream(uint32 ssrc) {
@@ -1063,21 +990,15 @@ bool WebRtcVideoChannel2::RemoveRecvStream(uint32 ssrc) {
ssrc = default_recv_ssrc_;
}
std::map<uint32, webrtc::VideoReceiveStream*>::iterator stream =
std::map<uint32, WebRtcVideoReceiveStream*>::iterator stream =
receive_streams_.find(ssrc);
if (stream == receive_streams_.end()) {
LOG(LS_ERROR) << "Stream not found for ssrc: " << ssrc;
return false;
}
call_->DestroyVideoReceiveStream(stream->second);
delete stream->second;
receive_streams_.erase(stream);
std::map<uint32, WebRtcVideoRenderer*>::iterator renderer =
renderers_.find(ssrc);
assert(renderer != renderers_.end());
delete renderer->second;
renderers_.erase(renderer);
if (ssrc == default_recv_ssrc_) {
default_recv_ssrc_ = 0;
}
@@ -1088,16 +1009,19 @@ bool WebRtcVideoChannel2::RemoveRecvStream(uint32 ssrc) {
bool WebRtcVideoChannel2::SetRenderer(uint32 ssrc, VideoRenderer* renderer) {
LOG(LS_INFO) << "SetRenderer: ssrc:" << ssrc << " "
<< (renderer ? "(ptr)" : "NULL");
bool is_default_ssrc = false;
if (ssrc == 0) {
is_default_ssrc = true;
if (default_recv_ssrc_!= 0) {
receive_streams_[default_recv_ssrc_]->SetRenderer(renderer);
}
ssrc = default_recv_ssrc_;
default_renderer_ = renderer;
return true;
}
std::map<uint32, WebRtcVideoRenderer*>::iterator it = renderers_.find(ssrc);
if (it == renderers_.end()) {
return is_default_ssrc;
std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
receive_streams_.find(ssrc);
if (it == receive_streams_.end()) {
return false;
}
it->second->SetRenderer(renderer);
@@ -1113,8 +1037,9 @@ bool WebRtcVideoChannel2::GetRenderer(uint32 ssrc, VideoRenderer** renderer) {
return true;
}
std::map<uint32, WebRtcVideoRenderer*>::iterator it = renderers_.find(ssrc);
if (it == renderers_.end()) {
std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
receive_streams_.find(ssrc);
if (it == receive_streams_.end()) {
return false;
}
*renderer = it->second->GetRenderer();
@@ -1179,6 +1104,7 @@ void WebRtcVideoChannel2::OnPacketReceived(
sp.ssrcs.push_back(ssrc);
LOG(LS_INFO) << "Creating default receive stream for SSRC=" << ssrc << ".";
AddRecvStream(sp);
SetRenderer(0, default_renderer_);
if (call_->Receiver()->DeliverPacket(
reinterpret_cast<const uint8_t*>(packet->data()), packet->length()) !=
@@ -1226,6 +1152,14 @@ bool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions(
webrtc_extensions.push_back(webrtc_extension);
}
recv_rtp_extensions_ = webrtc_extensions;
for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
receive_streams_.begin();
it != receive_streams_.end();
++it) {
it->second->SetRtpExtensions(recv_rtp_extensions_);
}
return true;
}
@@ -1241,6 +1175,12 @@ bool WebRtcVideoChannel2::SetSendRtpHeaderExtensions(
webrtc_extensions.push_back(webrtc_extension);
}
send_rtp_extensions_ = webrtc_extensions;
for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
send_streams_.begin();
it != send_streams_.end();
++it) {
it->second->SetRtpExtensions(send_rtp_extensions_);
}
return true;
}
@@ -1319,17 +1259,6 @@ void WebRtcVideoChannel2::StopAllSendStreams() {
}
}
void WebRtcVideoChannel2::SetCodecForAllSendStreams(
const WebRtcVideoChannel2::VideoCodecSettings& codec) {
for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
send_streams_.begin();
it != send_streams_.end();
++it) {
assert(it->second != NULL);
it->second->SetCodec(codec);
}
}
WebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters::
VideoSendStreamParameters(
const webrtc::VideoSendStream::Config& config,
@@ -1577,6 +1506,13 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodecAndOptions(
delete old_encoder;
}
void WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions(
const std::vector<webrtc::RtpExtension>& rtp_extensions) {
talk_base::CritScope cs(&lock_);
parameters_.config.rtp.extensions = rtp_extensions;
RecreateWebRtcStream();
}
void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(int width,
int height) {
assert(!parameters_.video_streams.empty());
@@ -1626,6 +1562,115 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
}
}
WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream(
webrtc::Call* call,
const webrtc::VideoReceiveStream::Config& config,
const std::vector<VideoCodecSettings>& recv_codecs)
: call_(call),
config_(config),
stream_(NULL),
last_width_(-1),
last_height_(-1),
renderer_(NULL) {
config_.renderer = this;
// SetRecvCodecs will also reset (start) the VideoReceiveStream.
SetRecvCodecs(recv_codecs);
}
WebRtcVideoChannel2::WebRtcVideoReceiveStream::~WebRtcVideoReceiveStream() {
call_->DestroyVideoReceiveStream(stream_);
}
void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvCodecs(
const std::vector<VideoCodecSettings>& recv_codecs) {
// TODO(pbos): Reconfigure RTX based on incoming recv_codecs.
// TODO(pbos): Base receive codecs off recv_codecs_ and set up using a
// DecoderFactory similar to send side. Pending webrtc:2854.
// Also set up default codecs if there's nothing in recv_codecs_.
webrtc::VideoCodec codec;
memset(&codec, 0, sizeof(codec));
codec.plType = kDefaultVideoCodecPref.payload_type;
strcpy(codec.plName, kDefaultVideoCodecPref.name);
codec.codecType = webrtc::kVideoCodecVP8;
codec.codecSpecific.VP8.resilience = webrtc::kResilientStream;
codec.codecSpecific.VP8.numberOfTemporalLayers = 1;
codec.codecSpecific.VP8.denoisingOn = true;
codec.codecSpecific.VP8.errorConcealmentOn = false;
codec.codecSpecific.VP8.automaticResizeOn = false;
codec.codecSpecific.VP8.frameDroppingOn = true;
codec.codecSpecific.VP8.keyFrameInterval = 3000;
// Bitrates don't matter and are ignored for the receiver. This is put in to
// have the current underlying implementation accept the VideoCodec.
codec.minBitrate = codec.startBitrate = codec.maxBitrate = 300;
config_.codecs.clear();
config_.codecs.push_back(codec);
config_.rtp.fec = recv_codecs.front().fec;
RecreateWebRtcStream();
}
void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRtpExtensions(
const std::vector<webrtc::RtpExtension>& extensions) {
config_.rtp.extensions = extensions;
RecreateWebRtcStream();
}
void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() {
if (stream_ != NULL) {
call_->DestroyVideoReceiveStream(stream_);
}
stream_ = call_->CreateVideoReceiveStream(config_);
stream_->Start();
}
void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RenderFrame(
const webrtc::I420VideoFrame& frame,
int time_to_render_ms) {
talk_base::CritScope crit(&renderer_lock_);
if (renderer_ == NULL) {
LOG(LS_WARNING) << "VideoReceiveStream not connected to a VideoRenderer.";
return;
}
if (frame.width() != last_width_ || frame.height() != last_height_) {
SetSize(frame.width(), frame.height());
}
LOG(LS_VERBOSE) << "RenderFrame: (" << frame.width() << "x" << frame.height()
<< ")";
const WebRtcVideoRenderFrame render_frame(&frame);
renderer_->RenderFrame(&render_frame);
}
void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRenderer(
cricket::VideoRenderer* renderer) {
talk_base::CritScope crit(&renderer_lock_);
renderer_ = renderer;
if (renderer_ != NULL && last_width_ != -1) {
SetSize(last_width_, last_height_);
}
}
VideoRenderer* WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetRenderer() {
// TODO(pbos): Remove GetRenderer and all uses of it, it's thread-unsafe by
// design.
talk_base::CritScope crit(&renderer_lock_);
return renderer_;
}
void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetSize(int width,
int height) {
talk_base::CritScope crit(&renderer_lock_);
if (!renderer_->SetSize(width, height, 0)) {
LOG(LS_ERROR) << "Could not set renderer size.";
}
last_width_ = width;
last_height_ = height;
}
WebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings()
: rtx_payload_type(-1) {}

View File

@@ -41,6 +41,7 @@
#include "webrtc/transport.h"
#include "webrtc/video_renderer.h"
#include "webrtc/video_send_stream.h"
#include "webrtc/video_receive_stream.h"
namespace webrtc {
class Call;
@@ -170,29 +171,6 @@ class WebRtcVideoEngine2 : public sigslot::has_slots<> {
WebRtcVideoEncoderFactory2 default_video_encoder_factory_;
};
// Adapter between webrtc::VideoRenderer and cricket::VideoRenderer.
// The webrtc::VideoRenderer is set once, whereas the cricket::VideoRenderer can
// be set after initialization. This adapter will also convert the incoming
// webrtc::I420VideoFrame to a frame type that cricket::VideoRenderer can
// render.
class WebRtcVideoRenderer : public webrtc::VideoRenderer {
public:
WebRtcVideoRenderer();
virtual void RenderFrame(const webrtc::I420VideoFrame& frame,
int time_to_render_ms) OVERRIDE;
void SetRenderer(cricket::VideoRenderer* renderer);
cricket::VideoRenderer* GetRenderer();
private:
void SetSize(int width, int height);
int last_width_;
int last_height_;
talk_base::CriticalSection lock_;
cricket::VideoRenderer* renderer_ GUARDED_BY(lock_);
};
class WebRtcVideoChannel2 : public talk_base::MessageHandler,
public VideoMediaChannel,
public webrtc::newapi::Transport {
@@ -261,6 +239,9 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler,
bool GetRenderer(uint32 ssrc, VideoRenderer** renderer);
private:
void ConfigureReceiverRtp(webrtc::VideoReceiveStream::Config* config,
const StreamParams& sp) const;
struct VideoCodecSettings {
VideoCodecSettings();
@@ -269,6 +250,8 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler,
int rtx_payload_type;
};
// Wrapper for the sender part, this is where the capturer is connected and
// frames are then converted from cricket frames to webrtc frames.
class WebRtcVideoSendStream : public sigslot::has_slots<> {
public:
WebRtcVideoSendStream(
@@ -282,6 +265,8 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler,
~WebRtcVideoSendStream();
void SetOptions(const VideoOptions& options);
void SetCodec(const VideoCodecSettings& codec);
void SetRtpExtensions(
const std::vector<webrtc::RtpExtension>& rtp_extensions);
void InputFrame(VideoCapturer* capturer, const VideoFrame* frame);
bool SetCapturer(VideoCapturer* capturer);
@@ -332,6 +317,41 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler,
webrtc::I420VideoFrame video_frame_ GUARDED_BY(frame_lock_);
};
// Wrapper for the receiver part, contains configs etc. that are needed to
// reconstruct the underlying VideoReceiveStream. Also serves as a wrapper
// between webrtc::VideoRenderer and cricket::VideoRenderer.
class WebRtcVideoReceiveStream : public webrtc::VideoRenderer {
public:
WebRtcVideoReceiveStream(
webrtc::Call*,
const webrtc::VideoReceiveStream::Config& config,
const std::vector<VideoCodecSettings>& recv_codecs);
~WebRtcVideoReceiveStream();
void SetRecvCodecs(const std::vector<VideoCodecSettings>& recv_codecs);
void SetRtpExtensions(const std::vector<webrtc::RtpExtension>& extensions);
virtual void RenderFrame(const webrtc::I420VideoFrame& frame,
int time_to_render_ms) OVERRIDE;
void SetRenderer(cricket::VideoRenderer* renderer);
cricket::VideoRenderer* GetRenderer();
private:
void SetSize(int width, int height);
void RecreateWebRtcStream();
webrtc::Call* const call_;
webrtc::VideoReceiveStream* stream_;
webrtc::VideoReceiveStream::Config config_;
talk_base::CriticalSection renderer_lock_;
cricket::VideoRenderer* renderer_ GUARDED_BY(renderer_lock_);
int last_width_;
int last_height_;
};
void Construct(webrtc::Call* call, WebRtcVideoEngine2* engine);
virtual bool SendRtp(const uint8_t* data, size_t len) OVERRIDE;
@@ -339,7 +359,7 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler,
void StartAllSendStreams();
void StopAllSendStreams();
void SetCodecForAllSendStreams(const VideoCodecSettings& codec);
static std::vector<VideoCodecSettings> MapCodecs(
const std::vector<VideoCodec>& codecs);
std::vector<VideoCodecSettings> FilterSupportedCodecs(
@@ -348,14 +368,13 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler,
uint32_t rtcp_receiver_report_ssrc_;
bool sending_;
talk_base::scoped_ptr<webrtc::Call> call_;
std::map<uint32, WebRtcVideoRenderer*> renderers_;
VideoRenderer* default_renderer_;
uint32_t default_send_ssrc_;
uint32_t default_recv_ssrc_;
VideoRenderer* default_renderer_;
// Using primary-ssrc (first ssrc) as key.
std::map<uint32, WebRtcVideoSendStream*> send_streams_;
std::map<uint32, webrtc::VideoReceiveStream*> receive_streams_;
std::map<uint32, WebRtcVideoReceiveStream*> receive_streams_;
Settable<VideoCodecSettings> send_codec_;
std::vector<webrtc::RtpExtension> send_rtp_extensions_;

View File

@@ -621,6 +621,7 @@ class WebRtcVideoChannel2Test : public WebRtcVideoEngine2Test {
void TestSetSendRtpHeaderExtensions(const std::string& cricket_ext,
const std::string& webrtc_ext) {
FakeCall* call = fake_channel_->GetFakeCall();
// Enable extension.
const int id = 1;
std::vector<cricket::RtpHeaderExtension> extensions;
@@ -642,15 +643,25 @@ class WebRtcVideoChannel2Test : public WebRtcVideoEngine2Test {
->GetConfig()
.rtp.extensions.empty());
// Remove the extension id, verify that this doesn't reset extensions as
// they should be set before creating channels.
// Verify that existing RTP header extensions can be removed.
std::vector<cricket::RtpHeaderExtension> empty_extensions;
EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(empty_extensions));
EXPECT_FALSE(send_stream->GetConfig().rtp.extensions.empty());
ASSERT_EQ(1u, call->GetVideoSendStreams().size());
send_stream = call->GetVideoSendStreams()[0];
EXPECT_TRUE(send_stream->GetConfig().rtp.extensions.empty());
// Verify that adding receive RTP header extensions adds them for existing
// streams.
EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions));
send_stream = call->GetVideoSendStreams()[0];
ASSERT_EQ(1u, send_stream->GetConfig().rtp.extensions.size());
EXPECT_EQ(id, send_stream->GetConfig().rtp.extensions[0].id);
EXPECT_EQ(webrtc_ext, send_stream->GetConfig().rtp.extensions[0].name);
}
void TestSetRecvRtpHeaderExtensions(const std::string& cricket_ext,
const std::string& webrtc_ext) {
FakeCall* call = fake_channel_->GetFakeCall();
// Enable extension.
const int id = 1;
std::vector<cricket::RtpHeaderExtension> extensions;
@@ -666,17 +677,27 @@ class WebRtcVideoChannel2Test : public WebRtcVideoEngine2Test {
EXPECT_EQ(webrtc_ext, recv_stream->GetConfig().rtp.extensions[0].name);
// Verify call with same set of extensions returns true.
EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions));
// Verify that SetRecvRtpHeaderExtensions doesn't implicitly add them for
// senders.
EXPECT_TRUE(AddSendStream(cricket::StreamParams::CreateLegacy(123))
->GetConfig()
.rtp.extensions.empty());
// Remove the extension id, verify that this doesn't reset extensions as
// they should be set before creating channels.
// Verify that existing RTP header extensions can be removed.
std::vector<cricket::RtpHeaderExtension> empty_extensions;
EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(empty_extensions));
EXPECT_FALSE(recv_stream->GetConfig().rtp.extensions.empty());
EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(empty_extensions));
ASSERT_EQ(1u, call->GetVideoReceiveStreams().size());
recv_stream = call->GetVideoReceiveStreams()[0];
EXPECT_TRUE(recv_stream->GetConfig().rtp.extensions.empty());
// Verify that adding receive RTP header extensions adds them for existing
// streams.
EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions));
recv_stream = call->GetVideoReceiveStreams()[0];
ASSERT_EQ(1u, recv_stream->GetConfig().rtp.extensions.size());
EXPECT_EQ(id, recv_stream->GetConfig().rtp.extensions[0].id);
EXPECT_EQ(webrtc_ext, recv_stream->GetConfig().rtp.extensions[0].name);
}
talk_base::scoped_ptr<VideoMediaChannel> channel_;
@@ -1230,8 +1251,24 @@ TEST_F(WebRtcVideoChannel2Test,
FAIL(); // TODO(pbos): Verify that the FEC parameters are set for all codecs.
}
TEST_F(WebRtcVideoChannel2Test, DISABLED_SetRecvCodecsWithoutFecDisablesFec) {
FAIL() << "Not implemented."; // TODO(pbos): Implement.
TEST_F(WebRtcVideoChannel2Test, SetRecvCodecsWithoutFecDisablesFec) {
std::vector<VideoCodec> codecs;
codecs.push_back(kVp8Codec);
codecs.push_back(kUlpfecCodec);
ASSERT_TRUE(channel_->SetSendCodecs(codecs));
FakeVideoReceiveStream* stream = AddRecvStream();
webrtc::VideoReceiveStream::Config config = stream->GetConfig();
EXPECT_EQ(kUlpfecCodec.id, config.rtp.fec.ulpfec_payload_type);
codecs.pop_back();
ASSERT_TRUE(channel_->SetRecvCodecs(codecs));
stream = fake_channel_->GetFakeCall()->GetVideoReceiveStreams()[0];
ASSERT_TRUE(stream != NULL);
config = stream->GetConfig();
EXPECT_EQ(-1, config.rtp.fec.ulpfec_payload_type)
<< "SetSendCodec without FEC should disable current FEC.";
}
TEST_F(WebRtcVideoChannel2Test, SetSendCodecsRejectDuplicateFecPayloads) {