@@ -2,10 +2,12 @@ package com.parseus.codecinfo.data.codecinfo
22
33import android.annotation.SuppressLint
44import android.content.Context
5+ import android.media.MediaCodec
56import android.media.MediaCodecInfo
67import android.media.MediaCodecInfo.CodecCapabilities.*
78import android.media.MediaCodecList
89import android.media.MediaFormat
10+ import android.os.Build
911import android.os.Build.VERSION.SDK_INT
1012import android.util.Range
1113import androidx.annotation.RequiresApi
@@ -16,10 +18,7 @@ import com.parseus.codecinfo.data.DetailsProperty
1618import com.parseus.codecinfo.data.codecinfo.colorformats.*
1719import com.parseus.codecinfo.data.codecinfo.profilelevels.*
1820import com.parseus.codecinfo.data.codecinfo.profilelevels.VP9Levels.*
19- import com.parseus.codecinfo.utils.isAudioCodec
20- import com.parseus.codecinfo.utils.toBytesPerSecond
21- import com.parseus.codecinfo.utils.toHexHstring
22- import com.parseus.codecinfo.utils.toKiloHertz
21+ import com.parseus.codecinfo.utils.*
2322import java.util.*
2423import kotlin.collections.ArrayList
2524
@@ -39,6 +38,9 @@ private const val DIVX6_1080P_MAX_FRAME_RATE = 30
3938private val DIVX4_MAX_RESOLUTION = intArrayOf(720 , 576 )
4039private val DIVX6_MAX_RESOLUTION = intArrayOf(1920 , 1080 )
4140
41+ private const val GOOGLE_RAW_DECODER = " OMX.google.raw.decoder"
42+ private const val MEDIATEK_RAW_DECODER = " OMX.MTK.AUDIO.DECODER.RAW"
43+
4244private val platformSupportedTypes = arrayOf(
4345 " audio/3gpp" ,
4446 " audio/amr-mb" ,
@@ -102,11 +104,38 @@ fun getSimpleCodecInfoList(context: Context, isAudio: Boolean): MutableList<Code
102104 return mutableListOf ()
103105 }
104106 } else {
105- @Suppress(" DEPRECATION" )
106- Array (MediaCodecList .getCodecCount()) { i -> MediaCodecList .getCodecInfoAt(i) }
107+ try {
108+ @Suppress(" DEPRECATION" )
109+ Array (MediaCodecList .getCodecCount()) { i -> MediaCodecList .getCodecInfoAt(i) }
110+ } catch (e: Exception ) {
111+ return mutableListOf ()
112+ }
107113 }
108114 }
109115
116+ if (SDK_INT in 21 .. 23 && mediaCodecInfos.find { it.name.endsWith(" secure" ) } == null ) {
117+ // Some devices don't list secure decoders on API 21 with a newer way of querying codecs,
118+ // but potentially could also happen on API levels 22 and 23.
119+ // In that case try the old way.
120+ try {
121+ @Suppress(" DEPRECATION" )
122+ val oldCodecInfos = Array (MediaCodecList .getCodecCount())
123+ { i -> MediaCodecList .getCodecInfoAt(i) }.filter { it.name.endsWith(" secure" ) }
124+ mediaCodecInfos + = oldCodecInfos
125+ } catch (e: Exception ) {}
126+ }
127+
128+ if (SDK_INT in 22 .. 25 && Build .DEVICE == " R9"
129+ && mediaCodecInfos.find { it.name == GOOGLE_RAW_DECODER } == null
130+ && mediaCodecInfos.find { it.name == MEDIATEK_RAW_DECODER } != null ) {
131+ // Oppo R9 does not list a generic raw audio decoder, yet it can be instantiated by name.
132+ try {
133+ val rawMediaCodec = MediaCodec .createByCodecName(GOOGLE_RAW_DECODER )
134+ // noinspection NewApi
135+ mediaCodecInfos + = rawMediaCodec.codecInfo
136+ } catch (e: Exception ) {}
137+ }
138+
110139 val showAliases = prefs.getBoolean(" show_aliases" , false )
111140 val filteringOption = prefs.getString(" filter_type" , " 2" )!! .toInt()
112141 var codecSimpleInfoList = ArrayList <CodecSimpleInfo >()
@@ -447,12 +476,12 @@ private fun adjustMaxInputChannelCount(codecId: String, codecName: String, maxCh
447476 }
448477 }
449478
450- if (SDK_INT < 28 ) {
479+ if (CAN_USE_REFLECTION_FOR_MCAPABILITIESINFO ) {
451480 /*
452481 mCapabilitiesInfo, a private MediaFormat instance hidden in MediaCodecInfo,
453482 can actually provide max input channel count (as well as other useful info).
454- Unfortunately, with P restricting non-API usage via reflection, I can only hope
455- that everything will work fine on newer versions.
483+ Android 9.0 put it on a dark greylist, though, so it can't be easily accessed anymore
484+ (although it is bypassed on a non-store mobile flavor). Newer versions are SOL here .
456485 */
457486 try {
458487 val capabilitiesInfo = capabilities::class .java.getDeclaredField(" mCapabilitiesInfo" )
@@ -462,8 +491,7 @@ private fun adjustMaxInputChannelCount(codecId: String, codecName: String, maxCh
462491 if (mediaFormat.containsKey(" max-channel-count" )) {
463492 return mediaFormat.getString(" max-channel-count" )!! .toInt()
464493 }
465- } catch (e: Exception ) {
466- }
494+ } catch (e: Exception ) {}
467495 }
468496
469497 if (codecId.endsWith(" flac" ) || codecId.endsWith(" alac" )) {
@@ -582,7 +610,7 @@ private fun addColorFormats(capabilities: MediaCodecInfo.CodecCapabilities, code
582610private fun getFormattedColorProfileString (context : Context , colorFormat : String , colorFormatInt : Int ): String {
583611 val prefs = PreferenceManager .getDefaultSharedPreferences(context)
584612
585- return when (prefs.getString(" known_values_color_profiles" , " 0 " )!! .toInt()) {
613+ return when (prefs.getString(" known_values_color_profiles" , " 1 " )!! .toInt()) {
586614 0 -> colorFormat
587615 1 -> " $colorFormat (${colorFormatInt.toHexHstring()} )"
588616 else -> " $colorFormat ($colorFormatInt )"
@@ -592,7 +620,7 @@ private fun getFormattedColorProfileString(context: Context, colorFormat: String
592620@RequiresApi(21 )
593621private fun getMaxResolution (codecId : String , videoCapabilities : MediaCodecInfo .VideoCapabilities ): IntArray {
594622 val maxWidth = videoCapabilities.supportedWidths.upper
595- val maxHeight = videoCapabilities.getSupportedHeightsFor(maxWidth) .upper
623+ val maxHeight = videoCapabilities.supportedHeights .upper
596624 val defaultResolution = intArrayOf(maxWidth, maxHeight)
597625
598626 return if (! areCapabilitiesUnknown(videoCapabilities)) {
@@ -803,7 +831,7 @@ private fun getProfileLevels(context: Context, codecId: String, codecName: Strin
803831private fun getFormattedProfileLevelString (context : Context , profile : String? , profileInt : Int ,
804832 level : String? , levelInt : Int ): String {
805833 val prefs = PreferenceManager .getDefaultSharedPreferences(context)
806- val option = prefs.getString(" known_values_profile_levels" , " 0 " )!! .toInt()
834+ val option = prefs.getString(" known_values_profile_levels" , " 1 " )!! .toInt()
807835 val unknownString = context.getString(R .string.unknown)
808836
809837 val profileString = when (option) {
@@ -872,7 +900,7 @@ private fun getMaxVP9ProfileLevel(capabilities: MediaCodecInfo.CodecCapabilities
872900}
873901
874902private fun isVendor (codecInfo : MediaCodecInfo ): Boolean {
875- val codecName = codecInfo.name.toLowerCase (Locale .ENGLISH )
903+ val codecName = codecInfo.name.lowercase (Locale .ENGLISH )
876904 return (! codecName.startsWith(" omx.google." )
877905 && ! codecName.startsWith(" c2.android." )
878906 && ! codecName.startsWith(" c2.google." )
@@ -885,7 +913,7 @@ private fun isSoftwareOnly(codecInfo: MediaCodecInfo): Boolean {
885913 return codecInfo.isSoftwareOnly
886914 }
887915
888- val codecName = codecInfo.name.toLowerCase (Locale .ENGLISH )
916+ val codecName = codecInfo.name.lowercase (Locale .ENGLISH )
889917
890918 // Broadcom codecs which specifically mention HW acceleration in their names
891919 if (codecName.contains(" omx.brcm.video" , true ) && codecName.contains(" hw" , true )) {
0 commit comments