Zgodne transkodowanie multimediów

Na Androidzie 12 (API na poziomie 31) i nowszym system może automatycznie konwertować filmy nagrane w formatach takich jak HEVC (H.265) na AVC (H.264), gdy są one otwierane przez aplikację, która nie obsługuje HEVC. Ta funkcja umożliwia aplikacjom do nagrywania filmów korzystanie z nowocześniejszego, bardziej wydajnego pod względem miejsca na dane kodowania filmów nagrywanych na urządzeniu bez utraty zgodności z innymi aplikacjami.

Te formaty mogą być automatycznie transkodowane w przypadku treści utworzonych na urządzeniu:

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

Android zakłada, że aplikacje mogą obsługiwać odtwarzanie wszystkich formatów multimediów, więc zgodne transkodowanie multimediów jest domyślnie wyłączone.

Kiedy używać transkodowania

Transkodowanie jest operacją wymagającą dużej mocy obliczeniowej i znacznie opóźnia otwarcie pliku wideo. Na przykład przekodowanie 1-minutowego pliku wideo HEVC na AVC na telefonie Pixel 3 zajmuje około 20 sekund. Dlatego plik wideo należy transkodować tylko wtedy, gdy wysyłasz go z urządzenia. Na przykład podczas 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 plików wideo podczas otwierania ich w celu odtwarzania na urządzeniu ani podczas tworzenia miniatur.

Konfigurowanie transkodowania

Aplikacje mogą kontrolować sposób transkodowania, deklarując swoje możliwości multimedialne. Możesz zadeklarować te możliwości na 2 sposoby: w kodzie lub w zasobie.

Deklarowanie funkcji w kodzie

Możesz zadeklarować możliwości multimedialne w kodzie, tworząc instancję obiektu ApplicationMediaCapabilities za pomocą kreatora:

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, gdy uzyskujesz dostęp do treści multimedialnych za pomocą metod takich 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 umożliwia szczegółową kontrolę nad konkretnymi ścieżkami kodu, np. wywoływanie transkodowania tylko podczas przesyłania pliku wideo z urządzenia. Ma ona pierwszeństwo przed metodą opisaną poniżej.

Deklarowanie możliwości w zasobie

Deklarowanie możliwości w zasobie umożliwia ogólną kontrolę nad transkodowaniem. Ta metoda powinna być używana tylko w bardzo konkretnych przypadkach. Jeśli na przykład Twoja aplikacja odbiera tylko pliki wideo z innych aplikacji (zamiast otwierać je bezpośrednio) i przesyła je na serwer, który nie obsługuje nowoczesnych kodeków wideo (patrz scenariusz 1 poniżej).

Używanie tej metody, gdy nie jest to absolutnie konieczne, może spowodować transkodowanie w nieoczekiwanych sytuacjach, np. podczas tworzenia miniatur filmów, co pogorszy wrażenia użytkownika.

Aby użyć tej metody, utwórz plik zasobu 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ą bezproblemowo transkodowane na filmy AVC SDR (o standardowym zakresie dynamiki), a filmy HEVC nie.

Użyj tagu property w tagu application, aby dodać odwołanie do pliku z informacjami o możliwościach multimedialnych. 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 za pomocą funkcji multimedialnych innej aplikacji

Jeśli Twoja aplikacja udostępnia plik wideo innej aplikacji, może być konieczne przekodowanie pliku wideo, zanim aplikacja odbierająca będzie mogła go otworzyć.

Możesz to zrobić, otwierając plik wideo za pomocą openTypedAssetFileDescriptor i określając identyfikator UID aplikacji odbierającej, który można uzyskać za pomocą Binder.getCallingUid. Platforma korzysta następnie z możliwości 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

Na diagramach poniżej przedstawiono 2 typowych przypadków użycia. W obu przypadkach oryginalny film jest przechowywany w formacie HEVC, a aplikacja do udostępniania filmów nie obsługuje tego formatu.

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 kodeka HEVC w pliku zasobów dotyczących możliwości multimedialnych. Następnie wysyła żądanie do aplikacji do nagrywania filmów. Aplikacja do nagrywania filmów obsługuje żądanie i otwiera plik za pomocą openTypedAssetFileDescriptor, podając identyfikator UID aplikacji do udostępniania. Spowoduje to rozpoczęcie procesu transkodowania. Po otrzymaniu przekodowanego filmu jest on przekazywany do aplikacji do udostępniania, która przesyła go na serwer w chmurze.

Przykład 2. Transkodowanie jest inicjowane przez aplikację do udostępniania filmów. Przykład 2 Aplikacja do nagrywania filmów udostępnia film aplikacji do udostępniania filmów za pomocą identyfikatora URI. Przykład 2MediaStore Aplikacja do udostępniania filmów otwiera plik wideo za pomocą openTypedAssetFileDescriptor, określając, że nie obsługuje HEVC w swoich możliwościach multimedialnych. Spowoduje to rozpoczęcie procesu transkodowania, a po jego zakończeniu plik zostanie przesłany na serwer w chmurze.

Niezadeklarowane formaty

Kompatybilne transkodowanie multimediów jest włączone w przypadku wszystkich formatów, które są zadeklarowane jako nieobsługiwane, i wyłączone w przypadku wszystkich formatów, które są zadeklarowane jako obsługiwane. W przypadku innych formatów, które nie zostały zadeklarowane, platforma decyduje, czy transkodować, czy nie. W Androidzie 12 transkodowanie jest wyłączone w przypadku wszystkich 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 w Androidzie, możesz użyć tych opcji programisty:

  • Zastąp ustawienia domyślne transkodowania: to ustawienie określa, czy platforma ma kontrolować automatyczne transkodowanie. Gdy zastępowanie jest włączone, domyślne ustawienia platformy są ignorowane, a ustawienie włącz transkodowanie kontroluje automatyczne transkodowanie. Domyślnie ta opcja jest wyłączona.

  • Włącz transkodowanie: to ustawienie określa, czy niezadeklarowane formaty mają być automatycznie transkodowane. Jest ona domyślnie włączona, ale ma wpływ tylko wtedy, gdy włączona jest też opcja zastąp domyślne ustawienia transkodowania.

  • Zakładaj, że aplikacje obsługują nowoczesne formaty To ustawienie decyduje o tym, co się stanie, gdy aplikacja spróbuje odtworzyć niezadeklarowany format. Dzieje się tak, gdy plik manifestu nie określa, czy aplikacja obsługuje dany format, lub gdy Google nie dodało aplikacji do listy wymuszonego transkodowania po stronie serwera. Gdy to ustawienie jest włączone, aplikacja nie transkoduje, a gdy jest wyłączone – transkoduje. Ta opcja jest domyślnie włączona.

  • Pokaż powiadomienia transkodowania: gdy ta opcja jest włączona, aplikacja wyświetla powiadomienie o postępach transkodowania, gdy transkodowanie jest wywoływane 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 podczas programowania, aby łatwo wywołać transkodowanie w przypadku nieobsługiwanego pliku multimedialnego, ale może powodować niską wydajność urządzenia. Domyślnie ta opcja jest wyłączona.