1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "WebrtcVideoCodecFactory.h" 7 8 #include "GmpVideoCodec.h" 9 #include "MediaDataCodec.h" 10 #include "VideoConduit.h" 11 #include "mozilla/StaticPrefs_media.h" 12 13 // libwebrtc includes 14 #include "api/rtp_headers.h" 15 #include "api/video_codecs/video_codec.h" 16 #include "api/video_codecs/video_encoder_software_fallback_wrapper.h" 17 #include "media/engine/encoder_simulcast_proxy.h" 18 #include "modules/video_coding/codecs/vp8/include/vp8.h" 19 #include "modules/video_coding/codecs/vp9/include/vp9.h" 20 21 namespace mozilla { 22 23 std::unique_ptr<webrtc::VideoDecoder> CreateVideoDecoder(const webrtc::SdpVideoFormat & aFormat)24WebrtcVideoDecoderFactory::CreateVideoDecoder( 25 const webrtc::SdpVideoFormat& aFormat) { 26 std::unique_ptr<webrtc::VideoDecoder> decoder; 27 auto type = webrtc::PayloadStringToCodecType(aFormat.name); 28 29 // Attempt to create a decoder using MediaDataDecoder. 30 decoder.reset(MediaDataCodec::CreateDecoder(type)); 31 if (decoder) { 32 return decoder; 33 } 34 35 switch (type) { 36 case webrtc::VideoCodecType::kVideoCodecH264: { 37 // Get an external decoder 38 auto gmpDecoder = WrapUnique(GmpVideoCodec::CreateDecoder(mPCHandle)); 39 mCreatedGmpPluginEvent.Forward(*gmpDecoder->InitPluginEvent()); 40 mReleasedGmpPluginEvent.Forward(*gmpDecoder->ReleasePluginEvent()); 41 decoder.reset(gmpDecoder.release()); 42 break; 43 } 44 45 // Use libvpx decoders as fallbacks. 46 case webrtc::VideoCodecType::kVideoCodecVP8: 47 if (!decoder) { 48 decoder = webrtc::VP8Decoder::Create(); 49 } 50 break; 51 case webrtc::VideoCodecType::kVideoCodecVP9: 52 decoder = webrtc::VP9Decoder::Create(); 53 break; 54 55 default: 56 break; 57 } 58 59 return decoder; 60 } 61 62 std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(const webrtc::SdpVideoFormat & aFormat)63WebrtcVideoEncoderFactory::CreateVideoEncoder( 64 const webrtc::SdpVideoFormat& aFormat) { 65 if (!mInternalFactory->Supports(aFormat)) { 66 return nullptr; 67 } 68 auto type = webrtc::PayloadStringToCodecType(aFormat.name); 69 switch (type) { 70 case webrtc::VideoCodecType::kVideoCodecVP8: 71 // XXX We might be able to use the simulcast proxy for more codecs, but 72 // that requires testing. 73 return std::make_unique<webrtc::EncoderSimulcastProxy>( 74 mInternalFactory.get(), aFormat); 75 default: 76 return mInternalFactory->CreateVideoEncoder(aFormat); 77 } 78 } 79 Supports(const webrtc::SdpVideoFormat & aFormat)80bool WebrtcVideoEncoderFactory::InternalFactory::Supports( 81 const webrtc::SdpVideoFormat& aFormat) { 82 switch (webrtc::PayloadStringToCodecType(aFormat.name)) { 83 case webrtc::VideoCodecType::kVideoCodecVP8: 84 case webrtc::VideoCodecType::kVideoCodecVP9: 85 case webrtc::VideoCodecType::kVideoCodecH264: 86 return true; 87 default: 88 return false; 89 } 90 } 91 92 std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(const webrtc::SdpVideoFormat & aFormat)93WebrtcVideoEncoderFactory::InternalFactory::CreateVideoEncoder( 94 const webrtc::SdpVideoFormat& aFormat) { 95 MOZ_ASSERT(Supports(aFormat)); 96 97 std::unique_ptr<webrtc::VideoEncoder> platformEncoder; 98 platformEncoder.reset(MediaDataCodec::CreateEncoder(aFormat)); 99 const bool fallback = StaticPrefs::media_webrtc_software_encoder_fallback(); 100 if (!fallback && platformEncoder) { 101 return platformEncoder; 102 } 103 104 std::unique_ptr<webrtc::VideoEncoder> encoder; 105 switch (webrtc::PayloadStringToCodecType(aFormat.name)) { 106 case webrtc::VideoCodecType::kVideoCodecH264: { 107 // get an external encoder 108 auto gmpEncoder = WrapUnique(GmpVideoCodec::CreateEncoder(mPCHandle)); 109 mCreatedGmpPluginEvent.Forward(*gmpEncoder->InitPluginEvent()); 110 mReleasedGmpPluginEvent.Forward(*gmpEncoder->ReleasePluginEvent()); 111 encoder.reset(gmpEncoder.release()); 112 break; 113 } 114 // libvpx fallbacks. 115 case webrtc::VideoCodecType::kVideoCodecVP8: 116 if (!encoder) { 117 encoder = webrtc::VP8Encoder::Create(); 118 } 119 break; 120 case webrtc::VideoCodecType::kVideoCodecVP9: 121 encoder = webrtc::VP9Encoder::Create(); 122 break; 123 124 default: 125 break; 126 } 127 if (fallback && encoder && platformEncoder) { 128 return webrtc::CreateVideoEncoderSoftwareFallbackWrapper( 129 std::move(encoder), std::move(platformEncoder), false); 130 } 131 if (platformEncoder) { 132 return platformEncoder; 133 } 134 return encoder; 135 } 136 137 } // namespace mozilla 138