Split TemporalLayers and TemporalLayers checker, clean up header.

This CL is a step towards making the TemporalLayers landable in api/ :
* It splits TemporalLayers from TemporalLayersChecker
* It initially renames temporal_layer.h to vp8_temporal_layers.h and
  moved it into the include/ folder
* It removes the dependency on VideoCodec, which was essentially only
  used to determine if screenshare_layers or default_temporal_layers
  should be used, and the number of temporal temporal layers to use.

Subsequent CLs will make further cleanup before attempting a move to api

Bug: webrtc:9012
Change-Id: I87ea7aac66d39284eaebd86aa9d015aba2eaaaea
Reviewed-on: https://webrtc-review.googlesource.com/94156
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24920}
diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn
index f000f41..c992da5 100644
--- a/modules/video_coding/BUILD.gn
+++ b/modules/video_coding/BUILD.gn
@@ -393,15 +393,18 @@
   sources = [
     "codecs/vp8/default_temporal_layers.cc",
     "codecs/vp8/default_temporal_layers.h",
+    "codecs/vp8/include/temporal_layers_checker.h",
     "codecs/vp8/include/vp8.h",
+    "codecs/vp8/include/vp8_temporal_layers.h",
     "codecs/vp8/libvpx_vp8_decoder.cc",
     "codecs/vp8/libvpx_vp8_decoder.h",
     "codecs/vp8/libvpx_vp8_encoder.cc",
     "codecs/vp8/libvpx_vp8_encoder.h",
     "codecs/vp8/screenshare_layers.cc",
     "codecs/vp8/screenshare_layers.h",
-    "codecs/vp8/temporal_layers.cc",
     "codecs/vp8/temporal_layers.h",
+    "codecs/vp8/temporal_layers_checker.cc",
+    "codecs/vp8/vp8_temporal_layers.cc",
   ]
 
   if (!build_with_chromium && is_clang) {
@@ -410,6 +413,7 @@
   }
 
   deps = [
+    ":codec_globals_headers",
     ":video_codec_interface",
     ":video_coding_utility",
     "..:module_api",
diff --git a/modules/video_coding/codecs/vp8/default_temporal_layers.h b/modules/video_coding/codecs/vp8/default_temporal_layers.h
index 6914479..ab54621 100644
--- a/modules/video_coding/codecs/vp8/default_temporal_layers.h
+++ b/modules/video_coding/codecs/vp8/default_temporal_layers.h
@@ -17,7 +17,8 @@
 #include <set>
 #include <vector>
 
-#include "modules/video_coding/codecs/vp8/temporal_layers.h"
+#include "modules/video_coding/codecs/vp8/include/temporal_layers_checker.h"
+#include "modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h"
 
 #include "absl/types/optional.h"
 
diff --git a/modules/video_coding/codecs/vp8/include/temporal_layers_checker.h b/modules/video_coding/codecs/vp8/include/temporal_layers_checker.h
new file mode 100644
index 0000000..9878ac9
--- /dev/null
+++ b/modules/video_coding/codecs/vp8/include/temporal_layers_checker.h
@@ -0,0 +1,63 @@
+/*
+ *  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 MODULES_VIDEO_CODING_CODECS_VP8_INCLUDE_TEMPORAL_LAYERS_CHECKER_H_
+#define MODULES_VIDEO_CODING_CODECS_VP8_INCLUDE_TEMPORAL_LAYERS_CHECKER_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h"
+
+namespace webrtc {
+
+// Interface for a class that verifies correctness of temporal layer
+// configurations (dependencies, sync flag, etc).
+// Intended to be used in tests as well as with real apps in debug mode.
+class TemporalLayersChecker {
+ public:
+  explicit TemporalLayersChecker(int num_temporal_layers);
+  virtual ~TemporalLayersChecker() {}
+
+  virtual bool CheckTemporalConfig(
+      bool frame_is_keyframe,
+      const TemporalLayers::FrameConfig& frame_config);
+
+  static std::unique_ptr<TemporalLayersChecker> CreateTemporalLayersChecker(
+      TemporalLayersType type,
+      int num_temporal_layers);
+
+ private:
+  struct BufferState {
+    BufferState() : is_keyframe(true), temporal_layer(0), sequence_number(0) {}
+    bool is_keyframe;
+    uint8_t temporal_layer;
+    uint32_t sequence_number;
+  };
+  bool CheckAndUpdateBufferState(BufferState* state,
+                                 bool* need_sync,
+                                 bool frame_is_keyframe,
+                                 uint8_t temporal_layer,
+                                 webrtc::TemporalLayers::BufferFlags flags,
+                                 uint32_t sequence_number,
+                                 uint32_t* lowest_sequence_referenced);
+  BufferState last_;
+  BufferState arf_;
+  BufferState golden_;
+  int num_temporal_layers_;
+  uint32_t sequence_number_;
+  uint32_t last_sync_sequence_number_;
+  uint32_t last_tl0_sequence_number_;
+};
+
+}  // namespace webrtc
+
+#endif  // MODULES_VIDEO_CODING_CODECS_VP8_INCLUDE_TEMPORAL_LAYERS_CHECKER_H_
diff --git a/modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h b/modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h
new file mode 100644
index 0000000..1b668eb
--- /dev/null
+++ b/modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h
@@ -0,0 +1,188 @@
+/*
+ *  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 MODULES_VIDEO_CODING_CODECS_VP8_INCLUDE_VP8_TEMPORAL_LAYERS_H_
+#define MODULES_VIDEO_CODING_CODECS_VP8_INCLUDE_VP8_TEMPORAL_LAYERS_H_
+
+#include <memory>
+#include <vector>
+
+namespace webrtc {
+
+// Some notes on the prerequisites of the TemporalLayers interface.
+// * Implementations of TemporalLayers may not contain internal synchronization
+//   so caller must make sure doing so thread safe.
+// * The encoder is assumed to encode all frames in order, and callbacks to
+//   PopulateCodecSpecific() / FrameEncoded() must happen in the same order.
+//
+// This means that in the case of pipelining encoders, it is OK to have a chain
+// of calls such as this:
+// - UpdateLayerConfig(timestampA)
+// - UpdateLayerConfig(timestampB)
+// - PopulateCodecSpecific(timestampA, ...)
+// - UpdateLayerConfig(timestampC)
+// - FrameEncoded(timestampA, 1234, ...)
+// - FrameEncoded(timestampB, 0, ...)
+// - PopulateCodecSpecific(timestampC, ...)
+// - FrameEncoded(timestampC, 1234, ...)
+// Note that UpdateLayerConfig() for a new frame can happen before
+// FrameEncoded() for a previous one, but calls themselves must be both
+// synchronized (e.g. run on a task queue) and in order (per type).
+
+enum class TemporalLayersType { kFixedPattern, kBitrateDynamic };
+
+struct CodecSpecificInfoVP8;
+enum class Vp8BufferReference : uint8_t {
+  kNone = 0,
+  kLast = 1,
+  kGolden = 2,
+  kAltref = 4
+};
+
+struct Vp8EncoderConfig {
+  static constexpr size_t kMaxPeriodicity = 16;
+  static constexpr size_t kMaxLayers = 5;
+
+  // Number of active temporal layers. Set to 0 if not used.
+  uint32_t ts_number_layers;
+  // Arrays of length |ts_number_layers|, indicating (cumulative) target bitrate
+  // and rate decimator (e.g. 4 if every 4th frame is in the given layer) for
+  // each active temporal layer, starting with temporal id 0.
+  uint32_t ts_target_bitrate[kMaxLayers];
+  uint32_t ts_rate_decimator[kMaxLayers];
+
+  // The periodicity of the temporal pattern. Set to 0 if not used.
+  uint32_t ts_periodicity;
+  // Array of length |ts_periodicity| indicating the sequence of temporal id's
+  // to assign to incoming frames.
+  uint32_t ts_layer_id[kMaxPeriodicity];
+
+  // Target bitrate, in bps.
+  uint32_t rc_target_bitrate;
+
+  // Clamp QP to min/max. Use 0 to disable clamping.
+  uint32_t rc_min_quantizer;
+  uint32_t rc_max_quantizer;
+};
+
+// This interface defines a way of getting the encoder settings needed to
+// realize a temporal layer structure of predefined size.
+class TemporalLayers {
+ public:
+  enum BufferFlags : int {
+    kNone = 0,
+    kReference = 1,
+    kUpdate = 2,
+    kReferenceAndUpdate = kReference | kUpdate,
+  };
+  enum FreezeEntropy { kFreezeEntropy };
+
+  struct FrameConfig {
+    FrameConfig();
+
+    FrameConfig(BufferFlags last, BufferFlags golden, BufferFlags arf);
+    FrameConfig(BufferFlags last,
+                BufferFlags golden,
+                BufferFlags arf,
+                FreezeEntropy);
+
+    bool drop_frame;
+    BufferFlags last_buffer_flags;
+    BufferFlags golden_buffer_flags;
+    BufferFlags arf_buffer_flags;
+
+    // The encoder layer ID is used to utilize the correct bitrate allocator
+    // inside the encoder. It does not control references nor determine which
+    // "actual" temporal layer this is. The packetizer temporal index determines
+    // which layer the encoded frame should be packetized into.
+    // Normally these are the same, but current temporal-layer strategies for
+    // screenshare use one bitrate allocator for all layers, but attempt to
+    // packetize / utilize references to split a stream into multiple layers,
+    // with different quantizer settings, to hit target bitrate.
+    // TODO(pbos): Screenshare layers are being reconsidered at the time of
+    // writing, we might be able to remove this distinction, and have a temporal
+    // layer imply both (the normal case).
+    int encoder_layer_id;
+    int packetizer_temporal_idx;
+
+    bool layer_sync;
+
+    bool freeze_entropy;
+
+    // Indicates in which order the encoder should search the reference buffers
+    // when doing motion prediction. Set to kNone to use unspecified order. Any
+    // buffer indicated here must not have the corresponding no_ref bit set.
+    // If all three buffers can be reference, the one not listed here should be
+    // searched last.
+    Vp8BufferReference first_reference;
+    Vp8BufferReference second_reference;
+
+    bool operator==(const FrameConfig& o) const;
+    bool operator!=(const FrameConfig& o) const { return !(*this == o); }
+
+   private:
+    FrameConfig(BufferFlags last,
+                BufferFlags golden,
+                BufferFlags arf,
+                bool freeze_entropy);
+  };
+
+  // Factory for TemporalLayer strategy. Default behavior is a fixed pattern
+  // of temporal layers. See default_temporal_layers.cc
+  static std::unique_ptr<TemporalLayers> CreateTemporalLayers(
+      TemporalLayersType type,
+      int num_temporal_layers);
+
+  virtual ~TemporalLayers() = default;
+
+  virtual bool SupportsEncoderFrameDropping() const = 0;
+
+  // New target bitrate, per temporal layer.
+  virtual void OnRatesUpdated(const std::vector<uint32_t>& bitrates_bps,
+                              int framerate_fps) = 0;
+
+  // Update the encoder configuration with target bitrates or other parameters.
+  // Returns true iff the configuration was actually modified.
+  virtual bool UpdateConfiguration(Vp8EncoderConfig* cfg) = 0;
+
+  // Returns the recommended VP8 encode flags needed, and moves the temporal
+  // pattern to the next frame.
+  // The timestamp may be used as both a time and a unique identifier, and so
+  // the caller must make sure no two frames use the same timestamp.
+  // The timestamp uses a 90kHz RTP clock.
+  // After calling this method, the actual encoder should be called with the
+  // provided frame configuration, after which:
+  // * On success, call PopulateCodecSpecific() and then FrameEncoded();
+  // * On failure/ frame drop: Call FrameEncoded() with size = 0.
+  virtual FrameConfig UpdateLayerConfig(uint32_t rtp_timestamp) = 0;
+
+  // Called after successful encoding of a frame. The rtp timestamp must match
+  // the one using in UpdateLayerConfig(). Some fields in |vp8_info| may have
+  // already been populated by the encoder, check before overwriting.
+  // |tl_config| is the frame config returned by UpdateLayerConfig() for this
+  // rtp_timestamp;
+  // If |is_keyframe| is true, the flags in |tl_config| will be ignored.
+  virtual void PopulateCodecSpecific(
+      bool is_keyframe,
+      const TemporalLayers::FrameConfig& tl_config,
+      CodecSpecificInfoVP8* vp8_info,
+      uint32_t rtp_timestamp) = 0;
+
+  // Called after an encode event. If the frame was dropped, |size_bytes| must
+  // be set to 0. The rtp timestamp must match the one using in
+  // UpdateLayerConfig()
+  virtual void FrameEncoded(uint32_t rtp_timestamp,
+                            size_t size_bytes,
+                            int qp) = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // MODULES_VIDEO_CODING_CODECS_VP8_INCLUDE_VP8_TEMPORAL_LAYERS_H_
diff --git a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
index 72e5f87..2b72508 100644
--- a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
+++ b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
@@ -72,24 +72,24 @@
   return true;
 }
 
-static_assert(
-    VP8_TS_MAX_PERIODICITY == VPX_TS_MAX_PERIODICITY,
-    "VP8_TS_MAX_PERIODICITY must be kept in sync with the constant in libvpx.");
-static_assert(
-    VP8_TS_MAX_LAYERS == VPX_TS_MAX_LAYERS,
-    "VP8_TS_MAX_LAYERS must be kept in sync with the constant in libvpx.");
+static_assert(Vp8EncoderConfig::kMaxPeriodicity == VPX_TS_MAX_PERIODICITY,
+              "Vp8EncoderConfig::kMaxPeriodicity must be kept in sync with the "
+              "constant in libvpx.");
+static_assert(Vp8EncoderConfig::kMaxLayers == VPX_TS_MAX_LAYERS,
+              "Vp8EncoderConfig::kMaxLayers must be kept in sync with the "
+              "constant in libvpx.");
 
 static Vp8EncoderConfig GetEncoderConfig(vpx_codec_enc_cfg* vpx_config) {
   Vp8EncoderConfig config;
 
   config.ts_number_layers = vpx_config->ts_number_layers;
   memcpy(config.ts_target_bitrate, vpx_config->ts_target_bitrate,
-         sizeof(unsigned int) * VP8_TS_MAX_LAYERS);
+         sizeof(unsigned int) * Vp8EncoderConfig::kMaxLayers);
   memcpy(config.ts_rate_decimator, vpx_config->ts_rate_decimator,
-         sizeof(unsigned int) * VP8_TS_MAX_LAYERS);
+         sizeof(unsigned int) * Vp8EncoderConfig::kMaxLayers);
   config.ts_periodicity = vpx_config->ts_periodicity;
   memcpy(config.ts_layer_id, vpx_config->ts_layer_id,
-         sizeof(unsigned int) * VP8_TS_MAX_PERIODICITY);
+         sizeof(unsigned int) * Vp8EncoderConfig::kMaxPeriodicity);
   config.rc_target_bitrate = vpx_config->rc_target_bitrate;
   config.rc_min_quantizer = vpx_config->rc_min_quantizer;
   config.rc_max_quantizer = vpx_config->rc_max_quantizer;
@@ -101,12 +101,12 @@
                                 const Vp8EncoderConfig& config) {
   vpx_config->ts_number_layers = config.ts_number_layers;
   memcpy(vpx_config->ts_target_bitrate, config.ts_target_bitrate,
-         sizeof(unsigned int) * VP8_TS_MAX_LAYERS);
+         sizeof(unsigned int) * Vp8EncoderConfig::kMaxLayers);
   memcpy(vpx_config->ts_rate_decimator, config.ts_rate_decimator,
-         sizeof(unsigned int) * VP8_TS_MAX_LAYERS);
+         sizeof(unsigned int) * Vp8EncoderConfig::kMaxLayers);
   vpx_config->ts_periodicity = config.ts_periodicity;
   memcpy(vpx_config->ts_layer_id, config.ts_layer_id,
-         sizeof(unsigned int) * VP8_TS_MAX_PERIODICITY);
+         sizeof(unsigned int) * Vp8EncoderConfig::kMaxPeriodicity);
   vpx_config->rc_target_bitrate = config.rc_target_bitrate;
   vpx_config->rc_min_quantizer = config.rc_min_quantizer;
   vpx_config->rc_max_quantizer = config.rc_max_quantizer;
@@ -120,6 +120,7 @@
     FillInEncoderConfig(cfg, config);
   return res;
 }
+
 }  // namespace
 
 std::unique_ptr<VP8Encoder> VP8Encoder::Create() {
@@ -284,15 +285,25 @@
   send_stream_[stream_idx] = send_stream;
 }
 
-void LibvpxVp8Encoder::SetupTemporalLayers(int num_streams,
-                                           int num_temporal_layers,
-                                           const VideoCodec& codec) {
+void LibvpxVp8Encoder::SetupTemporalLayers(const VideoCodec& codec) {
   RTC_DCHECK(temporal_layers_.empty());
+  int num_streams = SimulcastUtility::NumberOfSimulcastStreams(codec);
   for (int i = 0; i < num_streams; ++i) {
+    TemporalLayersType type;
+    int num_temporal_layers =
+        SimulcastUtility::NumberOfTemporalLayers(codec, i);
+    if (SimulcastUtility::IsConferenceModeScreenshare(codec) && i == 0) {
+      type = TemporalLayersType::kBitrateDynamic;
+      // Legacy screenshare layers supports max 2 layers.
+      num_temporal_layers = std::max<int>(2, num_temporal_layers);
+    } else {
+      type = TemporalLayersType::kFixedPattern;
+    }
     temporal_layers_.emplace_back(
-        TemporalLayers::CreateTemporalLayers(codec, i));
+        TemporalLayers::CreateTemporalLayers(type, num_temporal_layers));
     temporal_layers_checkers_.emplace_back(
-        TemporalLayers::CreateTemporalLayersChecker(codec, i));
+        TemporalLayersChecker::CreateTemporalLayersChecker(
+            type, num_temporal_layers));
   }
 }
 
@@ -324,21 +335,14 @@
   }
 
   int number_of_streams = SimulcastUtility::NumberOfSimulcastStreams(*inst);
-  bool doing_simulcast = (number_of_streams > 1);
-
-  if (doing_simulcast && (!SimulcastUtility::ValidSimulcastResolutions(
-                              *inst, number_of_streams) ||
-                          !SimulcastUtility::ValidSimulcastTemporalLayers(
-                              *inst, number_of_streams))) {
+  if (number_of_streams > 1 &&
+      (!SimulcastUtility::ValidSimulcastResolutions(*inst, number_of_streams) ||
+       !SimulcastUtility::ValidSimulcastTemporalLayers(*inst,
+                                                       number_of_streams))) {
     return WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED;
   }
 
-  int num_temporal_layers =
-      doing_simulcast ? inst->simulcastStream[0].numberOfTemporalLayers
-                      : inst->VP8().numberOfTemporalLayers;
-  RTC_DCHECK_GT(num_temporal_layers, 0);
-
-  SetupTemporalLayers(number_of_streams, num_temporal_layers, *inst);
+  SetupTemporalLayers(*inst);
 
   number_of_cores_ = number_of_cores;
   timestamp_ = 0;
@@ -396,7 +400,9 @@
 
   // Set the error resilience mode for temporal layers (but not simulcast).
   configurations_[0].g_error_resilient =
-      (num_temporal_layers > 1) ? VPX_ERROR_RESILIENT_DEFAULT : 0;
+      (SimulcastUtility::NumberOfTemporalLayers(*inst, 0) > 1)
+          ? VPX_ERROR_RESILIENT_DEFAULT
+          : 0;
 
   // rate control settings
   configurations_[0].rc_dropframe_thresh = FrameDropThreshold(0);
diff --git a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h
index b1889fc..8ee359e 100644
--- a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h
+++ b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h
@@ -18,8 +18,9 @@
 #include "api/video_codecs/video_encoder.h"
 #include "common_types.h"  // NOLINT(build/include)
 #include "common_video/include/video_frame.h"
+#include "modules/video_coding/codecs/vp8/include/temporal_layers_checker.h"
 #include "modules/video_coding/codecs/vp8/include/vp8.h"
-#include "modules/video_coding/codecs/vp8/temporal_layers.h"
+#include "modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h"
 #include "modules/video_coding/include/video_codec_interface.h"
 
 #include "vpx/vp8cx.h"
@@ -57,9 +58,7 @@
       const TemporalLayers::FrameConfig& references);
 
  private:
-  void SetupTemporalLayers(int num_streams,
-                           int num_temporal_layers,
-                           const VideoCodec& codec);
+  void SetupTemporalLayers(const VideoCodec& codec);
 
   // Set the cpu_speed setting for encoder based on resolution and/or platform.
   int SetCpuSpeed(int width, int height);
diff --git a/modules/video_coding/codecs/vp8/screenshare_layers.h b/modules/video_coding/codecs/vp8/screenshare_layers.h
index fcc3aca..cd12ac4 100644
--- a/modules/video_coding/codecs/vp8/screenshare_layers.h
+++ b/modules/video_coding/codecs/vp8/screenshare_layers.h
@@ -11,7 +11,7 @@
 
 #include <vector>
 
-#include "modules/video_coding/codecs/vp8/temporal_layers.h"
+#include "modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h"
 #include "modules/video_coding/utility/frame_dropper.h"
 #include "rtc_base/rate_statistics.h"
 #include "rtc_base/timeutils.h"
diff --git a/modules/video_coding/codecs/vp8/temporal_layers.h b/modules/video_coding/codecs/vp8/temporal_layers.h
index 91b5531..788d69a 100644
--- a/modules/video_coding/codecs/vp8/temporal_layers.h
+++ b/modules/video_coding/codecs/vp8/temporal_layers.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+/*
+ *  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
@@ -6,222 +7,11 @@
  *  in the file PATENTS.  All contributing project authors may
  *  be found in the AUTHORS file in the root of the source tree.
  */
-/*
- * This file defines the interface for doing temporal layers with VP8.
- */
+
 #ifndef MODULES_VIDEO_CODING_CODECS_VP8_TEMPORAL_LAYERS_H_
 #define MODULES_VIDEO_CODING_CODECS_VP8_TEMPORAL_LAYERS_H_
 
-#include <vector>
-#include <memory>
+// TODO(webrtc:9012) Remove this file when downstream projects have updated.
+#include "modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h"
 
-#include "api/video_codecs/video_codec.h"
-
-#define VP8_TS_MAX_PERIODICITY 16
-#define VP8_TS_MAX_LAYERS 5
-
-namespace webrtc {
-
-// Some notes on the prerequisites of the TemporalLayers interface.
-// * Implementations of TemporalLayers may not contain internal synchronization
-//   so caller must make sure doing so thread safe.
-// * The encoder is assumed to encode all frames in order, and callbacks to
-//   PopulateCodecSpecific() / FrameEncoded() must happen in the same order.
-//
-// This means that in the case of pipelining encoders, it is OK to have a chain
-// of calls such as this:
-// - UpdateLayerConfig(timestampA)
-// - UpdateLayerConfig(timestampB)
-// - PopulateCodecSpecific(timestampA, ...)
-// - UpdateLayerConfig(timestampC)
-// - FrameEncoded(timestampA, 1234, ...)
-// - FrameEncoded(timestampB, 0, ...)
-// - PopulateCodecSpecific(timestampC, ...)
-// - FrameEncoded(timestampC, 1234, ...)
-// Note that UpdateLayerConfig() for a new frame can happen before
-// FrameEncoded() for a previous one, but calls themselves must be both
-// synchronized (e.g. run on a task queue) and in order (per type).
-
-struct CodecSpecificInfoVP8;
-enum class Vp8BufferReference : uint8_t {
-  kNone = 0,
-  kLast = 1,
-  kGolden = 2,
-  kAltref = 4
-};
-
-struct Vp8EncoderConfig {
-  // Number of active temporal layers. Set to 0 if not used.
-  unsigned int ts_number_layers;
-  // Arrays of length |ts_number_layers|, indicating (cumulative) target bitrate
-  // and rate decimator (e.g. 4 if every 4th frame is in the given layer) for
-  // each active temporal layer, starting with temporal id 0.
-  unsigned int ts_target_bitrate[VP8_TS_MAX_LAYERS];
-  unsigned int ts_rate_decimator[VP8_TS_MAX_LAYERS];
-
-  // The periodicity of the temporal pattern. Set to 0 if not used.
-  unsigned int ts_periodicity;
-  // Array of length |ts_periodicity| indicating the sequence of temporal id's
-  // to assign to incoming frames.
-  unsigned int ts_layer_id[VP8_TS_MAX_PERIODICITY];
-
-  // Target bitrate, in bps.
-  unsigned int rc_target_bitrate;
-
-  // Clamp QP to min/max. Use 0 to disable clamping.
-  unsigned int rc_min_quantizer;
-  unsigned int rc_max_quantizer;
-};
-
-// This interface defines a way of getting the encoder settings needed to
-// realize a temporal layer structure of predefined size.
-class TemporalLayersChecker;
-class TemporalLayers {
- public:
-  enum BufferFlags : int {
-    kNone = 0,
-    kReference = 1,
-    kUpdate = 2,
-    kReferenceAndUpdate = kReference | kUpdate,
-  };
-  enum FreezeEntropy { kFreezeEntropy };
-
-  struct FrameConfig {
-    FrameConfig();
-
-    FrameConfig(BufferFlags last, BufferFlags golden, BufferFlags arf);
-    FrameConfig(BufferFlags last,
-                BufferFlags golden,
-                BufferFlags arf,
-                FreezeEntropy);
-
-    bool drop_frame;
-    BufferFlags last_buffer_flags;
-    BufferFlags golden_buffer_flags;
-    BufferFlags arf_buffer_flags;
-
-    // The encoder layer ID is used to utilize the correct bitrate allocator
-    // inside the encoder. It does not control references nor determine which
-    // "actual" temporal layer this is. The packetizer temporal index determines
-    // which layer the encoded frame should be packetized into.
-    // Normally these are the same, but current temporal-layer strategies for
-    // screenshare use one bitrate allocator for all layers, but attempt to
-    // packetize / utilize references to split a stream into multiple layers,
-    // with different quantizer settings, to hit target bitrate.
-    // TODO(pbos): Screenshare layers are being reconsidered at the time of
-    // writing, we might be able to remove this distinction, and have a temporal
-    // layer imply both (the normal case).
-    int encoder_layer_id;
-    int packetizer_temporal_idx;
-
-    bool layer_sync;
-
-    bool freeze_entropy;
-
-    // Indicates in which order the encoder should search the reference buffers
-    // when doing motion prediction. Set to kNone to use unspecified order. Any
-    // buffer indicated here must not have the corresponding no_ref bit set.
-    // If all three buffers can be reference, the one not listed here should be
-    // searched last.
-    Vp8BufferReference first_reference;
-    Vp8BufferReference second_reference;
-
-    bool operator==(const FrameConfig& o) const;
-    bool operator!=(const FrameConfig& o) const { return !(*this == o); }
-
-   private:
-    FrameConfig(BufferFlags last,
-                BufferFlags golden,
-                BufferFlags arf,
-                bool freeze_entropy);
-  };
-
-  // Factory for TemporalLayer strategy. Default behavior is a fixed pattern
-  // of temporal layers. See default_temporal_layers.cc
-  static std::unique_ptr<TemporalLayers> CreateTemporalLayers(
-      const VideoCodec& codec,
-      size_t spatial_id);
-  static std::unique_ptr<TemporalLayersChecker> CreateTemporalLayersChecker(
-      const VideoCodec& codec,
-      size_t spatial_id);
-
-  virtual ~TemporalLayers() = default;
-
-  virtual bool SupportsEncoderFrameDropping() const = 0;
-
-  // New target bitrate, per temporal layer.
-  virtual void OnRatesUpdated(const std::vector<uint32_t>& bitrates_bps,
-                              int framerate_fps) = 0;
-
-  // Update the encoder configuration with target bitrates or other parameters.
-  // Returns true iff the configuration was actually modified.
-  virtual bool UpdateConfiguration(Vp8EncoderConfig* cfg) = 0;
-
-  // Returns the recommended VP8 encode flags needed, and moves the temporal
-  // pattern to the next frame.
-  // The timestamp may be used as both a time and a unique identifier, and so
-  // the caller must make sure no two frames use the same timestamp.
-  // The timestamp uses a 90kHz RTP clock.
-  // After calling this method, the actual encoder should be called with the
-  // provided frame configuration, after which:
-  // * On success, call PopulateCodecSpecific() and then FrameEncoded();
-  // * On failure/ frame drop: Call FrameEncoded() with size = 0.
-  virtual FrameConfig UpdateLayerConfig(uint32_t rtp_timestamp) = 0;
-
-  // Called after successful encoding of a frame. The rtp timestamp must match
-  // the one using in UpdateLayerConfig(). Some fields in |vp8_info| may have
-  // already been populated by the encoder, check before overwriting.
-  // |tl_config| is the frame config returned by UpdateLayerConfig() for this
-  // rtp_timestamp;
-  // If |is_keyframe| is true, the flags in |tl_config| will be ignored.
-  virtual void PopulateCodecSpecific(
-      bool is_keyframe,
-      const TemporalLayers::FrameConfig& tl_config,
-      CodecSpecificInfoVP8* vp8_info,
-      uint32_t rtp_timestamp) = 0;
-
-  // Called after an encode event. If the frame was dropped, |size_bytes| must
-  // be set to 0. The rtp timestamp must match the one using in
-  // UpdateLayerConfig()
-  virtual void FrameEncoded(uint32_t rtp_timestamp,
-                            size_t size_bytes,
-                            int qp) = 0;
-};
-
-// Used only inside RTC_DCHECK(). It checks correctness of temporal layers
-// dependencies and sync bits. The only method of this class is called after
-// each UpdateLayersConfig() of a corresponding TemporalLayers class.
-class TemporalLayersChecker {
- public:
-  explicit TemporalLayersChecker(int num_temporal_layers);
-  virtual ~TemporalLayersChecker() {}
-
-  virtual bool CheckTemporalConfig(
-      bool frame_is_keyframe,
-      const TemporalLayers::FrameConfig& frame_config);
-
- private:
-  struct BufferState {
-    BufferState() : is_keyframe(true), temporal_layer(0), sequence_number(0) {}
-    bool is_keyframe;
-    uint8_t temporal_layer;
-    uint32_t sequence_number;
-  };
-  bool CheckAndUpdateBufferState(BufferState* state,
-                                 bool* need_sync,
-                                 bool frame_is_keyframe,
-                                 uint8_t temporal_layer,
-                                 webrtc::TemporalLayers::BufferFlags flags,
-                                 uint32_t sequence_number,
-                                 uint32_t* lowest_sequence_referenced);
-  BufferState last_;
-  BufferState arf_;
-  BufferState golden_;
-  int num_temporal_layers_;
-  uint32_t sequence_number_;
-  uint32_t last_sync_sequence_number_;
-  uint32_t last_tl0_sequence_number_;
-};
-
-}  // namespace webrtc
 #endif  // MODULES_VIDEO_CODING_CODECS_VP8_TEMPORAL_LAYERS_H_
diff --git a/modules/video_coding/codecs/vp8/temporal_layers.cc b/modules/video_coding/codecs/vp8/temporal_layers_checker.cc
similarity index 61%
rename from modules/video_coding/codecs/vp8/temporal_layers.cc
rename to modules/video_coding/codecs/vp8/temporal_layers_checker.cc
index 236950a..b77e8bc 100644
--- a/modules/video_coding/codecs/vp8/temporal_layers.cc
+++ b/modules/video_coding/codecs/vp8/temporal_layers_checker.cc
@@ -1,4 +1,5 @@
-/* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+/*
+ *  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
@@ -7,83 +8,25 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "modules/video_coding/codecs/vp8/temporal_layers.h"
-
-#include <algorithm>
-#include <memory>
-#include <set>
-#include <vector>
-
+#include "modules/video_coding/codecs/vp8/include/temporal_layers_checker.h"
 #include "absl/memory/memory.h"
-#include "modules/include/module_common_types.h"
+#include "modules/video_coding/codecs/interface/common_constants.h"
 #include "modules/video_coding/codecs/vp8/default_temporal_layers.h"
-#include "modules/video_coding/codecs/vp8/screenshare_layers.h"
-#include "modules/video_coding/include/video_codec_interface.h"
-#include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "system_wrappers/include/clock.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
-namespace {
-uint8_t NumTemporalLayers(const VideoCodec& codec, int spatial_id) {
-  uint8_t num_temporal_layers =
-      std::max<uint8_t>(1, codec.VP8().numberOfTemporalLayers);
-  if (codec.numberOfSimulcastStreams > 0) {
-    RTC_DCHECK_LT(spatial_id, codec.numberOfSimulcastStreams);
-    num_temporal_layers =
-        std::max(num_temporal_layers,
-                 codec.simulcastStream[spatial_id].numberOfTemporalLayers);
-  }
-  return num_temporal_layers;
-}
-
-bool IsConferenceModeScreenshare(const VideoCodec& codec) {
-  if (codec.mode != VideoCodecMode::kScreensharing ||
-      NumTemporalLayers(codec, 0) != 2) {
-    return false;
-  }
-  // Fixed default bitrates for legacy screenshare layers mode.
-  return (codec.numberOfSimulcastStreams == 0 && codec.maxBitrate == 1000) ||
-         (codec.numberOfSimulcastStreams >= 1 &&
-          codec.simulcastStream[0].maxBitrate == 1000 &&
-          codec.simulcastStream[0].targetBitrate == 200);
-}
-}  // namespace
-
-bool TemporalLayers::FrameConfig::operator==(const FrameConfig& o) const {
-  return drop_frame == o.drop_frame &&
-         last_buffer_flags == o.last_buffer_flags &&
-         golden_buffer_flags == o.golden_buffer_flags &&
-         arf_buffer_flags == o.arf_buffer_flags && layer_sync == o.layer_sync &&
-         freeze_entropy == o.freeze_entropy &&
-         encoder_layer_id == o.encoder_layer_id &&
-         packetizer_temporal_idx == o.packetizer_temporal_idx;
-}
-
-std::unique_ptr<TemporalLayers> TemporalLayers::CreateTemporalLayers(
-    const VideoCodec& codec,
-    size_t spatial_id) {
-  if (IsConferenceModeScreenshare(codec) && spatial_id == 0) {
-    // Conference mode temporal layering for screen content in base stream.
-    return absl::make_unique<ScreenshareLayers>(2, Clock::GetRealTimeClock());
-  }
-
-  return absl::make_unique<DefaultTemporalLayers>(
-      NumTemporalLayers(codec, spatial_id));
-}
 
 std::unique_ptr<TemporalLayersChecker>
-TemporalLayers::CreateTemporalLayersChecker(const VideoCodec& codec,
-                                            size_t spatial_id) {
-  if (IsConferenceModeScreenshare(codec) && spatial_id == 0) {
-    // Conference mode temporal layering for screen content in base stream,
-    // use generic checker.
-    return absl::make_unique<TemporalLayersChecker>(2);
+TemporalLayersChecker::CreateTemporalLayersChecker(TemporalLayersType type,
+                                                   int num_temporal_layers) {
+  switch (type) {
+    case TemporalLayersType::kFixedPattern:
+      return absl::make_unique<DefaultTemporalLayersChecker>(
+          num_temporal_layers);
+    case TemporalLayersType::kBitrateDynamic:
+      // Conference mode temporal layering for screen content in base stream.
+      return absl::make_unique<TemporalLayersChecker>(num_temporal_layers);
   }
-
-  return absl::make_unique<DefaultTemporalLayersChecker>(
-      NumTemporalLayers(codec, spatial_id));
 }
 
 TemporalLayersChecker::TemporalLayersChecker(int num_temporal_layers)
@@ -195,4 +138,5 @@
   }
   return true;
 }
+
 }  // namespace webrtc
diff --git a/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc b/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc
index dc55d17..45a090d 100644
--- a/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc
+++ b/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc
@@ -15,7 +15,7 @@
 #include "common_video/libyuv/include/webrtc_libyuv.h"
 #include "modules/video_coding/codecs/test/video_codec_unittest.h"
 #include "modules/video_coding/codecs/vp8/include/vp8.h"
-#include "modules/video_coding/codecs/vp8/temporal_layers.h"
+#include "modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h"
 #include "modules/video_coding/utility/vp8_header_parser.h"
 #include "rtc_base/timeutils.h"
 #include "test/video_codec_settings.h"
diff --git a/modules/video_coding/codecs/vp8/vp8_temporal_layers.cc b/modules/video_coding/codecs/vp8/vp8_temporal_layers.cc
new file mode 100644
index 0000000..4958441
--- /dev/null
+++ b/modules/video_coding/codecs/vp8/vp8_temporal_layers.cc
@@ -0,0 +1,42 @@
+/* Copyright (c) 2017 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 "modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h"
+
+#include "absl/memory/memory.h"
+#include "modules/video_coding/codecs/vp8/default_temporal_layers.h"
+#include "modules/video_coding/codecs/vp8/screenshare_layers.h"
+#include "system_wrappers/include/clock.h"
+
+namespace webrtc {
+
+bool TemporalLayers::FrameConfig::operator==(const FrameConfig& o) const {
+  return drop_frame == o.drop_frame &&
+         last_buffer_flags == o.last_buffer_flags &&
+         golden_buffer_flags == o.golden_buffer_flags &&
+         arf_buffer_flags == o.arf_buffer_flags && layer_sync == o.layer_sync &&
+         freeze_entropy == o.freeze_entropy &&
+         encoder_layer_id == o.encoder_layer_id &&
+         packetizer_temporal_idx == o.packetizer_temporal_idx;
+}
+
+std::unique_ptr<TemporalLayers> TemporalLayers::CreateTemporalLayers(
+    TemporalLayersType type,
+    int num_temporal_layers) {
+  switch (type) {
+    case TemporalLayersType::kFixedPattern:
+      return absl::make_unique<DefaultTemporalLayers>(num_temporal_layers);
+    case TemporalLayersType::kBitrateDynamic:
+      // Conference mode temporal layering for screen content in base stream.
+      return absl::make_unique<ScreenshareLayers>(num_temporal_layers,
+                                                  Clock::GetRealTimeClock());
+  }
+}
+
+}  // namespace webrtc
diff --git a/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc b/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc
index 8166420..332c4b8 100644
--- a/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc
+++ b/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc
@@ -15,7 +15,7 @@
 #include <utility>
 #include <vector>
 
-#include "modules/video_coding/codecs/vp8/temporal_layers.h"
+#include "modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h"
 
 #include "test/gmock.h"
 #include "test/gtest.h"
diff --git a/modules/video_coding/utility/simulcast_utility.cc b/modules/video_coding/utility/simulcast_utility.cc
index 60cf062..bc8616f 100644
--- a/modules/video_coding/utility/simulcast_utility.cc
+++ b/modules/video_coding/utility/simulcast_utility.cc
@@ -8,6 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <algorithm>
+
 #include "modules/video_coding/utility/simulcast_utility.h"
 
 namespace webrtc {
@@ -62,4 +64,29 @@
   return true;
 }
 
+bool SimulcastUtility::IsConferenceModeScreenshare(const VideoCodec& codec) {
+  if (codec.mode != VideoCodecMode::kScreensharing ||
+      NumberOfTemporalLayers(codec, 0) != 2) {
+    return false;
+  }
+  // Fixed default bitrates for legacy screenshare layers mode.
+  return (codec.numberOfSimulcastStreams == 0 && codec.maxBitrate == 1000) ||
+         (codec.numberOfSimulcastStreams >= 1 &&
+          codec.simulcastStream[0].maxBitrate == 1000 &&
+          codec.simulcastStream[0].targetBitrate == 200);
+}
+
+int SimulcastUtility::NumberOfTemporalLayers(const VideoCodec& codec,
+                                             int spatial_id) {
+  uint8_t num_temporal_layers =
+      std::max<uint8_t>(1, codec.VP8().numberOfTemporalLayers);
+  if (codec.numberOfSimulcastStreams > 0) {
+    RTC_DCHECK_LT(spatial_id, codec.numberOfSimulcastStreams);
+    num_temporal_layers =
+        std::max(num_temporal_layers,
+                 codec.simulcastStream[spatial_id].numberOfTemporalLayers);
+  }
+  return num_temporal_layers;
+}
+
 }  // namespace webrtc
diff --git a/modules/video_coding/utility/simulcast_utility.h b/modules/video_coding/utility/simulcast_utility.h
index cf690f2..02ccab6 100644
--- a/modules/video_coding/utility/simulcast_utility.h
+++ b/modules/video_coding/utility/simulcast_utility.h
@@ -23,6 +23,9 @@
                                         int num_streams);
   static bool ValidSimulcastTemporalLayers(const VideoCodec& codec,
                                            int num_streams);
+  static int NumberOfTemporalLayers(const VideoCodec& codec, int spatial_id);
+  // TODO(sprang): Remove this hack when ScreenshareLayers is gone.
+  static bool IsConferenceModeScreenshare(const VideoCodec& codec);
 };
 
 }  // namespace webrtc
diff --git a/modules/video_coding/video_codec_initializer_unittest.cc b/modules/video_coding/video_codec_initializer_unittest.cc
index 80a3016..fb601f0 100644
--- a/modules/video_coding/video_codec_initializer_unittest.cc
+++ b/modules/video_coding/video_codec_initializer_unittest.cc
@@ -12,7 +12,7 @@
 #include "api/video/video_bitrate_allocator.h"
 #include "api/video_codecs/video_encoder.h"
 #include "common_types.h"  // NOLINT(build/include)
-#include "modules/video_coding/codecs/vp8/temporal_layers.h"
+#include "modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h"
 #include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
 #include "rtc_base/refcountedobject.h"
 #include "test/gtest.h"
@@ -86,8 +86,9 @@
     // Make sure temporal layers instances have been created.
     if (codec_out_.codecType == VideoCodecType::kVideoCodecVP8) {
       for (int i = 0; i < codec_out_.numberOfSimulcastStreams; ++i) {
-        temporal_layers_.emplace_back(
-            TemporalLayers::CreateTemporalLayers(codec_out_, i));
+        temporal_layers_.emplace_back(TemporalLayers::CreateTemporalLayers(
+            TemporalLayersType::kFixedPattern,
+            codec_out_.VP8()->numberOfTemporalLayers));
       }
     }
     return true;
diff --git a/modules/video_coding/video_sender_unittest.cc b/modules/video_coding/video_sender_unittest.cc
index 5c7f32d..3cd9caf 100644
--- a/modules/video_coding/video_sender_unittest.cc
+++ b/modules/video_coding/video_sender_unittest.cc
@@ -13,7 +13,7 @@
 
 #include "api/video/i420_buffer.h"
 #include "modules/video_coding/codecs/vp8/include/vp8.h"
-#include "modules/video_coding/codecs/vp8/temporal_layers.h"
+#include "modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h"
 #include "modules/video_coding/include/mock/mock_vcm_callbacks.h"
 #include "modules/video_coding/include/mock/mock_video_codec_interface.h"
 #include "modules/video_coding/include/video_coding.h"