001package com.baidu.cloud.media.player; 002 003import android.annotation.TargetApi; 004import android.media.MediaCodecInfo; 005import android.media.MediaCodecInfo.CodecCapabilities; 006import android.media.MediaCodecInfo.CodecProfileLevel; 007import android.os.Build; 008import android.text.TextUtils; 009import android.util.Log; 010 011import java.util.Locale; 012import java.util.Map; 013import java.util.TreeMap; 014 015public class BDCloudMediaCodecInfo { 016 private static final String TAG = "BDCloudMediaCodecInfo"; 017 018 public static final int RANK_MAX = 1000; 019 public static final int RANK_TESTED = 800; 020 public static final int RANK_ACCEPTABLE = 700; 021 public static final int RANK_LAST_CHANCE = 600; 022 public static final int RANK_SECURE = 300; 023 public static final int RANK_SOFTWARE = 200; 024 public static final int RANK_NON_STANDARD = 100; 025 public static final int RANK_NO_SENSE = 0; 026 027 public MediaCodecInfo mCodecInfo; 028 public int mRank = 0; 029 public String mMimeType; 030 031 private static Map<String, Integer> sKnownCodecList; 032 033 private static synchronized Map<String, Integer> getKnownCodecList() { 034 if (sKnownCodecList != null) { 035 return sKnownCodecList; 036 } 037 038 sKnownCodecList = new TreeMap<String, Integer>(String.CASE_INSENSITIVE_ORDER); 039 040 // ----- Nvidia ----- 041 // Tegra3 042 // Nexus 7 (2012) 043 // Tegra K1 044 // Nexus 9 045 sKnownCodecList.put("OMX.Nvidia.h264.decode", RANK_TESTED); 046 sKnownCodecList.put("OMX.Nvidia.h264.decode.secure", RANK_SECURE); 047 048 // ----- Intel ----- 049 // Atom Z3735 050 // Teclast X98 Air 051 sKnownCodecList.put("OMX.Intel.hw_vd.h264", RANK_TESTED + 1); 052 // Atom Z2560 053 // Dell Venue 7 3730 054 sKnownCodecList.put("OMX.Intel.VideoDecoder.AVC", RANK_TESTED); 055 056 // ----- Qualcomm ----- 057 // MSM8260 058 // Xiaomi MI 1S 059 sKnownCodecList.put("OMX.qcom.video.decoder.avc", RANK_TESTED); 060 sKnownCodecList.put("OMX.ittiam.video.decoder.avc", RANK_NO_SENSE); 061 062 // ----- Samsung ----- 063 // Exynos 3110 064 // Nexus S 065 sKnownCodecList.put("OMX.SEC.avc.dec", RANK_TESTED); 066 sKnownCodecList.put("OMX.SEC.AVC.Decoder", RANK_TESTED - 1); 067 // OMX.SEC.avcdec doesn't reorder output pictures on GT-9100 068 sKnownCodecList.put("OMX.SEC.avcdec", RANK_TESTED - 2); 069 sKnownCodecList.put("OMX.SEC.avc.sw.dec", RANK_SOFTWARE); 070 // Exynos 5 ? 071 sKnownCodecList.put("OMX.Exynos.avc.dec", RANK_TESTED); 072 sKnownCodecList.put("OMX.Exynos.AVC.Decoder", RANK_TESTED - 1); 073 074 // ------ Huawei hisilicon ------ 075 // Kirin 910, Mali 450 MP 076 // Huawei HONOR 3C (H30-L01) 077 sKnownCodecList.put("OMX.k3.video.decoder.avc", RANK_TESTED); 078 // Kirin 920, Mali T624 079 // Huawei HONOR 6 080 sKnownCodecList.put("OMX.IMG.MSVDX.Decoder.AVC", RANK_TESTED); 081 082 // ----- TI ----- 083 // TI OMAP4460 084 // Galaxy Nexus 085 sKnownCodecList.put("OMX.TI.DUCATI1.VIDEO.DECODER", RANK_TESTED); 086 087 // ------ RockChip ------ 088 // Youku TVBox 089 sKnownCodecList.put("OMX.rk.video_decoder.avc", RANK_TESTED); 090 091 // ------ AMLogic ----- 092 // MiBox1, 1s, 2 093 sKnownCodecList.put("OMX.amlogic.avc.decoder.awesome", RANK_TESTED); 094 095 // ------ Marvell ------ 096 // Lenovo A788t 097 sKnownCodecList.put("OMX.MARVELL.VIDEO.HW.CODA7542DECODER", RANK_TESTED); 098 sKnownCodecList.put("OMX.MARVELL.VIDEO.H264DECODER", RANK_SOFTWARE); 099 100 // ----- TODO: need test ----- 101 sKnownCodecList.remove("OMX.Action.Video.Decoder"); 102 sKnownCodecList.remove("OMX.allwinner.video.decoder.avc"); 103 sKnownCodecList.remove("OMX.BRCM.vc4.decoder.avc"); 104 sKnownCodecList.remove("OMX.brcm.video.h264.hw.decoder"); 105 sKnownCodecList.remove("OMX.brcm.video.h264.decoder"); 106 sKnownCodecList.remove("OMX.cosmo.video.decoder.avc"); 107 sKnownCodecList.remove("OMX.duos.h264.decoder"); 108 sKnownCodecList.remove("OMX.hantro.81x0.video.decoder"); 109 sKnownCodecList.remove("OMX.hantro.G1.video.decoder"); 110 sKnownCodecList.remove("OMX.hisi.video.decoder"); 111 sKnownCodecList.remove("OMX.LG.decoder.video.avc"); 112 sKnownCodecList.remove("OMX.MS.AVC.Decoder"); 113 sKnownCodecList.remove("OMX.RENESAS.VIDEO.DECODER.H264"); 114 sKnownCodecList.remove("OMX.RTK.video.decoder"); 115 sKnownCodecList.remove("OMX.sprd.h264.decoder"); 116 sKnownCodecList.remove("OMX.ST.VFM.H264Dec"); 117 sKnownCodecList.remove("OMX.vpu.video_decoder.avc"); 118 sKnownCodecList.remove("OMX.WMT.decoder.avc"); 119 120 // Really ? 121 sKnownCodecList.remove("OMX.bluestacks.hw.decoder"); 122 123 // --------------- 124 // Useless codec 125 // ----- google ----- 126 sKnownCodecList.put("OMX.google.h264.decoder", RANK_SOFTWARE); 127 sKnownCodecList.put("OMX.google.h264.lc.decoder", RANK_SOFTWARE); 128 // ----- huawei k920 ----- 129 sKnownCodecList.put("OMX.k3.ffmpeg.decoder", RANK_SOFTWARE); 130 sKnownCodecList.put("OMX.ffmpeg.video.decoder", RANK_SOFTWARE); 131 // ----- unknown ----- 132 sKnownCodecList.put("OMX.sprd.soft.h264.decoder", RANK_SOFTWARE); 133 134 return sKnownCodecList; 135 } 136 137 @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 138 public static BDCloudMediaCodecInfo setupCandidate(MediaCodecInfo codecInfo, String mimeType) { 139 if (codecInfo == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { 140 return null; 141 } 142 143 String name = codecInfo.getName(); 144 if (TextUtils.isEmpty(name)) { 145 return null; 146 } 147 148 name = name.toLowerCase(Locale.US); 149 int rank = RANK_NO_SENSE; 150 if (!name.startsWith("omx.")) { 151 rank = RANK_NON_STANDARD; 152 } else if (name.startsWith("omx.pv")) { 153 rank = RANK_SOFTWARE; 154 } else if (name.startsWith("omx.google.")) { 155 rank = RANK_SOFTWARE; 156 } else if (name.startsWith("omx.ffmpeg.")) { 157 rank = RANK_SOFTWARE; 158 } else if (name.startsWith("omx.k3.ffmpeg.")) { 159 rank = RANK_SOFTWARE; 160 } else if (name.startsWith("omx.avcodec.")) { 161 rank = RANK_SOFTWARE; 162 } else if (name.startsWith("omx.ittiam.")) { 163 // unknown codec in qualcomm SoC 164 rank = RANK_NO_SENSE; 165 } else if (name.startsWith("omx.mtk.")) { 166 // 1. MTK only works on 4.3 and above 167 // 2. MTK works on MIUI 6 (4.2.1) 168 // 3. MTK still not ok when mpeg4 169 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2 || name.endsWith("decoder.mpeg4")) { 170 rank = RANK_NO_SENSE; 171 } else { 172 rank = RANK_TESTED; 173 } 174 } else { 175 Integer knownRank = getKnownCodecList().get(name); 176 if (knownRank != null) { 177 rank = knownRank; 178 } else { 179 try { 180 CodecCapabilities cap = codecInfo.getCapabilitiesForType(mimeType); 181 if (cap != null) { 182 rank = RANK_ACCEPTABLE; 183 } else { 184 rank = RANK_LAST_CHANCE; 185 } 186 } catch (Throwable e) { 187 rank = RANK_LAST_CHANCE; 188 } 189 } 190 } 191 192 BDCloudMediaCodecInfo candidate = new BDCloudMediaCodecInfo(); 193 candidate.mCodecInfo = codecInfo; 194 candidate.mRank = rank; 195 candidate.mMimeType = mimeType; 196 return candidate; 197 } 198 199 @TargetApi(Build.VERSION_CODES.JELLY_BEAN) 200 public void dumpProfileLevels(String mimeType) { 201 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { 202 return; 203 } 204 205 try { 206 CodecCapabilities caps = mCodecInfo.getCapabilitiesForType(mimeType); 207 int maxProfile = 0; 208 int maxLevel = 0; 209 if (caps != null) { 210 if (caps.profileLevels != null) { 211 for (CodecProfileLevel profileLevel : caps.profileLevels) { 212 if (profileLevel == null) { 213 continue; 214 } 215 216 maxProfile = Math.max(maxProfile, profileLevel.profile); 217 maxLevel = Math.max(maxLevel, profileLevel.level); 218 } 219 } 220 } 221 222 Log.i(TAG, String.format(Locale.US, "%s", getProfileLevelName(maxProfile, maxLevel))); 223 } catch (Throwable e) { 224 Log.i(TAG, "profile-level: exception"); 225 } 226 } 227 228 public static String getProfileLevelName(int profile, int level) { 229 return String.format(Locale.US, " %s Profile Level %s (%d,%d)", getProfileName(profile), getLevelName(level), 230 profile, level); 231 } 232 233 public static String getProfileName(int profile) { 234 switch (profile) { 235 case CodecProfileLevel.AVCProfileBaseline: 236 return "Baseline"; 237 case CodecProfileLevel.AVCProfileMain: 238 return "Main"; 239 case CodecProfileLevel.AVCProfileExtended: 240 return "Extends"; 241 case CodecProfileLevel.AVCProfileHigh: 242 return "High"; 243 case CodecProfileLevel.AVCProfileHigh10: 244 return "High10"; 245 case CodecProfileLevel.AVCProfileHigh422: 246 return "High422"; 247 case CodecProfileLevel.AVCProfileHigh444: 248 return "High444"; 249 default: 250 return "Unknown"; 251 } 252 } 253 254 public static String getLevelName(int level) { 255 switch (level) { 256 case CodecProfileLevel.AVCLevel1: 257 return "1"; 258 case CodecProfileLevel.AVCLevel1b: 259 return "1b"; 260 case CodecProfileLevel.AVCLevel11: 261 return "11"; 262 case CodecProfileLevel.AVCLevel12: 263 return "12"; 264 case CodecProfileLevel.AVCLevel13: 265 return "13"; 266 case CodecProfileLevel.AVCLevel2: 267 return "2"; 268 case CodecProfileLevel.AVCLevel21: 269 return "21"; 270 case CodecProfileLevel.AVCLevel22: 271 return "22"; 272 case CodecProfileLevel.AVCLevel3: 273 return "3"; 274 case CodecProfileLevel.AVCLevel31: 275 return "31"; 276 case CodecProfileLevel.AVCLevel32: 277 return "32"; 278 case CodecProfileLevel.AVCLevel4: 279 return "4"; 280 case CodecProfileLevel.AVCLevel41: 281 return "41"; 282 case CodecProfileLevel.AVCLevel42: 283 return "42"; 284 case CodecProfileLevel.AVCLevel5: 285 return "5"; 286 case CodecProfileLevel.AVCLevel51: 287 return "51"; 288 case 65536: // CodecProfileLevel.AVCLevel52: 289 return "52"; 290 default: 291 return "0"; 292 } 293 } 294}