311 lines
10 KiB
C++
311 lines
10 KiB
C++
|
/*
|
||
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||
|
*
|
||
|
* Use of this source code is governed by a BSD-style license
|
||
|
* that can be found in the LICENSE file in the root of the source
|
||
|
* tree. An additional intellectual property rights grant can be found
|
||
|
* in the file PATENTS. All contributing project authors may
|
||
|
* be found in the AUTHORS file in the root of the source tree.
|
||
|
*/
|
||
|
|
||
|
#include "vie_frame_provider_base.h"
|
||
|
#include "critical_section_wrapper.h"
|
||
|
#include "tick_util.h"
|
||
|
#include "trace.h"
|
||
|
#include "vie_defines.h"
|
||
|
|
||
|
namespace webrtc {
|
||
|
|
||
|
ViEFrameProviderBase::ViEFrameProviderBase(int Id, int engineId):
|
||
|
_id(Id),
|
||
|
_engineId(engineId),
|
||
|
_frameCallbackMap(),
|
||
|
_providerCritSect(*CriticalSectionWrapper::CreateCriticalSection()),
|
||
|
_ptrExtraFrame(NULL),
|
||
|
_frameDelay(0)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
ViEFrameProviderBase::~ViEFrameProviderBase()
|
||
|
{
|
||
|
if(_frameCallbackMap.Size()>0)
|
||
|
{
|
||
|
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo, ViEId(_engineId,_id), "FramCallbacks still exist when Provider deleted %d",_frameCallbackMap.Size());
|
||
|
}
|
||
|
for(MapItem* item=_frameCallbackMap.First();item!=NULL;item=_frameCallbackMap.Next(item))
|
||
|
{
|
||
|
static_cast<ViEFrameCallback*>(item->GetItem())->ProviderDestroyed(_id);
|
||
|
}
|
||
|
|
||
|
while(_frameCallbackMap.Erase(_frameCallbackMap.First()) == 0)
|
||
|
;
|
||
|
|
||
|
delete &_providerCritSect;
|
||
|
delete _ptrExtraFrame;
|
||
|
}
|
||
|
|
||
|
int ViEFrameProviderBase::Id()
|
||
|
{
|
||
|
return _id;
|
||
|
}
|
||
|
|
||
|
void ViEFrameProviderBase::DeliverFrame(webrtc::VideoFrame& videoFrame,int numCSRCs,
|
||
|
const WebRtc_UWord32 CSRC[kRtpCsrcSize])
|
||
|
{
|
||
|
#ifdef _DEBUG
|
||
|
const TickTime startProcessTime=TickTime::Now();
|
||
|
#endif
|
||
|
CriticalSectionScoped cs(_providerCritSect);
|
||
|
|
||
|
// Deliver the frame to all registered callbacks
|
||
|
if (_frameCallbackMap.Size() > 0)
|
||
|
{
|
||
|
if(_frameCallbackMap.Size()==1)
|
||
|
{
|
||
|
ViEFrameCallback* frameObserver = static_cast<ViEFrameCallback*>(_frameCallbackMap.First()->GetItem());
|
||
|
frameObserver->DeliverFrame(_id,videoFrame,numCSRCs,CSRC);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Make a copy of the frame for all callbacks
|
||
|
for (MapItem* mapItem = _frameCallbackMap.First();
|
||
|
mapItem != NULL;
|
||
|
mapItem = _frameCallbackMap.Next(mapItem))
|
||
|
{
|
||
|
if (_ptrExtraFrame == NULL)
|
||
|
{
|
||
|
_ptrExtraFrame = new webrtc::VideoFrame();
|
||
|
}
|
||
|
if (mapItem != NULL)
|
||
|
{
|
||
|
ViEFrameCallback* frameObserver = static_cast<ViEFrameCallback*>(mapItem->GetItem());
|
||
|
if (frameObserver != NULL)
|
||
|
{
|
||
|
// We must copy the frame each time since the previous receiver might swap it...
|
||
|
_ptrExtraFrame->CopyFrame(videoFrame);
|
||
|
frameObserver->DeliverFrame(_id, *_ptrExtraFrame,numCSRCs,CSRC);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
const int processTime=(int) (TickTime::Now()-startProcessTime).Milliseconds();
|
||
|
if(processTime>25) // Warn If the delivery time is too long.
|
||
|
{
|
||
|
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo, ViEId(_engineId,_id), "%s Too long time: %ums",__FUNCTION__,processTime);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void ViEFrameProviderBase::SetFrameDelay(int frameDelay)
|
||
|
{
|
||
|
|
||
|
CriticalSectionScoped cs(_providerCritSect);
|
||
|
_frameDelay=frameDelay;
|
||
|
|
||
|
for (MapItem* mapItem = _frameCallbackMap.First();
|
||
|
mapItem != NULL;
|
||
|
mapItem = _frameCallbackMap.Next(mapItem))
|
||
|
{
|
||
|
ViEFrameCallback* frameObserver = static_cast<ViEFrameCallback*>(mapItem->GetItem());
|
||
|
assert(frameObserver);
|
||
|
frameObserver->DelayChanged(_id,frameDelay);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
int ViEFrameProviderBase::FrameDelay()
|
||
|
{
|
||
|
return _frameDelay;
|
||
|
}
|
||
|
|
||
|
int ViEFrameProviderBase::GetBestFormat(int& bestWidth,
|
||
|
int& bestHeight,
|
||
|
int& bestFrameRate)
|
||
|
{
|
||
|
|
||
|
int largestWidth = 0;
|
||
|
int largestHeight = 0;
|
||
|
int highestFrameRate = 0;
|
||
|
|
||
|
CriticalSectionScoped cs(_providerCritSect);
|
||
|
|
||
|
// Check if this one already exists...
|
||
|
for (MapItem* mapItem = _frameCallbackMap.First();
|
||
|
mapItem != NULL;
|
||
|
mapItem = _frameCallbackMap.Next(mapItem))
|
||
|
{
|
||
|
|
||
|
|
||
|
int preferedWidth=0;
|
||
|
int preferedHeight=0;
|
||
|
int preferedFrameRate=0;
|
||
|
|
||
|
ViEFrameCallback* callbackObject = static_cast<ViEFrameCallback*>(mapItem->GetItem());
|
||
|
assert(callbackObject);
|
||
|
if(callbackObject->GetPreferedFrameSettings(preferedWidth,preferedHeight,preferedFrameRate)==0)
|
||
|
{
|
||
|
if (preferedWidth > largestWidth)
|
||
|
{
|
||
|
largestWidth = preferedWidth;
|
||
|
}
|
||
|
if (preferedHeight > largestHeight)
|
||
|
{
|
||
|
largestHeight = preferedHeight;
|
||
|
}
|
||
|
if (preferedFrameRate > highestFrameRate)
|
||
|
{
|
||
|
highestFrameRate = preferedFrameRate;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bestWidth = largestWidth;
|
||
|
bestHeight = largestHeight;
|
||
|
bestFrameRate = highestFrameRate;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int ViEFrameProviderBase::RegisterFrameCallback(int observerId,ViEFrameCallback* callbackObject)
|
||
|
{
|
||
|
if (callbackObject == NULL)
|
||
|
{
|
||
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId, _id),
|
||
|
"%s: No argument", __FUNCTION__);
|
||
|
return -1;
|
||
|
}
|
||
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _id),
|
||
|
"%s(0x%p)", callbackObject);
|
||
|
|
||
|
{
|
||
|
CriticalSectionScoped cs(_providerCritSect);
|
||
|
|
||
|
// Check if this one already exists...
|
||
|
for (MapItem* mapItem = _frameCallbackMap.First();
|
||
|
mapItem != NULL;
|
||
|
mapItem = _frameCallbackMap.Next(mapItem))
|
||
|
{
|
||
|
const ViEFrameCallback* observer=static_cast<ViEFrameCallback*> (mapItem->GetItem());
|
||
|
if (observer == callbackObject)
|
||
|
{
|
||
|
// This callback is already registered
|
||
|
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo, ViEId(_engineId, _id),
|
||
|
"%s 0x%p already registered", __FUNCTION__, callbackObject);
|
||
|
|
||
|
assert("!frameObserver already registered");
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (_frameCallbackMap.Insert(observerId,callbackObject) != 0)
|
||
|
{
|
||
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId, _id),
|
||
|
"%s: Could not add 0x%p to list", __FUNCTION__, callbackObject);
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
// Report current capture delay
|
||
|
callbackObject->DelayChanged(_id,_frameDelay);
|
||
|
|
||
|
FrameCallbackChanged(); // Notify implementer of this class that the callback list have changed
|
||
|
return 0;
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
// DeregisterFrameCallback
|
||
|
// ----------------------------------------------------------------------------
|
||
|
|
||
|
int ViEFrameProviderBase::DeregisterFrameCallback(const ViEFrameCallback* callbackObject)
|
||
|
{
|
||
|
if (callbackObject == NULL)
|
||
|
{
|
||
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId, _id),
|
||
|
"%s: No argument", __FUNCTION__);
|
||
|
return -1;
|
||
|
}
|
||
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _id),
|
||
|
"%s(0x%p)", callbackObject);
|
||
|
|
||
|
|
||
|
{
|
||
|
CriticalSectionScoped cs(_providerCritSect);
|
||
|
bool itemFound=false;
|
||
|
|
||
|
|
||
|
// Try to find the callback in our list
|
||
|
for (MapItem* mapItem = _frameCallbackMap.First();
|
||
|
mapItem != NULL;
|
||
|
mapItem = _frameCallbackMap.Next(mapItem))
|
||
|
{
|
||
|
const ViEFrameCallback* observer=static_cast<ViEFrameCallback*> (mapItem->GetItem());
|
||
|
if (observer == callbackObject)
|
||
|
{
|
||
|
// We found it, remove it!
|
||
|
_frameCallbackMap.Erase(mapItem);
|
||
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _id),
|
||
|
"%s 0x%p deregistered", __FUNCTION__, callbackObject);
|
||
|
itemFound=true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if(!itemFound)
|
||
|
{
|
||
|
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo, ViEId(_engineId, _id),
|
||
|
"%s 0x%p not found", __FUNCTION__, callbackObject);
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FrameCallbackChanged(); // Notify implementer of this class that the callback list have changed
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
// IsFrameCallbackRegistered
|
||
|
// ----------------------------------------------------------------------------
|
||
|
|
||
|
bool ViEFrameProviderBase::IsFrameCallbackRegistered(const ViEFrameCallback* callbackObject)
|
||
|
{
|
||
|
if (callbackObject == NULL)
|
||
|
{
|
||
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId, _id),
|
||
|
"%s: No argument", __FUNCTION__);
|
||
|
return false;
|
||
|
}
|
||
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _id),
|
||
|
"%s(0x%p)", callbackObject);
|
||
|
|
||
|
for (MapItem* mapItem = _frameCallbackMap.First();
|
||
|
mapItem != NULL;
|
||
|
mapItem = _frameCallbackMap.Next(mapItem))
|
||
|
{
|
||
|
if (callbackObject == mapItem->GetItem())
|
||
|
{
|
||
|
// We found the callback
|
||
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _id),
|
||
|
"%s 0x%p is registered", __FUNCTION__, callbackObject);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _id),
|
||
|
"%s 0x%p not registered", __FUNCTION__, callbackObject);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
// NumberOfRegistersFrameCallbacks
|
||
|
// ----------------------------------------------------------------------------
|
||
|
|
||
|
int ViEFrameProviderBase::NumberOfRegistersFrameCallbacks()
|
||
|
{
|
||
|
CriticalSectionScoped cs(_providerCritSect);
|
||
|
return _frameCallbackMap.Size();
|
||
|
}
|
||
|
} // namespac webrtc
|