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

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

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

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

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

יעד 1 יעד 2
סוג גודל מקסימלי סוג גודל מקסימלי תרחישים לדוגמה
YUV s1440p עיבוד תמונות או סרטונים מתוך האפליקציה
הרשאות 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 (1,920x1,440) או הרזולוציה המקסימלית הנתמכת לפורמט הספציפי שמוחזר על ידי StreamConfigurationMap.getOutputSizes(). מכשירים שהיכולות שלהם לא כוללות את ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE חייבים לתמוך לפחות בשידור Y16 אחד, Dataspace::DEPTH עם רזולוציית sVGA, בזמן פעולה בו-זמנית, כאשר sVGA הוא הקטן מבין שתי הרזולוציות הבאות:

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

הטמעה

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

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

אימות

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

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

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

תרחיש לדוגמה

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

בעיה

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

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

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

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

הפתרון

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

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

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

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

בעיה ב-testDual CameraPreview

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