Transkodowanie zgodnych multimediów

Na Androidzie 12 (poziom interfejsu API 31) i nowszych system może automatycznie konwertować filmy nagrane w formatach takich jak HEVC (H.265) na AVC (H.264), gdy są otwierane przez aplikację, która nie obsługuje HEVC. Ta funkcja pozwala aplikacjom do nagrywania filmów korzystać z nowocześniejszego kodowania, które pozwala oszczędzać miejsce w przypadku filmów nagranych na urządzeniu, zachowując zgodność z innymi aplikacjami.

W przypadku treści tworzonych na urządzeniu te formaty mogą być transkodowane automatycznie:

Format multimediów Atrybut XML Typ MIME MediaFormat
HEVC (H.265) Ogrzewanie, wentylacja i klimatyzacja MediaFormat.MIMETYPE_VIDEO_HEVC
HDR10HDR10 MediaFeature.HdrType.HDR10.
HDR10+ HDR10Plus MediaFeature.HdrType.HDR10_PLUS.

Android zakłada, że aplikacje mogą odtwarzać wszystkie formaty multimediów, więc zgodne transkodowanie multimediów jest domyślnie wyłączone.

Kiedy używać transkodowania

Transkodowanie jest kosztowne pod względem obliczeniowym i znaczne opóźnienie przy otwieraniu pliku wideo. Na przykład transkodowanie 1-minutowego pliku wideo HEVC na telefonie Pixel 3 trwa około 20 sekund. Z tego powodu należy transkodować plik wideo tylko wtedy, gdy wysyłasz go poza urządzenie. Dotyczy to na przykład udostępniania pliku wideo innym użytkownikom tej samej aplikacji lub serwera w chmurze, który nie obsługuje nowoczesnych formatów wideo.

Nie transkoduj w przypadku otwierania plików wideo w celu odtwarzania na urządzeniu ani tworzenia miniatur.

Konfigurowanie transkodowania

Aplikacje mogą kontrolować swoje transkodowanie przez deklarowanie swoich możliwości multimedialnych. Te możliwości można zadeklarować na 2 sposoby: w kodzie lub w zasobie.

Zadeklaruj możliwości w kodzie

Funkcje multimedialne możesz zadeklarować w kodzie, tworząc wystąpienie obiektu ApplicationMediaCapabilities za pomocą konstruktora:

Kotlin

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

Java

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

Używaj tego obiektu do uzyskiwania dostępu do treści multimedialnych za pomocą takich metod jak ContentResolver#openTypedAssetFileDescriptor():

Kotlin

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.
    }

Java

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.
}

Ta metoda zapewnia szczegółową kontrolę nad określonymi ścieżkami kodu, np. wywoływanie transkodowania tylko podczas przesyłania pliku wideo poza urządzenie. Ma to pierwszeństwo przed metodą opisaną poniżej.

Deklarowanie możliwości w zasobie

Zadeklarowanie możliwości w zasobie zapewnia ogólną kontrolę nad transkodowaniem. Tej metody należy używać tylko w ściśle określonych przypadkach. Przykładowo, jeśli aplikacja odbiera pliki wideo tylko z innych aplikacji (a nie otwiera ich bezpośrednio) i przesyła je na serwer, który nie obsługuje nowoczesnych kodeków wideo (zobacz przykład 1 poniżej).

Użycie tej metody, gdy nie jest absolutnie konieczne, może spowodować transkodowanie w niezamierzonych sytuacjach, na przykład przy miniaturze filmów, co pogorszy komfort korzystania z aplikacji.

Aby użyć tej metody, utwórz plik zasobów 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>

W tym przykładzie filmy HDR nagrane na urządzeniu są transkodowane na format AVC SDR (standardowy zakres dynamiczny), natomiast filmy HEVC już nie.

Aby dodać odwołanie do pliku możliwości multimedialnych, użyj tagu property w tagu application. Dodaj do pliku AndroidManifest.xml te właściwości:

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

Otwieranie pliku wideo przy użyciu funkcji multimedialnych innej aplikacji

Jeśli aplikacja udostępnia plik wideo innej aplikacji, możliwe, że plik wideo trzeba transkodować, zanim aplikacja odbierająca będzie mogła go otworzyć.

Aby rozwiązać ten problem, otwórz plik wideo za pomocą polecenia openTypedAssetFileDescriptor i podaj identyfikator UID aplikacji odbierającej, który można uzyskać za pomocą Binder.getCallingUid. Następnie platforma korzysta z funkcji multimedialnych aplikacji odbierającej, aby określić, czy plik wideo powinien zostać transkodowany.

Kotlin

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.
    }

Java

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.
}

Przykładowe scenariusze

Poniższe diagramy przedstawiają 2 typowe przypadki użycia. W obu przypadkach oryginalny film jest przechowywany w formacie HEVC, a aplikacja do udostępniania filmów nie obsługuje HEVC.

Przykład 1. Transkodowanie jest inicjowane przez aplikację do nagrywania filmów. Przykład 1 Aplikacja do udostępniania filmów deklaruje, że nie obsługuje HEVC w swoim pliku zasobów funkcji multimedialnych. Następnie wysyła żądanie udostępnienia filmu z aplikacji do nagrywania filmów. Aplikacja do przechwytywania wideo obsługuje żądanie i otwiera plik za pomocą openTypedAssetFileDescriptor, podając identyfikator UID aplikacji udostępniającej. Inicjuje to proces transkodowania. Po otrzymaniu transkodowanego filmu jest on przesyłany do aplikacji do udostępniania, która przesyła go na serwer w chmurze.

Przykład 2. Transkodowanie inicjuje aplikacja do udostępniania filmów. Przykład 2 Aplikacja do nagrywania filmów udostępnia film aplikacji do udostępniania wideo za pomocą identyfikatora URI MediaStore. Aplikacja do udostępniania filmów otwiera plik wideo przy użyciu narzędzia openTypedAssetFileDescriptor, wskazując, że nie obsługuje ona HEVC w ramach swoich funkcji multimedialnych. Powoduje to rozpoczęcie procesu transkodowania. Po jego zakończeniu plik jest przesyłany na serwer w chmurze.

Niezadeklarowane formaty

Zgodne transkodowanie multimediów jest włączone w przypadku wszystkich formatów, które zostały zadeklarowane jako nieobsługiwane, i wyłączone w przypadku wszystkich zadeklarowanych formatów. W przypadku innych formatów, które nie są zadeklarowane, platforma decyduje, czy transkodować. W Androidzie 12 transkodowanie jest wyłączone w przypadku niezadeklarowanych formatów. W przyszłości może się to zmienić w przypadku nowych formatów.

Opcje programisty

Aby zastąpić domyślne zachowanie transkodowania Androida, możesz użyć tych opcji programisty:

  • Zastąp domyślne ustawienia transkodowania To ustawienie określa, czy platforma kontroluje automatyczne transkodowanie. Gdy zastępowanie jest włączone, domyślne ustawienia platformy są ignorowane, a ustawienie Włącz transkodowanie steruje automatycznym transkodowaniem. Ta opcja jest domyślnie wyłączona.

  • Włącz transkodowanie To ustawienie określa, czy niezadeklarowane formaty mają być transkodowane automatycznie. Jest domyślnie włączone, ale działa tylko wtedy, gdy jest też włączone zastępowanie domyślnych ustawień transkodowania.

  • Załóżmy, że aplikacje obsługują nowoczesne formaty To ustawienie określa, co się dzieje, gdy aplikacja próbuje odtworzyć niezadeklarowany format. Dzieje się tak, gdy plik manifestu nie określa, czy aplikacja obsługuje określony format, lub gdy Google nie dodał aplikacji do listy wymuszonego transkodowania po stronie serwera. Gdy to ustawienie jest włączone, aplikacja nie transkoduje, a po jego wyłączeniu aplikacja transkoduje. Ta opcja jest domyślnie włączona.

  • Pokazuj powiadomienia o transkodowaniu: gdy ta opcja jest włączona, aplikacja wyświetla powiadomienie o postępie transkodowania, gdy jest on uruchamiany przez odczytanie nieobsługiwanego pliku multimedialnego. Ta opcja jest domyślnie włączona.

  • Wyłącz pamięć podręczną transkodowania Jeśli ta opcja jest włączona, aplikacje wymagające transkodowania nie korzystają z pamięci podręcznej transkodowania. Może to być przydatne na etapie programowania, aby łatwo aktywować transkodowanie nieobsługiwanego pliku multimedialnego, ale może też powodować obniżenie wydajności urządzenia. Domyślnie ta opcja jest wyłączona.