summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc/libwebrtcglue/WebrtcVideoCodecFactory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/webrtc/libwebrtcglue/WebrtcVideoCodecFactory.cpp')
-rw-r--r--dom/media/webrtc/libwebrtcglue/WebrtcVideoCodecFactory.cpp139
1 files changed, 139 insertions, 0 deletions
diff --git a/dom/media/webrtc/libwebrtcglue/WebrtcVideoCodecFactory.cpp b/dom/media/webrtc/libwebrtcglue/WebrtcVideoCodecFactory.cpp
new file mode 100644
index 0000000000..6acec07ea3
--- /dev/null
+++ b/dom/media/webrtc/libwebrtcglue/WebrtcVideoCodecFactory.cpp
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "WebrtcVideoCodecFactory.h"
+
+#include "GmpVideoCodec.h"
+#include "MediaDataCodec.h"
+#include "VideoConduit.h"
+#include "mozilla/StaticPrefs_media.h"
+
+// libwebrtc includes
+#include "api/rtp_headers.h"
+#include "api/video_codecs/video_codec.h"
+#include "api/video_codecs/video_encoder_software_fallback_wrapper.h"
+#include "media/engine/encoder_simulcast_proxy.h"
+#include "modules/video_coding/codecs/vp8/include/vp8.h"
+#include "modules/video_coding/codecs/vp9/include/vp9.h"
+
+namespace mozilla {
+
+std::unique_ptr<webrtc::VideoDecoder>
+WebrtcVideoDecoderFactory::CreateVideoDecoder(
+ const webrtc::SdpVideoFormat& aFormat) {
+ std::unique_ptr<webrtc::VideoDecoder> decoder;
+ auto type = webrtc::PayloadStringToCodecType(aFormat.name);
+
+ // Attempt to create a decoder using MediaDataDecoder.
+ decoder.reset(MediaDataCodec::CreateDecoder(type, mTrackingId));
+ if (decoder) {
+ return decoder;
+ }
+
+ switch (type) {
+ case webrtc::VideoCodecType::kVideoCodecH264: {
+ // Get an external decoder
+ auto gmpDecoder =
+ WrapUnique(GmpVideoCodec::CreateDecoder(mPCHandle, mTrackingId));
+ mCreatedGmpPluginEvent.Forward(*gmpDecoder->InitPluginEvent());
+ mReleasedGmpPluginEvent.Forward(*gmpDecoder->ReleasePluginEvent());
+ decoder.reset(gmpDecoder.release());
+ break;
+ }
+
+ // Use libvpx decoders as fallbacks.
+ case webrtc::VideoCodecType::kVideoCodecVP8:
+ if (!decoder) {
+ decoder = webrtc::VP8Decoder::Create();
+ }
+ break;
+ case webrtc::VideoCodecType::kVideoCodecVP9:
+ decoder = webrtc::VP9Decoder::Create();
+ break;
+
+ default:
+ break;
+ }
+
+ return decoder;
+}
+
+std::unique_ptr<webrtc::VideoEncoder>
+WebrtcVideoEncoderFactory::CreateVideoEncoder(
+ const webrtc::SdpVideoFormat& aFormat) {
+ if (!mInternalFactory->Supports(aFormat)) {
+ return nullptr;
+ }
+ auto type = webrtc::PayloadStringToCodecType(aFormat.name);
+ switch (type) {
+ case webrtc::VideoCodecType::kVideoCodecVP8:
+ // XXX We might be able to use the simulcast proxy for more codecs, but
+ // that requires testing.
+ return std::make_unique<webrtc::EncoderSimulcastProxy>(
+ mInternalFactory.get(), aFormat);
+ default:
+ return mInternalFactory->CreateVideoEncoder(aFormat);
+ }
+}
+
+bool WebrtcVideoEncoderFactory::InternalFactory::Supports(
+ const webrtc::SdpVideoFormat& aFormat) {
+ switch (webrtc::PayloadStringToCodecType(aFormat.name)) {
+ case webrtc::VideoCodecType::kVideoCodecVP8:
+ case webrtc::VideoCodecType::kVideoCodecVP9:
+ case webrtc::VideoCodecType::kVideoCodecH264:
+ return true;
+ default:
+ return false;
+ }
+}
+
+std::unique_ptr<webrtc::VideoEncoder>
+WebrtcVideoEncoderFactory::InternalFactory::CreateVideoEncoder(
+ const webrtc::SdpVideoFormat& aFormat) {
+ MOZ_ASSERT(Supports(aFormat));
+
+ std::unique_ptr<webrtc::VideoEncoder> platformEncoder;
+ platformEncoder.reset(MediaDataCodec::CreateEncoder(aFormat));
+ const bool fallback = StaticPrefs::media_webrtc_software_encoder_fallback();
+ if (!fallback && platformEncoder) {
+ return platformEncoder;
+ }
+
+ std::unique_ptr<webrtc::VideoEncoder> encoder;
+ switch (webrtc::PayloadStringToCodecType(aFormat.name)) {
+ case webrtc::VideoCodecType::kVideoCodecH264: {
+ // get an external encoder
+ auto gmpEncoder =
+ WrapUnique(GmpVideoCodec::CreateEncoder(aFormat, mPCHandle));
+ mCreatedGmpPluginEvent.Forward(*gmpEncoder->InitPluginEvent());
+ mReleasedGmpPluginEvent.Forward(*gmpEncoder->ReleasePluginEvent());
+ encoder.reset(gmpEncoder.release());
+ break;
+ }
+ // libvpx fallbacks.
+ case webrtc::VideoCodecType::kVideoCodecVP8:
+ if (!encoder) {
+ encoder = webrtc::VP8Encoder::Create();
+ }
+ break;
+ case webrtc::VideoCodecType::kVideoCodecVP9:
+ encoder = webrtc::VP9Encoder::Create();
+ break;
+
+ default:
+ break;
+ }
+ if (fallback && encoder && platformEncoder) {
+ return webrtc::CreateVideoEncoderSoftwareFallbackWrapper(
+ std::move(encoder), std::move(platformEncoder), false);
+ }
+ if (platformEncoder) {
+ return platformEncoder;
+ }
+ return encoder;
+}
+
+} // namespace mozilla