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