Skip to content

Commit

Permalink
Merge pull request #25 from Parseus/dev
Browse files Browse the repository at this point in the history
Dev -> master: version 2.4.0
  • Loading branch information
Parseus committed Oct 27, 2022
2 parents 24352e8 + e0619ec commit b9a489e
Show file tree
Hide file tree
Showing 110 changed files with 3,494 additions and 522 deletions.
1 change: 1 addition & 0 deletions .idea/.name

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

3 changes: 1 addition & 2 deletions .idea/gradle.xml

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

88 changes: 54 additions & 34 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'com.google.devtools.ksp' version '1.7.20-1.0.6'
}

android {
compileSdkVersion 31
namespace 'com.parseus.codecinfo'
compileSdkVersion 33
defaultConfig {
applicationId "com.parseus.codecinfo"
minSdkVersion 16
targetSdkVersion 31
versionCode 21
versionName "2.3.0"
resConfigs "en"
targetSdkVersion 33
versionCode 22
versionName "2.4.0"
resConfigs 'en'

vectorDrawables.useSupportLibrary = true
}
Expand All @@ -19,16 +22,12 @@ android {
versionNameSuffix "-dev"
if (!gradle.startParameter.taskNames.toString().contains('StandardTv')) {
multiDexEnabled true
manifestPlaceholders = [appName:"androidx.multidex.MultiDexApplication"]
} else {
manifestPlaceholders = [appName:"android.app.Application"]
}
}
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
manifestPlaceholders = [appName:"android.app.Application"]
}
}

Expand Down Expand Up @@ -71,57 +70,78 @@ android {
kotlinOptions {
jvmTarget = "11"
}

packagingOptions {
exclude 'kotlin/**'
exclude '**/*.kotlin_metadata'
exclude 'META-INF/*.kotlin_module'
exclude 'META-INF/*.version'
jniLibs {
excludes += ['kotlin/**']
}
resources {
excludes += ['kotlin/**', '**/*.kotlin_metadata', 'META-INF/*.kotlin_module', 'META-INF/*.version']
}
}


variantFilter { variant ->
def names = variant.flavors*.name
if (names.contains("nonFree") && names.contains("tv")) {
setIgnore(true)
}
}

sourceSets {
nonFreeMobileDebug {
java.srcDirs += 'src/mobileDebug/java'
}
standardMobileDebug {
java.srcDirs += 'src/mobileDebug/java'
}
nonFreeMobileRelease {
java.srcDirs += 'src/mobileRelease/java'
}
standardMobileRelease {
java.srcDirs += 'src/mobileRelease/java'
}
}
}

configurations {
nonFreeMobileImplementation {}
standardMobileImplementation {}
nonFreeMobileDebugImplementation {}
standardMobileDebugImplementation {}
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'

implementation 'androidx.appcompat:appcompat:1.3.1'
implementation "androidx.core:core-ktx:1.6.0"
implementation 'androidx.preference:preference-ktx:1.1.1'
implementation 'androidx.appcompat:appcompat:1.7.0-alpha01'
implementation "androidx.core:core-ktx:1.9.0"
implementation 'androidx.preference:preference-ktx:1.2.0'

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

implementation 'me.saket:better-link-movement-method:2.2.0'

debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanary_version"
standardMobileDebugImplementation 'androidx.multidex:multidex:2.0.1'
nonFreeMobileDebugImplementation 'androidx.multidex:multidex:2.0.1'

tvImplementation 'androidx.leanback:leanback:1.2.0-alpha01'
tvImplementation 'androidx.leanback:leanback-preference:1.2.0-alpha01'
tvImplementation 'androidx.leanback:leanback:1.2.0-alpha02'
tvImplementation 'androidx.leanback:leanback-preference:1.2.0-alpha02'

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

mobileImplementation 'androidx.constraintlayout:constraintlayout:2.1.0'
mobileImplementation 'androidx.core:core-splashscreen:1.0.0-alpha01'
mobileImplementation 'androidx.webkit:webkit:1.4.0'
mobileImplementation 'androidx.constraintlayout:constraintlayout:2.1.4'
mobileImplementation 'androidx.core:core-splashscreen:1.0.0'
mobileImplementation 'androidx.palette:palette-ktx:1.0.0'
mobileImplementation 'androidx.webkit:webkit:1.5.0'
mobileImplementation 'com.github.KieronQuinn:MonetCompat:0.4.1'
mobileImplementation 'com.github.marcoscgdev:Licenser:2.0.0'
mobileImplementation 'com.google.android.material:material:1.5.0-alpha03'
mobileImplementation 'com.google.android.material:material:1.8.0-alpha02'

nonFreeMobileImplementation fileTree(include: ['*.jar'], dir: 'libs')
nonFreeMobileImplementation 'com.google.android.play:core:1.10.1'
nonFreeMobileImplementation ('com.google.android.play:core-ktx:1.8.1') {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk7'
}
nonFreeMobileImplementation 'com.google.android.play:app-update-ktx:2.0.0'
nonFreeMobileImplementation 'com.google.android.play:review-ktx:2.0.0'
}
6 changes: 3 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="preferExternal"
package="com.parseus.codecinfo">
android:installLocation="preferExternal">

<uses-feature android:name="android.hardware.touchscreen" android:required="false" />

Expand All @@ -19,10 +18,11 @@
<!--suppress AndroidDomInspection -->
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:enableOnBackInvokedCallback="true"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:name="${appName}"
android:supportsRtl="true"
android:theme="@style/Theme.CodecInfo"
tools:ignore="MissingClass,RtlEnabled,UnusedAttribute">
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/assets/changelog.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
<html>
<body>

<h2>Version 2.4.0</h2>
<p>Added detecting features introduced in Android 13.</p>
<p>Improved detecting hardware acceleration for audio codecs.</p>
<p>Added more known codec issues.</p>
<p>Added a second database for known multimedia issues with devices regardless of a used codec.</p>
<p>AC3 codecs should now provide a correct max sampling rates also on older devices.</p>
<p>Fixed some video encoders under-reporting their 1080p/4K capabilities.</p>
<p>Dynamic theming can now be used on most Android 5.0+ devices.</p>
<p>Bugfixes and general improvements.</p>

<h2>Version 2.3.0</h2>
<p>Added detecting features introduced in Android 12.</p>
<p>Added optional dynamic theming on Android 12 and newer.</p>
Expand Down
Binary file modified app/src/main/ic_launcher-playstore.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.parseus.codecinfo.data.codecinfo

import android.annotation.SuppressLint
import android.content.Context
import android.media.CamcorderProfile
import android.media.MediaCodec
import android.media.MediaCodecInfo
import android.media.MediaCodecInfo.CodecCapabilities.*
Expand All @@ -21,6 +22,7 @@ import com.parseus.codecinfo.data.codecinfo.profilelevels.VP9Levels.*
import com.parseus.codecinfo.utils.*
import java.util.*
import kotlin.collections.ArrayList
import kotlin.math.min

// Source:
// https://android.googlesource.com/platform/frameworks/base/+/refs/heads/android10-release/media/java/android/media/MediaCodecInfo.java#1052
Expand All @@ -38,6 +40,9 @@ private const val DIVX6_1080P_MAX_FRAME_RATE = 30
private val DIVX4_MAX_RESOLUTION = intArrayOf(720, 576)
private val DIVX6_MAX_RESOLUTION = intArrayOf(1920, 1080)

// TODO: Find a good official source of the spec.
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"

Expand Down Expand Up @@ -122,7 +127,7 @@ fun getSimpleCodecInfoList(context: Context, isAudio: Boolean): MutableList<Code
val oldCodecInfos = Array(MediaCodecList.getCodecCount())
{ i -> MediaCodecList.getCodecInfoAt(i) }.filter { it.name.endsWith("secure") }
mediaCodecInfos += oldCodecInfos
} catch (e: Exception) {}
} catch (_: Exception) {}
}

if (SDK_INT in 22..25 && Build.DEVICE == "R9"
Expand All @@ -133,7 +138,7 @@ fun getSimpleCodecInfoList(context: Context, isAudio: Boolean): MutableList<Code
val rawMediaCodec = MediaCodec.createByCodecName(GOOGLE_RAW_DECODER)
//noinspection NewApi
mediaCodecInfos += rawMediaCodec.codecInfo
} catch (e: Exception) {}
} catch (_: Exception) {}
}

val showAliases = prefs.getBoolean("show_aliases", false)
Expand All @@ -160,6 +165,11 @@ fun getSimpleCodecInfoList(context: Context, isAudio: Boolean): MutableList<Code
return@forEachIndexed
}

if (codecId.startsWith("wfd")) {
// This type of video codecs can't be properly queried.
return@forEachIndexed
}

val isAudioCodec = mediaCodecInfo.isAudioCodec()

if (isAudio == isAudioCodec) {
Expand Down Expand Up @@ -266,6 +276,10 @@ fun getDetailedCodecInfo(context: Context, codecId: String, codecName: String):
if (SDK_INT >= 31) {
propertyList.addFeature(context, capabilities, FEATURE_QpBounds, R.string.qp_bounds)
}
if (SDK_INT >= 33) {
propertyList.addFeature(context, capabilities, FEATURE_EncodingStatistics, R.string.encoding_statistics)
propertyList.addFeature(context, capabilities, FEATURE_HdrEditing, R.string.hdr_editing)
}
}
}

Expand Down Expand Up @@ -463,10 +477,19 @@ private fun getAudioCapabilities(context: Context, codecId: String, codecName: S
}

else -> {
if (sampleRates[0].lower == sampleRates[0].upper) {
"${sampleRates[0].upper.toKiloHertz()} kHz"
var lower = sampleRates[0].lower
var upper = sampleRates[0].upper

// Some AC3 codecs, especially on older devices, provide maximum sample rate
// bigger than it's actually allowed by the spec.
if (codecId.endsWith("ac3")) {
lower = min(lower, AC3_MAX_SAMPLE_RATE)
upper = min(upper, AC3_MAX_SAMPLE_RATE)
}
if (lower == upper) {
"${upper.toKiloHertz()} kHz"
} else {
"${sampleRates[0].lower.toKiloHertz()}, ${sampleRates[0].upper.toKiloHertz()} kHz"
"${lower.toKiloHertz()} kHz \u2014 ${upper.toKiloHertz()} kHz"
}
}
}
Expand Down Expand Up @@ -510,7 +533,7 @@ private fun adjustMaxInputChannelCount(codecId: String, codecName: String, maxCh
if (mediaFormat.containsKey("max-channel-count")) {
return mediaFormat.getString("max-channel-count")!!.toInt()
}
} catch (e: Exception) {}
} catch (_: Exception) {}
}

if (codecId.endsWith("flac") || codecId.endsWith("alac")) {
Expand Down Expand Up @@ -642,6 +665,18 @@ private fun getMaxResolution(codecId: String, videoCapabilities: MediaCodecInfo.
val maxHeight = videoCapabilities.supportedHeights.upper
val defaultResolution = intArrayOf(maxWidth, maxHeight)

// Some devices (e.g. Samsung, Huawei, and Pixel 6) under-report their encoding
// 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.
if (maxHeight == 1072 && CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_1080P)) {
defaultResolution[0] = 1920
defaultResolution[1] = 1080
} else if (maxHeight == 2144 && CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_2160P)) {
defaultResolution[0] = 3840
defaultResolution[1] = 2160
}

return if (!areCapabilitiesUnknown(videoCapabilities)) {
defaultResolution
} else when {
Expand Down Expand Up @@ -772,6 +807,9 @@ private fun getProfileLevels(context: Context, codecId: String, codecName: Strin
level = H263Levels.from(it.level)
}
codecId.contains("hevc") || codecId.contains("heic") || codecId.contains("heif") -> {
if (needsHevc10BitProfileExcluded(codecId, it.profile)) {
return@forEach
}
profile = HEVCProfiles.from(it.profile)
level = HEVCLevels.from(it.level)
}
Expand Down Expand Up @@ -859,11 +897,7 @@ private fun getFormattedProfileLevelString(context: Context, profile: String?, p
else -> "${profile ?: unknownString} ($profileInt)"
}

val levelNameString = if (level != null) {
if (level.isNotEmpty()) level else ""
} else {
unknownString
}
val levelNameString = level?.ifEmpty { "" } ?: unknownString

return if (levelNameString.isNotEmpty()) {
val levelString = when (option) {
Expand Down Expand Up @@ -932,6 +966,11 @@ private fun isSoftwareOnly(codecInfo: MediaCodecInfo): Boolean {
return codecInfo.isSoftwareOnly
}

// Hardware audio decoders aren't really a thing, particularly on older devices.
if (codecInfo.isAudioCodec()) {
return true
}

val codecName = codecInfo.name.lowercase(Locale.ENGLISH)

// Broadcom codecs which specifically mention HW acceleration in their names
Expand Down Expand Up @@ -987,4 +1026,10 @@ private fun areCapabilitiesUnknown(videoCapabilities: MediaCodecInfo.VideoCapabi
return videoCapabilities.supportedFrameRates.upper == DEFAULT_MAX_FRAME_RATE
&& videoCapabilities.supportedWidths.upper == DEFAULT_MAX_SIZE
&& videoCapabilities.supportedHeights.upper == DEFAULT_MAX_SIZE
}

private fun needsHevc10BitProfileExcluded(codecId: String, profile: Int): Boolean {
// 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)
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ enum class StandardColorFormat(val value: Int) {
COLOR_FormatYVU422SemiPlanar(0x33),
COLOR_FormatYVU422PackedSemiPlanar(0x34),
COLOR_Format8bitBGR233(0x35),
COLOR_Format12bitBGR444(0x36),
COLOR_FormatYUVP010(0x36),
COLOR_Format16bitBGRA4444(0x37),
COLOR_Format16bitBGRA5551(0x38),
COLOR_Format18bitBGRA5661(0x39),
Expand All @@ -79,6 +79,8 @@ enum class StandardColorFormat(val value: Int) {
COLOR_FormatYUV422Flexible(0x7F422888),
COLOR_FormatYUV444Flexible(0x7F444888),
COLOR_FormatYUV444Y410(0x7F444AAA),
COLOR_Format32bitABGR2101010(0x7F00AAA2),
COLOR_Format64bitABGRFloat(0x7F000F16),

COLOR_QCOM_FormatYUV420SemiPlanar (0x7FA30C00),
COLOR_TI_FormatYUV420PackedSemiPlanar(0x7F000100),
Expand Down
Loading

0 comments on commit b9a489e

Please sign in to comment.