Media Enhancement API 提供低延遲、隱私權保護的裝置端 AI 解決方案,可運用硬體加速功能,以零 APK 膨脹率提供高品質的媒體改善功能。詳情請參閱「瞭解媒體強化功能」。
靜態 Bitmap 模式 (EnhancementMode.BITMAP) 適用於靜態、解碼的圖片處理作業。
在點陣圖模式下運作時,作業系統必須序列化未壓縮的像素資料,並從 CPU 記憶體透過系統匯流排複製到 GPU 記憶體,然後透過反向複製傳回處理過的影格。這項功能專為單一影格執行作業而設計,不支援即時影片串流。
這個工作流程包括建立工作階段、使用工作階段處理單一點陣圖,然後處理結果。前幾節的程式碼範例詳細說明瞭這個使用案例。
- 設定選項:建立
EnhancementOptions物件,並確保enhancementMode設為EnhancementMode.BITMAP。 - 建立工作階段:使用先前定義的
createSessionAsync包裝函式,建立EnhancementSession。這是重量級物件,因此請僅在需要時建立。 - 處理圖片:呼叫工作階段、輸入點陣圖,以及所需選項。
- 處理結果:暫停函式會在成功時傳回新的強化 Bitmap,失敗時則會擲回例外狀況。
- 釋出工作階段:完成後請務必呼叫
session.release(),釋出 GPU 資源。
EnhancementSession 是重量級的內容物件,可維護持續性的 GPU 或 NPU 記憶體管道。並分配專屬視訊 RAM (VRAM) 和原生系統控制代碼。為避免嚴重記憶體流失和潛在的OutOfMemoryError當機問題,請遵守下列生命週期原則:
- 延遲例項化:等到使用者啟動強化動作後,再建立工作階段。
- 策略性重複使用:處理多張設定相同的圖片 (尺寸和切換選項) 時,請維護並重複使用單一工作階段例項。
- 提示拆解:在視覺工作終止時立即叫用
session.release(),釋放共用硬體資源。
初始化強化引擎
這個方法會協調兩步驟檢查。這項功能會驗證裝置的硬體是否支援加速,然後確保有必要的機器學習模組。
執行這項必要步驟,可在應用程式嘗試處理媒體前驗證功能,避免發生執行階段初始化失敗的問題。
class MediaSetupViewModel(application: Application) : AndroidViewModel(application) {
private val enhancementClient = Enhancement.getClient(application)
fun initializeEnhancementEngine() {
viewModelScope.launch {
try {
// 1. Verify hardware capability
val isSupported = enhancementClient.isDeviceSupportedAsync()
if (!isSupported) {
notifyUiDeviceIncompatible()
return@launch
}
// 2. Verify and download the Google Play services ML modules
val isInstalled = enhancementClient.isModuleInstalledAsync()
if (!isInstalled) {
notifyUiDownloadingModels()
enhancementClient.installModule().await()
}
notifyUiEngineReady()
} catch (e: Exception) {
// Handle potential errors during session creation or image processing.
handleInitializationError(e)
}
}
}
}
建立工作階段和點陣圖程序包裝函式
使用這些 Kotlin 協同程式包裝函式,將以工作為基礎的用戶端回呼轉換為標準暫停函式,以便更簡潔地循序執行。
// Wraps the task-based createSession callback into a suspending function.
suspend fun EnhancementClient.createSessionAsync(
options: EnhancementOptions,
executor: Executor
): EnhancementSession = withContext(Dispatchers.Main) {
suspendCancellableCoroutine { continuation ->
// EnhancementSessionCallback handles session success or failure.
val callback = object : EnhancementSessionCallback {
override fun onSessionCreated(session: EnhancementSession) {
continuation.resume(session)
}
override fun onSessionCreationFailed(status: Status) {
continuation.resumeWithException(
Exception("Session creation failed: ${status.statusMessage} (${status.statusCode})")
)
}
override fun onSessionDestroyed() {}
override fun onSessionDisconnected(status: Status) {}
}
// Handles errors during the initial request trigger.
this.createSession(options, callback).addOnFailureListener(executor) { e ->
if (continuation.isActive) {
continuation.resumeWithException(e)
}
}
}
}
// Wraps this process in a suspending function for cleaner execution.
suspend fun EnhancementSession.processBitmapAsync(
bitmap: Bitmap,
options: EnhancementOptions
): Bitmap = suspendCancellableCoroutine { continuation ->
// EnhancementCallback returns the processed bitmap or an error code.
val callback = object : EnhancementCallback {
override fun onBitmapProcessed(enhancedBitmap: Bitmap) {
continuation.resume(enhancedBitmap)
}
override fun onError(statusCode: Int) {
continuation.resumeWithException(
Exception("Bitmap processing failed with status code: $statusCode")
)
}
override fun onSurfaceProcessed(timestamp: Long) {}
}
this.process(bitmap, options, callback)
}
在 ViewModel 中執行點陣圖管道
如要將強化管道整合至應用程式架構,請使用 ViewModel 管理工作階段生命週期。這麼做可確保在清除 ViewModel 時,系統會釋出大量 GPU 資源。
// Define a data class to hold image information.
data class ImageInfo(val bitmap: Bitmap)
// Define a UI state class to hold loading status, errors, and enhanced image.
data class EnhancementUiState(
val isLoading: Boolean = false,
val enhancementError: String? = null,
val enhancedImage: ImageInfo? = null
)
class EnhancementViewModel(application: Application) : AndroidViewModel(application) {
// Backing field for UI state, initialized with default values.
private val _uiState = MutableStateFlow(EnhancementUiState())
// Publicly exposed UI state flow for observation.
val uiState: StateFlow<EnhancementUiState> = _uiState.asStateFlow()
// Initialize client to interact with the Media Enhancement service.
private val enhancementClient: EnhancementClient = Enhancement.getClient(application)
// Single-thread executor for processing background enhancement tasks.
private val enhancementExecutor = Executors.newSingleThreadExecutor()
// Track session state to enable reuse across multiple processing calls.
private var enhancementSession: EnhancementSession? = null
// Primary function to trigger the enhancement workflow for a provided bitmap.
fun enhanceImage(bitmap: Bitmap) {
viewModelScope.launch(Dispatchers.IO) {
_uiState.update { it.copy(isLoading = true, enhancementError = null) }
try {
// 1. Establish the session lazily on demand
// Define enhancement options (for example, enable upscale, tonemapping) based
// on bitmap dimensions.
if (enhancementSession == null) {
val options = EnhancementOptions(
bitmap.width,
bitmap.height,
EnhancementMode.BITMAP,
enableTonemap = true,
enableDeblurDenoise = true,
enableDenoiseOnly = false,
enableUpscale = false,
)
enhancementSession = enhancementClient.createSessionAsync(options, enhancementExecutor)
}
val session = enhancementSession ?: throw IllegalStateException("Session unavailable.")
// 2. Dispatch image through the neural pipeline
val enhancedBitmap = session.processBitmapAsync(bitmap, session.defaultOptions)
// 3. Render output to UI
_uiState.update {
it.copy(enhancedImage = ImageInfo(bitmap = enhancedBitmap))
}
} catch (e: Exception) {
_uiState.update { it.copy(enhancementError = e.message) }
} finally {
// Ensure loading state is reset regardless of the outcome.
_uiState.update { it.copy(isLoading = false) }
}
}
}
override fun onCleared() {
// 4. Critical: Release native GPU hardware resources
enhancementSession?.release()
enhancementSession = null
enhancementExecutor.shutdown()
super.onCleared()
}
}