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