Use different RTX payload types for different H264 profiles

This CL is a quick fix to unblock H264 High Profile. This CL is supposed
to be superseded by a proper fix of
https://bugs.chromium.org/p/webrtc/issues/detail?id=6705 like
https://codereview.webrtc.org/2493133002/.

BUG=webrtc:6677

Review-Url: https://codereview.webrtc.org/2497773003
Cr-Commit-Position: refs/heads/master@{#15099}
This commit is contained in:
magjed 2016-11-16 00:48:13 -08:00 committed by Commit bot
parent 906c5dc6b7
commit 725e484e33
7 changed files with 72 additions and 21 deletions

View File

@ -117,7 +117,8 @@ const int kDefaultFlexfecPlType = 118;
const int kDefaultRtxVp8PlType = 96;
const int kDefaultRtxVp9PlType = 97;
const int kDefaultRtxRedPlType = 98;
const int kDefaultRtxH264PlType = 99;
const int kDefaultRtxH264ConstrainedBaselinePlType = 99;
const int kDefaultRtxH264ConstrainedHighPlType = 102;
const int kDefaultVideoMaxFramerate = 60;
} // namespace cricket

View File

@ -139,7 +139,8 @@ extern const int kDefaultFlexfecPlType;
extern const int kDefaultRtxVp8PlType;
extern const int kDefaultRtxVp9PlType;
extern const int kDefaultRtxRedPlType;
extern const int kDefaultRtxH264PlType;
extern const int kDefaultRtxH264ConstrainedBaselinePlType;
extern const int kDefaultRtxH264ConstrainedHighPlType;
extern const int kDefaultVideoMaxFramerate;
} // namespace cricket

View File

@ -233,6 +233,10 @@ class FakeWebRtcVideoEncoderFactory : public WebRtcVideoEncoderFactory {
encoders_have_internal_sources_ = internal_source;
}
void AddSupportedVideoCodec(const cricket::VideoCodec& codec) {
codecs_.push_back(codec);
}
void AddSupportedVideoCodecType(const std::string& name) {
codecs_.push_back(cricket::VideoCodec(name));
}

View File

@ -70,7 +70,7 @@ PayloadTypeMapper::PayloadTypeMapper()
{{kRtxCodecName, 90000, 0,
{{kCodecParamAssociatedPayloadType,
std::to_string(kDefaultH264PlType)}}},
kDefaultRtxH264PlType},
kDefaultRtxH264ConstrainedBaselinePlType},
// Other codecs
{{kVp8CodecName, 90000, 0}, kDefaultVp8PlType},
{{kVp9CodecName, 90000, 0}, kDefaultVp9PlType},

View File

@ -78,7 +78,8 @@ TEST_F(PayloadTypeMapperTest, WebRTCPayloadTypes) {
};
EXPECT_EQ(kDefaultRtxVp8PlType, rtx_mapping(kDefaultVp8PlType));
EXPECT_EQ(kDefaultRtxVp9PlType, rtx_mapping(kDefaultVp9PlType));
EXPECT_EQ(kDefaultRtxH264PlType, rtx_mapping(kDefaultH264PlType));
EXPECT_EQ(kDefaultRtxH264ConstrainedBaselinePlType,
rtx_mapping(kDefaultH264PlType));
EXPECT_EQ(kDefaultRtxRedPlType, rtx_mapping(kDefaultRedPlType));
EXPECT_EQ(102, FindMapping({kIlbcCodecName, 8000, 1}));

View File

@ -22,6 +22,7 @@
#include "webrtc/base/timeutils.h"
#include "webrtc/base/trace_event.h"
#include "webrtc/call.h"
#include "webrtc/common_video/h264/profile_level_id.h"
#include "webrtc/media/engine/constants.h"
#include "webrtc/media/engine/simulcast.h"
#include "webrtc/media/engine/videoencodersoftwarefallbackwrapper.h"
@ -404,7 +405,21 @@ void AddCodecAndMaybeRtxCodec(const VideoCodec& codec,
} else if (CodecNamesEq(codec.name, kVp9CodecName)) {
rtx_payload_type = kDefaultRtxVp9PlType;
} else if (CodecNamesEq(codec.name, kH264CodecName)) {
rtx_payload_type = kDefaultRtxH264PlType;
// Parse H264 profile.
const rtc::Optional<webrtc::H264::ProfileLevelId> profile_level_id =
webrtc::H264::ParseSdpProfileLevelId(codec.params);
if (!profile_level_id)
return;
const webrtc::H264::Profile profile = profile_level_id->profile;
// In H.264, we only support rtx for constrained baseline and constrained
// high profile.
if (profile == webrtc::H264::kProfileConstrainedBaseline) {
rtx_payload_type = kDefaultRtxH264ConstrainedBaselinePlType;
} else if (profile == webrtc::H264::kProfileConstrainedHigh) {
rtx_payload_type = kDefaultRtxH264ConstrainedHighPlType;
} else {
return;
}
} else if (CodecNamesEq(codec.name, kRedCodecName)) {
rtx_payload_type = kDefaultRtxRedPlType;
} else {

View File

@ -16,6 +16,7 @@
#include "webrtc/base/arraysize.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/stringutils.h"
#include "webrtc/common_video/h264/profile_level_id.h"
#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
#include "webrtc/media/base/testutils.h"
#include "webrtc/media/base/videoengine_unittest.h"
@ -61,6 +62,22 @@ void VerifyCodecHasDefaultFeedbackParams(const cricket::VideoCodec& codec) {
cricket::kRtcpFbParamCcm, cricket::kRtcpFbCcmParamFir)));
}
// Return true if any codec in |codecs| is an RTX codec with associated payload
// type |payload_type|.
bool HasRtxCodec(const std::vector<cricket::VideoCodec>& codecs,
int payload_type) {
for (const cricket::VideoCodec& codec : codecs) {
int associated_payload_type;
if (cricket::CodecNamesEq(codec.name.c_str(), "rtx") &&
codec.GetParam(cricket::kCodecParamAssociatedPayloadType,
&associated_payload_type) &&
associated_payload_type == payload_type) {
return true;
}
}
return false;
}
static rtc::scoped_refptr<webrtc::VideoFrameBuffer> CreateBlackFrameBuffer(
int width,
int height) {
@ -375,26 +392,38 @@ TEST_F(WebRtcVideoEngine2Test, UseExternalFactoryForVp8WhenSupported) {
// built with no internal H264 support. This test should be updated
// if/when we start adding RTX codecs for unrecognized codec names.
TEST_F(WebRtcVideoEngine2Test, RtxCodecAddedForExternalCodec) {
using webrtc::H264::ProfileLevelIdToString;
using webrtc::H264::ProfileLevelId;
using webrtc::H264::kLevel1;
cricket::VideoCodec h264_constrained_baseline("H264");
h264_constrained_baseline.params[kH264FmtpProfileLevelId] =
*ProfileLevelIdToString(
ProfileLevelId(webrtc::H264::kProfileConstrainedBaseline, kLevel1));
cricket::VideoCodec h264_constrained_high("H264");
h264_constrained_high.params[kH264FmtpProfileLevelId] =
*ProfileLevelIdToString(
ProfileLevelId(webrtc::H264::kProfileConstrainedHigh, kLevel1));
cricket::VideoCodec h264_high("H264");
h264_high.params[kH264FmtpProfileLevelId] = *ProfileLevelIdToString(
ProfileLevelId(webrtc::H264::kProfileHigh, kLevel1));
cricket::FakeWebRtcVideoEncoderFactory encoder_factory;
encoder_factory.AddSupportedVideoCodecType("H264");
encoder_factory.AddSupportedVideoCodec(h264_constrained_baseline);
encoder_factory.AddSupportedVideoCodec(h264_constrained_high);
encoder_factory.AddSupportedVideoCodec(h264_high);
engine_.SetExternalEncoderFactory(&encoder_factory);
engine_.Init();
auto codecs = engine_.codecs();
// First figure out what payload type the test codec got assigned.
auto test_codec_it =
std::find_if(codecs.begin(), codecs.end(),
[](const VideoCodec& c) { return c.name == "H264"; });
ASSERT_NE(codecs.end(), test_codec_it);
// Now search for an RTX codec for it.
EXPECT_TRUE(std::any_of(codecs.begin(), codecs.end(),
[&test_codec_it](const VideoCodec& c) {
int associated_payload_type;
return c.name == "rtx" &&
c.GetParam(kCodecParamAssociatedPayloadType,
&associated_payload_type) &&
associated_payload_type == test_codec_it->id;
}));
// First figure out what payload types the test codecs got assigned.
const std::vector<cricket::VideoCodec> codecs = engine_.codecs();
// Now search for RTX codecs for them. Expect that Constrained Baseline and
// Constrained High got an associated RTX codec, but not High.
EXPECT_TRUE(HasRtxCodec(
codecs, FindMatchingCodec(codecs, h264_constrained_baseline)->id));
EXPECT_TRUE(HasRtxCodec(
codecs, FindMatchingCodec(codecs, h264_constrained_high)->id));
EXPECT_FALSE(HasRtxCodec(
codecs, FindMatchingCodec(codecs, h264_high)->id));
}
void WebRtcVideoEngine2Test::TestExtendedEncoderOveruse(