video_render_impl.cc revision 4052d881620f3f79a63df3d779f93d6124a5dc63
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
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 = new IncomingVideoStream(_id,
201                                                                     streamId);
202    if (ptrIncomingStream == NULL)
203    {
204        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
205                     "%s: Can't create incoming stream", __FUNCTION__);
206        return NULL;
207    }
208
209
210    if (ptrIncomingStream->SetRenderCallback(ptrRenderCallback) == -1)
211    {
212        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
213                     "%s: Can't set render callback", __FUNCTION__);
214        delete ptrIncomingStream;
215        _ptrRenderer->DeleteIncomingRenderStream(streamId);
216        return NULL;
217    }
218
219    VideoRenderCallback* moduleCallback =
220            ptrIncomingStream->ModuleCallback();
221
222    // Store the stream
223    _streamRenderMap[streamId] = ptrIncomingStream;
224
225    return moduleCallback;
226}
227
228int32_t ModuleVideoRenderImpl::DeleteIncomingRenderStream(
229                                                                const uint32_t streamId)
230{
231    CriticalSectionScoped cs(&_moduleCrit);
232
233    if (!_ptrRenderer)
234    {
235        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
236                     "%s: No renderer", __FUNCTION__);
237        return -1;
238    }
239
240    IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
241    if (item == _streamRenderMap.end())
242    {
243        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
244                     "%s: stream doesn't exist", __FUNCTION__);
245        return -1;
246    }
247
248    delete item->second;
249
250    _ptrRenderer->DeleteIncomingRenderStream(streamId);
251
252    _streamRenderMap.erase(item);
253
254    return 0;
255}
256
257int32_t ModuleVideoRenderImpl::AddExternalRenderCallback(
258    const uint32_t streamId,
259    VideoRenderCallback* renderObject) {
260    CriticalSectionScoped cs(&_moduleCrit);
261
262    IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
263
264    if (item == _streamRenderMap.end())
265    {
266        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
267                     "%s: stream doesn't exist", __FUNCTION__);
268        return -1;
269    }
270
271    if (item->second == NULL) {
272        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
273                     "%s: could not get stream", __FUNCTION__);
274        return -1;
275    }
276    return item->second->SetExternalCallback(renderObject);
277}
278
279int32_t ModuleVideoRenderImpl::GetIncomingRenderStreamProperties(
280    const uint32_t streamId,
281    uint32_t& zOrder,
282    float& left,
283    float& top,
284    float& right,
285    float& bottom) const {
286    CriticalSectionScoped cs(&_moduleCrit);
287
288    if (!_ptrRenderer)
289    {
290        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
291                     "%s: No renderer", __FUNCTION__);
292        return -1;
293    }
294
295    return _ptrRenderer->GetIncomingRenderStreamProperties(streamId, zOrder,
296                                                           left, top, right,
297                                                           bottom);
298}
299
300uint32_t ModuleVideoRenderImpl::GetNumIncomingRenderStreams() const
301{
302    CriticalSectionScoped cs(&_moduleCrit);
303
304    return static_cast<uint32_t>(_streamRenderMap.size());
305}
306
307bool ModuleVideoRenderImpl::HasIncomingRenderStream(
308    const uint32_t streamId) const {
309  CriticalSectionScoped cs(&_moduleCrit);
310
311  return _streamRenderMap.find(streamId) != _streamRenderMap.end();
312}
313
314int32_t ModuleVideoRenderImpl::RegisterRawFrameCallback(
315    const uint32_t streamId,
316    VideoRenderCallback* callbackObj) {
317  return -1;
318}
319
320int32_t ModuleVideoRenderImpl::StartRender(const uint32_t streamId)
321{
322    CriticalSectionScoped cs(&_moduleCrit);
323
324    if (!_ptrRenderer)
325    {
326        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
327                     "%s: No renderer", __FUNCTION__);
328        return -1;
329    }
330
331    // Start the stream
332    IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
333
334    if (item == _streamRenderMap.end())
335    {
336        return -1;
337    }
338
339    if (item->second->Start() == -1)
340    {
341        return -1;
342    }
343
344    // Start the HW renderer
345    if (_ptrRenderer->StartRender() == -1)
346    {
347        return -1;
348    }
349    return 0;
350}
351
352int32_t ModuleVideoRenderImpl::StopRender(const uint32_t streamId)
353{
354    CriticalSectionScoped cs(&_moduleCrit);
355
356    if (!_ptrRenderer)
357    {
358        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
359                     "%s(%d): No renderer", __FUNCTION__, streamId);
360        return -1;
361    }
362
363    // Stop the incoming stream
364    IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
365
366    if (item == _streamRenderMap.end())
367    {
368        return -1;
369    }
370
371    if (item->second->Stop() == -1)
372    {
373        return -1;
374    }
375
376    return 0;
377}
378
379int32_t ModuleVideoRenderImpl::ResetRender()
380{
381    CriticalSectionScoped cs(&_moduleCrit);
382
383    int32_t ret = 0;
384    // Loop through all incoming streams and reset them
385    for (IncomingVideoStreamMap::iterator it = _streamRenderMap.begin();
386         it != _streamRenderMap.end();
387         ++it) {
388      if (it->second->Reset() == -1)
389        ret = -1;
390    }
391    return ret;
392}
393
394RawVideoType ModuleVideoRenderImpl::PreferredVideoType() const
395{
396    CriticalSectionScoped cs(&_moduleCrit);
397
398    if (_ptrRenderer == NULL)
399    {
400        return kVideoI420;
401    }
402
403    return _ptrRenderer->PerferedVideoType();
404}
405
406bool ModuleVideoRenderImpl::IsFullScreen()
407{
408    CriticalSectionScoped cs(&_moduleCrit);
409
410    if (!_ptrRenderer)
411    {
412        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
413                     "%s: No renderer", __FUNCTION__);
414        return false;
415    }
416    return _ptrRenderer->FullScreen();
417}
418
419int32_t ModuleVideoRenderImpl::GetScreenResolution(
420                                                         uint32_t& screenWidth,
421                                                         uint32_t& screenHeight) const
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->GetScreenResolution(screenWidth, screenHeight);
432}
433
434uint32_t ModuleVideoRenderImpl::RenderFrameRate(
435                                                      const uint32_t streamId)
436{
437    CriticalSectionScoped cs(&_moduleCrit);
438
439    if (!_ptrRenderer)
440    {
441        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
442                     "%s: No renderer", __FUNCTION__);
443        return false;
444    }
445    return _ptrRenderer->RenderFrameRate(streamId);
446}
447
448int32_t ModuleVideoRenderImpl::SetStreamCropping(
449                                                       const uint32_t streamId,
450                                                       const float left,
451                                                       const float top,
452                                                       const float right,
453                                                       const float bottom)
454{
455    CriticalSectionScoped cs(&_moduleCrit);
456
457    if (!_ptrRenderer)
458    {
459        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
460                     "%s: No renderer", __FUNCTION__);
461        return false;
462    }
463    return _ptrRenderer->SetStreamCropping(streamId, left, top, right, bottom);
464}
465
466int32_t ModuleVideoRenderImpl::SetTransparentBackground(const bool enable)
467{
468    CriticalSectionScoped cs(&_moduleCrit);
469
470    if (!_ptrRenderer)
471    {
472        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
473                     "%s: No renderer", __FUNCTION__);
474        return false;
475    }
476    return _ptrRenderer->SetTransparentBackground(enable);
477}
478
479int32_t ModuleVideoRenderImpl::FullScreenRender(void* window, const bool enable)
480{
481    return -1;
482}
483
484int32_t ModuleVideoRenderImpl::SetText(
485                                             const uint8_t textId,
486                                             const uint8_t* text,
487                                             const int32_t textLength,
488                                             const uint32_t textColorRef,
489                                             const uint32_t backgroundColorRef,
490                                             const float left, const float top,
491                                             const float right,
492                                             const float bottom)
493{
494    CriticalSectionScoped cs(&_moduleCrit);
495
496    if (!_ptrRenderer)
497    {
498        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
499                     "%s: No renderer", __FUNCTION__);
500        return -1;
501    }
502    return _ptrRenderer->SetText(textId, text, textLength, textColorRef,
503                                 backgroundColorRef, left, top, right, bottom);
504}
505
506int32_t ModuleVideoRenderImpl::SetBitmap(const void* bitMap,
507                                         const uint8_t pictureId,
508                                         const void* colorKey,
509                                         const float left,
510                                         const float top,
511                                         const float right,
512                                         const float bottom)
513{
514    CriticalSectionScoped cs(&_moduleCrit);
515
516    if (!_ptrRenderer)
517    {
518        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
519                     "%s: No renderer", __FUNCTION__);
520        return -1;
521    }
522    return _ptrRenderer->SetBitmap(bitMap, pictureId, colorKey, left, top,
523                                   right, bottom);
524}
525
526int32_t ModuleVideoRenderImpl::SetExpectedRenderDelay(
527    uint32_t stream_id, int32_t delay_ms) {
528  CriticalSectionScoped cs(&_moduleCrit);
529
530  if (!_ptrRenderer) {
531    WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
532                 "%s: No renderer", __FUNCTION__);
533    return false;
534  }
535
536  IncomingVideoStreamMap::const_iterator item =
537      _streamRenderMap.find(stream_id);
538  if (item == _streamRenderMap.end()) {
539    // This stream doesn't exist
540    WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
541                 "%s(%u, %d): stream doesn't exist", __FUNCTION__, stream_id,
542                 delay_ms);
543    return -1;
544  }
545
546  assert(item->second != NULL);
547  return item->second->SetExpectedRenderDelay(delay_ms);
548}
549
550int32_t ModuleVideoRenderImpl::ConfigureRenderer(
551                                                       const uint32_t streamId,
552                                                       const unsigned int zOrder,
553                                                       const float left,
554                                                       const float top,
555                                                       const float right,
556                                                       const float bottom)
557{
558    CriticalSectionScoped cs(&_moduleCrit);
559
560    if (!_ptrRenderer)
561    {
562        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
563                     "%s: No renderer", __FUNCTION__);
564        return false;
565    }
566    return _ptrRenderer->ConfigureRenderer(streamId, zOrder, left, top, right,
567                                           bottom);
568}
569
570int32_t ModuleVideoRenderImpl::SetStartImage(
571    const uint32_t streamId,
572    const I420VideoFrame& videoFrame)
573{
574    CriticalSectionScoped cs(&_moduleCrit);
575
576    if (!_ptrRenderer)
577    {
578        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
579                     "%s: No renderer", __FUNCTION__);
580        return -1;
581    }
582
583    IncomingVideoStreamMap::const_iterator item =
584        _streamRenderMap.find(streamId);
585    if (item == _streamRenderMap.end())
586    {
587        // This stream doesn't exist
588        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
589                     "%s: stream doesn't exist", __FUNCTION__);
590        return -1;
591    }
592    assert (item->second != NULL);
593    return item->second->SetStartImage(videoFrame);
594
595}
596
597int32_t ModuleVideoRenderImpl::SetTimeoutImage(
598    const uint32_t streamId,
599    const I420VideoFrame& videoFrame,
600    const uint32_t timeout)
601{
602    CriticalSectionScoped cs(&_moduleCrit);
603
604    if (!_ptrRenderer)
605    {
606        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
607                     "%s: No renderer", __FUNCTION__);
608        return -1;
609    }
610
611    IncomingVideoStreamMap::const_iterator item =
612        _streamRenderMap.find(streamId);
613    if (item == _streamRenderMap.end())
614    {
615        // This stream doesn't exist
616        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
617                     "%s: stream doesn't exist", __FUNCTION__);
618        return -1;
619    }
620    assert(item->second != NULL);
621    return item->second->SetTimeoutImage(videoFrame, timeout);
622}
623
624}  // namespace webrtc
625