--- /dev/null
+/*
+ * Copyright (C) 2012,2018 Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __GST_AMC_CODECLIST_H__
+#define __GST_AMC_CODECLIST_H__
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstAmcCodecInfoHandle GstAmcCodecInfoHandle;
+typedef struct _GstAmcCodecCapabilitiesHandle GstAmcCodecCapabilitiesHandle;
+typedef struct _GstAmcCodecProfileLevel GstAmcCodecProfileLevel;
+
+struct _GstAmcCodecProfileLevel
+{
+ gint profile;
+ gint level;
+};
+
+gboolean gst_amc_codeclist_static_init (void);
+
+gboolean gst_amc_codeclist_get_count (gint * count, GError **err);
+GstAmcCodecInfoHandle * gst_amc_codeclist_get_codec_info_at (gint index,
+ GError **err);
+
+void gst_amc_codec_info_handle_free (GstAmcCodecInfoHandle * handle);
+gchar * gst_amc_codec_info_handle_get_name (GstAmcCodecInfoHandle * handle,
+ GError ** err);
+gboolean gst_amc_codec_info_handle_is_encoder (GstAmcCodecInfoHandle * handle,
+ gboolean * is_encoder, GError ** err);
+gchar ** gst_amc_codec_info_handle_get_supported_types (
+ GstAmcCodecInfoHandle * handle, gsize * length, GError ** err);
+GstAmcCodecCapabilitiesHandle * gst_amc_codec_info_handle_get_capabilities_for_type (
+ GstAmcCodecInfoHandle * handle, const gchar * type, GError ** err);
+
+void gst_amc_codec_capabilities_handle_free (
+ GstAmcCodecCapabilitiesHandle * handle);
+gint * gst_amc_codec_capabilities_handle_get_color_formats (
+ GstAmcCodecCapabilitiesHandle * handle, gsize * length, GError ** err);
+GstAmcCodecProfileLevel * gst_amc_codec_capabilities_handle_get_profile_levels (
+ GstAmcCodecCapabilitiesHandle * handle, gsize * length, GError ** err);
+
+G_END_DECLS
+
+#endif /* __GST_AMC_CODECLIST_H__ */
scan_codecs (GstPlugin * plugin)
{
gboolean ret = TRUE;
- JNIEnv *env;
- jclass codec_list_class = NULL;
- jmethodID get_codec_count_id, get_codec_info_at_id;
- jint codec_count, i;
+ gint codec_count, i;
const GstStructure *cache_data;
+ GError *error = NULL;
GST_DEBUG ("Scanning codecs");
return TRUE;
}
- env = gst_amc_jni_get_env ();
-
- codec_list_class = (*env)->FindClass (env, "android/media/MediaCodecList");
- if (!codec_list_class) {
- ret = FALSE;
- GST_ERROR ("Failed to get codec list class");
- if ((*env)->ExceptionCheck (env)) {
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- }
- goto done;
- }
-
- get_codec_count_id =
- (*env)->GetStaticMethodID (env, codec_list_class, "getCodecCount", "()I");
- get_codec_info_at_id =
- (*env)->GetStaticMethodID (env, codec_list_class, "getCodecInfoAt",
- "(I)Landroid/media/MediaCodecInfo;");
- if (!get_codec_count_id || !get_codec_info_at_id) {
- ret = FALSE;
- GST_ERROR ("Failed to get codec list method IDs");
- if ((*env)->ExceptionCheck (env)) {
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- }
- goto done;
- }
-
- codec_count =
- (*env)->CallStaticIntMethod (env, codec_list_class, get_codec_count_id);
- if ((*env)->ExceptionCheck (env)) {
- ret = FALSE;
+ if (!gst_amc_codeclist_get_count (&codec_count, &error)) {
GST_ERROR ("Failed to get number of available codecs");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
+ ret = FALSE;
goto done;
}
for (i = 0; i < codec_count; i++) {
GstAmcCodecInfo *gst_codec_info;
- jobject codec_info = NULL;
- jclass codec_info_class = NULL;
- jmethodID get_capabilities_for_type_id, get_name_id;
- jmethodID get_supported_types_id, is_encoder_id;
- jobject name = NULL;
- const gchar *name_str = NULL;
- jboolean is_encoder;
- jarray supported_types = NULL;
- jsize n_supported_types;
- jsize j;
+ GstAmcCodecInfoHandle *codec_info = NULL;
+ gchar *name_str = NULL;
+ gboolean is_encoder;
+ gchar **supported_types = NULL;
+ gsize n_supported_types;
+ gsize j;
gboolean valid_codec = TRUE;
gst_codec_info = g_new0 (GstAmcCodecInfo, 1);
- codec_info =
- (*env)->CallStaticObjectMethod (env, codec_list_class,
- get_codec_info_at_id, i);
- if ((*env)->ExceptionCheck (env) || !codec_info) {
+ codec_info = gst_amc_codeclist_get_codec_info_at (i, &error);
+ if (!codec_info) {
GST_ERROR ("Failed to get codec info %d", i);
- if ((*env)->ExceptionCheck (env)) {
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- }
- valid_codec = FALSE;
- goto next_codec;
- }
-
- codec_info_class = (*env)->GetObjectClass (env, codec_info);
- if (!codec_list_class) {
- GST_ERROR ("Failed to get codec info class");
- if ((*env)->ExceptionCheck (env)) {
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- }
valid_codec = FALSE;
goto next_codec;
}
- get_capabilities_for_type_id =
- (*env)->GetMethodID (env, codec_info_class, "getCapabilitiesForType",
- "(Ljava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;");
- get_name_id =
- (*env)->GetMethodID (env, codec_info_class, "getName",
- "()Ljava/lang/String;");
- get_supported_types_id =
- (*env)->GetMethodID (env, codec_info_class, "getSupportedTypes",
- "()[Ljava/lang/String;");
- is_encoder_id =
- (*env)->GetMethodID (env, codec_info_class, "isEncoder", "()Z");
- if (!get_capabilities_for_type_id || !get_name_id
- || !get_supported_types_id || !is_encoder_id) {
- GST_ERROR ("Failed to get codec info method IDs");
- if ((*env)->ExceptionCheck (env)) {
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- }
- valid_codec = FALSE;
- goto next_codec;
- }
-
- name = (*env)->CallObjectMethod (env, codec_info, get_name_id);
- if ((*env)->ExceptionCheck (env)) {
+ name_str = gst_amc_codec_info_handle_get_name (codec_info, &error);
+ if (!name_str) {
GST_ERROR ("Failed to get codec name");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- valid_codec = FALSE;
- goto next_codec;
- }
- name_str = (*env)->GetStringUTFChars (env, name, NULL);
- if ((*env)->ExceptionCheck (env)) {
- GST_ERROR ("Failed to convert codec name to UTF8");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
valid_codec = FALSE;
goto next_codec;
}
}
gst_codec_info->name = g_strdup (name_str);
- is_encoder = (*env)->CallBooleanMethod (env, codec_info, is_encoder_id);
- if ((*env)->ExceptionCheck (env)) {
+ if (!gst_amc_codec_info_handle_is_encoder (codec_info, &is_encoder, &error)) {
GST_ERROR ("Failed to detect if codec is an encoder");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
valid_codec = FALSE;
goto next_codec;
}
gst_codec_info->gl_output_only = FALSE;
supported_types =
- (*env)->CallObjectMethod (env, codec_info, get_supported_types_id);
- if ((*env)->ExceptionCheck (env)) {
+ gst_amc_codec_info_handle_get_supported_types (codec_info,
+ &n_supported_types, &error);
+ if (!supported_types) {
GST_ERROR ("Failed to get supported types");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
valid_codec = FALSE;
goto next_codec;
}
- n_supported_types = (*env)->GetArrayLength (env, supported_types);
- if ((*env)->ExceptionCheck (env)) {
- GST_ERROR ("Failed to get supported types array length");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- valid_codec = FALSE;
- goto next_codec;
- }
-
- GST_INFO ("Codec '%s' has %d supported types", name_str, n_supported_types);
+ GST_INFO ("Codec '%s' has %" G_GSIZE_FORMAT " supported types", name_str,
+ n_supported_types);
gst_codec_info->supported_types =
g_new0 (GstAmcCodecType, n_supported_types);
for (j = 0; j < n_supported_types; j++) {
GstAmcCodecType *gst_codec_type;
- jobject supported_type = NULL;
- const gchar *supported_type_str = NULL;
- jobject capabilities = NULL;
- jclass capabilities_class = NULL;
- jfieldID profile_levels_id, color_formats_id;
- jobject profile_levels = NULL;
- jobject color_formats = NULL;
- jint *color_formats_elems = NULL;
- jsize n_elems, k;
+ const gchar *supported_type_str;
+ GstAmcCodecCapabilitiesHandle *capabilities = NULL;
+ gint k;
gst_codec_type = &gst_codec_info->supported_types[j];
-
- supported_type = (*env)->GetObjectArrayElement (env, supported_types, j);
- if ((*env)->ExceptionCheck (env)) {
- GST_ERROR ("Failed to get %d-th supported type", j);
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- valid_codec = FALSE;
- goto next_supported_type;
- }
-
- supported_type_str =
- (*env)->GetStringUTFChars (env, supported_type, NULL);
- if ((*env)->ExceptionCheck (env) || !supported_type_str) {
- GST_ERROR ("Failed to convert supported type to UTF8");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- valid_codec = FALSE;
- goto next_supported_type;
- }
+ supported_type_str = supported_types[j];
GST_INFO ("Supported type '%s'", supported_type_str);
gst_codec_type->mime = g_strdup (supported_type_str);
capabilities =
- (*env)->CallObjectMethod (env, codec_info,
- get_capabilities_for_type_id, supported_type);
- if ((*env)->ExceptionCheck (env)) {
+ gst_amc_codec_info_handle_get_capabilities_for_type (codec_info,
+ supported_type_str, &error);
+ if (!capabilities) {
GST_ERROR ("Failed to get capabilities for supported type");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- valid_codec = FALSE;
- goto next_supported_type;
- }
-
- capabilities_class = (*env)->GetObjectClass (env, capabilities);
- if (!capabilities_class) {
- GST_ERROR ("Failed to get capabilities class");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- valid_codec = FALSE;
- goto next_supported_type;
- }
-
- color_formats_id =
- (*env)->GetFieldID (env, capabilities_class, "colorFormats", "[I");
- profile_levels_id =
- (*env)->GetFieldID (env, capabilities_class, "profileLevels",
- "[Landroid/media/MediaCodecInfo$CodecProfileLevel;");
- if (!color_formats_id || !profile_levels_id) {
- GST_ERROR ("Failed to get capabilities field IDs");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
valid_codec = FALSE;
goto next_supported_type;
}
if (g_str_has_prefix (gst_codec_type->mime, "video/")) {
- color_formats =
- (*env)->GetObjectField (env, capabilities, color_formats_id);
- if ((*env)->ExceptionCheck (env)) {
- GST_ERROR ("Failed to get color formats");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- valid_codec = FALSE;
- goto next_supported_type;
- }
-
- n_elems = (*env)->GetArrayLength (env, color_formats);
- if ((*env)->ExceptionCheck (env)) {
- GST_ERROR ("Failed to get color formats array length");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- valid_codec = FALSE;
- goto next_supported_type;
- }
- gst_codec_type->n_color_formats = n_elems;
- gst_codec_type->color_formats = g_new0 (gint, n_elems);
- color_formats_elems =
- (*env)->GetIntArrayElements (env, color_formats, NULL);
- if ((*env)->ExceptionCheck (env)) {
+ gst_codec_type->color_formats =
+ gst_amc_codec_capabilities_handle_get_color_formats (capabilities,
+ &gst_codec_type->n_color_formats, &error);
+ if (!gst_codec_type->color_formats) {
GST_ERROR ("Failed to get color format elements");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
valid_codec = FALSE;
goto next_supported_type;
}
- for (k = 0; k < n_elems; k++) {
- GST_INFO ("Color format %d: 0x%x", k, color_formats_elems[k]);
- gst_codec_type->color_formats[k] = color_formats_elems[k];
+ for (k = 0; k < gst_codec_type->n_color_formats; k++) {
+ GST_INFO ("Color format %d: 0x%x", k,
+ gst_codec_type->color_formats[k]);
}
- if (!n_elems) {
+ if (!gst_codec_type->n_color_formats) {
GST_ERROR ("No supported color formats for video codec");
valid_codec = FALSE;
goto next_supported_type;
}
}
- profile_levels =
- (*env)->GetObjectField (env, capabilities, profile_levels_id);
- if ((*env)->ExceptionCheck (env)) {
+ gst_codec_type->profile_levels =
+ gst_amc_codec_capabilities_handle_get_profile_levels (capabilities,
+ &gst_codec_type->n_profile_levels, &error);
+ if (!gst_codec_type->profile_levels) {
GST_ERROR ("Failed to get profile/levels");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
valid_codec = FALSE;
goto next_supported_type;
}
- n_elems = (*env)->GetArrayLength (env, profile_levels);
- if ((*env)->ExceptionCheck (env)) {
- GST_ERROR ("Failed to get profile/levels array length");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- valid_codec = FALSE;
- goto next_supported_type;
- }
- gst_codec_type->n_profile_levels = n_elems;
- gst_codec_type->profile_levels =
- g_malloc0 (sizeof (gst_codec_type->profile_levels[0]) * n_elems);
- for (k = 0; k < n_elems; k++) {
- jobject profile_level = NULL;
- jclass profile_level_class = NULL;
- jfieldID level_id, profile_id;
- jint level, profile;
-
- profile_level = (*env)->GetObjectArrayElement (env, profile_levels, k);
- if ((*env)->ExceptionCheck (env)) {
- GST_ERROR ("Failed to get %d-th profile/level", k);
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- valid_codec = FALSE;
- goto next_profile_level;
- }
-
- profile_level_class = (*env)->GetObjectClass (env, profile_level);
- if (!profile_level_class) {
- GST_ERROR ("Failed to get profile/level class");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- valid_codec = FALSE;
- goto next_profile_level;
- }
-
- level_id = (*env)->GetFieldID (env, profile_level_class, "level", "I");
- profile_id =
- (*env)->GetFieldID (env, profile_level_class, "profile", "I");
- if (!level_id || !profile_id) {
- GST_ERROR ("Failed to get profile/level field IDs");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- valid_codec = FALSE;
- goto next_profile_level;
- }
-
- level = (*env)->GetIntField (env, profile_level, level_id);
- if ((*env)->ExceptionCheck (env)) {
- GST_ERROR ("Failed to get level");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- valid_codec = FALSE;
- goto next_profile_level;
- }
- GST_INFO ("Level %d: 0x%08x", k, level);
- gst_codec_type->profile_levels[k].level = level;
-
- profile = (*env)->GetIntField (env, profile_level, profile_id);
- if ((*env)->ExceptionCheck (env)) {
- GST_ERROR ("Failed to get profile");
- (*env)->ExceptionDescribe (env);
- (*env)->ExceptionClear (env);
- valid_codec = FALSE;
- goto next_profile_level;
- }
- GST_INFO ("Profile %d: 0x%08x", k, profile);
- gst_codec_type->profile_levels[k].profile = profile;
-
- next_profile_level:
- if (profile_level)
- (*env)->DeleteLocalRef (env, profile_level);
- profile_level = NULL;
- if (profile_level_class)
- (*env)->DeleteLocalRef (env, profile_level_class);
- profile_level_class = NULL;
- if (!valid_codec)
- break;
+ for (k = 0; k < gst_codec_type->n_profile_levels; k++) {
+ GST_INFO ("Level %d: 0x%08x", k,
+ gst_codec_type->profile_levels[k].level);
+ GST_INFO ("Profile %d: 0x%08x", k,
+ gst_codec_type->profile_levels[k].profile);
}
next_supported_type:
- if (color_formats_elems)
- (*env)->ReleaseIntArrayElements (env, color_formats,
- color_formats_elems, JNI_ABORT);
- color_formats_elems = NULL;
- if (color_formats)
- (*env)->DeleteLocalRef (env, color_formats);
- color_formats = NULL;
- if (profile_levels)
- (*env)->DeleteLocalRef (env, profile_levels);
- color_formats = NULL;
if (capabilities)
- (*env)->DeleteLocalRef (env, capabilities);
+ gst_amc_codec_capabilities_handle_free (capabilities);
capabilities = NULL;
- if (capabilities_class)
- (*env)->DeleteLocalRef (env, capabilities_class);
- capabilities_class = NULL;
- if (supported_type_str)
- (*env)->ReleaseStringUTFChars (env, supported_type, supported_type_str);
- supported_type_str = NULL;
- if (supported_type)
- (*env)->DeleteLocalRef (env, supported_type);
- supported_type = NULL;
+ g_clear_error (&error);
if (!valid_codec)
break;
}
/* Clean up of all local references we got */
next_codec:
if (name_str)
- (*env)->ReleaseStringUTFChars (env, name, name_str);
+ g_free (name_str);
name_str = NULL;
- if (name)
- (*env)->DeleteLocalRef (env, name);
- name = NULL;
if (supported_types)
- (*env)->DeleteLocalRef (env, supported_types);
+ g_strfreev (supported_types);
supported_types = NULL;
if (codec_info)
- (*env)->DeleteLocalRef (env, codec_info);
+ gst_amc_codec_info_handle_free (codec_info);
codec_info = NULL;
- if (codec_info_class)
- (*env)->DeleteLocalRef (env, codec_info_class);
- codec_info_class = NULL;
if (gst_codec_info) {
gint j;
}
gst_codec_info = NULL;
valid_codec = TRUE;
+ g_clear_error (&error);
}
ret = codec_infos.length != 0;
}
done:
- if (codec_list_class)
- (*env)->DeleteLocalRef (env, codec_list_class);
+ g_clear_error (&error);
return ret;
}
gst_amc_codec_info_quark = g_quark_from_static_string ("gst-amc-codec-info");
+ if (!gst_amc_codeclist_static_init ())
+ return FALSE;
+
if (!gst_amc_codec_static_init ())
return FALSE;
#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/audio/audio.h>
-#include <jni.h>
-
-#include "gstjniutils.h"
#include "gstamc-codec.h"
+#include "gstamc-codeclist.h"
#include "gstamc-format.h"
G_BEGIN_DECLS
gchar *mime;
gint *color_formats;
- gint n_color_formats;
+ gsize n_color_formats;
- struct {
- gint profile;
- gint level;
- } *profile_levels;
- gint n_profile_levels;
+ GstAmcCodecProfileLevel * profile_levels;
+ gsize n_profile_levels;
};
struct _GstAmcCodecInfo {
gint n_supported_types;
};
-
extern GQuark gst_amc_codec_info_quark;
GstVideoFormat gst_amc_color_format_to_video_format (const GstAmcCodecInfo * codec_info, const gchar * mime, gint color_format);
--- /dev/null
+/*
+ * Copyright (C) 2012,2018 Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * Copyright (C) 2015, Sebastian Dröge <sebastian@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "../gstjniutils.h"
+#include "../gstamc-codeclist.h"
+
+struct _GstAmcCodecInfoHandle
+{
+ jobject object;
+};
+
+struct _GstAmcCodecCapabilitiesHandle
+{
+ jobject object;
+};
+
+static struct
+{
+ jclass klass;
+ jmethodID get_codec_count;
+ jmethodID get_codec_info_at;
+} media_codeclist;
+
+static struct
+{
+ jclass klass;
+ jmethodID get_capabilities_for_type;
+ jmethodID get_name;
+ jmethodID get_supported_types;
+ jmethodID is_encoder;
+} media_codecinfo;
+
+static struct
+{
+ jclass klass;
+ jfieldID color_formats;
+ jfieldID profile_levels;
+} media_codeccapabilities;
+
+static struct
+{
+ jclass klass;
+ jfieldID level;
+ jfieldID profile;
+} media_codecprofilelevel;
+
+gboolean
+gst_amc_codeclist_static_init (void)
+{
+ JNIEnv *env;
+ GError *err = NULL;
+
+ env = gst_amc_jni_get_env ();
+
+ media_codeclist.klass =
+ gst_amc_jni_get_class (env, &err, "android/media/MediaCodecList");
+ if (!media_codeclist.klass) {
+ GST_ERROR ("Failed to get android.media.MediaCodecList class: %s",
+ err->message);
+ g_clear_error (&err);
+ return FALSE;
+ }
+
+ media_codeclist.get_codec_count =
+ gst_amc_jni_get_method_id (env, &err, media_codeclist.klass,
+ "getCodecCount", "()I");
+ if (!media_codeclist.get_codec_count) {
+ GST_ERROR ("Failed to get android.media.MediaCodecList getCodecCount(): %s",
+ err->message);
+ g_clear_error (&err);
+ return FALSE;
+ }
+
+ media_codeclist.get_codec_info_at =
+ gst_amc_jni_get_method_id (env, &err, media_codeclist.klass,
+ "getCodecInfoAt", "(I)Landroid/media/MediaCodecInfo;");
+ if (!media_codeclist.get_codec_count) {
+ GST_ERROR
+ ("Failed to get android.media.MediaCodecList getCodecInfoAt(): %s",
+ err->message);
+ g_clear_error (&err);
+ return FALSE;
+ }
+
+ media_codecinfo.klass =
+ gst_amc_jni_get_class (env, &err, "android/media/MediaCodecInfo");
+ if (!media_codecinfo.klass) {
+ GST_ERROR ("Failed to get android.media.MediaCodecInfo class: %s",
+ err->message);
+ g_clear_error (&err);
+ return FALSE;
+ }
+
+ media_codecinfo.get_capabilities_for_type =
+ gst_amc_jni_get_method_id (env, &err, media_codecinfo.klass,
+ "getCapabilitiesForType",
+ "(Ljava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;");
+ if (!media_codecinfo.get_capabilities_for_type) {
+ GST_ERROR
+ ("Failed to get android.media.MediaCodecInfo getCapabilitiesForType(): %s",
+ err->message);
+ g_clear_error (&err);
+ return FALSE;
+ }
+
+ media_codecinfo.get_name =
+ gst_amc_jni_get_method_id (env, &err, media_codecinfo.klass, "getName",
+ "()Ljava/lang/String;");
+ if (!media_codecinfo.get_name) {
+ GST_ERROR ("Failed to get android.media.MediaCodecInfo getName(): %s",
+ err->message);
+ g_clear_error (&err);
+ return FALSE;
+ }
+
+ media_codecinfo.get_supported_types =
+ gst_amc_jni_get_method_id (env, &err, media_codecinfo.klass,
+ "getSupportedTypes", "()[Ljava/lang/String;");
+ if (!media_codecinfo.get_supported_types) {
+ GST_ERROR
+ ("Failed to get android.media.MediaCodecInfo getSupportedTypes(): %s",
+ err->message);
+ g_clear_error (&err);
+ return FALSE;
+ }
+
+ media_codecinfo.is_encoder =
+ gst_amc_jni_get_method_id (env, &err, media_codecinfo.klass, "isEncoder",
+ "()Z");
+ if (!media_codecinfo.is_encoder) {
+ GST_ERROR ("Failed to get android.media.MediaCodecInfo isEncoder(): %s",
+ err->message);
+ g_clear_error (&err);
+ return FALSE;
+ }
+
+ media_codeccapabilities.klass =
+ gst_amc_jni_get_class (env, &err,
+ "android/media/MediaCodecInfo/CodecCapabilities");
+ if (!media_codeccapabilities.klass) {
+ GST_ERROR
+ ("Failed to get android.media.MediaCodecInfo.CodecCapabilities class: %s",
+ err->message);
+ g_clear_error (&err);
+ return FALSE;
+ }
+
+ media_codeccapabilities.color_formats =
+ gst_amc_jni_get_field_id (env, &err, media_codeccapabilities.klass,
+ "colorFormats", "[I");
+ if (!media_codeccapabilities.color_formats) {
+ GST_ERROR
+ ("Failed to get android.media.MediaCodecInfo.CodecCapabilities colorFormats: %s",
+ err->message);
+ g_clear_error (&err);
+ return FALSE;
+ }
+
+ media_codeccapabilities.profile_levels =
+ gst_amc_jni_get_field_id (env, &err, media_codeccapabilities.klass,
+ "profileLevels", "[Landroid/media/MediaCodecInfo$CodecProfileLevel;");
+ if (!media_codeccapabilities.profile_levels) {
+ GST_ERROR
+ ("Failed to get android.media.MediaCodecInfo.CodecCapabilities profileLevels: %s",
+ err->message);
+ g_clear_error (&err);
+ return FALSE;
+ }
+
+ media_codecprofilelevel.klass =
+ gst_amc_jni_get_class (env, &err,
+ "android/media/MediaCodecInfo/CodecProfileLevel");
+ if (!media_codecprofilelevel.klass) {
+ GST_ERROR
+ ("Failed to get android.media.MediaCodecInfo.CodecProfileLevel class: %s",
+ err->message);
+ g_clear_error (&err);
+ return FALSE;
+ }
+
+ media_codecprofilelevel.level =
+ gst_amc_jni_get_field_id (env, &err, media_codecprofilelevel.klass,
+ "level", "I");
+ if (!media_codecprofilelevel.level) {
+ GST_ERROR
+ ("Failed to get android.media.MediaCodecInfo.CodecProfileLevel level: %s",
+ err->message);
+ g_clear_error (&err);
+ return FALSE;
+ }
+
+ media_codecprofilelevel.profile =
+ gst_amc_jni_get_field_id (env, &err, media_codecprofilelevel.klass,
+ "profile", "I");
+ if (!media_codecprofilelevel.profile) {
+ GST_ERROR
+ ("Failed to get android.media.MediaCodecInfo.CodecProfileLevel profile: %s",
+ err->message);
+ g_clear_error (&err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+gst_amc_codeclist_get_count (gint * count, GError ** err)
+{
+ JNIEnv *env;
+
+ env = gst_amc_jni_get_env ();
+
+ if (!gst_amc_jni_call_static_int_method (env, err, media_codeclist.klass,
+ media_codeclist.get_codec_count, count))
+ return FALSE;
+
+ return TRUE;
+}
+
+GstAmcCodecInfoHandle *
+gst_amc_codeclist_get_codec_info_at (gint index, GError ** err)
+{
+ GstAmcCodecInfoHandle *ret;
+ jobject object;
+ JNIEnv *env;
+
+ env = gst_amc_jni_get_env ();
+
+ if (!gst_amc_jni_call_static_object_method (env, err, media_codeclist.klass,
+ media_codeclist.get_codec_info_at, &object, index))
+ return NULL;
+
+ ret = g_new0 (GstAmcCodecInfoHandle, 1);
+ ret->object = object;
+ return ret;
+}
+
+void
+gst_amc_codec_info_handle_free (GstAmcCodecInfoHandle * handle)
+{
+ JNIEnv *env;
+
+ g_return_if_fail (handle != NULL);
+
+ env = gst_amc_jni_get_env ();
+
+ if (handle->object)
+ gst_amc_jni_object_unref (env, handle->object);
+ g_free (handle);
+}
+
+gchar *
+gst_amc_codec_info_handle_get_name (GstAmcCodecInfoHandle * handle,
+ GError ** err)
+{
+ JNIEnv *env;
+ jstring v_str = NULL;
+
+ g_return_val_if_fail (handle != NULL, NULL);
+
+ env = gst_amc_jni_get_env ();
+
+ if (!gst_amc_jni_call_object_method (env, err, handle->object,
+ media_codecinfo.get_name, &v_str))
+ return NULL;
+
+ return gst_amc_jni_string_to_gchar (env, v_str, TRUE);
+}
+
+gboolean
+gst_amc_codec_info_handle_is_encoder (GstAmcCodecInfoHandle * handle,
+ gboolean * is_encoder, GError ** err)
+{
+ JNIEnv *env;
+
+ g_return_val_if_fail (handle != NULL, FALSE);
+ g_return_val_if_fail (is_encoder != NULL, FALSE);
+
+ env = gst_amc_jni_get_env ();
+
+ if (!gst_amc_jni_call_boolean_method (env, err, handle->object,
+ media_codecinfo.is_encoder, is_encoder))
+ return FALSE;
+
+ return TRUE;
+}
+
+gchar **
+gst_amc_codec_info_handle_get_supported_types (GstAmcCodecInfoHandle * handle,
+ gsize * length, GError ** err)
+{
+ JNIEnv *env;
+ jarray array = NULL;
+ jsize len;
+ jsize i;
+ gchar **strv = NULL;
+
+ g_return_val_if_fail (handle != NULL, NULL);
+
+ env = gst_amc_jni_get_env ();
+
+ if (!gst_amc_jni_call_object_method (env, err, handle->object,
+ media_codecinfo.get_name, &array))
+ goto done;
+
+ len = (*env)->GetArrayLength (env, array);
+ if ((*env)->ExceptionCheck (env)) {
+ gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
+ GST_LIBRARY_ERROR_FAILED, "Failed to get array length");
+ goto done;
+ }
+
+ strv = g_new0 (gchar *, len + 1);
+ *length = len;
+
+ for (i = 0; i < len; i++) {
+ jstring string;
+
+ string = (*env)->GetObjectArrayElement (env, array, i);
+ if ((*env)->ExceptionCheck (env)) {
+ gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
+ GST_LIBRARY_ERROR_FAILED, "Failed to get array element");
+ g_strfreev (strv);
+ strv = NULL;
+ goto done;
+ }
+
+ strv[i] = gst_amc_jni_string_to_gchar (env, string, TRUE);
+ if (!strv[i]) {
+ gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
+ GST_LIBRARY_ERROR_FAILED, "Failed create string");
+ g_strfreev (strv);
+ strv = NULL;
+ goto done;
+ }
+ }
+
+done:
+ if (array)
+ (*env)->DeleteLocalRef (env, array);
+
+ return strv;
+}
+
+GstAmcCodecCapabilitiesHandle *
+gst_amc_codec_info_handle_get_capabilities_for_type (GstAmcCodecInfoHandle *
+ handle, const gchar * type, GError ** err)
+{
+ GstAmcCodecCapabilitiesHandle *ret = NULL;
+ jstring type_str;
+ jobject object;
+ JNIEnv *env;
+
+ env = gst_amc_jni_get_env ();
+
+ type_str = gst_amc_jni_string_from_gchar (env, err, FALSE, type);
+ if (!type_str)
+ goto done;
+
+ if (!gst_amc_jni_call_object_method (env, err, handle->object,
+ media_codecinfo.get_capabilities_for_type, &object, type_str))
+ goto done;
+
+ ret = g_new0 (GstAmcCodecCapabilitiesHandle, 1);
+ ret->object = object;
+
+done:
+ if (type_str)
+ gst_amc_jni_object_local_unref (env, type_str);
+
+ return ret;
+}
+
+void
+gst_amc_codec_capabilities_handle_free (GstAmcCodecCapabilitiesHandle * handle)
+{
+ JNIEnv *env;
+
+ g_return_if_fail (handle != NULL);
+
+ env = gst_amc_jni_get_env ();
+
+ if (handle->object)
+ gst_amc_jni_object_unref (env, handle->object);
+ g_free (handle);
+}
+
+gint *gst_amc_codec_capabilities_handle_get_color_formats
+ (GstAmcCodecCapabilitiesHandle * handle, gsize * length, GError ** err)
+{
+ JNIEnv *env;
+ jarray array = NULL;
+ jsize len;
+ jint *elems = NULL;
+ gint *ret = NULL;
+
+ g_return_val_if_fail (handle != NULL, NULL);
+
+ env = gst_amc_jni_get_env ();
+
+ if (!gst_amc_jni_get_object_field (env, err, handle->object,
+ media_codeccapabilities.color_formats, &array))
+ goto done;
+
+ len = (*env)->GetArrayLength (env, array);
+ if ((*env)->ExceptionCheck (env)) {
+ gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
+ GST_LIBRARY_ERROR_FAILED, "Failed to get array length");
+ goto done;
+ }
+
+ elems = (*env)->GetIntArrayElements (env, array, NULL);
+ if ((*env)->ExceptionCheck (env)) {
+ gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
+ GST_LIBRARY_ERROR_FAILED, "Failed to get array elements");
+ goto done;
+ }
+
+ ret = g_memdup (elems, sizeof (jint) * len);
+ *length = len;
+
+done:
+ if (elems)
+ (*env)->ReleaseIntArrayElements (env, array, elems, JNI_ABORT);
+ if (array)
+ (*env)->DeleteLocalRef (env, array);
+
+ return ret;
+}
+
+GstAmcCodecProfileLevel *gst_amc_codec_capabilities_handle_get_profile_levels
+ (GstAmcCodecCapabilitiesHandle * handle, gsize * length, GError ** err)
+{
+ GstAmcCodecProfileLevel *ret = NULL;
+ JNIEnv *env;
+ jobject array = NULL;
+ jsize len;
+ jsize i;
+
+ env = gst_amc_jni_get_env ();
+
+ if (!gst_amc_jni_get_object_field (env, err, handle->object,
+ media_codeccapabilities.profile_levels, &array))
+ goto done;
+
+ len = (*env)->GetArrayLength (env, array);
+ if ((*env)->ExceptionCheck (env)) {
+ gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
+ GST_LIBRARY_ERROR_FAILED, "Failed to get array length");
+ goto done;
+ }
+
+ ret = g_new0 (GstAmcCodecProfileLevel, len);
+ *length = len;
+
+ for (i = 0; i < len; i++) {
+ jobject object = NULL;
+
+ object = (*env)->GetObjectArrayElement (env, array, i);
+ if ((*env)->ExceptionCheck (env)) {
+ gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
+ GST_LIBRARY_ERROR_FAILED, "Failed to get array element");
+ g_free (ret);
+ ret = NULL;
+ goto done;
+ }
+
+ if (!gst_amc_jni_get_int_field (env, err, object,
+ media_codecprofilelevel.level, &ret[i].level)) {
+ gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
+ GST_LIBRARY_ERROR_FAILED, "Failed to get level");
+ (*env)->DeleteLocalRef (env, object);
+ g_free (ret);
+ ret = NULL;
+ goto done;
+ }
+
+ if (!gst_amc_jni_get_int_field (env, err, object,
+ media_codecprofilelevel.profile, &ret[i].profile)) {
+ gst_amc_jni_set_error (env, err, GST_LIBRARY_ERROR,
+ GST_LIBRARY_ERROR_FAILED, "Failed to get profile");
+ (*env)->DeleteLocalRef (env, object);
+ g_free (ret);
+ ret = NULL;
+ goto done;
+ }
+
+ (*env)->DeleteLocalRef (env, object);
+ }
+
+done:
+ if (array)
+ (*env)->DeleteLocalRef (env, array);
+
+ return ret;
+}
'gst-android-hardware-sensor.c',
'gstjniutils.c',
'jni/gstamc-codec-jni.c',
+ 'jni/gstamc-codeclist-jni.c',
'jni/gstamc-format-jni.c',
]