فهم دورة حياة تحسين الوسائط في "وضع الصورة النقطية"

توفّر واجهة برمجة التطبيقات Media Enhancement API حلاً منخفض وقت الاستجابة ومحافظًا على الخصوصية ومستندًا إلى الذكاء الاصطناعي على الجهاز فقط، ويستفيد من تسريع الأجهزة لتقديم تحسينات عالية الجودة على الوسائط بدون أي تضخّم في حِزم APK. لمزيد من المعلومات، يُرجى الاطّلاع على التعرّف على إمكانات تحسين الوسائط.

تم تصميم وضع Bitmap الثابت (EnhancementMode.BITMAP) لمعالجة الصور الثابتة التي تم فك ترميزها.

يتطلّب التشغيل في وضع Bitmap أن يقوم نظام التشغيل بتسلسل بيانات البكسل غير المضغوطة ونسخها من ذاكرة وحدة المعالجة المركزية (CPU) عبر ناقل النظام إلى ذاكرة وحدة معالجة الرسومات (GPU)، ثم إعادة الإطار المعالج من خلال نسخة عكسية. تم تحسين هذا التطبيق لتنفيذ إطار واحد، وهو غير متوافق مع بث الفيديو في الوقت الفعلي.

يتضمّن سير العمل هذا إنشاء جلسة ومعالجة صورة نقطية واحدة باستخدامها، ثم التعامل مع النتيجة. تتضمّن أمثلة الرموز البرمجية من الأقسام السابقة شرحًا تفصيليًا لحالة الاستخدام هذه.

  1. ضبط الخيارات: أنشئ عنصر EnhancementOptions، وتأكَّد من ضبط enhancementMode على EnhancementMode.BITMAP.
  2. إنشاء جلسة: استخدِم برنامج تضمين createSessionAsync الذي حدّدناه سابقًا لإنشاء EnhancementSession. هذا كائن كبير الحجم، لذا لا تنشئه إلا عند الحاجة.
  3. معالجة الصورة: استدعِ الجلسة والصورة النقطية التي أدخلتها والخيارات التي تريدها.
  4. التعامل مع النتيجة: تعرض دالة التعليق المؤقت صورة نقطية جديدة ومحسّنة عند النجاح، أو تطرح استثناءً عند حدوث خطأ.
  5. تحرير الجلسة: من المهم جدًا استدعاء session.release() عند الانتهاء من استخدام وحدة معالجة الرسومات لتحرير مواردها.

EnhancementSession هو عنصر سياق كبير الحجم يحافظ على مسار ذاكرة مستمر لوحدة معالجة الرسومات أو وحدة المعالجة العصبية. ويخصّص ذاكرة وصول عشوائي للفيديو (VRAM) ومقابض نظام أصلية. لتجنُّب حدوث تسرُّبات كبيرة في الذاكرة وتعطُّل محتمل في OutOfMemoryError، يجب الالتزام بمبادئ دورة الحياة التالية:

  1. إنشاء مثيل عند الطلب: لا تنشئ جلسة إلا عندما يتّخذ المستخدم إجراءً لتحسين الأداء.
  2. إعادة الاستخدام الاستراتيجي: احتفِظ بنسخة واحدة من الجلسة وأعِد استخدامها عند معالجة صور متعدّدة بإعدادات متطابقة (الأبعاد والخيارات المفعّلة).
  3. تحليل الطلب: استدعِ 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 لإدارة مراحل نشاط الجلسة. يضمن هذا النهج إتاحة موارد وحدة معالجة الرسومات (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()
    }
}