Refactor to use std::list in the video rtp play tools.

BUG=
TEST=

Review URL: https://webrtc-codereview.appspot.com/349013

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1504 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
stefan@webrtc.org
2012-01-23 14:56:14 +00:00
parent 152c34cf11
commit 8fe03af674
11 changed files with 216 additions and 272 deletions

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@@ -23,8 +23,6 @@
namespace webrtc namespace webrtc
{ {
class ListWrapper;
// Number of time periods used for (max) window filter for packet loss // Number of time periods used for (max) window filter for packet loss
// TODO (marpan): set reasonable window size for filtered packet loss, // TODO (marpan): set reasonable window size for filtered packet loss,
// adjustment should be based on logged/real data of loss stats/correlation. // adjustment should be based on logged/real data of loss stats/correlation.

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@@ -11,7 +11,6 @@
#ifndef WEBRTC_MODULES_VIDEO_CODING_MEDIA_OPTIMIZATION_H_ #ifndef WEBRTC_MODULES_VIDEO_CODING_MEDIA_OPTIMIZATION_H_
#define WEBRTC_MODULES_VIDEO_CODING_MEDIA_OPTIMIZATION_H_ #define WEBRTC_MODULES_VIDEO_CODING_MEDIA_OPTIMIZATION_H_
#include "list_wrapper.h"
#include "module_common_types.h" #include "module_common_types.h"
#include "video_coding.h" #include "video_coding.h"
#include "trace.h" #include "trace.h"

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@@ -83,14 +83,14 @@ int DecodeFromStorageTest(CmdArgs& args)
vcm->RegisterFrameStorageCallback(&storageCallback); vcm->RegisterFrameStorageCallback(&storageCallback);
vcmPlayback->RegisterReceiveCallback(&receiveCallback); vcmPlayback->RegisterReceiveCallback(&receiveCallback);
RTPPlayer rtpStream(rtpFilename.c_str(), &dataCallback, &clock); RTPPlayer rtpStream(rtpFilename.c_str(), &dataCallback, &clock);
ListWrapper payloadTypes; PayloadTypeList payloadTypes;
payloadTypes.PushFront(new PayloadCodecTuple(VCM_VP8_PAYLOAD_TYPE, "VP8", kVideoCodecVP8)); payloadTypes.push_front(new PayloadCodecTuple(VCM_VP8_PAYLOAD_TYPE, "VP8",
kVideoCodecVP8));
// Register receive codecs in VCM // Register receive codecs in VCM
ListItem* item = payloadTypes.First(); for (PayloadTypeList::iterator it = payloadTypes.begin();
while (item != NULL) it != payloadTypes.end(); ++it) {
{ PayloadCodecTuple* payloadType = *it;
PayloadCodecTuple* payloadType = static_cast<PayloadCodecTuple*>(item->GetItem());
if (payloadType != NULL) if (payloadType != NULL)
{ {
VideoCodec codec; VideoCodec codec;
@@ -108,9 +108,8 @@ int DecodeFromStorageTest(CmdArgs& args)
return -1; return -1;
} }
} }
item = payloadTypes.Next(item);
} }
if (rtpStream.Initialize(payloadTypes) < 0) if (rtpStream.Initialize(&payloadTypes) < 0)
{ {
return -1; return -1;
} }
@@ -163,17 +162,10 @@ int DecodeFromStorageTest(CmdArgs& args)
rtpStream.Print(); rtpStream.Print();
// Tear down // Tear down
item = payloadTypes.First(); while (!payloadTypes.empty())
while (item != NULL)
{ {
PayloadCodecTuple* payloadType = static_cast<PayloadCodecTuple*>(item->GetItem()); delete payloadTypes.front();
if (payloadType != NULL) payloadTypes.pop_front();
{
delete payloadType;
}
ListItem* itemToRemove = item;
item = payloadTypes.Next(item);
payloadTypes.Erase(itemToRemove);
} }
VideoCodingModule::Destroy(vcm); VideoCodingModule::Destroy(vcm);
vcm = NULL; vcm = NULL;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@@ -56,7 +56,7 @@ TransportCallback::SendPacket(int channel, const void *data, int len)
// Insert outgoing packet into list // Insert outgoing packet into list
if (transmitPacket) if (transmitPacket)
{ {
rtpPacket* newPacket = new rtpPacket(); RtpPacket* newPacket = new RtpPacket();
memcpy(newPacket->data, data, len); memcpy(newPacket->data, data, len);
newPacket->length = len; newPacket->length = len;
// Simulate receive time = network delay + packet jitter // Simulate receive time = network delay + packet jitter
@@ -66,7 +66,7 @@ TransportCallback::SendPacket(int channel, const void *data, int len)
simulatedDelay = (WebRtc_Word32)NormalDist(_networkDelayMs, simulatedDelay = (WebRtc_Word32)NormalDist(_networkDelayMs,
sqrt(_jitterVar)); sqrt(_jitterVar));
newPacket->receiveTime = now + simulatedDelay; newPacket->receiveTime = now + simulatedDelay;
_rtpPackets.PushBack(newPacket); _rtpPackets.push_back(newPacket);
} }
return 0; return 0;
} }
@@ -75,14 +75,14 @@ int
TransportCallback::TransportPackets() TransportCallback::TransportPackets()
{ {
// Are we ready to send packets to the receiver? // Are we ready to send packets to the receiver?
rtpPacket* packet = NULL; RtpPacket* packet = NULL;
TickTimeBase clock; TickTimeBase clock;
int64_t now = clock.MillisecondTimestamp(); int64_t now = clock.MillisecondTimestamp();
while (!_rtpPackets.Empty()) while (!_rtpPackets.empty())
{ {
// Take first packet in list // Take first packet in list
packet = static_cast<rtpPacket*>((_rtpPackets.First())->GetItem()); packet = _rtpPackets.front();
WebRtc_Word64 timeToReceive = packet->receiveTime - now; WebRtc_Word64 timeToReceive = packet->receiveTime - now;
if (timeToReceive > 0) if (timeToReceive > 0)
{ {
@@ -90,7 +90,7 @@ TransportCallback::TransportPackets()
break; break;
} }
_rtpPackets.PopFront(); _rtpPackets.pop_front();
// Send to receive side // Send to receive side
if (_rtp->IncomingPacket((const WebRtc_UWord8*)packet->data, if (_rtp->IncomingPacket((const WebRtc_UWord8*)packet->data,
packet->length) < 0) packet->length) < 0)

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@@ -25,113 +25,114 @@
using namespace webrtc; using namespace webrtc;
RawRtpPacket::RawRtpPacket(WebRtc_UWord8* data, WebRtc_UWord16 len) RawRtpPacket::RawRtpPacket(uint8_t* rtp_data, uint16_t rtp_length)
: : data(rtp_data),
rtpData(), rtpLen(len), resendTimeMs(-1) length(rtp_length),
{ resend_time_ms(-1) {
rtpData = new WebRtc_UWord8[rtpLen]; data = new uint8_t[length];
memcpy(rtpData, data, rtpLen); memcpy(data, rtp_data, length);
} }
RawRtpPacket::~RawRtpPacket() RawRtpPacket::~RawRtpPacket() {
{ delete [] data;
delete [] rtpData;
} }
LostPackets::LostPackets() LostPackets::LostPackets()
: : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
_critSect(CriticalSectionWrapper::CreateCriticalSection()), loss_count_(0),
_lossCount(0), debug_file_(NULL),
_debugFile(NULL) packets_() {
{ debug_file_ = fopen("PacketLossDebug.txt", "w");
_debugFile = fopen("PacketLossDebug.txt", "w");
} }
LostPackets::~LostPackets() LostPackets::~LostPackets() {
{ if (debug_file_) {
if (_debugFile) fclose(debug_file_);
{ }
fclose(_debugFile); while (!packets_.empty()) {
} delete packets_.front();
ListItem* item = First(); packets_.pop_front();
while (item != NULL) }
{ delete crit_sect_;
RawRtpPacket* packet = static_cast<RawRtpPacket*>(item->GetItem()); }
if (packet != NULL)
{ void LostPackets::AddPacket(RawRtpPacket* packet) {
delete packet; CriticalSectionScoped cs(crit_sect_);
packets_.push_back(packet);
uint16_t seq_num = (packet->data[2] << 8) + packet->data[3];
if (debug_file_ != NULL) {
fprintf(debug_file_, "%u Lost packet: %u\n", loss_count_, seq_num);
}
++loss_count_;
}
void LostPackets::SetResendTime(uint16_t resend_seq_num,
int64_t resend_time_ms,
int64_t now_ms) {
CriticalSectionScoped cs(crit_sect_);
for (RtpPacketIterator it = packets_.begin(); it != packets_.end(); ++it) {
const uint16_t seq_num = ((*it)->data[2] << 8) +
(*it)->data[3];
if (resend_seq_num == seq_num) {
if ((*it)->resend_time_ms + 10 < now_ms) {
if (debug_file_ != NULL) {
fprintf(debug_file_, "Resend %u at %u\n", seq_num,
MaskWord64ToUWord32(resend_time_ms));
} }
Erase(item); (*it)->resend_time_ms = resend_time_ms;
item = First(); }
return;
} }
delete _critSect; }
assert(false);
} }
WebRtc_UWord32 LostPackets::AddPacket(WebRtc_UWord8* rtpData, WebRtc_UWord16 rtpLen) RawRtpPacket* LostPackets::NextPacketToResend(int64_t timeNow) {
{ CriticalSectionScoped cs(crit_sect_);
CriticalSectionScoped cs(_critSect); for (RtpPacketIterator it = packets_.begin(); it != packets_.end(); ++it) {
RawRtpPacket* packet = new RawRtpPacket(rtpData, rtpLen); if (timeNow >= (*it)->resend_time_ms && (*it)->resend_time_ms != -1) {
ListItem* newItem = new ListItem(packet); RawRtpPacket* packet = *it;
Insert(Last(), newItem); it = packets_.erase(it);
const WebRtc_UWord16 seqNo = (rtpData[2] << 8) + rtpData[3]; return packet;
if (_debugFile != NULL)
{
fprintf(_debugFile, "%u Lost packet: %u\n", _lossCount, seqNo);
} }
_lossCount++; }
return 0; return NULL;
} }
WebRtc_UWord32 LostPackets::SetResendTime(WebRtc_UWord16 sequenceNumber, int LostPackets::NumberOfPacketsToResend() const {
WebRtc_Word64 resendTime, CriticalSectionScoped cs(crit_sect_);
WebRtc_Word64 nowMs) int count = 0;
{ for (ConstRtpPacketIterator it = packets_.begin(); it != packets_.end();
CriticalSectionScoped cs(_critSect); ++it) {
ListItem* item = First(); if ((*it)->resend_time_ms >= 0) {
while (item != NULL) count++;
{
RawRtpPacket* packet = static_cast<RawRtpPacket*>(item->GetItem());
const WebRtc_UWord16 seqNo = (packet->rtpData[2] << 8) + packet->rtpData[3];
if (sequenceNumber == seqNo && packet->resendTimeMs + 10 < nowMs)
{
if (_debugFile != NULL)
{
fprintf(_debugFile, "Resend %u at %u\n", seqNo, MaskWord64ToUWord32(resendTime));
}
packet->resendTimeMs = resendTime;
return 0;
}
item = Next(item);
} }
fprintf(_debugFile, "Packet not lost %u\n", sequenceNumber); }
return -1; return count;
} }
WebRtc_UWord32 LostPackets::NumberOfPacketsToResend() const void LostPackets::SetPacketResent(uint16_t seq_num, int64_t now_ms) {
{ CriticalSectionScoped cs(crit_sect_);
CriticalSectionScoped cs(_critSect); if (debug_file_ != NULL) {
WebRtc_UWord32 count = 0; fprintf(debug_file_, "Resent %u at %u\n", seq_num,
ListItem* item = First(); MaskWord64ToUWord32(now_ms));
while (item != NULL) }
{
RawRtpPacket* packet = static_cast<RawRtpPacket*>(item->GetItem());
if (packet->resendTimeMs >= 0)
{
count++;
}
item = Next(item);
}
return count;
} }
void LostPackets::ResentPacket(WebRtc_UWord16 seqNo, WebRtc_Word64 nowMs) void LostPackets::Print() const {
{ CriticalSectionScoped cs(crit_sect_);
CriticalSectionScoped cs(_critSect); printf("Lost packets: %u\n", loss_count_);
if (_debugFile != NULL) printf("Packets waiting to be resent: %u\n",
{ NumberOfPacketsToResend());
fprintf(_debugFile, "Resent %u at %u\n", seqNo, printf("Packets still lost: %u\n",
MaskWord64ToUWord32(nowMs)); static_cast<unsigned int>(packets_.size()));
} printf("Sequence numbers:\n");
for (ConstRtpPacketIterator it = packets_.begin(); it != packets_.end();
++it) {
uint16_t seq_num = ((*it)->data[2] << 8) + (*it)->data[3];
printf("%u, ", seq_num);
}
printf("\n");
} }
RTPPlayer::RTPPlayer(const char* filename, RTPPlayer::RTPPlayer(const char* filename,
@@ -176,7 +177,7 @@ RTPPlayer::~RTPPlayer()
} }
} }
WebRtc_Word32 RTPPlayer::Initialize(const ListWrapper& payloadList) WebRtc_Word32 RTPPlayer::Initialize(const PayloadTypeList* payloadList)
{ {
std::srand(321); std::srand(321);
for (int i=0; i < RAND_VEC_LENGTH; i++) for (int i=0; i < RAND_VEC_LENGTH; i++)
@@ -205,10 +206,9 @@ WebRtc_Word32 RTPPlayer::Initialize(const ListWrapper& payloadList)
return -1; return -1;
} }
// Register payload types // Register payload types
ListItem* item = payloadList.First(); for (PayloadTypeList::const_iterator it = payloadList->begin();
while (item != NULL) it != payloadList->end(); ++it) {
{ PayloadCodecTuple* payloadType = *it;
PayloadCodecTuple* payloadType = static_cast<PayloadCodecTuple*>(item->GetItem());
if (payloadType != NULL) if (payloadType != NULL)
{ {
VideoCodec videoCodec; VideoCodec videoCodec;
@@ -219,7 +219,6 @@ WebRtc_Word32 RTPPlayer::Initialize(const ListWrapper& payloadList)
return -1; return -1;
} }
} }
item = payloadList.Next(item);
} }
if (ReadHeader() < 0) if (ReadHeader() < 0)
{ {
@@ -286,43 +285,21 @@ WebRtc_UWord32 RTPPlayer::TimeUntilNextPacket() const
WebRtc_Word32 RTPPlayer::NextPacket(const WebRtc_Word64 timeNow) WebRtc_Word32 RTPPlayer::NextPacket(const WebRtc_Word64 timeNow)
{ {
// Send any packets ready to be resent // Send any packets ready to be resent,
_lostPackets.Lock(); RawRtpPacket* resend_packet = _lostPackets.NextPacketToResend(timeNow);
ListItem* item = _lostPackets.First(); while (resend_packet != NULL) {
_lostPackets.Unlock(); const uint16_t seqNo = (resend_packet->data[2] << 8) +
while (item != NULL) resend_packet->data[3];
{ printf("Resend: %u\n", seqNo);
_lostPackets.Lock(); int ret = SendPacket(resend_packet->data, resend_packet->length);
RawRtpPacket* packet = static_cast<RawRtpPacket*>(item->GetItem()); delete resend_packet;
_lostPackets.Unlock(); _resendPacketCount++;
if (timeNow >= packet->resendTimeMs && packet->resendTimeMs != -1) if (ret > 0) {
{ _lostPackets.SetPacketResent(seqNo, _clock->MillisecondTimestamp());
const WebRtc_UWord16 seqNo = (packet->rtpData[2] << 8) + packet->rtpData[3]; } else if (ret < 0) {
printf("Resend: %u\n", seqNo); return ret;
WebRtc_Word32 ret = SendPacket(packet->rtpData, packet->rtpLen); }
ListItem* itemToRemove = item; resend_packet = _lostPackets.NextPacketToResend(timeNow);
_lostPackets.Lock();
item = _lostPackets.Next(item);
_lostPackets.Erase(itemToRemove);
delete packet;
_lostPackets.Unlock();
_resendPacketCount++;
if (ret > 0)
{
_lostPackets.ResentPacket(seqNo,
_clock->MillisecondTimestamp());
}
else if (ret < 0)
{
return ret;
}
}
else
{
_lostPackets.Lock();
item = _lostPackets.Next(item);
_lostPackets.Unlock();
}
} }
// Send any packets from rtp file // Send any packets from rtp file
@@ -344,7 +321,7 @@ WebRtc_Word32 RTPPlayer::NextPacket(const WebRtc_Word64 timeNow)
{ {
RawRtpPacket* rtpPacket = _reorderBuffer; RawRtpPacket* rtpPacket = _reorderBuffer;
_reorderBuffer = NULL; _reorderBuffer = NULL;
SendPacket(rtpPacket->rtpData, rtpPacket->rtpLen); SendPacket(rtpPacket->data, rtpPacket->length);
delete rtpPacket; delete rtpPacket;
} }
_firstPacket = false; _firstPacket = false;
@@ -379,11 +356,11 @@ WebRtc_Word32 RTPPlayer::SendPacket(WebRtc_UWord8* rtpData, WebRtc_UWord16 rtpLe
{ {
const WebRtc_UWord16 seqNo = (rtpData[2] << 8) + rtpData[3]; const WebRtc_UWord16 seqNo = (rtpData[2] << 8) + rtpData[3];
printf("Throw: %u\n", seqNo); printf("Throw: %u\n", seqNo);
_lostPackets.AddPacket(rtpData, rtpLen); _lostPackets.AddPacket(new RawRtpPacket(rtpData, rtpLen));
return 0; return 0;
} }
} }
else else if (rtpLen > 0)
{ {
WebRtc_Word32 ret = _rtpModule.IncomingPacket(rtpData, rtpLen); WebRtc_Word32 ret = _rtpModule.IncomingPacket(rtpData, rtpLen);
if (ret < 0) if (ret < 0)
@@ -461,17 +438,6 @@ WebRtc_Word32 RTPPlayer::ResendPackets(const WebRtc_UWord16* sequenceNumbers, We
void RTPPlayer::Print() const void RTPPlayer::Print() const
{ {
printf("Lost packets: %u, resent packets: %u\n", _lostPackets.TotalNumberOfLosses(), _resendPacketCount); printf("Resent packets: %u\n", _resendPacketCount);
printf("Packets still lost: %u\n", _lostPackets.GetSize()); _lostPackets.Print();
printf("Packets waiting to be resent: %u\n", _lostPackets.NumberOfPacketsToResend());
printf("Sequence numbers:\n");
ListItem* item = _lostPackets.First();
while (item != NULL)
{
RawRtpPacket* packet = static_cast<RawRtpPacket*>(item->GetItem());
const WebRtc_UWord16 seqNo = (packet->rtpData[2] << 8) + packet->rtpData[3];
printf("%u, ", seqNo);
item = _lostPackets.Next(item);
}
printf("\n");
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@@ -13,48 +13,55 @@
#include "typedefs.h" #include "typedefs.h"
#include "rtp_rtcp.h" #include "rtp_rtcp.h"
#include "list_wrapper.h"
#include "critical_section_wrapper.h" #include "critical_section_wrapper.h"
#include "video_coding_defines.h" #include "video_coding_defines.h"
#include "modules/video_coding/main/source/tick_time_base.h" #include "modules/video_coding/main/source/tick_time_base.h"
#include <stdio.h> #include <stdio.h>
#include <list>
#include <string> #include <string>
#define HDR_SIZE 8 // rtpplay packet header size in bytes #define HDR_SIZE 8 // rtpplay packet header size in bytes
#define FIRSTLINELEN 40 #define FIRSTLINELEN 40
#define RAND_VEC_LENGTH 4096 #define RAND_VEC_LENGTH 4096
class PayloadCodecTuple;
struct RawRtpPacket struct RawRtpPacket
{ {
public: public:
RawRtpPacket(WebRtc_UWord8* data, WebRtc_UWord16 len); RawRtpPacket(WebRtc_UWord8* rtp_data, WebRtc_UWord16 rtp_length);
~RawRtpPacket(); ~RawRtpPacket();
WebRtc_UWord8* rtpData; uint8_t* data;
WebRtc_UWord16 rtpLen; uint16_t length;
WebRtc_Word64 resendTimeMs; int64_t resend_time_ms;
}; };
class LostPackets : public webrtc::ListWrapper typedef std::list<PayloadCodecTuple*> PayloadTypeList;
{ typedef std::list<RawRtpPacket*> RtpPacketList;
public: typedef RtpPacketList::iterator RtpPacketIterator;
LostPackets(); typedef RtpPacketList::const_iterator ConstRtpPacketIterator;
~LostPackets();
WebRtc_UWord32 AddPacket(WebRtc_UWord8* rtpData, WebRtc_UWord16 rtpLen); class LostPackets {
WebRtc_UWord32 SetResendTime(WebRtc_UWord16 sequenceNumber, public:
WebRtc_Word64 resendTime, LostPackets();
WebRtc_Word64 nowMs); ~LostPackets();
WebRtc_UWord32 TotalNumberOfLosses() const { return _lossCount; };
WebRtc_UWord32 NumberOfPacketsToResend() const; void AddPacket(RawRtpPacket* packet);
void ResentPacket(WebRtc_UWord16 seqNo, WebRtc_Word64 nowMs); void SetResendTime(uint16_t sequenceNumber,
void Lock() {_critSect->Enter();}; int64_t resendTime,
void Unlock() {_critSect->Leave();}; int64_t nowMs);
private: RawRtpPacket* NextPacketToResend(int64_t timeNow);
webrtc::CriticalSectionWrapper* _critSect; int NumberOfPacketsToResend() const;
WebRtc_UWord32 _lossCount; void SetPacketResent(uint16_t seqNo, int64_t nowMs);
FILE* _debugFile; void Print() const;
private:
webrtc::CriticalSectionWrapper* crit_sect_;
int loss_count_;
FILE* debug_file_;
RtpPacketList packets_;
}; };
struct PayloadCodecTuple struct PayloadCodecTuple
@@ -74,7 +81,7 @@ public:
webrtc::TickTimeBase* clock); webrtc::TickTimeBase* clock);
virtual ~RTPPlayer(); virtual ~RTPPlayer();
WebRtc_Word32 Initialize(const webrtc::ListWrapper& payloadList); WebRtc_Word32 Initialize(const PayloadTypeList* payloadList);
WebRtc_Word32 NextPacket(const WebRtc_Word64 timeNow); WebRtc_Word32 NextPacket(const WebRtc_Word64 timeNow);
WebRtc_UWord32 TimeUntilNextPacket() const; WebRtc_UWord32 TimeUntilNextPacket() const;
WebRtc_Word32 SimulatePacketLoss(float lossRate, bool enableNack = false, WebRtc_UWord32 rttMs = 0); WebRtc_Word32 SimulatePacketLoss(float lossRate, bool enableNack = false, WebRtc_UWord32 rttMs = 0);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@@ -225,11 +225,11 @@ RTPSendCompleteCallback::~RTPSendCompleteCallback()
RtpDump::DestroyRtpDump(_rtpDump); RtpDump::DestroyRtpDump(_rtpDump);
} }
// Delete remaining packets // Delete remaining packets
while (!_rtpPackets.Empty()) while (!_rtpPackets.empty())
{ {
// Take first packet in list // Take first packet in list
delete static_cast<rtpPacket*>((_rtpPackets.First())->GetItem()); delete _rtpPackets.front();
_rtpPackets.PopFront(); _rtpPackets.pop_front();
} }
} }
@@ -254,7 +254,7 @@ RTPSendCompleteCallback::SendPacket(int channel, const void *data, int len)
// Insert outgoing packet into list // Insert outgoing packet into list
if (transmitPacket) if (transmitPacket)
{ {
rtpPacket* newPacket = new rtpPacket(); RtpPacket* newPacket = new RtpPacket();
memcpy(newPacket->data, data, len); memcpy(newPacket->data, data, len);
newPacket->length = len; newPacket->length = len;
// Simulate receive time = network delay + packet jitter // Simulate receive time = network delay + packet jitter
@@ -264,16 +264,16 @@ RTPSendCompleteCallback::SendPacket(int channel, const void *data, int len)
simulatedDelay = (WebRtc_Word32)NormalDist(_networkDelayMs, simulatedDelay = (WebRtc_Word32)NormalDist(_networkDelayMs,
sqrt(_jitterVar)); sqrt(_jitterVar));
newPacket->receiveTime = now + simulatedDelay; newPacket->receiveTime = now + simulatedDelay;
_rtpPackets.PushBack(newPacket); _rtpPackets.push_back(newPacket);
} }
// Are we ready to send packets to the receiver? // Are we ready to send packets to the receiver?
rtpPacket* packet = NULL; RtpPacket* packet = NULL;
while (!_rtpPackets.Empty()) while (!_rtpPackets.empty())
{ {
// Take first packet in list // Take first packet in list
packet = static_cast<rtpPacket*>((_rtpPackets.First())->GetItem()); packet = _rtpPackets.front();
WebRtc_Word64 timeToReceive = packet->receiveTime - now; WebRtc_Word64 timeToReceive = packet->receiveTime - now;
if (timeToReceive > 0) if (timeToReceive > 0)
{ {
@@ -281,7 +281,7 @@ RTPSendCompleteCallback::SendPacket(int channel, const void *data, int len)
break; break;
} }
_rtpPackets.PopFront(); _rtpPackets.pop_front();
// Send to receive side // Send to receive side
if (_rtp->IncomingPacket((const WebRtc_UWord8*)packet->data, if (_rtp->IncomingPacket((const WebRtc_UWord8*)packet->data,
packet->length) < 0) packet->length) < 0)

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@@ -16,11 +16,11 @@
*/ */
#include <string.h>
#include <cstdlib> #include <cstdlib>
#include <fstream> #include <fstream>
#include <string.h> #include <list>
#include "list_wrapper.h"
#include "module_common_types.h" #include "module_common_types.h"
#include "rtp_rtcp.h" #include "rtp_rtcp.h"
#include "test_util.h" #include "test_util.h"
@@ -29,7 +29,7 @@
namespace webrtc namespace webrtc
{ {
class RtpDump; class RtpDump;
// Send Side - Packetization callback - send an encoded frame to the VCMReceiver // Send Side - Packetization callback - send an encoded frame to the VCMReceiver
class VCMEncodeCompleteCallback: public VCMPacketizationCallback class VCMEncodeCompleteCallback: public VCMPacketizationCallback
@@ -147,7 +147,6 @@ private:
WebRtc_UWord32 _decodedBytes; WebRtc_UWord32 _decodedBytes;
}; // end of VCMDecodeCompleCallback class }; // end of VCMDecodeCompleCallback class
// Transport callback // Transport callback
// Called by the RTP Sender - simulates sending packets through a network to the // Called by the RTP Sender - simulates sending packets through a network to the
// RTP receiver. User can set network conditions as: RTT, packet loss, // RTP receiver. User can set network conditions as: RTT, packet loss,
@@ -192,7 +191,7 @@ protected:
double _jitterVar; double _jitterVar;
bool _prevLossState; bool _prevLossState;
WebRtc_UWord32 _totalSentLength; WebRtc_UWord32 _totalSentLength;
ListWrapper _rtpPackets; std::list<RtpPacket*> _rtpPackets;
RtpDump* _rtpDump; RtpDump* _rtpDump;
}; };

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@@ -61,12 +61,11 @@ class CmdArgs
int MTRxTxTest(CmdArgs& args); int MTRxTxTest(CmdArgs& args);
double NormalDist(double mean, double stdDev); double NormalDist(double mean, double stdDev);
typedef struct struct RtpPacket {
{ WebRtc_Word8 data[1650]; // max packet size
WebRtc_Word8 data[1650]; // max packet size WebRtc_Word32 length;
WebRtc_Word32 length; WebRtc_Word64 receiveTime;
WebRtc_Word64 receiveTime; };
} rtpPacket;
// Codec type conversion // Codec type conversion

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@@ -80,7 +80,7 @@ int RtpPlay(CmdArgs& args)
bool protectionEnabled = false; bool protectionEnabled = false;
VCMVideoProtection protectionMethod = kProtectionNack; VCMVideoProtection protectionMethod = kProtectionNack;
WebRtc_UWord32 rttMS = 10; WebRtc_UWord32 rttMS = 0;
float lossRate = 0.0f; float lossRate = 0.0f;
bool reordering = false; bool reordering = false;
WebRtc_UWord32 renderDelayMs = 0; WebRtc_UWord32 renderDelayMs = 0;
@@ -96,8 +96,9 @@ int RtpPlay(CmdArgs& args)
RTPPlayer rtpStream(args.inputFile.c_str(), &dataCallback, &clock); RTPPlayer rtpStream(args.inputFile.c_str(), &dataCallback, &clock);
ListWrapper payloadTypes; PayloadTypeList payloadTypes;
payloadTypes.PushFront(new PayloadCodecTuple(VCM_VP8_PAYLOAD_TYPE, "VP8", kVideoCodecVP8)); payloadTypes.push_front(new PayloadCodecTuple(VCM_VP8_PAYLOAD_TYPE, "VP8",
kVideoCodecVP8));
Trace::CreateTrace(); Trace::CreateTrace();
Trace::SetTraceFile((test::OutputPath() + "receiverTestTrace.txt").c_str()); Trace::SetTraceFile((test::OutputPath() + "receiverTestTrace.txt").c_str());
@@ -115,10 +116,9 @@ int RtpPlay(CmdArgs& args)
vcm->RegisterPacketRequestCallback(&rtpStream); vcm->RegisterPacketRequestCallback(&rtpStream);
// Register receive codecs in VCM // Register receive codecs in VCM
ListItem* item = payloadTypes.First(); for (PayloadTypeList::iterator it = payloadTypes.begin();
while (item != NULL) it != payloadTypes.end(); ++it) {
{ PayloadCodecTuple* payloadType = *it;
PayloadCodecTuple* payloadType = static_cast<PayloadCodecTuple*>(item->GetItem());
if (payloadType != NULL) if (payloadType != NULL)
{ {
VideoCodec codec; VideoCodec codec;
@@ -132,15 +132,15 @@ int RtpPlay(CmdArgs& args)
return -1; return -1;
} }
} }
item = payloadTypes.Next(item);
} }
if (rtpStream.Initialize(payloadTypes) < 0) if (rtpStream.Initialize(&payloadTypes) < 0)
{ {
return -1; return -1;
} }
bool nackEnabled = protectionEnabled && (protectionMethod == kProtectionNack || bool nackEnabled = protectionEnabled &&
protectionMethod == kProtectionDualDecoder); (protectionMethod == kProtectionNack ||
protectionMethod == kProtectionDualDecoder);
rtpStream.SimulatePacketLoss(lossRate, nackEnabled, rttMS); rtpStream.SimulatePacketLoss(lossRate, nackEnabled, rttMS);
rtpStream.SetReordering(reordering); rtpStream.SetReordering(reordering);
vcm->SetChannelParameters(0, 0, rttMS); vcm->SetChannelParameters(0, 0, rttMS);
@@ -166,7 +166,8 @@ int RtpPlay(CmdArgs& args)
{ {
vcm->Process(); vcm->Process();
} }
if (MAX_RUNTIME_MS > -1 && clock.MillisecondTimestamp() >= MAX_RUNTIME_MS) if (MAX_RUNTIME_MS > -1 && clock.MillisecondTimestamp() >=
MAX_RUNTIME_MS)
{ {
break; break;
} }
@@ -189,17 +190,10 @@ int RtpPlay(CmdArgs& args)
rtpStream.Print(); rtpStream.Print();
// Tear down // Tear down
item = payloadTypes.First(); while (!payloadTypes.empty())
while (item != NULL)
{ {
PayloadCodecTuple* payloadType = static_cast<PayloadCodecTuple*>(item->GetItem()); delete payloadTypes.front();
if (payloadType != NULL) payloadTypes.pop_front();
{
delete payloadType;
}
ListItem* itemToRemove = item;
item = payloadTypes.Next(item);
payloadTypes.Erase(itemToRemove);
} }
delete vcm; delete vcm;
vcm = NULL; vcm = NULL;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@@ -137,10 +137,9 @@ int RtpPlayMT(CmdArgs& args, int releaseTestNo, webrtc::VideoCodecType releaseTe
printf("Watch %s to verify that the output is reasonable\n", outFilename.c_str()); printf("Watch %s to verify that the output is reasonable\n", outFilename.c_str());
} }
RTPPlayer rtpStream(rtpFilename.c_str(), &dataCallback, &clock); RTPPlayer rtpStream(rtpFilename.c_str(), &dataCallback, &clock);
ListWrapper payloadTypes; PayloadTypeList payloadTypes;
payloadTypes.PushFront(new PayloadCodecTuple(VCM_VP8_PAYLOAD_TYPE, payloadTypes.push_front(new PayloadCodecTuple(VCM_VP8_PAYLOAD_TYPE, "VP8",
"VP8", kVideoCodecVP8)); kVideoCodecVP8));
Trace::CreateTrace(); Trace::CreateTrace();
Trace::SetTraceFile("receiverTestTrace.txt"); Trace::SetTraceFile("receiverTestTrace.txt");
Trace::SetLevelFilter(webrtc::kTraceAll); Trace::SetLevelFilter(webrtc::kTraceAll);
@@ -151,7 +150,7 @@ int RtpPlayMT(CmdArgs& args, int releaseTestNo, webrtc::VideoCodecType releaseTe
SharedState mtState(*vcm, rtpStream); SharedState mtState(*vcm, rtpStream);
if (rtpStream.Initialize(payloadTypes) < 0) if (rtpStream.Initialize(&payloadTypes) < 0)
{ {
return -1; return -1;
} }
@@ -172,10 +171,9 @@ int RtpPlayMT(CmdArgs& args, int releaseTestNo, webrtc::VideoCodecType releaseTe
&mtState, kNormalPriority, "DecodeThread"); &mtState, kNormalPriority, "DecodeThread");
// Register receive codecs in VCM // Register receive codecs in VCM
ListItem* item = payloadTypes.First(); for (PayloadTypeList::iterator it = payloadTypes.begin();
while (item != NULL) it != payloadTypes.end(); ++it) {
{ PayloadCodecTuple* payloadType = *it;
PayloadCodecTuple* payloadType = static_cast<PayloadCodecTuple*>(item->GetItem());
if (payloadType != NULL) if (payloadType != NULL)
{ {
VideoCodec codec; VideoCodec codec;
@@ -186,7 +184,6 @@ int RtpPlayMT(CmdArgs& args, int releaseTestNo, webrtc::VideoCodecType releaseTe
return -1; return -1;
} }
} }
item = payloadTypes.Next(item);
} }
if (processingThread != NULL) if (processingThread != NULL)
@@ -235,17 +232,10 @@ int RtpPlayMT(CmdArgs& args, int releaseTestNo, webrtc::VideoCodecType releaseTe
waitEvent.Wait(MAX_RUNTIME_MS); waitEvent.Wait(MAX_RUNTIME_MS);
// Tear down // Tear down
item = payloadTypes.First(); while (!payloadTypes.empty())
while (item != NULL)
{ {
PayloadCodecTuple* payloadType = static_cast<PayloadCodecTuple*>(item->GetItem()); delete payloadTypes.front();
if (payloadType != NULL) payloadTypes.pop_front();
{
delete payloadType;
}
ListItem* itemToRemove = item;
item = payloadTypes.Next(item);
payloadTypes.Erase(itemToRemove);
} }
while (!processingThread->Stop()) while (!processingThread->Stop())
{ {