ב-Android מגרסה 11 ואילך, אפשר להשתמש ב-Android מסגרת טיונר להעברת תוכן אודיו/וידאו. ה-framework משתמש בחומרה של צינור עיבוד נתונים מספקים, וכך הוא מתאים גם ל-SoC מתקדם וגם ל-SoC מתקדם. ה-framework מספק דרך מאובטחת להעברת תוכן אודיו/וידאו המוגן באמצעות וסביבת הפעלה מהימנה (TEE) ונתיב מדיה מאובטח (SMP), וכך מאפשרים לשימוש בסביבה מוגבלת מאוד להגנה על תוכן.
הממשק הסטנדרטי בין טיונר ל-Android CAS מספק
שילוב בין ספקי טיונר לספקי CAS. ממשק הטיונר פועל
עם MediaCodec
ועם AudioTrack
כדי לפתח פתרון עולמי אחד ל-Android TV.
ממשק הטיונר תומך בטלוויזיה דיגיטלית ובטלוויזיה אנלוגית, על בסיס
תקני שידור.
רכיבים
ב-Android 11, קיימים שלושה רכיבים ספציפיים שמיועד לפלטפורמת הטלוויזיה.
- Tuner HAL: ממשק בין ה-framework לבין הספקים
- Tuner SDK API: ממשק בין ה-framework לבין האפליקציות
- Tuner Resource Manager (TRM): משאבים של Coordinates Tuner HW
ב-Android 11 הרכיבים הבאים עודכנו משופרת.
- CAS גרסה 2
TvInputService
או שירות קלט טלוויזיה (TIS)TvInputManagerService
או שירות של מנהל קלט הטלוויזיה (TIMS)MediaCodec
או קודק מדיהAudioTrack
או טראק של אודיוMediaResourceManager
או מנהל/ת משאבי מדיה (MRM)
איור 1. אינטראקציות בין רכיבים של Android TV
תכונות
הקצה הקדמי תומך בתקני ה-DTV שמפורטים בהמשך.
- ATSC
- ATSC3
- DVB C/S/T
- ISDB S/S3/T
- אנלוגי
החזית ב-Android 12 עם טיונר HAL 1.1 ואילך תומכת בתקן ה-DTV שלמטה.
- DTMB
הדגמה (Demux) תומכת בפרוטוקולים של השידורים שבהמשך.
- Transport Stream (TS)
- פרוטוקול העברת מדיה MPEG (MMTP)
- פרוטוקול אינטרנט (IP)
- ערך אורך סוג (TLV)
- ATSC פרוטוקול שכבת קישור (ALP)
הכלי Descrambler תומך בהגנות התוכן הבאות.
- נתיב מדיה מאובטח
- ניקוי נתיב המדיה
- רשומה מקומית מאובטחת
- הפעלה מקומית מאובטחת
ממשקי API של טיונר תומכים בתרחישים לדוגמה שבהמשך.
- סריקה
- בשידור חי
- הפעלה
- הקלטה
בטיונר, MediaCodec
ו-AudioTrack
תומכים במצבי זרימת הנתונים שבהמשך.
- מטען ייעודי (payload) של ES עם מאגר זיכרון ברור
- מטען ייעודי (payload) של ES עם נקודת אחיזה מאובטחת לזיכרון
- שקופה
עיצוב כללי
ממשק הטיונר HAL מוגדר בין ה-framework של Android לבין חומרה.
- מתאר למה המסגרת מצפה מהספק ואיך הספק עשוי לעשות את זה.
- מייצאת את הפונקציונליות של ממשק הקצה, של דגימת ה-Demux ושל המפענח,
מסגרת דרך
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
, ו-ILnb
וממשקים. - כולל את הפונקציות לשילוב HAL של הטיונר עם framework אחר
רכיבים שונים, כמו
MediaCodec
ו-AudioTrack
.
המערכת יוצרת כיתת טיונר Java ומחלקה נייטיב.
- ה-Tuner Java API מאפשר לאפליקציות לקבל גישה ל-Tuner HAL דרך ממשקי API ציבוריים.
- מחלקה מקומית מאפשרת לשלוט בהרשאות גדולות ולטפל בהן הקלטה או הפעלה של נתונים באמצעות ממשק הטיונר HAL.
- מודול Native Tur (טיונר) מגשר בין המחלקה 'טיונר Java' לבין הטיונר HAL.
נוצרת מחלקה של TRM.
- ניהול משאבים מוגבלים בטיונר, כמו Frontend, LNB, סשנים של CAS ומכשיר לקליטת נתונים מהטלוויזיה עם HAL.
- החלת כללים כדי להחזיר משאבים לא מספיקים מ- באפליקציות. כלל ברירת המחדל הוא מנצחת בחזית.
אישורי CAS ו-CAS HAL משופרים בעזרת התכונות הבאות.
- פתיחת סשנים של CAS לשימושים ולאלגוריתמים שונים.
- תמיכה במערכות CAS דינמיות, כמו הסרה והוספה של CICAM.
- משתלב עם ממשק ה-HAL של הטיונר באמצעות מתן אסימוני מפתח.
MediaCodec
ו-AudioTrack
שופרו באמצעות התכונות שמפורטות בהמשך.
- מקבל זיכרון A/V מאובטח כקלט תוכן.
- מוגדר לביצוע סנכרון אודיו/וידאו של חומרה בהפעלה עם מנהרה.
- הוגדרו תמיכה ב-
ES_payload
ובמצב 'העברת מידע'.
איור 2. תרשים הרכיבים בתוך הטיונר HAL
תהליך עבודה כולל
התרשימים הבאים ממחישים רצפי שיחות להפעלה של שידור חי.
הגדרה
איור 3. הגדרת רצף להפעלה של שידור חי
טיפול בוידאו/וידאו
איור 4. טיפול בוידאו/וידאו להפעלה של שידור חי
טיפול בתוכן מעורבל
איור 5. טיפול בתוכן מעורבל להפעלה של שידור חי
מתבצע עיבוד של נתוני אודיו/וידאו
איור 6. עיבוד אודיו/וידאו להפעלה של שידור חי
API של טיונר SDK
ה-Tuner SDK API מטפל באינטראקציות עם ה-JNI של טיונר, ה-Tuner HAL
וTunerResourceManager
. אפליקציית TIS משתמשת ב-Tionr SDK API כדי לגשת לטיונר
או מרכיבי משנה כמו המסנן והמפענח. קצה קדמי ו
demux הם רכיבים פנימיים.
איור 7. אינטראקציות עם Tur SDK API
גרסאות
החל מ-Android 12, Tuner SDK API תומך בתכונה חדשה ב-Tuner HAL 1.1. הוא שדרוג גרסה תואם לאחור של טיונר 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 של Tur SDK
Android.media.tv.כוונוןr
חבילת הטיונר היא נקודת כניסה לשימוש במסגרת הטיונר. אפליקציית TIS משתמש בחבילה כדי לאתחל ולקבל מופעים של משאבים על ידי ציון את ההגדרה הראשונית ואת הקריאה החוזרת.
tuner()
: מאתחל מופע של טיונר על ידי ציון הערכיםuseCase
sessionId
פרמטרים.tune()
: מקבל משאב וכוונון בקצה הקדמי על ידי ציון הרכיבFrontendSetting
.openFilter()
: קבלת מופע של מסנן על ידי ציון סוג המסנן.openDvrRecorder()
: קבלת מופע הקלטה על ידי ציון מאגר הנתונים הזמני גודל.openDvrPlayback()
: קבלת מופע הפעלה על ידי ציון מאגר הנתונים הזמני גודל.openDescrambler()
: קבלת מופע של מפענח.openLnb()
: מקבלת מכונת LNB פנימית.openLnbByName()
: מקבלת מכונת LNB חיצונית.openTimeFilter()
: אחזור מופע של מסנן זמן.
חבילת הטיונר מספקת פונקציות שלא נכללות חבילות הסינון, ה-DVR והחזית. הפונקציות האלה מפורטות בהמשך.
cancelTuning
-
scan
מתוךcancelScanning
getAvSyncHwId
getAvSyncTime
-
connectCiCam1
מתוךdisconnectCiCam
shareFrontendFromTuner
updateResourcePriority
setOnTuneEventListener
setResourceLostListener
Android.media.tv.tensr.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 עם Tiunr 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
.
Listenr.scan(auto_SCAN)
אם ב-TIS אין מספיק מידע כדי להשתמש ב-Tuner.tune
, אבל יש לו תדירות
והסוג הסטנדרטי (לדוגמה, DVB T/C/S),
ואז מומלץ להשתמש ב-Tuner.scan(AUTO_SCAN)
.
כשהמשתמש מתקשר אל Tuner.scan(AUTO_SCAN)
, מתרחשות הפעולות הבאות:
ב-TIS נעשה שימוש ב-
Tuner.scan(AUTO_SCAN)
עם ערך שלFrontendSettings
במילוי תדירות.אם האות נעול, מתבצע סריקה של
LOCKED
הודעות בדוחות HAL. מדד ה-HAL עשוי לדווח גם על הודעות סריקה אחרות כדי לספק מידע נוסף על את האות.ב-TIS נעשה שימוש ב-
Frontend.getStatus
כדי לאסוף את המידע הנחוץ.מערכת TIS מפעילה את הפונקציה
Tuner.scan
כדי לאפשר ל-HAL להמשיך להגדרה הבאה באותו אופן בתדירות גבוהה. אם המבנהFrontendSettings
ריק, ה-HAL משתמש בפונקציה הבאה ההגדרה הזמינה. אחרת, HAL משתמש ב-FrontendSettings
באופן חד-פעמי לסרוק ולשלוח את הפקודהEND
כדי לציין שפעולת הסריקה הסתיימה.מערכת TIS חוזרת על הפעולות שלמעלה עד שכל ההגדרות של התדירות מותשים.
HAL שולח
END
כדי לציין שפעולת הסריקה הסתיימה.ה-TIS עובר לתדירות הזמינה הבאה ברשימת התדירות שלו.
TIS קורא שוב למספר Tuner.scan(AUTO_SCAN)
עד שכל התדרים יתמלאו.
במהלך הסריקה, אפשר להתקשר אל stopScan()
או close()
כדי להשהות או לסיים את
לסרוק.
Listenr.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
הוא המערכת מתעלמת מהצומת.) - מערכת TIS חוזרת על הפעולות שלמעלה עד שכל ההגדרות של התדירות
מותשים. ה-HAL מגביר את התדירות ללא צורך בפעולה נוספת מ-TIS.
מערכת HAL מדווחת על
PROGRESS
.
TIS קורא שוב למספר Tuner.scan(AUTO_SCAN)
עד שכל התדרים יתמלאו.
תקן HAL מדווח על END
כדי לציין שפעולת הסריקה הסתיימה.
במהלך הסריקה, אפשר להתקשר אל stopScan()
או close()
כדי להשהות או לסיים את הסריקה.
איור 9. תרשים זרימה של סריקת TIS
Android.media.tv.tuner.filter
חבילת הסינון היא אוסף של פעולות סינון יחד עם הגדרות אישיות, הגדרות, קריאות חוזרות (callback) ואירועים. החבילה כוללת את הפעולות הבאות. רשימה מלאה של הפעולות מופיעה בקוד המקור של 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 עם Donr 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 .הלקוח יכול להתקשר אל Filter.flush אחרי קבלת DemuxFilterStatus::DATA_OVERFLOW . |
לא רלוונטי |
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 למאגר הנתונים הזמני של הלקוח. |
חבילת המטען הייעודי (payload) של כתובת ה-IP מתמלאת ב-FMQ על ידי חבילת מטען ייעודי (payload) אחרת של 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.tensr.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); } } };
טיונר HAL
הטיונר HAL עוקב אחר HIDL ומגדיר את הממשק בין ה-framework בחומרה של הספק. ספקים משתמשים בממשק כדי להטמיע את ממשק הטיונר HAL framework משתמשת בו כדי לתקשר עם הטמעת ה-Tuner HAL.
מודולים
טיונר 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 |
טיונר HAL 1.1 (נגזר מטיונר 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. תרשים האינטראקציות בין המודולים של טיונר 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. תרשים זרימה של קישור מסנן עבור שכבות מרובות
מנהל המשאבים של הטיונר
לפני המעבר למנהל המשאבים של טיונר (TRM), המעבר בין שתי אפליקציות חייב אותה חומרת טיונר. TV קלט Framework (TIF) השתמשה ב"זכייה ראשונה בהשגת" מנגנון כזה, כלומר האפליקציה שמקבלת את המשאב קודם שומרת את המשאב. עם זאת, יכול להיות שהמנגנון הזה לא יהיה אידיאלי בתרחישים מורכבים מסוימים.
TRM פועל כשירות מערכת לניהול החומרה של הטיונר, 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)
הממשקים לשליחת בקשה ולשחרור המשאבים מפורטים בהמשך.
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
ללקוח כדי לעדכן את השרירות
ערך עדיפות וערך נחמד.
ערך העדיפות השרירותית מחליף את ערך העדיפות שמחושב
מסוג תרחיש לדוגמה וממזהה הסשן.
הערך 'יפה' מציין עד כמה מאופקת התנהגות הלקוח כשהוא מחלוקות עם לקוח אחר. הערך היפה מקטין את העדיפות של הלקוח לפני ערך העדיפות שלו בהשוואה ללקוח המאתגר.
מנגנון דרישה
התרשים הבא מראה איך המשאבים מוחזרים ומוקצים מתרחשת התנגשות בין משאבים.
איור 15. תרשים של מנגנון דרישה להתנגשות בין טיונר משאבים