| /* | 
 |  *  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 "video_engine/vie_render_manager.h" | 
 |  | 
 | #include "engine_configurations.h"  // NOLINT | 
 | #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 scope(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 |