/* * 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 (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