Media Enhancement API menyediakan solusi AI di perangkat yang hemat latensi, menjaga privasi, dan memanfaatkan akselerasi hardware untuk memberikan peningkatan kualitas media yang tinggi tanpa pembengkakan APK. Untuk mengetahui informasi selengkapnya, lihat Memahami kemampuan peningkatan kualitas media.
Mode Bitmap statis (EnhancementMode.BITMAP) dirancang untuk pemrosesan gambar statis yang didekode.
Beroperasi dalam mode Bitmap mengharuskan OS menserialisasi data piksel yang tidak dikompresi dan menyalinnya dari memori CPU melalui bus sistem ke memori GPU, lalu menampilkan frame yang diproses melalui salinan terbalik. API ini dioptimalkan untuk eksekusi frame tunggal dan tidak kompatibel dengan streaming video real-time.
Alur kerja ini melibatkan pembuatan sesi, pemrosesan satu bitmap dengannya, lalu penanganan hasilnya. Contoh kode dari bagian sebelumnya membahas kasus penggunaan ini secara mendetail.
- Mengonfigurasi opsi: Buat objek
EnhancementOptions, pastikanenhancementModedisetel keEnhancementMode.BITMAP. - Buat sesi: Gunakan wrapper
createSessionAsyncyang kita tentukan sebelumnya untuk membuatEnhancementSession. Objek ini adalah objek yang berat, jadi buatlah hanya jika diperlukan. - Proses gambar: Panggil sesi, bitmap input, dan opsi yang Anda inginkan.
- Tangani hasil: Fungsi penangguhan menampilkan Bitmap baru yang ditingkatkan saat berhasil atau menampilkan pengecualian saat gagal.
- Lepaskan sesi: Yang penting, panggil
session.release()setelah Anda selesai untuk membebaskan resource GPU.
EnhancementSession adalah objek konteks berat yang mempertahankan pipeline memori GPU atau NPU yang persisten. Hal ini mengalokasikan RAM video (VRAM) khusus
dan menangani sistem native. Untuk mencegah kebocoran memori parah dan potensi error OutOfMemoryError, patuhi prinsip siklus proses berikut:
- Instansiasi lambat: Jangan membuat sesi hingga pengguna memulai tindakan peningkatan.
- Penggunaan ulang strategis: Pertahankan dan gunakan kembali satu instance sesi saat memproses beberapa gambar dengan konfigurasi yang identik (dimensi dan opsi yang diaktifkan).
- Penguraian perintah: Panggil
session.release()segera saat tugas visual berakhir untuk membebaskan resource hardware bersama.
Melakukan inisialisasi mesin peningkatan
Metode ini mengatur pemeriksaan dua langkah. Fitur ini memverifikasi apakah hardware perangkat mendukung akselerasi, lalu memastikan modul machine learning yang diperlukan ada.
Menjalankan ini sebagai langkah prasyarat mencegah kegagalan inisialisasi runtime dengan memvalidasi kemampuan sebelum aplikasi Anda mencoba memproses media.
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)
}
}
}
}
Membuat wrapper proses bitmap dan sesi
Gunakan wrapper coroutine Kotlin ini untuk mengonversi callback klien berbasis tugas menjadi fungsi penangguhan standar, sehingga memungkinkan eksekusi yang lebih bersih dan berurutan.
// 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)
}
Jalankan pipeline bitmap di ViewModel
Untuk mengintegrasikan pipeline peningkatan ke dalam arsitektur aplikasi Anda, gunakan
ViewModel untuk mengelola siklus proses sesi. Pendekatan ini memastikan bahwa resource GPU yang berat dilepaskan saat ViewModel dihapus.
// 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()
}
}