Chromium Code Reviews| 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 880f45fa7e4ca7f0ffa55ccd67251e3e5f986eec..a58bdac6cf78b04f225230dceb8bea3e0a81b60f 100644 |
| --- a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc |
| +++ b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc |
| @@ -83,17 +83,6 @@ int VerifyCodec(const webrtc::VideoCodec* inst) { |
| 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. |
| @@ -116,6 +105,25 @@ class AdapterEncodedImageCallback : public webrtc::EncodedImageCallback { |
| 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 { |
| @@ -125,7 +133,6 @@ SimulcastEncoderAdapter::SimulcastEncoderAdapter(VideoEncoderFactory* factory) |
| encoded_complete_callback_(nullptr), |
| implementation_name_("SimulcastEncoderAdapter") { |
| memset(&codec_, 0, sizeof(webrtc::VideoCodec)); |
| - rate_allocator_.reset(new SimulcastRateAllocator(codec_)); |
| } |
| SimulcastEncoderAdapter::~SimulcastEncoderAdapter() { |
| @@ -173,14 +180,13 @@ int SimulcastEncoderAdapter::InitEncode(const VideoCodec* inst, |
| } |
| codec_ = *inst; |
| - 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(); |
| + 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); |
| } |
| std::string implementation_name; |
| @@ -200,6 +206,9 @@ int SimulcastEncoderAdapter::InitEncode(const VideoCodec* inst, |
| PopulateStreamCodec(&codec_, i, start_bitrate_kbps, |
| highest_resolution_stream, &stream_codec); |
| } |
| + TemporalLayersFactoryAdapter tl_factory_adapter( |
| + i, *codec_.codecSpecific.VP8.tl_factory); |
| + stream_codec.codecSpecific.VP8.tl_factory = &tl_factory_adapter; |
| // TODO(ronghuawu): Remove once this is handled in VP8EncoderImpl. |
| if (stream_codec.qpMax < kDefaultMinQp) { |
| @@ -340,61 +349,48 @@ int SimulcastEncoderAdapter::SetChannelParameters(uint32_t packet_loss, |
| return WEBRTC_VIDEO_CODEC_OK; |
| } |
| -int SimulcastEncoderAdapter::SetRates(uint32_t new_bitrate_kbit, |
| - uint32_t new_framerate) { |
| - if (!Initialized()) { |
| +int SimulcastEncoderAdapter::SetRateAllocation(const BitrateAllocation& bitrate, |
| + uint32_t new_framerate) { |
| + if (!Initialized()) |
| return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
| - } |
| - if (new_framerate < 1) { |
| + |
| + 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 (codec_.maxBitrate > 0 && new_bitrate_kbit > codec_.maxBitrate) { |
| - new_bitrate_kbit = codec_.maxBitrate; |
| - } |
| - std::vector<uint32_t> stream_bitrates; |
| - if (new_bitrate_kbit > 0) { |
| + if (bitrate.get_sum_bps() > 0) { |
| // Make sure the bitrate fits the configured min bitrates. 0 is a special |
| // value that means paused, though, so leave it alone. |
| - if (new_bitrate_kbit < codec_.minBitrate) { |
| - new_bitrate_kbit = codec_.minBitrate; |
| - } |
| + if (bitrate.get_sum_kbps() < codec_.minBitrate) |
| + return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| + |
| if (codec_.numberOfSimulcastStreams > 0 && |
| - new_bitrate_kbit < codec_.simulcastStream[0].minBitrate) { |
| - new_bitrate_kbit = codec_.simulcastStream[0].minBitrate; |
| + bitrate.get_sum_kbps() < codec_.simulcastStream[0].minBitrate) { |
| + return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| } |
| - 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); |
| + codec_.maxFramerate = new_framerate; |
| for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) { |
| - uint32_t stream_bitrate_kbps = stream_bitrates[stream_idx]; |
| + uint32_t stream_bitrate_kbps = |
| + bitrate.GetSpatialLayerSum(stream_idx) / 1000; |
| + |
| // 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; |
| - // TODO(holmer): This is a temporary hack for screensharing, where we |
|
stefan-webrtc
2016/11/02 10:26:35
Is it safe to remove the hack? :)
sprang_webrtc
2016/11/02 13:28:33
It's not removed; it's only been moved into the Ra
|
| - // 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); |
| + // 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); |
| } |
| return WEBRTC_VIDEO_CODEC_OK; |