מערכת משנה של HAL

בקשות

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

דגם בקשת המצלמה

איור 1. דגם מצלמה

מערכת המשנה של המצלמה ו-HAL

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

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

שיטת הפשטת חומרה (HAL) של המצלמה

איור 2. צינור עיבוד נתונים של המצלמה

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

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

סיכום השימוש ב-API
זהו סיכום קצר של השלבים לשימוש ב-Android Camera API. בקטע 'רצף ההפעלה והפעולות הצפוי' מפורטים השלבים האלה, כולל קריאות ל-API.

  1. האזנה למכשירי מצלמה וספירתם.
  2. פותחים את המכשיר ומחברים את המאזינים.
  3. מגדירים פלט לתרחיש השימוש הרצוי (למשל, צילום תמונה, הקלטה וכו').
  4. יוצרים בקשות למקרה השימוש הרצוי.
  5. לזהות בקשות חוזרות ופרצי תנועה.
  6. קבלת מטא-נתונים של התוצאה ונתוני תמונה.
  7. כשעוברים לתרחיש שימוש אחר, חוזרים לשלב 3.

סיכום פעולות HAL

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

איור 3. סקירה כללית של Camera HAL

רצף ההפעלה והפעולות הצפוי

בקטע הזה מוסבר בפירוט על השלבים שצריך לבצע כשמשתמשים בממשק ה-API של המצלמה. הגדרות של ממשק HIDL מפורטות בכתובת platform/hardware/interfaces/camera/‎.

מנייה, פתיחה של מכשירי מצלמה ויצירה של סשן פעיל

  1. אחרי האתחול, המסגרת מתחילה להאזין לספקי מצלמות קיימים שמטמיעים את הממשק ICameraProvider. אם יש ספק או ספקים כאלה, המסגרת תנסה ליצור חיבור.
  2. המסגרת מפרטת את מכשירי המצלמה באמצעות ICameraProvider::getCameraIdList().
  3. המסגרת יוצרת מופע חדש של ICameraDevice על ידי קריאה ל-ICameraProvider::getCameraDeviceInterface_VX_X() המתאים.
  4. המסגרת קוראת ל-ICameraDevice::open() כדי ליצור סשן פעיל חדש של לכידת תמונות ICameraDeviceSession.

שימוש בסשן פעיל של המצלמה

  1. המסגרת קוראת ל-ICameraDeviceSession::configureStreams() עם רשימה של זרמי קלט/פלט למכשיר HAL.
  2. המסגרת מבקשת הגדרות ברירת מחדל לכמה תרחישי שימוש באמצעות קריאות ל-ICameraDeviceSession::constructDefaultRequestSettings(). המצב הזה יכול להתרחש בכל שלב אחרי ש-ICameraDeviceSession נוצר על ידי ICameraDevice::open.
  3. המסגרת בונה ושולחת את בקשת הצילום הראשונה ל-HAL עם הגדרות שמבוססות על אחת מהקבוצות של הגדרות ברירת המחדל, ועם לפחות זרם פלט אחד שנרשם קודם על ידי המסגרת. הבקשה הזו נשלחת ל-HAL עם ICameraDeviceSession::processCaptureRequest(). שכבת ה-HAL צריכה לחסום את החזרה של השיחה הזו עד שהיא תהיה מוכנה לשליחת הבקשה הבאה.
  4. המסגרת ממשיכה לשלוח בקשות ושיחות ICameraDeviceSession::constructDefaultRequestSettings() כדי לקבל מאגרי הגדרות ברירת מחדל לתרחישי שימוש אחרים לפי הצורך.
  5. כשמתחילים לצלם תמונה (החיישן מתחיל את החשיפה לצילום), ה-HAL קורא ל-ICameraDeviceCallback::notify() עם הודעת הצילום, כולל מספר הפריים וחותמת הזמן של תחילת החשיפה. הקריאה החוזרת notify לא חייבת להתבצע לפני הקריאה הראשונה של processCaptureResult() לבקשה, אבל לא מועברים תוצאות לאפליקציה לצילום עד שמתבצעת הקריאה של notify() לצילום הזה.
  6. אחרי עיכוב מסוים בצינור, ה-HAL מתחיל להחזיר ל-framework לכידות שהושלמו עם ICameraDeviceCallback::processCaptureResult(). התשובות מוחזרות באותו סדר שבו נשלחו הבקשות. יכולות להיות כמה בקשות בהמתנה בו-זמנית, בהתאם לעומק צינור העיבוד של מכשיר ה-HAL של המצלמה.

אחרי זמן מה, אחת מהאפשרויות הבאות תתרחש:

  • יכול להיות שהמסגרת תפסיק לשלוח בקשות חדשות, תחכה עד שהלכידות הקיימות יושלמו (כל המאגרים יתמלאו, כל התוצאות יוחזרו) ואז תקרא שוב ל-ICameraDeviceSession::configureStreams(). הפעולה הזו מאפסת את חומרת המצלמה ואת צינור הנתונים עבור קבוצה חדשה של זרמי קלט/פלט. יכול להיות שחלק מהשידורים יחזרו על עצמם מההגדרה הקודמת. לאחר מכן, המסגרת ממשיכה מבקשת הלכידה הראשונה אל HAL, אם נשאר לפחות פלט אחד רשום. (אחרת, קודם צריך להזין את ICameraDeviceSession::configureStreams()).
  • יכול להיות שה-framework יקרא ל-ICameraDeviceSession::close() כדי לסיים את סשן המצלמה. אפשר לקרוא לפונקציה הזו בכל שלב שבו אין שיחות אחרות פעילות מהמסגרת, אבל יכול להיות שהשיחה תיחסם עד שכל הלכידות הפעילות יושלמו (כל התוצאות יוחזרו, כל המאגרים ימולאו). אחרי שהקריאה ל-close() מוחזרת, לא ניתן לבצע יותר קריאות ל-ICameraDeviceCallback מ-HAL. אחרי שמתחילה שיחה עם close(), יכול להיות שהמסגרת לא תקרא לפונקציות אחרות של מכשיר HAL.
  • במקרה של שגיאה או אירוע אסינכרוני אחר, שכבת ה-HAL צריכה לקרוא ל-ICameraDeviceCallback::notify() עם הודעת השגיאה או האירוע המתאימה. אחרי שחוזרים מהודעה על שגיאה קריטית במכשיר, שכבת ה-HAL צריכה לפעול כאילו בוצעה בה קריאה ל-close(). עם זאת, מודול ה-HAL חייב לבטל או להשלים את כל הלכידות התלויות ועומדות לפני הקריאה ל-notify(), כדי שברגע שתתבצע קריאה ל-notify() עם שגיאה חמורה, לא יתקבלו עוד קריאות חוזרות מהמכשיר אל המסגרת. שיטות אחרות מלבד close() צריכות להחזיר ‎-ENODEV או NULL אחרי שהשיטה notify() מחזירה הודעת שגיאה חמורה.
רשימת השלבים לשימוש במצלמה

איור 4. רשימת השלבים להפעלת המצלמה

רמות חומרה

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

אינטראקציה בין בקשת הצילום של האפליקציה, בקרת 3A וצינור העיבוד

בהתאם להגדרות בבלוק הבקרה של 3A, צינור המצלמה מתעלם מחלק מהפרמטרים בבקשת הצילום של האפליקציה ומשתמש בערכים שסופקו על ידי שגרות הבקרה של 3A במקום זאת. לדוגמה, כשחשיפה אוטומטית פעילה, הפרמטרים של זמן החשיפה, משך הפריימים והרגישות של החיישן נשלטים על ידי אלגוריתם 3A של הפלטפורמה, וכל הערכים שצוינו באפליקציה מתעלמים. הערכים שנבחרו למסגרת על ידי שגרות ה-3A צריכים להיות מדווחים במטא-נתונים של הפלט. בטבלה הבאה מתוארים המצבים השונים של בלוק הבקרה 3A והמאפיינים שמנוהלים על ידי המצבים האלה. הגדרות המאפיינים האלה מפורטות בקובץ platform/system/media/camera/docs/docs.html.

פרמטר מדינה מאפיינים מבוקרים
android.control.aeMode מושבתת ללא
מופעלת ‫android.sensor.exposureTime android.sensor.frameDuration android.sensor.sensitivity android.lens.aperture (if supported) android.lens.filterDensity (if supported)
ON_AUTO_FLASH הכול מופעל, בנוסף ל-android.flash.firingPower,‏ android.flash.firingTime ו-android.flash.mode
ON_ALWAYS_FLASH בדיוק כמו ON_AUTO_FLASH
ON_AUTO_FLASH_RED_EYE בדיוק כמו ON_AUTO_FLASH
android.control.awbMode מושבתת ללא
WHITE_BALANCE_* ‫android.colorCorrection.transform. התאמות ספציפיות לפלטפורמה אם הערך של android.colorCorrection.mode הוא FAST או HIGH_QUALITY.
android.control.afMode מושבתת ללא
FOCUS_MODE_* android.lens.focusDistance
android.control.videoStabilization מושבתת ללא
מופעלת אפשר לשנות את הערך של android.scaler.cropRegion כדי להטמיע ייצוב וידאו
android.control.mode מושבתת התכונות AE,‏ AWB ו-AF מושבתות
אוטומטי הגדרות נפרדות של AE,‏ AWB ו-AF
SCENE_MODE_* אפשר להגדיר ערכים חלופיים לכל הפרמטרים שצוינו למעלה. אמצעי הבקרה האישיים של 3A מושבתים.

הפקדים בבלוק Image Processing (עיבוד תמונה) באיור 2 פועלים על פי עיקרון דומה, ובדרך כלל לכל בלוק יש שלושה מצבים:

  • מושבת: חסימת העיבוד הזו מושבתת. אי אפשר להשבית את הבלוקים של הסרת הפסיפס, תיקון הצבע והתאמת עקומת הטונים.
  • מהיר: במצב הזה, יכול להיות שבלוק העיבוד לא יאט את קצב הפריימים של הפלט בהשוואה למצב 'מושבת', אבל הוא אמור להפיק את הפלט באיכות הכי טובה שאפשר בהתחשב בהגבלה הזו. בדרך כלל, משתמשים בזה במצבי תצוגה מקדימה או הקלטת סרטונים, או בצילום רצף של תמונות סטילס. במכשירים מסוימים, יכול להיות שההגדרה הזו תהיה שוות ערך למצב OFF (לא ניתן לבצע עיבוד בלי להאט את קצב הפריימים), ובמכשירים אחרים, יכול להיות שהיא תהיה שוות ערך למצב HIGH_QUALITY (האיכות הכי טובה עדיין לא מאטה את קצב הפריימים).
  • ‫HIGH_QUALITY: במצב הזה, בלוק העיבוד צריך להפיק את התוצאה האיכותית ביותר שאפשר, ולהאט את קצב הפריימים של הפלט לפי הצורך. בדרך כלל, משתמשים באפשרות הזו כדי לצלם תמונות באיכות גבוהה. חלק מהבלוקים כוללים אמצעי בקרה ידני שאפשר לבחור בו במקום FAST או HIGH_QUALITY. לדוגמה, בלוק תיקון הצבע תומך במטריצת טרנספורמציה של צבע, בעוד שהתאמת עקומת הטונים תומכת בעקומת מיפוי טונים גלובלית שרירותית.

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

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

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

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