1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "third_party/blink/renderer/platform/peerconnection/video_codec_factory.h"
6 
7 #include "base/memory/ptr_util.h"
8 #include "build/build_config.h"
9 #include "media/video/gpu_video_accelerator_factories.h"
10 #include "third_party/blink/public/platform/platform.h"
11 #include "third_party/blink/renderer/platform/peerconnection/rtc_video_decoder_factory.h"
12 #include "third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.h"
13 #include "third_party/webrtc/api/video_codecs/video_decoder_software_fallback_wrapper.h"
14 #include "third_party/webrtc/api/video_codecs/video_encoder_software_fallback_wrapper.h"
15 #include "third_party/webrtc/media/base/codec.h"
16 #include "third_party/webrtc/media/engine/encoder_simulcast_proxy.h"
17 #include "third_party/webrtc/media/engine/internal_decoder_factory.h"
18 #include "third_party/webrtc/media/engine/internal_encoder_factory.h"
19 #include "third_party/webrtc/media/engine/simulcast_encoder_adapter.h"
20 
21 #if defined(OS_ANDROID)
22 #include "media/base/android/media_codec_util.h"
23 #endif
24 
25 namespace blink {
26 
27 namespace {
28 
IsFormatSupported(const std::vector<webrtc::SdpVideoFormat> & supported_formats,const webrtc::SdpVideoFormat & format)29 bool IsFormatSupported(
30     const std::vector<webrtc::SdpVideoFormat>& supported_formats,
31     const webrtc::SdpVideoFormat& format) {
32   for (const webrtc::SdpVideoFormat& supported_format : supported_formats) {
33     if (cricket::IsSameCodec(format.name, format.parameters,
34                              supported_format.name,
35                              supported_format.parameters)) {
36       return true;
37     }
38   }
39   return false;
40 }
41 
42 template <typename Factory>
IsFormatSupported(const Factory * factory,const webrtc::SdpVideoFormat & format)43 bool IsFormatSupported(const Factory* factory,
44                        const webrtc::SdpVideoFormat& format) {
45   return factory && IsFormatSupported(factory->GetSupportedFormats(), format);
46 }
47 
48 // Merge |formats1| and |formats2|, but avoid adding duplicate formats.
MergeFormats(std::vector<webrtc::SdpVideoFormat> formats1,const std::vector<webrtc::SdpVideoFormat> & formats2)49 std::vector<webrtc::SdpVideoFormat> MergeFormats(
50     std::vector<webrtc::SdpVideoFormat> formats1,
51     const std::vector<webrtc::SdpVideoFormat>& formats2) {
52   for (const webrtc::SdpVideoFormat& format : formats2) {
53     // Don't add same format twice.
54     if (!IsFormatSupported(formats1, format))
55       formats1.push_back(format);
56   }
57   return formats1;
58 }
59 
CreateDecoder(webrtc::VideoDecoderFactory * factory,const webrtc::SdpVideoFormat & format)60 std::unique_ptr<webrtc::VideoDecoder> CreateDecoder(
61     webrtc::VideoDecoderFactory* factory,
62     const webrtc::SdpVideoFormat& format) {
63   return factory ? factory->CreateVideoDecoder(format) : nullptr;
64 }
65 
Wrap(std::unique_ptr<webrtc::VideoDecoder> software_decoder,std::unique_ptr<webrtc::VideoDecoder> hardware_decoder)66 std::unique_ptr<webrtc::VideoDecoder> Wrap(
67     std::unique_ptr<webrtc::VideoDecoder> software_decoder,
68     std::unique_ptr<webrtc::VideoDecoder> hardware_decoder) {
69   if (software_decoder && hardware_decoder) {
70     return webrtc::CreateVideoDecoderSoftwareFallbackWrapper(
71         std::move(software_decoder), std::move(hardware_decoder));
72   }
73   return hardware_decoder ? std::move(hardware_decoder)
74                           : std::move(software_decoder);
75 }
76 
Wrap(std::unique_ptr<webrtc::VideoEncoder> software_encoder,std::unique_ptr<webrtc::VideoEncoder> hardware_encoder)77 std::unique_ptr<webrtc::VideoEncoder> Wrap(
78     std::unique_ptr<webrtc::VideoEncoder> software_encoder,
79     std::unique_ptr<webrtc::VideoEncoder> hardware_encoder) {
80   if (software_encoder && hardware_encoder) {
81     return webrtc::CreateVideoEncoderSoftwareFallbackWrapper(
82         std::move(software_encoder), std::move(hardware_encoder));
83   }
84   return hardware_encoder ? std::move(hardware_encoder)
85                           : std::move(software_encoder);
86 }
87 
88 // This class combines a hardware factory with the internal factory and adds
89 // internal SW codecs, simulcast, and SW fallback wrappers.
90 class EncoderAdapter : public webrtc::VideoEncoderFactory {
91  public:
EncoderAdapter(std::unique_ptr<webrtc::VideoEncoderFactory> hardware_encoder_factory)92   explicit EncoderAdapter(
93       std::unique_ptr<webrtc::VideoEncoderFactory> hardware_encoder_factory)
94       : hardware_encoder_factory_(std::move(hardware_encoder_factory)) {}
95 
QueryVideoEncoder(const webrtc::SdpVideoFormat & format) const96   webrtc::VideoEncoderFactory::CodecInfo QueryVideoEncoder(
97       const webrtc::SdpVideoFormat& format) const override {
98     const webrtc::VideoEncoderFactory* factory =
99         IsFormatSupported(hardware_encoder_factory_.get(), format)
100             ? hardware_encoder_factory_.get()
101             : &software_encoder_factory_;
102     return factory->QueryVideoEncoder(format);
103   }
104 
CreateVideoEncoder(const webrtc::SdpVideoFormat & format)105   std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(
106       const webrtc::SdpVideoFormat& format) override {
107     const bool supported_in_software =
108         IsFormatSupported(&software_encoder_factory_, format);
109     const bool supported_in_hardware =
110         IsFormatSupported(hardware_encoder_factory_.get(), format);
111 
112     if (!supported_in_software && !supported_in_hardware)
113       return nullptr;
114 
115     if (base::EqualsCaseInsensitiveASCII(format.name.c_str(),
116                                          cricket::kVp9CodecName) ||
117         base::EqualsCaseInsensitiveASCII(format.name.c_str(),
118                                          cricket::kAv1CodecName)) {
119       // For VP9 and AV1 we don't use simulcast.
120       if (supported_in_hardware && supported_in_software) {
121         return Wrap(software_encoder_factory_.CreateVideoEncoder(format),
122                     hardware_encoder_factory_->CreateVideoEncoder(format));
123       } else if (supported_in_software) {
124         return software_encoder_factory_.CreateVideoEncoder(format);
125       }
126       return hardware_encoder_factory_->CreateVideoEncoder(format);
127     }
128 
129     if (!supported_in_hardware || !hardware_encoder_factory_.get()) {
130       return std::make_unique<webrtc::SimulcastEncoderAdapter>(
131           &software_encoder_factory_, nullptr, format);
132     } else if (!supported_in_software) {
133       return std::make_unique<webrtc::SimulcastEncoderAdapter>(
134           hardware_encoder_factory_.get(), nullptr, format);
135     }
136 
137     return std::make_unique<webrtc::SimulcastEncoderAdapter>(
138         hardware_encoder_factory_.get(), &software_encoder_factory_, format);
139   }
140 
GetSupportedFormats() const141   std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override {
142     std::vector<webrtc::SdpVideoFormat> software_formats =
143         software_encoder_factory_.GetSupportedFormats();
144     return hardware_encoder_factory_
145                ? MergeFormats(software_formats,
146                               hardware_encoder_factory_->GetSupportedFormats())
147                : software_formats;
148   }
149 
150  private:
151   webrtc::InternalEncoderFactory software_encoder_factory_;
152   const std::unique_ptr<webrtc::VideoEncoderFactory> hardware_encoder_factory_;
153 };
154 
155 // This class combines a hardware codec factory with the internal factory and
156 // adds internal SW codecs and SW fallback wrappers.
157 class DecoderAdapter : public webrtc::VideoDecoderFactory {
158  public:
DecoderAdapter(std::unique_ptr<webrtc::VideoDecoderFactory> hardware_decoder_factory)159   explicit DecoderAdapter(
160       std::unique_ptr<webrtc::VideoDecoderFactory> hardware_decoder_factory)
161       : hardware_decoder_factory_(std::move(hardware_decoder_factory)) {}
162 
CreateVideoDecoder(const webrtc::SdpVideoFormat & format)163   std::unique_ptr<webrtc::VideoDecoder> CreateVideoDecoder(
164       const webrtc::SdpVideoFormat& format) override {
165     std::unique_ptr<webrtc::VideoDecoder> software_decoder =
166         CreateDecoder(&software_decoder_factory_, format);
167 
168     std::unique_ptr<webrtc::VideoDecoder> hardware_decoder =
169         CreateDecoder(hardware_decoder_factory_.get(), format);
170 
171     return Wrap(std::move(software_decoder), std::move(hardware_decoder));
172   }
173 
GetSupportedFormats() const174   std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override {
175     std::vector<webrtc::SdpVideoFormat> software_formats =
176         software_decoder_factory_.GetSupportedFormats();
177     return hardware_decoder_factory_
178                ? MergeFormats(software_formats,
179                               hardware_decoder_factory_->GetSupportedFormats())
180                : software_formats;
181   }
182 
183  private:
184   webrtc::InternalDecoderFactory software_decoder_factory_;
185   const std::unique_ptr<webrtc::VideoDecoderFactory> hardware_decoder_factory_;
186 };
187 
188 }  // namespace
189 
CreateHWVideoEncoderFactory(media::GpuVideoAcceleratorFactories * gpu_factories)190 std::unique_ptr<webrtc::VideoEncoderFactory> CreateHWVideoEncoderFactory(
191     media::GpuVideoAcceleratorFactories* gpu_factories) {
192   std::unique_ptr<webrtc::VideoEncoderFactory> encoder_factory;
193 
194   if (gpu_factories && gpu_factories->IsGpuVideoAcceleratorEnabled() &&
195       Platform::Current()->IsWebRtcHWEncodingEnabled()) {
196     encoder_factory = std::make_unique<RTCVideoEncoderFactory>(gpu_factories);
197   }
198 
199 #if defined(OS_ANDROID)
200   if (!media::MediaCodecUtil::SupportsSetParameters())
201     encoder_factory.reset();
202 #endif
203 
204   return encoder_factory;
205 }
206 
CreateWebrtcVideoEncoderFactory(media::GpuVideoAcceleratorFactories * gpu_factories)207 std::unique_ptr<webrtc::VideoEncoderFactory> CreateWebrtcVideoEncoderFactory(
208     media::GpuVideoAcceleratorFactories* gpu_factories) {
209   return std::make_unique<EncoderAdapter>(
210       CreateHWVideoEncoderFactory(gpu_factories));
211 }
212 
CreateWebrtcVideoDecoderFactory(media::GpuVideoAcceleratorFactories * gpu_factories)213 std::unique_ptr<webrtc::VideoDecoderFactory> CreateWebrtcVideoDecoderFactory(
214     media::GpuVideoAcceleratorFactories* gpu_factories) {
215   std::unique_ptr<webrtc::VideoDecoderFactory> decoder_factory;
216 
217   if (gpu_factories && gpu_factories->IsGpuVideoAcceleratorEnabled() &&
218       Platform::Current()->IsWebRtcHWDecodingEnabled()) {
219     decoder_factory = std::make_unique<RTCVideoDecoderFactory>(gpu_factories);
220   }
221 
222   return std::make_unique<DecoderAdapter>(std::move(decoder_factory));
223 }
224 
225 }  // namespace blink
226