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 <niklas.enbom@webrtc.org>
Reviewed-by: Niklas Enbom <niklas.enbom@webrtc.org>
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21210}
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 729517f..c6237ee 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 <memory>
#include <vector>
+#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 @@
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 @@
const rtc::Optional<uint8_t>& stereo_qp);
VideoDecoderFactory* const factory_;
+ const SdpVideoFormat associated_format_;
std::vector<std::unique_ptr<VideoDecoder>> decoders_;
std::vector<std::unique_ptr<AdapterDecodedImageCallback>> 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 74ed1a2..95283f1 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 <memory>
#include <vector>
+#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 @@
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 AdapterEncodedImageCallback;
VideoEncoderFactory* const factory_;
+ const SdpVideoFormat associated_format_;
std::vector<std::unique_ptr<VideoEncoder>> encoders_;
std::vector<std::unique_ptr<AdapterEncodedImageCallback>> 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 caf3299..96d5552 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 @@
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 @@
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<VideoDecoder> 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 ed7a486..60e3ea8 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 @@
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 @@
// 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<VideoEncoder> 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 @@
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 @@
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 34723c5..976a5bb 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 @@
namespace webrtc {
+constexpr const char* kStereoAssociatedCodecName = cricket::kVp9CodecName;
+const VideoCodecType kStereoAssociatedCodecType =
+ PayloadStringToCodecType(kStereoAssociatedCodecName);
+
class TestStereoAdapter : public VideoCodecTest {
public:
TestStereoAdapter()
@@ -32,18 +38,21 @@
protected:
std::unique_ptr<VideoDecoder> CreateDecoder() override {
- return rtc::MakeUnique<StereoDecoderAdapter>(decoder_factory_.get());
+ return rtc::MakeUnique<StereoDecoderAdapter>(
+ decoder_factory_.get(), SdpVideoFormat(kStereoAssociatedCodecName));
}
std::unique_ptr<VideoEncoder> CreateEncoder() override {
- return rtc::MakeUnique<StereoEncoderAdapter>(encoder_factory_.get());
+ return rtc::MakeUnique<StereoEncoderAdapter>(
+ 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 @@
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 @@
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 @@
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 3e1b0e1..c5cd452 100644
--- a/modules/video_coding/video_codec_initializer.cc
+++ b/modules/video_coding/video_codec_initializer.cc
@@ -39,6 +39,20 @@
bool nack_enabled,
VideoCodec* codec,
std::unique_ptr<VideoBitrateAllocator>* 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 48bf466..0862b72 100644
--- a/modules/video_coding/video_codec_initializer_unittest.cc
+++ b/modules/video_coding/video_codec_initializer_unittest.cc
@@ -79,6 +79,7 @@
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 @@
&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 @@
bitrate_allocation.GetBitrate(1, 1));
}
+TEST_F(VideoCodecInitializerTest, SingleStreamStereoCodec) {
+ SetUpFor(VideoCodecType::kVideoCodecStereo, 1, 1, true);
+ streams_.push_back(DefaultStream());
+ EXPECT_TRUE(InitializeCodec());
+}
+
} // namespace webrtc