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

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

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

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

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

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

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

KotlinJava
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():

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

KotlinJava
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 אפליקציית הצילום משתפת סרטון עם אפליקציית שיתוף הסרטונים באמצעות MediaStore URI. אפליקציית שיתוף הסרטונים פותחת את קובץ הווידאו באמצעות openTypedAssetFileDescriptor, ומציינת שהיא לא תומכת ב-HEVC ביכולות המדיה שלה. הזה מתחיל תהליך המרת הקידוד, וכשהקובץ מסתיים, מועלה שרת בענן.

פורמטים לא מוצהרים

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

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

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

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

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

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

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

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