Merge branch 'androidmedia-caps' into 'main'

androidmedia: Read video codec details from VideoCapabilities

Closes #3387

See merge request gstreamer/gstreamer!6796
This commit is contained in:
Jochen Henneberg 2024-05-03 21:34:53 +00:00
commit 4b3b7ef21b
5 changed files with 418 additions and 49 deletions

View file

@ -29,12 +29,22 @@ typedef struct _GstAmcCodecInfoHandle GstAmcCodecInfoHandle;
typedef struct _GstAmcCodecCapabilitiesHandle GstAmcCodecCapabilitiesHandle;
typedef struct _GstAmcCodecProfileLevel GstAmcCodecProfileLevel;
typedef struct _GstAmcVideoCapabilitiesHandle GstAmcVideoCapabilitiesHandle;
struct _GstAmcCodecProfileLevel
{
gint profile;
gint level;
};
typedef struct _GstAmcValueRange GstAmcValueRange;
struct _GstAmcValueRange
{
gint lower;
gint upper;
};
gboolean gst_amc_codeclist_get_count (gint * count, GError **err);
GstAmcCodecInfoHandle * gst_amc_codeclist_get_codec_info_at (gint index,
GError **err);
@ -56,6 +66,16 @@ gint * gst_amc_codec_capabilities_handle_get_color_formats (
GstAmcCodecProfileLevel * gst_amc_codec_capabilities_handle_get_profile_levels (
GstAmcCodecCapabilitiesHandle * handle, gsize * length, GError ** err);
GstAmcVideoCapabilitiesHandle * gst_amc_capabilities_get_video_capabilities (GstAmcCodecCapabilitiesHandle * handle,
GError **err);
void gst_amc_capabilities_video_capabilities_handle_free (GstAmcVideoCapabilitiesHandle * handle);
GstAmcValueRange gst_amc_video_capabilities_get_widths (
GstAmcVideoCapabilitiesHandle * handle, GError ** err);
GstAmcValueRange gst_amc_video_capabilities_get_heights (
GstAmcVideoCapabilitiesHandle * handle, GError ** err);
GstAmcValueRange gst_amc_video_capabilities_get_framerates (
GstAmcVideoCapabilitiesHandle * handle, GError ** err);
G_END_DECLS
#endif /* __GST_AMC_CODECLIST_H__ */

View file

@ -93,6 +93,7 @@ enum
COLOR_Format18BitBGR666 = 41,
COLOR_Format24BitARGB6666 = 42,
COLOR_Format24BitABGR6666 = 43,
COLOR_FormatYUVP010 = 54,
COLOR_FormatAndroidOpaque = 0x7F000789,
COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100,
COLOR_INTEL_FormatYUV420PackedSemiPlanar = 0x7fa00e00,

View file

@ -50,6 +50,9 @@
GST_DEBUG_CATEGORY (gst_amc_debug);
#define GST_CAT_DEFAULT gst_amc_debug
/* Should be advanced whenever the codec cache structure changes */
#define GST_AMC_CODEC_CACHE_VERSION 1
GQuark gst_amc_codec_info_quark = 0;
static GQueue codec_infos = G_QUEUE_INIT;
@ -68,12 +71,17 @@ scan_codecs (GstPlugin * plugin)
gboolean ret = TRUE;
gint codec_count, i;
const GstStructure *cache_data;
const GValue *arr = NULL;
GError *error = NULL;
GST_DEBUG ("Scanning codecs");
if ((cache_data = gst_plugin_get_cache_data (plugin))) {
const GValue *arr = gst_structure_get_value (cache_data, "codecs");
cache_data = gst_plugin_get_cache_data (plugin);
if (cache_data)
arr = gst_structure_get_value (cache_data,
"codecs-" G_STRINGIFY (GST_AMC_CODEC_CACHE_VERSION));
if (arr) {
guint i, n;
GST_DEBUG ("Getting codecs from cache");
@ -108,6 +116,7 @@ scan_codecs (GstPlugin * plugin)
const GValue *plarr;
guint k, n3;
GstAmcCodecType *gst_codec_type = &gst_codec_info->supported_types[j];
const GValue *range, *frac;
mime = gst_structure_get_string (sts, "mime");
gst_codec_type->mime = g_strdup (mime);
@ -141,6 +150,24 @@ scan_codecs (GstPlugin * plugin)
gst_codec_type->profile_levels[k].profile = g_value_get_int (p);
gst_codec_type->profile_levels[k].level = g_value_get_int (l);
}
if (g_str_has_prefix (mime, "video/")) {
range = gst_structure_get_value (sts, "width");
gst_codec_type->width.lower = gst_value_get_int_range_min (range);
gst_codec_type->width.upper = gst_value_get_int_range_max (range);
range = gst_structure_get_value (sts, "height");
gst_codec_type->height.lower = gst_value_get_int_range_min (range);
gst_codec_type->height.upper = gst_value_get_int_range_max (range);
range = gst_structure_get_value (sts, "framerate");
frac = gst_value_get_fraction_range_min (range);
gst_codec_type->framerate.lower =
gst_value_get_fraction_numerator (frac);
frac = gst_value_get_fraction_range_max (range);
gst_codec_type->framerate.upper =
gst_value_get_fraction_numerator (frac);
}
}
g_queue_push_tail (&codec_infos, gst_codec_info);
@ -283,6 +310,21 @@ scan_codecs (GstPlugin * plugin)
}
if (g_str_has_prefix (gst_codec_type->mime, "video/")) {
GstAmcVideoCapabilitiesHandle *vid_caps = NULL;
/* These function are safe to be called even if the API level
does not give us the MediaCodecInfo.VideoCapabilities. In
that case we will get the default values. */
vid_caps =
gst_amc_capabilities_get_video_capabilities (capabilities, &error);
gst_codec_type->width =
gst_amc_video_capabilities_get_widths (vid_caps, &error);
gst_codec_type->height =
gst_amc_video_capabilities_get_heights (vid_caps, &error);
gst_codec_type->framerate =
gst_amc_video_capabilities_get_framerates (vid_caps, &error);
gst_amc_capabilities_video_capabilities_handle_free (vid_caps);
gst_codec_type->color_formats =
gst_amc_codec_capabilities_handle_get_color_formats (capabilities,
&gst_codec_type->n_color_formats, &error);
@ -474,6 +516,37 @@ scan_codecs (GstPlugin * plugin)
}
gst_structure_set_value (sts, "profile-levels", &tmparr);
if (g_str_has_prefix (gst_codec_type->mime, "video/")) {
GValue tmprange = { 0, };
GValue tmpfracl = { 0, };
GValue tmpfracu = { 0, };
g_value_init (&tmprange, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&tmprange,
gst_codec_type->width.lower, gst_codec_type->width.upper);
gst_structure_set_value (sts, "width", &tmprange);
g_value_unset (&tmprange);
g_value_init (&tmprange, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&tmprange,
gst_codec_type->height.lower, gst_codec_type->height.upper);
gst_structure_set_value (sts, "height", &tmprange);
g_value_unset (&tmprange);
g_value_init (&tmprange, GST_TYPE_FRACTION_RANGE);
g_value_init (&tmpfracl, GST_TYPE_FRACTION);
g_value_init (&tmpfracu, GST_TYPE_FRACTION);
gst_value_set_fraction (&tmpfracl, gst_codec_type->framerate.lower,
1);
gst_value_set_fraction (&tmpfracu, gst_codec_type->framerate.upper,
1);
gst_value_set_fraction_range (&tmprange, &tmpfracl, &tmpfracu);
gst_structure_set_value (sts, "framerate", &tmprange);
g_value_unset (&tmprange);
g_value_unset (&tmpfracl);
g_value_unset (&tmpfracu);
}
g_value_init (&stv, GST_TYPE_STRUCTURE);
gst_value_set_structure (&stv, sts);
gst_value_array_append_value (&starr, &stv);
@ -491,7 +564,8 @@ scan_codecs (GstPlugin * plugin)
gst_structure_free (cs);
}
gst_structure_set_value (new_cache_data, "codecs", &arr);
gst_structure_set_value (new_cache_data,
"codecs-" G_STRINGIFY (GST_AMC_CODEC_CACHE_VERSION), &arr);
g_value_unset (&arr);
gst_plugin_set_cache_data (plugin, new_cache_data);
@ -523,7 +597,8 @@ static const struct
COLOR_QCOM_FormatYVU420SemiPlanar32mMultiView, GST_VIDEO_FORMAT_NV12}, {
COLOR_OMX_SEC_FormatNV12Tiled, GST_VIDEO_FORMAT_NV12}, {
COLOR_FormatYCbYCr, GST_VIDEO_FORMAT_YUY2}, {
COLOR_FormatYV12, GST_VIDEO_FORMAT_YV12}
COLOR_FormatYV12, GST_VIDEO_FORMAT_YV12}, {
COLOR_FormatYUVP010, GST_VIDEO_FORMAT_P010_10LE}
};
static gboolean
@ -2088,9 +2163,10 @@ gst_amc_codec_info_to_caps (const GstAmcCodecInfo * codec_info,
tmp = gst_structure_new ("video/x-raw",
"format", G_TYPE_STRING, gst_video_format_to_string (format),
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
"width", GST_TYPE_INT_RANGE, type->width.lower, type->width.upper,
"height", GST_TYPE_INT_RANGE, type->height.lower,
type->height.upper, "framerate", GST_TYPE_FRACTION_RANGE,
type->framerate.lower, 1, type->framerate.upper, 1, NULL);
raw_ret = gst_caps_merge_structure (raw_ret, tmp);
}
@ -2102,13 +2178,12 @@ gst_amc_codec_info_to_caps (const GstAmcCodecInfo * codec_info,
gboolean have_profile_level = FALSE;
tmp = gst_structure_new ("video/mpeg",
"width", GST_TYPE_INT_RANGE, 16, 4096,
"height", GST_TYPE_INT_RANGE, 16, 4096,
"framerate", GST_TYPE_FRACTION_RANGE,
0, 1, G_MAXINT, 1,
"mpegversion", G_TYPE_INT, 4,
"systemstream", G_TYPE_BOOLEAN, FALSE,
"parsed", G_TYPE_BOOLEAN, TRUE, NULL);
"width", GST_TYPE_INT_RANGE, type->width.lower, type->width.upper,
"height", GST_TYPE_INT_RANGE, type->height.lower,
type->height.upper, "framerate", GST_TYPE_FRACTION_RANGE,
type->framerate.lower, 1, type->framerate.upper, 1, "mpegversion",
G_TYPE_INT, 4, "systemstream", G_TYPE_BOOLEAN, FALSE, "parsed",
G_TYPE_BOOLEAN, TRUE, NULL);
if (type->n_profile_levels) {
for (j = type->n_profile_levels - 1; j >= 0; j--) {
@ -2177,12 +2252,11 @@ gst_amc_codec_info_to_caps (const GstAmcCodecInfo * codec_info,
gboolean have_profile_level = FALSE;
tmp = gst_structure_new ("video/x-h263",
"width", GST_TYPE_INT_RANGE, 16, 4096,
"height", GST_TYPE_INT_RANGE, 16, 4096,
"framerate", GST_TYPE_FRACTION_RANGE,
0, 1, G_MAXINT, 1,
"parsed", G_TYPE_BOOLEAN, TRUE,
"variant", G_TYPE_STRING, "itu", NULL);
"width", GST_TYPE_INT_RANGE, type->width.lower, type->width.upper,
"height", GST_TYPE_INT_RANGE, type->height.lower,
type->height.upper, "framerate", GST_TYPE_FRACTION_RANGE,
type->framerate.lower, 1, type->framerate.upper, 1, "parsed",
G_TYPE_BOOLEAN, TRUE, "variant", G_TYPE_STRING, "itu", NULL);
if (type->n_profile_levels) {
for (j = type->n_profile_levels - 1; j >= 0; j--) {
@ -2241,13 +2315,12 @@ gst_amc_codec_info_to_caps (const GstAmcCodecInfo * codec_info,
gboolean have_profile_level = FALSE;
tmp = gst_structure_new ("video/x-h264",
"width", GST_TYPE_INT_RANGE, 16, 4096,
"height", GST_TYPE_INT_RANGE, 16, 4096,
"framerate", GST_TYPE_FRACTION_RANGE,
0, 1, G_MAXINT, 1,
"parsed", G_TYPE_BOOLEAN, TRUE,
"stream-format", G_TYPE_STRING, "byte-stream",
"alignment", G_TYPE_STRING, "au", NULL);
"width", GST_TYPE_INT_RANGE, type->width.lower, type->width.upper,
"height", GST_TYPE_INT_RANGE, type->height.lower,
type->height.upper, "framerate", GST_TYPE_FRACTION_RANGE,
type->framerate.lower, 1, type->framerate.upper, 1, "parsed",
G_TYPE_BOOLEAN, TRUE, "stream-format", G_TYPE_STRING,
"byte-stream", "alignment", G_TYPE_STRING, "au", NULL);
if (type->n_profile_levels) {
for (j = type->n_profile_levels - 1; j >= 0; j--) {
@ -2317,13 +2390,12 @@ gst_amc_codec_info_to_caps (const GstAmcCodecInfo * codec_info,
gboolean have_profile_level = FALSE;
tmp = gst_structure_new ("video/x-h265",
"width", GST_TYPE_INT_RANGE, 16, 4096,
"height", GST_TYPE_INT_RANGE, 16, 4096,
"framerate", GST_TYPE_FRACTION_RANGE,
0, 1, G_MAXINT, 1,
"parsed", G_TYPE_BOOLEAN, TRUE,
"stream-format", G_TYPE_STRING, "byte-stream",
"alignment", G_TYPE_STRING, "au", NULL);
"width", GST_TYPE_INT_RANGE, type->width.lower, type->width.upper,
"height", GST_TYPE_INT_RANGE, type->height.lower,
type->height.upper, "framerate", GST_TYPE_FRACTION_RANGE,
type->framerate.lower, 1, type->framerate.upper, 1, "parsed",
G_TYPE_BOOLEAN, TRUE, "stream-format", G_TYPE_STRING,
"byte-stream", "alignment", G_TYPE_STRING, "au", NULL);
if (type->n_profile_levels) {
for (j = type->n_profile_levels - 1; j >= 0; j--) {
@ -2382,35 +2454,37 @@ gst_amc_codec_info_to_caps (const GstAmcCodecInfo * codec_info,
}
} else if (strcmp (type->mime, "video/x-vnd.on2.vp8") == 0) {
tmp = gst_structure_new ("video/x-vp8",
"width", GST_TYPE_INT_RANGE, 16, 4096,
"height", GST_TYPE_INT_RANGE, 16, 4096,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
"width", GST_TYPE_INT_RANGE, type->width.lower, type->width.upper,
"height", GST_TYPE_INT_RANGE, type->height.lower,
type->height.upper, "framerate", GST_TYPE_FRACTION_RANGE,
type->framerate.lower, 1, type->framerate.upper, 1, NULL);
encoded_ret = gst_caps_merge_structure (encoded_ret, tmp);
} else if (strcmp (type->mime, "video/x-vnd.on2.vp9") == 0) {
tmp = gst_structure_new ("video/x-vp9",
"width", GST_TYPE_INT_RANGE, 16, 4096,
"height", GST_TYPE_INT_RANGE, 16, 4096,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
"width", GST_TYPE_INT_RANGE, type->width.lower, type->width.upper,
"height", GST_TYPE_INT_RANGE, type->height.lower,
type->height.upper, "framerate", GST_TYPE_FRACTION_RANGE,
type->framerate.lower, 1, type->framerate.upper, 1, NULL);
encoded_ret = gst_caps_merge_structure (encoded_ret, tmp);
} else if (strcmp (type->mime, "video/av01") == 0) {
tmp = gst_structure_new ("video/x-av1",
"stream-format", G_TYPE_STRING, "obu-stream",
"alignment", G_TYPE_STRING, "tu",
"width", GST_TYPE_INT_RANGE, 16, 4096,
"height", GST_TYPE_INT_RANGE, 16, 4096,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
"width", GST_TYPE_INT_RANGE, type->width.lower, type->width.upper,
"height", GST_TYPE_INT_RANGE, type->height.lower,
type->height.upper, "framerate", GST_TYPE_FRACTION_RANGE,
type->framerate.lower, 1, type->framerate.upper, 1, NULL);
encoded_ret = gst_caps_merge_structure (encoded_ret, tmp);
} else if (strcmp (type->mime, "video/mpeg2") == 0) {
tmp = gst_structure_new ("video/mpeg",
"width", GST_TYPE_INT_RANGE, 16, 4096,
"height", GST_TYPE_INT_RANGE, 16, 4096,
"framerate", GST_TYPE_FRACTION_RANGE,
0, 1, G_MAXINT, 1,
"mpegversion", GST_TYPE_INT_RANGE, 1, 2,
"systemstream", G_TYPE_BOOLEAN, FALSE,
"width", GST_TYPE_INT_RANGE, type->width.lower, type->width.upper,
"height", GST_TYPE_INT_RANGE, type->height.lower,
type->height.upper, "framerate", GST_TYPE_FRACTION_RANGE,
type->framerate.lower, 1, type->framerate.upper, 1, "mpegversion",
GST_TYPE_INT_RANGE, 1, 2, "systemstream", G_TYPE_BOOLEAN, FALSE,
"parsed", G_TYPE_BOOLEAN, TRUE, NULL);
encoded_ret = gst_caps_merge_structure (encoded_ret, tmp);

View file

@ -41,6 +41,11 @@ struct _GstAmcCodecType {
GstAmcCodecProfileLevel * profile_levels;
gsize n_profile_levels;
/* video codecs only */
GstAmcValueRange width;
GstAmcValueRange height;
GstAmcValueRange framerate;
};
struct _GstAmcCodecInfo {

View file

@ -38,6 +38,11 @@ struct _GstAmcCodecCapabilitiesHandle
jobject object;
};
struct _GstAmcVideoCapabilitiesHandle
{
jobject object;
};
static struct
{
jclass klass;
@ -57,6 +62,7 @@ static struct
static struct
{
jclass klass;
jmethodID get_video_capabilities;
jfieldID color_formats;
jfieldID profile_levels;
} media_codeccapabilities;
@ -68,11 +74,100 @@ static struct
jfieldID profile;
} media_codecprofilelevel;
static struct
{
jclass klass;
jmethodID get_supported_heights;
jmethodID get_supported_widths;
jmethodID get_supported_framerates;
} media_videocapabilities;
static struct
{
jclass klass;
jmethodID get_lower;
jmethodID get_upper;
} util_range;
static struct
{
jclass klass;
jmethodID int_value;
} lang_integer;
static gboolean
gst_amc_codeclist_jni_static_init_21 (void)
{
JNIEnv *env;
GError *err = NULL;
env = gst_amc_jni_get_env ();
media_codeccapabilities.get_video_capabilities =
gst_amc_jni_get_method_id (env, &err, media_codeccapabilities.klass,
"getVideoCapabilities",
"()Landroid/media/MediaCodecInfo$VideoCapabilities;");
if (!media_codeccapabilities.get_video_capabilities) {
GST_ERROR
("Failed to get android.media.MediaCodecInfo getVideoCapabilities(): %s",
err->message);
g_clear_error (&err);
return FALSE;
}
media_videocapabilities.klass =
gst_amc_jni_get_class (env, &err,
"android/media/MediaCodecInfo$VideoCapabilities");
if (!media_videocapabilities.klass) {
GST_ERROR
("Failed to get android.media.MediaCodecInfo.VideoCapabilities class: %s",
err->message);
g_clear_error (&err);
return FALSE;
}
media_videocapabilities.get_supported_widths =
gst_amc_jni_get_method_id (env, &err, media_videocapabilities.klass,
"getSupportedWidths", "()Landroid/util/Range;");
if (!media_videocapabilities.get_supported_widths) {
GST_ERROR
("Failed to get android.media.MediaCodecInfo.VideoCapabilities getSupportedWidths(): %s",
err->message);
g_clear_error (&err);
return FALSE;
}
media_videocapabilities.get_supported_heights =
gst_amc_jni_get_method_id (env, &err, media_videocapabilities.klass,
"getSupportedHeights", "()Landroid/util/Range;");
if (!media_videocapabilities.get_supported_heights) {
GST_ERROR
("Failed to get android.media.MediaCodecInfo.VideoCapabilities getSupportedHeights(): %s",
err->message);
g_clear_error (&err);
return FALSE;
}
media_videocapabilities.get_supported_framerates =
gst_amc_jni_get_method_id (env, &err, media_videocapabilities.klass,
"getSupportedFrameRates", "()Landroid/util/Range;");
if (!media_videocapabilities.get_supported_framerates) {
GST_ERROR
("Failed to get android.media.MediaCodecInfo.VideoCapabilities getSupportedFrameRates(): %s",
err->message);
g_clear_error (&err);
return FALSE;
}
return TRUE;
}
gboolean
gst_amc_codeclist_jni_static_init (void)
{
JNIEnv *env;
GError *err = NULL;
gboolean api_level_gt_21 = android_get_device_api_level () > 21;
env = gst_amc_jni_get_env ();
@ -224,6 +319,50 @@ gst_amc_codeclist_jni_static_init (void)
return FALSE;
}
util_range.klass = gst_amc_jni_get_class (env, &err, "android/util/Range");
if (!util_range.klass) {
GST_ERROR ("Failed to get android.util.Range class: %s", err->message);
g_clear_error (&err);
return FALSE;
}
util_range.get_lower =
gst_amc_jni_get_method_id (env, &err, util_range.klass, "getLower",
"()Ljava/lang/Comparable;");
if (!util_range.get_lower) {
GST_ERROR ("Failed to get android.util.Range getLower(): %s", err->message);
g_clear_error (&err);
return FALSE;
}
util_range.get_upper =
gst_amc_jni_get_method_id (env, &err, util_range.klass, "getUpper",
"()Ljava/lang/Comparable;");
if (!util_range.get_upper) {
GST_ERROR ("Failed to get android.util.Range getUpper(): %s", err->message);
g_clear_error (&err);
return FALSE;
}
lang_integer.klass = gst_amc_jni_get_class (env, &err, "java/lang/Integer");
if (!lang_integer.klass) {
GST_ERROR ("Failed to get java.lang.Integer class: %s", err->message);
g_clear_error (&err);
return FALSE;
}
lang_integer.int_value =
gst_amc_jni_get_method_id (env, &err, lang_integer.klass, "intValue",
"()I");
if (!lang_integer.int_value) {
GST_ERROR ("Failed to get java.lang.Integer intValue(): %s", err->message);
g_clear_error (&err);
return FALSE;
}
if (api_level_gt_21)
return gst_amc_codeclist_jni_static_init_21 ();
return TRUE;
}
@ -518,3 +657,133 @@ done:
return ret;
}
GstAmcVideoCapabilitiesHandle *
gst_amc_capabilities_get_video_capabilities (GstAmcCodecCapabilitiesHandle *
handle, GError ** err)
{
GstAmcVideoCapabilitiesHandle *ret = NULL;
jobject object;
JNIEnv *env;
env = gst_amc_jni_get_env ();
if (!gst_amc_jni_call_object_method (env, err, handle->object,
media_codeccapabilities.get_video_capabilities, &object))
goto done;
ret = g_new0 (GstAmcVideoCapabilitiesHandle, 1);
ret->object = object;
done:
return ret;
}
void gst_amc_capabilities_video_capabilities_handle_free
(GstAmcVideoCapabilitiesHandle * handle)
{
JNIEnv *env;
if (!handle)
return;
env = gst_amc_jni_get_env ();
if (handle->object)
gst_amc_jni_object_local_unref (env, handle->object);
g_free (handle);
}
static void
gst_amc_from_range (jobject range, GstAmcValueRange * res, GError ** err)
{
jobject lower, upper;
JNIEnv *env;
gint lower_int, upper_int;
env = gst_amc_jni_get_env ();
if (!gst_amc_jni_call_object_method (env, err, range,
util_range.get_lower, &lower))
return;
if (!gst_amc_jni_call_object_method (env, err, range,
util_range.get_upper, &upper))
return;
if (!gst_amc_jni_call_int_method (env, err, lower,
lang_integer.int_value, &lower_int))
return;
if (!gst_amc_jni_call_int_method (env, err, upper,
lang_integer.int_value, &upper_int))
return;
if (lower_int != upper_int) {
res->lower = MAX (res->lower, lower_int);
res->upper = MIN (res->upper, upper_int);
}
}
GstAmcValueRange
gst_amc_video_capabilities_get_widths (GstAmcVideoCapabilitiesHandle * handle,
GError ** err)
{
GstAmcValueRange ret = { 16, 4096 };
jobject range;
JNIEnv *env;
if (!handle)
goto out;
env = gst_amc_jni_get_env ();
if (gst_amc_jni_call_object_method (env, err, handle->object,
media_videocapabilities.get_supported_widths, &range))
gst_amc_from_range (range, &ret, err);
out:
return ret;
}
GstAmcValueRange
gst_amc_video_capabilities_get_heights (GstAmcVideoCapabilitiesHandle * handle,
GError ** err)
{
GstAmcValueRange ret = { 16, 4096 };
jobject range;
JNIEnv *env;
if (!handle)
goto out;
env = gst_amc_jni_get_env ();
if (gst_amc_jni_call_object_method (env, err, handle->object,
media_videocapabilities.get_supported_heights, &range))
gst_amc_from_range (range, &ret, err);
out:
return ret;
}
GstAmcValueRange
gst_amc_video_capabilities_get_framerates (GstAmcVideoCapabilitiesHandle *
handle, GError ** err)
{
GstAmcValueRange ret = { 0, G_MAXINT };
jobject range;
JNIEnv *env;
if (!handle)
goto out;
env = gst_amc_jni_get_env ();
if (gst_amc_jni_call_object_method (env, err, handle->object,
media_videocapabilities.get_supported_framerates, &range))
gst_amc_from_range (range, &ret, err);
out:
return ret;
}