Avoid infinite recursion if a RED packet encapsulate a RED packet.

Bug: None
Change-Id: Ife982f28637c7a1b5a4f06fa0446841d76da8392
Reviewed-on: https://webrtc-review.googlesource.com/40880
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Commit-Queue: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21718}
diff --git a/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc b/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc
index a5512e1..480e764 100644
--- a/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc
+++ b/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc
@@ -219,7 +219,19 @@
 // TODO(nisse): Drop always-zero return value.
 int32_t UlpfecReceiverImpl::ProcessReceivedFec() {
   crit_sect_.Enter();
-  for (const auto& received_packet : received_packets_) {
+
+  // If we iterate over |received_packets_| and it contains a packet that cause
+  // us to recurse back to this function (for example a RED packet encapsulating
+  // a RED packet), then we will recurse forever. To avoid this we swap
+  // |received_packets_| with an empty vector so that the next recursive call
+  // wont iterate over the same packet again. This also solves the problem of
+  // not modifying the vector we are currently iterating over (packets are added
+  // in AddReceivedRedPacket).
+  std::vector<std::unique_ptr<ForwardErrorCorrection::ReceivedPacket>>
+    received_packets;
+  received_packets.swap(received_packets_);
+
+  for (const auto& received_packet : received_packets) {
     // Send received media packet to VCM.
     if (!received_packet->is_fec) {
       ForwardErrorCorrection::Packet* packet = received_packet->pkt;
@@ -230,7 +242,6 @@
     }
     fec_->DecodeFec(*received_packet, &recovered_packets_);
   }
-  received_packets_.clear();
 
   // Send any recovered media packets to VCM.
   for (const auto& recovered_packet : recovered_packets_) {
@@ -248,6 +259,7 @@
                                                   packet->length);
     crit_sect_.Enter();
   }
+
   crit_sect_.Leave();
   return 0;
 }