| /* |
| * 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 "video_engine/vie_renderer.h" |
| |
| #include "common_video/libyuv/include/libyuv.h" |
| #include "modules/video_render/main/interface/video_render.h" |
| #include "modules/video_render/main/interface/video_render_defines.h" |
| #include "video_engine/vie_render_manager.h" |
| |
| namespace webrtc { |
| |
| ViERenderer* ViERenderer::CreateViERenderer(const WebRtc_Word32 render_id, |
| const WebRtc_Word32 engine_id, |
| VideoRender& render_module, |
| ViERenderManager& render_manager, |
| const WebRtc_UWord32 z_order, |
| const float left, |
| const float top, |
| const float right, |
| const float bottom) { |
| ViERenderer* self = new ViERenderer(render_id, engine_id, render_module, |
| render_manager); |
| if (!self || self->Init(z_order, left, top, right, bottom) != 0) { |
| delete self; |
| self = NULL; |
| } |
| return self; |
| } |
| |
| ViERenderer::~ViERenderer(void) { |
| if (render_callback_) |
| render_module_.DeleteIncomingRenderStream(render_id_); |
| |
| if (incoming_external_callback_) |
| delete incoming_external_callback_; |
| } |
| |
| WebRtc_Word32 ViERenderer::StartRender() { |
| return render_module_.StartRender(render_id_); |
| } |
| WebRtc_Word32 ViERenderer::StopRender() { |
| return render_module_.StopRender(render_id_); |
| } |
| |
| WebRtc_Word32 ViERenderer::GetLastRenderedFrame(const WebRtc_Word32 renderID, |
| VideoFrame& video_frame) { |
| return render_module_.GetLastRenderedFrame(renderID, video_frame); |
| } |
| |
| WebRtc_Word32 ViERenderer::ConfigureRenderer(const unsigned int z_order, |
| const float left, |
| const float top, |
| const float right, |
| const float bottom) { |
| return render_module_.ConfigureRenderer(render_id_, z_order, left, top, right, |
| bottom); |
| } |
| |
| VideoRender& ViERenderer::RenderModule() { |
| return render_module_; |
| } |
| |
| WebRtc_Word32 ViERenderer::EnableMirroring(const WebRtc_Word32 render_id, |
| const bool enable, |
| const bool mirror_xaxis, |
| const bool mirror_yaxis) { |
| return render_module_.MirrorRenderStream(render_id, enable, mirror_xaxis, |
| mirror_yaxis); |
| } |
| |
| WebRtc_Word32 ViERenderer::SetTimeoutImage(const VideoFrame& timeout_image, |
| const WebRtc_Word32 timeout_value) { |
| return render_module_.SetTimeoutImage(render_id_, timeout_image, |
| timeout_value); |
| } |
| |
| WebRtc_Word32 ViERenderer::SetRenderStartImage(const VideoFrame& start_image) { |
| return render_module_.SetStartImage(render_id_, start_image); |
| } |
| |
| WebRtc_Word32 ViERenderer::SetExternalRenderer( |
| const WebRtc_Word32 render_id, |
| RawVideoType video_input_format, |
| ExternalRenderer* external_renderer) { |
| if (!incoming_external_callback_) |
| return -1; |
| |
| incoming_external_callback_->SetViEExternalRenderer(external_renderer, |
| video_input_format); |
| return render_module_.AddExternalRenderCallback(render_id, |
| incoming_external_callback_); |
| } |
| |
| ViERenderer::ViERenderer(const WebRtc_Word32 render_id, |
| const WebRtc_Word32 engine_id, |
| VideoRender& render_module, |
| ViERenderManager& render_manager) |
| : render_id_(render_id), |
| engine_id_(engine_id), |
| render_module_(render_module), |
| render_manager_(render_manager), |
| render_callback_(NULL), |
| incoming_external_callback_(new ViEExternalRendererImpl()) { |
| } |
| |
| WebRtc_Word32 ViERenderer::Init(const WebRtc_UWord32 z_order, |
| const float left, |
| const float top, |
| const float right, |
| const float bottom) { |
| render_callback_ = |
| static_cast<VideoRenderCallback*>(render_module_.AddIncomingRenderStream( |
| render_id_, z_order, left, top, right, bottom)); |
| if (!render_callback_) { |
| // Logging done. |
| return -1; |
| } |
| return 0; |
| } |
| |
| void ViERenderer::DeliverFrame(int id, |
| VideoFrame& video_frame, |
| int num_csrcs, |
| const WebRtc_UWord32 CSRC[kRtpCsrcSize]) { |
| render_callback_->RenderFrame(render_id_, video_frame); |
| } |
| |
| void ViERenderer::DelayChanged(int id, int frame_delay) {} |
| |
| int ViERenderer::GetPreferedFrameSettings(int& width, |
| int& height, |
| int& frame_rate) { |
| return -1; |
| } |
| |
| void ViERenderer::ProviderDestroyed(int id) { |
| // Remove the render stream since the provider is destroyed. |
| render_manager_.RemoveRenderStream(render_id_); |
| } |
| |
| ViEExternalRendererImpl::ViEExternalRendererImpl() |
| : external_renderer_(NULL), |
| external_renderer_format_(kVideoUnknown), |
| external_renderer_width_(0), |
| external_renderer_height_(0), |
| converted_frame_(new VideoFrame()){ |
| } |
| |
| int ViEExternalRendererImpl::SetViEExternalRenderer( |
| ExternalRenderer* external_renderer, |
| RawVideoType video_input_format) { |
| external_renderer_ = external_renderer; |
| external_renderer_format_ = video_input_format; |
| return 0; |
| } |
| |
| WebRtc_Word32 ViEExternalRendererImpl::RenderFrame( |
| const WebRtc_UWord32 stream_id, |
| VideoFrame& video_frame) { |
| VideoFrame* out_frame = converted_frame_.get(); |
| |
| // Convert to requested format. |
| VideoType type = |
| RawVideoTypeToCommonVideoVideoType(external_renderer_format_); |
| int buffer_size = CalcBufferSize(type, video_frame.Width(), |
| video_frame.Height()); |
| if (buffer_size <= 0) { |
| // Unsupported video format. |
| assert(false); |
| return -1; |
| } |
| converted_frame_->VerifyAndAllocate(buffer_size); |
| |
| switch (external_renderer_format_) { |
| case kVideoI420: |
| out_frame = &video_frame; |
| break; |
| case kVideoYV12: |
| case kVideoYUY2: |
| case kVideoUYVY: |
| case kVideoARGB: |
| case kVideoRGB24: |
| { |
| ConvertFromI420(video_frame.Buffer(), video_frame.Width(), type, 0, |
| video_frame.Width(), video_frame.Height(), |
| converted_frame_->Buffer()); |
| } |
| break; |
| case kVideoIYUV: |
| // no conversion available |
| break; |
| case kVideoRGB565: |
| ConvertI420ToRGB565(video_frame.Buffer(), converted_frame_->Buffer(), |
| video_frame.Width(), video_frame.Height()); |
| break; |
| case kVideoARGB4444: |
| ConvertI420ToARGB4444(video_frame.Buffer(), converted_frame_->Buffer(), |
| video_frame.Width(), video_frame.Height(), 0); |
| break; |
| case kVideoARGB1555 : |
| ConvertI420ToARGB1555(video_frame.Buffer(), converted_frame_->Buffer(), |
| video_frame.Width(), video_frame.Height(), 0); |
| break; |
| default: |
| assert(false); |
| out_frame = NULL; |
| break; |
| } |
| |
| if (external_renderer_width_ != video_frame.Width() || |
| external_renderer_height_ != video_frame.Height()) { |
| external_renderer_width_ = video_frame.Width(); |
| external_renderer_height_ = video_frame.Height(); |
| external_renderer_->FrameSizeChange(external_renderer_width_, |
| external_renderer_height_, stream_id); |
| } |
| |
| if (out_frame) { |
| external_renderer_->DeliverFrame(out_frame->Buffer(), |
| out_frame->Length(), |
| video_frame.TimeStamp()); |
| } |
| return 0; |
| } |
| |
| } // namespace webrtc |