Allow multiple REMB groups and introduce receive channels.
BUG=312 TEST=ViE standard autotest and API test. Review URL: https://webrtc-codereview.appspot.com/432005 git-svn-id: http://webrtc.googlecode.com/svn/trunk@1836 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
855ced7336
commit
9ec883e8bd
@ -1662,7 +1662,7 @@ WebRtc_Word32 ModuleRtpRtcpImpl::SetREMBData(const WebRtc_UWord32 bitrate,
|
||||
}
|
||||
|
||||
WebRtc_Word32 ModuleRtpRtcpImpl::SetMaximumBitrateEstimate(
|
||||
const WebRtc_UWord32 bitrate) {
|
||||
const WebRtc_UWord32 bitrate) {
|
||||
if (_defaultModule) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
||||
"SetMaximumBitrateEstimate - Should be called on default "
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
@ -85,10 +85,22 @@ class WEBRTC_DLLEXPORT ViEBase {
|
||||
// synchronization.
|
||||
virtual int SetVoiceEngine(VoiceEngine* voice_engine) = 0;
|
||||
|
||||
// Creates a new channel, either with a new encoder instance or by sharing
|
||||
// encoder instance with an already created channel.
|
||||
// Creates a new channel.
|
||||
virtual int CreateChannel(int& video_channel) = 0;
|
||||
virtual int CreateChannel(int& video_channel, int original_channel) = 0;
|
||||
|
||||
// Creates a new channel grouped together with |original_channel|. The channel
|
||||
// can both send and receive video. It is assumed the channel is sending
|
||||
// and/or receiving video to the same end-point.
|
||||
// Note: |CreateReceiveChannel| will give better performance and network
|
||||
// properties for receive only channels.
|
||||
virtual int CreateChannel(int& video_channel,
|
||||
int original_channel) = 0;
|
||||
|
||||
// Creates a new channel grouped together with |original_channel|. The channel
|
||||
// can only receive video and it is assumed the remote end-point is the same
|
||||
// as for |original_channel|.
|
||||
virtual int CreateReceiveChannel(int& video_channel,
|
||||
int original_channel) = 0;
|
||||
|
||||
// Deletes an existing channel and releases the utilized resources.
|
||||
virtual int DeleteChannel(const int video_channel) = 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
@ -21,6 +21,7 @@ enum ViEErrors {
|
||||
kViEBaseInvalidArgument,
|
||||
kViEBaseAlreadySending, // StartSend called on channel that is already sending.
|
||||
kViEBaseNotSending, // StopSend called on channel that is not sending.
|
||||
kViEBaseReceiveOnlyChannel, // Can't send on a receive only channel.
|
||||
kViEBaseAlreadyReceiving, // StartReceive called on channel that is already receiving.
|
||||
kViEBaseObserverAlreadyRegistered, // RegisterObserver- an observer has already been set.
|
||||
kViEBaseObserverNotRegistered, // DeregisterObserver - no observer has been registered.
|
||||
@ -33,6 +34,7 @@ enum ViEErrors {
|
||||
kViECodecInvalidCodec, // SetSendCodec,SetReceiveCodec- The codec structure is invalid.
|
||||
kViECodecInvalidChannelId, // The channel does not exist.
|
||||
kViECodecInUse, // SetSendCodec- Can't change codec size or type when multiple channels use the same encoder.
|
||||
kViECodecReceiveOnlyChannel, // SetSendCodec, can't change receive only channel.
|
||||
kViECodecUnknownError, // An unknown error has occurred. Check the log file.
|
||||
|
||||
// ViERender.
|
||||
|
@ -133,6 +133,9 @@ void ViEAutoTest::ViEBaseAPITest() {
|
||||
ptrViEBase = webrtc::ViEBase::GetInterface(ptrViE);
|
||||
EXPECT_TRUE(NULL != ptrViEBase);
|
||||
|
||||
webrtc::ViENetwork* ptrVieNetwork = webrtc::ViENetwork::GetInterface(ptrViE);
|
||||
EXPECT_TRUE(ptrVieNetwork != NULL);
|
||||
|
||||
// ***************************************************************
|
||||
// Engine ready. Begin testing class
|
||||
// ***************************************************************
|
||||
@ -148,16 +151,35 @@ void ViEAutoTest::ViEBaseAPITest() {
|
||||
EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel));
|
||||
|
||||
int videoChannel2 = -1;
|
||||
int videoChannel3 = -1;
|
||||
EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel2));
|
||||
EXPECT_NE(videoChannel, videoChannel2) <<
|
||||
"Should allocate new number for independent channel";
|
||||
|
||||
EXPECT_EQ(0, ptrViEBase->DeleteChannel(videoChannel2));
|
||||
|
||||
EXPECT_EQ(-1, ptrViEBase->CreateChannel(videoChannel2, videoChannel + 1)) <<
|
||||
"Should fail since neither channel exists (the second must)";
|
||||
EXPECT_EQ(-1, ptrViEBase->CreateChannel(videoChannel2, videoChannel + 1))
|
||||
<< "Should fail since neither channel exists (the second must)";
|
||||
|
||||
EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel2, videoChannel));
|
||||
// Create a receive only channel and a send channel. Verify we can't send on
|
||||
// the receive only channel.
|
||||
EXPECT_EQ(0, ptrViEBase->CreateReceiveChannel(videoChannel2, videoChannel));
|
||||
EXPECT_EQ(0, ptrViEBase->CreateChannel(videoChannel3, videoChannel));
|
||||
|
||||
const char* ipAddress = "127.0.0.1\0";
|
||||
const int sendPort = 1234;
|
||||
EXPECT_EQ(0, ptrVieNetwork->SetSendDestination(videoChannel, ipAddress,
|
||||
sendPort));
|
||||
EXPECT_EQ(0, ptrVieNetwork->SetSendDestination(videoChannel2,ipAddress,
|
||||
sendPort + 2));
|
||||
EXPECT_EQ(0, ptrVieNetwork->SetSendDestination(videoChannel3,ipAddress,
|
||||
sendPort + 4));
|
||||
|
||||
EXPECT_EQ(0, ptrViEBase->StartSend(videoChannel));
|
||||
EXPECT_EQ(-1, ptrViEBase->StartSend(videoChannel2));
|
||||
EXPECT_EQ(0, ptrViEBase->StartSend(videoChannel3));
|
||||
EXPECT_EQ(0, ptrViEBase->StopSend(videoChannel));
|
||||
EXPECT_EQ(0, ptrViEBase->StopSend(videoChannel3));
|
||||
|
||||
// Test Voice Engine integration with Video Engine.
|
||||
webrtc::VoiceEngine* ptrVoE = NULL;
|
||||
@ -191,6 +213,7 @@ void ViEAutoTest::ViEBaseAPITest() {
|
||||
EXPECT_EQ(0, ptrViEBase->DisconnectAudioChannel(videoChannel));
|
||||
|
||||
// Clean up voice engine
|
||||
EXPECT_EQ(0, ptrVieNetwork->Release());
|
||||
EXPECT_EQ(0, ptrViEBase->SetVoiceEngine(NULL));
|
||||
EXPECT_EQ(0, ptrVoEBase->Release());
|
||||
EXPECT_TRUE(webrtc::VoiceEngine::Delete(ptrVoE));
|
||||
|
@ -139,99 +139,116 @@ void ViEAutoTest::ViECodecExtendedTest()
|
||||
}
|
||||
|
||||
//
|
||||
// Default channel
|
||||
// Multiple send channels.
|
||||
//
|
||||
{
|
||||
// Create VIE
|
||||
// Create two channels, where the second channel is created from the
|
||||
// first channel. Send different resolutions on the channels and verify
|
||||
// the received streams.
|
||||
|
||||
TbInterfaces ViE("ViECodecExtendedTest2");
|
||||
// Create a capture device
|
||||
TbCaptureDevice tbCapture(ViE);
|
||||
|
||||
// Create channel 1
|
||||
// Create channel 1.
|
||||
int videoChannel1 = -1;
|
||||
EXPECT_EQ(0, ViE.base->CreateChannel(videoChannel1));
|
||||
|
||||
// Create channel 2 based on the first channel.
|
||||
int videoChannel2 = -1;
|
||||
EXPECT_EQ(0, ViE.base->CreateChannel(videoChannel2, videoChannel1));
|
||||
EXPECT_NE(videoChannel1, videoChannel2) <<
|
||||
"Channel 2 should be unique.";
|
||||
|
||||
unsigned short rtpPort1 = 12000;
|
||||
unsigned short rtpPort2 = 13000;
|
||||
EXPECT_EQ(0, ViE.network->SetLocalReceiver(
|
||||
videoChannel1, rtpPort1));
|
||||
EXPECT_EQ(0, ViE.network->SetSendDestination(
|
||||
videoChannel1, "127.0.0.1", rtpPort1));
|
||||
EXPECT_EQ(0, ViE.network->SetLocalReceiver(
|
||||
videoChannel2, rtpPort2));
|
||||
EXPECT_EQ(0, ViE.network->SetSendDestination(
|
||||
videoChannel2, "127.0.0.1", rtpPort2));
|
||||
|
||||
tbCapture.ConnectTo(videoChannel1);
|
||||
tbCapture.ConnectTo(videoChannel2);
|
||||
|
||||
EXPECT_EQ(0, ViE.rtp_rtcp->SetKeyFrameRequestMethod(
|
||||
videoChannel1, webrtc::kViEKeyFrameRequestPliRtcp));
|
||||
EXPECT_EQ(0, ViE.rtp_rtcp->SetKeyFrameRequestMethod(
|
||||
videoChannel2, webrtc::kViEKeyFrameRequestPliRtcp));
|
||||
EXPECT_EQ(0, ViE.render->AddRenderer(
|
||||
videoChannel1, _window1, 0, 0.0, 0.0, 1.0, 1.0));
|
||||
EXPECT_EQ(0, ViE.render->StartRender(videoChannel1));
|
||||
|
||||
ViEAutotestCodecObserver codecObserver1;
|
||||
EXPECT_EQ(0, ViE.codec->RegisterEncoderObserver(
|
||||
videoChannel1, codecObserver1));
|
||||
EXPECT_EQ(0, ViE.codec->RegisterDecoderObserver(
|
||||
videoChannel1, codecObserver1));
|
||||
EXPECT_EQ(0, ViE.render->AddRenderer(
|
||||
videoChannel2, _window2, 0, 0.0, 0.0, 1.0, 1.0));
|
||||
EXPECT_EQ(0, ViE.render->StartRender(videoChannel2));
|
||||
|
||||
// Set Send codec
|
||||
unsigned short codecWidth = 176;
|
||||
unsigned short codecHeight = 144;
|
||||
unsigned short codecWidth = 320;
|
||||
unsigned short codecHeight = 240;
|
||||
bool codecSet = false;
|
||||
webrtc::VideoCodec videoCodec;
|
||||
webrtc::VideoCodec sendCodec1;
|
||||
webrtc::VideoCodec sendCodec2;
|
||||
for (int idx = 0; idx < ViE.codec->NumberOfCodecs(); idx++)
|
||||
{
|
||||
EXPECT_EQ(0, ViE.codec->GetCodec(idx, videoCodec));
|
||||
EXPECT_EQ(0, ViE.codec->SetReceiveCodec(videoChannel1, videoCodec));
|
||||
if (videoCodec.codecType == webrtc::kVideoCodecVP8)
|
||||
{
|
||||
videoCodec.width = codecWidth;
|
||||
videoCodec.height = codecHeight;
|
||||
videoCodec.startBitrate = 200;
|
||||
videoCodec.maxBitrate = 300;
|
||||
EXPECT_EQ(0, ViE.codec->SetSendCodec(
|
||||
videoChannel1, videoCodec));
|
||||
memcpy(&sendCodec1, &videoCodec, sizeof(videoCodec));
|
||||
sendCodec1.width = codecWidth;
|
||||
sendCodec1.height = codecHeight;
|
||||
EXPECT_EQ(0, ViE.codec->SetSendCodec(videoChannel1,
|
||||
sendCodec1));
|
||||
memcpy(&sendCodec2, &videoCodec, sizeof(videoCodec));
|
||||
sendCodec2.width = 2 * codecWidth;
|
||||
sendCodec2.height = 2 * codecHeight;
|
||||
EXPECT_EQ(0, ViE.codec->SetSendCodec(videoChannel2,
|
||||
sendCodec2));
|
||||
codecSet = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(codecSet);
|
||||
webrtc::VideoCodec send_codec;
|
||||
memcpy(&send_codec, &videoCodec, sizeof(videoCodec));
|
||||
|
||||
EXPECT_EQ(0, ViE.base->StartSend(videoChannel1));
|
||||
|
||||
// We need to verify using render effect filter since we won't trigger
|
||||
// a decode reset in loopback (due to using the same SSRC).
|
||||
RenderFilter filter1;
|
||||
RenderFilter filter2;
|
||||
EXPECT_EQ(0,
|
||||
ViE.image_process->RegisterRenderEffectFilter(videoChannel1,
|
||||
filter1));
|
||||
EXPECT_EQ(0,
|
||||
ViE.image_process->RegisterRenderEffectFilter(videoChannel2,
|
||||
filter2));
|
||||
|
||||
EXPECT_EQ(0, ViE.base->StartReceive(videoChannel1));
|
||||
|
||||
// Create channel 2, based on channel 1
|
||||
int videoChannel2 = -1;
|
||||
EXPECT_EQ(0, ViE.base->CreateChannel(videoChannel2, videoChannel1));
|
||||
EXPECT_NE(videoChannel1, videoChannel2) <<
|
||||
"Channel 2 should be seop";
|
||||
|
||||
EXPECT_EQ(0, ViE.rtp_rtcp->SetKeyFrameRequestMethod(
|
||||
videoChannel2, webrtc::kViEKeyFrameRequestPliRtcp));
|
||||
|
||||
// Prepare receive codecs
|
||||
for (int idx = 0; idx < ViE.codec->NumberOfCodecs(); idx++)
|
||||
{
|
||||
EXPECT_EQ(0, ViE.codec->GetCodec(idx, videoCodec));
|
||||
EXPECT_EQ(0, ViE.codec->SetReceiveCodec(videoChannel2, videoCodec));
|
||||
}
|
||||
|
||||
ViEAutotestCodecObserver codecObserver2;
|
||||
EXPECT_EQ(0, ViE.codec->RegisterDecoderObserver(
|
||||
videoChannel2, codecObserver2));
|
||||
EXPECT_EQ(0, ViE.render->AddRenderer(
|
||||
videoChannel2, _window2, 0, 0.0, 0.0, 1.0, 1.0));
|
||||
EXPECT_EQ(0, ViE.render->StartRender(videoChannel2));
|
||||
|
||||
unsigned short rtpPort2 = 13000;
|
||||
EXPECT_EQ(0, ViE.network->SetLocalReceiver(videoChannel2, rtpPort2));
|
||||
EXPECT_EQ(0, ViE.network->SetSendDestination(
|
||||
videoChannel2, "127.0.0.1", rtpPort2));
|
||||
|
||||
EXPECT_EQ(0, ViE.base->StartSend(videoChannel1));
|
||||
EXPECT_EQ(0, ViE.base->StartReceive(videoChannel2));
|
||||
EXPECT_EQ(-1, ViE.base->StartSend(videoChannel2));
|
||||
EXPECT_EQ(0, ViE.base->StartSend(videoChannel2));
|
||||
|
||||
|
||||
AutoTestSleep(KAutoTestSleepTimeMs);
|
||||
|
||||
EXPECT_EQ(0, ViE.base->StopReceive(videoChannel1));
|
||||
EXPECT_EQ(0, ViE.base->StopSend(videoChannel1));
|
||||
EXPECT_EQ(0, ViE.base->StopReceive(videoChannel2));
|
||||
EXPECT_EQ(0, ViE.base->StopSend(videoChannel2));
|
||||
|
||||
EXPECT_EQ(0, ViE.image_process->DeregisterRenderEffectFilter(
|
||||
videoChannel1));
|
||||
EXPECT_EQ(0, ViE.image_process->DeregisterRenderEffectFilter(
|
||||
videoChannel2));
|
||||
EXPECT_EQ(sendCodec1.width, filter1.last_render_width_);
|
||||
EXPECT_EQ(sendCodec1.height, filter1.last_render_height_);
|
||||
EXPECT_EQ(sendCodec2.width, filter2.last_render_width_);
|
||||
EXPECT_EQ(sendCodec2.height, filter2.last_render_height_);
|
||||
|
||||
EXPECT_EQ(0, ViE.base->DeleteChannel(videoChannel1));
|
||||
EXPECT_EQ(0, ViE.base->DeleteChannel(videoChannel2));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,6 @@ void ViEAutoTest::ViERtpRtcpStandardTest()
|
||||
// ***************************************************************
|
||||
// Engine ready. Begin testing class
|
||||
// ***************************************************************
|
||||
|
||||
unsigned short startSequenceNumber = 12345;
|
||||
ViETest::Log("Set start sequence number: %u", startSequenceNumber);
|
||||
EXPECT_EQ(0, ViE.rtp_rtcp->SetStartSequenceNumber(
|
||||
@ -279,13 +278,14 @@ void ViEAutoTest::ViERtpRtcpStandardTest()
|
||||
// __FUNCTION__, __LINE__);
|
||||
|
||||
EXPECT_EQ(0, ViE.base->StopReceive(tbChannel.videoChannel));
|
||||
EXPECT_EQ(0, ViE.base->StopSend(tbChannel.videoChannel));
|
||||
EXPECT_EQ(0, ViE.rtp_rtcp->SetNACKStatus(tbChannel.videoChannel, false));
|
||||
|
||||
|
||||
//
|
||||
// Keepalive
|
||||
//
|
||||
ViETest::Log("Testing RTP keep alive...\n");
|
||||
EXPECT_EQ(0, ViE.base->StopSend(tbChannel.videoChannel));
|
||||
EXPECT_EQ(0, ViE.base->StartReceive(tbChannel.videoChannel));
|
||||
|
||||
myTransport.SetPacketLoss(0);
|
||||
@ -375,6 +375,94 @@ void ViEAutoTest::ViERtpRtcpStandardTest()
|
||||
// Deregister external transport
|
||||
EXPECT_EQ(0, ViE.network->DeregisterSendTransport(tbChannel.videoChannel));
|
||||
|
||||
{
|
||||
// Create three channels. 1 and 2 are grouped together and will get a
|
||||
// common REMB packet. 3 is in its own group and will get a separate REMB
|
||||
// packet. To verify we receive a REMB, set a higher start bitrate for 2
|
||||
// than 1 and verify the estimated send bitrate for 2 is lowered. Also,
|
||||
// verify that the bitrate estimate for 3 is kept high and not lowered
|
||||
// due to 1 and 2.
|
||||
const unsigned int start_rate_1_bps = 100000;
|
||||
const unsigned int start_rate_2_bps = 300000;
|
||||
const unsigned int start_rate_3_bps = 1000000;
|
||||
|
||||
int channel_1 = -1;
|
||||
int channel_2 = -1;
|
||||
int channel_3 = -1;
|
||||
EXPECT_EQ(0, ViE.base->CreateChannel(channel_1));
|
||||
EXPECT_EQ(0, ViE.base->CreateChannel(channel_2, channel_1));
|
||||
EXPECT_EQ(0, ViE.base->CreateChannel(channel_3));
|
||||
|
||||
//TbCaptureDevice tbCapture(ViE);
|
||||
tbCapture.ConnectTo(channel_1);
|
||||
tbCapture.ConnectTo(channel_2);
|
||||
tbCapture.ConnectTo(channel_3);
|
||||
|
||||
TbExternalTransport transport_1(*(ViE.network));
|
||||
TbExternalTransport transport_2(*(ViE.network));
|
||||
TbExternalTransport transport_3(*(ViE.network));
|
||||
|
||||
EXPECT_EQ(0, ViE.network->RegisterSendTransport(channel_1, transport_1));
|
||||
EXPECT_EQ(0, ViE.network->RegisterSendTransport(channel_2, transport_2));
|
||||
EXPECT_EQ(0, ViE.network->RegisterSendTransport(channel_3, transport_3));
|
||||
|
||||
webrtc::VideoCodec video_codec;
|
||||
for (int idx = 0; idx < ViE.codec->NumberOfCodecs(); ++idx) {
|
||||
ViE.codec->GetCodec(idx, video_codec);
|
||||
if (video_codec.codecType == webrtc::kVideoCodecVP8) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(0, ViE.codec->SetReceiveCodec(channel_1, video_codec));
|
||||
EXPECT_EQ(0, ViE.codec->SetReceiveCodec(channel_2, video_codec));
|
||||
EXPECT_EQ(0, ViE.codec->SetReceiveCodec(channel_3, video_codec));
|
||||
|
||||
video_codec.startBitrate = start_rate_1_bps / 1000;
|
||||
EXPECT_EQ(0, ViE.codec->SetSendCodec(channel_1, video_codec));
|
||||
video_codec.startBitrate = start_rate_2_bps / 1000;
|
||||
EXPECT_EQ(0, ViE.codec->SetSendCodec(channel_2, video_codec));
|
||||
video_codec.startBitrate = start_rate_3_bps / 1000;
|
||||
EXPECT_EQ(0, ViE.codec->SetSendCodec(channel_3, video_codec));
|
||||
|
||||
EXPECT_EQ(0, ViE.rtp_rtcp->SetRembStatus(channel_1, true, true));
|
||||
EXPECT_EQ(0, ViE.rtp_rtcp->SetRembStatus(channel_2, true, true));
|
||||
EXPECT_EQ(0, ViE.rtp_rtcp->SetRembStatus(channel_3, true, true));
|
||||
|
||||
EXPECT_EQ(0, ViE.base->StartReceive(channel_1));
|
||||
EXPECT_EQ(0, ViE.base->StartReceive(channel_2));
|
||||
EXPECT_EQ(0, ViE.base->StartReceive(channel_3));
|
||||
EXPECT_EQ(0, ViE.base->StartSend(channel_1));
|
||||
EXPECT_EQ(0, ViE.base->StartSend(channel_2));
|
||||
EXPECT_EQ(0, ViE.base->StartSend(channel_3));
|
||||
|
||||
AutoTestSleep(KAutoTestSleepTimeMs);
|
||||
|
||||
EXPECT_EQ(0, ViE.base->StopReceive(channel_1));
|
||||
EXPECT_EQ(0, ViE.base->StopReceive(channel_2));
|
||||
EXPECT_EQ(0, ViE.base->StopReceive(channel_3));
|
||||
EXPECT_EQ(0, ViE.base->StopSend(channel_1));
|
||||
EXPECT_EQ(0, ViE.base->StopSend(channel_2));
|
||||
EXPECT_EQ(0, ViE.base->StopSend(channel_3));
|
||||
|
||||
unsigned int bw_estimate_1 = 0;
|
||||
unsigned int bw_estimate_2 = 0;
|
||||
unsigned int bw_estimate_3 = 0;
|
||||
ViE.rtp_rtcp->GetEstimatedSendBandwidth(channel_1, &bw_estimate_1);
|
||||
ViE.rtp_rtcp->GetEstimatedSendBandwidth(channel_2, &bw_estimate_2);
|
||||
ViE.rtp_rtcp->GetEstimatedSendBandwidth(channel_3, &bw_estimate_3);
|
||||
|
||||
EXPECT_LT(bw_estimate_1, start_rate_2_bps);
|
||||
EXPECT_LT(bw_estimate_2, start_rate_2_bps);
|
||||
EXPECT_NE(bw_estimate_1, start_rate_1_bps);
|
||||
|
||||
// Add some margin to avoid flaky test runs.
|
||||
EXPECT_GT(bw_estimate_3, 0.75 * start_rate_3_bps);
|
||||
|
||||
EXPECT_EQ(0, ViE.base->DeleteChannel(channel_1));
|
||||
EXPECT_EQ(0, ViE.base->DeleteChannel(channel_2));
|
||||
EXPECT_EQ(0, ViE.base->DeleteChannel(channel_3));
|
||||
}
|
||||
|
||||
//***************************************************************
|
||||
// Testing finished. Tear down Video Engine
|
||||
//***************************************************************
|
||||
|
@ -78,6 +78,7 @@
|
||||
'vie_shared_data.h',
|
||||
'vie_capturer.h',
|
||||
'vie_channel.h',
|
||||
'vie_channel_group.h',
|
||||
'vie_channel_manager.h',
|
||||
'vie_encoder.h',
|
||||
'vie_file_image.h',
|
||||
@ -109,6 +110,7 @@
|
||||
'vie_shared_data.cc',
|
||||
'vie_capturer.cc',
|
||||
'vie_channel.cc',
|
||||
'vie_channel_group.cc',
|
||||
'vie_channel_manager.cc',
|
||||
'vie_encoder.cc',
|
||||
'vie_file_image.cc',
|
||||
|
@ -124,34 +124,12 @@ int ViEBaseImpl::CreateChannel(int& video_channel) {
|
||||
}
|
||||
|
||||
int ViEBaseImpl::CreateChannel(int& video_channel, int original_channel) {
|
||||
if (!(shared_data_.Initialized())) {
|
||||
shared_data_.SetLastError(kViENotInitialized);
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
|
||||
"%s - ViE instance %d not initialized", __FUNCTION__,
|
||||
shared_data_.instance_id());
|
||||
return -1;
|
||||
}
|
||||
return CreateChannel(video_channel, original_channel, true);
|
||||
}
|
||||
|
||||
ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
|
||||
if (!cs.Channel(original_channel)) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
|
||||
"%s - original_channel does not exist.", __FUNCTION__,
|
||||
shared_data_.instance_id());
|
||||
shared_data_.SetLastError(kViEBaseInvalidChannelId);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (shared_data_.channel_manager()->CreateChannel(video_channel,
|
||||
original_channel) == -1) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
|
||||
"%s: Could not create channel", __FUNCTION__);
|
||||
video_channel = -1;
|
||||
shared_data_.SetLastError(kViEBaseChannelCreationFailed);
|
||||
return -1;
|
||||
}
|
||||
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(shared_data_.instance_id()),
|
||||
"%s: channel created: %d", __FUNCTION__, video_channel);
|
||||
return 0;
|
||||
int ViEBaseImpl::CreateReceiveChannel(int& video_channel,
|
||||
int original_channel) {
|
||||
return CreateChannel(video_channel, original_channel, false);
|
||||
}
|
||||
|
||||
int ViEBaseImpl::DeleteChannel(const int video_channel) {
|
||||
@ -270,27 +248,13 @@ int ViEBaseImpl::StartSend(const int video_channel) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Verify no other channel using the same encoder is sending.
|
||||
ChannelList channels;
|
||||
cs.ChannelsUsingViEEncoder(video_channel, &channels);
|
||||
for (ChannelList::iterator it = channels.begin(); it != channels.end();
|
||||
++it) {
|
||||
if ((*it)->Sending()) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo,
|
||||
ViEId(shared_data_.instance_id(), video_channel),
|
||||
"A channel using this encoder is already synding");
|
||||
shared_data_.SetLastError(kViEBaseAlreadySending);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ViEEncoder* vie_encoder = cs.Encoder(video_channel);
|
||||
if (!vie_encoder) {
|
||||
assert(false);
|
||||
assert(vie_encoder != NULL);
|
||||
if (vie_encoder->Owner() != video_channel) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo,
|
||||
ViEId(shared_data_.instance_id(), video_channel),
|
||||
"%s: Could not find encoder for channel %d", __FUNCTION__,
|
||||
video_channel);
|
||||
"Can't start ssend on a receive only channel.");
|
||||
shared_data_.SetLastError(kViEBaseReceiveOnlyChannel);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -491,4 +455,37 @@ WebRtc_Word32 ViEBaseImpl::AddExternalTransportBuild(char* str) const {
|
||||
#endif
|
||||
}
|
||||
|
||||
int ViEBaseImpl::CreateChannel(int& video_channel, int original_channel,
|
||||
bool sender) {
|
||||
if (!(shared_data_.Initialized())) {
|
||||
shared_data_.SetLastError(kViENotInitialized);
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
|
||||
"%s - ViE instance %d not initialized", __FUNCTION__,
|
||||
shared_data_.instance_id());
|
||||
return -1;
|
||||
}
|
||||
|
||||
ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
|
||||
if (!cs.Channel(original_channel)) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
|
||||
"%s - original_channel does not exist.", __FUNCTION__,
|
||||
shared_data_.instance_id());
|
||||
shared_data_.SetLastError(kViEBaseInvalidChannelId);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (shared_data_.channel_manager()->CreateChannel(video_channel,
|
||||
original_channel,
|
||||
sender) == -1) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_.instance_id()),
|
||||
"%s: Could not create channel", __FUNCTION__);
|
||||
video_channel = -1;
|
||||
shared_data_.SetLastError(kViEBaseChannelCreationFailed);
|
||||
return -1;
|
||||
}
|
||||
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(shared_data_.instance_id()),
|
||||
"%s: channel created: %d", __FUNCTION__, video_channel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
@ -27,52 +27,23 @@ class ViEBaseImpl
|
||||
public:
|
||||
virtual int Release();
|
||||
|
||||
// Initializes VideoEngine and must be called before any other API is called.
|
||||
// Implements ViEBase.
|
||||
virtual int Init();
|
||||
|
||||
// Connects ViE to a VoE instance. Pass in NULL to forget about a previously
|
||||
// set voice engine and release all resources we allocated from it.
|
||||
virtual int SetVoiceEngine(VoiceEngine* voice_engine);
|
||||
|
||||
// Creates a new ViE channel.
|
||||
virtual int CreateChannel(int& video_channel);
|
||||
|
||||
// Creates a new ViE channel that will use the same capture device and encoder
|
||||
// as |original_channel|.
|
||||
virtual int CreateChannel(int& video_channel, int original_channel);
|
||||
|
||||
// Deletes a ViE channel.
|
||||
virtual int CreateReceiveChannel(int& video_channel, int original_channel);
|
||||
virtual int DeleteChannel(const int video_channel);
|
||||
|
||||
// Connects a ViE channel with a VoE channel.
|
||||
virtual int ConnectAudioChannel(const int video_channel,
|
||||
const int audio_channel);
|
||||
|
||||
// Disconnects a video/voice channel pair.
|
||||
virtual int DisconnectAudioChannel(const int video_channel);
|
||||
|
||||
// Starts sending on video_channel and also starts the encoder.
|
||||
virtual int StartSend(const int video_channel);
|
||||
|
||||
// Stops sending on the specified channel.
|
||||
virtual int StopSend(const int video_channel);
|
||||
|
||||
// Starts receiving on the channel and also start decoding.
|
||||
virtual int StartReceive(const int video_channel);
|
||||
|
||||
// Stops receiving on the specified channel.
|
||||
virtual int StopReceive(const int video_channel);
|
||||
|
||||
// Registers a customer implemented observer.
|
||||
virtual int RegisterObserver(ViEBaseObserver& observer);
|
||||
|
||||
// Deregisters the observer.
|
||||
virtual int DeregisterObserver();
|
||||
|
||||
// Prints version information into |version|.
|
||||
virtual int GetVersion(char version[1024]);
|
||||
|
||||
// Returns the error code for the last registered error.
|
||||
virtual int LastError();
|
||||
|
||||
protected:
|
||||
@ -87,6 +58,8 @@ class ViEBaseImpl
|
||||
WebRtc_Word32 AddBuildInfo(char* str) const;
|
||||
WebRtc_Word32 AddExternalTransportBuild(char* str) const;
|
||||
|
||||
int CreateChannel(int& video_channel, int original_channel, bool sender);
|
||||
|
||||
// ViEBaseImpl owns ViESharedData used by all interface implementations.
|
||||
ViESharedData shared_data_;
|
||||
};
|
||||
|
@ -219,6 +219,13 @@ int ViECaptureImpl::ConnectCaptureDevice(const int capture_id,
|
||||
shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId);
|
||||
return -1;
|
||||
}
|
||||
if (vie_encoder->Owner() != video_channel) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo,
|
||||
ViEId(shared_data_->instance_id(), video_channel),
|
||||
"Can't connect capture device to a receive only channel.");
|
||||
shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId);
|
||||
return -1;
|
||||
}
|
||||
// Check if the encoder already has a connected frame provider
|
||||
if (is.FrameProvider(vie_encoder) != NULL) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo,
|
||||
|
79
src/video_engine/vie_channel_group.cc
Normal file
79
src/video_engine/vie_channel_group.cc
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "video_engine/vie_channel_group.h"
|
||||
|
||||
#include "modules/rtp_rtcp/interface/rtp_rtcp.h"
|
||||
#include "video_engine/vie_channel.h"
|
||||
#include "video_engine/vie_encoder.h"
|
||||
#include "video_engine/vie_remb.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
ChannelGroup::ChannelGroup(ProcessThread* process_thread)
|
||||
: remb_(new VieRemb(process_thread)) {}
|
||||
|
||||
ChannelGroup::~ChannelGroup() {
|
||||
assert(channels_.empty());
|
||||
assert(!remb_->InUse());
|
||||
}
|
||||
void ChannelGroup::AddChannel(int channel_id) {
|
||||
channels_.insert(channel_id);
|
||||
}
|
||||
|
||||
void ChannelGroup::RemoveChannel(int channel_id) {
|
||||
channels_.erase(channel_id);
|
||||
}
|
||||
|
||||
bool ChannelGroup::HasChannel(int channel_id) {
|
||||
return channels_.find(channel_id) != channels_.end();
|
||||
}
|
||||
|
||||
bool ChannelGroup::Empty() {
|
||||
return channels_.empty();
|
||||
}
|
||||
|
||||
bool ChannelGroup::SetChannelRembStatus(int channel_id,
|
||||
bool sender,
|
||||
bool receiver,
|
||||
ViEChannel* channel,
|
||||
ViEEncoder* encoder) {
|
||||
// Update the channel state.
|
||||
if (sender || receiver) {
|
||||
if (!channel->EnableRemb(true)) {
|
||||
return false;
|
||||
}
|
||||
} else if (channel) {
|
||||
channel->EnableRemb(false);
|
||||
}
|
||||
|
||||
// Update the remb instance with necesary RTp modules.
|
||||
RtpRtcp* rtp_module = channel->rtp_rtcp();
|
||||
if (sender) {
|
||||
remb_->AddRembSender(rtp_module);
|
||||
remb_->AddSendChannel(encoder->SendRtpRtcpModule());
|
||||
} else {
|
||||
remb_->RemoveRembSender(rtp_module);
|
||||
remb_->RemoveSendChannel(encoder->SendRtpRtcpModule());
|
||||
}
|
||||
if (receiver) {
|
||||
remb_->AddReceiveChannel(rtp_module);
|
||||
} else {
|
||||
remb_->RemoveReceiveChannel(rtp_module);
|
||||
}
|
||||
if (sender || receiver) {
|
||||
rtp_module->SetRemoteBitrateObserver(remb_.get());
|
||||
} else {
|
||||
rtp_module->SetRemoteBitrateObserver(NULL);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
52
src/video_engine/vie_channel_group.h
Normal file
52
src/video_engine/vie_channel_group.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_VIDEO_ENGINE_VIE_CHANNEL_GROUP_H_
|
||||
#define WEBRTC_VIDEO_ENGINE_VIE_CHANNEL_GROUP_H_
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "system_wrappers/interface/scoped_ptr.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ProcessThread;
|
||||
class ViEChannel;
|
||||
class ViEEncoder;
|
||||
class VieRemb;
|
||||
|
||||
// Channel group contains data common for several channels. All channels in the
|
||||
// group are assumed to send/receive data to the same end-point.
|
||||
class ChannelGroup {
|
||||
public:
|
||||
explicit ChannelGroup(ProcessThread* process_thread);
|
||||
~ChannelGroup();
|
||||
|
||||
void AddChannel(int channel_id);
|
||||
void RemoveChannel(int channel_id);
|
||||
bool HasChannel(int channel_id);
|
||||
bool Empty();
|
||||
|
||||
bool SetChannelRembStatus(int channel_id,
|
||||
bool sender,
|
||||
bool receiver,
|
||||
ViEChannel* channel,
|
||||
ViEEncoder* encoder);
|
||||
|
||||
private:
|
||||
typedef std::set<int> ChannelSet;
|
||||
|
||||
scoped_ptr<VieRemb> remb_;
|
||||
ChannelSet channels_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_VIDEO_ENGINE_VIE_CHANNEL_GROUP_H_
|
@ -35,7 +35,6 @@ ViEChannelManager::ViEChannelManager(
|
||||
free_channel_ids_(new bool[kViEMaxNumberOfChannels]),
|
||||
free_channel_ids_size_(kViEMaxNumberOfChannels),
|
||||
voice_sync_interface_(NULL),
|
||||
remb_(new VieRemb(engine_id)),
|
||||
voice_engine_(NULL),
|
||||
module_process_thread_(NULL) {
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceVideo, ViEId(engine_id),
|
||||
@ -50,7 +49,6 @@ ViEChannelManager::~ViEChannelManager() {
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceVideo, ViEId(engine_id_),
|
||||
"ViEChannelManager Destructor, engine_id: %d", engine_id_);
|
||||
|
||||
module_process_thread_->DeRegisterModule(remb_.get());
|
||||
while (channel_map_.size() > 0) {
|
||||
ChannelMap::iterator it = channel_map_.begin();
|
||||
// DeleteChannel will erase this channel from the map and invalidate |it|.
|
||||
@ -69,131 +67,83 @@ ViEChannelManager::~ViEChannelManager() {
|
||||
free_channel_ids_ = NULL;
|
||||
free_channel_ids_size_ = 0;
|
||||
}
|
||||
assert(channel_groups_.empty());
|
||||
assert(channel_map_.empty());
|
||||
assert(vie_encoder_map_.empty());
|
||||
}
|
||||
|
||||
void ViEChannelManager::SetModuleProcessThread(
|
||||
ProcessThread& module_process_thread) {
|
||||
assert(!module_process_thread_);
|
||||
module_process_thread_ = &module_process_thread;
|
||||
module_process_thread_->RegisterModule(remb_.get());
|
||||
}
|
||||
|
||||
int ViEChannelManager::CreateChannel(int& channel_id) {
|
||||
CriticalSectionScoped cs(*channel_id_critsect_);
|
||||
|
||||
// Get a free id for the new channel.
|
||||
if (!GetFreeChannelId(channel_id)) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_),
|
||||
"Max number of channels reached: %d", channel_map_.size());
|
||||
// Get a new channel id.
|
||||
int new_channel_id = FreeChannelId();
|
||||
if (new_channel_id == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ViEChannel* vie_channel = new ViEChannel(channel_id, engine_id_,
|
||||
// Create a new channel group and add this channel.
|
||||
ChannelGroup* group = new ChannelGroup(module_process_thread_);
|
||||
ViEEncoder* vie_encoder = new ViEEncoder(engine_id_, new_channel_id,
|
||||
number_of_cores_,
|
||||
*module_process_thread_);
|
||||
if (!vie_channel) {
|
||||
ReturnChannelId(channel_id);
|
||||
return -1;
|
||||
}
|
||||
if (vie_channel->Init() != 0) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_),
|
||||
"%s could not init channel", __FUNCTION__, channel_id);
|
||||
ReturnChannelId(channel_id);
|
||||
delete vie_channel;
|
||||
vie_channel = NULL;
|
||||
return -1;
|
||||
if (!CreateChannelObject(new_channel_id, vie_encoder)) {
|
||||
delete vie_encoder;
|
||||
vie_encoder = NULL;
|
||||
ReturnChannelId(new_channel_id);
|
||||
delete group;
|
||||
}
|
||||
|
||||
// There is no ViEEncoder for this channel, create one with default settings.
|
||||
ViEEncoder* vie_encoder = new ViEEncoder(engine_id_, channel_id,
|
||||
number_of_cores_,
|
||||
*module_process_thread_);
|
||||
if (!vie_encoder) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_),
|
||||
"%s(video_channel_id: %d) - Could not create a new encoder",
|
||||
__FUNCTION__, channel_id);
|
||||
delete vie_channel;
|
||||
return -1;
|
||||
}
|
||||
|
||||
vie_encoder_map_[channel_id] = vie_encoder;
|
||||
channel_map_[channel_id] = vie_channel;
|
||||
|
||||
// Register the channel at the encoder.
|
||||
RtpRtcp* send_rtp_rtcp_module = vie_encoder->SendRtpRtcpModule();
|
||||
if (vie_channel->RegisterSendRtpRtcpModule(*send_rtp_rtcp_module) != 0) {
|
||||
assert(false);
|
||||
vie_encoder_map_.erase(channel_id);
|
||||
channel_map_.erase(channel_id);
|
||||
ReturnChannelId(channel_id);
|
||||
delete vie_channel;
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id),
|
||||
"%s: Could not register rtp module %d", __FUNCTION__,
|
||||
channel_id);
|
||||
return -1;
|
||||
}
|
||||
channel_id = new_channel_id;
|
||||
group->AddChannel(channel_id);
|
||||
channel_groups_.push_back(group);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ViEChannelManager::CreateChannel(int& channel_id, int original_channel) {
|
||||
int ViEChannelManager::CreateChannel(int& channel_id,
|
||||
int original_channel,
|
||||
bool sender) {
|
||||
CriticalSectionScoped cs(*channel_id_critsect_);
|
||||
|
||||
// Check that original_channel already exists.
|
||||
ViEEncoder* vie_encoder = ViEEncoderPtr(original_channel);
|
||||
ChannelGroup* channel_group = FindGroup(original_channel);
|
||||
if (!channel_group) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int new_channel_id = FreeChannelId();
|
||||
if (new_channel_id == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ViEEncoder* vie_encoder = NULL;
|
||||
if (sender) {
|
||||
// We need to create a new ViEEncoder.
|
||||
vie_encoder = new ViEEncoder(engine_id_, new_channel_id, number_of_cores_,
|
||||
*module_process_thread_);
|
||||
if (!CreateChannelObject(new_channel_id, vie_encoder)) {
|
||||
delete vie_encoder;
|
||||
vie_encoder = NULL;
|
||||
}
|
||||
} else {
|
||||
vie_encoder = ViEEncoderPtr(original_channel);
|
||||
assert(vie_encoder);
|
||||
if (!CreateChannelObject(new_channel_id, vie_encoder)) {
|
||||
vie_encoder = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vie_encoder) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_),
|
||||
"%s: Original channel doesn't exist", __FUNCTION__,
|
||||
original_channel);
|
||||
ReturnChannelId(new_channel_id);
|
||||
return -1;
|
||||
}
|
||||
VideoCodec video_codec;
|
||||
vie_encoder->GetEncoder(video_codec);
|
||||
|
||||
// Get a free id for the new channel.
|
||||
if (GetFreeChannelId(channel_id) == false) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_),
|
||||
"Max number of channels reached: %d", channel_map_.size());
|
||||
return -1;
|
||||
}
|
||||
ViEChannel* vie_channel = new ViEChannel(channel_id, engine_id_,
|
||||
number_of_cores_,
|
||||
*module_process_thread_);
|
||||
if (!vie_channel) {
|
||||
ReturnChannelId(channel_id);
|
||||
return -1;
|
||||
}
|
||||
if (vie_channel->Init() != 0) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_),
|
||||
"%s could not init channel", __FUNCTION__, channel_id);
|
||||
ReturnChannelId(channel_id);
|
||||
delete vie_channel;
|
||||
vie_channel = NULL;
|
||||
return -1;
|
||||
}
|
||||
vie_encoder_map_[channel_id] = vie_encoder;
|
||||
|
||||
// Set the same encoder settings for the channel as used by the master
|
||||
// channel. Do this before attaching rtp module to ensure all rtp children has
|
||||
// the same codec type.
|
||||
VideoCodec encoder;
|
||||
if (vie_encoder->GetEncoder(encoder) == 0) {
|
||||
vie_channel->SetSendCodec(encoder);
|
||||
}
|
||||
channel_map_[channel_id] = vie_channel;
|
||||
|
||||
// Register the channel at the encoder.
|
||||
RtpRtcp* send_rtp_rtcp_module = vie_encoder->SendRtpRtcpModule();
|
||||
if (vie_channel->RegisterSendRtpRtcpModule(*send_rtp_rtcp_module) != 0) {
|
||||
assert(false);
|
||||
vie_encoder_map_.erase(channel_id);
|
||||
channel_map_.erase(channel_id);
|
||||
ReturnChannelId(channel_id);
|
||||
delete vie_channel;
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id),
|
||||
"%s: Could not register rtp module %d", __FUNCTION__,
|
||||
channel_id);
|
||||
return -1;
|
||||
}
|
||||
channel_id = new_channel_id;
|
||||
channel_group->AddChannel(channel_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -204,8 +154,9 @@ int ViEChannelManager::DeleteChannel(int channel_id) {
|
||||
// Write lock to make sure no one is using the channel.
|
||||
ViEManagerWriteScoped wl(*this);
|
||||
|
||||
// Protect the map.
|
||||
// Protect the maps.
|
||||
CriticalSectionScoped cs(*channel_id_critsect_);
|
||||
|
||||
ChannelMap::iterator c_it = channel_map_.find(channel_id);
|
||||
if (c_it == channel_map_.end()) {
|
||||
// No such channel.
|
||||
@ -216,11 +167,6 @@ int ViEChannelManager::DeleteChannel(int channel_id) {
|
||||
vie_channel = c_it->second;
|
||||
channel_map_.erase(c_it);
|
||||
|
||||
// Deregister possible remb modules.
|
||||
RtpRtcp* rtp_module = vie_channel->rtp_rtcp();
|
||||
remb_->RemoveRembSender(rtp_module);
|
||||
remb_->RemoveReceiveChannel(rtp_module);
|
||||
|
||||
// Deregister the channel from the ViEEncoder to stop the media flow.
|
||||
vie_channel->DeregisterSendRtpRtcpModule();
|
||||
ReturnChannelId(channel_id);
|
||||
@ -230,7 +176,14 @@ int ViEChannelManager::DeleteChannel(int channel_id) {
|
||||
assert(e_it != vie_encoder_map_.end());
|
||||
vie_encoder = e_it->second;
|
||||
|
||||
remb_->RemoveSendChannel(vie_encoder->SendRtpRtcpModule());
|
||||
ChannelGroup* group = FindGroup(channel_id);
|
||||
group->SetChannelRembStatus(channel_id, false, false, vie_channel,
|
||||
vie_encoder);
|
||||
group->RemoveChannel(channel_id);
|
||||
if (group->Empty()) {
|
||||
channel_groups_.remove(group);
|
||||
delete group;
|
||||
}
|
||||
|
||||
// Check if other channels are using the same encoder.
|
||||
if (ChannelUsingViEEncoder(channel_id)) {
|
||||
@ -327,38 +280,49 @@ VoiceEngine* ViEChannelManager::GetVoiceEngine() {
|
||||
bool ViEChannelManager::SetRembStatus(int channel_id, bool sender,
|
||||
bool receiver) {
|
||||
CriticalSectionScoped cs(*channel_id_critsect_);
|
||||
ChannelGroup* group = FindGroup(channel_id);
|
||||
if (!group) {
|
||||
return -1;
|
||||
}
|
||||
ViEChannel* channel = ViEChannelPtr(channel_id);
|
||||
if (!channel) {
|
||||
assert(channel);
|
||||
ViEEncoder* encoder = ViEEncoderPtr(channel_id);
|
||||
assert(encoder);
|
||||
|
||||
return group->SetChannelRembStatus(channel_id, sender, receiver, channel,
|
||||
encoder);
|
||||
}
|
||||
|
||||
bool ViEChannelManager::CreateChannelObject(int channel_id,
|
||||
ViEEncoder* vie_encoder) {
|
||||
ViEChannel* vie_channel = new ViEChannel(channel_id, engine_id_,
|
||||
number_of_cores_,
|
||||
*module_process_thread_);
|
||||
if (vie_channel->Init() != 0) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_),
|
||||
"%s could not init channel", __FUNCTION__, channel_id);
|
||||
delete vie_channel;
|
||||
return false;
|
||||
}
|
||||
|
||||
ViEEncoder* encoder = ViEEncoderPtr(channel_id);
|
||||
VideoCodec encoder;
|
||||
vie_encoder->GetEncoder(encoder);
|
||||
if (vie_channel->SetSendCodec(encoder) != 0) {
|
||||
vie_encoder = NULL;
|
||||
}
|
||||
|
||||
if (sender || receiver) {
|
||||
if (!channel->EnableRemb(true)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
channel->EnableRemb(false);
|
||||
}
|
||||
RtpRtcp* rtp_module = channel->rtp_rtcp();
|
||||
if (sender) {
|
||||
remb_->AddRembSender(rtp_module);
|
||||
remb_->AddSendChannel(encoder->SendRtpRtcpModule());
|
||||
} else {
|
||||
remb_->RemoveRembSender(rtp_module);
|
||||
remb_->RemoveSendChannel(encoder->SendRtpRtcpModule());
|
||||
}
|
||||
if (receiver) {
|
||||
remb_->AddReceiveChannel(rtp_module);
|
||||
} else {
|
||||
remb_->RemoveReceiveChannel(rtp_module);
|
||||
}
|
||||
if (sender || receiver) {
|
||||
rtp_module->SetRemoteBitrateObserver(remb_.get());
|
||||
} else {
|
||||
rtp_module->SetRemoteBitrateObserver(NULL);
|
||||
// Register the channel at the encoder.
|
||||
RtpRtcp* send_rtp_rtcp_module = vie_encoder->SendRtpRtcpModule();
|
||||
if (vie_channel->RegisterSendRtpRtcpModule(*send_rtp_rtcp_module) != 0) {
|
||||
delete vie_channel;
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id),
|
||||
"%s: Could not register RTP module", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store the channel, add it to the channel group and save the vie_encoder.
|
||||
channel_map_[channel_id] = vie_channel;
|
||||
vie_encoder_map_[channel_id] = vie_encoder;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -395,21 +359,19 @@ ViEEncoder* ViEChannelManager::ViEEncoderPtr(int video_channel_id) const {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
bool ViEChannelManager::GetFreeChannelId(int& free_channel_id) {
|
||||
CriticalSectionScoped cs(*channel_id_critsect_);
|
||||
int ViEChannelManager::FreeChannelId() {
|
||||
int idx = 0;
|
||||
while (idx < free_channel_ids_size_) {
|
||||
if (free_channel_ids_[idx] == true) {
|
||||
// We've found a free id, allocate it and return.
|
||||
free_channel_ids_[idx] = false;
|
||||
free_channel_id = idx + kViEChannelIdBase;
|
||||
return true;
|
||||
return idx + kViEChannelIdBase;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
// No free channel id.
|
||||
free_channel_id = -1;
|
||||
return false;
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_),
|
||||
"Max number of channels reached: %d", channel_map_.size());
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ViEChannelManager::ReturnChannelId(int channel_id) {
|
||||
@ -419,10 +381,20 @@ void ViEChannelManager::ReturnChannelId(int channel_id) {
|
||||
free_channel_ids_[channel_id - kViEChannelIdBase] = true;
|
||||
}
|
||||
|
||||
ChannelGroup* ViEChannelManager::FindGroup(int channel_id) {
|
||||
for (ChannelGroups::iterator it = channel_groups_.begin();
|
||||
it != channel_groups_.end(); ++it) {
|
||||
if ((*it)->HasChannel(channel_id)) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ViEChannelManager::ChannelUsingViEEncoder(int channel_id) const {
|
||||
CriticalSectionScoped cs(*channel_id_critsect_);
|
||||
EncoderMap::const_iterator orig_it = vie_encoder_map_.find(channel_id);
|
||||
if(orig_it == vie_encoder_map_.end()) {
|
||||
if (orig_it == vie_encoder_map_.end()) {
|
||||
// No ViEEncoder for this channel.
|
||||
return false;
|
||||
}
|
||||
|
@ -17,8 +17,10 @@
|
||||
#include "engine_configurations.h"
|
||||
#include "system_wrappers/interface/scoped_ptr.h"
|
||||
#include "typedefs.h"
|
||||
#include "video_engine/vie_channel_group.h"
|
||||
#include "video_engine/vie_defines.h"
|
||||
#include "video_engine/vie_manager_base.h"
|
||||
#include "video_engine/vie_remb.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -28,10 +30,10 @@ class ProcessThread;
|
||||
class ViEChannel;
|
||||
class ViEEncoder;
|
||||
class ViEPerformanceMonitor;
|
||||
class VieRemb;
|
||||
class VoEVideoSync;
|
||||
class VoiceEngine;
|
||||
|
||||
typedef std::list<ChannelGroup*> ChannelGroups;
|
||||
typedef std::list<ViEChannel*> ChannelList;
|
||||
typedef std::map<int, ViEChannel*> ChannelMap;
|
||||
typedef std::map<int, ViEEncoder*> EncoderMap;
|
||||
@ -49,8 +51,10 @@ class ViEChannelManager: private ViEManagerBase {
|
||||
// Creates a new channel. 'channelId' will be the id of the created channel.
|
||||
int CreateChannel(int& channel_id);
|
||||
|
||||
// Creates a channel and attaches to an already existing ViEEncoder.
|
||||
int CreateChannel(int& channel_id, int original_channel);
|
||||
// Creates a new channel grouped with |original_channel|. The new channel
|
||||
// will get its own |ViEEncoder| if |sender| is set to true. It will be a
|
||||
// receive only channel, without an own |ViEEncoder| if |sender| is false.
|
||||
int CreateChannel(int& channel_id, int original_channel, bool sender);
|
||||
|
||||
// Deletes a channel.
|
||||
int DeleteChannel(int channel_id);
|
||||
@ -70,6 +74,10 @@ class ViEChannelManager: private ViEManagerBase {
|
||||
bool SetRembStatus(int channel_id, bool sender, bool receiver);
|
||||
|
||||
private:
|
||||
// Creates a channel object connected to |vie_encoder|. Assumed to be called
|
||||
// protected.
|
||||
bool CreateChannelObject(int channel_id, ViEEncoder* vie_encoder);
|
||||
|
||||
// Used by ViEChannelScoped, forcing a manager user to use scoped.
|
||||
// Returns a pointer to the channel with id 'channelId'.
|
||||
ViEChannel* ViEChannelPtr(int channel_id) const;
|
||||
@ -81,13 +89,15 @@ class ViEChannelManager: private ViEManagerBase {
|
||||
// Gets the ViEEncoder used as input for video_channel_id
|
||||
ViEEncoder* ViEEncoderPtr(int video_channel_id) const;
|
||||
|
||||
// Returns true if we found a new channel id, free_channel_id, false
|
||||
// otherwise.
|
||||
bool GetFreeChannelId(int& free_channel_id);
|
||||
// Returns a free channel id, -1 if failing.
|
||||
int FreeChannelId();
|
||||
|
||||
// Returns a previously allocated channel id.
|
||||
void ReturnChannelId(int channel_id);
|
||||
|
||||
// Returns the iterator to the ChannelGroup containing |channel_id|.
|
||||
ChannelGroup* FindGroup(int channel_id);
|
||||
|
||||
// Returns true if at least one other channels uses the same ViEEncoder as
|
||||
// channel_id.
|
||||
bool ChannelUsingViEEncoder(int channel_id) const;
|
||||
@ -98,14 +108,20 @@ class ViEChannelManager: private ViEManagerBase {
|
||||
int engine_id_;
|
||||
int number_of_cores_;
|
||||
ViEPerformanceMonitor& vie_performance_monitor_;
|
||||
|
||||
// TODO(mflodman) Make part of channel group.
|
||||
ChannelMap channel_map_;
|
||||
bool* free_channel_ids_;
|
||||
int free_channel_ids_size_;
|
||||
|
||||
// List with all channel groups.
|
||||
std::list<ChannelGroup*> channel_groups_;
|
||||
|
||||
// TODO(mflodman) Make part of channel group.
|
||||
// Maps Channel id -> ViEEncoder.
|
||||
EncoderMap vie_encoder_map_;
|
||||
VoEVideoSync* voice_sync_interface_;
|
||||
scoped_ptr<VieRemb> remb_;
|
||||
|
||||
VoiceEngine* voice_engine_;
|
||||
ProcessThread* module_process_thread_;
|
||||
};
|
||||
|
@ -144,6 +144,16 @@ int ViECodecImpl::SetSendCodec(const int video_channel,
|
||||
return -1;
|
||||
}
|
||||
|
||||
ViEEncoder* vie_encoder = cs.Encoder(video_channel);
|
||||
assert(vie_encoder);
|
||||
if (vie_encoder->Owner() != video_channel) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideo,
|
||||
ViEId(shared_data_->instance_id(), video_channel),
|
||||
"%s: Receive only channel %d", __FUNCTION__, video_channel);
|
||||
shared_data_->SetLastError(kViECodecReceiveOnlyChannel);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set a max_bitrate if the user hasn't set one.
|
||||
VideoCodec video_codec_internal;
|
||||
memcpy(&video_codec_internal, &video_codec, sizeof(VideoCodec));
|
||||
@ -163,28 +173,9 @@ int ViECodecImpl::SetSendCodec(const int video_channel,
|
||||
video_codec_internal.maxBitrate);
|
||||
}
|
||||
|
||||
ViEEncoder* vie_encoder = cs.Encoder(video_channel);
|
||||
if (!vie_encoder) {
|
||||
assert(false);
|
||||
WEBRTC_TRACE(kTraceInfo, kTraceVideo,
|
||||
ViEId(shared_data_->instance_id(), video_channel),
|
||||
"%s: No encoder found for channel %d", __FUNCTION__);
|
||||
shared_data_->SetLastError(kViECodecInvalidChannelId);
|
||||
return -1;
|
||||
}
|
||||
|
||||
VideoCodec encoder;
|
||||
vie_encoder->GetEncoder(encoder);
|
||||
if (encoder.codecType != video_codec_internal.codecType &&
|
||||
cs.ChannelUsingViEEncoder(video_channel)) {
|
||||
// We don't allow changing codec type when several channels share encoder.
|
||||
WEBRTC_TRACE(kTraceInfo, kTraceVideo,
|
||||
ViEId(shared_data_->instance_id(), video_channel),
|
||||
"%s: Settings differs from other channels using encoder",
|
||||
__FUNCTION__);
|
||||
shared_data_->SetLastError(kViECodecInUse);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Make sure to generate a new SSRC if the codec type and/or resolution has
|
||||
// changed. This won't have any effect if the user has set an SSRC.
|
||||
bool new_rtp_stream = false;
|
||||
@ -193,17 +184,6 @@ int ViECodecImpl::SetSendCodec(const int video_channel,
|
||||
encoder.height != video_codec_internal.height) {
|
||||
new_rtp_stream = true;
|
||||
}
|
||||
if (video_codec_internal.numberOfSimulcastStreams > 1) {
|
||||
if (cs.ChannelUsingViEEncoder(video_channel)) {
|
||||
// We don't allow simulcast channels to share encoder.
|
||||
WEBRTC_TRACE(kTraceInfo, kTraceVideo,
|
||||
ViEId(shared_data_->instance_id(), video_channel),
|
||||
"%s: Can't share simulcast encoder",
|
||||
__FUNCTION__);
|
||||
shared_data_->SetLastError(kViECodecInUse);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ViEInputManagerScoped is(*(shared_data_->input_manager()));
|
||||
ViEFrameProviderBase* frame_provider = NULL;
|
||||
|
@ -172,6 +172,10 @@ ViEEncoder::~ViEEncoder() {
|
||||
delete qm_callback_;
|
||||
}
|
||||
|
||||
int ViEEncoder::Owner() const {
|
||||
return channel_id_;
|
||||
}
|
||||
|
||||
void ViEEncoder::Pause() {
|
||||
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
|
||||
ViEId(engine_id_, channel_id_),
|
||||
|
@ -45,6 +45,9 @@ class ViEEncoder
|
||||
ProcessThread& module_process_thread);
|
||||
~ViEEncoder();
|
||||
|
||||
// Returns the id of the owning channel.
|
||||
int Owner() const;
|
||||
|
||||
// Drops incoming packets before they get to the encoder.
|
||||
void Pause();
|
||||
void Restart();
|
||||
@ -144,7 +147,7 @@ class ViEEncoder
|
||||
|
||||
private:
|
||||
WebRtc_Word32 engine_id_;
|
||||
WebRtc_Word32 channel_id_;
|
||||
const int channel_id_;
|
||||
const WebRtc_UWord32 number_of_cores_;
|
||||
|
||||
VideoCodingModule& vcm_;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <cassert>
|
||||
|
||||
#include "modules/rtp_rtcp/interface/rtp_rtcp.h"
|
||||
#include "modules/utility/interface/process_thread.h"
|
||||
#include "system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "system_wrappers/interface/tick_util.h"
|
||||
#include "system_wrappers/interface/trace.h"
|
||||
@ -25,19 +26,21 @@ const int kRembSendIntervallMs = 1000;
|
||||
// % threshold for if we should send a new REMB asap.
|
||||
const int kSendThresholdPercent = 97;
|
||||
|
||||
VieRemb::VieRemb(int engine_id)
|
||||
: engine_id_(engine_id),
|
||||
VieRemb::VieRemb(ProcessThread* process_thread)
|
||||
: process_thread_(process_thread),
|
||||
list_crit_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
last_remb_time_(TickTime::MillisecondTimestamp()),
|
||||
last_send_bitrate_(0) {
|
||||
process_thread->RegisterModule(this);
|
||||
}
|
||||
|
||||
VieRemb::~VieRemb() {
|
||||
process_thread_->DeRegisterModule(this);
|
||||
}
|
||||
|
||||
void VieRemb::AddReceiveChannel(RtpRtcp* rtp_rtcp) {
|
||||
assert(rtp_rtcp);
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, engine_id_,
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, -1,
|
||||
"VieRemb::AddReceiveChannel(%p)", rtp_rtcp);
|
||||
|
||||
CriticalSectionScoped cs(list_crit_.get());
|
||||
@ -45,7 +48,7 @@ void VieRemb::AddReceiveChannel(RtpRtcp* rtp_rtcp) {
|
||||
receive_modules_.end())
|
||||
return;
|
||||
|
||||
WEBRTC_TRACE(kTraceInfo, kTraceVideo, engine_id_, "AddRembChannel");
|
||||
WEBRTC_TRACE(kTraceInfo, kTraceVideo, -1, "AddRembChannel");
|
||||
// The module probably doesn't have a remote SSRC yet, so don't add it to the
|
||||
// map.
|
||||
receive_modules_.push_back(rtp_rtcp);
|
||||
@ -53,7 +56,7 @@ void VieRemb::AddReceiveChannel(RtpRtcp* rtp_rtcp) {
|
||||
|
||||
void VieRemb::RemoveReceiveChannel(RtpRtcp* rtp_rtcp) {
|
||||
assert(rtp_rtcp);
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, engine_id_,
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, -1,
|
||||
"VieRemb::RemoveReceiveChannel(%p)", rtp_rtcp);
|
||||
|
||||
CriticalSectionScoped cs(list_crit_.get());
|
||||
@ -70,7 +73,7 @@ void VieRemb::RemoveReceiveChannel(RtpRtcp* rtp_rtcp) {
|
||||
|
||||
void VieRemb::AddRembSender(RtpRtcp* rtp_rtcp) {
|
||||
assert(rtp_rtcp);
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, engine_id_,
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, -1,
|
||||
"VieRemb::AddRembSender(%p)", rtp_rtcp);
|
||||
|
||||
CriticalSectionScoped cs(list_crit_.get());
|
||||
@ -84,7 +87,7 @@ void VieRemb::AddRembSender(RtpRtcp* rtp_rtcp) {
|
||||
|
||||
void VieRemb::RemoveRembSender(RtpRtcp* rtp_rtcp) {
|
||||
assert(rtp_rtcp);
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, engine_id_,
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, -1,
|
||||
"VieRemb::RemoveRembSender(%p)", rtp_rtcp);
|
||||
|
||||
CriticalSectionScoped cs(list_crit_.get());
|
||||
@ -99,7 +102,7 @@ void VieRemb::RemoveRembSender(RtpRtcp* rtp_rtcp) {
|
||||
|
||||
void VieRemb::AddSendChannel(RtpRtcp* rtp_rtcp) {
|
||||
assert(rtp_rtcp);
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, engine_id_,
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, -1,
|
||||
"VieRemb::AddSendChannel(%p)", rtp_rtcp);
|
||||
|
||||
CriticalSectionScoped cs(list_crit_.get());
|
||||
@ -113,7 +116,7 @@ void VieRemb::AddSendChannel(RtpRtcp* rtp_rtcp) {
|
||||
|
||||
void VieRemb::RemoveSendChannel(RtpRtcp* rtp_rtcp) {
|
||||
assert(rtp_rtcp);
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, engine_id_,
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVideo, -1,
|
||||
"VieRemb::RemoveSendChannel(%p)", rtp_rtcp);
|
||||
|
||||
CriticalSectionScoped cs(list_crit_.get());
|
||||
@ -126,8 +129,16 @@ void VieRemb::RemoveSendChannel(RtpRtcp* rtp_rtcp) {
|
||||
}
|
||||
}
|
||||
|
||||
bool VieRemb::InUse() const {
|
||||
CriticalSectionScoped cs(list_crit_.get());
|
||||
if(receive_modules_.empty() && send_modules_.empty() && rtcp_sender_.empty())
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
void VieRemb::OnReceiveBitrateChanged(unsigned int ssrc, unsigned int bitrate) {
|
||||
WEBRTC_TRACE(kTraceStream, kTraceVideo, engine_id_,
|
||||
WEBRTC_TRACE(kTraceStream, kTraceVideo, -1,
|
||||
"VieRemb::UpdateBitrateEstimate(ssrc: %u, bitrate: %u)",
|
||||
ssrc, bitrate);
|
||||
CriticalSectionScoped cs(list_crit_.get());
|
||||
@ -147,7 +158,7 @@ void VieRemb::OnReceiveBitrateChanged(unsigned int ssrc, unsigned int bitrate) {
|
||||
}
|
||||
|
||||
void VieRemb::OnReceivedRemb(unsigned int bitrate) {
|
||||
WEBRTC_TRACE(kTraceStream, kTraceVideo, engine_id_,
|
||||
WEBRTC_TRACE(kTraceStream, kTraceVideo, -1,
|
||||
"VieRemb::OnReceivedRemb(bitrate: %u)", bitrate);
|
||||
// TODO(mflodman) Should be extended to allow different split of bitrate.
|
||||
// TODO(mflodman) Do we want to call |SetMaximumBitrateEstimate| from
|
||||
|
@ -28,11 +28,12 @@
|
||||
namespace webrtc {
|
||||
|
||||
class CriticalSectionWrapper;
|
||||
class ProcessThread;
|
||||
class RtpRtcp;
|
||||
|
||||
class VieRemb : public RtpRemoteBitrateObserver, public Module {
|
||||
public:
|
||||
explicit VieRemb(int engine_id);
|
||||
VieRemb(ProcessThread* process_thread);
|
||||
~VieRemb();
|
||||
|
||||
// Called to add a receive channel to include in the REMB packet.
|
||||
@ -54,6 +55,9 @@ class VieRemb : public RtpRemoteBitrateObserver, public Module {
|
||||
// Removes the specified channel from receiving REMB packet estimates.
|
||||
void RemoveSendChannel(RtpRtcp* rtp_rtcp);
|
||||
|
||||
// Returns true if the instance is in use, false otherwise.
|
||||
bool InUse() const;
|
||||
|
||||
// Called every time there is a new bitrate estimate for the received stream
|
||||
// with given SSRC. This call will trigger a new RTCP REMB packet if the
|
||||
// bitrate estimate has decreased or if no RTCP REMB packet has been sent for
|
||||
@ -74,7 +78,7 @@ class VieRemb : public RtpRemoteBitrateObserver, public Module {
|
||||
typedef std::list<RtpRtcp*> RtpModules;
|
||||
typedef std::map<unsigned int, unsigned int> SsrcBitrate;
|
||||
|
||||
int engine_id_;
|
||||
ProcessThread* process_thread_;
|
||||
scoped_ptr<CriticalSectionWrapper> list_crit_;
|
||||
|
||||
// The last time a REMB was sent.
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "modules/rtp_rtcp/interface/rtp_rtcp.h"
|
||||
#include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
|
||||
#include "modules/utility/interface/process_thread.h"
|
||||
#include "system_wrappers/interface/scoped_ptr.h"
|
||||
#include "video_engine/vie_remb.h"
|
||||
|
||||
@ -28,11 +29,25 @@ using ::testing::Return;
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// TODO(mflodman) Make a trigger function for this class to fake a clock and
|
||||
// remove sleeps in the test.
|
||||
class TestProcessThread : public ProcessThread {
|
||||
public:
|
||||
explicit TestProcessThread() {}
|
||||
~TestProcessThread() {}
|
||||
virtual WebRtc_Word32 Start() { return 0; }
|
||||
virtual WebRtc_Word32 Stop() { return 0; }
|
||||
virtual WebRtc_Word32 RegisterModule(const Module* module) { return 0; }
|
||||
virtual WebRtc_Word32 DeRegisterModule(const Module* module) { return 0; }
|
||||
};
|
||||
|
||||
class ViERembTest : public ::testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
vie_remb_.reset(new VieRemb(1234));
|
||||
process_thread_.reset(new TestProcessThread);
|
||||
vie_remb_.reset(new VieRemb(process_thread_.get()));
|
||||
}
|
||||
scoped_ptr<TestProcessThread> process_thread_;
|
||||
scoped_ptr<VieRemb> vie_remb_;
|
||||
|
||||
void TestSleep(unsigned int time_ms) {
|
||||
|
Loading…
Reference in New Issue
Block a user