Media Enhancement API, donanım hızlandırmadan yararlanarak yüksek kaliteli medya iyileştirmeleri sunan, düşük gecikmeli, gizliliği korumaya yönelik ve cihaz üzerinde çalışan bir yapay zeka çözümü sağlar. Bu çözüm, APK boyutunu artırmaz. Daha fazla bilgi için Medya geliştirme özelliklerini anlama başlıklı makaleyi inceleyin.
Statik Bitmap modu (EnhancementMode.BITMAP), statik ve kodu çözülmüş görüntü işleme için tasarlanmıştır.
Bitmap modunda çalışmak için işletim sisteminin sıkıştırılmamış piksel verilerini seri hale getirmesi ve sistem yolu üzerinden CPU belleğinden GPU belleğine kopyalaması gerekir. İşlenmiş kare, ters kopya yoluyla döndürülür. Tek kareli yürütme için optimize edilmiştir ve gerçek zamanlı video akışıyla uyumlu değildir.
Bu iş akışı, oturum oluşturmayı, tek bir bit eşlemi oturumla işlemeyi ve ardından sonucu işlemeyi içerir. Önceki bölümlerdeki kod örnekleri bu kullanım alanını ayrıntılı olarak ele almaktadır.
- Seçenekleri yapılandırma:
EnhancementOptionsnesnesi oluşturun veenhancementModedeğerininEnhancementMode.BITMAPolarak ayarlandığından emin olun. - Oturum oluşturma:
createSessionAsyncsarmalayıcısını kullanarakEnhancementSessionoluşturun. Bu ağır bir nesne olduğundan yalnızca gerektiğinde oluşturun. - Resmi işleme: Oturumu, giriş bit eşleminizi ve istediğiniz seçenekleri çağırın.
- Sonucu işleme: Askıya alma işlevi, başarı durumunda yeni ve geliştirilmiş bir Bitmap döndürür veya hata durumunda istisna oluşturur.
- Oturumu serbest bırakma: GPU kaynaklarını boşaltmak için işiniz bittiğinde
session.release()işlevini çağırmanız çok önemlidir.
EnhancementSession, kalıcı bir GPU veya NPU bellek hattını koruyan ağır bir bağlam nesnesidir. Özel video RAM (VRAM) ve yerel sistem işleyicileri ayırır. Ciddi bellek sızıntılarını ve olası OutOfMemoryError kilitlenmelerini önlemek için aşağıdaki yaşam döngüsü ilkelerine uyun:
- Geç oluşturma: Kullanıcı bir geliştirme işlemi başlatana kadar oturum oluşturmayın.
- Stratejik yeniden kullanım: Aynı yapılandırmalara (boyutlar ve etkinleştirilen seçenekler) sahip birden fazla görüntü işlenirken tek bir oturum örneğini koruyun ve yeniden kullanın.
- İstem ayrıştırma: Paylaşılan donanım kaynaklarını boşaltmak için görsel görevler sonlandırıldığında
session.release()hemen çağrılır.
Geliştirme motorunu başlatma
Bu yöntem, iki adımlı bir kontrol gerçekleştirir. Cihazın donanımının hızlandırmayı destekleyip desteklemediğini doğrular ve ardından gerekli makine öğrenimi modüllerinin mevcut olduğundan emin olur.
Bu işlemi ön koşul adımı olarak çalıştırmak, uygulamanız medyayı işlemeye çalışmadan önce özellikleri doğrulayarak çalışma zamanı başlatma hatalarını önler.
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)
}
}
}
}
Oturum ve bit eşlem işlemi sarmalayıcıları oluşturma
Görev tabanlı istemci geri çağırmalarını standart askıya alma işlevlerine dönüştürmek için bu Kotlin coroutine sarmalayıcılarını kullanın. Böylece daha temiz ve sıralı bir yürütme sağlayabilirsiniz.
// 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)
}
Bit eşlem ardışık düzenini ViewModel içinde yürütme
Geliştirme ardışık düzenini uygulama mimarinize entegre etmek için oturum yaşam döngüsünü yönetmek üzere ViewModel kullanın. Bu yaklaşım, ViewModel temizlendiğinde yoğun GPU kaynaklarının serbest bırakılmasını sağlar.
// 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()
}
}