From 0a375470334181d13f78f249b34351a418450ffd Mon Sep 17 00:00:00 2001 From: Emircan Uysaler Date: Mon, 11 Dec 2017 12:21:02 +0530 Subject: [PATCH] Add optional stereo codec to SDP negotiation - Defines stereo codec case, similar to RTX, that adds stereo codec to the SDP negotiation. The underlying codec's payload type is similarly defined by "apt". - If this negotiation is successful, codec name is included in sdp line via "acn". - Adds codec setting initializers for these specific stereo cases. - Introduces new Stereo*Factory classes as optional convenience wrappers that inserts stereo codec to the existing set of supported codecs on demand. This CL is the step 5 for adding alpha channel support over the wire in webrtc. Design Doc: https://goo.gl/sFeSUT Bug: webrtc:7671 Change-Id: Ie12c56c8fcf7934e216135d73af33adec5248f76 Reviewed-on: https://webrtc-review.googlesource.com/22901 Commit-Queue: Niklas Enbom Reviewed-by: Niklas Enbom Reviewed-by: Magnus Jedvert Cr-Commit-Position: refs/heads/master@{#21210} --- common_types.cc | 11 +- media/BUILD.gn | 4 + media/base/mediaconstants.cc | 2 + media/base/mediaconstants.h | 2 + media/engine/stereocodecfactory.cc | 111 ++++++++++++++++++ media/engine/stereocodecfactory.h | 49 ++++++++ media/engine/stereocodecfactory_unittest.cc | 47 ++++++++ .../stereo/include/stereo_decoder_adapter.h | 5 +- .../stereo/include/stereo_encoder_adapter.h | 5 +- .../codecs/stereo/stereo_decoder_adapter.cc | 13 +- .../codecs/stereo/stereo_encoder_adapter.cc | 24 ++-- .../stereo/test/stereo_adapter_unittest.cc | 21 +++- .../video_coding/video_codec_initializer.cc | 14 +++ .../video_codec_initializer_unittest.cc | 10 +- video/video_receive_stream.cc | 6 + 15 files changed, 298 insertions(+), 26 deletions(-) create mode 100644 media/engine/stereocodecfactory.cc create mode 100644 media/engine/stereocodecfactory.h create mode 100644 media/engine/stereocodecfactory_unittest.cc diff --git a/common_types.cc b/common_types.cc index 0526d59540..f1b2f1e13e 100644 --- a/common_types.cc +++ b/common_types.cc @@ -137,6 +137,7 @@ static const char* kPayloadNameI420 = "I420"; static const char* kPayloadNameRED = "RED"; static const char* kPayloadNameULPFEC = "ULPFEC"; static const char* kPayloadNameGeneric = "Generic"; +static const char* kPayloadNameStereo = "Stereo"; static bool CodecNamesEq(const char* name1, const char* name2) { return _stricmp(name1, name2) == 0; @@ -156,10 +157,14 @@ const char* CodecTypeToPayloadString(VideoCodecType type) { return kPayloadNameRED; case kVideoCodecULPFEC: return kPayloadNameULPFEC; - default: - // Unrecognized codecs default to generic. + // Other codecs default to generic. + case kVideoCodecStereo: + case kVideoCodecFlexfec: + case kVideoCodecGeneric: + case kVideoCodecUnknown: return kPayloadNameGeneric; } + return kPayloadNameGeneric; } VideoCodecType PayloadStringToCodecType(const std::string& name) { @@ -175,6 +180,8 @@ VideoCodecType PayloadStringToCodecType(const std::string& name) { return kVideoCodecRED; if (CodecNamesEq(name.c_str(), kPayloadNameULPFEC)) return kVideoCodecULPFEC; + if (CodecNamesEq(name.c_str(), kPayloadNameStereo)) + return kVideoCodecStereo; return kVideoCodecGeneric; } diff --git a/media/BUILD.gn b/media/BUILD.gn index 754a89aed0..9911ce2437 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn @@ -157,6 +157,8 @@ rtc_static_library("rtc_audio_video") { "engine/simulcast.h", "engine/simulcast_encoder_adapter.cc", "engine/simulcast_encoder_adapter.h", + "engine/stereocodecfactory.cc", + "engine/stereocodecfactory.h", "engine/videodecodersoftwarefallbackwrapper.cc", "engine/videodecodersoftwarefallbackwrapper.h", "engine/videoencodersoftwarefallbackwrapper.cc", @@ -243,6 +245,7 @@ rtc_static_library("rtc_audio_video") { "../modules/video_capture:video_capture_module", "../modules/video_coding", "../modules/video_coding:webrtc_h264", + "../modules/video_coding:webrtc_stereo", "../modules/video_coding:webrtc_vp8", "../modules/video_coding:webrtc_vp9", "../p2p:rtc_p2p", @@ -450,6 +453,7 @@ if (rtc_include_tests) { "engine/payload_type_mapper_unittest.cc", "engine/simulcast_encoder_adapter_unittest.cc", "engine/simulcast_unittest.cc", + "engine/stereocodecfactory_unittest.cc", "engine/videodecodersoftwarefallbackwrapper_unittest.cc", "engine/videoencodersoftwarefallbackwrapper_unittest.cc", "engine/vp8_encoder_simulcast_proxy_unittest.cc", diff --git a/media/base/mediaconstants.cc b/media/base/mediaconstants.cc index 06c172c07c..9496d9f60c 100644 --- a/media/base/mediaconstants.cc +++ b/media/base/mediaconstants.cc @@ -25,6 +25,7 @@ const float kProcessCpuThreshold = 0.10f; const char kRtxCodecName[] = "rtx"; const char kRedCodecName[] = "red"; const char kUlpfecCodecName[] = "ulpfec"; +const char kStereoCodecName[] = "stereo"; // TODO(brandtr): Change this to 'flexfec' when we are confident that the // header format is not changing anymore. @@ -34,6 +35,7 @@ const char kFlexfecCodecName[] = "flexfec-03"; const char kFlexfecFmtpRepairWindow[] = "repair-window"; const char kCodecParamAssociatedPayloadType[] = "apt"; +const char kCodecParamAssociatedCodecName[] = "acn"; const char kOpusCodecName[] = "opus"; const char kIsacCodecName[] = "ISAC"; diff --git a/media/base/mediaconstants.h b/media/base/mediaconstants.h index 106fad0cf4..58a66d917a 100644 --- a/media/base/mediaconstants.h +++ b/media/base/mediaconstants.h @@ -30,11 +30,13 @@ extern const char kRtxCodecName[]; extern const char kRedCodecName[]; extern const char kUlpfecCodecName[]; extern const char kFlexfecCodecName[]; +extern const char kStereoCodecName[]; extern const char kFlexfecFmtpRepairWindow[]; // Codec parameters extern const char kCodecParamAssociatedPayloadType[]; +extern const char kCodecParamAssociatedCodecName[]; extern const char kOpusCodecName[]; extern const char kIsacCodecName[]; diff --git a/media/engine/stereocodecfactory.cc b/media/engine/stereocodecfactory.cc new file mode 100644 index 0000000000..5ffb0c406d --- /dev/null +++ b/media/engine/stereocodecfactory.cc @@ -0,0 +1,111 @@ +/* + * 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/stereocodecfactory.h" + +#include + +#include "api/video_codecs/sdp_video_format.h" +#include "media/base/codec.h" +#include "media/base/mediaconstants.h" +#include "modules/video_coding/codecs/stereo/include/stereo_decoder_adapter.h" +#include "modules/video_coding/codecs/stereo/include/stereo_encoder_adapter.h" +#include "rtc_base/logging.h" + +namespace { + +bool IsStereoCodec(const cricket::VideoCodec& codec) { + return cricket::CodecNamesEq(codec.name.c_str(), cricket::kStereoCodecName); +} + +} // anonymous namespace + +namespace webrtc { + +constexpr const char* kStereoAssociatedCodecName = cricket::kVp9CodecName; + +StereoEncoderFactory::StereoEncoderFactory( + std::unique_ptr factory) + : factory_(std::move(factory)) {} + +std::vector StereoEncoderFactory::GetSupportedFormats() const { + std::vector formats = factory_->GetSupportedFormats(); + for (const auto& format : formats) { + if (cricket::CodecNamesEq(format.name, kStereoAssociatedCodecName)) { + SdpVideoFormat stereo_format = format; + stereo_format.parameters[cricket::kCodecParamAssociatedCodecName] = + format.name; + stereo_format.name = cricket::kStereoCodecName; + formats.push_back(stereo_format); + break; + } + } + return formats; +} + +VideoEncoderFactory::CodecInfo StereoEncoderFactory::QueryVideoEncoder( + const SdpVideoFormat& format) const { + if (!IsStereoCodec(cricket::VideoCodec(format))) + return factory_->QueryVideoEncoder(format); + return factory_->QueryVideoEncoder( + SdpVideoFormat(kStereoAssociatedCodecName)); +} + +std::unique_ptr StereoEncoderFactory::CreateVideoEncoder( + const SdpVideoFormat& format) { + if (!IsStereoCodec(cricket::VideoCodec(format))) + return factory_->CreateVideoEncoder(format); + const auto& it = + format.parameters.find(cricket::kCodecParamAssociatedCodecName); + if (it == format.parameters.end()) { + RTC_LOG(LS_ERROR) << "No assicated codec for stereo."; + return nullptr; + } + SdpVideoFormat associated_format = format; + associated_format.name = it->second; + return std::unique_ptr( + new StereoEncoderAdapter(factory_.get(), associated_format)); +} + +StereoDecoderFactory::StereoDecoderFactory( + std::unique_ptr factory) + : factory_(std::move(factory)) {} + +std::vector StereoDecoderFactory::GetSupportedFormats() const { + std::vector formats = factory_->GetSupportedFormats(); + for (const auto& format : formats) { + if (cricket::CodecNamesEq(format.name, kStereoAssociatedCodecName)) { + SdpVideoFormat stereo_format = format; + stereo_format.parameters[cricket::kCodecParamAssociatedCodecName] = + format.name; + stereo_format.name = cricket::kStereoCodecName; + formats.push_back(stereo_format); + } + } + return formats; +} + +std::unique_ptr StereoDecoderFactory::CreateVideoDecoder( + const SdpVideoFormat& format) { + if (!IsStereoCodec(cricket::VideoCodec(format))) + return factory_->CreateVideoDecoder(format); + const auto& it = + format.parameters.find(cricket::kCodecParamAssociatedCodecName); + if (it == format.parameters.end()) { + RTC_LOG(LS_ERROR) << "No assicated codec for stereo."; + return nullptr; + } + SdpVideoFormat associated_format = format; + associated_format.name = it->second; + return std::unique_ptr( + new StereoDecoderAdapter(factory_.get(), associated_format)); +} + +} // namespace webrtc diff --git a/media/engine/stereocodecfactory.h b/media/engine/stereocodecfactory.h new file mode 100644 index 0000000000..468d2faf0b --- /dev/null +++ b/media/engine/stereocodecfactory.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#ifndef MEDIA_ENGINE_STEREOCODECFACTORY_H_ +#define MEDIA_ENGINE_STEREOCODECFACTORY_H_ + +#include +#include + +#include "api/video_codecs/video_decoder_factory.h" +#include "api/video_codecs/video_encoder_factory.h" + +namespace webrtc { + +class StereoEncoderFactory : public VideoEncoderFactory { + public: + explicit StereoEncoderFactory(std::unique_ptr factory); + + std::vector GetSupportedFormats() const override; + CodecInfo QueryVideoEncoder(const SdpVideoFormat& format) const override; + std::unique_ptr CreateVideoEncoder( + const SdpVideoFormat& format) override; + + private: + std::unique_ptr factory_; +}; + +class StereoDecoderFactory : public VideoDecoderFactory { + public: + explicit StereoDecoderFactory(std::unique_ptr factory); + + std::vector GetSupportedFormats() const override; + std::unique_ptr CreateVideoDecoder( + const SdpVideoFormat& format) override; + + private: + std::unique_ptr factory_; +}; + +} // namespace webrtc + +#endif // MEDIA_ENGINE_STEREOCODECFACTORY_H_ diff --git a/media/engine/stereocodecfactory_unittest.cc b/media/engine/stereocodecfactory_unittest.cc new file mode 100644 index 0000000000..a86eff04ac --- /dev/null +++ b/media/engine/stereocodecfactory_unittest.cc @@ -0,0 +1,47 @@ +/* + * 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/stereocodecfactory.h" + +#include + +#include "api/video_codecs/sdp_video_format.h" +#include "api/video_codecs/video_decoder.h" +#include "api/video_codecs/video_encoder.h" +#include "media/base/mediaconstants.h" +#include "media/engine/internaldecoderfactory.h" +#include "media/engine/internalencoderfactory.h" +#include "test/gtest.h" + +namespace webrtc { + +TEST(StereoDecoderFactory, CreateVideoDecoder) { + std::unique_ptr internal_factory( + new InternalDecoderFactory()); + StereoDecoderFactory factory(std::move(internal_factory)); + std::unique_ptr decoder = + factory.CreateVideoDecoder(SdpVideoFormat( + cricket::kStereoCodecName, + {{cricket::kCodecParamAssociatedCodecName, cricket::kVp9CodecName}})); + EXPECT_TRUE(decoder); +} + +TEST(StereoEncoderFactory, CreateVideoEncoder) { + std::unique_ptr internal_factory( + new InternalEncoderFactory()); + StereoEncoderFactory factory(std::move(internal_factory)); + std::unique_ptr encoder = + factory.CreateVideoEncoder(SdpVideoFormat( + cricket::kStereoCodecName, + {{cricket::kCodecParamAssociatedCodecName, cricket::kVp9CodecName}})); + EXPECT_TRUE(encoder); +} + +} // namespace webrtc diff --git a/modules/video_coding/codecs/stereo/include/stereo_decoder_adapter.h b/modules/video_coding/codecs/stereo/include/stereo_decoder_adapter.h index 729517fb5d..c6237eece4 100644 --- a/modules/video_coding/codecs/stereo/include/stereo_decoder_adapter.h +++ b/modules/video_coding/codecs/stereo/include/stereo_decoder_adapter.h @@ -15,6 +15,7 @@ #include #include +#include "api/video_codecs/sdp_video_format.h" #include "api/video_codecs/video_decoder.h" #include "api/video_codecs/video_decoder_factory.h" #include "modules/video_coding/codecs/stereo/include/stereo_encoder_adapter.h" @@ -24,7 +25,8 @@ namespace webrtc { class StereoDecoderAdapter : public VideoDecoder { public: // |factory| is not owned and expected to outlive this class' lifetime. - explicit StereoDecoderAdapter(VideoDecoderFactory* factory); + explicit StereoDecoderAdapter(VideoDecoderFactory* factory, + const SdpVideoFormat& associated_format); virtual ~StereoDecoderAdapter(); // Implements VideoDecoder @@ -59,6 +61,7 @@ class StereoDecoderAdapter : public VideoDecoder { const rtc::Optional& stereo_qp); VideoDecoderFactory* const factory_; + const SdpVideoFormat associated_format_; std::vector> decoders_; std::vector> adapter_callbacks_; DecodedImageCallback* decoded_complete_callback_; diff --git a/modules/video_coding/codecs/stereo/include/stereo_encoder_adapter.h b/modules/video_coding/codecs/stereo/include/stereo_encoder_adapter.h index 74ed1a2a2f..95283f19a8 100644 --- a/modules/video_coding/codecs/stereo/include/stereo_encoder_adapter.h +++ b/modules/video_coding/codecs/stereo/include/stereo_encoder_adapter.h @@ -15,6 +15,7 @@ #include #include +#include "api/video_codecs/sdp_video_format.h" #include "api/video_codecs/video_encoder.h" #include "api/video_codecs/video_encoder_factory.h" #include "modules/video_coding/include/video_codec_interface.h" @@ -30,7 +31,8 @@ enum AlphaCodecStream { class StereoEncoderAdapter : public VideoEncoder { public: // |factory| is not owned and expected to outlive this class' lifetime. - explicit StereoEncoderAdapter(VideoEncoderFactory* factory); + explicit StereoEncoderAdapter(VideoEncoderFactory* factory, + const SdpVideoFormat& associated_format); virtual ~StereoEncoderAdapter(); // Implements VideoEncoder @@ -58,6 +60,7 @@ class StereoEncoderAdapter : public VideoEncoder { class AdapterEncodedImageCallback; VideoEncoderFactory* const factory_; + const SdpVideoFormat associated_format_; std::vector> encoders_; std::vector> adapter_callbacks_; EncodedImageCallback* encoded_complete_callback_; diff --git a/modules/video_coding/codecs/stereo/stereo_decoder_adapter.cc b/modules/video_coding/codecs/stereo/stereo_decoder_adapter.cc index caf32996e2..96d55524d4 100644 --- a/modules/video_coding/codecs/stereo/stereo_decoder_adapter.cc +++ b/modules/video_coding/codecs/stereo/stereo_decoder_adapter.cc @@ -12,7 +12,6 @@ #include "api/video/i420_buffer.h" #include "api/video/video_frame_buffer.h" -#include "api/video_codecs/sdp_video_format.h" #include "common_video/include/video_frame.h" #include "common_video/include/video_frame_buffer.h" #include "common_video/libyuv/include/webrtc_libyuv.h" @@ -80,8 +79,10 @@ struct StereoDecoderAdapter::DecodedImageData { RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(DecodedImageData); }; -StereoDecoderAdapter::StereoDecoderAdapter(VideoDecoderFactory* factory) - : factory_(factory) {} +StereoDecoderAdapter::StereoDecoderAdapter( + VideoDecoderFactory* factory, + const SdpVideoFormat& associated_format) + : factory_(factory), associated_format_(associated_format) {} StereoDecoderAdapter::~StereoDecoderAdapter() { Release(); @@ -89,12 +90,12 @@ StereoDecoderAdapter::~StereoDecoderAdapter() { int32_t StereoDecoderAdapter::InitDecode(const VideoCodec* codec_settings, int32_t number_of_cores) { + RTC_DCHECK_EQ(kVideoCodecStereo, codec_settings->codecType); VideoCodec settings = *codec_settings; - settings.codecType = kVideoCodecVP9; + settings.codecType = PayloadStringToCodecType(associated_format_.name); for (size_t i = 0; i < kAlphaCodecStreams; ++i) { - const SdpVideoFormat format("VP9"); std::unique_ptr decoder = - factory_->CreateVideoDecoder(format); + factory_->CreateVideoDecoder(associated_format_); const int32_t rv = decoder->InitDecode(&settings, number_of_cores); if (rv) return rv; diff --git a/modules/video_coding/codecs/stereo/stereo_encoder_adapter.cc b/modules/video_coding/codecs/stereo/stereo_encoder_adapter.cc index ed7a48659e..60e3ea8cee 100644 --- a/modules/video_coding/codecs/stereo/stereo_encoder_adapter.cc +++ b/modules/video_coding/codecs/stereo/stereo_encoder_adapter.cc @@ -10,7 +10,6 @@ #include "modules/video_coding/codecs/stereo/include/stereo_encoder_adapter.h" -#include "api/video_codecs/sdp_video_format.h" #include "common_video/include/video_frame.h" #include "common_video/include/video_frame_buffer.h" #include "common_video/libyuv/include/webrtc_libyuv.h" @@ -58,8 +57,12 @@ struct StereoEncoderAdapter::ImageStereoInfo { RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ImageStereoInfo); }; -StereoEncoderAdapter::StereoEncoderAdapter(VideoEncoderFactory* factory) - : factory_(factory), encoded_complete_callback_(nullptr) {} +StereoEncoderAdapter::StereoEncoderAdapter( + VideoEncoderFactory* factory, + const SdpVideoFormat& associated_format) + : factory_(factory), + associated_format_(associated_format), + encoded_complete_callback_(nullptr) {} StereoEncoderAdapter::~StereoEncoderAdapter() { Release(); @@ -74,13 +77,16 @@ int StereoEncoderAdapter::InitEncode(const VideoCodec* inst, // It is more expensive to encode 0x00, so use 0x80 instead. std::fill(stereo_dummy_planes_.begin(), stereo_dummy_planes_.end(), 0x80); + RTC_DCHECK_EQ(kVideoCodecStereo, inst->codecType); + VideoCodec settings = *inst; + settings.codecType = PayloadStringToCodecType(associated_format_.name); for (size_t i = 0; i < kAlphaCodecStreams; ++i) { - const SdpVideoFormat format("VP9"); std::unique_ptr encoder = - factory_->CreateVideoEncoder(format); - const int rv = encoder->InitEncode(inst, number_of_cores, max_payload_size); + factory_->CreateVideoEncoder(associated_format_); + const int rv = + encoder->InitEncode(&settings, number_of_cores, max_payload_size); if (rv) { - RTC_LOG(LS_ERROR) << "Failed to create stere codec index " << i; + RTC_LOG(LS_ERROR) << "Failed to create stereo codec index " << i; return rv; } adapter_callbacks_.emplace_back(new AdapterEncodedImageCallback( @@ -180,7 +186,7 @@ EncodedImageCallback::Result StereoEncoderAdapter::OnEncodedImage( const EncodedImage& encodedImage, const CodecSpecificInfo* codecSpecificInfo, const RTPFragmentationHeader* fragmentation) { - const VideoCodecType associated_coded_type = codecSpecificInfo->codecType; + const VideoCodecType associated_codec_type = codecSpecificInfo->codecType; const auto& image_stereo_info_itr = image_stereo_info_.find(encodedImage._timeStamp); RTC_DCHECK(image_stereo_info_itr != image_stereo_info_.end()); @@ -193,7 +199,7 @@ EncodedImageCallback::Result StereoEncoderAdapter::OnEncodedImage( CodecSpecificInfo codec_info = *codecSpecificInfo; codec_info.codecType = kVideoCodecStereo; codec_info.codec_name = "stereo"; - codec_info.codecSpecific.stereo.associated_codec_type = associated_coded_type; + codec_info.codecSpecific.stereo.associated_codec_type = associated_codec_type; codec_info.codecSpecific.stereo.indices.frame_index = stream_idx; codec_info.codecSpecific.stereo.indices.frame_count = frame_count; codec_info.codecSpecific.stereo.indices.picture_index = picture_index; diff --git a/modules/video_coding/codecs/stereo/test/stereo_adapter_unittest.cc b/modules/video_coding/codecs/stereo/test/stereo_adapter_unittest.cc index 34723c5ab1..976a5bb8a2 100644 --- a/modules/video_coding/codecs/stereo/test/stereo_adapter_unittest.cc +++ b/modules/video_coding/codecs/stereo/test/stereo_adapter_unittest.cc @@ -10,8 +10,10 @@ #include "api/test/mock_video_decoder_factory.h" #include "api/test/mock_video_encoder_factory.h" +#include "api/video_codecs/sdp_video_format.h" #include "common_video/include/video_frame_buffer.h" #include "common_video/libyuv/include/webrtc_libyuv.h" +#include "media/base/mediaconstants.h" #include "modules/video_coding/codecs/stereo/include/stereo_decoder_adapter.h" #include "modules/video_coding/codecs/stereo/include/stereo_encoder_adapter.h" #include "modules/video_coding/codecs/test/video_codec_test.h" @@ -24,6 +26,10 @@ using testing::Return; namespace webrtc { +constexpr const char* kStereoAssociatedCodecName = cricket::kVp9CodecName; +const VideoCodecType kStereoAssociatedCodecType = + PayloadStringToCodecType(kStereoAssociatedCodecName); + class TestStereoAdapter : public VideoCodecTest { public: TestStereoAdapter() @@ -32,18 +38,21 @@ class TestStereoAdapter : public VideoCodecTest { protected: std::unique_ptr CreateDecoder() override { - return rtc::MakeUnique(decoder_factory_.get()); + return rtc::MakeUnique( + decoder_factory_.get(), SdpVideoFormat(kStereoAssociatedCodecName)); } std::unique_ptr CreateEncoder() override { - return rtc::MakeUnique(encoder_factory_.get()); + return rtc::MakeUnique( + encoder_factory_.get(), SdpVideoFormat(kStereoAssociatedCodecName)); } VideoCodec codec_settings() override { VideoCodec codec_settings; - codec_settings.codecType = webrtc::kVideoCodecVP9; + codec_settings.codecType = kStereoAssociatedCodecType; codec_settings.VP9()->numberOfTemporalLayers = 1; codec_settings.VP9()->numberOfSpatialLayers = 1; + codec_settings.codecType = webrtc::kVideoCodecStereo; return codec_settings; } @@ -103,7 +112,7 @@ TEST_F(TestStereoAdapter, EncodeDecodeI420Frame) { ASSERT_TRUE(WaitForEncodedFrame(&encoded_frame, &codec_specific_info)); EXPECT_EQ(kVideoCodecStereo, codec_specific_info.codecType); - EXPECT_EQ(kVideoCodecVP9, + EXPECT_EQ(kStereoAssociatedCodecType, codec_specific_info.codecSpecific.stereo.associated_codec_type); EXPECT_EQ(0, codec_specific_info.codecSpecific.stereo.indices.frame_index); EXPECT_EQ(1, codec_specific_info.codecSpecific.stereo.indices.frame_count); @@ -134,7 +143,7 @@ TEST_F(TestStereoAdapter, EncodeDecodeI420AFrame) { const CodecSpecificInfo& yuv_info = codec_specific_infos[kYUVStream]; EXPECT_EQ(kVideoCodecStereo, yuv_info.codecType); - EXPECT_EQ(kVideoCodecVP9, + EXPECT_EQ(kStereoAssociatedCodecType, yuv_info.codecSpecific.stereo.associated_codec_type); EXPECT_EQ(kYUVStream, yuv_info.codecSpecific.stereo.indices.frame_index); EXPECT_EQ(kAlphaCodecStreams, @@ -143,7 +152,7 @@ TEST_F(TestStereoAdapter, EncodeDecodeI420AFrame) { const CodecSpecificInfo& axx_info = codec_specific_infos[kAXXStream]; EXPECT_EQ(kVideoCodecStereo, axx_info.codecType); - EXPECT_EQ(kVideoCodecVP9, + EXPECT_EQ(kStereoAssociatedCodecType, axx_info.codecSpecific.stereo.associated_codec_type); EXPECT_EQ(kAXXStream, axx_info.codecSpecific.stereo.indices.frame_index); EXPECT_EQ(kAlphaCodecStreams, diff --git a/modules/video_coding/video_codec_initializer.cc b/modules/video_coding/video_codec_initializer.cc index 3e1b0e1163..c5cd452b04 100644 --- a/modules/video_coding/video_codec_initializer.cc +++ b/modules/video_coding/video_codec_initializer.cc @@ -39,6 +39,20 @@ bool VideoCodecInitializer::SetupCodec( bool nack_enabled, VideoCodec* codec, std::unique_ptr* bitrate_allocator) { + if (PayloadStringToCodecType(settings.payload_name) == kVideoCodecStereo) { + VideoSendStream::Config::EncoderSettings associated_codec_settings = + settings; + associated_codec_settings.payload_name = + CodecTypeToPayloadString(kVideoCodecVP9); + if (!SetupCodec(config, associated_codec_settings, streams, nack_enabled, + codec, bitrate_allocator)) { + RTC_LOG(LS_ERROR) << "Failed to create stereo encoder configuration."; + return false; + } + codec->codecType = kVideoCodecStereo; + return true; + } + *codec = VideoEncoderConfigToVideoCodec(config, streams, settings.payload_name, settings.payload_type, nack_enabled); diff --git a/modules/video_coding/video_codec_initializer_unittest.cc b/modules/video_coding/video_codec_initializer_unittest.cc index 48bf466863..0862b7282e 100644 --- a/modules/video_coding/video_codec_initializer_unittest.cc +++ b/modules/video_coding/video_codec_initializer_unittest.cc @@ -79,6 +79,7 @@ class VideoCodecInitializerTest : public ::testing::Test { webrtc::VideoEncoderConfig::Vp8EncoderSpecificSettings>(vp8_settings); settings_.payload_name = kVp8PayloadName; settings_.payload_type = kVp8PayloadType; + } else if (type == VideoCodecType::kVideoCodecStereo) { } else { ADD_FAILURE() << "Unexpected codec type: " << type; } @@ -93,7 +94,8 @@ class VideoCodecInitializerTest : public ::testing::Test { &bitrate_allocator_out_)) { return false; } - + if (codec_out_.codecType == VideoCodecType::kVideoCodecStereo) + return true; // Make sure temporal layers instances have been created. if (codec_out_.codecType == VideoCodecType::kVideoCodecVP8) { if (!codec_out_.VP8()->tl_factory) @@ -215,4 +217,10 @@ TEST_F(VideoCodecInitializerTest, HighFpsSimlucastVp8Screenshare) { bitrate_allocation.GetBitrate(1, 1)); } +TEST_F(VideoCodecInitializerTest, SingleStreamStereoCodec) { + SetUpFor(VideoCodecType::kVideoCodecStereo, 1, 1, true); + streams_.push_back(DefaultStream()); + EXPECT_TRUE(InitializeCodec()); +} + } // namespace webrtc diff --git a/video/video_receive_stream.cc b/video/video_receive_stream.cc index 5f6b5cf6b2..62a4dd2f7c 100644 --- a/video/video_receive_stream.cc +++ b/video/video_receive_stream.cc @@ -59,6 +59,12 @@ VideoCodec CreateDecoderVideoCodec(const VideoReceiveStream::Decoder& decoder) { *(codec.H264()) = VideoEncoder::GetDefaultH264Settings(); codec.H264()->profile = H264::ParseSdpProfileLevelId(decoder.codec_params)->profile; + } else if (codec.codecType == kVideoCodecStereo) { + VideoReceiveStream::Decoder associated_decoder = decoder; + associated_decoder.payload_name = CodecTypeToPayloadString(kVideoCodecVP9); + VideoCodec associated_codec = CreateDecoderVideoCodec(associated_decoder); + associated_codec.codecType = kVideoCodecStereo; + return associated_codec; } codec.width = 320;