Commit b5f5ab1e authored by Emircan Uysaler's avatar Emircan Uysaler Committed by Commit Bot

Reland "WebRTC: Migrate completely to new video codec factories API"

This reverts commit 6e62467b as PS#1. Landing
these interface changes will unblock WebRTC for changing the codec factory
interfaces and allow us to do further work on supporting VP9 profile 2 HW
codec on Chromium side.

In PS#2, it makes the changes that will make sure we have a 1-to-2 mapping
between media::BASELINE to webrtc::CONSTRAINED_BASELINE and webrtc::BASELINE
profiles. This is a temporary workaround until https://crbug.com/345569 is
solved. We don't expect to hit the earlier regressions that caused this
to be reverted with this mapping.

Bug: 908945,webrtc:7925
Change-Id: I93e408f8bd0ff0987d3f4c374132433a9ccdc0c6
Reviewed-on: https://chromium-review.googlesource.com/c/1351108Reviewed-by: default avatarMagnus Jedvert <magjed@chromium.org>
Commit-Queue: Emircan Uysaler <emircan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#613121}
parent 9887251b
......@@ -396,6 +396,8 @@ target(link_target_type, "renderer") {
"media/webrtc/transceiver_state_surfacer.cc",
"media/webrtc/transceiver_state_surfacer.h",
"media/webrtc/two_keys_adapter_map.h",
"media/webrtc/video_codec_factory.cc",
"media/webrtc/video_codec_factory.h",
"media/webrtc/webrtc_audio_device_impl.cc",
"media/webrtc/webrtc_audio_device_impl.h",
"media/webrtc/webrtc_audio_device_not_impl.cc",
......@@ -712,11 +714,13 @@ target(link_target_type, "renderer") {
"//third_party/webrtc/api/video:video_bitrate_allocation",
"//third_party/webrtc/api/video:video_frame",
"//third_party/webrtc/api/video:video_frame_i420",
"//third_party/webrtc/api/video_codecs:rtc_software_fallback_wrappers",
"//third_party/webrtc/api/video_codecs:video_codecs_api",
"//third_party/webrtc/common_video:common_video",
"//third_party/webrtc/media:rtc_internal_video_codecs",
"//third_party/webrtc/media:rtc_media",
"//third_party/webrtc/media:rtc_media_base",
"//third_party/webrtc/media:rtc_simulcast_encoder_adapter",
"//third_party/webrtc/modules/audio_device",
"//third_party/webrtc/modules/audio_processing",
"//third_party/webrtc/modules/audio_processing:api",
......
......@@ -34,9 +34,8 @@
#include "content/renderer/media/stream/media_stream_video_track.h"
#include "content/renderer/media/webrtc/audio_codec_factory.h"
#include "content/renderer/media/webrtc/rtc_peer_connection_handler.h"
#include "content/renderer/media/webrtc/rtc_video_decoder_factory.h"
#include "content/renderer/media/webrtc/rtc_video_encoder_factory.h"
#include "content/renderer/media/webrtc/stun_field_trial.h"
#include "content/renderer/media/webrtc/video_codec_factory.h"
#include "content/renderer/media/webrtc/webrtc_audio_device_impl.h"
#include "content/renderer/media/webrtc/webrtc_uma_histograms.h"
#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
......@@ -64,19 +63,12 @@
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/webrtc/api/create_peerconnection_factory.h"
#include "third_party/webrtc/api/mediaconstraintsinterface.h"
#include "third_party/webrtc/api/video_codecs/video_decoder_factory.h"
#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h"
#include "third_party/webrtc/api/videosourceproxy.h"
#include "third_party/webrtc/media/engine/convert_legacy_video_factory.h"
#include "third_party/webrtc/media/engine/multiplexcodecfactory.h"
#include "third_party/webrtc/modules/video_coding/codecs/h264/include/h264.h"
#include "third_party/webrtc/rtc_base/refcountedobject.h"
#include "third_party/webrtc/rtc_base/ssladapter.h"
#if defined(OS_ANDROID)
#include "media/base/android/media_codec_util.h"
#endif
namespace content {
namespace {
......@@ -299,31 +291,12 @@ void PeerConnectionDependencyFactory::InitializeSignalingThread(
socket_factory_.reset(new IpcPacketSocketFactory(p2p_socket_dispatcher_.get(),
traffic_annotation));
std::unique_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory;
std::unique_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory;
const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
if (gpu_factories && gpu_factories->IsGpuVideoAcceleratorEnabled()) {
if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWDecoding))
decoder_factory.reset(new RTCVideoDecoderFactory(gpu_factories));
if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWEncoding))
encoder_factory.reset(new RTCVideoEncoderFactory(gpu_factories));
}
#if defined(OS_ANDROID)
if (!media::MediaCodecUtil::SupportsSetParameters())
encoder_factory.reset();
#endif
// TODO(magjed): Update RTCVideoEncoderFactory/RTCVideoDecoderFactory to new
// interface and let Chromium be responsible in what order video codecs are
// listed, instead of using
// cricket::ConvertVideoEncoderFactory/cricket::ConvertVideoDecoderFactory.
std::unique_ptr<webrtc::VideoEncoderFactory> webrtc_encoder_factory =
ConvertVideoEncoderFactory(std::move(encoder_factory));
CreateWebrtcVideoEncoderFactory(gpu_factories);
std::unique_ptr<webrtc::VideoDecoderFactory> webrtc_decoder_factory =
ConvertVideoDecoderFactory(std::move(decoder_factory));
CreateWebrtcVideoDecoderFactory(gpu_factories);
// Enable Multiplex codec in SDP optionally.
if (base::FeatureList::IsEnabled(features::kWebRtcMultiplexCodec)) {
......
......@@ -137,12 +137,6 @@ std::unique_ptr<RTCVideoDecoder> RTCVideoDecoder::Create(
return decoder;
}
// static
void RTCVideoDecoder::Destroy(webrtc::VideoDecoder* decoder,
media::GpuVideoAcceleratorFactories* factories) {
factories->GetTaskRunner()->DeleteSoon(FROM_HERE, decoder);
}
int32_t RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings,
int32_t /*numberOfCores*/) {
DVLOG(2) << "InitDecode";
......
......@@ -7,38 +7,178 @@
#include <memory>
#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
#include "content/renderer/media/webrtc/rtc_video_decoder.h"
#include "content/renderer/media/webrtc/rtc_video_decoder_adapter.h"
#include "media/base/media_switches.h"
#include "media/video/gpu_video_accelerator_factories.h"
#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
#include "third_party/webrtc/common_video/h264/profile_level_id.h"
#include "third_party/webrtc/media/base/codec.h"
namespace content {
namespace {
const int kDefaultFps = 30;
// Translate from media::VideoDecodeAccelerator::SupportedProfile to
// webrtc::SdpVideoFormat, or return nothing if the profile isn't supported.
base::Optional<webrtc::SdpVideoFormat> VDAToWebRTCFormat(
const media::VideoDecodeAccelerator::SupportedProfile& profile) {
if (profile.profile >= media::VP8PROFILE_MIN &&
profile.profile <= media::VP8PROFILE_MAX) {
return webrtc::SdpVideoFormat("VP8");
} else if (profile.profile >= media::VP9PROFILE_MIN &&
profile.profile <= media::VP9PROFILE_MAX) {
return webrtc::SdpVideoFormat("VP9");
} else if (profile.profile >= media::H264PROFILE_MIN &&
profile.profile <= media::H264PROFILE_MAX) {
webrtc::H264::Profile h264_profile;
switch (profile.profile) {
case media::H264PROFILE_BASELINE:
h264_profile = webrtc::H264::kProfileBaseline;
break;
case media::H264PROFILE_MAIN:
h264_profile = webrtc::H264::kProfileMain;
break;
case media::H264PROFILE_HIGH:
h264_profile = webrtc::H264::kProfileHigh;
break;
default:
// Unsupported H264 profile in WebRTC.
return base::nullopt;
}
const int width = profile.max_resolution.width();
const int height = profile.max_resolution.height();
const absl::optional<webrtc::H264::Level> h264_level =
webrtc::H264::SupportedLevel(width * height, kDefaultFps);
const webrtc::H264::ProfileLevelId profile_level_id(
h264_profile, h264_level.value_or(webrtc::H264::kLevel1));
webrtc::SdpVideoFormat format("H264");
format.parameters = {
{cricket::kH264FmtpProfileLevelId,
*webrtc::H264::ProfileLevelIdToString(profile_level_id)},
{cricket::kH264FmtpLevelAsymmetryAllowed, "1"},
{cricket::kH264FmtpPacketizationMode, "1"}};
return format;
}
return base::nullopt;
}
// Due to https://crbug.com/345569, HW decoders do not distinguish between
// Constrained Baseline(CBP) and Baseline(BP) profiles. Since CBP is a subset of
// BP, we can report support for both. It is safe to do so when SW fallback is
// available.
// TODO(emircan): Remove this when the bug referred above is fixed.
void MapBaselineProfile(
std::vector<webrtc::SdpVideoFormat>* supported_formats) {
for (const auto& format : *supported_formats) {
const absl::optional<webrtc::H264::ProfileLevelId> profile_level_id =
webrtc::H264::ParseSdpProfileLevelId(format.parameters);
if (profile_level_id &&
profile_level_id->profile == webrtc::H264::kProfileBaseline) {
webrtc::SdpVideoFormat cbp_format = format;
webrtc::H264::ProfileLevelId cbp_profile = *profile_level_id;
cbp_profile.profile = webrtc::H264::kProfileConstrainedBaseline;
cbp_format.parameters[cricket::kH264FmtpProfileLevelId] =
*webrtc::H264::ProfileLevelIdToString(cbp_profile);
supported_formats->push_back(cbp_format);
return;
}
}
}
// This extra indirection is needed so that we can delete the decoder on the
// correct thread.
class ScopedVideoDecoder : public webrtc::VideoDecoder {
public:
ScopedVideoDecoder(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
std::unique_ptr<webrtc::VideoDecoder> decoder)
: task_runner_(task_runner), decoder_(std::move(decoder)) {}
int32_t InitDecode(const webrtc::VideoCodec* codec_settings,
int32_t number_of_cores) override {
return decoder_->InitDecode(codec_settings, number_of_cores);
}
int32_t RegisterDecodeCompleteCallback(
webrtc::DecodedImageCallback* callback) override {
return decoder_->RegisterDecodeCompleteCallback(callback);
}
int32_t Release() override { return decoder_->Release(); }
int32_t Decode(const webrtc::EncodedImage& input_image,
bool missing_frames,
const webrtc::CodecSpecificInfo* codec_specific_info,
int64_t render_time_ms) override {
return decoder_->Decode(input_image, missing_frames, codec_specific_info,
render_time_ms);
}
bool PrefersLateDecoding() const override {
return decoder_->PrefersLateDecoding();
}
const char* ImplementationName() const override {
return decoder_->ImplementationName();
}
// Runs on Chrome_libJingle_WorkerThread. The child thread is blocked while
// this runs.
~ScopedVideoDecoder() override {
task_runner_->DeleteSoon(FROM_HERE, decoder_.release());
}
private:
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
std::unique_ptr<webrtc::VideoDecoder> decoder_;
};
} // namespace
RTCVideoDecoderFactory::RTCVideoDecoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories)
: gpu_factories_(gpu_factories) {
DVLOG(2) << __func__;
const media::VideoDecodeAccelerator::SupportedProfiles profiles =
gpu_factories_->GetVideoDecodeAcceleratorCapabilities()
.supported_profiles;
for (const auto& profile : profiles) {
base::Optional<webrtc::SdpVideoFormat> format = VDAToWebRTCFormat(profile);
if (format)
supported_formats_.push_back(std::move(*format));
}
MapBaselineProfile(&supported_formats_);
}
std::vector<webrtc::SdpVideoFormat>
RTCVideoDecoderFactory::GetSupportedFormats() const {
return supported_formats_;
}
RTCVideoDecoderFactory::~RTCVideoDecoderFactory() {
DVLOG(2) << __func__;
}
webrtc::VideoDecoder* RTCVideoDecoderFactory::CreateVideoDecoder(
webrtc::VideoCodecType type) {
std::unique_ptr<webrtc::VideoDecoder>
RTCVideoDecoderFactory::CreateVideoDecoder(
const webrtc::SdpVideoFormat& format) {
DVLOG(2) << __func__;
std::unique_ptr<webrtc::VideoDecoder> decoder;
if (base::FeatureList::IsEnabled(media::kRTCVideoDecoderAdapter)) {
return RTCVideoDecoderAdapter::Create(gpu_factories_, type).release();
decoder = RTCVideoDecoderAdapter::Create(
gpu_factories_, webrtc::PayloadStringToCodecType(format.name));
} else {
return RTCVideoDecoder::Create(type, gpu_factories_).release();
decoder = RTCVideoDecoder::Create(
webrtc::PayloadStringToCodecType(format.name), gpu_factories_);
}
}
void RTCVideoDecoderFactory::DestroyVideoDecoder(
webrtc::VideoDecoder* decoder) {
DVLOG(2) << __func__;
gpu_factories_->GetTaskRunner()->DeleteSoon(FROM_HERE, decoder);
// ScopedVideoDecoder uses the task runner to make sure the decoder is
// destructed on the correct thread.
return decoder ? std::make_unique<ScopedVideoDecoder>(
gpu_factories_->GetTaskRunner(), std::move(decoder))
: nullptr;
}
} // namespace content
......@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
#include "third_party/webrtc/media/engine/webrtcvideodecoderfactory.h"
#include "third_party/webrtc/api/video_codecs/video_decoder_factory.h"
#include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h"
namespace webrtc {
......@@ -23,7 +23,7 @@ namespace content {
// TODO(wuchengli): add unittest.
class CONTENT_EXPORT RTCVideoDecoderFactory
: public cricket::WebRtcVideoDecoderFactory {
: public webrtc::VideoDecoderFactory {
public:
explicit RTCVideoDecoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories);
......@@ -31,15 +31,14 @@ class CONTENT_EXPORT RTCVideoDecoderFactory
// Runs on Chrome_libJingle_WorkerThread. The child thread is blocked while
// this runs.
webrtc::VideoDecoder* CreateVideoDecoder(
webrtc::VideoCodecType type) override;
std::unique_ptr<webrtc::VideoDecoder> CreateVideoDecoder(
const webrtc::SdpVideoFormat& format) override;
// Runs on Chrome_libJingle_WorkerThread. The child thread is blocked while
// this runs.
void DestroyVideoDecoder(webrtc::VideoDecoder* decoder) override;
std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override;
private:
media::GpuVideoAcceleratorFactories* gpu_factories_;
std::vector<webrtc::SdpVideoFormat> supported_formats_;
DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoderFactory);
};
......
......@@ -15,23 +15,24 @@
#include "content/renderer/media/webrtc/rtc_video_encoder.h"
#include "media/media_buildflags.h"
#include "media/video/gpu_video_accelerator_factories.h"
#include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
#include "third_party/webrtc/common_video/h264/profile_level_id.h"
#include "third_party/webrtc/media/base/codec.h"
namespace content {
namespace {
// Translate from media::VideoEncodeAccelerator::SupportedProfile to
// cricket::WebRtcVideoEncoderFactory::VideoCodec, or return nothing if the
// profile isn't supported.
base::Optional<cricket::VideoCodec> VEAToWebRTCCodec(
// webrtc::SdpVideoFormat, or return nothing if the profile isn't supported.
base::Optional<webrtc::SdpVideoFormat> VEAToWebRTCFormat(
const media::VideoEncodeAccelerator::SupportedProfile& profile) {
DCHECK_EQ(profile.max_framerate_denominator, 1U);
if (profile.profile >= media::VP8PROFILE_MIN &&
profile.profile <= media::VP8PROFILE_MAX) {
if (base::FeatureList::IsEnabled(features::kWebRtcHWVP8Encoding)) {
return base::Optional<cricket::VideoCodec>(cricket::VideoCodec("VP8"));
return webrtc::SdpVideoFormat("VP8");
}
} else if (profile.profile >= media::H264PROFILE_MIN &&
profile.profile <= media::H264PROFILE_MAX) {
......@@ -66,7 +67,7 @@ base::Optional<cricket::VideoCodec> VEAToWebRTCCodec(
break;
default:
// Unsupported H264 profile in WebRTC.
return base::Optional<cricket::VideoCodec>();
return base::nullopt;
}
const int width = profile.max_resolution.width();
......@@ -79,15 +80,22 @@ base::Optional<cricket::VideoCodec> VEAToWebRTCCodec(
const webrtc::H264::ProfileLevelId profile_level_id(
h264_profile, h264_level.value_or(webrtc::H264::kLevel1));
cricket::VideoCodec codec("H264");
codec.SetParam(cricket::kH264FmtpProfileLevelId,
*webrtc::H264::ProfileLevelIdToString(profile_level_id));
codec.SetParam(cricket::kH264FmtpLevelAsymmetryAllowed, "1");
codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
return base::Optional<cricket::VideoCodec>(codec);
webrtc::SdpVideoFormat format("H264");
format.parameters = {
{cricket::kH264FmtpProfileLevelId,
*webrtc::H264::ProfileLevelIdToString(profile_level_id)},
{cricket::kH264FmtpLevelAsymmetryAllowed, "1"},
{cricket::kH264FmtpPacketizationMode, "1"}};
return format;
}
}
return base::Optional<cricket::VideoCodec>();
return base::nullopt;
}
bool IsSameFormat(const webrtc::SdpVideoFormat& format1,
const webrtc::SdpVideoFormat& format2) {
return cricket::IsSameCodec(format1.name, format2.parameters, format2.name,
format2.parameters);
}
} // anonymous namespace
......@@ -98,49 +106,39 @@ RTCVideoEncoderFactory::RTCVideoEncoderFactory(
const media::VideoEncodeAccelerator::SupportedProfiles& profiles =
gpu_factories_->GetVideoEncodeAcceleratorSupportedProfiles();
for (const auto& profile : profiles) {
base::Optional<cricket::VideoCodec> codec = VEAToWebRTCCodec(profile);
if (codec) {
supported_codecs_.push_back(std::move(*codec));
base::Optional<webrtc::SdpVideoFormat> format = VEAToWebRTCFormat(profile);
if (format) {
supported_formats_.push_back(std::move(*format));
profiles_.push_back(profile.profile);
}
}
// There should be a 1:1 mapping between media::VideoCodecProfile and
// cricket::VideoCodec.
CHECK_EQ(profiles_.size(), supported_codecs_.size());
}
RTCVideoEncoderFactory::~RTCVideoEncoderFactory() {}
webrtc::VideoEncoder* RTCVideoEncoderFactory::CreateVideoEncoder(
const cricket::VideoCodec& codec) {
for (size_t i = 0; i < supported_codecs_.size(); ++i) {
if (!base::EqualsCaseInsensitiveASCII(codec.name,
supported_codecs_[i].name)) {
continue;
}
// Check H264 profile.
using webrtc::H264::ParseSdpProfileLevelId;
if (base::EqualsCaseInsensitiveASCII(codec.name, cricket::kH264CodecName) &&
ParseSdpProfileLevelId(codec.params)->profile !=
ParseSdpProfileLevelId(supported_codecs_[i].params)->profile) {
continue;
std::unique_ptr<webrtc::VideoEncoder>
RTCVideoEncoderFactory::CreateVideoEncoder(
const webrtc::SdpVideoFormat& format) {
for (size_t i = 0; i < supported_formats_.size(); ++i) {
if (IsSameFormat(format, supported_formats_[i])) {
return std::make_unique<RTCVideoEncoder>(profiles_[i], gpu_factories_);
}
// There should be a 1:1 mapping between media::VideoCodecProfile and
// cricket::VideoCodec.
CHECK_EQ(profiles_.size(), supported_codecs_.size());
return new RTCVideoEncoder(profiles_[i], gpu_factories_);
}
return nullptr;
}
const std::vector<cricket::VideoCodec>&
RTCVideoEncoderFactory::supported_codecs() const {
return supported_codecs_;
std::vector<webrtc::SdpVideoFormat>
RTCVideoEncoderFactory::GetSupportedFormats() const {
return supported_formats_;
}
void RTCVideoEncoderFactory::DestroyVideoEncoder(
webrtc::VideoEncoder* encoder) {
delete encoder;
webrtc::VideoEncoderFactory::CodecInfo
RTCVideoEncoderFactory::QueryVideoEncoder(
const webrtc::SdpVideoFormat& format) const {
CodecInfo info;
info.has_internal_source = false;
info.is_hardware_accelerated = true;
return info;
}
} // namespace content
......@@ -12,7 +12,7 @@
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "media/base/video_codecs.h"
#include "third_party/webrtc/media/engine/webrtcvideoencoderfactory.h"
#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h"
namespace media {
class GpuVideoAcceleratorFactories;
......@@ -23,26 +23,27 @@ namespace content {
// This class creates RTCVideoEncoder instances (each wrapping a
// media::VideoEncodeAccelerator) on behalf of the WebRTC stack.
class CONTENT_EXPORT RTCVideoEncoderFactory
: public cricket::WebRtcVideoEncoderFactory {
: public webrtc::VideoEncoderFactory {
public:
explicit RTCVideoEncoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories);
~RTCVideoEncoderFactory() override;
// cricket::WebRtcVideoEncoderFactory implementation.
webrtc::VideoEncoder* CreateVideoEncoder(
const cricket::VideoCodec& codec) override;
const std::vector<cricket::VideoCodec>& supported_codecs() const override;
void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) override;
// webrtc::VideoEncoderFactory implementation.
std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(
const webrtc::SdpVideoFormat& format) override;
std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override;
webrtc::VideoEncoderFactory::CodecInfo QueryVideoEncoder(
const webrtc::SdpVideoFormat& format) const override;
private:
media::GpuVideoAcceleratorFactories* gpu_factories_;
// List of supported cricket::WebRtcVideoEncoderFactory::VideoCodec.
// |profiles_| and |supported_codecs_| have the same length and the profile
// for |supported_codecs_[i]| is |profiles_[i]|.
// List of supported webrtc::SdpVideoFormat. |profiles_| and
// |supported_formats_| have the same length and the profile for
// |supported_formats_[i]| is |profiles_[i]|.
std::vector<media::VideoCodecProfile> profiles_;
std::vector<cricket::VideoCodec> supported_codecs_;
std::vector<webrtc::SdpVideoFormat> supported_formats_;
DISALLOW_COPY_AND_ASSIGN(RTCVideoEncoderFactory);
};
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/media/webrtc/video_codec_factory.h"
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/media/webrtc/rtc_video_decoder_factory.h"
#include "content/renderer/media/webrtc/rtc_video_encoder_factory.h"
#include "third_party/webrtc/api/video_codecs/video_decoder_software_fallback_wrapper.h"
#include "third_party/webrtc/api/video_codecs/video_encoder_software_fallback_wrapper.h"
#include "third_party/webrtc/media/base/codec.h"
#include "third_party/webrtc/media/engine/internaldecoderfactory.h"
#include "third_party/webrtc/media/engine/internalencoderfactory.h"
#include "third_party/webrtc/media/engine/simulcast_encoder_adapter.h"
#include "third_party/webrtc/media/engine/vp8_encoder_simulcast_proxy.h"
#if defined(OS_ANDROID)
#include "media/base/android/media_codec_util.h"
#endif
namespace content {
namespace {
bool IsFormatSupported(
const std::vector<webrtc::SdpVideoFormat>& supported_formats,
const webrtc::SdpVideoFormat& format) {
for (const webrtc::SdpVideoFormat& supported_format : supported_formats) {
if (cricket::IsSameCodec(format.name, format.parameters,
supported_format.name,
supported_format.parameters)) {
return true;
}
}
return false;
}
template <typename Factory>
bool IsFormatSupported(const Factory* factory,
const webrtc::SdpVideoFormat& format) {
return factory && IsFormatSupported(factory->GetSupportedFormats(), format);
}
// Merge |formats1| and |formats2|, but avoid adding duplicate formats.
std::vector<webrtc::SdpVideoFormat> MergeFormats(
std::vector<webrtc::SdpVideoFormat> formats1,
const std::vector<webrtc::SdpVideoFormat>& formats2) {
for (const webrtc::SdpVideoFormat& format : formats2) {
// Don't add same format twice.
if (!IsFormatSupported(formats1, format))
formats1.push_back(format);
}
return formats1;
}
std::unique_ptr<webrtc::VideoDecoder> CreateDecoder(
webrtc::VideoDecoderFactory* factory,
const webrtc::SdpVideoFormat& format) {
return IsFormatSupported(factory, format)
? factory->CreateVideoDecoder(format)
: nullptr;
}
std::unique_ptr<webrtc::VideoDecoder> Wrap(
std::unique_ptr<webrtc::VideoDecoder> software_decoder,
std::unique_ptr<webrtc::VideoDecoder> hardware_decoder) {
if (software_decoder && hardware_decoder) {
return webrtc::CreateVideoDecoderSoftwareFallbackWrapper(
std::move(software_decoder), std::move(hardware_decoder));
}
return hardware_decoder ? std::move(hardware_decoder)
: std::move(software_decoder);
}
std::unique_ptr<webrtc::VideoEncoder> Wrap(
std::unique_ptr<webrtc::VideoEncoder> software_encoder,
std::unique_ptr<webrtc::VideoEncoder> hardware_encoder) {
if (software_encoder && hardware_encoder) {
return webrtc::CreateVideoEncoderSoftwareFallbackWrapper(
std::move(software_encoder), std::move(hardware_encoder));
}
return hardware_encoder ? std::move(hardware_encoder)
: std::move(software_encoder);
}
// This class combines a hardware factory with the internal factory and adds
// internal SW codecs, simulcast, and SW fallback wrappers.
class EncoderAdapter : public webrtc::VideoEncoderFactory {
public:
explicit EncoderAdapter(
std::unique_ptr<webrtc::VideoEncoderFactory> hardware_encoder_factory)
: hardware_encoder_factory_(std::move(hardware_encoder_factory)) {}
webrtc::VideoEncoderFactory::CodecInfo QueryVideoEncoder(
const webrtc::SdpVideoFormat& format) const override {
const webrtc::VideoEncoderFactory* factory =
IsFormatSupported(hardware_encoder_factory_.get(), format)
? hardware_encoder_factory_.get()
: &software_encoder_factory_;
return factory->QueryVideoEncoder(format);
}
std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(
const webrtc::SdpVideoFormat& format) override {
std::unique_ptr<webrtc::VideoEncoder> software_encoder;
if (IsFormatSupported(&software_encoder_factory_, format)) {
software_encoder =
base::EqualsCaseInsensitiveASCII(format.name.c_str(),
cricket::kVp8CodecName)
? std::make_unique<webrtc::VP8EncoderSimulcastProxy>(
&software_encoder_factory_)
: software_encoder_factory_.CreateVideoEncoder(format);
}
std::unique_ptr<webrtc::VideoEncoder> hardware_encoder;
if (IsFormatSupported(hardware_encoder_factory_.get(), format)) {
hardware_encoder =
base::EqualsCaseInsensitiveASCII(format.name.c_str(),
cricket::kVp8CodecName)
? std::make_unique<webrtc::SimulcastEncoderAdapter>(
hardware_encoder_factory_.get(), format)
: hardware_encoder_factory_->CreateVideoEncoder(format);
}
return Wrap(std::move(software_encoder), std::move(hardware_encoder));
}
std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override {
std::vector<webrtc::SdpVideoFormat> software_formats =
software_encoder_factory_.GetSupportedFormats();
return hardware_encoder_factory_
? MergeFormats(software_formats,
hardware_encoder_factory_->GetSupportedFormats())
: software_formats;
}
private:
webrtc::InternalEncoderFactory software_encoder_factory_;
const std::unique_ptr<webrtc::VideoEncoderFactory> hardware_encoder_factory_;
};
// This class combines a hardware codec factory with the internal factory and
// adds internal SW codecs and SW fallback wrappers.
class DecoderAdapter : public webrtc::VideoDecoderFactory {
public:
explicit DecoderAdapter(
std::unique_ptr<webrtc::VideoDecoderFactory> hardware_decoder_factory)
: hardware_decoder_factory_(std::move(hardware_decoder_factory)) {}
std::unique_ptr<webrtc::VideoDecoder> CreateVideoDecoder(
const webrtc::SdpVideoFormat& format) override {
std::unique_ptr<webrtc::VideoDecoder> software_decoder =
CreateDecoder(&software_decoder_factory_, format);
std::unique_ptr<webrtc::VideoDecoder> hardware_decoder =
CreateDecoder(hardware_decoder_factory_.get(), format);
return Wrap(std::move(software_decoder), std::move(hardware_decoder));
}
std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override {
std::vector<webrtc::SdpVideoFormat> software_formats =
software_decoder_factory_.GetSupportedFormats();
return hardware_decoder_factory_
? MergeFormats(software_formats,
hardware_decoder_factory_->GetSupportedFormats())
: software_formats;
}
private:
webrtc::InternalDecoderFactory software_decoder_factory_;
const std::unique_ptr<webrtc::VideoDecoderFactory> hardware_decoder_factory_;
};
} // namespace
std::unique_ptr<webrtc::VideoEncoderFactory> CreateWebrtcVideoEncoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories) {
std::unique_ptr<webrtc::VideoEncoderFactory> encoder_factory;
const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
if (gpu_factories && gpu_factories->IsGpuVideoAcceleratorEnabled() &&
!cmd_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) {
encoder_factory.reset(new RTCVideoEncoderFactory(gpu_factories));
}
#if defined(OS_ANDROID)
if (!media::MediaCodecUtil::SupportsSetParameters())
encoder_factory.reset();
#endif
return std::make_unique<EncoderAdapter>(std::move(encoder_factory));
}
std::unique_ptr<webrtc::VideoDecoderFactory> CreateWebrtcVideoDecoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories) {
std::unique_ptr<webrtc::VideoDecoderFactory> decoder_factory;
const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
if (gpu_factories && gpu_factories->IsGpuVideoAcceleratorEnabled() &&
!cmd_line->HasSwitch(switches::kDisableWebRtcHWDecoding)) {
decoder_factory.reset(new RTCVideoDecoderFactory(gpu_factories));
}
return std::make_unique<DecoderAdapter>(std::move(decoder_factory));
}
} // namespace content
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_VIDEO_CODEC_FACTORY_H_
#define CONTENT_RENDERER_MEDIA_WEBRTC_VIDEO_CODEC_FACTORY_H_
#include "media/video/gpu_video_accelerator_factories.h"
#include "third_party/webrtc/api/video_codecs/video_decoder_factory.h"
#include "third_party/webrtc/api/video_codecs/video_encoder_factory.h"
namespace content {
std::unique_ptr<webrtc::VideoEncoderFactory> CreateWebrtcVideoEncoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories);
std::unique_ptr<webrtc::VideoDecoderFactory> CreateWebrtcVideoDecoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories);
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_WEBRTC_VIDEO_CODEC_FACTORY_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment