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