| /* |
| * 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. |
| */ |
| |
| /* |
| * vie_render_impl.cc |
| */ |
| |
| #include "vie_render_impl.h" |
| |
| // Defines |
| #include "engine_configurations.h" |
| #include "vie_defines.h" |
| |
| #include "trace.h" |
| #include "video_render.h" |
| #include "video_render_defines.h" |
| #include "vie_errors.h" |
| #include "vie_impl.h" |
| #include "vie_capturer.h" |
| #include "vie_channel.h" |
| #include "vie_frame_provider_base.h" |
| #include "vie_channel_manager.h" |
| #include "vie_input_manager.h" |
| #include "vie_render_manager.h" |
| |
| namespace webrtc |
| { |
| |
| // ---------------------------------------------------------------------------- |
| // GetInterface |
| // ---------------------------------------------------------------------------- |
| |
| ViERender* ViERender::GetInterface(VideoEngine* videoEngine) |
| { |
| #ifdef WEBRTC_VIDEO_ENGINE_RENDER_API |
| if (videoEngine == NULL) |
| { |
| return NULL; |
| } |
| VideoEngineImpl* vieImpl = reinterpret_cast<VideoEngineImpl*> (videoEngine); |
| ViERenderImpl* vieRenderImpl = vieImpl; |
| (*vieRenderImpl)++; // Increase ref count |
| |
| return vieRenderImpl; |
| #else |
| return NULL; |
| #endif |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // Release |
| // |
| // Releases the interface, i.e. reduces the reference counter. The number of |
| // remaining references is returned, -1 if released too many times. |
| // ---------------------------------------------------------------------------- |
| |
| int ViERenderImpl::Release() |
| { |
| WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, _instanceId, |
| "ViERender::Release()"); |
| (*this)--; // Decrease ref count |
| |
| WebRtc_Word32 refCount = GetCount(); |
| if (refCount < 0) |
| { |
| WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo, _instanceId, |
| "ViERender release too many times"); |
| // SetLastError() |
| return -1; |
| } |
| WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, _instanceId, |
| "ViERender reference count: %d", refCount); |
| return refCount; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // Constructor |
| // ---------------------------------------------------------------------------- |
| |
| ViERenderImpl::ViERenderImpl() |
| { |
| WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo, _instanceId, |
| "ViERenderImpl::ViERenderImpl() Ctor"); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // Destructor |
| // ---------------------------------------------------------------------------- |
| |
| ViERenderImpl::~ViERenderImpl() |
| { |
| WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo, _instanceId, |
| "ViERenderImpl::~ViERenderImpl() Dtor"); |
| } |
| |
| // ============================================================================ |
| // Registration of render module |
| // ============================================================================ |
| |
| // ---------------------------------------------------------------------------- |
| // RegisterVideoRenderModule |
| // |
| // Registers a video render module, must be called before |
| // AddRenderer is called for an input stream associated |
| // with the same window as the module. |
| // ---------------------------------------------------------------------------- |
| |
| int ViERenderImpl::RegisterVideoRenderModule( |
| VideoRender& renderModule) |
| { |
| WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s (&renderModule: %p)", __FUNCTION__, &renderModule); |
| |
| if (_renderManager.RegisterVideoRenderModule(renderModule) != 0) |
| { |
| // Error logging is done in RegisterVideoRenderModule |
| SetLastError(kViERenderUnknownError); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // DeRegisterVideoRenderModule |
| // |
| // De-registers a video render module, must be called after |
| // RemoveRenderer has been called for all input streams associated |
| // with the same window as the module. |
| // ---------------------------------------------------------------------------- |
| |
| int ViERenderImpl::DeRegisterVideoRenderModule( |
| VideoRender& renderModule) |
| { |
| WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s (&renderModule: %p)", __FUNCTION__, &renderModule); |
| if (_renderManager.DeRegisterVideoRenderModule(renderModule) != 0) |
| { |
| // Error logging is done in DeRegisterVideoRenderModule |
| SetLastError(kViERenderUnknownError); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| // ============================================================================ |
| // Add renderer |
| // ============================================================================ |
| |
| int ViERenderImpl::AddRenderer(const int renderId, void* window, |
| const unsigned int zOrder, const float left, |
| const float top, const float right, |
| const float bottom) |
| { |
| WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s (renderId: %d, window: 0x%p, zOrder: %u, left: %f, " |
| "top: %f, right: %f, bottom: %f)", |
| __FUNCTION__, renderId, window, zOrder, left, top, right, |
| bottom); |
| if (!IsInitialized()) |
| { |
| SetLastError(kViENotInitialized); |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s - ViE instance %d not initialized", __FUNCTION__, |
| _instanceId); |
| return -1; |
| } |
| |
| { // Check if the renderer exist already |
| ViERenderManagerScoped rs(_renderManager); |
| if (rs.Renderer(renderId) != NULL) |
| { |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s - Renderer already exist %d.", __FUNCTION__, |
| renderId); |
| SetLastError(kViERenderAlreadyExists); |
| return -1; |
| } |
| } |
| |
| if (renderId >= kViEChannelIdBase && renderId <= kViEChannelIdMax) |
| { |
| // This is a channel |
| ViEChannelManagerScoped cm(_channelManager); |
| ViEFrameProviderBase* frameProvider = cm.Channel(renderId); |
| if (frameProvider == NULL) |
| { |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s: FrameProvider id %d doesn't exist", __FUNCTION__, |
| renderId); |
| SetLastError(kViERenderInvalidRenderId); |
| return -1; |
| } |
| ViERenderer* renderer = _renderManager.AddRenderStream(renderId, |
| window, zOrder, |
| left, top, |
| right, bottom); |
| if (renderer == NULL) |
| { |
| SetLastError(kViERenderUnknownError); |
| return -1; |
| } |
| return frameProvider->RegisterFrameCallback(renderId, renderer); |
| } |
| else // camera or file |
| { |
| ViEInputManagerScoped is(_inputManager); |
| ViEFrameProviderBase* frameProvider = is.FrameProvider(renderId); |
| if (frameProvider == NULL) |
| { |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s: FrameProvider id %d doesn't exist", __FUNCTION__, |
| renderId); |
| SetLastError(kViERenderInvalidRenderId); |
| return -1; |
| } |
| ViERenderer* renderer = _renderManager.AddRenderStream(renderId, |
| window, zOrder, |
| left, top, |
| right, bottom); |
| if (renderer == NULL) |
| { |
| SetLastError(kViERenderUnknownError); |
| return -1; |
| } |
| return frameProvider->RegisterFrameCallback(renderId, renderer); |
| } |
| SetLastError(kViERenderInvalidRenderId); |
| return -1; |
| |
| } |
| |
| int ViERenderImpl::RemoveRenderer(const int renderId) |
| { |
| WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s(renderId: %d)", __FUNCTION__, renderId); |
| if (!IsInitialized()) |
| { |
| SetLastError(kViENotInitialized); |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s - ViE instance %d not initialized", __FUNCTION__, |
| _instanceId); |
| return -1; |
| } |
| |
| ViERenderer* renderer = NULL; |
| { |
| ViERenderManagerScoped rs(_renderManager); |
| renderer = rs.Renderer(renderId); |
| if (!renderer) |
| { |
| WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s No render exist with renderId: %d", __FUNCTION__, |
| renderId); |
| SetLastError(kViERenderInvalidRenderId); |
| return -1; |
| } |
| } // Leave the scope lock since we don't want to lock two managers |
| // simultanousely |
| |
| if (renderId >= kViEChannelIdBase && renderId <= kViEChannelIdMax) |
| { |
| // This is a channel |
| ViEChannelManagerScoped cm(_channelManager); |
| ViEChannel* channel = cm.Channel(renderId); |
| if (!channel) |
| { |
| WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s: no channel with id %d exists ", __FUNCTION__, |
| renderId); |
| SetLastError(kViERenderInvalidRenderId); |
| return -1; |
| } |
| channel->DeregisterFrameCallback(renderer); |
| } |
| else //Provider owned by inputmanager - ie file or capture device |
| { |
| ViEInputManagerScoped is(_inputManager); |
| ViEFrameProviderBase* provider = is.FrameProvider(renderId); |
| if (!provider) |
| { |
| WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s: no provider with id %d exists ", __FUNCTION__, |
| renderId); |
| SetLastError(kViERenderInvalidRenderId); |
| return -1; |
| } |
| provider->DeregisterFrameCallback(renderer); |
| |
| } |
| if (_renderManager.RemoveRenderStream(renderId) != 0) |
| { |
| SetLastError(kViERenderUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| // ============================================================================ |
| // Start/stop |
| // ============================================================================ |
| |
| // ---------------------------------------------------------------------------- |
| // StartRender |
| // |
| // Starts rendering the stream from the channel |
| // ---------------------------------------------------------------------------- |
| |
| int ViERenderImpl::StartRender(const int renderId) |
| { |
| WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, |
| ViEId(_instanceId, renderId), "%s(channel: %d)", __FUNCTION__, |
| renderId); |
| |
| ViERenderManagerScoped rs(_renderManager); |
| ViERenderer* ptrRender = rs.Renderer(renderId); |
| if (ptrRender == NULL) |
| { |
| // No renderer for this channel |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, |
| ViEId(_instanceId, renderId), |
| "%s: No renderer with render Id %d exist.", __FUNCTION__, |
| renderId); |
| SetLastError(kViERenderInvalidRenderId); |
| return -1; |
| } |
| |
| if (ptrRender->StartRender() != 0) |
| { |
| SetLastError(kViERenderUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // StopRender |
| // |
| // Stop rendering a stream |
| // ---------------------------------------------------------------------------- |
| |
| int ViERenderImpl::StopRender(const int renderId) |
| { |
| WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, |
| ViEId(_instanceId, renderId), "%s(channel: %d)", __FUNCTION__, |
| renderId); |
| |
| ViERenderManagerScoped rs(_renderManager); |
| ViERenderer* ptrRender = rs.Renderer(renderId); |
| if (ptrRender == NULL) |
| { |
| // No renderer for this channel |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, |
| ViEId(_instanceId, renderId), |
| "%s: No renderer with renderId %d exist.", __FUNCTION__, |
| renderId); |
| SetLastError(kViERenderInvalidRenderId); |
| return -1; |
| } |
| if (ptrRender->StopRender() != 0) |
| { |
| SetLastError(kViERenderUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| // ============================================================================ |
| // Stream configurations |
| // ============================================================================ |
| |
| // ---------------------------------------------------------------------------- |
| // ConfigureRender |
| // |
| // Reconfigures an already added render stream |
| // ---------------------------------------------------------------------------- |
| |
| int ViERenderImpl::ConfigureRender(int renderId, const unsigned int zOrder, |
| const float left, const float top, |
| const float right, const float bottom) |
| { |
| WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, ViEId(_instanceId, renderId), |
| "%s(channel: %d)", __FUNCTION__, renderId); |
| |
| ViERenderManagerScoped rs(_renderManager); |
| ViERenderer* ptrRender = rs.Renderer(renderId); |
| if (ptrRender == NULL) |
| { |
| // No renderer for this channel |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, |
| ViEId(_instanceId, renderId), |
| "%s: No renderer with renderId %d exist.", __FUNCTION__, |
| renderId); |
| SetLastError(kViERenderInvalidRenderId); |
| return -1; |
| } |
| |
| if (ptrRender->ConfigureRenderer(zOrder, left, top, right, bottom) != 0) |
| { |
| SetLastError(kViERenderUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // MirrorRenderStream |
| // |
| // Enables mirror rendering |
| // ---------------------------------------------------------------------------- |
| |
| int ViERenderImpl::MirrorRenderStream(const int renderId, const bool enable, |
| const bool mirrorXAxis, |
| const bool mirrorYAxis) |
| { |
| ViERenderManagerScoped rs(_renderManager); |
| ViERenderer* ptrRender = rs.Renderer(renderId); |
| if (ptrRender == NULL) |
| { |
| // No renderer for this channel |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, |
| ViEId(_instanceId, renderId), |
| "%s: No renderer with renderId %d exist.", __FUNCTION__, |
| renderId); |
| SetLastError(kViERenderInvalidRenderId); |
| return -1; |
| } |
| if (ptrRender->EnableMirroring(renderId, enable, mirrorXAxis, mirrorYAxis) |
| != 0) |
| { |
| SetLastError(kViERenderUnknownError); |
| return -1; |
| } |
| return 0; |
| } |
| |
| // ============================================================================ |
| // External render |
| // ============================================================================ |
| |
| |
| // ---------------------------------------------------------------------------- |
| // |
| // |
| // AddRenderer |
| // ---------------------------------------------------------------------------- |
| |
| int ViERenderImpl::AddRenderer(const int renderId, |
| webrtc::RawVideoType videoInputFormat, |
| ExternalRenderer* externalRenderer) |
| { |
| // check if the client requested a format that we can convert the frames to |
| if (videoInputFormat != webrtc::kVideoI420 |
| && videoInputFormat != webrtc::kVideoYV12 |
| && videoInputFormat != webrtc::kVideoYUY2 |
| && videoInputFormat != webrtc::kVideoUYVY |
| && videoInputFormat != webrtc::kVideoARGB |
| && videoInputFormat != webrtc::kVideoRGB24 |
| && videoInputFormat != webrtc::kVideoRGB565 |
| && videoInputFormat != webrtc::kVideoARGB4444 |
| && videoInputFormat != webrtc::kVideoARGB1555) |
| { |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, |
| ViEId(_instanceId, renderId), |
| "%s: Unsupported video frame format requested", |
| __FUNCTION__, renderId); |
| SetLastError(kViERenderInvalidFrameFormat); |
| return -1; |
| } |
| |
| if (!IsInitialized()) |
| { |
| SetLastError(kViENotInitialized); |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s - ViE instance %d not initialized", __FUNCTION__, |
| _instanceId); |
| return -1; |
| } |
| |
| { // Check if the renderer exist already |
| ViERenderManagerScoped rs(_renderManager); |
| if (rs.Renderer(renderId) != NULL) |
| { |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s - Renderer already exist %d.", __FUNCTION__, |
| renderId); |
| SetLastError(kViERenderAlreadyExists); |
| return -1; |
| } |
| } |
| |
| if (renderId >= kViEChannelIdBase && renderId <= kViEChannelIdMax) |
| { |
| // This is a channel |
| ViEChannelManagerScoped cm(_channelManager); |
| ViEFrameProviderBase* frameProvider = cm.Channel(renderId); |
| if (frameProvider == NULL) |
| { |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s: FrameProvider id %d doesn't exist", __FUNCTION__, |
| renderId); |
| SetLastError(kViERenderInvalidRenderId); |
| return -1; |
| } |
| ViERenderer* ptrRender = _renderManager.AddRenderStream(renderId, NULL, |
| 0, 0.0f, 0.0f, |
| 1.0f, 1.0f); |
| if (ptrRender == NULL) |
| { |
| SetLastError(kViERenderUnknownError); |
| return -1; |
| } |
| if (-1 == ptrRender->SetExternalRenderer(renderId, videoInputFormat, |
| externalRenderer)) |
| { |
| SetLastError(kViERenderUnknownError); |
| return -1; |
| } |
| |
| return frameProvider->RegisterFrameCallback(renderId, ptrRender); |
| } |
| else // camera or file |
| { |
| ViEInputManagerScoped is(_inputManager); |
| ViEFrameProviderBase* frameProvider = is.FrameProvider(renderId); |
| if (frameProvider == NULL) |
| { |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId), |
| "%s: FrameProvider id %d doesn't exist", __FUNCTION__, |
| renderId); |
| SetLastError(kViERenderInvalidRenderId); |
| return -1; |
| } |
| ViERenderer* ptrRender = _renderManager.AddRenderStream(renderId, NULL, |
| 0, 0.0f, 0.0f, |
| 1.0f, 1.0f); |
| if (ptrRender == NULL) |
| { |
| SetLastError(kViERenderUnknownError); |
| return -1; |
| } |
| if (-1 == ptrRender->SetExternalRenderer(renderId, videoInputFormat, |
| externalRenderer)) |
| { |
| SetLastError(kViERenderUnknownError); |
| return -1; |
| } |
| return frameProvider->RegisterFrameCallback(renderId, ptrRender); |
| } |
| SetLastError(kViERenderInvalidRenderId); |
| return -1; |
| |
| } |
| |
| } // namespace webrtc |