Reland of Add full stack tests for MediaCodec encoder (moved from Rietveld).

* Add audio_ prefix to CallTest::{en,de}coder_factory_.
* Let VideoQualityTest only instantiate encoders using encoder factories.
* Add HW encoder factories to VideoQualityTest.
* Add full stack tests:
  - sqcif7 at  30 kbps: libvpx.
  - 240p10 at 100 kbps: MediaCodec, libvpx, and MediaCodec+libvpx.

BUG=webrtc:8219
TBR=asapersson@webrtc.org,kjellander@webrtc.org,stefan@webrtc.org,sprang@webrtc.org

Change-Id: I464409ac0d5276defa78c1bf66034c6cca717d74
Reviewed-on: https://webrtc-review.googlesource.com/4740
Commit-Queue: Rasmus Brandt <brandtr@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20041}
diff --git a/BUILD.gn b/BUILD.gn
index e590644..209a3fb 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -477,6 +477,8 @@
     "resources/audio_coding/testfile32kHz.pcm",
     "resources/ConferenceMotion_1280_720_50.yuv",
     "resources/difficult_photo_1850_1110.yuv",
+    "resources/foreman_128x96.yuv",
+    "resources/foreman_320x240.yuv",
     "resources/foreman_cif.yuv",
     "resources/google-wifi-3mbps.rx",
     "resources/paris_qcif.yuv",
@@ -513,7 +515,13 @@
 
     data = webrtc_perf_tests_resources
     if (is_android) {
-      deps += [ "//testing/android/native_test:native_test_native_code" ]
+      deps += [
+        # Including Java classes seems only to be possible from rtc_test
+        # targets. Therefore we include this target here, instead of
+        # in video_full_stack_tests, where it is actually used.
+        "sdk/android:libjingle_peerconnection_java",
+        "//testing/android/native_test:native_test_native_code",
+      ]
       shard_timeout = 2700
     }
     if (is_ios) {
diff --git a/call/call_perf_tests.cc b/call/call_perf_tests.cc
index 98ebe8b..2bd5e22 100644
--- a/call/call_perf_tests.cc
+++ b/call/call_perf_tests.cc
@@ -177,7 +177,7 @@
         FakeAudioDevice::CreatePulsedNoiseCapturer(256, 48000),
         FakeAudioDevice::CreateDiscardRenderer(48000), audio_rtp_speed);
     EXPECT_EQ(0, voe_base->Init(fake_audio_device.get(), audio_processing.get(),
-                                decoder_factory_));
+                                audio_decoder_factory_));
     VoEBase::ChannelConfig config;
     config.enable_voice_pacing = true;
     send_channel_id = voe_base->CreateChannel(config);
@@ -250,7 +250,7 @@
     audio_recv_config.rtp.local_ssrc = kAudioRecvSsrc;
     audio_recv_config.voe_channel_id = recv_channel_id;
     audio_recv_config.sync_group = kSyncGroup;
-    audio_recv_config.decoder_factory = decoder_factory_;
+    audio_recv_config.decoder_factory = audio_decoder_factory_;
     audio_recv_config.decoder_map = {
         {kAudioSendPayloadType, {"ISAC", 16000, 1}}};
 
diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn
index 785533a..463665f 100644
--- a/modules/video_coding/BUILD.gn
+++ b/modules/video_coding/BUILD.gn
@@ -394,6 +394,23 @@
     ]
   }
 
+  if (is_android) {
+    rtc_source_set("codecs_test_android_test_initializer") {
+      testonly = true
+
+      sources = [
+        "codecs/test/android_test_initializer.cc",
+        "codecs/test/android_test_initializer.h",
+      ]
+
+      deps = [
+        "../../rtc_base:rtc_base_approved",
+        "../../sdk/android:libjingle_peerconnection_jni",
+        "//base",
+      ]
+    }
+  }
+
   video_coding_modules_tests_resources = [
     "../../resources/foreman_128x96.yuv",
     "../../resources/foreman_160x120.yuv",
@@ -455,15 +472,9 @@
     data = video_coding_modules_tests_resources
 
     if (is_android) {
-      sources += [
-        "codecs/test/android_test_initializer.cc",
-        "codecs/test/android_test_initializer.h",
-        "codecs/test/videoprocessor_integrationtest_mediacodec.cc",
-      ]
-
       deps += [
-        "../../sdk/android:libjingle_peerconnection_jni",
-        "//base",
+        ":codecs_test_android_test_initializer",
+        "../../sdk/android:video_jni",
       ]
     }
 
@@ -471,8 +482,6 @@
       deps += [
         ":codec_test_objc",
         ":video_coding_modules_tests_resources_bundle_data",
-        "../../media:rtc_media_base",
-        "../../sdk:videotoolbox_objc",
       ]
     }
 
diff --git a/test/call_test.cc b/test/call_test.cc
index f4b3877..4d75ef9 100644
--- a/test/call_test.cc
+++ b/test/call_test.cc
@@ -42,8 +42,8 @@
       num_video_streams_(1),
       num_audio_streams_(0),
       num_flexfec_streams_(0),
-      decoder_factory_(CreateBuiltinAudioDecoderFactory()),
-      encoder_factory_(CreateBuiltinAudioEncoderFactory()),
+      audio_decoder_factory_(CreateBuiltinAudioDecoderFactory()),
+      audio_encoder_factory_(CreateBuiltinAudioEncoderFactory()),
       task_queue_("CallTestTaskQueue"),
       fake_send_audio_device_(nullptr),
       fake_recv_audio_device_(nullptr) {}
@@ -223,7 +223,7 @@
     audio_send_config_.send_codec_spec =
         rtc::Optional<AudioSendStream::Config::SendCodecSpec>(
             {kAudioSendPayloadType, {"opus", 48000, 2, {{"stereo", "1"}}}});
-    audio_send_config_.encoder_factory = encoder_factory_;
+    audio_send_config_.encoder_factory = audio_encoder_factory_;
   }
 
   // TODO(brandtr): Update this when we support multistream protection.
@@ -268,7 +268,7 @@
     audio_config.rtcp_send_transport = rtcp_send_transport;
     audio_config.voe_channel_id = voe_recv_.channel_id;
     audio_config.rtp.remote_ssrc = audio_send_config_.rtp.ssrc;
-    audio_config.decoder_factory = decoder_factory_;
+    audio_config.decoder_factory = audio_decoder_factory_;
     audio_config.decoder_map = {{kAudioSendPayloadType, {"opus", 48000, 2}}};
     audio_receive_configs_.push_back(audio_config);
   }
@@ -428,7 +428,7 @@
   voe_send_.voice_engine = VoiceEngine::Create();
   voe_send_.base = VoEBase::GetInterface(voe_send_.voice_engine);
   EXPECT_EQ(0, voe_send_.base->Init(fake_send_audio_device_.get(),
-                                    apm_send_.get(), decoder_factory_));
+                                    apm_send_.get(), audio_decoder_factory_));
   VoEBase::ChannelConfig config;
   config.enable_voice_pacing = true;
   voe_send_.channel_id = voe_send_.base->CreateChannel(config);
@@ -437,7 +437,7 @@
   voe_recv_.voice_engine = VoiceEngine::Create();
   voe_recv_.base = VoEBase::GetInterface(voe_recv_.voice_engine);
   EXPECT_EQ(0, voe_recv_.base->Init(fake_recv_audio_device_.get(),
-                                    apm_recv_.get(), decoder_factory_));
+                                    apm_recv_.get(), audio_decoder_factory_));
   voe_recv_.channel_id = voe_recv_.base->CreateChannel();
   EXPECT_GE(voe_recv_.channel_id, 0);
 }
diff --git a/test/call_test.h b/test/call_test.h
index cf15aac..238539c 100644
--- a/test/call_test.h
+++ b/test/call_test.h
@@ -133,8 +133,8 @@
   size_t num_video_streams_;
   size_t num_audio_streams_;
   size_t num_flexfec_streams_;
-  rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_;
-  rtc::scoped_refptr<AudioEncoderFactory> encoder_factory_;
+  rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory_;
+  rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory_;
   test::FakeVideoRenderer fake_renderer_;
 
   SingleThreadedTaskQueueForTesting task_queue_;
diff --git a/video/BUILD.gn b/video/BUILD.gn
index 202a706..cab0421 100644
--- a/video/BUILD.gn
+++ b/video/BUILD.gn
@@ -124,6 +124,15 @@
       "../voice_engine",
       "//testing/gtest",
     ]
+    if (is_android) {
+      deps += [
+        "../modules/video_coding:codecs_test_android_test_initializer",
+        "../sdk/android:video_jni",
+      ]
+    }
+    if (is_ios || is_mac) {
+      deps += [ "../modules/video_coding:codec_test_objc" ]
+    }
     if (!build_with_chromium && is_clang) {
       # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
       suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
diff --git a/video/DEPS b/video/DEPS
index b94455e..03bb099 100644
--- a/video/DEPS
+++ b/video/DEPS
@@ -14,6 +14,7 @@
   "+modules/video_coding",
   "+modules/video_capture",
   "+modules/video_processing",
+  "+sdk",
   "+system_wrappers",
   "+voice_engine",
 ]
diff --git a/video/full_stack_tests.cc b/video/full_stack_tests.cc
index ea1e37f..836b8c3 100644
--- a/video/full_stack_tests.cc
+++ b/video/full_stack_tests.cc
@@ -9,6 +9,8 @@
  */
 #include <stdio.h>
 
+#include <string>
+
 #include "modules/pacing/alr_detector.h"
 #include "test/field_trial.h"
 #include "test/gtest.h"
@@ -49,8 +51,9 @@
   // TODO(pbos): Decide on psnr/ssim thresholds for foreman_cif.
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,  352, 288, 30, 700000, 700000, 700000,       false,
-                       "VP9", 1,   0,   0,  false,  false,  "foreman_cif"};
+  foreman_cif.video = {true,   352,   288,   30,    700000,       700000,
+                       700000, false, "VP9", false, false,        1,
+                       0,      0,     false, false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_net_delay_0_0_plr_0_VP9", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   RunTest(foreman_cif);
@@ -59,8 +62,9 @@
 TEST_F(FullStackTest, ForemanCifPlr5Vp9) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,  352, 288, 30, 30000, 500000, 2000000,      false,
-                       "VP9", 1,   0,   0,  false, false,  "foreman_cif"};
+  foreman_cif.video = {true,    352,   288,   30,    30000,        500000,
+                       2000000, false, "VP9", false, false,        1,
+                       0,       0,     false, false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_delay_50_0_plr_5_VP9", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   foreman_cif.pipe.loss_percent = 5;
@@ -72,8 +76,9 @@
 TEST_F(FullStackTest, ParisQcifWithoutPacketLoss) {
   VideoQualityTest::Params paris_qcif;
   paris_qcif.call.send_side_bwe = true;
-  paris_qcif.video = {true,  176, 144, 30, 300000, 300000, 300000,      false,
-                      "VP8", 1,   0,   0,  false,  false,  "paris_qcif"};
+  paris_qcif.video = {true,   176,   144,   30,    300000,      300000,
+                      300000, false, "VP8", false, false,       1,
+                      0,      0,     false, false, "paris_qcif"};
   paris_qcif.analyzer = {"net_delay_0_0_plr_0", 36.0, 0.96,
                          kFullStackTestDurationSecs};
   RunTest(paris_qcif);
@@ -83,8 +88,9 @@
   // TODO(pbos): Decide on psnr/ssim thresholds for foreman_cif.
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,  352, 288, 30, 700000, 700000, 700000,       false,
-                       "VP8", 1,   0,   0,  false,  false,  "foreman_cif"};
+  foreman_cif.video = {true,   352,   288,   30,    700000,       700000,
+                       700000, false, "VP8", false, false,        1,
+                       0,      0,     false, false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_net_delay_0_0_plr_0", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   RunTest(foreman_cif);
@@ -93,8 +99,9 @@
 TEST_F(FullStackTest, ForemanCif30kbpsWithoutPacketLoss) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,  352, 288, 10, 30000, 30000, 30000,        false,
-                       "VP8", 1,   0,   0,  false, false, "foreman_cif"};
+  foreman_cif.video = {true,  352,   288,   10,    30000,        30000,
+                       30000, false, "VP8", false, false,        1,
+                       0,     0,     false, false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_30kbps_net_delay_0_0_plr_0", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   RunTest(foreman_cif);
@@ -103,8 +110,9 @@
 TEST_F(FullStackTest, ForemanCifPlr5) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,  352, 288, 30, 30000, 500000, 2000000,      false,
-                       "VP8", 1,   0,   0,  false, false,  "foreman_cif"};
+  foreman_cif.video = {true,    352,   288,   30,    30000,        500000,
+                       2000000, false, "VP8", false, false,        1,
+                       0,       0,     false, false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_delay_50_0_plr_5", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   foreman_cif.pipe.loss_percent = 5;
@@ -115,8 +123,9 @@
 TEST_F(FullStackTest, ForemanCifPlr5Ulpfec) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,  352, 288, 30, 30000, 500000, 2000000,      false,
-                       "VP8", 1,   0,   0,  true,  false,  "foreman_cif"};
+  foreman_cif.video = {true,    352,   288,   30,    30000,        500000,
+                       2000000, false, "VP8", false, false,        1,
+                       0,       0,     true,  false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_delay_50_0_plr_5_ulpfec", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   foreman_cif.pipe.loss_percent = 5;
@@ -127,8 +136,9 @@
 TEST_F(FullStackTest, ForemanCifPlr5Flexfec) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,  352, 288, 30, 30000, 500000, 2000000,      false,
-                       "VP8", 1,   0,   0,  false, true,   "foreman_cif"};
+  foreman_cif.video = {true,    352,   288,   30,    30000,        500000,
+                       2000000, false, "VP8", false, false,        1,
+                       0,       0,     false, true,  "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_delay_50_0_plr_5_flexfec", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   foreman_cif.pipe.loss_percent = 5;
@@ -139,8 +149,9 @@
 TEST_F(FullStackTest, ForemanCif500kbpsPlr3Flexfec) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,  352, 288, 30, 30000, 500000, 2000000,      false,
-                       "VP8", 1,   0,   0,  false, true,   "foreman_cif"};
+  foreman_cif.video = {true,    352,   288,   30,    30000,        500000,
+                       2000000, false, "VP8", false, false,        1,
+                       0,       0,     false, true,  "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_500kbps_delay_50_0_plr_3_flexfec", 0.0,
                           0.0, kFullStackTestDurationSecs};
   foreman_cif.pipe.loss_percent = 3;
@@ -152,8 +163,9 @@
 TEST_F(FullStackTest, ForemanCif500kbpsPlr3Ulpfec) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,  352, 288, 30, 30000, 500000, 2000000,      false,
-                       "VP8", 1,   0,   0,  true,  false,  "foreman_cif"};
+  foreman_cif.video = {true,    352,   288,   30,    30000,        500000,
+                       2000000, false, "VP8", false, false,        1,
+                       0,       0,     true,  false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_500kbps_delay_50_0_plr_3_ulpfec", 0.0,
                           0.0, kFullStackTestDurationSecs};
   foreman_cif.pipe.loss_percent = 3;
@@ -167,9 +179,9 @@
   // TODO(pbos): Decide on psnr/ssim thresholds for foreman_cif.
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,   352,    288,   30,     700000,
-                       700000, 700000, false, "H264", 1,
-                       0,      0,      false, false,  "foreman_cif"};
+  foreman_cif.video = {true,   352,   288,    30,    700000,       700000,
+                       700000, false, "H264", false, false,        1,
+                       0,      0,     false,  false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_net_delay_0_0_plr_0_H264", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   RunTest(foreman_cif);
@@ -178,8 +190,9 @@
 TEST_F(FullStackTest, ForemanCif30kbpsWithoutPacketlossH264) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,   352, 288, 10, 30000, 30000, 30000,        false,
-                       "H264", 1,   0,   0,  false, false, "foreman_cif"};
+  foreman_cif.video = {true,  352,   288,    10,    30000,        30000,
+                       30000, false, "H264", false, false,        1,
+                       0,     0,     false,  false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_30kbps_net_delay_0_0_plr_0_H264", 0.0,
                           0.0, kFullStackTestDurationSecs};
   RunTest(foreman_cif);
@@ -188,8 +201,9 @@
 TEST_F(FullStackTest, ForemanCifPlr5H264) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,   352, 288, 30, 30000, 500000, 2000000,      false,
-                       "H264", 1,   0,   0,  false, false,  "foreman_cif"};
+  foreman_cif.video = {true,    352,   288,    30,    30000,        500000,
+                       2000000, false, "H264", false, false,        1,
+                       0,       0,     false,  false, "foreman_cif"};
   std::string fec_description;
   foreman_cif.analyzer = {"foreman_cif_delay_50_0_plr_5_H264", 0.0, 0.0,
                           kFullStackTestDurationSecs};
@@ -202,8 +216,9 @@
 TEST_F(FullStackTest, ForemanCifPlr5H264Flexfec) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,   352, 288, 30, 30000, 500000, 2000000,      false,
-                       "H264", 1,   0,   0,  false, true,   "foreman_cif"};
+  foreman_cif.video = {true,    352,   288,    30,    30000,        500000,
+                       2000000, false, "H264", false, false,        1,
+                       0,       0,     false,  true,  "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_delay_50_0_plr_5_H264_flexfec", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   foreman_cif.pipe.loss_percent = 5;
@@ -216,8 +231,9 @@
 TEST_F(FullStackTest, DISABLED_ForemanCifPlr5H264Ulpfec) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,   352, 288, 30, 30000, 500000, 2000000,      false,
-                       "H264", 1,   0,   0,  true,  false,  "foreman_cif"};
+  foreman_cif.video = {true,    352,   288,    30,    30000,        500000,
+                       2000000, false, "H264", false, false,        1,
+                       0,       0,     true,   false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_delay_50_0_plr_5_H264_ulpfec", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   foreman_cif.pipe.loss_percent = 5;
@@ -229,8 +245,9 @@
 TEST_F(FullStackTest, ForemanCif500kbps) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,  352, 288, 30, 30000, 500000, 2000000,      false,
-                       "VP8", 1,   0,   0,  false, false,  "foreman_cif"};
+  foreman_cif.video = {true,    352,   288,   30,    30000,        500000,
+                       2000000, false, "VP8", false, false,        1,
+                       0,       0,     false, false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_500kbps", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   foreman_cif.pipe.queue_length_packets = 0;
@@ -239,11 +256,81 @@
   RunTest(foreman_cif);
 }
 
+TEST_F(FullStackTest, ForemanSqcif30kbpsLibvpx) {
+  VideoQualityTest::Params foreman_sqcif;
+  foreman_sqcif.call.send_side_bwe = true;
+  foreman_sqcif.video = {true,    128,   96,    7,     30000,           30000,
+                         2000000, false, "VP8", false, false,           1,
+                         0,       0,     false, false, "foreman_128x96"};
+  foreman_sqcif.analyzer = {"foreman_sqcif_30kbps_libvpx", 0.0, 0.0,
+                            kFullStackTestDurationSecs};
+  foreman_sqcif.pipe.link_capacity_kbps = 30;
+  RunTest(foreman_sqcif);
+}
+
+TEST_F(FullStackTest, Foreman240p100kbpsLibvpx) {
+  VideoQualityTest::Params foreman_240p;
+  foreman_240p.call.send_side_bwe = true;
+  foreman_240p.video = {
+      true,  320, 240, 10, 30000, 100000, 2000000,          false, "VP8", false,
+      false, 1,   0,   0,  false, false,  "foreman_320x240"};
+  foreman_240p.analyzer = {"foreman_240p_100kbps_libvpx", 0.0, 0.0,
+                           kFullStackTestDurationSecs};
+  foreman_240p.pipe.link_capacity_kbps = 100;
+  RunTest(foreman_240p);
+}
+
+#if defined(WEBRTC_ANDROID)
+// TODO(brandtr): Enable when the test is more robust against failing encoders,
+// or when the perf waterfall Android bots all support sqcif.
+TEST_F(FullStackTest, DISABLED_ForemanSqcif30kbpsMediaCodec) {
+  VideoQualityTest::Params foreman_sqcif;
+  foreman_sqcif.call.send_side_bwe = true;
+  foreman_sqcif.video = {true,    128,   96,    7,     30000,           30000,
+                         2000000, false, "VP8", true,  false,           1,
+                         0,       0,     false, false, "foreman_128x96"};
+  foreman_sqcif.analyzer = {"foreman_sqcif_30kbps_mediacodec", 0.0, 0.0,
+                            kFullStackTestDurationSecs};
+  foreman_sqcif.pipe.link_capacity_kbps = 30;
+  RunTest(foreman_sqcif);
+}
+
+TEST_F(FullStackTest, Foreman240p100kbpsMediaCodec) {
+  VideoQualityTest::Params foreman_240p;
+  foreman_240p.call.send_side_bwe = true;
+  foreman_240p.video = {
+      true,  320, 240, 10, 30000, 100000, 2000000,          false, "VP8", true,
+      false, 1,   0,   0,  false, false,  "foreman_320x240"};
+  foreman_240p.analyzer = {"foreman_240p_100kbps_mediacodec", 0.0, 0.0,
+                           kFullStackTestDurationSecs};
+  foreman_240p.pipe.link_capacity_kbps = 100;
+  RunTest(foreman_240p);
+}
+
+TEST_F(FullStackTest, Foreman240p100kbpsMediaCodecWithForcedSwFallback) {
+  std::string field_trial =
+      "WebRTC-VP8-Forced-Fallback-Encoder/Enabled-150,175," +
+      std::to_string(1000 * kFullStackTestDurationSecs / 2) + ",19200/";
+  test::ScopedFieldTrials override_field_trials(field_trial);
+
+  VideoQualityTest::Params foreman_240p;
+  foreman_240p.call.send_side_bwe = true;
+  foreman_240p.video = {
+      true, 320, 240, 10, 30000, 100000, 2000000,          false, "VP8", true,
+      true, 1,   0,   0,  false, false,  "foreman_320x240"};
+  foreman_240p.analyzer = {"foreman_240p_100kbps_mediacodec_sw_fallback", 0.0,
+                           0.0, kFullStackTestDurationSecs};
+  foreman_240p.pipe.link_capacity_kbps = 100;
+  RunTest(foreman_240p);
+}
+#endif  // defined(WEBRTC_ANDROID)
+
 TEST_F(FullStackTest, ForemanCif500kbpsLimitedQueue) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,  352, 288, 30, 30000, 500000, 2000000,      false,
-                       "VP8", 1,   0,   0,  false, false,  "foreman_cif"};
+  foreman_cif.video = {true,    352,   288,   30,    30000,        500000,
+                       2000000, false, "VP8", false, false,        1,
+                       0,       0,     false, false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_500kbps_32pkts_queue", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   foreman_cif.pipe.queue_length_packets = 32;
@@ -255,8 +342,9 @@
 TEST_F(FullStackTest, ForemanCif500kbps100ms) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,  352, 288, 30, 30000, 500000, 2000000,      false,
-                       "VP8", 1,   0,   0,  false, false,  "foreman_cif"};
+  foreman_cif.video = {true,    352,   288,   30,    30000,        500000,
+                       2000000, false, "VP8", false, false,        1,
+                       0,       0,     false, false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_500kbps_100ms", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   foreman_cif.pipe.queue_length_packets = 0;
@@ -268,8 +356,9 @@
 TEST_F(FullStackTest, ForemanCif500kbps100msLimitedQueue) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,  352, 288, 30, 30000, 500000, 2000000,      false,
-                       "VP8", 1,   0,   0,  false, false,  "foreman_cif"};
+  foreman_cif.video = {true,    352,   288,   30,    30000,        500000,
+                       2000000, false, "VP8", false, false,        1,
+                       0,       0,     false, false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_500kbps_100ms_32pkts_queue", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   foreman_cif.pipe.queue_length_packets = 32;
@@ -281,8 +370,9 @@
 TEST_F(FullStackTest, ForemanCif500kbps100msLimitedQueueRecvBwe) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = false;
-  foreman_cif.video = {true,  352, 288, 30, 30000, 500000, 2000000,      false,
-                       "VP8", 1,   0,   0,  false, false,  "foreman_cif"};
+  foreman_cif.video = {true,    352,   288,   30,    30000,        500000,
+                       2000000, false, "VP8", false, false,        1,
+                       0,       0,     false, false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_500kbps_100ms_32pkts_queue_recv_bwe",
                           0.0, 0.0, kFullStackTestDurationSecs};
   foreman_cif.pipe.queue_length_packets = 32;
@@ -294,8 +384,9 @@
 TEST_F(FullStackTest, ForemanCif1000kbps100msLimitedQueue) {
   VideoQualityTest::Params foreman_cif;
   foreman_cif.call.send_side_bwe = true;
-  foreman_cif.video = {true,  352, 288, 30, 30000, 2000000, 2000000,      false,
-                       "VP8", 1,   0,   0,  false, false,   "foreman_cif"};
+  foreman_cif.video = {true,    352,   288,   30,    30000,        2000000,
+                       2000000, false, "VP8", false, false,        1,
+                       0,       0,     false, false, "foreman_cif"};
   foreman_cif.analyzer = {"foreman_cif_1000kbps_100ms_32pkts_queue", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   foreman_cif.pipe.queue_length_packets = 32;
@@ -308,10 +399,23 @@
 TEST_F(FullStackTest, ConferenceMotionHd2000kbps100msLimitedQueue) {
   VideoQualityTest::Params conf_motion_hd;
   conf_motion_hd.call.send_side_bwe = true;
-  conf_motion_hd.video = {
-      true,    1280,    720,   50,    30000,
-      3000000, 3000000, false, "VP8", 1,
-      0,       0,       false, false, "ConferenceMotion_1280_720_50"};
+  conf_motion_hd.video = {true,
+                          1280,
+                          720,
+                          50,
+                          30000,
+                          3000000,
+                          3000000,
+                          false,
+                          "VP8",
+                          false,
+                          false,
+                          1,
+                          0,
+                          0,
+                          false,
+                          false,
+                          "ConferenceMotion_1280_720_50"};
   conf_motion_hd.analyzer = {"conference_motion_hd_2000kbps_100ms_32pkts_queue",
                              0.0, 0.0, kFullStackTestDurationSecs};
   conf_motion_hd.pipe.queue_length_packets = 32;
@@ -323,10 +427,23 @@
 TEST_F(FullStackTest, ConferenceMotionHd1TLModerateLimits) {
   VideoQualityTest::Params conf_motion_hd;
   conf_motion_hd.call.send_side_bwe = true;
-  conf_motion_hd.video = {
-      true,    1280,    720,   50,    30000,
-      3000000, 3000000, false, "VP8", 1,
-      -1,      0,       false, false, "ConferenceMotion_1280_720_50"};
+  conf_motion_hd.video = {true,
+                          1280,
+                          720,
+                          50,
+                          30000,
+                          3000000,
+                          3000000,
+                          false,
+                          "VP8",
+                          false,
+                          false,
+                          1,
+                          -1,
+                          0,
+                          false,
+                          false,
+                          "ConferenceMotion_1280_720_50"};
   conf_motion_hd.analyzer = {"conference_motion_hd_1tl_moderate_limits", 0.0,
                              0.0, kFullStackTestDurationSecs};
   conf_motion_hd.pipe.queue_length_packets = 50;
@@ -339,10 +456,23 @@
 TEST_F(FullStackTest, ConferenceMotionHd2TLModerateLimits) {
   VideoQualityTest::Params conf_motion_hd;
   conf_motion_hd.call.send_side_bwe = true;
-  conf_motion_hd.video = {
-      true,    1280,    720,   50,    30000,
-      3000000, 3000000, false, "VP8", 2,
-      -1,      0,       false, false, "ConferenceMotion_1280_720_50"};
+  conf_motion_hd.video = {true,
+                          1280,
+                          720,
+                          50,
+                          30000,
+                          3000000,
+                          3000000,
+                          false,
+                          "VP8",
+                          false,
+                          false,
+                          2,
+                          -1,
+                          0,
+                          false,
+                          false,
+                          "ConferenceMotion_1280_720_50"};
   conf_motion_hd.analyzer = {"conference_motion_hd_2tl_moderate_limits", 0.0,
                              0.0, kFullStackTestDurationSecs};
   conf_motion_hd.pipe.queue_length_packets = 50;
@@ -355,10 +485,23 @@
 TEST_F(FullStackTest, ConferenceMotionHd3TLModerateLimits) {
   VideoQualityTest::Params conf_motion_hd;
   conf_motion_hd.call.send_side_bwe = true;
-  conf_motion_hd.video = {
-      true,    1280,    720,   50,    30000,
-      3000000, 3000000, false, "VP8", 3,
-      -1,      0,       false, false, "ConferenceMotion_1280_720_50"};
+  conf_motion_hd.video = {true,
+                          1280,
+                          720,
+                          50,
+                          30000,
+                          3000000,
+                          3000000,
+                          false,
+                          "VP8",
+                          false,
+                          false,
+                          3,
+                          -1,
+                          0,
+                          false,
+                          false,
+                          "ConferenceMotion_1280_720_50"};
   conf_motion_hd.analyzer = {"conference_motion_hd_3tl_moderate_limits", 0.0,
                              0.0, kFullStackTestDurationSecs};
   conf_motion_hd.pipe.queue_length_packets = 50;
@@ -371,10 +514,23 @@
 TEST_F(FullStackTest, ConferenceMotionHd4TLModerateLimits) {
   VideoQualityTest::Params conf_motion_hd;
   conf_motion_hd.call.send_side_bwe = true;
-  conf_motion_hd.video = {
-      true,    1280,    720,   50,    30000,
-      3000000, 3000000, false, "VP8", 4,
-      -1,      0,       false, false, "ConferenceMotion_1280_720_50"};
+  conf_motion_hd.video = {true,
+                          1280,
+                          720,
+                          50,
+                          30000,
+                          3000000,
+                          3000000,
+                          false,
+                          "VP8",
+                          false,
+                          false,
+                          4,
+                          -1,
+                          0,
+                          false,
+                          false,
+                          "ConferenceMotion_1280_720_50"};
   conf_motion_hd.analyzer = {"conference_motion_hd_4tl_moderate_limits", 0.0,
                              0.0, kFullStackTestDurationSecs};
   conf_motion_hd.pipe.queue_length_packets = 50;
@@ -388,10 +544,23 @@
   test::ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/");
   VideoQualityTest::Params conf_motion_hd;
   conf_motion_hd.call.send_side_bwe = true;
-  conf_motion_hd.video = {
-      true,    1280,    720,   50,    30000,
-      3000000, 3000000, false, "VP8", 3,
-      -1,      0,       false, false, "ConferenceMotion_1280_720_50"};
+  conf_motion_hd.video = {true,
+                          1280,
+                          720,
+                          50,
+                          30000,
+                          3000000,
+                          3000000,
+                          false,
+                          "VP8",
+                          false,
+                          false,
+                          3,
+                          -1,
+                          0,
+                          false,
+                          false,
+                          "ConferenceMotion_1280_720_50"};
   conf_motion_hd.analyzer = {"conference_motion_hd_3tl_alt_moderate_limits",
                              0.0, 0.0, kFullStackTestDurationSecs};
   conf_motion_hd.pipe.queue_length_packets = 50;
@@ -405,10 +574,23 @@
 TEST_F(FullStackTest, ConferenceMotionHd2000kbps100msLimitedQueueVP9) {
   VideoQualityTest::Params conf_motion_hd;
   conf_motion_hd.call.send_side_bwe = true;
-  conf_motion_hd.video = {
-      true,    1280,    720,   50,    30000,
-      3000000, 3000000, false, "VP9", 1,
-      0,       0,       false, false, "ConferenceMotion_1280_720_50"};
+  conf_motion_hd.video = {true,
+                          1280,
+                          720,
+                          50,
+                          30000,
+                          3000000,
+                          3000000,
+                          false,
+                          "VP9",
+                          false,
+                          false,
+                          1,
+                          0,
+                          0,
+                          false,
+                          false,
+                          "ConferenceMotion_1280_720_50"};
   conf_motion_hd.analyzer = {
       "conference_motion_hd_2000kbps_100ms_32pkts_queue_vp9", 0.0, 0.0,
       kFullStackTestDurationSecs};
@@ -422,8 +604,9 @@
 TEST_F(FullStackTest, ScreenshareSlidesVP8_2TL) {
   VideoQualityTest::Params screenshare;
   screenshare.call.send_side_bwe = true;
-  screenshare.video = {true,  1850, 1110, 5,      50000, 200000, 2000000, false,
-                       "VP8", 2,    1,    400000, false, false,  ""};
+  screenshare.video = {true,    1850,   1110,  5,     50000, 200000,
+                       2000000, false,  "VP8", false, false, 2,
+                       1,       400000, false, false, ""};
   screenshare.screenshare = {true, false, 10};
   screenshare.analyzer = {"screenshare_slides", 0.0, 0.0,
                           kFullStackTestDurationSecs};
@@ -435,19 +618,19 @@
   VideoQualityTest::Params screenshare;
   screenshare.call.send_side_bwe = true;
   screenshare.screenshare = {true, false, 10};
-  screenshare.video = {true,    1850,    1110,  5,     800000,
-                       2500000, 2500000, false, "VP8", 3,
-                       2,       400000,  false, false, ""};
+  screenshare.video = {true,    1850,   1110,  5,     800000, 2500000,
+                       2500000, false,  "VP8", false, false,  3,
+                       2,       400000, false, false, ""};
   screenshare.analyzer = {"screenshare_slides_simulcast", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   VideoQualityTest::Params screenshare_params_high;
-  screenshare_params_high.video = {true,    1850,    1110,  5,     800000,
-                                   2500000, 2500000, false, "VP8", 3,
-                                   0,       400000,  false, false, ""};
+  screenshare_params_high.video = {
+      true,  1850,  1110, 5, 800000, 2500000, 2500000, false, "VP8",
+      false, false, 3,    0, 400000, false,   false,   ""};
   VideoQualityTest::Params screenshare_params_low;
-  screenshare_params_low.video = {true,   1850,    1110,  5,     50000,
-                                  200000, 2000000, false, "VP8", 2,
-                                  0,      400000,  false, false, ""};
+  screenshare_params_low.video = {true,    1850,   1110,  5,     50000, 200000,
+                                  2000000, false,  "VP8", false, false, 2,
+                                  0,       400000, false, false, ""};
 
   std::vector<VideoStream> streams = {
       DefaultVideoStream(screenshare_params_low),
@@ -459,8 +642,9 @@
 TEST_F(FullStackTest, ScreenshareSlidesVP8_2TL_Scroll) {
   VideoQualityTest::Params config;
   config.call.send_side_bwe = true;
-  config.video = {true,  1850, 1110 / 2, 5,      50000, 200000, 2000000, false,
-                  "VP8", 2,    1,        400000, false, false,  ""};
+  config.video = {true,    1850,   1110 / 2, 5,     50000, 200000,
+                  2000000, false,  "VP8",    false, false, 2,
+                  1,       400000, false,    false, ""};
   config.screenshare = {true, false, 10, 2};
   config.analyzer = {"screenshare_slides_scrolling", 0.0, 0.0,
                      kFullStackTestDurationSecs};
@@ -470,8 +654,9 @@
 TEST_F(FullStackTest, ScreenshareSlidesVP8_2TL_LossyNet) {
   VideoQualityTest::Params screenshare;
   screenshare.call.send_side_bwe = true;
-  screenshare.video = {true,  1850, 1110, 5,      50000, 200000, 2000000, false,
-                       "VP8", 2,    1,    400000, false, false,  ""};
+  screenshare.video = {true,    1850,   1110,  5,     50000, 200000,
+                       2000000, false,  "VP8", false, false, 2,
+                       1,       400000, false, false, ""};
   screenshare.screenshare = {true, false, 10};
   screenshare.analyzer = {"screenshare_slides_lossy_net", 0.0, 0.0,
                           kFullStackTestDurationSecs};
@@ -484,8 +669,9 @@
 TEST_F(FullStackTest, ScreenshareSlidesVP8_2TL_VeryLossyNet) {
   VideoQualityTest::Params screenshare;
   screenshare.call.send_side_bwe = true;
-  screenshare.video = {true,  1850, 1110, 5,      50000, 200000, 2000000, false,
-                       "VP8", 2,    1,    400000, false, false,  ""};
+  screenshare.video = {true,    1850,   1110,  5,     50000, 200000,
+                       2000000, false,  "VP8", false, false, 2,
+                       1,       400000, false, false, ""};
   screenshare.screenshare = {true, false, 10};
   screenshare.analyzer = {"screenshare_slides_very_lossy", 0.0, 0.0,
                           kFullStackTestDurationSecs};
@@ -498,8 +684,9 @@
 TEST_F(FullStackTest, ScreenshareSlidesVP8_2TL_LossyNetRestrictedQueue) {
   VideoQualityTest::Params screenshare;
   screenshare.call.send_side_bwe = true;
-  screenshare.video = {true,  1850, 1110, 5,      50000, 200000, 2000000, false,
-                       "VP8", 2,    1,    400000, false, false,  ""};
+  screenshare.video = {true,    1850,   1110,  5,     50000, 200000,
+                       2000000, false,  "VP8", false, false, 2,
+                       1,       400000, false, false, ""};
   screenshare.screenshare = {true, false, 10};
   screenshare.analyzer = {"screenshare_slides_lossy_limited", 0.0, 0.0,
                           kFullStackTestDurationSecs};
@@ -513,8 +700,9 @@
 TEST_F(FullStackTest, ScreenshareSlidesVP8_2TL_ModeratelyRestricted) {
   VideoQualityTest::Params screenshare;
   screenshare.call.send_side_bwe = true;
-  screenshare.video = {true,  1850, 1110, 5,      50000, 200000, 2000000, false,
-                       "VP8", 2,    1,    400000, false, false,  ""};
+  screenshare.video = {true,    1850,   1110,  5,     50000, 200000,
+                       2000000, false,  "VP8", false, false, 2,
+                       1,       400000, false, false, ""};
   screenshare.screenshare = {true, false, 10};
   screenshare.analyzer = {"screenshare_slides_moderately_restricted", 0.0, 0.0,
                           kFullStackTestDurationSecs};
@@ -530,8 +718,9 @@
   test::ScopedFieldTrials field_trial(kAlrProbingExperiment);
   VideoQualityTest::Params screenshare;
   screenshare.call.send_side_bwe = true;
-  screenshare.video = {true,  1850, 1110, 5,      50000, 200000, 2000000, false,
-                       "VP8", 2,    1,    400000, false, false,  ""};
+  screenshare.video = {true,    1850,   1110,  5,     50000, 200000,
+                       2000000, false,  "VP8", false, false, 2,
+                       1,       400000, false, false, ""};
   screenshare.screenshare = {true, false, 10};
   screenshare.analyzer = {"screenshare_slides_lossy_limited_ALR", 0.0, 0.0,
                           kFullStackTestDurationSecs};
@@ -546,8 +735,9 @@
   test::ScopedFieldTrials field_trial(kAlrProbingExperiment);
   VideoQualityTest::Params screenshare;
   screenshare.call.send_side_bwe = true;
-  screenshare.video = {true,  1850, 1110, 5,      50000, 200000, 2000000, false,
-                       "VP8", 2,    1,    400000, false, false,  ""};
+  screenshare.video = {true,    1850,   1110,  5,     50000, 200000,
+                       2000000, false,  "VP8", false, false, 2,
+                       1,       400000, false, false, ""};
   screenshare.screenshare = {true, false, 10};
   screenshare.analyzer = {"screenshare_slides_ALR", 0.0, 0.0,
                           kFullStackTestDurationSecs};
@@ -558,8 +748,9 @@
   test::ScopedFieldTrials field_trial(kAlrProbingExperiment);
   VideoQualityTest::Params screenshare;
   screenshare.call.send_side_bwe = true;
-  screenshare.video = {true,  1850, 1110, 5,      50000, 200000, 2000000, false,
-                       "VP8", 2,    1,    400000, false, false,  ""};
+  screenshare.video = {true,    1850,   1110,  5,     50000, 200000,
+                       2000000, false,  "VP8", false, false, 2,
+                       1,       400000, false, false, ""};
   screenshare.screenshare = {true, false, 10};
   screenshare.analyzer = {"screenshare_slides_moderately_restricted_ALR", 0.0,
                           0.0, kFullStackTestDurationSecs};
@@ -576,19 +767,19 @@
   VideoQualityTest::Params screenshare;
   screenshare.call.send_side_bwe = true;
   screenshare.screenshare = {true, false, 10};
-  screenshare.video = {true,    1850,    1110,  5,     800000,
-                       2500000, 2500000, false, "VP8", 3,
-                       2,       400000,  false, false, ""};
+  screenshare.video = {true,    1850,   1110,  5,     800000, 2500000,
+                       2500000, false,  "VP8", false, false,  3,
+                       2,       400000, false, false, ""};
   screenshare.analyzer = {"screenshare_slides_simulcast_alr", 0.0, 0.0,
                           kFullStackTestDurationSecs};
   VideoQualityTest::Params screenshare_params_high;
-  screenshare_params_high.video = {true,    1850,    1110,  5,     800000,
-                                   2500000, 2500000, false, "VP8", 3,
-                                   0,       400000,  false, false, ""};
+  screenshare_params_high.video = {
+      true,  1850,  1110, 5, 800000, 2500000, 2500000, false, "VP8",
+      false, false, 3,    0, 400000, false,   false,   ""};
   VideoQualityTest::Params screenshare_params_low;
-  screenshare_params_low.video = {true,   1850,    1110,  5,     50000,
-                                  200000, 2000000, false, "VP8", 2,
-                                  0,      400000,  false, false, ""};
+  screenshare_params_low.video = {true,    1850,   1110,  5,     50000, 200000,
+                                  2000000, false,  "VP8", false, false, 2,
+                                  0,       400000, false, false, ""};
 
   std::vector<VideoStream> streams = {
       DefaultVideoStream(screenshare_params_low),
@@ -598,31 +789,88 @@
 }
 
 const VideoQualityTest::Params::Video kSvcVp9Video = {
-    true,    1280,    720,   30,    800000,
-    2500000, 2500000, false, "VP9", 3,
-    2,       400000,  false, false, "ConferenceMotion_1280_720_50"};
+    true,
+    1280,
+    720,
+    30,
+    800000,
+    2500000,
+    2500000,
+    false,
+    "VP9",
+    false,
+    false,
+    3,
+    2,
+    400000,
+    false,
+    false,
+    "ConferenceMotion_1280_720_50"};
 
 const VideoQualityTest::Params::Video kSimulcastVp8VideoHigh = {
-    true,    1280,    720,   30,    800000,
-    2500000, 2500000, false, "VP8", 3,
-    2,       400000,  false, false, "ConferenceMotion_1280_720_50"};
+    true,
+    1280,
+    720,
+    30,
+    800000,
+    2500000,
+    2500000,
+    false,
+    "VP8",
+    false,
+    false,
+    3,
+    2,
+    400000,
+    false,
+    false,
+    "ConferenceMotion_1280_720_50"};
 
 const VideoQualityTest::Params::Video kSimulcastVp8VideoMedium = {
-    true,   640,    360,   30,    150000,
-    500000, 700000, false, "VP8", 3,
-    2,      400000, false, false, "ConferenceMotion_1280_720_50"};
+    true,
+    640,
+    360,
+    30,
+    150000,
+    500000,
+    700000,
+    false,
+    "VP8",
+    false,
+    false,
+    3,
+    2,
+    400000,
+    false,
+    false,
+    "ConferenceMotion_1280_720_50"};
 
 const VideoQualityTest::Params::Video kSimulcastVp8VideoLow = {
-    true,   320,    180,   30,    30000,
-    150000, 200000, false, "VP8", 3,
-    2,      400000, false, false, "ConferenceMotion_1280_720_50"};
+    true,
+    320,
+    180,
+    30,
+    30000,
+    150000,
+    200000,
+    false,
+    "VP8",
+    false,
+    false,
+    3,
+    2,
+    400000,
+    false,
+    false,
+    "ConferenceMotion_1280_720_50"};
 
 #if !defined(RTC_DISABLE_VP9)
 TEST_F(FullStackTest, ScreenshareSlidesVP9_2SL) {
   VideoQualityTest::Params screenshare;
   screenshare.call.send_side_bwe = true;
-  screenshare.video = {true,  1850, 1110, 5,      50000, 200000, 2000000, false,
-                       "VP9", 1,    0,    400000, false, false,  ""};
+  screenshare.video = {true,    1850,   1110,  5,     50000, 200000,
+                       2000000, false,  "VP9", false, false, 1,
+                       0,       400000, false, false, ""};
   screenshare.screenshare = {true, false, 10};
   screenshare.analyzer = {"screenshare_slides_vp9_2sl", 0.0, 0.0,
                           kFullStackTestDurationSecs};
@@ -674,9 +922,9 @@
 TEST_F(FullStackTest, MAYBE_SimulcastFullHdOveruse) {
   VideoQualityTest::Params simulcast;
   simulcast.call.send_side_bwe = true;
-  simulcast.video = {true,    1920,    1080,  30,    800000,
-                     2500000, 2500000, false, "VP8", 3,
-                     2,       400000,  false, false, "Generator"};
+  simulcast.video = {true,    1920,   1080,  30,    800000,     2500000,
+                     2500000, false,  "VP8", false, false,      3,
+                     2,       400000, false, false, "Generator"};
   simulcast.analyzer = {"simulcast_HD_high", 0.0, 0.0,
                         kFullStackTestDurationSecs};
   simulcast.pipe.loss_percent = 0;
diff --git a/video/screenshare_loopback.cc b/video/screenshare_loopback.cc
index 8cb8193..6d26762 100644
--- a/video/screenshare_loopback.cc
+++ b/video/screenshare_loopback.cc
@@ -279,6 +279,8 @@
                   flags::MaxBitrateKbps() * 1000,
                   false,
                   flags::Codec(),
+                  false,  // No HW encoder.
+                  false,  // No SW fallback encoder.
                   flags::NumTemporalLayers(),
                   flags::SelectedTL(),
                   flags::MinTransmitBitrateKbps() * 1000,
diff --git a/video/video_loopback.cc b/video/video_loopback.cc
index d5d525a..5ade6f1 100644
--- a/video/video_loopback.cc
+++ b/video/video_loopback.cc
@@ -276,6 +276,8 @@
                   flags::MaxBitrateKbps() * 1000,
                   flags::FLAG_suspend_below_min_bitrate,
                   flags::Codec(),
+                  false,  // No HW encoder.
+                  false,  // No SW fallback encoder.
                   flags::NumTemporalLayers(),
                   flags::SelectedTL(),
                   0,  // No min transmit bitrate.
diff --git a/video/video_quality_test.cc b/video/video_quality_test.cc
index 2bfe0e3..32df77d 100644
--- a/video/video_quality_test.cc
+++ b/video/video_quality_test.cc
@@ -18,10 +18,20 @@
 #include <string>
 #include <vector>
 
+#if defined(WEBRTC_ANDROID)
+#include "modules/video_coding/codecs/test/android_test_initializer.h"
+#include "sdk/android/src/jni/androidmediadecoder_jni.h"
+#include "sdk/android/src/jni/androidmediaencoder_jni.h"
+#elif defined(WEBRTC_IOS)
+#include "modules/video_coding/codecs/test/objc_codec_h264_test.h"
+#endif
+
 #include "api/optional.h"
 #include "call/call.h"
 #include "common_video/libyuv/include/webrtc_libyuv.h"
 #include "logging/rtc_event_log/rtc_event_log.h"
+#include "media/engine/internalencoderfactory.h"
+#include "media/engine/videoencodersoftwarefallbackwrapper.h"
 #include "media/engine/webrtcvideoengine.h"
 #include "modules/audio_mixer/audio_mixer_impl.h"
 #include "modules/rtp_rtcp/include/rtp_header_parser.h"
@@ -1128,35 +1138,6 @@
   const int64_t start_ms_;
 };
 
-class Vp8EncoderFactory : public cricket::WebRtcVideoEncoderFactory {
- public:
-  Vp8EncoderFactory() {
-    supported_codecs_.push_back(cricket::VideoCodec("VP8"));
-  }
-  ~Vp8EncoderFactory() override { RTC_CHECK(live_encoders_.empty()); }
-
-  const std::vector<cricket::VideoCodec>& supported_codecs() const override {
-    return supported_codecs_;
-  }
-
-  VideoEncoder* CreateVideoEncoder(const cricket::VideoCodec& codec) override {
-    VideoEncoder* encoder = VP8Encoder::Create();
-    live_encoders_.insert(encoder);
-    return encoder;
-  }
-
-  void DestroyVideoEncoder(VideoEncoder* encoder) override {
-    auto it = live_encoders_.find(encoder);
-    RTC_CHECK(it != live_encoders_.end());
-    live_encoders_.erase(it);
-    delete encoder;
-  }
-
- private:
-  std::vector<cricket::VideoCodec> supported_codecs_;
-  std::set<VideoEncoder*> live_encoders_;
-};
-
 VideoQualityTest::VideoQualityTest()
     : clock_(Clock::GetRealTimeClock()), receive_logs_(0), send_logs_(0) {
   payload_type_map_ = test::CallTest::payload_type_map_;
@@ -1169,12 +1150,16 @@
   payload_type_map_[kPayloadTypeH264] = webrtc::MediaType::VIDEO;
   payload_type_map_[kPayloadTypeVP8] = webrtc::MediaType::VIDEO;
   payload_type_map_[kPayloadTypeVP9] = webrtc::MediaType::VIDEO;
+
+#if defined(WEBRTC_ANDROID)
+  InitializeAndroidObjects();
+#endif
 }
 
 VideoQualityTest::Params::Params()
     : call({false, Call::Config::BitrateConfig(), 0}),
-      video({false, 640, 480, 30, 50, 800, 800, false, "VP8", 1, -1, 0, false,
-             false, ""}),
+      video({false, 640, 480, 30, 50, 800, 800, false, "VP8", false, false, 1,
+             -1, 0, false, false, ""}),
       audio({false, false, false}),
       screenshare({false, false, 10, 0}),
       analyzer({"", 0.0, 0.0, 0, "", ""}),
@@ -1413,28 +1398,51 @@
   size_t num_flexfec_streams = params_.video.flexfec ? 1 : 0;
   CreateSendConfig(num_video_streams, 0, num_flexfec_streams, send_transport);
 
+  if (params_.video.hw_encoder) {
+#if defined(WEBRTC_ANDROID)
+    video_encoder_factory_.reset(new jni::MediaCodecVideoEncoderFactory());
+#elif defined(WEBRTC_IOS)
+    video_encoder_factory_ = CreateObjCEncoderFactory();
+#else
+    RTC_NOTREACHED() << "Only support HW encoder on Android and iOS.";
+#endif
+  } else {
+    video_encoder_factory_.reset(new cricket::InternalEncoderFactory());
+  }
+
+  cricket::VideoCodec codec;
   int payload_type;
   if (params_.video.codec == "H264") {
-    video_encoder_.reset(H264Encoder::Create(cricket::VideoCodec("H264")));
+    // TODO(brandtr): Add support for high profile here.
+    codec = cricket::VideoCodec(cricket::kH264CodecName);
+    video_encoder_.reset(video_encoder_factory_->CreateVideoEncoder(codec));
     payload_type = kPayloadTypeH264;
   } else if (params_.video.codec == "VP8") {
+    codec = cricket::VideoCodec(cricket::kVp8CodecName);
     if (params_.screenshare.enabled && params_.ss.streams.size() > 1) {
-      // Simulcast screenshare needs a simulcast encoder adapter to work, since
-      // encoders usually can't natively do simulcast with different frame rates
-      // for the different layers.
+      // Simulcast screenshare needs a simulcast encoder adapter to work,
+      // since encoders usually can't natively do simulcast with
+      // different frame rates for the different layers.
       video_encoder_.reset(
-          new SimulcastEncoderAdapter(new Vp8EncoderFactory()));
+          new SimulcastEncoderAdapter(video_encoder_factory_.get()));
     } else {
-      video_encoder_.reset(VP8Encoder::Create());
+      video_encoder_.reset(video_encoder_factory_->CreateVideoEncoder(codec));
     }
     payload_type = kPayloadTypeVP8;
   } else if (params_.video.codec == "VP9") {
-    video_encoder_.reset(VP9Encoder::Create());
+    codec = cricket::VideoCodec(cricket::kVp9CodecName);
+    video_encoder_.reset(video_encoder_factory_->CreateVideoEncoder(codec));
     payload_type = kPayloadTypeVP9;
   } else {
     RTC_NOTREACHED() << "Codec not supported!";
     return;
   }
+
+  if (params_.video.sw_fallback_encoder) {
+    video_encoder_ = rtc::MakeUnique<VideoEncoderSoftwareFallbackWrapper>(
+        codec, std::move(video_encoder_));
+  }
+
   video_send_config_.encoder_settings.encoder = video_encoder_.get();
   video_send_config_.encoder_settings.payload_name = params_.video.codec;
   video_send_config_.encoder_settings.payload_type = payload_type;
@@ -1965,7 +1973,7 @@
            {"OPUS", 48000, 2,
             {{"usedtx", (params_.audio.dtx ? "1" : "0")},
               {"stereo", "1"}}}});
-  audio_send_config_.encoder_factory = encoder_factory_;
+  audio_send_config_.encoder_factory = audio_encoder_factory_;
   audio_send_stream_ = sender_call_->CreateAudioSendStream(audio_send_config_);
 
   AudioReceiveStream::Config audio_config;
@@ -1975,7 +1983,7 @@
   audio_config.rtp.remote_ssrc = audio_send_config_.rtp.ssrc;
   audio_config.rtp.transport_cc = params_.call.send_side_bwe;
   audio_config.rtp.extensions = audio_send_config_.rtp.extensions;
-  audio_config.decoder_factory = decoder_factory_;
+  audio_config.decoder_factory = audio_decoder_factory_;
   audio_config.decoder_map = {{kAudioSendPayloadType, {"OPUS", 48000, 2}}};
   if (params_.video.enabled && params_.audio.sync_video)
     audio_config.sync_group = kSyncGroup;
@@ -2005,7 +2013,7 @@
         webrtc::AudioProcessing::Create());
 
     if (params_.audio.enabled) {
-      CreateVoiceEngine(&voe, audio_processing.get(), decoder_factory_);
+      CreateVoiceEngine(&voe, audio_processing.get(), audio_decoder_factory_);
       AudioState::Config audio_state_config;
       audio_state_config.voice_engine = voe.voice_engine;
       audio_state_config.audio_mixer = AudioMixerImpl::Create();
diff --git a/video/video_quality_test.h b/video/video_quality_test.h
index c16105c..bbbd0c8 100644
--- a/video/video_quality_test.h
+++ b/video/video_quality_test.h
@@ -16,6 +16,7 @@
 #include <vector>
 
 #include "media/engine/simulcast_encoder_adapter.h"
+#include "media/engine/webrtcvideoencoderfactory.h"
 #include "test/call_test.h"
 #include "test/frame_generator.h"
 #include "test/testsupport/trace_to_stderr.h"
@@ -46,6 +47,8 @@
       int max_bitrate_bps;
       bool suspend_below_min_bitrate;
       std::string codec;
+      bool hw_encoder;
+      bool sw_fallback_encoder;
       int num_temporal_layers;
       int selected_tl;
       int min_transmit_bps;
@@ -142,8 +145,8 @@
   std::vector<std::unique_ptr<test::VideoCapturer>> thumbnail_capturers_;
   std::unique_ptr<test::TraceToStderr> trace_to_stderr_;
   std::unique_ptr<test::FrameGenerator> frame_generator_;
+  std::unique_ptr<cricket::WebRtcVideoEncoderFactory> video_encoder_factory_;
   std::unique_ptr<VideoEncoder> video_encoder_;
-  std::unique_ptr<cricket::WebRtcVideoEncoderFactory> vp8_encoder_factory_;
 
   std::vector<std::unique_ptr<VideoEncoder>> thumbnail_encoders_;
   std::vector<VideoSendStream::Config> thumbnail_send_configs_;