ב-Android מגרסה 11 ואילך, תוכלו להשתמש ב-Android Touner framework כדי להעביר תוכן אודיו/וידאו. תוכנת ה-framework משתמשת בצינור עיבוד נתונים של חומרה, ולכן היא מתאימה גם ל-SoC מתקדם וגם ל-SoC מתקדם. ה-framework מספק דרך מאובטחת להעביר תוכן A/V שמוגן על ידי סביבת הפעלה מהימנה (TEE) ונתיב מדיה מאובטח (SMP), וכך אפשר להשתמש בו בסביבה מוגבלת מאוד להגנה על תוכן.
הממשק הסטנדרטי בין טיונר וספקי CAS של Android מאפשר שילוב מהיר יותר בין ספקים של טיונר לבין ספקי CAS. ממשק הטיונר עובד עם MediaCodec
ועם AudioTrack
כדי לבנות פתרון עולמי אחד ל-Android TV.
ממשק הטיונר תומך גם בטלוויזיה דיגיטלית וגם בטלוויזיה אנלוגית לפי תקני שידור מובילים.
רכיבים
ב-Android 11, יש שלושה רכיבים שמיועדים במיוחד לפלטפורמת הטלוויזיה.
- Tuner HAL: ממשק בין המסגרת לבין הספקים
- Tuner SDK API: ממשק בין ה-framework לבין האפליקציות
- Tuner Resource Manager (TRM): משאבים של Coordinates Tuner HW
הרכיבים הבאים עברו שיפור ל-Android 11.
- CAS גרסה 2
TvInputService
או שירות קלט טלוויזיה (TIS)TvInputManagerService
או שירות TV Input Manager (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
ניתוח הנתונים תומך בפרוטוקולים הבאים של שידורים.
- Transport stream (TS)
- פרוטוקול העברת מדיה MPEG (MMTP)
- פרוטוקול אינטרנט (IP)
- ערך אורך סוג (TLV)
- פרוטוקול שכבת הקישור של ATSC (ALP)
ה-Descrambler תומך באמצעי ההגנה הבאים על תוכן:
- נתיב מדיה מאובטח
- ניקוי נתיב המדיה
- רשומה מקומית מאובטחת
- הפעלה מקומית מאובטחת
ממשקי ה-API של Tuner תומכים בתרחישים לדוגמה הבאים.
- סריקה
- בשידור חי
- הפעלה
- הקלטה
בטיונר, MediaCodec
ו-AudioTrack
תומכים במצבי זרימת הנתונים שבהמשך.
- מטען ייעודי (payload) של ES עם מאגר זיכרון ברור
- עומס עבודה של ES עם טיפול מאובטח בזיכרון
- שקופה
העיצוב הכללי
HAL של הטיונר מוגדר בין ה-framework של Android לבין החומרה של הספק.
- מתאר למה ה-framework מצפה מהספק ואיך הספק יכול לעשות זאת.
- ייצוא הפונקציות של ממשק הקצה, המפצל והפענוח למסגרת דרך ממשקי
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
ו-ILnb
. - כוללת את הפונקציות לשילוב HAL של הטיונר עם רכיבי framework אחרים, כמו
MediaCodec
ו-AudioTrack
.
המערכת יוצרת כיתת טיונר Java ומחלקה נייטיב.
- ה-Tuner Java API מאפשר לאפליקציות לקבל גישה ל-Tuner HAL דרך ממשקי API ציבוריים.
- סיווג Native מאפשר לשלוט בכמות גדולה של נתוני הקלטה או הפעלה באמצעות תכונת הטיונר HAL, ולטפל בהם.
- מודול Tuner מקורי הוא גשר בין הכיתה Tuner ב-Java לבין Tuner HAL.
נוצרת מחלקה של TRM.
- ניהול משאבים מוגבלים בטיונר, כמו Frontend, LNB, סשנים של CAS ומכשיר לקליטת נתונים בטלוויזיה מ-HAL של קלט הטלוויזיה.
- החלת כללים כדי לשחזר כמות לא מספיקה של משאבים מאפליקציות. כלל ברירת המחדל הוא שהחזית מנצחת.
אישורי CAS ו-CAS HAL משופרים בעזרת התכונות שמפורטות בהמשך.
- פתיחת סשנים של CAS לשימושים ולאלגוריתמים שונים.
- תמיכה במערכות CAS דינמיות, כמו הסרה והוספה של CICAM.
- השילוב עם Tuner HAL מתבצע באמצעות אספקת אסימוני מפתחות.
התכונות הבאות כוללות את MediaCodec
ואת AudioTrack
.
- מקבל זיכרון A/V מאובטח כקלט תוכן.
- מוגדר לביצוע סנכרון אודיו/וידאו של חומרה בהפעלה עם מנהרה.
- הגדרת תמיכה ב-
ES_payload
ובמצב העברה (passthrough).
איור 2. תרשים של הרכיבים ב-HAL של Tuner
תהליך העבודה הכולל
התרשימים הבאים ממחישים רצפי שיחות להפעלה של שידור חי.
הגדרה
איור 3. רצף ההגדרה להפעלה של שידור חי
טיפול בוידאו/וידאו
איור 4. טיפול באודיו-וידאו להפעלת שידור חי
טיפול בתוכן מעורבל
איור 5. טיפול בתוכן מוצפן להפעלה של שידורים חיים
עיבוד נתוני אודיו/וידאו
איור 6. עיבוד אודיו/וידאו להפעלה של שידור חי
API של טיונר SDK
ה-Tuner SDK API מטפל באינטראקציות עם ה-JNI של הטיונר, עם ה-TTV HAL ועם TunerResourceManager
. אפליקציית TIS משתמשת ב-Tuner SDK API כדי לגשת למשאבים ולרכיבי המשנה של Tuner, כמו המסנן והמפענח. רכיבי הקצה הקדמי וה-demux הם רכיבים פנימיים.
איור 7. אינטראקציות עם Tuner SDK API
גרסאות
החל מ-Android 12, Tuner SDK API תומך בתכונה חדשה ב-Tuner HAL 1.1, שהיא שדרוג של גרסה 1.0 שלTuner 1.0 שתואמת לאחור.
כדי לבדוק איזו גרסת HAL פועלת, צריך להשתמש ב-API הבא.
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
גרסת ה-HAL המינימלית הנדרשת מופיעה במסמכים של ממשקי ה-API החדשים של Android 12.
חבילות
Tiunr SDK API מספק את ארבע החבילות הבאות.
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.כוונוןr
חבילת הטיונר היא נקודת כניסה לשימוש במסגרת הטיונר. אפליקציית 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 עם Tiunr 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.כוונוןr.filter
חבילת הסינון היא אוסף של פעולות סינון יחד עם הגדרות, הגדרות, קריאה חוזרת ואירועים. החבילה כוללת את הפעולות הבאות. רשימה מלאה של הפעולות מופיעה בקוד המקור של 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 למאגר הנתונים הזמני של הלקוח. |
חבילה אחת של מומחי מוצרים ממלאת ב-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++ כדי להשתמש באודיו ישיר של 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::* ולתזמון הפנימי, מבצעים אחת מהפעולות הבאות:
|
לנתוני אינדקס: מועבר במטען ייעודי (payload) של אירועים. לתוכן שהוקלט: שידור 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::* ולתזמון הפנימי, מבצעים אחת מהפעולות הבאות:
|
לנתוני אינדקס: מועבר במטען ייעודי (payload) של אירועים. לתוכן שהוקלט: שידור מוקלט משולב שמתמלא ב-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 |
מתבצע סינון של הפידים של המטען הייעודי (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. זרימה לשימוש ב-MediaEvent ממסנן
- פתיחה, הגדרה והפעלה של מסנני A/V.
- עיבוד של
MediaEvent
. - מקבלים את
MediaEvent
. - מוסיפים את הבלוק הלינארי ל-
codec
. - משחררים את נקודת האחיזה להקלטת אודיו/וידאו בסיום צריכת הנתונים.
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
טיונר HAL פועל באמצעות HIDL ומגדיר את הממשק בין ה-framework לחומרה של הספק. הספקים משתמשים בממשק כדי להטמיע את 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 תומך בקישור מסנן כך שניתן לקשר מסננים למסננים אחרים עבור מספר שכבות. המסננים פועלים לפי הכללים הבאים.
- המסננים מקושרים כעץ, אסור לסגור את הנתיב.
- צומת הרמה הבסיסית (root) הוא 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 (TRM), כדי לעבור בין שתי אפליקציות היה צורך באותה חומרה של Tuner. במסגרת הטלוויזיה של קלט (TIF) נעשה שימוש במנגנון של 'קודם לזכייה', כלומר, כל אפליקציה שמקבלת את המשאב קודם משאירה אותו. עם זאת, יכול להיות שהמנגנון הזה לא יהיה אידיאלי במקרים מורכבים מסוימים.
TRM פועל כשירות מערכת לניהול המשאבים של חומרת ה-Tuner, TVInput
ו-CAS לאפליקציות. ב-TRM נעשה שימוש במנגנון 'מנצחת בחזית', שמחשב את עדיפות האפליקציה על סמך הסטטוס של האפליקציה בחזית או ברקע וסוג התרחיש לדוגמה שלה. TRM מעניק או מבטל את המשאב על סמך העדיפות. TRM מרכזת את ניהול משאבי ה-ATV לשידור, ישירות ללקוח (OTT) ול-DVR.
ממשק TRM
TRM חושפת ממשקי AIDL ב-ITunerResourceManager.aidl
בשביל ה-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. תרשים של מנגנון ההחזרה להתנגשות בין משאבי טיונר