Media Enhancement API cung cấp một giải pháp AI có độ trễ thấp, bảo đảm quyền riêng tư và trên thiết bị, tận dụng tính năng tăng tốc phần cứng để mang lại những cải tiến chất lượng cao cho nội dung nghe nhìn mà không làm tăng kích thước APK. Để biết thêm thông tin, hãy xem bài viết Tìm hiểu các tính năng nâng cao nội dung nghe nhìn.
Chế độ Bitmap tĩnh (EnhancementMode.BITMAP) được thiết kế để xử lý hình ảnh tĩnh đã giải mã.
Khi hoạt động ở chế độ Bitmap, hệ điều hành cần chuyển đổi tuần tự dữ liệu pixel chưa nén và sao chép dữ liệu đó từ bộ nhớ CPU qua bus hệ thống sang bộ nhớ GPU, trả về khung hình đã xử lý thông qua một bản sao ngược. Thư viện này được tối ưu hoá để thực thi một khung hình và không tương thích với tính năng phát trực tiếp video theo thời gian thực.
Quy trình này bao gồm việc tạo một phiên, xử lý một bitmap bằng phiên đó, rồi xử lý kết quả. Các ví dụ về mã trong các phần trước đề cập chi tiết đến trường hợp sử dụng này.
- Định cấu hình các lựa chọn: Tạo một đối tượng
EnhancementOptions, đảm bảo rằngenhancementModeđược đặt thànhEnhancementMode.BITMAP. - Tạo phiên: Sử dụng trình bao bọc
createSessionAsyncmà chúng ta đã xác định trước đó để tạoEnhancementSession. Đây là một đối tượng có kích thước lớn, vì vậy, bạn chỉ nên tạo đối tượng này khi cần. - Xử lý hình ảnh: Gọi phiên, bitmap đầu vào và các lựa chọn bạn muốn.
- Xử lý kết quả: Hàm tạm ngưng sẽ trả về một Bitmap mới, nâng cao khi thành công hoặc gửi một ngoại lệ khi không thành công.
- Giải phóng phiên: Điều quan trọng là bạn phải gọi
session.release()khi hoàn tất để giải phóng tài nguyên GPU.
EnhancementSession là một đối tượng bối cảnh có dung lượng lớn, duy trì một quy trình bộ nhớ GPU hoặc NPU liên tục. Nó phân bổ RAM video (VRAM) chuyên dụng và các trình xử lý hệ thống gốc. Để ngăn chặn tình trạng rò rỉ bộ nhớ nghiêm trọng và sự cố OutOfMemoryError tiềm ẩn, hãy tuân thủ các nguyên tắc sau về vòng đời:
- Khởi tạo trễ: Không tạo phiên cho đến khi người dùng bắt đầu một thao tác nâng cao.
- Sử dụng lại một cách chiến lược: Duy trì và sử dụng lại một phiên bản phiên duy nhất khi xử lý nhiều hình ảnh có cấu hình giống hệt nhau (kích thước và các lựa chọn được bật/tắt).
- Phân tích cú pháp câu lệnh: Gọi
session.release()ngay khi các tác vụ trực quan kết thúc để giải phóng tài nguyên phần cứng dùng chung.
Khởi chạy công cụ nâng cao
Phương thức này điều phối quy trình kiểm tra gồm hai bước. Thư viện này xác minh xem phần cứng của thiết bị có hỗ trợ tính năng tăng tốc hay không, sau đó đảm bảo có các mô-đun học máy cần thiết.
Việc chạy bước này như một bước tiên quyết sẽ ngăn chặn lỗi khởi tạo thời gian chạy bằng cách xác thực các chức năng trước khi ứng dụng của bạn cố gắng xử lý nội dung nghe nhìn.
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)
}
}
}
}
Tạo trình bao bọc quy trình phiên và bitmap
Sử dụng các trình bao bọc coroutine Kotlin này để chuyển đổi lệnh gọi lại của ứng dụng dựa trên tác vụ thành các hàm tạm ngưng tiêu chuẩn, cho phép thực thi rõ ràng và tuần tự hơn.
// 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)
}
Thực thi quy trình bitmap trong ViewModel
Để tích hợp quy trình nâng cao vào cấu trúc ứng dụng, hãy sử dụng ViewModel để quản lý vòng đời của phiên. Phương pháp này đảm bảo rằng các tài nguyên GPU có dung lượng lớn sẽ được giải phóng khi ViewModel bị xoá.
// 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()
}
}