調諧器架構

如果是 Android 11 以上版本,您可以使用 Android 裝置 用於提供 A/V 內容的調諧器架構。架構會使用 管道,因此適用於低階和高階 SoC。 這個架構能讓使用者以安全的方式,提供受試者保護的 A/V 內容 信任的執行環境 (TEE) 和安全媒體路徑 (SMP),以允許 用於嚴格限制的內容保護環境

Tuner 與 Android CAS 之間的標準化介面可加快 協調工具供應商與 CAS 供應商之間的整合調諧器介面可正常運作 與 MediaCodecAudioTrack 攜手打造全方位的 Android TV 解決方案。 The Tuner 介面可同時支援數位電視和類比電視, 廣播標準

元件

針對 Android 11,三個元件會特別 專為電視平台設計的應用程式

  • Tuner HAL:架構和廠商之間的介面
  • Tuner SDK API:架構與應用程式之間的介面
  • Tuner Resource Manager (TRM):協調 Tuner HW 資源

對於 Android 11,下列元件 強化。

  • CAS V2
  • TvInputService 或電視輸入服務 (TIS)
  • TvInputManagerService」或電視輸入管理員服務 (TIMS)
  • MediaCodec 或媒體轉碼器
  • AudioTrack 或音軌
  • MediaResourceManager 或媒體資源管理工具 (MRM)

調諧器架構元件的流程圖。

圖 1. Android TV 元件之間的互動

功能

前端支援下列 DTV 標準。

  • ATSC 架構
  • ATSC3
  • DVB C/S/T
  • ISDB S/S3/T
  • 類比

在搭載 Tuner HAL 1.1 以上版本的 Android 12 前端,即可支援下方的 DTV 標準。

  • 資料移轉

Demux 支援下列串流通訊協定。

  • 傳輸串流 (TS)
  • MPEG 媒體傳輸通訊協定 (MMTP)
  • 網際網路通訊協定 (IP)
  • 類型長度值 (TLV)
  • ATSC 連結層通訊協定 (ALP)

Descrambler 支援下列內容保護功能。

  • 安全的媒體路徑
  • 清除媒體路徑
  • 保護本機記錄
  • 安全本機播放

Tuner API 支援下列用途。

  • 掃描
  • 直播
  • 播放
  • 錄製

協調器、MediaCodecAudioTrack 支援下列的資料流程模式。

  • 具有清除記憶體緩衝區的 ES 酬載
  • 具有安全記憶體控點的 ES 酬載
  • 透視

整體設計

調諧器 HAL 的定義應介於 Android 架構與供應商的 硬體

  • 說明供應商對架構的預期,以及供應商可能的接受方式 親自體驗
  • 將前端、demux 和 descrambler 的功能匯出到 整合了 IFrontendIDemuxIDescramblerIFilterIDvr 和 和 ILnb 介面。
  • 包含將 Tuner HAL 與其他架構整合的功能 例如 MediaCodecAudioTrack

系統會建立 Tuner Java 類別和原生類別。

  • Tuner Java API 可讓應用程式透過公用 API 存取 Tuner HAL。
  • 原生類別允許權限控制及處理大量 透過調諧器 HAL 建立記錄或播放資料
  • Native Tuner 模組是 Tuner Java 類別與 Tuner 之間的橋樑 HAL。

系統隨即建立 TRM 類別。

  • 可管理有限的 Tuner 資源,例如 Frontend、LNB 以及來自電視輸入 HAL 的電視輸入裝置。
  • 套用規則來收回不足的資源 應用程式。預設規則為前景勝出。

媒體 CAS 和 CAS HAL 使用以下功能來增強效果。

  • 開啟不同用法和演算法的 CAS 工作階段。
  • 支援動態 CAS 系統,例如 CICAM 移除和插入。
  • 提供金鑰權杖,與調諧器 HAL 整合。

使用下列功能強化 MediaCodecAudioTrack

  • 使用安全的 A/V 記憶體做為內容輸入來源。
  • 已設為在通道播放時進行硬體 A/V 同步處理。
  • 設定對 ES_payload 和直通模式的支援。

調諧器 HAL 的整體設計。

圖 2. 調諧器 HAL 內的元件圖表

整體工作流程

下圖是即時播送播放的呼叫序列。

設定

設定現場直播播放圖表的順序。

圖 3. 現場直播播放的設定順序

處理 A/V

處理現場直播播放的 A/V 流程圖。

圖 4. 處理現場直播播放的 A/V

處理打散的內容

處理直播播放圖表的打散內容。

圖 5. 處理打散播放的直播影片

正在處理影音設備資料

處理現場直播播放的 A/V 資料。

圖 6. 處理 A/V 進行即時播送

調諧器 SDK API

Tuner SDK API 會處理與 Tuner JNI、 Tuner HAL 的互動 和TunerResourceManager。TIS 應用程式使用 Tuner SDK API 存取 Tuner 和子元件,例如篩選器和解碼器元件前端和 demux 是內部元件。

Tuner SDK API 的流程圖。

圖 7. 與 Tuner SDK API 的互動

版本

自 Android 12 起, Tuner SDK API 支援 Tuner HAL 1.1 的新功能 是 Tuner 1.0 的回溯相容版本升級版本。

使用以下 API 檢查執行中的 HAL 版本。

  • android.media.tv.tuner.TunerVersionChecker.getTunerVersion()

您可以參閱新版 Android 12 API 的說明文件,瞭解需要的最低 HAL 版本。

套件

Tuner SDK API 提供以下四個套件。

  • android.media.tv.tuner
  • android.media.tv.tuner.frontend
  • android.media.tv.tuner.filter
  • android.media.tv.tuner.dvr

Tuner SDK API 套件的流程圖。

圖 8. Tuner SDK API 套件

Android.media.tv.tuner

Tuner 套件是使用 Tuner 架構的進入點。TIS 應用程式 使用此套件初始化及取得資源執行個體,方法是指定 初始設定和回呼

  • tuner():透過指定 useCasesessionId 參數。
  • 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

前端套件包含一組前端相關設定, 資訊、狀態、事件和功能

類別

下列類別依不同的 DTV 標準衍生 FrontendSettings

  • AnalogFrontendSettings
  • Atsc3FrontendSettings
  • AtscFrontendSettings
  • DvbcFrontendSettings
  • DvbsFrontendSettings
  • DvbtFrontendSettings
  • Isdbs3FrontendSettings
  • IsdbsFrontendSettings
  • IsdbtFrontendSettings

從搭載 Tuner HAL 1.1 以上版本的 Android 12 起,支援下列 DTV 標準。

  • DtmbFrontendSettings

系統會依類別針對不同的 DTV 標準衍生 FrontendCapabilities

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

從搭載 Tuner HAL 1.1 以上版本的 Android 12 起,支援下列 DTV 標準。

  • DtmbFrontendCapabilities

FrontendInfo 會擷取前端資訊。 FrontendStatus 會擷取前端的目前狀態。 OnTuneEventListener 會監聽前端的事件。 TIS 應用程式會使用 ScanCallback 掃描前端的訊息。

頻道掃描

設定電視時,應用程式會掃描可能的頻率,並建立頻道 供使用者存取TIS 可能會使用 Tuner.tuneTuner.scan(BLIND_SCAN),或 Tuner.scan(AUTO_SCAN)以完成頻道 或是掃描內容

如果目標曝光比重 (TIS) 提供的信號放送資訊 (例如頻率) 標準 (例如 T/T2、S/S2) 和其他必要資訊 (例如 PLD ID) 建議設為 Tuner.tune,這是更快速的選項。

使用者呼叫 Tuner.tune 時,會發生以下動作:

  • TIS 會使用 Tuner.tune 將必要資訊填入 FrontendSettings
  • 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 對 HAL 呼叫 Tuner.scan,以便繼續在同一環境下進行下一個設定 頻率。 如果 FrontendSettings 結構空白,HAL 會使用下一個 可用的設定。否則,HAL 會使用 FrontendSettings 一次使用一次 掃描並傳送 END,表示掃描作業已完成。

  • TIS 會重複上述動作,直到頻率的所有設定都達到 。

  • 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 是 略過)。
  • TIS 會重複上述動作,直到頻率的所有設定都達到 。HAL 會遞增頻率,TIS 不需要採取任何動作。 HAL 報告 PROGRESS

TIS 會再次呼叫 Tuner.scan(AUTO_SCAN),直到所有頻率都用盡為止。 HAL 會回報 END,指出掃描作業已完成。

在掃描期間,您可以呼叫 stopScan()close() 來暫停或結束掃描作業。

TIS 掃描程序的流程圖。

圖 9.TIS 掃描的流程圖

Android.media.tv.tuner.filter

篩選器套件是一組篩選作業和設定 設定、回呼及事件等。套件包含以下作業。 如需完整的作業清單,請參閱 Android 原始碼。

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

如需完整清單,請參閱 Android 原始碼。

FilterConfiguration 衍生自以下類別。設定分別為 並指定篩選器要使用哪個通訊協定 擷取資料。

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

設定衍生自下列類別。這是篩選器的設定 子類型,用來指定篩選器可以排除的資料類型。

  • SectionSettings
  • AvSettings
  • PesSettings
  • RecordSettings
  • DownloadSettings

FilterEvent 衍生自以下類別,可回報不同類別的事件 不同種類的資料

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

從搭載 Tuner HAL 1.1 以上版本的 Android 12 版本開始,系統會支援下列事件。

  • 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) 一或多個 次。

資料會從 HAL 的 MQ 複製到用戶端緩衝區。
一個組裝的工作階段套件由另一個 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)


資料會從 HAL 的 MQ 複製到用戶端緩衝區。
TS.PES isRaw:
true
必要程序:

DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
建議:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
根據活動和內部排程,執行
Filter.read(buffer, offset, adjustedSize) 一或多個 次。

資料會從 HAL 的 MQ 複製到用戶端緩衝區。
一個 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)


資料會從 HAL 的 MQ 複製到用戶端緩衝區。
MMTP.PES isRaw:
true
必要程序:

DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
建議:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
根據活動和內部排程,執行
Filter.read(buffer, offset, adjustedSize) 一或多個 次。

資料會從 HAL 的 MQ 複製到用戶端緩衝區。
一個組裝的 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)


資料會從 HAL 的 MQ 複製到用戶端緩衝區。
TS.TS
必要程序:

DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
建議:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
根據活動和內部排程,執行
Filter.read(buffer, offset, adjustedSize) 一或多個 次。

資料會從 HAL 的 MQ 複製到用戶端緩衝區。
已篩除含有ts標題
的「ts」 就需要填寫 FMQ 編號
TS.Audio
TS.Video
MMTP.Audio
MMTP.Video
isPassthrough:
true
選用:

DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
用戶端可在收到 DemuxFilterStatus::DATA_READY 後啟動 MediaCodec
用戶端可在收到 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()


如何使用 AudioTrack 的直接音訊功能:
for i=0; i<n; i++
audioHandle = MediaEvent[i].getAudioHandle();
audiotrack.write(encapsulated(audiohandle))
ION 記憶體中的 ES 或部分 ES 資料。
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) 可能會佔用儲存空間
    資料會從 HAL 的 MQ 移轉至儲存空間。
  • 執行 DvrRecord.write(buffer, adustedSize) 緩衝處理至少一次
    資料會從 HAL 的 MQ 複製到用戶端緩衝區。
索引資料:包含在事件酬載中。

錄製的內容:混合型 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) 一或多個 次。

資料會從 HAL 的 MQ 複製到用戶端緩衝區。
已篩除含有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) 次以上 。
    資料會從 HAL 的 MQ 移轉至儲存空間。
  • 執行 DvrRecord.write(buffer, adjustedSize)1 或 額外緩衝。
    資料會從 HAL 的 MQ 複製到用戶端緩衝區。
索引資料:包含在事件酬載中。

錄製內容:混合的錄製內容串流,並填入資料 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)

資料會從 HAL 的 MQ 複製到用戶端緩衝區。
下載套件已由其他 IP 下載套件填入 FMQ。
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)

資料會從 HAL 的 MQ 複製到用戶端緩衝區。
IP 酬載套件會由另一個 IP 酬載套件填入 FMQ。
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) 一或多個 次。

資料會從 HAL 的 MQ 複製到用戶端緩衝區。
已篩除含有通訊協定標頭的通訊協定子串流 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. 在已經使用資料後,釋放 A/V 控制代碼。

Android.media.tv.tuner.dvr

DvrRecorder 提供了這些錄製方法。

  • configure
  • attachFilter
  • detachFilter
  • start
  • flush
  • stop
  • setFileDescriptor
  • write

DvrPlayback 提供這些播放方法。

  • configure
  • start
  • flush
  • stop
  • setFileDescriptor
  • read

DvrSettings 可用來設定 DvrRecorderDvrPlayback。 使用 OnPlaybackStatusChangedListenerOnRecordStatusChangedListener 回報 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 並定義了架構與 供應商硬體。供應商可使用介面實作 Tuner HAL,以及 架構會使用此架構與 Tuner HAL 實作通訊

模組

調諧器 HAL 1.0

模組 基本控制選項 模組專屬控制項 HAL 檔案
ITuner frontend(open, getIds, getInfo)openDemuxopenDescrambleropenLnbgetDemuxCaps ITuner.hal
IFrontend setCallbackgetStatusclose tunestopTunescansetLnbstopScan IFrontend.hal
IFrontendCallback.hal
IDemux close setFrontendDataSourceopenFilteropenDvrgetAvSyncHwIdgetAvSyncTimeconnect / disconnectCiCam IDemux.hal
IDvr closestartstopconfigure attach/detachFiltersflushgetQueueDesc IDvr.hal
IDvrCallback.hal
IFilter closestartstopconfiguregetId flushgetQueueDescreleaseAvHandlesetDataSource IFilter.hal
IFilterCallback.hal
ILnb closesetCallback setVoltagesetTonesetSatellitePositionsendDiseqcMessage ILnb.hal
ILnbCallback.hal
IDescrambler close setDemuxSourcesetKeyTokenaddPid removePid IDescrambler.hal

調諧器 HAL 1.1 (衍生自調諧器 HAL 1.0)

模組 基本控制選項 模組專屬控制項 HAL 檔案
ITuner getFrontendDtmbCapabilities @1.1::ITuner.hal
IFrontend tune_1_1scan_1_1getStatusExt1_1 link/unlinkCiCam @1.1::IFrontend.hal
@1.1::IFrontendCallback.hal
IFilter getStatusExt1_1 configureIpCidconfigureAvStreamTypegetAvSharedHandleconfigureMonitorEvent @1.1::IFilter.hal
@1.1::IFilterCallback.hal

調諧器 HAL 模組之間的互動流程圖。

圖 13. 調諧器 HAL 模組之間的互動圖表

篩選器連結

調諧器 HAL 支援篩選器連結,讓篩選器可與其他 多個圖層的篩選器篩選器會採用下列規則。

  • 篩選器以樹狀結構連結,無法使用關閉路徑。
  • 根節點為 demux。
  • 篩選器會獨立運作,
  • 所有篩選器都會開始取得資料。
  • 最後一個篩選器的連結內容會清除。

下方程式碼區塊和圖 14 顯示篩選多重值的範例 包含四個不同的層

demuxCaps = ITuner.getDemuxCap;
If (demuxCaps[IP][MMTP] == true) {
        ipFilter = ITuner.openFilter(<IP, ..>)
        mmtpFilter1 = ITuner.openFilter(<MMTP ..>)
        mmtpFilter2 = ITuner.openFilter(<MMTP ..>)
        mmtpFilter1.setDataSource(<ipFilter>)
        mmtpFilter2.setDataSource(<ipFilter>)
}

篩選器連結範例圖表。

圖 14. 多個圖層的篩選器連結流程圖

調整器資源管理工具

在使用 Tuner Resource Manager (TRM) 之前,您必須在兩個應用程式之間切換: 相同的調諧器硬體電視輸入架構 (TIF) 使用「第一至獲勝」 機制,也就是任何先取得資源的應用程式都能保留資源。 不過,這個機制對於一些複雜的用途而言可能不是理想的選擇。

TRM 會以系統服務的形式運作,以管理 Tuner、TVInput 和 CAS 硬體 管理應用程式的所有資源TRM 使用「前景勝出」是針對 根據應用程式的前景或背景計算應用程式的優先順序 狀態和用途類型TRM 會根據以下項目授予或撤銷資源: TRM 為廣播、OTT、 以及 DVR 功能

TRM 介面

TRM 會在 ITunerResourceManager.aidl 中為調諧器公開 AIDL 介面 架構、MediaCasTvInputHardwareManager 來註冊、要求或 釋出資源

下方列出客戶管理的介面。

  • 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 擷取程序 ID,判斷應用程式是否 則是前景或背景應用程式如要建立「mTvInputSessionId」, TvInputService.onCreateSessionTvInputService.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,讓用戶端更新任意 預測的價值 任意優先順序值會覆寫先前計算的優先值 從用途類型和工作階段 ID 擷取

理想的值代表用戶端行為的寬鬆程度 與其他用戶端相衝突良好的值會降低客戶優先順序 比較困難的客戶進行比較。

回收機制

下圖顯示系統如何在 會發生資源衝突的情況

回收機製程序的圖表。

圖 15.調諧器之間衝突的回收機制圖表 資源