Estrutura do sintonizador

Para o Android 11 ou superior, você pode usar a estrutura do Android Tuner para fornecer conteúdo A/V. A estrutura usa o pipeline de hardware dos fornecedores, tornando-a adequada para SoC de baixo e alto nível. A estrutura fornece uma maneira segura de fornecer conteúdo A/V protegido por um ambiente de execução confiável (TEE) e caminho de mídia seguro (SMP), permitindo que ele seja usado em um ambiente de proteção de conteúdo altamente restrito.

A interface padronizada entre o Tuner e o Android CAS resulta em uma integração mais rápida entre os fornecedores do Tuner e os fornecedores do CAS. A interface do Tuner funciona com MediaCodec e AudioTrack para criar uma solução mundial para Android TV. A interface do sintonizador suporta TV digital e TV analógica com base nos principais padrões de transmissão.

Componentes

Para o Android 11, três componentes são projetados especificamente para a plataforma de TV.

  • Tuner HAL: Uma interface entre o framework e os fornecedores
  • API do SDK do Tuner: uma interface entre a estrutura e os aplicativos
  • Tuner Resource Manager (TRM): coordena os recursos do Tuner HW

Para o Android 11, os componentes a seguir foram aprimorados.

  • CAS V2
  • TvInputService ou serviço de entrada de TV (TIS)
  • TvInputManagerService ou TV Input Manager Service (TIMS)
  • MediaCodec ou codec de mídia
  • AudioTrack ou faixa de áudio
  • MediaResourceManager ou gerenciador de recursos de mídia (MRM)

Diagrama de fluxo dos componentes da estrutura do Tuner.

Figura 1. Interações entre os componentes do Android TV

Características

Frontend suporta os padrões DTV abaixo.

  • ATSC
  • ATSC3
  • DVB C/S/T
  • ISDB S/S3/T
  • Analógico

O frontend no Android 12 com Tuner HAL 1.1 ou superior é compatível com o padrão DTV abaixo.

  • DTMB

O Demux suporta os protocolos de stream abaixo.

  • Fluxo de transporte (TS)
  • Protocolo de transporte de mídia MPEG (MMTP)
  • Protocolo de Internet (IP)
  • Valor do comprimento do tipo (TLV)
  • Protocolo de camada de link ATSC (ALP)

O Descrambler suporta as proteções de conteúdo abaixo.

  • Caminho de mídia seguro
  • Limpar caminho de mídia
  • Registro local seguro
  • Reprodução local segura

As APIs do Tuner são compatíveis com os casos de uso abaixo.

  • Varredura
  • Viver
  • Reprodução
  • Registro

Tuner, MediaCodec e AudioTrack suportam os modos de fluxo de dados abaixo.

  • Carga útil ES com buffer de memória limpo
  • Carga útil ES com alça de memória segura
  • Atravessar

Design geral

O Tuner HAL é definido entre a estrutura do Android e o hardware do fornecedor.

  • Descreve o que a estrutura espera do fornecedor e como o fornecedor pode fazer isso.
  • Exporta as funcionalidades de frontend, demux e descrambler para a estrutura por meio das IFrontend , IDemux , IDescrambler , IFilter , IDvr e ILnb .
  • Inclui as funções para integrar o Tuner HAL com outros componentes do framework, como MediaCodec e AudioTrack .

Uma classe Tuner Java e uma classe nativa são criadas.

  • A API Tuner Java permite que aplicativos acessem o Tuner HAL por meio de APIs públicas.
  • A classe nativa permite o controle de permissão e manuseio de grandes quantidades de dados de gravação ou reprodução com o Tuner HAL.
  • O módulo Native Tuner é uma ponte entre a classe Tuner Java e o Tuner HAL.

Uma classe TRM é criada.

  • Gerencia recursos limitados do Tuner, como Frontend, LNB, sessões CAS e um dispositivo de entrada de TV a partir do HAL de entrada de TV.
  • Aplica regras para recuperar recursos insuficientes de aplicativos. A regra padrão é a vitória em primeiro plano.

O Media CAS e o CAS HAL são aprimorados com os recursos abaixo.

  • Abre sessões CAS para diferentes usos e algoritmos.
  • Suporta sistemas CAS dinâmicos, como remoção e inserção CICAM.
  • Integra-se ao Tuner HAL fornecendo tokens de chave.

MediaCodec e AudioTrack são aprimorados com os recursos abaixo.

  • Aceita memória A/V segura como entrada de conteúdo.
  • Configurado para fazer sincronização A/V de hardware na reprodução em túnel.
  • Suporte configurado para ES_payload e modo de passagem.

Design geral do Tuner HAL.

Figura 2. Diagrama dos componentes dentro do Tuner HAL

Fluxo de trabalho geral

Os diagramas abaixo ilustram as sequências de chamadas para reprodução de transmissão ao vivo.

Configurar

Sequência de configuração do diagrama de reprodução de transmissão ao vivo.

Figura 3. Sequência de configuração para reprodução de transmissão ao vivo

Manipulação de A/V

Manipulação de A/V para diagrama de reprodução de transmissão ao vivo.

Figura 4. Manipulação de A/V para reprodução de transmissão ao vivo

Manipulação de conteúdo embaralhado

Manipulação de conteúdo codificado para diagrama de reprodução de transmissão ao vivo.

Figura 5. Manipulação de conteúdo codificado para reprodução de transmissão ao vivo

Processando dados A/V

Processe dados A/V para diagrama de reprodução de transmissão ao vivo.

Figura 6. Processamento de A/V para reprodução de transmissão ao vivo

API do SDK do Tuner

A API do SDK do Tuner lida com as interações com o Tuner JNI, o Tuner HAL e TunerResourceManager . O aplicativo TIS usa a API Tuner SDK para acessar recursos e subcomponentes do Tuner, como o filtro e o decodificador. Frontend e demux são componentes internos.

Diagrama de fluxo da API Tuner SDK.

Figura 7. Interações com a API Tuner SDK

Versões

A partir do Android 12, a API do SDK do Tuner oferece suporte ao novo recurso do Tuner HAL 1.1, que é uma atualização de versão compatível com versões anteriores do Tuner 1.0.

Use a seguinte API para verificar a versão HAL em execução.

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

A versão HAL mínima exigida pode ser encontrada na documentação das novas APIs do Android 12.

Pacotes

A API Tuner SDK fornece os quatro pacotes abaixo.

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

Diagrama de fluxo dos pacotes da API Tuner SDK.

Figura 8. Pacotes de API do Tuner SDK

Android.media.tv.tuner

O pacote Tuner é um ponto de entrada para usar a estrutura Tuner. O aplicativo TIS usa o pacote para inicializar e adquirir instâncias de recursos especificando a configuração inicial e o retorno de chamada.

  • tuner() : Inicializa uma instância do Tuner especificando os parâmetros useCase e sessionId .
  • tune() : Adquire um recurso de frontend e ajusta especificando o parâmetro FrontendSetting .
  • openFilter() : Adquire uma instância de filtro especificando o tipo de filtro.
  • openDvrRecorder() : Adquire uma instância de gravação especificando o tamanho do buffer.
  • openDvrPlayback() : Adquire uma instância de reprodução especificando o tamanho do buffer.
  • openDescrambler() : Adquire uma instância descrambler.
  • openLnb() : Adquire uma instância interna do LNB.
  • openLnbByName() : Adquire uma instância LNB externa.
  • openTimeFilter() : Adquire uma instância de filtro de tempo.

O pacote Tuner fornece funcionalidades que não são cobertas pelos pacotes de filtro, DVR e front-end. As funcionalidades estão listadas abaixo.

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

Android.media.tv.tuner.frontend

O pacote frontend inclui coleções de configurações, informações, status, eventos e recursos relacionados ao frontend.

Aulas

FrontendSettings é derivado para diferentes padrões de DTV pelas classes abaixo.

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

A partir do Android 12 com Tuner HAL 1.1 ou superior, o padrão DTV a seguir é compatível.

  • DtmbFrontendSettings

FrontendCapabilities é derivado para diferentes padrões de DTV pelas classes abaixo.

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

A partir do Android 12 com Tuner HAL 1.1 ou superior, o padrão DTV a seguir é compatível.

  • DtmbFrontendCapabilities

FrontendInfo recupera as informações do frontend. FrontendStatus recupera o status atual do frontend. OnTuneEventListener escuta os eventos no frontend. O aplicativo TIS usa ScanCallback para processar mensagens de verificação do frontend.

Varredura de canal

Para configurar uma TV, o aplicativo verifica as frequências possíveis e cria uma linha de canais para os usuários acessarem. O TIS pode usar Tuner.tune , Tuner.scan(BLIND_SCAN) ou Tuner.scan(AUTO_SCAN) para concluir a varredura de canal.

Se o TIS tiver informações de entrega precisas para o sinal, como frequência, padrão (por exemplo, T/T2, S/S2) e informações adicionais necessárias (por exemplo, PLD ID), então Tuner.tune é recomendado como a opção mais rápida .

Quando o usuário chama Tuner.tune , as seguintes ações acontecem:

  • O TIS preenche FrontendSettings com as informações necessárias usando Tuner.tune .
  • O HAL reporta mensagens de sintonia LOCKED se o sinal estiver bloqueado.
  • TIS usa Frontend.getStatus para coletar as informações necessárias.
  • O TIS move-se para a próxima frequência disponível em sua lista de frequências.

O TIS chama Tuner.tune novamente até que todas as frequências se esgotem.

Durante o ajuste, você pode chamar stopTune() ou close() para pausar ou encerrar a chamada Tuner.tune .

Tuner.scan(AUTO_SCAN)

Se o TIS não tiver informações suficientes para usar Tuner.tune , mas tiver uma lista de frequências e um tipo padrão (por exemplo, DVB T/C/S), então Tuner.scan(AUTO_SCAN) é recomendado.

Quando o usuário chama Tuner.scan(AUTO_SCAN) , as seguintes ações acontecem:

  • TIS usa Tuner.scan(AUTO_SCAN) com FrontendSettings preenchido com frequência.

  • Os relatórios HAL verificam mensagens LOCKED se o sinal estiver bloqueado. O HAL também pode relatar outras mensagens de varredura para fornecer informações adicionais sobre o sinal.

  • TIS usa Frontend.getStatus para coletar as informações necessárias.

  • O TIS chama Tuner.scan para que o HAL continue para a próxima configuração na mesma frequência. Se a estrutura FrontendSettings estiver vazia, o HAL usará a próxima configuração disponível. Caso contrário, o HAL usa FrontendSettings para uma verificação única e envia END para indicar que a operação de verificação foi concluída.

  • O TIS repete as ações acima até que todas as configurações da frequência sejam esgotadas.

  • O HAL envia END para indicar que a operação de varredura foi concluída.

  • O TIS move-se para a próxima frequência disponível em sua lista de frequências.

O TIS chama Tuner.scan(AUTO_SCAN) novamente até que todas as frequências se esgotem.

Durante a varredura, você pode chamar stopScan() ou close() para pausar ou encerrar a varredura.

Tuner.scan(BLIND_SCAN)

Se o TIS não tiver uma lista de frequência e o fornecedor HAL puder pesquisar a frequência do frontend especificado pelo usuário para obter o recurso de frontend, então Tuner.scan(BLIND_SCAN) é recomendado.

  • TIS usa Tuner.scan(BLIND_SCAN) . Uma frequência pode ser especificada em FrontendSettings para frequência inicial, mas o TIS ignora outras configurações em FrontendSettings .
  • O HAL relata uma mensagem de varredura LOCKED se o sinal estiver bloqueado.
  • TIS usa Frontend.getStatus para coletar as informações necessárias.
  • O TIS chama Tuner.scan novamente para continuar a varredura. ( FrontendSettings é ignorado.)
  • O TIS repete as ações acima até que todas as configurações da frequência sejam esgotadas. O HAL aumenta a frequência sem necessidade de ação do TIS. O HAL relata PROGRESS .

O TIS chama Tuner.scan(AUTO_SCAN) novamente até que todas as frequências se esgotem. O HAL informa END para indicar que a operação de varredura foi concluída.

Durante a varredura, você pode chamar stopScan() ou close() para pausar ou encerrar a varredura.

Diagrama de fluxo do processo TIS Scan.

Figura 9. Diagrama de fluxo de uma varredura TIS

Android.media.tv.tuner.filter

O pacote de filtro é uma coleção de operações de filtro junto com configuração, configurações, retornos de chamada e eventos. O pacote inclui as operações abaixo. Consulte o código-fonte do Android para obter a lista completa de operações.

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

Consulte o código-fonte do Android para obter a lista completa.

FilterConfiguration é derivado das classes abaixo. As configurações são para o tipo de filtro principal e especificam qual protocolo o filtro usa para extrair dados.

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

As configurações são derivadas das classes abaixo. As configurações são para o subtipo de filtro e especificam quais tipos de dados o filtro pode excluir.

  • SectionSettings
  • AvSettings
  • PesSettings
  • RecordSettings
  • DownloadSettings

FilterEvent é derivado das classes abaixo para relatar eventos para diferentes tipos de dados.

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

A partir do Android 12 com Tuner HAL 1.1 ou superior, os eventos a seguir são compatíveis.

  • IpCidChangeEvent
  • RestartEvent
  • ScramblingStatusEvent
Eventos e formato de dados do filtro
Tipo de filtro Bandeiras Eventos Operação de dados Formato de dados
TS.SECTION
MMTP.SECTION
IP.SECTION
TLV.SECTION
ALP.SECTION
isRaw:
true
Obrigatoriedade:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recomendado:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
De acordo com o evento e programação interna, corra
Filter.read(buffer, offset, adjustedSize) uma ou mais vezes.

Os dados são copiados do MQ do HAL para o buffer do cliente.
Um pacote de sessão montado é preenchido no FMQ por outro pacote de sessão.
isRaw:
false
Obrigatoriedade:
DemuxFilterEvent::DemuxFilterSectionEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

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


Os dados são copiados do MQ do HAL para o buffer do cliente.
TS.PES isRaw:
true
Obrigatoriedade:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recomendado:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
De acordo com o evento e programação interna, corra
Filter.read(buffer, offset, adjustedSize) uma ou mais vezes.

Os dados são copiados do MQ do HAL para o buffer do cliente.
Um pacote PES montado é preenchido no FMQ por outro pacote PES.
isRaw:
false
Obrigatoriedade:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

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


Os dados são copiados do MQ do HAL para o buffer do cliente.
MMTP.PES isRaw:
true
Obrigatoriedade:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recomendado:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
De acordo com o evento e programação interna, corra
Filter.read(buffer, offset, adjustedSize) uma ou mais vezes.

Os dados são copiados do MQ do HAL para o buffer do cliente.
Um pacote MFU montado é preenchido no FMQ por outro pacote MFU.
isRaw:
false
Obrigatoriedade:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

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


Os dados são copiados do MQ do HAL para o buffer do cliente.
TS.TS
N / D Obrigatoriedade:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recomendado:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
De acordo com o evento e programação interna, corra
Filter.read(buffer, offset, adjustedSize) uma ou mais vezes.

Os dados são copiados do MQ do HAL para o buffer do cliente.
Filtrado ts com cabeçalho ts
é preenchido em FMQ.
TS.Audio
TS.Video
MMTP.Audio
MMTP.Video
isPassthrough:
true
Opcional:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
O cliente pode iniciar o MediaCodec após receber DemuxFilterStatus::DATA_READY .
O cliente pode chamar Filter.flush após receber DemuxFilterStatus::DATA_OVERFLOW .
N / D
isPassthrough:
false
Obrigatoriedade:
DemuxFilterEvent::DemuxFilterMediaEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

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


Para usar o áudio direto do AudioTrack :
for i=0; i<n; i++
audioHandle = MediaEvent[i].getAudioHandle();
audiotrack.write(encapsulated(audiohandle))
Dados ES ou ES parciais na memória ION.
TS.PCR
IP.NTP
ALP.PTP
N / D Obrigatório: N/A
Opcional: N/A
N / D N / D
TS.RECORD N / D Obrigatoriedade:
DemuxFilterEvent::DemuxFilterTsRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Opcional:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Para dados de índice:
for i=0; i<n; i++
DemuxFilterTsRecordEvent[i];


Para conteúdo gravado , de acordo com RecordStatus::* e programação interna, siga um destes procedimentos:
  • Execute DvrRecord.write(adustedSize) uma ou mais vezes para armazenamento.
    Os dados são transferidos do MQ do HAL para o armazenamento.
  • Execute DvrRecord.write(buffer, adustedSize) uma ou mais vezes para armazenar em buffer.
    Os dados são copiados do MQ do HAL para o buffer do cliente.
Para dados de índice: transportado na carga útil do evento.

Para conteúdo gravado: fluxo TS misturado preenchido em FMQ.
TS.TEMI N / D Obrigatoriedade:
DemuxFilterEvent::DemuxFilterTemiEvent[n]

Opcional:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
DemuxFilterTemiEvent[i];
N / D
MMTP.MMTP N / D Obrigatoriedade:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recomendado:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
De acordo com o evento e programação interna, corra
Filter.read(buffer, offset, adjustedSize) uma ou mais vezes.

Os dados são copiados do MQ do HAL para o buffer do cliente.
Mtp mmtp com cabeçalho mmtp
é preenchido em FMQ.
MMTP.RECORD N / D Obrigatoriedade:
DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

Opcional:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
Para dados de índice: for i=0; i<n; i++
DemuxFilterMmtpRecordEvent[i];


Para conteúdo gravado , de acordo com RecordStatus::* e programação interna, siga um destes procedimentos:
  • Execute DvrRecord.write(adjustedSize) uma ou mais vezes para armazenamento.
    Os dados são transferidos do MQ do HAL para o armazenamento.
  • Execute DvrRecord.write(buffer, adjustedSize) uma ou mais vezes para armazenar em buffer.
    Os dados são copiados do MQ do HAL para o buffer do cliente.
Para dados de índice: transportado na carga útil do evento.

Para conteúdo gravado: fluxo gravado mixado preenchido em FMQ.

Se a origem do filtro para gravação for TLV.TLV para IP.IP com passagem, o fluxo gravado terá um cabeçalho TLV e IP.
MMTP.DOWNLOAD N / D Obrigatoriedade:
DemuxFilterEvent::DemuxFilterDownloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

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

Os dados são copiados do MQ do HAL para o buffer do cliente.
O pacote de download é preenchido no FMQ por outro pacote de download de IP.
IP.IP_PAYLOAD N / D Obrigatoriedade:
DemuxFilterEvent::DemuxFilterIpPayloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

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

Os dados são copiados do MQ do HAL para o buffer do cliente.
O pacote de carga útil IP é preenchido no FMQ por outro pacote de carga útil IP.
IP.IP
TLV.TLV
ALP.ALP
isPassthrough:
true
Opcional:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
O subfluxo de protocolo filtrado alimenta o próximo filtro na cadeia de filtros. N / D
isPassthrough:
false
Obrigatoriedade:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

Recomendado:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
De acordo com o evento e programação interna, corra
Filter.read(buffer, offset, adjustedSize) uma ou mais vezes.

Os dados são copiados do MQ do HAL para o buffer do cliente.
O subfluxo de protocolo filtrado com cabeçalho de protocolo é preenchido em FMQ.
IP.PAYLOAD_THROUGH
TLV.PAYLOAD_THROUGH
ALP.PAYLOAD_THROUGH
N / D Opcional:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
A carga útil do protocolo filtrada alimenta o próximo filtro na cadeia de filtros. N / D
Fluxo de exemplo para usar filtro para construir PSI/SI

Fluxo de exemplo para usar filtro para construir PSI/SI.

Figura 10. Fluxo para construir PSI/SI

  1. Abra um filtro.

    Filter filter = tuner.openFilter(
      Filter.TYPE_TS,
      Filter.SUBTYPE_SECTION,
      /* bufferSize */1000,
      executor,
      filterCallback
    );
    
  2. Configure e inicie o filtro.

    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. Processo 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); }
          }
        }
    };
    
Fluxo de exemplo para usar MediaEvent do filtro

Fluxo de exemplo para usar MediaEvent do filtro.

Figura 11. Fluxo para usar MediaEvent do filtro

  1. Abra, configure e inicie os filtros A/V.
  2. Processar MediaEvent .
  3. Receba MediaEvent .
  4. Enfileirar o bloco linear para codec .
  5. Solte o identificador A/V quando os dados tiverem sido consumidos.

Android.media.tv.tuner.dvr

DvrRecorder fornece esses métodos para gravação.

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

DvrPlayback fornece esses métodos para reprodução.

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

DvrSettings é usado para configurar DvrRecorder e DvrPlayback . OnPlaybackStatusChangedListener e OnRecordStatusChangedListener são usados ​​para relatar o status de uma instância de DVR.

Fluxo de exemplo para iniciar um registro

Fluxo de exemplo para iniciar um registro.

Figura 12. Fluxo para iniciar um registro

  1. Abra, configure e inicie 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. Receba RecordEvent e recupere as informações de índice.

    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. Inicialize OnRecordStatusChangedListener e armazene os dados do registro.

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

Sintonizador HAL

O Tuner HAL segue o HIDL e define a interface entre o framework e o hardware do fornecedor. Os fornecedores usam a interface para implementar o Tuner HAL e a estrutura a usa para se comunicar com a implementação do Tuner HAL.

Módulos

Sintonizador HAL 1.0

Módulos Controles básicos Controles específicos do módulo Arquivos HAL
ITuner N / D 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 (derivado do Tuner HAL 1.0)

Módulos Controles básicos Controles específicos do módulo Arquivos HAL
ITuner N / D 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

Diagrama de fluxo de interações entre os módulos do Tuner HAL.

Figura 13. Diagrama das interações entre os módulos Tuner HAL

Filtrar vinculação

O Tuner HAL suporta a vinculação de filtros de forma que os filtros possam ser vinculados a outros filtros para várias camadas. Os filtros seguem as regras abaixo.

  • Os filtros são vinculados como uma árvore, o caminho fechado não é permitido.
  • O nó raiz é demux.
  • Os filtros operam de forma independente.
  • Todos os filtros começam a obter dados.
  • A ligação do filtro é lavada no último filtro.

O bloco de código abaixo e a Figura 14 ilustram um exemplo de filtragem de várias camadas.

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

Diagrama de exemplo de ligação de filtro.

Figura 14. Diagrama de fluxo de uma ligação de filtro para várias camadas

Gerenciador de recursos do sintonizador

Antes do Tuner Resource Manager (TRM), alternar entre dois aplicativos exigia o mesmo hardware Tuner. O TV Input Framework (TIF) usou um mecanismo "primeiro a adquirir", o que significa que o aplicativo que obtém o recurso primeiro mantém o recurso. No entanto, esse mecanismo pode não ser ideal para alguns casos de uso complicados.

O TRM é executado como um serviço do sistema para gerenciar os recursos de hardware Tuner, TVInput e CAS para aplicativos. O TRM usa um mecanismo de "ganho em primeiro plano", que calcula a prioridade do aplicativo com base no status em primeiro plano ou em segundo plano e no tipo de caso de uso. O TRM concede ou revoga o recurso com base na prioridade. O TRM centraliza o gerenciamento de recursos ATV para transmissão, OTT e DVR.

Interface TRM

TRM expõe interfaces AIDL em ITunerResourceManager.aidl para a estrutura Tuner, MediaCas e TvInputHardwareManager para registrar, solicitar ou liberar recursos.

As interfaces para gerenciamento de clientes estão listadas abaixo.

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

As interfaces para solicitar e liberar recursos estão listadas abaixo.

  • 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

As classes de cliente e solicitação estão listadas abaixo.

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

Prioridade do cliente

O TRM calcula a prioridade do cliente usando parâmetros do perfil do cliente e o valor de prioridade do arquivo de configuração. A prioridade também pode ser atualizada por um valor de prioridade arbitrário do cliente.

Parâmetros no perfil do cliente

O TRM recupera o ID do processo de mTvInputSessionId para decidir se um aplicativo é um aplicativo em primeiro ou segundo plano. Para criar mTvInputSessionId , TvInputService.onCreateSession ou TvInputService.onCreateRecordingSession inicializa uma sessão TIS.

mUseCase indica o caso de uso da sessão. Os casos de uso predefinidos estão listados abaixo.

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
}

Arquivo de configuração

Arquivo de configuração padrão

O arquivo de configuração padrão abaixo fornece valores de prioridade para casos de uso predefinidos. Os usuários podem alterar os valores usando um arquivo de configuração personalizado .

Caso de uso Primeiro plano Fundo
LIVE 490 400
PLAYBACK 480 300
RECORD 600 500
SCAN 450 200
BACKGROUND 180 100
Arquivo de configuração personalizado

Os fornecedores podem personalizar o arquivo de configuração /vendor/etc/tunerResourceManagerUseCaseConfig.xml . Este arquivo é usado para incluir, remover ou atualizar os tipos de caso de uso e os valores de prioridade do caso de uso. O arquivo personalizado pode usar platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml como modelo.

Por exemplo, um novo caso de uso de fornecedor é VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000] . O formato deve seguir platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd .

Valor de prioridade arbitrário e valor agradável

O TRM fornece updateClientPriority para o cliente atualizar o valor de prioridade arbitrário e o valor legal. O valor de prioridade arbitrário substitui o valor de prioridade calculado a partir do tipo de caso de uso e do ID da sessão.

O valor nice indica quão tolerante é o comportamento do cliente quando está em conflito com outro cliente. O valor agradável diminui o valor de prioridade do cliente antes que seu valor de prioridade seja comparado ao cliente desafiador.

Mecanismo de recuperação

O diagrama abaixo mostra como os recursos são recuperados e atribuídos quando ocorre um conflito de recursos.

Diagrama do processo do mecanismo de recuperação.

Figura 15. Diagrama do mecanismo de recuperação de um conflito entre recursos do Tuner