Forward Encode failure codes from sub encoders.

Previously, failure codes were ignored, which meant simulcasted codecs
couldn't e.g. trigger software fallback. This stops the simulcasted
Encode call at the first faiulre and returns that code.

Another option is to continue sending the frame to the other encoders
but still return the first failure code. It's not clear that that is any
better than just quitting as soon as a failure happens.

BUG=

Review-Url: https://codereview.webrtc.org/2008723002
Cr-Commit-Position: refs/heads/master@{#12892}
diff --git a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc
index be55133..4f389b8 100644
--- a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc
+++ b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc
@@ -293,8 +293,11 @@
     // scale it to match what the encoder expects (below).
     if ((dst_width == src_width && dst_height == src_height) ||
         input_image.IsZeroSize()) {
-      streaminfos_[stream_idx].encoder->Encode(input_image, codec_specific_info,
-                                               &stream_frame_types);
+      int ret = streaminfos_[stream_idx].encoder->Encode(
+          input_image, codec_specific_info, &stream_frame_types);
+      if (ret != WEBRTC_VIDEO_CODEC_OK) {
+        return ret;
+      }
     } else {
       VideoFrame dst_frame;
       // Making sure that destination frame is of sufficient size.
@@ -318,8 +321,11 @@
                         libyuv::kFilterBilinear);
       dst_frame.set_timestamp(input_image.timestamp());
       dst_frame.set_render_time_ms(input_image.render_time_ms());
-      streaminfos_[stream_idx].encoder->Encode(dst_frame, codec_specific_info,
-                                               &stream_frame_types);
+      int ret = streaminfos_[stream_idx].encoder->Encode(
+          dst_frame, codec_specific_info, &stream_frame_types);
+      if (ret != WEBRTC_VIDEO_CODEC_OK) {
+        return ret;
+      }
     }
   }
 
diff --git a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter_unittest.cc b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter_unittest.cc
index aafcd79..89c61ce 100644
--- a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter_unittest.cc
+++ b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter_unittest.cc
@@ -121,7 +121,7 @@
   int32_t Encode(const VideoFrame& inputImage,
                  const CodecSpecificInfo* codecSpecificInfo,
                  const std::vector<FrameType>* frame_types) /* override */ {
-    return 0;
+    return encode_return_value_;
   }
 
   int32_t RegisterEncodeCompleteCallback(
@@ -160,10 +160,15 @@
     supports_native_handle_ = enabled;
   }
 
+  void set_encode_return_value(int value) {
+    encode_return_value_ = value;
+  }
+
   MOCK_CONST_METHOD0(ImplementationName, const char*());
 
  private:
   bool supports_native_handle_ = false;
+  int encode_return_value_ = WEBRTC_VIDEO_CODEC_OK;
   VideoCodec codec_;
   EncodedImageCallback* callback_;
 };
@@ -171,7 +176,8 @@
 class MockVideoEncoderFactory : public VideoEncoderFactory {
  public:
   VideoEncoder* Create() override {
-    MockVideoEncoder* encoder = new MockVideoEncoder();
+    MockVideoEncoder* encoder = new
+        ::testing::NiceMock<MockVideoEncoder>();
     const char* encoder_name = encoder_names_.empty()
                                    ? "codec_implementation_name"
                                    : encoder_names_[encoders_.size()];
@@ -460,5 +466,33 @@
   EXPECT_FALSE(adapter_->SupportsNativeHandle());
 }
 
+TEST_F(TestSimulcastEncoderAdapterFake, TestFailureReturnCodesFromEncodeCalls) {
+  TestVp8Simulcast::DefaultSettings(
+      &codec_, static_cast<const int*>(kTestTemporalLayerProfile));
+  codec_.numberOfSimulcastStreams = 3;
+  EXPECT_EQ(0, adapter_->InitEncode(&codec_, 1, 1200));
+  adapter_->RegisterEncodeCompleteCallback(this);
+  ASSERT_EQ(3u, helper_->factory()->encoders().size());
+  // Tell the 2nd encoder to request software fallback.
+  helper_->factory()->encoders()[1]->set_encode_return_value(
+      WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE);
+
+  // Send a fake frame and assert the return is software fallback.
+  VideoFrame input_frame;
+  int half_width = (kDefaultWidth + 1) / 2;
+  input_frame.CreateEmptyFrame(kDefaultWidth, kDefaultHeight, kDefaultWidth,
+                                half_width, half_width);
+  memset(input_frame.video_frame_buffer()->MutableDataY(), 0,
+         input_frame.allocated_size(kYPlane));
+  memset(input_frame.video_frame_buffer()->MutableDataU(), 0,
+         input_frame.allocated_size(kUPlane));
+  memset(input_frame.video_frame_buffer()->MutableDataV(), 0,
+         input_frame.allocated_size(kVPlane));
+
+  std::vector<FrameType> frame_types(3, kVideoFrameKey);
+  EXPECT_EQ(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE,
+            adapter_->Encode(input_frame, nullptr, &frame_types));
+}
+
 }  // namespace testing
 }  // namespace webrtc