diff options
Diffstat (limited to 'webrtc/modules/video_render/video_render_impl.cc')
-rw-r--r-- | webrtc/modules/video_render/video_render_impl.cc | 603 |
1 files changed, 603 insertions, 0 deletions
diff --git a/webrtc/modules/video_render/video_render_impl.cc b/webrtc/modules/video_render/video_render_impl.cc new file mode 100644 index 0000000000..32ec2b0e75 --- /dev/null +++ b/webrtc/modules/video_render/video_render_impl.cc @@ -0,0 +1,603 @@ +/* + * Copyright (c) 2012 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 <assert.h> + +#include "webrtc/common_video/interface/incoming_video_stream.h" +#include "webrtc/engine_configurations.h" +#include "webrtc/modules/video_render/external/video_render_external_impl.h" +#include "webrtc/modules/video_render/i_video_render.h" +#include "webrtc/modules/video_render/include/video_render_defines.h" +#include "webrtc/modules/video_render/video_render_impl.h" +#include "webrtc/system_wrappers/include/critical_section_wrapper.h" +#include "webrtc/system_wrappers/include/trace.h" + +namespace webrtc { + +VideoRender* +VideoRender::CreateVideoRender(const int32_t id, + void* window, + const bool fullscreen, + const VideoRenderType videoRenderType/*=kRenderDefault*/) +{ + VideoRenderType resultVideoRenderType = videoRenderType; + if (videoRenderType == kRenderDefault) + { + resultVideoRenderType = kRenderExternal; + } + return new ModuleVideoRenderImpl(id, resultVideoRenderType, window, + fullscreen); +} + +void VideoRender::DestroyVideoRender( + VideoRender* module) +{ + if (module) + { + delete module; + } +} + +ModuleVideoRenderImpl::ModuleVideoRenderImpl( + const int32_t id, + const VideoRenderType videoRenderType, + void* window, + const bool fullscreen) : + _id(id), _moduleCrit(*CriticalSectionWrapper::CreateCriticalSection()), + _ptrWindow(window), _fullScreen(fullscreen), _ptrRenderer(NULL) +{ + + // Create platform specific renderer + switch (videoRenderType) + { + case kRenderExternal: + { + VideoRenderExternalImpl* ptrRenderer(NULL); + ptrRenderer = new VideoRenderExternalImpl(_id, videoRenderType, + window, _fullScreen); + if (ptrRenderer) + { + _ptrRenderer = reinterpret_cast<IVideoRender*> (ptrRenderer); + } + } + break; + default: + // Error... + break; + } + if (_ptrRenderer) + { + if (_ptrRenderer->Init() == -1) + { + } + } +} + +ModuleVideoRenderImpl::~ModuleVideoRenderImpl() +{ + delete &_moduleCrit; + + for (IncomingVideoStreamMap::iterator it = _streamRenderMap.begin(); + it != _streamRenderMap.end(); + ++it) { + delete it->second; + } + + // Delete platform specific renderer + if (_ptrRenderer) + { + VideoRenderType videoRenderType = _ptrRenderer->RenderType(); + + switch (videoRenderType) + { + case kRenderExternal: + { + VideoRenderExternalImpl + * ptrRenderer = + reinterpret_cast<VideoRenderExternalImpl*> (_ptrRenderer); + _ptrRenderer = NULL; + delete ptrRenderer; + } + break; + + default: + // Error... + break; + } + } +} + +int64_t ModuleVideoRenderImpl::TimeUntilNextProcess() +{ + // Not used + return 50; +} +int32_t ModuleVideoRenderImpl::Process() +{ + // Not used + return 0; +} + +void* +ModuleVideoRenderImpl::Window() +{ + CriticalSectionScoped cs(&_moduleCrit); + return _ptrWindow; +} + +int32_t ModuleVideoRenderImpl::ChangeWindow(void* window) +{ + return -1; +} + +int32_t ModuleVideoRenderImpl::Id() +{ + CriticalSectionScoped cs(&_moduleCrit); + return _id; +} + +uint32_t ModuleVideoRenderImpl::GetIncomingFrameRate(const uint32_t streamId) { + CriticalSectionScoped cs(&_moduleCrit); + + IncomingVideoStreamMap::iterator it = _streamRenderMap.find(streamId); + + if (it == _streamRenderMap.end()) { + // This stream doesn't exist + WEBRTC_TRACE(kTraceError, + kTraceVideoRenderer, + _id, + "%s: stream doesn't exist", + __FUNCTION__); + return 0; + } + assert(it->second != NULL); + return it->second->IncomingRate(); +} + +VideoRenderCallback* +ModuleVideoRenderImpl::AddIncomingRenderStream(const uint32_t streamId, + const uint32_t zOrder, + const float left, + const float top, + const float right, + const float bottom) +{ + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: No renderer", __FUNCTION__); + return NULL; + } + + if (_streamRenderMap.find(streamId) != _streamRenderMap.end()) { + // The stream already exists... + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: stream already exists", __FUNCTION__); + return NULL; + } + + VideoRenderCallback* ptrRenderCallback = + _ptrRenderer->AddIncomingRenderStream(streamId, zOrder, left, top, + right, bottom); + if (ptrRenderCallback == NULL) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: Can't create incoming stream in renderer", + __FUNCTION__); + return NULL; + } + + // Create platform independant code + IncomingVideoStream* ptrIncomingStream = new IncomingVideoStream(streamId); + ptrIncomingStream->SetRenderCallback(ptrRenderCallback); + VideoRenderCallback* moduleCallback = ptrIncomingStream->ModuleCallback(); + + // Store the stream + _streamRenderMap[streamId] = ptrIncomingStream; + + return moduleCallback; +} + +int32_t ModuleVideoRenderImpl::DeleteIncomingRenderStream( + const uint32_t streamId) +{ + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: No renderer", __FUNCTION__); + return -1; + } + + IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId); + if (item == _streamRenderMap.end()) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: stream doesn't exist", __FUNCTION__); + return -1; + } + + delete item->second; + + _ptrRenderer->DeleteIncomingRenderStream(streamId); + + _streamRenderMap.erase(item); + + return 0; +} + +int32_t ModuleVideoRenderImpl::AddExternalRenderCallback( + const uint32_t streamId, + VideoRenderCallback* renderObject) { + CriticalSectionScoped cs(&_moduleCrit); + + IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId); + + if (item == _streamRenderMap.end()) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: stream doesn't exist", __FUNCTION__); + return -1; + } + + if (item->second == NULL) { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: could not get stream", __FUNCTION__); + return -1; + } + item->second->SetExternalCallback(renderObject); + return 0; +} + +int32_t ModuleVideoRenderImpl::GetIncomingRenderStreamProperties( + const uint32_t streamId, + uint32_t& zOrder, + float& left, + float& top, + float& right, + float& bottom) const { + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: No renderer", __FUNCTION__); + return -1; + } + + return _ptrRenderer->GetIncomingRenderStreamProperties(streamId, zOrder, + left, top, right, + bottom); +} + +uint32_t ModuleVideoRenderImpl::GetNumIncomingRenderStreams() const +{ + CriticalSectionScoped cs(&_moduleCrit); + + return static_cast<uint32_t>(_streamRenderMap.size()); +} + +bool ModuleVideoRenderImpl::HasIncomingRenderStream( + const uint32_t streamId) const { + CriticalSectionScoped cs(&_moduleCrit); + + return _streamRenderMap.find(streamId) != _streamRenderMap.end(); +} + +int32_t ModuleVideoRenderImpl::RegisterRawFrameCallback( + const uint32_t streamId, + VideoRenderCallback* callbackObj) { + return -1; +} + +int32_t ModuleVideoRenderImpl::StartRender(const uint32_t streamId) +{ + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: No renderer", __FUNCTION__); + return -1; + } + + // Start the stream + IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId); + + if (item == _streamRenderMap.end()) + { + return -1; + } + + if (item->second->Start() == -1) + { + return -1; + } + + // Start the HW renderer + if (_ptrRenderer->StartRender() == -1) + { + return -1; + } + return 0; +} + +int32_t ModuleVideoRenderImpl::StopRender(const uint32_t streamId) +{ + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s(%d): No renderer", __FUNCTION__, streamId); + return -1; + } + + // Stop the incoming stream + IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId); + + if (item == _streamRenderMap.end()) + { + return -1; + } + + if (item->second->Stop() == -1) + { + return -1; + } + + return 0; +} + +int32_t ModuleVideoRenderImpl::ResetRender() +{ + CriticalSectionScoped cs(&_moduleCrit); + + int32_t ret = 0; + // Loop through all incoming streams and reset them + for (IncomingVideoStreamMap::iterator it = _streamRenderMap.begin(); + it != _streamRenderMap.end(); + ++it) { + if (it->second->Reset() == -1) + ret = -1; + } + return ret; +} + +RawVideoType ModuleVideoRenderImpl::PreferredVideoType() const +{ + CriticalSectionScoped cs(&_moduleCrit); + + if (_ptrRenderer == NULL) + { + return kVideoI420; + } + + return _ptrRenderer->PerferedVideoType(); +} + +bool ModuleVideoRenderImpl::IsFullScreen() +{ + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: No renderer", __FUNCTION__); + return false; + } + return _ptrRenderer->FullScreen(); +} + +int32_t ModuleVideoRenderImpl::GetScreenResolution( + uint32_t& screenWidth, + uint32_t& screenHeight) const +{ + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: No renderer", __FUNCTION__); + return false; + } + return _ptrRenderer->GetScreenResolution(screenWidth, screenHeight); +} + +uint32_t ModuleVideoRenderImpl::RenderFrameRate( + const uint32_t streamId) +{ + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: No renderer", __FUNCTION__); + return false; + } + return _ptrRenderer->RenderFrameRate(streamId); +} + +int32_t ModuleVideoRenderImpl::SetStreamCropping( + const uint32_t streamId, + const float left, + const float top, + const float right, + const float bottom) +{ + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: No renderer", __FUNCTION__); + return false; + } + return _ptrRenderer->SetStreamCropping(streamId, left, top, right, bottom); +} + +int32_t ModuleVideoRenderImpl::SetTransparentBackground(const bool enable) +{ + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: No renderer", __FUNCTION__); + return false; + } + return _ptrRenderer->SetTransparentBackground(enable); +} + +int32_t ModuleVideoRenderImpl::FullScreenRender(void* window, const bool enable) +{ + return -1; +} + +int32_t ModuleVideoRenderImpl::SetText( + const uint8_t textId, + const uint8_t* text, + const int32_t textLength, + const uint32_t textColorRef, + const uint32_t backgroundColorRef, + const float left, const float top, + const float right, + const float bottom) +{ + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: No renderer", __FUNCTION__); + return -1; + } + return _ptrRenderer->SetText(textId, text, textLength, textColorRef, + backgroundColorRef, left, top, right, bottom); +} + +int32_t ModuleVideoRenderImpl::SetBitmap(const void* bitMap, + const uint8_t pictureId, + const void* colorKey, + const float left, + const float top, + const float right, + const float bottom) +{ + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: No renderer", __FUNCTION__); + return -1; + } + return _ptrRenderer->SetBitmap(bitMap, pictureId, colorKey, left, top, + right, bottom); +} + +int32_t ModuleVideoRenderImpl::SetExpectedRenderDelay( + uint32_t stream_id, int32_t delay_ms) { + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: No renderer", __FUNCTION__); + return false; + } + + IncomingVideoStreamMap::const_iterator item = + _streamRenderMap.find(stream_id); + if (item == _streamRenderMap.end()) { + // This stream doesn't exist + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s(%u, %d): stream doesn't exist", __FUNCTION__, stream_id, + delay_ms); + return -1; + } + + assert(item->second != NULL); + return item->second->SetExpectedRenderDelay(delay_ms); +} + +int32_t ModuleVideoRenderImpl::ConfigureRenderer( + const uint32_t streamId, + const unsigned int zOrder, + const float left, + const float top, + const float right, + const float bottom) +{ + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: No renderer", __FUNCTION__); + return false; + } + return _ptrRenderer->ConfigureRenderer(streamId, zOrder, left, top, right, + bottom); +} + +int32_t ModuleVideoRenderImpl::SetStartImage(const uint32_t streamId, + const VideoFrame& videoFrame) { + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: No renderer", __FUNCTION__); + return -1; + } + + IncomingVideoStreamMap::const_iterator item = + _streamRenderMap.find(streamId); + if (item == _streamRenderMap.end()) + { + // This stream doesn't exist + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: stream doesn't exist", __FUNCTION__); + return -1; + } + assert (item->second != NULL); + return item->second->SetStartImage(videoFrame); + +} + +int32_t ModuleVideoRenderImpl::SetTimeoutImage(const uint32_t streamId, + const VideoFrame& videoFrame, + const uint32_t timeout) { + CriticalSectionScoped cs(&_moduleCrit); + + if (!_ptrRenderer) + { + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: No renderer", __FUNCTION__); + return -1; + } + + IncomingVideoStreamMap::const_iterator item = + _streamRenderMap.find(streamId); + if (item == _streamRenderMap.end()) + { + // This stream doesn't exist + WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, + "%s: stream doesn't exist", __FUNCTION__); + return -1; + } + assert(item->second != NULL); + return item->second->SetTimeoutImage(videoFrame, timeout); +} + +} // namespace webrtc |