סטרימינג ממצלמה בו-זמנית

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

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

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

כל מכשיר מצלמה שמפורסם דרך getConcurrentStreamingCameraIds() חייב לתמוך בהגדרות הבאות להבטחת שידורים בו-זמניים.

יעד 1 יעד 2
סוג גודל מקסימלי סוג גודל מקסימלי תרחישים לדוגמה
YUV s1440p עיבוד תמונות או סרטונים בתוך האפליקציה
PRIV s1440p ניתוח של עינית המצלמה באפליקציה
JPEG s1440p אי אפשר לצלם תמונות סטילס במסך העיון
YUV / PRIV s720p JPEG s1440p צילום סטנדרטי של תמונות סטילס
YUV / PRIV s720p YUV / PRIV s1440p סרטון באפליקציה או עיבוד עם תצוגה מקדימה

במכשירים עם יכולת MONOCHROME (CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES כולל CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) שתומכים ב-Y8, חייבת להיות תמיכה בהחלפת שידורי YUV ב-Y8 בכל השילובים המובטחים של שידורים.

הערך של s720p מתייחס ל-720p‏ (1280 x 720) או לרזולוציה המקסימלית הנתמכת בפורמט הספציפי שמוחזר על ידי StreamConfigurationMap.getOutputSizes(). הערך של s1440p מתייחס ל-1440p‏ (1920 x 1440) או לרזולוציה המקסימלית הנתמכת בפורמט הספציפי שמוחזר על ידי StreamConfigurationMap.getOutputSizes(). במכשירים שהיכולות שלהם לא כוללות את ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE, חייבת להיות תמיכה לפחות בשידור Y16 אחד, Dataspace::DEPTH ברזולוציית sVGA, במהלך פעולה בו-זמנית. רזולוציית sVGA היא הרזולוציה הקטנה מבין שתי הרזולוציות הבאות:

  • רזולוציית הפלט המקסימלית לפורמט הנתון
  • 640 x 480

הטמעה

כדי לאפשר לאפליקציות לשלוח שאילתה למכשיר כדי לקבוע אם המצלמות שלו תומכות בסטרימינג בו-זמנית, צריך להטמיע את ממשק ה-HAL‏ ICameraProvider@2.6, שכולל את השיטות הבאות:

להטמעה לדוגמה של ממשק ה-HAL‏ ICameraProvider@2.6, אפשר לעיין בספריית ה-HAL של המצלמה המשוכפלת בכתובת EmulatedCameraProviderHWLImpl.cpp.

אימות

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

בעיות בהקצאות משאבים

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

תרחיש לדוגמה

התרחיש הבא מדגים את הבעיה הזו.

בעיה

במכשיר מוגדרות ההגדרות הבאות:

  • מזהה המצלמה 0 הוא מצלמה לוגית שמגובת על ידי מצלמה רחבה ומצלמת Ultrawide, שכל אחת מהן תופסת משאב ISP אחד.
  • מזהה המצלמה 1 הוא מצלמה שמשתמשת במשאב ISP אחד.

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

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

הפתרון

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

כדי להטמיע את הפתרון הזה, מבצעים את העדכונים הבאים ב-provider@2.6::ICameraProvider::getConcurrentCameraStreamingCameraIds.

  • כדי להפעיל כמה מצלמות בו-זמנית, צריך לחייב את מסגרת המצלמה לפתוח את מכשירי המצלמה (@3.2::ICameraDevice::open) לפני שמגדירים סשנים במכשירי המצלמה. כך ספקי המצלמות יוכלו להקצות את המשאבים בהתאם.

  • כדי לטפל בבעיה של חוסר היכולת לטפל ביחס המלא של טווח הזום, צריך לוודא שאפליקציות המצלמה, כשמשתמשים במצלמות בו-זמנית, משתמשות בהגדרת הבקרה ZOOM_RATIO בין 1x ל-MAX_DIGITAL_ZOOM בלבד, במקום ב-ZOOM_RATIO_RANGE המלא (כך מונעים את המעבר הפנימי בין מצלמות פיזיות, שעלול לדרוש יותר ספקי אינטרנט).

בעיה ב-testDualCameraPreview

כשמבצעים את העדכונים שלמעלה, יכולה להיווצר בעיה בהתנהגות שמותר לבצע אותה לפי הבדיקה MultiViewTest.java#testDualCameraPreview.

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

for each camera  in cameraDevices :
  device = openCamera(camera)
     createCaptureSession(device);

עם זאת, הוא סובל כשלונות בפתיחת המצלמה עם ERROR_MAX_CAMERAS_IN_USE [1]. יכול להיות שאפליקציות של צד שלישי תלויות בהתנהגות הזו.

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

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