Implement SimulcastEncoderAdapter support.
R=stefan@webrtc.org BUG=1788 Review URL: https://webrtc-codereview.appspot.com/37589004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@8061 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
8315d7de85
commit
f18fba2f7b
@ -153,9 +153,16 @@ class FakeWebRtcVideoEncoder : public webrtc::VideoEncoder {
|
||||
virtual int32 InitEncode(const webrtc::VideoCodec* codecSettings,
|
||||
int32 numberOfCores,
|
||||
size_t maxPayloadSize) {
|
||||
rtc::CritScope lock(&crit_);
|
||||
codec_settings_ = *codecSettings;
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
}
|
||||
|
||||
webrtc::VideoCodec GetCodecSettings() {
|
||||
rtc::CritScope lock(&crit_);
|
||||
return codec_settings_;
|
||||
}
|
||||
|
||||
virtual int32 Encode(
|
||||
const webrtc::I420VideoFrame& inputImage,
|
||||
const webrtc::CodecSpecificInfo* codecSpecificInfo,
|
||||
@ -192,6 +199,7 @@ class FakeWebRtcVideoEncoder : public webrtc::VideoEncoder {
|
||||
private:
|
||||
rtc::CriticalSection crit_;
|
||||
int num_frames_encoded_ GUARDED_BY(crit_);
|
||||
webrtc::VideoCodec codec_settings_ GUARDED_BY(crit_);
|
||||
};
|
||||
|
||||
// Fake class for mocking out WebRtcVideoEncoderFactory.
|
||||
|
@ -138,36 +138,6 @@ class EncoderFactoryAdapter : public webrtc::VideoEncoderFactory {
|
||||
cricket::WebRtcVideoEncoderFactory* factory_;
|
||||
};
|
||||
|
||||
// Wrap encoder factory to a simulcast encoder factory.
|
||||
class SimulcastEncoderFactory : public cricket::WebRtcVideoEncoderFactory {
|
||||
public:
|
||||
// SimulcastEncoderFactory doesn't take ownership of |factory|, which is owned
|
||||
// by e.g. PeerConnectionFactory.
|
||||
explicit SimulcastEncoderFactory(cricket::WebRtcVideoEncoderFactory* factory)
|
||||
: factory_(factory) {}
|
||||
virtual ~SimulcastEncoderFactory() {}
|
||||
|
||||
virtual webrtc::VideoEncoder* CreateVideoEncoder(
|
||||
webrtc::VideoCodecType type) OVERRIDE {
|
||||
ASSERT(type == webrtc::kVideoCodecVP8);
|
||||
ASSERT(factory_ != NULL);
|
||||
return new webrtc::SimulcastEncoderAdapter(
|
||||
webrtc::scoped_ptr<webrtc::VideoEncoderFactory>(
|
||||
new EncoderFactoryAdapter(factory_)).Pass());
|
||||
}
|
||||
|
||||
virtual const std::vector<VideoCodec>& codecs() const OVERRIDE {
|
||||
return factory_->codecs();
|
||||
}
|
||||
|
||||
virtual void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) OVERRIDE {
|
||||
delete encoder;
|
||||
}
|
||||
|
||||
private:
|
||||
cricket::WebRtcVideoEncoderFactory* factory_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace cricket {
|
||||
@ -316,6 +286,37 @@ std::vector<VideoCodec> DefaultVideoCodecList() {
|
||||
return codecs;
|
||||
}
|
||||
|
||||
WebRtcSimulcastEncoderFactory::WebRtcSimulcastEncoderFactory(
|
||||
cricket::WebRtcVideoEncoderFactory* factory)
|
||||
: factory_(factory) {
|
||||
}
|
||||
|
||||
WebRtcSimulcastEncoderFactory::~WebRtcSimulcastEncoderFactory() {
|
||||
}
|
||||
|
||||
bool WebRtcSimulcastEncoderFactory::UseSimulcastEncoderFactory(
|
||||
const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs) {
|
||||
return codecs.size() == 1 && codecs[0].type == webrtc::kVideoCodecVP8;
|
||||
}
|
||||
|
||||
webrtc::VideoEncoder* WebRtcSimulcastEncoderFactory::CreateVideoEncoder(
|
||||
webrtc::VideoCodecType type) {
|
||||
ASSERT(type == webrtc::kVideoCodecVP8);
|
||||
ASSERT(factory_ != NULL);
|
||||
return new webrtc::SimulcastEncoderAdapter(
|
||||
new EncoderFactoryAdapter(factory_));
|
||||
}
|
||||
|
||||
const std::vector<WebRtcVideoEncoderFactory::VideoCodec>&
|
||||
WebRtcSimulcastEncoderFactory::codecs() const {
|
||||
return factory_->codecs();
|
||||
}
|
||||
|
||||
void WebRtcSimulcastEncoderFactory::DestroyVideoEncoder(
|
||||
webrtc::VideoEncoder* encoder) {
|
||||
delete encoder;
|
||||
}
|
||||
|
||||
struct FlushBlackFrameData : public rtc::MessageData {
|
||||
FlushBlackFrameData(uint32 s, int64 t, int i)
|
||||
: ssrc(s), timestamp(t), interval(i) {
|
||||
@ -1690,15 +1691,15 @@ void WebRtcVideoEngine::SetExternalEncoderFactory(
|
||||
return;
|
||||
|
||||
// No matter what happens we shouldn't hold on to a stale
|
||||
// SimulcastEncoderFactory.
|
||||
// WebRtcSimulcastEncoderFactory.
|
||||
simulcast_encoder_factory_.reset();
|
||||
|
||||
if (encoder_factory) {
|
||||
const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs =
|
||||
encoder_factory->codecs();
|
||||
if (codecs.size() == 1 && codecs[0].type == webrtc::kVideoCodecVP8) {
|
||||
if (WebRtcSimulcastEncoderFactory::UseSimulcastEncoderFactory(codecs)) {
|
||||
simulcast_encoder_factory_.reset(
|
||||
new SimulcastEncoderFactory(encoder_factory));
|
||||
new WebRtcSimulcastEncoderFactory(encoder_factory));
|
||||
encoder_factory = simulcast_encoder_factory_.get();
|
||||
}
|
||||
}
|
||||
|
@ -523,6 +523,28 @@ class WebRtcVideoMediaChannel : public rtc::MessageHandler,
|
||||
int ratio_h_;
|
||||
};
|
||||
|
||||
// Wrap encoder factory to a simulcast encoder factory. Exposed here for code to
|
||||
// be shared with WebRtcVideoEngine2, not to be used externally.
|
||||
class WebRtcSimulcastEncoderFactory
|
||||
: public cricket::WebRtcVideoEncoderFactory {
|
||||
public:
|
||||
// WebRtcSimulcastEncoderFactory doesn't take ownership of |factory|, which is
|
||||
// owned by e.g. PeerConnectionFactory.
|
||||
explicit WebRtcSimulcastEncoderFactory(
|
||||
cricket::WebRtcVideoEncoderFactory* factory);
|
||||
virtual ~WebRtcSimulcastEncoderFactory();
|
||||
|
||||
static bool UseSimulcastEncoderFactory(const std::vector<VideoCodec>& codecs);
|
||||
|
||||
virtual webrtc::VideoEncoder* CreateVideoEncoder(
|
||||
webrtc::VideoCodecType type) OVERRIDE;
|
||||
virtual const std::vector<VideoCodec>& codecs() const OVERRIDE;
|
||||
virtual void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) OVERRIDE;
|
||||
|
||||
private:
|
||||
cricket::WebRtcVideoEncoderFactory* factory_;
|
||||
};
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
#endif // TALK_MEDIA_WEBRTCVIDEOENGINE_H_
|
||||
|
@ -477,6 +477,20 @@ void WebRtcVideoEngine2::SetExternalDecoderFactory(
|
||||
void WebRtcVideoEngine2::SetExternalEncoderFactory(
|
||||
WebRtcVideoEncoderFactory* encoder_factory) {
|
||||
assert(!initialized_);
|
||||
if (external_encoder_factory_ == encoder_factory)
|
||||
return;
|
||||
|
||||
// No matter what happens we shouldn't hold on to a stale
|
||||
// WebRtcSimulcastEncoderFactory.
|
||||
simulcast_encoder_factory_.reset();
|
||||
|
||||
if (encoder_factory &&
|
||||
WebRtcSimulcastEncoderFactory::UseSimulcastEncoderFactory(
|
||||
encoder_factory->codecs())) {
|
||||
simulcast_encoder_factory_.reset(
|
||||
new WebRtcSimulcastEncoderFactory(encoder_factory));
|
||||
encoder_factory = simulcast_encoder_factory_.get();
|
||||
}
|
||||
external_encoder_factory_ = encoder_factory;
|
||||
|
||||
video_codecs_ = GetSupportedCodecs();
|
||||
|
@ -208,6 +208,7 @@ class WebRtcVideoEngine2 : public sigslot::has_slots<> {
|
||||
|
||||
WebRtcVideoDecoderFactory* external_decoder_factory_;
|
||||
WebRtcVideoEncoderFactory* external_encoder_factory_;
|
||||
rtc::scoped_ptr<WebRtcVideoEncoderFactory> simulcast_encoder_factory_;
|
||||
};
|
||||
|
||||
class WebRtcVideoChannel2 : public rtc::MessageHandler,
|
||||
|
@ -592,6 +592,35 @@ VideoMediaChannel* WebRtcVideoEngine2Test::SetUpForExternalDecoderFactory(
|
||||
return channel;
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoEngine2Test, UsesSimulcastAdapterForVp8Factories) {
|
||||
cricket::FakeWebRtcVideoEncoderFactory encoder_factory;
|
||||
encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
|
||||
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));
|
||||
|
||||
EXPECT_GT(encoder_factory.encoders().size(), 1u);
|
||||
|
||||
// Verify that encoders are configured for simulcast through adapter
|
||||
// (increasing resolution and only configured to send one stream each).
|
||||
int prev_width = -1;
|
||||
for (size_t i = 0; i < encoder_factory.encoders().size(); ++i) {
|
||||
webrtc::VideoCodec codec_settings =
|
||||
encoder_factory.encoders()[i]->GetCodecSettings();
|
||||
EXPECT_EQ(0, codec_settings.numberOfSimulcastStreams);
|
||||
EXPECT_GT(codec_settings.width, prev_width);
|
||||
prev_width = codec_settings.width;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoEngine2Test, ChannelWithExternalH264CanChangeToInternalVp8) {
|
||||
cricket::FakeWebRtcVideoEncoderFactory encoder_factory;
|
||||
encoder_factory.AddSupportedVideoCodecType(webrtc::kVideoCodecH264, "H264");
|
||||
|
@ -116,9 +116,8 @@ struct ScreenshareTemporalLayersFactory : webrtc::TemporalLayers::Factory {
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
SimulcastEncoderAdapter::SimulcastEncoderAdapter(
|
||||
scoped_ptr<VideoEncoderFactory> factory)
|
||||
: factory_(factory.Pass()), encoded_complete_callback_(NULL) {
|
||||
SimulcastEncoderAdapter::SimulcastEncoderAdapter(VideoEncoderFactory* factory)
|
||||
: factory_(factory), encoded_complete_callback_(NULL) {
|
||||
memset(&codec_, 0, sizeof(webrtc::VideoCodec));
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,7 @@ class VideoEncoderFactory {
|
||||
class SimulcastEncoderAdapter : public VP8Encoder,
|
||||
public EncodedImageCallback {
|
||||
public:
|
||||
explicit SimulcastEncoderAdapter(scoped_ptr<VideoEncoderFactory> factory);
|
||||
|
||||
explicit SimulcastEncoderAdapter(VideoEncoderFactory* factory);
|
||||
virtual ~SimulcastEncoderAdapter();
|
||||
|
||||
// Implements VideoEncoder
|
||||
|
@ -171,8 +171,7 @@ class TestSimulcastEncoderAdapterFakeHelper {
|
||||
// Can only be called once as the SimulcastEncoderAdapter will take the
|
||||
// ownership of |factory_|.
|
||||
VP8Encoder* CreateMockEncoderAdapter() {
|
||||
scoped_ptr<VideoEncoderFactory> scoped_factory(factory_);
|
||||
return new SimulcastEncoderAdapter(scoped_factory.Pass());
|
||||
return new SimulcastEncoderAdapter(factory_);
|
||||
}
|
||||
|
||||
void ExpectCallSetChannelParameters(uint32_t packetLoss, int64_t rtt) {
|
||||
|
@ -32,8 +32,7 @@ class VP8EncoderImplFactory : public VideoEncoderFactory {
|
||||
|
||||
VP8Encoder* VP8Encoder::Create() {
|
||||
if (VP8EncoderFactoryConfig::use_simulcast_adapter()) {
|
||||
scoped_ptr<VideoEncoderFactory> factory(new VP8EncoderImplFactory());
|
||||
return new SimulcastEncoderAdapter(factory.Pass());
|
||||
return new SimulcastEncoderAdapter(new VP8EncoderImplFactory());
|
||||
} else {
|
||||
return new VP8EncoderImpl();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user