1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/video_engine/vie_render_manager.h"
12
13#include "webrtc/engine_configurations.h"
14#include "webrtc/modules/video_render/include/video_render.h"
15#include "webrtc/modules/video_render/include/video_render_defines.h"
16#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
17#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
18#include "webrtc/system_wrappers/interface/logging.h"
19#include "webrtc/video_engine/vie_defines.h"
20#include "webrtc/video_engine/vie_renderer.h"
21
22namespace webrtc {
23
24ViERenderManagerScoped::ViERenderManagerScoped(
25    const ViERenderManager& vie_render_manager)
26    : ViEManagerScopedBase(vie_render_manager) {
27}
28
29ViERenderer* ViERenderManagerScoped::Renderer(int32_t render_id) const {
30  return static_cast<const ViERenderManager*>(vie_manager_)->ViERenderPtr(
31           render_id);
32}
33
34ViERenderManager::ViERenderManager(int32_t engine_id)
35    : list_cs_(CriticalSectionWrapper::CreateCriticalSection()),
36      engine_id_(engine_id),
37      use_external_render_module_(false) {
38}
39
40ViERenderManager::~ViERenderManager() {
41  for (RendererMap::iterator it = stream_to_vie_renderer_.begin();
42       it != stream_to_vie_renderer_.end();
43       ++it) {
44    // The renderer is deleted in RemoveRenderStream.
45    RemoveRenderStream(it->first);
46  }
47}
48
49int32_t ViERenderManager::RegisterVideoRenderModule(
50    VideoRender* render_module) {
51  // See if there is already a render module registered for the window that
52  // the registrant render module is associated with.
53  VideoRender* current_module = FindRenderModule(render_module->Window());
54  if (current_module) {
55    LOG_F(LS_ERROR) << "A render module is already registered for this window.";
56    return -1;
57  }
58
59  // Register module.
60  render_list_.push_back(render_module);
61  use_external_render_module_ = true;
62  return 0;
63}
64
65int32_t ViERenderManager::DeRegisterVideoRenderModule(
66    VideoRender* render_module) {
67  // Check if there are streams in the module.
68  uint32_t n_streams = render_module->GetNumIncomingRenderStreams();
69  if (n_streams != 0) {
70    LOG(LS_ERROR) << "There are still " << n_streams
71                  << "in this module, cannot de-register.";
72    return -1;
73  }
74
75  for (RenderList::iterator iter = render_list_.begin();
76       iter != render_list_.end(); ++iter) {
77    if (render_module == *iter) {
78      // We've found our renderer. Erase the render module from the map.
79      render_list_.erase(iter);
80      return 0;
81    }
82  }
83
84  LOG(LS_ERROR) << "Module not registered.";
85  return -1;
86}
87
88ViERenderer* ViERenderManager::AddRenderStream(const int32_t render_id,
89                                               void* window,
90                                               const uint32_t z_order,
91                                               const float left,
92                                               const float top,
93                                               const float right,
94                                               const float bottom) {
95  CriticalSectionScoped cs(list_cs_.get());
96
97  if (stream_to_vie_renderer_.find(render_id) !=
98      stream_to_vie_renderer_.end()) {
99    LOG(LS_ERROR) << "Render stream already exists";
100    return NULL;
101  }
102
103  // Get the render module for this window.
104  VideoRender* render_module = FindRenderModule(window);
105  if (render_module == NULL) {
106    // No render module for this window, create a new one.
107    render_module = VideoRender::CreateVideoRender(ViEModuleId(engine_id_, -1),
108                                                  window, false);
109    if (!render_module)
110      return NULL;
111
112    render_list_.push_back(render_module);
113  }
114
115  ViERenderer* vie_renderer = ViERenderer::CreateViERenderer(render_id,
116                                                             engine_id_,
117                                                             *render_module,
118                                                             *this, z_order,
119                                                             left, top, right,
120                                                             bottom);
121  if (!vie_renderer)
122    return NULL;
123
124  stream_to_vie_renderer_[render_id] = vie_renderer;
125  return vie_renderer;
126}
127
128int32_t ViERenderManager::RemoveRenderStream(
129    const int32_t render_id) {
130  // We need exclusive right to the items in the render manager to delete a
131  // stream.
132  ViEManagerWriteScoped scope(this);
133  CriticalSectionScoped cs(list_cs_.get());
134  RendererMap::iterator it = stream_to_vie_renderer_.find(render_id);
135  if (it == stream_to_vie_renderer_.end()) {
136    LOG(LS_ERROR) << "No renderer found for render_id: " << render_id;
137    return 0;
138  }
139
140  // Get the render module pointer for this vie_render object.
141  VideoRender& renderer = it->second->RenderModule();
142
143  // Delete the vie_render.
144  // This deletes the stream in the render module.
145  delete it->second;
146
147  // Remove from the stream map.
148  stream_to_vie_renderer_.erase(it);
149
150  // Check if there are other streams in the module.
151  if (!use_external_render_module_ &&
152      renderer.GetNumIncomingRenderStreams() == 0) {
153    // Erase the render module from the map.
154    for (RenderList::iterator iter = render_list_.begin();
155         iter != render_list_.end(); ++iter) {
156      if (&renderer == *iter) {
157        // We've found our renderer.
158        render_list_.erase(iter);
159        break;
160      }
161    }
162    // Destroy the module.
163    VideoRender::DestroyVideoRender(&renderer);
164  }
165  return 0;
166}
167
168VideoRender* ViERenderManager::FindRenderModule(void* window) {
169  for (RenderList::iterator iter = render_list_.begin();
170       iter != render_list_.end(); ++iter) {
171    if ((*iter)->Window() == window) {
172      // We've found the render module.
173      return *iter;
174    }
175  }
176  return NULL;
177}
178
179ViERenderer* ViERenderManager::ViERenderPtr(int32_t render_id) const {
180  RendererMap::const_iterator it = stream_to_vie_renderer_.find(render_id);
181  if (it == stream_to_vie_renderer_.end())
182    return NULL;
183
184  return it->second;
185}
186
187}  // namespace webrtc
188