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

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

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

قالب رسانه ویژگی XML MediaFormat نوع mime
HEVC (H.265) HEVC MediaFormat.MIMETYPE_VIDEO_HEVC
HDR10 HDR10 MediaFeature.HdrType.HDR10
HDR10+ HDR10Plus MediaFeature.HdrType.HDR10_PLUS

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

زمان استفاده از رمزگذاری

Transcoding یک عملیات محاسباتی گران است و تاخیر قابل توجهی را هنگام باز کردن یک فایل ویدیویی اضافه می کند. برای مثال، تبدیل یک فایل ویدیویی 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.
}

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

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

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

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

برای استفاده از این روش، یک فایل منبع 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 پشتیبانی نمی‌کند.

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

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

فرمت های اعلام نشده

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

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

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

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

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

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

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

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