Bug 1803368 - Plumb H264 configuration from sdp negotiation into libwebrtc. r=webrtc-reviewers,mjf

The plumbing for this was broken in
https://hg.mozilla.org/mozilla-central/rev/f3fc736c62d289ba9d7be9ed01806de7b6c00855

This patch puts the config data into SdpVideoFormat::Parameters which gets
passed into libwebrtc. Further down the line, these parameters will have to be
picked up by encoders. Subsequent patches fixes this for WebrtcGmpVideoEncoder
and WebrtcMediaDataEncoder.

Differential Revision: https://phabricator.services.mozilla.com/D163470
This commit is contained in:
Andreas Pehrson 2022-12-01 13:21:37 +00:00
Родитель 7f88fb67c4
Коммит fcb762f2ba
2 изменённых файлов: 80 добавлений и 4 удалений

Просмотреть файл

@ -30,6 +30,7 @@
// libwebrtc includes
#include "api/transport/bitrate_settings.h"
#include "api/video_codecs/h264_profile_level_id.h"
#include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_codec.h"
#include "media/base/media_constants.h"
@ -126,7 +127,8 @@ webrtc::VideoCodecType SupportedCodecType(webrtc::VideoCodecType aType) {
// Call thread only.
rtc::scoped_refptr<webrtc::VideoEncoderConfig::EncoderSpecificSettings>
ConfigureVideoEncoderSettings(const VideoCodecConfig& aConfig,
const WebrtcVideoConduit* aConduit) {
const WebrtcVideoConduit* aConduit,
webrtc::SdpVideoFormat::Parameters& aParameters) {
bool is_screencast =
aConduit->CodecMode() == webrtc::VideoCodecMode::kScreensharing;
// No automatic resizing when using simulcast or screencast.
@ -141,6 +143,25 @@ ConfigureVideoEncoderSettings(const VideoCodecConfig& aConfig,
codec_default_denoising = !denoising;
}
if (aConfig.mName == kH264CodecName) {
aParameters[kH264FmtpPacketizationMode] =
std::to_string(aConfig.mPacketizationMode);
{
std::stringstream ss;
ss << std::hex << std::setfill('0');
ss << std::setw(2) << static_cast<uint32_t>(aConfig.mProfile);
ss << std::setw(2) << static_cast<uint32_t>(aConfig.mConstraints);
ss << std::setw(2) << static_cast<uint32_t>(aConfig.mLevel);
std::string profileLevelId = ss.str();
auto parsedProfileLevelId =
webrtc::ParseH264ProfileLevelId(profileLevelId.c_str());
MOZ_DIAGNOSTIC_ASSERT(parsedProfileLevelId);
if (parsedProfileLevelId) {
aParameters[kH264FmtpProfileLevelId] = profileLevelId;
}
}
aParameters[kH264FmtpSpropParameterSets] = aConfig.mSpropParameterSets;
}
if (aConfig.mName == kVp8CodecName) {
webrtc::VideoCodecVP8 vp8_settings =
webrtc::VideoEncoder::GetDefaultVp8Settings();
@ -628,15 +649,16 @@ void WebrtcVideoConduit::OnControlConfigChange() {
// XXX parse the encoded SPS/PPS data and set
// spsData/spsLen/ppsData/ppsLen
mEncoderConfig.video_format =
webrtc::SdpVideoFormat(codecConfig->mName);
mEncoderConfig.encoder_specific_settings =
ConfigureVideoEncoderSettings(*codecConfig, this);
ConfigureVideoEncoderSettings(
*codecConfig, this, mEncoderConfig.video_format.parameters);
mEncoderConfig.codec_type = SupportedCodecType(
webrtc::PayloadStringToCodecType(codecConfig->mName));
MOZ_RELEASE_ASSERT(mEncoderConfig.codec_type !=
webrtc::VideoCodecType::kVideoCodecGeneric);
mEncoderConfig.video_format =
webrtc::SdpVideoFormat(codecConfig->mName);
mEncoderConfig.content_type =
mControl.mCodecMode.Ref() == webrtc::VideoCodecMode::kRealtimeVideo

Просмотреть файл

@ -17,6 +17,7 @@
#include "WebrtcGmpVideoCodec.h"
#include "api/video/video_sink_interface.h"
#include "media/base/media_constants.h"
#include "media/base/video_adapter.h"
#include "MockCall.h"
@ -2235,4 +2236,57 @@ TEST_F(VideoConduitTest, TestExternalRemoteSsrcCollision) {
Not(testing::AnyOf(0U, 1U)));
}
TEST_F(VideoConduitTest, TestVideoConfigurationH264) {
const int profileLevelId1 = 0x42E00D;
const int profileLevelId2 = 0x64000C;
const char* sprop1 = "foo bar";
const char* sprop2 = "baz";
// Test that VideoConduit propagates H264 configuration data properly.
// We do two tests:
// - Test valid data in packetization mode 0 (SingleNALU)
// - Test different valid data in packetization mode 1 (NonInterleaved)
{
mControl.Update([&](auto& aControl) {
aControl.mTransmitting = true;
VideoCodecConfigH264 h264{};
h264.packetization_mode = 0;
h264.profile_level_id = profileLevelId1;
strncpy(h264.sprop_parameter_sets, sprop1,
sizeof(h264.sprop_parameter_sets) - 1);
VideoCodecConfig codecConfig(97, "H264", EncodingConstraints(), &h264);
codecConfig.mEncodings.emplace_back();
aControl.mVideoSendCodec = Some(codecConfig);
aControl.mVideoSendRtpRtcpConfig =
Some(RtpRtcpConfig(webrtc::RtcpMode::kCompound));
});
ASSERT_TRUE(Call()->mVideoSendEncoderConfig);
auto& params = Call()->mVideoSendEncoderConfig->video_format.parameters;
EXPECT_EQ(params[cricket::kH264FmtpPacketizationMode], "0");
EXPECT_EQ(params[cricket::kH264FmtpProfileLevelId], "42e00d");
EXPECT_EQ(params[cricket::kH264FmtpSpropParameterSets], sprop1);
}
{
mControl.Update([&](auto& aControl) {
VideoCodecConfigH264 h264{};
h264.packetization_mode = 1;
h264.profile_level_id = profileLevelId2;
strncpy(h264.sprop_parameter_sets, sprop2,
sizeof(h264.sprop_parameter_sets) - 1);
VideoCodecConfig codecConfig(126, "H264", EncodingConstraints(), &h264);
codecConfig.mEncodings.emplace_back();
aControl.mVideoSendCodec = Some(codecConfig);
});
ASSERT_TRUE(Call()->mVideoSendEncoderConfig);
auto& params = Call()->mVideoSendEncoderConfig->video_format.parameters;
EXPECT_EQ(params[cricket::kH264FmtpPacketizationMode], "1");
EXPECT_EQ(params[cricket::kH264FmtpProfileLevelId], "64000c");
EXPECT_EQ(params[cricket::kH264FmtpSpropParameterSets], sprop2);
}
}
} // End namespace test.