Media Enhancement API มีโซลูชัน AI ในอุปกรณ์ที่มีเวลาในการตอบสนองต่ำ รักษาความเป็นส่วนตัว ซึ่งใช้ประโยชน์จากการเร่งฮาร์ดแวร์เพื่อปรับปรุงสื่อคุณภาพสูง โดยไม่มีการขยายขนาด APK ดูข้อมูลเพิ่มเติมได้ที่ทำความเข้าใจ ความสามารถในการปรับปรุงสื่อ
โหมดบิตแมปแบบคงที่ (EnhancementMode.BITMAP) ออกแบบมาสําหรับการประมวลผลรูปภาพแบบคงที่ที่ถอดรหัสแล้ว
การทำงานในโหมดบิตแมปกำหนดให้ระบบปฏิบัติการต้องจัดลำดับข้อมูลพิกเซลที่ไม่ได้บีบอัด และคัดลอกจากหน่วยความจำ CPU ผ่านบัสของระบบไปยังหน่วยความจำ GPU แล้วส่งคืน เฟรมที่ประมวลผลแล้วผ่านการคัดลอกย้อนกลับ โดยได้รับการเพิ่มประสิทธิภาพสำหรับการดำเนินการแบบเฟรมเดียว และไม่รองรับการสตรีมวิดีโอแบบเรียลไทม์
เวิร์กโฟลว์นี้เกี่ยวข้องกับการสร้างเซสชัน การประมวลผลบิตแมปเดียวด้วยเซสชันนั้น แล้วจึงจัดการผลลัพธ์ ตัวอย่างโค้ดจากส่วนก่อนหน้าจะครอบคลุมกรณีการใช้งานนี้โดยละเอียด
- กำหนดค่าตัวเลือก: สร้างออบเจ็กต์
EnhancementOptionsโดยตรวจสอบว่าได้ตั้งค่าenhancementModeเป็นEnhancementMode.BITMAPแล้ว - สร้างเซสชัน: ใช้ Wrapper
createSessionAsyncที่เรากำหนดไว้ก่อนหน้านี้ เพื่อสร้างEnhancementSessionออบเจ็กต์นี้มีขนาดใหญ่ ดังนั้นให้สร้างเมื่อจำเป็นเท่านั้น - ประมวลผลรูปภาพ: เรียกเซสชัน บิตแมปอินพุต และตัวเลือก ที่ต้องการ
- จัดการผลลัพธ์: ฟังก์ชันระงับจะแสดงผลบิตแมปใหม่ที่ได้รับการปรับปรุงเมื่อสำเร็จ หรือส่งข้อยกเว้นเมื่อไม่สำเร็จ
- ปล่อยเซสชัน: สิ่งสำคัญคือให้เรียกใช้
session.release()เมื่อคุณ ทำงานเสร็จแล้วเพื่อเพิ่มพื้นที่ว่างสำหรับทรัพยากร GPU
EnhancementSession เป็นออบเจ็กต์บริบทที่มีน้ำหนักมากซึ่งรักษาไปป์ไลน์หน่วยความจำ GPU หรือ NPU ที่ต่อเนื่อง โดยจะจัดสรร RAM วิดีโอ (VRAM) เฉพาะ
และแฮนเดิลระบบเนทีฟ โปรดปฏิบัติตามหลักการวงจรต่อไปนี้เพื่อป้องกันการรั่วไหลของหน่วยความจำอย่างรุนแรงและ
OutOfMemoryErrorการขัดข้องที่อาจเกิดขึ้น
- การเริ่มต้นใช้งานแบบเลซี่: อย่าสร้างเซสชันจนกว่าผู้ใช้จะเริ่มดำเนินการปรับปรุง
- การนำกลับมาใช้ใหม่เชิงกลยุทธ์: รักษาและนำอินสแตนซ์เซสชันเดียวกลับมาใช้ใหม่เมื่อ ประมวลผลรูปภาพหลายรูปที่มีการกำหนดค่าเหมือนกัน (ขนาดและ ตัวเลือกที่สลับ)
- การหยุดทำงานของพรอมต์: เรียกใช้
session.release()ทันทีเมื่องานที่มองเห็นได้ สิ้นสุดลงเพื่อเพิ่มพื้นที่ว่างให้กับทรัพยากรฮาร์ดแวร์ที่ใช้ร่วมกัน
เริ่มต้นเครื่องมือเพิ่มประสิทธิภาพ
วิธีนี้จะจัดระเบียบการตรวจสอบ 2 ขั้นตอน โดยจะตรวจสอบว่าฮาร์ดแวร์ของอุปกรณ์ รองรับการเร่งความเร็วหรือไม่ จากนั้นจะตรวจสอบว่ามีโมดูลแมชชีนเลิร์นนิงที่จำเป็น อยู่หรือไม่
การเรียกใช้ขั้นตอนนี้เป็นข้อกำหนดเบื้องต้นจะช่วยป้องกันไม่ให้การเริ่มต้นรันไทม์ล้มเหลวโดยการตรวจสอบความสามารถก่อนที่แอปจะพยายามประมวลผลสื่อ
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)
}
}
}
}
สร้าง Wrapper ของกระบวนการเซสชันและบิตแมป
ใช้ Wrapper ของ Kotlin Coroutine เหล่านี้เพื่อแปลงการเรียกกลับของไคลเอ็นต์ที่อิงตามงานเป็น ฟังก์ชันระงับมาตรฐาน ซึ่งช่วยให้การดำเนินการเป็นไปอย่างราบรื่นและต่อเนื่อง
// 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 เพื่อจัดการวงจรเซสชัน วิธีนี้ช่วยให้มั่นใจได้ว่าระบบจะปล่อยทรัพยากร GPU ที่มี
การใช้งานสูงเมื่อล้าง ViewModel
// 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()
}
}