תוספים למצלמה

יצרני מכשירים יכולים לחשוף תוספים כמו בוקה, מצב לילה ו-HDR למפתחים של צד שלישי דרך ממשק התוספים למצלמה שמסופק על ידי ספריית הספק של ה-OEM. מפתחים יכולים להשתמש ב-Camera2 Extensions API וב-CameraX Extensions API כדי לגשת לתוספים שמופעלים בספריית הספק של יצרן הציוד המקורי.

רשימת התוספים הנתמכים, זהה ב-Camera2 וב-CameraX, מופיעה במאמר CameraX Extensions API. אם רוצים להוסיף תוסף, צריך לדווח על באג בכלי למעקב אחר בעיות.

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

ארכיטקטורה

בתרשים הבא מתוארת הארכיטקטורה של הממשק של התוספים למצלמה, או extensions-interface: ארכיטקטורה

איור 1. תרשים הארכיטקטורה של התוספים למצלמה

כפי שמוצג בתרשים, כדי לתמוך בתוספים למצלמה, צריך להטמיע את extensions-interface שמסופק על ידי ספריית הספק של ה-OEM. ספריית הספק של ה-OEM מאפשרת להשתמש בשני ממשקי API: CameraX Extensions API ו-Camera2 Extensions API, שבהם משתמשות האפליקציות CameraX ו-Camera2, בהתאמה, כדי לגשת לתוספים של ספקים.

הטמעת ספריית הספק של OEM

כדי להטמיע את ספריית הספק של ה-OEM, מעתיקים את הקבצים camera-extensions-stub לפרויקט של ספריית מערכת. הקבצים האלה מגדירים את הממשק של התוספים למצלמה.

קובצי camera-extensions-stub מחולקים לקטגוריות הבאות:

קבצי ממשק חיוניים (לא משנים)

  • PreviewExtenderImpl.java
  • ImageCaptureExtenderImpl.java
  • ExtenderStateListener.java
  • ProcessorImpl.java
  • PreviewImageProcessorImpl.java
  • CaptureProcessorImpl.java
  • CaptureStageImpl.java
  • RequestUpdateProcessorImpl.java
  • ProcessResultImpl.java
  • advanced/AdvancedExtenderImpl.java
  • advanced/Camera2OutputConfigImpl.java
  • advanced/Camera2SessionConfigImpl.java
  • advanced/ImageProcessorImpl.java
  • advanced/ImageReaderOutputConfigImpl.java
  • advanced/ImageReferenceImpl.java
  • advanced/MultiResolutionImageReaderOutputConfigImpl.java
  • advanced/OutputSurfaceImpl.java
  • advanced/RequestProcessorImpl.java
  • advanced/SessionProcessorImpl.java
  • advanced/SurfaceOutputConfigImpl.java

הטמעות חובה (מוסיפים את ההטמעה שלכם)

  • ExtensionVersionImpl.java
  • InitializerImpl.java

מחלקות של Bokeh extender (צריך להטמיע אותן אם יש תמיכה בתוסף Bokeh)

  • BokehImageCaptureExtenderImpl.java
  • BokehPreviewExtenderImpl.java
  • advanced/BokehAdvancedExtenderImpl.java

כיתות להארכת שעות הלימודים (צריך להטמיע את התכונה הזו אם היא נתמכת)

  • NightImageCaptureExtenderImpl.java
  • NightPreviewExtenderImpl.java
  • advanced/NightAdvancedExtenderImpl.java

כיתות של תוספים אוטומטיים (מטמיעים אותן אם יש תמיכה בתוספים אוטומטיים)

  • AutoImageCaptureExtenderImpl.java
  • AutoPreviewExtenderImpl.java
  • advanced/AutoAdvancedExtenderImpl.java

כיתות של מרחיבי HDR (מטמיעים אותן אם יש תמיכה בהרחבת HDR)

  • HdrImageCaptureExtenderImpl.java
  • HdrPreviewExtenderImpl.java
  • advanced/HdrAdvancedExtenderImpl.java

כיתות של תוספים לריטוש פנים (צריך להטמיע אותן אם יש תמיכה בתוסף לריטוש פנים)

  • BeautyImageCaptureExtenderImpl.java
  • BeautyPreviewExtenderImpl.java
  • advanced/BeautyAdvancedExtenderImpl.java

כלי עזר (אופציונלי, אפשר למחוק)

  • advanced/Camera2OutputConfigImplBuilder.java
  • advanced/Camera2SessionConfigImplBuilder.java

אין צורך לספק הטמעה לכל תוסף. אם לא מטמיעים תוסף, מגדירים את isExtensionAvailable() כך שיחזיר את הערך false או מסירים את הכיתות המתאימות של Extender. ממשקי ה-API של התוספים של Camera2 ו-CameraX מדווחים לאפליקציה שהתוסף לא זמין.

נראה איך ממשקי ה-API של התוספים של Camera2 ו-CameraX פועלים עם ספריית הספק כדי להפעיל תוסף. התרשים הבא מדגים את התהליך מקצה לקצה באמצעות התוסף Night בתור דוגמה:

Mainflow

איור 2. הטמעה של תוסף לילה

  1. אימות הגרסה:

    Camera2/X מבצעת קריאה ל-ExtensionVersionImpl.checkApiVersion() כדי לוודא שהגרסה של extensions-interface שהוטמעה על ידי יצרן הציוד המקורי תואמת לגרסאות הנתמכות של Camera2/X.

  2. הפעלת ספריית הספק:

    ל-InitializerImpl יש שיטה init() שמפעילה את ספריית הספק. Camera2/X משלים את האינטוליזציה לפני שהוא ניגש לכיתות Extender.

  3. יצירת מופעים של כיתות Extender:

    יצירת מופע של כיתות Extender עבור התוסף. יש שני סוגים של Extender: Basic Extender ו-Advanced Extender. צריך להטמיע סוג אחד של Extender לכל התוספים. מידע נוסף זמין במאמר מַרחיב בסיסי לעומת מַרחיב מתקדם.

    ‏Camera2/X יוצר מופע של כיתות Extender ומקיים איתן אינטראקציה כדי לאחזר מידע ולהפעיל את התוסף. להרחבה נתונה, Camera2/X יכול ליצור עותקים של הכיתות של Extender כמה פעמים. לכן, אל תבצעו את עבודת האיפוס הכבדה ב-constructor או בקריאה ל-init(). כדאי לבצע את הפעולות הכבדות רק כשסשן המצלמה עומד להתחיל, למשל כשמתבצעת קריאה ל-onInit() ב-Basic Extender או כשמתבצעת קריאה ל-initSession() ב-Advanced Extender.

    בתוסף Night, הכיתות הבאות של Extender נוצרות עבור הסוג Basic Extender:

    • NightImageCaptureExtenderImpl.java
    • NightPreviewExtenderImpl.java

    ועבור סוג Extender מתקדם:

    • NightAdvancedExtenderImpl.java
  4. בודקים את הזמינות של התוסף:

    לפני הפעלת התוסף, isExtensionAvailable() בודק אם התוסף זמין במזהה המצלמה שצוין באמצעות מכונה של Extender.

  5. מפעילים את המפצל באמצעות פרטי המצלמה:

    Camera2/X קורא ל-init() במכונה של Extender ומעביר לה את מזהה המצלמה ו-CameraCharacteristics.

  6. פרטי השאילתה:

    הפונקציה מפעילה את הכיתה Extender כדי לאחזר מידע כמו רזולוציות נתמכות, עדיין לתעד זמן אחזור משוער ולתעד מפתחות בקשה מה-Extender לקראת הפעלת התוסף.

  7. מפעילים את התוסף במכשיר ההרחבה:

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

    בסוג 'מגדיל מתקדם', Camera2/X יוצר אינטראקציה עם SessionProcessorImpl כדי להפעיל את התוסף. Camera2/X מאחזרת את המכונה SessionProcessorImpl באמצעות קריאה ל-createSessionProcessor() במכשיר ההרחבה.

בקטעים הבאים מתוארת תהליך ההוספה של התוסף בפירוט רב יותר.

אימות הגרסה

כשספריית הספק של ה-OEM נטענת מהמכשיר בזמן הריצה, Camera2/X מוודאת שהספרייה תואמת לגרסה extensions-interface. השדה extensions-interface משתמש בפורמט סמנטי לניהול גרסאות, או בפורמט MAJOR.MINOR.PATCH, לדוגמה 1.1.0 או 1.2.0. עם זאת, רק הגרסאות הראשיות והמשניות משמשות במהלך אימות הגרסה.

כדי לאמת את הגרסה, Camera2/X מבצעת קריאה ל-ExtensionVersionImpl.checkApiVersion() עם הגרסה הנתמכת של extensions-interface. לאחר מכן, Camera2/X משתמשת בגרסה שדווחה על ידי ספריית ה-OEM כדי לקבוע אם ניתן להפעיל את התוסף ואילו יכולות הוא צריך להפעיל.

תאימות לגרסה הראשית

אם הגרסאות הראשיות של extension-interface שונות בין Camera2/X לבין ספריית הספק, המערכת תתייחס לכך כאל חוסר תאימות והתוסף יושבת.

תאימות לאחור

כל עוד הגרסה הראשית זהה, Camera2/X מבטיחה תאימות לאחור לספריות של ספקי OEM שנוצרו בגרסאות קודמות של extensions-interface. לדוגמה, אם Camera2/X תומכת ב-extensions-interface 1.3.0, ספריות הספקים של יצרני ציוד מקורי שהטמיעו את הגרסאות 1.0.0,‏ 1.1.0 ו-1.2.0 עדיין תואמות. המשמעות היא גם שאחרי שמטמיעים גרסה ספציפית של ספריית הספק, Camera2/X מוודאת שהספרייה תואמת לאחור לגרסאות extension-interface עתידיות.

תאימות קדימה

התאימות לעתיד עם ספריות של ספקים של extensions-interface גרסאות חדשות יותר תלויה בכם, יצרני הציוד המקורי. אם אתם צריכים תכונות מסוימות כדי להטמיע את התוספים, כדאי להפעיל את התוספים החל מגרסה מסוימת. במקרה כזה, אפשר להחזיר את גרסת extensions-interface הנתמכת כשגרסת הספרייה של Camera2/X עומדת בדרישות. אם הגרסאות של Camera2/X לא נתמכות, אפשר להחזיר גרסה לא תואמת, כמו 99.0.0, כדי להשבית את התוספים.

איפוס של ספריית הספק

אחרי אימות הגרסה של extensions-interface שספריית ה-OEM הטמיעה, Camera2/X מתחיל את תהליך האיפוס. השיטה InitializerImpl.init() מאותתת לספריית ה-OEM שאפליקציה מנסה להשתמש בתוספים.

Camera2/X לא מבצעת קריאות נוספות לספריית ה-OEM (מלבד בדיקת הגרסה) עד שספריית הספק של ה-OEM קוראת ל-OnExtensionsInitializedCallback.onSuccess() כדי להודיע על השלמת האיפוס.

עליכם להטמיע את InitializerImpl החל מגרסה 1.1.0 של extensions-interface. Camera2/X מדלגים על שלב האתחול של הספרייה אם ספריית הספק של ה-OEM מיישמת את extensions-interface 1.0.0.

הרחבה בסיסית לעומת הרחבה מתקדמת

יש שני סוגים של הטמעת extensions-interface: Basic Extender ו-Advanced Extender. התמיכה ב-Advanced Extender החלה בגרסה extensions-interface 1.2.0.

מטמיעים את Basic Extender לתוספים שמעבדים תמונות ב-HAL של המצלמה, או משתמשים במעבד פוסט-עיבוד שיכול לעבד זרמי YUV.

הטמעת Advanced Extender עבור תוספים שצריכים להתאים אישית את הגדרת הסטרימינג של Camera2 ולשלוח בקשות צילום לפי הצורך.

בטבלה הבאה מופיעה ההשוואה:

מאריך בסיסי Advanced Extender
הגדרות של שידורים תוקנה
תצוגה מקדימה: PRIVATE או YUV_420_888 (אם המעבד קיים)
צילום סטילס: JPEG או YUV_420_888 (אם המעבד קיים)
ניתן להתאמה אישית על ידי יצרן ציוד מקורי.
שליחת בקשה לצילום רק Camera2/X יכול לשלוח בקשות צילום. אפשר להגדיר את הפרמטרים לבקשות האלה. כשהמעבד מסופק לצילום תמונות, Camera2/X יכול לשלוח כמה בקשות צילום ולשלוח את כל התמונות ותוצאות הצילום למעבד. יינתן לכם מכונה של RequestProcessorImpl כדי להריץ את בקשת הצילום של camera2 ולקבל את התוצאות והתמונה.

Camera2/X מפעיל את startRepeating ו-startCapture ב-SessionProcessorImpl כדי לאותת ליצרן הציוד המקורי להתחיל את הבקשה החוזרת לתצוגה מקדימה ולהתחיל את רצף הצילום של התמונות הסטטיות, בהתאמה.

הוספת ווקים לצינור עיבוד הנתונים של המצלמה
  • onPresetSession מספק פרמטרים של סשנים.
  • onEnableSession שולח בקשה אחת מיד אחרי ההגדרה של CameraCaptureSession.
  • onDisableSession שולח בקשה אחת לפני ש-CameraCaptureSession נסגר.
  • initSession מאתחלת ומחזירה הגדרה מותאמת אישית של סשן camera2 ליצירת סשן הצילום.
  • onCaptureSessionStart מופעל מיד אחרי ההגדרה של CameraCaptureSession.
  • onCaptureSessionEnd מופעל לפני ש-CameraCaptureSession נסגר.
מתאים תוספים שמופעלים ב-HAL של המצלמה או במעבד שעובד תמונות YUV.
  • יש להטמעות של התוספים שמבוססות על Camera2.
  • נדרשת הגדרת שידור בהתאמה אישית, כמו שידור RAW.
  • נדרש רצף צילום אינטראקטיבי.
גרסת ה-API הנתמכת Camera2 Extensions: ‏ Android 13 ואילך
CameraX Extensions: ‏ camera-extensions 1.1.0 ואילך
תוספים ל-Camera2: Android 12L ואילך
תוספים ל-CameraX: camera-extensions 1.2.0-alpha03 ואילך

תהליכי עבודה באפליקציות

בטבלה הבאה מוצגים שלושה סוגים של תהליכי אפליקציה והקריאות התואמות ל-Camera Extensions API. ספריות Camera2/X מספקות את ממשקי ה-API האלה, אבל צריך להטמיע כראוי את ספריית הספק כדי לתמוך בתהליכים האלה. נתאר את התהליך בפירוט רב יותר בקטע מאוחר יותר.

תוספי Camera2 תוספים ל-CameraX
זמינות התוספים לשאילתות CameraExtensionCharacteristics .getSupportedExtensions ExtensionsManager. isExtensionAvailable
פרטי השאילתה CameraExtensionCharacteristics. getExtensionSupportedSizes CameraExtensionCharacteristics. getEstimatedCaptureLatencyRangeMillis CameraExtensionCharacteristics. getAvailableCaptureRequestKeys CameraExtensionCharacteristics. getAvailableCaptureResultKeys ExtensionsManager. getEstimatedCaptureLatencyRange

CameraX מטפל בשאר המידע בספרייה.

תצוגה מקדימה וצילום תמונות סטילס כשהתוסף מופעל CameraDevice. createExtensionSession

cameraExtensionsSession. setRepeatingRequest

cameraExtensionsSession. capture

val cameraSelector = ExtensionsManager. getExtensionEnabledCameraSelector

bindToLifecycle(lifecycleOwner, cameraSelector, preview, ...)

מאריך בסיסי

בממשק Basic Extender יש ווקים בכמה מקומות בצינור עיבוד הנתונים של המצלמה. לכל סוג תוסף יש כיתות Extender תואמות ש-OEM צריכים להטמיע.

בטבלה הבאה מפורטות כיתות Extender ש-OEM צריכים להטמיע לכל תוסף:

כיתות הרחבה להטמעה
לילה NightPreviewExtenderImpl.java

NightImageCaptureExtenderImpl.java

HDR HdrPreviewExtenderImpl.java

HdrImageCaptureExtenderImpl.java

Auto AutoPreviewExtenderImpl.java

AutoImageCaptureExtenderImpl.java

Bokeh BokehPreviewExtenderImpl.java

BokehImageCaptureExtenderImpl.java

ריטוש פנים BeautyPreviewExtenderImpl.java

BeautyImageCaptureExtenderImpl.java

בדוגמה הבאה אנחנו משתמשים ב-PreviewExtenderImpl וב-ImageCaptureExtenderImpl כ-placeholders. מחליפים את השמות האלה בשמות של הקבצים בפועל שאתם מטמיעים.

למפצל הבסיסי יש את היכולות הבאות:

  • להחדיר פרמטרים של סשן כשמגדירים את CameraCaptureSession ( onPresetSession).
  • לעדכן אתכם באירועי ההתחלה והסגירה של סשן הצילום, ולשלוח בקשה אחת כדי להודיע ל-HAL על הפרמטרים שהוחזרו (onEnableSession,‏ onDisableSession).
  • להחדיר פרמטרים של תיעוד לבקשה (PreviewExtenderImpl.getCaptureStage,‏ ImageCaptureExtenderImpl.getCaptureStages).
  • הוספת מעבדים לתצוגה מקדימה ועדיין לצילום, שיכולים לעבד את מקור הנתונים YUV_420_888.

נראה איך Camera2/X מפעיל את extensions-interface כדי להשיג את שלושת תהליכי האפליקציה שצוינו למעלה.

תהליך האפליקציה 1: בדיקת הזמינות של התוסף

BasicExtenderAppFlow1

איור 3. תהליך האפליקציה 1 במתאם בסיסי

בתהליך הזה, Camera2/X קורא ישירות לשיטה isExtensionAvailable() של PreviewExtenderImpl וגם של ImageCaptureExtenderImpl בלי לקרוא ל-init(). שתי הכיתות של Extender צריכות להחזיר את הערך true כדי להפעיל את התוספים.

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

תהליך האפליקציה 2: מידע על השאילתה

BasicExtenderAppFlow2

איור 4. תהליך האפליקציה 2 במתאם בסיסי

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

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

  • הגדלים הנתמכים של שטח התצוגה המקדימה ושטח הצילום: הפונקציות ImageCaptureExtenderImpl.getSupportedResolutions ו-PreviewExtenderImpl.getSupportedResolutions מחזירות רשימה של פורמטים של תמונות והגדלים הנתמכים לפורמט ולגודל של שטח הצילום.

  • מפתחות בקשה ותוצאה נתמכים: Camera2/X מפעיל את השיטות הבאות כדי לאחזר מההטמעה שלכם את מפתחות הבקשה והתוצאה הנתמכים לצילום:

    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys
    • ImageCaptureExtenderImpl.getAvailableCapturetResultKeys

ב-Camera2/X, תמיד קוראים ל-init() קודם בכיתות Extender האלה לפני ששולחים שאילתה לקבלת מידע נוסף.

תהליך האפליקציה 3: תצוגה מקדימה/צילום סטילס כשהתוסף מופעל (הטמעת HAL)

BasicExtenderAppFlow3

איור 5. תהליך האפליקציה 3 במתאם בסיסי

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

בתהליך הזה, Camera2/X קורא קודם ל-init() ואז ל-onInit, שמציג הודעה על כך שסשן מצלמה עומד להתחיל עם התוספים שצוינו. אפשר לבצע את עבודת האינטוליזציה הכבדה ב-onInit().

כשמגדירים את CameraCaptureSession, Camera2/X מפעיל את onPresetSession כדי לקבל את פרמטרי הסשן. אחרי שהסשן של הצילום מוגדר בהצלחה, Camera2/X מפעיל את onEnableSession ומחזיר מופע של CaptureStageImpl שמכיל את הפרמטרים של הצילום. Camera2/X שולחת באופן מיידי בקשה אחת עם פרמטרי הצילום האלה כדי להודיע ל-HAL. באופן דומה, לפני סגירת סשן הצילום, Camera2/X מפעילה את onDisableSession ולאחר מכן שולחת בקשה אחת עם הפרמטרים של הצילום שהוחזרו.

הבקשה החוזרת שמופעל על ידי Camera2/X מכילה את פרמטרים הבקשה שמוחזרים על ידי PreviewExtenderImpl.getCaptureStage(). בנוסף, הבקשה לצילום תמונה סטטית מכילה את הפרמטרים שמוחזרים על ידי ImageCaptureExtenderImpl.getCaptureStages().

לבסוף, Camera2/X מפעיל את onDeInit() אחרי סיום סשן המצלמה. אפשר לשחרר משאבים ב-onDeinit().

מעבד תצוגה מקדימה

בנוסף ל-HAL של המצלמה, אפשר גם להטמיע תוספים במעבד.

מטמיעים את PreviewExtenderImpl.getProcessorType כדי לציין את סוג המעבד, כפי שמוסבר בהמשך:

  • PROCESSOR_TYPE_NONE: אין מעבד. התמונות עוברות עיבוד ב-HAL של המצלמה.

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

    הפונקציה PreviewExtenderImpl.getProcessor חייבת להחזיר מופע של RequestUpdateProcessorImpl שמטפל במופע TotalCaptureResult ומחזיר מופע של CaptureStageImpl כדי לעדכן את הבקשה החוזרת. הערך של PreviewExtenderImpl.getCaptureStage() צריך לשקף גם את תוצאת העיבוד ולהחזיר את הערך העדכני ביותר של CaptureStageImpl.

  • PROCESSOR_TYPE_IMAGE_PROCESSOR: הסוג הזה מאפשר להטמיע מעבד לעיבוד תמונות YUV_420_888 ולכתוב את הפלט על גבי משטח PRIVATE.

    צריך להטמיע ולחזור מופע של PreviewImageProcessorImpl ב-PreviewExtenderImpl.getProcessor. המעבד אחראי על עיבוד תמונות הקלט של YUV_420_888. הפלט צריך להירשם בפורמט PRIVATE של קטע מקדים. ב-Camera2/X נעשה שימוש במשטח YUV_420_888 במקום ב-PRIVATE כדי להגדיר את CameraCaptureSession לתצוגה מקדימה.

    התהליך מתואר באיור הבא:

PreviewProcessor

איור 6. תצוגה מקדימה של התהליך באמצעות PreviewImageProcessorImpl

הממשק PreviewImageProcessorImpl הוא תוספת לממשק ProcessImpl, והוא כולל שלוש שיטות חשובות:

  • onOutputSurface(Surface surface, int imageFormat) מגדיר את משטח הפלט של המעבד. עבור PreviewImageProcessorImpl, הערך של imageFormat הוא פורמט פיקסלים, כמו PixelFormat.RGBA_8888.

  • onResolutionUpdate(Size size) מגדיר את הגודל של קובץ הקלט.

  • onImageFormatUpdate(int imageFormat) מגדיר את פורמט התמונה של התמונה להזנה. בשלב הזה, אפשר להגדיר רק את הערך YUV_420_888.

מעבד לצילום תמונות

כדי לצלם תמונות סטילס, אפשר להטמיע מעבד על ידי החזרת מכונה של CaptureProcessorImpl באמצעות ImageCaptureExtenderImpl.getCaptureProcessor. המעבד אחראי לעבד רשימה של תמונות YUV_420_888 ומופעים TotalCaptureResult שצולמו, ולכתוב את הפלט למשטח YUV_420_888.

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

התהליך מתואר בתרשים הבא:

CaptureProcessor

איור 7. תיעוד זרימה באמצעות CaptureProcessorImpl

  1. Camera2/X משתמש בפלטפורמה בפורמט YUV_420_888 לצילום סטילס כדי להגדיר את סשן הצילום. Camera2/X מכין את CaptureProcessorImpl באמצעות קריאה ל-:

    • CaptureProcessorImpl.onImageFormatUpdate() עם YUV_420_888.
    • CaptureProcessorImpl.onResolutionUpdate() עם גודל קובץ הקלט של התמונה.
    • CaptureProcessorImpl.onOutputSurface() עם משטח פלט YUV_420_888.
  2. הפונקציה ImageCaptureExtenderImpl.getCaptureStages מחזירה רשימה של CaptureStageImpl, שבה כל רכיב ממופה למכונה של CaptureRequest עם פרמטרים של צילום שנשלחים על ידי Camera2/X. לדוגמה, אם המערכת מחזירה רשימה של שלוש מכונות CaptureStageImpl, Camera2/X שולחת שלוש בקשות צילום עם פרמטרים תואמים של הצילום באמצעות ה-API captureBurst.

  3. התמונות ומכונות ה-TotalCaptureResult שהתקבלו מקובצים יחד ונשלחים ל-CaptureProcessorImpl לעיבוד.

  4. CaptureProcessorImpl כותב את התמונה של התוצאה (בפורמט YUV_420_888) למשטח הפלט שצוין בקריאה onOutputSurface(). אם צריך, Camera2/X ממירה אותם לתמונות JPEG.

תמיכה במפתחות ובתוצאות של בקשות צילום

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

השיטות הבאות נוספו ל-extensions-interface 1.3.0 כדי לאפשר לכם לחשוף את הפרמטרים שההטמעה שלכם תומכת בהם:

  • הפונקציה ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys() מחזירה את מפתחות הבקשה לתיעוד שנתמכים בהטמעה שלכם.
  • הפונקציה ImageCaptureExtenderImpl.getAvailableCaptureResultKeys() מחזירה את המפתחות של תוצאות הצילום שמכילות את תוצאות הצילום.

אם ה-HAL של המצלמה מעבד את התוסף, Camera2/X מאחזר את תוצאות הצילום ב-CameraCaptureSession.CaptureCallback. עם זאת, אם המעבד מוטמע, המערכת של Camera2/X מאחזרת את תוצאות הצילום ב-ProcessResultImpl, והן מועברות ל-method‏ process() ב-PreviewImageProcessorImpl וב-CaptureProcessorImpl. באחריותכם לדווח על תוצאת הצילום דרך ProcessResultImpl אל Camera2/X.

בדוגמה הבאה מופיעה ההגדרה של ממשק CaptureProcessorImpl. ב-extensions-interface בגרסה 1.3.0 ואילך, הקריאה השנייה של process() מופעלת:

Interface CaptureProcessorImpl extends ProcessorImpl {
    // invoked when extensions-interface version < 1.3.0
    void process(Map<Integer, Pair<Image, TotalCaptureResult>> results);
    // invoked when extensions-interface version >= 1.3.0
    void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
            ProcessResultImpl resultCallback, Executor executor);
}

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

  • מרחק מהתצוגה:
    • CaptureRequest#CONTROL_ZOOM_RATIO
    • CaptureRequest#SCALER_CROP_REGION
  • מקישים כדי להתמקד:
    • CaptureRequest#CONTROL_AF_MODE
    • CaptureRequest#CONTROL_AF_TRIGGER
    • CaptureRequest#CONTROL_AF_REGIONS
    • CaptureRequest#CONTROL_AE_REGIONS
    • CaptureRequest#CONTROL_AWB_REGIONS
  • Flash:
    • CaptureRequest#CONTROL_AE_MODE
    • CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
    • CaptureRequest#FLASH_MODE
  • פיצוי חשיפה:
    • CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION

ב-CameraX Extensions API יש תמיכה מפורשת בכל המפתחות שלמעלה עבור תוספים בסיסיים שמטמיעים את הגרסה 1.2.0 או גרסאות קודמות. בגרסה extensions-interface 1.3.0, גם CameraX וגם Camera2 מכבדים את הרשימה המוחזרת ותומכים רק במפתחות שמופיעים בה. לדוגמה, אם תחליטו להחזיר רק את הערכים CaptureRequest#CONTROL_ZOOM_RATIO ו-CaptureRequest#SCALER_CROP_REGION בהטמעה של 1.3.0, המשמעות היא שהאפליקציה תתמוך רק בהגדלת התצוגה, ולא תהיה אפשרות להשתמש בהקשה להתמקד, בפלאש ובתיקון החשיפות.

Advanced Extender

'מַרחיב מתקדם' הוא סוג של הטמעה של ספק שמבוססת על Camera2 API. סוג המכשיר הזה נוסף ב-extensions-interface 1.2.0. בהתאם ליצרן המכשיר, יכול להיות שהתוספים יוטמעו בשכבת האפליקציה, בהתאם לגורמים הבאים:

  • הגדרת סטרימינג בהתאמה אישית: הגדרת סטרימינג בהתאמה אישית, כמו שידור RAW, או שימוש בכמה שידורים למזהים פיזיים שונים של מצלמות.

  • יכולת לשלוח בקשות ל-Camera2: תמיכה בלוגיקה מורכבת של אינטראקציה שיכולה לשלוח בקשות צילום עם פרמטרים על סמך התוצאות של בקשות קודמות.

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

הקבצים להטמעה

כדי לעבור להטמעה של מרחיב מתקדם, השיטה isAdvancedExtenderImplemented() ב-ExtensionVersionImpl חייבת להחזיר את הערך true. לכל סוג תוסף, יצרני ציוד מקורי צריכים להטמיע את המחלקות המתאימות של Extender. קובצי ההטמעה של Advanced Extender נמצאים בחבילה advanced.

כיתות Extender להטמעה
לילה advanced/NightAdvancedExtenderImpl.java
HDR advanced/HdrAdvancedExtenderImpl.java
Auto advanced/AutoAdvancedExtenderImpl.java
Bokeh advanced/BokehAdvancedExtenderImpl.java
ריטוש פנים advanced/BeautyAdvancedExtenderImpl.java

בדוגמה הבאה אנחנו משתמשים ב-AdvancedExtenderImpl כ-placeholder. מחליפים אותו בשם של קובץ Extender של התוסף שמטמיעים.

נראה איך Camera2/X מפעיל את extensions-interface כדי להשיג את שלושת תהליכי האפליקציה.

תהליך הפעלת האפליקציה 1: בדיקת הזמינות של התוספים

AdvancedAppFlow1

איור 8. תהליך האפליקציה 1 ב-Advanced Extender

קודם כול, האפליקציה בודקת אם יש תמיכה בסיומת הנתונה.

תהליך האפליקציה 2: מידע על השאילתה

AdvancedAppFlow2

איור 9. תהליך האפליקציה 2 ב-Advanced Extender

אחרי קריאה ל-AdvancedExtenderImpl.init(), האפליקציה יכולה להריץ שאילתה לפי המידע הבא ב-AdvancedExtenderImpl:

  • זמן האחזור המשוער לצילום תמונה סטילס: הפונקציה AdvancedExtenderImpl.getEstimatedCaptureLatencyRange() מחזירה את טווח זמן האחזור לצילום תמונה סטילס, כדי שהאפליקציה תוכל להעריך אם כדאי להפעיל את התוסף בתרחיש הנוכחי.

  • רזולוציות נתמכות לתצוגה מקדימה ולצילום תמונות סטילס:

    • הפונקציה AdvancedExtenderImpl.getSupportedPreviewOutputResolutions() מחזירה מפה של פורמט התמונה לרשימה של הגדלים הנתמכים לפורמט ולגודל של שטח התצוגה המקדימה. יצרני ציוד מקורי חייבים לתמוך לפחות בפורמט PRIVATE.

    • הפונקציה AdvancedExtenderImpl.getSupportedCaptureOutputResolutions() מחזירה את הפורמטים והגדלים הנתמכים של שטח הצילום. יצרני ציוד מקורי חייבים לתמוך בפלט בפורמט JPEG ובפורמט YUV_420_888.

    • הפונקציה AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions() מחזירה את הגדלים הנתמכים של מקור נתונים נוסף מסוג YUV_420_888 לניתוח תמונות. אם אין תמיכה בשטח הפנים של YUV לניתוח תמונות, הפונקציה getSupportedYuvAnalysisResolutions() אמורה להחזיר את הערך null או רשימה ריקה.

  • מפתחות/תוצאות של בקשות צילום זמינים (נוספו ב-extensions-interface 1.3.0):‏ Camera2/X מפעיל את השיטות הבאות כדי לאחזר מההטמעה שלכם את מפתחות התוצאות ומפתחות הבקשות הנתמכים של הצילום:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys

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

תהליך האפליקציה 3: תצוגה מקדימה/צילום סטילס כשהתוסף מופעל

AdvancedAppFlow3

איור 10. תהליך האפליקציה 3 ב-Advanced Extender

בתרשים שלמעלה מוצג התהליך הראשי להתחלת התצוגה המקדימה ולצילום תמונות סטילס לסוג 'מגבר מתקדם'. נסביר על כל שלב.

  1. מכונה של SessionProcessorImpl

    הליבה של הטמעת Advanced Extender נמצאת ב-SessionProcessorImpl, שמספק הגדרות מותאמות אישית של סשנים ושולח בקשות צילום כדי להפעיל את הבקשה לתצוגה המקדימה ואת הבקשה לצילום סטילס. AdvancedExtenderImpl.createSessionProcessor() מופעל כדי להחזיר את המופע של SessionProcessorImpl.

  2. initSession

    SessionProcessorImpl.initSession() מאתחלת את הסשן של התוסף. כאן מקצים משאבים ומחזירים הגדרת סשן לצורך הכנת CameraCaptureSession.

    בפרמטרים של הקלט, Camera2/X מציין את הגדרות פלט הפנים לתצוגה מקדימה, לצילום סטילס ולניתוח תמונות YUV אופציונלי. הגדרת הפלט של שטח התצוגה (OutputSurfaceImpl) מכילה את שטח התצוגה, הגודל ופורמט התמונה שאוחזרים באמצעות השיטות הבאות ב-AdvancedExtenderImpl:

    • getSupportedPreviewOutputResolutions()
    • getSupportedCaptureOutputResolutions()
    • getSupportedYuvAnalysisResolutions()

    צריך להחזיר מכונה של Camera2SessionConfigImpl, שמכילה רשימה של מכונות Camera2OutputConfigImpl ואת פרמטרי הסשן ששימשו להגדרת CameraCaptureSession. אתם אחראים להציג את התמונות הנכונות מהמצלמה בפלט של משטחי הפלט שהועברו על ידי Camera2/X. ריכזנו כאן כמה אפשרויות להפעלת הפלט:

    • עיבוד ב-HAL של המצלמה: אפשר להוסיף ישירות את משטחי הפלט ל-CameraCaptureSession באמצעות הטמעה של SurfaceOutputConfigImpl. כך מגדירים את משטח הפלט שסופק לצינור עיבוד הנתונים של המצלמה ומאפשרים ל-HAL של המצלמה לעבד את התמונה.
    • עיבוד של משטח ביניים מסוג ImageReader (RAW,‏ YUV וכו'): מוסיפים את המשטחים הביניים מסוג ImageReader ל-CameraCaptureSession באמצעות מכונה מסוג ImageReaderOutputConfigImpl.

      צריך לעבד את התמונות הביניים ולכתוב את תמונת התוצאה על פני הפלט.

    • שימוש בשיתוף של משטח ב-Camera2: כדי לשתף משטח עם משטח אחר, מוסיפים מופע Camera2OutputConfigImpl לשיטה getSurfaceSharingOutputConfigs() של מופע Camera2OutputConfigImpl אחר. הפורמט והגודל של פני השטח חייבים להיות זהים.

    לכל Camera2OutputConfigImpl, כולל SurfaceOutputConfigImpl ו-ImageReaderOutputConfigImpl, צריך להיות מזהה ייחודי (getId()) שמשמש לציון פלטפורמת היעד ולאחזור התמונה מ-ImageReaderOutputConfigImpl.

  3. onCaptureSessionStart ו-RequestProcessorImpl

    כש-CameraCaptureSession מתחיל לפעול והמסגרת של Camera מפעילה את onConfigured(), ‏Camera2/X מפעילה את SessionProcessorImpl.onCaptureSessionStart() עם מעטפת הבקשה של Camera2‏ RequestProcessImpl. ב-Camera2/X מוטמעת RequestProcessImpl, שמאפשרת להריץ את בקשות הצילום ולאחזר תמונות אם נעשה שימוש ב-ImageReaderOutputConfigImpl.

    ממשקי ה-API של RequestProcessImpl דומים לממשקי ה-API של Camera2‏ CameraCaptureSession מבחינת ביצוע הבקשות. ההבדלים הם:

    • הממשק של היעד מצוין לפי המזהה של המכונה Camera2OutputConfigImpl.
    • היכולת לאחזר את התמונה של ImageReader.

    אפשר להפעיל את RequestProcessorImpl.setImageProcessor() עם מזהה Camera2OutputConfigImpl ספציפי כדי לרשום מכונה של ImageProcessorImpl לקבלת תמונות.

    המכונה RequestProcessImpl הופכת ללא חוקית אחרי ש-Camera2/X קורא ל-SessionProcessorImpl.onCaptureSessionEnd().

  4. התחלת התצוגה המקדימה וצילום תמונה

    בהטמעה של Extender מתקדם, אפשר לשלוח בקשות צילום דרך הממשק RequestProcessorImpl. כדי להתחיל את הבקשה החוזרת לתצוגה המקדימה או את רצף הצילום של התמונות הסטטיות, מערכת Camera2/X תודיע לכם על כך על ידי קריאה ל-SessionProcessorImpl#startRepeating ול-SessionProcessorImpl#startCapture, בהתאמה. כדי לענות על הבקשות האלה לצילומי תצוגה מקדימה ולצילומי סטילס, צריך לשלוח בקשות צילום.

    Camera2/X מגדיר גם את הפרמטרים של בקשת הצילום באמצעות SessionProcessorImpl#setParameters. צריך להגדיר את פרמטרים הבקשה האלה (אם הפרמטרים נתמכים) גם בבקשות החוזרות וגם בבקשות היחידניות.

    חובה לתמוך ב-CaptureRequest.JPEG_ORIENTATION וב-CaptureRequest.JPEG_QUALITY לפחות. extensions-interface 1.3.0 תומך במפתחות של בקשות ותוצאות, שנחשפים באמצעות השיטות הבאות:

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys()
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys()

    כשהמפתחים מגדירים את המפתחות ברשימה getAvailableCaptureRequestKeys, צריך להפעיל את הפרמטרים ולוודא שתוצאת הצילום מכילה את המפתחות ברשימה getAvailableCaptureResultKeys.

  5. startTrigger

    SessionProcessorImpl.startTrigger() מופעל כדי להפעיל את הטריגר, למשל CaptureRequest.CONTROL_AF_TRIGGER ו-CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER. אפשר להתעלם מכל מפתחות הבקשה לתיעוד שלא פורסמו ב-AdvancedExtenderImpl.getAvailableCaptureRequestKeys().

    התמיכה ב-startTrigger() קיימת מאז גרסת extensions-interface 1.3.0. היא מאפשרת לאפליקציות להטמיע את התכונות 'הקשה להתמקד' ו'הבזק' באמצעות תוספים.

  6. ניקוי

    כשמסיימים סשן צילום, SessionProcessorImpl.onCaptureSessionEnd() מופעל לפני סגירת CameraCaptureSession. אחרי סגירת סשן הצילום, deInitSession() מבצע את הניקוי.

תמיכה בתצוגה מקדימה, בצילום סטילס ובניתוח תמונות

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

עבור סוג התוסף 'מרחיב בסיסי', ללא קשר להפעלת התוסף לתצוגה מקדימה, צריך להטמיע גם את ImageCaptureExtenderImpl וגם את PreviewExtenderImpl לתוסף נתון. לרוב, אפליקציה משתמשת גם בזרם YUV כדי לנתח את תוכן התמונה, למשל כדי למצוא קודי QR או טקסט. כדי לתמוך טוב יותר בתרחיש לדוגמה הזה, צריך לתמוך בשילוב של מקור נתונים עם תצוגה מקדימה, צילום סטילס ומקור נתונים מסוג YUV_420_888 להגדרת CameraCaptureSession. כלומר, אם מטמיעים מעבד, צריך לתמוך בשילוב של שלושה מקורות נתונים מסוג YUV_420_888.

ב-Advanced Extender, ‏Camera2/X מעבירה שלוש פלטפורמות פלט לקריאה SessionProcessorImpl.initSession(). פלטפורמות הפלט האלה מיועדות לתצוגה מקדימה, לצילום סטילס ולניתוח תמונות, בהתאמה. חשוב לוודא שפני השטח של הפלט של התצוגה המקדימה וצילום הסטילס מציגים את הפלט הנכון. עם זאת, חשוב לוודא שהיא פועלת רק כשהיא לא null, עבור פלט ניתוח התמונה. אם ההטמעה שלכם לא תומכת בשידור של ניתוח התמונות, תוכלו להחזיר רשימה ריקה ב-AdvancedExtenderImpl.getSupportedYuvAnalysisResolutions(). כך מוודאים שפני השטח של הפלט של ניתוח התמונה תמיד יהיו null ב-SessionProcessorImpl.initSession().

תמיכה בצילום וידאו

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

אנחנו בודקים את האפשרות להוסיף תמיכה במשטחים של MediaCodec ושל MediaRecorder.

מטא-נתונים ספציפיים לתוסף

ב-Android מגרסה 14 ואילך, מטא-נתונים ספציפיים לתוסף מאפשרים ללקוחות של תוסף המצלמה להגדיר ולקבל את ההגדרות והתוצאות של בקשות הצילום הספציפיות לתוסף. באופן ספציפי, לקוחות של תוסף מצלמה יכולים להשתמש בפרמטר EXTENSION_STRENGTH של בקשת הצילום כדי לשלוט בעוצמת התוסף, ובתוצאת הצילום EXTENSION_CURRENT_TYPE כדי לציין את סוג התוסף שהופעל.

תיעוד בקשות

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

  • BOKEH: קובע את מידת הטשטוש.
  • HDR ו-NIGHT: קובעים את מספר התמונות שמשולבות ואת הבהירות של התמונה הסופית.
  • FACE_RETOUCH: קובע את מידת השיפורים הקוסמטיים וההחלקות העור.

הטווח הנתמך של הפרמטר EXTENSION_STRENGTH הוא בין 0 ל-100, כאשר הערך 0 מציין שאין עיבוד של התוסף או העברה פשוטה, והערך 100 מציין את עוצמת התוסף המקסימלית של אפקט העיבוד.

כדי להוסיף תמיכה ב-EXTENSION_STRENGTH, צריך להשתמש בממשקי ה-API של הפרמטרים הספציפיים לספק, שהוצגו בגרסה 1.3.0 של ממשק ספריית התוספים. מידע נוסף זמין במאמר getAvailableCaptureRequestKeys().

תיעוד התוצאות

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

תוספים מסוג AUTO עוברים באופן דינמי בין סוגי תוספים כמו HDR ו-NIGHT בהתאם לתנאי הסצנה, ולכן אפליקציות של תוספים למצלמה יכולות להשתמש ב-EXTENSION_CURRENT_TYPE כדי להציג מידע על התוסף הנוכחי שנבחר על ידי התוסף AUTO.

אומדן זמן האחזור לצילום תמונה סטילס בזמן אמת

ב-Android מגרסה 14 ואילך, לקוחות של תוסף מצלמה יכולים להריץ שאילתות בזמן אמת כדי לקבל אומדנים של זמן האחזור לצילום תמונות סטילס, על סמך תנאי הסביבה והסצנה, באמצעות getRealtimeStillCaptureLatency(). השיטה הזו מספקת אומדנים מדויקים יותר מהשיטה הסטטית getEstimatedCaptureLatencyRangeMillis(). על סמך אומדן זמן האחזור, האפליקציות יכולות להחליט לדלג על עיבוד התוספים או להציג אינדיקציה כדי להודיע למשתמשים על פעולה שנמשכת זמן רב.

CameraExtensionSession.StillCaptureLatency latency;

latency = extensionSession.getRealtimeStillCaptureLatency();

// The capture latency from ExtensionCaptureCallback#onCaptureStarted() until ExtensionCaptureCallback#onCaptureProcessStarted().

latency.getCaptureLatency();

// The processing latency from  ExtensionCaptureCallback#onCaptureProcessStarted() until  the processed frame returns to the client.

latency.getProcessingLatency();

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

תיעוד קריאות חוזרות (callbacks) של התקדמות העיבוד

ב-Android מגרסה 14 ואילך, לקוחות של תוסף מצלמה יכולים לקבל קריאות חוזרות (callbacks) לגבי התקדמות של פעולות עיבוד ממושכות של צילומי סטילס. אפליקציות יכולות להציג למשתמשים את ההתקדמות הנוכחית כדי לשפר את חוויית המשתמש הכוללת.

כדי לשלב את התכונה הזו באפליקציות, אפשר להשתמש בקוד הבא:

import android.hardware.camera2.CameraExtensionSession.
ExtensionCaptureCallback;

{
…
  class AppCallbackImpl extends ExtensionCaptureCallback {
…
    @Override
    public void onCaptureProcessProgressed(
      @NonNull CameraExtensionSession session,
      @NonNull CaptureRequest request,
      @IntRange(from = 0, to = 100) int progress) {
      // Update app UI with current progress
    }
  }
…
}

כדי לתמוך בקריאות חזרה (callbacks) עם עדכונים על התקדמות העיבוד של התמונות, ההטמעה של ספק התוסף צריכה להפעיל את קריאות החזרה הבאות עם ערך ההתקדמות הנוכחי:

צילום סטטי של 'צפייה לאחר צפייה'

ב-Android מגרסה 14 ואילך, תוספים למצלמה יכולים לספק תצוגה מקדימה (תמונה של התצוגה המקדימה) באמצעות setPostviewOutputConfiguration. כדי לשפר את חוויית המשתמש, אפליקציות יכולות להציג תמונה של פוסט-וידאו כתמונה זמנית כשיש לתוסף זמן אחזור ארוך יותר לעיבוד, ולהחליף את התמונה כשהתמונה הסופית תהיה זמינה. אפליקציות יכולות להגדיר ולשלוח בקשות לצילום לאחר צפייה באמצעות קוד העזרה הבא:

{
…
if (!CameraExtensionCharacteristics.isPostviewAvailable()) {
    continue;
}
…
ExtensionSessionConfiguration extensionConfiguration = new
        ExtensionSessionConfiguration(
                CameraExtensionCharacteristics.EXTENSION_NIGHT,
                outputConfig,
                backgroundExecutor,
                extensionSessionStateCallback
    );

extensionConfiguration.setPostviewOutputConfiguration(
    postviewImageOutput);
…
CaptureRequest.Builder captureRequestBuilder =
    cameraDevice.createCaptureRequest(
        CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequestBuilder.addTarget(stillImageReader.getSurface());
captureRequestBuilder.addTarget(postviewImageSurface);

CaptureRequest captureRequest = captureRequestBuilder.build();
…
}

כדי לתמוך בצילום תמונות סטילס לאחר הצפייה, ההטמעה של הספק צריכה לכלול את הרכיבים הבאים:

תמיכה בפלט של SurfaceView

ב-Android מגרסה 14 ואילך, לקוחות של תוסף מצלמה יכולים להשתמש בנתיבים שמותאמים לשימוש באנרגיה ובביצועים לעיבוד תצוגה מקדימה, על ידי רישום מכונה של SurfaceView לתצוגה המקדימה של בקשות חוזרות.

כדי לתמוך בפלט של SurfaceView, ההטמעה של תוסף הספק צריכה לאפשר סטרימינג של תצוגה מקדימה ופלט שלה למכונות SurfaceView. כדי לוודא שיש תמיכה בכך, מריצים את מודול ה-CTS‏ SurfaceViewExtensionPreviewTest.java.

סוגי סשנים ספציפיים לספק

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

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

כדי לבחור סוג סשן ספציפי לספק, צריך להטמיע את הקוד הבא בספריות התוספים: * ExtenderStateListener.onSessionType() לתוספים בסיסיים * Camera2SessionConfigImpl.getSessionType() לתוספים מתקדמים

היסטוריית הגרסאות של ממשק התוספים

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

גרסה תכונות שנוספו
1.0.0
  • אימות הגרסה
    • ExtensionVersionImpl
  • הרחבה בסיסית
    • PreviewExtenderImpl
    • ImageCaptureExtenderImpl
    • Processor
      • PreviewImageProcessorImpl
      • CaptureProcessorImpl
      • RequestUpdateProcessorImpl
1.1.0
  • אתחול הספרייה
    • InitializerImpl
  • חשיפת הרזולוציות הנתמכות
    • PreviewExtenderImpl.getSupportedResolutions
    • ImageCaptureExtenderImpl.getSupportedResolutions
1.2.0
  • AdvancedExtender
    • AdvancedExtenderImpl
    • SessionProcessorImpl
  • אחזור זמן משוער לצילום
    • ImageCaptureExtenderImpl.getEstimatedCaptureLatencyRange
1.3.0
  • חשיפת מפתחות תוצאות או מפתחות של בקשות צילום שנתמכים
    • ImageCaptureExtenderImpl.getAvailableCaptureRequestKeys וגם getAvailableCaptureResultKeys
    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys וגם getAvailableCaptureResultKeys
    • שיחה חדשה ב-process() עם ProcessResultImpl ב-PreviewImageProcessorImpl וב-CaptureProcessorImpl
    • בקשה לקבלת תמיכה בסוג הגורם המפעיל
      • AdvancedExtenderImpl.startTrigger
1.4.0
  • מטא-נתונים ספציפיים לתוסף
  • אומדני זמן האחזור הדינמי לצילום תמונות סטילס
  • תיעוד קריאות חוזרות (callbacks) של התקדמות העיבוד
  • צילום סטטי של 'צפייה לאחר צפייה'
  • תמיכה בפלט SurfaceView
  • סוגי סשנים ספציפיים לספק

הטמעת עזר

הטמעות הספריות של ספקי ה-OEM לדוגמה זמינות ב-frameworks/ex.

  • advancedSample: הטמעה בסיסית של Advanced Extender.

  • sample: הטמעה בסיסית של Basic Extender.

  • service_based_sample: הטמעה שמראה איך לארח תוספים למצלמה ב-Service. ההטמעה הזו כוללת את הרכיבים הבאים:

    • oem_library: ספריית OEM של Camera Extensions ל-Camera2 ול-CameraX Extensions API שמטמיעה את Extensions-Interface. הוא פועל כמעבר שמעביר את הקריאות מ-Extensions-Interface לשירות. הספרייה הזו מספקת גם קובצי AIDL וקלאסיות עטיפה (wrapper) לצורך תקשורת עם השירות.

      התכונה 'מתחבר מתקדם' מופעלת כברירת מחדל. כדי להפעיל את מרחיב ה-Basic, משנים את הערך של ExtensionsVersionImpl#isAdvancedExtenderImplemented ל-false.

    • extensions_service: הטמעה לדוגמה של שירות התוספים. מוסיפים את ההטמעה כאן. הממשק להטמעה בשירות דומה לממשק של Extensions-Interface. לדוגמה, הטמעת IAdvancedExtenderImpl.Stub מבצעת את אותן פעולות כמו AdvancedExtenderImpl. ImageWrapper ו-TotalCaptureResultWrapper נדרשים כדי לאפשר חלוקה של Image ו-TotalCaptureResult.

הגדרת ספריית הספק במכשיר

ספריית הספק של יצרן הציוד המקורי לא מובנית באפליקציה, אלא נטענת מהמכשיר בזמן הריצה על ידי Camera2/X. ב-CameraX, התג <uses-library> מצהיר שהספרייה androidx.camera.extensions.impl, שמוגדרת בקובץ AndroidManifest.xml של הספרייה camera-extensions, היא תלות של CameraX וצריך לטעון אותה בזמן הריצה. ב-Camera2, המסגרת טוענת שירות של תוספים שמצהיר גם ש-<uses-library> טוען את אותה ספרייה androidx.camera.extensions.impl בזמן הריצה.

כך אפליקציות צד שלישי שמשתמשות בתוספים יכולות לטעון באופן אוטומטי את ספריית הספק של ה-OEM. הספרייה של יצרן הציוד המקורי מסומנת כאופציונלית, כך שאפליקציות יכולות לפעול במכשירים שלא כוללים את הספרייה. כשאפליקציה מנסה להשתמש בתוסף מצלמה, המערכת של Camera2/X מטפלת בהתנהגות הזו באופן אוטומטי, כל עוד יצרן המכשיר מוסיף את ספריית ה-OEM למכשיר כדי שהאפליקציה תוכל לזהות אותה.

כדי להגדיר את ספריית ה-OEM במכשיר:

  1. מוסיפים קובץ הרשאות, שנדרש בתג <uses-library>, בפורמט הבא: /etc/permissions/ANY_FILENAME.xml. לדוגמה, /etc/permissions/camera_extensions.xml. הקבצים בתיקייה הזו מספקים מיפוי של הספרייה שצוינה ב-<uses-library> לנתיב הקובץ בפועל במכשיר.
  2. השתמשו בדוגמה הבאה כדי להוסיף את הפרטים הנדרשים לקובץ.

    • הערך של name חייב להיות androidx.camera.extensions.impl כי זו הספרייה ש-CameraX מחפשת.
    • file הוא הנתיב המוחלט של הקובץ שמכיל את הטמעת התוספים (לדוגמה, /system/framework/androidx.camera.extensions.impl.jar).
    <?xml version="1.0" encoding="utf-8"?>
    <permissions>
        <library name="androidx.camera.extensions.impl"
                 file="OEM_IMPLEMENTED_JAR" />
    </permissions>
    

ב-Android 12 ואילך, במכשירים שתומכים בתוספים של CameraX צריך להגדיר את המאפיין ro.camerax.extensions.enabled לערך true, כדי לאפשר לשלוח שאילתה לגבי תמיכה בתוספים. כדי לעשות זאת, מוסיפים את השורה הבאה לקובץ של יצרן המכשיר:

PRODUCT_VENDOR_PROPERTIES += \
    ro.camerax.extensions.enabled=true \

אימות

כדי לבדוק את ההטמעה של ספריית הספק של ה-OEM בשלב הפיתוח, תוכלו להשתמש באפליקציית הדוגמה שבכתובת androidx-main/camera/integration-tests/extensionstestapp/, שמפעילה תוספים שונים של ספקים.

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

מצב 'סצנה מורחבת' לעומת תוספי מצלמה

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

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

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

מומלץ לחשוף את אפקט הבוקה גם באמצעות מצב התמונה המורחב וגם באמצעות התוספים למצלמה, כי יכול להיות שאפליקציות יעדיפו להשתמש בממשק API מסוים כדי להפעיל את אפקט הבוקה. מומלץ להשתמש קודם במצב התמונה המורחב, כי זו הדרך הגמישה ביותר שבה אפליקציות יכולות להפעיל את התכונה 'בוקה'. לאחר מכן תוכלו להטמיע את ממשק התוספים של המצלמה על סמך מצב התמונה המורחב. אם קשה להטמיע את אפקט הבוקה ב-HAL של המצלמה, למשל כי נדרש מעבד פוסט-עיבוד שפועל בשכבת האפליקציה כדי לעבד תמונות, מומלץ להטמיע את התוסף של הבוקה באמצעות ממשק התוספים של המצלמה.

שאלות נפוצות

האם יש הגבלות על רמות ה-API?

כן. זה תלוי בחבילת התכונות של Android API שנדרשת להטמעה של ספריית הספק של ה-OEM. לדוגמה, ExtenderStateListener.onPresetSession() משתמש בקריאה SessionConfiguration.setSessionParameters() כדי להגדיר קבוצת בסיס של תגים. הקריאה הזו זמינה רק ברמת API 28 ואילך. פרטים על שיטות ממשק ספציפיות זמינים במאמרי העזרה של API.