From 8deb81808655693234d54a81e3ff2fcbda846d93 Mon Sep 17 00:00:00 2001 From: Magnus Jedvert Date: Thu, 5 Oct 2017 13:13:32 +0200 Subject: [PATCH] Support more H264 profiles for internal software codec Care should be taken when landing this, because it will affect users of WebRTC. I'm thinking primarily of Chromium. Chromium will start to support High profile and Baseline profile using SW codecs with this CL. Clients who do SDP munging without looking at the H264 profile might switch from Constrained Baseline to High profile with this change. Bug: webrtc:8317 Change-Id: Idca3a6b761a66d9e521b913b850c6ae14381f1f4 Reviewed-on: https://webrtc-review.googlesource.com/6341 Reviewed-by: Rasmus Brandt Commit-Queue: Magnus Jedvert Cr-Commit-Position: refs/heads/master@{#20190} --- media/engine/webrtcvideoengine_unittest.cc | 15 +++++++++-- modules/video_coding/DEPS | 5 ---- modules/video_coding/codecs/h264/DEPS | 5 ++++ modules/video_coding/codecs/h264/h264.cc | 31 +++++++++++++++------- 4 files changed, 39 insertions(+), 17 deletions(-) create mode 100644 modules/video_coding/codecs/h264/DEPS diff --git a/media/engine/webrtcvideoengine_unittest.cc b/media/engine/webrtcvideoengine_unittest.cc index 974f479380..7fc5924c92 100644 --- a/media/engine/webrtcvideoengine_unittest.cc +++ b/media/engine/webrtcvideoengine_unittest.cc @@ -564,8 +564,19 @@ TEST_F(WebRtcVideoEngineTest, PropagatesInputFrameTimestamp) { cricket::VideoCodec WebRtcVideoEngineTest::GetEngineCodec( const std::string& name) { for (const cricket::VideoCodec& engine_codec : engine_.codecs()) { - if (CodecNamesEq(name, engine_codec.name)) - return engine_codec; + if (!CodecNamesEq(name, engine_codec.name)) + continue; + // The tests only use H264 Constrained Baseline. Make sure we don't return + // an internal H264 codec from the engine with a different H264 profile. + if (CodecNamesEq(name.c_str(), kH264CodecName)) { + const rtc::Optional profile_level_id = + webrtc::H264::ParseSdpProfileLevelId(engine_codec.params); + if (profile_level_id->profile != + webrtc::H264::kProfileConstrainedBaseline) { + continue; + } + } + return engine_codec; } // This point should never be reached. ADD_FAILURE() << "Unrecognized codec name: " << name; diff --git a/modules/video_coding/DEPS b/modules/video_coding/DEPS index af1a6e7f98..a02ed634ae 100644 --- a/modules/video_coding/DEPS +++ b/modules/video_coding/DEPS @@ -1,6 +1,4 @@ include_rules = [ - "+third_party/ffmpeg", - "+third_party/openh264", "+vpx", "+call", "+common_video", @@ -17,7 +15,4 @@ specific_include_rules = { "+media/engine", "+sdk", ], - ".*h264\.h": [ - "+media/base/codec.h" - ], } diff --git a/modules/video_coding/codecs/h264/DEPS b/modules/video_coding/codecs/h264/DEPS new file mode 100644 index 0000000000..4e110917d8 --- /dev/null +++ b/modules/video_coding/codecs/h264/DEPS @@ -0,0 +1,5 @@ +include_rules = [ + "+third_party/ffmpeg", + "+third_party/openh264", + "+media/base", +] diff --git a/modules/video_coding/codecs/h264/h264.cc b/modules/video_coding/codecs/h264/h264.cc index c24162d890..d7ed3b42e8 100644 --- a/modules/video_coding/codecs/h264/h264.cc +++ b/modules/video_coding/codecs/h264/h264.cc @@ -12,6 +12,7 @@ #include "modules/video_coding/codecs/h264/include/h264.h" #include "api/video_codecs/sdp_video_format.h" +#include "media/base/h264_profile_level_id.h" #if defined(WEBRTC_USE_H264) #include "modules/video_coding/codecs/h264/h264_decoder_impl.h" @@ -29,7 +30,7 @@ namespace { bool g_rtc_use_h264 = true; #endif -// If any H.264 codec is supported (iOS HW or OpenH264/FFmpeg). +// If H.264 OpenH264/FFmpeg codec is supported. bool IsH264CodecSupported() { #if defined(WEBRTC_USE_H264) return g_rtc_use_h264; @@ -38,6 +39,16 @@ bool IsH264CodecSupported() { #endif } +SdpVideoFormat CreateH264Format(H264::Profile profile, H264::Level level) { + const rtc::Optional profile_string = + H264::ProfileLevelIdToString(H264::ProfileLevelId(profile, level)); + RTC_CHECK(profile_string); + return SdpVideoFormat(cricket::kH264CodecName, + {{cricket::kH264FmtpProfileLevelId, *profile_string}, + {cricket::kH264FmtpLevelAsymmetryAllowed, "1"}, + {cricket::kH264FmtpPacketizationMode, "1"}}); +} + } // namespace void DisableRtcUseH264() { @@ -49,15 +60,15 @@ void DisableRtcUseH264() { std::vector SupportedH264Codecs() { if (!IsH264CodecSupported()) return std::vector(); - std::vector codecs; - - codecs.push_back(SdpVideoFormat( - cricket::kH264CodecName, {{cricket::kH264FmtpProfileLevelId, - cricket::kH264ProfileLevelConstrainedBaseline}, - {cricket::kH264FmtpLevelAsymmetryAllowed, "1"}, - {cricket::kH264FmtpPacketizationMode, "1"}})); - - return codecs; + // We only support encoding Constrained Baseline Profile (CBP), but the + // decoder supports more profiles. We can list all profiles here that are + // supported by the decoder and that are also supersets of CBP, i.e. the + // decoder for that profile is required to be able to decode CBP. This means + // we can encode and send CBP even though we negotiated a potentially + // higher profile. See the H264 spec for more information. + return {CreateH264Format(H264::kProfileHigh, H264::kLevel3_1), + CreateH264Format(H264::kProfileConstrainedBaseline, H264::kLevel3_1), + CreateH264Format(H264::kProfileBaseline, H264::kLevel3_1)}; } H264Encoder* H264Encoder::Create(const cricket::VideoCodec& codec) {