Add ability to enable frame dumping decoder via field trial.

--force_fieldtrial=/WebRTC-DecoderDataDumpDirectory/./ will create a
file ./webrtc_receive_stream_[ssrc].ivf containing the exact data that
is fed to the decoder.

Bug: None
Change-Id: I4042298c9b851fc4b61c417652315fa2610de1ed
Reviewed-on: https://webrtc-review.googlesource.com/c/107644
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25467}
diff --git a/video/BUILD.gn b/video/BUILD.gn
index 33dcbe6..e6a39e7 100644
--- a/video/BUILD.gn
+++ b/video/BUILD.gn
@@ -52,6 +52,7 @@
   }
 
   deps = [
+    ":frame_dumping_decoder",
     "..:webrtc_common",
     "../api:fec_controller_api",
     "../api:libjingle_peerconnection_api",
@@ -133,6 +134,25 @@
   ]
 }
 
+rtc_source_set("frame_dumping_decoder") {
+  visibility = [ "*" ]
+
+  sources = [
+    "frame_dumping_decoder.cc",
+    "frame_dumping_decoder.h",
+  ]
+
+  deps = [
+    "../api/video:encoded_frame",
+    "../api/video_codecs:video_codecs_api",
+    "../modules/video_coding:video_codec_interface",
+    "../modules/video_coding:video_coding",
+    "../modules/video_coding:video_coding_utility",
+    "../rtc_base:rtc_base_approved",
+    "//third_party/abseil-cpp/absl/memory",
+  ]
+}
+
 rtc_source_set("video_stream_encoder_impl") {
   visibility = [ "*" ]
 
@@ -204,6 +224,7 @@
       "video_quality_test.h",
     ]
     deps = [
+      ":frame_dumping_decoder",
       "../api:fec_controller_api",
       "../api:test_dependency_factory",
       "../api:video_quality_test_fixture_api",
diff --git a/video/frame_dumping_decoder.cc b/video/frame_dumping_decoder.cc
new file mode 100644
index 0000000..7798511
--- /dev/null
+++ b/video/frame_dumping_decoder.cc
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "video/frame_dumping_decoder.h"
+
+#include <utility>
+
+#include "modules/video_coding/include/video_codec_interface.h"
+
+namespace webrtc {
+
+FrameDumpingDecoder::FrameDumpingDecoder(std::unique_ptr<VideoDecoder> decoder,
+                                         rtc::PlatformFile file)
+    : decoder_(std::move(decoder)),
+      writer_(IvfFileWriter::Wrap(rtc::File(file),
+                                  /* byte_limit= */ 100000000)) {}
+
+FrameDumpingDecoder::~FrameDumpingDecoder() = default;
+
+int32_t FrameDumpingDecoder::InitDecode(const VideoCodec* codec_settings,
+                                        int32_t number_of_cores) {
+  return decoder_->InitDecode(codec_settings, number_of_cores);
+}
+
+int32_t FrameDumpingDecoder::Decode(
+    const EncodedImage& input_image,
+    bool missing_frames,
+    const CodecSpecificInfo* codec_specific_info,
+    int64_t render_time_ms) {
+  int32_t ret = decoder_->Decode(input_image, missing_frames,
+                                 codec_specific_info, render_time_ms);
+  writer_->WriteFrame(input_image, codec_specific_info->codecType);
+
+  return ret;
+}
+
+int32_t FrameDumpingDecoder::RegisterDecodeCompleteCallback(
+    DecodedImageCallback* callback) {
+  return decoder_->RegisterDecodeCompleteCallback(callback);
+}
+
+int32_t FrameDumpingDecoder::Release() {
+  return decoder_->Release();
+}
+
+bool FrameDumpingDecoder::PrefersLateDecoding() const {
+  return decoder_->PrefersLateDecoding();
+}
+
+const char* FrameDumpingDecoder::ImplementationName() const {
+  return decoder_->ImplementationName();
+}
+
+}  // namespace webrtc
diff --git a/video/frame_dumping_decoder.h b/video/frame_dumping_decoder.h
new file mode 100644
index 0000000..e19e9b4
--- /dev/null
+++ b/video/frame_dumping_decoder.h
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VIDEO_FRAME_DUMPING_DECODER_H_
+#define VIDEO_FRAME_DUMPING_DECODER_H_
+
+#include <memory>
+
+#include "api/video_codecs/video_decoder.h"
+#include "modules/video_coding/utility/ivf_file_writer.h"
+#include "rtc_base/platform_file.h"
+
+namespace webrtc {
+
+// A decoder wrapper that writes the encoded frames to a file.
+class FrameDumpingDecoder : public VideoDecoder {
+ public:
+  FrameDumpingDecoder(std::unique_ptr<VideoDecoder> decoder,
+                      rtc::PlatformFile file);
+  ~FrameDumpingDecoder() override;
+
+  int32_t InitDecode(const VideoCodec* codec_settings,
+                     int32_t number_of_cores) override;
+  int32_t Decode(const EncodedImage& input_image,
+                 bool missing_frames,
+                 const CodecSpecificInfo* codec_specific_info,
+                 int64_t render_time_ms) override;
+  int32_t RegisterDecodeCompleteCallback(
+      DecodedImageCallback* callback) override;
+  int32_t Release() override;
+  bool PrefersLateDecoding() const override;
+  const char* ImplementationName() const override;
+
+ private:
+  std::unique_ptr<VideoDecoder> decoder_;
+  std::unique_ptr<IvfFileWriter> writer_;
+};
+
+}  // namespace webrtc
+
+#endif  // VIDEO_FRAME_DUMPING_DECODER_H_
diff --git a/video/video_quality_test.cc b/video/video_quality_test.cc
index 15579d8..6517c97 100644
--- a/video/video_quality_test.cc
+++ b/video/video_quality_test.cc
@@ -35,6 +35,7 @@
 #include "test/run_loop.h"
 #include "test/testsupport/fileutils.h"
 #include "test/video_renderer.h"
+#include "video/frame_dumping_decoder.h"
 #ifdef WEBRTC_WIN
 #include "modules/audio_device/include/audio_device_factory.h"
 #endif
@@ -74,54 +75,6 @@
   std::vector<VideoStream> streams_;
 };
 
-// A decoder wrapper that writes the encoded frames to a file.
-class FrameDumpingDecoder : public VideoDecoder {
- public:
-  FrameDumpingDecoder(std::unique_ptr<VideoDecoder> decoder,
-                      rtc::PlatformFile file)
-      : decoder_(std::move(decoder)),
-        writer_(IvfFileWriter::Wrap(rtc::File(file),
-                                    /* byte_limit= */ 100000000)) {}
-
-  int32_t InitDecode(const VideoCodec* codec_settings,
-                     int32_t number_of_cores) override {
-    return decoder_->InitDecode(codec_settings, number_of_cores);
-  }
-
-  int32_t Decode(const EncodedImage& input_image,
-                 bool missing_frames,
-                 const CodecSpecificInfo* codec_specific_info,
-                 int64_t render_time_ms) override {
-    int32_t ret = decoder_->Decode(input_image, missing_frames,
-                                   codec_specific_info, render_time_ms);
-    writer_->WriteFrame(input_image, codec_specific_info->codecType);
-
-    return ret;
-  }
-
-  int32_t RegisterDecodeCompleteCallback(
-      DecodedImageCallback* callback) override {
-    return decoder_->RegisterDecodeCompleteCallback(callback);
-  }
-
-  int32_t Release() override { return decoder_->Release(); }
-
-  // Returns true if the decoder prefer to decode frames late.
-  // That is, it can not decode infinite number of frames before the decoded
-  // frame is consumed.
-  bool PrefersLateDecoding() const override {
-    return decoder_->PrefersLateDecoding();
-  }
-
-  const char* ImplementationName() const override {
-    return decoder_->ImplementationName();
-  }
-
- private:
-  std::unique_ptr<VideoDecoder> decoder_;
-  std::unique_ptr<IvfFileWriter> writer_;
-};
-
 // This wrapper provides two features needed by the video quality tests:
 //  1. Invoke VideoAnalyzer callbacks before and after encoding each frame.
 //  2. Write the encoded frames to file, one file per simulcast layer.
@@ -285,7 +238,8 @@
           }),
       receive_logs_(0),
       send_logs_(0),
-      injection_components_(std::move(injection_components)) {
+      injection_components_(std::move(injection_components)),
+      num_video_streams_(0) {
   if (injection_components_ == nullptr) {
     injection_components_ = absl::make_unique<InjectionComponents>();
   }
diff --git a/video/video_receive_stream.cc b/video/video_receive_stream.cc
index 9ffd278..2f78a80 100644
--- a/video/video_receive_stream.cc
+++ b/video/video_receive_stream.cc
@@ -35,10 +35,13 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/location.h"
 #include "rtc_base/logging.h"
+#include "rtc_base/platform_file.h"
+#include "rtc_base/strings/string_builder.h"
 #include "rtc_base/trace_event.h"
 #include "system_wrappers/include/clock.h"
 #include "system_wrappers/include/field_trial.h"
 #include "video/call_stats.h"
+#include "video/frame_dumping_decoder.h"
 #include "video/receive_statistics_proxy.h"
 
 namespace webrtc {
@@ -246,6 +249,18 @@
     if (!video_decoder) {
       video_decoder = absl::make_unique<NullVideoDecoder>();
     }
+
+    std::string decoded_output_file =
+        field_trial::FindFullName("WebRTC-DecoderDataDumpDirectory");
+    if (!decoded_output_file.empty()) {
+      char filename_buffer[256];
+      rtc::SimpleStringBuilder ssb(filename_buffer);
+      ssb << decoded_output_file << "/webrtc_receive_stream_"
+          << this->config_.rtp.local_ssrc << ".ivf";
+      video_decoder = absl::make_unique<FrameDumpingDecoder>(
+          std::move(video_decoder), rtc::CreatePlatformFile(ssb.str()));
+    }
+
     video_decoders_.push_back(std::move(video_decoder));
 
     video_receiver_.RegisterExternalDecoder(video_decoders_.back().get(),