Set RTPVideoHeader picture id in PayloadRouter if forced fallback for VP8 is enabled.

The SW and HW encoder have separate picture id sequences.
Set picture id to not cause sequence discontinuties at encoder changes.

Bug: webrtc:6634
Change-Id: Ie47168791399303d88cbec3ef6ae8ef8c16ced30
Reviewed-on: https://webrtc-review.googlesource.com/5481
Commit-Queue: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20188}
diff --git a/video/payload_router.cc b/video/payload_router.cc
index a7a20de..017b937 100644
--- a/video/payload_router.cc
+++ b/video/payload_router.cc
@@ -14,6 +14,9 @@
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/video_coding/include/video_codec_interface.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/random.h"
+#include "rtc_base/timeutils.h"
+#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 
@@ -89,11 +92,56 @@
 
 }  // namespace
 
+// Currently only used if forced fallback for VP8 is enabled.
+// Consider adding tl0idx and set for VP8 and VP9.
+// Make picture id not codec specific.
+class PayloadRouter::RtpPayloadParams final {
+ public:
+  RtpPayloadParams(const uint32_t ssrc, const RtpPayloadState* state)
+      : ssrc_(ssrc) {
+    Random random(rtc::TimeMicros());
+    state_.picture_id =
+        state ? state->picture_id : (random.Rand<int16_t>() & 0x7FFF);
+  }
+  ~RtpPayloadParams() {}
+
+  void Set(RTPVideoHeader* rtp_video_header) {
+    if (rtp_video_header->codec == kRtpVideoVp8 &&
+        rtp_video_header->codecHeader.VP8.pictureId != kNoPictureId) {
+      rtp_video_header->codecHeader.VP8.pictureId = state_.picture_id;
+      state_.picture_id = (state_.picture_id + 1) & 0x7FFF;
+    }
+  }
+
+  uint32_t ssrc() const { return ssrc_; }
+
+  RtpPayloadState state() const { return state_; }
+
+ private:
+  const uint32_t ssrc_;
+  RtpPayloadState state_;
+};
+
 PayloadRouter::PayloadRouter(const std::vector<RtpRtcp*>& rtp_modules,
-                             int payload_type)
+                             const std::vector<uint32_t>& ssrcs,
+                             int payload_type,
+                             const std::map<uint32_t, RtpPayloadState>& states)
     : active_(false),
       rtp_modules_(rtp_modules),
-      payload_type_(payload_type) {
+      payload_type_(payload_type),
+      forced_fallback_enabled_((webrtc::field_trial::IsEnabled(
+          "WebRTC-VP8-Forced-Fallback-Encoder"))) {
+  RTC_DCHECK_EQ(ssrcs.size(), rtp_modules.size());
+  // SSRCs are assumed to be sorted in the same order as |rtp_modules|.
+  for (uint32_t ssrc : ssrcs) {
+    // Restore state if it previously existed.
+    const RtpPayloadState* state = nullptr;
+    auto it = states.find(ssrc);
+    if (it != states.end()) {
+      state = &it->second;
+    }
+    params_.push_back(RtpPayloadParams(ssrc, state));
+  }
 }
 
 PayloadRouter::~PayloadRouter() {}
@@ -115,6 +163,15 @@
   return active_ && !rtp_modules_.empty();
 }
 
+std::map<uint32_t, RtpPayloadState> PayloadRouter::GetRtpPayloadStates() const {
+  rtc::CritScope lock(&crit_);
+  std::map<uint32_t, RtpPayloadState> payload_states;
+  for (const auto& param : params_) {
+    payload_states[param.ssrc()] = param.state();
+  }
+  return payload_states;
+}
+
 EncodedImageCallback::Result PayloadRouter::OnEncodedImage(
     const EncodedImage& encoded_image,
     const CodecSpecificInfo* codec_specific_info,
@@ -149,6 +206,12 @@
 
   int stream_index = rtp_video_header.simulcastIdx;
   RTC_DCHECK_LT(stream_index, rtp_modules_.size());
+  if (forced_fallback_enabled_) {
+    // Sets picture id. The SW and HW encoder have separate picture id
+    // sequences, set picture id to not cause sequence discontinuties at encoder
+    // changes.
+    params_[stream_index].Set(&rtp_video_header);
+  }
   uint32_t frame_id;
   bool send_result = rtp_modules_[stream_index]->SendOutgoingData(
       encoded_image._frameType, payload_type_, encoded_image._timeStamp,