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 a58bdac6cf78b04f225230dceb8bea3e0a81b60f..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_.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) { |
@@ -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; |