رمزگذاری رسانه سازگار

در اندروید ۱۲ (سطح API 31) و بالاتر، سیستم می‌تواند به‌طور خودکار ویدیوهای ضبط‌شده با فرمت‌هایی مانند HEVC (H.265) را به AVC (H.264) تبدیل کند، زمانی که ویدیوها توسط برنامه‌ای که از HEVC پشتیبانی نمی‌کند باز می‌شوند. این ویژگی به برنامه‌های ضبط ویدیو اجازه می‌دهد تا از رمزگذاری مدرن‌تر و کم‌مصرف‌تر برای ویدیوهای ضبط‌شده در دستگاه استفاده کنند، بدون اینکه سازگاری با سایر برنامه‌ها را از دست بدهند.

فرمت‌های زیر می‌توانند به طور خودکار برای محتوایی که روی دستگاه ایجاد می‌شوند، تبدیل کد شوند:

قالب رسانه ویژگی XML نوع مایم MediaFormat
اچ‌ای‌وی‌سی (اچ.۲۶۵) اچ‌ای‌وی‌سی MediaFormat.MIMETYPE_VIDEO_HEVC
اچ‌دی‌آر۱۰ اچ‌دی‌آر۱۰ ویژگی رسانه.نوع HDR.HDR10
اچ‌دی‌آر۱۰+ HDR10Plus ویژگی رسانه.نوع HDR.HDR10_PLUS

اندروید فرض می‌کند که برنامه‌ها می‌توانند از پخش همه فرمت‌های رسانه‌ای پشتیبانی کنند، بنابراین تبدیل فرمت سازگار با رسانه به طور پیش‌فرض غیرفعال است.

چه زمانی از ترانس‌کدینگ استفاده کنیم؟

تبدیل کد یک عملیات محاسباتی پرهزینه است و هنگام باز کردن یک فایل ویدیویی، تأخیر قابل توجهی ایجاد می‌کند. به عنوان مثال، تبدیل یک فایل ویدیویی یک دقیقه‌ای HEVC به AVC در تلفن Pixel 3 تقریباً 20 ثانیه طول می‌کشد. به همین دلیل، شما باید فقط زمانی که فایل ویدیویی را از دستگاه ارسال می‌کنید، آن را تبدیل کد کنید. به عنوان مثال، هنگام اشتراک‌گذاری یک فایل ویدیویی با سایر کاربران همان برنامه یا یک سرور ابری که از فرمت‌های ویدیویی مدرن پشتیبانی نمی‌کند.

هنگام باز کردن فایل‌های ویدیویی برای پخش در دستگاه یا برای ایجاد تصاویر کوچک، کد را تغییر ندهید.

پیکربندی کدگذاری

برنامه‌ها می‌توانند با اعلام قابلیت‌های رسانه‌ای خود، رفتار تبدیل کد خود را کنترل کنند. دو راه برای اعلام این قابلیت‌ها وجود دارد: در کد یا در یک منبع.

قابلیت‌ها را در کد اعلام کنید

شما می‌توانید با ساخت یک نمونه از شیء ApplicationMediaCapabilities با استفاده از یک سازنده، قابلیت‌های رسانه را در کد اعلام کنید:

کاتلین

val mediaCapabilities = ApplicationMediaCapabilities.Builder()
    .addSupportedVideoMimeType(MediaFormat.MIMETYPE_VIDEO_HEVC)
    .addUnsupportedHdrType(MediaFeature.HdrType.HDR10)
    .addUnsupportedHdrType(MediaFeature.HdrType.HDR10_PLUS)
    .build()

جاوا

ApplicationMediaCapabilities mediaCapabilities = new ApplicationMediaCapabilities.Builder()
        .addSupportedVideoMimeType(MediaFormat.MIMETYPE_VIDEO_HEVC)
        .addUnsupportedHdrType(MediaFeature.HdrType.HDR10)
        .addUnsupportedHdrType(MediaFeature.HdrType.HDR10_PLUS)
        .build();

از این شیء هنگام دسترسی به محتوای رسانه از طریق متدهایی مانند ContentResolver#openTypedAssetFileDescriptor() استفاده کنید:

کاتلین

val providerOptions = Bundle().apply {
    putParcelable(MediaStore.EXTRA_MEDIA_CAPABILITIES, mediaCapabilities)
}
contentResolver.openTypedAssetFileDescriptor(mediaUri, mediaMimeType, providerOptions)
    .use { fileDescriptor ->
        // Content will be transcoded based on values defined in the
        // ApplicationMediaCapabilities provided.
    }

جاوا

Bundle providerOptions = new Bundle();
providerOptions.putParcelable(MediaStore.EXTRA_MEDIA_CAPABILITIES, mediaCapabilities);
try (AssetFileDescriptor fileDescriptor =  contentResolver.openTypedAssetFileDescriptor(mediaUri, mediaMimeType, providerOptions)) {
    // Content will be transcoded based on values defined in the
    // ApplicationMediaCapabilities provided.
}

این روش امکان کنترل جزئی برای مسیرهای کد خاص را فراهم می‌کند، مانند فراخوانی کدگذاری فقط هنگام انتقال یک فایل ویدیویی خارج از دستگاه. این روش نسبت به روشی که در زیر توضیح داده شده است، اولویت دارد.

قابلیت‌ها را در یک منبع اعلام کنید

اعلام قابلیت‌ها در یک منبع، امکان کنترل کامل بر کدگذاری را فراهم می‌کند. این روش فقط باید در موارد بسیار خاص استفاده شود. به عنوان مثال، اگر برنامه شما فقط فایل‌های ویدیویی را از برنامه‌های دیگر دریافت می‌کند (به جای باز کردن مستقیم آنها) و آنها را در سروری آپلود می‌کند که از کدک‌های ویدیویی مدرن پشتیبانی نمی‌کند (به مثال سناریوی ۱ در زیر مراجعه کنید).

استفاده از این روش در مواقع غیرضروری ممکن است در سناریوهای ناخواسته، مانند نمایش کوچک ویدیوها، منجر به تبدیل کد شود و در نتیجه تجربه کاربری را کاهش دهد.

برای استفاده از این روش، یک فایل منبع media_capabilities.xml ایجاد کنید:

<?xml version="1.0" encoding="utf-8"?>
<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
    <format android:name="HEVC" supported="true"/>
    <format android:name="HDR10" supported="false"/>
    <format android:name="HDR10Plus" supported="false"/>
</media-capabilities>

در این مثال، ویدیوهای HDR ضبط‌شده روی دستگاه به‌طور یکپارچه به ویدیوی AVC SDR (محدوده دینامیکی استاندارد) تبدیل می‌شوند، در حالی که ویدیوهای HEVC این‌طور نیستند.

از یک تگ property درون تگ application برای اضافه کردن ارجاع به فایل قابلیت‌های رسانه استفاده کنید. این ویژگی‌ها را به فایل AndroidManifest.xml خود اضافه کنید:

<property
    android:name="android.media.PROPERTY_MEDIA_CAPABILITIES"
    android:resource="@xml/media_capabilities" />

استفاده از قابلیت‌های رسانه‌ای یک برنامه دیگر برای باز کردن یک فایل ویدیویی

اگر برنامه شما یک فایل ویدیویی را با برنامه دیگری به اشتراک می‌گذارد، ممکن است قبل از اینکه برنامه گیرنده بتواند آن را باز کند، فایل ویدیویی نیاز به تبدیل کد داشته باشد.

شما می‌توانید این مورد را با باز کردن یک فایل ویدیویی با استفاده از openTypedAssetFileDescriptor و مشخص کردن UID برنامه‌ی گیرنده که می‌توان آن را با استفاده از Binder.getCallingUid بدست آورد، مدیریت کنید. سپس پلتفرم از قابلیت‌های رسانه‌ای برنامه‌ی گیرنده برای تعیین اینکه آیا فایل ویدیویی باید تبدیل کد شود یا خیر، استفاده می‌کند.

کاتلین

val providerOptions = Bundle().apply {
    putParcelable(MediaStore.EXTRA_MEDIA_CAPABILITIES_UID, Binder.getCallingUid())
}
contentResolver.openTypedAssetFileDescriptor(mediaUri, mediaMimeType, providerOptions)
    .use { fileDescriptor ->
        // Content will be transcoded based on the media capabilities of the
        // calling app.
    }

جاوا

Bundle providerOptions = new Bundle();
providerOptions.putParcelable(MediaStore.EXTRA_MEDIA_CAPABILITIES_UID, Binder.getCallingUid());
try (AssetFileDescriptor fileDescriptor =  contentResolver.openTypedAssetFileDescriptor(mediaUri, mediaMimeType, providerOptions)) {
    // Content will be transcoded based on the media capabilities of the
    // calling app.
}

سناریوهای مثال

نمودارهای زیر دو مورد استفاده رایج را نشان می‌دهند. در هر دو مورد، ویدیوی اصلی با فرمت HEVC ذخیره می‌شود و برنامه اشتراک‌گذاری ویدیو از HEVC پشتیبانی نمی‌کند.

مثال ۱. تبدیل کد توسط برنامه ضبط ویدیو آغاز می‌شود. مثال ۱ برنامه اشتراک‌گذاری ویدیو اعلام می‌کند که در فایل منبع قابلیت‌های رسانه‌ای خود از HEVC پشتیبانی نمی‌کند. سپس از برنامه ضبط ویدیو درخواست ویدیو می‌کند. برنامه ضبط ویدیو درخواست را مدیریت کرده و فایل را با استفاده از openTypedAssetFileDescriptor که شناسه کاربری برنامه اشتراک‌گذاری را مشخص می‌کند، باز می‌کند. این کار فرآیند تبدیل کد را آغاز می‌کند. وقتی ویدیوی تبدیل کد شده دریافت شد، به برنامه اشتراک‌گذاری ارائه می‌شود که آن را در سروری در فضای ابری آپلود می‌کند.

مثال ۲. تبدیل کد توسط برنامه اشتراک‌گذاری ویدیو آغاز می‌شود. مثال ۲ برنامه ضبط ویدیو، ویدیویی را با استفاده از یک MediaStore URI با برنامه اشتراک‌گذاری ویدیو به اشتراک می‌گذارد. برنامه اشتراک‌گذاری ویدیو، فایل ویدیویی را با استفاده از openTypedAssetFileDescriptor باز می‌کند و مشخص می‌کند که از HEVC در قابلیت‌های رسانه‌ای خود پشتیبانی نمی‌کند. این کار فرآیند تبدیل کد را آغاز می‌کند و پس از اتمام، فایل در یک سرور در فضای ابری آپلود می‌شود.

قالب‌های اعلام نشده

تبدیل کد رسانه‌های سازگار برای تمام فرمت‌هایی که پشتیبانی نمی‌شوند فعال و برای تمام فرمت‌هایی که پشتیبانی می‌شوند غیرفعال است. برای سایر فرمت‌هایی که اعلام نشده‌اند، پلتفرم تصمیم می‌گیرد که تبدیل کد انجام شود یا خیر. در اندروید ۱۲، تبدیل کد برای تمام فرمت‌های اعلام نشده غیرفعال است. این رفتار ممکن است در آینده برای فرمت‌های جدید تغییر کند.

گزینه‌های توسعه‌دهنده

شما می‌توانید از گزینه‌های توسعه‌دهنده‌ی زیر برای لغو رفتار پیش‌فرض تبدیل کد اندروید استفاده کنید:

  • نادیده گرفتن پیش‌فرض‌های تبدیل کد (transcoding defaults) این تنظیم تعیین می‌کند که آیا پلتفرم، تبدیل کد خودکار را کنترل می‌کند یا خیر. وقتی گزینه‌ی لغو فعال باشد، پیش‌فرض‌های پلتفرم نادیده گرفته می‌شوند و تنظیم فعال کردن تبدیل کد، تبدیل کد خودکار را کنترل می‌کند. این گزینه به طور پیش‌فرض غیرفعال است.

  • فعال کردن تبدیل کد (transcoding) این تنظیم مشخص می‌کند که آیا فرمت‌های تعریف نشده به طور خودکار تبدیل کد شوند یا خیر. این تنظیم به طور پیش‌فرض فعال است، اما فقط در صورتی تأثیر دارد که تنظیمات پیش‌فرض تبدیل کد (transcoding defaults) نیز فعال باشد.

  • فرض کنید برنامه‌ها از فرمت‌های مدرن پشتیبانی می‌کنند. این تنظیم کنترل می‌کند که وقتی برنامه سعی می‌کند یک فرمت اعلام نشده را پخش کند، چه اتفاقی بیفتد. این اتفاق زمانی می‌افتد که مانیفست اعلام نکند که آیا برنامه از یک فرمت خاص پشتیبانی می‌کند یا خیر، یا گوگل برنامه را به لیست تبدیل کد اجباری سمت سرور اضافه نکرده باشد. وقتی این تنظیم فعال باشد، برنامه تبدیل کد انجام نمی‌دهد، وقتی غیرفعال باشد، برنامه تبدیل کد انجام می‌دهد. این گزینه به طور پیش‌فرض فعال است.

  • نمایش اعلان‌های تبدیل کد (نمایش اعلان‌های تبدیل کد) در صورت فعال بودن، برنامه هنگام فعال شدن تبدیل کد با خواندن یک فایل رسانه‌ای پشتیبانی نشده، یک اعلان پیشرفت تبدیل کد نمایش می‌دهد. این گزینه به طور پیش‌فرض فعال است.

  • غیرفعال کردن حافظه پنهان کدگذاری در صورت فعال بودن، برنامه‌هایی که نیاز به کدگذاری دارند از حافظه پنهان کدگذاری استفاده نمی‌کنند. این می‌تواند در طول توسعه برای فعال کردن آسان کدگذاری روی یک فایل رسانه‌ای پشتیبانی نشده مفید باشد، اما می‌تواند باعث عملکرد ضعیف دستگاه شود. این گزینه به طور پیش‌فرض غیرفعال است.