תוספי מצלמה

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

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

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

ארכיטקטורה

בתרשים הבא מתוארת הארכיטקטורה של הממשק Camera Extensions או extensions-interface: ארכיטקטורה

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

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

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

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

קובצי 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

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

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

כיתות להארכת הלילה (מטמיעים את התכונה אם היא נתמכת)

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

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

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

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

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

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

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

Utilities (אופציונלי, אפשר למחוק)

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

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

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

Mainflow

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

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

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

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

    ל-InitializerImpl יש method init() שמאחלת את ספריית הספק. האתחול של Camera2/X מסתיים לפני הגישה למחלקות Extender.

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

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

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

    בתוסף Night, מופעלות הדוגמאות הבאות של מחלקות Extender עבור סוג Basic Extender:

    • NightImageCaptureExtenderImpl.java
    • NightPreviewExtenderImpl.java

    ובסוג Advanced Extender:

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

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

  5. מאחלים את המאריך עם פרטי המצלמה:

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

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

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

  7. הפעלת התוסף ב-Extender:

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

    בסוג Advanced Extender, ‏ Camera2/X מתקשר עם SessionProcessorImpl כדי להפעיל את התוסף. ‫Camera2/X מאחזר את מופע SessionProcessorImpl על ידי קריאה ל-createSessionProcessor() ב-Extender.

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

אימות גרסה

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

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

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

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

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

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

תאימות קדימה

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

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

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

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

צריך להטמיע את InitializerImpl מגרסה extensions-interface 1.1.0. ‫Camera2/X מדלג על שלב האתחול של הספרייה אם ספריית הספק של יצרן הציוד המקורי מטמיעה את 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 ולשלוח בקשות צילום לפי הצורך.

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

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

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

Hooks בצינור העברת הנתונים של המצלמה
  • 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

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

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

Extender classes to implement
לילה NightPreviewExtenderImpl.java

NightImageCaptureExtenderImpl.java

HDR HdrPreviewExtenderImpl.java

HdrImageCaptureExtenderImpl.java

אוטומטי AutoPreviewExtenderImpl.java

AutoImageCaptureExtenderImpl.java

Bokeh BokehPreviewExtenderImpl.java

BokehImageCaptureExtenderImpl.java

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

BeautyImageCaptureExtenderImpl.java

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

התכונה 'הארכה בסיסית' כוללת את היכולות הבאות:

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

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

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

BasicExtenderAppFlow1

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

בתהליך הזה, 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 ב-Basic Extender

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

    getCaptureStages()
  3. התמונות והמופעים של TotalCaptureResult שמתקבלים נארזים יחד ונשלחים אל CaptureProcessorImpl לעיבוד.

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

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

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

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

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

אם רכיב HAL של המצלמה מעבד את התוסף, Camera2/X מאחזר את תוצאות הצילום ב-CameraCaptureSession.CaptureCallback. אבל אם המעבד מיושם, אז Camera2/X מאחזר את תוצאות הצילום ב-ProcessResultImpl, שמועבר למתודה 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

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

מאריך מתקדם

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

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

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

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

קבצים להטמעה

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

כיתות להרחבה להטמעה
לילה advanced/NightAdvancedExtenderImpl.java
HDR advanced/HdrAdvancedExtenderImpl.java
אוטומטי 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() מחזירה מיפוי של פורמט התמונה לרשימת הגדלים שנתמכים עבור פורמט וגודל של משטח תצוגה מקדימה. יצרני ציוד מקורי (OEM) צריכים לתמוך בפורמט PRIVATE לפחות.

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

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

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

    • AdvancedExtenderImpl.getAvailableCaptureRequestKeys
    • AdvancedExtenderImpl.getAvailableCaptureResultKeys

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

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

AdvancedAppFlow3

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

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

  1. SessionProcessorImpl instance

    ההטמעה העיקרית של 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 framework מפעיל את onConfigured(), ‏ Camera2/X מפעיל את SessionProcessorImpl.onCaptureSessionStart() עם ה-Camera2 request wrapper‏ RequestProcessImpl. ‫Camera2/X מטמיע את RequestProcessImpl, שמאפשר לכם להריץ את בקשות הצילום ולאחזר תמונות אם נעשה שימוש ב-ImageReaderOutputConfigImpl.

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

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

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

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

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

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

תצוגה מקדימה של תמיכה, צילום תמונות וניתוח תמונות

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

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

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

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

הארכיטקטורה הנוכחית של Camera Extension תומכת רק בתרחישי השימוש של תצוגה מקדימה וצילום תמונות סטילס. אנחנו לא תומכים בהפעלת התוסף בפלטפורמות 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();

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

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

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

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

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

}

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

צילום מסך של פוסט

ב-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. כדי לוודא שיש תמיכה, מריצים את מודול SurfaceViewExtensionPreviewTest.javaCTS.

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

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

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

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

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

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

Version תכונות שנוספו
1.0.0
  • אימות גרסה
    • ExtensionVersionImpl
  • Basic Extender
    • 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
  • מטא-נתונים ספציפיים לתוסף
  • הערכות של זמן האחזור בצילום תמונות סטילס דינמיות
  • קריאות חוזרות (callback) לדיווח על התקדמות העיבוד
  • צילום מסך של פוסט
  • תמיכה בפלט של SurfaceView
  • סוגי סשנים ספציפיים לספק

הטמעה לדוגמה

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

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

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

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

    • oem_library: ספריית OEM של תוספים למצלמה עבור Camera2 ו-CameraX Extensions APIs שמטמיעה את Extensions-Interface. הוא פועל כצינור להעברת נתונים ומעביר שיחות מ-Extensions-Interface לשירות. הספרייה הזו מספקת גם קובצי AIDL ומחלקות wrapper כדי לתקשר עם השירות.

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

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

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

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

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

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

אימות

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

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

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

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

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

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

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

שאלות נפוצות

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

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