diff --git a/webrtc/config.h b/webrtc/config.h index b2dfe2d272..1550a9f8a1 100644 --- a/webrtc/config.h +++ b/webrtc/config.h @@ -16,6 +16,7 @@ #include #include +#include "webrtc/base/optional.h" #include "webrtc/common.h" #include "webrtc/common_types.h" #include "webrtc/typedefs.h" @@ -146,6 +147,16 @@ struct VideoEncoderConfig { bool expect_encode_from_texture; }; +struct VideoDecoderH264Settings { + std::string sprop_parameter_sets; +}; + +class DecoderSpecificSettings { + public: + virtual ~DecoderSpecificSettings() {} + rtc::Optional h264_extra_settings; +}; + // Controls the capacity of the packet buffer in NetEq. The capacity is the // maximum number of packets that the buffer can contain. If the limit is // exceeded, the buffer will be flushed. The capacity does not affect the actual diff --git a/webrtc/media/engine/webrtcvideoengine2.cc b/webrtc/media/engine/webrtcvideoengine2.cc index ef88acd3ae..dc9cdf0422 100644 --- a/webrtc/media/engine/webrtcvideoengine2.cc +++ b/webrtc/media/engine/webrtcvideoengine2.cc @@ -2331,6 +2331,20 @@ WebRtcVideoChannel2::WebRtcVideoReceiveStream::CreateOrReuseVideoDecoder( webrtc::kVideoCodecUnknown, false); } +void ConfigureDecoderSpecifics(webrtc::VideoReceiveStream::Decoder* decoder, + const cricket::VideoCodec& recv_video_codec) { + if (recv_video_codec.name.compare("H264") == 0) { + auto it = recv_video_codec.params.find("sprop-parameter-sets"); + if (it != recv_video_codec.params.end()) { + decoder->decoder_specific.h264_extra_settings = + rtc::Optional( + webrtc::VideoDecoderH264Settings()); + decoder->decoder_specific.h264_extra_settings->sprop_parameter_sets = + it->second; + } + } +} + void WebRtcVideoChannel2::WebRtcVideoReceiveStream::ConfigureCodecs( const std::vector& recv_codecs, std::vector* old_decoders) { @@ -2346,6 +2360,7 @@ void WebRtcVideoChannel2::WebRtcVideoReceiveStream::ConfigureCodecs( decoder.decoder = allocated_decoder.decoder; decoder.payload_type = recv_codecs[i].codec.id; decoder.payload_name = recv_codecs[i].codec.name; + ConfigureDecoderSpecifics(&decoder, recv_codecs[i].codec); config_.decoders.push_back(decoder); } diff --git a/webrtc/media/engine/webrtcvideoengine2_unittest.cc b/webrtc/media/engine/webrtcvideoengine2_unittest.cc index 24cd8fc957..9a37e9d7cf 100644 --- a/webrtc/media/engine/webrtcvideoengine2_unittest.cc +++ b/webrtc/media/engine/webrtcvideoengine2_unittest.cc @@ -3595,6 +3595,40 @@ TEST_F(WebRtcVideoChannel2Test, GetRtpReceiveParametersCodecs) { EXPECT_EQ(kVp9Codec.ToCodecParameters(), rtp_parameters.codecs[1]); } +TEST_F(WebRtcVideoChannel2Test, GetRtpReceiveFmtpSprop) { + cricket::VideoRecvParameters parameters; + cricket::VideoCodec kH264sprop1(101, "H264", 640, 400, 15); + kH264sprop1.SetParam("sprop-parameter-sets", "uvw"); + parameters.codecs.push_back(kH264sprop1); + cricket::VideoCodec kH264sprop2(102, "H264", 640, 400, 15); + kH264sprop2.SetParam("sprop-parameter-sets", "xyz"); + parameters.codecs.push_back(kH264sprop2); + EXPECT_TRUE(channel_->SetRecvParameters(parameters)); + + FakeVideoReceiveStream* recv_stream = AddRecvStream(); + const webrtc::VideoReceiveStream::Config& cfg = recv_stream->GetConfig(); + webrtc::RtpParameters rtp_parameters = + channel_->GetRtpReceiveParameters(last_ssrc_); + ASSERT_EQ(2u, rtp_parameters.codecs.size()); + EXPECT_EQ(kH264sprop1.ToCodecParameters(), rtp_parameters.codecs[0]); + ASSERT_EQ(2u, cfg.decoders.size()); + EXPECT_EQ(101, cfg.decoders[0].payload_type); + EXPECT_EQ("H264", cfg.decoders[0].payload_name); + std::string sprop; + const webrtc::DecoderSpecificSettings* decoder_specific; + decoder_specific = &cfg.decoders[0].decoder_specific; + ASSERT_TRUE(static_cast(decoder_specific->h264_extra_settings)); + sprop = decoder_specific->h264_extra_settings->sprop_parameter_sets; + EXPECT_EQ("uvw", sprop); + + EXPECT_EQ(102, cfg.decoders[1].payload_type); + EXPECT_EQ("H264", cfg.decoders[1].payload_name); + decoder_specific = &cfg.decoders[1].decoder_specific; + ASSERT_TRUE(static_cast(decoder_specific->h264_extra_settings)); + sprop = decoder_specific->h264_extra_settings->sprop_parameter_sets; + EXPECT_EQ("xyz", sprop); +} + // Test that RtpParameters for receive stream has one encoding and it has // the correct SSRC. TEST_F(WebRtcVideoChannel2Test, RtpEncodingParametersSsrcIsSet) { diff --git a/webrtc/video/video_receive_stream.cc b/webrtc/video/video_receive_stream.cc index b07759b9d3..4b5dd754c5 100644 --- a/webrtc/video/video_receive_stream.cc +++ b/webrtc/video/video_receive_stream.cc @@ -48,6 +48,11 @@ std::string VideoReceiveStream::Decoder::ToString() const { ss << "{decoder: " << (decoder ? "(VideoDecoder)" : "nullptr"); ss << ", payload_type: " << payload_type; ss << ", payload_name: " << payload_name; + ss << ", decoder_specific: {"; + ss << " h264_extra_settings: " + << (decoder_specific.h264_extra_settings ? "(h264_extra_settings)" + : "nullptr"); + ss << '}'; ss << '}'; return ss.str(); diff --git a/webrtc/video_receive_stream.h b/webrtc/video_receive_stream.h index 410d5aff7f..49466ffcbd 100644 --- a/webrtc/video_receive_stream.h +++ b/webrtc/video_receive_stream.h @@ -43,6 +43,8 @@ class VideoReceiveStream { // Name of the decoded payload (such as VP8). Maps back to the depacketizer // used to unpack incoming packets. std::string payload_name; + + DecoderSpecificSettings decoder_specific; }; struct Stats {