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}
This commit is contained in:

committed by
Commit Bot

parent
654320666d
commit
0a37547033
@ -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 @@ 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<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_;
|
||||
|
@ -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 @@ 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<std::unique_ptr<VideoEncoder>> encoders_;
|
||||
std::vector<std::unique_ptr<AdapterEncodedImageCallback>> adapter_callbacks_;
|
||||
EncodedImageCallback* encoded_complete_callback_;
|
||||
|
@ -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<VideoDecoder> decoder =
|
||||
factory_->CreateVideoDecoder(format);
|
||||
factory_->CreateVideoDecoder(associated_format_);
|
||||
const int32_t rv = decoder->InitDecode(&settings, number_of_cores);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
@ -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<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 @@ 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;
|
||||
|
@ -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<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 @@ 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,
|
||||
|
Reference in New Issue
Block a user