[vlc-devel] [PATCH 2/2] mediacodec: check if the codec can handle the H264 profile of the input format

Felix Abecassis felix.abecassis at gmail.com
Tue Feb 11 13:31:12 CET 2014


The level is ignored for now since some encoders are not computing the
level and instead set it to the maximum possible value.
---
 modules/codec/omxil/android_mediacodec.c | 47 ++++++++++++++++++++++++--------
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/modules/codec/omxil/android_mediacodec.c b/modules/codec/omxil/android_mediacodec.c
index bf53e76..9150acc 100644
--- a/modules/codec/omxil/android_mediacodec.c
+++ b/modules/codec/omxil/android_mediacodec.c
@@ -57,7 +57,8 @@ struct decoder_sys_t
     jclass media_codec_list_class, media_codec_class, media_format_class;
     jclass buffer_info_class, byte_buffer_class;
     jmethodID tostring;
-    jmethodID get_codec_count, get_codec_info_at, is_encoder;
+    jmethodID get_codec_count, get_codec_info_at, is_encoder, get_capabilities_for_type;
+    jfieldID profile_levels_field, profile_field, level_field;
     jmethodID get_supported_types, get_name;
     jmethodID create_by_codec_name, configure, start, stop, flush, release;
     jmethodID get_output_format, get_input_buffers, get_output_buffers;
@@ -127,6 +128,11 @@ static const struct member members[] = {
     { "isEncoder", "()Z", "android/media/MediaCodecInfo", OFF(is_encoder), METHOD },
     { "getSupportedTypes", "()[Ljava/lang/String;", "android/media/MediaCodecInfo", OFF(get_supported_types), METHOD },
     { "getName", "()Ljava/lang/String;", "android/media/MediaCodecInfo", OFF(get_name), METHOD },
+    { "getCapabilitiesForType", "(Ljava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;", "android/media/MediaCodecInfo", OFF(get_capabilities_for_type), METHOD },
+
+    { "profileLevels", "[Landroid/media/MediaCodecInfo$CodecProfileLevel;", "android/media/MediaCodecInfo$CodecCapabilities", OFF(profile_levels_field), FIELD },
+    { "profile", "I", "android.media.MediaCodecInfo$CodecProfileLevel", OFF(profile_field), FIELD },
+    { "level", "I", "android.media.MediaCodecInfo$CodecProfileLevel", OFF(level_field), FIELD },
 
     { "createByCodecName", "(Ljava/lang/String;)Landroid/media/MediaCodec;", "android/media/MediaCodec", OFF(create_by_codec_name), STATIC_METHOD },
     { "configure", "(Landroid/media/MediaFormat;Landroid/view/Surface;Landroid/media/MediaCrypto;I)V", "android/media/MediaCodec", OFF(configure), METHOD },
@@ -224,14 +230,9 @@ static int OpenDecoder(vlc_object_t *p_this)
         return VLC_EGENERIC;
     }
 
-    if (p_dec->fmt_in.i_codec == VLC_CODEC_H264) {
-        size_t i_profile = 0xFFFF;
-        h264_get_profile_level(&p_dec->fmt_in, &i_profile, NULL, NULL);
-        if (i_profile >= 110) {
-            msg_Err(p_dec, "H.264 profile is too high or unknown. Disabling Hardware Acceleration.");
-            return VLC_EGENERIC;
-        }
-    }
+    size_t fmt_profile = 0;
+    if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
+        h264_get_profile_level(&p_dec->fmt_in, &fmt_profile, NULL, NULL);
 
     /* Allocate the memory needed to store the decoder's structure */
     if ((p_dec->p_sys = p_sys = calloc(1, sizeof(*p_sys))) == NULL)
@@ -303,13 +304,37 @@ static int OpenDecoder(vlc_object_t *p_this)
             (*env)->DeleteLocalRef(env, info);
             continue;
         }
+
+	jobject codec_capabilities = (*env)->CallObjectMethod(env, info, p_sys->get_capabilities_for_type,
+							      (*env)->NewStringUTF(env, mime));
+	jobject profile_levels = (*env)->GetObjectField(env, codec_capabilities, p_sys->profile_levels_field);
+	int profile_levels_len = (*env)->GetArrayLength(env, profile_levels);
+
         jobject types = (*env)->CallObjectMethod(env, info, p_sys->get_supported_types);
         int num_types = (*env)->GetArrayLength(env, types);
         bool found = false;
         for (int j = 0; j < num_types && !found; j++) {
             jobject type = (*env)->GetObjectArrayElement(env, types, j);
-            if (!jstrcmp(env, type, mime))
-                found = true;
+            if (!jstrcmp(env, type, mime)) {
+                /* The mime type is matching for this component. We
+                   now check if the capabilities of the codec is
+                   matching the video format. */
+                if (p_dec->fmt_in.i_codec == VLC_CODEC_H264 && fmt_profile) {
+                    for (int i = 0; i < profile_levels_len && !found; ++i) {
+                        jobject profile_level = (*env)->GetObjectArrayElement(env, profile_levels, i);
+
+                        int omx_profile = (*env)->GetLongField(env, profile_level, p_sys->profile_field);
+                        size_t codec_profile = convert_omx_to_profile_idc(omx_profile);
+                        if (codec_profile != fmt_profile)
+                            continue;
+                        /* Some encoders set the level too high, thus we ignore it for the moment.
+                           We could try to guess the actual profile based on the resolution. */
+                        found = true;
+                    }
+                }
+                else
+                    found = true;
+            }
             (*env)->DeleteLocalRef(env, type);
         }
         if (found) {
-- 
1.8.3.2




More information about the vlc-devel mailing list