Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る
このページは Cloud Translation API によって翻訳されました。
Switch to English

チューナーフレームワーク

Android 11以降の場合、Androidチューナーフレームワークを使用してA / Vコンテンツを配信できます。このフレームワークはベンダーのハードウェアパイプラインを使用しているため、ローエンドとハイエンドの両方のSoCに適しています。このフレームワークは、信頼できる実行環境(TEE)と安全なメディアパス(SMP)によって保護されたA / Vコンテンツを配信する安全な方法を提供し、高度に制限されたコンテンツ保護環境で使用できるようにします。

チューナーとAndroidCAS間の標準化されたインターフェースにより、チューナーベンダーとCASベンダー間の統合が高速化されます。チューナーインターフェイスはMediaCodecおよびAudioTrackAudioTrackして、 AudioTrack向けのワンワールドソリューションを構築します。チューナーインターフェイスは、主要な放送規格に基づいて、デジタルTVとアナログTVの両方をサポートします。

コンポーネント

Android 11の場合、3つのコンポーネントがTVプラットフォーム用に特別に設計されています。

  • チューナーHAL:フレームワークとベンダー間のインターフェース
  • チューナーSDKAPI:フレームワークとアプリ間のインターフェース
  • チューナーリソースマネージャー(TRM):チューナーHWリソースを調整します

Android 11では、次のコンポーネントが拡張されています。

  • CAS V2
  • TvInputServiceまたはTV入力サービス(TIS)
  • TvInputManagerServiceまたはTvInputManagerService Manager Service(TIMS)
  • MediaCodecまたはメディアコーデック
  • AudioTrackまたはオーディオトラック
  • MediaResourceManagerまたはメディアリソースマネージャー(MRM)

チューナーフレームワークコンポーネントのフロー図。

図1.AndroidTVコンポーネント間の相互作用

特徴

フロントエンドは、以下のDTV規格をサポートしています。

  • ATSC
  • ATSC3
  • DVB C / S / T
  • ISDB S / S3 / T
  • アナログ

Demuxは、以下のストリームプロトコルをサポートしています。

  • トランスポートストリーム(TS)
  • MPEGメディアトランスポートプロトコル(MMTP)
  • インターネットプロトコル(IP)
  • タイプレングス値(TLV)
  • ATSCリンク層プロトコル(ALP)

Descramblerは、以下のコンテンツ保護をサポートしています。

  • 安全なメディアパス
  • メディアパスをクリアする
  • ローカルレコードを保護する
  • 安全なローカル再生

チューナーAPIは、以下のユースケースをサポートします。

  • スキャン
  • 住む
  • 再生
  • 記録

Tuner、 MediaCodec 、およびAudioTrackは、以下のデータフローモードをサポートしています。

  • クリアメモリバッファを備えたESペイロード
  • 安全なメモリハンドルを備えたESペイロード
  • パススルー

全体的なデザイン

チューナーHALは、Androidフレームワークとベンダーのハードウェアの間で定義されます。

  • フレームワークがベンダーに期待することと、ベンダーがそれを行う方法について説明します。
  • フロントエンド、デマルチプレクサ、およびデスクランブラーの機能を、 IFrontendIDemuxIDescramblerIFilterIDvr 、およびILnbインターフェイスを介してフレームワークにILnbます。
  • チューナーHALをMediaCodecAudioTrackなどの他のフレームワークコンポーネントと統合するための関数が含まれています。

チューナーJavaクラスとネイティブクラスが作成されます。

  • Tuner Java APIを使用すると、アプリはパブリックAPIを介してTunerHALにアクセスできます。
  • ネイティブクラスを使用すると、TunerHALを使用して大量の記録または再生データのアクセス許可を制御および処理できます。
  • ネイティブチューナーモジュールは、チューナーJavaクラスとチューナーHALの間のブリッジです。

TRMクラスが作成されます。

  • フロントエンド、LNB、CASセッション、TV入力HALからのTV入力デバイスなどの限られたチューナーリソースを管理します。
  • ルールを適用して、アプリから不十分なリソースを再利用します。デフォルトのルールはフォアグラウンドウィンです。

MediaCASとCASHALは、以下の機能で強化されています。

  • さまざまな使用法とアルゴリズムのCASセッションを開きます。
  • CICAMの取り外しや挿入などの動的CASシステムをサポートします。
  • キートークンを提供することにより、チューナーHALと統合します。

MediaCodecAudioTrackは、以下の機能で拡張されています。

  • コンテンツ入力としてセキュア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の処理

チューナーSDKAPI

Tuner SDK APIは、Tuner JNI、Tuner HAL、およびTunerResourceManagerとの相互作用を処理します。 TISアプリは、Tuner SDK APIを使用して、Tunerリソースおよびフィルターやデスクランブラーなどのサブコンポーネントにアクセスします。フロントエンドとデマルチプレクサは内部コンポーネントです。

チューナーSDKAPIのフロー図。

図7.Tuner SDKAPIとの相互作用

パッケージ

Tuner SDK APIは、以下の4つのパッケージを提供します。

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

Tuner SDKAPIパッケージのフロー図。

図8.チューナーSDKAPIパッケージ

Android.media.tv.tuner

Tunerパッケージは、Tunerフレームワークを使用するためのエントリポイントです。 TISアプリは、パッケージを使用して、初期設定とコールバックを指定することにより、リソースインスタンスを初期化および取得します。

  • tuner()指定して初期化チューナーインスタンスuseCasesessionIdパラメータを。
  • tune() :フロントエンドリソースを取得し、 FrontendSettingパラメーターを指定して調整します。
  • openFilter() :フィルタータイプを指定してフィルターインスタンスを取得します。
  • openDvrRecorder() :バッファサイズを指定して記録インスタンスを取得します。
  • openDvrPlayback() :バッファサイズを指定して再生インスタンスを取得します。
  • openDescrambler() :デスクランブラーインスタンスを取得します。
  • openLnb() :内部LNBインスタンスを取得します。
  • openLnbByName() :外部LNBインスタンスを取得します。
  • openTimeFilter() :時間フィルターインスタンスを取得します。

チューナーパッケージは、フィルター、DVR、およびフロントエンドパッケージでカバーされていない機能を提供します。機能は以下のとおりです。

  • cancelTuning
  • scan / cancelScanning scan
  • getAvSyncHwId
  • getAvSyncTime
  • connectCiCam1 / disconnectCiCam
  • shareFrontendFromTuner
  • updateResourcePriority
  • setOnTuneEventListener
  • setResourceLostListener

Android.media.tv.tuner.frontend

フロントエンドパッケージには、フロントエンド関連の設定、情報、ステータス、イベント、および機能のコレクションが含まれています。

クラス

FrontendSettingsは、以下のクラスによってさまざまなDTV標準用に派生しています。

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

FrontendCapabilitiesは、以下のクラスによってさまざまなDTV標準用に派生しています。

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

FrontendInfoは、フロントエンドの情報を取得します。 FrontendStatusは、 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に必要な情報をTuner.tuneます。
  • 信号がロックされている場合、HALはLOCKEDメッセージを報告します。
  • TISは、 Frontend.getStatusを使用して必要な情報を収集します。
  • TISは、周波数リストで次に使用可能な周波数に移動します。

TISは、すべての周波数が使い果たされるまで、 Tuner.tune再度呼び出します。

チューニング中に、 stopTune()またはclose()を呼び出して、 Tuner.tune呼び出しを一時停止または終了Tuner.tuneます。

Tuner.scan(AUTO_SCAN)

TISにTuner.tuneを使用するのに十分な情報がないが、周波数リストと標準タイプ(DVB T / C / Sなど)がある場合は、 Tuner.scan(AUTO_SCAN)をお勧めします。

ユーザーがTuner.scan(AUTO_SCAN)呼び出すと、次のアクションが発生します。

  • TISは、 FrontendSettingsが頻度で満たされたTuner.scan(AUTO_SCAN)を使用します。

  • HALレポートは、スキャンLOCKED信号がロックされている場合は、メッセージを。 HALは、信号に関する追加情報を提供するために、他のスキャンメッセージを報告する場合もあります。

  • TISは、 Frontend.getStatusを使用して必要な情報を収集します。

  • TISはTuner.scanを呼び出してHALをTuner.scan 、同じ周波数で次の設定に進みます。 FrontendSettings構造が空の場合、HALは次に使用可能な設定を使用します。それ以外の場合、HALはFrontendSettingsを1回のスキャンに使用し、スキャン操作が終了したことを示すために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
フィルタからのイベントとデータ形式
フィルタタイプフラグイベントデータ操作データ形式
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) 1回以上。

データはHALのMQからクライアントバッファにコピーされます。
アセンブルされた1つのセッションパッケージは、別のセッションパッケージによって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) 1回以上。

データはHALのMQからクライアントバッファにコピーされます。
組み立てられた1つのPESパッケージは、別のPESパッケージによってFMQに入力されます。
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) 1回以上。

データはHALのMQからクライアントバッファにコピーされます。
組み立てられた1つのMFUパッケージは、別のMFUパッケージによってFMQに入力されます。
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) 1回以上。

データは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を開始できます。
クライアントが呼び出すことができる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))
IONメモリ内のESまたは部分的なESデータ。
TS.PCR
IP.NTP
ALP.PTP
該当なし必須: N / A
オプション: N / A
該当なし該当なし
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)をストレージに対して1回以上実行します。
    データはHALのMQからストレージに転送されます。
  • DvrRecord.write(buffer, adustedSize) 1回以上実行して、バッファリングします。
    データはHALのMQからクライアントバッファにコピーされます。
インデックスデータの場合:イベントペイロードで運ばれます。

記録されたコンテンツの場合: FMQで入力されたMuxedTSストリーム。
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) 1回以上。

データはHALのMQからクライアントバッファにコピーされます。
mmtpヘッダーでmmtpmmtpmmtp
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)をストレージに対して1回以上実行します。
    データはHALのMQからストレージに転送されます。
  • DvrRecord.write(buffer, adjustedSize) 1回以上実行して、バッファリングします。
    データはHALのMQからクライアントバッファにコピーされます。
インデックスデータの場合:イベントペイロードで運ばれます。

記録されたコンテンツの場合: FMQに入力されたMuxed記録されたストリーム。

記録用のフィルターソースがパススルー付きの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) 1回以上。

データは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処理し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処理しMediaEvent
  3. MediaEventを受信しMediaEvent
  4. 線形ブロックをcodecキュー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を構成するために使用されます。 OnPlaybackStatusChangedListenerおよびOnRecordStatusChangedListenerは、DVRインスタンスのステータスを報告するために使用されます。

レコードを開始するフローの例

レコードを開始するためのフローの例。

図12.レコードを開始するフロー

  1. DvrRecorder開き、構成して、起動し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に従い、フレームワークとベンダーハードウェア間のインターフェイスを定義します。ベンダーはインターフェースを使用してTunerHALを実装し、フレームワークはそれを使用してTunerHAL実装と通信します。

モジュール

モジュール基本的なコントロールモジュール固有のコントロールHALファイル
ITuner該当なしfrontend(open, getIds, getInfo)openDemuxopenDescrambleropenLnbgetDemuxCaps ITuner.hal
IFrontend setCallbackgetStatusclose tunestopTunescanstopScansetLnb 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 setDemuxSourcesetKeyTokenaddPidremovePid IDescrambler.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)以前は、2つのアプリを切り替えるには同じTunerハードウェアが必要でした。 TV Input Framework(TIF)は、「最初に獲得する勝利」メカニズムを使用しました。これは、リソースを最初に取得するアプリがリソースを保持することを意味します。ただし、このメカニズムは、一部の複雑なユースケースには理想的ではない場合があります。

TRMは、アプリのチューナー、 TVInput 、およびCASハードウェアリソースを管理するためのシステムサービスとして実行されます。 TRMは、アプリのフォアグラウンドまたはバックグラウンドステータスとユースケースタイプに基づいてアプリの優先度を計算する「フォアグラウンドウィン」メカニズムを使用します。 TRMは、優先度に基づいてリソースを付与または取り消します。 TRMは、放送、OTT、およびDVRのATVリソース管理を一元化します。

TRMインターフェース

TRMが露出AIDLインターフェイスでITunerResourceManager.aidlチューナーフレームワークのための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からプロセスIDを取得して、アプリがフォアグラウンドアプリかバックグラウンドアプリかを判断します。 mTvInputSessionIdTvInputService.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な値を更新するためのupdateClientPriorityを提供します。任意の優先度値は、ユースケースタイプとセッションIDから計算された優先度値を上書きします。

nice値は、別のクライアントと競合しているときのクライアントの動作がどれだけ寛大であるかを示します。 nice値は、クライアントの優先度値を、チャレンジングクライアントと比較する前に減少させます。

再利用メカニズム

次の図は、リソースの競合が発生したときにリソースがどのように再利用および割り当てられるかを示しています。

再利用メカニズムプロセスの図。

図15.チューナーリソース間の競合に対する再利用メカニズムの図