1 /*
2  *			GPAC - Multimedia Framework C SDK
3  *
4  *			Authors: Ivica Arsov, Jean Le Feuvre
5  *			Copyright (c) Mines-Telecom 2009-
6  *					All rights reserved
7  *
8  *  This file is part of GPAC / MPEG-V Input sensor for android
9  *
10  *  GPAC is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU Lesser General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  *  GPAC is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 #include <jni.h>
27 #include <android/log.h>
28 
29 /*driver interfaces*/
30 
31 #include <gpac/list.h>
32 #include <gpac/constants.h>
33 
34 #include <gpac/setup.h>
35 
36 #include <gpac/modules/codec.h>
37 #include <gpac/scenegraph_vrml.h>
38 
39 #include <gpac/thread.h>
40 
41 #define LOG_TAG "MPEG-V_IN"
42 #ifdef ANDROID
43 #  define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
44 #  define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
45 #else
46 #  define QUOTEME_(x) #x
47 #  define QUOTEME(x) QUOTEME_(x)
48 #  define LOGI(...) fprintf(stderr, "I/" LOG_TAG " (" __FILE__ ":" QUOTEME(__LINE__) "): " __VA_ARGS__)
49 #  define LOGE(...) fprintf(stderr, "E/" LOG_TAG "(" ")" __VA_ARGS__)
50 #endif
51 
52 JNIEXPORT void JNICALL Java_com_gpac_Osmo4_MPEGVSensor_sendData( JNIEnv* env, jobject thiz, jint ptr, jstring data);
53 
54 static JavaVM* javaVM = 0;
55 static jclass sensCtrlClass;
56 static jmethodID cid;
57 static jmethodID startSensor;
58 static jmethodID stopSensor;
59 
60 #ifndef GPAC_STATIC_MODULES
61 
62 //----------------------------------------------------------------------
JNI_OnLoad(JavaVM * vm,void * reserved)63 jint JNI_OnLoad(JavaVM* vm, void* reserved)
64 {
65 	JNIEnv* env = 0;
66 	javaVM = vm;
67 
68 	if ( (*javaVM)->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2) != JNI_OK )
69 		return -1;
70 
71 	// Get the class and its methods in the main env
72 
73 	// Get the CameraController class
74 	// This is just a local refenrece. Cannot be used in the other JNI calls.
75 	sensCtrlClass = (*env)->FindClass(env, "com/gpac/Osmo4/MPEGVSensor");
76 	if (sensCtrlClass == 0)
77 	{
78 		LOGE("[MPEG-V_IN] Class MPEGVSensor not found\n");
79 		return -1;
80 	}
81 
82 	// Get Global Reference to be able to use the class
83 	sensCtrlClass = (*env)->NewGlobalRef(env, sensCtrlClass);
84 	if ( sensCtrlClass == 0 )
85 	{
86 		LOGE("[MPEG-V_IN] Caanot create Global Reference\n");
87 		return -1;
88 	}
89 
90 	// Get the method ID for the CameraController constructor.
91 	cid = (*env)->GetMethodID(env, sensCtrlClass, "<init>", "()V");
92 	if (cid == 0)
93 	{
94 		LOGE("[MPEG-V_IN] MPEGVSensor Constructor not found\n");
95 		return -1;
96 	}
97 
98 	// Get startCamera() method from class CameraController
99 	startSensor = (*env)->GetMethodID(env, sensCtrlClass, "startSensor", "(II)V");
100 	if (startSensor == 0)
101 	{
102 		LOGE("[MPEG-V_IN] Function startSensor not found\n");
103 		return -1;
104 	}
105 
106 	stopSensor = (*env)->GetMethodID(env, sensCtrlClass, "stopSensor", "()V");
107 	if (stopSensor == 0)
108 	{
109 		LOGE("[MPEG-V_IN] Function stopSensor not found\n");
110 		return -1;
111 	}
112 
113 	return JNI_VERSION_1_2;
114 }
115 
JNI_OnUnload(JavaVM * vm,void * reserved)116 void JNI_OnUnload(JavaVM *vm, void *reserved)
117 {
118 	JNIEnv* env = 0;
119 
120 	if ( (*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_2) != JNI_OK )
121 		return;
122 
123 	(*env)->DeleteGlobalRef(env, sensCtrlClass);
124 }
125 
126 //----------------------------------------------------------------------
GetJavaVM()127 JavaVM* GetJavaVM()
128 {
129 	return javaVM;
130 }
131 //----------------------------------------------------------------------
132 #else
133 JavaVM* GetJavaVM();
134 JNIEnv* GetEnv();
135 
136 #endif
137 
138 typedef struct
139 {
140 	char sensor[50];
141 	u16 sensorAndroidType;
142 	u8 isAttached;
143 
144 	GF_Thread *trd;
145 	u8 stop;
146 
147 	JNIEnv* env;
148 	jclass sensCtrlClass;
149 	jmethodID cid;
150 	jobject sensCtrlObj;
151 	jmethodID startSensor;
152 	jmethodID stopSensor;
153 } MPEGVSensorContext;
154 
155 #define MPEGVSCTX	MPEGVSensorContext *rc = (MPEGVSensorContext *)dr->udta
156 
unloadSensorController(MPEGVSensorContext * rc)157 void unloadSensorController(MPEGVSensorContext *rc)
158 {
159 	if ( rc->isAttached )
160 	{
161 		(*rc->env)->PopLocalFrame(rc->env, NULL);
162 		(*GetJavaVM())->DetachCurrentThread(GetJavaVM());
163 		rc->isAttached = 0;
164 	}
165 
166 	rc->env = NULL;
167 }
168 
loadSensorControler(MPEGVSensorContext * rc)169 void loadSensorControler(MPEGVSensorContext *rc)
170 {
171 	JNIEnv* env = NULL;
172 	jint res = 0;
173 
174 	// Here we can be in a thread
175 
176 	res = (*GetJavaVM())->GetEnv(javaVM, (void**)&env, JNI_VERSION_1_2);
177 	if ( res == JNI_EDETACHED )
178 	{
179 		GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] The current thread is not attached to the VM, assuming native thread\n"));
180 		res = (*GetJavaVM())->AttachCurrentThread(GetJavaVM(), &env, NULL);
181 		if ( res )
182 		{
183 			GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Attach current thread failed: %d\n", res));
184 			return;
185 		}
186 		rc->isAttached = 1;
187 		(*env)->PushLocalFrame(env, 2);
188 	}
189 	else if ( res == JNI_EVERSION )
190 	{
191 		GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] The specified version is not supported\n"));
192 		return;
193 	}
194 
195 	rc->env = env;
196 	rc->sensCtrlClass = sensCtrlClass;
197 	rc->cid = cid;
198 	rc->startSensor = startSensor;
199 	rc->stopSensor = stopSensor;
200 
201 	// Create the sensor object in the thread
202 	rc->sensCtrlObj = (*rc->env)->NewObject(rc->env, rc->sensCtrlClass, rc->cid);
203 	if (rc->sensCtrlObj == 0)
204 	{
205 		GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Cannot create MPEGVSensor object\n"));
206 		return;
207 	}
208 }
209 
MPEGVS_RegisterDevice(struct __input_device * dr,const char * urn,const char * dsi,u32 dsi_size,void (* AddField)(struct __input_device * _this,u32 fieldType,const char * name))210 Bool MPEGVS_RegisterDevice(struct __input_device *dr, const char *urn, const char *dsi, u32 dsi_size, void (*AddField)(struct __input_device *_this, u32 fieldType, const char *name))
211 {
212 	MPEGVSCTX;
213 
214 	//"MPEG-V:siv:OrientationSensorType"
215 
216 	if ( strnicmp(urn, "MPEG-V", 6) )
217 		return 0;
218 
219 	if ( strlen(urn) <= 6 )
220 	{
221 		GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[MPEG-V] No sensor type specified\n"));
222 		return 0;
223 	}
224 
225 	if ( strnicmp(urn+6, ":siv:", 5) )
226 	{
227 		GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[MPEG-V] Not valid sensor type specified\n"));
228 		return 0;
229 	}
230 
231 	strcpy(rc->sensor, urn+11);
232 
233 	if ( !strcmp(rc->sensor, "OrientationSensorType") )
234 	{
235 		AddField(dr, GF_SG_VRML_SFVEC3F, "Orientation");
236 
237 		rc->sensorAndroidType = 3;
238 
239 		return 1;
240 	}
241 	else if ( !strcmp(rc->sensor, "AccelerationSensorType") )
242 	{
243 		AddField(dr, GF_SG_VRML_SFVEC3F, "Acceleration");
244 
245 		rc->sensorAndroidType = 1;
246 
247 		return 1;
248 	}
249 	else if ( !strcmp(rc->sensor, "AngularVelocitySensorType") )
250 	{
251 		AddField(dr, GF_SG_VRML_SFVEC3F, "AngularVelocity");
252 
253 		rc->sensorAndroidType = 4;
254 
255 		return 1;
256 	}
257 	else if ( !strcmp(rc->sensor, "MagneticFieldSensorType") )
258 	{
259 		AddField(dr, GF_SG_VRML_SFVEC3F, "MagneticField");
260 
261 		rc->sensorAndroidType = 2;
262 
263 		return 1;
264 	}
265 	else if ( !strcmp(rc->sensor, "LightSensorType") )
266 	{
267 		AddField(dr, GF_SG_VRML_SFFLOAT, "Light");
268 
269 		rc->sensorAndroidType = 5;
270 
271 		return 1;
272 	}
273 	else if ( !strcmp(rc->sensor, "AtmosphericPressureSensorType") )
274 	{
275 		AddField(dr, GF_SG_VRML_SFFLOAT, "AtmosphericPressure");
276 
277 		rc->sensorAndroidType = 6;
278 
279 		return 1;
280 	}
281 	else if ( !strcmp(rc->sensor, "RotationVectorSensorType") )
282 	{
283 		AddField(dr, GF_SG_VRML_SFVEC3F, "RotationVector");
284 
285 		rc->sensorAndroidType = 11;
286 
287 		return 1;
288 	}
289 	else if ( !strcmp(rc->sensor, "GlobalPositionSensorType") )
290 	{
291 		AddField(dr, GF_SG_VRML_SFVEC3F, "Position");
292 		AddField(dr, GF_SG_VRML_SFFLOAT, "Accuracy");
293 		AddField(dr, GF_SG_VRML_SFFLOAT, "Bearing");
294 
295 		rc->sensorAndroidType = 100;
296 
297 		return 1;
298 	}
299 	else
300 	{
301 		GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[MPEG-V_IN] Unsupported sensor type: %s\n", rc->sensor));
302 		return 0;
303 	}
304 }
305 
MPEGVS_OnData(struct __input_device * dr,const char * data)306 u32 MPEGVS_OnData(struct __input_device * dr, const char* data)
307 {
308 	GF_BitStream *bs;
309 	u8 *buf;
310 	u32 buf_size;
311 	float x, y, z, /*q,*/ a, b;
312 	MPEGVSCTX;
313 
314 	bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
315 
316 	if ( rc->sensorAndroidType == 1
317 	        || rc->sensorAndroidType == 2
318 	        || rc->sensorAndroidType == 3
319 	        || rc->sensorAndroidType == 4 )
320 	{
321 		sscanf(data, "%f;%f;%f;", &x, &y, &z);
322 		gf_bs_write_int(bs, 1, 1);
323 		gf_bs_write_float(bs, x);
324 		gf_bs_write_float(bs, y);
325 		gf_bs_write_float(bs, z);
326 	}
327 	else if ( rc->sensorAndroidType == 5
328 	          || rc->sensorAndroidType == 6 )
329 	{
330 		sscanf(data, "%f;", &x);
331 
332 		gf_bs_write_int(bs, 1, 1);
333 		gf_bs_write_float(bs, x);
334 	}
335 	else if ( rc->sensorAndroidType == 11 )
336 	{
337 		sscanf(data, "%f;%f;%f;", &x, &y, &z);
338 
339 		gf_bs_write_int(bs, 1, 1);
340 		gf_bs_write_float(bs, x);
341 		gf_bs_write_float(bs, y);
342 		gf_bs_write_float(bs, z);
343 		/*gf_bs_write_float(bs, q);*/
344 	}
345 	else if ( rc->sensorAndroidType == 100 )
346 	{
347 		sscanf(data, "%f;%f;%f;%f;%f;", &x, &y, &z, &a, &b);
348 
349 		gf_bs_write_int(bs, 1, 1);
350 		gf_bs_write_float(bs, x);
351 		gf_bs_write_float(bs, y);
352 		gf_bs_write_float(bs, z);
353 		gf_bs_write_int(bs, 1, 1);
354 		gf_bs_write_float(bs, a);
355 		gf_bs_write_int(bs, 1, 1);
356 		gf_bs_write_float(bs, b);
357 		/*gf_bs_write_float(bs, q);*/
358 	}
359 
360 	gf_bs_align(bs);
361 	gf_bs_get_content(bs, &buf, &buf_size);
362 	gf_bs_del(bs);
363 
364 	dr->DispatchFrame(dr, (u8*)buf, buf_size);
365 	gf_free(buf);
366 
367 	return GF_OK;
368 }
369 
Java_com_gpac_Osmo4_MPEGVSensor_sendData(JNIEnv * env,jobject thiz,jint ptr,jstring data)370 JNIEXPORT void Java_com_gpac_Osmo4_MPEGVSensor_sendData( JNIEnv* env, jobject thiz, jint ptr, jstring data)
371 {
372 	jboolean isCopy;
373 	const char * cData = (*env)->GetStringUTFChars(env, data, &isCopy);
374 
375 	MPEGVS_OnData((struct __input_device *)ptr, cData);
376 
377 	(*env)->ReleaseStringUTFChars(env, data, cData);
378 }
379 
ThreadRun(void * param)380 u32 ThreadRun(void* param)
381 {
382 	struct __input_device * dr = (struct __input_device *)param;
383 	MPEGVSCTX;
384 
385 	GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Start: %d\n", gf_th_id()));
386 
387 	loadSensorControler(rc);
388 
389 	if (!rc->env || !rc->sensCtrlObj)
390 		return GF_OK;
391 
392 	(*rc->env)->CallNonvirtualVoidMethod(rc->env, rc->sensCtrlObj, rc->sensCtrlClass, rc->startSensor, (s32)dr, rc->sensorAndroidType);
393 
394 	while (!rc->stop)
395 		gf_sleep(10);
396 
397 	GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[MPEG-V_IN] Stop: %d\n", gf_th_id()));
398 
399 	if (!rc->env)
400 		return GF_OK;
401 
402 	if ( rc->sensCtrlObj )
403 	{
404 		(*rc->env)->CallNonvirtualVoidMethod(rc->env, rc->sensCtrlObj, rc->sensCtrlClass, rc->stopSensor);
405 
406 		(*rc->env)->DeleteLocalRef( rc->env, rc->sensCtrlObj );
407 	}
408 
409 	unloadSensorController(rc);
410 	return GF_OK;
411 }
412 
MPEGVS_Start(struct __input_device * dr)413 void MPEGVS_Start(struct __input_device * dr)
414 {
415 	MPEGVSCTX;
416 
417 	rc->trd = gf_th_new("MPEG-V_IN");
418 	gf_th_run(rc->trd, ThreadRun, dr);
419 }
420 
MPEGVS_Stop(struct __input_device * dr)421 void MPEGVS_Stop(struct __input_device * dr)
422 {
423 	MPEGVSCTX;
424 
425 	if ( rc->trd )
426 	{
427 		rc->stop = 1;
428 		while ( gf_th_status(rc->trd) == GF_THREAD_STATUS_RUN )
429 			gf_sleep(5);
430 
431 		gf_th_del(rc->trd);
432 		rc->trd = NULL;
433 		rc->stop = 0;
434 	}
435 }
436 
NewMPEGVSInputSesor()437 GF_InputSensorDevice* NewMPEGVSInputSesor()
438 {
439 	MPEGVSensorContext* ctx;
440 	GF_InputSensorDevice* driv;
441 
442 	driv = (GF_InputSensorDevice *) gf_malloc(sizeof(GF_InputSensorDevice));
443 	memset(driv, 0, sizeof(GF_InputSensorDevice));
444 	GF_REGISTER_MODULE_INTERFACE(driv, GF_INPUT_DEVICE_INTERFACE, "MPEG-V Sensors Input Module", "gpac distribution");
445 
446 	driv->RegisterDevice = MPEGVS_RegisterDevice;
447 	driv->Start = MPEGVS_Start;
448 	driv->Stop = MPEGVS_Stop;
449 
450 	ctx = (MPEGVSensorContext*) gf_malloc (sizeof(MPEGVSensorContext));
451 	memset(ctx, 0, sizeof(MPEGVSensorContext));
452 
453 	driv->udta = (void*)ctx;
454 
455 	return driv;
456 }
457 
DeleteMPEGVSInputSensor(GF_InputSensorDevice * dev)458 void DeleteMPEGVSInputSensor(GF_InputSensorDevice* dev)
459 {
460 	MPEGVS_Stop(dev);
461 	gf_free(dev->udta);
462 	gf_free(dev);
463 }
464 
465 /*interface query*/
466 GPAC_MODULE_EXPORT
QueryInterfaces()467 const u32 *QueryInterfaces()
468 {
469 	static u32 si [] = {
470 		GF_INPUT_DEVICE_INTERFACE,
471 		0
472 	};
473 	return si;
474 }
475 
476 /*interface create*/
477 GPAC_MODULE_EXPORT
LoadInterface(u32 InterfaceType)478 GF_BaseInterface *LoadInterface(u32 InterfaceType)
479 {
480 	if (InterfaceType == GF_INPUT_DEVICE_INTERFACE) return (GF_BaseInterface *) NewMPEGVSInputSesor();
481 	return NULL;
482 }
483 
484 /*interface destroy*/
485 GPAC_MODULE_EXPORT
ShutdownInterface(GF_BaseInterface * ifce)486 void ShutdownInterface(GF_BaseInterface *ifce)
487 {
488 	switch (ifce->InterfaceType) {
489 	case GF_INPUT_DEVICE_INTERFACE:
490 		DeleteMPEGVSInputSensor((GF_InputSensorDevice *)ifce);
491 		break;
492 	}
493 }
494 
495 GPAC_MODULE_STATIC_DECLARATION( droid_mpegv )
496