• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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