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..32472750f5f0fc21df8512431ece44af806377d7 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_.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) { |
@@ -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 |
- // 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; |