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:
parent
d0b436a935
commit
79cf3acc79
@ -12,9 +12,9 @@
|
||||
#define WEBRTC_MODULES_AUDIO_CONFERENCE_MIXER_SOURCE_MEMORY_POOL_GENERIC_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <list>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/list_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -40,7 +40,7 @@ private:
|
||||
|
||||
bool _terminate;
|
||||
|
||||
ListWrapper _memoryPool;
|
||||
std::list<MemoryType*> _memoryPool;
|
||||
|
||||
uint32_t _initialPoolSize;
|
||||
uint32_t _createdMemory;
|
||||
@ -51,7 +51,6 @@ template<class MemoryType>
|
||||
MemoryPoolImpl<MemoryType>::MemoryPoolImpl(int32_t initialPoolSize)
|
||||
: _crit(CriticalSectionWrapper::CreateCriticalSection()),
|
||||
_terminate(false),
|
||||
_memoryPool(),
|
||||
_initialPoolSize(initialPoolSize),
|
||||
_createdMemory(0),
|
||||
_outstandingMemory(0)
|
||||
@ -76,20 +75,17 @@ int32_t MemoryPoolImpl<MemoryType>::PopMemory(MemoryType*& memory)
|
||||
memory = NULL;
|
||||
return -1;
|
||||
}
|
||||
ListItem* item = _memoryPool.First();
|
||||
if(item == NULL)
|
||||
{
|
||||
if (_memoryPool.empty()) {
|
||||
// _memoryPool empty create new memory.
|
||||
CreateMemory(_initialPoolSize);
|
||||
item = _memoryPool.First();
|
||||
if(item == NULL)
|
||||
if(_memoryPool.empty())
|
||||
{
|
||||
memory = NULL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
memory = static_cast<MemoryType*>(item->GetItem());
|
||||
_memoryPool.Erase(item);
|
||||
memory = _memoryPool.front();
|
||||
_memoryPool.pop_front();
|
||||
_outstandingMemory++;
|
||||
return 0;
|
||||
}
|
||||
@ -103,7 +99,7 @@ int32_t MemoryPoolImpl<MemoryType>::PushMemory(MemoryType*& memory)
|
||||
}
|
||||
CriticalSectionScoped cs(_crit);
|
||||
_outstandingMemory--;
|
||||
if(_memoryPool.GetSize() > (_initialPoolSize << 1))
|
||||
if(_memoryPool.size() > (_initialPoolSize << 1))
|
||||
{
|
||||
// Reclaim memory if less than half of the pool is unused.
|
||||
_createdMemory--;
|
||||
@ -111,7 +107,7 @@ int32_t MemoryPoolImpl<MemoryType>::PushMemory(MemoryType*& memory)
|
||||
memory = NULL;
|
||||
return 0;
|
||||
}
|
||||
_memoryPool.PushBack(static_cast<void*>(memory));
|
||||
_memoryPool.push_back(memory);
|
||||
memory = NULL;
|
||||
return 0;
|
||||
}
|
||||
@ -127,21 +123,15 @@ template<class MemoryType>
|
||||
int32_t MemoryPoolImpl<MemoryType>::Terminate()
|
||||
{
|
||||
CriticalSectionScoped cs(_crit);
|
||||
assert(_createdMemory == _outstandingMemory + _memoryPool.GetSize());
|
||||
assert(_createdMemory == _outstandingMemory + _memoryPool.size());
|
||||
|
||||
_terminate = true;
|
||||
// Reclaim all memory.
|
||||
while(_createdMemory > 0)
|
||||
{
|
||||
ListItem* item = _memoryPool.First();
|
||||
if(item == NULL)
|
||||
{
|
||||
// There is memory that hasn't been returned yet.
|
||||
return -1;
|
||||
}
|
||||
MemoryType* memory = static_cast<MemoryType*>(item->GetItem());
|
||||
MemoryType* memory = _memoryPool.front();
|
||||
_memoryPool.pop_front();
|
||||
delete memory;
|
||||
_memoryPool.Erase(item);
|
||||
_createdMemory--;
|
||||
}
|
||||
return 0;
|
||||
@ -158,7 +148,7 @@ int32_t MemoryPoolImpl<MemoryType>::CreateMemory(
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
_memoryPool.PushBack(static_cast<void*>(memory));
|
||||
_memoryPool.push_back(memory);
|
||||
_createdMemory++;
|
||||
}
|
||||
return 0;
|
||||
|
@ -37,15 +37,6 @@ const char* RecordedMicrophoneBoostFile =
|
||||
const char* RecordedMicrophoneAGCFile = "recorded_microphone_AGC_mono_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
|
||||
#if !defined(WEBRTC_IOS)
|
||||
char* GetFilename(char* filename)
|
||||
@ -103,8 +94,7 @@ AudioTransportImpl::AudioTransportImpl(AudioDeviceModule* audioDevice) :
|
||||
_loopBackMeasurements(false),
|
||||
_playFile(*FileWrapper::Create()),
|
||||
_recCount(0),
|
||||
_playCount(0),
|
||||
_audioList()
|
||||
_playCount(0)
|
||||
{
|
||||
_resampler.Reset(48000, 48000, kResamplerSynchronousStereo);
|
||||
}
|
||||
@ -115,18 +105,9 @@ AudioTransportImpl::~AudioTransportImpl()
|
||||
_playFile.CloseFile();
|
||||
delete &_playFile;
|
||||
|
||||
while (!_audioList.Empty())
|
||||
{
|
||||
ListItem* item = _audioList.First();
|
||||
if (item)
|
||||
{
|
||||
AudioPacket* packet = static_cast<AudioPacket*> (item->GetItem());
|
||||
if (packet)
|
||||
{
|
||||
delete packet;
|
||||
}
|
||||
}
|
||||
_audioList.PopFront();
|
||||
for (AudioPacketList::iterator iter = _audioList.begin();
|
||||
iter != _audioList.end(); ++iter) {
|
||||
delete *iter;
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,19 +133,11 @@ void AudioTransportImpl::SetFullDuplex(bool enable)
|
||||
{
|
||||
_fullDuplex = enable;
|
||||
|
||||
while (!_audioList.Empty())
|
||||
{
|
||||
ListItem* item = _audioList.First();
|
||||
if (item)
|
||||
{
|
||||
AudioPacket* packet = static_cast<AudioPacket*> (item->GetItem());
|
||||
if (packet)
|
||||
{
|
||||
delete packet;
|
||||
}
|
||||
}
|
||||
_audioList.PopFront();
|
||||
for (AudioPacketList::iterator iter = _audioList.begin();
|
||||
iter != _audioList.end(); ++iter) {
|
||||
delete *iter;
|
||||
}
|
||||
_audioList.clear();
|
||||
}
|
||||
|
||||
int32_t AudioTransportImpl::RecordedDataIsAvailable(
|
||||
@ -179,7 +152,7 @@ int32_t AudioTransportImpl::RecordedDataIsAvailable(
|
||||
const bool keyPressed,
|
||||
uint32_t& newMicLevel)
|
||||
{
|
||||
if (_fullDuplex && _audioList.GetSize() < 15)
|
||||
if (_fullDuplex && _audioList.size() < 15)
|
||||
{
|
||||
AudioPacket* packet = new AudioPacket();
|
||||
memcpy(packet->dataBuffer, audioSamples, nSamples * nBytesPerSample);
|
||||
@ -187,7 +160,7 @@ int32_t AudioTransportImpl::RecordedDataIsAvailable(
|
||||
packet->nBytesPerSample = nBytesPerSample;
|
||||
packet->nChannels = nChannels;
|
||||
packet->samplesPerSec = samplesPerSec;
|
||||
_audioList.PushBack(packet);
|
||||
_audioList.push_back(packet);
|
||||
}
|
||||
|
||||
_recCount++;
|
||||
@ -323,14 +296,14 @@ int32_t AudioTransportImpl::NeedMorePlayData(
|
||||
{
|
||||
if (_fullDuplex)
|
||||
{
|
||||
if (_audioList.Empty())
|
||||
if (_audioList.empty())
|
||||
{
|
||||
// use zero stuffing when not enough data
|
||||
memset(audioSamples, 0, nBytesPerSample * nSamples);
|
||||
} else
|
||||
{
|
||||
ListItem* item = _audioList.First();
|
||||
AudioPacket* packet = static_cast<AudioPacket*> (item->GetItem());
|
||||
AudioPacket* packet = _audioList.front();
|
||||
_audioList.pop_front();
|
||||
if (packet)
|
||||
{
|
||||
int ret(0);
|
||||
@ -441,7 +414,6 @@ int32_t AudioTransportImpl::NeedMorePlayData(
|
||||
nSamplesOut = nSamples;
|
||||
delete packet;
|
||||
}
|
||||
_audioList.PopFront();
|
||||
}
|
||||
} // if (_fullDuplex)
|
||||
|
||||
@ -531,12 +503,12 @@ int32_t AudioTransportImpl::NeedMorePlayData(
|
||||
{
|
||||
uint16_t recDelayMS(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->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));
|
||||
|
||||
|
@ -13,13 +13,13 @@
|
||||
|
||||
#include "webrtc/modules/audio_device/audio_device_utility.h"
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/common_audio/resampler/include/resampler.h"
|
||||
#include "webrtc/modules/audio_device/include/audio_device.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/list_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
#if defined(WEBRTC_IOS) || defined(ANDROID)
|
||||
@ -60,6 +60,15 @@ enum TestType
|
||||
TTTest = 66,
|
||||
};
|
||||
|
||||
struct AudioPacket
|
||||
{
|
||||
uint8_t dataBuffer[4 * 960];
|
||||
uint16_t nSamples;
|
||||
uint16_t nBytesPerSample;
|
||||
uint8_t nChannels;
|
||||
uint32_t samplesPerSec;
|
||||
};
|
||||
|
||||
class ProcessThread;
|
||||
|
||||
namespace webrtc
|
||||
@ -165,6 +174,7 @@ public:
|
||||
;
|
||||
|
||||
private:
|
||||
typedef std::list<AudioPacket*> AudioPacketList;
|
||||
AudioDeviceModule* _audioDevice;
|
||||
|
||||
bool _playFromFile;
|
||||
@ -181,8 +191,7 @@ private:
|
||||
|
||||
uint32_t _recCount;
|
||||
uint32_t _playCount;
|
||||
|
||||
ListWrapper _audioList;
|
||||
AudioPacketList _audioList;
|
||||
|
||||
Resampler _resampler;
|
||||
};
|
||||
|
@ -23,7 +23,6 @@
|
||||
|
||||
#include "webrtc/system_wrappers/interface/critical_section_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"
|
||||
|
||||
// http://msdn2.microsoft.com/en-us/library/ms779636.aspx
|
||||
@ -178,8 +177,7 @@ AviFile::AviFile()
|
||||
_videoCodecConfigParamsLength(0),
|
||||
_videoStreamDataChunkPrefix(0),
|
||||
_audioStreamDataChunkPrefix(0),
|
||||
_created(false),
|
||||
_indexList(new ListWrapper())
|
||||
_created(false)
|
||||
{
|
||||
ResetComplexMembers();
|
||||
}
|
||||
@ -188,7 +186,6 @@ AviFile::~AviFile()
|
||||
{
|
||||
Close();
|
||||
|
||||
delete _indexList;
|
||||
delete[] _videoCodecConfigParams;
|
||||
delete _crit;
|
||||
}
|
||||
@ -1712,21 +1709,11 @@ uint32_t AviFile::StreamAndTwoCharCodeToTag(int32_t streamNum,
|
||||
|
||||
void AviFile::ClearIndexList()
|
||||
{
|
||||
while (!_indexList->Empty())
|
||||
{
|
||||
ListItem* listItem = _indexList->First();
|
||||
if (listItem == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
AVIINDEXENTRY* item = static_cast<AVIINDEXENTRY*>(listItem->GetItem());
|
||||
if (item != NULL)
|
||||
{
|
||||
delete item;
|
||||
}
|
||||
_indexList->PopFront();
|
||||
for (IndexList::iterator iter = _indexList.begin();
|
||||
iter != _indexList.end(); ++iter) {
|
||||
delete *iter;
|
||||
}
|
||||
_indexList.clear();
|
||||
}
|
||||
|
||||
void AviFile::AddChunkToIndexList(uint32_t inChunkId,
|
||||
@ -1734,7 +1721,7 @@ void AviFile::AddChunkToIndexList(uint32_t inChunkId,
|
||||
uint32_t inOffset,
|
||||
uint32_t inSize)
|
||||
{
|
||||
_indexList->PushBack(new AVIINDEXENTRY(inChunkId, inFlags, inOffset,
|
||||
_indexList.push_back(new AVIINDEXENTRY(inChunkId, inFlags, inOffset,
|
||||
inSize));
|
||||
}
|
||||
|
||||
@ -1747,20 +1734,14 @@ void AviFile::WriteIndex()
|
||||
_bytesWritten += PutLE32(0);
|
||||
const size_t idxChunkSize = _bytesWritten;
|
||||
|
||||
for (ListItem* listItem = _indexList->First();
|
||||
listItem != NULL;
|
||||
listItem = _indexList->Next(listItem))
|
||||
{
|
||||
const AVIINDEXENTRY* item =
|
||||
static_cast<AVIINDEXENTRY*>(listItem->GetItem());
|
||||
if (item != NULL)
|
||||
{
|
||||
for (IndexList::iterator iter = _indexList.begin();
|
||||
iter != _indexList.end(); ++iter) {
|
||||
const AVIINDEXENTRY* item = *iter;
|
||||
_bytesWritten += PutLE32(item->ckid);
|
||||
_bytesWritten += PutLE32(item->dwFlags);
|
||||
_bytesWritten += PutLE32(item->dwChunkOffset);
|
||||
_bytesWritten += PutLE32(item->dwChunkLength);
|
||||
}
|
||||
}
|
||||
PutLE32LengthFromCurrent(static_cast<long>(idxChunkSize));
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
@ -14,12 +14,12 @@
|
||||
#define WEBRTC_MODULES_MEDIA_FILE_SOURCE_AVI_FILE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <list>
|
||||
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
class CriticalSectionWrapper;
|
||||
class ListWrapper;
|
||||
|
||||
struct AVISTREAMHEADER
|
||||
{
|
||||
@ -194,6 +194,7 @@ private:
|
||||
void WriteIndex();
|
||||
|
||||
private:
|
||||
typedef std::list<AVIINDEXENTRY*> IndexList;
|
||||
struct AVIMAINHEADER
|
||||
{
|
||||
AVIMAINHEADER();
|
||||
@ -269,7 +270,7 @@ private:
|
||||
uint32_t _audioStreamDataChunkPrefix;
|
||||
bool _created;
|
||||
|
||||
ListWrapper* _indexList; // Elements are of type AVIINDEXENTRY.
|
||||
IndexList _indexList;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
virtual int32_t Start() = 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;
|
||||
protected:
|
||||
virtual ~ProcessThread();
|
||||
|
@ -342,31 +342,6 @@ int32_t FileRecorderImpl::WriteEncodedAudioData(
|
||||
|
||||
|
||||
#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)
|
||||
: FileRecorderImpl(instanceID, fileFormat),
|
||||
_videoOnly(false),
|
||||
@ -545,20 +520,17 @@ int32_t AviRecorder::ProcessAudio()
|
||||
{
|
||||
// Syncronize audio to the current frame to process by throwing away
|
||||
// audio samples with older timestamp than the video frame.
|
||||
uint32_t numberOfAudioElements =
|
||||
_audioFramesToWrite.GetSize();
|
||||
for (uint32_t i = 0; i < numberOfAudioElements; ++i)
|
||||
{
|
||||
AudioFrameFileInfo* frameInfo =
|
||||
(AudioFrameFileInfo*)_audioFramesToWrite.First()->GetItem();
|
||||
if(frameInfo)
|
||||
size_t numberOfAudioElements =
|
||||
_audioFramesToWrite.size();
|
||||
for (size_t i = 0; i < numberOfAudioElements; ++i)
|
||||
{
|
||||
AudioFrameFileInfo* frameInfo = _audioFramesToWrite.front();
|
||||
if(TickTime::TicksToMilliseconds(
|
||||
frameInfo->_playoutTS.Ticks()) <
|
||||
frameToProcess->render_time_ms())
|
||||
{
|
||||
delete frameInfo;
|
||||
_audioFramesToWrite.PopFront();
|
||||
_audioFramesToWrite.pop_front();
|
||||
} else
|
||||
{
|
||||
break;
|
||||
@ -566,29 +538,22 @@ int32_t AviRecorder::ProcessAudio()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Write all audio up to current timestamp.
|
||||
int32_t error = 0;
|
||||
uint32_t numberOfAudioElements = _audioFramesToWrite.GetSize();
|
||||
for (uint32_t i = 0; i < numberOfAudioElements; ++i)
|
||||
{
|
||||
AudioFrameFileInfo* frameInfo =
|
||||
(AudioFrameFileInfo*)_audioFramesToWrite.First()->GetItem();
|
||||
if(frameInfo)
|
||||
size_t numberOfAudioElements = _audioFramesToWrite.size();
|
||||
for (size_t i = 0; i < numberOfAudioElements; ++i)
|
||||
{
|
||||
AudioFrameFileInfo* frameInfo = _audioFramesToWrite.front();
|
||||
if((TickTime::Now() - frameInfo->_playoutTS).Milliseconds() > 0)
|
||||
{
|
||||
_moduleFile->IncomingAudioData(frameInfo->_audioData,
|
||||
frameInfo->_audioSize);
|
||||
_writtenAudioMS += frameInfo->_audioMS;
|
||||
delete frameInfo;
|
||||
_audioFramesToWrite.PopFront();
|
||||
_audioFramesToWrite.pop_front();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
_audioFramesToWrite.PopFront();
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
@ -762,7 +727,7 @@ int32_t AviRecorder::WriteEncodedAudioData(
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (_audioFramesToWrite.GetSize() > kMaxAudioBufferQueueLength)
|
||||
if (_audioFramesToWrite.size() > kMaxAudioBufferQueueLength)
|
||||
{
|
||||
StopRecording();
|
||||
return -1;
|
||||
@ -771,12 +736,12 @@ int32_t AviRecorder::WriteEncodedAudioData(
|
||||
|
||||
if(playoutTS)
|
||||
{
|
||||
_audioFramesToWrite.PushBack(new AudioFrameFileInfo(audioBuffer,
|
||||
_audioFramesToWrite.push_back(new AudioFrameFileInfo(audioBuffer,
|
||||
bufferLength,
|
||||
millisecondsOfData,
|
||||
*playoutTS));
|
||||
} else {
|
||||
_audioFramesToWrite.PushBack(new AudioFrameFileInfo(audioBuffer,
|
||||
_audioFramesToWrite.push_back(new AudioFrameFileInfo(audioBuffer,
|
||||
bufferLength,
|
||||
millisecondsOfData,
|
||||
TickTime::Now()));
|
||||
|
@ -15,6 +15,8 @@
|
||||
#ifndef 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_types.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 { kMaxAudioBufferQueueLength = 100 };
|
||||
|
||||
class CriticalSectionWrapper;
|
||||
|
||||
class FileRecorderImpl : public FileRecorder
|
||||
{
|
||||
public:
|
||||
@ -103,6 +107,31 @@ private:
|
||||
|
||||
|
||||
#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
|
||||
{
|
||||
public:
|
||||
@ -126,6 +155,7 @@ protected:
|
||||
uint16_t millisecondsOfData,
|
||||
const TickTime* playoutTS);
|
||||
private:
|
||||
typedef std::list<AudioFrameFileInfo*> AudioInfoList;
|
||||
static bool Run(ThreadObj threadObj);
|
||||
bool Process();
|
||||
|
||||
@ -141,7 +171,7 @@ private:
|
||||
VideoCodec _videoCodecInst;
|
||||
bool _videoOnly;
|
||||
|
||||
ListWrapper _audioFramesToWrite;
|
||||
AudioInfoList _audioFramesToWrite;
|
||||
bool _firstAudioFrameReceived;
|
||||
|
||||
VideoFramesQueue* _videoFramesQueue;
|
||||
|
@ -87,25 +87,23 @@ int32_t ProcessThreadImpl::Stop()
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ProcessThreadImpl::RegisterModule(const Module* module)
|
||||
int32_t ProcessThreadImpl::RegisterModule(Module* module)
|
||||
{
|
||||
CriticalSectionScoped lock(_critSectModules);
|
||||
|
||||
// Only allow module to be registered once.
|
||||
ListItem* item = _modules.First();
|
||||
for(uint32_t i = 0; i < _modules.GetSize() && item; i++)
|
||||
{
|
||||
if(module == item->GetItem())
|
||||
for (ModuleList::iterator iter = _modules.begin();
|
||||
iter != _modules.end(); ++iter) {
|
||||
if(module == *iter)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
item = _modules.Next(item);
|
||||
}
|
||||
|
||||
_modules.PushFront(module);
|
||||
_modules.push_front(module);
|
||||
WEBRTC_TRACE(kTraceInfo, kTraceUtility, -1,
|
||||
"number of registered modules has increased to %d",
|
||||
_modules.GetSize());
|
||||
_modules.size());
|
||||
// Wake the thread calling ProcessThreadImpl::Process() to update the
|
||||
// waiting time. The waiting time for the just registered module may be
|
||||
// shorter than all other registered modules.
|
||||
@ -116,19 +114,16 @@ int32_t ProcessThreadImpl::RegisterModule(const Module* module)
|
||||
int32_t ProcessThreadImpl::DeRegisterModule(const Module* module)
|
||||
{
|
||||
CriticalSectionScoped lock(_critSectModules);
|
||||
|
||||
ListItem* item = _modules.First();
|
||||
for(uint32_t i = 0; i < _modules.GetSize() && item; i++)
|
||||
for (ModuleList::iterator iter = _modules.begin();
|
||||
iter != _modules.end(); ++iter) {
|
||||
if(module == *iter)
|
||||
{
|
||||
if(module == item->GetItem())
|
||||
{
|
||||
int res = _modules.Erase(item);
|
||||
_modules.erase(iter);
|
||||
WEBRTC_TRACE(kTraceInfo, kTraceUtility, -1,
|
||||
"number of registered modules has decreased to %d",
|
||||
_modules.GetSize());
|
||||
return res;
|
||||
_modules.size());
|
||||
return 0;
|
||||
}
|
||||
item = _modules.Next(item);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -145,16 +140,13 @@ bool ProcessThreadImpl::Process()
|
||||
int32_t minTimeToNext = 100;
|
||||
{
|
||||
CriticalSectionScoped lock(_critSectModules);
|
||||
ListItem* item = _modules.First();
|
||||
for(uint32_t i = 0; i < _modules.GetSize() && item; i++)
|
||||
{
|
||||
int32_t timeToNext =
|
||||
static_cast<Module*>(item->GetItem())->TimeUntilNextProcess();
|
||||
for (ModuleList::iterator iter = _modules.begin();
|
||||
iter != _modules.end(); ++iter) {
|
||||
int32_t timeToNext = (*iter)->TimeUntilNextProcess();
|
||||
if(minTimeToNext > timeToNext)
|
||||
{
|
||||
minTimeToNext = timeToNext;
|
||||
}
|
||||
item = _modules.Next(item);
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,16 +164,13 @@ bool ProcessThreadImpl::Process()
|
||||
}
|
||||
{
|
||||
CriticalSectionScoped lock(_critSectModules);
|
||||
ListItem* item = _modules.First();
|
||||
for(uint32_t i = 0; i < _modules.GetSize() && item; i++)
|
||||
{
|
||||
int32_t timeToNext =
|
||||
static_cast<Module*>(item->GetItem())->TimeUntilNextProcess();
|
||||
for (ModuleList::iterator iter = _modules.begin();
|
||||
iter != _modules.end(); ++iter) {
|
||||
int32_t timeToNext = (*iter)->TimeUntilNextProcess();
|
||||
if(timeToNext < 1)
|
||||
{
|
||||
static_cast<Module*>(item->GetItem())->Process();
|
||||
(*iter)->Process();
|
||||
}
|
||||
item = _modules.Next(item);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -11,10 +11,11 @@
|
||||
#ifndef 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/system_wrappers/interface/critical_section_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/typedefs.h"
|
||||
|
||||
@ -28,7 +29,7 @@ public:
|
||||
virtual int32_t Start();
|
||||
virtual int32_t Stop();
|
||||
|
||||
virtual int32_t RegisterModule(const Module* module);
|
||||
virtual int32_t RegisterModule(Module* module);
|
||||
virtual int32_t DeRegisterModule(const Module* module);
|
||||
|
||||
protected:
|
||||
@ -37,9 +38,10 @@ protected:
|
||||
bool Process();
|
||||
|
||||
private:
|
||||
typedef std::list<Module*> ModuleList;
|
||||
EventWrapper& _timeEvent;
|
||||
CriticalSectionWrapper* _critSectModules;
|
||||
ListWrapper _modules;
|
||||
ModuleList _modules;
|
||||
ThreadWrapper* _thread;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
@ -21,36 +21,24 @@
|
||||
|
||||
namespace webrtc {
|
||||
VideoFramesQueue::VideoFramesQueue()
|
||||
: _incomingFrames(),
|
||||
_renderDelayMs(10)
|
||||
: _renderDelayMs(10)
|
||||
{
|
||||
}
|
||||
|
||||
VideoFramesQueue::~VideoFramesQueue() {
|
||||
while (!_incomingFrames.Empty()) {
|
||||
ListItem* item = _incomingFrames.First();
|
||||
if (item) {
|
||||
I420VideoFrame* ptrFrame = static_cast<I420VideoFrame*>(item->GetItem());
|
||||
assert(ptrFrame != NULL);
|
||||
delete ptrFrame;
|
||||
for (FrameList::iterator iter = _incomingFrames.begin();
|
||||
iter != _incomingFrames.end(); ++iter) {
|
||||
delete *iter;
|
||||
}
|
||||
_incomingFrames.Erase(item);
|
||||
}
|
||||
while (!_emptyFrames.Empty()) {
|
||||
ListItem* item = _emptyFrames.First();
|
||||
if (item) {
|
||||
I420VideoFrame* ptrFrame =
|
||||
static_cast<I420VideoFrame*>(item->GetItem());
|
||||
assert(ptrFrame != NULL);
|
||||
delete ptrFrame;
|
||||
}
|
||||
_emptyFrames.Erase(item);
|
||||
for (FrameList::iterator iter = _emptyFrames.begin();
|
||||
iter != _emptyFrames.end(); ++iter) {
|
||||
delete *iter;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t VideoFramesQueue::AddFrame(const I420VideoFrame& newFrame) {
|
||||
if (newFrame.native_handle() != NULL) {
|
||||
_incomingFrames.PushBack(new TextureVideoFrame(
|
||||
_incomingFrames.push_back(new TextureVideoFrame(
|
||||
static_cast<NativeHandle*>(newFrame.native_handle()),
|
||||
newFrame.width(),
|
||||
newFrame.height(),
|
||||
@ -61,15 +49,12 @@ int32_t VideoFramesQueue::AddFrame(const I420VideoFrame& newFrame) {
|
||||
|
||||
I420VideoFrame* ptrFrameToAdd = NULL;
|
||||
// Try to re-use a VideoFrame. Only allocate new memory if it is necessary.
|
||||
if (!_emptyFrames.Empty()) {
|
||||
ListItem* item = _emptyFrames.First();
|
||||
if (item) {
|
||||
ptrFrameToAdd = static_cast<I420VideoFrame*>(item->GetItem());
|
||||
_emptyFrames.Erase(item);
|
||||
}
|
||||
if (!_emptyFrames.empty()) {
|
||||
ptrFrameToAdd = _emptyFrames.front();
|
||||
_emptyFrames.pop_front();
|
||||
}
|
||||
if (!ptrFrameToAdd) {
|
||||
if (_emptyFrames.GetSize() + _incomingFrames.GetSize() >
|
||||
if (_emptyFrames.size() + _incomingFrames.size() >
|
||||
KMaxNumberOfFrames) {
|
||||
WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, -1,
|
||||
"%s: too many frames, limit: %d", __FUNCTION__,
|
||||
@ -79,17 +64,12 @@ int32_t VideoFramesQueue::AddFrame(const I420VideoFrame& newFrame) {
|
||||
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceVideoRenderer, -1,
|
||||
"%s: allocating buffer %d", __FUNCTION__,
|
||||
_emptyFrames.GetSize() + _incomingFrames.GetSize());
|
||||
_emptyFrames.size() + _incomingFrames.size());
|
||||
|
||||
ptrFrameToAdd = new I420VideoFrame();
|
||||
if (!ptrFrameToAdd) {
|
||||
WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, -1,
|
||||
"%s: could not create new frame for", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ptrFrameToAdd->CopyFrame(newFrame);
|
||||
_incomingFrames.PushBack(ptrFrameToAdd);
|
||||
_incomingFrames.push_back(ptrFrameToAdd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -99,20 +79,16 @@ int32_t VideoFramesQueue::AddFrame(const I420VideoFrame& newFrame) {
|
||||
// Recycle all frames that are older than the most recent frame.
|
||||
I420VideoFrame* VideoFramesQueue::FrameToRecord() {
|
||||
I420VideoFrame* ptrRenderFrame = NULL;
|
||||
ListItem* item = _incomingFrames.First();
|
||||
while(item) {
|
||||
I420VideoFrame* ptrOldestFrameInList =
|
||||
static_cast<I420VideoFrame*>(item->GetItem());
|
||||
for (FrameList::iterator iter = _incomingFrames.begin();
|
||||
iter != _incomingFrames.end(); ++iter) {
|
||||
I420VideoFrame* ptrOldestFrameInList = *iter;
|
||||
if (ptrOldestFrameInList->render_time_ms() <=
|
||||
TickTime::MillisecondTimestamp() + _renderDelayMs) {
|
||||
if (ptrRenderFrame) {
|
||||
// List is traversed beginning to end. If ptrRenderFrame is not
|
||||
// NULL it must be the first, and thus oldest, VideoFrame in the
|
||||
// queue. It can be recycled.
|
||||
ReturnFrame(ptrRenderFrame);
|
||||
_incomingFrames.PopFront();
|
||||
}
|
||||
item = _incomingFrames.Next(item);
|
||||
iter = _incomingFrames.erase(iter);
|
||||
ptrRenderFrame = ptrOldestFrameInList;
|
||||
} else {
|
||||
// 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_render_time_ms(0);
|
||||
ptrOldFrame->ResetSize();
|
||||
_emptyFrames.PushBack(ptrOldFrame);
|
||||
_emptyFrames.push_back(ptrOldFrame);
|
||||
} else {
|
||||
delete ptrOldFrame;
|
||||
}
|
||||
|
@ -13,9 +13,10 @@
|
||||
|
||||
#ifdef WEBRTC_MODULE_UTILITY_VIDEO
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "webrtc/common_video/interface/i420_video_frame.h"
|
||||
#include "webrtc/engine_configurations.h"
|
||||
#include "webrtc/system_wrappers/interface/list_wrapper.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -42,6 +43,7 @@ class VideoFramesQueue {
|
||||
int32_t ReturnFrame(I420VideoFrame* ptrOldFrame);
|
||||
|
||||
private:
|
||||
typedef std::list<I420VideoFrame*> FrameList;
|
||||
// Don't allow the buffer to expand beyond KMaxNumberOfFrames VideoFrames.
|
||||
// 300 frames correspond to 10 seconds worth of frames at 30 fps.
|
||||
enum {KMaxNumberOfFrames = 300};
|
||||
@ -49,9 +51,9 @@ class VideoFramesQueue {
|
||||
// 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
|
||||
// was inserted first.
|
||||
ListWrapper _incomingFrames;
|
||||
FrameList _incomingFrames;
|
||||
// A list of frames that are free to be re-used.
|
||||
ListWrapper _emptyFrames;
|
||||
FrameList _emptyFrames;
|
||||
|
||||
// Estimated render delay.
|
||||
uint32_t _renderDelayMs;
|
||||
|
@ -8,7 +8,7 @@
|
||||
* 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>
|
||||
|
||||
@ -19,13 +19,12 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
const int32_t KEventMaxWaitTimeMs = 200;
|
||||
const uint32_t KEventMaxWaitTimeMs = 200;
|
||||
const uint32_t kMinRenderDelayMs = 10;
|
||||
const uint32_t kMaxRenderDelayMs= 500;
|
||||
|
||||
VideoRenderFrames::VideoRenderFrames()
|
||||
: incoming_frames_(),
|
||||
render_delay_ms_(10) {
|
||||
: render_delay_ms_(10) {
|
||||
}
|
||||
|
||||
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
|
||||
// really slow system never renders any frames.
|
||||
if (!incoming_frames_.Empty() &&
|
||||
if (!incoming_frames_.empty() &&
|
||||
new_frame->render_time_ms() + KOldRenderTimestampMS < time_now) {
|
||||
WEBRTC_TRACE(kTraceWarning,
|
||||
kTraceVideoRenderer,
|
||||
@ -56,26 +55,23 @@ int32_t VideoRenderFrames::AddFrame(I420VideoFrame* new_frame) {
|
||||
}
|
||||
|
||||
if (new_frame->native_handle() != NULL) {
|
||||
incoming_frames_.PushBack(new TextureVideoFrame(
|
||||
incoming_frames_.push_back(new TextureVideoFrame(
|
||||
static_cast<NativeHandle*>(new_frame->native_handle()),
|
||||
new_frame->width(),
|
||||
new_frame->height(),
|
||||
new_frame->timestamp(),
|
||||
new_frame->render_time_ms()));
|
||||
return incoming_frames_.GetSize();
|
||||
return static_cast<int32_t>(incoming_frames_.size());
|
||||
}
|
||||
|
||||
// Get an empty frame
|
||||
I420VideoFrame* frame_to_add = NULL;
|
||||
if (!empty_frames_.Empty()) {
|
||||
ListItem* item = empty_frames_.First();
|
||||
if (item) {
|
||||
frame_to_add = static_cast<I420VideoFrame*>(item->GetItem());
|
||||
empty_frames_.Erase(item);
|
||||
}
|
||||
if (!empty_frames_.empty()) {
|
||||
frame_to_add = empty_frames_.front();
|
||||
empty_frames_.pop_front();
|
||||
}
|
||||
if (!frame_to_add) {
|
||||
if (empty_frames_.GetSize() + incoming_frames_.GetSize() >
|
||||
if (empty_frames_.size() + incoming_frames_.size() >
|
||||
KMaxNumberOfFrames) {
|
||||
// Already allocated too many frames.
|
||||
WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer,
|
||||
@ -87,7 +83,7 @@ int32_t VideoRenderFrames::AddFrame(I420VideoFrame* new_frame) {
|
||||
// Allocate new memory.
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceVideoRenderer, -1,
|
||||
"%s: allocating buffer %d", __FUNCTION__,
|
||||
empty_frames_.GetSize() + incoming_frames_.GetSize());
|
||||
empty_frames_.size() + incoming_frames_.size());
|
||||
|
||||
frame_to_add = new I420VideoFrame();
|
||||
if (!frame_to_add) {
|
||||
@ -104,18 +100,16 @@ int32_t VideoRenderFrames::AddFrame(I420VideoFrame* new_frame) {
|
||||
// TODO(mflodman) Change this!
|
||||
// Remove const ness. Copying will be costly.
|
||||
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* render_frame = NULL;
|
||||
while (!incoming_frames_.Empty()) {
|
||||
ListItem* item = incoming_frames_.First();
|
||||
if (item) {
|
||||
I420VideoFrame* oldest_frame_in_list =
|
||||
static_cast<I420VideoFrame*>(item->GetItem());
|
||||
FrameList::iterator iter = incoming_frames_.begin();
|
||||
while(iter != incoming_frames_.end()) {
|
||||
I420VideoFrame* oldest_frame_in_list = *iter;
|
||||
if (oldest_frame_in_list->render_time_ms() <=
|
||||
TickTime::MillisecondTimestamp() + render_delay_ms_) {
|
||||
// This is the oldest one so far and it's OK to render.
|
||||
@ -124,14 +118,11 @@ I420VideoFrame* VideoRenderFrames::FrameToRender() {
|
||||
ReturnFrame(render_frame);
|
||||
}
|
||||
render_frame = oldest_frame_in_list;
|
||||
incoming_frames_.Erase(item);
|
||||
iter = incoming_frames_.erase(iter);
|
||||
} else {
|
||||
// We can't release this one yet, we're done here.
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
return render_frame;
|
||||
}
|
||||
@ -142,7 +133,7 @@ int32_t VideoRenderFrames::ReturnFrame(I420VideoFrame* old_frame) {
|
||||
old_frame->ResetSize();
|
||||
old_frame->set_timestamp(0);
|
||||
old_frame->set_render_time_ms(0);
|
||||
empty_frames_.PushBack(old_frame);
|
||||
empty_frames_.push_back(old_frame);
|
||||
} else {
|
||||
delete old_frame;
|
||||
}
|
||||
@ -150,41 +141,30 @@ int32_t VideoRenderFrames::ReturnFrame(I420VideoFrame* old_frame) {
|
||||
}
|
||||
|
||||
int32_t VideoRenderFrames::ReleaseAllFrames() {
|
||||
while (!incoming_frames_.Empty()) {
|
||||
ListItem* item = incoming_frames_.First();
|
||||
if (item) {
|
||||
I420VideoFrame* frame = static_cast<I420VideoFrame*>(item->GetItem());
|
||||
assert(frame != NULL);
|
||||
delete frame;
|
||||
for (FrameList::iterator iter = incoming_frames_.begin();
|
||||
iter != incoming_frames_.end(); ++iter) {
|
||||
delete *iter;
|
||||
}
|
||||
incoming_frames_.Erase(item);
|
||||
}
|
||||
while (!empty_frames_.Empty()) {
|
||||
ListItem* item = empty_frames_.First();
|
||||
if (item) {
|
||||
I420VideoFrame* frame = static_cast<I420VideoFrame*>(item->GetItem());
|
||||
assert(frame != NULL);
|
||||
delete frame;
|
||||
}
|
||||
empty_frames_.Erase(item);
|
||||
incoming_frames_.clear();
|
||||
|
||||
for (FrameList::iterator iter = empty_frames_.begin();
|
||||
iter != empty_frames_.end(); ++iter) {
|
||||
delete *iter;
|
||||
}
|
||||
empty_frames_.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t VideoRenderFrames::TimeToNextFrameRelease() {
|
||||
int64_t time_to_release = 0;
|
||||
ListItem* item = incoming_frames_.First();
|
||||
if (item) {
|
||||
I420VideoFrame* oldest_frame =
|
||||
static_cast<I420VideoFrame*>(item->GetItem());
|
||||
time_to_release = oldest_frame->render_time_ms() - render_delay_ms_
|
||||
if (incoming_frames_.empty()) {
|
||||
return KEventMaxWaitTimeMs;
|
||||
}
|
||||
I420VideoFrame* oldest_frame = incoming_frames_.front();
|
||||
int64_t time_to_release = oldest_frame->render_time_ms() - render_delay_ms_
|
||||
- TickTime::MillisecondTimestamp();
|
||||
if (time_to_release < 0) {
|
||||
time_to_release = 0;
|
||||
}
|
||||
} else {
|
||||
time_to_release = KEventMaxWaitTimeMs;
|
||||
}
|
||||
return static_cast<uint32_t>(time_to_release);
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,9 @@
|
||||
#ifndef 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/system_wrappers/interface/list_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -41,6 +42,8 @@ class VideoRenderFrames {
|
||||
int32_t SetRenderDelay(const uint32_t render_delay);
|
||||
|
||||
private:
|
||||
typedef std::list<I420VideoFrame*> FrameList;
|
||||
|
||||
// 10 seconds for 30 fps.
|
||||
enum { KMaxNumberOfFrames = 300 };
|
||||
// Don't render frames with timestamp older than 500ms from now.
|
||||
@ -49,9 +52,9 @@ class VideoRenderFrames {
|
||||
enum { KFutureRenderTimestampMS = 10000 };
|
||||
|
||||
// Sorted list with framed to be rendered, oldest first.
|
||||
ListWrapper incoming_frames_;
|
||||
FrameList incoming_frames_;
|
||||
// Empty frames.
|
||||
ListWrapper empty_frames_;
|
||||
FrameList empty_frames_;
|
||||
|
||||
// Estimated delay from a frame is released until it's rendered.
|
||||
uint32_t render_delay_ms_;
|
||||
|
@ -65,14 +65,11 @@ UdpSocket2ManagerWindows::~UdpSocket2ManagerWindows()
|
||||
}
|
||||
StopWorkerThreads();
|
||||
|
||||
// All threads are stopped. Safe to delete them.
|
||||
ListItem* pItem = NULL;
|
||||
while((pItem = _workerThreadsList.First()) != NULL)
|
||||
{
|
||||
delete static_cast<UdpSocket2WorkerWindows*>(pItem->GetItem());
|
||||
_workerThreadsList.PopFront();
|
||||
for (WorkerList::iterator iter = _workerThreadsList.begin();
|
||||
iter != _workerThreadsList.end(); ++iter) {
|
||||
delete *iter;
|
||||
}
|
||||
|
||||
_workerThreadsList.clear();
|
||||
_ioContextPool.Free();
|
||||
|
||||
_numOfActiveManagers--;
|
||||
@ -134,14 +131,10 @@ bool UdpSocket2ManagerWindows::Start()
|
||||
// Start worker threads.
|
||||
_stopped = false;
|
||||
int32_t error = 0;
|
||||
ListItem* pItem = _workerThreadsList.First();
|
||||
UdpSocket2WorkerWindows* pWorker;
|
||||
while(pItem != NULL && !error)
|
||||
{
|
||||
pWorker = (UdpSocket2WorkerWindows*)pItem->GetItem();
|
||||
if(!pWorker->Start())
|
||||
for (WorkerList::iterator iter = _workerThreadsList.begin();
|
||||
iter != _workerThreadsList.end() && !error; ++iter) {
|
||||
if(!(*iter)->Start())
|
||||
error = 1;
|
||||
pItem = _workerThreadsList.Next(pItem);
|
||||
}
|
||||
if(error)
|
||||
{
|
||||
@ -194,7 +187,7 @@ bool UdpSocket2ManagerWindows::StartWorkerThreads()
|
||||
delete pWorker;
|
||||
break;
|
||||
}
|
||||
_workerThreadsList.PushFront(pWorker);
|
||||
_workerThreadsList.push_front(pWorker);
|
||||
i++;
|
||||
}
|
||||
if(error)
|
||||
@ -207,12 +200,11 @@ bool UdpSocket2ManagerWindows::StartWorkerThreads()
|
||||
"creating work threads",
|
||||
_managerNumber);
|
||||
// Delete worker threads.
|
||||
ListItem* pItem = NULL;
|
||||
while((pItem = _workerThreadsList.First()) != NULL)
|
||||
{
|
||||
delete static_cast<UdpSocket2WorkerWindows*>(pItem->GetItem());
|
||||
_workerThreadsList.PopFront();
|
||||
for (WorkerList::iterator iter = _workerThreadsList.begin();
|
||||
iter != _workerThreadsList.end(); ++iter) {
|
||||
delete *iter;
|
||||
}
|
||||
_workerThreadsList.clear();
|
||||
_pCrit->Leave();
|
||||
return false;
|
||||
}
|
||||
@ -281,38 +273,30 @@ bool UdpSocket2ManagerWindows::StopWorkerThreads()
|
||||
threadsStoped, numActicve Sockets=%d",
|
||||
_managerNumber,
|
||||
_numActiveSockets);
|
||||
UdpSocket2WorkerWindows* pWorker;
|
||||
ListItem* pItem = _workerThreadsList.First();
|
||||
|
||||
// Set worker threads to not alive so that they will stop calling
|
||||
// UdpSocket2WorkerWindows::Run().
|
||||
while(pItem != NULL)
|
||||
{
|
||||
pWorker = (UdpSocket2WorkerWindows*)pItem->GetItem();
|
||||
pWorker->SetNotAlive();
|
||||
pItem = _workerThreadsList.Next(pItem);
|
||||
for (WorkerList::iterator iter = _workerThreadsList.begin();
|
||||
iter != _workerThreadsList.end(); ++iter) {
|
||||
(*iter)->SetNotAlive();
|
||||
}
|
||||
// Release all threads waiting for GetQueuedCompletionStatus(..).
|
||||
if(_ioCompletionHandle)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for(i = 0; i < _workerThreadsList.GetSize(); i++)
|
||||
for(i = 0; i < _workerThreadsList.size(); i++)
|
||||
{
|
||||
PostQueuedCompletionStatus(_ioCompletionHandle, 0 ,0 , NULL);
|
||||
}
|
||||
}
|
||||
pItem = _workerThreadsList.First();
|
||||
|
||||
while(pItem != NULL)
|
||||
{
|
||||
pWorker = (UdpSocket2WorkerWindows*)pItem->GetItem();
|
||||
if(pWorker->Stop() == false)
|
||||
for (WorkerList::iterator iter = _workerThreadsList.begin();
|
||||
iter != _workerThreadsList.end(); ++iter) {
|
||||
if((*iter)->Stop() == false)
|
||||
{
|
||||
error = -1;
|
||||
WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1,
|
||||
"failed to stop worker thread");
|
||||
}
|
||||
pItem = _workerThreadsList.Next(pItem);
|
||||
}
|
||||
|
||||
if(error)
|
||||
|
@ -12,11 +12,11 @@
|
||||
#define WEBRTC_TEST_CHANNEL_TRANSPORT_UDP_SOCKET2_MANAGER_WINDOWS_H_
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <list>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/atomic32.h"
|
||||
#include "webrtc/system_wrappers/interface/critical_section_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/test/channel_transport/udp_socket2_win.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_manager_wrapper.h"
|
||||
@ -91,6 +91,27 @@ private:
|
||||
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
|
||||
{
|
||||
@ -115,6 +136,7 @@ public:
|
||||
int32_t PushIoContext(PerIoContext* pIoContext);
|
||||
|
||||
private:
|
||||
typedef std::list<UdpSocket2WorkerWindows*> WorkerList;
|
||||
bool StopWorkerThreads();
|
||||
bool StartWorkerThreads();
|
||||
bool AddSocketPrv(UdpSocket2Windows* s);
|
||||
@ -129,35 +151,13 @@ private:
|
||||
volatile bool _stopped;
|
||||
bool _init;
|
||||
int32_t _numActiveSockets;
|
||||
ListWrapper _workerThreadsList;
|
||||
WorkerList _workerThreadsList;
|
||||
EventWrapper* _event;
|
||||
|
||||
HANDLE _ioCompletionHandle;
|
||||
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 webrtc
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "webrtc/system_wrappers/interface/condition_variable_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/critical_section_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/trace.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket2_manager_win.h"
|
||||
|
@ -322,7 +322,7 @@ bool UdpSocketManagerPosixImpl::AddSocket(UdpSocketWrapper* s)
|
||||
return false;
|
||||
}
|
||||
_critSectList->Enter();
|
||||
_addList.PushBack(s);
|
||||
_addList.push_back(s);
|
||||
_critSectList->Leave();
|
||||
return true;
|
||||
}
|
||||
@ -333,26 +333,24 @@ bool UdpSocketManagerPosixImpl::RemoveSocket(UdpSocketWrapper* s)
|
||||
_critSectList->Enter();
|
||||
|
||||
// If the socket is in the add list it's safe to remove and delete it.
|
||||
ListItem* addListItem = _addList.First();
|
||||
while(addListItem)
|
||||
{
|
||||
UdpSocketPosix* addSocket = (UdpSocketPosix*)addListItem->GetItem();
|
||||
for (SocketList::iterator iter = _addList.begin();
|
||||
iter != _addList.end(); ++iter) {
|
||||
UdpSocketPosix* addSocket = static_cast<UdpSocketPosix*>(*iter);
|
||||
unsigned int addFD = addSocket->GetFd();
|
||||
unsigned int removeFD = static_cast<UdpSocketPosix*>(s)->GetFd();
|
||||
if(removeFD == addFD)
|
||||
{
|
||||
_removeList.PushBack(removeFD);
|
||||
_removeList.push_back(removeFD);
|
||||
_critSectList->Leave();
|
||||
return true;
|
||||
}
|
||||
addListItem = _addList.Next(addListItem);
|
||||
}
|
||||
|
||||
// Checking the socket map is safe since all Erase and Insert calls to this
|
||||
// map are also protected by _critSectList.
|
||||
if (_socketMap.find(static_cast<UdpSocketPosix*>(s)->GetFd()) !=
|
||||
_socketMap.end()) {
|
||||
_removeList.PushBack(static_cast<UdpSocketPosix*>(s)->GetFd());
|
||||
_removeList.push_back(static_cast<UdpSocketPosix*>(s)->GetFd());
|
||||
_critSectList->Leave();
|
||||
return true;
|
||||
}
|
||||
@ -364,25 +362,23 @@ void UdpSocketManagerPosixImpl::UpdateSocketMap()
|
||||
{
|
||||
// Remove items in remove list.
|
||||
_critSectList->Enter();
|
||||
while(!_removeList.Empty())
|
||||
{
|
||||
for (FdList::iterator iter = _removeList.begin();
|
||||
iter != _removeList.end(); ++iter) {
|
||||
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
|
||||
// map yet. Just remove the socket from the add list.
|
||||
ListItem* addListItem = _addList.First();
|
||||
while(addListItem)
|
||||
{
|
||||
UdpSocketPosix* addSocket = (UdpSocketPosix*)addListItem->GetItem();
|
||||
for (SocketList::iterator iter = _addList.begin();
|
||||
iter != _addList.end(); ++iter) {
|
||||
UdpSocketPosix* addSocket = static_cast<UdpSocketPosix*>(*iter);
|
||||
SOCKET addFD = addSocket->GetFd();
|
||||
if(removeFD == addFD)
|
||||
{
|
||||
deleteSocket = addSocket;
|
||||
_addList.Erase(addListItem);
|
||||
_addList.erase(iter);
|
||||
break;
|
||||
}
|
||||
addListItem = _addList.Next(addListItem);
|
||||
}
|
||||
|
||||
// Find and remove socket from _socketMap.
|
||||
@ -398,19 +394,18 @@ void UdpSocketManagerPosixImpl::UpdateSocketMap()
|
||||
deleteSocket->ReadyForDeletion();
|
||||
delete deleteSocket;
|
||||
}
|
||||
_removeList.PopFront();
|
||||
}
|
||||
_removeList.clear();
|
||||
|
||||
// Add sockets from add list.
|
||||
while(!_addList.Empty())
|
||||
{
|
||||
UdpSocketPosix* s =
|
||||
static_cast<UdpSocketPosix*>(_addList.First()->GetItem());
|
||||
for (SocketList::iterator iter = _addList.begin();
|
||||
iter != _addList.end(); ++iter) {
|
||||
UdpSocketPosix* s = static_cast<UdpSocketPosix*>(*iter);
|
||||
if(s) {
|
||||
_socketMap[s->GetFd()] = s;
|
||||
}
|
||||
_addList.PopFront();
|
||||
}
|
||||
_addList.clear();
|
||||
_critSectList->Leave();
|
||||
}
|
||||
|
||||
|
@ -14,10 +14,10 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#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/test/channel_transport/udp_socket_manager_wrapper.h"
|
||||
#include "webrtc/test/channel_transport/udp_socket_wrapper.h"
|
||||
@ -74,14 +74,16 @@ protected:
|
||||
void UpdateSocketMap();
|
||||
|
||||
private:
|
||||
typedef std::list<UdpSocketWrapper*> SocketList;
|
||||
typedef std::list<SOCKET> FdList;
|
||||
ThreadWrapper* _thread;
|
||||
CriticalSectionWrapper* _critSectList;
|
||||
|
||||
fd_set _readFds;
|
||||
|
||||
std::map<SOCKET, UdpSocketPosix*> _socketMap;
|
||||
ListWrapper _addList;
|
||||
ListWrapper _removeList;
|
||||
SocketList _addList;
|
||||
FdList _removeList;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
|
@ -30,7 +30,7 @@ class TestProcessThread : public ProcessThread {
|
||||
~TestProcessThread() {}
|
||||
virtual int32_t Start() { 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; }
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,7 @@ class TestProcessThread : public ProcessThread {
|
||||
~TestProcessThread() {}
|
||||
virtual int32_t Start() { 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; }
|
||||
};
|
||||
|
||||
|
@ -65,7 +65,7 @@ int32_t ViERenderManager::RegisterVideoRenderModule(
|
||||
}
|
||||
|
||||
// Register module.
|
||||
render_list_.PushBack(static_cast<void*>(render_module));
|
||||
render_list_.push_back(render_module);
|
||||
use_external_render_module_ = true;
|
||||
return 0;
|
||||
}
|
||||
@ -81,25 +81,18 @@ int32_t ViERenderManager::DeRegisterVideoRenderModule(
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Erase the render module from the map.
|
||||
ListItem* list_item = NULL;
|
||||
bool found = false;
|
||||
for (list_item = render_list_.First(); list_item != NULL;
|
||||
list_item = render_list_.Next(list_item)) {
|
||||
if (render_module == static_cast<VideoRender*>(list_item->GetItem())) {
|
||||
// We've found our renderer.
|
||||
render_list_.Erase(list_item);
|
||||
found = true;
|
||||
break;
|
||||
for (RenderList::iterator iter = render_list_.begin();
|
||||
iter != render_list_.end(); ++iter) {
|
||||
if (render_module == *iter) {
|
||||
// We've found our renderer. Erase the render module from the map.
|
||||
render_list_.erase(iter);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_),
|
||||
"Module not registered");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ViERenderer* ViERenderManager::AddRenderStream(const int32_t render_id,
|
||||
void* window,
|
||||
@ -129,7 +122,7 @@ ViERenderer* ViERenderManager::AddRenderStream(const int32_t render_id,
|
||||
"Could not create new render module");
|
||||
return NULL;
|
||||
}
|
||||
render_list_.PushBack(static_cast<void*>(render_module));
|
||||
render_list_.push_back(render_module);
|
||||
}
|
||||
|
||||
ViERenderer* vie_renderer = ViERenderer::CreateViERenderer(render_id,
|
||||
@ -176,12 +169,11 @@ int32_t ViERenderManager::RemoveRenderStream(
|
||||
if (!use_external_render_module_ &&
|
||||
renderer.GetNumIncomingRenderStreams() == 0) {
|
||||
// Erase the render module from the map.
|
||||
ListItem* list_item = NULL;
|
||||
for (list_item = render_list_.First(); list_item != NULL;
|
||||
list_item = render_list_.Next(list_item)) {
|
||||
if (&renderer == static_cast<VideoRender*>(list_item->GetItem())) {
|
||||
for (RenderList::iterator iter = render_list_.begin();
|
||||
iter != render_list_.end(); ++iter) {
|
||||
if (&renderer == *iter) {
|
||||
// We've found our renderer.
|
||||
render_list_.Erase(list_item);
|
||||
render_list_.erase(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -192,21 +184,14 @@ int32_t ViERenderManager::RemoveRenderStream(
|
||||
}
|
||||
|
||||
VideoRender* ViERenderManager::FindRenderModule(void* window) {
|
||||
VideoRender* renderer = NULL;
|
||||
ListItem* list_item = NULL;
|
||||
for (list_item = render_list_.First(); list_item != NULL;
|
||||
list_item = render_list_.Next(list_item)) {
|
||||
renderer = static_cast<VideoRender*>(list_item->GetItem());
|
||||
if (renderer == NULL) {
|
||||
break;
|
||||
}
|
||||
if (renderer->Window() == window) {
|
||||
for (RenderList::iterator iter = render_list_.begin();
|
||||
iter != render_list_.end(); ++iter) {
|
||||
if ((*iter)->Window() == window) {
|
||||
// We've found the render module.
|
||||
break;
|
||||
return *iter;
|
||||
}
|
||||
renderer = NULL;
|
||||
}
|
||||
return renderer;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ViERenderer* ViERenderManager::ViERenderPtr(int32_t render_id) const {
|
||||
|
@ -11,9 +11,9 @@
|
||||
#ifndef WEBRTC_VIDEO_ENGINE_VIE_RENDER_MANAGER_H_
|
||||
#define WEBRTC_VIDEO_ENGINE_VIE_RENDER_MANAGER_H_
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "webrtc/system_wrappers/interface/list_wrapper.h"
|
||||
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
#include "webrtc/video_engine/vie_manager_base.h"
|
||||
@ -46,6 +46,7 @@ class ViERenderManager : private ViEManagerBase {
|
||||
int32_t RemoveRenderStream(int32_t render_id);
|
||||
|
||||
private:
|
||||
typedef std::list<VideoRender*> RenderList;
|
||||
// Returns a pointer to the render module if it exists in the render list.
|
||||
// Assumed protected.
|
||||
VideoRender* FindRenderModule(void* window);
|
||||
@ -58,8 +59,7 @@ class ViERenderManager : private ViEManagerBase {
|
||||
// Protected by ViEManagerBase.
|
||||
typedef std::map<int32_t, ViERenderer*> RendererMap;
|
||||
RendererMap stream_to_vie_renderer_;
|
||||
|
||||
ListWrapper render_list_;
|
||||
RenderList render_list_;
|
||||
bool use_external_render_module_;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user