diff --git a/webrtc/api/webrtcsdp.cc b/webrtc/api/webrtcsdp.cc index 93d4acc6c3..90e0007628 100644 --- a/webrtc/api/webrtcsdp.cc +++ b/webrtc/api/webrtcsdp.cc @@ -1574,15 +1574,27 @@ void WriteFmtpParameters(const cricket::CodecParameterMap& parameters, bool IsFmtpParam(const std::string& name) { const char* kFmtpParams[] = { - kCodecParamMinPTime, kCodecParamSPropStereo, - kCodecParamStereo, kCodecParamUseInbandFec, kCodecParamUseDtx, - kCodecParamStartBitrate, kCodecParamMaxBitrate, kCodecParamMinBitrate, - kCodecParamMaxQuantization, kCodecParamSctpProtocol, kCodecParamSctpStreams, - kCodecParamMaxAverageBitrate, kCodecParamMaxPlaybackRate, - kCodecParamAssociatedPayloadType - }; + // TODO(hta): Split FMTP parameters apart from parameters in general. + // FMTP parameters are codec specific, not generic. + kCodecParamMinPTime, + kCodecParamSPropStereo, + kCodecParamStereo, + kCodecParamUseInbandFec, + kCodecParamUseDtx, + kCodecParamStartBitrate, + kCodecParamMaxBitrate, + kCodecParamMinBitrate, + kCodecParamMaxQuantization, + kCodecParamSctpProtocol, + kCodecParamSctpStreams, + kCodecParamMaxAverageBitrate, + kCodecParamMaxPlaybackRate, + kCodecParamAssociatedPayloadType, + cricket::kH264FmtpPacketizationMode, + cricket::kH264FmtpLevelAsymmetryAllowed, + cricket::kH264FmtpProfileLevelId}; for (size_t i = 0; i < arraysize(kFmtpParams); ++i) { - if (_stricmp(name.c_str(), kFmtpParams[i]) == 0) { + if (name.compare(kFmtpParams[i]) == 0) { return true; } } diff --git a/webrtc/api/webrtcsdp_unittest.cc b/webrtc/api/webrtcsdp_unittest.cc index c52720453b..3734ac5b86 100644 --- a/webrtc/api/webrtcsdp_unittest.cc +++ b/webrtc/api/webrtcsdp_unittest.cc @@ -25,6 +25,8 @@ #include "webrtc/base/stringencode.h" #include "webrtc/base/stringutils.h" #include "webrtc/media/base/mediaconstants.h" +#include "webrtc/media/engine/webrtcvideoengine2.h" +#include "webrtc/modules/video_coding/codecs/h264/include/h264.h" #include "webrtc/p2p/base/p2pconstants.h" #include "webrtc/pc/mediasession.h" @@ -2088,6 +2090,33 @@ TEST_F(WebRtcSdpTest, SerializeTcpCandidates) { EXPECT_EQ(std::string(kSdpTcpActiveCandidate), message); } +TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithH264) { + if (!webrtc::H264Encoder::IsSupported()) + return; + for (const auto& codec : cricket::DefaultVideoCodecList()) { + video_desc_->AddCodec(codec); + } + jdesc_.Initialize(desc_.Copy(), kSessionId, kSessionVersion); + + std::string message = webrtc::SdpSerialize(jdesc_, false); + size_t after_pt = message.find(" H264/90000"); + ASSERT_NE(after_pt, std::string::npos); + size_t before_pt = message.rfind("a=rtpmap:", after_pt); + ASSERT_NE(before_pt, std::string::npos); + before_pt += strlen("a=rtpmap:"); + std::string pt = message.substr(before_pt, after_pt - before_pt); + // TODO(hta): Check if payload type |pt| occurs in the m=video line. + std::string to_find = "a=fmtp:" + pt + " "; + size_t fmtp_pos = message.find(to_find); + ASSERT_NE(std::string::npos, fmtp_pos) << "Failed to find " << to_find; + size_t fmtp_endpos = message.find("\n", fmtp_pos); + ASSERT_NE(std::string::npos, fmtp_endpos); + std::string fmtp_value = message.substr(fmtp_pos, fmtp_endpos); + EXPECT_NE(std::string::npos, fmtp_value.find("level-asymmetry-allowed=1")); + EXPECT_NE(std::string::npos, fmtp_value.find("packetization-mode=1")); + EXPECT_NE(std::string::npos, fmtp_value.find("profile-level-id=42e01f")); +} + TEST_F(WebRtcSdpTest, DeserializeSessionDescription) { JsepSessionDescription jdesc(kDummyString); // Deserialize diff --git a/webrtc/media/base/mediaconstants.cc b/webrtc/media/base/mediaconstants.cc index 2190a54d10..d6bb7e3d48 100644 --- a/webrtc/media/base/mediaconstants.cc +++ b/webrtc/media/base/mediaconstants.cc @@ -116,6 +116,12 @@ const char kVp8CodecName[] = "VP8"; const char kVp9CodecName[] = "VP9"; const char kH264CodecName[] = "H264"; +// RFC 6184 RTP Payload Format for H.264 video +const char kH264FmtpProfileLevelId[] = "profile-level-id"; +const char kH264FmtpLevelAsymmetryAllowed[] = "level-asymmetry-allowed"; +const char kH264FmtpPacketizationMode[] = "packetization-mode"; +const char kH264ProfileLevelConstrainedBaseline[] = "42e01f"; + const int kDefaultVp8PlType = 100; const int kDefaultVp9PlType = 101; const int kDefaultH264PlType = 107; diff --git a/webrtc/media/base/mediaconstants.h b/webrtc/media/base/mediaconstants.h index 94225def4b..708ca5b80e 100644 --- a/webrtc/media/base/mediaconstants.h +++ b/webrtc/media/base/mediaconstants.h @@ -149,6 +149,12 @@ extern const char kVp8CodecName[]; extern const char kVp9CodecName[]; extern const char kH264CodecName[]; +// RFC 6184 RTP Payload Format for H.264 video +extern const char kH264FmtpProfileLevelId[]; +extern const char kH264FmtpLevelAsymmetryAllowed[]; +extern const char kH264FmtpPacketizationMode[]; +extern const char kH264ProfileLevelConstrainedBaseline[]; + extern const int kDefaultVp8PlType; extern const int kDefaultVp9PlType; extern const int kDefaultH264PlType; diff --git a/webrtc/media/engine/webrtcvideoengine2.cc b/webrtc/media/engine/webrtcvideoengine2.cc index ec6b033d2f..b9dbd66684 100644 --- a/webrtc/media/engine/webrtcvideoengine2.cc +++ b/webrtc/media/engine/webrtcvideoengine2.cc @@ -386,8 +386,18 @@ std::vector DefaultVideoCodecList() { VideoCodec::CreateRtxCodec(kDefaultRtxVp9PlType, kDefaultVp9PlType)); } if (CodecIsInternallySupported(kH264CodecName)) { - codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultH264PlType, - kH264CodecName)); + VideoCodec codec = MakeVideoCodecWithDefaultFeedbackParams( + kDefaultH264PlType, kH264CodecName); + // TODO(hta): Move all parameter generation for SDP into the codec + // implementation, for all codecs and parameters. + // TODO(hta): Move selection of profile-level-id to H.264 codec + // implementation. + // TODO(hta): Set FMTP parameters for all codecs of type H264. + codec.SetParam(kH264FmtpProfileLevelId, + kH264ProfileLevelConstrainedBaseline); + codec.SetParam(kH264FmtpLevelAsymmetryAllowed, "1"); + codec.SetParam(kH264FmtpPacketizationMode, "1"); + codecs.push_back(codec); codecs.push_back( VideoCodec::CreateRtxCodec(kDefaultRtxH264PlType, kDefaultH264PlType)); }