ב-Android מגרסה 11 ואילך, אפשר להשתמש במסגרת Android Tuner כדי להציג תוכן אודיו/וידאו. המסגרת משתמשת בצינור החומרה של הספקים, ולכן היא מתאימה למערכות SoC ברמה נמוכה וברמה גבוהה. המסגרת מספקת דרך מאובטחת להעברת תוכן אודיו/וידאו שמוגן על ידי סביבת ביצוע מהימנה (TEE) ונתיב מדיה מאובטח (SMP), ולכן אפשר להשתמש בה בסביבה מוגבלת מאוד להגנה על תוכן.
הממשק המתוקנן בין Tuner לבין Android CAS מאפשר שילוב מהיר יותר בין ספקי Tuner לבין ספקי CAS. ממשק הכוונון פועל עם MediaCodec ועם AudioTrack כדי ליצור פתרון עולמי ל-Android TV.
ממשק הכוונון תומך בטלוויזיה דיגיטלית ובטלוויזיה אנלוגית על סמך תקני שידור מרכזיים.
רכיבים
ב-Android 11, יש שלושה רכיבים שנועדו במיוחד לפלטפורמת הטלוויזיה.
- Tuner HAL: ממשק בין המסגרת לבין הספקים
- Tuner SDK API: ממשק בין המסגרת לבין האפליקציות
- Tuner Resource Manager (TRM): מתאם בין משאבי חומרה של מקלט
ב-Android 11, הרכיבים הבאים שופרו:
- CAS V2
-
TvInputServiceאו שירות קלט לטלוויזיה (TIS) -
TvInputManagerServiceאו TV Input Manager Service (TIMS) -
MediaCodecאו קודק מדיה AudioTrackאו טראק אודיו-
MediaResourceManagerאו מנהל משאבי מדיה (MRM)
איור 1. אינטראקציות בין רכיבים של Android TV
תכונות
החלק הקדמי של המערכת תומך בתקני DTV הבאים.
- ATSC
- ATSC3
- DVB C/S/T
- ISDB S/S3/T
- אנלוגי
ממשק הקצה ב-Android 12 עם Tuner HAL 1.1 ואילך תומך בתקן DTV שמופיע בהמשך.
- DTMB
הכלי Demux תומך בפרוטוקולי הסטרימינג הבאים.
- Transport stream (TS)
- פרוטוקול להעברת מדיה MPEG (MMTP)
- פרוטוקול אינטרנט (IP)
- ערך אורך הסוג (TLV)
- פרוטוקול שכבת הקישור (ALP) של ATSC
הכלי לביטול הצפנה תומך באמצעי ההגנה על התוכן שמופיעים בהמשך.
- נתיב מדיה מאובטח
- ניקוי נתיב המדיה
- הקלטה מקומית מאובטחת
- הפעלה מאובטחת של קבצים מקומיים
ממשקי Tuner API תומכים בתרחישי השימוש הבאים.
- סריקה
- בשידור חי
- הפעלה
- הקלטה
הכלים Tuner, MediaCodec ו-AudioTrack תומכים במצבי זרימת הנתונים שמופיעים בהמשך.
- מטען ייעודי (payload) של ES עם מאגר נתונים זמני ברור
- מטען ייעודי (payload) של ES עם טיפול מאובטח בזיכרון
- שקופה
עיצוב כללי
ה-HAL של הכלי Tuner מוגדר בין מסגרת Android לבין החומרה של הספק.
- מתאר מה נדרש מהספק במסגרת ואיך הספק יכול לעשות את זה.
- מייצא את הפונקציות של הקצה הקדמי, demux ו-descrambler ל-framework באמצעות הממשקים
IFrontend,IDemux,IDescrambler,IFilter,IDvrו-ILnb. - כולל את הפונקציות לשילוב של Tuner HAL עם רכיבים אחרים של המסגרת, כמו
MediaCodecו-AudioTrack.
נוצרות מחלקת Java ומחלקה מקורית של Tuner.
- ממשק ה-API של Tuner Java מאפשר לאפליקציות לגשת ל-Tuner HAL דרך ממשקי API ציבוריים.
- המחלקות המקוריות מאפשרות שליטה בהרשאות וטיפול בכמויות גדולות של נתוני הקלטה או הפעלה באמצעות Tuner HAL.
- מודול Tuner מקורי הוא גשר בין מחלקת Tuner Java לבין Tuner HAL.
נוצרת קטגוריה של TRM.
- מנהל משאבים מוגבלים של מקלט, כמו Frontend, LNB, CAS sessions ומכשיר קלט לטלוויזיה מ-TV input HAL.
- החלת כללים כדי לשחרר משאבים לא מספיקים מאפליקציות. כלל ברירת המחדל הוא שהאפליקציה בחזית היא הזוכה.
התכונות הבאות משפרות את Media CAS ואת CAS HAL.
- פתיחת סשנים של CAS לשימושים ולאלגוריתמים שונים.
- תמיכה במערכות CAS דינמיות, כמו הסרה והוספה של CICAM.
- הוא משתלב עם Tuner HAL על ידי אספקת אסימוני מפתח.
MediaCodec ו-AudioTrack משופרים באמצעות התכונות הבאות.
- מקבל זיכרון מאובטח של אודיו ווידאו כקלט תוכן.
- ההגדרה היא לבצע סנכרון של אודיו ווידאו בחומרה בהפעלה מנהרתית.
- הגדרת תמיכה ב-
ES_payloadובמצב העברה.
איור 2. תרשים של הרכיבים ב-Tuner HAL
תהליך העבודה הכולל
בתרשימים הבאים אפשר לראות את רצפי הקריאות להפעלה של שידור חי.
הגדרה
איור 3. הגדרת רצף להפעלת שידור חי
טיפול באודיו/וידאו
איור 4. טיפול באודיו ובווידאו בהפעלה של שידור חי
טיפול בתוכן מבולבל
איור 5. טיפול בתוכן מקושקש להפעלה בשידור חי
עיבוד נתונים של אודיו ווידאו
איור 6. עיבוד של אודיו ווידאו להפעלת שידור חי
Tuner SDK API
ממשק ה-API של Tuner SDK מטפל באינטראקציות עם Tuner JNI, Tuner HAL ו-TunerResourceManager. אפליקציית TIS משתמשת ב-Tuner SDK API כדי לגשת למשאבי Tuner ולרכיבי משנה כמו המסנן וה-descrambler. ה-Frontend וה-demux הם רכיבים פנימיים.
איור 7. אינטראקציות עם Tuner SDK API
גרסאות
מ-Android 12, Tuner SDK API תומך בתכונה חדשה ב-Tuner HAL 1.1, שהיא שדרוג גרסה תואם לאחור של Tuner 1.0.
כדי לבדוק איזו גרסת HAL פועלת, משתמשים ב-API הבא.
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
אפשר למצוא את גרסת ה-HAL המינימלית הנדרשת בתיעוד של ממשקי ה-API החדשים של Android 12.
חבילות
ממשק ה-API של Tuner SDK מספק את ארבע החבילות הבאות.
android.media.tv.tunerandroid.media.tv.tuner.frontendandroid.media.tv.tuner.filterandroid.media.tv.tuner.dvr
איור 8. חבילות Tuner SDK API
Android.media.tv.tuner
חבילת Tuner היא נקודת כניסה לשימוש ב-Tuner framework. אפליקציית TIS משתמשת בחבילה כדי לאתחל ולקבל מופעים של משאבים על ידי ציון ההגדרה הראשונית והקריאה החוזרת.
-
tuner(): מאתחל מופע של Tuner על ידי ציון הפרמטריםuseCaseו-sessionId. -
tune(): מקבלים משאב קצה קדמי ומכוונים אותו על ידי ציון הפרמטרFrontendSetting. -
openFilter(): מקבל מופע של מסנן על ידי ציון סוג המסנן. -
openDvrRecorder(): מקבלים מופע הקלטה על ידי ציון גודל המאגר. -
openDvrPlayback(): מקבל מופע הפעלה על ידי ציון גודל המאגר. -
openDescrambler(): מקבל מופע של descrambler. -
openLnb(): קבלת מופע LNB פנימי. -
openLnbByName(): קבלת מופע LNB חיצוני. -
openTimeFilter(): מקבל מופע של מסנן זמן.
חבילת Tuner מספקת פונקציות שלא נכללות בחבילות filter, DVR ו-frontend. הפונקציות מפורטות בהמשך.
cancelTuningscan/cancelScanninggetAvSyncHwIdgetAvSyncTimeconnectCiCam1/disconnectCiCamshareFrontendFromTunerupdateResourcePrioritysetOnTuneEventListenersetResourceLostListener
Android.media.tv.tuner.frontend
חבילת ה-Frontend כוללת אוספים של הגדרות, מידע, סטטוסים, אירועים ויכולות שקשורים ל-Frontend.
קורסים
FrontendSettings נגזר מתקני DTV שונים לפי המחלקות שבהמשך.
AnalogFrontendSettingsAtsc3FrontendSettingsAtscFrontendSettingsDvbcFrontendSettingsDvbsFrontendSettingsDvbtFrontendSettingsIsdbs3FrontendSettingsIsdbsFrontendSettingsIsdbtFrontendSettings
מ-Android 12 עם Tuner HAL 1.1 ואילך, יש תמיכה בתקן DTV הבא.
DtmbFrontendSettings
FrontendCapabilities נגזר עבור תקני DTV שונים על ידי המחלקות שלמטה.
AnalogFrontendCapabilitiesAtsc3FrontendCapabilitiesAtscFrontendCapabilitiesDvbcFrontendCapabilitiesDvbsFrontendCapabilitiesDvbtFrontendCapabilitiesIsdbs3FrontendCapabilitiesIsdbsFrontendCapabilitiesIsdbtFrontendCapabilities
מ-Android 12 עם Tuner HAL 1.1 ואילך, יש תמיכה בתקן DTV הבא.
DtmbFrontendCapabilities
FrontendInfo מאחזר את המידע של חזית האתר.
FrontendStatus מחזירה את הסטטוס הנוכחי של חזית האתר.
OnTuneEventListener מקשיב לאירועים בחלק הקדמי של האתר.
אפליקציית TIS משתמשת ב-ScanCallback כדי לעבד הודעות סריקה מהחלק הקדמי של האתר.
סריקת ערוצים
כדי להגדיר טלוויזיה, האפליקציה סורקת תדרים אפשריים ויוצרת רשימת ערוצים שהמשתמשים יכולים לגשת אליה. יכול להיות ש-TIS ישתמש ב-Tuner.tune, ב-Tuner.scan(BLIND_SCAN) או ב-Tuner.scan(AUTO_SCAN) כדי להשלים את סריקת הערוצים.
אם ל-TIS יש נתוני משלוח מדויקים לאות, כמו תדר, תקן (למשל, T/T2, S/S2) ומידע נוסף שנדרש (למשל, מזהה PLD), מומלץ להשתמש ב-Tuner.tune כי זו האפשרות המהירה יותר.
כשהמשתמש מתקשר אל Tuner.tune, הפעולות הבאות מתבצעות:
- מערכת TIS מאכלסת את
FrontendSettingsבמידע הנדרש באמצעותTuner.tune. - אם האות נעול, שכבת ה-HAL מדווחת על הודעות של כוונון
LOCKED. - מערכת TIS משתמשת ב-
Frontend.getStatusכדי לאסוף את המידע הנדרש. - מערכת TIS עוברת לתדר הזמין הבא ברשימת התדרים שלה.
הפונקציה TIS מתקשרת שוב Tuner.tune עד שכל התדרים מוצו.
במהלך ההגדרה, אפשר להתקשר אל stopTune() או אל close() כדי להשהות או לסיים את השיחה עם Tuner.tune.
Tuner.scan(AUTO_SCAN)
אם ל-TIS אין מספיק מידע כדי להשתמש ב-Tuner.tune, אבל יש לו רשימת תדרים וסוג סטנדרטי (לדוגמה, DVB T/C/S), מומלץ להשתמש ב-Tuner.scan(AUTO_SCAN).
כשהמשתמש מתקשר אל Tuner.scan(AUTO_SCAN), הפעולות הבאות מתבצעות:
ב-TIS נעשה שימוש ב-
Tuner.scan(AUTO_SCAN)עםFrontendSettingsשמולא בתדירות.אם האות נעול, ה-HAL מדווח על סריקת הודעות
LOCKED. יכול להיות ש-HAL ידווח גם על הודעות סריקה אחרות כדי לספק מידע נוסף על האות.מערכת TIS משתמשת ב-
Frontend.getStatusכדי לאסוף את המידע הנדרש.TIS מתקשר אל
Tuner.scanכדי ש-HAL ימשיך להגדרה הבאה באותו תדר. אם המבנהFrontendSettingsריק, שכבת ה-HAL משתמשת בהגדרה הזמינה הבאה. אחרת, HAL משתמש ב-FrontendSettingsלסריקה חד-פעמית ושולחENDכדי לציין שפעולת הסריקה הסתיימה.הכלי TIS חוזר על הפעולות שלמעלה עד שכל ההגדרות בתדירות מסוימת מושלמות.
שכבת ה-HAL שולחת
ENDכדי לציין שפעולת הסריקה הסתיימה.מערכת TIS עוברת לתדר הזמין הבא ברשימת התדרים שלה.
הפונקציה TIS מתקשרת שוב Tuner.scan(AUTO_SCAN) עד שכל התדרים מוצו.
במהלך הסריקה, אפשר להתקשר אל stopScan() או אל close() כדי להשהות או לסיים את הסריקה.
Tuner.scan(BLIND_SCAN)
אם ל-TIS אין רשימת תדרים ו-Vendor HAL יכול לחפש את התדר של חזית המשתמש שצוינה כדי לקבל את משאב החזית, מומלץ להשתמש ב-Tuner.scan(BLIND_SCAN).
- מערכת TIS משתמשת ב-
Tuner.scan(BLIND_SCAN). אפשר לציין תדירות ב-FrontendSettingsלתדירות התחלה, אבל TIS מתעלם מהגדרות אחרות ב-FrontendSettings. - אם האות נעול, שכבת ה-HAL מדווחת על הודעת סריקה
LOCKED. - מערכת TIS משתמשת ב-
Frontend.getStatusכדי לאסוף את המידע הנדרש. - TIS מתקשרת שוב אל
Tuner.scanכדי להמשיך בסריקה. (FrontendSettingsמתעלמים.) - הכלי TIS חוזר על הפעולות שלמעלה עד שכל ההגדרות בתדירות מסוימת מושלמות. ה-HAL מגדיל את התדירות בלי שתידרש פעולה מצד TIS.
דוחות HAL
PROGRESS.
הפונקציה TIS מתקשרת שוב Tuner.scan(AUTO_SCAN) עד שכל התדרים מוצו.
ה-HAL מדווח על END כדי לציין שפעולת הסריקה הסתיימה.
במהלך הסריקה, אפשר להתקשר אל stopScan() או אל close() כדי להשהות או לסיים את הסריקה.
איור 9. תרשים זרימה של סריקת TIS
Android.media.tv.tuner.filter
חבילת המסננים היא אוסף של פעולות סינון, יחד עם הגדרות, קריאות חוזרות ואירועים. החבילה כוללת את הפעולות הבאות. רשימה מלאה של הפעולות מופיעה בקוד המקור של Android.
configure()start()stop()flush()read()
הרשימה המלאה מופיעה בקוד המקור של Android.
הציון FilterConfiguration מחושב על סמך הציונים בכיתות שלמטה. ההגדרות הן לסוג המסנן הראשי, והן מציינות באיזה פרוטוקול המסנן משתמש כדי לחלץ נתונים.
AlpFilterConfigurationIpFilterConfigurationMmtpFilterConfigurationTlvFilterConfigurationTsFilterConfiguration
ההגדרות נגזרות מהכיתות שמופיעות בהמשך. ההגדרות מתייחסות לסוג המשנה של המסנן ומציינות אילו סוגי נתונים המסנן יכול להחריג.
SectionSettingsAvSettingsPesSettingsRecordSettingsDownloadSettings
FilterEvent נגזר מהמחלקות שבהמשך כדי לדווח על אירועים עבור סוגים שונים של נתונים.
SectionEventMediaEventPesEventTsRecordEventMmtpRecordEventTemiEventDownloadEventIpPayloadEvent
מ-Android 12 עם Tuner HAL 1.1 ואילך, האירועים הבאים נתמכים.
IpCidChangeEventRestartEventScramblingStatusEvent
אירועים ופורמט נתונים מהמסנן
| סוג הפילטר | דגלים | אירועים | פעולת נתונים | פורמט נתונים |
|---|---|---|---|---|
TS.SECTIONMMTP.SECTIONIP.SECTIONTLV.SECTIONALP.SECTION |
isRaw: |
חובה:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWמומלץ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
בהתאם לאירוע וללוח הזמנים הפנימי, הפעלה שלFilter.read(buffer, offset, adjustedSize) פעם אחת או יותר.הנתונים מועתקים מ-HAL's MQ למאגר הלקוח. |
חבילת סשן אחת שהורכבה מתמלאת ב-FMQ על ידי חבילת סשן אחרת. |
isRaw: |
מאפיינים חובה:DemuxFilterEvent::DemuxFilterSectionEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWמאפיינים אופציונליים: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++הנתונים מועתקים מ-HAL's MQ למאגר הלקוח. |
||
TS.PES |
isRaw: |
חובה:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWמומלץ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
בהתאם לאירוע וללוח הזמנים הפנימי, הפעלה שלFilter.read(buffer, offset, adjustedSize) פעם אחת או יותר.הנתונים מועתקים מ-HAL's MQ למאגר הלקוח. |
חבילת PES אחת מורכבת ממולאת ב-FMQ על ידי חבילת PES אחרת. |
isRaw: |
מאפיינים חובה:DemuxFilterEvent::DemuxFilterPesEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWמאפיינים אופציונליים: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++הנתונים מועתקים מ-HAL's MQ למאגר הלקוח. |
||
MMTP.PES |
isRaw: |
חובה:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWמומלץ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
בהתאם לאירוע וללוח הזמנים הפנימי, הפעלה שלFilter.read(buffer, offset, adjustedSize) פעם אחת או יותר.הנתונים מועתקים מ-MQ של HAL למאגר הלקוח. |
חבילת MFU אחת מורכבת וממולאת ב-FMQ על ידי חבילת MFU אחרת. |
isRaw: |
מאפיינים חובה:DemuxFilterEvent::DemuxFilterPesEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWמאפיינים אופציונליים: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++הנתונים מועתקים מ-HAL's MQ למאגר הלקוח. |
||
TS.TS |
לא רלוונטי | חובה:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWמומלץ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
לפי האירוע ולוח הזמנים הפנימי, הפעולה תרוץFilter.read(buffer, offset, adjustedSize) פעם אחת או יותר.הנתונים מועתקים מ-MQ של HAL למאגר הלקוח. |
הסינון בוצע ts עם ts כותרתמלאה ב-FMQ. |
TS.AudioTS.VideoMMTP.AudioMMTP.Video |
isPassthrough: |
אופציונלי:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOW |
הלקוח יכול להתחיל את MediaCodec אחרי שהוא מקבל את DemuxFilterStatus::DATA_READY.הלקוח יכול להתקשר אל Filter.flush אחרי שהוא מקבל את DemuxFilterStatus::DATA_OVERFLOW. |
לא רלוונטי |
isPassthrough: |
מאפיינים חובה:DemuxFilterEvent::DemuxFilterMediaEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWמאפיינים אופציונליים: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
כדי להשתמש ב-MediaCodec:for i=0; i<n; i++כדי להשתמש באודיו ישיר של AudioTrack:for i=0; i<n; i++ |
נתוני ES או נתוני ES חלקיים בזיכרון של ION. | |
TS.PCRIP.NTPALP.PTP |
לא רלוונטי | חובה: לא רלוונטי
אופציונלי: לא רלוונטי |
לא רלוונטי | לא רלוונטי |
TS.RECORD |
לא רלוונטי | חובה: DemuxFilterEvent::DemuxFilterTsRecordEvent[n]RecordStatus::DATA_READYRecordStatus::DATA_OVERFLOWRecordStatus::LOW_WATERRecordStatus::HIGH_WATERאופציונלי: DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWDemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
לנתוני אינדקס:for i=0; i<n; i++לתוכן מוקלט, בהתאם ל- RecordStatus::* ולתזמון הפנימי, מבצעים
אחת מהפעולות הבאות:
|
לגבי נתוני אינדקס: מועברים במטען הייעודי (payload) של האירוע. לתוכן מוקלט: Muxed TS stream filled in FMQ. |
TS.TEMI |
לא רלוונטי | חובה:DemuxFilterEvent::DemuxFilterTemiEvent[n]אופציונלי: DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWDemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ |
לא רלוונטי |
MMTP.MMTP |
לא רלוונטי | חובה:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWמומלץ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
בהתאם לאירוע וללוח הזמנים הפנימי, הפעלה שלFilter.read(buffer, offset, adjustedSize) פעם אחת או יותר.הנתונים מועתקים מ-MQ של HAL למאגר הלקוח. |
הסינון בוצע mmtp עם mmtp כותרתמלאה ב-FMQ. |
MMTP.RECORD |
לא רלוונטי | חובה:DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n]RecordStatus::DATA_READYRecordStatus::DATA_OVERFLOWRecordStatus::LOW_WATERRecordStatus::HIGH_WATERאופציונלי: DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWDemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
לנתוני אינדקס: for i=0; i<n; i++לתוכן מוקלט, בהתאם ל RecordStatus::* ולתזמון הפנימי, מבצעים אחת מהפעולות הבאות:
|
לגבי נתוני אינדקס: מועברים במטען הייעודי (payload) של האירוע. לתוכן מוקלט: הסטרימינג המוקלט המעורב מולא ב-FMQ. אם מקור הסינון להקלטה הוא TLV.TLV עד IP.IP עם העברה, לזרם המוקלט יש TLV וכותרת IP. |
MMTP.DOWNLOAD |
לא רלוונטי | מאפיינים חובה:DemuxFilterEvent::DemuxFilterDownloadEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWמאפיינים אופציונליים: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size)הנתונים מועתקים מ-HAL's MQ למאגר הלקוח. |
חבילת ההורדה מתמלאת ב-FMQ על ידי חבילת הורדה אחרת של IP. |
IP.IP_PAYLOAD |
לא רלוונטי | מאפיינים חובה:DemuxFilterEvent::DemuxFilterIpPayloadEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWמאפיינים אופציונליים: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size)הנתונים מועתקים מ-HAL's MQ למאגר הלקוח. |
חבילת מטען ייעודי (payload) של IP מתמלאת ב-FMQ על ידי חבילת מטען ייעודי (payload) אחרת של IP. |
IP.IPTLV.TLVALP.ALP |
isPassthrough: |
אופציונלי:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOW |
הפידים של זרמי המשנה של הפרוטוקול שסוננו מוזנים למסנן הבא בשרשרת המסננים. | לא רלוונטי |
isPassthrough: |
חובה:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWמומלץ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
בהתאם לאירוע וללוח הזמנים הפנימי, הפעלה שלFilter.read(buffer, offset, adjustedSize) פעם אחת או יותר.הנתונים מועתקים מ-MQ של HAL למאגר הלקוח. |
Filtered out protocol sub stream with protocol header is filled in FMQ. | |
IP.PAYLOAD_THROUGHTLV.PAYLOAD_THROUGHALP.PAYLOAD_THROUGH |
לא רלוונטי | אופציונלי:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOW |
הפידים של מטען הייעודי (payload) של הפרוטוקול שסוננו מוזנים למסנן הבא בשרשרת המסננים. | לא רלוונטי |
תרשים זרימה לדוגמה לשימוש במסנן כדי ליצור PSI/SI
איור 10. תהליך ליצירת PSI/SI
פותחים מסנן.
Filter filter = tuner.openFilter( Filter.TYPE_TS, Filter.SUBTYPE_SECTION, /* bufferSize */1000, executor, filterCallback );מגדירים את המסנן ומתחילים להשתמש בו.
Settings settings = SectionSettingsWithTableInfo .builder(Filter.TYPE_TS) .setTableId(2) .setVersion(1) .setCrcEnabled(true) .setRaw(false) .setRepeat(false) .build(); FilterConfiguration config = TsFilterConfiguration .builder() .setTpid(10) .setSettings(settings) .build(); filter.configure(config); filter.start();עיבוד
SectionEvent.FilterCallback filterCallback = new FilterCallback() { @Override public void onFilterEvent(Filter filter, FilterEvent[] events) { for (FilterEvent event : events) { if (event instanceof SectionEvent) { SectionEvent sectionEvent = (SectionEvent) event; int tableId = sectionEvent.getTableId(); int version = sectionEvent.getVersion(); int dataLength = sectionEvent.getDataLength(); int sectionNumber = sectionEvent.getSectionNumber(); filter.read(buffer, 0, dataLength); } } } };
דוגמה לשימוש ב-MediaEvent מתוך מסנן
איור 11. Flow to use MediaEvent from filter
- פותחים את המסננים של האודיו והווידאו, מגדירים אותם ומתחילים להשתמש בהם.
- עיבוד
MediaEvent. - קבלת
MediaEvent. - מוסיפים את הבלוק הליניארי לתור של
codec. - משחררים את ה-handle של האודיו והווידאו אחרי שהנתונים נצרכו.
Android.media.tv.tuner.dvr
DvrRecorder מספקת את ה-methods האלה להקלטה.
configureattachFilterdetachFilterstartflushstopsetFileDescriptorwrite
DvrPlayback מספקת את ה-methods האלה להפעלה.
configurestartflushstopsetFileDescriptorread
DvrSettings משמש להגדרה של DvrRecorder ושל DvrPlayback.
הערכים OnPlaybackStatusChangedListener ו-OnRecordStatusChangedListener משמשים לדיווח על הסטטוס של מופע DVR.
דוגמה לתהליך ליצירת רשומה
איור 12. תהליך ליצירת רשומה
פותחים את
DvrRecorder, מגדירים אותו ומתחילים להשתמש בו.DvrRecorder recorder = openDvrRecorder(/* bufferSize */ 1000, executor, listener); DvrSettings dvrSettings = DvrSettings .builder() .setDataFormat(DvrSettings.DATA_FORMAT_TS) .setLowThreshold(100) .setHighThreshold(900) .setPacketSize(188) .build(); recorder.configure(dvrSettings); recorder.attachFilter(filter); recorder.setFileDescriptor(fd); recorder.start();מקבלים את
RecordEventומאחזרים את פרטי האינדקס.FilterCallback filterCallback = new FilterCallback() { @Override public void onFilterEvent(Filter filter, FilterEvent[] events) { for (FilterEvent event : events) { if (event instanceof TsRecordEvent) { TsRecordEvent recordEvent = (TsRecordEvent) event; int tsMask = recordEvent.getTsIndexMask(); int scMask = recordEvent.getScIndexMask(); int packetId = recordEvent.getPacketId(); long dataLength = recordEvent.getDataLength(); // handle the masks etc. } } } };מאתחלים את
OnRecordStatusChangedListenerושומרים את נתוני הרשומה.OnRecordStatusChangedListener listener = new OnRecordStatusChangedListener() { @Override public void onRecordStatusChanged(int status) { // a customized way to consume data efficiently by using status as a hint. if (status == Filter.STATUS_DATA_READY) { recorder.write(size); } } };
Tuner HAL
ה-HAL של הכרטיס הדיגיטלי לשידור (Tuner) פועל לפי HIDL ומגדיר את הממשק בין המסגרת לבין חומרה של ספק. הספקים משתמשים בממשק כדי להטמיע את Tuner HAL, והמסגרת משתמשת בו כדי לתקשר עם ההטמעה של Tuner HAL.
מודולים
Tuner HAL 1.0
| מודולים | פקדים בסיסיים | אמצעי בקרה ספציפיים למודול | קובצי HAL |
|---|---|---|---|
ITuner |
לא רלוונטי | frontend(open, getIds, getInfo), openDemux,
openDescrambler, openLnb,
getDemuxCaps |
ITuner.hal |
IFrontend |
setCallback, getStatus, close
| tune, stopTune, scan,
stopScan, setLnb |
IFrontend.halIFrontendCallback.hal |
IDemux |
close |
setFrontendDataSource, openFilter, openDvr, getAvSyncHwId,
getAvSyncTime, connect / disconnectCiCam |
IDemux.hal |
IDvr |
close, start, stop, configure |
attach/detachFilters, flush, getQueueDesc |
IDvr.halIDvrCallback.hal |
IFilter |
close, start, stop, configure, getId |
flush, getQueueDesc, releaseAvHandle, setDataSource |
IFilter.halIFilterCallback.hal |
ILnb |
close, setCallback |
setVoltage, setTone, setSatellitePosition, sendDiseqcMessage |
ILnb.halILnbCallback.hal |
IDescrambler |
close |
setDemuxSource, setKeyToken,
addPid, removePid |
IDescrambler.hal |
Tuner HAL 1.1 (נגזר מ-Tuner HAL 1.0)
| מודולים | פקדים בסיסיים | אמצעי בקרה ספציפיים למודול | קובצי HAL |
|---|---|---|---|
ITuner |
לא רלוונטי | getFrontendDtmbCapabilities |
@1.1::ITuner.hal |
IFrontend |
tune_1_1, scan_1_1, getStatusExt1_1 |
link/unlinkCiCam |
@1.1::IFrontend.hal@1.1::IFrontendCallback.hal |
IFilter |
getStatusExt1_1 |
configureIpCid, configureAvStreamType, getAvSharedHandle, configureMonitorEvent |
@1.1::IFilter.hal@1.1::IFilterCallback.hal |
איור 13. תרשים של האינטראקציות בין מודולי Tuner HAL
קישור סינון
ה-HAL של Tuner תומך בקישור מסננים כך שאפשר לקשר מסננים למסננים אחרים לכמה שכבות. המסננים פועלים לפי הכללים הבאים.
- המסננים מקושרים כעץ, ואסור להשתמש בנתיב סגור.
- צומת הבסיס הוא demux.
- המסננים פועלים באופן עצמאי.
- כל המסננים מתחילים לקבל נתונים.
- הקישור של המסנן מתבצע במסנן האחרון.
בלוק הקוד שבהמשך ואיור 14 ממחישים דוגמה לסינון של כמה שכבות.
demuxCaps = ITuner.getDemuxCap;
If (demuxCaps[IP][MMTP] == true) {
ipFilter = ITuner.openFilter(<IP, ..>)
mmtpFilter1 = ITuner.openFilter(<MMTP ..>)
mmtpFilter2 = ITuner.openFilter(<MMTP ..>)
mmtpFilter1.setDataSource(<ipFilter>)
mmtpFilter2.setDataSource(<ipFilter>)
}
איור 14. תרשים זרימה של קישור מסנן למספר שכבות
Tuner Resource Manager
לפני Tuner Resource Manager (TRM), כדי לעבור בין שתי אפליקציות היה צריך להשתמש באותו חומרה של מקלט. ב-TV Input Framework (TIF) נעשה שימוש במנגנון 'הראשון זוכה', כלומר האפליקציה שמקבלת את המשאב ראשונה שומרת אותו. עם זאת, יכול להיות שהמנגנון הזה לא יתאים לתרחישי שימוש מורכבים.
ה-TRM פועל כשירות מערכת לניהול של מקלט, TVInput ומשאבי חומרה של CAS עבור אפליקציות. התכונה 'ניהול תעבורה' משתמשת במנגנון'ניצחון במצב פעיל', שמחשב את העדיפות של האפליקציה על סמך הסטטוס שלה (פעילה או ברקע) וסוג תרחיש השימוש. ה-TRM מעניק או מבטל את הגישה למשאב על סמך העדיפות. TRM מרכז את ניהול המשאבים של ATV לשידור, ל-OTT ול-DVR.
ממשק TRM
TRM חושף ממשקי AIDL ב-ITunerResourceManager.aidl עבור Tuner Framework, MediaCas ו-TvInputHardwareManager כדי לרשום, לבקש או לשחרר משאבים.
בהמשך מפורטים ממשקים לניהול לקוחות.
registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)unregisterClientProfile(in int clientId)
בהמשך מפורטים הממשקים לבקשת משאבים ולשחרור משאבים.
requestFrontend(TunerFrontendRequest request, int[] frontendHandle)/releaseFrontendrequestDemux(TunerDemuxRequest request, int[] demuxHandle)/releaseDemuxrequestDescrambler(TunerDescramblerRequest request, int[] descramblerHandle)/releaseDescramblerrequestCasSession(CasSessionRequest request, int[] casSessionHandle)/releaseCasSessionrequestLnb(TunerLnbRequest request, int[] lnbHandle)/releaseLnb
בהמשך מפורטות מחלקות הלקוחות והבקשות.
ResourceClientProfileResourcesReclaimListenerTunerFrontendRequestTunerDemuxRequestTunerDescramblerRequestCasSessionRequestTunerLnbRequest
עדיפות של לקוחות
המודול TRM מחשב את העדיפות של הלקוח באמצעות פרמטרים מהפרופיל של הלקוח וערך העדיפות מקובץ התצורה. יכול להיות שהעדיפות תעודכן גם לפי ערך עדיפות שרירותי מהלקוח.
פרמטרים בפרופיל של הלקוח
הכלי TRM מאחזר את מזהה התהליך מ-mTvInputSessionId כדי להחליט אם האפליקציה היא אפליקציה בחזית או ברקע. כדי ליצור mTvInputSessionId, TvInputService.onCreateSession או TvInputService.onCreateRecordingSession, הכלי מאתחל סשן TIS.
mUseCase מציין את תרחיש השימוש בסשן. תרחישים מוגדרים מראש מפורטים בהמשך.
TvInputService.PriorityHintUseCaseType {
PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK
PRIORITY_HINT_USE_CASE_TYPE_LIVE
PRIORITY_HINT_USE_CASE_TYPE_RECORD,
PRIORITY_HINT_USE_CASE_TYPE_SCAN,
PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND
}
קובץ תצורה
קובץ תצורה שמוגדר כברירת מחדל
קובץ ההגדרות שמוגדר כברירת מחדל שמוצג בהמשך מספק ערכי עדיפות לתרחישי שימוש מוגדרים מראש. המשתמשים יכולים לשנות את הערכים באמצעות קובץ הגדרות בהתאמה אישית.
| תרחיש שימוש | חזית | רקע |
|---|---|---|
LIVE |
490 | 400 |
PLAYBACK |
480 | 300 |
RECORD |
600 | 500 |
SCAN |
450 | 200 |
BACKGROUND |
180 | 100 |
קובץ הגדרות בהתאמה אישית
ספקים יכולים להתאים אישית את קובץ ההגדרות /vendor/etc/tunerResourceManagerUseCaseConfig.xml. הקובץ הזה משמש להוספה, להסרה או לעדכון של סוגי תרחישי השימוש וערכי העדיפות של תרחישי השימוש.
אפשר להשתמש בקובץ המותאם אישית בתור תבנית של platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml.
לדוגמה, תרחיש שימוש חדש של ספק הוא VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000].
הפורמט צריך להיות platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd.
ערך עדיפות שרירותי וערך nice
ה-TRM מספק updateClientPriority ללקוח כדי לעדכן את ערך העדיפות השרירותי ואת ערך ה-nice.
ערך העדיפות השרירותי מחליף את ערך העדיפות שחושב לפי סוג תרחיש השימוש ומזהה הסשן.
הערך nice מציין עד כמה ההתנהגות של הלקוח סלחנית כשהיא נמצאת בסתירה עם לקוח אחר. הערך nice מקטין את ערך העדיפות של הלקוח לפני שערך העדיפות שלו מושווה לערך העדיפות של הלקוח המאתגר.
מנגנון ההחזרה
בתרשים הבא מוצג איך המערכת משחררת משאבים ומקצה אותם מחדש כשמתרחש קונפליקט משאבים.
איור 15. דיאגרמה של מנגנון ההחזרה לשימוש במקרה של קונפליקט בין משאבי מקלט