| 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
|
| deleted file mode 100644
|
| index dbf8b258ecdb84ce43a61654e7fbdbc62d1ab6cd..0000000000000000000000000000000000000000
|
| --- a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc
|
| +++ /dev/null
|
| @@ -1,536 +0,0 @@
|
| -/*
|
| - * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
| - *
|
| - * Use of this source code is governed by a BSD-style license
|
| - * that can be found in the LICENSE file in the root of the source
|
| - * tree. An additional intellectual property rights grant can be found
|
| - * in the file PATENTS. All contributing project authors may
|
| - * be found in the AUTHORS file in the root of the source tree.
|
| - */
|
| -
|
| -#include "webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h"
|
| -
|
| -#include <algorithm>
|
| -
|
| -// NOTE(ajm): Path provided by gyp.
|
| -#include "libyuv/scale.h" // NOLINT
|
| -
|
| -#include "webrtc/api/video/i420_buffer.h"
|
| -#include "webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h"
|
| -#include "webrtc/modules/video_coding/codecs/vp8/simulcast_rate_allocator.h"
|
| -#include "webrtc/rtc_base/checks.h"
|
| -#include "webrtc/system_wrappers/include/clock.h"
|
| -
|
| -namespace {
|
| -
|
| -const unsigned int kDefaultMinQp = 2;
|
| -const unsigned int kDefaultMaxQp = 56;
|
| -// Max qp for lowest spatial resolution when doing simulcast.
|
| -const unsigned int kLowestResMaxQp = 45;
|
| -
|
| -uint32_t SumStreamMaxBitrate(int streams, const webrtc::VideoCodec& codec) {
|
| - uint32_t bitrate_sum = 0;
|
| - for (int i = 0; i < streams; ++i) {
|
| - bitrate_sum += codec.simulcastStream[i].maxBitrate;
|
| - }
|
| - return bitrate_sum;
|
| -}
|
| -
|
| -int NumberOfStreams(const webrtc::VideoCodec& codec) {
|
| - int streams =
|
| - codec.numberOfSimulcastStreams < 1 ? 1 : codec.numberOfSimulcastStreams;
|
| - uint32_t simulcast_max_bitrate = SumStreamMaxBitrate(streams, codec);
|
| - if (simulcast_max_bitrate == 0) {
|
| - streams = 1;
|
| - }
|
| - return streams;
|
| -}
|
| -
|
| -bool ValidSimulcastResolutions(const webrtc::VideoCodec& codec,
|
| - int num_streams) {
|
| - if (codec.width != codec.simulcastStream[num_streams - 1].width ||
|
| - codec.height != codec.simulcastStream[num_streams - 1].height) {
|
| - return false;
|
| - }
|
| - for (int i = 0; i < num_streams; ++i) {
|
| - if (codec.width * codec.simulcastStream[i].height !=
|
| - codec.height * codec.simulcastStream[i].width) {
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -int VerifyCodec(const webrtc::VideoCodec* inst) {
|
| - if (inst == nullptr) {
|
| - return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
| - }
|
| - if (inst->maxFramerate < 1) {
|
| - return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
| - }
|
| - // allow zero to represent an unspecified maxBitRate
|
| - if (inst->maxBitrate > 0 && inst->startBitrate > inst->maxBitrate) {
|
| - return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
| - }
|
| - if (inst->width <= 1 || inst->height <= 1) {
|
| - return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
| - }
|
| - if (inst->VP8().automaticResizeOn && inst->numberOfSimulcastStreams > 1) {
|
| - return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
| - }
|
| - return WEBRTC_VIDEO_CODEC_OK;
|
| -}
|
| -
|
| -// 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.
|
| -class AdapterEncodedImageCallback : public webrtc::EncodedImageCallback {
|
| - public:
|
| - AdapterEncodedImageCallback(webrtc::SimulcastEncoderAdapter* adapter,
|
| - size_t stream_idx)
|
| - : adapter_(adapter), stream_idx_(stream_idx) {}
|
| -
|
| - EncodedImageCallback::Result OnEncodedImage(
|
| - const webrtc::EncodedImage& encoded_image,
|
| - const webrtc::CodecSpecificInfo* codec_specific_info,
|
| - const webrtc::RTPFragmentationHeader* fragmentation) override {
|
| - return adapter_->OnEncodedImage(stream_idx_, encoded_image,
|
| - codec_specific_info, fragmentation);
|
| - }
|
| -
|
| - private:
|
| - webrtc::SimulcastEncoderAdapter* const adapter_;
|
| - 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 {
|
| -
|
| -SimulcastEncoderAdapter::SimulcastEncoderAdapter(VideoEncoderFactory* factory)
|
| - : inited_(0),
|
| - factory_(factory),
|
| - encoded_complete_callback_(nullptr),
|
| - implementation_name_("SimulcastEncoderAdapter") {
|
| - // The adapter is typically created on the worker thread, but operated on
|
| - // the encoder task queue.
|
| - encoder_queue_.Detach();
|
| -
|
| - memset(&codec_, 0, sizeof(webrtc::VideoCodec));
|
| -}
|
| -
|
| -SimulcastEncoderAdapter::~SimulcastEncoderAdapter() {
|
| - RTC_DCHECK(!Initialized());
|
| - DestroyStoredEncoders();
|
| -}
|
| -
|
| -int SimulcastEncoderAdapter::Release() {
|
| - RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
|
| -
|
| - while (!streaminfos_.empty()) {
|
| - VideoEncoder* encoder = streaminfos_.back().encoder;
|
| - encoder->Release();
|
| - // Even though it seems very unlikely, there are no guarantees that the
|
| - // encoder will not call back after being Release()'d. Therefore, we disable
|
| - // the callbacks here.
|
| - encoder->RegisterEncodeCompleteCallback(nullptr);
|
| - streaminfos_.pop_back(); // Deletes callback adapter.
|
| - stored_encoders_.push(encoder);
|
| - }
|
| -
|
| - // It's legal to move the encoder to another queue now.
|
| - encoder_queue_.Detach();
|
| -
|
| - rtc::AtomicOps::ReleaseStore(&inited_, 0);
|
| -
|
| - return WEBRTC_VIDEO_CODEC_OK;
|
| -}
|
| -
|
| -int SimulcastEncoderAdapter::InitEncode(const VideoCodec* inst,
|
| - int number_of_cores,
|
| - size_t max_payload_size) {
|
| - RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
|
| -
|
| - if (number_of_cores < 1) {
|
| - return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
| - }
|
| -
|
| - int ret = VerifyCodec(inst);
|
| - if (ret < 0) {
|
| - return ret;
|
| - }
|
| -
|
| - ret = Release();
|
| - if (ret < 0) {
|
| - return ret;
|
| - }
|
| -
|
| - int number_of_streams = NumberOfStreams(*inst);
|
| - RTC_DCHECK_LE(number_of_streams, kMaxSimulcastStreams);
|
| - const bool doing_simulcast = (number_of_streams > 1);
|
| -
|
| - if (doing_simulcast && !ValidSimulcastResolutions(*inst, number_of_streams)) {
|
| - return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
| - }
|
| -
|
| - 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);
|
| - }
|
| -
|
| - std::string implementation_name;
|
| - // Create |number_of_streams| of encoder instances and init them.
|
| - for (int i = 0; i < number_of_streams; ++i) {
|
| - VideoCodec stream_codec;
|
| - uint32_t start_bitrate_kbps = start_bitrates[i];
|
| - if (!doing_simulcast) {
|
| - stream_codec = codec_;
|
| - stream_codec.numberOfSimulcastStreams = 1;
|
| - } else {
|
| - // Cap start bitrate to the min bitrate in order to avoid strange codec
|
| - // behavior. Since sending sending will be false, this should not matter.
|
| - start_bitrate_kbps =
|
| - std::max(codec_.simulcastStream[i].minBitrate, start_bitrate_kbps);
|
| - bool highest_resolution_stream = (i == (number_of_streams - 1));
|
| - 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) {
|
| - stream_codec.qpMax = kDefaultMaxQp;
|
| - }
|
| -
|
| - // If an existing encoder instance exists, reuse it.
|
| - // TODO(brandtr): Set initial RTP state (e.g., picture_id/tl0_pic_idx) here,
|
| - // when we start storing that state outside the encoder wrappers.
|
| - VideoEncoder* encoder;
|
| - if (!stored_encoders_.empty()) {
|
| - encoder = stored_encoders_.top();
|
| - stored_encoders_.pop();
|
| - } else {
|
| - encoder = factory_->Create();
|
| - }
|
| -
|
| - ret = encoder->InitEncode(&stream_codec, number_of_cores, max_payload_size);
|
| - if (ret < 0) {
|
| - // Explicitly destroy the current encoder; because we haven't registered a
|
| - // StreamInfo for it yet, Release won't do anything about it.
|
| - factory_->Destroy(encoder);
|
| - Release();
|
| - return ret;
|
| - }
|
| - std::unique_ptr<EncodedImageCallback> callback(
|
| - new AdapterEncodedImageCallback(this, i));
|
| - encoder->RegisterEncodeCompleteCallback(callback.get());
|
| - streaminfos_.emplace_back(encoder, std::move(callback), stream_codec.width,
|
| - stream_codec.height, start_bitrate_kbps > 0);
|
| -
|
| - if (i != 0) {
|
| - implementation_name += ", ";
|
| - }
|
| - implementation_name += streaminfos_[i].encoder->ImplementationName();
|
| - }
|
| -
|
| - if (doing_simulcast) {
|
| - implementation_name_ =
|
| - "SimulcastEncoderAdapter (" + implementation_name + ")";
|
| - } else {
|
| - implementation_name_ = implementation_name;
|
| - }
|
| -
|
| - // To save memory, don't store encoders that we don't use.
|
| - DestroyStoredEncoders();
|
| -
|
| - rtc::AtomicOps::ReleaseStore(&inited_, 1);
|
| -
|
| - return WEBRTC_VIDEO_CODEC_OK;
|
| -}
|
| -
|
| -int SimulcastEncoderAdapter::Encode(
|
| - const VideoFrame& input_image,
|
| - const CodecSpecificInfo* codec_specific_info,
|
| - const std::vector<FrameType>* frame_types) {
|
| - RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
|
| -
|
| - if (!Initialized()) {
|
| - return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
| - }
|
| - if (encoded_complete_callback_ == nullptr) {
|
| - return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
| - }
|
| -
|
| - // All active streams should generate a key frame if
|
| - // a key frame is requested by any stream.
|
| - bool send_key_frame = false;
|
| - if (frame_types) {
|
| - for (size_t i = 0; i < frame_types->size(); ++i) {
|
| - if (frame_types->at(i) == kVideoFrameKey) {
|
| - send_key_frame = true;
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) {
|
| - if (streaminfos_[stream_idx].key_frame_request &&
|
| - streaminfos_[stream_idx].send_stream) {
|
| - send_key_frame = true;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - int src_width = input_image.width();
|
| - int src_height = input_image.height();
|
| - for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) {
|
| - // Don't encode frames in resolutions that we don't intend to send.
|
| - if (!streaminfos_[stream_idx].send_stream) {
|
| - continue;
|
| - }
|
| -
|
| - std::vector<FrameType> stream_frame_types;
|
| - if (send_key_frame) {
|
| - stream_frame_types.push_back(kVideoFrameKey);
|
| - streaminfos_[stream_idx].key_frame_request = false;
|
| - } else {
|
| - stream_frame_types.push_back(kVideoFrameDelta);
|
| - }
|
| -
|
| - int dst_width = streaminfos_[stream_idx].width;
|
| - int dst_height = streaminfos_[stream_idx].height;
|
| - // If scaling isn't required, because the input resolution
|
| - // matches the destination or the input image is empty (e.g.
|
| - // a keyframe request for encoders with internal camera
|
| - // sources) or the source image has a native handle, pass the image on
|
| - // directly. Otherwise, we'll scale it to match what the encoder expects
|
| - // (below).
|
| - // For texture frames, the underlying encoder is expected to be able to
|
| - // correctly sample/scale the source texture.
|
| - // TODO(perkj): ensure that works going forward, and figure out how this
|
| - // affects webrtc:5683.
|
| - if ((dst_width == src_width && dst_height == src_height) ||
|
| - input_image.video_frame_buffer()->type() ==
|
| - VideoFrameBuffer::Type::kNative) {
|
| - int ret = streaminfos_[stream_idx].encoder->Encode(
|
| - input_image, codec_specific_info, &stream_frame_types);
|
| - if (ret != WEBRTC_VIDEO_CODEC_OK) {
|
| - return ret;
|
| - }
|
| - } else {
|
| - rtc::scoped_refptr<I420Buffer> dst_buffer =
|
| - I420Buffer::Create(dst_width, dst_height);
|
| - rtc::scoped_refptr<I420BufferInterface> src_buffer =
|
| - input_image.video_frame_buffer()->ToI420();
|
| - libyuv::I420Scale(src_buffer->DataY(), src_buffer->StrideY(),
|
| - src_buffer->DataU(), src_buffer->StrideU(),
|
| - src_buffer->DataV(), src_buffer->StrideV(), src_width,
|
| - src_height, dst_buffer->MutableDataY(),
|
| - dst_buffer->StrideY(), dst_buffer->MutableDataU(),
|
| - dst_buffer->StrideU(), dst_buffer->MutableDataV(),
|
| - dst_buffer->StrideV(), dst_width, dst_height,
|
| - libyuv::kFilterBilinear);
|
| -
|
| - int ret = streaminfos_[stream_idx].encoder->Encode(
|
| - VideoFrame(dst_buffer, input_image.timestamp(),
|
| - input_image.render_time_ms(), webrtc::kVideoRotation_0),
|
| - codec_specific_info, &stream_frame_types);
|
| - if (ret != WEBRTC_VIDEO_CODEC_OK) {
|
| - return ret;
|
| - }
|
| - }
|
| - }
|
| -
|
| - return WEBRTC_VIDEO_CODEC_OK;
|
| -}
|
| -
|
| -int SimulcastEncoderAdapter::RegisterEncodeCompleteCallback(
|
| - EncodedImageCallback* callback) {
|
| - RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
|
| - encoded_complete_callback_ = callback;
|
| - return WEBRTC_VIDEO_CODEC_OK;
|
| -}
|
| -
|
| -int SimulcastEncoderAdapter::SetChannelParameters(uint32_t packet_loss,
|
| - int64_t rtt) {
|
| - RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
|
| - for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) {
|
| - streaminfos_[stream_idx].encoder->SetChannelParameters(packet_loss, rtt);
|
| - }
|
| - return WEBRTC_VIDEO_CODEC_OK;
|
| -}
|
| -
|
| -int SimulcastEncoderAdapter::SetRateAllocation(const BitrateAllocation& bitrate,
|
| - uint32_t new_framerate) {
|
| - RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
|
| -
|
| - 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) {
|
| - // 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 (codec_.numberOfSimulcastStreams > 0 &&
|
| - bitrate.get_sum_kbps() < codec_.simulcastStream[0].minBitrate) {
|
| - return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
| - }
|
| - }
|
| -
|
| - codec_.maxFramerate = new_framerate;
|
| -
|
| - for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++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;
|
| -
|
| - // 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;
|
| -}
|
| -
|
| -// TODO(brandtr): Add task checker to this member function, when all encoder
|
| -// callbacks are coming in on the encoder queue.
|
| -EncodedImageCallback::Result SimulcastEncoderAdapter::OnEncodedImage(
|
| - size_t stream_idx,
|
| - const EncodedImage& encodedImage,
|
| - const CodecSpecificInfo* codecSpecificInfo,
|
| - const RTPFragmentationHeader* fragmentation) {
|
| - CodecSpecificInfo stream_codec_specific = *codecSpecificInfo;
|
| - stream_codec_specific.codec_name = implementation_name_.c_str();
|
| - CodecSpecificInfoVP8* vp8Info = &(stream_codec_specific.codecSpecific.VP8);
|
| - vp8Info->simulcastIdx = stream_idx;
|
| -
|
| - return encoded_complete_callback_->OnEncodedImage(
|
| - encodedImage, &stream_codec_specific, fragmentation);
|
| -}
|
| -
|
| -void SimulcastEncoderAdapter::PopulateStreamCodec(
|
| - const webrtc::VideoCodec& inst,
|
| - int stream_index,
|
| - uint32_t start_bitrate_kbps,
|
| - bool highest_resolution_stream,
|
| - webrtc::VideoCodec* stream_codec) {
|
| - *stream_codec = inst;
|
| -
|
| - // Stream specific settings.
|
| - stream_codec->VP8()->numberOfTemporalLayers =
|
| - inst.simulcastStream[stream_index].numberOfTemporalLayers;
|
| - stream_codec->numberOfSimulcastStreams = 0;
|
| - stream_codec->width = inst.simulcastStream[stream_index].width;
|
| - stream_codec->height = inst.simulcastStream[stream_index].height;
|
| - stream_codec->maxBitrate = inst.simulcastStream[stream_index].maxBitrate;
|
| - stream_codec->minBitrate = inst.simulcastStream[stream_index].minBitrate;
|
| - stream_codec->qpMax = inst.simulcastStream[stream_index].qpMax;
|
| - // Settings that are based on stream/resolution.
|
| - const bool lowest_resolution_stream = (stream_index == 0);
|
| - if (lowest_resolution_stream) {
|
| - // Settings for lowest spatial resolutions.
|
| - stream_codec->qpMax = kLowestResMaxQp;
|
| - }
|
| - if (!highest_resolution_stream) {
|
| - // For resolutions below CIF, set the codec |complexity| parameter to
|
| - // kComplexityHigher, which maps to cpu_used = -4.
|
| - int pixels_per_frame = stream_codec->width * stream_codec->height;
|
| - if (pixels_per_frame < 352 * 288) {
|
| - stream_codec->VP8()->complexity = webrtc::kComplexityHigher;
|
| - }
|
| - // Turn off denoising for all streams but the highest resolution.
|
| - stream_codec->VP8()->denoisingOn = false;
|
| - }
|
| - // TODO(ronghuawu): what to do with targetBitrate.
|
| -
|
| - stream_codec->startBitrate = start_bitrate_kbps;
|
| -}
|
| -
|
| -bool SimulcastEncoderAdapter::Initialized() const {
|
| - return rtc::AtomicOps::AcquireLoad(&inited_) == 1;
|
| -}
|
| -
|
| -void SimulcastEncoderAdapter::DestroyStoredEncoders() {
|
| - while (!stored_encoders_.empty()) {
|
| - VideoEncoder* encoder = stored_encoders_.top();
|
| - factory_->Destroy(encoder);
|
| - stored_encoders_.pop();
|
| - }
|
| -}
|
| -
|
| -bool SimulcastEncoderAdapter::SupportsNativeHandle() const {
|
| - RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
|
| - // We should not be calling this method before streaminfos_ are configured.
|
| - RTC_DCHECK(!streaminfos_.empty());
|
| - for (const auto& streaminfo : streaminfos_) {
|
| - if (!streaminfo.encoder->SupportsNativeHandle()) {
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -VideoEncoder::ScalingSettings SimulcastEncoderAdapter::GetScalingSettings()
|
| - const {
|
| - // TODO(brandtr): Investigate why the sequence checker below fails on mac.
|
| - // RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
|
| - // Turn off quality scaling for simulcast.
|
| - if (!Initialized() || NumberOfStreams(codec_) != 1) {
|
| - return VideoEncoder::ScalingSettings(false);
|
| - }
|
| - return streaminfos_[0].encoder->GetScalingSettings();
|
| -}
|
| -
|
| -const char* SimulcastEncoderAdapter::ImplementationName() const {
|
| - RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
|
| - return implementation_name_.c_str();
|
| -}
|
| -
|
| -} // namespace webrtc
|
|
|