| /* |
| * 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 "video_engine/vie_render_manager.h" |
| |
| #include "engine_configurations.h" |
| #include "modules/video_render/main/interface/video_render.h" |
| #include "modules/video_render/main/interface/video_render_defines.h" |
| #include "system_wrappers/interface/critical_section_wrapper.h" |
| #include "system_wrappers/interface/rw_lock_wrapper.h" |
| #include "system_wrappers/interface/trace.h" |
| #include "video_engine/vie_defines.h" |
| #include "video_engine/vie_renderer.h" |
| |
| namespace webrtc { |
| |
| ViERenderManagerScoped::ViERenderManagerScoped( |
| const ViERenderManager& vie_render_manager) |
| : ViEManagerScopedBase(vie_render_manager) { |
| } |
| |
| ViERenderer* ViERenderManagerScoped::Renderer(WebRtc_Word32 render_id) const { |
| return static_cast<const ViERenderManager*>(vie_manager_)->ViERenderPtr( |
| render_id); |
| } |
| |
| ViERenderManager::ViERenderManager(WebRtc_Word32 engine_id) |
| : list_cs_(CriticalSectionWrapper::CreateCriticalSection()), |
| engine_id_(engine_id), |
| use_external_render_module_(false) { |
| WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo, ViEId(engine_id), |
| "ViERenderManager::ViERenderManager(engine_id: %d) - " |
| "Constructor", engine_id); |
| } |
| |
| ViERenderManager::~ViERenderManager() { |
| WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo, ViEId(engine_id_), |
| "ViERenderManager Destructor, engine_id: %d", engine_id_); |
| |
| while (stream_to_vie_renderer_.Size() != 0) { |
| MapItem* item = stream_to_vie_renderer_.First(); |
| assert(item); |
| const WebRtc_Word32 render_id = item->GetId(); |
| // The renderer is delete in RemoveRenderStream. |
| item = NULL; |
| RemoveRenderStream(render_id); |
| } |
| } |
| |
| WebRtc_Word32 ViERenderManager::RegisterVideoRenderModule( |
| VideoRender& render_module) { |
| // See if there is already a render module registered for the window that |
| // the registrant render module is associated with. |
| VideoRender* current_module = FindRenderModule(render_module.Window()); |
| if (current_module) { |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_), |
| "A module is already registered for this window (window=%p, " |
| "current module=%p, registrant module=%p.", |
| render_module.Window(), current_module, &render_module); |
| return -1; |
| } |
| |
| // Register module. |
| render_list_.PushBack(static_cast<void*>(&render_module)); |
| use_external_render_module_ = true; |
| return 0; |
| } |
| |
| WebRtc_Word32 ViERenderManager::DeRegisterVideoRenderModule( |
| VideoRender& render_module) { |
| // Check if there are streams in the module. |
| WebRtc_UWord32 n_streams = render_module.GetNumIncomingRenderStreams(); |
| if (n_streams != 0) { |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_), |
| "There are still %d streams in this module, cannot " |
| "de-register", n_streams); |
| 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; |
| } |
| } |
| if (!found) { |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_), |
| "Module not registered"); |
| return -1; |
| } |
| return 0; |
| } |
| |
| ViERenderer* ViERenderManager::AddRenderStream(const WebRtc_Word32 render_id, |
| void* window, |
| const WebRtc_UWord32 z_order, |
| const float left, |
| const float top, |
| const float right, |
| const float bottom) { |
| CriticalSectionScoped cs(list_cs_.get()); |
| |
| if (stream_to_vie_renderer_.Find(render_id) != NULL) { |
| // This stream is already added to a renderer, not allowed! |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_), |
| "Render stream already exists"); |
| return NULL; |
| } |
| |
| // Get the render module for this window. |
| VideoRender* render_module = FindRenderModule(window); |
| if (render_module == NULL) { |
| // No render module for this window, create a new one. |
| render_module = VideoRender::CreateVideoRender(ViEModuleId(engine_id_, -1), |
| window, false); |
| if (!render_module) { |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(engine_id_), |
| "Could not create new render module"); |
| return NULL; |
| } |
| render_list_.PushBack(static_cast<void*>(render_module)); |
| } |
| |
| ViERenderer* vie_renderer = ViERenderer::CreateViERenderer(render_id, |
| engine_id_, |
| *render_module, |
| *this, z_order, |
| left, top, right, |
| bottom); |
| if (!vie_renderer) { |
| WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, |
| ViEId(engine_id_, render_id), |
| "Could not create new render stream"); |
| return NULL; |
| } |
| stream_to_vie_renderer_.Insert(render_id, vie_renderer); |
| return vie_renderer; |
| } |
| |
| WebRtc_Word32 ViERenderManager::RemoveRenderStream( |
| const WebRtc_Word32 render_id) { |
| // We need exclusive right to the items in the render manager to delete a |
| // stream. |
| ViEManagerWriteScoped(*this); |
| |
| CriticalSectionScoped cs(list_cs_.get()); |
| MapItem* map_item = stream_to_vie_renderer_.Find(render_id); |
| if (!map_item) { |
| // No such stream |
| WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo, ViEId(engine_id_), |
| "No renderer for this stream found, channel_id"); |
| return 0; |
| } |
| |
| ViERenderer* vie_renderer = static_cast<ViERenderer*>(map_item->GetItem()); |
| assert(vie_renderer); |
| |
| // Get the render module pointer for this vie_render object. |
| VideoRender& renderer = vie_renderer->RenderModule(); |
| |
| // Delete the vie_render. |
| // This deletes the stream in the render module. |
| delete vie_renderer; |
| |
| // Remove from the stream map. |
| stream_to_vie_renderer_.Erase(map_item); |
| |
| // Check if there are other streams in the module. |
| 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())) { |
| // We've found our renderer. |
| render_list_.Erase(list_item); |
| break; |
| } |
| } |
| // Destroy the module. |
| VideoRender::DestroyVideoRender(&renderer); |
| } |
| return 0; |
| } |
| |
| 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) { |
| // We've found the render module. |
| break; |
| } |
| renderer = NULL; |
| } |
| return renderer; |
| } |
| |
| ViERenderer* ViERenderManager::ViERenderPtr(WebRtc_Word32 render_id) const { |
| ViERenderer* renderer = NULL; |
| MapItem* map_item = stream_to_vie_renderer_.Find(render_id); |
| if (!map_item) { |
| // No such stream in any renderer. |
| return NULL; |
| } |
| renderer = static_cast<ViERenderer*>(map_item->GetItem()); |
| |
| return renderer; |
| } |
| |
| } // namespace webrtc |