| Index: webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc
|
| diff --git a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc
|
| index 32472750f5f0fc21df8512431ece44af806377d7..880f45fa7e4ca7f0ffa55ccd67251e3e5f986eec 100644
|
| --- a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc
|
| +++ b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc
|
| @@ -83,6 +83,17 @@
|
| return WEBRTC_VIDEO_CODEC_OK;
|
| }
|
|
|
| +struct ScreenshareTemporalLayersFactory : webrtc::TemporalLayersFactory {
|
| + ScreenshareTemporalLayersFactory() {}
|
| + virtual ~ScreenshareTemporalLayersFactory() {}
|
| +
|
| + virtual webrtc::TemporalLayers* Create(int num_temporal_layers,
|
| + uint8_t initial_tl0_pic_idx) const {
|
| + return new webrtc::ScreenshareLayers(num_temporal_layers, rand(),
|
| + webrtc::Clock::GetRealTimeClock());
|
| + }
|
| +};
|
| +
|
| // An EncodedImageCallback implementation that forwards on calls to a
|
| // SimulcastEncoderAdapter, but with the stream index it's registered with as
|
| // the first parameter to Encoded.
|
| @@ -105,25 +116,6 @@
|
| const size_t stream_idx_;
|
| };
|
|
|
| -// Utility class used to adapt the simulcast id as reported by the temporal
|
| -// layers factory, since each sub-encoder will report stream 0.
|
| -class TemporalLayersFactoryAdapter : public webrtc::TemporalLayersFactory {
|
| - public:
|
| - TemporalLayersFactoryAdapter(int adapted_simulcast_id,
|
| - const TemporalLayersFactory& tl_factory)
|
| - : adapted_simulcast_id_(adapted_simulcast_id), tl_factory_(tl_factory) {}
|
| - ~TemporalLayersFactoryAdapter() override {}
|
| - webrtc::TemporalLayers* Create(int simulcast_id,
|
| - int temporal_layers,
|
| - uint8_t initial_tl0_pic_idx) const override {
|
| - return tl_factory_.Create(adapted_simulcast_id_, temporal_layers,
|
| - initial_tl0_pic_idx);
|
| - }
|
| -
|
| - const int adapted_simulcast_id_;
|
| - const TemporalLayersFactory& tl_factory_;
|
| -};
|
| -
|
| } // namespace
|
|
|
| namespace webrtc {
|
| @@ -133,6 +125,7 @@
|
| encoded_complete_callback_(nullptr),
|
| implementation_name_("SimulcastEncoderAdapter") {
|
| memset(&codec_, 0, sizeof(webrtc::VideoCodec));
|
| + rate_allocator_.reset(new SimulcastRateAllocator(codec_));
|
| }
|
|
|
| SimulcastEncoderAdapter::~SimulcastEncoderAdapter() {
|
| @@ -180,13 +173,14 @@
|
| }
|
|
|
| codec_ = *inst;
|
| - SimulcastRateAllocator rate_allocator(codec_, nullptr);
|
| - BitrateAllocation allocation = rate_allocator.GetAllocation(
|
| - codec_.startBitrate * 1000, codec_.maxFramerate);
|
| - std::vector<uint32_t> start_bitrates;
|
| - for (int i = 0; i < kMaxSimulcastStreams; ++i) {
|
| - uint32_t stream_bitrate = allocation.GetSpatialLayerSum(i) / 1000;
|
| - start_bitrates.push_back(stream_bitrate);
|
| + rate_allocator_.reset(new SimulcastRateAllocator(codec_));
|
| + std::vector<uint32_t> start_bitrates =
|
| + rate_allocator_->GetAllocation(codec_.startBitrate);
|
| +
|
| + // Special mode when screensharing on a single stream.
|
| + if (number_of_streams == 1 && inst->mode == kScreensharing) {
|
| + screensharing_tl_factory_.reset(new ScreenshareTemporalLayersFactory());
|
| + codec_.VP8()->tl_factory = screensharing_tl_factory_.get();
|
| }
|
|
|
| std::string implementation_name;
|
| @@ -206,9 +200,6 @@
|
| PopulateStreamCodec(&codec_, i, start_bitrate_kbps,
|
| highest_resolution_stream, &stream_codec);
|
| }
|
| - TemporalLayersFactoryAdapter tl_factory_adapter(i,
|
| - *codec_.VP8()->tl_factory);
|
| - stream_codec.VP8()->tl_factory = &tl_factory_adapter;
|
|
|
| // TODO(ronghuawu): Remove once this is handled in VP8EncoderImpl.
|
| if (stream_codec.qpMax < kDefaultMinQp) {
|
| @@ -349,48 +340,61 @@
|
| return WEBRTC_VIDEO_CODEC_OK;
|
| }
|
|
|
| -int SimulcastEncoderAdapter::SetRateAllocation(const BitrateAllocation& bitrate,
|
| - uint32_t new_framerate) {
|
| - if (!Initialized())
|
| +int SimulcastEncoderAdapter::SetRates(uint32_t new_bitrate_kbit,
|
| + uint32_t new_framerate) {
|
| + if (!Initialized()) {
|
| return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
| -
|
| - if (new_framerate < 1)
|
| - return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
| -
|
| - if (codec_.maxBitrate > 0 && bitrate.get_sum_kbps() > codec_.maxBitrate)
|
| - return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
| -
|
| - if (bitrate.get_sum_bps() > 0) {
|
| + }
|
| + if (new_framerate < 1) {
|
| + return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
| + }
|
| + if (codec_.maxBitrate > 0 && new_bitrate_kbit > codec_.maxBitrate) {
|
| + new_bitrate_kbit = codec_.maxBitrate;
|
| + }
|
| +
|
| + std::vector<uint32_t> stream_bitrates;
|
| + if (new_bitrate_kbit > 0) {
|
| // Make sure the bitrate fits the configured min bitrates. 0 is a special
|
| // value that means paused, though, so leave it alone.
|
| - if (bitrate.get_sum_kbps() < codec_.minBitrate)
|
| - return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
| -
|
| + if (new_bitrate_kbit < codec_.minBitrate) {
|
| + new_bitrate_kbit = codec_.minBitrate;
|
| + }
|
| if (codec_.numberOfSimulcastStreams > 0 &&
|
| - bitrate.get_sum_kbps() < codec_.simulcastStream[0].minBitrate) {
|
| - return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
| - }
|
| - }
|
| -
|
| + new_bitrate_kbit < codec_.simulcastStream[0].minBitrate) {
|
| + new_bitrate_kbit = codec_.simulcastStream[0].minBitrate;
|
| + }
|
| + stream_bitrates = rate_allocator_->GetAllocation(new_bitrate_kbit);
|
| + }
|
| codec_.maxFramerate = new_framerate;
|
|
|
| + // Disable any stream not in the current allocation.
|
| + stream_bitrates.resize(streaminfos_.size(), 0U);
|
| +
|
| for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) {
|
| - uint32_t stream_bitrate_kbps =
|
| - bitrate.GetSpatialLayerSum(stream_idx) / 1000;
|
| -
|
| + uint32_t stream_bitrate_kbps = stream_bitrates[stream_idx];
|
| // Need a key frame if we have not sent this stream before.
|
| if (stream_bitrate_kbps > 0 && !streaminfos_[stream_idx].send_stream) {
|
| streaminfos_[stream_idx].key_frame_request = true;
|
| }
|
| streaminfos_[stream_idx].send_stream = stream_bitrate_kbps > 0;
|
|
|
| - // Slice the temporal layers out of the full allocation and pass it on to
|
| - // the encoder handling the current simulcast stream.
|
| - BitrateAllocation stream_allocation;
|
| - for (int i = 0; i < kMaxTemporalStreams; ++i)
|
| - stream_allocation.SetBitrate(0, i, bitrate.GetBitrate(stream_idx, i));
|
| - streaminfos_[stream_idx].encoder->SetRateAllocation(stream_allocation,
|
| - new_framerate);
|
| + // TODO(holmer): This is a temporary hack for screensharing, where we
|
| + // interpret the startBitrate as the encoder target bitrate. This is
|
| + // to allow for a different max bitrate, so if the codec can't meet
|
| + // the target we still allow it to overshoot up to the max before dropping
|
| + // frames. This hack should be improved.
|
| + if (codec_.targetBitrate > 0 &&
|
| + (codec_.VP8()->numberOfTemporalLayers == 2 ||
|
| + codec_.simulcastStream[0].numberOfTemporalLayers == 2)) {
|
| + stream_bitrate_kbps = std::min(codec_.maxBitrate, stream_bitrate_kbps);
|
| + // TODO(ronghuawu): Can't change max bitrate via the VideoEncoder
|
| + // interface. And VP8EncoderImpl doesn't take negative framerate.
|
| + // max_bitrate = std::min(codec_.maxBitrate, stream_bitrate_kbps);
|
| + // new_framerate = -1;
|
| + }
|
| +
|
| + streaminfos_[stream_idx].encoder->SetRates(stream_bitrate_kbps,
|
| + new_framerate);
|
| }
|
|
|
| return WEBRTC_VIDEO_CODEC_OK;
|
|
|