• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "webrtc/video_engine/vie_renderer.h"
12 
13 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
14 #include "webrtc/modules/video_render/include/video_render.h"
15 #include "webrtc/modules/video_render/include/video_render_defines.h"
16 #include "webrtc/video_engine/vie_render_manager.h"
17 
18 namespace webrtc {
19 
CreateViERenderer(const int32_t render_id,const int32_t engine_id,VideoRender & render_module,ViERenderManager & render_manager,const uint32_t z_order,const float left,const float top,const float right,const float bottom)20 ViERenderer* ViERenderer::CreateViERenderer(const int32_t render_id,
21                                             const int32_t engine_id,
22                                             VideoRender& render_module,
23                                             ViERenderManager& render_manager,
24                                             const uint32_t z_order,
25                                             const float left,
26                                             const float top,
27                                             const float right,
28                                             const float bottom) {
29   ViERenderer* self = new ViERenderer(render_id, engine_id, render_module,
30                                       render_manager);
31   if (!self || self->Init(z_order, left, top, right, bottom) != 0) {
32     delete self;
33     self = NULL;
34   }
35   return self;
36 }
37 
~ViERenderer(void)38 ViERenderer::~ViERenderer(void) {
39   if (render_callback_)
40     render_module_.DeleteIncomingRenderStream(render_id_);
41 
42   if (incoming_external_callback_)
43     delete incoming_external_callback_;
44 }
45 
StartRender()46 int32_t ViERenderer::StartRender() {
47   return render_module_.StartRender(render_id_);
48 }
StopRender()49 int32_t ViERenderer::StopRender() {
50   return render_module_.StopRender(render_id_);
51 }
52 
GetLastRenderedFrame(const int32_t renderID,I420VideoFrame & video_frame)53 int32_t ViERenderer::GetLastRenderedFrame(const int32_t renderID,
54                                           I420VideoFrame& video_frame) {
55   return render_module_.GetLastRenderedFrame(renderID, video_frame);
56 }
57 
SetExpectedRenderDelay(int render_delay)58 int ViERenderer::SetExpectedRenderDelay(int render_delay) {
59   return render_module_.SetExpectedRenderDelay(render_id_, render_delay);
60 }
61 
ConfigureRenderer(const unsigned int z_order,const float left,const float top,const float right,const float bottom)62 int32_t ViERenderer::ConfigureRenderer(const unsigned int z_order,
63                                        const float left,
64                                        const float top,
65                                        const float right,
66                                        const float bottom) {
67   return render_module_.ConfigureRenderer(render_id_, z_order, left, top, right,
68                                           bottom);
69 }
70 
RenderModule()71 VideoRender& ViERenderer::RenderModule() {
72   return render_module_;
73 }
74 
EnableMirroring(const int32_t render_id,const bool enable,const bool mirror_xaxis,const bool mirror_yaxis)75 int32_t ViERenderer::EnableMirroring(const int32_t render_id,
76                                      const bool enable,
77                                      const bool mirror_xaxis,
78                                      const bool mirror_yaxis) {
79   return render_module_.MirrorRenderStream(render_id, enable, mirror_xaxis,
80                                            mirror_yaxis);
81 }
82 
SetTimeoutImage(const I420VideoFrame & timeout_image,const int32_t timeout_value)83 int32_t ViERenderer::SetTimeoutImage(const I420VideoFrame& timeout_image,
84                                      const int32_t timeout_value) {
85   return render_module_.SetTimeoutImage(render_id_, timeout_image,
86                                         timeout_value);
87 }
88 
SetRenderStartImage(const I420VideoFrame & start_image)89 int32_t  ViERenderer::SetRenderStartImage(
90     const I420VideoFrame& start_image) {
91   return render_module_.SetStartImage(render_id_, start_image);
92 }
93 
SetExternalRenderer(const int32_t render_id,RawVideoType video_input_format,ExternalRenderer * external_renderer)94 int32_t ViERenderer::SetExternalRenderer(
95     const int32_t render_id,
96     RawVideoType video_input_format,
97     ExternalRenderer* external_renderer) {
98   if (!incoming_external_callback_)
99     return -1;
100 
101   incoming_external_callback_->SetViEExternalRenderer(external_renderer,
102                                                       video_input_format);
103   return render_module_.AddExternalRenderCallback(render_id,
104                                                   incoming_external_callback_);
105 }
106 
SetVideoRenderCallback(int32_t render_id,VideoRenderCallback * callback)107 int32_t ViERenderer::SetVideoRenderCallback(int32_t render_id,
108                                             VideoRenderCallback* callback) {
109   return render_module_.AddExternalRenderCallback(render_id, callback);
110 }
111 
ViERenderer(const int32_t render_id,const int32_t engine_id,VideoRender & render_module,ViERenderManager & render_manager)112 ViERenderer::ViERenderer(const int32_t render_id,
113                          const int32_t engine_id,
114                          VideoRender& render_module,
115                          ViERenderManager& render_manager)
116     : render_id_(render_id),
117       render_module_(render_module),
118       render_manager_(render_manager),
119       render_callback_(NULL),
120       incoming_external_callback_(new ViEExternalRendererImpl()) {
121 }
122 
Init(const uint32_t z_order,const float left,const float top,const float right,const float bottom)123 int32_t ViERenderer::Init(const uint32_t z_order,
124                           const float left,
125                           const float top,
126                           const float right,
127                           const float bottom) {
128   render_callback_ =
129       static_cast<VideoRenderCallback*>(render_module_.AddIncomingRenderStream(
130           render_id_, z_order, left, top, right, bottom));
131   if (!render_callback_) {
132     // Logging done.
133     return -1;
134   }
135   return 0;
136 }
137 
DeliverFrame(int id,I420VideoFrame * video_frame,int num_csrcs,const uint32_t CSRC[kRtpCsrcSize])138 void ViERenderer::DeliverFrame(int id,
139                                I420VideoFrame* video_frame,
140                                int num_csrcs,
141                                const uint32_t CSRC[kRtpCsrcSize]) {
142   render_callback_->RenderFrame(render_id_, *video_frame);
143 }
144 
DelayChanged(int id,int frame_delay)145 void ViERenderer::DelayChanged(int id, int frame_delay) {}
146 
GetPreferedFrameSettings(int * width,int * height,int * frame_rate)147 int ViERenderer::GetPreferedFrameSettings(int* width,
148                                           int* height,
149                                           int* frame_rate) {
150     return -1;
151 }
152 
ProviderDestroyed(int id)153 void ViERenderer::ProviderDestroyed(int id) {
154   // Remove the render stream since the provider is destroyed.
155   render_manager_.RemoveRenderStream(render_id_);
156 }
157 
ViEExternalRendererImpl()158 ViEExternalRendererImpl::ViEExternalRendererImpl()
159     : external_renderer_(NULL),
160       external_renderer_format_(kVideoUnknown),
161       external_renderer_width_(0),
162       external_renderer_height_(0),
163       converted_frame_(new VideoFrame()) {
164 }
165 
SetViEExternalRenderer(ExternalRenderer * external_renderer,RawVideoType video_input_format)166 int ViEExternalRendererImpl::SetViEExternalRenderer(
167     ExternalRenderer* external_renderer,
168     RawVideoType video_input_format) {
169   external_renderer_ = external_renderer;
170   external_renderer_format_ = video_input_format;
171   return 0;
172 }
173 
RenderFrame(const uint32_t stream_id,I420VideoFrame & video_frame)174 int32_t ViEExternalRendererImpl::RenderFrame(
175     const uint32_t stream_id,
176     I420VideoFrame&   video_frame) {
177   if (video_frame.native_handle() != NULL) {
178     NotifyFrameSizeChange(stream_id, video_frame);
179 
180     if (external_renderer_->IsTextureSupported()) {
181       external_renderer_->DeliverFrame(NULL,
182                                        0,
183                                        video_frame.timestamp(),
184                                        video_frame.ntp_time_ms(),
185                                        video_frame.render_time_ms(),
186                                        video_frame.native_handle());
187     } else {
188       // TODO(wuchengli): readback the pixels and deliver the frame.
189     }
190     return 0;
191   }
192 
193   VideoFrame* out_frame = converted_frame_.get();
194 
195   // Convert to requested format.
196   VideoType type =
197       RawVideoTypeToCommonVideoVideoType(external_renderer_format_);
198   int buffer_size = CalcBufferSize(type, video_frame.width(),
199                                    video_frame.height());
200   if (buffer_size <= 0) {
201     // Unsupported video format.
202     assert(false);
203     return -1;
204   }
205   converted_frame_->VerifyAndAllocate(buffer_size);
206 
207   switch (external_renderer_format_) {
208     case kVideoI420: {
209       // TODO(mikhal): need to copy the buffer as is.
210       // can the output here be a I420 frame?
211       int length = ExtractBuffer(video_frame, out_frame->Size(),
212                                  out_frame->Buffer());
213       if (length < 0)
214         return -1;
215       out_frame->SetLength(length);
216       break;
217     }
218     case kVideoYV12:
219     case kVideoYUY2:
220     case kVideoUYVY:
221     case kVideoARGB:
222     case kVideoRGB24:
223     case kVideoRGB565:
224     case kVideoARGB4444:
225     case kVideoARGB1555 :
226       {
227         if (ConvertFromI420(video_frame, type, 0,
228                             converted_frame_->Buffer()) < 0)
229           return -1;
230         converted_frame_->SetLength(buffer_size);
231       }
232       break;
233     case kVideoIYUV:
234       // no conversion available
235       break;
236     default:
237       assert(false);
238       out_frame = NULL;
239       break;
240   }
241 
242   NotifyFrameSizeChange(stream_id, video_frame);
243 
244   if (out_frame) {
245     external_renderer_->DeliverFrame(out_frame->Buffer(),
246                                      out_frame->Length(),
247                                      video_frame.timestamp(),
248                                      video_frame.ntp_time_ms(),
249                                      video_frame.render_time_ms(),
250                                      NULL);
251   }
252   return 0;
253 }
254 
NotifyFrameSizeChange(const uint32_t stream_id,I420VideoFrame & video_frame)255 void ViEExternalRendererImpl::NotifyFrameSizeChange(
256     const uint32_t stream_id,
257     I420VideoFrame& video_frame) {
258   if (external_renderer_width_ != video_frame.width() ||
259       external_renderer_height_ != video_frame.height()) {
260     external_renderer_width_ = video_frame.width();
261     external_renderer_height_ = video_frame.height();
262     external_renderer_->FrameSizeChange(
263         external_renderer_width_, external_renderer_height_, stream_id);
264   }
265 }
266 
267 }  // namespace webrtc
268