Commit ce209f5a authored by Thomas Guillem's avatar Thomas Guillem Committed by Jean-Baptiste Kempf

Use HW Decoders before 4.3 for a list of known devices

Add HWDecoderUtil: Utility class that return the preferred hardware decoder
(none, mediacodec and/or iomx) from a list of known devices. It's only taking
effect before Android 4.3 as MediaCodec will always be preferred after.

That class use the hidden android.os.SystemProperties API to retrieve
properties like "ro.board.platform" in order to know which device we are
running. That API won't be used after 4.3 as we want to limit the usage of
android private API.
Signed-off-by: Jean-Baptiste Kempf's avatarJean-Baptiste Kempf <jb@videolan.org>
parent 3a052c9a
/*****************************************************************************
* HWDecUtil.java
*****************************************************************************
* Copyright © 2010-2013 VLC authors and VideoLAN
*
* This program 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; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
package org.videolan.libvlc;
import java.lang.reflect.Method;
import java.util.HashMap;
/**
* Utility class that return the preferred hardware decoder from a list of known devices.
*/
public class HWDecoderUtil {
public enum Decoder {
UNKNOWN, NONE, OMX, MEDIACODEC, ALL
}
private static class DecoderBySOC {
public final String key;
public final Decoder dec;
public final String[] list;
public DecoderBySOC(String key, Decoder dec, String[] list) {
this.key = key;
this.dec = dec;
this.list = list;
}
}
private static final DecoderBySOC[] sDecoderBySOCList = new DecoderBySOC[] {
/*
* Put first devices you want to blacklist
* because theses devices can match the next rules.
*/
new DecoderBySOC ("ro.product.brand", Decoder.NONE, new String[] {
"SEMC", // Xperia S
}),
new DecoderBySOC ("ro.board.platform", Decoder.NONE, new String[] {
"msm7627", // QCOM S1
}),
/*
* Devices working on OMX
*/
new DecoderBySOC ("ro.board.platform", Decoder.OMX, new String[] {
"omap3", // Omap 3
"rockchip", "rk29", // Rockchip RK29
"tegra", // Tegra 2
"msm7630", // QCOM S2
"s5pc", // Exynos 3
"montblanc", // Montblanc
"exdroid", // Allwinner A31
}),
new DecoderBySOC ("ro.hardware", Decoder.OMX, new String[] {
"sun6i", // Allwinner A31
}),
/*
* Devices working on Mediacodec and OMX
*/
new DecoderBySOC ("ro.board.platform", Decoder.ALL, new String[] {
"omap4", // Omap 4
"msm8660", // QCOM S3
"exynos4", // Exynos 4 (Samsung Galaxy S2/S3)
"exynos5", // Exynos 5 (Samsung Galaxy S4)
"rk30", "rk31", // Rockchip RK3*
}),
new DecoderBySOC ("ro.hardware", Decoder.ALL, new String[] {
"mt65", "mt83", // MTK
}),
};
private static final HashMap<String, String> sSystemPropertyMap = new HashMap<String, String>();
/**
* @return the hardware decoder known to work for the running device
* (Always return Dec.ALL after Android 4.3)
*/
public static Decoder getDecoderFromDevice() {
if (LibVlcUtil.isJellyBeanMR2OrLater())
return Decoder.ALL;
for (DecoderBySOC decBySOC : sDecoderBySOCList) {
String prop = sSystemPropertyMap.get(decBySOC.key);
if (prop == null) {
prop = getSystemProperty(decBySOC.key, "none");
sSystemPropertyMap.put(decBySOC.key, prop);
}
if (prop != null) {
for (String decProp: decBySOC.list)
if (prop.contains(decProp))
return decBySOC.dec;
}
}
return Decoder.UNKNOWN;
}
private static String getSystemProperty(String key, String def) {
try {
final ClassLoader cl = ClassLoader.getSystemClassLoader();
final Class<?> SystemProperties = cl.loadClass("android.os.SystemProperties");
final Class<?>[] paramTypes = new Class[] { String.class, String.class };
final Method get = SystemProperties.getMethod("get", paramTypes);
final Object[] params = new Object[] { key, def };
return (String) get.invoke(SystemProperties, params);
} catch (Exception e){
return def;
}
}
}
......@@ -43,6 +43,8 @@ public class LibVLC {
public static final int HW_ACCELERATION_DECODING = 1;
public static final int HW_ACCELERATION_FULL = 2;
private static final String DEFAULT_CODEC_LIST = "mediacodec,iomx,all";
private static LibVLC sInstance;
/** libVLC instance C pointer */
......@@ -65,6 +67,7 @@ public class LibVLC {
/** Settings */
private int hardwareAcceleration = HW_ACCELERATION_AUTOMATIC;
private String codecList = DEFAULT_CODEC_LIST;
private String subtitlesEncoding = "";
private int aout = LibVlcUtil.isGingerbreadOrLater() ? AOUT_OPENSLES : AOUT_AUDIOTRACK_JAVA;
private int vout = VOUT_ANDROID_SURFACE;
......@@ -245,15 +248,49 @@ public class LibVLC {
}
public void setHardwareAcceleration(int hardwareAcceleration) {
if (hardwareAcceleration < 0) {
// Automatic mode: activate MediaCodec opaque direct rendering for 4.3 and above.
if (LibVlcUtil.isJellyBeanMR2OrLater())
this.hardwareAcceleration = HW_ACCELERATION_FULL;
else
if (hardwareAcceleration == HW_ACCELERATION_DISABLED) {
Log.d(TAG, "HWDec disabled: by user");
this.hardwareAcceleration = HW_ACCELERATION_DISABLED;
this.codecList = "all";
} else {
// Automatic or forced
HWDecoderUtil.Decoder decoder = HWDecoderUtil.getDecoderFromDevice();
if (decoder == HWDecoderUtil.Decoder.NONE) {
// NONE
this.hardwareAcceleration = HW_ACCELERATION_DISABLED;
this.codecList = "all";
Log.d(TAG, "HWDec disabled: device not working with mediacodec,iomx");
} else if (decoder == HWDecoderUtil.Decoder.UNKNOWN) {
// UNKNOWN
if (hardwareAcceleration < 0) {
this.hardwareAcceleration = HW_ACCELERATION_DISABLED;
this.codecList = "all";
Log.d(TAG, "HWDec disabled: automatic and (unknown device or android version < 4.3)");
} else {
this.hardwareAcceleration = hardwareAcceleration;
this.codecList = DEFAULT_CODEC_LIST;
Log.d(TAG, "HWDec enabled: forced by user and unknown device");
}
} else {
// OMX, MEDIACODEC or ALL
this.hardwareAcceleration = hardwareAcceleration < 0 ?
HW_ACCELERATION_FULL : hardwareAcceleration;
if (decoder == HWDecoderUtil.Decoder.ALL)
this.codecList = DEFAULT_CODEC_LIST;
else {
final StringBuilder sb = new StringBuilder();
if (decoder == HWDecoderUtil.Decoder.MEDIACODEC)
sb.append("mediacodec,");
else if (decoder == HWDecoderUtil.Decoder.OMX)
sb.append("iomx,");
sb.append("all");
this.codecList = sb.toString();
}
Log.d(TAG, "HWDec enabled: device working with: " + this.codecList);
}
}
else
this.hardwareAcceleration = hardwareAcceleration;
}
public String[] getMediaOptions(boolean noHardwareAcceleration, boolean noVideo) {
......@@ -274,7 +311,7 @@ public class LibVLC {
*/
options.add(":file-caching=1500");
options.add(":network-caching=1500");
options.add(":codec=mediacodec,iomx,all");
options.add(":codec="+this.codecList);
}
if (noVideo)
options.add(":no-video");
......
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