Add support for H.264 constrained high profile in VideoProcessor.

BUG=webrtc:8448

Change-Id: I968d6cd78dd4f3c19a7944ae4cc73c5eddb9a949
Reviewed-on: https://webrtc-review.googlesource.com/16160
Commit-Queue: Rasmus Brandt <brandtr@webrtc.org>
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20466}
diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn
index c91c849..eb0a419 100644
--- a/modules/video_coding/BUILD.gn
+++ b/modules/video_coding/BUILD.gn
@@ -444,6 +444,7 @@
       "../../api:video_frame_api",
       "../../common_video",
       "../../media:rtc_audio_video",
+      "../../media:rtc_media_base",
       "../../rtc_base:rtc_base_approved",
       "../../rtc_base:rtc_base_tests_utils",
       "../../system_wrappers",
diff --git a/modules/video_coding/DEPS b/modules/video_coding/DEPS
index a02ed63..b4612db 100644
--- a/modules/video_coding/DEPS
+++ b/modules/video_coding/DEPS
@@ -12,6 +12,7 @@
     "+sdk",
   ],
   "(.*test\.cc|.*test\.h|.*test\.mm)": [
+     "+media/base",
      "+media/engine",
      "+sdk",
   ],
diff --git a/modules/video_coding/codecs/test/test_config.cc b/modules/video_coding/codecs/test/test_config.cc
index bc7f063..31bbd9b 100644
--- a/modules/video_coding/codecs/test/test_config.cc
+++ b/modules/video_coding/codecs/test/test_config.cc
@@ -179,5 +179,19 @@
   return ss.str();
 }
 
+std::string TestConfig::CodecName() const {
+  std::string codec_name = CodecTypeToPayloadString(codec_settings.codecType);
+  if (codec_settings.codecType == kVideoCodecH264) {
+    if (h264_codec_settings.profile == H264::kProfileConstrainedHigh) {
+      codec_name += "-CHP";
+    } else {
+      RTC_DCHECK_EQ(h264_codec_settings.profile,
+                    H264::kProfileConstrainedBaseline);
+      codec_name += "-CBP";
+    }
+  }
+  return codec_name;
+}
+
 }  // namespace test
 }  // namespace webrtc
diff --git a/modules/video_coding/codecs/test/test_config.h b/modules/video_coding/codecs/test/test_config.h
index 1b17305..c4561f9 100644
--- a/modules/video_coding/codecs/test/test_config.h
+++ b/modules/video_coding/codecs/test/test_config.h
@@ -56,6 +56,7 @@
   int TemporalLayerForFrame(int frame_idx) const;
   std::vector<FrameType> FrameTypeForFrame(int frame_idx) const;
   std::string ToString() const;
+  std::string CodecName() const;
 
   // Plain name of YUV file to process without file extension.
   std::string filename;
@@ -99,6 +100,13 @@
   // Codec settings to use.
   webrtc::VideoCodec codec_settings;
 
+  // H.264 specific settings.
+  struct H264CodecSettings {
+    H264::Profile profile = H264::kProfileConstrainedBaseline;
+    H264PacketizationMode packetization_mode =
+        webrtc::H264PacketizationMode::NonInterleaved;
+  } h264_codec_settings;
+
   // Should hardware accelerated codecs be used?
   bool hw_encoder = false;
   bool hw_decoder = false;
@@ -107,10 +115,6 @@
   bool sw_fallback_encoder = false;
   bool sw_fallback_decoder = false;
 
-  // RTP H264 packetization mode.
-  H264PacketizationMode packetization_mode =
-      webrtc::H264PacketizationMode::NonInterleaved;
-
   // Custom checker that will be called for each frame.
   const EncodedFrameChecker* encoded_frame_checker = nullptr;
 };
diff --git a/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc b/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc
index 8baa963..84a77b7 100644
--- a/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc
+++ b/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc
@@ -21,6 +21,8 @@
 #include "modules/video_coding/codecs/test/objc_codec_h264_test.h"
 #endif
 
+#include "common_types.h"  // NOLINT(build/include)
+#include "media/base/h264_profile_level_id.h"
 #include "media/engine/internaldecoderfactory.h"
 #include "media/engine/internalencoderfactory.h"
 #include "media/engine/videodecodersoftwarefallbackwrapper.h"
@@ -328,12 +330,27 @@
           decoder_factory->CreateVideoDecoderWithParams(codec, decoder_params));
       break;
     case kVideoCodecH264:
-      // TODO(brandtr): Generalize so that we support multiple profiles here.
       codec = cricket::VideoCodec(cricket::kH264CodecName);
-      if (config_.packetization_mode == H264PacketizationMode::NonInterleaved) {
+      if (config_.h264_codec_settings.profile ==
+          H264::kProfileConstrainedHigh) {
+        const H264::ProfileLevelId constrained_high_profile(
+            H264::kProfileConstrainedHigh, H264::kLevel3_1);
+        codec.SetParam(cricket::kH264FmtpProfileLevelId,
+                       *H264::ProfileLevelIdToString(constrained_high_profile));
+      } else {
+        RTC_CHECK_EQ(config_.h264_codec_settings.profile,
+                     H264::kProfileConstrainedBaseline);
+        const H264::ProfileLevelId constrained_baseline_profile(
+            H264::kProfileConstrainedBaseline, H264::kLevel3_1);
+        codec.SetParam(
+            cricket::kH264FmtpProfileLevelId,
+            *H264::ProfileLevelIdToString(constrained_baseline_profile));
+      }
+      if (config_.h264_codec_settings.packetization_mode ==
+          H264PacketizationMode::NonInterleaved) {
         codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
       } else {
-        RTC_CHECK_EQ(config_.packetization_mode,
+        RTC_CHECK_EQ(config_.h264_codec_settings.packetization_mode,
                      H264PacketizationMode::SingleNalUnit);
         codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
       }
@@ -577,8 +594,7 @@
   const char* decoder_name = decoder_->ImplementationName();
   printf(" Decoder implementation name: %s\n", decoder_name);
   if (strcmp(encoder_name, decoder_name) == 0) {
-    printf(" Codec implementation name  : %s_%s\n",
-           CodecTypeToPayloadString(config_.codec_settings.codecType),
+    printf(" Codec implementation name : %s_%s\n", config_.CodecName().c_str(),
            encoder_name);
   }
   printf("\n");
diff --git a/modules/video_coding/codecs/test/videoprocessor_integrationtest_mediacodec.cc b/modules/video_coding/codecs/test/videoprocessor_integrationtest_mediacodec.cc
index 3cb078c..8155fc5 100644
--- a/modules/video_coding/codecs/test/videoprocessor_integrationtest_mediacodec.cc
+++ b/modules/video_coding/codecs/test/videoprocessor_integrationtest_mediacodec.cc
@@ -12,6 +12,7 @@
 
 #include <vector>
 
+#include "common_types.h"  // NOLINT(build/include)
 #include "test/field_trial.h"
 #include "test/testsupport/fileutils.h"
 
@@ -58,7 +59,7 @@
                               kNoVisualizationParams);
 }
 
-TEST_F(VideoProcessorIntegrationTestMediaCodec, ForemanCif500kbpsH264) {
+TEST_F(VideoProcessorIntegrationTestMediaCodec, ForemanCif500kbpsH264CBP) {
   config_.encoded_frame_checker = &h264_keyframe_checker_;
   config_.SetCodecSettings(kVideoCodecH264, 1, false, false, false, false,
                            false, 352, 288);
@@ -78,6 +79,31 @@
                               kNoVisualizationParams);
 }
 
+// TODO(brandtr): Enable this test when we have trybots/buildbots with
+// HW encoders that support CHP.
+TEST_F(VideoProcessorIntegrationTestMediaCodec,
+       DISABLED_ForemanCif500kbpsH264CHP) {
+  ScopedFieldTrials override_field_trials("WebRTC-H264HighProfile/Enabled/");
+
+  config_.h264_codec_settings.profile = H264::kProfileConstrainedHigh;
+  config_.encoded_frame_checker = &h264_keyframe_checker_;
+  config_.SetCodecSettings(kVideoCodecH264, 1, false, false, false, false,
+                           false, 352, 288);
+
+  std::vector<RateProfile> rate_profiles = {{500, 30, kForemanNumFrames + 1}};
+
+  // The thresholds below may have to be tweaked to let even poor MediaCodec
+  // implementations pass. If this test fails on the bots, disable it and
+  // ping brandtr@.
+  std::vector<RateControlThresholds> rc_thresholds = {{5, 60, 20, 5, 15, 0, 1}};
+
+  QualityThresholds quality_thresholds(33.0, 30.0, 0.90, 0.85);
+
+  ProcessFramesAndMaybeVerify(rate_profiles, &rc_thresholds,
+                              &quality_thresholds, nullptr,
+                              kNoVisualizationParams);
+}
+
 TEST_F(VideoProcessorIntegrationTestMediaCodec,
        Foreman240p100kbpsVp8WithForcedSwFallback) {
   ScopedFieldTrials override_field_trials(
diff --git a/modules/video_coding/codecs/test/videoprocessor_integrationtest_openh264.cc b/modules/video_coding/codecs/test/videoprocessor_integrationtest_openh264.cc
index d3122da..9967fbd 100644
--- a/modules/video_coding/codecs/test/videoprocessor_integrationtest_openh264.cc
+++ b/modules/video_coding/codecs/test/videoprocessor_integrationtest_openh264.cc
@@ -73,7 +73,8 @@
 // H264: Enable SingleNalUnit packetization mode. Encoder should split
 // large frames into multiple slices and limit length of NAL units.
 TEST_F(VideoProcessorIntegrationTestOpenH264, ProcessNoLossSingleNalUnit) {
-  config_.packetization_mode = H264PacketizationMode::SingleNalUnit;
+  config_.h264_codec_settings.packetization_mode =
+      H264PacketizationMode::SingleNalUnit;
   config_.networking_config.max_payload_size_in_bytes = 500;
   config_.SetCodecSettings(kVideoCodecH264, 1, false, false, true, false,
                            kResilienceOn, kCifWidth, kCifHeight);
diff --git a/modules/video_coding/codecs/test/videoprocessor_integrationtest_videotoolbox.cc b/modules/video_coding/codecs/test/videoprocessor_integrationtest_videotoolbox.cc
index 7e139c6..2e040a4 100644
--- a/modules/video_coding/codecs/test/videoprocessor_integrationtest_videotoolbox.cc
+++ b/modules/video_coding/codecs/test/videoprocessor_integrationtest_videotoolbox.cc
@@ -12,6 +12,7 @@
 
 #include <vector>
 
+#include "test/field_trial.h"
 #include "test/testsupport/fileutils.h"
 
 namespace webrtc {
@@ -40,9 +41,10 @@
 };
 
 // Since we don't currently run the iOS tests on physical devices on the bots,
-// this test is disabled.
+// the tests are disabled.
+
 TEST_F(VideoProcessorIntegrationTestVideoToolbox,
-       DISABLED_ForemanCif500kbpsH264) {
+       DISABLED_ForemanCif500kbpsH264CBP) {
   config_.SetCodecSettings(kVideoCodecH264, 1, false, false, false, false,
                            false, 352, 288);
 
@@ -58,6 +60,25 @@
                               kNoVisualizationParams);
 }
 
+TEST_F(VideoProcessorIntegrationTestVideoToolbox,
+       DISABLED_ForemanCif500kbpsH264CHP) {
+  ScopedFieldTrials override_field_trials("WebRTC-H264HighProfile/Enabled/");
+
+  config_.h264_codec_settings.profile = H264::kProfileConstrainedHigh;
+  config_.SetCodecSettings(kVideoCodecH264, 1, false, false, false, false,
+                           false, 352, 288);
+
+  std::vector<RateProfile> rate_profiles = {{500, 30, kForemanNumFrames + 1}};
+
+  std::vector<RateControlThresholds> rc_thresholds = {{5, 75, 65, 60, 6, 0, 1}};
+
+  QualityThresholds quality_thresholds(30.0, 14.0, 0.86, 0.39);
+
+  ProcessFramesAndMaybeVerify(rate_profiles, &rc_thresholds,
+                              &quality_thresholds, nullptr,
+                              kNoVisualizationParams);
+}
+
 #endif  // defined(WEBRTC_IOS)
 
 }  // namespace test