מסגרת טיונר

עבור Android 11 ומעלה, אתה יכול להשתמש במסגרת Android Tuner כדי לספק תוכן A/V. המסגרת משתמשת בצינור החומרה של ספקים, מה שהופך אותה למתאימה ל-SoC ברמה נמוכה וגם ל-high-end. המסגרת מספקת דרך מאובטחת לספק תוכן A/V מוגן על ידי סביבת ביצוע מהימנה (TEE) ונתיב מדיה מאובטח (SMP), המאפשרת להשתמש בו בסביבת הגנה על תוכן מוגבלת ביותר.

הממשק הסטנדרטי בין Tuner ו-Android CAS מביא לאינטגרציה מהירה יותר בין ספקי Tuner וספקי CAS. ממשק הטיונר עובד עם MediaCodec ו- AudioTrack כדי לבנות פתרון של עולם אחד עבור Android TV. ממשק הטיונר תומך הן בטלוויזיה דיגיטלית והן בטלוויזיה אנלוגית המבוססת על תקני שידור עיקריים.

רכיבים

עבור אנדרואיד 11, שלושה רכיבים תוכננו במיוחד עבור פלטפורמת הטלוויזיה.

  • Tuner HAL: ממשק בין המסגרת לספקים
  • Tuner SDK API: ממשק בין המסגרת לאפליקציות
  • מנהל משאבי טיונר (TRM): מתאם משאבי טיונר HW

עבור אנדרואיד 11, הרכיבים הבאים שופרו.

  • CAS V2
  • TvInputService או שירות קלט טלוויזיה (TIS)
  • TvInputManagerService או TV Input Manager Service (TIMS)
  • MediaCodec או MediaCodec
  • AudioTrack או רצועת אודיו
  • MediaResourceManager או מנהל משאבי מדיה (MRM)

דיאגרמת זרימה של רכיבי מסגרת טיונר.

איור 1. אינטראקציות בין רכיבי Android TV

מאפיינים

Frontend תומך בתקני DTV להלן.

  • ATSC
  • ATSC3
  • DVB C/S/T
  • ISDB S/S3/T
  • אנלוגי

הקצה הקדמי באנדרואיד 12 עם Tuner HAL 1.1 ומעלה תומך בתקן DTV למטה.

  • DTMB

Demux תומך בפרוטוקולי הזרם שלהלן.

  • זרם תחבורה (TS)
  • פרוטוקול העברת מדיה MPEG (MMTP)
  • פרוטוקול אינטרנט (IP)
  • ערך אורך סוג (TLV)
  • פרוטוקול שכבת קישור ATSC (ALP)

Descrambler תומך בהגנות התוכן שלהלן.

  • נתיב מדיה מאובטח
  • נקה נתיב מדיה
  • תיעוד מקומי מאובטח
  • השמעה מקומית מאובטחת

ממשקי API של Tuner תומכים במקרי השימוש שלהלן.

  • לִסְרוֹק
  • לחיות
  • השמעה
  • תקליט

טיונר, MediaCodec ו- AudioTrack תומכים במצבי זרימת הנתונים שלהלן.

  • מטען ES עם מאגר זיכרון נקי
  • מטען ES עם ידית זיכרון מאובטחת
  • עובר דרך

עיצוב כולל

ה-Tuner HAL מוגדר בין מסגרת האנדרואיד לבין החומרה של הספק.

  • מתאר מה המסגרת מצפה מהספק וכיצד הספק עשוי לעשות זאת.
  • מייצא את הפונקציונליות של Frontend, Demux ו-Descrambler למסגרת באמצעות ממשקי IFrontend , IDemux , IDescrambler , IFilter , IDvr ו- ILnb .
  • כולל את הפונקציות לשילוב ה-Tuner HAL עם רכיבי מסגרת אחרים, כגון MediaCodec ו- AudioTrack .

נוצרות מחלקה של Tuner Java ומחלקה מקורית.

  • ה-API של Tuner Java מאפשר לאפליקציות לגשת ל-Tuner HAL דרך ממשקי API ציבוריים.
  • מחלקה מקורית מאפשרת בקרת הרשאות וטיפול בכמויות גדולות של נתוני הקלטה או השמעה באמצעות Tuner HAL.
  • מודול טיונר מקורי הוא גשר בין מחלקת הטיונר Java לבין הטיונר HAL.

נוצר כיתת TRM.

  • מנהל משאבי טיונר מוגבלים, כגון הפעלות Frontend, LNB, CAS והתקן קלט טלוויזיה מכניסת הטלוויזיה HAL.
  • מחיל כללים כדי להחזיר משאבים לא מספיקים מאפליקציות. כלל ברירת המחדל הוא הניצחון בחזית.

Media CAS ו-CAS HAL משופרים עם התכונות שלהלן.

  • פותח הפעלות CAS עבור שימושים ואלגוריתמים שונים.
  • תומך במערכות CAS דינמיות, כגון הסרה והכנסת CICAM.
  • משתלב עם Tuner HAL על ידי מתן אסימוני מפתח.

MediaCodec ו- AudioTrack משופרים עם התכונות שלהלן.

  • לוקח זיכרון A/V מאובטח כקלט תוכן.
  • מוגדר לבצע סינכרון A/V של החומרה בהשמעה במנהור.
  • תמיכה מוגדרת עבור ES_payload ומצב מעבר.

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

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

זרימת עבודה כוללת

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

להכין

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

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

טיפול ב-A/V

טיפול ב-A/V עבור דיאגרמת השמעת שידור חי.

איור 4. טיפול ב-A/V עבור השמעת שידור חי

טיפול בתוכן מקושקש

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

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

עיבוד נתוני A/V

עיבוד נתוני A/V עבור דיאגרמת השמעת שידור חי.

איור 6. עיבוד A/V עבור השמעת שידור חי

טיונר SDK API

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

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

איור 7. אינטראקציות עם ה-API של Tuner SDK

גרסאות

מאנדרואיד 12, ה-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

חבילת הטיונר היא נקודת כניסה לשימוש במסגרת הטיונר. אפליקציית TIS משתמשת בחבילה כדי לאתחל ולרכוש מופעי משאבים על ידי ציון ההגדרה הראשונית והתקשרות חוזרת.

  • tuner() : מאתחל מופע של Tuner על ידי ציון הפרמטרים useCase ו- sessionId .
  • tune() : רוכש משאב קצה ומכוון על ידי ציון הפרמטר FrontendSetting .
  • openFilter() : רוכש מופע מסנן על ידי ציון סוג המסנן.
  • openDvrRecorder() : רוכש מופע הקלטה על ידי ציון גודל המאגר.
  • openDvrPlayback() : רוכש מופע השמעה על ידי ציון גודל המאגר.
  • openDescrambler() : רוכש מופע Descrambler.
  • openLnb() : רוכש מופע LNB פנימי.
  • openLnbByName() : רוכש מופע LNB חיצוני.
  • openTimeFilter() : רוכש מופע מסנן זמן.

חבילת הטיונר מספקת פונקציות שאינן מכוסות תחת חבילות המסנן, ה-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

מאנדרואיד 12 עם Tuner HAL 1.1 ומעלה, תקן ה-DTV הבא נתמך.

  • DtmbFrontendSettings

FrontendCapabilities נגזרת עבור תקני DTV שונים לפי המעמדות שלהלן.

  • AnalogFrontendCapabilities
  • Atsc3FrontendCapabilities
  • AtscFrontendCapabilities
  • DvbcFrontendCapabilities
  • DvbsFrontendCapabilities
  • DvbtFrontendCapabilities
  • Isdbs3FrontendCapabilities
  • IsdbsFrontendCapabilities
  • IsdbtFrontendCapabilities

מאנדרואיד 12 עם Tuner HAL 1.1 ומעלה, תקן ה-DTV הבא נתמך.

  • DtmbFrontendCapabilities

FrontendInfo מאחזר את המידע של ה-frontend. FrontendStatus מאחזר את המצב הנוכחי של ה-frontend. 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 כדי לציין שפעולת הסריקה הסתיימה.

  • TIS חוזר על הפעולות לעיל עד למיצוי כל ההגדרות בתדר.

  • ה-HAL שולח END כדי לציין שפעולת הסריקה הסתיימה.

  • TIS עובר לתדר הזמין הבא ברשימת התדרים שלו.

TIS מתקשר שוב Tuner.scan(AUTO_SCAN) עד למיצוי כל התדרים.

במהלך הסריקה, אתה יכול לקרוא stopScan() או close() כדי להשהות או לסיים את הסריקה.

Tuner.scan(BLIND_SCAN)

אם ל-TIS אין רשימת תדרים וה-HAL של הספק יכול לחפש את התדירות של ה-frontend שצוין על-ידי המשתמש כדי לקבל את המשאב ה-frontend, אז 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

אנדרואיד.media.tv.tuner.filter

חבילת הסינון היא אוסף של פעולות סינון יחד עם תצורה, הגדרות, התקשרויות חוזרות ואירועים. החבילה כוללת את הפעולות שלהלן. עיין בקוד המקור של אנדרואיד לקבלת רשימה מלאה של פעולות.

  • configure()
  • start()
  • stop()
  • flush()
  • read()

עיין בקוד המקור של אנדרואיד לרשימה המלאה.

FilterConfiguration נגזר מהשיעורים שלהלן. התצורות מיועדות לסוג המסנן הראשי והן מציינות באיזה פרוטוקול המסנן משתמש כדי לחלץ נתונים.

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

ההגדרות נגזרות מהשיעורים שלהלן. ההגדרות מיועדות לתת-סוג המסנן והן מציינות אילו סוגי נתונים המסנן יכול לא לכלול.

  • SectionSettings
  • AvSettings
  • PesSettings
  • RecordSettings
  • DownloadSettings

FilterEvent נגזר מהשיעורים למטה כדי לדווח על אירועים עבור סוגים שונים של נתונים.

  • SectionEvent
  • MediaEvent
  • PesEvent
  • TsRecordEvent
  • MmtpRecordEvent
  • TemiEvent
  • DownloadEvent
  • IpPayloadEvent

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

לתוכן מוקלט: זרם TS Muxed מלא ב-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. Process 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. שחרר את ידית ה-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);
          }
        }
      };
    

טיונר HAL

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

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

קישור סינון

ה-Tuner HAL תומך בקישור מסננים כך שניתן לקשר מסננים למסננים אחרים עבור מספר שכבות. המסננים פועלים לפי הכללים הבאים.

  • מסננים מקושרים כעץ, נתיב סגור אסור.
  • צומת השורש הוא דמוקס.
  • מסננים פועלים באופן עצמאי.
  • כל המסננים מתחילים לקבל נתונים.
  • הצמדת המסנן שוטפת את המסנן האחרון.

בלוק הקוד למטה ואיור 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 Input Framework (TIF) השתמשה במנגנון "ראשון לרכישה", כלומר כל אפליקציה שמקבלת את המשאב תחילה שומרת על המשאב. עם זאת, מנגנון זה עשוי שלא להיות אידיאלי עבור מקרי שימוש מסובכים.

TRM פועל כשירות מערכת לניהול משאבי החומרה של Tuner, TVInput ו-CAS עבור אפליקציות. TRM משתמש במנגנון "ניצחון בחזית", אשר מחשב את עדיפות האפליקציה על סמך מצב החזית או הרקע של האפליקציה וסוג מקרה השימוש. TRM מעניק או מבטל את המשאב על סמך העדיפות. TRM מרכזת את ניהול משאבי הטרקטורונים עבור שידור, OTT ו-DVR.

ממשק TRM

TRM חושף ממשקי AIDL ב- ITunerResourceManager.aidl עבור מסגרת Tuner, 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. תרשים של מנגנון החזרה להתנגשות בין משאבי הטיונר