במכשירי Android מגרסה 11 ואילך, אפשר להשתמש במסגרת Android Tuner כדי להעביר תוכן A/V. המסגרת משתמשת בצינור עיבוד הנתונים של החומרה מהספקים, כך שהיא מתאימה גם ל-SoC ברמה נמוכה וגם ל-SoC ברמה גבוהה. המסגרת מספקת דרך מאובטחת להעברת תוכן A/V שמוגן על ידי סביבת ביצוע מהימנה (TEE) ונתיב מדיה מאובטח (SMP), ומאפשרת להשתמש בה בסביבה מוגבלת מאוד של הגנה על תוכן.
הממשק הסטנדרטי בין Tuner לבין Android CAS מאפשר שילוב מהיר יותר בין ספקי Tuner לבין ספקי CAS. ממשק הממיר פועל עם MediaCodec
ו-AudioTrack
כדי ליצור פתרון גלובלי אחד ל-Android TV.
ממשק הממיר תומך גם בטלוויזיה דיגיטלית וגם בטלוויזיה אנלוגית על סמך תקני השידור העיקריים.
רכיבים
ב-Android 11, יש שלושה רכיבים שמיועדים במיוחד לפלטפורמת הטלוויזיה.
- Tuner HAL: ממשק בין המסגרת לבין הספקים
- Tuner SDK API: ממשק בין המסגרת לאפליקציות
- Tuner Resource Manager (TRM): תיאום משאבי החומרה של Tuner
ב-Android 11, הרכיבים הבאים שופרו.
- CAS V2
TvInputService
או שירות הקלט של הטלוויזיה (TIS)TvInputManagerService
או שירות ניהול הקלט של הטלוויזיה (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
פרוטוקולים של מקור הנתונים (stream) שנתמכים ב-Demux:
- Transport stream (TS)
- פרוטוקול העברת מדיה של MPEG (MMTP)
- פרוטוקול אינטרנט (IP)
- טיפוס, אורך, ערך (TLV)
- פרוטוקול שכבת הקישור של ATSC (ALP)
הכלי לביטול ההצפנה תומך באמצעי ההגנה הבאים על תוכן:
- נתיב מדיה מאובטח
- ניקוי נתיב המדיה
- רשומה מקומית מאובטחת
- הפעלה מקומית מאובטחת
ממשקי Tuner API תומכים בתרחישי השימוש הבאים.
- סריקה
- בשידור חי
- הפעלה
- הקלטה
Tuner, MediaCodec
ו-AudioTrack
תומכים במצבי זרימת הנתונים הבאים.
- עומס עבודה ב-ES עם מאגר נתונים זמני של זיכרון נקי
- עומס עבודה של ES עם מנוף זיכרון מאובטח
- שקופה
העיצוב הכללי
ה-HAL של Tuner מוגדר בין מסגרת Android לחומרה של הספק.
- תיאור מה צפוי מהספק במסגרת הזו ואיך הספק יכול לעשות זאת.
- ייצוא הפונקציות של ממשק הקצה, המפצל והפענוח למסגרת דרך ממשקי
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
ו-ILnb
. - כולל את הפונקציות לשילוב ה-HAL של Tuner עם רכיבים אחרים של המסגרת, כמו
MediaCodec
ו-AudioTrack
.
נוצרות כיתה של Tuner ב-Java וכיתה מקומית.
- Tuner Java API מאפשר לאפליקציות לגשת ל-Tuner HAL דרך ממשקי API ציבוריים.
- הכיתה המקורית מאפשרת לשלוט בהרשאות ולנהל כמויות גדולות של נתוני הקלטה או הפעלה באמצעות Tuner HAL.
- מודול Tuner מקורי הוא גשר בין הכיתה Tuner ב-Java לבין Tuner HAL.
נוצרת קטגוריה של TRM.
- ניהול משאבי טיונר מוגבלים, כמו Frontend, LNB, סשנים של CAS והתקן קלט של טלוויזיה מ-HAL של קלט הטלוויזיה.
- החלת כללים לצורך ביטול הקצאה של משאבים לא מספיקים מאפליקציות. כלל ברירת המחדל הוא שהחזית מנצחת.
התכונות הבאות נוספו ל-Media CAS ול-CAS HAL.
- פתיחת סשנים של CAS לשימושים ולאלגוריתמים שונים.
- תמיכה במערכות CAS דינמיות, כמו הסרה והוספה של CICAM.
- השילוב עם Tuner HAL מתבצע באמצעות אספקת אסימוני מפתחות.
MediaCodec
ו-AudioTrack
משופרים באמצעות התכונות הבאות.
- זיכרון A/V מאובטח כקלט תוכן.
- ההגדרה היא לבצע סנכרון אודיו-וידאו בחומרה בהפעלה במנהרה.
- הגדרת תמיכה ב-
ES_payload
ובמצב העברה (passthrough).
איור 2. תרשים של הרכיבים ב-HAL של Tuner
תהליך העבודה הכולל
בתרשים הבא מוצגות רצפי הקריאות להפעלה של שידור חי.
הגדרה
איור 3. הגדרת רצף להפעלה של שידור חי
טיפול ב-A/V
איור 4. טיפול באודיו-וידאו להפעלת שידור חי
טיפול בתוכן מוצפן
איור 5. טיפול בתוכן מוצפן להפעלה של שידורים חיים
עיבוד נתוני אודיו/וידאו
איור 6. עיבוד אודיו-וידאו להפעלת שידור חי
Tuner SDK API
ממשק ה-API של Tuner SDK מטפל באינטראקציות עם Tuner JNI, Tuner HAL ו-TunerResourceManager
. אפליקציית TIS משתמשת ב-Tuner SDK API כדי לגשת למשאבים ולרכיבי המשנה של Tuner, כמו המסנן והמפענח. רכיבי הקצה הקדמי וה-demux הם רכיבים פנימיים.
איור 7. אינטראקציות עם Tuner SDK API
גרסאות
החל מגרסה 12 של Android, ממשק ה-API של Tuner SDK תומך בתכונה חדשה ב-Tuner HAL 1.1, שהוא שדרוג של Tuner 1.0 עם תאימות לאחור.
אפשר להשתמש ב-API הבא כדי לבדוק את גרסת ה-HAL שפועלת.
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
הגרסה המינימלית הנדרשת של HAL מופיעה במסמכי התיעוד של ממשקי ה-API החדשים של Android 12.
חבילות
ממשק ה-API של Tuner SDK מספק את ארבע החבילות הבאות.
android.media.tv.tuner
android.media.tv.tuner.frontend
android.media.tv.tuner.filter
android.media.tv.tuner.dvr
איור 8. חבילות API של Tuner SDK
Android.media.tv.tuner
חבילת Tuner היא נקודת הכניסה לשימוש במסגרת Tuner. אפליקציית TIS משתמשת בחבילה כדי לאתחל ולקבל מכונות של משאבים, על ידי ציון ההגדרה הראשונית והקריאה החוזרת (callback).
tuner()
: הפונקציה מגדירה מופע של Tuner על ידי ציון הפרמטריםuseCase
ו-sessionId
.tune()
: יצירת משאב חזית ושינוי ההגדרות שלו באמצעות ציון הפרמטרFrontendSetting
.openFilter()
: יצירת מופע מסנן על ידי ציון סוג המסנן.openDvrRecorder()
: יצירת מכונה להקלטה על ידי ציון גודל המאגר.openDvrPlayback()
: יצירת מכונה להפעלה על ידי ציון גודל המאגר הזמני.openDescrambler()
: יצירת מופע של מפרק הצפנה.openLnb()
: יצירת מכונה פנימית של LNB.openLnbByName()
: יצירת מכונה חיצונית של LNB.openTimeFilter()
: יצירת מופע של מסנן זמן.
חבילת ה-Tuner מספקת פונקציות שלא נכללות בחבילות הסינון, ה-DVR והחזית. הפונקציות מפורטות בהמשך.
cancelTuning
-
scan
מתוךcancelScanning
getAvSyncHwId
getAvSyncTime
-
connectCiCam1
מתוךdisconnectCiCam
shareFrontendFromTuner
updateResourcePriority
setOnTuneEventListener
setResourceLostListener
Android.media.tv.tuner.frontend
חבילת הקצה הקדמי כוללת אוספים של הגדרות, מידע, סטטוסים, אירועים ויכולות שקשורות לקצה הקדמי.
שיעורים
הערך של FrontendSettings
נגזר מהתקנים השונים של DTV לפי הכיתות הבאות.
AnalogFrontendSettings
Atsc3FrontendSettings
AtscFrontendSettings
DvbcFrontendSettings
DvbsFrontendSettings
DvbtFrontendSettings
Isdbs3FrontendSettings
IsdbsFrontendSettings
IsdbtFrontendSettings
החל מגרסה Android 12 עם Tuner HAL 1.1 ואילך, יש תמיכה בתקן ה-DTV הבא.
DtmbFrontendSettings
FrontendCapabilities
נגזר מהתקנים השונים של DTV לפי הכיתות הבאות.
AnalogFrontendCapabilities
Atsc3FrontendCapabilities
AtscFrontendCapabilities
DvbcFrontendCapabilities
DvbsFrontendCapabilities
DvbtFrontendCapabilities
Isdbs3FrontendCapabilities
IsdbsFrontendCapabilities
IsdbtFrontendCapabilities
החל מגרסה 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
כדי לציין שפעולת הסריקה הסתיימה.המערכת חוזרת על הפעולות שלמעלה עד שכל ההגדרות בתדר נגמרו.
ה-HAL שולח את הערך
END
כדי לציין שפעולת הסריקה הסתיימה.ה-TIS עובר לתדר הזמין הבא ברשימת התדרים שלו.
TIS יתקשר שוב אל Tuner.scan(AUTO_SCAN)
עד שכל התדרים ינוצלו.
במהלך הסריקה, אפשר להקיש על stopScan()
או על close()
כדי להשהות או לסיים את הסריקה.
Tuner.scan(BLIND_SCAN)
אם ל-TIS אין רשימת תדירויות, ו-HAL של הספק יכול לחפש את התדירות של ממשק הקצה שצוין על ידי המשתמש כדי לקבל את המשאב של ממשק הקצה, מומלץ להשתמש ב-Tuner.scan(BLIND_SCAN)
.
- TIS משתמש ב-
Tuner.scan(BLIND_SCAN)
. אפשר לציין תדירות ב-FrontendSettings
לתדירות ההתחלה, אבל TIS מתעלם מהגדרות אחרות ב-FrontendSettings
. - ה-HAL מדווח על הודעת סריקה
LOCKED
אם האות נעול. - TIS משתמש ב-
Frontend.getStatus
כדי לאסוף את המידע הנדרש. - TIS קורא שוב ל-
Tuner.scan
כדי להמשיך את הסריקה. (הערך שלFrontendSettings
מתעלם). - המערכת חוזרת על הפעולות שלמעלה עד שכל ההגדרות בתדר נגמרו. ה-HAL מגדיל את התדירות ללא צורך בפעולה מצד ה-TIS.
ה-HAL מדווח על
PROGRESS
.
TIS יתקשר שוב אל Tuner.scan(AUTO_SCAN)
עד שכל התדרים ינוצלו.
ה-HAL מדווח על END
כדי לציין שפעולת הסריקה הסתיימה.
במהלך הסריקה, אפשר להקיש על stopScan()
או על close()
כדי להשהות או לסיים את הסריקה.
איור 9. תרשים זרימה של סריקה של TIS
Android.media.tv.tuner.filter
חבילת המסנן היא אוסף של פעולות סינון יחד עם הגדרות, אירועים ופונקציות חזרה (callbacks). החבילה כוללת את הפעולות הבאות. בקוד המקור של Android מופיעה רשימה מלאה של הפעולות.
configure()
start()
stop()
flush()
read()
הרשימה המלאה מופיעה בקוד המקור של Android.
המאפיין FilterConfiguration
נגזר מהמערכות הבאות. ההגדרות הן לסוג המסנן הראשי, והן מציינות את הפרוטוקול שבו המסנן משתמש כדי לחלץ נתונים.
AlpFilterConfiguration
IpFilterConfiguration
MmtpFilterConfiguration
TlvFilterConfiguration
TsFilterConfiguration
ההגדרות נגזרות מהקלאסות הבאות. ההגדרות הן של סוג המשנה של המסנן, והן מציינות אילו סוגי נתונים המסנן יכול להחריג.
SectionSettings
AvSettings
PesSettings
RecordSettings
DownloadSettings
FilterEvent
נגזר מהכיתות הבאות כדי לדווח על אירועים של סוגים שונים של נתונים.
SectionEvent
MediaEvent
PesEvent
TsRecordEvent
MmtpRecordEvent
TemiEvent
DownloadEvent
IpPayloadEvent
החל מגרסה Android 12 עם Tuner HAL 1.1 ואילך, המערכת תומכת באירועים הבאים.
IpCidChangeEvent
RestartEvent
ScramblingStatusEvent
אירועים ותבנית נתונים מהמסנן
סוג מסנן | דגלים | אירועים | פעולה בנתונים | פורמט הנתונים |
---|---|---|---|---|
TS.SECTION MMTP.SECTION IP.SECTION TLV.SECTION ALP.SECTION |
isRaw: |
חובה:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW מומלץ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
בהתאם לאירוע וללוח הזמנים הפנימי, מריצים אתFilter.read(buffer, offset, adjustedSize) פעם אחת או יותר.הנתונים מועתקים מ-MQ של HAL למאגר הנתונים של הלקוח. |
חבילת סשן אחת מורכבת וממולאת ב-FMQ על ידי חבילת סשן אחרת. |
isRaw: |
חובה:DemuxFilterEvent::DemuxFilterSectionEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW אופציונלי: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ הנתונים מועתקים מ-MQ של HAL למאגר של הלקוח. |
||
TS.PES |
isRaw: |
חובה:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW מומלץ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
בהתאם לאירוע וללוח הזמנים הפנימי, מריצים אתFilter.read(buffer, offset, adjustedSize) פעם אחת או יותר.הנתונים מועתקים מ-MQ של HAL למאגר הנתונים של הלקוח. |
חבילה אחת של PES מורכבת ממלאת את FMQ בחבילת PES אחרת. |
isRaw: |
חובה:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW אופציונלי: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ הנתונים מועתקים מ-MQ של HAL למאגר הנתונים של הלקוח. |
||
MMTP.PES |
isRaw: |
חובה:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW מומלץ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
בהתאם לאירוע וללוח הזמנים הפנימי, מריצים אתFilter.read(buffer, offset, adjustedSize) פעם אחת או יותר.הנתונים מועתקים מ-MQ של HAL למאגר הנתונים של הלקוח. |
חבילת MFU אחת מורכבת וממולאת ב-FMQ על ידי חבילת MFU אחרת. |
isRaw: |
חובה:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW אופציונלי: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ הנתונים מועתקים מ-MQ של HAL למאגר הנתונים של הלקוח. |
||
TS.TS |
לא רלוונטי | חובה:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW מומלץ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
בהתאם לאירוע וללוח הזמנים הפנימי, מריצים אתFilter.read(buffer, offset, adjustedSize) פעם אחת או יותר.הנתונים מועתקים מ-MQ של HAL למאגר הנתונים של הלקוח. |
ts שסוננו עם הכותרת ts מתמלאים ב-FMQ. |
TS.Audio TS.Video MMTP.Audio MMTP.Video |
isPassthrough: |
אופציונלי:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
הלקוח יכול להתחיל את MediaCodec אחרי שהוא מקבל את DemuxFilterStatus::DATA_READY .אחרי קבלת DemuxFilterStatus::DATA_OVERFLOW , הלקוח יכול לקרוא ל-Filter.flush . |
לא רלוונטי |
isPassthrough: |
חובה:DemuxFilterEvent::DemuxFilterMediaEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW אופציונלי: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
כדי להשתמש ב-MediaCodec :for i=0; i<n; i++ כדי להשתמש ב-Direct Audio של AudioTrack :for i=0; i<n; i++ |
נתוני ES או נתונים חלקיים של ES בזיכרון ION. | |
TS.PCR IP.NTP ALP.PTP |
לא רלוונטי | חובה: לא רלוונטי
אופציונלי: לא רלוונטי |
לא רלוונטי | לא רלוונטי |
TS.RECORD |
לא רלוונטי | חובה: DemuxFilterEvent::DemuxFilterTsRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER אופציונלי: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
לנתוני אינדקס:for i=0; i<n; i++ לתוכן שהוקלט, בהתאם ל- RecordStatus::* ולתזמון הפנימי, מבצעים אחת מהפעולות הבאות:
|
לנתוני אינדקס: הנתונים מועברים בתוכן של האירוע. לתוכן שהוקלט: שידור TS מעורבב שמתמלא ב-FMQ. |
TS.TEMI |
לא רלוונטי | חובה:DemuxFilterEvent::DemuxFilterTemiEvent[n] אופציונלי: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ |
לא רלוונטי |
MMTP.MMTP |
לא רלוונטי | חובה:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW מומלץ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
בהתאם לאירוע וללוח הזמנים הפנימי, מריצים אתFilter.read(buffer, offset, adjustedSize) פעם אחת או יותר.הנתונים מועתקים מ-MQ של HAL למאגר הנתונים של הלקוח. |
mmtp שסוננו עם הכותרת mmtp מתמלאים ב-FMQ. |
MMTP.RECORD |
לא רלוונטי | חובה:DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n] RecordStatus::DATA_READY RecordStatus::DATA_OVERFLOW RecordStatus::LOW_WATER RecordStatus::HIGH_WATER אופציונלי: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
לנתוני אינדקס: for i=0; i<n; i++ לתוכן שהוקלט, בהתאם ל- RecordStatus::* ולתזמון הפנימי, מבצעים אחת מהפעולות הבאות:
|
לנתוני אינדקס: הנתונים מועברים בתוכן של האירוע. לתוכן שהוקלט: שידור מוקלט משולב שמתמלא ב-FMQ. אם מקור המסנן להקלטה הוא TLV.TLV עד
IP.IP עם העברה ישירה, בסטרימינג המוקלט יש כותרת TLV ו-IP. |
MMTP.DOWNLOAD |
לא רלוונטי | חובה:DemuxFilterEvent::DemuxFilterDownloadEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW אופציונלי: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size) הנתונים מועתקים מ-MQ של HAL למאגר של הלקוח. |
חבילת ההורדה מתמלאת ב-FMQ על ידי חבילת הורדה אחרת של IP. |
IP.IP_PAYLOAD |
לא רלוונטי | חובה:DemuxFilterEvent::DemuxFilterIpPayloadEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW אופציונלי: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size) הנתונים מועתקים מ-MQ של HAL למאגר של הלקוח. |
חבילת נתוני העל של ה-IP מתמלאת ב-FMQ על ידי חבילת נתוני עלי של IP אחרת. |
IP.IP TLV.TLV ALP.ALP |
isPassthrough: |
אופציונלי:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
מקור הנתונים המשני של הפרוטוקול שעבר סינון מזין את המסנן הבא בשרשרת המסננים. | לא רלוונטי |
isPassthrough: |
חובה:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW מומלץ: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
בהתאם לאירוע וללוח הזמנים הפנימי, מריצים אתFilter.read(buffer, offset, adjustedSize) פעם אחת או יותר.הנתונים מועתקים מ-MQ של HAL למאגר הנתונים של הלקוח. |
מקור הנתונים המשני של הפרוטוקול שעבר סינון עם כותרת הפרוטוקול מתמלא ב-FMQ. | |
IP.PAYLOAD_THROUGH TLV.PAYLOAD_THROUGH ALP.PAYLOAD_THROUGH |
לא רלוונטי | אופציונלי:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
עומס העבודה של הפרוטוקול שסונן מזין את המסנן הבא בשרשרת המסננים. | לא רלוונטי |
תהליך לדוגמה לשימוש במסנן ליצירת 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. תהליך השימוש ב-MediaEvent מהמסנן
- פותחים, מגדירים ומפעילים את המסננים של הווידאו והאודיו.
- מעבדים את
MediaEvent
. - מקבלים את
MediaEvent
. - מוסיפים את הבלוק הליניארי לתור של
codec
. - משחררים את ה-handle של ה-A/V כשהנתונים נצרכים.
Android.media.tv.tuner.dvr
DvrRecorder
מספק את השיטות האלה להקלטה.
configure
attachFilter
detachFilter
start
flush
stop
setFileDescriptor
write
DvrPlayback
מספק את השיטות האלה להפעלה.
configure
start
flush
stop
setFileDescriptor
read
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
Tuner HAL פועל לפי 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.hal IFrontendCallback.hal |
IDemux |
close |
setFrontendDataSource , openFilter , openDvr , getAvSyncHwId ,
getAvSyncTime , connect / disconnectCiCam |
IDemux.hal |
IDvr |
close , start , stop , configure |
attach/detachFilters , flush getQueueDesc |
IDvr.hal IDvrCallback.hal |
IFilter |
close , start , stop , configure , getId |
flush , getQueueDesc , releaseAvHandle , setDataSource |
IFilter.hal IFilterCallback.hal |
ILnb |
close , setCallback |
setVoltage , setTone , setSatellitePosition , sendDiseqcMessage |
ILnb.hal ILnbCallback.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
לפני Tuner Resource Manager (TRM), כדי לעבור בין שתי אפליקציות היה צורך באותה חומרה של Tuner. ב-TV Input Framework (TIF) נעשה שימוש במנגנון 'הראשון לקבל זוכה', כלומר האפליקציה שמקבלת את המשאב קודם שומרת עליו. עם זאת, יכול להיות שהמנגנון הזה לא יתאים לתרחישים מסוימים של שימוש מורכב.
TRM פועל כשירות מערכת לניהול המשאבים של חומרת ה-Tuner, TVInput
ו-CAS לאפליקציות. ב-TRM נעשה שימוש במנגנון 'עדיפות לחזית', שמחשב את העדיפות של האפליקציה על סמך הסטטוס שלה (חזית או רקע) וסוג התרחיש לדוגמה. 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)
ממשקי ה-API לבקשה ולשחרור משאבים מפורטים בהמשך.
requestFrontend(TunerFrontendRequest request, int[] frontendHandle)
/releaseFrontend
requestDemux(TunerDemuxRequest request, int[] demuxHandle)
/releaseDemux
requestDescrambler(TunerDescramblerRequest request, int[] descramblerHandle)
/releaseDescrambler
requestCasSession(CasSessionRequest request, int[] casSessionHandle)
/releaseCasSession
-
requestLnb(TunerLnbRequest request, int[] lnbHandle)
מתוךreleaseLnb
הכיתות של הלקוח והבקשה מפורטות בהמשך.
ResourceClientProfile
ResourcesReclaimListener
TunerFrontendRequest
TunerDemuxRequest
TunerDescramblerRequest
CasSessionRequest
TunerLnbRequest
עדיפות הלקוח
מערכת 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
.
ערך שרירותי של עדיפות וערך נוח
TRM מספק את updateClientPriority
ללקוח כדי לעדכן את ערך העדיפות והערך הרצוי.
ערך העדיפות השרירותי מחליף את ערך העדיפות שמחושב מסוג תרחיש השימוש וממזהה הסשן.
הערך nice מציין את מידת הסובלנות של הלקוח כשיש לו התנגשויות עם לקוח אחר. הערך 'נחמד' מקטין את ערך העדיפות של הלקוח לפני שהערך הזה מושווה לערך העדיפות של הלקוח המאתגר.
מנגנון להחזרת מספרים
בתרשים הבא מוצג איך משאבים מוקצים מחדש כשמתרחש סכסוך על משאבים.
איור 15. דיאגרמה של מנגנון משיכת המשאבים במקרה של התנגשויות בין משאבי Tuner