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:
parent
16a87b97f9
commit
818c4984e4
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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.";
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user