המרת קידוד למדיה תואמת

ב-Android 12 (רמת API‏ 31) ומעלה, המערכת יכולה להמיר באופן אוטומטי סרטונים שצולמו בפורמטים כמו HEVC‏ (H.265) ל-AVC‏ (H.264) כשהסרטונים נפתחים באפליקציה שלא תומכת ב-HEVC. התכונה הזו מאפשרת לאפליקציות לצילום וידאו להשתמש בקידוד מודרני ויעיל יותר לאחסון סרטונים שצולמו במכשיר, בלי לפגוע בתאימות לאפליקציות אחרות.

אפשר לבצע באופן אוטומטי המרה של תוכן שנוצר במכשיר לפורמטים הבאים:

פורמט מדיה מאפיין XML סוג MIME של MediaFormat
HEVC (H.265) HEVC MediaFormat.MIMETYPE_VIDEO_HEVC
HDR10HDR10 ‫MediaFeature.HdrType.HDR10
HDR10+‎ HDR10Plus ‫MediaFeature.HdrType.HDR10_PLUS

מערכת Android מניחה שאפליקציות יכולות לתמוך בהשמעה של כל פורמטי המדיה, ולכן המרת קידוד של מדיה תואמת מושבתת כברירת מחדל.

מתי כדאי להשתמש בטרנסקודינג

קידוד טרנספורמציה הוא פעולה שדורשת הרבה משאבי מחשוב, והיא גורמת לעיכוב משמעותי בפתיחה של קובץ וידאו. לדוגמה, המרת קובץ וידאו בפורמט HEVC באורך של דקה אחת לפורמט AVC בטלפון Pixel 3 נמשכת בערך 20 שניות. לכן, כדאי לבצע טרנסקוד לקובץ וידאו רק כששולחים אותו מהמכשיר. לדוגמה, כשמשתפים קובץ וידאו עם משתמשים אחרים באותה אפליקציה, או עם שרת ענן שלא תומך בפורמטים מודרניים של וידאו.

לא להמיר את הקידוד כשפותחים קובצי וידאו להפעלה במכשיר או ליצירת תמונות ממוזערות.

הגדרת המרת קידוד

אפליקציות יכולות לשלוט בהתנהגות הטרנסקוד שלהן על ידי הצהרה על יכולות המדיה שלהן. יש שתי דרכים להצהיר על היכולות האלה: בקוד או במשאב.

הצהרה על יכולות בקוד

אפשר להצהיר על יכולות מדיה בקוד על ידי יצירת מופע של אובייקט ApplicationMediaCapabilities באמצעות כלי ליצירה:

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();

משתמשים באובייקט הזה כשניגשים לתוכן מדיה באמצעות שיטות כמו 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.
}

השיטה הזו מאפשרת שליטה מדויקת בנתיבי קוד מסוימים, כמו הפעלת קידוד טרנסקוד רק כשמעבירים קובץ וידאו מהמכשיר. השיטה הזו מקבלת עדיפות על פני השיטה שמתוארת בהמשך.

הצהרה על יכולות במשאב

הצהרה על יכולות במשאב מאפשרת שליטה גורפת בהמרת קידוד. צריך להשתמש בשיטה הזו רק במקרים מאוד ספציפיים. לדוגמה, אם האפליקציה שלכם מקבלת רק קובצי וידאו מאפליקציות אחרות (ולא פותחת אותם ישירות) ומעלה אותם לשרת שלא תומך בקודי וידאו מודרניים (ראו תרחיש לדוגמה 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. לאחר מכן, הפלטפורמה משתמשת ביכולות המדיה של האפליקציה המקבלת כדי לקבוע אם צריך לבצע המרה של קובץ הווידאו.

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

תרחישים לדוגמה

הדיאגרמות הבאות מציגות את שני תרחישי השימוש הנפוצים. בשני המקרים, הסרטון המקורי מאוחסן בפורמט HEVC ואפליקציית שיתוף הסרטונים לא תומכת ב-HEVC.

דוגמה 1. הקידוד מחדש מופעל על ידי אפליקציית צילום הווידאו. דוגמה 1 אפליקציית שיתוף הווידאו מצהירה שהיא לא תומכת ב-HEVC בקובץ המשאבים של יכולות המדיה שלה. לאחר מכן, נשלחת בקשה לסרטון מאפליקציית צילום הווידאו. אפליקציית צילום הווידאו מטפלת בבקשה ופותחת את הקובץ באמצעות openTypedAssetFileDescriptor, תוך ציון ה-UID של אפליקציית השיתוף. תהליך הקידוד יתחיל. כשמתקבל הסרטון שעבר המרה, הוא מועבר לאפליקציית השיתוף, שמעלה אותו לשרת בענן.

דוגמה 2. הקידוד מחדש מתחיל באפליקציה לשיתוף סרטונים. דוגמה 2 האפליקציה לצילום סרטונים משתפת סרטון עם האפליקציה לשיתוף סרטונים באמצעות MediaStore URI. אפליקציית שיתוף הסרטונים פותחת את קובץ הסרטון באמצעות openTypedAssetFileDescriptor, ומציינת שהיא לא תומכת ב-HEVC ביכולות המדיה שלה. הפעולה הזו תתחיל את תהליך הקידוד מחדש, ולאחר השלמתו הקובץ יועלה לשרת בענן.

פורמטים שלא הוגדרו

ההמרה של מדיה בפורמטים תואמים מופעלת לכל הפורמטים שמוצהר שהם לא נתמכים, ומושבתת לכל הפורמטים שמוצהר שהם נתמכים. בפורמטים אחרים שלא הוגדרו, הפלטפורמה מחליטה אם לבצע המרה או לא. ב-Android 12, טרנסקוד מושבת לכל הפורמטים שלא הוגדרו. יכול להיות שההתנהגות הזו תשתנה בעתיד בפורמטים חדשים.

אפשרויות למפתחים

אפשר להשתמש באפשרויות הבאות למפתחים כדי לשנות את התנהגות ברירת המחדל של טרנסקוד ב-Android:

  • ביטול ברירות המחדל של המרת קידוד ההגדרה הזו קובעת אם הפלטפורמה שולטת בהמרת קידוד אוטומטית. כשהאפשרות override מופעלת, המערכת מתעלמת מברירות המחדל של הפלטפורמה וההגדרה enable transcoding שולטת בהמרת הקידוד האוטומטית. האפשרות הזו מושבתת כברירת מחדל.

  • הפעלת המרת קידוד ההגדרה הזו קובעת אם פורמטים לא מוצהרים יומרו אוטומטית. היא מופעלת כברירת מחדל, אבל היא תקפה רק אם גם ההגדרה החלפת הגדרות ברירת המחדל של המרת פורמט מופעלת.

  • הנחת העבודה היא שאפליקציות תומכות בפורמטים מודרניים ההגדרה הזו קובעת מה קורה כשהאפליקציה מנסה להפעיל פורמט שלא הוגדר. המצב הזה קורה אם בקובץ המניפסט לא מצוין אם האפליקציה תומכת בפורמט מסוים או לא, או אם Google לא הוסיפה את האפליקציה לרשימת ההמרות הכפויות בצד השרת. כשההגדרה מופעלת, האפליקציה לא מבצעת טרנסקוד, וכשהיא מושבתת, האפליקציה מבצעת טרנסקוד. האפשרות הזו מופעלת כברירת מחדל.

  • הצגת התראות לגבי המרת קידוד כשההגדרה הזו מופעלת, האפליקציה מציגה התראה על התקדמות המרת הקידוד כשמתבצעת המרת קידוד בעקבות קריאה של קובץ מדיה שלא נתמך. האפשרות הזו מופעלת כברירת מחדל.

  • השבתת השמירה של המרת הקידוד במטמון אם ההגדרה הזו מופעלת, אפליקציות שנדרשת בהן המרת קידוד לא משתמשות במטמון של המרת הקידוד. האפשרות הזו יכולה לעזור במהלך הפיתוח להפעלת המרת קידוד בקלות בקובץ מדיה שלא נתמך, אבל היא עלולה לגרום לביצועים נמוכים של המכשיר. האפשרות הזו מושבתת כברירת מחדל.