Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / video_render / video_render_impl.cc
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/engine_configurations.h"
14 #include "webrtc/modules/video_render/external/video_render_external_impl.h"
15 #include "webrtc/modules/video_render/include/video_render_defines.h"
16 #include "webrtc/modules/video_render/incoming_video_stream.h"
17 #include "webrtc/modules/video_render/i_video_render.h"
18 #include "webrtc/modules/video_render/video_render_impl.h"
19 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
20 #include "webrtc/system_wrappers/interface/trace.h"
21
22 namespace webrtc {
23
24 VideoRender*
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
39 void VideoRender::DestroyVideoRender(
40                                                          VideoRender* module)
41 {
42     if (module)
43     {
44         delete module;
45     }
46 }
47
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
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
117 int32_t ModuleVideoRenderImpl::ChangeUniqueId(const int32_t id)
118 {
119
120     CriticalSectionScoped cs(&_moduleCrit);
121
122     _id = id;
123
124     if (_ptrRenderer)
125     {
126         _ptrRenderer->ChangeUniqueId(_id);
127     }
128
129     return 0;
130 }
131
132 int32_t ModuleVideoRenderImpl::TimeUntilNextProcess()
133 {
134     // Not used
135     return 50;
136 }
137 int32_t ModuleVideoRenderImpl::Process()
138 {
139     // Not used
140     return 0;
141 }
142
143 void*
144 ModuleVideoRenderImpl::Window()
145 {
146     CriticalSectionScoped cs(&_moduleCrit);
147     return _ptrWindow;
148 }
149
150 int32_t ModuleVideoRenderImpl::ChangeWindow(void* window)
151 {
152     return -1;
153 }
154
155 int32_t ModuleVideoRenderImpl::Id()
156 {
157     CriticalSectionScoped cs(&_moduleCrit);
158     return _id;
159 }
160
161 uint32_t ModuleVideoRenderImpl::GetIncomingFrameRate(const uint32_t streamId) {
162   CriticalSectionScoped cs(&_moduleCrit);
163
164   IncomingVideoStreamMap::iterator it = _streamRenderMap.find(streamId);
165
166   if (it == _streamRenderMap.end()) {
167     // This stream doesn't exist
168     WEBRTC_TRACE(kTraceError,
169                  kTraceVideoRenderer,
170                  _id,
171                  "%s: stream doesn't exist",
172                  __FUNCTION__);
173     return 0;
174   }
175   assert(it->second != NULL);
176   return it->second->IncomingRate();
177 }
178
179 VideoRenderCallback*
180 ModuleVideoRenderImpl::AddIncomingRenderStream(const uint32_t streamId,
181                                                const uint32_t zOrder,
182                                                const float left,
183                                                const float top,
184                                                const float right,
185                                                const float bottom)
186 {
187     CriticalSectionScoped cs(&_moduleCrit);
188
189     if (!_ptrRenderer)
190     {
191         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
192                      "%s: No renderer", __FUNCTION__);
193         return NULL;
194     }
195
196     if (_streamRenderMap.find(streamId) != _streamRenderMap.end()) {
197         // The stream already exists...
198         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
199                      "%s: stream already exists", __FUNCTION__);
200         return NULL;
201     }
202
203     VideoRenderCallback* ptrRenderCallback =
204             _ptrRenderer->AddIncomingRenderStream(streamId, zOrder, left, top,
205                                                   right, bottom);
206     if (ptrRenderCallback == NULL)
207     {
208         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
209                      "%s: Can't create incoming stream in renderer",
210                      __FUNCTION__);
211         return NULL;
212     }
213
214     // Create platform independant code
215     IncomingVideoStream* ptrIncomingStream = new IncomingVideoStream(_id,
216                                                                      streamId);
217     if (ptrIncomingStream == NULL)
218     {
219         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
220                      "%s: Can't create incoming stream", __FUNCTION__);
221         return NULL;
222     }
223
224
225     if (ptrIncomingStream->SetRenderCallback(ptrRenderCallback) == -1)
226     {
227         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
228                      "%s: Can't set render callback", __FUNCTION__);
229         delete ptrIncomingStream;
230         _ptrRenderer->DeleteIncomingRenderStream(streamId);
231         return NULL;
232     }
233
234     VideoRenderCallback* moduleCallback =
235             ptrIncomingStream->ModuleCallback();
236
237     // Store the stream
238     _streamRenderMap[streamId] = ptrIncomingStream;
239
240     return moduleCallback;
241 }
242
243 int32_t ModuleVideoRenderImpl::DeleteIncomingRenderStream(
244                                                                 const uint32_t streamId)
245 {
246     CriticalSectionScoped cs(&_moduleCrit);
247
248     if (!_ptrRenderer)
249     {
250         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
251                      "%s: No renderer", __FUNCTION__);
252         return -1;
253     }
254
255     IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
256     if (item == _streamRenderMap.end())
257     {
258         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
259                      "%s: stream doesn't exist", __FUNCTION__);
260         return -1;
261     }
262
263     delete item->second;
264
265     _ptrRenderer->DeleteIncomingRenderStream(streamId);
266
267     _streamRenderMap.erase(item);
268
269     return 0;
270 }
271
272 int32_t ModuleVideoRenderImpl::AddExternalRenderCallback(
273     const uint32_t streamId,
274     VideoRenderCallback* renderObject) {
275     CriticalSectionScoped cs(&_moduleCrit);
276
277     IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
278
279     if (item == _streamRenderMap.end())
280     {
281         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
282                      "%s: stream doesn't exist", __FUNCTION__);
283         return -1;
284     }
285
286     if (item->second == NULL) {
287         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
288                      "%s: could not get stream", __FUNCTION__);
289         return -1;
290     }
291     return item->second->SetExternalCallback(renderObject);
292 }
293
294 int32_t ModuleVideoRenderImpl::GetIncomingRenderStreamProperties(
295     const uint32_t streamId,
296     uint32_t& zOrder,
297     float& left,
298     float& top,
299     float& right,
300     float& bottom) const {
301     CriticalSectionScoped cs(&_moduleCrit);
302
303     if (!_ptrRenderer)
304     {
305         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
306                      "%s: No renderer", __FUNCTION__);
307         return -1;
308     }
309
310     return _ptrRenderer->GetIncomingRenderStreamProperties(streamId, zOrder,
311                                                            left, top, right,
312                                                            bottom);
313 }
314
315 uint32_t ModuleVideoRenderImpl::GetNumIncomingRenderStreams() const
316 {
317     CriticalSectionScoped cs(&_moduleCrit);
318
319     return static_cast<uint32_t>(_streamRenderMap.size());
320 }
321
322 bool ModuleVideoRenderImpl::HasIncomingRenderStream(
323     const uint32_t streamId) const {
324   CriticalSectionScoped cs(&_moduleCrit);
325
326   return _streamRenderMap.find(streamId) != _streamRenderMap.end();
327 }
328
329 int32_t ModuleVideoRenderImpl::RegisterRawFrameCallback(
330     const uint32_t streamId,
331     VideoRenderCallback* callbackObj) {
332   return -1;
333 }
334
335 int32_t ModuleVideoRenderImpl::StartRender(const uint32_t streamId)
336 {
337     CriticalSectionScoped cs(&_moduleCrit);
338
339     if (!_ptrRenderer)
340     {
341         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
342                      "%s: No renderer", __FUNCTION__);
343         return -1;
344     }
345
346     // Start the stream
347     IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
348
349     if (item == _streamRenderMap.end())
350     {
351         return -1;
352     }
353
354     if (item->second->Start() == -1)
355     {
356         return -1;
357     }
358
359     // Start the HW renderer
360     if (_ptrRenderer->StartRender() == -1)
361     {
362         return -1;
363     }
364     return 0;
365 }
366
367 int32_t ModuleVideoRenderImpl::StopRender(const uint32_t streamId)
368 {
369     CriticalSectionScoped cs(&_moduleCrit);
370
371     if (!_ptrRenderer)
372     {
373         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
374                      "%s(%d): No renderer", __FUNCTION__, streamId);
375         return -1;
376     }
377
378     // Stop the incoming stream
379     IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
380
381     if (item == _streamRenderMap.end())
382     {
383         return -1;
384     }
385
386     if (item->second->Stop() == -1)
387     {
388         return -1;
389     }
390
391     return 0;
392 }
393
394 int32_t ModuleVideoRenderImpl::ResetRender()
395 {
396     CriticalSectionScoped cs(&_moduleCrit);
397
398     int32_t ret = 0;
399     // Loop through all incoming streams and reset them
400     for (IncomingVideoStreamMap::iterator it = _streamRenderMap.begin();
401          it != _streamRenderMap.end();
402          ++it) {
403       if (it->second->Reset() == -1)
404         ret = -1;
405     }
406     return ret;
407 }
408
409 RawVideoType ModuleVideoRenderImpl::PreferredVideoType() const
410 {
411     CriticalSectionScoped cs(&_moduleCrit);
412
413     if (_ptrRenderer == NULL)
414     {
415         return kVideoI420;
416     }
417
418     return _ptrRenderer->PerferedVideoType();
419 }
420
421 bool ModuleVideoRenderImpl::IsFullScreen()
422 {
423     CriticalSectionScoped cs(&_moduleCrit);
424
425     if (!_ptrRenderer)
426     {
427         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
428                      "%s: No renderer", __FUNCTION__);
429         return false;
430     }
431     return _ptrRenderer->FullScreen();
432 }
433
434 int32_t ModuleVideoRenderImpl::GetScreenResolution(
435                                                          uint32_t& screenWidth,
436                                                          uint32_t& screenHeight) const
437 {
438     CriticalSectionScoped cs(&_moduleCrit);
439
440     if (!_ptrRenderer)
441     {
442         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
443                      "%s: No renderer", __FUNCTION__);
444         return false;
445     }
446     return _ptrRenderer->GetScreenResolution(screenWidth, screenHeight);
447 }
448
449 uint32_t ModuleVideoRenderImpl::RenderFrameRate(
450                                                       const uint32_t streamId)
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->RenderFrameRate(streamId);
461 }
462
463 int32_t ModuleVideoRenderImpl::SetStreamCropping(
464                                                        const uint32_t streamId,
465                                                        const float left,
466                                                        const float top,
467                                                        const float right,
468                                                        const float bottom)
469 {
470     CriticalSectionScoped cs(&_moduleCrit);
471
472     if (!_ptrRenderer)
473     {
474         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
475                      "%s: No renderer", __FUNCTION__);
476         return false;
477     }
478     return _ptrRenderer->SetStreamCropping(streamId, left, top, right, bottom);
479 }
480
481 int32_t ModuleVideoRenderImpl::SetTransparentBackground(const bool enable)
482 {
483     CriticalSectionScoped cs(&_moduleCrit);
484
485     if (!_ptrRenderer)
486     {
487         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
488                      "%s: No renderer", __FUNCTION__);
489         return false;
490     }
491     return _ptrRenderer->SetTransparentBackground(enable);
492 }
493
494 int32_t ModuleVideoRenderImpl::FullScreenRender(void* window, const bool enable)
495 {
496     return -1;
497 }
498
499 int32_t ModuleVideoRenderImpl::SetText(
500                                              const uint8_t textId,
501                                              const uint8_t* text,
502                                              const int32_t textLength,
503                                              const uint32_t textColorRef,
504                                              const uint32_t backgroundColorRef,
505                                              const float left, const float top,
506                                              const float right,
507                                              const float bottom)
508 {
509     CriticalSectionScoped cs(&_moduleCrit);
510
511     if (!_ptrRenderer)
512     {
513         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
514                      "%s: No renderer", __FUNCTION__);
515         return -1;
516     }
517     return _ptrRenderer->SetText(textId, text, textLength, textColorRef,
518                                  backgroundColorRef, left, top, right, bottom);
519 }
520
521 int32_t ModuleVideoRenderImpl::SetBitmap(const void* bitMap,
522                                          const uint8_t pictureId,
523                                          const void* colorKey,
524                                          const float left,
525                                          const float top,
526                                          const float right,
527                                          const float bottom)
528 {
529     CriticalSectionScoped cs(&_moduleCrit);
530
531     if (!_ptrRenderer)
532     {
533         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
534                      "%s: No renderer", __FUNCTION__);
535         return -1;
536     }
537     return _ptrRenderer->SetBitmap(bitMap, pictureId, colorKey, left, top,
538                                    right, bottom);
539 }
540
541 int32_t ModuleVideoRenderImpl::GetLastRenderedFrame(
542     const uint32_t streamId,
543     I420VideoFrame &frame) const
544 {
545     CriticalSectionScoped cs(&_moduleCrit);
546
547     if (!_ptrRenderer)
548     {
549         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
550                      "%s: No renderer", __FUNCTION__);
551         return -1;
552     }
553
554     IncomingVideoStreamMap::const_iterator item =
555         _streamRenderMap.find(streamId);
556     if (item == _streamRenderMap.end())
557     {
558         // This stream doesn't exist
559         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
560                      "%s: stream doesn't exist", __FUNCTION__);
561         return 0;
562     }
563
564     assert(item->second != NULL);
565     return item->second->GetLastRenderedFrame(frame);
566 }
567
568 int32_t ModuleVideoRenderImpl::SetExpectedRenderDelay(
569     uint32_t stream_id, int32_t delay_ms) {
570   CriticalSectionScoped cs(&_moduleCrit);
571
572   if (!_ptrRenderer) {
573     WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
574                  "%s: No renderer", __FUNCTION__);
575     return false;
576   }
577
578   IncomingVideoStreamMap::const_iterator item =
579       _streamRenderMap.find(stream_id);
580   if (item == _streamRenderMap.end()) {
581     // This stream doesn't exist
582     WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
583                  "%s(%u, %d): stream doesn't exist", __FUNCTION__, stream_id,
584                  delay_ms);
585     return -1;
586   }
587
588   assert(item->second != NULL);
589   return item->second->SetExpectedRenderDelay(delay_ms);
590 }
591
592 int32_t ModuleVideoRenderImpl::ConfigureRenderer(
593                                                        const uint32_t streamId,
594                                                        const unsigned int zOrder,
595                                                        const float left,
596                                                        const float top,
597                                                        const float right,
598                                                        const float bottom)
599 {
600     CriticalSectionScoped cs(&_moduleCrit);
601
602     if (!_ptrRenderer)
603     {
604         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
605                      "%s: No renderer", __FUNCTION__);
606         return false;
607     }
608     return _ptrRenderer->ConfigureRenderer(streamId, zOrder, left, top, right,
609                                            bottom);
610 }
611
612 int32_t ModuleVideoRenderImpl::SetStartImage(
613     const uint32_t streamId,
614     const I420VideoFrame& videoFrame)
615 {
616     CriticalSectionScoped cs(&_moduleCrit);
617
618     if (!_ptrRenderer)
619     {
620         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
621                      "%s: No renderer", __FUNCTION__);
622         return -1;
623     }
624
625     IncomingVideoStreamMap::const_iterator item =
626         _streamRenderMap.find(streamId);
627     if (item == _streamRenderMap.end())
628     {
629         // This stream doesn't exist
630         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
631                      "%s: stream doesn't exist", __FUNCTION__);
632         return -1;
633     }
634     assert (item->second != NULL);
635     return item->second->SetStartImage(videoFrame);
636
637 }
638
639 int32_t ModuleVideoRenderImpl::SetTimeoutImage(
640     const uint32_t streamId,
641     const I420VideoFrame& videoFrame,
642     const uint32_t timeout)
643 {
644     CriticalSectionScoped cs(&_moduleCrit);
645
646     if (!_ptrRenderer)
647     {
648         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
649                      "%s: No renderer", __FUNCTION__);
650         return -1;
651     }
652
653     IncomingVideoStreamMap::const_iterator item =
654         _streamRenderMap.find(streamId);
655     if (item == _streamRenderMap.end())
656     {
657         // This stream doesn't exist
658         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
659                      "%s: stream doesn't exist", __FUNCTION__);
660         return -1;
661     }
662     assert(item->second != NULL);
663     return item->second->SetTimeoutImage(videoFrame, timeout);
664 }
665
666 int32_t ModuleVideoRenderImpl::MirrorRenderStream(const int renderId,
667                                                   const bool enable,
668                                                   const bool mirrorXAxis,
669                                                   const bool mirrorYAxis)
670 {
671     CriticalSectionScoped cs(&_moduleCrit);
672
673     if (!_ptrRenderer)
674     {
675         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
676                      "%s: No renderer", __FUNCTION__);
677         return -1;
678     }
679
680     IncomingVideoStreamMap::const_iterator item =
681         _streamRenderMap.find(renderId);
682     if (item == _streamRenderMap.end())
683     {
684         // This stream doesn't exist
685         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
686                      "%s: stream doesn't exist", __FUNCTION__);
687         return 0;
688     }
689     assert(item->second != NULL);
690
691     return item->second->EnableMirroring(enable, mirrorXAxis, mirrorYAxis);
692 }
693
694 }  // namespace webrtc