Commit f990835b authored by Anders Carlsson's avatar Anders Carlsson Committed by Commit Bot

WebRTC: Migrate completely to new video codec factories API

This CL is a reland of
https://chromium-review.googlesource.com/c/chromium/src/+/788410

This CL makes the Chromium HW video factories implement the new
interfaces directly. It also adds SW codecs, simulcast, and SW fallback
codecs manually, instead of relying on WebRTC to do this. This will
give Chromium more flexibility in the future, and will allow us to
simplify the WebRTC code, since it's only Chromium that uses some of
these features.

Bug: webrtc:7925
Change-Id: Ib66ec75827363dc9e0985c35a6de936ca8f3a523
Reviewed-on: https://chromium-review.googlesource.com/1100463Reviewed-by: default avatarEmircan Uysaler <emircan@chromium.org>
Reviewed-by: default avatarHirokazu Honda <hiroh@chromium.org>
Commit-Queue: Anders Carlsson <andersc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#580144}
parent 21950e81
...@@ -416,6 +416,8 @@ target(link_target_type, "renderer") { ...@@ -416,6 +416,8 @@ target(link_target_type, "renderer") {
"media/webrtc/transceiver_state_surfacer.cc", "media/webrtc/transceiver_state_surfacer.cc",
"media/webrtc/transceiver_state_surfacer.h", "media/webrtc/transceiver_state_surfacer.h",
"media/webrtc/two_keys_adapter_map.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.cc",
"media/webrtc/webrtc_audio_device_impl.h", "media/webrtc/webrtc_audio_device_impl.h",
"media/webrtc/webrtc_audio_device_not_impl.cc", "media/webrtc/webrtc_audio_device_not_impl.cc",
...@@ -734,6 +736,7 @@ target(link_target_type, "renderer") { ...@@ -734,6 +736,7 @@ target(link_target_type, "renderer") {
"//third_party/webrtc/api/video:video_bitrate_allocation", "//third_party/webrtc/api/video:video_bitrate_allocation",
"//third_party/webrtc/api/video:video_frame", "//third_party/webrtc/api/video:video_frame",
"//third_party/webrtc/api/video:video_frame_i420", "//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/api/video_codecs:video_codecs_api",
"//third_party/webrtc/common_video:common_video", "//third_party/webrtc/common_video:common_video",
"//third_party/webrtc/media:rtc_internal_video_codecs", "//third_party/webrtc/media:rtc_internal_video_codecs",
......
...@@ -34,9 +34,8 @@ ...@@ -34,9 +34,8 @@
#include "content/renderer/media/stream/media_stream_video_track.h" #include "content/renderer/media/stream/media_stream_video_track.h"
#include "content/renderer/media/webrtc/audio_codec_factory.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_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/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_audio_device_impl.h"
#include "content/renderer/media/webrtc/webrtc_uma_histograms.h" #include "content/renderer/media/webrtc/webrtc_uma_histograms.h"
#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h" #include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
...@@ -62,19 +61,12 @@ ...@@ -62,19 +61,12 @@
#include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/webrtc/api/mediaconstraintsinterface.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/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/media/engine/multiplexcodecfactory.h"
#include "third_party/webrtc/modules/video_coding/codecs/h264/include/h264.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/refcountedobject.h"
#include "third_party/webrtc/rtc_base/ssladapter.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 content {
namespace { namespace {
...@@ -271,31 +263,12 @@ void PeerConnectionDependencyFactory::InitializeSignalingThread( ...@@ -271,31 +263,12 @@ void PeerConnectionDependencyFactory::InitializeSignalingThread(
socket_factory_.reset(new IpcPacketSocketFactory(p2p_socket_dispatcher_.get(), socket_factory_.reset(new IpcPacketSocketFactory(p2p_socket_dispatcher_.get(),
traffic_annotation)); traffic_annotation));
std::unique_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory;
std::unique_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory;
const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); 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 = std::unique_ptr<webrtc::VideoEncoderFactory> webrtc_encoder_factory =
ConvertVideoEncoderFactory(std::move(encoder_factory)); CreateWebrtcVideoEncoderFactory(gpu_factories);
std::unique_ptr<webrtc::VideoDecoderFactory> webrtc_decoder_factory = std::unique_ptr<webrtc::VideoDecoderFactory> webrtc_decoder_factory =
ConvertVideoDecoderFactory(std::move(decoder_factory)); CreateWebrtcVideoDecoderFactory(gpu_factories);
// Enable Multiplex codec in SDP optionally. // Enable Multiplex codec in SDP optionally.
if (base::FeatureList::IsEnabled(features::kWebRtcMultiplexCodec)) { if (base::FeatureList::IsEnabled(features::kWebRtcMultiplexCodec)) {
......
...@@ -137,12 +137,6 @@ std::unique_ptr<RTCVideoDecoder> RTCVideoDecoder::Create( ...@@ -137,12 +137,6 @@ std::unique_ptr<RTCVideoDecoder> RTCVideoDecoder::Create(
return decoder; 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 RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings,
int32_t /*numberOfCores*/) { int32_t /*numberOfCores*/) {
DVLOG(2) << "InitDecode"; DVLOG(2) << "InitDecode";
......
...@@ -6,31 +6,154 @@ ...@@ -6,31 +6,154 @@
#include <memory> #include <memory>
#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.h"
#include "media/video/gpu_video_accelerator_factories.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 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:
#if defined(OS_ANDROID)
// Force HW H264 on Android to be CBP for most compatibility, since:
// - Only HW H264 is available on Android at present.
// - MediaCodec only advise BP, which works same as CBP in most cases.
// - Some peers only expect CBP in negotiation.
h264_profile = webrtc::H264::kProfileConstrainedBaseline;
#else
h264_profile = webrtc::H264::kProfileBaseline;
#endif
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;
}
// 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( RTCVideoDecoderFactory::RTCVideoDecoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories) media::GpuVideoAcceleratorFactories* gpu_factories)
: gpu_factories_(gpu_factories) { : gpu_factories_(gpu_factories) {
DVLOG(2) << __func__; 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));
}
} }
RTCVideoDecoderFactory::~RTCVideoDecoderFactory() { std::vector<webrtc::SdpVideoFormat>
DVLOG(2) << __func__; RTCVideoDecoderFactory::GetSupportedFormats() const {
return supported_formats_;
} }
webrtc::VideoDecoder* RTCVideoDecoderFactory::CreateVideoDecoder( RTCVideoDecoderFactory::~RTCVideoDecoderFactory() {
webrtc::VideoCodecType type) {
DVLOG(2) << __func__; DVLOG(2) << __func__;
return RTCVideoDecoder::Create(type, gpu_factories_).release();
} }
void RTCVideoDecoderFactory::DestroyVideoDecoder( std::unique_ptr<webrtc::VideoDecoder>
webrtc::VideoDecoder* decoder) { RTCVideoDecoderFactory::CreateVideoDecoder(
const webrtc::SdpVideoFormat& format) {
DVLOG(2) << __func__; DVLOG(2) << __func__;
RTCVideoDecoder::Destroy(decoder, gpu_factories_); std::unique_ptr<webrtc::VideoDecoder> decoder = RTCVideoDecoder::Create(
webrtc::PayloadStringToCodecType(format.name), gpu_factories_);
// 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 } // namespace content
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/threading/thread.h" #include "base/threading/thread.h"
#include "content/common/content_export.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" #include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h"
namespace webrtc { namespace webrtc {
...@@ -23,7 +23,7 @@ namespace content { ...@@ -23,7 +23,7 @@ namespace content {
// TODO(wuchengli): add unittest. // TODO(wuchengli): add unittest.
class CONTENT_EXPORT RTCVideoDecoderFactory class CONTENT_EXPORT RTCVideoDecoderFactory
: public cricket::WebRtcVideoDecoderFactory { : public webrtc::VideoDecoderFactory {
public: public:
explicit RTCVideoDecoderFactory( explicit RTCVideoDecoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories); media::GpuVideoAcceleratorFactories* gpu_factories);
...@@ -31,15 +31,14 @@ class CONTENT_EXPORT RTCVideoDecoderFactory ...@@ -31,15 +31,14 @@ class CONTENT_EXPORT RTCVideoDecoderFactory
// Runs on Chrome_libJingle_WorkerThread. The child thread is blocked while // Runs on Chrome_libJingle_WorkerThread. The child thread is blocked while
// this runs. // this runs.
webrtc::VideoDecoder* CreateVideoDecoder( std::unique_ptr<webrtc::VideoDecoder> CreateVideoDecoder(
webrtc::VideoCodecType type) override; const webrtc::SdpVideoFormat& format) override;
// Runs on Chrome_libJingle_WorkerThread. The child thread is blocked while std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override;
// this runs.
void DestroyVideoDecoder(webrtc::VideoDecoder* decoder) override;
private: private:
media::GpuVideoAcceleratorFactories* gpu_factories_; media::GpuVideoAcceleratorFactories* gpu_factories_;
std::vector<webrtc::SdpVideoFormat> supported_formats_;
DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoderFactory); DISALLOW_COPY_AND_ASSIGN(RTCVideoDecoderFactory);
}; };
......
...@@ -14,23 +14,24 @@ ...@@ -14,23 +14,24 @@
#include "content/renderer/media/webrtc/rtc_video_encoder.h" #include "content/renderer/media/webrtc/rtc_video_encoder.h"
#include "media/media_buildflags.h" #include "media/media_buildflags.h"
#include "media/video/gpu_video_accelerator_factories.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/common_video/h264/profile_level_id.h"
#include "third_party/webrtc/media/base/codec.h"
namespace content { namespace content {
namespace { namespace {
// Translate from media::VideoEncodeAccelerator::SupportedProfile to // Translate from media::VideoEncodeAccelerator::SupportedProfile to
// cricket::WebRtcVideoEncoderFactory::VideoCodec, or return nothing if the // webrtc::SdpVideoFormat, or return nothing if the profile isn't supported.
// profile isn't supported. base::Optional<webrtc::SdpVideoFormat> VEAToWebRTCFormat(
base::Optional<cricket::VideoCodec> VEAToWebRTCCodec(
const media::VideoEncodeAccelerator::SupportedProfile& profile) { const media::VideoEncodeAccelerator::SupportedProfile& profile) {
DCHECK_EQ(profile.max_framerate_denominator, 1U); DCHECK_EQ(profile.max_framerate_denominator, 1U);
if (profile.profile >= media::VP8PROFILE_MIN && if (profile.profile >= media::VP8PROFILE_MIN &&
profile.profile <= media::VP8PROFILE_MAX) { profile.profile <= media::VP8PROFILE_MAX) {
if (base::FeatureList::IsEnabled(features::kWebRtcHWVP8Encoding)) { 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 && } else if (profile.profile >= media::H264PROFILE_MIN &&
profile.profile <= media::H264PROFILE_MAX) { profile.profile <= media::H264PROFILE_MAX) {
...@@ -65,7 +66,7 @@ base::Optional<cricket::VideoCodec> VEAToWebRTCCodec( ...@@ -65,7 +66,7 @@ base::Optional<cricket::VideoCodec> VEAToWebRTCCodec(
break; break;
default: default:
// Unsupported H264 profile in WebRTC. // Unsupported H264 profile in WebRTC.
return base::Optional<cricket::VideoCodec>(); return base::nullopt;
} }
const int width = profile.max_resolution.width(); const int width = profile.max_resolution.width();
...@@ -78,15 +79,22 @@ base::Optional<cricket::VideoCodec> VEAToWebRTCCodec( ...@@ -78,15 +79,22 @@ base::Optional<cricket::VideoCodec> VEAToWebRTCCodec(
const webrtc::H264::ProfileLevelId profile_level_id( const webrtc::H264::ProfileLevelId profile_level_id(
h264_profile, h264_level.value_or(webrtc::H264::kLevel1)); h264_profile, h264_level.value_or(webrtc::H264::kLevel1));
cricket::VideoCodec codec("H264"); webrtc::SdpVideoFormat format("H264");
codec.SetParam(cricket::kH264FmtpProfileLevelId, format.parameters = {
*webrtc::H264::ProfileLevelIdToString(profile_level_id)); {cricket::kH264FmtpProfileLevelId,
codec.SetParam(cricket::kH264FmtpLevelAsymmetryAllowed, "1"); *webrtc::H264::ProfileLevelIdToString(profile_level_id)},
codec.SetParam(cricket::kH264FmtpPacketizationMode, "1"); {cricket::kH264FmtpLevelAsymmetryAllowed, "1"},
return base::Optional<cricket::VideoCodec>(codec); {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 } // anonymous namespace
...@@ -97,47 +105,39 @@ RTCVideoEncoderFactory::RTCVideoEncoderFactory( ...@@ -97,47 +105,39 @@ RTCVideoEncoderFactory::RTCVideoEncoderFactory(
const media::VideoEncodeAccelerator::SupportedProfiles& profiles = const media::VideoEncodeAccelerator::SupportedProfiles& profiles =
gpu_factories_->GetVideoEncodeAcceleratorSupportedProfiles(); gpu_factories_->GetVideoEncodeAcceleratorSupportedProfiles();
for (const auto& profile : profiles) { for (const auto& profile : profiles) {
base::Optional<cricket::VideoCodec> codec = VEAToWebRTCCodec(profile); base::Optional<webrtc::SdpVideoFormat> format = VEAToWebRTCFormat(profile);
if (codec) { if (format) {
supported_codecs_.push_back(std::move(*codec)); supported_formats_.push_back(std::move(*format));
profiles_.push_back(profile.profile); 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() {} RTCVideoEncoderFactory::~RTCVideoEncoderFactory() {}
webrtc::VideoEncoder* RTCVideoEncoderFactory::CreateVideoEncoder( std::unique_ptr<webrtc::VideoEncoder>
const cricket::VideoCodec& codec) { RTCVideoEncoderFactory::CreateVideoEncoder(
for (size_t i = 0; i < supported_codecs_.size(); ++i) { const webrtc::SdpVideoFormat& format) {
if (!cricket::CodecNamesEq(codec.name, supported_codecs_[i].name)) for (size_t i = 0; i < supported_formats_.size(); ++i) {
continue; if (IsSameFormat(format, supported_formats_[i])) {
// Check H264 profile. return std::make_unique<RTCVideoEncoder>(profiles_[i], gpu_factories_);
using webrtc::H264::ParseSdpProfileLevelId;
if (cricket::CodecNamesEq(codec.name.c_str(), cricket::kH264CodecName) &&
ParseSdpProfileLevelId(codec.params)->profile !=
ParseSdpProfileLevelId(supported_codecs_[i].params)->profile) {
continue;
} }
// 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; return nullptr;
} }
const std::vector<cricket::VideoCodec>& std::vector<webrtc::SdpVideoFormat>
RTCVideoEncoderFactory::supported_codecs() const { RTCVideoEncoderFactory::GetSupportedFormats() const {
return supported_codecs_; return supported_formats_;
} }
void RTCVideoEncoderFactory::DestroyVideoEncoder( webrtc::VideoEncoderFactory::CodecInfo
webrtc::VideoEncoder* encoder) { RTCVideoEncoderFactory::QueryVideoEncoder(
delete encoder; const webrtc::SdpVideoFormat& format) const {
CodecInfo info;
info.has_internal_source = false;
info.is_hardware_accelerated = true;
return info;
} }
} // namespace content } // namespace content
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "media/base/video_codecs.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 { namespace media {
class GpuVideoAcceleratorFactories; class GpuVideoAcceleratorFactories;
...@@ -23,26 +23,27 @@ namespace content { ...@@ -23,26 +23,27 @@ namespace content {
// This class creates RTCVideoEncoder instances (each wrapping a // This class creates RTCVideoEncoder instances (each wrapping a
// media::VideoEncodeAccelerator) on behalf of the WebRTC stack. // media::VideoEncodeAccelerator) on behalf of the WebRTC stack.
class CONTENT_EXPORT RTCVideoEncoderFactory class CONTENT_EXPORT RTCVideoEncoderFactory
: public cricket::WebRtcVideoEncoderFactory { : public webrtc::VideoEncoderFactory {
public: public:
explicit RTCVideoEncoderFactory( explicit RTCVideoEncoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories); media::GpuVideoAcceleratorFactories* gpu_factories);
~RTCVideoEncoderFactory() override; ~RTCVideoEncoderFactory() override;
// cricket::WebRtcVideoEncoderFactory implementation. // webrtc::VideoEncoderFactory implementation.
webrtc::VideoEncoder* CreateVideoEncoder( std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(
const cricket::VideoCodec& codec) override; const webrtc::SdpVideoFormat& format) override;
const std::vector<cricket::VideoCodec>& supported_codecs() const override; std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override;
void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) override; webrtc::VideoEncoderFactory::CodecInfo QueryVideoEncoder(
const webrtc::SdpVideoFormat& format) const override;
private: private:
media::GpuVideoAcceleratorFactories* gpu_factories_; media::GpuVideoAcceleratorFactories* gpu_factories_;
// List of supported cricket::WebRtcVideoEncoderFactory::VideoCodec. // List of supported webrtc::SdpVideoFormat. |profiles_| and
// |profiles_| and |supported_codecs_| have the same length and the profile // |supported_formats_| have the same length and the profile for
// for |supported_codecs_[i]| is |profiles_[i]|. // |supported_formats_[i]| is |profiles_[i]|.
std::vector<media::VideoCodecProfile> profiles_; std::vector<media::VideoCodecProfile> profiles_;
std::vector<cricket::VideoCodec> supported_codecs_; std::vector<webrtc::SdpVideoFormat> supported_formats_;
DISALLOW_COPY_AND_ASSIGN(RTCVideoEncoderFactory); 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 =
cricket::CodecNamesEq(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 =
cricket::CodecNamesEq(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