Cadre de tuner

Pour Android 11 ou version ultérieure, vous pouvez utiliser le framework Android Tuner pour diffuser du contenu A/V. Le framework utilise le pipeline matériel des fournisseurs, ce qui le rend adapté aux SoC bas de gamme et haut de gamme. Le cadre fournit un moyen sécurisé de fournir du contenu audiovisuel protégé par un environnement d'exécution de confiance (TEE) et un chemin multimédia sécurisé (SMP), lui permettant d'être utilisé dans un environnement de protection de contenu hautement restreint.

L'interface standardisée entre Tuner et Android CAS permet une intégration plus rapide entre les fournisseurs Tuner et CAS. L'interface Tuner fonctionne avec MediaCodec et AudioTrack pour créer une solution mondiale pour Android TV. L'interface Tuner prend en charge à la fois la télévision numérique et la télévision analogique sur la base des principales normes de diffusion.

Composants

Pour Android 11, trois composants sont spécifiquement conçus pour la plateforme TV.

  • Tuner HAL : Une interface entre le framework et les fournisseurs
  • API Tuner SDK : une interface entre le framework et les applications
  • Tuner Resource Manager (TRM) : coordonne les ressources matérielles du Tuner

Pour Android 11, les composants suivants ont été améliorés.

  • CAS V2
  • TvInputService ou service d'entrée TV (TIS)
  • TvInputManagerService ou service de gestion des entrées TV (TIMS)
  • MediaCodec ou codec multimédia
  • AudioTrack ou piste audio
  • MediaResourceManager ou gestionnaire de ressources multimédias (MRM)

Organigramme des composants du framework Tuner.

Figure 1. Interactions entre les composants d'Android TV

Caractéristiques

Frontend prend en charge les normes DTV ci-dessous.

  • ATSC
  • ATSC3
  • DVB-C/S/T
  • ISDB S/S3/T
  • Analogique

L'interface sous Android 12 avec Tuner HAL 1.1 ou supérieur prend en charge la norme DTV ci-dessous.

  • DTMB

Demux prend en charge les protocoles de flux ci-dessous.

  • Flux de transport (TS)
  • Protocole de transport multimédia MPEG (MMTP)
  • Protocole Internet (IP)
  • Valeur de longueur de type (TLV)
  • Protocole de couche liaison ATSC (ALP)

Descrambler prend en charge les protections de contenu ci-dessous.

  • Chemin multimédia sécurisé
  • Chemin multimédia clair
  • Enregistrement local sécurisé
  • Lecture locale sécurisée

Les API Tuner prennent en charge les cas d'utilisation ci-dessous.

  • Analyse
  • En direct
  • Relecture
  • Enregistrer

Tuner, MediaCodec et AudioTrack prennent en charge les modes de flux de données ci-dessous.

  • Charge utile ES avec tampon mémoire vide
  • Charge utile ES avec poignée de mémoire sécurisée
  • Traverser

Conception générale

Le Tuner HAL est défini entre le framework Android et le matériel du fournisseur.

  • Décrit ce que le framework attend du fournisseur et comment le fournisseur peut le faire.
  • Exporte les fonctionnalités du frontend, du démultiplexage et du désembrouilleur vers le framework via les interfaces IFrontend , IDemux , IDescrambler , IFilter , IDvr et ILnb .
  • Inclut les fonctions permettant d'intégrer le Tuner HAL avec d'autres composants du framework, tels que MediaCodec et AudioTrack .

Une classe Java Tuner et une classe native sont créées.

  • L'API Java Tuner permet aux applications d'accéder au Tuner HAL via des API publiques.
  • La classe native permet le contrôle des autorisations et la gestion de grandes quantités de données d'enregistrement ou de lecture avec le Tuner HAL.
  • Le module Native Tuner est un pont entre la classe Tuner Java et le Tuner HAL.

Une classe TRM est créée.

  • Gère les ressources limitées du tuner, telles que le frontend, le LNB, les sessions CAS et un périphérique d'entrée TV à partir de l'entrée TV HAL.
  • Applique des règles pour récupérer les ressources insuffisantes des applications. La règle par défaut est la victoire au premier plan.

Media CAS et CAS HAL sont améliorés avec les fonctionnalités ci-dessous.

  • Ouvre les sessions CAS pour différents usages et algorithmes.
  • Prend en charge les systèmes CAS dynamiques, tels que le retrait et l'insertion CICAM.
  • S'intègre au Tuner HAL en fournissant des jetons clés.

MediaCodec et AudioTrack sont améliorés avec les fonctionnalités ci-dessous.

  • Prend une mémoire A/V sécurisée comme entrée de contenu.
  • Configuré pour effectuer la synchronisation A/V matérielle en lecture tunnelée.
  • Prise en charge configurée pour ES_payload et le mode passthrough.

Conception globale du Tuner HAL.

Figure 2. Schéma des composants du Tuner HAL

Flux de travail global

Les diagrammes ci-dessous illustrent les séquences d'appel pour la lecture d'une diffusion en direct.

Installation

Séquence de configuration du diagramme de lecture de diffusion en direct.

Figure 3. Séquence de configuration pour la lecture d'une diffusion en direct

Gestion de l'audiovisuel

Gestion de l'A/V pour le diagramme de lecture de diffusion en direct.

Figure 4. Gestion de l'A/V pour la lecture d'une diffusion en direct

Gestion du contenu crypté

Gestion du contenu brouillé pour le diagramme de lecture en direct.

Figure 5. Gestion du contenu crypté pour la lecture de diffusion en direct

Traitement des données A/V

Traitez les données A/V pour le diagramme de lecture de diffusion en direct.

Figure 6. Traitement A/V pour la lecture d'une diffusion en direct

API du SDK du tuner

L'API Tuner SDK gère les interactions avec Tuner JNI, Tuner HAL et TunerResourceManager . L'application TIS utilise l'API Tuner SDK pour accéder aux ressources et sous-composants Tuner tels que le filtre et le désembrouilleur. Frontend et demux sont des composants internes.

Organigramme de l'API Tuner SDK.

Figure 7. Interactions avec l'API du SDK Tuner

Versions

À partir d'Android 12, l'API Tuner SDK prend en charge la nouvelle fonctionnalité de Tuner HAL 1.1, qui est une mise à niveau de version rétrocompatible de Tuner 1.0.

Utilisez l'API suivante pour vérifier la version HAL en cours d'exécution.

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

La version minimale requise de HAL se trouve dans la documentation des nouvelles API Android 12.

Paquets

L'API Tuner SDK fournit les quatre packages ci-dessous.

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

Organigramme des packages API Tuner SDK.

Figure 8. Packages API du SDK Tuner

Android.media.tv.tuner

Le package Tuner est un point d’entrée pour utiliser le framework Tuner. L'application TIS utilise le package pour initialiser et acquérir des instances de ressources en spécifiant le paramètre initial et le rappel.

  • tuner() : initialise une instance de Tuner en spécifiant les paramètres useCase et sessionId .
  • tune() : acquiert une ressource frontend et la règle en spécifiant le paramètre FrontendSetting .
  • openFilter() : acquiert une instance de filtre en spécifiant le type de filtre.
  • openDvrRecorder() : acquiert une instance d'enregistrement en spécifiant la taille du tampon.
  • openDvrPlayback() : acquiert une instance de lecture en spécifiant la taille du tampon.
  • openDescrambler() : acquiert une instance de désembrouilleur.
  • openLnb() : acquiert une instance LNB interne.
  • openLnbByName() : acquiert une instance LNB externe.
  • openTimeFilter() : acquiert une instance de filtre temporel.

Le package Tuner fournit des fonctionnalités qui ne sont pas couvertes par les packages de filtre, DVR et frontend. Les fonctionnalités sont répertoriées ci-dessous.

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

Android.media.tv.tuner.frontend

Le package frontend comprend des ensembles de paramètres, d'informations, de statuts, d'événements et de fonctionnalités liés au frontend.

Des classes

FrontendSettings est dérivé pour différentes normes DTV par les classes ci-dessous.

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

À partir d'Android 12 avec Tuner HAL 1.1 ou supérieur, la norme DTV suivante est prise en charge.

  • DtmbFrontendSettings

FrontendCapabilities est dérivé pour différentes normes DTV par les classes ci-dessous.

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

À partir d'Android 12 avec Tuner HAL 1.1 ou supérieur, la norme DTV suivante est prise en charge.

  • DtmbFrontendCapabilities

FrontendInfo récupère les informations du frontend. FrontendStatus récupère l'état actuel du frontend. OnTuneEventListener écoute les événements sur le frontend. L'application TIS utilise ScanCallback pour traiter les messages d'analyse provenant du frontend.

Balayage des chaînes

Pour configurer un téléviseur, l'application analyse les fréquences possibles et crée une gamme de chaînes accessible aux utilisateurs. TIS peut utiliser Tuner.tune , Tuner.scan(BLIND_SCAN) ou Tuner.scan(AUTO_SCAN) pour terminer la numérisation des chaînes.

Si TIS dispose d'informations de livraison précises pour le signal, telles que la fréquence, la norme (par exemple, T/T2, S/S2) et des informations supplémentaires nécessaires (par exemple, ID PLD), alors Tuner.tune est recommandé comme option la plus rapide. .

Lorsque l'utilisateur appelle Tuner.tune , les actions suivantes se produisent :

  • TIS remplit FrontendSettings avec les informations requises à l'aide Tuner.tune .
  • Le HAL signale l'accord des messages LOCKED si le signal est verrouillé.
  • TIS utilise Frontend.getStatus pour collecter les informations nécessaires.
  • TIS passe à la fréquence disponible suivante dans sa liste de fréquences.

TIS appelle à nouveau Tuner.tune jusqu'à ce que toutes les fréquences soient épuisées.

Pendant le réglage, vous pouvez appeler stopTune() ou close() pour mettre en pause ou mettre fin à l'appel Tuner.tune .

Tuner.scan(AUTO_SCAN)

Si TIS ne dispose pas de suffisamment d'informations pour utiliser Tuner.tune , mais dispose d'une liste de fréquences et d'un type standard (par exemple, DVB T/C/S), alors Tuner.scan(AUTO_SCAN) est recommandé.

Lorsque l'utilisateur appelle Tuner.scan(AUTO_SCAN) , les actions suivantes se produisent :

  • TIS utilise Tuner.scan(AUTO_SCAN) avec FrontendSettings rempli de fréquence.

  • Les rapports HAL analysent les messages LOCKED si le signal est verrouillé. Le HAL peut également signaler d'autres messages d'analyse pour fournir des informations supplémentaires sur le signal.

  • TIS utilise Frontend.getStatus pour collecter les informations nécessaires.

  • TIS appelle Tuner.scan pour que le HAL passe au réglage suivant sur la même fréquence. Si la structure FrontendSettings est vide, la HAL utilise le paramètre disponible suivant. Sinon, HAL utilise FrontendSettings pour une analyse unique et envoie END pour indiquer que l'opération d'analyse est terminée.

  • TIS répète les actions ci-dessus jusqu'à ce que tous les réglages sur la fréquence soient épuisés.

  • Le HAL envoie END pour indiquer que l'opération d'analyse est terminée.

  • TIS passe à la fréquence disponible suivante dans sa liste de fréquences.

TIS appelle à nouveau Tuner.scan(AUTO_SCAN) jusqu'à ce que toutes les fréquences soient épuisées.

Pendant l'analyse, vous pouvez appeler stopScan() ou close() pour suspendre ou terminer l'analyse.

Tuner.scan(BLIND_SCAN)

Si TIS ne dispose pas de liste de fréquences et que le fournisseur HAL peut rechercher la fréquence du frontend spécifié par l'utilisateur pour obtenir la ressource frontend, alors Tuner.scan(BLIND_SCAN) est recommandé.

  • TIS utilise Tuner.scan(BLIND_SCAN) . Une fréquence peut être spécifiée dans FrontendSettings pour la fréquence de démarrage, mais TIS ignore les autres paramètres dans FrontendSettings .
  • Le HAL signale un message de balayage LOCKED si le signal est verrouillé.
  • TIS utilise Frontend.getStatus pour collecter les informations nécessaires.
  • TIS appelle à nouveau Tuner.scan pour poursuivre la numérisation. ( FrontendSettings est ignoré.)
  • TIS répète les actions ci-dessus jusqu'à ce que tous les réglages sur la fréquence soient épuisés. Le HAL incrémente la fréquence sans aucune action nécessaire de la part du TIS. Le HAL rapporte PROGRESS .

TIS appelle à nouveau Tuner.scan(AUTO_SCAN) jusqu'à ce que toutes les fréquences soient épuisées. Le HAL rapporte END pour indiquer que l'opération d'analyse est terminée.

Pendant l'analyse, vous pouvez appeler stopScan() ou close() pour suspendre ou terminer l'analyse.

Organigramme du processus TIS Scan.

Figure 9. Organigramme d'une analyse TIS

Android.media.tv.tuner.filter

Le package de filtrage est un ensemble d'opérations de filtrage ainsi que la configuration, les paramètres, les rappels et les événements. Le package comprend les opérations ci-dessous. Reportez-vous au code source Android pour la liste complète des opérations.

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

Reportez-vous au code source Android pour la liste complète.

FilterConfiguration est dérivé des classes ci-dessous. Les configurations concernent le type de filtre principal et spécifient le protocole utilisé par le filtre pour extraire les données.

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

Les paramètres sont dérivés des classes ci-dessous. Les paramètres concernent le sous-type de filtre et spécifient les types de données que le filtre peut exclure.

  • SectionSettings
  • AvSettings
  • PesSettings
  • RecordSettings
  • DownloadSettings

FilterEvent est dérivé des classes ci-dessous pour signaler des événements pour différents types de données.

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

À partir d'Android 12 avec Tuner HAL 1.1 ou supérieur, les événements suivants sont pris en charge.

  • IpCidChangeEvent
  • RestartEvent
  • ScramblingStatusEvent
Événements et format de données du filtre
Type de filtre Drapeaux Événements Opération de données Format des données
TS.SECTION
MMTP.SECTION
IP.SECTION
TLV.SECTION
ALP.SECTION
isRaw:
true
Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ de HAL vers le tampon client.
Un package de session assemblé est rempli en FMQ par un autre package de session.
isRaw:
false
Obligatoire:
DemuxFilterEvent::DemuxFilterSectionEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterSectionEven[i].size)


Les données sont copiées du MQ de HAL vers le tampon client.
TS.PES isRaw:
true
Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ du HAL vers le tampon client.
Un package PES assemblé est rempli en FMQ par un autre package PES.
isRaw:
false
Obligatoire:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


Les données sont copiées du MQ de HAL vers le tampon client.
MMTP.PES isRaw:
true
Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ du HAL vers le tampon client.
Un package MFU assemblé est rempli en FMQ par un autre package MFU.
isRaw:
false
Obligatoire:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


Les données sont copiées du MQ du HAL vers le tampon client.
TS.TS
N / A Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ du HAL vers le tampon client.
ts filtré avec en-tête ts
est rempli en FMQ.
TS.Audio
TS.Video
MMTP.Audio
MMTP.Video
isPassthrough:
true
Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Le client peut démarrer MediaCodec après avoir reçu DemuxFilterStatus::DATA_READY .
Le client peut appeler Filter.flush après avoir reçu DemuxFilterStatus::DATA_OVERFLOW .
N / A
isPassthrough:
false
Obligatoire:
DemuxFilterEvent::DemuxFilterMediaEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Pour utiliser MediaCodec :
for i=0; i<n; i++
linearblock = MediaEvent[i].getLinearBlock();
codec.startQueueLinearBlock(linearblock)
linearblock.recycle()


Pour utiliser l'audio direct d' AudioTrack :
for i=0; i<n; i++
audioHandle = MediaEvent[i].getAudioHandle();
audiotrack.write(encapsulated(audiohandle))
Données ES ou ES partielles dans la mémoire ION.
TS.PCR
IP.NTP
ALP.PTP
N / A Obligatoire : N/A
Facultatif : N/A
N / A N / A
TS.RECORD N / A Obligatoire:
DemuxFilterEvent::DemuxFilterTsRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Pour les données d'index :
for i=0; i<n; i++
DemuxFilterTsRecordEvent[i];


Pour le contenu enregistré , selon RecordStatus::* et la planification interne, effectuez l'une des opérations suivantes :
  • Exécutez DvrRecord.write(adustedSize) une ou plusieurs fois pour le stockage.
    Les données sont transférées du MQ du HAL vers le stockage.
  • Exécutez DvrRecord.write(buffer, adustedSize) une ou plusieurs fois pour mettre en mémoire tampon.
    Les données sont copiées du MQ du HAL vers le tampon client.
Pour les données d'index : transportées dans la charge utile de l'événement.

Pour le contenu enregistré : flux TS multiplexé rempli en FMQ.
TS.TEMI N / A Obligatoire:
DemuxFilterEvent::DemuxFilterTemiEvent[n]

Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
DemuxFilterTemiEvent[i];
N / A
MMTP.MMTP N / A Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ du HAL vers le tampon client.
mmtp filtré avec l'en-tête mmtp
est rempli en FMQ.
MMTP.RECORD N / A Obligatoire:
DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Pour les données d'index : for i=0; i<n; i++
DemuxFilterMmtpRecordEvent[i];


Pour le contenu enregistré , selon RecordStatus::* et la planification interne, effectuez l'une des opérations suivantes :
  • Exécutez DvrRecord.write(adjustedSize) une ou plusieurs fois pour le stockage.
    Les données sont transférées du MQ du HAL vers le stockage.
  • Exécutez DvrRecord.write(buffer, adjustedSize) une ou plusieurs fois pour mettre en mémoire tampon.
    Les données sont copiées du MQ du HAL vers le tampon client.
Pour les données d'index : transportées dans la charge utile de l'événement.

Pour le contenu enregistré : flux enregistré multiplexé rempli en FMQ.

Si la source de filtre pour l'enregistrement est TLV.TLV vers IP.IP avec passthrough, le flux enregistré a un en-tête TLV et IP.
MMTP.DOWNLOAD N / A Obligatoire:
DemuxFilterEvent::DemuxFilterDownloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size)

Les données sont copiées du MQ de HAL vers le tampon client.
Le package de téléchargement est rempli dans FMQ par un autre package de téléchargement IP.
IP.IP_PAYLOAD N / A Obligatoire:
DemuxFilterEvent::DemuxFilterIpPayloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size)

Les données sont copiées du MQ de HAL vers le tampon client.
Le package de charge utile IP est rempli dans FMQ par un autre package de charge utile IP.
IP.IP
TLV.TLV
ALP.ALP
isPassthrough:
true
Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Le sous-flux de protocole filtré alimente le filtre suivant dans la chaîne de filtres. N / A
isPassthrough:
false
Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ du HAL vers le tampon client.
Le sous-flux de protocole filtré avec en-tête de protocole est rempli dans FMQ.
IP.PAYLOAD_THROUGH
TLV.PAYLOAD_THROUGH
ALP.PAYLOAD_THROUGH
N / A Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
La charge utile du protocole filtrée alimente le filtre suivant dans la chaîne de filtres. N / A
Exemple de flux pour utiliser le filtre pour créer PSI/SI

Exemple de flux pour utiliser un filtre pour créer PSI/SI.

Figure 10. Flux pour construire PSI/SI

  1. Ouvrez un filtre.

    Filter filter = tuner.openFilter(
      Filter.TYPE_TS,
      Filter.SUBTYPE_SECTION,
      /* bufferSize */1000,
      executor,
      filterCallback
    );
    
  2. Configurez et démarrez le filtre.

    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. Traiter 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); }
          }
        }
    };
    
Exemple de flux pour utiliser MediaEvent à partir du filtre

Exemple de flux pour utiliser MediaEvent à partir du filtre.

Figure 11. Flux pour utiliser MediaEvent à partir du filtre

  1. Ouvrez, configurez et démarrez les filtres A/V.
  2. Traiter MediaEvent .
  3. Recevez MediaEvent .
  4. Mettez le bloc linéaire en file d'attente dans codec .
  5. Relâchez la poignée A/V lorsque les données ont été consommées.

Android.media.tv.tuner.dvr

DvrRecorder fournit ces méthodes d'enregistrement.

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

DvrPlayback fournit ces méthodes de lecture.

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

DvrSettings est utilisé pour configurer DvrRecorder et DvrPlayback . OnPlaybackStatusChangedListener et OnRecordStatusChangedListener sont utilisés pour signaler l'état d'une instance DVR.

Exemple de flux pour démarrer un enregistrement

Exemple de flux pour démarrer un enregistrement.

Figure 12. Flux pour démarrer un enregistrement

  1. Ouvrez, configurez et démarrez 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. Recevez RecordEvent et récupérez les informations d’index.

    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. Initialisez OnRecordStatusChangedListener et stockez les données d'enregistrement.

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

Accordeur HAL

Le Tuner HAL suit HIDL et définit l'interface entre le framework et le matériel du fournisseur. Les fournisseurs utilisent l'interface pour implémenter le Tuner HAL et le framework l'utilise pour communiquer avec l'implémentation du Tuner HAL.

Modules

Accordeur HAL 1.0

Modules Contrôles de base Commandes spécifiques au module Fichiers HAL
ITuner N / A 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 (dérivé de Tuner HAL 1.0)

Modules Contrôles de base Commandes spécifiques au module Fichiers HAL
ITuner N / A 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

Organigramme des interactions entre les modules du Tuner HAL.

Figure 13. Schéma des interactions entre les modules Tuner HAL

Liaison de filtre

Le Tuner HAL prend en charge la liaison de filtres de telle sorte que les filtres peuvent être liés à d'autres filtres pour plusieurs couches. Les filtres suivent les règles ci-dessous.

  • Les filtres sont liés sous forme d'arborescence, la fermeture du chemin n'est pas autorisée.
  • Le nœud racine est démultiplexé.
  • Les filtres fonctionnent indépendamment.
  • Tous les filtres commencent à obtenir des données.
  • La tringlerie du filtre rince sur le dernier filtre.

Le bloc de code ci-dessous et la figure 14 illustrent un exemple de filtrage de plusieurs couches.

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

Diagramme d'un exemple de liaison de filtre.

Figure 14. Organigramme d'une liaison de filtre pour plusieurs couches

Gestionnaire de ressources du tuner

Avant Tuner Resource Manager (TRM), la commutation entre deux applications nécessitait le même matériel Tuner. TV Input Framework (TIF) a utilisé un mécanisme de « premier à acquérir la victoire », ce qui signifie que la première application qui obtient la ressource conserve la ressource. Cependant, ce mécanisme n’est peut-être pas idéal pour certains cas d’utilisation complexes.

TRM fonctionne comme un service système pour gérer les ressources matérielles Tuner, TVInput et CAS pour les applications. TRM utilise un mécanisme de « victoire au premier plan », qui calcule la priorité de l'application en fonction de l'état de premier plan ou d'arrière-plan de l'application et du type de cas d'utilisation. TRM accorde ou révoque la ressource en fonction de la priorité. TRM centralise la gestion des ressources ATV pour la diffusion, l'OTT et le DVR.

Interface TRM

TRM expose les interfaces AIDL dans ITunerResourceManager.aidl pour le framework Tuner, MediaCas et TvInputHardwareManager pour enregistrer, demander ou libérer des ressources.

Les interfaces pour la gestion des clients sont répertoriées ci-dessous.

  • registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)
  • unregisterClientProfile(in int clientId)

Les interfaces pour demander et libérer des ressources sont répertoriées ci-dessous.

  • 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

Les classes de clients et de demandes sont répertoriées ci-dessous.

  • ResourceClientProfile
  • ResourcesReclaimListener
  • TunerFrontendRequest
  • TunerDemuxRequest
  • TunerDescramblerRequest
  • CasSessionRequest
  • TunerLnbRequest

Priorité client

TRM calcule la priorité du client en utilisant les paramètres du profil du client et la valeur de priorité du fichier de configuration. La priorité peut également être mise à jour par une valeur de priorité arbitraire du client.

Paramètres dans le profil du client

TRM récupère l'ID de processus à partir de mTvInputSessionId pour décider si une application est une application de premier plan ou d'arrière-plan. Pour créer mTvInputSessionId , TvInputService.onCreateSession ou TvInputService.onCreateRecordingSession initialise une session TIS.

mUseCase indique le cas d'utilisation de la session. Les cas d'utilisation prédéfinis sont répertoriés ci-dessous.

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
}

Fichier de configuration

Fichier de configuration par défaut

Le fichier de configuration par défaut ci-dessous fournit des valeurs de priorité pour les cas d'utilisation prédéfinis. Les utilisateurs peuvent modifier les valeurs à l'aide d'un fichier de configuration personnalisé .

Cas d'utilisation Premier plan Arrière-plan
LIVE 490 400
PLAYBACK 480 300
RECORD 600 500
SCAN 450 200
BACKGROUND 180 100
Fichier de configuration personnalisé

Les fournisseurs peuvent personnaliser le fichier de configuration /vendor/etc/tunerResourceManagerUseCaseConfig.xml . Ce fichier est utilisé pour ajouter, supprimer ou mettre à jour les types de cas d'utilisation et les valeurs de priorité des cas d'utilisation. Le fichier personnalisé peut utiliser platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml comme modèle.

Par exemple, un nouveau cas d'utilisation de fournisseur est VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000] . Le format doit suivre platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd .

Valeur prioritaire arbitraire et valeur intéressante

TRM fournit updateClientPriority pour que le client mette à jour la valeur de priorité arbitraire et la valeur intéressante. La valeur de priorité arbitraire écrase la valeur de priorité calculée à partir du type de cas d'utilisation et de l'ID de session.

La valeur nice indique à quel point le comportement du client est indulgent lorsqu'il est en conflit avec un autre client. La valeur intéressante diminue la valeur de priorité du client avant que sa valeur de priorité ne soit comparée à celle du client difficile.

Mécanisme de récupération

Le diagramme ci-dessous montre comment les ressources sont récupérées et attribuées en cas de conflit de ressources.

Schéma du processus du mécanisme de récupération.

Figure 15. Schéma du mécanisme de récupération en cas de conflit entre ressources Tuner

,

Pour Android 11 ou version ultérieure, vous pouvez utiliser le framework Android Tuner pour diffuser du contenu A/V. Le framework utilise le pipeline matériel des fournisseurs, ce qui le rend adapté aux SoC bas de gamme et haut de gamme. Le cadre fournit un moyen sécurisé de fournir du contenu audiovisuel protégé par un environnement d'exécution de confiance (TEE) et un chemin multimédia sécurisé (SMP), lui permettant d'être utilisé dans un environnement de protection de contenu hautement restreint.

L'interface standardisée entre Tuner et Android CAS permet une intégration plus rapide entre les fournisseurs Tuner et CAS. L'interface Tuner fonctionne avec MediaCodec et AudioTrack pour créer une solution mondiale pour Android TV. L'interface Tuner prend en charge à la fois la télévision numérique et la télévision analogique sur la base des principales normes de diffusion.

Composants

Pour Android 11, trois composants sont spécifiquement conçus pour la plateforme TV.

  • Tuner HAL : Une interface entre le framework et les fournisseurs
  • API Tuner SDK : une interface entre le framework et les applications
  • Tuner Resource Manager (TRM) : coordonne les ressources matérielles du Tuner

Pour Android 11, les composants suivants ont été améliorés.

  • CAS V2
  • TvInputService ou service d'entrée TV (TIS)
  • TvInputManagerService ou service de gestion des entrées TV (TIMS)
  • MediaCodec ou codec multimédia
  • AudioTrack ou piste audio
  • MediaResourceManager ou gestionnaire de ressources multimédias (MRM)

Organigramme des composants du framework Tuner.

Figure 1. Interactions entre les composants d'Android TV

Caractéristiques

Frontend prend en charge les normes DTV ci-dessous.

  • ATSC
  • ATSC3
  • DVB-C/S/T
  • ISDB S/S3/T
  • Analogique

L'interface sous Android 12 avec Tuner HAL 1.1 ou supérieur prend en charge la norme DTV ci-dessous.

  • DTMB

Demux prend en charge les protocoles de flux ci-dessous.

  • Flux de transport (TS)
  • Protocole de transport multimédia MPEG (MMTP)
  • Protocole Internet (IP)
  • Valeur de longueur de type (TLV)
  • Protocole de couche liaison ATSC (ALP)

Descrambler prend en charge les protections de contenu ci-dessous.

  • Chemin multimédia sécurisé
  • Chemin multimédia clair
  • Enregistrement local sécurisé
  • Lecture locale sécurisée

Les API Tuner prennent en charge les cas d'utilisation ci-dessous.

  • Analyse
  • En direct
  • Relecture
  • Enregistrer

Tuner, MediaCodec et AudioTrack prennent en charge les modes de flux de données ci-dessous.

  • Charge utile ES avec tampon mémoire vide
  • Charge utile ES avec poignée de mémoire sécurisée
  • Traverser

Conception générale

Le Tuner HAL est défini entre le framework Android et le matériel du fournisseur.

  • Décrit ce que le framework attend du fournisseur et comment le fournisseur peut le faire.
  • Exporte les fonctionnalités du frontend, du démultiplexage et du désembrouilleur vers le framework via les interfaces IFrontend , IDemux , IDescrambler , IFilter , IDvr et ILnb .
  • Inclut les fonctions permettant d'intégrer le Tuner HAL avec d'autres composants du framework, tels que MediaCodec et AudioTrack .

Une classe Java Tuner et une classe native sont créées.

  • L'API Java Tuner permet aux applications d'accéder au Tuner HAL via des API publiques.
  • La classe native permet le contrôle des autorisations et la gestion de grandes quantités de données d'enregistrement ou de lecture avec le Tuner HAL.
  • Le module Native Tuner est un pont entre la classe Tuner Java et le Tuner HAL.

Une classe TRM est créée.

  • Gère les ressources limitées du tuner, telles que le frontend, le LNB, les sessions CAS et un périphérique d'entrée TV à partir de l'entrée TV HAL.
  • Applique des règles pour récupérer les ressources insuffisantes des applications. La règle par défaut est la victoire au premier plan.

Media CAS et CAS HAL sont améliorés avec les fonctionnalités ci-dessous.

  • Ouvre les sessions CAS pour différents usages et algorithmes.
  • Prend en charge les systèmes CAS dynamiques, tels que le retrait et l'insertion CICAM.
  • S'intègre au Tuner HAL en fournissant des jetons clés.

MediaCodec et AudioTrack sont améliorés avec les fonctionnalités ci-dessous.

  • Prend une mémoire A/V sécurisée comme entrée de contenu.
  • Configuré pour effectuer la synchronisation A/V matérielle en lecture tunnelée.
  • Prise en charge configurée pour ES_payload et le mode passthrough.

Conception globale du Tuner HAL.

Figure 2. Schéma des composants du Tuner HAL

Flux de travail global

Les diagrammes ci-dessous illustrent les séquences d'appel pour la lecture d'une diffusion en direct.

Installation

Séquence de configuration du diagramme de lecture de diffusion en direct.

Figure 3. Séquence de configuration pour la lecture d'une diffusion en direct

Gestion de l'audiovisuel

Gestion de l'A/V pour le diagramme de lecture de diffusion en direct.

Figure 4. Gestion de l'A/V pour la lecture d'une diffusion en direct

Gestion du contenu crypté

Gestion du contenu brouillé pour le diagramme de lecture en direct.

Figure 5. Gestion du contenu crypté pour la lecture de diffusion en direct

Traitement des données A/V

Traitez les données A/V pour le diagramme de lecture de diffusion en direct.

Figure 6. Traitement A/V pour la lecture d'une diffusion en direct

API du SDK du tuner

L'API Tuner SDK gère les interactions avec Tuner JNI, Tuner HAL et TunerResourceManager . L'application TIS utilise l'API Tuner SDK pour accéder aux ressources et sous-composants Tuner tels que le filtre et le désembrouilleur. Frontend et demux sont des composants internes.

Organigramme de l'API Tuner SDK.

Figure 7. Interactions avec l'API du SDK Tuner

Versions

À partir d'Android 12, l'API Tuner SDK prend en charge la nouvelle fonctionnalité de Tuner HAL 1.1, qui est une mise à niveau de version rétrocompatible de Tuner 1.0.

Utilisez l'API suivante pour vérifier la version HAL en cours d'exécution.

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

La version minimale requise de HAL se trouve dans la documentation des nouvelles API Android 12.

Paquets

L'API Tuner SDK fournit les quatre packages ci-dessous.

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

Organigramme des packages API Tuner SDK.

Figure 8. Packages API du SDK Tuner

Android.media.tv.tuner

Le package Tuner est un point d’entrée pour utiliser le framework Tuner. L'application TIS utilise le package pour initialiser et acquérir des instances de ressources en spécifiant le paramètre initial et le rappel.

  • tuner() : initialise une instance de Tuner en spécifiant les paramètres useCase et sessionId .
  • tune() : acquiert une ressource frontend et la règle en spécifiant le paramètre FrontendSetting .
  • openFilter() : acquiert une instance de filtre en spécifiant le type de filtre.
  • openDvrRecorder() : acquiert une instance d'enregistrement en spécifiant la taille du tampon.
  • openDvrPlayback() : acquiert une instance de lecture en spécifiant la taille du tampon.
  • openDescrambler() : acquiert une instance de désembrouilleur.
  • openLnb() : acquiert une instance LNB interne.
  • openLnbByName() : acquiert une instance LNB externe.
  • openTimeFilter() : acquiert une instance de filtre temporel.

Le package Tuner fournit des fonctionnalités qui ne sont pas couvertes par les packages de filtre, DVR et frontend. Les fonctionnalités sont répertoriées ci-dessous.

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

Android.media.tv.tuner.frontend

Le package frontend comprend des ensembles de paramètres, d'informations, de statuts, d'événements et de fonctionnalités liés au frontend.

Des classes

FrontendSettings est dérivé pour différentes normes DTV par les classes ci-dessous.

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

À partir d'Android 12 avec Tuner HAL 1.1 ou supérieur, la norme DTV suivante est prise en charge.

  • DtmbFrontendSettings

FrontendCapabilities est dérivé pour différentes normes DTV par les classes ci-dessous.

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

À partir d'Android 12 avec Tuner HAL 1.1 ou supérieur, la norme DTV suivante est prise en charge.

  • DtmbFrontendCapabilities

FrontendInfo récupère les informations du frontend. FrontendStatus récupère l'état actuel du frontend. OnTuneEventListener écoute les événements sur le frontend. L'application TIS utilise ScanCallback pour traiter les messages d'analyse provenant du frontend.

Balayage des chaînes

Pour configurer un téléviseur, l'application analyse les fréquences possibles et crée une gamme de chaînes accessible aux utilisateurs. TIS peut utiliser Tuner.tune , Tuner.scan(BLIND_SCAN) ou Tuner.scan(AUTO_SCAN) pour terminer la numérisation des chaînes.

Si TIS dispose d'informations de livraison précises pour le signal, telles que la fréquence, la norme (par exemple, T/T2, S/S2) et des informations supplémentaires nécessaires (par exemple, ID PLD), alors Tuner.tune est recommandé comme option la plus rapide. .

Lorsque l'utilisateur appelle Tuner.tune , les actions suivantes se produisent :

  • TIS remplit FrontendSettings avec les informations requises à l'aide Tuner.tune .
  • Le HAL signale l'accord des messages LOCKED si le signal est verrouillé.
  • TIS utilise Frontend.getStatus pour collecter les informations nécessaires.
  • TIS passe à la fréquence disponible suivante dans sa liste de fréquences.

TIS appelle à nouveau Tuner.tune jusqu'à ce que toutes les fréquences soient épuisées.

Pendant le réglage, vous pouvez appeler stopTune() ou close() pour mettre en pause ou mettre fin à l'appel Tuner.tune .

Tuner.scan(AUTO_SCAN)

Si TIS ne dispose pas de suffisamment d'informations pour utiliser Tuner.tune , mais dispose d'une liste de fréquences et d'un type standard (par exemple, DVB T/C/S), alors Tuner.scan(AUTO_SCAN) est recommandé.

Lorsque l'utilisateur appelle Tuner.scan(AUTO_SCAN) , les actions suivantes se produisent :

  • TIS utilise Tuner.scan(AUTO_SCAN) avec FrontendSettings rempli de fréquence.

  • Les rapports HAL analysent les messages LOCKED si le signal est verrouillé. Le HAL peut également signaler d'autres messages d'analyse pour fournir des informations supplémentaires sur le signal.

  • TIS utilise Frontend.getStatus pour collecter les informations nécessaires.

  • TIS appelle Tuner.scan pour que le HAL passe au réglage suivant sur la même fréquence. Si la structure FrontendSettings est vide, la HAL utilise le paramètre disponible suivant. Sinon, HAL utilise FrontendSettings pour une analyse unique et envoie END pour indiquer que l'opération d'analyse est terminée.

  • TIS répète les actions ci-dessus jusqu'à ce que tous les réglages sur la fréquence soient épuisés.

  • Le HAL envoie END pour indiquer que l'opération d'analyse est terminée.

  • TIS passe à la fréquence disponible suivante dans sa liste de fréquences.

TIS appelle à nouveau Tuner.scan(AUTO_SCAN) jusqu'à ce que toutes les fréquences soient épuisées.

Pendant l'analyse, vous pouvez appeler stopScan() ou close() pour suspendre ou terminer l'analyse.

Tuner.scan(BLIND_SCAN)

Si TIS ne dispose pas de liste de fréquences et que le fournisseur HAL peut rechercher la fréquence du frontend spécifié par l'utilisateur pour obtenir la ressource frontend, alors Tuner.scan(BLIND_SCAN) est recommandé.

  • TIS utilise Tuner.scan(BLIND_SCAN) . Une fréquence peut être spécifiée dans FrontendSettings pour la fréquence de démarrage, mais TIS ignore les autres paramètres dans FrontendSettings .
  • Le HAL signale un message de balayage LOCKED si le signal est verrouillé.
  • TIS utilise Frontend.getStatus pour collecter les informations nécessaires.
  • TIS appelle à nouveau Tuner.scan pour poursuivre la numérisation. ( FrontendSettings est ignoré.)
  • TIS répète les actions ci-dessus jusqu'à ce que tous les réglages sur la fréquence soient épuisés. Le HAL incrémente la fréquence sans aucune action nécessaire de la part du TIS. Le HAL rapporte PROGRESS .

TIS appelle à nouveau Tuner.scan(AUTO_SCAN) jusqu'à ce que toutes les fréquences soient épuisées. Le HAL rapporte END pour indiquer que l'opération d'analyse est terminée.

Pendant l'analyse, vous pouvez appeler stopScan() ou close() pour suspendre ou terminer l'analyse.

Organigramme du processus TIS Scan.

Figure 9. Organigramme d'une analyse TIS

Android.media.tv.tuner.filter

Le package de filtrage est un ensemble d'opérations de filtrage ainsi que la configuration, les paramètres, les rappels et les événements. Le package comprend les opérations ci-dessous. Reportez-vous au code source Android pour la liste complète des opérations.

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

Reportez-vous au code source Android pour la liste complète.

FilterConfiguration est dérivé des classes ci-dessous. Les configurations concernent le type de filtre principal et spécifient le protocole utilisé par le filtre pour extraire les données.

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

Les paramètres sont dérivés des classes ci-dessous. Les paramètres concernent le sous-type de filtre et spécifient les types de données que le filtre peut exclure.

  • SectionSettings
  • AvSettings
  • PesSettings
  • RecordSettings
  • DownloadSettings

FilterEvent est dérivé des classes ci-dessous pour signaler des événements pour différents types de données.

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

À partir d'Android 12 avec Tuner HAL 1.1 ou supérieur, les événements suivants sont pris en charge.

  • IpCidChangeEvent
  • RestartEvent
  • ScramblingStatusEvent
Événements et format de données du filtre
Type de filtre Drapeaux Événements Opération de données Format des données
TS.SECTION
MMTP.SECTION
IP.SECTION
TLV.SECTION
ALP.SECTION
isRaw:
true
Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ de HAL vers le tampon client.
Un package de session assemblé est rempli en FMQ par un autre package de session.
isRaw:
false
Obligatoire:
DemuxFilterEvent::DemuxFilterSectionEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterSectionEven[i].size)


Les données sont copiées du MQ de HAL vers le tampon client.
TS.PES isRaw:
true
Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ du HAL vers le tampon client.
Un package PES assemblé est rempli en FMQ par un autre package PES.
isRaw:
false
Obligatoire:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


Les données sont copiées du MQ de HAL vers le tampon client.
MMTP.PES isRaw:
true
Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ du HAL vers le tampon client.
Un package MFU assemblé est rempli en FMQ par un autre package MFU.
isRaw:
false
Obligatoire:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


Les données sont copiées du MQ du HAL vers le tampon client.
TS.TS
N / A Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ du HAL vers le tampon client.
ts filtré avec en-tête ts
est rempli en FMQ.
TS.Audio
TS.Video
MMTP.Audio
MMTP.Video
isPassthrough:
true
Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Le client peut démarrer MediaCodec après avoir reçu DemuxFilterStatus::DATA_READY .
Le client peut appeler Filter.flush après avoir reçu DemuxFilterStatus::DATA_OVERFLOW .
N / A
isPassthrough:
false
Obligatoire:
DemuxFilterEvent::DemuxFilterMediaEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Pour utiliser MediaCodec :
for i=0; i<n; i++
linearblock = MediaEvent[i].getLinearBlock();
codec.startQueueLinearBlock(linearblock)
linearblock.recycle()


Pour utiliser l'audio direct d' AudioTrack :
for i=0; i<n; i++
audioHandle = MediaEvent[i].getAudioHandle();
audiotrack.write(encapsulated(audiohandle))
Données ES ou ES partielles dans la mémoire ION.
TS.PCR
IP.NTP
ALP.PTP
N / A Obligatoire : N/A
Facultatif : N/A
N / A N / A
TS.RECORD N / A Obligatoire:
DemuxFilterEvent::DemuxFilterTsRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Pour les données d'index :
for i=0; i<n; i++
DemuxFilterTsRecordEvent[i];


Pour le contenu enregistré , selon RecordStatus::* et la planification interne, effectuez l'une des opérations suivantes :
  • Exécutez DvrRecord.write(adustedSize) une ou plusieurs fois pour le stockage.
    Les données sont transférées du MQ du HAL vers le stockage.
  • Exécutez DvrRecord.write(buffer, adustedSize) une ou plusieurs fois pour mettre en mémoire tampon.
    Les données sont copiées du MQ du HAL vers le tampon client.
Pour les données d'index : transportées dans la charge utile de l'événement.

Pour le contenu enregistré : flux TS multiplexé rempli en FMQ.
TS.TEMI N / A Obligatoire:
DemuxFilterEvent::DemuxFilterTemiEvent[n]

Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
DemuxFilterTemiEvent[i];
N / A
MMTP.MMTP N / A Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ du HAL vers le tampon client.
mmtp filtré avec l'en-tête mmtp
est rempli en FMQ.
MMTP.RECORD N / A Obligatoire:
DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Pour les données d'index : for i=0; i<n; i++
DemuxFilterMmtpRecordEvent[i];


Pour le contenu enregistré , selon RecordStatus::* et la planification interne, effectuez l'une des opérations suivantes :
  • Exécutez DvrRecord.write(adjustedSize) une ou plusieurs fois pour le stockage.
    Les données sont transférées du MQ du HAL vers le stockage.
  • Exécutez DvrRecord.write(buffer, adjustedSize) une ou plusieurs fois pour mettre en mémoire tampon.
    Les données sont copiées du MQ du HAL vers le tampon client.
Pour les données d'index : transportées dans la charge utile de l'événement.

Pour le contenu enregistré : flux enregistré multiplexé rempli en FMQ.

Si la source de filtre pour l'enregistrement est TLV.TLV vers IP.IP avec passthrough, le flux enregistré a un en-tête TLV et IP.
MMTP.DOWNLOAD N / A Obligatoire:
DemuxFilterEvent::DemuxFilterDownloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size)

Les données sont copiées du MQ de HAL vers le tampon client.
Le package de téléchargement est rempli dans FMQ par un autre package de téléchargement IP.
IP.IP_PAYLOAD N / A Obligatoire:
DemuxFilterEvent::DemuxFilterIpPayloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size)

Les données sont copiées du MQ de HAL vers le tampon client.
Le package de charge utile IP est rempli dans FMQ par un autre package de charge utile IP.
IP.IP
TLV.TLV
ALP.ALP
isPassthrough:
true
Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Le sous-flux de protocole filtré alimente le filtre suivant dans la chaîne de filtres. N / A
isPassthrough:
false
Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ du HAL vers le tampon client.
Le sous-flux de protocole filtré avec en-tête de protocole est rempli dans FMQ.
IP.PAYLOAD_THROUGH
TLV.PAYLOAD_THROUGH
ALP.PAYLOAD_THROUGH
N / A Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
La charge utile du protocole filtrée alimente le filtre suivant dans la chaîne de filtres. N / A
Exemple de flux pour utiliser le filtre pour créer PSI/SI

Exemple de flux pour utiliser un filtre pour créer PSI/SI.

Figure 10. Flux pour construire PSI/SI

  1. Ouvrez un filtre.

    Filter filter = tuner.openFilter(
      Filter.TYPE_TS,
      Filter.SUBTYPE_SECTION,
      /* bufferSize */1000,
      executor,
      filterCallback
    );
    
  2. Configurez et démarrez le filtre.

    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. Traiter 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); }
          }
        }
    };
    
Exemple de flux pour utiliser MediaEvent à partir du filtre

Exemple de flux pour utiliser MediaEvent à partir du filtre.

Figure 11. Flux pour utiliser MediaEvent à partir du filtre

  1. Ouvrez, configurez et démarrez les filtres A/V.
  2. Traiter MediaEvent .
  3. Recevez MediaEvent .
  4. Mettez le bloc linéaire en file d'attente dans codec .
  5. Relâchez la poignée A/V lorsque les données ont été consommées.

Android.media.tv.tuner.dvr

DvrRecorder fournit ces méthodes d'enregistrement.

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

DvrPlayback fournit ces méthodes de lecture.

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

DvrSettings est utilisé pour configurer DvrRecorder et DvrPlayback . OnPlaybackStatusChangedListener et OnRecordStatusChangedListener sont utilisés pour signaler l'état d'une instance DVR.

Exemple de flux pour démarrer un enregistrement

Exemple de flux pour démarrer un enregistrement.

Figure 12. Flux pour démarrer un enregistrement

  1. Ouvrez, configurez et démarrez 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. Recevez RecordEvent et récupérez les informations d’index.

    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. Initialisez OnRecordStatusChangedListener et stockez les données d'enregistrement.

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

Accordeur HAL

Le Tuner HAL suit HIDL et définit l'interface entre le framework et le matériel du fournisseur. Les fournisseurs utilisent l'interface pour implémenter le Tuner HAL et le framework l'utilise pour communiquer avec l'implémentation du Tuner HAL.

Modules

Accordeur HAL 1.0

Modules Contrôles de base Commandes spécifiques au module Fichiers HAL
ITuner N / A 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 (dérivé de Tuner HAL 1.0)

Modules Contrôles de base Commandes spécifiques au module Fichiers HAL
ITuner N / A 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

Organigramme des interactions entre les modules du Tuner HAL.

Figure 13. Schéma des interactions entre les modules Tuner HAL

Liaison de filtre

Le Tuner HAL prend en charge la liaison de filtres de telle sorte que les filtres peuvent être liés à d'autres filtres pour plusieurs couches. Les filtres suivent les règles ci-dessous.

  • Les filtres sont liés sous forme d'arborescence, la fermeture du chemin n'est pas autorisée.
  • Le nœud racine est démultiplexé.
  • Les filtres fonctionnent indépendamment.
  • Tous les filtres commencent à obtenir des données.
  • La tringlerie du filtre rince sur le dernier filtre.

Le bloc de code ci-dessous et la figure 14 illustrent un exemple de filtrage de plusieurs couches.

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

Diagramme d'un exemple de liaison de filtre.

Figure 14. Organigramme d'une liaison de filtre pour plusieurs couches

Gestionnaire de ressources du tuner

Avant Tuner Resource Manager (TRM), la commutation entre deux applications nécessitait le même matériel Tuner. TV Input Framework (TIF) a utilisé un mécanisme de « premier à acquérir la victoire », ce qui signifie que la première application qui obtient la ressource conserve la ressource. Cependant, ce mécanisme n’est peut-être pas idéal pour certains cas d’utilisation complexes.

TRM fonctionne comme un service système pour gérer les ressources matérielles Tuner, TVInput et CAS pour les applications. TRM utilise un mécanisme de « victoire au premier plan », qui calcule la priorité de l'application en fonction de l'état de premier plan ou d'arrière-plan de l'application et du type de cas d'utilisation. TRM accorde ou révoque la ressource en fonction de la priorité. TRM centralise la gestion des ressources ATV pour la diffusion, l'OTT et le DVR.

Interface TRM

TRM expose les interfaces AIDL dans ITunerResourceManager.aidl pour le framework Tuner, MediaCas et TvInputHardwareManager pour enregistrer, demander ou libérer des ressources.

Les interfaces pour la gestion des clients sont répertoriées ci-dessous.

  • registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)
  • unregisterClientProfile(in int clientId)

Les interfaces pour demander et libérer des ressources sont répertoriées ci-dessous.

  • 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

Les classes de clients et de demandes sont répertoriées ci-dessous.

  • ResourceClientProfile
  • ResourcesReclaimListener
  • TunerFrontendRequest
  • TunerDemuxRequest
  • TunerDescramblerRequest
  • CasSessionRequest
  • TunerLnbRequest

Priorité client

TRM calcule la priorité du client en utilisant les paramètres du profil du client et la valeur de priorité du fichier de configuration. La priorité peut également être mise à jour par une valeur de priorité arbitraire du client.

Paramètres dans le profil du client

TRM récupère l'ID de processus à partir de mTvInputSessionId pour décider si une application est une application de premier plan ou d'arrière-plan. Pour créer mTvInputSessionId , TvInputService.onCreateSession ou TvInputService.onCreateRecordingSession initialise une session TIS.

mUseCase indique le cas d'utilisation de la session. Les cas d'utilisation prédéfinis sont répertoriés ci-dessous.

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
}

Fichier de configuration

Fichier de configuration par défaut

Le fichier de configuration par défaut ci-dessous fournit des valeurs de priorité pour les cas d'utilisation prédéfinis. Les utilisateurs peuvent modifier les valeurs à l'aide d'un fichier de configuration personnalisé .

Cas d'utilisation Premier plan Arrière-plan
LIVE 490 400
PLAYBACK 480 300
RECORD 600 500
SCAN 450 200
BACKGROUND 180 100
Fichier de configuration personnalisé

Les fournisseurs peuvent personnaliser le fichier de configuration /vendor/etc/tunerResourceManagerUseCaseConfig.xml . Ce fichier est utilisé pour ajouter, supprimer ou mettre à jour les types de cas d'utilisation et les valeurs de priorité des cas d'utilisation. Le fichier personnalisé peut utiliser platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml comme modèle.

Par exemple, un nouveau cas d'utilisation de fournisseur est VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000] . Le format doit suivre platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd .

Valeur prioritaire arbitraire et valeur intéressante

TRM fournit updateClientPriority pour que le client mette à jour la valeur de priorité arbitraire et la valeur intéressante. La valeur de priorité arbitraire écrase la valeur de priorité calculée à partir du type de cas d'utilisation et de l'ID de session.

La valeur nice indique à quel point le comportement du client est indulgent lorsqu'il est en conflit avec un autre client. La valeur intéressante diminue la valeur de priorité du client avant que sa valeur de priorité ne soit comparée à celle du client difficile.

Mécanisme de récupération

Le diagramme ci-dessous montre comment les ressources sont récupérées et attribuées en cas de conflit de ressources.

Schéma du processus du mécanisme de récupération.

Figure 15. Schéma du mécanisme de récupération en cas de conflit entre ressources Tuner

,

Pour Android 11 ou version ultérieure, vous pouvez utiliser le framework Android Tuner pour diffuser du contenu A/V. Le framework utilise le pipeline matériel des fournisseurs, ce qui le rend adapté aux SoC bas de gamme et haut de gamme. Le cadre fournit un moyen sécurisé de fournir du contenu audiovisuel protégé par un environnement d'exécution de confiance (TEE) et un chemin multimédia sécurisé (SMP), lui permettant d'être utilisé dans un environnement de protection de contenu hautement restreint.

L'interface standardisée entre Tuner et Android CAS permet une intégration plus rapide entre les fournisseurs Tuner et CAS. L'interface Tuner fonctionne avec MediaCodec et AudioTrack pour créer une solution mondiale pour Android TV. L'interface Tuner prend en charge à la fois la télévision numérique et la télévision analogique sur la base des principales normes de diffusion.

Composants

Pour Android 11, trois composants sont spécifiquement conçus pour la plateforme TV.

  • Tuner HAL : Une interface entre le framework et les fournisseurs
  • API Tuner SDK : une interface entre le framework et les applications
  • Tuner Resource Manager (TRM) : coordonne les ressources matérielles du Tuner

Pour Android 11, les composants suivants ont été améliorés.

  • CAS V2
  • TvInputService ou service d'entrée TV (TIS)
  • TvInputManagerService ou service de gestion des entrées TV (TIMS)
  • MediaCodec ou codec multimédia
  • AudioTrack ou piste audio
  • MediaResourceManager ou gestionnaire de ressources multimédias (MRM)

Organigramme des composants du framework Tuner.

Figure 1. Interactions entre les composants d'Android TV

Caractéristiques

Frontend prend en charge les normes DTV ci-dessous.

  • ATSC
  • ATSC3
  • DVB-C/S/T
  • ISDB S/S3/T
  • Analogique

L'interface sous Android 12 avec Tuner HAL 1.1 ou supérieur prend en charge la norme DTV ci-dessous.

  • DTMB

Demux prend en charge les protocoles de flux ci-dessous.

  • Flux de transport (TS)
  • Protocole de transport multimédia MPEG (MMTP)
  • Protocole Internet (IP)
  • Valeur de longueur de type (TLV)
  • Protocole de couche liaison ATSC (ALP)

Descrambler prend en charge les protections de contenu ci-dessous.

  • Chemin multimédia sécurisé
  • Chemin multimédia clair
  • Enregistrement local sécurisé
  • Lecture locale sécurisée

Les API Tuner prennent en charge les cas d'utilisation ci-dessous.

  • Analyse
  • En direct
  • Relecture
  • Enregistrer

Tuner, MediaCodec et AudioTrack prennent en charge les modes de flux de données ci-dessous.

  • Charge utile ES avec tampon mémoire vide
  • Charge utile ES avec poignée de mémoire sécurisée
  • Traverser

Conception générale

Le Tuner HAL est défini entre le framework Android et le matériel du fournisseur.

  • Décrit ce que le framework attend du fournisseur et comment le fournisseur peut le faire.
  • Exporte les fonctionnalités du frontend, du démultiplexage et du désembrouilleur vers le framework via les interfaces IFrontend , IDemux , IDescrambler , IFilter , IDvr et ILnb .
  • Inclut les fonctions permettant d'intégrer le Tuner HAL avec d'autres composants du framework, tels que MediaCodec et AudioTrack .

Une classe Java Tuner et une classe native sont créées.

  • L'API Java Tuner permet aux applications d'accéder au Tuner HAL via des API publiques.
  • La classe native permet le contrôle des autorisations et la gestion de grandes quantités de données d'enregistrement ou de lecture avec le Tuner HAL.
  • Le module Native Tuner est un pont entre la classe Tuner Java et le Tuner HAL.

Une classe TRM est créée.

  • Gère les ressources limitées du tuner, telles que le frontend, le LNB, les sessions CAS et un périphérique d'entrée TV à partir de l'entrée TV HAL.
  • Applique des règles pour récupérer les ressources insuffisantes des applications. La règle par défaut est la victoire au premier plan.

Media CAS et CAS HAL sont améliorés avec les fonctionnalités ci-dessous.

  • Ouvre les sessions CAS pour différents usages et algorithmes.
  • Prend en charge les systèmes CAS dynamiques, tels que le retrait et l'insertion CICAM.
  • S'intègre au Tuner HAL en fournissant des jetons clés.

MediaCodec et AudioTrack sont améliorés avec les fonctionnalités ci-dessous.

  • Prend une mémoire A/V sécurisée comme entrée de contenu.
  • Configuré pour effectuer la synchronisation A/V matérielle en lecture tunnelée.
  • Prise en charge configurée pour ES_payload et le mode passthrough.

Conception globale du Tuner HAL.

Figure 2. Schéma des composants du Tuner HAL

Flux de travail global

Les diagrammes ci-dessous illustrent les séquences d'appel pour la lecture d'une diffusion en direct.

Installation

Séquence de configuration du diagramme de lecture de diffusion en direct.

Figure 3. Séquence de configuration pour la lecture d'une diffusion en direct

Gestion de l'audiovisuel

Gestion de l'A/V pour le diagramme de lecture de diffusion en direct.

Figure 4. Gestion de l'A/V pour la lecture d'une diffusion en direct

Gestion du contenu crypté

Gestion du contenu brouillé pour le diagramme de lecture en direct.

Figure 5. Gestion du contenu crypté pour la lecture de diffusion en direct

Traitement des données A/V

Traitez les données A/V pour le diagramme de lecture de diffusion en direct.

Figure 6. Traitement A/V pour la lecture d'une diffusion en direct

API du SDK du tuner

L'API Tuner SDK gère les interactions avec Tuner JNI, Tuner HAL et TunerResourceManager . L'application TIS utilise l'API Tuner SDK pour accéder aux ressources et sous-composants Tuner tels que le filtre et le désembrouilleur. Frontend et demux sont des composants internes.

Organigramme de l'API Tuner SDK.

Figure 7. Interactions avec l'API du SDK Tuner

Versions

À partir d'Android 12, l'API Tuner SDK prend en charge la nouvelle fonctionnalité de Tuner HAL 1.1, qui est une mise à niveau de version rétrocompatible de Tuner 1.0.

Utilisez l'API suivante pour vérifier la version HAL en cours d'exécution.

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

La version minimale requise de HAL se trouve dans la documentation des nouvelles API Android 12.

Paquets

L'API Tuner SDK fournit les quatre packages ci-dessous.

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

Organigramme des packages API Tuner SDK.

Figure 8. Packages API du SDK Tuner

Android.media.tv.tuner

Le package Tuner est un point d’entrée pour utiliser le framework Tuner. L'application TIS utilise le package pour initialiser et acquérir des instances de ressources en spécifiant le paramètre initial et le rappel.

  • tuner() : initialise une instance de Tuner en spécifiant les paramètres useCase et sessionId .
  • tune() : acquiert une ressource frontend et la règle en spécifiant le paramètre FrontendSetting .
  • openFilter() : acquiert une instance de filtre en spécifiant le type de filtre.
  • openDvrRecorder() : acquiert une instance d'enregistrement en spécifiant la taille du tampon.
  • openDvrPlayback() : acquiert une instance de lecture en spécifiant la taille du tampon.
  • openDescrambler() : acquiert une instance de désembrouilleur.
  • openLnb() : acquiert une instance LNB interne.
  • openLnbByName() : acquiert une instance LNB externe.
  • openTimeFilter() : acquiert une instance de filtre temporel.

Le package Tuner fournit des fonctionnalités qui ne sont pas couvertes par les packages de filtre, DVR et frontend. Les fonctionnalités sont répertoriées ci-dessous.

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

Android.media.tv.tuner.frontend

Le package frontend comprend des ensembles de paramètres, d'informations, de statuts, d'événements et de fonctionnalités liés au frontend.

Des classes

FrontendSettings est dérivé pour différentes normes DTV par les classes ci-dessous.

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

À partir d'Android 12 avec Tuner HAL 1.1 ou supérieur, la norme DTV suivante est prise en charge.

  • DtmbFrontendSettings

FrontendCapabilities est dérivé pour différentes normes DTV par les classes ci-dessous.

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

À partir d'Android 12 avec Tuner HAL 1.1 ou supérieur, la norme DTV suivante est prise en charge.

  • DtmbFrontendCapabilities

FrontendInfo récupère les informations du frontend. FrontendStatus récupère l'état actuel du frontend. OnTuneEventListener écoute les événements sur le frontend. L'application TIS utilise ScanCallback pour traiter les messages d'analyse provenant du frontend.

Balayage des chaînes

Pour configurer un téléviseur, l'application analyse les fréquences possibles et crée une gamme de chaînes accessible aux utilisateurs. TIS peut utiliser Tuner.tune , Tuner.scan(BLIND_SCAN) ou Tuner.scan(AUTO_SCAN) pour terminer la numérisation des chaînes.

Si TIS dispose d'informations de livraison précises pour le signal, telles que la fréquence, la norme (par exemple, T/T2, S/S2) et des informations supplémentaires nécessaires (par exemple, ID PLD), alors Tuner.tune est recommandé comme option la plus rapide. .

Lorsque l'utilisateur appelle Tuner.tune , les actions suivantes se produisent :

  • TIS remplit FrontendSettings avec les informations requises à l'aide Tuner.tune .
  • Le HAL signale l'accord des messages LOCKED si le signal est verrouillé.
  • TIS utilise Frontend.getStatus pour collecter les informations nécessaires.
  • TIS passe à la fréquence disponible suivante dans sa liste de fréquences.

TIS appelle à nouveau Tuner.tune jusqu'à ce que toutes les fréquences soient épuisées.

Pendant le réglage, vous pouvez appeler stopTune() ou close() pour mettre en pause ou mettre fin à l'appel Tuner.tune .

Tuner.scan(AUTO_SCAN)

Si TIS ne dispose pas de suffisamment d'informations pour utiliser Tuner.tune , mais dispose d'une liste de fréquences et d'un type standard (par exemple, DVB T/C/S), alors Tuner.scan(AUTO_SCAN) est recommandé.

Lorsque l'utilisateur appelle Tuner.scan(AUTO_SCAN) , les actions suivantes se produisent :

  • TIS utilise Tuner.scan(AUTO_SCAN) avec FrontendSettings rempli de fréquence.

  • Les rapports HAL analysent les messages LOCKED si le signal est verrouillé. Le HAL peut également signaler d'autres messages d'analyse pour fournir des informations supplémentaires sur le signal.

  • TIS utilise Frontend.getStatus pour collecter les informations nécessaires.

  • TIS appelle Tuner.scan pour que le HAL passe au réglage suivant sur la même fréquence. Si la structure FrontendSettings est vide, la HAL utilise le paramètre disponible suivant. Sinon, HAL utilise FrontendSettings pour une analyse unique et envoie END pour indiquer que l'opération d'analyse est terminée.

  • TIS répète les actions ci-dessus jusqu'à ce que tous les réglages sur la fréquence soient épuisés.

  • Le HAL envoie END pour indiquer que l'opération d'analyse est terminée.

  • TIS passe à la fréquence disponible suivante dans sa liste de fréquences.

TIS appelle à nouveau Tuner.scan(AUTO_SCAN) jusqu'à ce que toutes les fréquences soient épuisées.

Pendant l'analyse, vous pouvez appeler stopScan() ou close() pour suspendre ou terminer l'analyse.

Tuner.scan(BLIND_SCAN)

Si TIS ne dispose pas de liste de fréquences et que le fournisseur HAL peut rechercher la fréquence du frontend spécifié par l'utilisateur pour obtenir la ressource frontend, alors Tuner.scan(BLIND_SCAN) est recommandé.

  • TIS utilise Tuner.scan(BLIND_SCAN) . Une fréquence peut être spécifiée dans FrontendSettings pour la fréquence de démarrage, mais TIS ignore les autres paramètres dans FrontendSettings .
  • Le HAL signale un message de balayage LOCKED si le signal est verrouillé.
  • TIS utilise Frontend.getStatus pour collecter les informations nécessaires.
  • TIS appelle à nouveau Tuner.scan pour poursuivre la numérisation. ( FrontendSettings est ignoré.)
  • TIS répète les actions ci-dessus jusqu'à ce que tous les réglages sur la fréquence soient épuisés. Le HAL incrémente la fréquence sans aucune action nécessaire de la part du TIS. Le HAL rapporte PROGRESS .

TIS appelle à nouveau Tuner.scan(AUTO_SCAN) jusqu'à ce que toutes les fréquences soient épuisées. Le HAL rapporte END pour indiquer que l'opération d'analyse est terminée.

Pendant l'analyse, vous pouvez appeler stopScan() ou close() pour suspendre ou terminer l'analyse.

Organigramme du processus TIS Scan.

Figure 9. Organigramme d'une analyse TIS

Android.media.tv.tuner.filter

Le package de filtrage est un ensemble d'opérations de filtrage ainsi que la configuration, les paramètres, les rappels et les événements. Le package comprend les opérations ci-dessous. Reportez-vous au code source Android pour la liste complète des opérations.

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

Reportez-vous au code source Android pour la liste complète.

FilterConfiguration est dérivé des classes ci-dessous. Les configurations concernent le type de filtre principal et spécifient le protocole utilisé par le filtre pour extraire les données.

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

Les paramètres sont dérivés des classes ci-dessous. Les paramètres concernent le sous-type de filtre et spécifient les types de données que le filtre peut exclure.

  • SectionSettings
  • AvSettings
  • PesSettings
  • RecordSettings
  • DownloadSettings

FilterEvent est dérivé des classes ci-dessous pour signaler des événements pour différents types de données.

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

À partir d'Android 12 avec Tuner HAL 1.1 ou supérieur, les événements suivants sont pris en charge.

  • IpCidChangeEvent
  • RestartEvent
  • ScramblingStatusEvent
Événements et format de données du filtre
Type de filtre Drapeaux Événements Opération de données Format des données
TS.SECTION
MMTP.SECTION
IP.SECTION
TLV.SECTION
ALP.SECTION
isRaw:
true
Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ de HAL vers le tampon client.
Un package de session assemblé est rempli en FMQ par un autre package de session.
isRaw:
false
Obligatoire:
DemuxFilterEvent::DemuxFilterSectionEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterSectionEven[i].size)


Les données sont copiées du MQ de HAL vers le tampon client.
TS.PES isRaw:
true
Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ du HAL vers le tampon client.
Un package PES assemblé est rempli en FMQ par un autre package PES.
isRaw:
false
Obligatoire:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


Les données sont copiées du MQ de HAL vers le tampon client.
MMTP.PES isRaw:
true
Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ du HAL vers le tampon client.
Un package MFU assemblé est rempli en FMQ par un autre package MFU.
isRaw:
false
Obligatoire:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


Les données sont copiées du MQ du HAL vers le tampon client.
TS.TS
N / A Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ du HAL vers le tampon client.
ts filtré avec en-tête ts
est rempli en FMQ.
TS.Audio
TS.Video
MMTP.Audio
MMTP.Video
isPassthrough:
true
Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Le client peut démarrer MediaCodec après avoir reçu DemuxFilterStatus::DATA_READY .
Le client peut appeler Filter.flush après avoir reçu DemuxFilterStatus::DATA_OVERFLOW .
N / A
isPassthrough:
false
Obligatoire:
DemuxFilterEvent::DemuxFilterMediaEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Pour utiliser MediaCodec :
for i=0; i<n; i++
linearblock = MediaEvent[i].getLinearBlock();
codec.startQueueLinearBlock(linearblock)
linearblock.recycle()


Pour utiliser l'audio direct d' AudioTrack :
for i=0; i<n; i++
audioHandle = MediaEvent[i].getAudioHandle();
audiotrack.write(encapsulated(audiohandle))
Données ES ou ES partielles dans la mémoire ION.
TS.PCR
IP.NTP
ALP.PTP
N / A Obligatoire : N/A
Facultatif : N/A
N / A N / A
TS.RECORD N / A Obligatoire:
DemuxFilterEvent::DemuxFilterTsRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Pour les données d'index :
for i=0; i<n; i++
DemuxFilterTsRecordEvent[i];


Pour le contenu enregistré , selon RecordStatus::* et la planification interne, effectuez l'une des opérations suivantes :
  • Exécutez DvrRecord.write(adustedSize) une ou plusieurs fois pour le stockage.
    Les données sont transférées du MQ du HAL vers le stockage.
  • Exécutez DvrRecord.write(buffer, adustedSize) une ou plusieurs fois pour mettre en mémoire tampon.
    Les données sont copiées du MQ du HAL vers le tampon client.
Pour les données d'index : transportées dans la charge utile de l'événement.

Pour le contenu enregistré : flux TS multiplexé rempli en FMQ.
TS.TEMI N / A Obligatoire:
DemuxFilterEvent::DemuxFilterTemiEvent[n]

Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
DemuxFilterTemiEvent[i];
N / A
MMTP.MMTP N / A Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ du HAL vers le tampon client.
mmtp filtré avec l'en-tête mmtp
est rempli en FMQ.
MMTP.RECORD N / A Obligatoire:
DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Pour les données d'index : for i=0; i<n; i++
DemuxFilterMmtpRecordEvent[i];


Pour le contenu enregistré , selon RecordStatus::* et la planification interne, effectuez l'une des opérations suivantes :
  • Exécutez DvrRecord.write(adjustedSize) une ou plusieurs fois pour le stockage.
    Les données sont transférées du MQ du HAL vers le stockage.
  • Exécutez DvrRecord.write(buffer, adjustedSize) une ou plusieurs fois pour mettre en mémoire tampon.
    Les données sont copiées du MQ du HAL vers le tampon client.
Pour les données d'index : transportées dans la charge utile de l'événement.

Pour le contenu enregistré : flux enregistré multiplexé rempli en FMQ.

Si la source de filtre pour l'enregistrement est TLV.TLV vers IP.IP avec passthrough, le flux enregistré a un en-tête TLV et IP.
MMTP.DOWNLOAD N / A Obligatoire:
DemuxFilterEvent::DemuxFilterDownloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size)

Les données sont copiées du MQ de HAL vers le tampon client.
Le package de téléchargement est rempli dans FMQ par un autre package de téléchargement IP.
IP.IP_PAYLOAD N / A Obligatoire:
DemuxFilterEvent::DemuxFilterIpPayloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Facultatif:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size)

Les données sont copiées du MQ de HAL vers le tampon client.
Le package de charge utile IP est rempli dans FMQ par un autre package de charge utile IP.
IP.IP
TLV.TLV
ALP.ALP
isPassthrough:
true
Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
Le sous-flux de protocole filtré alimente le filtre suivant dans la chaîne de filtres. N / A
isPassthrough:
false
Obligatoire:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recommandé:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Selon l'événement et le planning interne, exécutez
Filter.read(buffer, offset, adjustedSize) une ou plusieurs fois.

Les données sont copiées du MQ du HAL vers le tampon client.
Le sous-flux de protocole filtré avec en-tête de protocole est rempli dans FMQ.
IP.PAYLOAD_THROUGH
TLV.PAYLOAD_THROUGH
ALP.PAYLOAD_THROUGH
N / A Facultatif:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
La charge utile du protocole filtrée alimente le filtre suivant dans la chaîne de filtres. N / A
Exemple de flux pour utiliser le filtre pour créer PSI/SI

Exemple de flux pour utiliser un filtre pour créer PSI/SI.

Figure 10. Flux pour construire PSI/SI

  1. Ouvrez un filtre.

    Filter filter = tuner.openFilter(
      Filter.TYPE_TS,
      Filter.SUBTYPE_SECTION,
      /* bufferSize */1000,
      executor,
      filterCallback
    );
    
  2. Configurez et démarrez le filtre.

    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. Traiter 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); }
          }
        }
    };
    
Exemple de flux pour utiliser MediaEvent à partir du filtre

Exemple de flux pour utiliser MediaEvent à partir du filtre.

Figure 11. Flux pour utiliser MediaEvent à partir du filtre

  1. Ouvrez, configurez et démarrez les filtres A/V.
  2. Traiter MediaEvent .
  3. Recevez MediaEvent .
  4. Mettez le bloc linéaire en file d'attente dans codec .
  5. Relâchez la poignée A/V lorsque les données ont été consommées.

Android.media.tv.tuner.dvr

DvrRecorder fournit ces méthodes d'enregistrement.

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

DvrPlayback fournit ces méthodes de lecture.

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

DvrSettings est utilisé pour configurer DvrRecorder et DvrPlayback . OnPlaybackStatusChangedListener et OnRecordStatusChangedListener sont utilisés pour signaler l'état d'une instance DVR.

Exemple de flux pour démarrer un enregistrement

Exemple de flux pour démarrer un enregistrement.

Figure 12. Flux pour démarrer un enregistrement

  1. Ouvrez, configurez et démarrez 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. Recevez RecordEvent et récupérez les informations d’index.

    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. Initialisez OnRecordStatusChangedListener et stockez les données d'enregistrement.

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

Accordeur HAL

Le Tuner HAL suit HIDL et définit l'interface entre le framework et le matériel du fournisseur. Les fournisseurs utilisent l'interface pour implémenter le Tuner HAL et le framework l'utilise pour communiquer avec l'implémentation du Tuner HAL.

Modules

Accordeur HAL 1.0

Modules Contrôles de base Commandes spécifiques au module Fichiers HAL
ITuner N / A 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 (dérivé de Tuner HAL 1.0)

Modules Contrôles de base Commandes spécifiques au module Fichiers HAL
ITuner N / A 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

Organigramme des interactions entre les modules du Tuner HAL.

Figure 13. Schéma des interactions entre les modules Tuner HAL

Liaison de filtre

Le Tuner HAL prend en charge la liaison de filtres de telle sorte que les filtres peuvent être liés à d'autres filtres pour plusieurs couches. Les filtres suivent les règles ci-dessous.

  • Les filtres sont liés sous forme d'arborescence, la fermeture du chemin n'est pas autorisée.
  • Le nœud racine est démultiplexé.
  • Les filtres fonctionnent indépendamment.
  • Tous les filtres commencent à obtenir des données.
  • La tringlerie du filtre rince sur le dernier filtre.

Le bloc de code ci-dessous et la figure 14 illustrent un exemple de filtrage de plusieurs couches.

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

Diagramme d'un exemple de liaison de filtre.

Figure 14. Organigramme d'une liaison de filtre pour plusieurs couches

Gestionnaire de ressources du tuner

Avant Tuner Resource Manager (TRM), la commutation entre deux applications nécessitait le même matériel Tuner. TV Input Framework (TIF) a utilisé un mécanisme de « premier à acquérir la victoire », ce qui signifie que la première application qui obtient la ressource conserve la ressource. Cependant, ce mécanisme n’est peut-être pas idéal pour certains cas d’utilisation complexes.

TRM fonctionne comme un service système pour gérer les ressources matérielles Tuner, TVInput et CAS pour les applications. TRM utilise un mécanisme de « victoire au premier plan », qui calcule la priorité de l'application en fonction de l'état de premier plan ou d'arrière-plan de l'application et du type de cas d'utilisation. TRM accorde ou révoque la ressource en fonction de la priorité. TRM centralise la gestion des ressources ATV pour la diffusion, l'OTT et le DVR.

Interface TRM

TRM expose les interfaces AIDL dans ITunerResourceManager.aidl pour le framework Tuner, MediaCas et TvInputHardwareManager pour enregistrer, demander ou libérer des ressources.

Les interfaces pour la gestion des clients sont répertoriées ci-dessous.

  • registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)
  • unregisterClientProfile(in int clientId)

Les interfaces pour demander et libérer des ressources sont répertoriées ci-dessous.

  • 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

Les classes de clients et de demandes sont répertoriées ci-dessous.

  • ResourceClientProfile
  • ResourcesReclaimListener
  • TunerFrontendRequest
  • TunerDemuxRequest
  • TunerDescramblerRequest
  • CasSessionRequest
  • TunerLnbRequest

Priorité client

TRM calcule la priorité du client en utilisant les paramètres du profil du client et la valeur de priorité du fichier de configuration. La priorité peut également être mise à jour par une valeur de priorité arbitraire du client.

Paramètres dans le profil du client

TRM récupère l'ID de processus à partir de mTvInputSessionId pour décider si une application est une application de premier plan ou d'arrière-plan. Pour créer mTvInputSessionId , TvInputService.onCreateSession ou TvInputService.onCreateRecordingSession initialise une session TIS.

mUseCase indique le cas d'utilisation de la session. Les cas d'utilisation prédéfinis sont répertoriés ci-dessous.

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
}

Fichier de configuration

Fichier de configuration par défaut

Le fichier de configuration par défaut ci-dessous fournit des valeurs de priorité pour les cas d'utilisation prédéfinis. Les utilisateurs peuvent modifier les valeurs à l'aide d'un fichier de configuration personnalisé .

Cas d'utilisation Premier plan Arrière-plan
LIVE 490 400
PLAYBACK 480 300
RECORD 600 500
SCAN 450 200
BACKGROUND 180 100
Fichier de configuration personnalisé

Les fournisseurs peuvent personnaliser le fichier de configuration /vendor/etc/tunerResourceManagerUseCaseConfig.xml . Ce fichier est utilisé pour ajouter, supprimer ou mettre à jour les types de cas d'utilisation et les valeurs de priorité des cas d'utilisation. Le fichier personnalisé peut utiliser platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml comme modèle.

Par exemple, un nouveau cas d'utilisation de fournisseur est VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000] . Le format doit suivre platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd .

Valeur prioritaire arbitraire et valeur intéressante

TRM fournit updateClientPriority pour que le client mette à jour la valeur de priorité arbitraire et la valeur intéressante. La valeur de priorité arbitraire écrase la valeur de priorité calculée à partir du type de cas d'utilisation et de l'ID de session.

La valeur nice indique à quel point le comportement du client est indulgent lorsqu'il est en conflit avec un autre client. La valeur intéressante diminue la valeur de priorité du client avant que sa valeur de priorité ne soit comparée à celle du client difficile.

Mécanisme de récupération

Le diagramme ci-dessous montre comment les ressources sont récupérées et attribuées en cas de conflit de ressources.

Schéma du processus du mécanisme de récupération.

Figure 15. Schéma du mécanisme de récupération en cas de conflit entre ressources Tuner