Modify the simulcast encoder factory adapter to allow external encoder factories that support more than one codec.

Only VP8 encoders will be wrapped in the simulcast adapter; other codec types will be created directly with the real encoder factory and cleaned up appropriately.

BUG=
R=pbos@webrtc.org, pthatcher@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#8623}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8623 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
pthatcher@webrtc.org 2015-03-06 02:20:58 +00:00
parent 16a87b97f9
commit 818c4984e4
4 changed files with 113 additions and 16 deletions

View File

@ -294,15 +294,29 @@ WebRtcSimulcastEncoderFactory::~WebRtcSimulcastEncoderFactory() {
bool WebRtcSimulcastEncoderFactory::UseSimulcastEncoderFactory( bool WebRtcSimulcastEncoderFactory::UseSimulcastEncoderFactory(
const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs) { const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs) {
return codecs.size() == 1 && codecs[0].type == webrtc::kVideoCodecVP8; // If any codec is VP8, use the simulcast factory. If asked to create a
// non-VP8 codec, we'll just return a contained factory encoder directly.
for (const auto& codec: codecs) {
if (codec.type == webrtc::kVideoCodecVP8) {
return true;
}
}
return false;
} }
webrtc::VideoEncoder* WebRtcSimulcastEncoderFactory::CreateVideoEncoder( webrtc::VideoEncoder* WebRtcSimulcastEncoderFactory::CreateVideoEncoder(
webrtc::VideoCodecType type) { webrtc::VideoCodecType type) {
ASSERT(type == webrtc::kVideoCodecVP8);
ASSERT(factory_ != NULL); ASSERT(factory_ != NULL);
// If it's a codec type we can simulcast, create a wrapped encoder.
if (type == webrtc::kVideoCodecVP8) {
return new webrtc::SimulcastEncoderAdapter( return new webrtc::SimulcastEncoderAdapter(
new EncoderFactoryAdapter(factory_)); new EncoderFactoryAdapter(factory_));
}
webrtc::VideoEncoder* encoder = factory_->CreateVideoEncoder(type);
if (encoder) {
non_simulcast_encoders_.push_back(encoder);
}
return encoder;
} }
const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& const std::vector<WebRtcVideoEncoderFactory::VideoCodec>&
@ -312,6 +326,17 @@ WebRtcSimulcastEncoderFactory::codecs() const {
void WebRtcSimulcastEncoderFactory::DestroyVideoEncoder( void WebRtcSimulcastEncoderFactory::DestroyVideoEncoder(
webrtc::VideoEncoder* encoder) { webrtc::VideoEncoder* encoder) {
// Check first to see if the encoder wasn't wrapped in a
// SimulcastEncoderAdapter. In that case, ask the factory to destroy it.
if (std::remove(non_simulcast_encoders_.begin(),
non_simulcast_encoders_.end(), encoder) !=
non_simulcast_encoders_.end()) {
factory_->DestroyVideoEncoder(encoder);
return;
}
// Otherwise, SimulcastEncoderAdapter can be deleted directly, and will call
// DestroyVideoEncoder on the factory for individual encoder instances.
delete encoder; delete encoder;
} }

View File

@ -515,8 +515,11 @@ class WebRtcVideoMediaChannel : public rtc::MessageHandler,
int ratio_h_; int ratio_h_;
}; };
// Wrap encoder factory to a simulcast encoder factory. Exposed here for code to // An encoder factory that wraps Create requests for simulcastable codec types
// be shared with WebRtcVideoEngine2, not to be used externally. // with a webrtc::SimulcastEncoderAdapter. Non simulcastable codec type
// requests are just passed through to the contained encoder factory.
// Exposed here for code to be shared with WebRtcVideoEngine2, not to be used
// externally.
class WebRtcSimulcastEncoderFactory class WebRtcSimulcastEncoderFactory
: public cricket::WebRtcVideoEncoderFactory { : public cricket::WebRtcVideoEncoderFactory {
public: public:
@ -535,6 +538,9 @@ class WebRtcSimulcastEncoderFactory
private: private:
cricket::WebRtcVideoEncoderFactory* factory_; cricket::WebRtcVideoEncoderFactory* factory_;
// A list of encoders that were created without being wrapped in a
// SimulcastEncoderAdapter.
std::vector<webrtc::VideoEncoder*> non_simulcast_encoders_;
}; };
} // namespace cricket } // namespace cricket

View File

@ -683,6 +683,9 @@ TEST_F(WebRtcVideoEngine2Test, UsesSimulcastAdapterForVp8Factories) {
} }
EXPECT_TRUE(channel->SetCapturer(ssrcs.front(), NULL)); EXPECT_TRUE(channel->SetCapturer(ssrcs.front(), NULL));
channel.reset();
ASSERT_EQ(0u, encoder_factory.encoders().size());
} }
TEST_F(WebRtcVideoEngine2Test, ChannelWithExternalH264CanChangeToInternalVp8) { TEST_F(WebRtcVideoEngine2Test, ChannelWithExternalH264CanChangeToInternalVp8) {
@ -717,6 +720,66 @@ TEST_F(WebRtcVideoEngine2Test,
EXPECT_TRUE( EXPECT_TRUE(
channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc))); channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
// Make sure DestroyVideoEncoder was called on the factory.
ASSERT_EQ(0u, encoder_factory.encoders().size());
}
TEST_F(WebRtcVideoEngine2Test,
UsesSimulcastAdapterForVp8WithCombinedVP8AndH264Factory) {
cricket::FakeWebRtcVideoEncoderFactory encoder_factory;
encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264");
std::vector<cricket::VideoCodec> codecs;
codecs.push_back(kVp8Codec);
rtc::scoped_ptr<VideoMediaChannel> channel(
SetUpForExternalEncoderFactory(&encoder_factory, codecs));
std::vector<uint32> ssrcs = MAKE_VECTOR(kSsrcs3);
EXPECT_TRUE(
channel->AddSendStream(CreateSimStreamParams("cname", ssrcs)));
EXPECT_TRUE(channel->SetSend(true));
// Send a fake frame, or else the media engine will configure the simulcast
// encoder adapter at a low-enough size that it'll only create a single
// encoder layer.
cricket::FakeVideoCapturer capturer;
EXPECT_TRUE(channel->SetCapturer(ssrcs.front(), &capturer));
EXPECT_EQ(cricket::CS_RUNNING,
capturer.Start(capturer.GetSupportedFormats()->front()));
EXPECT_TRUE(capturer.CaptureFrame());
ASSERT_GT(encoder_factory.encoders().size(), 1u);
EXPECT_EQ(webrtc::kVideoCodecVP8,
encoder_factory.encoders()[0]->GetCodecSettings().codecType);
channel.reset();
// Make sure DestroyVideoEncoder was called on the factory.
EXPECT_EQ(0u, encoder_factory.encoders().size());
}
TEST_F(WebRtcVideoEngine2Test,
DestroysNonSimulcastEncoderFromCombinedVP8AndH264Factory) {
cricket::FakeWebRtcVideoEncoderFactory encoder_factory;
encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264");
std::vector<cricket::VideoCodec> codecs;
codecs.push_back(kH264Codec);
rtc::scoped_ptr<VideoMediaChannel> channel(
SetUpForExternalEncoderFactory(&encoder_factory, codecs));
EXPECT_TRUE(
channel->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc)));
ASSERT_EQ(1u, encoder_factory.encoders().size());
EXPECT_EQ(webrtc::kVideoCodecH264,
encoder_factory.encoders()[0]->GetCodecSettings().codecType);
channel.reset();
// Make sure DestroyVideoEncoder was called on the factory.
ASSERT_EQ(0u, encoder_factory.encoders().size()); ASSERT_EQ(0u, encoder_factory.encoders().size());
} }
@ -2656,12 +2719,6 @@ TEST_F(WebRtcVideoEngine2SimulcastTest,
FAIL() << "Not implemented."; FAIL() << "Not implemented.";
} }
TEST_F(WebRtcVideoEngine2SimulcastTest,
DISABLED_DontUseSimulcastAdapterOnMultipleCodecsFactory) {
// TODO(pbos): Implement.
FAIL() << "Not implemented.";
}
TEST_F(WebRtcVideoChannel2SimulcastTest, DISABLED_SimulcastSend_1280x800) { TEST_F(WebRtcVideoChannel2SimulcastTest, DISABLED_SimulcastSend_1280x800) {
// TODO(pbos): Implement. // TODO(pbos): Implement.
FAIL() << "Not implemented."; FAIL() << "Not implemented.";

View File

@ -4253,7 +4253,16 @@ TEST_F(WebRtcVideoEngineSimulcastTestFake,
} }
TEST_F(WebRtcVideoEngineSimulcastTestFake, TEST_F(WebRtcVideoEngineSimulcastTestFake,
DontUseSimulcastAdapterOnNoneVp8Factory) { UsesSimulcastAdapterForVp8WithCombinedVP8AndH264Factory) {
encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric,
"H264");
TestSimulcastAdapter(kVP8Codec, true);
}
TEST_F(WebRtcVideoEngineSimulcastTestFake,
DontUseSimulcastAdapterForH264WithCombinedVP8AndH264Factory) {
encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric, encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric,
"H264"); "H264");
static const cricket::VideoCodec kH264Codec(100, "H264", 640, 400, 30, 0); static const cricket::VideoCodec kH264Codec(100, "H264", 640, 400, 30, 0);
@ -4261,11 +4270,11 @@ TEST_F(WebRtcVideoEngineSimulcastTestFake,
} }
TEST_F(WebRtcVideoEngineSimulcastTestFake, TEST_F(WebRtcVideoEngineSimulcastTestFake,
DontUseSimulcastAdapterOnMultipleCodecsFactory) { DontUseSimulcastAdapterOnNonVp8Factory) {
encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric, encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric,
"H264"); "H264");
TestSimulcastAdapter(kVP8Codec, false); static const cricket::VideoCodec kH264Codec(100, "H264", 640, 400, 30, 0);
TestSimulcastAdapter(kH264Codec, false);
} }
// Flaky on Windows and tsan. https://code.google.com/p/webrtc/issues/detail?id=4135 // Flaky on Windows and tsan. https://code.google.com/p/webrtc/issues/detail?id=4135