Removes usage of ListWrapper from several files.

BUG=2164
R=andrew@webrtc.org, pbos@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5373 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
henrike@webrtc.org 2014-01-13 15:21:30 +00:00
parent d0b436a935
commit 79cf3acc79
23 changed files with 314 additions and 449 deletions

View File

@ -12,9 +12,9 @@
#define WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_GENERIC_H_ #define WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_GENERIC_H_
#include <assert.h> #include <assert.h>
#include <list>
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/list_wrapper.h"
#include "webrtc/typedefs.h" #include "webrtc/typedefs.h"
namespace webrtc { namespace webrtc {
@ -40,7 +40,7 @@ private:
bool _terminate; bool _terminate;
ListWrapper _memoryPool; std::list<MemoryType*> _memoryPool;
uint32_t _initialPoolSize; uint32_t _initialPoolSize;
uint32_t _createdMemory; uint32_t _createdMemory;
@ -51,7 +51,6 @@ template<class MemoryType>
MemoryPoolImpl<MemoryType>::MemoryPoolImpl(int32_t initialPoolSize) MemoryPoolImpl<MemoryType>::MemoryPoolImpl(int32_t initialPoolSize)
: _crit(CriticalSectionWrapper::CreateCriticalSection()), : _crit(CriticalSectionWrapper::CreateCriticalSection()),
_terminate(false), _terminate(false),
_memoryPool(),
_initialPoolSize(initialPoolSize), _initialPoolSize(initialPoolSize),
_createdMemory(0), _createdMemory(0),
_outstandingMemory(0) _outstandingMemory(0)
@ -76,20 +75,17 @@ int32_t MemoryPoolImpl<MemoryType>::PopMemory(MemoryType*& memory)
memory = NULL; memory = NULL;
return -1; return -1;
} }
ListItem* item = _memoryPool.First(); if (_memoryPool.empty()) {
if(item == NULL)
{
// _memoryPool empty create new memory. // _memoryPool empty create new memory.
CreateMemory(_initialPoolSize); CreateMemory(_initialPoolSize);
item = _memoryPool.First(); if(_memoryPool.empty())
if(item == NULL)
{ {
memory = NULL; memory = NULL;
return -1; return -1;
} }
} }
memory = static_cast<MemoryType*>(item->GetItem()); memory = _memoryPool.front();
_memoryPool.Erase(item); _memoryPool.pop_front();
_outstandingMemory++; _outstandingMemory++;
return 0; return 0;
} }
@ -103,7 +99,7 @@ int32_t MemoryPoolImpl<MemoryType>::PushMemory(MemoryType*& memory)
} }
CriticalSectionScoped cs(_crit); CriticalSectionScoped cs(_crit);
_outstandingMemory--; _outstandingMemory--;
if(_memoryPool.GetSize() > (_initialPoolSize << 1)) if(_memoryPool.size() > (_initialPoolSize << 1))
{ {
// Reclaim memory if less than half of the pool is unused. // Reclaim memory if less than half of the pool is unused.
_createdMemory--; _createdMemory--;
@ -111,7 +107,7 @@ int32_t MemoryPoolImpl<MemoryType>::PushMemory(MemoryType*& memory)
memory = NULL; memory = NULL;
return 0; return 0;
} }
_memoryPool.PushBack(static_cast<void*>(memory)); _memoryPool.push_back(memory);
memory = NULL; memory = NULL;
return 0; return 0;
} }
@ -127,21 +123,15 @@ template<class MemoryType>
int32_t MemoryPoolImpl<MemoryType>::Terminate() int32_t MemoryPoolImpl<MemoryType>::Terminate()
{ {
CriticalSectionScoped cs(_crit); CriticalSectionScoped cs(_crit);
assert(_createdMemory == _outstandingMemory + _memoryPool.GetSize()); assert(_createdMemory == _outstandingMemory + _memoryPool.size());
_terminate = true; _terminate = true;
// Reclaim all memory. // Reclaim all memory.
while(_createdMemory > 0) while(_createdMemory > 0)
{ {
ListItem* item = _memoryPool.First(); MemoryType* memory = _memoryPool.front();
if(item == NULL) _memoryPool.pop_front();
{
// There is memory that hasn't been returned yet.
return -1;
}
MemoryType* memory = static_cast<MemoryType*>(item->GetItem());
delete memory; delete memory;
_memoryPool.Erase(item);
_createdMemory--; _createdMemory--;
} }
return 0; return 0;
@ -158,7 +148,7 @@ int32_t MemoryPoolImpl<MemoryType>::CreateMemory(
{ {
return -1; return -1;
} }
_memoryPool.PushBack(static_cast<void*>(memory)); _memoryPool.push_back(memory);
_createdMemory++; _createdMemory++;
} }
return 0; return 0;

View File

@ -37,15 +37,6 @@ const char* RecordedMicrophoneBoostFile =
const char* RecordedMicrophoneAGCFile = "recorded_microphone_AGC_mono_48.pcm"; const char* RecordedMicrophoneAGCFile = "recorded_microphone_AGC_mono_48.pcm";
const char* RecordedSpeakerFile = "recorded_speaker_48.pcm"; const char* RecordedSpeakerFile = "recorded_speaker_48.pcm";
struct AudioPacket
{
uint8_t dataBuffer[4 * 960];
uint16_t nSamples;
uint16_t nBytesPerSample;
uint8_t nChannels;
uint32_t samplesPerSec;
};
// Helper functions // Helper functions
#if !defined(WEBRTC_IOS) #if !defined(WEBRTC_IOS)
char* GetFilename(char* filename) char* GetFilename(char* filename)
@ -103,8 +94,7 @@ AudioTransportImpl::AudioTransportImpl(AudioDeviceModule* audioDevice) :
_loopBackMeasurements(false), _loopBackMeasurements(false),
_playFile(*FileWrapper::Create()), _playFile(*FileWrapper::Create()),
_recCount(0), _recCount(0),
_playCount(0), _playCount(0)
_audioList()
{ {
_resampler.Reset(48000, 48000, kResamplerSynchronousStereo); _resampler.Reset(48000, 48000, kResamplerSynchronousStereo);
} }
@ -115,18 +105,9 @@ AudioTransportImpl::~AudioTransportImpl()
_playFile.CloseFile(); _playFile.CloseFile();
delete &_playFile; delete &_playFile;
while (!_audioList.Empty()) for (AudioPacketList::iterator iter = _audioList.begin();
{ iter != _audioList.end(); ++iter) {
ListItem* item = _audioList.First(); delete *iter;
if (item)
{
AudioPacket* packet = static_cast<AudioPacket*> (item->GetItem());
if (packet)
{
delete packet;
}
}
_audioList.PopFront();
} }
} }
@ -152,19 +133,11 @@ void AudioTransportImpl::SetFullDuplex(bool enable)
{ {
_fullDuplex = enable; _fullDuplex = enable;
while (!_audioList.Empty()) for (AudioPacketList::iterator iter = _audioList.begin();
{ iter != _audioList.end(); ++iter) {
ListItem* item = _audioList.First(); delete *iter;
if (item)
{
AudioPacket* packet = static_cast<AudioPacket*> (item->GetItem());
if (packet)
{
delete packet;
}
}
_audioList.PopFront();
} }
_audioList.clear();
} }
int32_t AudioTransportImpl::RecordedDataIsAvailable( int32_t AudioTransportImpl::RecordedDataIsAvailable(
@ -179,7 +152,7 @@ int32_t AudioTransportImpl::RecordedDataIsAvailable(
const bool keyPressed, const bool keyPressed,
uint32_t& newMicLevel) uint32_t& newMicLevel)
{ {
if (_fullDuplex && _audioList.GetSize() < 15) if (_fullDuplex && _audioList.size() < 15)
{ {
AudioPacket* packet = new AudioPacket(); AudioPacket* packet = new AudioPacket();
memcpy(packet->dataBuffer, audioSamples, nSamples * nBytesPerSample); memcpy(packet->dataBuffer, audioSamples, nSamples * nBytesPerSample);
@ -187,7 +160,7 @@ int32_t AudioTransportImpl::RecordedDataIsAvailable(
packet->nBytesPerSample = nBytesPerSample; packet->nBytesPerSample = nBytesPerSample;
packet->nChannels = nChannels; packet->nChannels = nChannels;
packet->samplesPerSec = samplesPerSec; packet->samplesPerSec = samplesPerSec;
_audioList.PushBack(packet); _audioList.push_back(packet);
} }
_recCount++; _recCount++;
@ -323,14 +296,14 @@ int32_t AudioTransportImpl::NeedMorePlayData(
{ {
if (_fullDuplex) if (_fullDuplex)
{ {
if (_audioList.Empty()) if (_audioList.empty())
{ {
// use zero stuffing when not enough data // use zero stuffing when not enough data
memset(audioSamples, 0, nBytesPerSample * nSamples); memset(audioSamples, 0, nBytesPerSample * nSamples);
} else } else
{ {
ListItem* item = _audioList.First(); AudioPacket* packet = _audioList.front();
AudioPacket* packet = static_cast<AudioPacket*> (item->GetItem()); _audioList.pop_front();
if (packet) if (packet)
{ {
int ret(0); int ret(0);
@ -441,7 +414,6 @@ int32_t AudioTransportImpl::NeedMorePlayData(
nSamplesOut = nSamples; nSamplesOut = nSamples;
delete packet; delete packet;
} }
_audioList.PopFront();
} }
} // if (_fullDuplex) } // if (_fullDuplex)
@ -531,12 +503,12 @@ int32_t AudioTransportImpl::NeedMorePlayData(
{ {
uint16_t recDelayMS(0); uint16_t recDelayMS(0);
uint16_t playDelayMS(0); uint16_t playDelayMS(0);
uint32_t nItemsInList(0); size_t nItemsInList(0);
nItemsInList = _audioList.GetSize(); nItemsInList = _audioList.size();
EXPECT_EQ(0, _audioDevice->RecordingDelay(&recDelayMS)); EXPECT_EQ(0, _audioDevice->RecordingDelay(&recDelayMS));
EXPECT_EQ(0, _audioDevice->PlayoutDelay(&playDelayMS)); EXPECT_EQ(0, _audioDevice->PlayoutDelay(&playDelayMS));
TEST_LOG("Delay (rec+play)+buf: %3u (%3u+%3u)+%3u [ms]\n", TEST_LOG("Delay (rec+play)+buf: %3zu (%3u+%3u)+%3zu [ms]\n",
recDelayMS + playDelayMS + 10 * (nItemsInList + 1), recDelayMS + playDelayMS + 10 * (nItemsInList + 1),
recDelayMS, playDelayMS, 10 * (nItemsInList + 1)); recDelayMS, playDelayMS, 10 * (nItemsInList + 1));

View File

@ -13,13 +13,13 @@
#include "webrtc/modules/audio_device/audio_device_utility.h" #include "webrtc/modules/audio_device/audio_device_utility.h"
#include <list>
#include <string> #include <string>
#include "webrtc/common_audio/resampler/include/resampler.h" #include "webrtc/common_audio/resampler/include/resampler.h"
#include "webrtc/modules/audio_device/include/audio_device.h" #include "webrtc/modules/audio_device/include/audio_device.h"
#include "webrtc/modules/audio_device/test/audio_device_test_defines.h" #include "webrtc/modules/audio_device/test/audio_device_test_defines.h"
#include "webrtc/system_wrappers/interface/file_wrapper.h" #include "webrtc/system_wrappers/interface/file_wrapper.h"
#include "webrtc/system_wrappers/interface/list_wrapper.h"
#include "webrtc/typedefs.h" #include "webrtc/typedefs.h"
#if defined(WEBRTC_IOS) || defined(ANDROID) #if defined(WEBRTC_IOS) || defined(ANDROID)
@ -60,6 +60,15 @@ enum TestType
TTTest = 66, TTTest = 66,
}; };
struct AudioPacket
{
uint8_t dataBuffer[4 * 960];
uint16_t nSamples;
uint16_t nBytesPerSample;
uint8_t nChannels;
uint32_t samplesPerSec;
};
class ProcessThread; class ProcessThread;
namespace webrtc namespace webrtc
@ -165,6 +174,7 @@ public:
; ;
private: private:
typedef std::list<AudioPacket*> AudioPacketList;
AudioDeviceModule* _audioDevice; AudioDeviceModule* _audioDevice;
bool _playFromFile; bool _playFromFile;
@ -181,8 +191,7 @@ private:
uint32_t _recCount; uint32_t _recCount;
uint32_t _playCount; uint32_t _playCount;
AudioPacketList _audioList;
ListWrapper _audioList;
Resampler _resampler; Resampler _resampler;
}; };

View File

@ -23,7 +23,6 @@
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/file_wrapper.h" #include "webrtc/system_wrappers/interface/file_wrapper.h"
#include "webrtc/system_wrappers/interface/list_wrapper.h"
#include "webrtc/system_wrappers/interface/trace.h" #include "webrtc/system_wrappers/interface/trace.h"
// http://msdn2.microsoft.com/en-us/library/ms779636.aspx // http://msdn2.microsoft.com/en-us/library/ms779636.aspx
@ -178,8 +177,7 @@ AviFile::AviFile()
_videoCodecConfigParamsLength(0), _videoCodecConfigParamsLength(0),
_videoStreamDataChunkPrefix(0), _videoStreamDataChunkPrefix(0),
_audioStreamDataChunkPrefix(0), _audioStreamDataChunkPrefix(0),
_created(false), _created(false)
_indexList(new ListWrapper())
{ {
ResetComplexMembers(); ResetComplexMembers();
} }
@ -188,7 +186,6 @@ AviFile::~AviFile()
{ {
Close(); Close();
delete _indexList;
delete[] _videoCodecConfigParams; delete[] _videoCodecConfigParams;
delete _crit; delete _crit;
} }
@ -1712,21 +1709,11 @@ uint32_t AviFile::StreamAndTwoCharCodeToTag(int32_t streamNum,
void AviFile::ClearIndexList() void AviFile::ClearIndexList()
{ {
while (!_indexList->Empty()) for (IndexList::iterator iter = _indexList.begin();
{ iter != _indexList.end(); ++iter) {
ListItem* listItem = _indexList->First(); delete *iter;
if (listItem == 0) }
{ _indexList.clear();
break;
}
AVIINDEXENTRY* item = static_cast<AVIINDEXENTRY*>(listItem->GetItem());
if (item != NULL)
{
delete item;
}
_indexList->PopFront();
}
} }
void AviFile::AddChunkToIndexList(uint32_t inChunkId, void AviFile::AddChunkToIndexList(uint32_t inChunkId,
@ -1734,7 +1721,7 @@ void AviFile::AddChunkToIndexList(uint32_t inChunkId,
uint32_t inOffset, uint32_t inOffset,
uint32_t inSize) uint32_t inSize)
{ {
_indexList->PushBack(new AVIINDEXENTRY(inChunkId, inFlags, inOffset, _indexList.push_back(new AVIINDEXENTRY(inChunkId, inFlags, inOffset,
inSize)); inSize));
} }
@ -1747,19 +1734,13 @@ void AviFile::WriteIndex()
_bytesWritten += PutLE32(0); _bytesWritten += PutLE32(0);
const size_t idxChunkSize = _bytesWritten; const size_t idxChunkSize = _bytesWritten;
for (ListItem* listItem = _indexList->First(); for (IndexList::iterator iter = _indexList.begin();
listItem != NULL; iter != _indexList.end(); ++iter) {
listItem = _indexList->Next(listItem)) const AVIINDEXENTRY* item = *iter;
{ _bytesWritten += PutLE32(item->ckid);
const AVIINDEXENTRY* item = _bytesWritten += PutLE32(item->dwFlags);
static_cast<AVIINDEXENTRY*>(listItem->GetItem()); _bytesWritten += PutLE32(item->dwChunkOffset);
if (item != NULL) _bytesWritten += PutLE32(item->dwChunkLength);
{
_bytesWritten += PutLE32(item->ckid);
_bytesWritten += PutLE32(item->dwFlags);
_bytesWritten += PutLE32(item->dwChunkOffset);
_bytesWritten += PutLE32(item->dwChunkLength);
}
} }
PutLE32LengthFromCurrent(static_cast<long>(idxChunkSize)); PutLE32LengthFromCurrent(static_cast<long>(idxChunkSize));
} }

View File

@ -14,12 +14,12 @@
#define WEBRTC_MODULES_MEDIA_FILE_SOURCE_AVI_FILE_H_ #define WEBRTC_MODULES_MEDIA_FILE_SOURCE_AVI_FILE_H_
#include <stdio.h> #include <stdio.h>
#include <list>
#include "webrtc/typedefs.h" #include "webrtc/typedefs.h"
namespace webrtc { namespace webrtc {
class CriticalSectionWrapper; class CriticalSectionWrapper;
class ListWrapper;
struct AVISTREAMHEADER struct AVISTREAMHEADER
{ {
@ -194,6 +194,7 @@ private:
void WriteIndex(); void WriteIndex();
private: private:
typedef std::list<AVIINDEXENTRY*> IndexList;
struct AVIMAINHEADER struct AVIMAINHEADER
{ {
AVIMAINHEADER(); AVIMAINHEADER();
@ -269,7 +270,7 @@ private:
uint32_t _audioStreamDataChunkPrefix; uint32_t _audioStreamDataChunkPrefix;
bool _created; bool _created;
ListWrapper* _indexList; // Elements are of type AVIINDEXENTRY. IndexList _indexList;
}; };
} // namespace webrtc } // namespace webrtc

View File

@ -25,7 +25,7 @@ public:
virtual int32_t Start() = 0; virtual int32_t Start() = 0;
virtual int32_t Stop() = 0; virtual int32_t Stop() = 0;
virtual int32_t RegisterModule(const Module* module) = 0; virtual int32_t RegisterModule(Module* module) = 0;
virtual int32_t DeRegisterModule(const Module* module) = 0; virtual int32_t DeRegisterModule(const Module* module) = 0;
protected: protected:
virtual ~ProcessThread(); virtual ~ProcessThread();

View File

@ -342,31 +342,6 @@ int32_t FileRecorderImpl::WriteEncodedAudioData(
#ifdef WEBRTC_MODULE_UTILITY_VIDEO #ifdef WEBRTC_MODULE_UTILITY_VIDEO
class AudioFrameFileInfo
{
public:
AudioFrameFileInfo(const int8_t* audioData,
const uint16_t audioSize,
const uint16_t audioMS,
const TickTime& playoutTS)
: _audioData(), _audioSize(audioSize), _audioMS(audioMS),
_playoutTS(playoutTS)
{
if(audioSize > MAX_AUDIO_BUFFER_IN_BYTES)
{
assert(false);
_audioSize = 0;
return;
}
memcpy(_audioData, audioData, audioSize);
};
// TODO (hellner): either turn into a struct or provide get/set functions.
int8_t _audioData[MAX_AUDIO_BUFFER_IN_BYTES];
uint16_t _audioSize;
uint16_t _audioMS;
TickTime _playoutTS;
};
AviRecorder::AviRecorder(uint32_t instanceID, FileFormats fileFormat) AviRecorder::AviRecorder(uint32_t instanceID, FileFormats fileFormat)
: FileRecorderImpl(instanceID, fileFormat), : FileRecorderImpl(instanceID, fileFormat),
_videoOnly(false), _videoOnly(false),
@ -545,49 +520,39 @@ int32_t AviRecorder::ProcessAudio()
{ {
// Syncronize audio to the current frame to process by throwing away // Syncronize audio to the current frame to process by throwing away
// audio samples with older timestamp than the video frame. // audio samples with older timestamp than the video frame.
uint32_t numberOfAudioElements = size_t numberOfAudioElements =
_audioFramesToWrite.GetSize(); _audioFramesToWrite.size();
for (uint32_t i = 0; i < numberOfAudioElements; ++i) for (size_t i = 0; i < numberOfAudioElements; ++i)
{ {
AudioFrameFileInfo* frameInfo = AudioFrameFileInfo* frameInfo = _audioFramesToWrite.front();
(AudioFrameFileInfo*)_audioFramesToWrite.First()->GetItem(); if(TickTime::TicksToMilliseconds(
if(frameInfo) frameInfo->_playoutTS.Ticks()) <
frameToProcess->render_time_ms())
{ {
if(TickTime::TicksToMilliseconds( delete frameInfo;
frameInfo->_playoutTS.Ticks()) < _audioFramesToWrite.pop_front();
frameToProcess->render_time_ms()) } else
{ {
delete frameInfo; break;
_audioFramesToWrite.PopFront();
} else
{
break;
}
} }
} }
} }
} }
// Write all audio up to current timestamp. // Write all audio up to current timestamp.
int32_t error = 0; int32_t error = 0;
uint32_t numberOfAudioElements = _audioFramesToWrite.GetSize(); size_t numberOfAudioElements = _audioFramesToWrite.size();
for (uint32_t i = 0; i < numberOfAudioElements; ++i) for (size_t i = 0; i < numberOfAudioElements; ++i)
{ {
AudioFrameFileInfo* frameInfo = AudioFrameFileInfo* frameInfo = _audioFramesToWrite.front();
(AudioFrameFileInfo*)_audioFramesToWrite.First()->GetItem(); if((TickTime::Now() - frameInfo->_playoutTS).Milliseconds() > 0)
if(frameInfo)
{ {
if((TickTime::Now() - frameInfo->_playoutTS).Milliseconds() > 0) _moduleFile->IncomingAudioData(frameInfo->_audioData,
{ frameInfo->_audioSize);
_moduleFile->IncomingAudioData(frameInfo->_audioData, _writtenAudioMS += frameInfo->_audioMS;
frameInfo->_audioSize); delete frameInfo;
_writtenAudioMS += frameInfo->_audioMS; _audioFramesToWrite.pop_front();
delete frameInfo;
_audioFramesToWrite.PopFront();
} else {
break;
}
} else { } else {
_audioFramesToWrite.PopFront(); break;
} }
} }
return error; return error;
@ -762,7 +727,7 @@ int32_t AviRecorder::WriteEncodedAudioData(
{ {
return -1; return -1;
} }
if (_audioFramesToWrite.GetSize() > kMaxAudioBufferQueueLength) if (_audioFramesToWrite.size() > kMaxAudioBufferQueueLength)
{ {
StopRecording(); StopRecording();
return -1; return -1;
@ -771,15 +736,15 @@ int32_t AviRecorder::WriteEncodedAudioData(
if(playoutTS) if(playoutTS)
{ {
_audioFramesToWrite.PushBack(new AudioFrameFileInfo(audioBuffer, _audioFramesToWrite.push_back(new AudioFrameFileInfo(audioBuffer,
bufferLength, bufferLength,
millisecondsOfData, millisecondsOfData,
*playoutTS)); *playoutTS));
} else { } else {
_audioFramesToWrite.PushBack(new AudioFrameFileInfo(audioBuffer, _audioFramesToWrite.push_back(new AudioFrameFileInfo(audioBuffer,
bufferLength, bufferLength,
millisecondsOfData, millisecondsOfData,
TickTime::Now())); TickTime::Now()));
} }
_timeEvent.Set(); _timeEvent.Set();
return 0; return 0;

View File

@ -15,6 +15,8 @@
#ifndef WEBRTC_MODULES_UTILITY_SOURCE_FILE_RECORDER_IMPL_H_ #ifndef WEBRTC_MODULES_UTILITY_SOURCE_FILE_RECORDER_IMPL_H_
#define WEBRTC_MODULES_UTILITY_SOURCE_FILE_RECORDER_IMPL_H_ #define WEBRTC_MODULES_UTILITY_SOURCE_FILE_RECORDER_IMPL_H_
#include <list>
#include "webrtc/common_audio/resampler/include/resampler.h" #include "webrtc/common_audio/resampler/include/resampler.h"
#include "webrtc/common_types.h" #include "webrtc/common_types.h"
#include "webrtc/engine_configurations.h" #include "webrtc/engine_configurations.h"
@ -40,6 +42,8 @@ enum { MAX_AUDIO_BUFFER_IN_SAMPLES = 60*32};
enum { MAX_AUDIO_BUFFER_IN_BYTES = MAX_AUDIO_BUFFER_IN_SAMPLES*2}; enum { MAX_AUDIO_BUFFER_IN_BYTES = MAX_AUDIO_BUFFER_IN_SAMPLES*2};
enum { kMaxAudioBufferQueueLength = 100 }; enum { kMaxAudioBufferQueueLength = 100 };
class CriticalSectionWrapper;
class FileRecorderImpl : public FileRecorder class FileRecorderImpl : public FileRecorder
{ {
public: public:
@ -103,6 +107,31 @@ private:
#ifdef WEBRTC_MODULE_UTILITY_VIDEO #ifdef WEBRTC_MODULE_UTILITY_VIDEO
class AudioFrameFileInfo
{
public:
AudioFrameFileInfo(const int8_t* audioData,
const uint16_t audioSize,
const uint16_t audioMS,
const TickTime& playoutTS)
: _audioData(), _audioSize(audioSize), _audioMS(audioMS),
_playoutTS(playoutTS)
{
if(audioSize > MAX_AUDIO_BUFFER_IN_BYTES)
{
assert(false);
_audioSize = 0;
return;
}
memcpy(_audioData, audioData, audioSize);
};
// TODO (hellner): either turn into a struct or provide get/set functions.
int8_t _audioData[MAX_AUDIO_BUFFER_IN_BYTES];
uint16_t _audioSize;
uint16_t _audioMS;
TickTime _playoutTS;
};
class AviRecorder : public FileRecorderImpl class AviRecorder : public FileRecorderImpl
{ {
public: public:
@ -126,6 +155,7 @@ protected:
uint16_t millisecondsOfData, uint16_t millisecondsOfData,
const TickTime* playoutTS); const TickTime* playoutTS);
private: private:
typedef std::list<AudioFrameFileInfo*> AudioInfoList;
static bool Run(ThreadObj threadObj); static bool Run(ThreadObj threadObj);
bool Process(); bool Process();
@ -141,7 +171,7 @@ private:
VideoCodec _videoCodecInst; VideoCodec _videoCodecInst;
bool _videoOnly; bool _videoOnly;
ListWrapper _audioFramesToWrite; AudioInfoList _audioFramesToWrite;
bool _firstAudioFrameReceived; bool _firstAudioFrameReceived;
VideoFramesQueue* _videoFramesQueue; VideoFramesQueue* _videoFramesQueue;

View File

@ -87,25 +87,23 @@ int32_t ProcessThreadImpl::Stop()
return 0; return 0;
} }
int32_t ProcessThreadImpl::RegisterModule(const Module* module) int32_t ProcessThreadImpl::RegisterModule(Module* module)
{ {
CriticalSectionScoped lock(_critSectModules); CriticalSectionScoped lock(_critSectModules);
// Only allow module to be registered once. // Only allow module to be registered once.
ListItem* item = _modules.First(); for (ModuleList::iterator iter = _modules.begin();
for(uint32_t i = 0; i < _modules.GetSize() && item; i++) iter != _modules.end(); ++iter) {
{ if(module == *iter)
if(module == item->GetItem())
{ {
return -1; return -1;
} }
item = _modules.Next(item);
} }
_modules.PushFront(module); _modules.push_front(module);
WEBRTC_TRACE(kTraceInfo, kTraceUtility, -1, WEBRTC_TRACE(kTraceInfo, kTraceUtility, -1,
"number of registered modules has increased to %d", "number of registered modules has increased to %d",
_modules.GetSize()); _modules.size());
// Wake the thread calling ProcessThreadImpl::Process() to update the // Wake the thread calling ProcessThreadImpl::Process() to update the
// waiting time. The waiting time for the just registered module may be // waiting time. The waiting time for the just registered module may be
// shorter than all other registered modules. // shorter than all other registered modules.
@ -116,19 +114,16 @@ int32_t ProcessThreadImpl::RegisterModule(const Module* module)
int32_t ProcessThreadImpl::DeRegisterModule(const Module* module) int32_t ProcessThreadImpl::DeRegisterModule(const Module* module)
{ {
CriticalSectionScoped lock(_critSectModules); CriticalSectionScoped lock(_critSectModules);
for (ModuleList::iterator iter = _modules.begin();
ListItem* item = _modules.First(); iter != _modules.end(); ++iter) {
for(uint32_t i = 0; i < _modules.GetSize() && item; i++) if(module == *iter)
{
if(module == item->GetItem())
{ {
int res = _modules.Erase(item); _modules.erase(iter);
WEBRTC_TRACE(kTraceInfo, kTraceUtility, -1, WEBRTC_TRACE(kTraceInfo, kTraceUtility, -1,
"number of registered modules has decreased to %d", "number of registered modules has decreased to %d",
_modules.GetSize()); _modules.size());
return res; return 0;
} }
item = _modules.Next(item);
} }
return -1; return -1;
} }
@ -145,16 +140,13 @@ bool ProcessThreadImpl::Process()
int32_t minTimeToNext = 100; int32_t minTimeToNext = 100;
{ {
CriticalSectionScoped lock(_critSectModules); CriticalSectionScoped lock(_critSectModules);
ListItem* item = _modules.First(); for (ModuleList::iterator iter = _modules.begin();
for(uint32_t i = 0; i < _modules.GetSize() && item; i++) iter != _modules.end(); ++iter) {
{ int32_t timeToNext = (*iter)->TimeUntilNextProcess();
int32_t timeToNext =
static_cast<Module*>(item->GetItem())->TimeUntilNextProcess();
if(minTimeToNext > timeToNext) if(minTimeToNext > timeToNext)
{ {
minTimeToNext = timeToNext; minTimeToNext = timeToNext;
} }
item = _modules.Next(item);
} }
} }
@ -172,16 +164,13 @@ bool ProcessThreadImpl::Process()
} }
{ {
CriticalSectionScoped lock(_critSectModules); CriticalSectionScoped lock(_critSectModules);
ListItem* item = _modules.First(); for (ModuleList::iterator iter = _modules.begin();
for(uint32_t i = 0; i < _modules.GetSize() && item; i++) iter != _modules.end(); ++iter) {
{ int32_t timeToNext = (*iter)->TimeUntilNextProcess();
int32_t timeToNext =
static_cast<Module*>(item->GetItem())->TimeUntilNextProcess();
if(timeToNext < 1) if(timeToNext < 1)
{ {
static_cast<Module*>(item->GetItem())->Process(); (*iter)->Process();
} }
item = _modules.Next(item);
} }
} }
return true; return true;

View File

@ -11,10 +11,11 @@
#ifndef WEBRTC_MODULES_UTILITY_SOURCE_PROCESS_THREAD_IMPL_H_ #ifndef WEBRTC_MODULES_UTILITY_SOURCE_PROCESS_THREAD_IMPL_H_
#define WEBRTC_MODULES_UTILITY_SOURCE_PROCESS_THREAD_IMPL_H_ #define WEBRTC_MODULES_UTILITY_SOURCE_PROCESS_THREAD_IMPL_H_
#include <list>
#include "webrtc/modules/utility/interface/process_thread.h" #include "webrtc/modules/utility/interface/process_thread.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h" #include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/list_wrapper.h"
#include "webrtc/system_wrappers/interface/thread_wrapper.h" #include "webrtc/system_wrappers/interface/thread_wrapper.h"
#include "webrtc/typedefs.h" #include "webrtc/typedefs.h"
@ -28,7 +29,7 @@ public:
virtual int32_t Start(); virtual int32_t Start();
virtual int32_t Stop(); virtual int32_t Stop();
virtual int32_t RegisterModule(const Module* module); virtual int32_t RegisterModule(Module* module);
virtual int32_t DeRegisterModule(const Module* module); virtual int32_t DeRegisterModule(const Module* module);
protected: protected:
@ -37,9 +38,10 @@ protected:
bool Process(); bool Process();
private: private:
typedef std::list<Module*> ModuleList;
EventWrapper& _timeEvent; EventWrapper& _timeEvent;
CriticalSectionWrapper* _critSectModules; CriticalSectionWrapper* _critSectModules;
ListWrapper _modules; ModuleList _modules;
ThreadWrapper* _thread; ThreadWrapper* _thread;
}; };
} // namespace webrtc } // namespace webrtc

View File

@ -21,36 +21,24 @@
namespace webrtc { namespace webrtc {
VideoFramesQueue::VideoFramesQueue() VideoFramesQueue::VideoFramesQueue()
: _incomingFrames(), : _renderDelayMs(10)
_renderDelayMs(10)
{ {
} }
VideoFramesQueue::~VideoFramesQueue() { VideoFramesQueue::~VideoFramesQueue() {
while (!_incomingFrames.Empty()) { for (FrameList::iterator iter = _incomingFrames.begin();
ListItem* item = _incomingFrames.First(); iter != _incomingFrames.end(); ++iter) {
if (item) { delete *iter;
I420VideoFrame* ptrFrame = static_cast<I420VideoFrame*>(item->GetItem());
assert(ptrFrame != NULL);
delete ptrFrame;
}
_incomingFrames.Erase(item);
} }
while (!_emptyFrames.Empty()) { for (FrameList::iterator iter = _emptyFrames.begin();
ListItem* item = _emptyFrames.First(); iter != _emptyFrames.end(); ++iter) {
if (item) { delete *iter;
I420VideoFrame* ptrFrame =
static_cast<I420VideoFrame*>(item->GetItem());
assert(ptrFrame != NULL);
delete ptrFrame;
}
_emptyFrames.Erase(item);
} }
} }
int32_t VideoFramesQueue::AddFrame(const I420VideoFrame& newFrame) { int32_t VideoFramesQueue::AddFrame(const I420VideoFrame& newFrame) {
if (newFrame.native_handle() != NULL) { if (newFrame.native_handle() != NULL) {
_incomingFrames.PushBack(new TextureVideoFrame( _incomingFrames.push_back(new TextureVideoFrame(
static_cast<NativeHandle*>(newFrame.native_handle()), static_cast<NativeHandle*>(newFrame.native_handle()),
newFrame.width(), newFrame.width(),
newFrame.height(), newFrame.height(),
@ -61,15 +49,12 @@ int32_t VideoFramesQueue::AddFrame(const I420VideoFrame& newFrame) {
I420VideoFrame* ptrFrameToAdd = NULL; I420VideoFrame* ptrFrameToAdd = NULL;
// Try to re-use a VideoFrame. Only allocate new memory if it is necessary. // Try to re-use a VideoFrame. Only allocate new memory if it is necessary.
if (!_emptyFrames.Empty()) { if (!_emptyFrames.empty()) {
ListItem* item = _emptyFrames.First(); ptrFrameToAdd = _emptyFrames.front();
if (item) { _emptyFrames.pop_front();
ptrFrameToAdd = static_cast<I420VideoFrame*>(item->GetItem());
_emptyFrames.Erase(item);
}
} }
if (!ptrFrameToAdd) { if (!ptrFrameToAdd) {
if (_emptyFrames.GetSize() + _incomingFrames.GetSize() > if (_emptyFrames.size() + _incomingFrames.size() >
KMaxNumberOfFrames) { KMaxNumberOfFrames) {
WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, -1, WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, -1,
"%s: too many frames, limit: %d", __FUNCTION__, "%s: too many frames, limit: %d", __FUNCTION__,
@ -79,17 +64,12 @@ int32_t VideoFramesQueue::AddFrame(const I420VideoFrame& newFrame) {
WEBRTC_TRACE(kTraceMemory, kTraceVideoRenderer, -1, WEBRTC_TRACE(kTraceMemory, kTraceVideoRenderer, -1,
"%s: allocating buffer %d", __FUNCTION__, "%s: allocating buffer %d", __FUNCTION__,
_emptyFrames.GetSize() + _incomingFrames.GetSize()); _emptyFrames.size() + _incomingFrames.size());
ptrFrameToAdd = new I420VideoFrame(); ptrFrameToAdd = new I420VideoFrame();
if (!ptrFrameToAdd) {
WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, -1,
"%s: could not create new frame for", __FUNCTION__);
return -1;
}
} }
ptrFrameToAdd->CopyFrame(newFrame); ptrFrameToAdd->CopyFrame(newFrame);
_incomingFrames.PushBack(ptrFrameToAdd); _incomingFrames.push_back(ptrFrameToAdd);
return 0; return 0;
} }
@ -99,20 +79,16 @@ int32_t VideoFramesQueue::AddFrame(const I420VideoFrame& newFrame) {
// Recycle all frames that are older than the most recent frame. // Recycle all frames that are older than the most recent frame.
I420VideoFrame* VideoFramesQueue::FrameToRecord() { I420VideoFrame* VideoFramesQueue::FrameToRecord() {
I420VideoFrame* ptrRenderFrame = NULL; I420VideoFrame* ptrRenderFrame = NULL;
ListItem* item = _incomingFrames.First(); for (FrameList::iterator iter = _incomingFrames.begin();
while(item) { iter != _incomingFrames.end(); ++iter) {
I420VideoFrame* ptrOldestFrameInList = I420VideoFrame* ptrOldestFrameInList = *iter;
static_cast<I420VideoFrame*>(item->GetItem());
if (ptrOldestFrameInList->render_time_ms() <= if (ptrOldestFrameInList->render_time_ms() <=
TickTime::MillisecondTimestamp() + _renderDelayMs) { TickTime::MillisecondTimestamp() + _renderDelayMs) {
if (ptrRenderFrame) { // List is traversed beginning to end. If ptrRenderFrame is not
// List is traversed beginning to end. If ptrRenderFrame is not // NULL it must be the first, and thus oldest, VideoFrame in the
// NULL it must be the first, and thus oldest, VideoFrame in the // queue. It can be recycled.
// queue. It can be recycled. ReturnFrame(ptrRenderFrame);
ReturnFrame(ptrRenderFrame); iter = _incomingFrames.erase(iter);
_incomingFrames.PopFront();
}
item = _incomingFrames.Next(item);
ptrRenderFrame = ptrOldestFrameInList; ptrRenderFrame = ptrOldestFrameInList;
} else { } else {
// All VideoFrames following this one will be even newer. No match // All VideoFrames following this one will be even newer. No match
@ -131,7 +107,7 @@ int32_t VideoFramesQueue::ReturnFrame(I420VideoFrame* ptrOldFrame) {
ptrOldFrame->set_height(0); ptrOldFrame->set_height(0);
ptrOldFrame->set_render_time_ms(0); ptrOldFrame->set_render_time_ms(0);
ptrOldFrame->ResetSize(); ptrOldFrame->ResetSize();
_emptyFrames.PushBack(ptrOldFrame); _emptyFrames.push_back(ptrOldFrame);
} else { } else {
delete ptrOldFrame; delete ptrOldFrame;
} }

View File

@ -13,9 +13,10 @@
#ifdef WEBRTC_MODULE_UTILITY_VIDEO #ifdef WEBRTC_MODULE_UTILITY_VIDEO
#include <list>
#include "webrtc/common_video/interface/i420_video_frame.h" #include "webrtc/common_video/interface/i420_video_frame.h"
#include "webrtc/engine_configurations.h" #include "webrtc/engine_configurations.h"
#include "webrtc/system_wrappers/interface/list_wrapper.h"
#include "webrtc/typedefs.h" #include "webrtc/typedefs.h"
namespace webrtc { namespace webrtc {
@ -42,6 +43,7 @@ class VideoFramesQueue {
int32_t ReturnFrame(I420VideoFrame* ptrOldFrame); int32_t ReturnFrame(I420VideoFrame* ptrOldFrame);
private: private:
typedef std::list<I420VideoFrame*> FrameList;
// Don't allow the buffer to expand beyond KMaxNumberOfFrames VideoFrames. // Don't allow the buffer to expand beyond KMaxNumberOfFrames VideoFrames.
// 300 frames correspond to 10 seconds worth of frames at 30 fps. // 300 frames correspond to 10 seconds worth of frames at 30 fps.
enum {KMaxNumberOfFrames = 300}; enum {KMaxNumberOfFrames = 300};
@ -49,9 +51,9 @@ class VideoFramesQueue {
// List of VideoFrame pointers. The list is sorted in the order of when the // List of VideoFrame pointers. The list is sorted in the order of when the
// VideoFrame was inserted into the list. The first VideoFrame in the list // VideoFrame was inserted into the list. The first VideoFrame in the list
// was inserted first. // was inserted first.
ListWrapper _incomingFrames; FrameList _incomingFrames;
// A list of frames that are free to be re-used. // A list of frames that are free to be re-used.
ListWrapper _emptyFrames; FrameList _emptyFrames;
// Estimated render delay. // Estimated render delay.
uint32_t _renderDelayMs; uint32_t _renderDelayMs;

View File

@ -8,7 +8,7 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include "webrtc/modules/video_render//video_render_frames.h" #include "webrtc/modules/video_render/video_render_frames.h"
#include <assert.h> #include <assert.h>
@ -19,13 +19,12 @@
namespace webrtc { namespace webrtc {
const int32_t KEventMaxWaitTimeMs = 200; const uint32_t KEventMaxWaitTimeMs = 200;
const uint32_t kMinRenderDelayMs = 10; const uint32_t kMinRenderDelayMs = 10;
const uint32_t kMaxRenderDelayMs= 500; const uint32_t kMaxRenderDelayMs= 500;
VideoRenderFrames::VideoRenderFrames() VideoRenderFrames::VideoRenderFrames()
: incoming_frames_(), : render_delay_ms_(10) {
render_delay_ms_(10) {
} }
VideoRenderFrames::~VideoRenderFrames() { VideoRenderFrames::~VideoRenderFrames() {
@ -37,7 +36,7 @@ int32_t VideoRenderFrames::AddFrame(I420VideoFrame* new_frame) {
// Drop old frames only when there are other frames in the queue, otherwise, a // Drop old frames only when there are other frames in the queue, otherwise, a
// really slow system never renders any frames. // really slow system never renders any frames.
if (!incoming_frames_.Empty() && if (!incoming_frames_.empty() &&
new_frame->render_time_ms() + KOldRenderTimestampMS < time_now) { new_frame->render_time_ms() + KOldRenderTimestampMS < time_now) {
WEBRTC_TRACE(kTraceWarning, WEBRTC_TRACE(kTraceWarning,
kTraceVideoRenderer, kTraceVideoRenderer,
@ -56,26 +55,23 @@ int32_t VideoRenderFrames::AddFrame(I420VideoFrame* new_frame) {
} }
if (new_frame->native_handle() != NULL) { if (new_frame->native_handle() != NULL) {
incoming_frames_.PushBack(new TextureVideoFrame( incoming_frames_.push_back(new TextureVideoFrame(
static_cast<NativeHandle*>(new_frame->native_handle()), static_cast<NativeHandle*>(new_frame->native_handle()),
new_frame->width(), new_frame->width(),
new_frame->height(), new_frame->height(),
new_frame->timestamp(), new_frame->timestamp(),
new_frame->render_time_ms())); new_frame->render_time_ms()));
return incoming_frames_.GetSize(); return static_cast<int32_t>(incoming_frames_.size());
} }
// Get an empty frame // Get an empty frame
I420VideoFrame* frame_to_add = NULL; I420VideoFrame* frame_to_add = NULL;
if (!empty_frames_.Empty()) { if (!empty_frames_.empty()) {
ListItem* item = empty_frames_.First(); frame_to_add = empty_frames_.front();
if (item) { empty_frames_.pop_front();
frame_to_add = static_cast<I420VideoFrame*>(item->GetItem());
empty_frames_.Erase(item);
}
} }
if (!frame_to_add) { if (!frame_to_add) {
if (empty_frames_.GetSize() + incoming_frames_.GetSize() > if (empty_frames_.size() + incoming_frames_.size() >
KMaxNumberOfFrames) { KMaxNumberOfFrames) {
// Already allocated too many frames. // Already allocated too many frames.
WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer,
@ -87,7 +83,7 @@ int32_t VideoRenderFrames::AddFrame(I420VideoFrame* new_frame) {
// Allocate new memory. // Allocate new memory.
WEBRTC_TRACE(kTraceMemory, kTraceVideoRenderer, -1, WEBRTC_TRACE(kTraceMemory, kTraceVideoRenderer, -1,
"%s: allocating buffer %d", __FUNCTION__, "%s: allocating buffer %d", __FUNCTION__,
empty_frames_.GetSize() + incoming_frames_.GetSize()); empty_frames_.size() + incoming_frames_.size());
frame_to_add = new I420VideoFrame(); frame_to_add = new I420VideoFrame();
if (!frame_to_add) { if (!frame_to_add) {
@ -104,33 +100,28 @@ int32_t VideoRenderFrames::AddFrame(I420VideoFrame* new_frame) {
// TODO(mflodman) Change this! // TODO(mflodman) Change this!
// Remove const ness. Copying will be costly. // Remove const ness. Copying will be costly.
frame_to_add->SwapFrame(new_frame); frame_to_add->SwapFrame(new_frame);
incoming_frames_.PushBack(frame_to_add); incoming_frames_.push_back(frame_to_add);
return incoming_frames_.GetSize(); return static_cast<int32_t>(incoming_frames_.size());
} }
I420VideoFrame* VideoRenderFrames::FrameToRender() { I420VideoFrame* VideoRenderFrames::FrameToRender() {
I420VideoFrame* render_frame = NULL; I420VideoFrame* render_frame = NULL;
while (!incoming_frames_.Empty()) { FrameList::iterator iter = incoming_frames_.begin();
ListItem* item = incoming_frames_.First(); while(iter != incoming_frames_.end()) {
if (item) { I420VideoFrame* oldest_frame_in_list = *iter;
I420VideoFrame* oldest_frame_in_list = if (oldest_frame_in_list->render_time_ms() <=
static_cast<I420VideoFrame*>(item->GetItem()); TickTime::MillisecondTimestamp() + render_delay_ms_) {
if (oldest_frame_in_list->render_time_ms() <= // This is the oldest one so far and it's OK to render.
TickTime::MillisecondTimestamp() + render_delay_ms_) { if (render_frame) {
// This is the oldest one so far and it's OK to render. // This one is older than the newly found frame, remove this one.
if (render_frame) { ReturnFrame(render_frame);
// This one is older than the newly found frame, remove this one.
ReturnFrame(render_frame);
}
render_frame = oldest_frame_in_list;
incoming_frames_.Erase(item);
} else {
// We can't release this one yet, we're done here.
break;
} }
render_frame = oldest_frame_in_list;
iter = incoming_frames_.erase(iter);
} else { } else {
assert(false); // We can't release this one yet, we're done here.
break;
} }
} }
return render_frame; return render_frame;
@ -142,7 +133,7 @@ int32_t VideoRenderFrames::ReturnFrame(I420VideoFrame* old_frame) {
old_frame->ResetSize(); old_frame->ResetSize();
old_frame->set_timestamp(0); old_frame->set_timestamp(0);
old_frame->set_render_time_ms(0); old_frame->set_render_time_ms(0);
empty_frames_.PushBack(old_frame); empty_frames_.push_back(old_frame);
} else { } else {
delete old_frame; delete old_frame;
} }
@ -150,40 +141,29 @@ int32_t VideoRenderFrames::ReturnFrame(I420VideoFrame* old_frame) {
} }
int32_t VideoRenderFrames::ReleaseAllFrames() { int32_t VideoRenderFrames::ReleaseAllFrames() {
while (!incoming_frames_.Empty()) { for (FrameList::iterator iter = incoming_frames_.begin();
ListItem* item = incoming_frames_.First(); iter != incoming_frames_.end(); ++iter) {
if (item) { delete *iter;
I420VideoFrame* frame = static_cast<I420VideoFrame*>(item->GetItem());
assert(frame != NULL);
delete frame;
}
incoming_frames_.Erase(item);
} }
while (!empty_frames_.Empty()) { incoming_frames_.clear();
ListItem* item = empty_frames_.First();
if (item) { for (FrameList::iterator iter = empty_frames_.begin();
I420VideoFrame* frame = static_cast<I420VideoFrame*>(item->GetItem()); iter != empty_frames_.end(); ++iter) {
assert(frame != NULL); delete *iter;
delete frame;
}
empty_frames_.Erase(item);
} }
empty_frames_.clear();
return 0; return 0;
} }
uint32_t VideoRenderFrames::TimeToNextFrameRelease() { uint32_t VideoRenderFrames::TimeToNextFrameRelease() {
int64_t time_to_release = 0; if (incoming_frames_.empty()) {
ListItem* item = incoming_frames_.First(); return KEventMaxWaitTimeMs;
if (item) { }
I420VideoFrame* oldest_frame = I420VideoFrame* oldest_frame = incoming_frames_.front();
static_cast<I420VideoFrame*>(item->GetItem()); int64_t time_to_release = oldest_frame->render_time_ms() - render_delay_ms_
time_to_release = oldest_frame->render_time_ms() - render_delay_ms_ - TickTime::MillisecondTimestamp();
- TickTime::MillisecondTimestamp(); if (time_to_release < 0) {
if (time_to_release < 0) { time_to_release = 0;
time_to_release = 0;
}
} else {
time_to_release = KEventMaxWaitTimeMs;
} }
return static_cast<uint32_t>(time_to_release); return static_cast<uint32_t>(time_to_release);
} }

View File

@ -11,8 +11,9 @@
#ifndef WEBRTC_MODULES_VIDEO_RENDER_MAIN_SOURCE_VIDEO_RENDER_FRAMES_H_ // NOLINT #ifndef WEBRTC_MODULES_VIDEO_RENDER_MAIN_SOURCE_VIDEO_RENDER_FRAMES_H_ // NOLINT
#define WEBRTC_MODULES_VIDEO_RENDER_MAIN_SOURCE_VIDEO_RENDER_FRAMES_H_ // NOLINT #define WEBRTC_MODULES_VIDEO_RENDER_MAIN_SOURCE_VIDEO_RENDER_FRAMES_H_ // NOLINT
#include <list>
#include "webrtc/modules/video_render/include/video_render.h" #include "webrtc/modules/video_render/include/video_render.h"
#include "webrtc/system_wrappers/interface/list_wrapper.h"
namespace webrtc { namespace webrtc {
@ -41,6 +42,8 @@ class VideoRenderFrames {
int32_t SetRenderDelay(const uint32_t render_delay); int32_t SetRenderDelay(const uint32_t render_delay);
private: private:
typedef std::list<I420VideoFrame*> FrameList;
// 10 seconds for 30 fps. // 10 seconds for 30 fps.
enum { KMaxNumberOfFrames = 300 }; enum { KMaxNumberOfFrames = 300 };
// Don't render frames with timestamp older than 500ms from now. // Don't render frames with timestamp older than 500ms from now.
@ -49,9 +52,9 @@ class VideoRenderFrames {
enum { KFutureRenderTimestampMS = 10000 }; enum { KFutureRenderTimestampMS = 10000 };
// Sorted list with framed to be rendered, oldest first. // Sorted list with framed to be rendered, oldest first.
ListWrapper incoming_frames_; FrameList incoming_frames_;
// Empty frames. // Empty frames.
ListWrapper empty_frames_; FrameList empty_frames_;
// Estimated delay from a frame is released until it's rendered. // Estimated delay from a frame is released until it's rendered.
uint32_t render_delay_ms_; uint32_t render_delay_ms_;

View File

@ -65,14 +65,11 @@ UdpSocket2ManagerWindows::~UdpSocket2ManagerWindows()
} }
StopWorkerThreads(); StopWorkerThreads();
// All threads are stopped. Safe to delete them. for (WorkerList::iterator iter = _workerThreadsList.begin();
ListItem* pItem = NULL; iter != _workerThreadsList.end(); ++iter) {
while((pItem = _workerThreadsList.First()) != NULL) delete *iter;
{
delete static_cast<UdpSocket2WorkerWindows*>(pItem->GetItem());
_workerThreadsList.PopFront();
} }
_workerThreadsList.clear();
_ioContextPool.Free(); _ioContextPool.Free();
_numOfActiveManagers--; _numOfActiveManagers--;
@ -134,14 +131,10 @@ bool UdpSocket2ManagerWindows::Start()
// Start worker threads. // Start worker threads.
_stopped = false; _stopped = false;
int32_t error = 0; int32_t error = 0;
ListItem* pItem = _workerThreadsList.First(); for (WorkerList::iterator iter = _workerThreadsList.begin();
UdpSocket2WorkerWindows* pWorker; iter != _workerThreadsList.end() && !error; ++iter) {
while(pItem != NULL && !error) if(!(*iter)->Start())
{ error = 1;
pWorker = (UdpSocket2WorkerWindows*)pItem->GetItem();
if(!pWorker->Start())
error = 1;
pItem = _workerThreadsList.Next(pItem);
} }
if(error) if(error)
{ {
@ -194,7 +187,7 @@ bool UdpSocket2ManagerWindows::StartWorkerThreads()
delete pWorker; delete pWorker;
break; break;
} }
_workerThreadsList.PushFront(pWorker); _workerThreadsList.push_front(pWorker);
i++; i++;
} }
if(error) if(error)
@ -207,12 +200,11 @@ bool UdpSocket2ManagerWindows::StartWorkerThreads()
"creating work threads", "creating work threads",
_managerNumber); _managerNumber);
// Delete worker threads. // Delete worker threads.
ListItem* pItem = NULL; for (WorkerList::iterator iter = _workerThreadsList.begin();
while((pItem = _workerThreadsList.First()) != NULL) iter != _workerThreadsList.end(); ++iter) {
{ delete *iter;
delete static_cast<UdpSocket2WorkerWindows*>(pItem->GetItem());
_workerThreadsList.PopFront();
} }
_workerThreadsList.clear();
_pCrit->Leave(); _pCrit->Leave();
return false; return false;
} }
@ -281,38 +273,30 @@ bool UdpSocket2ManagerWindows::StopWorkerThreads()
threadsStoped, numActicve Sockets=%d", threadsStoped, numActicve Sockets=%d",
_managerNumber, _managerNumber,
_numActiveSockets); _numActiveSockets);
UdpSocket2WorkerWindows* pWorker;
ListItem* pItem = _workerThreadsList.First();
// Set worker threads to not alive so that they will stop calling // Set worker threads to not alive so that they will stop calling
// UdpSocket2WorkerWindows::Run(). // UdpSocket2WorkerWindows::Run().
while(pItem != NULL) for (WorkerList::iterator iter = _workerThreadsList.begin();
{ iter != _workerThreadsList.end(); ++iter) {
pWorker = (UdpSocket2WorkerWindows*)pItem->GetItem(); (*iter)->SetNotAlive();
pWorker->SetNotAlive();
pItem = _workerThreadsList.Next(pItem);
} }
// Release all threads waiting for GetQueuedCompletionStatus(..). // Release all threads waiting for GetQueuedCompletionStatus(..).
if(_ioCompletionHandle) if(_ioCompletionHandle)
{ {
uint32_t i = 0; uint32_t i = 0;
for(i = 0; i < _workerThreadsList.GetSize(); i++) for(i = 0; i < _workerThreadsList.size(); i++)
{ {
PostQueuedCompletionStatus(_ioCompletionHandle, 0 ,0 , NULL); PostQueuedCompletionStatus(_ioCompletionHandle, 0 ,0 , NULL);
} }
} }
pItem = _workerThreadsList.First(); for (WorkerList::iterator iter = _workerThreadsList.begin();
iter != _workerThreadsList.end(); ++iter) {
while(pItem != NULL) if((*iter)->Stop() == false)
{
pWorker = (UdpSocket2WorkerWindows*)pItem->GetItem();
if(pWorker->Stop() == false)
{ {
error = -1; error = -1;
WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1, WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1,
"failed to stop worker thread"); "failed to stop worker thread");
} }
pItem = _workerThreadsList.Next(pItem);
} }
if(error) if(error)

View File

@ -12,11 +12,11 @@
#define WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET2_MANAGER_WINDOWS_H_ #define WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET2_MANAGER_WINDOWS_H_
#include <winsock2.h> #include <winsock2.h>
#include <list>
#include "webrtc/system_wrappers/interface/atomic32.h" #include "webrtc/system_wrappers/interface/atomic32.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h" #include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/list_wrapper.h"
#include "webrtc/system_wrappers/interface/thread_wrapper.h" #include "webrtc/system_wrappers/interface/thread_wrapper.h"
#include "webrtc/test/channel_transport/udp_socket2_win.h" #include "webrtc/test/channel_transport/udp_socket2_win.h"
#include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h" #include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
@ -91,6 +91,27 @@ private:
Atomic32 _inUse; Atomic32 _inUse;
}; };
class UdpSocket2WorkerWindows
{
public:
UdpSocket2WorkerWindows(HANDLE ioCompletionHandle);
virtual ~UdpSocket2WorkerWindows();
virtual bool Start();
virtual bool Stop();
virtual int32_t Init();
virtual void SetNotAlive();
protected:
static bool Run(ThreadObj obj);
bool Process();
private:
HANDLE _ioCompletionHandle;
ThreadWrapper*_pThread;
static int32_t _numOfWorkers;
int32_t _workerNumber;
volatile bool _stop;
bool _init;
};
class UdpSocket2ManagerWindows : public UdpSocketManager class UdpSocket2ManagerWindows : public UdpSocketManager
{ {
@ -115,6 +136,7 @@ public:
int32_t PushIoContext(PerIoContext* pIoContext); int32_t PushIoContext(PerIoContext* pIoContext);
private: private:
typedef std::list<UdpSocket2WorkerWindows*> WorkerList;
bool StopWorkerThreads(); bool StopWorkerThreads();
bool StartWorkerThreads(); bool StartWorkerThreads();
bool AddSocketPrv(UdpSocket2Windows* s); bool AddSocketPrv(UdpSocket2Windows* s);
@ -129,35 +151,13 @@ private:
volatile bool _stopped; volatile bool _stopped;
bool _init; bool _init;
int32_t _numActiveSockets; int32_t _numActiveSockets;
ListWrapper _workerThreadsList; WorkerList _workerThreadsList;
EventWrapper* _event; EventWrapper* _event;
HANDLE _ioCompletionHandle; HANDLE _ioCompletionHandle;
IoContextPool _ioContextPool; IoContextPool _ioContextPool;
}; };
class UdpSocket2WorkerWindows
{
public:
UdpSocket2WorkerWindows(HANDLE ioCompletionHandle);
virtual ~UdpSocket2WorkerWindows();
virtual bool Start();
virtual bool Stop();
virtual int32_t Init();
virtual void SetNotAlive();
protected:
static bool Run(ThreadObj obj);
bool Process();
private:
HANDLE _ioCompletionHandle;
ThreadWrapper*_pThread;
static int32_t _numOfWorkers;
int32_t _workerNumber;
volatile bool _stop;
bool _init;
};
} // namespace test } // namespace test
} // namespace webrtc } // namespace webrtc

View File

@ -23,7 +23,6 @@
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h" #include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h" #include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/list_wrapper.h"
#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h" #include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
#include "webrtc/system_wrappers/interface/trace.h" #include "webrtc/system_wrappers/interface/trace.h"
#include "webrtc/test/channel_transport/udp_socket2_manager_win.h" #include "webrtc/test/channel_transport/udp_socket2_manager_win.h"

View File

@ -322,7 +322,7 @@ bool UdpSocketManagerPosixImpl::AddSocket(UdpSocketWrapper* s)
return false; return false;
} }
_critSectList->Enter(); _critSectList->Enter();
_addList.PushBack(s); _addList.push_back(s);
_critSectList->Leave(); _critSectList->Leave();
return true; return true;
} }
@ -333,26 +333,24 @@ bool UdpSocketManagerPosixImpl::RemoveSocket(UdpSocketWrapper* s)
_critSectList->Enter(); _critSectList->Enter();
// If the socket is in the add list it's safe to remove and delete it. // If the socket is in the add list it's safe to remove and delete it.
ListItem* addListItem = _addList.First(); for (SocketList::iterator iter = _addList.begin();
while(addListItem) iter != _addList.end(); ++iter) {
{ UdpSocketPosix* addSocket = static_cast<UdpSocketPosix*>(*iter);
UdpSocketPosix* addSocket = (UdpSocketPosix*)addListItem->GetItem();
unsigned int addFD = addSocket->GetFd(); unsigned int addFD = addSocket->GetFd();
unsigned int removeFD = static_cast<UdpSocketPosix*>(s)->GetFd(); unsigned int removeFD = static_cast<UdpSocketPosix*>(s)->GetFd();
if(removeFD == addFD) if(removeFD == addFD)
{ {
_removeList.PushBack(removeFD); _removeList.push_back(removeFD);
_critSectList->Leave(); _critSectList->Leave();
return true; return true;
} }
addListItem = _addList.Next(addListItem);
} }
// Checking the socket map is safe since all Erase and Insert calls to this // Checking the socket map is safe since all Erase and Insert calls to this
// map are also protected by _critSectList. // map are also protected by _critSectList.
if (_socketMap.find(static_cast<UdpSocketPosix*>(s)->GetFd()) != if (_socketMap.find(static_cast<UdpSocketPosix*>(s)->GetFd()) !=
_socketMap.end()) { _socketMap.end()) {
_removeList.PushBack(static_cast<UdpSocketPosix*>(s)->GetFd()); _removeList.push_back(static_cast<UdpSocketPosix*>(s)->GetFd());
_critSectList->Leave(); _critSectList->Leave();
return true; return true;
} }
@ -364,25 +362,23 @@ void UdpSocketManagerPosixImpl::UpdateSocketMap()
{ {
// Remove items in remove list. // Remove items in remove list.
_critSectList->Enter(); _critSectList->Enter();
while(!_removeList.Empty()) for (FdList::iterator iter = _removeList.begin();
{ iter != _removeList.end(); ++iter) {
UdpSocketPosix* deleteSocket = NULL; UdpSocketPosix* deleteSocket = NULL;
SOCKET removeFD = _removeList.First()->GetUnsignedItem(); SOCKET removeFD = *iter;
// If the socket is in the add list it hasn't been added to the socket // If the socket is in the add list it hasn't been added to the socket
// map yet. Just remove the socket from the add list. // map yet. Just remove the socket from the add list.
ListItem* addListItem = _addList.First(); for (SocketList::iterator iter = _addList.begin();
while(addListItem) iter != _addList.end(); ++iter) {
{ UdpSocketPosix* addSocket = static_cast<UdpSocketPosix*>(*iter);
UdpSocketPosix* addSocket = (UdpSocketPosix*)addListItem->GetItem();
SOCKET addFD = addSocket->GetFd(); SOCKET addFD = addSocket->GetFd();
if(removeFD == addFD) if(removeFD == addFD)
{ {
deleteSocket = addSocket; deleteSocket = addSocket;
_addList.Erase(addListItem); _addList.erase(iter);
break; break;
} }
addListItem = _addList.Next(addListItem);
} }
// Find and remove socket from _socketMap. // Find and remove socket from _socketMap.
@ -398,19 +394,18 @@ void UdpSocketManagerPosixImpl::UpdateSocketMap()
deleteSocket->ReadyForDeletion(); deleteSocket->ReadyForDeletion();
delete deleteSocket; delete deleteSocket;
} }
_removeList.PopFront();
} }
_removeList.clear();
// Add sockets from add list. // Add sockets from add list.
while(!_addList.Empty()) for (SocketList::iterator iter = _addList.begin();
{ iter != _addList.end(); ++iter) {
UdpSocketPosix* s = UdpSocketPosix* s = static_cast<UdpSocketPosix*>(*iter);
static_cast<UdpSocketPosix*>(_addList.First()->GetItem());
if(s) { if(s) {
_socketMap[s->GetFd()] = s; _socketMap[s->GetFd()] = s;
} }
_addList.PopFront();
} }
_addList.clear();
_critSectList->Leave(); _critSectList->Leave();
} }

View File

@ -14,10 +14,10 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <list>
#include <map> #include <map>
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/list_wrapper.h"
#include "webrtc/system_wrappers/interface/thread_wrapper.h" #include "webrtc/system_wrappers/interface/thread_wrapper.h"
#include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h" #include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
#include "webrtc/test/channel_transport/udp_socket_wrapper.h" #include "webrtc/test/channel_transport/udp_socket_wrapper.h"
@ -74,14 +74,16 @@ protected:
void UpdateSocketMap(); void UpdateSocketMap();
private: private:
typedef std::list<UdpSocketWrapper*> SocketList;
typedef std::list<SOCKET> FdList;
ThreadWrapper* _thread; ThreadWrapper* _thread;
CriticalSectionWrapper* _critSectList; CriticalSectionWrapper* _critSectList;
fd_set _readFds; fd_set _readFds;
std::map<SOCKET, UdpSocketPosix*> _socketMap; std::map<SOCKET, UdpSocketPosix*> _socketMap;
ListWrapper _addList; SocketList _addList;
ListWrapper _removeList; FdList _removeList;
}; };
} // namespace test } // namespace test

View File

@ -30,7 +30,7 @@ class TestProcessThread : public ProcessThread {
~TestProcessThread() {} ~TestProcessThread() {}
virtual int32_t Start() { return 0; } virtual int32_t Start() { return 0; }
virtual int32_t Stop() { return 0; } virtual int32_t Stop() { return 0; }
virtual int32_t RegisterModule(const Module* module) { return 0; } virtual int32_t RegisterModule(Module* module) { return 0; }
virtual int32_t DeRegisterModule(const Module* module) { return 0; } virtual int32_t DeRegisterModule(const Module* module) { return 0; }
}; };

View File

@ -35,7 +35,7 @@ class TestProcessThread : public ProcessThread {
~TestProcessThread() {} ~TestProcessThread() {}
virtual int32_t Start() { return 0; } virtual int32_t Start() { return 0; }
virtual int32_t Stop() { return 0; } virtual int32_t Stop() { return 0; }
virtual int32_t RegisterModule(const Module* module) { return 0; } virtual int32_t RegisterModule(Module* module) { return 0; }
virtual int32_t DeRegisterModule(const Module* module) { return 0; } virtual int32_t DeRegisterModule(const Module* module) { return 0; }
}; };

View File

@ -65,7 +65,7 @@ int32_t ViERenderManager::RegisterVideoRenderModule(
} }
// Register module. // Register module.
render_list_.PushBack(static_cast<void*>(render_module)); render_list_.push_back(render_module);
use_external_render_module_ = true; use_external_render_module_ = true;
return 0; return 0;
} }
@ -81,24 +81,17 @@ int32_t ViERenderManager::DeRegisterVideoRenderModule(
return -1; return -1;
} }
// Erase the render module from the map. for (RenderList::iterator iter = render_list_.begin();
ListItem* list_item = NULL; iter != render_list_.end(); ++iter) {
bool found = false; if (render_module == *iter) {
for (list_item = render_list_.First(); list_item != NULL; // We've found our renderer. Erase the render module from the map.
list_item = render_list_.Next(list_item)) { render_list_.erase(iter);
if (render_module == static_cast<VideoRender*>(list_item->GetItem())) { return 0;
// We've found our renderer.
render_list_.Erase(list_item);
found = true;
break;
} }
} }
if (!found) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_), "Module not registered");
"Module not registered"); return -1;
return -1;
}
return 0;
} }
ViERenderer* ViERenderManager::AddRenderStream(const int32_t render_id, ViERenderer* ViERenderManager::AddRenderStream(const int32_t render_id,
@ -129,7 +122,7 @@ ViERenderer* ViERenderManager::AddRenderStream(const int32_t render_id,
"Could not create new render module"); "Could not create new render module");
return NULL; return NULL;
} }
render_list_.PushBack(static_cast<void*>(render_module)); render_list_.push_back(render_module);
} }
ViERenderer* vie_renderer = ViERenderer::CreateViERenderer(render_id, ViERenderer* vie_renderer = ViERenderer::CreateViERenderer(render_id,
@ -176,12 +169,11 @@ int32_t ViERenderManager::RemoveRenderStream(
if (!use_external_render_module_ && if (!use_external_render_module_ &&
renderer.GetNumIncomingRenderStreams() == 0) { renderer.GetNumIncomingRenderStreams() == 0) {
// Erase the render module from the map. // Erase the render module from the map.
ListItem* list_item = NULL; for (RenderList::iterator iter = render_list_.begin();
for (list_item = render_list_.First(); list_item != NULL; iter != render_list_.end(); ++iter) {
list_item = render_list_.Next(list_item)) { if (&renderer == *iter) {
if (&renderer == static_cast<VideoRender*>(list_item->GetItem())) {
// We've found our renderer. // We've found our renderer.
render_list_.Erase(list_item); render_list_.erase(iter);
break; break;
} }
} }
@ -192,21 +184,14 @@ int32_t ViERenderManager::RemoveRenderStream(
} }
VideoRender* ViERenderManager::FindRenderModule(void* window) { VideoRender* ViERenderManager::FindRenderModule(void* window) {
VideoRender* renderer = NULL; for (RenderList::iterator iter = render_list_.begin();
ListItem* list_item = NULL; iter != render_list_.end(); ++iter) {
for (list_item = render_list_.First(); list_item != NULL; if ((*iter)->Window() == window) {
list_item = render_list_.Next(list_item)) {
renderer = static_cast<VideoRender*>(list_item->GetItem());
if (renderer == NULL) {
break;
}
if (renderer->Window() == window) {
// We've found the render module. // We've found the render module.
break; return *iter;
} }
renderer = NULL;
} }
return renderer; return NULL;
} }
ViERenderer* ViERenderManager::ViERenderPtr(int32_t render_id) const { ViERenderer* ViERenderManager::ViERenderPtr(int32_t render_id) const {

View File

@ -11,9 +11,9 @@
#ifndef WEBRTC_VIDEO_ENGINE_VIE_RENDER_MANAGER_H_ #ifndef WEBRTC_VIDEO_ENGINE_VIE_RENDER_MANAGER_H_
#define WEBRTC_VIDEO_ENGINE_VIE_RENDER_MANAGER_H_ #define WEBRTC_VIDEO_ENGINE_VIE_RENDER_MANAGER_H_
#include <list>
#include <map> #include <map>
#include "webrtc/system_wrappers/interface/list_wrapper.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h" #include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/typedefs.h" #include "webrtc/typedefs.h"
#include "webrtc/video_engine/vie_manager_base.h" #include "webrtc/video_engine/vie_manager_base.h"
@ -46,6 +46,7 @@ class ViERenderManager : private ViEManagerBase {
int32_t RemoveRenderStream(int32_t render_id); int32_t RemoveRenderStream(int32_t render_id);
private: private:
typedef std::list<VideoRender*> RenderList;
// Returns a pointer to the render module if it exists in the render list. // Returns a pointer to the render module if it exists in the render list.
// Assumed protected. // Assumed protected.
VideoRender* FindRenderModule(void* window); VideoRender* FindRenderModule(void* window);
@ -58,8 +59,7 @@ class ViERenderManager : private ViEManagerBase {
// Protected by ViEManagerBase. // Protected by ViEManagerBase.
typedef std::map<int32_t, ViERenderer*> RendererMap; typedef std::map<int32_t, ViERenderer*> RendererMap;
RendererMap stream_to_vie_renderer_; RendererMap stream_to_vie_renderer_;
RenderList render_list_;
ListWrapper render_list_;
bool use_external_render_module_; bool use_external_render_module_;
}; };