blob: 6495e277c4ae8203ce8ddc2961966050534a8126 [file] [log] [blame]
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "media/engine/convert_legacy_video_factory.h"
#include <utility>
#include <vector>
#include "api/video_codecs/video_decoder_factory.h"
#include "api/video_codecs/video_encoder_factory.h"
#include "media/engine/internaldecoderfactory.h"
#include "media/engine/internalencoderfactory.h"
#include "media/engine/scopedvideodecoder.h"
#include "media/engine/scopedvideoencoder.h"
#include "media/engine/simulcast_encoder_adapter.h"
#include "media/engine/videodecodersoftwarefallbackwrapper.h"
#include "media/engine/videoencodersoftwarefallbackwrapper.h"
#include "media/engine/vp8_encoder_simulcast_proxy.h"
#include "media/engine/webrtcvideodecoderfactory.h"
#include "media/engine/webrtcvideoencoderfactory.h"
#include "rtc_base/checks.h"
namespace cricket {
namespace {
class EncoderAdapter : public webrtc::VideoEncoderFactory {
public:
explicit EncoderAdapter(
std::unique_ptr<WebRtcVideoEncoderFactory> external_encoder_factory)
: internal_encoder_factory_(new InternalEncoderFactory()),
external_encoder_factory_(std::move(external_encoder_factory)) {}
webrtc::VideoEncoderFactory::CodecInfo QueryVideoEncoder(
const webrtc::SdpVideoFormat& format) const {
const VideoCodec codec(format);
if (external_encoder_factory_ != nullptr &&
FindMatchingCodec(external_encoder_factory_->supported_codecs(),
codec)) {
// Format is supported by the external factory.
const webrtc::VideoCodecType codec_type =
webrtc::PayloadStringToCodecType(codec.name);
webrtc::VideoEncoderFactory::CodecInfo info;
info.has_internal_source =
external_encoder_factory_->EncoderTypeHasInternalSource(codec_type);
info.is_hardware_accelerated = true;
return info;
}
// Format must be one of the internal formats.
RTC_DCHECK(FindMatchingCodec(internal_encoder_factory_->supported_codecs(),
codec));
webrtc::VideoEncoderFactory::CodecInfo info;
info.has_internal_source = false;
info.is_hardware_accelerated = false;
return info;
}
std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(
const webrtc::SdpVideoFormat& format) {
const VideoCodec codec(format);
// Try creating external encoder.
if (external_encoder_factory_ != nullptr &&
FindMatchingCodec(external_encoder_factory_->supported_codecs(),
codec)) {
std::unique_ptr<webrtc::VideoEncoder> external_encoder;
if (CodecNamesEq(codec.name.c_str(), kVp8CodecName)) {
// If it's a codec type we can simulcast, create a wrapped encoder.
external_encoder = std::unique_ptr<webrtc::VideoEncoder>(
new webrtc::SimulcastEncoderAdapter(
external_encoder_factory_.get()));
} else {
external_encoder =
CreateScopedVideoEncoder(external_encoder_factory_.get(), codec);
}
if (external_encoder) {
return std::unique_ptr<webrtc::VideoEncoder>(
new webrtc::VideoEncoderSoftwareFallbackWrapper(
codec, std::move(external_encoder)));
}
}
// Try creating internal encoder.
if (FindMatchingCodec(internal_encoder_factory_->supported_codecs(),
codec)) {
if (CodecNamesEq(codec.name.c_str(), kVp8CodecName)) {
return std::unique_ptr<webrtc::VideoEncoder>(
new webrtc::VP8EncoderSimulcastProxy(
internal_encoder_factory_.get()));
} else {
return std::unique_ptr<webrtc::VideoEncoder>(
internal_encoder_factory_->CreateVideoEncoder(codec));
}
}
// This shouldn't happen, we should not be trying to create something we
// don't support.
RTC_NOTREACHED();
return nullptr;
}
std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const {
std::vector<VideoCodec> codecs =
InternalEncoderFactory().supported_codecs();
// Add external codecs.
if (external_encoder_factory_ != nullptr) {
const std::vector<VideoCodec>& external_codecs =
external_encoder_factory_->supported_codecs();
for (const VideoCodec& codec : external_codecs) {
// Don't add same codec twice.
if (!FindMatchingCodec(codecs, codec))
codecs.push_back(codec);
}
}
std::vector<webrtc::SdpVideoFormat> formats;
for (const VideoCodec& codec : codecs) {
formats.push_back(webrtc::SdpVideoFormat(codec.name, codec.params));
}
return formats;
}
private:
const std::unique_ptr<WebRtcVideoEncoderFactory> internal_encoder_factory_;
const std::unique_ptr<WebRtcVideoEncoderFactory> external_encoder_factory_;
};
class DecoderAdapter : public webrtc::VideoDecoderFactory {
public:
explicit DecoderAdapter(
std::unique_ptr<WebRtcVideoDecoderFactory> external_decoder_factory)
: internal_decoder_factory_(new InternalDecoderFactory()),
external_decoder_factory_(std::move(external_decoder_factory)) {}
std::unique_ptr<webrtc::VideoDecoder> CreateVideoDecoder(
const webrtc::SdpVideoFormat& format) override {
const VideoCodec codec(format);
const VideoDecoderParams params = {};
if (external_decoder_factory_ != nullptr) {
std::unique_ptr<webrtc::VideoDecoder> external_decoder =
CreateScopedVideoDecoder(external_decoder_factory_.get(), codec,
params);
if (external_decoder) {
webrtc::VideoCodecType type =
webrtc::PayloadStringToCodecType(codec.name);
std::unique_ptr<webrtc::VideoDecoder> internal_decoder(
new webrtc::VideoDecoderSoftwareFallbackWrapper(
type, std::move(external_decoder)));
return internal_decoder;
}
}
std::unique_ptr<webrtc::VideoDecoder> internal_decoder(
internal_decoder_factory_->CreateVideoDecoderWithParams(codec, params));
return internal_decoder;
}
std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override {
// This is not implemented for the legacy decoder factory.
RTC_NOTREACHED();
return std::vector<webrtc::SdpVideoFormat>();
}
private:
const std::unique_ptr<WebRtcVideoDecoderFactory> internal_decoder_factory_;
const std::unique_ptr<WebRtcVideoDecoderFactory> external_decoder_factory_;
};
} // namespace
std::unique_ptr<webrtc::VideoEncoderFactory> ConvertVideoEncoderFactory(
std::unique_ptr<WebRtcVideoEncoderFactory> external_encoder_factory) {
return std::unique_ptr<webrtc::VideoEncoderFactory>(
new EncoderAdapter(std::move(external_encoder_factory)));
}
std::unique_ptr<webrtc::VideoDecoderFactory> ConvertVideoDecoderFactory(
std::unique_ptr<WebRtcVideoDecoderFactory> external_decoder_factory) {
return std::unique_ptr<webrtc::VideoDecoderFactory>(
new DecoderAdapter(std::move(external_decoder_factory)));
}
} // namespace cricket