Commit 6e62467b authored by Anders Carlsson's avatar Anders Carlsson Committed by Commit Bot

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

This reverts commit f990835b.

Reason for revert: Breaks H264 profile negotiation in some cases.

Original change's description:
> 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/1100463
> Reviewed-by: Emircan Uysaler <emircan@chromium.org>
> Reviewed-by: Hirokazu Honda <hiroh@chromium.org>
> Commit-Queue: Anders Carlsson <andersc@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#580144}

TBR=haraken@chromium.org,emircan@chromium.org,hiroh@chromium.org,andersc@chromium.org

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: webrtc:7925
Change-Id: I4b9c7ef3c386d310156611898ecbd552df8c1520
Reviewed-on: https://chromium-review.googlesource.com/1255636
Commit-Queue: Anders Carlsson <andersc@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#595809}
parent 3423a879
...@@ -416,8 +416,6 @@ target(link_target_type, "renderer") { ...@@ -416,8 +416,6 @@ 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",
...@@ -736,7 +734,6 @@ target(link_target_type, "renderer") { ...@@ -736,7 +734,6 @@ 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,8 +34,9 @@ ...@@ -34,8 +34,9 @@
#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"
...@@ -61,12 +62,19 @@ ...@@ -61,12 +62,19 @@
#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 {
...@@ -282,12 +290,31 @@ void PeerConnectionDependencyFactory::InitializeSignalingThread( ...@@ -282,12 +290,31 @@ 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 =
CreateWebrtcVideoEncoderFactory(gpu_factories); ConvertVideoEncoderFactory(std::move(encoder_factory));
std::unique_ptr<webrtc::VideoDecoderFactory> webrtc_decoder_factory = std::unique_ptr<webrtc::VideoDecoderFactory> webrtc_decoder_factory =
CreateWebrtcVideoDecoderFactory(gpu_factories); ConvertVideoDecoderFactory(std::move(decoder_factory));
// 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,6 +137,12 @@ std::unique_ptr<RTCVideoDecoder> RTCVideoDecoder::Create( ...@@ -137,6 +137,12 @@ 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";
......
...@@ -7,162 +7,38 @@ ...@@ -7,162 +7,38 @@
#include <memory> #include <memory>
#include "base/feature_list.h" #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.h"
#include "content/renderer/media/webrtc/rtc_video_decoder_adapter.h" #include "content/renderer/media/webrtc/rtc_video_decoder_adapter.h"
#include "media/base/media_switches.h" #include "media/base/media_switches.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));
}
}
std::vector<webrtc::SdpVideoFormat>
RTCVideoDecoderFactory::GetSupportedFormats() const {
return supported_formats_;
} }
RTCVideoDecoderFactory::~RTCVideoDecoderFactory() { RTCVideoDecoderFactory::~RTCVideoDecoderFactory() {
DVLOG(2) << __func__; DVLOG(2) << __func__;
} }
std::unique_ptr<webrtc::VideoDecoder> webrtc::VideoDecoder* RTCVideoDecoderFactory::CreateVideoDecoder(
RTCVideoDecoderFactory::CreateVideoDecoder( webrtc::VideoCodecType type) {
const webrtc::SdpVideoFormat& format) {
DVLOG(2) << __func__; DVLOG(2) << __func__;
std::unique_ptr<webrtc::VideoDecoder> decoder;
if (base::FeatureList::IsEnabled(media::kRTCVideoDecoderAdapter)) { if (base::FeatureList::IsEnabled(media::kRTCVideoDecoderAdapter)) {
decoder = RTCVideoDecoderAdapter::Create( return RTCVideoDecoderAdapter::Create(gpu_factories_, type).release();
gpu_factories_, webrtc::PayloadStringToCodecType(format.name));
} else { } else {
decoder = RTCVideoDecoder::Create( return RTCVideoDecoder::Create(type, gpu_factories_).release();
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>( void RTCVideoDecoderFactory::DestroyVideoDecoder(
gpu_factories_->GetTaskRunner(), std::move(decoder)) webrtc::VideoDecoder* decoder) {
: nullptr; DVLOG(2) << __func__;
gpu_factories_->GetTaskRunner()->DeleteSoon(FROM_HERE, decoder);
} }
} // 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/api/video_codecs/video_decoder_factory.h" #include "third_party/webrtc/media/engine/webrtcvideodecoderfactory.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 webrtc::VideoDecoderFactory { : public cricket::WebRtcVideoDecoderFactory {
public: public:
explicit RTCVideoDecoderFactory( explicit RTCVideoDecoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories); media::GpuVideoAcceleratorFactories* gpu_factories);
...@@ -31,14 +31,15 @@ class CONTENT_EXPORT RTCVideoDecoderFactory ...@@ -31,14 +31,15 @@ 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.
std::unique_ptr<webrtc::VideoDecoder> CreateVideoDecoder( webrtc::VideoDecoder* CreateVideoDecoder(
const webrtc::SdpVideoFormat& format) override; webrtc::VideoCodecType type) override;
std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override; // Runs on Chrome_libJingle_WorkerThread. The child thread is blocked while
// 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,24 +14,23 @@ ...@@ -14,24 +14,23 @@
#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
// webrtc::SdpVideoFormat, or return nothing if the profile isn't supported. // cricket::WebRtcVideoEncoderFactory::VideoCodec, or return nothing if the
base::Optional<webrtc::SdpVideoFormat> VEAToWebRTCFormat( // profile isn't supported.
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 webrtc::SdpVideoFormat("VP8"); return base::Optional<cricket::VideoCodec>(cricket::VideoCodec("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) {
...@@ -66,7 +65,7 @@ base::Optional<webrtc::SdpVideoFormat> VEAToWebRTCFormat( ...@@ -66,7 +65,7 @@ base::Optional<webrtc::SdpVideoFormat> VEAToWebRTCFormat(
break; break;
default: default:
// Unsupported H264 profile in WebRTC. // Unsupported H264 profile in WebRTC.
return base::nullopt; return base::Optional<cricket::VideoCodec>();
} }
const int width = profile.max_resolution.width(); const int width = profile.max_resolution.width();
...@@ -79,22 +78,15 @@ base::Optional<webrtc::SdpVideoFormat> VEAToWebRTCFormat( ...@@ -79,22 +78,15 @@ base::Optional<webrtc::SdpVideoFormat> VEAToWebRTCFormat(
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));
webrtc::SdpVideoFormat format("H264"); cricket::VideoCodec codec("H264");
format.parameters = { codec.SetParam(cricket::kH264FmtpProfileLevelId,
{cricket::kH264FmtpProfileLevelId, *webrtc::H264::ProfileLevelIdToString(profile_level_id));
*webrtc::H264::ProfileLevelIdToString(profile_level_id)}, codec.SetParam(cricket::kH264FmtpLevelAsymmetryAllowed, "1");
{cricket::kH264FmtpLevelAsymmetryAllowed, "1"}, codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
{cricket::kH264FmtpPacketizationMode, "1"}}; return base::Optional<cricket::VideoCodec>(codec);
return format;
} }
} }
return base::nullopt; return base::Optional<cricket::VideoCodec>();
}
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
...@@ -105,39 +97,47 @@ RTCVideoEncoderFactory::RTCVideoEncoderFactory( ...@@ -105,39 +97,47 @@ 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<webrtc::SdpVideoFormat> format = VEAToWebRTCFormat(profile); base::Optional<cricket::VideoCodec> codec = VEAToWebRTCCodec(profile);
if (format) { if (codec) {
supported_formats_.push_back(std::move(*format)); supported_codecs_.push_back(std::move(*codec));
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() {}
std::unique_ptr<webrtc::VideoEncoder> webrtc::VideoEncoder* RTCVideoEncoderFactory::CreateVideoEncoder(
RTCVideoEncoderFactory::CreateVideoEncoder( const cricket::VideoCodec& codec) {
const webrtc::SdpVideoFormat& format) { for (size_t i = 0; i < supported_codecs_.size(); ++i) {
for (size_t i = 0; i < supported_formats_.size(); ++i) { if (!cricket::CodecNamesEq(codec.name, supported_codecs_[i].name))
if (IsSameFormat(format, supported_formats_[i])) { continue;
return std::make_unique<RTCVideoEncoder>(profiles_[i], gpu_factories_); // Check H264 profile.
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;
} }
std::vector<webrtc::SdpVideoFormat> const std::vector<cricket::VideoCodec>&
RTCVideoEncoderFactory::GetSupportedFormats() const { RTCVideoEncoderFactory::supported_codecs() const {
return supported_formats_; return supported_codecs_;
} }
webrtc::VideoEncoderFactory::CodecInfo void RTCVideoEncoderFactory::DestroyVideoEncoder(
RTCVideoEncoderFactory::QueryVideoEncoder( webrtc::VideoEncoder* encoder) {
const webrtc::SdpVideoFormat& format) const { delete encoder;
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/api/video_codecs/video_encoder_factory.h" #include "third_party/webrtc/media/engine/webrtcvideoencoderfactory.h"
namespace media { namespace media {
class GpuVideoAcceleratorFactories; class GpuVideoAcceleratorFactories;
...@@ -23,27 +23,26 @@ namespace content { ...@@ -23,27 +23,26 @@ 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 webrtc::VideoEncoderFactory { : public cricket::WebRtcVideoEncoderFactory {
public: public:
explicit RTCVideoEncoderFactory( explicit RTCVideoEncoderFactory(
media::GpuVideoAcceleratorFactories* gpu_factories); media::GpuVideoAcceleratorFactories* gpu_factories);
~RTCVideoEncoderFactory() override; ~RTCVideoEncoderFactory() override;
// webrtc::VideoEncoderFactory implementation. // cricket::WebRtcVideoEncoderFactory implementation.
std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder( webrtc::VideoEncoder* CreateVideoEncoder(
const webrtc::SdpVideoFormat& format) override; const cricket::VideoCodec& codec) override;
std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override; const std::vector<cricket::VideoCodec>& supported_codecs() const override;
webrtc::VideoEncoderFactory::CodecInfo QueryVideoEncoder( void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) override;
const webrtc::SdpVideoFormat& format) const override;
private: private:
media::GpuVideoAcceleratorFactories* gpu_factories_; media::GpuVideoAcceleratorFactories* gpu_factories_;
// List of supported webrtc::SdpVideoFormat. |profiles_| and // List of supported cricket::WebRtcVideoEncoderFactory::VideoCodec.
// |supported_formats_| have the same length and the profile for // |profiles_| and |supported_codecs_| have the same length and the profile
// |supported_formats_[i]| is |profiles_[i]|. // for |supported_codecs_[i]| is |profiles_[i]|.
std::vector<media::VideoCodecProfile> profiles_; std::vector<media::VideoCodecProfile> profiles_;
std::vector<webrtc::SdpVideoFormat> supported_formats_; std::vector<cricket::VideoCodec> supported_codecs_;
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