1 /*
2 * Copyright (C) 2012,2018 Collabora Ltd.
3 * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
4 * Copyright (C) 2015, Sebastian Dröge <sebastian@centricular.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation
9 * version 2.1 of the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "../gstjniutils.h"
27 #include "../gstamc-codeclist.h"
28
29 struct _GstAmcCodecInfoHandle
30 {
31 jobject object;
32 };
33
34 struct _GstAmcCodecCapabilitiesHandle
35 {
36 jobject object;
37 };
38
39 static struct
40 {
41 jclass klass;
42 jmethodID get_codec_count;
43 jmethodID get_codec_info_at;
44 } media_codeclist;
45
46 static struct
47 {
48 jclass klass;
49 jmethodID get_capabilities_for_type;
50 jmethodID get_name;
51 jmethodID get_supported_types;
52 jmethodID is_encoder;
53 } media_codecinfo;
54
55 static struct
56 {
57 jclass klass;
58 jfieldID color_formats;
59 jfieldID profile_levels;
60 } media_codeccapabilities;
61
62 static struct
63 {
64 jclass klass;
65 jfieldID level;
66 jfieldID profile;
67 } media_codecprofilelevel;
68
69 gboolean
gst_amc_codeclist_static_init(void)70 gst_amc_codeclist_static_init (void)
71 {
72 JNIEnv *env;
73 GError *err = NULL;
74
75 env = gst_amc_jni_get_env ();
76
77 media_codeclist.klass =
78 gst_amc_jni_get_class (env, &err, "android/media/MediaCodecList");
79 if (!media_codeclist.klass) {
80 GST_ERROR ("Failed to get android.media.MediaCodecList class: %s",
81 err->message);
82 g_clear_error (&err);
83 return FALSE;
84 }
85
86 media_codeclist.get_codec_count =
87 gst_amc_jni_get_static_method_id (env, &err, media_codeclist.klass,
88 "getCodecCount", "()I");
89 if (!media_codeclist.get_codec_count) {
90 GST_ERROR ("Failed to get android.media.MediaCodecList getCodecCount(): %s",
91 err->message);
92 g_clear_error (&err);
93 return FALSE;
94 }
95
96 media_codeclist.get_codec_info_at =
97 gst_amc_jni_get_static_method_id (env, &err, media_codeclist.klass,
98 "getCodecInfoAt", "(I)Landroid/media/MediaCodecInfo;");
99 if (!media_codeclist.get_codec_count) {
100 GST_ERROR
101 ("Failed to get android.media.MediaCodecList getCodecInfoAt(): %s",
102 err->message);
103 g_clear_error (&err);
104 return FALSE;
105 }
106
107 media_codecinfo.klass =
108 gst_amc_jni_get_class (env, &err, "android/media/MediaCodecInfo");
109 if (!media_codecinfo.klass) {
110 GST_ERROR ("Failed to get android.media.MediaCodecInfo class: %s",
111 err->message);
112 g_clear_error (&err);
113 return FALSE;
114 }
115
116 media_codecinfo.get_capabilities_for_type =
117 gst_amc_jni_get_method_id (env, &err, media_codecinfo.klass,
118 "getCapabilitiesForType",
119 "(Ljava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;");
120 if (!media_codecinfo.get_capabilities_for_type) {
121 GST_ERROR
122 ("Failed to get android.media.MediaCodecInfo getCapabilitiesForType(): %s",
123 err->message);
124 g_clear_error (&err);
125 return FALSE;
126 }
127
128 media_codecinfo.get_name =
129 gst_amc_jni_get_method_id (env, &err, media_codecinfo.klass, "getName",
130 "()Ljava/lang/String;");
131 if (!media_codecinfo.get_name) {
132 GST_ERROR ("Failed to get android.media.MediaCodecInfo getName(): %s",
133 err->message);
134 g_clear_error (&err);
135 return FALSE;
136 }
137
138 media_codecinfo.get_supported_types =
139 gst_amc_jni_get_method_id (env, &err, media_codecinfo.klass,
140 "getSupportedTypes", "()[Ljava/lang/String;");
141 if (!media_codecinfo.get_supported_types) {
142 GST_ERROR
143 ("Failed to get android.media.MediaCodecInfo getSupportedTypes(): %s",
144 err->message);
145 g_clear_error (&err);
146 return FALSE;
147 }
148
149 media_codecinfo.is_encoder =
150 gst_amc_jni_get_method_id (env, &err, media_codecinfo.klass, "isEncoder",
151 "()Z");
152 if (!media_codecinfo.is_encoder) {
153 GST_ERROR ("Failed to get android.media.MediaCodecInfo isEncoder(): %s",
154 err->message);
155 g_clear_error (&err);
156 return FALSE;
157 }
158
159 media_codeccapabilities.klass =
160 gst_amc_jni_get_class (env, &err,
161 "android/media/MediaCodecInfo$CodecCapabilities");
162 if (!media_codeccapabilities.klass) {
163 GST_ERROR
164 ("Failed to get android.media.MediaCodecInfo.CodecCapabilities class: %s",
165 err->message);
166 g_clear_error (&err);
167 return FALSE;
168 }
169
170 media_codeccapabilities.color_formats =
171 gst_amc_jni_get_field_id (env, &err, media_codeccapabilities.klass,
172 "colorFormats", "[I");
173 if (!media_codeccapabilities.color_formats) {
174 GST_ERROR
175 ("Failed to get android.media.MediaCodecInfo.CodecCapabilities colorFormats: %s",
176 err->message);
177 g_clear_error (&err);
178 return FALSE;
179 }
180
181 media_codeccapabilities.profile_levels =
182 gst_amc_jni_get_field_id (env, &err, media_codeccapabilities.klass,
183 "profileLevels", "[Landroid/media/MediaCodecInfo$CodecProfileLevel;");
184 if (!media_codeccapabilities.profile_levels) {
185 GST_ERROR
186 ("Failed to get android.media.MediaCodecInfo.CodecCapabilities profileLevels: %s",
187 err->message);
188 g_clear_error (&err);
189 return FALSE;
190 }
191
192 media_codecprofilelevel.klass =
193 gst_amc_jni_get_class (env, &err,
194 "android/media/MediaCodecInfo$CodecProfileLevel");
195 if (!media_codecprofilelevel.klass) {
196 GST_ERROR
197 ("Failed to get android.media.MediaCodecInfo.CodecProfileLevel class: %s",
198 err->message);
199 g_clear_error (&err);
200 return FALSE;
201 }
202
203 media_codecprofilelevel.level =
204 gst_amc_jni_get_field_id (env, &err, media_codecprofilelevel.klass,
205 "level", "I");
206 if (!media_codecprofilelevel.level) {
207 GST_ERROR
208 ("Failed to get android.media.MediaCodecInfo.CodecProfileLevel level: %s",
209 err->message);
210 g_clear_error (&err);
211 return FALSE;
212 }
213
214 media_codecprofilelevel.profile =
215 gst_amc_jni_get_field_id (env, &err, media_codecprofilelevel.klass,
216 "profile", "I");
217 if (!media_codecprofilelevel.profile) {
218 GST_ERROR
219 ("Failed to get android.media.MediaCodecInfo.CodecProfileLevel profile: %s",
220 err->message);
221 g_clear_error (&err);
222 return FALSE;
223 }
224
225 return TRUE;
226 }
227
228 gboolean
gst_amc_codeclist_get_count(gint * count,GError ** err)229 gst_amc_codeclist_get_count (gint * count, GError ** err)
230 {
231 JNIEnv *env;
232
233 env = gst_amc_jni_get_env ();
234
235 if (!gst_amc_jni_call_static_int_method (env, err, media_codeclist.klass,
236 media_codeclist.get_codec_count, count))
237 return FALSE;
238
239 return TRUE;
240 }
241
242 GstAmcCodecInfoHandle *
gst_amc_codeclist_get_codec_info_at(gint index,GError ** err)243 gst_amc_codeclist_get_codec_info_at (gint index, GError ** err)
244 {
245 GstAmcCodecInfoHandle *ret;
246 jobject object;
247 JNIEnv *env;
248
249 env = gst_amc_jni_get_env ();
250
251 if (!gst_amc_jni_call_static_object_method (env, err, media_codeclist.klass,
252 media_codeclist.get_codec_info_at, &object, index))
253 return NULL;
254
255 ret = g_new0 (GstAmcCodecInfoHandle, 1);
256 ret->object = object;
257 return ret;
258 }
259
260 void
gst_amc_codec_info_handle_free(GstAmcCodecInfoHandle * handle)261 gst_amc_codec_info_handle_free (GstAmcCodecInfoHandle * handle)
262 {
263 JNIEnv *env;
264
265 g_return_if_fail (handle != NULL);
266
267 env = gst_amc_jni_get_env ();
268
269 if (handle->object)
270 gst_amc_jni_object_local_unref (env, handle->object);
271 g_free (handle);
272 }
273
274 gchar *
gst_amc_codec_info_handle_get_name(GstAmcCodecInfoHandle * handle,GError ** err)275 gst_amc_codec_info_handle_get_name (GstAmcCodecInfoHandle * handle,
276 GError ** err)
277 {
278 JNIEnv *env;
279 jstring v_str = NULL;
280
281 g_return_val_if_fail (handle != NULL, NULL);
282
283 env = gst_amc_jni_get_env ();
284
285 if (!gst_amc_jni_call_object_method (env, err, handle->object,
286 media_codecinfo.get_name, &v_str))
287 return NULL;
288
289 return gst_amc_jni_string_to_gchar (env, v_str, TRUE);
290 }
291
292 gboolean
gst_amc_codec_info_handle_is_encoder(GstAmcCodecInfoHandle * handle,gboolean * is_encoder,GError ** err)293 gst_amc_codec_info_handle_is_encoder (GstAmcCodecInfoHandle * handle,
294 gboolean * is_encoder, GError ** err)
295 {
296 JNIEnv *env;
297
298 g_return_val_if_fail (handle != NULL, FALSE);
299 g_return_val_if_fail (is_encoder != NULL, FALSE);
300
301 env = gst_amc_jni_get_env ();
302
303 if (!gst_amc_jni_call_boolean_method (env, err, handle->object,
304 media_codecinfo.is_encoder, is_encoder))
305 return FALSE;
306
307 return TRUE;
308 }
309
310 gchar **
gst_amc_codec_info_handle_get_supported_types(GstAmcCodecInfoHandle * handle,gsize * length,GError ** err)311 gst_amc_codec_info_handle_get_supported_types (GstAmcCodecInfoHandle * handle,
312 gsize * length, GError ** err)
313 {
314 JNIEnv *env;
315 jarray array = NULL;
316 jsize len;
317 jsize i;
318 gchar **strv = NULL;
319
320 g_return_val_if_fail (handle != NULL, NULL);
321
322 env = gst_amc_jni_get_env ();
323
324 if (!gst_amc_jni_call_object_method (env, err, handle->object,
325 media_codecinfo.get_supported_types, &array))
326 goto done;
327
328 len = (*env)->GetArrayLength (env, array);
329 if ((*env)->ExceptionCheck (env)) {
330 gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
331 GST_LIBRARY_ERROR_FAILED, "Failed to get array length");
332 goto done;
333 }
334
335 strv = g_new0 (gchar *, len + 1);
336 *length = len;
337
338 for (i = 0; i < len; i++) {
339 jstring string;
340
341 string = (*env)->GetObjectArrayElement (env, array, i);
342 if ((*env)->ExceptionCheck (env)) {
343 gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
344 GST_LIBRARY_ERROR_FAILED, "Failed to get array element");
345 g_strfreev (strv);
346 strv = NULL;
347 goto done;
348 }
349
350 strv[i] = gst_amc_jni_string_to_gchar (env, string, TRUE);
351 if (!strv[i]) {
352 gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
353 GST_LIBRARY_ERROR_FAILED, "Failed create string");
354 g_strfreev (strv);
355 strv = NULL;
356 goto done;
357 }
358 }
359
360 done:
361 if (array)
362 (*env)->DeleteLocalRef (env, array);
363
364 return strv;
365 }
366
367 GstAmcCodecCapabilitiesHandle *
gst_amc_codec_info_handle_get_capabilities_for_type(GstAmcCodecInfoHandle * handle,const gchar * type,GError ** err)368 gst_amc_codec_info_handle_get_capabilities_for_type (GstAmcCodecInfoHandle *
369 handle, const gchar * type, GError ** err)
370 {
371 GstAmcCodecCapabilitiesHandle *ret = NULL;
372 jstring type_str;
373 jobject object;
374 JNIEnv *env;
375
376 env = gst_amc_jni_get_env ();
377
378 type_str = gst_amc_jni_string_from_gchar (env, err, FALSE, type);
379 if (!type_str)
380 goto done;
381
382 if (!gst_amc_jni_call_object_method (env, err, handle->object,
383 media_codecinfo.get_capabilities_for_type, &object, type_str))
384 goto done;
385
386 ret = g_new0 (GstAmcCodecCapabilitiesHandle, 1);
387 ret->object = object;
388
389 done:
390 if (type_str)
391 gst_amc_jni_object_local_unref (env, type_str);
392
393 return ret;
394 }
395
396 void
gst_amc_codec_capabilities_handle_free(GstAmcCodecCapabilitiesHandle * handle)397 gst_amc_codec_capabilities_handle_free (GstAmcCodecCapabilitiesHandle * handle)
398 {
399 JNIEnv *env;
400
401 g_return_if_fail (handle != NULL);
402
403 env = gst_amc_jni_get_env ();
404
405 if (handle->object)
406 gst_amc_jni_object_local_unref (env, handle->object);
407 g_free (handle);
408 }
409
gst_amc_codec_capabilities_handle_get_color_formats(GstAmcCodecCapabilitiesHandle * handle,gsize * length,GError ** err)410 gint *gst_amc_codec_capabilities_handle_get_color_formats
411 (GstAmcCodecCapabilitiesHandle * handle, gsize * length, GError ** err)
412 {
413 JNIEnv *env;
414 jarray array = NULL;
415 jsize len;
416 jint *elems = NULL;
417 gint *ret = NULL;
418
419 g_return_val_if_fail (handle != NULL, NULL);
420
421 env = gst_amc_jni_get_env ();
422
423 if (!gst_amc_jni_get_object_field (env, err, handle->object,
424 media_codeccapabilities.color_formats, &array))
425 goto done;
426
427 len = (*env)->GetArrayLength (env, array);
428 if ((*env)->ExceptionCheck (env)) {
429 gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
430 GST_LIBRARY_ERROR_FAILED, "Failed to get array length");
431 goto done;
432 }
433
434 elems = (*env)->GetIntArrayElements (env, array, NULL);
435 if ((*env)->ExceptionCheck (env)) {
436 gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
437 GST_LIBRARY_ERROR_FAILED, "Failed to get array elements");
438 goto done;
439 }
440
441 ret = g_memdup2 (elems, sizeof (jint) * len);
442 *length = len;
443
444 done:
445 if (elems)
446 (*env)->ReleaseIntArrayElements (env, array, elems, JNI_ABORT);
447 if (array)
448 (*env)->DeleteLocalRef (env, array);
449
450 return ret;
451 }
452
gst_amc_codec_capabilities_handle_get_profile_levels(GstAmcCodecCapabilitiesHandle * handle,gsize * length,GError ** err)453 GstAmcCodecProfileLevel *gst_amc_codec_capabilities_handle_get_profile_levels
454 (GstAmcCodecCapabilitiesHandle * handle, gsize * length, GError ** err)
455 {
456 GstAmcCodecProfileLevel *ret = NULL;
457 JNIEnv *env;
458 jobject array = NULL;
459 jsize len;
460 jsize i;
461
462 env = gst_amc_jni_get_env ();
463
464 if (!gst_amc_jni_get_object_field (env, err, handle->object,
465 media_codeccapabilities.profile_levels, &array))
466 goto done;
467
468 len = (*env)->GetArrayLength (env, array);
469 if ((*env)->ExceptionCheck (env)) {
470 gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
471 GST_LIBRARY_ERROR_FAILED, "Failed to get array length");
472 goto done;
473 }
474
475 ret = g_new0 (GstAmcCodecProfileLevel, len);
476 *length = len;
477
478 for (i = 0; i < len; i++) {
479 jobject object = NULL;
480
481 object = (*env)->GetObjectArrayElement (env, array, i);
482 if ((*env)->ExceptionCheck (env)) {
483 gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
484 GST_LIBRARY_ERROR_FAILED, "Failed to get array element");
485 g_free (ret);
486 ret = NULL;
487 goto done;
488 }
489
490 if (!gst_amc_jni_get_int_field (env, err, object,
491 media_codecprofilelevel.level, &ret[i].level)) {
492 gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
493 GST_LIBRARY_ERROR_FAILED, "Failed to get level");
494 (*env)->DeleteLocalRef (env, object);
495 g_free (ret);
496 ret = NULL;
497 goto done;
498 }
499
500 if (!gst_amc_jni_get_int_field (env, err, object,
501 media_codecprofilelevel.profile, &ret[i].profile)) {
502 gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
503 GST_LIBRARY_ERROR_FAILED, "Failed to get profile");
504 (*env)->DeleteLocalRef (env, object);
505 g_free (ret);
506 ret = NULL;
507 goto done;
508 }
509
510 (*env)->DeleteLocalRef (env, object);
511 }
512
513 done:
514 if (array)
515 (*env)->DeleteLocalRef (env, array);
516
517 return ret;
518 }
519