Skip to content

Commit

Permalink
Merge pull request #29 from Parseus/dev
Browse files Browse the repository at this point in the history
Dev -> master: version 2.6.0
  • Loading branch information
Parseus authored Feb 16, 2024
2 parents 6a9ef57 + b06fffb commit 4cfc0d3
Show file tree
Hide file tree
Showing 62 changed files with 716 additions and 159 deletions.
5 changes: 2 additions & 3 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 0 additions & 12 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/migrations.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Missing color formats
- OMX.IMG.VIDEO.TOPAZ.Encoder - color formats 0x7F000005-12 (although 1-3 are probably incorrect, too)
- MediaTek S900/MT9950 - 0x7F000101-3
82 changes: 45 additions & 37 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'com.google.devtools.ksp' version '1.9.10-1.0.13'
alias libs.plugins.agp
alias libs.plugins.kotlin
alias libs.plugins.ksp
}

android {
Expand All @@ -11,8 +11,8 @@ android {
applicationId "com.parseus.codecinfo"
minSdkVersion 21
targetSdkVersion 34
versionCode 24
versionName "2.5.1"
versionCode 25
versionName "2.6.0"
resConfigs 'en'
}
buildTypes {
Expand All @@ -26,9 +26,17 @@ android {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

packagingOptions {
resources.excludes += "DebugProbesKt.bin"
}
}
}

buildFeatures {
buildConfig = true
}

flavorDimensions = ["app", "platform"]

productFlavors {
Expand Down Expand Up @@ -91,36 +99,36 @@ configurations {
}

dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3'

implementation 'androidx.appcompat:appcompat:1.7.0-alpha03'
implementation "androidx.core:core-ktx:1.12.0"
implementation 'androidx.fragment:fragment-ktx:1.7.0-alpha04'
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.recyclerview:recyclerview:1.3.1'

implementation "com.squareup.leakcanary:plumber-android:$leakCanary_version"
implementation "com.squareup.moshi:moshi:$moshi_version"
ksp "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
implementation "com.squareup.okio:okio:3.5.0"

debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanary_version"

tvImplementation 'androidx.leanback:leanback:1.2.0-alpha03'
tvImplementation 'androidx.leanback:leanback-preference:1.2.0-alpha03'

standardMobileImplementation 'org.lsposed.hiddenapibypass:hiddenapibypass:4.3'

mobileImplementation 'androidx.constraintlayout:constraintlayout:2.1.4'
mobileImplementation 'androidx.core:core-splashscreen:1.1.0-alpha02'
mobileImplementation 'androidx.palette:palette-ktx:1.0.0'
mobileImplementation 'androidx.webkit:webkit:1.8.0'
mobileImplementation 'com.github.KieronQuinn:MonetCompat:0.4.1'
mobileImplementation 'com.github.marcoscgdev:Licenser:2.0.0'
mobileImplementation 'com.google.android.material:material:1.11.0-alpha02'

nonFreeMobileImplementation 'com.google.android.play:app-update:2.1.0'
nonFreeMobileImplementation 'com.google.android.play:app-update-ktx:2.1.0'
nonFreeMobileImplementation 'com.google.android.play:review:2.0.1'
nonFreeMobileImplementation 'com.google.android.play:review-ktx:2.0.1'
implementation libs.coroutines

implementation libs.androidx.appcompat
implementation libs.androidx.core
implementation libs.androidx.fragment
implementation libs.androidx.preference
implementation libs.androidx.recyclerview

implementation libs.plumber.android
implementation libs.moshi
ksp libs.moshi.codegen
implementation libs.okio

debugImplementation libs.leakcanary.android

tvImplementation libs.androidx.leanback
tvImplementation libs.androidx.leanback.preference

standardMobileImplementation libs.hiddenapibypass

mobileImplementation libs.androidx.constraintlayout
mobileImplementation libs.androidx.core.splashscreen
mobileImplementation libs.androidx.palette
mobileImplementation libs.androidx.webkit
mobileImplementation libs.monetcompat
mobileImplementation libs.licenser
mobileImplementation libs.material

nonFreeMobileImplementation libs.app.update
nonFreeMobileImplementation libs.app.update.ktx
nonFreeMobileImplementation libs.review
nonFreeMobileImplementation libs.review.ktx
}
11 changes: 10 additions & 1 deletion app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
public static void checkExpressionValueIsNotNull(java.lang.Object, java.lang.String);
public static void checkFieldIsNotNull(java.lang.Object, java.lang.String);
public static void checkFieldIsNotNull(java.lang.Object, java.lang.String, java.lang.String);
public static void checkNotNull(java.lang.Object);
public static void checkNotNull(java.lang.Object, java.lang.String);
public static void checkNotNullExpressionValue(java.lang.Object, java.lang.String);
public static void checkNotNullParameter(java.lang.Object, java.lang.String);
public static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
public static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String);
public static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String, java.lang.String);
}

-keepattributes SourceFile, LineNumberTable
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/assets/changelog.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
<html>
<body>

<h2>Version 2.6.0</h2>
<p>Added an option to save info for a selected codec/DRM to Logcat.</p>
<p>Added querying for a resource rating tier and decrypt hash function for Widevine.</p>
<p>Added more known codec and device issues.</p>
<p>Added 12 more color formats from Samsung.</p>
<p>Viewing info for an already seen codec/DRM should be much faster now.</p>
<p>Improved reporting of the max resolution for codecs on devices that underreport it.</p>
<p>Bugfixes and general improvements.</p>

<h2>Version 2.5.1</h2>
<p>Removed support for Android 4.4 and older.</p>
<p>Removed support for legacy gestures on a few very old Samsung phones.</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import android.media.MediaCodecList
import android.media.MediaFormat
import android.os.Build
import android.os.Build.VERSION.SDK_INT
import android.util.Log
import android.util.Range
import androidx.annotation.RequiresApi
import androidx.annotation.StringRes
Expand Down Expand Up @@ -46,6 +47,14 @@ private const val AC3_MAX_SAMPLE_RATE = 48000
private const val GOOGLE_RAW_DECODER = "OMX.google.raw.decoder"
private const val MEDIATEK_RAW_DECODER = "OMX.MTK.AUDIO.DECODER.RAW"

private val incorrectMpeg4ResolutionModelList = listOf(
"Nokia 1",
"moto c",
"infinix x650",
"LG-X230",
"twist 2 pro"
)

private val platformSupportedTypes = arrayOf(
"audio/3gpp",
"audio/amr-mb",
Expand Down Expand Up @@ -98,6 +107,7 @@ private var mediaCodecInfos: Array<MediaCodecInfo> = emptyArray()
val audioCodecList: MutableList<CodecSimpleInfo> = mutableListOf()
val videoCodecList: MutableList<CodecSimpleInfo> = mutableListOf()

val detailedCodecInfos: MutableMap<String, List<DetailsProperty>> = mutableMapOf()

fun getSimpleCodecInfoList(context: Context, isAudio: Boolean): MutableList<CodecSimpleInfo> {
if (isAudio && audioCodecList.isNotEmpty()) {
Expand Down Expand Up @@ -209,7 +219,19 @@ fun getSimpleCodecInfoList(context: Context, isAudio: Boolean): MutableList<Code
return codecSimpleInfoList
}

fun isDetailedCodecInfoCached(codecId: String, codecName: String): Boolean {
val combinedCodecName = "$codecId/$codecName"
return detailedCodecInfos[combinedCodecName] != null
}

fun getDetailedCodecInfo(context: Context, codecId: String, codecName: String): List<DetailsProperty> {
val combinedCodecName = "$codecId/$codecName"
if (detailedCodecInfos[combinedCodecName] != null) {
return detailedCodecInfos[combinedCodecName]!!.also {
saveToLogcat(context, codecId, codecName, it)
}
}

val mediaCodecInfo = mediaCodecInfos.find { it.name == codecName } ?: return emptyList()

// Google uses the same decoder for both DP and non-DP content for MPEG-4,
Expand Down Expand Up @@ -335,7 +357,11 @@ fun getDetailedCodecInfo(context: Context, codecId: String, codecName: String):
propertyList.add(DetailsProperty(propertyList.size.toLong(), profileString, it))
}

return propertyList
detailedCodecInfos[combinedCodecName] = propertyList

return propertyList.also {
saveToLogcat(context, codecId, codecName, it)
}
}

@RequiresApi(30)
Expand Down Expand Up @@ -698,12 +724,17 @@ private fun getMaxResolution(codecId: String, videoCapabilities: MediaCodecInfo.
// capabilities. The supported height reported for H265@3840x2160 is 2144,
// and H264@1920x1080 is 1072.
// Cross reference with CamcorderProfile to ensure a resolution is supported.
// Several other devices also indicate a wrong resolution (174x174) for MPEG-4 SP.
// On Huawei Mate 9, HEVC reports only H265@3840x2112 instead of full 4K.
if (maxHeight == 1072 && CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_1080P)) {
defaultResolution[0] = 1920
defaultResolution[1] = 1080
} else if (maxHeight == 2144 && CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_2160P)) {
} else if ((maxHeight == 2144 || (maxHeight == 2112 && Build.MODEL == "mha-l29")) && CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_2160P)) {
defaultResolution[0] = 3840
defaultResolution[1] = 2160
} else if (needsMaxResolutionFixForMPEG4(codecId)) {
defaultResolution[0] = 1280
defaultResolution[1] = 720
}

return if (!areCapabilitiesUnknown(videoCapabilities)) {
Expand Down Expand Up @@ -760,20 +791,35 @@ private fun getFrameRatePerResolutions(context: Context, codecId: String,
return@forEachIndexed
}

if (videoCapabilities.isSizeSupported(resolution[0], resolution[1])) {
maxFrameRate = getSupportedFrameRatesFor(codecId, videoCapabilities, resolution[0], resolution[1]).upper
try {
if (isSizeSupported(videoCapabilities, resolution[0], resolution[1])) {
maxFrameRate = getSupportedFrameRatesFor(codecId, videoCapabilities, resolution[0], resolution[1]).upper

if (option == 0) {
capabilities.append("${framerateClasses[index]}: ${"%.1f".format(maxFrameRate)} $fpsString\n")
} else {
capabilities.append("${resolution[0]}x${resolution[1]}: ${"%.1f".format(maxFrameRate)} $fpsString\n")
if (option == 0) {
capabilities.append("${framerateClasses[index]}: ${"%.1f".format(maxFrameRate)} $fpsString\n")
} else {
capabilities.append("${resolution[0]}x${resolution[1]}: ${"%.1f".format(maxFrameRate)} $fpsString\n")
}
}
}
} catch (_: Throwable) {}
}

return capabilities.toString().dropLast(1) // Remove the last \n
}

private fun isSizeSupported(videoCapabilities: MediaCodecInfo.VideoCapabilities, width: Int, height: Int): Boolean {
if (videoCapabilities.isSizeSupported(width, height)) return true

if (width == 1920 && height == 1080) {
return CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_1080P)
}
if (width == 3840 && height == 2160) {
return CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_2160P)
}

return false
}

@SuppressLint("NewApi")
private fun getProfileLevels(context: Context, codecId: String, codecName: String,
capabilities: MediaCodecInfo.CodecCapabilities): String? {
Expand Down Expand Up @@ -1064,4 +1110,15 @@ private fun needsHevc10BitProfileExcluded(codecId: String, profile: Int): Boolea
// See https://github.com/google/ExoPlayer/issues/3537 for more info.
return "video/hevc" == codecId && HEVCProfiles.HEVCProfileMain10.value == profile
&& ("sailfish" == Build.DEVICE || "marlin" == Build.DEVICE)
}

private fun needsMaxResolutionFixForMPEG4(codecId: String) = "video/mp4v-es" == codecId && Build.MODEL in incorrectMpeg4ResolutionModelList

private fun saveToLogcat(context: Context, codecId: String, codecName: String, detailsList: List<DetailsProperty>) {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val saveDetailsToLogcat = prefs.getBoolean("save_details_to_logcat", false)
if (saveDetailsToLogcat) {
Log.i("CodecUtils", "Codec MIME type: $codecId, codec name: $codecName")
Log.i("CodecUtils", detailsList.joinToString("\n"))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ enum class BroadcomColorFormat(val value: Int) {
OMX_COLOR_FormatRawGrey14bit16bpp(0x7F00001D);

companion object {
fun from(findValue: Int) = values().find { it.value == findValue }?.name
fun from(findValue: Int) = entries.find { it.value == findValue }?.name
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ enum class IMGColorFormat(val value: Int) {
OMX_COLOR_FormatCMYK(0x7F000004);

companion object {
fun from(findValue: Int) = values().find { it.value == findValue }?.name
fun from(findValue: Int) = entries.find { it.value == findValue }?.name
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ enum class MarvellColorFormat(val value: Int) {
OMX_COLOR_FormatIppPicture(0x7F000006);

companion object {
fun from(findValue: Int) = values().find { it.value == findValue }?.name
fun from(findValue: Int) = entries.find { it.value == findValue }?.name
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ enum class MediaTekColorFormat(val value: Int) {
OMX_MTK_COLOR_FormatBitStream(0x7F000300);

companion object {
fun from(findValue: Int) = values().find { it.value == findValue }?.name
fun from(findValue: Int) = entries.find { it.value == findValue }?.name
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ enum class NvidiaColorFormat(val value: Int) {
NVX_IMAGE_COLOR_FormatY(0x7F000003);

companion object {
fun from(findValue: Int) = values().find { it.value == findValue }?.name
fun from(findValue: Int) = entries.find { it.value == findValue }?.name
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ enum class OtherColorFormat(val value: Int) {
OMX_TI_COLOR_FormatYUV420PackedSemiPlanar(0x7F000100);

companion object {
fun from(findValue: Int) = values().find { it.value == findValue }?.name
fun from(findValue: Int) = entries.find { it.value == findValue }?.name
}

}
Loading

0 comments on commit 4cfc0d3

Please sign in to comment.