תוספי מצלמה

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

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

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

ארכיטקטורה

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

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

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

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

  • 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

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

  • 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 כולל שיטה 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.

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

אימות גרסה

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

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

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

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

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

ל-Basic Extender יש את היכולות הבאות:

  • הוספת פרמטרים של סשן כשמגדירים את 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 ב-Basic Extender

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

  • Still capture latency range: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 surface.
  2. ImageCaptureExtenderImpl.getCaptureStages מחזירה רשימה של CaptureStageImpl, כאשר כל רכיב ממופה למופע CaptureRequest עם פרמטרים של לכידה שנשלחים על ידי Camera2/X. לדוגמה, אם הפונקציה מחזירה רשימה של שלושה מופעים של CaptureStageImpl, ‏ Camera2/X שולחת שלוש בקשות צילום עם פרמטרים מתאימים של צילום באמצעות ה-API‏ captureBurst.

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

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

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

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

הוספנו לגרסה 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.

Extender classes to implement
לילה 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

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

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

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() לתוספים מתקדמים

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

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

גרסה תכונות שנוספו
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. השדות ImageWrapper ו-TotalCaptureResultWrapper נדרשים כדי להפוך את Image ו-TotalCaptureResult לניתנים להעברה.

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

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