מסגרת טיונר

ב-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 ובמצב 'העברת מידע'.

העיצוב הכללי של הטיונר HAL.

איור 2. תרשים הרכיבים בתוך הטיונר HAL

תהליך עבודה כולל

התרשימים הבאים ממחישים רצפי שיחות להפעלה של שידור חי.

הגדרה

הגדרת רצף של תרשים הפעלה של שידור חי.

איור 3. הגדרת רצף להפעלה של שידור חי

טיפול בוידאו/וידאו

טיפול באודיו/וידאו בתרשים הפעלה של שידור חי.

איור 4. טיפול בוידאו/וידאו להפעלה של שידור חי

טיפול בתוכן מעורבל

טיפול בתוכן מעורבל בתרשים הפעלה של שידור חי.

איור 5. טיפול בתוכן מעורבל להפעלה של שידור חי

מתבצע עיבוד של נתוני אודיו/וידאו

עיבוד נתוני אודיו/וידאו עבור תרשים של הפעלת שידור חי.

איור 6. עיבוד אודיו/וידאו להפעלה של שידור חי

API של טיונר SDK

ה-Tuner SDK API מטפל באינטראקציות עם ה-JNI של טיונר, ה-Tuner HAL וTunerResourceManager. אפליקציית TIS משתמשת ב-Tionr SDK API כדי לגשת לטיונר או מרכיבי משנה כמו המסנן והמפענח. קצה קדמי ו demux הם רכיבים פנימיים.

דיאגרמה של הזרימה ב-Tuner SDK API.

איור 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

תרשים זרימה של חבילות ממשקי ה-API שלTuner SDK.

איור 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() כדי להשהות או לסיים את הסריקה.

תרשים זרימה של תהליך סריקת ה-TIS.

איור 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:
true
חובה:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

מומלץ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
בהתאם לאירוע וללוח הזמנים הפנימי, יש להריץ
Filter.read(buffer, offset, adjustedSize) אחד או יותר פעמים.

הנתונים מועתקים מה-MQ של HAL למאגר הנתונים הזמני של הלקוח.
אחת מחבילות הסשן שהורכבה מולאה ב-FMQ על ידי מכשיר אחר חבילת גלישה.
isRaw:
false
חובה:
DemuxFilterEvent::DemuxFilterSectionEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

אופציונלי:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterSectionEven[i].size)


הנתונים מועתקים מה-MQ של HAL למאגר הנתונים הזמני של הלקוח.
TS.PES isRaw:
true
חובה:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

מומלץ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
בהתאם לאירוע וללוח הזמנים הפנימי, יש להריץ
Filter.read(buffer, offset, adjustedSize) אחד או יותר פעמים.

הנתונים מועתקים מה-MQ של HAL למאגר הנתונים הזמני של הלקוח.
אחת מחבילות ה-PES המורכבות מולאה ב-FMQ על ידי אחר חבילת מומחי מוצרים (PES).
isRaw:
false
חובה:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

אופציונלי:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


הנתונים מועתקים מה-MQ של HAL למאגר הנתונים הזמני של הלקוח.
MMTP.PES isRaw:
true
חובה:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

מומלץ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
בהתאם לאירוע וללוח הזמנים הפנימי, יש להריץ
Filter.read(buffer, offset, adjustedSize) אחד או יותר פעמים.

הנתונים מועתקים מה-MQ של HAL למאגר הנתונים הזמני של הלקוח.
אחת מחבילות ה-MFU המורכבות מולאה ב-FMQ על ידי מכשיר אחר חבילת MFU.
isRaw:
false
חובה:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

אופציונלי:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


הנתונים מועתקים מה-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:
true
אופציונלי:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
הלקוח יכול להתחיל MediaCodec אחרי קבלת DemuxFilterStatus::DATA_READY.
הלקוח יכול להתקשר אל Filter.flush אחרי קבלת DemuxFilterStatus::DATA_OVERFLOW.
לא רלוונטי
isPassthrough:
false
חובה:
DemuxFilterEvent::DemuxFilterMediaEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

אופציונלי:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
כדי להשתמש בתכונה MediaCodec:
for i=0; i<n; i++
linearblock = MediaEvent[i].getLinearBlock();
codec.startQueueLinearBlock(linearblock)
linearblock.recycle()


כדי להשתמש באודיו ישיר ב-AudioTrack:
for i=0; i<n; i++
audioHandle = MediaEvent[i].getAudioHandle();
audiotrack.write(encapsulated(audiohandle))
נתוני 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++
DemuxFilterTsRecordEvent[i];


בתוכן מוקלט: בהתאם לRecordStatus::* וללוח הזמנים הפנימי, אחד מהפרטים הבאים:
  • הפעלה של DvrRecord.write(adustedSize) פעם אחת או יותר באחסון.
    הנתונים מועברים מה-MQ של HAL לאחסון.
  • הפעלה של DvrRecord.write(buffer, adustedSize) פעם אחת או יותר למאגר הנתונים הזמני.
    הנתונים מועתקים מה-MQ של HAL למאגר הנתונים הזמני של הלקוח.
לנתוני אינדקס: מועבר במטען ייעודי (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++
DemuxFilterTemiEvent[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++
DemuxFilterMmtpRecordEvent[i];


בתוכן מוקלט, בהתאם RecordStatus::* ולוח זמנים פנימי, מבצעים אחת מהפעולות הבאות הבאים:
  • הפעלה של DvrRecord.write(adjustedSize) פעם אחת או יותר לאחסון.
    הנתונים מועברים מה-MQ של HAL לאחסון.
  • מפעילים DvrRecord.write(buffer, adjustedSize)אחת או יותר פעמים למאגר נתונים זמני.
    הנתונים מועתקים מה-MQ של HAL למאגר הנתונים הזמני של הלקוח.
לנתוני אינדקס: מועבר במטען ייעודי (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:
true
אופציונלי:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
מסננים של פידים משניים של פרוטוקולים, במסנן הבא במסנן או שרשרת אספקה. לא רלוונטי
isPassthrough:
false
חובה:
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

תהליך לדוגמה לשימוש במסנן לפיתוח PSI/SI.

איור 10. תהליך לבניית PSI/SI

  1. פותחים מסנן.

    Filter filter = tuner.openFilter(
      Filter.TYPE_TS,
      Filter.SUBTYPE_SECTION,
      /* bufferSize */1000,
      executor,
      filterCallback
    );
    
  2. מגדירים ומפעילים את המסנן.

    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();
    
  3. עיבוד של 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 ממסנן

תהליך לדוגמה לשימוש ב-MediaEvent ממסנן.

איור 11. זרימה לשימוש ב-MediaEvent ממסנן

  1. פתיחה, הגדרה והפעלה של מסנני A/V.
  2. עיבוד של MediaEvent.
  3. מקבלים את MediaEvent.
  4. מוסיפים את הבלוק הלינארי ל-codec.
  5. משחררים את נקודת האחיזה להקלטת אודיו/וידאו בסיום צריכת הנתונים.

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. זרימה כדי להתחיל רשומה

  1. פתיחה, הגדרה והפעלה של 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();
    
  2. מקבלים את הקוד 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. }
          }
        }
    };
    
  3. הפעלת 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

תרשים זרימה של אינטראקציות בין המודולים של טיונר 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. תרשים של מנגנון דרישה להתנגשות בין טיונר משאבים