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