Commit 9d9e5d29 authored by Thomas Guillem's avatar Thomas Guillem
Browse files

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.
parent 8ca8549c
......@@ -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;
}
......
......@@ -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
{
......
......@@ -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;
}
......
......@@ -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;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment