[vlc-commits] mediacodec: add adaptive playback support

Thomas Guillem git at videolan.org
Wed Mar 29 15:49:45 CEST 2017


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Fri Mar 24 12:02:22 2017 +0100| [9d9e5d293f2ffa5341a787435ba74655d2a9b0cb] | committer: Thomas Guillem

mediacodec: add adaptive playback support

Starting Android 4.4, devices can have the "adaptive-playback" capability. If a
device have such capability, we don't have to use hxxx_helper to detect SPS/PPS
change since the device is capable of handling it. It can also handle a video
size change.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=9d9e5d293f2ffa5341a787435ba74655d2a9b0cb
---

 modules/codec/omxil/mediacodec.c     | 30 ++++++++++++++++++++++++++---
 modules/codec/omxil/mediacodec.h     |  4 ++++
 modules/codec/omxil/mediacodec_jni.c | 37 ++++++++++++++++++++++++++++--------
 modules/codec/omxil/mediacodec_ndk.c | 13 +++++++++----
 4 files changed, 69 insertions(+), 15 deletions(-)

diff --git a/modules/codec/omxil/mediacodec.c b/modules/codec/omxil/mediacodec.c
index d107bd3..05a6dbb 100644
--- a/modules/codec/omxil/mediacodec.c
+++ b/modules/codec/omxil/mediacodec.c
@@ -103,6 +103,7 @@ struct decoder_sys_t
     /* If true, the first input block was successfully dequeued */
     bool            b_input_dequeued;
     bool            b_aborted;
+    bool            b_adaptive;
     int             i_decode_flags;
 
     union
@@ -283,6 +284,12 @@ static int ParseVideoExtraH264(decoder_t *p_dec, uint8_t *p_extra, int i_extra)
     if (i_ret != VLC_SUCCESS)
         return i_ret;
 
+    if (!hh->b_is_xvcC && p_sys->api.i_quirks & MC_API_VIDEO_QUIRKS_ADAPTIVE)
+    {
+        p_sys->b_adaptive = true;
+        return VLC_SUCCESS;
+    }
+
     assert(hh->pf_process_block != NULL);
     p_sys->pf_on_new_block = VideoHXXX_OnNewBlock;
 
@@ -297,9 +304,20 @@ static int ParseVideoExtraHEVC(decoder_t *p_dec, uint8_t *p_extra, int i_extra)
     struct hxxx_helper *hh = &p_sys->video.hh;
 
     int i_ret = hxxx_helper_set_extra(hh, p_extra, i_extra);
-    if (i_ret != VLC_SUCCESS || hh->pf_process_block == NULL)
+    if (i_ret != VLC_SUCCESS)
         return i_ret;
 
+    if (!hh->b_is_xvcC)
+    {
+        if (p_sys->api.i_quirks & MC_API_VIDEO_QUIRKS_ADAPTIVE)
+        {
+            p_sys->b_adaptive = true;
+            return VLC_SUCCESS;
+        }
+        else /* TODO */
+            return VLC_EGENERIC;
+    }
+
     assert(hh->pf_process_block != NULL);
     p_sys->pf_on_new_block = VideoHXXX_OnNewBlock;
 
@@ -445,7 +463,8 @@ static int StartMediaCodec(decoder_t *p_dec)
     decoder_sys_t *p_sys = p_dec->p_sys;
     union mc_api_args args;
 
-    if (((p_sys->api.i_quirks & MC_API_QUIRKS_NEED_CSD) && !p_sys->i_csd_count))
+    if ((p_sys->api.i_quirks & MC_API_QUIRKS_NEED_CSD) && !p_sys->i_csd_count
+     && !p_sys->b_adaptive)
     {
         msg_Warn(p_dec, "waiting for extra data for codec %4.4s",
                  (const char *)&p_dec->fmt_in.i_codec);
@@ -454,7 +473,8 @@ static int StartMediaCodec(decoder_t *p_dec)
 
     if (p_dec->fmt_in.i_cat == VIDEO_ES)
     {
-        if (!p_dec->fmt_out.video.i_width  || !p_dec->fmt_out.video.i_height)
+        if (!p_sys->b_adaptive
+         && (!p_dec->fmt_out.video.i_width || !p_dec->fmt_out.video.i_height))
         {
             msg_Warn(p_dec, "waiting for a valid video size for codec %4.4s",
                      (const char *)&p_dec->fmt_in.i_codec);
@@ -468,6 +488,9 @@ static int StartMediaCodec(decoder_t *p_dec)
         args.video.p_jsurface = p_sys->video.p_jsurface;
         args.video.b_tunneled_playback = args.video.p_surface ?
                 var_InheritBool(p_dec, CFG_PREFIX "tunneled-playback") : false;
+        if (p_sys->b_adaptive)
+            msg_Dbg(p_dec, "mediacodec configured for adaptative playback");
+        args.video.b_adaptive_playback = p_sys->b_adaptive;
     }
     else
     {
@@ -1368,6 +1391,7 @@ static int DecodeBlock(decoder_t *p_dec, block_t *p_in_block)
                     if (!i_ts && p_block->i_dts)
                         i_ts = p_block->i_dts;
                 }
+                else fprintf(stderr, "send CSD\n");
                 p_buf = p_block->p_buffer;
                 i_size = p_block->i_buffer;
             }
diff --git a/modules/codec/omxil/mediacodec.h b/modules/codec/omxil/mediacodec.h
index 211bbf6..ed0eb73 100644
--- a/modules/codec/omxil/mediacodec.h
+++ b/modules/codec/omxil/mediacodec.h
@@ -45,6 +45,9 @@ int MediaCodecNdk_Init(mc_api*);
 #define MC_API_VIDEO_QUIRKS_SUPPORT_INTERLACED 0x4
 #define MC_API_AUDIO_QUIRKS_NEED_CHANNELS 0x8
 
+/* MediaCodec only QUIRKS */
+#define MC_API_VIDEO_QUIRKS_ADAPTIVE 0x1000
+
 struct mc_api_out
 {
     enum {
@@ -94,6 +97,7 @@ union mc_api_args
         int i_height;
         int i_angle;
         bool b_tunneled_playback;
+        bool b_adaptive_playback;
     } video;
     struct
     {
diff --git a/modules/codec/omxil/mediacodec_jni.c b/modules/codec/omxil/mediacodec_jni.c
index 426f33c..b69cb1a 100644
--- a/modules/codec/omxil/mediacodec_jni.c
+++ b/modules/codec/omxil/mediacodec_jni.c
@@ -38,7 +38,7 @@
 #include "mediacodec.h"
 
 char* MediaCodec_GetName(vlc_object_t *p_obj, const char *psz_mime,
-                         size_t h264_profile);
+                         size_t h264_profile, bool *p_adaptive);
 
 #define THREAD_NAME "mediacodec_jni"
 
@@ -58,6 +58,7 @@ struct jfields
     jclass buffer_info_class, byte_buffer_class;
     jmethodID tostring;
     jmethodID get_codec_count, get_codec_info_at, is_encoder, get_capabilities_for_type;
+    jmethodID is_feature_supported;
     jfieldID profile_levels_field, profile_field, level_field;
     jmethodID get_supported_types, get_name;
     jmethodID create_by_codec_name, configure, start, stop, flush, release;
@@ -113,7 +114,7 @@ static const struct member members[] = {
     { "getSupportedTypes", "()[Ljava/lang/String;", "android/media/MediaCodecInfo", OFF(get_supported_types), METHOD, true },
     { "getName", "()Ljava/lang/String;", "android/media/MediaCodecInfo", OFF(get_name), METHOD, true },
     { "getCapabilitiesForType", "(Ljava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;", "android/media/MediaCodecInfo", OFF(get_capabilities_for_type), METHOD, true },
-
+    { "isFeatureSupported", "(Ljava/lang/String;)Z", "android/media/MediaCodecInfo$CodecCapabilities", OFF(is_feature_supported), METHOD, false },
     { "profileLevels", "[Landroid/media/MediaCodecInfo$CodecProfileLevel;", "android/media/MediaCodecInfo$CodecCapabilities", OFF(profile_levels_field), FIELD, true },
     { "profile", "I", "android/media/MediaCodecInfo$CodecProfileLevel", OFF(profile_field), FIELD, true },
     { "level", "I", "android/media/MediaCodecInfo$CodecProfileLevel", OFF(level_field), FIELD, true },
@@ -309,7 +310,7 @@ struct mc_api_sys
  * MediaCodec_GetName
  *****************************************************************************/
 char* MediaCodec_GetName(vlc_object_t *p_obj, const char *psz_mime,
-                         size_t h264_profile)
+                         size_t h264_profile, bool *p_adaptive)
 {
     JNIEnv *env;
     int num_codecs;
@@ -341,6 +342,7 @@ char* MediaCodec_GetName(vlc_object_t *p_obj, const char *psz_mime,
         int profile_levels_len = 0, num_types = 0;
         const char *name_ptr = NULL;
         bool found = false;
+        bool b_adaptive = false;
 
         info = (*env)->CallStaticObjectMethod(env, jfields.media_codec_list_class,
                                               jfields.get_codec_info_at, i);
@@ -368,6 +370,16 @@ char* MediaCodec_GetName(vlc_object_t *p_obj, const char *psz_mime,
             profile_levels = (*env)->GetObjectField(env, codec_capabilities, jfields.profile_levels_field);
             if (profile_levels)
                 profile_levels_len = (*env)->GetArrayLength(env, profile_levels);
+            if (jfields.is_feature_supported)
+            {
+                jstring jfeature = JNI_NEW_STRING("adaptive-playback");
+                b_adaptive =
+                    (*env)->CallBooleanMethod(env, codec_capabilities,
+                                              jfields.is_feature_supported,
+                                              jfeature);
+                CHECK_EXCEPTION();
+                (*env)->DeleteLocalRef(env, jfeature);
+            }
         }
         msg_Dbg(p_obj, "Number of profile levels: %d", profile_levels_len);
 
@@ -418,6 +430,7 @@ char* MediaCodec_GetName(vlc_object_t *p_obj, const char *psz_mime,
                 memcpy(psz_name, name_ptr, name_len);
                 psz_name[name_len] = '\0';
             }
+            *p_adaptive = b_adaptive;
         }
 loopclean:
         if (name)
@@ -543,10 +556,15 @@ static int Start(mc_api *api, union mc_api_args *p_args)
         if (p_args->video.i_angle != 0)
             SET_INTEGER(jformat, "rotation-degrees", p_args->video.i_angle);
 
-        /* feature-tunneled-playback available since API 21 */
-        if (b_direct_rendering && jfields.get_input_buffer)
-            SET_INTEGER(jformat, "feature-tunneled-playback",
-                        p_args->video.b_tunneled_playback);
+        if (b_direct_rendering)
+        {
+            /* feature-tunneled-playback available since API 21 */
+            if (jfields.get_input_buffer && p_args->video.b_tunneled_playback)
+                SET_INTEGER(jformat, "feature-tunneled-playback", 1);
+
+            if (p_args->video.b_adaptive_playback)
+                SET_INTEGER(jformat, "feature-adaptive-playback", 1);
+        }
     }
     else
     {
@@ -946,8 +964,9 @@ static void Clean(mc_api *api)
 static int Configure(mc_api *api, size_t i_h264_profile)
 {
     free(api->psz_name);
+    bool b_adaptive;
     api->psz_name = MediaCodec_GetName(api->p_obj, api->psz_mime,
-                                       i_h264_profile);
+                                       i_h264_profile, &b_adaptive);
     if (!api->psz_name)
         return MC_API_ERROR;
     api->i_quirks = OMXCodec_GetQuirks(api->i_cat, api->i_codec, api->psz_name,
@@ -956,6 +975,8 @@ static int Configure(mc_api *api, size_t i_h264_profile)
     /* Allow interlaced picture after API 21 */
     if (jfields.get_input_buffer && jfields.get_output_buffer)
         api->i_quirks |= MC_API_VIDEO_QUIRKS_SUPPORT_INTERLACED;
+    if (b_adaptive)
+        api->i_quirks |= MC_API_VIDEO_QUIRKS_ADAPTIVE;
     return 0;
 }
 
diff --git a/modules/codec/omxil/mediacodec_ndk.c b/modules/codec/omxil/mediacodec_ndk.c
index 8677c74..a07ec20 100644
--- a/modules/codec/omxil/mediacodec_ndk.c
+++ b/modules/codec/omxil/mediacodec_ndk.c
@@ -39,7 +39,7 @@
 #include "mediacodec.h"
 
 char* MediaCodec_GetName(vlc_object_t *p_obj, const char *psz_mime,
-                         size_t h264_profile);
+                         size_t h264_profile, bool *p_adaptive);
 
 #define THREAD_NAME "mediacodec_ndk"
 
@@ -342,8 +342,10 @@ static int Start(mc_api *api, union mc_api_args *p_args)
             p_anw = p_args->video.p_surface;
             if (p_args->video.b_tunneled_playback)
                 syms.AMediaFormat.setInt32(p_sys->p_format,
-                                           "feature-tunneled-playback",
-                                           p_args->video.b_tunneled_playback);
+                                           "feature-tunneled-playback", 1);
+            if (p_args->video.b_adaptive_playback)
+                syms.AMediaFormat.setInt32(p_sys->p_format,
+                                           "feature-adaptive-playback", 1);
         }
     }
     else
@@ -584,14 +586,17 @@ static void Clean(mc_api *api)
 static int Configure(mc_api * api, size_t i_h264_profile)
 {
     free(api->psz_name);
+    bool b_adaptive;
     api->psz_name = MediaCodec_GetName(api->p_obj, api->psz_mime,
-                                       i_h264_profile);
+                                       i_h264_profile, &b_adaptive);
     if (!api->psz_name)
         return MC_API_ERROR;
     api->i_quirks = OMXCodec_GetQuirks(api->i_cat, api->i_codec, api->psz_name,
                                        strlen(api->psz_name));
     /* Allow interlaced picture after API 21 */
     api->i_quirks |= MC_API_VIDEO_QUIRKS_SUPPORT_INTERLACED;
+    if (b_adaptive)
+        api->i_quirks |= MC_API_VIDEO_QUIRKS_ADAPTIVE;
     return 0;
 }
 



More information about the vlc-commits mailing list