No Android 11 ou versões mais recentes, você pode usar o framework do Android Tuner para fornecer conteúdo A/V. O framework usa o pipeline de hardware dos fornecedores, o que o torna adequado para SoCs de baixo e alto desempenho. O framework oferece uma maneira segura de fornecer conteúdo A/V protegido por um ambiente de execução confiável (TEE) e um 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 de CAS. A interface do sintonizador funciona
com MediaCodec
e AudioTrack
para criar uma solução global para Android TV.
A interface do Tuner oferece suporte à TV digital e analógica com base nos principais
padrões de transmissão.
Componentes
No 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 Tuner SDK:uma interface entre o framework e os apps
- Tuner Resource Manager (TRM): coordena os recursos de sintonizador de hardware.
No Android 11, os seguintes componentes foram aprimorados.
- CAS V2
TvInputService
ou serviço de entrada de TV (TIS)TvInputManagerService
ou o TV Input Manager Service (TIMS)MediaCodec
ou codec de mídiaAudioTrack
ou faixa de áudioMediaResourceManager
ou media resource manager (MRM)
Figura 1. Interações entre componentes do Android TV
Recursos
O front-end é compatível com os padrões DTV abaixo.
- ATSC
- ATSC3
- DVB C/S/T
- ISDB S/S3/T
- Analógico
O front-end no Android 12 com Tuner HAL 1.1 ou mais recente oferece suporte ao padrão DTV abaixo.
- DTMB
O Demux é compatível com os protocolos de stream abaixo.
- Stream de transporte (TS)
- Protocolo de transporte de mídia MPEG (MMTP)
- Protocolo de Internet (IP)
- Valor de tipo e comprimento (TLV, na sigla em inglês)
- Protocolo de camada de link (ALP, na sigla em inglês) ATSC
O decodificador oferece suporte às proteções de conteúdo abaixo.
- Caminho de mídia seguro
- Limpar caminho de mídia
- Proteger registro local
- Reprodução local segura
As APIs Tuner oferecem suporte aos casos de uso abaixo.
- Verificar
- Ao vivo
- Reprodução
- Gravar
O Tuner, MediaCodec
e AudioTrack
são compatíveis com os modos de fluxo de dados abaixo.
- Payload do ES com buffer de memória clara
- Payload ES com gerenciador de memória seguro
- Transparente
Design em geral
A HAL do Tuner é definida entre o framework do Android e o hardware do fornecedor.
- Descreve o que o framework espera do fornecedor e como ele pode fazer isso.
- Exporta as funcionalidades do front-end, demux e descrambler para o
framework usando as interfaces
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
eILnb
. - Inclui as funções para integrar o Tuner HAL a outros componentes
do framework, como
MediaCodec
eAudioTrack
.
Uma classe Java e uma classe nativa do Tuner são criadas.
- A API Java Tuner permite que os apps acessem o Tuner HAL por meio de APIs públicas.
- A classe nativa permite o controle de permissões e o processamento de grandes quantidades de dados de gravação ou reprodução com a HAL Tuner.
- O módulo de sintonizador nativo é uma ponte entre a classe Java do sintonizador e o HAL do sintonizador.
Uma classe TRM é criada.
- Gerencia recursos limitados do sintonizador, como front-end, LNB, sessões CAS e um dispositivo de entrada de TV do HAL de entrada de TV.
- Aplica regras para recuperar recursos insuficientes de apps. A regra padrão é a vitória em primeiro plano.
O CAS de mídia e o HAL de CAS foram aprimorados com os recursos abaixo.
- Abre sessões do CAS para diferentes usos e algoritmos.
- Suporte a sistemas CAS dinâmicos, como a remoção e inserção de CICAM.
- Integra-se com a HAL de sintonizador fornecendo tokens de chave.
MediaCodec
e AudioTrack
foram aprimorados com os recursos abaixo.
- Usa a memória A/V segura como entrada de conteúdo.
- Configurado para fazer a sincronização A/V de hardware na reprodução em túnel.
- Configuração de suporte para
ES_payload
e modo de passagem.
Figura 2. Diagrama dos componentes no HAL do sintonizador
Fluxo de trabalho geral
Os diagramas abaixo ilustram sequências de chamadas para a reprodução de transmissão ao vivo.
Configurar
Figura 3. Sequência de configurações para reprodução de transmissão ao vivo
Manuseio de A/V
Figura 4. Como processar áudio e vídeo para a reprodução de transmissões ao vivo
Como processar conteúdo embaralhado
Figura 5. Como processar conteúdo embaralhado para reprodução de transmissão ao vivo
Como processar dados A/V
Figura 6. Processamento de áudio e vídeo para reprodução de transmissão ao vivo
API Tuner SDK
A API Tuner SDK processa as interações com o JNI do Tuner, o HAL do Tuner
e o TunerResourceManager
. O app TIS usa a API SDK Tuner para acessar recursos
e subcomponentes do sintonizador, como o filtro e o decodificador. Front-end e demux são componentes internos.
Figura 7. Interações com a API Tuner SDK
Versões
No Android 12 e versões mais recentes, a API Tuner SDK oferece suporte ao novo recurso do Tuner HAL 1.1, que é um upgrade do Tuner 1.0 compatível com versões anteriores.
Use a API a seguir para verificar a versão da HAL em execução.
android.media.tv.tuner.TunerVersionChecker.getTunerVersion()
A versão mínima necessária do HAL pode ser encontrada na documentação das novas APIs do Android 12.
Pacotes
A API Tuner SDK oferece os quatro pacotes abaixo.
android.media.tv.tuner
android.media.tv.tuner.frontend
android.media.tv.tuner.filter
android.media.tv.tuner.dvr
Figura 8. Pacotes da API Tuner SDK
Android.media.tv.tuner
O pacote Tuner é um ponto de entrada para usar o framework Tuner. O app TIS usa o pacote para inicializar e adquirir instâncias de recursos especificando a configuração inicial e o callback.
tuner()
: inicializa uma instância do sintonizador especificando os parâmetrosuseCase
esessionId
.tune()
: adquire um recurso de front-end e faz ajustes especificando o parâmetroFrontendSetting
.openFilter()
: recebe 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 de descrambler.openLnb()
: adquire uma instância interna do LNB.openLnbByName()
: adquire uma instância externa de LNB.openTimeFilter()
: adquire uma instância de filtro de tempo.
O pacote Tuner oferece funcionalidades que não estão incluídas nos 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 de front-end inclui coleções de configurações, informações, status, eventos e recursos relacionados ao front-end.
Classes
O FrontendSettings
é derivado para diferentes padrões de DTV pelas classes abaixo.
AnalogFrontendSettings
Atsc3FrontendSettings
AtscFrontendSettings
DvbcFrontendSettings
DvbsFrontendSettings
DvbtFrontendSettings
Isdbs3FrontendSettings
IsdbsFrontendSettings
IsdbtFrontendSettings
No Android 12 com Tuner HAL 1.1 ou mais recente, o seguinte padrão de DTV é aceito.
DtmbFrontendSettings
A FrontendCapabilities
é derivada para diferentes padrões de DTV pelas classes
abaixo.
AnalogFrontendCapabilities
Atsc3FrontendCapabilities
AtscFrontendCapabilities
DvbcFrontendCapabilities
DvbsFrontendCapabilities
DvbtFrontendCapabilities
Isdbs3FrontendCapabilities
IsdbsFrontendCapabilities
IsdbtFrontendCapabilities
No Android 12 com o Tuner HAL 1.1 ou mais recente, o padrão DTV abaixo tem suporte.
DtmbFrontendCapabilities
FrontendInfo
recupera as informações do front-end.
FrontendStatus
recupera o status atual do front-end.
O OnTuneEventListener
detecta os eventos no front-end.
O app TIS usa ScanCallback
para processar mensagens de verificação do front-end.
Busca de canais
Para configurar uma TV, o app verifica as frequências possíveis e cria uma programação
de canais para que os usuários acessem. O TIS pode usar Tuner.tune
, Tuner.scan(BLIND_SCAN)
ou Tuner.scan(AUTO_SCAN)
para concluir a verificação de canais.
Se o TIS tiver informações de entrega precisas para o sinal, como frequência,
padrão (por exemplo, T/T2, S/S2) e outras informações necessárias
(por exemplo, ID do PLD), 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 usandoTuner.tune
. - O HAL informa mensagens
LOCKED
de ajuste se o sinal estiver bloqueado. - O TIS usa
Frontend.getStatus
para coletar as informações necessárias. - O TIS passa para a próxima frequência disponível na lista de frequência.
O TIS chama Tuner.tune
de novo até que todas as frequências sejam esgotadas.
Durante o ajuste, é possível 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),
recomendamos o uso de Tuner.scan(AUTO_SCAN)
.
Quando o usuário chama Tuner.scan(AUTO_SCAN)
, as seguintes ações acontecem:
O TIS usa
Tuner.scan(AUTO_SCAN)
comFrontendSettings
preenchidos com frequência.O HAL informa a detecção de mensagens
LOCKED
se o sinal estiver bloqueado. O HAL também pode relatar outras mensagens de verificação para fornecer mais informações sobre o sinal.O 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 estruturaFrontendSettings
estiver vazia, a HAL usará a próxima configuração disponível. Caso contrário, o HAL usaFrontendSettings
para uma verificação única e enviaEND
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.
A HAL envia
END
para indicar que a operação de verificação foi concluída.O TIS passa para a próxima frequência disponível na lista de frequência.
O TIS chama Tuner.scan(AUTO_SCAN)
novamente até que todas as frequências sejam esgotadas.
Durante a verificação, é possível chamar stopScan()
ou close()
para pausar ou finalizar a
verificação.
Tuner.scan(BLIND_SCAN)
Se o TIS não tiver uma lista de frequência e a HAL do fornecedor puder pesquisar
a frequência do front-end especificado pelo usuário para receber o recurso de front-end, recomendamos Tuner.scan(BLIND_SCAN)
.
- O TIS usa
Tuner.scan(BLIND_SCAN)
. Uma frequência pode ser especificada emFrontendSettings
para a frequência de início, mas o TIS ignora outras configurações emFrontendSettings
. - O HAL informa uma mensagem de verificação
LOCKED
se o sinal estiver bloqueado. - O TIS usa
Frontend.getStatus
para coletar as informações necessárias. - O TIS chama
Tuner.scan
novamente para continuar a verificação.FrontendSettings
é ignorado. - O TIS repete as ações acima até que todas as configurações da frequência sejam
esgotadas. A HAL incrementa a frequência sem necessidade de ação da TIS.
A HAL informa
PROGRESS
.
O TIS chama Tuner.scan(AUTO_SCAN)
de novo até que todas as frequências sejam esgotadas.
O HAL informa END
para indicar que a operação de verificação foi concluída.
Durante a leitura, é possível chamar stopScan()
ou close()
para pausar ou finalizar a verificação.
Figura 9. Diagrama de fluxo de uma verificação de TIS
Android.media.tv.tuner.filter
O pacote de filtro é uma coleção de operações de filtro, além de configuração, configurações, callbacks e eventos. O pacote inclui as operações abaixo. Consulte o código-fonte do Android para conferir a lista completa de operações.
configure()
start()
stop()
flush()
read()
Consulte o código-fonte do Android para conferir 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 que tipos de dados o filtro pode excluir.
SectionSettings
AvSettings
PesSettings
RecordSettings
DownloadSettings
O FilterEvent
é derivado das classes abaixo para relatar eventos para diferentes
tipos de dados.
SectionEvent
MediaEvent
PesEvent
TsRecordEvent
MmtpRecordEvent
TemiEvent
DownloadEvent
IpPayloadEvent
No Android 12 com o Tuner HAL 1.1 ou mais recente, os eventos abaixo têm suporte.
IpCidChangeEvent
RestartEvent
ScramblingStatusEvent
Eventos e formato de dados do filtro
Tipo de filtro | Flags | Eventos | Operação de dados | Formato de dados |
---|---|---|---|---|
TS.SECTION MMTP.SECTION IP.SECTION TLV.SECTION ALP.SECTION |
isRaw: |
Obrigatório:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
De acordo com o evento e a programação interna, executeFilter.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: |
Obrigatório:DemuxFilterEvent::DemuxFilterSectionEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcional: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ Os dados são copiados do MQ do HAL para o buffer do cliente. |
||
TS.PES |
isRaw: |
Obrigatório:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
De acordo com o evento e a programação interna, executeFilter.read(buffer, offset, adjustedSize) uma ou mais
vezes.Os dados são copiados do MQ da HAL para o buffer do cliente. |
Um pacote PES montado é preenchido na FMQ por outro pacote PES. |
isRaw: |
Obrigatório:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcional: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ Os dados são copiados do MQ do HAL para o buffer do cliente. |
||
MMTP.PES |
isRaw: |
Obrigatório:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
De acordo com o evento e a programação interna, executeFilter.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 em FMQ por outro pacote MFU. |
isRaw: |
Obrigatório:DemuxFilterEvent::DemuxFilterPesEvent[n] DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Opcional: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ Os dados são copiados do MQ da HAL para o buffer do cliente. |
||
TS.TS |
N/A | Obrigatório:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
De acordo com o evento e a programação interna, executeFilter.read(buffer, offset, adjustedSize) uma ou mais
vezes.Os dados são copiados do MQ do HAL para o buffer do cliente. |
ts filtrado com cabeçalho ts é preenchido no FMQ. |
TS.Audio TS.Video MMTP.Audio MMTP.Video |
isPassthrough: |
Opcional:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
O cliente pode iniciar MediaCodec depois de receber DemuxFilterStatus::DATA_READY .O cliente pode chamar Filter.flush depois de receber DemuxFilterStatus::DATA_OVERFLOW . |
N/A |
isPassthrough: |
Obrigatório: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++ Para usar o áudio direto de AudioTrack :for i=0; i<n; i++ |
Dados de ES ou ES parcial na memória ION. | |
TS.PCR IP.NTP ALP.PTP |
N/A | Obrigatório: N/A
Opcional: N/A |
N/A | N/A |
TS.RECORD |
N/A | Obrigatório: 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++ Para conteúdo gravado, de acordo com RecordStatus::* e a programação interna, siga
um destes procedimentos:
|
Para dados de índice: transportados no payload do evento. Para conteúdo gravado: o fluxo TS mixado foi preenchido na FMQ. |
TS.TEMI |
N/A | Obrigatório:DemuxFilterEvent::DemuxFilterTemiEvent[n] Opcional: DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ |
N/A |
MMTP.MMTP |
N/A | Obrigatório:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
De acordo com o evento e a programação interna, executeFilter.read(buffer, offset, adjustedSize) uma ou mais
vezes.Os dados são copiados do MQ da HAL para o buffer do cliente. |
O mmtp filtrado com cabeçalho mmtp é preenchido no FMQ. |
MMTP.RECORD |
N/A | Obrigatório: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++ Para conteúdo gravado, de acordo com RecordStatus::* e a programação interna, faça uma das
seguintes ações:
|
Para dados de índice: são transportados no payload do evento. Para conteúdo gravado: stream gravado com multiplexação preenchida em FMQ. Se a origem do filtro para gravação for TLV.TLV para
IP.IP com passagem, o fluxo gravado terá um
TLV e um cabeçalho IP. |
MMTP.DOWNLOAD |
N/A | Obrigatório: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/A | Obrigatório: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 da HAL para o buffer do cliente. |
O pacote de payload IP é preenchido no FMQ por outro pacote de payload IP. |
IP.IP TLV.TLV ALP.ALP |
isPassthrough: |
Opcional:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
A subfluxo de protocolo filtrado alimenta o próximo filtro na cadeia de filtros. | N/A |
isPassthrough: |
Obrigatório:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
De acordo com o evento e a programação interna, executeFilter.read(buffer, offset, adjustedSize) uma ou mais
vezes.Os dados são copiados do MQ da HAL para o buffer do cliente. |
O subfluxo do protocolo filtrado com o cabeçalho do protocolo é preenchido em FMQ. | |
IP.PAYLOAD_THROUGH TLV.PAYLOAD_THROUGH ALP.PAYLOAD_THROUGH |
N/A | Opcional:DemuxFilterStatus::DATA_READY DemuxFilterStatus::DATA_OVERFLOW |
O payload do protocolo filtrado alimenta o próximo filtro na cadeia de filtros. | N/A |
Exemplo de fluxo para usar o filtro para criar PSI/SI
Figura 10. Fluxo para criar PSI/SI
Abra um filtro.
Filter filter = tuner.openFilter( Filter.TYPE_TS, Filter.SUBTYPE_SECTION, /* bufferSize */1000, executor, filterCallback );
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();
Processe
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); } } } };
Exemplo de fluxo para usar MediaEvent do filtro
Figura 11. Fluxo para usar o MediaEvent do filtro
- Abra, configure e inicie os filtros de áudio/vídeo.
- Processar
MediaEvent
. - Receba
MediaEvent
. - Coloque o bloco linear na fila para
codec
. - Libere o identificador A/V quando os dados forem consumidos.
Android.media.tv.tuner.dvr
DvrRecorder
fornece estes métodos para gravação.
configure
attachFilter
detachFilter
start
flush
stop
setFileDescriptor
write
A DvrPlayback
oferece 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 informar o status de uma instância de DVR.
Exemplo de fluxo para iniciar uma gravação
Figura 12. Fluxo para iniciar um registro
Abra, configure e inicie o
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();
Receba
RecordEvent
e extraia as informações do í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. } } } };
Inicialize
OnRecordStatusChangedListener
e armazene os dados de 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); } } };
HAL do sintonizador
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 HAL do sintonizador, e o framework a usa para se comunicar com a implementação do HAL do sintonizador.
Módulos
Tuner HAL 1.0
Módulos | Controles básicos | Controles específicos do módulo | Arquivos 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 e 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/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 |
Figura 13. Diagrama das interações entre os módulos HAL do sintonizador
Vinculação do filtro
A HAL Tuner oferece suporte à vinculação de filtros, de modo 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. Não é permitido fechar caminhos.
- O nó raiz é demux.
- Os filtros funcionam de forma independente.
- Todos os filtros começam a receber dados.
- A vinculação do filtro é eliminada 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>)
}
Figura 14. Diagrama de fluxo de uma vinculação de filtros para várias camadas
Tuner Resource Manager
Antes do Tuner Resource Manager (TRM), a alternância entre dois apps exigia o mesmo hardware do sintonizador. O TV Input Framework (TIF) usava um mecanismo de "primeiro a adquirir", o que significa que o app que recebe o recurso primeiro o mantém. 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 do Tuner, TVInput
e
CAS para apps. O TRM usa um mecanismo de "vitória em primeiro plano", que
calcula a prioridade do app com base no status em primeiro ou segundo plano
e no tipo de caso de uso do app. O TRM concede ou revoga o recurso com base na prioridade. O TRM centraliza o gerenciamento de recursos do ATV para transmissão, OTT
e DVR.
Interface do TRM
O TRM expõe interfaces AIDL em ITunerResourceManager.aidl
para que o framework
tuner, MediaCas
e TvInputHardwareManager
registrem, solicitem ou
liberem 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 app
está em primeiro ou segundo plano. Para criar mTvInputSessionId
,
TvInputService.onCreateSession
ou TvInputService.onCreateRecordingSession
, inicializa uma sessão de TIS.
mUseCase
indica o caso de uso da sessão. Confira abaixo os casos de uso predefinidos.
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 mudar os valores usando um arquivo de configuração personalizado.
Caso de uso | Primeiro plano | Contexto |
---|---|---|
LIVE |
490 | 400 |
PLAYBACK |
sobreposição ou | 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
. Esse arquivo é usado para adicionar, 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 do fornecedor é VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000]
.
O formato precisa 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 que o cliente atualize o valor de prioridade
arbitrário e o valor ideal.
O valor de prioridade arbitrário substitui o valor calculado
com base no tipo de caso de uso e no ID da sessão.
O valor nice indica o quão flexível é o comportamento do cliente quando ele está em conflito com outro cliente. O valor bom diminui o valor de prioridade do cliente antes que ele 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.
Figura 15. Diagrama do mecanismo de recuperação de um conflito entre recursos do Tuner