1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
117fff32c808707eb6810d1057747069d7afce9939stefan@webrtc.org#include "webrtc/modules/video_coding/main/test/rtp_player.h"
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
133f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <stdio.h>
143f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org
154d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#include <map>
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
176696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
187fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h"
197fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h"
207fff32c808707eb6810d1057747069d7afce9939stefan@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
217fff32c808707eb6810d1057747069d7afce9939stefan@webrtc.org#include "webrtc/modules/video_coding/main/source/internal_defines.h"
227fff32c808707eb6810d1057747069d7afce9939stefan@webrtc.org#include "webrtc/modules/video_coding/main/test/test_util.h"
231bb2146351979b6610107419b2a9c86cca2692a3stefan@webrtc.org#include "webrtc/system_wrappers/interface/clock.h"
244d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
254d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#include "webrtc/system_wrappers/interface/scoped_ptr.h"
26ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#include "webrtc/test/rtp_file_reader.h"
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
284d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#if 1
294d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org# define DEBUG_LOG1(text, arg)
304d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#else
314d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org# define DEBUG_LOG1(text, arg) (printf(text "\n", arg))
324d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#endif
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
344d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgnamespace webrtc {
354d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgnamespace rtpplayer {
364d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
374d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgenum {
384d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kMaxPacketBufferSize = 4096,
394d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  kDefaultTransmissionTimeOffsetExtensionId = 2
404d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org};
414d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
424d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgclass RawRtpPacket {
434d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org public:
444d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  RawRtpPacket(const uint8_t* data, uint32_t length, uint32_t ssrc,
454d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org               uint16_t seq_num)
464d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      : data_(new uint8_t[length]),
474d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        length_(length),
484d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        resend_time_ms_(-1),
494d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        ssrc_(ssrc),
504d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        seq_num_(seq_num) {
514d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    assert(data);
524d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    memcpy(data_.get(), data, length_);
534d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
554d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  const uint8_t* data() const { return data_.get(); }
564d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  uint32_t length() const { return length_; }
574d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int64_t resend_time_ms() const { return resend_time_ms_; }
584d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  void set_resend_time_ms(int64_t timeMs) { resend_time_ms_ = timeMs; }
594d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  uint32_t ssrc() const { return ssrc_; }
604d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  uint16_t seq_num() const { return seq_num_; }
614d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
624d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org private:
63ba47616ee5a8d8a4d94e160b64b79a56845e291bandrew@webrtc.org  scoped_ptr<uint8_t[]> data_;
644d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  uint32_t length_;
654d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int64_t resend_time_ms_;
664d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  uint32_t ssrc_;
674d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  uint16_t seq_num_;
684d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
694d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  DISALLOW_IMPLICIT_CONSTRUCTORS(RawRtpPacket);
704d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org};
714d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
724d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgclass LostPackets {
734d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org public:
744d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  LostPackets(Clock* clock, uint32_t rtt_ms)
754d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
764d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        debug_file_(fopen("PacketLossDebug.txt", "w")),
774d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        loss_count_(0),
784d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        packets_(),
794d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        clock_(clock),
804d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        rtt_ms_(rtt_ms) {
814d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    assert(clock);
824d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
844d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  ~LostPackets() {
854d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (debug_file_) {
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      fclose(debug_file_);
874d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      debug_file_ = NULL;
884d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
894d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    while (!packets_.empty()) {
904d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      delete packets_.back();
914d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      packets_.pop_back();
924d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
954d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  void AddPacket(RawRtpPacket* packet) {
964d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    assert(packet);
974d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    printf("Throw:  %08x:%u\n", packet->ssrc(), packet->seq_num());
984d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    CriticalSectionScoped cs(crit_sect_.get());
994d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (debug_file_) {
1004d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      fprintf(debug_file_, "%u Lost packet: %u\n", loss_count_,
1014d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org              packet->seq_num());
1024d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
1034d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    packets_.push_back(packet);
1044d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    loss_count_++;
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1074d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  void SetResendTime(uint32_t ssrc, int16_t resendSeqNum) {
1084d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    int64_t resend_time_ms = clock_->TimeInMilliseconds() + rtt_ms_;
1094d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    int64_t now_ms = clock_->TimeInMilliseconds();
1104d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    CriticalSectionScoped cs(crit_sect_.get());
1114d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    for (RtpPacketIterator it = packets_.begin(); it != packets_.end(); ++it) {
1124d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      RawRtpPacket* packet = *it;
1134d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      if (ssrc == packet->ssrc() && resendSeqNum == packet->seq_num() &&
1144d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org          packet->resend_time_ms() + 10 < now_ms) {
1154d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        if (debug_file_) {
1164d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org          fprintf(debug_file_, "Resend %u at %u\n", packet->seq_num(),
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                  MaskWord64ToUWord32(resend_time_ms));
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
1194d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        packet->set_resend_time_ms(resend_time_ms);
1204d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        return;
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1234d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // We may get here since the captured stream may itself be missing packets.
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1264d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  RawRtpPacket* NextPacketToResend(int64_t time_now) {
1274d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    CriticalSectionScoped cs(crit_sect_.get());
1284d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    for (RtpPacketIterator it = packets_.begin(); it != packets_.end(); ++it) {
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      RawRtpPacket* packet = *it;
1304d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      if (time_now >= packet->resend_time_ms() &&
1314d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org          packet->resend_time_ms() != -1) {
1324d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        packets_.erase(it);
1334d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        return packet;
1344d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1364d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return NULL;
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1394d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int NumberOfPacketsToResend() const {
1404d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    CriticalSectionScoped cs(crit_sect_.get());
1414d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    int count = 0;
1424d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    for (ConstRtpPacketIterator it = packets_.begin(); it != packets_.end();
1434d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        ++it) {
1444d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      if ((*it)->resend_time_ms() >= 0) {
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        count++;
1464d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1484d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return count;
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1514d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  void LogPacketResent(RawRtpPacket* packet) {
1524d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    int64_t now_ms = clock_->TimeInMilliseconds();
1534d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    CriticalSectionScoped cs(crit_sect_.get());
1544d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (debug_file_) {
1554d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      fprintf(debug_file_, "Resent %u at %u\n", packet->seq_num(),
1564d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org              MaskWord64ToUWord32(now_ms));
1574d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1604d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  void Print() const {
1614d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    CriticalSectionScoped cs(crit_sect_.get());
1624d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    printf("Lost packets: %u\n", loss_count_);
1634d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    printf("Packets waiting to be resent: %d\n", NumberOfPacketsToResend());
1644d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    printf("Packets still lost: %zd\n", packets_.size());
1654d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    printf("Sequence numbers:\n");
1664d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    for (ConstRtpPacketIterator it = packets_.begin(); it != packets_.end();
1674d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        ++it) {
1684d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      printf("%u, ", (*it)->seq_num());
1694d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
1704d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    printf("\n");
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1734d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org private:
1744d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  typedef std::vector<RawRtpPacket*> RtpPacketList;
1754d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  typedef RtpPacketList::iterator RtpPacketIterator;
1764d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  typedef RtpPacketList::const_iterator ConstRtpPacketIterator;
1774d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
1784d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  scoped_ptr<CriticalSectionWrapper> crit_sect_;
1794d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  FILE* debug_file_;
1804d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int loss_count_;
1814d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  RtpPacketList packets_;
1824d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  Clock* clock_;
1834d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  uint32_t rtt_ms_;
1844d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
1854d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  DISALLOW_IMPLICIT_CONSTRUCTORS(LostPackets);
1864d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org};
1874d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
1884d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgclass SsrcHandlers {
1894d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org public:
1904d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  SsrcHandlers(PayloadSinkFactoryInterface* payload_sink_factory,
1914d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org               const PayloadTypes& payload_types)
1924d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      : payload_sink_factory_(payload_sink_factory),
1934d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        payload_types_(payload_types),
1944d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        handlers_() {
1954d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    assert(payload_sink_factory);
1964d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1984d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  ~SsrcHandlers() {
1994d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    while (!handlers_.empty()) {
2004d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      delete handlers_.begin()->second;
2014d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      handlers_.erase(handlers_.begin());
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2034d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
2044d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
205e1c99022cc666e440e9fc74dc7cf8414987a47a5stefan@webrtc.org  int RegisterSsrc(uint32_t ssrc, LostPackets* lost_packets, Clock* clock) {
2064d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (handlers_.count(ssrc) > 0) {
2074d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return 0;
2084d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
2094d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    DEBUG_LOG1("Registering handler for ssrc=%08x", ssrc);
2104d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
2114d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    scoped_ptr<Handler> handler(
2124d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        new Handler(ssrc, payload_types_, lost_packets));
2134d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    handler->payload_sink_.reset(payload_sink_factory_->Create(handler.get()));
2144d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (handler->payload_sink_.get() == NULL) {
2154d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return -1;
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    RtpRtcp::Configuration configuration;
219e1c99022cc666e440e9fc74dc7cf8414987a47a5stefan@webrtc.org    configuration.clock = clock;
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    configuration.id = 1;
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    configuration.audio = false;
2227fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org    handler->rtp_module_.reset(RtpReceiver::CreateVideoReceiver(
2237fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org        configuration.id, configuration.clock, handler->payload_sink_.get(),
2247fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org        NULL, handler->rtp_payload_registry_.get()));
2254d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (handler->rtp_module_.get() == NULL) {
2264d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return -1;
227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
229db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org    handler->rtp_module_->SetNACKStatus(kNackOff);
2306696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org    handler->rtp_header_parser_->RegisterRtpHeaderExtension(
2314d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        kRtpExtensionTransmissionTimeOffset,
2324d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        kDefaultTransmissionTimeOffsetExtensionId);
2334d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
2344d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    for (PayloadTypesIterator it = payload_types_.begin();
2354d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        it != payload_types_.end(); ++it) {
2364d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      VideoCodec codec;
2374d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      memset(&codec, 0, sizeof(codec));
2384d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      strncpy(codec.plName, it->name().c_str(), sizeof(codec.plName)-1);
2394d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      codec.plType = it->payload_type();
2404d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      codec.codecType = it->codec_type();
2417fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org      if (handler->rtp_module_->RegisterReceivePayload(codec.plName,
2427fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                                                       codec.plType,
2437fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                                                       90000,
2447fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                                                       0,
2457fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org                                                       codec.maxBitrate) < 0) {
246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
2474d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2494d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
2504d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    handlers_[ssrc] = handler.release();
251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
2524d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2544d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  void IncomingPacket(const uint8_t* data, uint32_t length) {
2554d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    for (HandlerMapIt it = handlers_.begin(); it != handlers_.end(); ++it) {
2567fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org      if (!it->second->rtp_header_parser_->IsRtcp(data, length)) {
2576696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org        RTPHeader header;
2586696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org        it->second->rtp_header_parser_->Parse(data, length, &header);
2597fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org        PayloadUnion payload_specific;
2607fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org        it->second->rtp_payload_registry_->GetPayloadSpecifics(
2617fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org            header.payloadType, &payload_specific);
262db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org        it->second->rtp_module_->IncomingRtpPacket(header, data, length,
263db74c61ddfa26c23d3e392b241c983010e10b1c5stefan@webrtc.org                                                   payload_specific, true);
2646696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org      }
265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2664d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
2674d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
2684d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org private:
2694d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  class Handler : public RtpStreamInterface {
2704d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org   public:
2714d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    Handler(uint32_t ssrc, const PayloadTypes& payload_types,
2724d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org            LostPackets* lost_packets)
2736696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org        : rtp_header_parser_(RtpHeaderParser::Create()),
2747fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org          rtp_payload_registry_(new RTPPayloadRegistry(
27599681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org              RTPPayloadStrategy::CreateStrategy(false))),
2766696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org          rtp_module_(),
2774d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org          payload_sink_(),
2784d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org          ssrc_(ssrc),
2794d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org          payload_types_(payload_types),
2804d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org          lost_packets_(lost_packets) {
2814d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      assert(lost_packets);
282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2834d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    virtual ~Handler() {}
284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2854d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    virtual void ResendPackets(const uint16_t* sequence_numbers,
2864d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org                               uint16_t length) {
2874d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      assert(sequence_numbers);
2884d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      for (uint16_t i = 0; i < length; i++) {
2894d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        lost_packets_->SetResendTime(ssrc_, sequence_numbers[i]);
2904d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
2914d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    }
292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2934d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    virtual uint32_t ssrc() const { return ssrc_; }
2944d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    virtual const PayloadTypes& payload_types() const {
2954d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return payload_types_;
296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2986696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org    scoped_ptr<RtpHeaderParser> rtp_header_parser_;
2997fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org    scoped_ptr<RTPPayloadRegistry> rtp_payload_registry_;
3007fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org    scoped_ptr<RtpReceiver> rtp_module_;
3014d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    scoped_ptr<PayloadSinkInterface> payload_sink_;
3024d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3034d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org   private:
3044d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    uint32_t ssrc_;
3054d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    const PayloadTypes& payload_types_;
3064d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    LostPackets* lost_packets_;
3074d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3084d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    DISALLOW_COPY_AND_ASSIGN(Handler);
3094d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  };
3104d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3114d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  typedef std::map<uint32_t, Handler*> HandlerMap;
3124d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  typedef std::map<uint32_t, Handler*>::iterator HandlerMapIt;
3134d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3144d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  PayloadSinkFactoryInterface* payload_sink_factory_;
3154d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  PayloadTypes payload_types_;
3164d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  HandlerMap handlers_;
3174d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3184d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  DISALLOW_IMPLICIT_CONSTRUCTORS(SsrcHandlers);
3194d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org};
3204d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3214d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgclass RtpPlayerImpl : public RtpPlayerInterface {
3224d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org public:
3234d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  RtpPlayerImpl(PayloadSinkFactoryInterface* payload_sink_factory,
3244d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      const PayloadTypes& payload_types, Clock* clock,
325ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      scoped_ptr<test::RtpFileReader>* packet_source,
3264d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      float loss_rate, uint32_t rtt_ms, bool reordering)
3274d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    : ssrc_handlers_(payload_sink_factory, payload_types),
3284d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      clock_(clock),
3294d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      next_rtp_time_(0),
3304d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      first_packet_(true),
3314d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      first_packet_rtp_time_(0),
3324d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      first_packet_time_ms_(0),
3334d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      loss_rate_(loss_rate),
3344d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      lost_packets_(clock, rtt_ms),
3354d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      resend_packet_count_(0),
3364d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      no_loss_startup_(100),
3374d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      end_of_file_(false),
3384d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      reordering_(false),
339ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      reorder_buffer_() {
3404d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    assert(clock);
3414d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    assert(packet_source);
3424d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    assert(packet_source->get());
3434d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    packet_source_.swap(*packet_source);
3444d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    srand(321);
3454d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
3464d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3474d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  virtual ~RtpPlayerImpl() {}
3484d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3494d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  virtual int NextPacket(int64_t time_now) {
3504d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // Send any packets ready to be resent.
35122c283b04855b8775d323e8788a0438ce2d7c2b5henrike@webrtc.org    for (RawRtpPacket* packet = lost_packets_.NextPacketToResend(time_now);
35222c283b04855b8775d323e8788a0438ce2d7c2b5henrike@webrtc.org         packet != NULL;
35322c283b04855b8775d323e8788a0438ce2d7c2b5henrike@webrtc.org         packet = lost_packets_.NextPacketToResend(time_now)) {
3544d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      int ret = SendPacket(packet->data(), packet->length());
355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (ret > 0) {
3564d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        printf("Resend: %08x:%u\n", packet->ssrc(), packet->seq_num());
3574d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        lost_packets_.LogPacketResent(packet);
3584d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        resend_packet_count_++;
3594d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
3604d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      delete packet;
3614d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      if (ret < 0) {
362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return ret;
363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
3664d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    // Send any packets from packet source.
3674d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (!end_of_file_ && (TimeUntilNextPacket() == 0 || first_packet_)) {
3684d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      if (first_packet_) {
369ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org        if (!packet_source_->NextPacket(&next_packet_))
3704d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org          return 0;
371ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org        first_packet_rtp_time_ = next_packet_.time_ms;
3724d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        first_packet_time_ms_ = clock_->TimeInMilliseconds();
3734d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        first_packet_ = false;
3744d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
3754d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
3764d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      if (reordering_ && reorder_buffer_.get() == NULL) {
377ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org        reorder_buffer_.reset(
378ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org            new RawRtpPacket(next_packet_.data,
379ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org                             static_cast<uint32_t>(next_packet_.length),
380ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org                             0,
381ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org                             0));
3824d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        return 0;
3834d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
384ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      int ret = SendPacket(next_packet_.data,
385ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org                           static_cast<uint32_t>(next_packet_.length));
3864d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      if (reorder_buffer_.get()) {
3874d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        SendPacket(reorder_buffer_->data(), reorder_buffer_->length());
3884d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        reorder_buffer_.reset(NULL);
3894d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
3904d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      if (ret < 0) {
3914d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        return ret;
3924d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
3934d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
394ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      if (!packet_source_->NextPacket(&next_packet_)) {
3954d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        end_of_file_ = true;
3964d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        return 0;
3974d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
398ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      else if (next_packet_.length == 0) {
3994d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        return 0;
4004d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
4024d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4034d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (end_of_file_ && lost_packets_.NumberOfPacketsToResend() == 0) {
4044d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return 1;
405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
4074d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
4094d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  virtual uint32_t TimeUntilNextPacket() const {
4104d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    int64_t time_left = (next_rtp_time_ - first_packet_rtp_time_) -
4114d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        (clock_->TimeInMilliseconds() - first_packet_time_ms_);
4124d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (time_left < 0) {
4134d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return 0;
414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
4154d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return static_cast<uint32_t>(time_left);
4164d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
4184d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  virtual void Print() const {
4194d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    printf("Resent packets: %u\n", resend_packet_count_);
4204d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    lost_packets_.Print();
4214d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
4234d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org private:
4244d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int SendPacket(const uint8_t* data, uint32_t length) {
4254d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    assert(data);
4264d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    assert(length > 0);
427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
4286696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org    scoped_ptr<RtpHeaderParser> rtp_header_parser(RtpHeaderParser::Create());
4296696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org    if (!rtp_header_parser->IsRtcp(data, length)) {
4306696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org      RTPHeader header;
4316696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org      if (!rtp_header_parser->Parse(data, length, &header)) {
4324d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        return -1;
4334d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
4346696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org      uint32_t ssrc = header.ssrc;
435e1c99022cc666e440e9fc74dc7cf8414987a47a5stefan@webrtc.org      if (ssrc_handlers_.RegisterSsrc(ssrc, &lost_packets_, clock_) < 0) {
4364d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        DEBUG_LOG1("Unable to register ssrc: %d", ssrc);
4374d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        return -1;
4384d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
4404d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      if (no_loss_startup_ > 0) {
4414d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        no_loss_startup_--;
4424d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      } else if ((rand() + 1.0)/(RAND_MAX + 1.0) < loss_rate_) {
4436696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org        uint16_t seq_num = header.sequenceNumber;
4444d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        lost_packets_.AddPacket(new RawRtpPacket(data, length, ssrc, seq_num));
4454d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        DEBUG_LOG1("Dropped packet: %d!", header.header.sequenceNumber);
4464d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org        return 0;
4474d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      }
448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
4504d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    ssrc_handlers_.IncomingPacket(data, length);
4514d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    return 1;
4524d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
4544d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  SsrcHandlers ssrc_handlers_;
4554d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  Clock* clock_;
456ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  scoped_ptr<test::RtpFileReader> packet_source_;
457ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  test::RtpFileReader::Packet next_packet_;
4584d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  uint32_t next_rtp_time_;
4594d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  bool first_packet_;
4604d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int64_t first_packet_rtp_time_;
4614d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  int64_t first_packet_time_ms_;
4624d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  float loss_rate_;
4634d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  LostPackets lost_packets_;
4644d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  uint32_t resend_packet_count_;
4654d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  uint32_t no_loss_startup_;
4664d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  bool end_of_file_;
4674d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  bool reordering_;
4684d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  scoped_ptr<RawRtpPacket> reorder_buffer_;
4694d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4704d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  DISALLOW_IMPLICIT_CONSTRUCTORS(RtpPlayerImpl);
4714d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org};
4724d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org
4734d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgRtpPlayerInterface* Create(const std::string& input_filename,
4744d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    PayloadSinkFactoryInterface* payload_sink_factory, Clock* clock,
4754d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    const PayloadTypes& payload_types, float loss_rate, uint32_t rtt_ms,
4764d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    bool reordering) {
477ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org  scoped_ptr<test::RtpFileReader> packet_source(test::RtpFileReader::Create(
478ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org      test::RtpFileReader::kRtpDump, input_filename));
4794d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  if (packet_source.get() == NULL) {
480ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org    packet_source.reset(test::RtpFileReader::Create(test::RtpFileReader::kPcap,
481ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org                                                    input_filename));
4824d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org    if (packet_source.get() == NULL) {
4834d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      return NULL;
484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
4854d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  }
486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
4874d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  scoped_ptr<RtpPlayerImpl> impl(new RtpPlayerImpl(payload_sink_factory,
4884d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org      payload_types, clock, &packet_source, loss_rate, rtt_ms, reordering));
4894d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org  return impl.release();
490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
4914d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org}  // namespace rtpplayer
4924d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org}  // namespace webrtc
493