/* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "vie_renderer.h" #include "video_render.h" #include "video_render_defines.h" #include "vie_render_manager.h" #include "vplib.h" namespace webrtc { ViERenderer* ViERenderer::CreateViERenderer( const WebRtc_Word32 renderId, const WebRtc_Word32 engineId, VideoRender& renderModule, ViERenderManager& renderManager, const WebRtc_UWord32 zOrder, const float left, const float top, const float right, const float bottom) { ViERenderer* self=new ViERenderer(renderId,engineId,renderModule,renderManager); if(!self || self->Init(zOrder,left,top,right,bottom)!=0) { delete self; self=NULL; } return self; } ViERenderer::~ViERenderer(void) { if(_ptrRenderCallback) { _renderModule.DeleteIncomingRenderStream( _renderId); } if(_ptrIncomingExternalCallback){ delete _ptrIncomingExternalCallback; } } ViERenderer::ViERenderer(const WebRtc_Word32 renderId,const WebRtc_Word32 engineId, VideoRender& renderModule, ViERenderManager& renderManager) : _renderId(renderId), _engineId(engineId), _renderModule(renderModule), _renderManager(renderManager), _ptrRenderCallback(NULL), _ptrIncomingExternalCallback(new ViEExternalRendererImpl()) { } WebRtc_Word32 ViERenderer::Init(const WebRtc_UWord32 zOrder, const float left, const float top, const float right, const float bottom) { _ptrRenderCallback = (VideoRenderCallback*)_renderModule.AddIncomingRenderStream( _renderId, zOrder, left, top, right, bottom); if (_ptrRenderCallback == NULL) { // Logging done return -1; } return 0; } WebRtc_Word32 ViERenderer::GetLastRenderedFrame(const WebRtc_Word32 renderID, webrtc::VideoFrame& videoFrame) { return _renderModule.GetLastRenderedFrame(renderID, videoFrame); } WebRtc_Word32 ViERenderer::StartRender() { return _renderModule.StartRender(_renderId); } WebRtc_Word32 ViERenderer::StopRender() { return _renderModule.StopRender(_renderId); } // Implement ViEFrameCallback void ViERenderer::DeliverFrame(int id, webrtc::VideoFrame& videoFrame, int numCSRCs, const WebRtc_UWord32 CSRC[kRtpCsrcSize]) { _ptrRenderCallback->RenderFrame(_renderId,videoFrame); } // Implement ViEFrameCallback void ViERenderer::ProviderDestroyed(int id) { _renderManager.RemoveRenderStream(_renderId); // Remove the render stream since the provider is destroyed. } VideoRender& ViERenderer::RenderModule() { return _renderModule; } WebRtc_Word32 ViERenderer::ConfigureRenderer(const unsigned int zOrder, const float left, const float top, const float right, const float bottom) { return _renderModule.ConfigureRenderer(_renderId, zOrder, left, top, right, bottom); } WebRtc_Word32 ViERenderer::SetTimeoutImage(const webrtc::VideoFrame& timeoutImage,const WebRtc_Word32 timeoutValue) { return _renderModule.SetTimeoutImage(_renderId,timeoutImage,timeoutValue); } WebRtc_Word32 ViERenderer::SetRenderStartImage(const webrtc::VideoFrame& startImage) { return _renderModule.SetStartImage(_renderId,startImage); } WebRtc_Word32 ViERenderer::EnableMirroring(const WebRtc_Word32 renderId, const bool enable, const bool mirrorXAxis, const bool mirrorYAxis) { return _renderModule.MirrorRenderStream(renderId, enable, mirrorXAxis, mirrorYAxis); } WebRtc_Word32 ViERenderer::SetExternalRenderer(const WebRtc_Word32 renderId, webrtc::RawVideoType videoInputFormat, ExternalRenderer* externalRenderer) { if(NULL == _ptrIncomingExternalCallback){ return -1; } _ptrIncomingExternalCallback->SetViEExternalRenderer(externalRenderer, videoInputFormat); return _renderModule.AddExternalRenderCallback(renderId, _ptrIncomingExternalCallback); } ViEExternalRendererImpl::ViEExternalRendererImpl() : _externalRenderer(NULL), _externalRendererFormat(), _externalRendererWidth(0), _externalRendererHeight(0) { } int ViEExternalRendererImpl::SetViEExternalRenderer(ExternalRenderer* externalRenderer, webrtc::RawVideoType videoInputFormat) { _externalRenderer = externalRenderer; _externalRendererFormat = videoInputFormat; return 0; } // implements VideoRenderCallback WebRtc_Word32 ViEExternalRendererImpl::RenderFrame(const WebRtc_UWord32 streamId, webrtc::VideoFrame& videoFrame) { webrtc::VideoFrame convertedFrame; webrtc::VideoFrame* pConvertedFrame = &convertedFrame; // convert to requested format switch(_externalRendererFormat) { case webrtc::kVideoI420: pConvertedFrame = &videoFrame; break; case webrtc::kVideoYV12: convertedFrame.VerifyAndAllocate(webrtc::CalcBufferSize(webrtc::kYV12,videoFrame.Width(),videoFrame.Height())); webrtc::ConvertI420ToYV12(videoFrame.Buffer(), convertedFrame.Buffer(), videoFrame.Width(), videoFrame.Height(), 0); break; case webrtc::kVideoYUY2: convertedFrame.VerifyAndAllocate(webrtc::CalcBufferSize(webrtc::kYUY2,videoFrame.Width(),videoFrame.Height())); webrtc::ConvertI420ToYUY2(videoFrame.Buffer(), convertedFrame.Buffer(), videoFrame.Width(), videoFrame.Height(), 0); break; case webrtc::kVideoUYVY: convertedFrame.VerifyAndAllocate(webrtc::CalcBufferSize(webrtc::kUYVY,videoFrame.Width(),videoFrame.Height())); webrtc::ConvertI420ToUYVY(videoFrame.Buffer(), convertedFrame.Buffer(), videoFrame.Width(), videoFrame.Height(), 0); break; case webrtc::kVideoIYUV: // no conversion available break; case webrtc::kVideoARGB: convertedFrame.VerifyAndAllocate(webrtc::CalcBufferSize(webrtc::kARGB,videoFrame.Width(),videoFrame.Height())); webrtc::ConvertI420ToARGB(videoFrame.Buffer(), convertedFrame.Buffer(), videoFrame.Width(), videoFrame.Height(), 0); break; case webrtc::kVideoRGB24: convertedFrame.VerifyAndAllocate(webrtc::CalcBufferSize(webrtc::kRGB24,videoFrame.Width(),videoFrame.Height())); webrtc::ConvertI420ToRGB24(videoFrame.Buffer(), convertedFrame.Buffer(), videoFrame.Width(), videoFrame.Height()); break; case webrtc::kVideoRGB565: convertedFrame.VerifyAndAllocate(webrtc::CalcBufferSize(webrtc::kRGB565,videoFrame.Width(),videoFrame.Height())); webrtc::ConvertI420ToRGB565(videoFrame.Buffer(), convertedFrame.Buffer(), videoFrame.Width(), videoFrame.Height()); break; case webrtc::kVideoARGB4444: convertedFrame.VerifyAndAllocate(webrtc::CalcBufferSize(webrtc::kARGB4444,videoFrame.Width(),videoFrame.Height())); webrtc::ConvertI420ToARGB4444(videoFrame.Buffer(), convertedFrame.Buffer(), videoFrame.Width(), videoFrame.Height(), 0); break; case webrtc::kVideoARGB1555 : convertedFrame.VerifyAndAllocate(webrtc::CalcBufferSize(webrtc::kARGB1555,videoFrame.Width(),videoFrame.Height())); webrtc::ConvertI420ToARGB1555(videoFrame.Buffer(), convertedFrame.Buffer(), videoFrame.Width(), videoFrame.Height(), 0); break; default: // the format is something funny. Should never reach here... assert(false); pConvertedFrame = NULL; break; } if(_externalRendererWidth!=videoFrame.Width() || _externalRendererHeight!=videoFrame.Height()) { _externalRendererWidth = videoFrame.Width(); _externalRendererHeight = videoFrame.Height(); _externalRenderer->FrameSizeChange(_externalRendererWidth, _externalRendererHeight, streamId); } if(pConvertedFrame) { _externalRenderer->DeliverFrame(pConvertedFrame->Buffer(), pConvertedFrame->Length()); } return 0; } } //namespace webrtc