2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
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"
25 VideoRender::CreateVideoRender(const int32_t id,
27 const bool fullscreen,
28 const VideoRenderType videoRenderType/*=kRenderDefault*/)
30 VideoRenderType resultVideoRenderType = videoRenderType;
31 if (videoRenderType == kRenderDefault)
33 resultVideoRenderType = kRenderExternal;
35 return new ModuleVideoRenderImpl(id, resultVideoRenderType, window,
39 void VideoRender::DestroyVideoRender(
48 ModuleVideoRenderImpl::ModuleVideoRenderImpl(
50 const VideoRenderType videoRenderType,
52 const bool fullscreen) :
53 _id(id), _moduleCrit(*CriticalSectionWrapper::CreateCriticalSection()),
54 _ptrWindow(window), _fullScreen(fullscreen), _ptrRenderer(NULL)
57 // Create platform specific renderer
58 switch (videoRenderType)
62 VideoRenderExternalImpl* ptrRenderer(NULL);
63 ptrRenderer = new VideoRenderExternalImpl(_id, videoRenderType,
67 _ptrRenderer = reinterpret_cast<IVideoRender*> (ptrRenderer);
77 if (_ptrRenderer->Init() == -1)
83 ModuleVideoRenderImpl::~ModuleVideoRenderImpl()
87 for (IncomingVideoStreamMap::iterator it = _streamRenderMap.begin();
88 it != _streamRenderMap.end();
93 // Delete platform specific renderer
96 VideoRenderType videoRenderType = _ptrRenderer->RenderType();
98 switch (videoRenderType)
100 case kRenderExternal:
102 VideoRenderExternalImpl
104 reinterpret_cast<VideoRenderExternalImpl*> (_ptrRenderer);
117 int32_t ModuleVideoRenderImpl::ChangeUniqueId(const int32_t id)
120 CriticalSectionScoped cs(&_moduleCrit);
126 _ptrRenderer->ChangeUniqueId(_id);
132 int32_t ModuleVideoRenderImpl::TimeUntilNextProcess()
137 int32_t ModuleVideoRenderImpl::Process()
144 ModuleVideoRenderImpl::Window()
146 CriticalSectionScoped cs(&_moduleCrit);
150 int32_t ModuleVideoRenderImpl::ChangeWindow(void* window)
155 int32_t ModuleVideoRenderImpl::Id()
157 CriticalSectionScoped cs(&_moduleCrit);
161 uint32_t ModuleVideoRenderImpl::GetIncomingFrameRate(const uint32_t streamId) {
162 CriticalSectionScoped cs(&_moduleCrit);
164 IncomingVideoStreamMap::iterator it = _streamRenderMap.find(streamId);
166 if (it == _streamRenderMap.end()) {
167 // This stream doesn't exist
168 WEBRTC_TRACE(kTraceError,
171 "%s: stream doesn't exist",
175 assert(it->second != NULL);
176 return it->second->IncomingRate();
180 ModuleVideoRenderImpl::AddIncomingRenderStream(const uint32_t streamId,
181 const uint32_t zOrder,
187 CriticalSectionScoped cs(&_moduleCrit);
191 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
192 "%s: No renderer", __FUNCTION__);
196 if (_streamRenderMap.find(streamId) != _streamRenderMap.end()) {
197 // The stream already exists...
198 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
199 "%s: stream already exists", __FUNCTION__);
203 VideoRenderCallback* ptrRenderCallback =
204 _ptrRenderer->AddIncomingRenderStream(streamId, zOrder, left, top,
206 if (ptrRenderCallback == NULL)
208 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
209 "%s: Can't create incoming stream in renderer",
214 // Create platform independant code
215 IncomingVideoStream* ptrIncomingStream = new IncomingVideoStream(_id,
217 if (ptrIncomingStream == NULL)
219 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
220 "%s: Can't create incoming stream", __FUNCTION__);
225 if (ptrIncomingStream->SetRenderCallback(ptrRenderCallback) == -1)
227 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
228 "%s: Can't set render callback", __FUNCTION__);
229 delete ptrIncomingStream;
230 _ptrRenderer->DeleteIncomingRenderStream(streamId);
234 VideoRenderCallback* moduleCallback =
235 ptrIncomingStream->ModuleCallback();
238 _streamRenderMap[streamId] = ptrIncomingStream;
240 return moduleCallback;
243 int32_t ModuleVideoRenderImpl::DeleteIncomingRenderStream(
244 const uint32_t streamId)
246 CriticalSectionScoped cs(&_moduleCrit);
250 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
251 "%s: No renderer", __FUNCTION__);
255 IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
256 if (item == _streamRenderMap.end())
258 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
259 "%s: stream doesn't exist", __FUNCTION__);
265 _ptrRenderer->DeleteIncomingRenderStream(streamId);
267 _streamRenderMap.erase(item);
272 int32_t ModuleVideoRenderImpl::AddExternalRenderCallback(
273 const uint32_t streamId,
274 VideoRenderCallback* renderObject) {
275 CriticalSectionScoped cs(&_moduleCrit);
277 IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
279 if (item == _streamRenderMap.end())
281 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
282 "%s: stream doesn't exist", __FUNCTION__);
286 if (item->second == NULL) {
287 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
288 "%s: could not get stream", __FUNCTION__);
291 return item->second->SetExternalCallback(renderObject);
294 int32_t ModuleVideoRenderImpl::GetIncomingRenderStreamProperties(
295 const uint32_t streamId,
300 float& bottom) const {
301 CriticalSectionScoped cs(&_moduleCrit);
305 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
306 "%s: No renderer", __FUNCTION__);
310 return _ptrRenderer->GetIncomingRenderStreamProperties(streamId, zOrder,
315 uint32_t ModuleVideoRenderImpl::GetNumIncomingRenderStreams() const
317 CriticalSectionScoped cs(&_moduleCrit);
319 return static_cast<uint32_t>(_streamRenderMap.size());
322 bool ModuleVideoRenderImpl::HasIncomingRenderStream(
323 const uint32_t streamId) const {
324 CriticalSectionScoped cs(&_moduleCrit);
326 return _streamRenderMap.find(streamId) != _streamRenderMap.end();
329 int32_t ModuleVideoRenderImpl::RegisterRawFrameCallback(
330 const uint32_t streamId,
331 VideoRenderCallback* callbackObj) {
335 int32_t ModuleVideoRenderImpl::StartRender(const uint32_t streamId)
337 CriticalSectionScoped cs(&_moduleCrit);
341 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
342 "%s: No renderer", __FUNCTION__);
347 IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
349 if (item == _streamRenderMap.end())
354 if (item->second->Start() == -1)
359 // Start the HW renderer
360 if (_ptrRenderer->StartRender() == -1)
367 int32_t ModuleVideoRenderImpl::StopRender(const uint32_t streamId)
369 CriticalSectionScoped cs(&_moduleCrit);
373 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
374 "%s(%d): No renderer", __FUNCTION__, streamId);
378 // Stop the incoming stream
379 IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
381 if (item == _streamRenderMap.end())
386 if (item->second->Stop() == -1)
394 int32_t ModuleVideoRenderImpl::ResetRender()
396 CriticalSectionScoped cs(&_moduleCrit);
399 // Loop through all incoming streams and reset them
400 for (IncomingVideoStreamMap::iterator it = _streamRenderMap.begin();
401 it != _streamRenderMap.end();
403 if (it->second->Reset() == -1)
409 RawVideoType ModuleVideoRenderImpl::PreferredVideoType() const
411 CriticalSectionScoped cs(&_moduleCrit);
413 if (_ptrRenderer == NULL)
418 return _ptrRenderer->PerferedVideoType();
421 bool ModuleVideoRenderImpl::IsFullScreen()
423 CriticalSectionScoped cs(&_moduleCrit);
427 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
428 "%s: No renderer", __FUNCTION__);
431 return _ptrRenderer->FullScreen();
434 int32_t ModuleVideoRenderImpl::GetScreenResolution(
435 uint32_t& screenWidth,
436 uint32_t& screenHeight) const
438 CriticalSectionScoped cs(&_moduleCrit);
442 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
443 "%s: No renderer", __FUNCTION__);
446 return _ptrRenderer->GetScreenResolution(screenWidth, screenHeight);
449 uint32_t ModuleVideoRenderImpl::RenderFrameRate(
450 const uint32_t streamId)
452 CriticalSectionScoped cs(&_moduleCrit);
456 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
457 "%s: No renderer", __FUNCTION__);
460 return _ptrRenderer->RenderFrameRate(streamId);
463 int32_t ModuleVideoRenderImpl::SetStreamCropping(
464 const uint32_t streamId,
470 CriticalSectionScoped cs(&_moduleCrit);
474 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
475 "%s: No renderer", __FUNCTION__);
478 return _ptrRenderer->SetStreamCropping(streamId, left, top, right, bottom);
481 int32_t ModuleVideoRenderImpl::SetTransparentBackground(const bool enable)
483 CriticalSectionScoped cs(&_moduleCrit);
487 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
488 "%s: No renderer", __FUNCTION__);
491 return _ptrRenderer->SetTransparentBackground(enable);
494 int32_t ModuleVideoRenderImpl::FullScreenRender(void* window, const bool enable)
499 int32_t ModuleVideoRenderImpl::SetText(
500 const uint8_t textId,
502 const int32_t textLength,
503 const uint32_t textColorRef,
504 const uint32_t backgroundColorRef,
505 const float left, const float top,
509 CriticalSectionScoped cs(&_moduleCrit);
513 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
514 "%s: No renderer", __FUNCTION__);
517 return _ptrRenderer->SetText(textId, text, textLength, textColorRef,
518 backgroundColorRef, left, top, right, bottom);
521 int32_t ModuleVideoRenderImpl::SetBitmap(const void* bitMap,
522 const uint8_t pictureId,
523 const void* colorKey,
529 CriticalSectionScoped cs(&_moduleCrit);
533 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
534 "%s: No renderer", __FUNCTION__);
537 return _ptrRenderer->SetBitmap(bitMap, pictureId, colorKey, left, top,
541 int32_t ModuleVideoRenderImpl::GetLastRenderedFrame(
542 const uint32_t streamId,
543 I420VideoFrame &frame) const
545 CriticalSectionScoped cs(&_moduleCrit);
549 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
550 "%s: No renderer", __FUNCTION__);
554 IncomingVideoStreamMap::const_iterator item =
555 _streamRenderMap.find(streamId);
556 if (item == _streamRenderMap.end())
558 // This stream doesn't exist
559 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
560 "%s: stream doesn't exist", __FUNCTION__);
564 assert(item->second != NULL);
565 return item->second->GetLastRenderedFrame(frame);
568 int32_t ModuleVideoRenderImpl::SetExpectedRenderDelay(
569 uint32_t stream_id, int32_t delay_ms) {
570 CriticalSectionScoped cs(&_moduleCrit);
573 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
574 "%s: No renderer", __FUNCTION__);
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,
588 assert(item->second != NULL);
589 return item->second->SetExpectedRenderDelay(delay_ms);
592 int32_t ModuleVideoRenderImpl::ConfigureRenderer(
593 const uint32_t streamId,
594 const unsigned int zOrder,
600 CriticalSectionScoped cs(&_moduleCrit);
604 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
605 "%s: No renderer", __FUNCTION__);
608 return _ptrRenderer->ConfigureRenderer(streamId, zOrder, left, top, right,
612 int32_t ModuleVideoRenderImpl::SetStartImage(
613 const uint32_t streamId,
614 const I420VideoFrame& videoFrame)
616 CriticalSectionScoped cs(&_moduleCrit);
620 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
621 "%s: No renderer", __FUNCTION__);
625 IncomingVideoStreamMap::const_iterator item =
626 _streamRenderMap.find(streamId);
627 if (item == _streamRenderMap.end())
629 // This stream doesn't exist
630 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
631 "%s: stream doesn't exist", __FUNCTION__);
634 assert (item->second != NULL);
635 return item->second->SetStartImage(videoFrame);
639 int32_t ModuleVideoRenderImpl::SetTimeoutImage(
640 const uint32_t streamId,
641 const I420VideoFrame& videoFrame,
642 const uint32_t timeout)
644 CriticalSectionScoped cs(&_moduleCrit);
648 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
649 "%s: No renderer", __FUNCTION__);
653 IncomingVideoStreamMap::const_iterator item =
654 _streamRenderMap.find(streamId);
655 if (item == _streamRenderMap.end())
657 // This stream doesn't exist
658 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
659 "%s: stream doesn't exist", __FUNCTION__);
662 assert(item->second != NULL);
663 return item->second->SetTimeoutImage(videoFrame, timeout);
666 int32_t ModuleVideoRenderImpl::MirrorRenderStream(const int renderId,
668 const bool mirrorXAxis,
669 const bool mirrorYAxis)
671 CriticalSectionScoped cs(&_moduleCrit);
675 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
676 "%s: No renderer", __FUNCTION__);
680 IncomingVideoStreamMap::const_iterator item =
681 _streamRenderMap.find(renderId);
682 if (item == _streamRenderMap.end())
684 // This stream doesn't exist
685 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
686 "%s: stream doesn't exist", __FUNCTION__);
689 assert(item->second != NULL);
691 return item->second->EnableMirroring(enable, mirrorXAxis, mirrorYAxis);
694 } // namespace webrtc