מסגרת הטיונר

במכשירי 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)

תרשים זרימה של הרכיבים של מסגרת Tuner.

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

העיצוב הכללי של HAL של Tuner.

איור 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 הם רכיבים פנימיים.

תרשים זרימה של Tuner SDK API.

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

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

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

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

איור 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:
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.
אחרי קבלת DemuxFilterStatus::DATA_OVERFLOW, הלקוח יכול לקרוא ל-Filter.flush.
לא רלוונטי
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()


כדי להשתמש ב-Direct Audio של 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 למאגר הנתונים של הלקוח.
לנתוני אינדקס: הנתונים מועברים בתוכן של האירוע.

לתוכן שהוקלט: שידור 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 למאגר הנתונים של הלקוח.
לנתוני אינדקס: הנתונים מועברים בתוכן של האירוע.

לתוכן שהוקלט: שידור מוקלט משולב שמתמלא ב-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:
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
עומס העבודה של הפרוטוקול שסונן מזין את המסנן הבא בשרשרת המסננים. לא רלוונטי
תהליך לדוגמה לשימוש במסנן ליצירת 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. פותחים, מגדירים ומפעילים את המסננים של הווידאו והאודיו.
  2. מעבדים את MediaEvent.
  3. מקבלים את MediaEvent.
  4. מוסיפים את הבלוק הליניארי לתור של codec.
  5. משחררים את ה-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. תהליך התחלת ההקלטה

  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);
          }
        }
      };
    

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

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