diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4a2e9d7..8dc491e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -14,8 +14,8 @@ android { applicationId = "compress.joshattic.us" minSdk = 24 targetSdk = 36 - versionCode = 16 - versionName = "1.5.1" + versionCode = 17 + versionName = "1.5.1 (Experimental, google-pixel-10-fix branch)" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/compress/joshattic/us/CompressorViewModel.kt b/app/src/main/java/compress/joshattic/us/CompressorViewModel.kt index 4ff16e3..6a84b5e 100644 --- a/app/src/main/java/compress/joshattic/us/CompressorViewModel.kt +++ b/app/src/main/java/compress/joshattic/us/CompressorViewModel.kt @@ -76,13 +76,14 @@ data class CompressorUiState( val totalSavedBytes: Long = 0L, val supportedCodecs: List = emptyList(), - val appInfoVersion: String = "1.5.1", + val appInfoVersion: String = "1.5.1 (Experimental, google-pixel-10-fix branch)", val showBitrate: Boolean = false, val useMbps: Boolean = false, val hasShared: Boolean = false, val removeAudio: Boolean = false, val audioBitrate: Int = 128_000, - val audioVolume: Float = 1.0f + val audioVolume: Float = 1.0f, + val warnings: List = emptyList() ) { private val minBitrate: Long get() { @@ -660,7 +661,7 @@ class CompressorViewModel(application: Application) : AndroidViewModel(applicati val currentState = _uiState.value val inputUri = currentState.selectedUri ?: return - _uiState.update { it.copy(isCompressing = true, progress = 0f, currentOutputSize = 0L, error = null, errorLog = null, compressedUri = null, saveSuccess = false) } + _uiState.update { it.copy(isCompressing = true, progress = 0f, currentOutputSize = 0L, error = null, errorLog = null, compressedUri = null, saveSuccess = false, warnings = emptyList()) } val outputDir = File(context.cacheDir, "compressed_videos") outputDir.mkdirs() @@ -692,7 +693,7 @@ class CompressorViewModel(application: Application) : AndroidViewModel(applicati ) .build() - val transformer = Transformer.Builder(context) + val transformerBuilder = Transformer.Builder(context) .setVideoMimeType(videoMimeType) .setEncoderFactory(encoderFactory) .addListener(object : Transformer.Listener { @@ -739,7 +740,8 @@ class CompressorViewModel(application: Application) : AndroidViewModel(applicati } } }) - .build() + + val transformer = transformerBuilder.build() activeTransformer = transformer @@ -769,9 +771,25 @@ class CompressorViewModel(application: Application) : AndroidViewModel(applicati .setRemoveAudio(currentState.removeAudio) .build() + var hdrMode = Composition.HDR_MODE_KEEP_HDR + // this is certainly a workaround ever, a workaround so horrific, it would be enough to stop me from getting through the pearly gates + // also google's fault, womp womp, can google stop being absolute garbage at anything related to the gpus + // me, a pixel 8 pro user, laughing at pixel 10 users because the gpu on the tensor g5 is 56% slower than the g3 :skull: + if (Build.MANUFACTURER.equals("Google", ignoreCase = true) && Build.MODEL.contains("Pixel 10")) { + if (videoMimeType == MimeTypes.VIDEO_H265 || videoMimeType == MimeTypes.VIDEO_H264) { + if (isHdr(context, inputUri)) { + hdrMode = Composition.HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL + val warningMsg = getApplication().getString(R.string.warning_hdr_tone_mapped) + _uiState.update { it.copy(warnings = listOf(warningMsg)) } + } + } + } + val composition = Composition.Builder( listOf(EditedMediaItemSequence(editedMediaItem)) - ).build() + ) + .setHdrMode(hdrMode) + .build() transformer.start(composition, outputPath) @@ -809,6 +827,24 @@ class CompressorViewModel(application: Application) : AndroidViewModel(applicati return 0 } + private fun isHdr(context: Context, uri: Uri): Boolean { + val retriever = android.media.MediaMetadataRetriever() + try { + retriever.setDataSource(context, uri) + // METADATA_KEY_COLOR_TRANSFER (36) is available on API 24+ + if (Build.VERSION.SDK_INT >= 24) { + val transfer = retriever.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_COLOR_TRANSFER) + // 6 = ST2084 (PQ), 7 = HLG + return transfer == "6" || transfer == "7" + } + } catch (e: Exception) { + e.printStackTrace() + } finally { + try { retriever.release() } catch(e: Exception) {} + } + return false + } + fun saveToUri(context: Context, targetUri: Uri) { val currentState = _uiState.value val compressedUri = currentState.compressedUri ?: return diff --git a/app/src/main/java/compress/joshattic/us/MainActivity.kt b/app/src/main/java/compress/joshattic/us/MainActivity.kt index 3c93a82..e7a6309 100644 --- a/app/src/main/java/compress/joshattic/us/MainActivity.kt +++ b/app/src/main/java/compress/joshattic/us/MainActivity.kt @@ -569,6 +569,44 @@ fun ResultScreen( fontWeight = FontWeight.Bold ) } + + if (state.warnings.isNotEmpty()) { + Spacer(modifier = Modifier.height(16.dp)) + var showWarningDialog by remember { mutableStateOf(false) } + + OutlinedButton( + onClick = { showWarningDialog = true }, + colors = ButtonDefaults.outlinedButtonColors( + contentColor = MaterialTheme.colorScheme.error + ), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.error) + ) { + Icon(Icons.Outlined.Warning, contentDescription = null) + Spacer(modifier = Modifier.width(8.dp)) + Text("${state.warnings.size} Warning${if (state.warnings.size > 1) "s" else ""} - Tap for Details") + } + + if (showWarningDialog) { + AlertDialog( + onDismissRequest = { showWarningDialog = false }, + icon = { Icon(Icons.Outlined.Warning, contentDescription = null, tint = MaterialTheme.colorScheme.error) }, + title = { Text(stringResource(R.string.warning_details)) }, + text = { + Column { + state.warnings.forEach { warning -> + Text("• $warning", style = MaterialTheme.typography.bodyMedium) + Spacer(modifier = Modifier.height(8.dp)) + } + } + }, + confirmButton = { + TextButton(onClick = { showWarningDialog = false }) { + Text(stringResource(R.string.dismiss)) + } + } + ) + } + } Spacer(modifier = Modifier.height(48.dp)) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index d2003d1..881f2e1 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -92,4 +92,9 @@ Fehlerdetails Protokolle kopieren Issue Tracker öffnen + + HDR-Video wurde in SDR umgewandelt, um Encoder-Kompatibilitätsprobleme auf diesem Gerät zu vermeiden. Verwenden Sie AV1, wenn Sie HDR beibehalten möchten. + Warnungsdetails + Schließen + \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 5389c16..b7d5eff 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -78,4 +78,9 @@ Detalles del Error Copiar Registros Abrir Rastreador de Problemas + + El video HDR se convirtió a SDR para evitar problemas de compatibilidad del codificador en este dispositivo. Usa AV1 si necesitas mantener HDR. + Detalles de advertencia + Descartar + \ No newline at end of file diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 75cb150..8e0a533 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -103,4 +103,9 @@ エラーの詳細 ログをコピー 課題トラッカーを開く + + このデバイスでのエンコーダー互換性の問題を回避するため、HDRビデオはSDRにトーンマッピングされました。HDRを維持する必要がある場合は、AV1を使用してください。 + 警告の詳細 + 閉じる + \ No newline at end of file diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 224d66e..a768108 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -92,4 +92,9 @@ 오류 세부 정보 로그 복사 이슈 트래커 열기 + + 이 장치에서 인코더 호환성 문제를 방지하기 위해 HDR 비디오가 SDR로 톤 매핑되었습니다. HDR을 보존하려면 AV1을 사용하십시오. + 경고 세부 정보 + 닫기 + \ No newline at end of file diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 4ddef56..da9bf6c 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -76,4 +76,9 @@ Detalhes do Erro Copiar Logs Abrir Rastreador de Problemas + + O vídeo HDR foi convertido para SDR para evitar problemas de compatibilidade do codificador neste dispositivo. Use AV1 se precisar preservar o HDR. + Detalhes do aviso + Dispensar + \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 50ab100..d9cb63b 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -90,4 +90,9 @@ Детали ошибки Копировать логи Открыть трекер задач + + HDR-видео было преобразовано в SDR, чтобы избежать проблем с кодировщиком на этом устройстве. Используйте AV1, если нужно сохранить HDR. + Детали предупреждения + Закрыть + \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index cf46fd8..9724f63 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -92,4 +92,9 @@ 错误详情 复制日志 打开问题追踪器 + + HDR 视频已转换为 SDR,以避免此设备上的编码器兼容性问题。如需保留 HDR,请使用 AV1。 + 警告详情 + 关闭 + \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 98decc2..8669f0b 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -76,4 +76,9 @@ 錯誤詳情 複製日誌 打開問題追蹤器 + + HDR 影片已轉換為 SDR,以避免此裝置上的編碼器相容性問題。如需保留 HDR,請使用 AV1。 + 警告詳情 + 關閉 + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 53e7653..a992e5f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -48,6 +48,10 @@ 60fps 30fps Start Compression + HDR video was tone-mapped to SDR to avoid encoder compatibility issues on this device. Use AV1 if you need to preserve HDR. + Warning Details + Dismiss + Error: %1$s Select a video to compress Add Video