ב-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 אל המסגרת באמצעות הממשקים
IFrontend,IDemux,IDescrambler,IFilter,IDvrו-ILnb. - כולל את הפונקציות לשילוב של Tuner HAL עם רכיבים אחרים של המסגרת, כמו
MediaCodecו-AudioTrack.
נוצרות מחלקת Java ומחלקה מקורית של Tuner.
- ממשק Tuner Java API מאפשר לאפליקציות לגשת ל-Tuner HAL דרך ממשקי API ציבוריים.
- המחלקות המקוריות מאפשרות שליטה בהרשאות וטיפול בכמויות גדולות של נתוני הקלטה או הפעלה באמצעות Tuner HAL.
- מודול Native Tuner הוא גשר בין מחלקת Tuner Java לבין Tuner HAL.
נוצרת כיתת TRM.
- מנהל משאבי כוונון מוגבלים, כמו Frontend, LNB, סשנים של CAS ומכשיר קלט לטלוויזיה מ-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, ה-API של Tuner SDK תומך בתכונה חדשה ב-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(): קבלת מופע של מפענח. -
openLnb(): קבלת מופע פנימי של מאזן עומסים. -
openLnbByName(): קבלת מופע LNB חיצוני. -
openTimeFilter(): מקבל מופע של מסנן זמן.
חבילת Tuner מספקת פונקציות שלא נכללות בחבילות filter, DVR ו-frontend. הפונקציות מפורטות בהמשך.
cancelTuning-
scanמתוךcancelScanning getAvSyncHwIdgetAvSyncTime-
connectCiCam1מתוךdisconnectCiCam shareFrontendFromTunerupdateResourcePrioritysetOnTuneEventListenersetResourceLostListener
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 קורא 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 קורא 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 MQ למאגר הלקוח. |
חבילת סשן אחת שהורכבה מתמלאת ב-FMQ על ידי חבילת סשן אחרת. |
isRaw: |
מאפיינים חובה:DemuxFilterEvent::DemuxFilterSectionEvent[n]DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWמאפיינים אופציונליים: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++הנתונים מועתקים מ-HAL 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) פעם אחת או יותר.הנתונים מועתקים מ-HAL MQ למאגר הלקוח. |
חבילת 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) פעם אחת או יותר.הנתונים מועתקים מ-HAL MQ למאגר הלקוח. |
הסינון בוצע 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 שמולא ב-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) פעם אחת או יותר.הנתונים מועתקים מ-HAL MQ למאגר הלקוח. |
הסינון בוצע 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. 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 |
הפידים של זרמי המשנה של הפרוטוקול שסוננו מוזנים למסנן הבא בשרשרת המסננים filter. | לא רלוונטי |
isPassthrough: |
חובה:DemuxFilterStatus::DATA_READYDemuxFilterStatus::DATA_OVERFLOWמומלץ: DemuxFilterStatus::LOW_WATERDemuxFilterStatus::HIGH_WATER |
בהתאם לאירוע וללוח הזמנים הפנימי, מריצים אתFilter.read(buffer, offset, adjustedSize) פעם אחת או יותר.הנתונים מועתקים מ-HAL MQ למאגר הלקוח. |
הסינון של נתוני המשנה של הפרוטוקול עם כותרת הפרוטוקול הושלם 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 מספק את השיטות האלה להקלטה.
configureattachFilterdetachFilterstartflushstopsetFileDescriptorwrite
DvrPlayback מספק את השיטות האלה להפעלה.
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)/releaseCasSession-
requestLnb(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. דיאגרמה של מנגנון ההחזרה של משאבי Tuner במקרה של קונפליקט