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
22namespace webrtc {
23
24VideoRender*
25VideoRender::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
39void VideoRender::DestroyVideoRender(
40                                                         VideoRender* module)
41{
42    if (module)
43    {
44        delete module;
45    }
46}
47
48ModuleVideoRenderImpl::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
83ModuleVideoRenderImpl::~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
117int64_t ModuleVideoRenderImpl::TimeUntilNextProcess()
118{
119    // Not used
120    return 50;
121}
122int32_t ModuleVideoRenderImpl::Process()
123{
124    // Not used
125    return 0;
126}
127
128void*
129ModuleVideoRenderImpl::Window()
130{
131    CriticalSectionScoped cs(&_moduleCrit);
132    return _ptrWindow;
133}
134
135int32_t ModuleVideoRenderImpl::ChangeWindow(void* window)
136{
137    return -1;
138}
139
140int32_t ModuleVideoRenderImpl::Id()
141{
142    CriticalSectionScoped cs(&_moduleCrit);
143    return _id;
144}
145
146uint32_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
164VideoRenderCallback*
165ModuleVideoRenderImpl::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
211int32_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
240int32_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
263int32_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
284uint32_t ModuleVideoRenderImpl::GetNumIncomingRenderStreams() const
285{
286    CriticalSectionScoped cs(&_moduleCrit);
287
288    return static_cast<uint32_t>(_streamRenderMap.size());
289}
290
291bool ModuleVideoRenderImpl::HasIncomingRenderStream(
292    const uint32_t streamId) const {
293  CriticalSectionScoped cs(&_moduleCrit);
294
295  return _streamRenderMap.find(streamId) != _streamRenderMap.end();
296}
297
298int32_t ModuleVideoRenderImpl::RegisterRawFrameCallback(
299    const uint32_t streamId,
300    VideoRenderCallback* callbackObj) {
301  return -1;
302}
303
304int32_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
336int32_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
363int32_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
378RawVideoType 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
390bool 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
403int32_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
418uint32_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
432int32_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
450int32_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
463int32_t ModuleVideoRenderImpl::FullScreenRender(void* window, const bool enable)
464{
465    return -1;
466}
467
468int32_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
490int32_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
510int32_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
534int32_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
554int32_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
579int32_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