blob: 260a3b8b793eae93212d458d40ee73afbad24f97 [file] [log] [blame]
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +00001/*
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 "video_engine/vie_render_impl.h"
12
13#include "engine_configurations.h" // NOLINT
andrew@webrtc.orgb43b6112012-10-31 05:22:11 +000014#include "webrtc/modules/video_render/include/video_render.h"
15#include "webrtc/modules/video_render/include/video_render_defines.h"
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000016#include "system_wrappers/interface/trace.h"
17#include "video_engine/include/vie_errors.h"
18#include "video_engine/vie_capturer.h"
19#include "video_engine/vie_channel.h"
20#include "video_engine/vie_channel_manager.h"
21#include "video_engine/vie_defines.h"
22#include "video_engine/vie_frame_provider_base.h"
23#include "video_engine/vie_impl.h"
24#include "video_engine/vie_input_manager.h"
25#include "video_engine/vie_render_manager.h"
26#include "video_engine/vie_renderer.h"
27#include "video_engine/vie_shared_data.h"
28
29namespace webrtc {
30
31ViERender* ViERender::GetInterface(VideoEngine* video_engine) {
32#ifdef WEBRTC_VIDEO_ENGINE_RENDER_API
33 if (!video_engine) {
34 return NULL;
35 }
andrew@webrtc.orgd3d364e2013-05-09 02:12:07 +000036 VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000037 ViERenderImpl* vie_render_impl = vie_impl;
38 // Increase ref count.
39 (*vie_render_impl)++;
40 return vie_render_impl;
41#else
42 return NULL;
43#endif
44}
45
46int ViERenderImpl::Release() {
47 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, shared_data_->instance_id(),
48 "ViERender::Release()");
49 // Decrease ref count
50 (*this)--;
pbos@webrtc.org2a5d2292013-04-09 13:41:51 +000051 int32_t ref_count = GetCount();
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000052 if (ref_count < 0) {
53 WEBRTC_TRACE(kTraceWarning, kTraceVideo, shared_data_->instance_id(),
54 "ViERender release too many times");
55 return -1;
56 }
57 WEBRTC_TRACE(kTraceInfo, kTraceVideo, shared_data_->instance_id(),
58 "ViERender reference count: %d", ref_count);
59 return ref_count;
60}
61
62ViERenderImpl::ViERenderImpl(ViESharedData* shared_data)
63 : shared_data_(shared_data) {
64 WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_->instance_id(),
65 "ViERenderImpl::ViERenderImpl() Ctor");
66}
67
68ViERenderImpl::~ViERenderImpl() {
69 WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_->instance_id(),
70 "ViERenderImpl::~ViERenderImpl() Dtor");
71}
72
73int ViERenderImpl::RegisterVideoRenderModule(
74 VideoRender& render_module) {
75 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
76 "%s (&render_module: %p)", __FUNCTION__, &render_module);
77 if (shared_data_->render_manager()->RegisterVideoRenderModule(
78 &render_module) != 0) {
79 shared_data_->SetLastError(kViERenderUnknownError);
80 return -1;
81 }
82 return 0;
83}
84
85int ViERenderImpl::DeRegisterVideoRenderModule(
86 VideoRender& render_module) {
87 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
88 "%s (&render_module: %p)", __FUNCTION__, &render_module);
89 if (shared_data_->render_manager()->DeRegisterVideoRenderModule(
90 &render_module) != 0) {
91 // Error logging is done in ViERenderManager::DeRegisterVideoRenderModule.
92 shared_data_->SetLastError(kViERenderUnknownError);
93 return -1;
94 }
95 return 0;
96}
97
98int ViERenderImpl::AddRenderer(const int render_id, void* window,
99 const unsigned int z_order, const float left,
100 const float top, const float right,
101 const float bottom) {
102 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
103 "%s (render_id: %d, window: 0x%p, z_order: %u, left: %f, "
104 "top: %f, right: %f, bottom: %f)",
105 __FUNCTION__, render_id, window, z_order, left, top, right,
106 bottom);
107 if (!shared_data_->Initialized()) {
108 shared_data_->SetLastError(kViENotInitialized);
109 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
110 "%s - ViE instance %d not initialized", __FUNCTION__,
111 shared_data_->instance_id());
112 return -1;
113 }
114 {
115 ViERenderManagerScoped rs(*(shared_data_->render_manager()));
116 if (rs.Renderer(render_id)) {
117 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
118 "%s - Renderer already exist %d.", __FUNCTION__,
119 render_id);
120 shared_data_->SetLastError(kViERenderAlreadyExists);
121 return -1;
122 }
123 }
124 if (render_id >= kViEChannelIdBase && render_id <= kViEChannelIdMax) {
125 // This is a channel.
126 ViEChannelManagerScoped cm(*(shared_data_->channel_manager()));
127 ViEFrameProviderBase* frame_provider = cm.Channel(render_id);
128 if (!frame_provider) {
129 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
130 "%s: FrameProvider id %d doesn't exist", __FUNCTION__,
131 render_id);
132 shared_data_->SetLastError(kViERenderInvalidRenderId);
133 return -1;
134 }
135 ViERenderer* renderer = shared_data_->render_manager()->AddRenderStream(
136 render_id, window, z_order, left, top, right, bottom);
137 if (!renderer) {
138 shared_data_->SetLastError(kViERenderUnknownError);
139 return -1;
140 }
141 return frame_provider->RegisterFrameCallback(render_id, renderer);
142 } else {
143 // Camera or file.
144 ViEInputManagerScoped is(*(shared_data_->input_manager()));
145 ViEFrameProviderBase* frame_provider = is.FrameProvider(render_id);
146 if (!frame_provider) {
147 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
148 "%s: FrameProvider id %d doesn't exist", __FUNCTION__,
149 render_id);
150 shared_data_->SetLastError(kViERenderInvalidRenderId);
151 return -1;
152 }
153 ViERenderer* renderer = shared_data_->render_manager()->AddRenderStream(
154 render_id, window, z_order, left, top, right, bottom);
155 if (!renderer) {
156 shared_data_->SetLastError(kViERenderUnknownError);
157 return -1;
158 }
159 return frame_provider->RegisterFrameCallback(render_id, renderer);
160 }
161}
162
163int ViERenderImpl::RemoveRenderer(const int render_id) {
164 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
165 "%s(render_id: %d)", __FUNCTION__, render_id);
166 if (!shared_data_->Initialized()) {
167 shared_data_->SetLastError(kViENotInitialized);
168 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
169 "%s - ViE instance %d not initialized", __FUNCTION__,
170 shared_data_->instance_id());
171 return -1;
172 }
173
174 ViERenderer* renderer = NULL;
175 {
176 ViERenderManagerScoped rs(*(shared_data_->render_manager()));
177 renderer = rs.Renderer(render_id);
178 if (!renderer) {
179 WEBRTC_TRACE(kTraceWarning, kTraceVideo,
180 ViEId(shared_data_->instance_id()),
181 "%s No render exist with render_id: %d", __FUNCTION__,
182 render_id);
183 shared_data_->SetLastError(kViERenderInvalidRenderId);
184 return -1;
185 }
186 // Leave the scope lock since we don't want to lock two managers
187 // simultanousely.
188 }
189 if (render_id >= kViEChannelIdBase && render_id <= kViEChannelIdMax) {
190 // This is a channel.
191 ViEChannelManagerScoped cm(*(shared_data_->channel_manager()));
192 ViEChannel* channel = cm.Channel(render_id);
193 if (!channel) {
194 WEBRTC_TRACE(kTraceWarning, kTraceVideo,
195 ViEId(shared_data_->instance_id()),
196 "%s: no channel with id %d exists ", __FUNCTION__,
197 render_id);
198 shared_data_->SetLastError(kViERenderInvalidRenderId);
199 return -1;
200 }
201 channel->DeregisterFrameCallback(renderer);
202 } else {
203 // Provider owned by inputmanager, i.e. file or capture device.
204 ViEInputManagerScoped is(*(shared_data_->input_manager()));
205 ViEFrameProviderBase* provider = is.FrameProvider(render_id);
206 if (!provider) {
207 WEBRTC_TRACE(kTraceWarning, kTraceVideo,
208 ViEId(shared_data_->instance_id()),
209 "%s: no provider with id %d exists ", __FUNCTION__,
210 render_id);
211 shared_data_->SetLastError(kViERenderInvalidRenderId);
212 return -1;
213 }
214 provider->DeregisterFrameCallback(renderer);
215 }
216 if (shared_data_->render_manager()->RemoveRenderStream(render_id) != 0) {
217 shared_data_->SetLastError(kViERenderUnknownError);
218 return -1;
219 }
220 return 0;
221}
222
223int ViERenderImpl::StartRender(const int render_id) {
224 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
225 ViEId(shared_data_->instance_id(), render_id),
226 "%s(channel: %d)", __FUNCTION__, render_id);
227 ViERenderManagerScoped rs(*(shared_data_->render_manager()));
228 ViERenderer* renderer = rs.Renderer(render_id);
229 if (!renderer) {
230 WEBRTC_TRACE(kTraceError, kTraceVideo,
231 ViEId(shared_data_->instance_id(), render_id),
232 "%s: No renderer with render Id %d exist.", __FUNCTION__,
233 render_id);
234 shared_data_->SetLastError(kViERenderInvalidRenderId);
235 return -1;
236 }
237 if (renderer->StartRender() != 0) {
238 shared_data_->SetLastError(kViERenderUnknownError);
239 return -1;
240 }
241 return 0;
242}
243
244int ViERenderImpl::StopRender(const int render_id) {
245 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
246 ViEId(shared_data_->instance_id(), render_id),
247 "%s(channel: %d)", __FUNCTION__, render_id);
248 ViERenderManagerScoped rs(*(shared_data_->render_manager()));
249 ViERenderer* renderer = rs.Renderer(render_id);
250 if (!renderer) {
251 WEBRTC_TRACE(kTraceError, kTraceVideo,
252 ViEId(shared_data_->instance_id(), render_id),
253 "%s: No renderer with render_id %d exist.", __FUNCTION__,
254 render_id);
255 shared_data_->SetLastError(kViERenderInvalidRenderId);
256 return -1;
257 }
258 if (renderer->StopRender() != 0) {
259 shared_data_->SetLastError(kViERenderUnknownError);
260 return -1;
261 }
262 return 0;
263}
264
265int ViERenderImpl::SetExpectedRenderDelay(int render_id, int render_delay) {
266 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
267 ViEId(shared_data_->instance_id(), render_id),
268 "%s(channel: %d)", __FUNCTION__, render_id);
269 ViERenderManagerScoped rs(*(shared_data_->render_manager()));
270 ViERenderer* renderer = rs.Renderer(render_id);
271 if (!renderer) {
272 WEBRTC_TRACE(kTraceError, kTraceVideo,
273 ViEId(shared_data_->instance_id(), render_id),
274 "%s: No renderer with render_id %d exist.", __FUNCTION__,
275 render_id);
276 shared_data_->SetLastError(kViERenderInvalidRenderId);
277 return -1;
278 }
279 if (renderer->SetExpectedRenderDelay(render_delay) != 0) {
280 shared_data_->SetLastError(kViERenderUnknownError);
281 return -1;
282 }
283 return 0;
284}
285
286int ViERenderImpl::ConfigureRender(int render_id, const unsigned int z_order,
287 const float left, const float top,
288 const float right, const float bottom) {
289 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
290 ViEId(shared_data_->instance_id(), render_id),
291 "%s(channel: %d)", __FUNCTION__, render_id);
292 ViERenderManagerScoped rs(*(shared_data_->render_manager()));
293 ViERenderer* renderer = rs.Renderer(render_id);
294 if (!renderer) {
295 WEBRTC_TRACE(kTraceError, kTraceVideo,
296 ViEId(shared_data_->instance_id(), render_id),
297 "%s: No renderer with render_id %d exist.", __FUNCTION__,
298 render_id);
299 shared_data_->SetLastError(kViERenderInvalidRenderId);
300 return -1;
301 }
302
303 if (renderer->ConfigureRenderer(z_order, left, top, right, bottom) != 0) {
304 shared_data_->SetLastError(kViERenderUnknownError);
305 return -1;
306 }
307 return 0;
308}
309
310int ViERenderImpl::MirrorRenderStream(const int render_id, const bool enable,
311 const bool mirror_xaxis,
312 const bool mirror_yaxis) {
313 ViERenderManagerScoped rs(*(shared_data_->render_manager()));
314 ViERenderer* renderer = rs.Renderer(render_id);
315 if (!renderer) {
316 WEBRTC_TRACE(kTraceError, kTraceVideo,
317 ViEId(shared_data_->instance_id(), render_id),
318 "%s: No renderer with render_id %d exist.", __FUNCTION__,
319 render_id);
320 shared_data_->SetLastError(kViERenderInvalidRenderId);
321 return -1;
322 }
323 if (renderer->EnableMirroring(render_id, enable, mirror_xaxis, mirror_yaxis)
324 != 0) {
325 shared_data_->SetLastError(kViERenderUnknownError);
326 return -1;
327 }
328 return 0;
329}
330
331int ViERenderImpl::AddRenderer(const int render_id,
332 RawVideoType video_input_format,
333 ExternalRenderer* external_renderer) {
334 // Check if the client requested a format that we can convert the frames to.
335 if (video_input_format != kVideoI420 &&
336 video_input_format != kVideoYV12 &&
337 video_input_format != kVideoYUY2 &&
338 video_input_format != kVideoUYVY &&
339 video_input_format != kVideoARGB &&
340 video_input_format != kVideoRGB24 &&
341 video_input_format != kVideoRGB565 &&
342 video_input_format != kVideoARGB4444 &&
343 video_input_format != kVideoARGB1555) {
344 WEBRTC_TRACE(kTraceError, kTraceVideo,
345 ViEId(shared_data_->instance_id(), render_id),
346 "%s: Unsupported video frame format requested",
347 __FUNCTION__, render_id);
348 shared_data_->SetLastError(kViERenderInvalidFrameFormat);
349 return -1;
350 }
351 if (!shared_data_->Initialized()) {
352 shared_data_->SetLastError(kViENotInitialized);
353 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
354 "%s - ViE instance %d not initialized", __FUNCTION__,
355 shared_data_->instance_id());
356 return -1;
357 }
358 {
359 // Verify the renderer doesn't exist.
360 ViERenderManagerScoped rs(*(shared_data_->render_manager()));
361 if (rs.Renderer(render_id)) {
362 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
363 "%s - Renderer already exist %d.", __FUNCTION__,
364 render_id);
365 shared_data_->SetLastError(kViERenderAlreadyExists);
366 return -1;
367 }
368 }
369 if (render_id >= kViEChannelIdBase && render_id <= kViEChannelIdMax) {
370 // This is a channel.
371 ViEChannelManagerScoped cm(*(shared_data_->channel_manager()));
372 ViEFrameProviderBase* frame_provider = cm.Channel(render_id);
373 if (!frame_provider) {
374 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
375 "%s: FrameProvider id %d doesn't exist", __FUNCTION__,
376 render_id);
377 shared_data_->SetLastError(kViERenderInvalidRenderId);
378 return -1;
379 }
380 ViERenderer* renderer = shared_data_->render_manager()->AddRenderStream(
381 render_id, NULL, 0, 0.0f, 0.0f, 1.0f, 1.0f);
382 if (!renderer) {
383 shared_data_->SetLastError(kViERenderUnknownError);
384 return -1;
385 }
386 if (renderer->SetExternalRenderer(render_id, video_input_format,
387 external_renderer) == -1) {
388 shared_data_->SetLastError(kViERenderUnknownError);
389 return -1;
390 }
391
392 return frame_provider->RegisterFrameCallback(render_id, renderer);
393 } else {
394 // Camera or file.
395 ViEInputManagerScoped is(*(shared_data_->input_manager()));
396 ViEFrameProviderBase* frame_provider = is.FrameProvider(render_id);
397 if (!frame_provider) {
398 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(shared_data_->instance_id()),
399 "%s: FrameProvider id %d doesn't exist", __FUNCTION__,
400 render_id);
401 shared_data_->SetLastError(kViERenderInvalidRenderId);
402 return -1;
403 }
404 ViERenderer* renderer = shared_data_->render_manager()->AddRenderStream(
405 render_id, NULL, 0, 0.0f, 0.0f, 1.0f, 1.0f);
406 if (!renderer) {
407 shared_data_->SetLastError(kViERenderUnknownError);
408 return -1;
409 }
410 if (renderer->SetExternalRenderer(render_id, video_input_format,
411 external_renderer) == -1) {
412 shared_data_->SetLastError(kViERenderUnknownError);
413 return -1;
414 }
415 return frame_provider->RegisterFrameCallback(render_id, renderer);
416 }
417}
418
419} // namespace webrtc