• 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/modules/video_render/android/video_render_android_impl.h"
12 
13 #include "webrtc/modules/video_render/video_render_internal.h"
14 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
15 #include "webrtc/system_wrappers/include/event_wrapper.h"
16 #include "webrtc/system_wrappers/include/tick_util.h"
17 
18 #ifdef ANDROID
19 #include <android/log.h>
20 #include <stdio.h>
21 
22 #undef WEBRTC_TRACE
23 #define WEBRTC_TRACE(a,b,c,...)  __android_log_print(ANDROID_LOG_DEBUG, "*WEBRTCN*", __VA_ARGS__)
24 #else
25 #include "webrtc/system_wrappers/include/trace.h"
26 #endif
27 
28 namespace webrtc {
29 
30 JavaVM* VideoRenderAndroid::g_jvm = NULL;
31 
SetRenderAndroidVM(JavaVM * javaVM)32 int32_t SetRenderAndroidVM(JavaVM* javaVM) {
33   WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, -1, "%s", __FUNCTION__);
34   VideoRenderAndroid::g_jvm = javaVM;
35   return 0;
36 }
37 
VideoRenderAndroid(const int32_t id,const VideoRenderType videoRenderType,void * window,const bool)38 VideoRenderAndroid::VideoRenderAndroid(
39     const int32_t id,
40     const VideoRenderType videoRenderType,
41     void* window,
42     const bool /*fullscreen*/):
43     _id(id),
44     _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
45     _renderType(videoRenderType),
46     _ptrWindow((jobject)(window)),
47     _javaShutDownFlag(false),
48     _javaShutdownEvent(*EventWrapper::Create()),
49     _javaRenderEvent(*EventWrapper::Create()),
50     _lastJavaRenderEvent(0),
51     _javaRenderJniEnv(NULL) {
52 }
53 
~VideoRenderAndroid()54 VideoRenderAndroid::~VideoRenderAndroid() {
55   WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id,
56                "VideoRenderAndroid dtor");
57 
58   if (_javaRenderThread)
59     StopRender();
60 
61   for (AndroidStreamMap::iterator it = _streamsMap.begin();
62        it != _streamsMap.end();
63        ++it) {
64     delete it->second;
65   }
66   delete &_javaShutdownEvent;
67   delete &_javaRenderEvent;
68   delete &_critSect;
69 }
70 
ChangeWindow(void *)71 int32_t VideoRenderAndroid::ChangeWindow(void* /*window*/) {
72   return -1;
73 }
74 
75 VideoRenderCallback*
AddIncomingRenderStream(const uint32_t streamId,const uint32_t zOrder,const float left,const float top,const float right,const float bottom)76 VideoRenderAndroid::AddIncomingRenderStream(const uint32_t streamId,
77                                             const uint32_t zOrder,
78                                             const float left, const float top,
79                                             const float right,
80                                             const float bottom) {
81   CriticalSectionScoped cs(&_critSect);
82 
83   AndroidStream* renderStream = NULL;
84   AndroidStreamMap::iterator item = _streamsMap.find(streamId);
85   if (item != _streamsMap.end() && item->second != NULL) {
86     WEBRTC_TRACE(kTraceInfo,
87                  kTraceVideoRenderer,
88                  -1,
89                  "%s: Render stream already exists",
90                  __FUNCTION__);
91     return renderStream;
92   }
93 
94   renderStream = CreateAndroidRenderChannel(streamId, zOrder, left, top,
95                                             right, bottom, *this);
96   if (renderStream) {
97     _streamsMap[streamId] = renderStream;
98   }
99   else {
100     WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
101                  "(%s:%d): renderStream is NULL", __FUNCTION__, __LINE__);
102     return NULL;
103   }
104   return renderStream;
105 }
106 
DeleteIncomingRenderStream(const uint32_t streamId)107 int32_t VideoRenderAndroid::DeleteIncomingRenderStream(
108     const uint32_t streamId) {
109   CriticalSectionScoped cs(&_critSect);
110 
111   AndroidStreamMap::iterator item = _streamsMap.find(streamId);
112   if (item == _streamsMap.end()) {
113     WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
114                  "(%s:%d): renderStream is NULL", __FUNCTION__, __LINE__);
115     return -1;
116   }
117   delete item->second;
118   _streamsMap.erase(item);
119   return 0;
120 }
121 
GetIncomingRenderStreamProperties(const uint32_t streamId,uint32_t & zOrder,float & left,float & top,float & right,float & bottom) const122 int32_t VideoRenderAndroid::GetIncomingRenderStreamProperties(
123     const uint32_t streamId,
124     uint32_t& zOrder,
125     float& left,
126     float& top,
127     float& right,
128     float& bottom) const {
129   return -1;
130 }
131 
StartRender()132 int32_t VideoRenderAndroid::StartRender() {
133   CriticalSectionScoped cs(&_critSect);
134 
135   if (_javaRenderThread) {
136     // StartRender is called when this stream should start render.
137     // However StopRender is not called when the streams stop rendering.
138     // Thus the the thread  is only deleted when the renderer is removed.
139     WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id,
140                  "%s, Render thread already exist", __FUNCTION__);
141     return 0;
142   }
143 
144   _javaRenderThread.reset(new rtc::PlatformThread(JavaRenderThreadFun, this,
145                                                   "AndroidRenderThread"));
146 
147   _javaRenderThread->Start();
148   WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s: thread started",
149                __FUNCTION__);
150   _javaRenderThread->SetPriority(rtc::kRealtimePriority);
151   return 0;
152 }
153 
StopRender()154 int32_t VideoRenderAndroid::StopRender() {
155   WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s:", __FUNCTION__);
156   {
157     CriticalSectionScoped cs(&_critSect);
158     if (!_javaRenderThread)
159     {
160       return -1;
161     }
162     _javaShutDownFlag = true;
163     _javaRenderEvent.Set();
164   }
165 
166   _javaShutdownEvent.Wait(3000);
167   CriticalSectionScoped cs(&_critSect);
168   _javaRenderThread->Stop();
169   _javaRenderThread.reset();
170 
171   return 0;
172 }
173 
ReDraw()174 void VideoRenderAndroid::ReDraw() {
175   CriticalSectionScoped cs(&_critSect);
176   // Allow redraw if it was more than 20ms since last.
177   if (_lastJavaRenderEvent < TickTime::MillisecondTimestamp() - 20) {
178     _lastJavaRenderEvent = TickTime::MillisecondTimestamp();
179     _javaRenderEvent.Set();
180   }
181 }
182 
JavaRenderThreadFun(void * obj)183 bool VideoRenderAndroid::JavaRenderThreadFun(void* obj) {
184   return static_cast<VideoRenderAndroid*> (obj)->JavaRenderThreadProcess();
185 }
186 
JavaRenderThreadProcess()187 bool VideoRenderAndroid::JavaRenderThreadProcess()
188 {
189   _javaRenderEvent.Wait(1000);
190 
191   CriticalSectionScoped cs(&_critSect);
192   if (!_javaRenderJniEnv) {
193     // try to attach the thread and get the env
194     // Attach this thread to JVM
195     jint res = g_jvm->AttachCurrentThread(&_javaRenderJniEnv, NULL);
196 
197     // Get the JNI env for this thread
198     if ((res < 0) || !_javaRenderJniEnv) {
199       WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
200                    "%s: Could not attach thread to JVM (%d, %p)",
201                    __FUNCTION__, res, _javaRenderJniEnv);
202       return false;
203     }
204   }
205 
206   for (AndroidStreamMap::iterator it = _streamsMap.begin();
207        it != _streamsMap.end();
208        ++it) {
209     it->second->DeliverFrame(_javaRenderJniEnv);
210   }
211 
212   if (_javaShutDownFlag) {
213     if (g_jvm->DetachCurrentThread() < 0)
214       WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, _id,
215                    "%s: Could not detach thread from JVM", __FUNCTION__);
216     else {
217       WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id,
218                    "%s: Java thread detached", __FUNCTION__);
219     }
220     _javaRenderJniEnv = NULL;
221     _javaShutDownFlag = false;
222     _javaShutdownEvent.Set();
223     return false; // Do not run this thread again.
224   }
225   return true;
226 }
227 
RenderType()228 VideoRenderType VideoRenderAndroid::RenderType() {
229   return _renderType;
230 }
231 
PerferedVideoType()232 RawVideoType VideoRenderAndroid::PerferedVideoType() {
233   return kVideoI420;
234 }
235 
FullScreen()236 bool VideoRenderAndroid::FullScreen() {
237   return false;
238 }
239 
GetGraphicsMemory(uint64_t &,uint64_t &) const240 int32_t VideoRenderAndroid::GetGraphicsMemory(
241     uint64_t& /*totalGraphicsMemory*/,
242     uint64_t& /*availableGraphicsMemory*/) const {
243   WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
244                "%s - not supported on Android", __FUNCTION__);
245   return -1;
246 }
247 
GetScreenResolution(uint32_t &,uint32_t &) const248 int32_t VideoRenderAndroid::GetScreenResolution(
249     uint32_t& /*screenWidth*/,
250     uint32_t& /*screenHeight*/) const {
251   WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
252                "%s - not supported on Android", __FUNCTION__);
253   return -1;
254 }
255 
RenderFrameRate(const uint32_t)256 uint32_t VideoRenderAndroid::RenderFrameRate(
257     const uint32_t /*streamId*/) {
258   WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
259                "%s - not supported on Android", __FUNCTION__);
260   return -1;
261 }
262 
SetStreamCropping(const uint32_t,const float,const float,const float,const float)263 int32_t VideoRenderAndroid::SetStreamCropping(
264     const uint32_t /*streamId*/,
265     const float /*left*/,
266     const float /*top*/,
267     const float /*right*/,
268     const float /*bottom*/) {
269   WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
270                "%s - not supported on Android", __FUNCTION__);
271   return -1;
272 }
273 
SetTransparentBackground(const bool enable)274 int32_t VideoRenderAndroid::SetTransparentBackground(const bool enable) {
275   WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
276                "%s - not supported on Android", __FUNCTION__);
277   return -1;
278 }
279 
ConfigureRenderer(const uint32_t streamId,const unsigned int zOrder,const float left,const float top,const float right,const float bottom)280 int32_t VideoRenderAndroid::ConfigureRenderer(
281     const uint32_t streamId,
282     const unsigned int zOrder,
283     const float left,
284     const float top,
285     const float right,
286     const float bottom) {
287   WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
288                "%s - not supported on Android", __FUNCTION__);
289   return -1;
290 }
291 
SetText(const uint8_t textId,const uint8_t * text,const int32_t textLength,const uint32_t textColorRef,const uint32_t backgroundColorRef,const float left,const float top,const float rigth,const float bottom)292 int32_t VideoRenderAndroid::SetText(
293     const uint8_t textId,
294     const uint8_t* text,
295     const int32_t textLength,
296     const uint32_t textColorRef,
297     const uint32_t backgroundColorRef,
298     const float left, const float top,
299     const float rigth, const float bottom) {
300   WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
301                "%s - not supported on Android", __FUNCTION__);
302   return -1;
303 }
304 
SetBitmap(const void * bitMap,const uint8_t pictureId,const void * colorKey,const float left,const float top,const float right,const float bottom)305 int32_t VideoRenderAndroid::SetBitmap(const void* bitMap,
306                                       const uint8_t pictureId,
307                                       const void* colorKey,
308                                       const float left, const float top,
309                                       const float right,
310                                       const float bottom) {
311   WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
312                "%s - not supported on Android", __FUNCTION__);
313   return -1;
314 }
315 
316 }  // namespace webrtc
317