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 <assert.h>
12
13 #include "webrtc/common_video/include/incoming_video_stream.h"
14 #include "webrtc/engine_configurations.h"
15 #include "webrtc/modules/video_render/external/video_render_external_impl.h"
16 #include "webrtc/modules/video_render/i_video_render.h"
17 #include "webrtc/modules/video_render/video_render_defines.h"
18 #include "webrtc/modules/video_render/video_render_impl.h"
19 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
20 #include "webrtc/system_wrappers/include/trace.h"
21
22 namespace webrtc {
23
24 VideoRender*
CreateVideoRender(const int32_t id,void * window,const bool fullscreen,const VideoRenderType videoRenderType)25 VideoRender::CreateVideoRender(const int32_t id,
26 void* window,
27 const bool fullscreen,
28 const VideoRenderType videoRenderType/*=kRenderDefault*/)
29 {
30 VideoRenderType resultVideoRenderType = videoRenderType;
31 if (videoRenderType == kRenderDefault)
32 {
33 resultVideoRenderType = kRenderExternal;
34 }
35 return new ModuleVideoRenderImpl(id, resultVideoRenderType, window,
36 fullscreen);
37 }
38
DestroyVideoRender(VideoRender * module)39 void VideoRender::DestroyVideoRender(
40 VideoRender* module)
41 {
42 if (module)
43 {
44 delete module;
45 }
46 }
47
ModuleVideoRenderImpl(const int32_t id,const VideoRenderType videoRenderType,void * window,const bool fullscreen)48 ModuleVideoRenderImpl::ModuleVideoRenderImpl(
49 const int32_t id,
50 const VideoRenderType videoRenderType,
51 void* window,
52 const bool fullscreen) :
53 _id(id), _moduleCrit(*CriticalSectionWrapper::CreateCriticalSection()),
54 _ptrWindow(window), _fullScreen(fullscreen), _ptrRenderer(NULL)
55 {
56
57 // Create platform specific renderer
58 switch (videoRenderType)
59 {
60 case kRenderExternal:
61 {
62 VideoRenderExternalImpl* ptrRenderer(NULL);
63 ptrRenderer = new VideoRenderExternalImpl(_id, videoRenderType,
64 window, _fullScreen);
65 if (ptrRenderer)
66 {
67 _ptrRenderer = reinterpret_cast<IVideoRender*> (ptrRenderer);
68 }
69 }
70 break;
71 default:
72 // Error...
73 break;
74 }
75 if (_ptrRenderer)
76 {
77 if (_ptrRenderer->Init() == -1)
78 {
79 }
80 }
81 }
82
~ModuleVideoRenderImpl()83 ModuleVideoRenderImpl::~ModuleVideoRenderImpl()
84 {
85 delete &_moduleCrit;
86
87 for (IncomingVideoStreamMap::iterator it = _streamRenderMap.begin();
88 it != _streamRenderMap.end();
89 ++it) {
90 delete it->second;
91 }
92
93 // Delete platform specific renderer
94 if (_ptrRenderer)
95 {
96 VideoRenderType videoRenderType = _ptrRenderer->RenderType();
97
98 switch (videoRenderType)
99 {
100 case kRenderExternal:
101 {
102 VideoRenderExternalImpl
103 * ptrRenderer =
104 reinterpret_cast<VideoRenderExternalImpl*> (_ptrRenderer);
105 _ptrRenderer = NULL;
106 delete ptrRenderer;
107 }
108 break;
109
110 default:
111 // Error...
112 break;
113 }
114 }
115 }
116
TimeUntilNextProcess()117 int64_t ModuleVideoRenderImpl::TimeUntilNextProcess()
118 {
119 // Not used
120 return 50;
121 }
Process()122 int32_t ModuleVideoRenderImpl::Process()
123 {
124 // Not used
125 return 0;
126 }
127
128 void*
Window()129 ModuleVideoRenderImpl::Window()
130 {
131 CriticalSectionScoped cs(&_moduleCrit);
132 return _ptrWindow;
133 }
134
ChangeWindow(void * window)135 int32_t ModuleVideoRenderImpl::ChangeWindow(void* window)
136 {
137 return -1;
138 }
139
Id()140 int32_t ModuleVideoRenderImpl::Id()
141 {
142 CriticalSectionScoped cs(&_moduleCrit);
143 return _id;
144 }
145
GetIncomingFrameRate(const uint32_t streamId)146 uint32_t ModuleVideoRenderImpl::GetIncomingFrameRate(const uint32_t streamId) {
147 CriticalSectionScoped cs(&_moduleCrit);
148
149 IncomingVideoStreamMap::iterator it = _streamRenderMap.find(streamId);
150
151 if (it == _streamRenderMap.end()) {
152 // This stream doesn't exist
153 WEBRTC_TRACE(kTraceError,
154 kTraceVideoRenderer,
155 _id,
156 "%s: stream doesn't exist",
157 __FUNCTION__);
158 return 0;
159 }
160 assert(it->second != NULL);
161 return it->second->IncomingRate();
162 }
163
164 VideoRenderCallback*
AddIncomingRenderStream(const uint32_t streamId,const uint32_t zOrder,const float left,const float top,const float right,const float bottom)165 ModuleVideoRenderImpl::AddIncomingRenderStream(const uint32_t streamId,
166 const uint32_t zOrder,
167 const float left,
168 const float top,
169 const float right,
170 const float bottom)
171 {
172 CriticalSectionScoped cs(&_moduleCrit);
173
174 if (!_ptrRenderer)
175 {
176 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
177 "%s: No renderer", __FUNCTION__);
178 return NULL;
179 }
180
181 if (_streamRenderMap.find(streamId) != _streamRenderMap.end()) {
182 // The stream already exists...
183 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
184 "%s: stream already exists", __FUNCTION__);
185 return NULL;
186 }
187
188 VideoRenderCallback* ptrRenderCallback =
189 _ptrRenderer->AddIncomingRenderStream(streamId, zOrder, left, top,
190 right, bottom);
191 if (ptrRenderCallback == NULL)
192 {
193 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
194 "%s: Can't create incoming stream in renderer",
195 __FUNCTION__);
196 return NULL;
197 }
198
199 // Create platform independant code
200 IncomingVideoStream* ptrIncomingStream =
201 new IncomingVideoStream(streamId, false);
202 ptrIncomingStream->SetRenderCallback(ptrRenderCallback);
203 VideoRenderCallback* moduleCallback = ptrIncomingStream->ModuleCallback();
204
205 // Store the stream
206 _streamRenderMap[streamId] = ptrIncomingStream;
207
208 return moduleCallback;
209 }
210
DeleteIncomingRenderStream(const uint32_t streamId)211 int32_t ModuleVideoRenderImpl::DeleteIncomingRenderStream(
212 const uint32_t streamId)
213 {
214 CriticalSectionScoped cs(&_moduleCrit);
215
216 if (!_ptrRenderer)
217 {
218 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
219 "%s: No renderer", __FUNCTION__);
220 return -1;
221 }
222
223 IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
224 if (item == _streamRenderMap.end())
225 {
226 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
227 "%s: stream doesn't exist", __FUNCTION__);
228 return -1;
229 }
230
231 delete item->second;
232
233 _ptrRenderer->DeleteIncomingRenderStream(streamId);
234
235 _streamRenderMap.erase(item);
236
237 return 0;
238 }
239
AddExternalRenderCallback(const uint32_t streamId,VideoRenderCallback * renderObject)240 int32_t ModuleVideoRenderImpl::AddExternalRenderCallback(
241 const uint32_t streamId,
242 VideoRenderCallback* renderObject) {
243 CriticalSectionScoped cs(&_moduleCrit);
244
245 IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
246
247 if (item == _streamRenderMap.end())
248 {
249 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
250 "%s: stream doesn't exist", __FUNCTION__);
251 return -1;
252 }
253
254 if (item->second == NULL) {
255 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
256 "%s: could not get stream", __FUNCTION__);
257 return -1;
258 }
259 item->second->SetExternalCallback(renderObject);
260 return 0;
261 }
262
GetIncomingRenderStreamProperties(const uint32_t streamId,uint32_t & zOrder,float & left,float & top,float & right,float & bottom) const263 int32_t ModuleVideoRenderImpl::GetIncomingRenderStreamProperties(
264 const uint32_t streamId,
265 uint32_t& zOrder,
266 float& left,
267 float& top,
268 float& right,
269 float& bottom) const {
270 CriticalSectionScoped cs(&_moduleCrit);
271
272 if (!_ptrRenderer)
273 {
274 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
275 "%s: No renderer", __FUNCTION__);
276 return -1;
277 }
278
279 return _ptrRenderer->GetIncomingRenderStreamProperties(streamId, zOrder,
280 left, top, right,
281 bottom);
282 }
283
GetNumIncomingRenderStreams() const284 uint32_t ModuleVideoRenderImpl::GetNumIncomingRenderStreams() const
285 {
286 CriticalSectionScoped cs(&_moduleCrit);
287
288 return static_cast<uint32_t>(_streamRenderMap.size());
289 }
290
HasIncomingRenderStream(const uint32_t streamId) const291 bool ModuleVideoRenderImpl::HasIncomingRenderStream(
292 const uint32_t streamId) const {
293 CriticalSectionScoped cs(&_moduleCrit);
294
295 return _streamRenderMap.find(streamId) != _streamRenderMap.end();
296 }
297
RegisterRawFrameCallback(const uint32_t streamId,VideoRenderCallback * callbackObj)298 int32_t ModuleVideoRenderImpl::RegisterRawFrameCallback(
299 const uint32_t streamId,
300 VideoRenderCallback* callbackObj) {
301 return -1;
302 }
303
StartRender(const uint32_t streamId)304 int32_t ModuleVideoRenderImpl::StartRender(const uint32_t streamId)
305 {
306 CriticalSectionScoped cs(&_moduleCrit);
307
308 if (!_ptrRenderer)
309 {
310 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
311 "%s: No renderer", __FUNCTION__);
312 return -1;
313 }
314
315 // Start the stream
316 IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
317
318 if (item == _streamRenderMap.end())
319 {
320 return -1;
321 }
322
323 if (item->second->Start() == -1)
324 {
325 return -1;
326 }
327
328 // Start the HW renderer
329 if (_ptrRenderer->StartRender() == -1)
330 {
331 return -1;
332 }
333 return 0;
334 }
335
StopRender(const uint32_t streamId)336 int32_t ModuleVideoRenderImpl::StopRender(const uint32_t streamId)
337 {
338 CriticalSectionScoped cs(&_moduleCrit);
339
340 if (!_ptrRenderer)
341 {
342 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
343 "%s(%d): No renderer", __FUNCTION__, streamId);
344 return -1;
345 }
346
347 // Stop the incoming stream
348 IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
349
350 if (item == _streamRenderMap.end())
351 {
352 return -1;
353 }
354
355 if (item->second->Stop() == -1)
356 {
357 return -1;
358 }
359
360 return 0;
361 }
362
ResetRender()363 int32_t ModuleVideoRenderImpl::ResetRender()
364 {
365 CriticalSectionScoped cs(&_moduleCrit);
366
367 int32_t ret = 0;
368 // Loop through all incoming streams and reset them
369 for (IncomingVideoStreamMap::iterator it = _streamRenderMap.begin();
370 it != _streamRenderMap.end();
371 ++it) {
372 if (it->second->Reset() == -1)
373 ret = -1;
374 }
375 return ret;
376 }
377
PreferredVideoType() const378 RawVideoType ModuleVideoRenderImpl::PreferredVideoType() const
379 {
380 CriticalSectionScoped cs(&_moduleCrit);
381
382 if (_ptrRenderer == NULL)
383 {
384 return kVideoI420;
385 }
386
387 return _ptrRenderer->PerferedVideoType();
388 }
389
IsFullScreen()390 bool ModuleVideoRenderImpl::IsFullScreen()
391 {
392 CriticalSectionScoped cs(&_moduleCrit);
393
394 if (!_ptrRenderer)
395 {
396 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
397 "%s: No renderer", __FUNCTION__);
398 return false;
399 }
400 return _ptrRenderer->FullScreen();
401 }
402
GetScreenResolution(uint32_t & screenWidth,uint32_t & screenHeight) const403 int32_t ModuleVideoRenderImpl::GetScreenResolution(
404 uint32_t& screenWidth,
405 uint32_t& screenHeight) const
406 {
407 CriticalSectionScoped cs(&_moduleCrit);
408
409 if (!_ptrRenderer)
410 {
411 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
412 "%s: No renderer", __FUNCTION__);
413 return false;
414 }
415 return _ptrRenderer->GetScreenResolution(screenWidth, screenHeight);
416 }
417
RenderFrameRate(const uint32_t streamId)418 uint32_t ModuleVideoRenderImpl::RenderFrameRate(
419 const uint32_t streamId)
420 {
421 CriticalSectionScoped cs(&_moduleCrit);
422
423 if (!_ptrRenderer)
424 {
425 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
426 "%s: No renderer", __FUNCTION__);
427 return false;
428 }
429 return _ptrRenderer->RenderFrameRate(streamId);
430 }
431
SetStreamCropping(const uint32_t streamId,const float left,const float top,const float right,const float bottom)432 int32_t ModuleVideoRenderImpl::SetStreamCropping(
433 const uint32_t streamId,
434 const float left,
435 const float top,
436 const float right,
437 const float bottom)
438 {
439 CriticalSectionScoped cs(&_moduleCrit);
440
441 if (!_ptrRenderer)
442 {
443 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
444 "%s: No renderer", __FUNCTION__);
445 return false;
446 }
447 return _ptrRenderer->SetStreamCropping(streamId, left, top, right, bottom);
448 }
449
SetTransparentBackground(const bool enable)450 int32_t ModuleVideoRenderImpl::SetTransparentBackground(const bool enable)
451 {
452 CriticalSectionScoped cs(&_moduleCrit);
453
454 if (!_ptrRenderer)
455 {
456 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
457 "%s: No renderer", __FUNCTION__);
458 return false;
459 }
460 return _ptrRenderer->SetTransparentBackground(enable);
461 }
462
FullScreenRender(void * window,const bool enable)463 int32_t ModuleVideoRenderImpl::FullScreenRender(void* window, const bool enable)
464 {
465 return -1;
466 }
467
SetText(const uint8_t textId,const uint8_t * text,const int32_t textLength,const uint32_t textColorRef,const uint32_t backgroundColorRef,const float left,const float top,const float right,const float bottom)468 int32_t ModuleVideoRenderImpl::SetText(
469 const uint8_t textId,
470 const uint8_t* text,
471 const int32_t textLength,
472 const uint32_t textColorRef,
473 const uint32_t backgroundColorRef,
474 const float left, const float top,
475 const float right,
476 const float bottom)
477 {
478 CriticalSectionScoped cs(&_moduleCrit);
479
480 if (!_ptrRenderer)
481 {
482 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
483 "%s: No renderer", __FUNCTION__);
484 return -1;
485 }
486 return _ptrRenderer->SetText(textId, text, textLength, textColorRef,
487 backgroundColorRef, left, top, right, bottom);
488 }
489
SetBitmap(const void * bitMap,const uint8_t pictureId,const void * colorKey,const float left,const float top,const float right,const float bottom)490 int32_t ModuleVideoRenderImpl::SetBitmap(const void* bitMap,
491 const uint8_t pictureId,
492 const void* colorKey,
493 const float left,
494 const float top,
495 const float right,
496 const float bottom)
497 {
498 CriticalSectionScoped cs(&_moduleCrit);
499
500 if (!_ptrRenderer)
501 {
502 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
503 "%s: No renderer", __FUNCTION__);
504 return -1;
505 }
506 return _ptrRenderer->SetBitmap(bitMap, pictureId, colorKey, left, top,
507 right, bottom);
508 }
509
SetExpectedRenderDelay(uint32_t stream_id,int32_t delay_ms)510 int32_t ModuleVideoRenderImpl::SetExpectedRenderDelay(
511 uint32_t stream_id, int32_t delay_ms) {
512 CriticalSectionScoped cs(&_moduleCrit);
513
514 if (!_ptrRenderer) {
515 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
516 "%s: No renderer", __FUNCTION__);
517 return false;
518 }
519
520 IncomingVideoStreamMap::const_iterator item =
521 _streamRenderMap.find(stream_id);
522 if (item == _streamRenderMap.end()) {
523 // This stream doesn't exist
524 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
525 "%s(%u, %d): stream doesn't exist", __FUNCTION__, stream_id,
526 delay_ms);
527 return -1;
528 }
529
530 assert(item->second != NULL);
531 return item->second->SetExpectedRenderDelay(delay_ms);
532 }
533
ConfigureRenderer(const uint32_t streamId,const unsigned int zOrder,const float left,const float top,const float right,const float bottom)534 int32_t ModuleVideoRenderImpl::ConfigureRenderer(
535 const uint32_t streamId,
536 const unsigned int zOrder,
537 const float left,
538 const float top,
539 const float right,
540 const float bottom)
541 {
542 CriticalSectionScoped cs(&_moduleCrit);
543
544 if (!_ptrRenderer)
545 {
546 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
547 "%s: No renderer", __FUNCTION__);
548 return false;
549 }
550 return _ptrRenderer->ConfigureRenderer(streamId, zOrder, left, top, right,
551 bottom);
552 }
553
SetStartImage(const uint32_t streamId,const VideoFrame & videoFrame)554 int32_t ModuleVideoRenderImpl::SetStartImage(const uint32_t streamId,
555 const VideoFrame& videoFrame) {
556 CriticalSectionScoped cs(&_moduleCrit);
557
558 if (!_ptrRenderer)
559 {
560 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
561 "%s: No renderer", __FUNCTION__);
562 return -1;
563 }
564
565 IncomingVideoStreamMap::const_iterator item =
566 _streamRenderMap.find(streamId);
567 if (item == _streamRenderMap.end())
568 {
569 // This stream doesn't exist
570 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
571 "%s: stream doesn't exist", __FUNCTION__);
572 return -1;
573 }
574 assert (item->second != NULL);
575 return item->second->SetStartImage(videoFrame);
576
577 }
578
SetTimeoutImage(const uint32_t streamId,const VideoFrame & videoFrame,const uint32_t timeout)579 int32_t ModuleVideoRenderImpl::SetTimeoutImage(const uint32_t streamId,
580 const VideoFrame& videoFrame,
581 const uint32_t timeout) {
582 CriticalSectionScoped cs(&_moduleCrit);
583
584 if (!_ptrRenderer)
585 {
586 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
587 "%s: No renderer", __FUNCTION__);
588 return -1;
589 }
590
591 IncomingVideoStreamMap::const_iterator item =
592 _streamRenderMap.find(streamId);
593 if (item == _streamRenderMap.end())
594 {
595 // This stream doesn't exist
596 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
597 "%s: stream doesn't exist", __FUNCTION__);
598 return -1;
599 }
600 assert(item->second != NULL);
601 return item->second->SetTimeoutImage(videoFrame, timeout);
602 }
603
604 } // namespace webrtc
605