Совместимое транскодирование мультимедиа

В Android 12 (уровень API 31) и выше система может автоматически конвертировать видео, записанные в таких форматах, как HEVC (H.265), в AVC (H.264), когда видео открывается приложением, не поддерживающим HEVC. Эта функция позволяет приложениям для захвата видео использовать более современное и эффективное кодирование видео, записанных на устройстве, без ущерба для совместимости с другими приложениями.

Следующие форматы могут быть автоматически перекодированы для контента, созданного на устройстве:

Медиа-формат XML-атрибут Тип MIME MediaFormat
HEVC (H.265) HEVC MediaFormat.MIMETYPE_VIDEO_HEVC
HDR10 HDR10 MediaFeature.HdrType.HDR10
HDR10+ HDR10Plus MediaFeature.HdrType.HDR10_PLUS

Android предполагает, что приложения могут поддерживать воспроизведение всех форматов мультимедиа, поэтому совместимое транскодирование мультимедиа по умолчанию отключено.

Когда использовать транскодирование

Транскодирование — это трудоемкая операция, которая приводит к значительной задержке при открытии видеофайла. Например, перекодирование одноминутного видеофайла 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. Транскодирование инициируется приложением для захвата видео. Пример 1 Приложение для обмена видео заявляет, что оно не поддерживает HEVC в своем файле ресурсов мультимедийных возможностей. Затем он запрашивает видео из приложения для захвата видео. Приложение видеозахвата обрабатывает запрос и открывает файл с помощью openTypedAssetFileDescriptor , указывая UID приложения для совместного использования. Это инициирует процесс перекодирования. Когда перекодированное видео получено, оно передается в приложение для обмена, которое загружает его на сервер в облаке.

Пример 2. Транскодирование инициируется приложением для обмена видео. Пример 2 Приложение для захвата видео передает видео приложению для обмена видео, используя URI MediaStore . Приложение для обмена видео открывает видеофайл с помощью openTypedAssetFileDescriptor , указывая, что оно не поддерживает HEVC в своих мультимедийных возможностях. Это инициирует процесс перекодирования, и после его завершения файл загружается на сервер в облаке.

Необъявленные форматы

Перекодирование совместимого мультимедиа включено для всех форматов, объявленных неподдерживаемыми, и отключено для всех форматов, объявленных поддерживаемыми. Для других форматов, которые не объявлены, платформа решает, перекодировать или нет. В Android 12 транскодирование отключено для всех необъявленных форматов. В будущем это поведение может измениться для новых форматов.

Опции разработчика

Вы можете использовать следующие параметры разработчика, чтобы переопределить поведение транскодирования Android по умолчанию:

  • Переопределить настройки транскодирования по умолчанию. Этот параметр определяет, контролирует ли платформа автоматическое транскодирование. Если переопределение включено, настройки платформы по умолчанию игнорируются, а настройка включения транскодирования управляет автоматическим транскодированием. Эта опция отключена по умолчанию.

  • Включить перекодирование Этот параметр определяет, будут ли необъявленные форматы автоматически перекодироваться. Он включен по умолчанию, но имеет эффект только в том случае, если также включено переопределение настроек транскодирования по умолчанию .

  • Предполагать, что приложения поддерживают современные форматы. Этот параметр определяет, что происходит, когда приложение пытается воспроизвести необъявленный формат. Это происходит, когда в манифесте не указано, поддерживает ли приложение определенный формат, или Google не добавил приложение в список принудительного перекодирования на стороне сервера. Если этот параметр включен, приложение не выполняет перекодирование, если он отключен, приложение выполняет перекодирование. Эта опция включена по умолчанию.

  • Показывать уведомления о перекодировании. Если этот параметр включен, приложение отображает уведомление о ходе перекодирования, когда перекодирование запускается при чтении неподдерживаемого мультимедийного файла. Эта опция включена по умолчанию.

  • Отключить кеш перекодирования. Если этот параметр включен, приложения, требующие перекодирования, не используют кеш перекодирования. Это может быть полезно во время разработки, чтобы легко запустить перекодирование неподдерживаемого медиафайла, но может привести к снижению производительности устройства. Эта опция отключена по умолчанию.