Para o Android 11 ou versões mais recentes, você pode usar o Android Framework de sintonizador para oferecer conteúdo A/V. O framework usa a arquitetura pipeline de preços de fornecedores, o que o torna adequado para SoC simples e sofisticado. O framework oferece uma maneira segura de fornecer conteúdo A/V protegido por uma o ambiente de execução confiável (TEE) e o caminho de mídia seguro (SMP), o que permite para uso em um ambiente de proteção de conteúdo altamente restrito.
A interface padronizada entre o Tuner e o Android CAS resulta em uma experiência
integração entre fornecedores do Tuner e fornecedores do CAS. A interface do Tuner funciona
com MediaCodec
e AudioTrack
para criar uma solução mundial para o Android TV.
A interface do Tuner é compatível com TV digital e TV analógica com base nas principais
padrões de transmissão.
Componentes
Para o Android 11, três componentes são especificamente projetado 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): recursos de HW do Coordenador do Tuner
Para o Android 11, os seguintes componentes foram aprimorado.
- CAS V2
TvInputService
ou serviço de entrada de TV (TIS, na sigla em inglês)TvInputManagerService
ou o TV Input Manager Service (TIMS)MediaCodec
ou codec de mídiaAudioTrack
ou faixa de áudioMediaResourceManager
ou gerente de recursos de mídia (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 do Android 12 com o 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 comprimento do tipo (TLV)
- protocolo de camada de link (ALP, na sigla em inglês) ATSC
O descrambador é compatível com as 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 do Tuner oferecem suporte aos casos de uso abaixo.
- Verificar
- Ao vivo
- Reprodução
- Gravar
Tuner, MediaCodec
e AudioTrack
oferecem suporte aos modos de fluxo de dados abaixo.
- Payload ES com buffer de memória limpo
- Payload ES com gerenciador de memória seguro
- Transparente
Design em geral
A HAL do Tuner é definida entre o framework do Android e o ao hardware.
- Descreve o que o framework espera do fornecedor e como ele pode fazer isso.
- Exporta as funcionalidades de front-end, demux e descrambler para o
pela
IFrontend
,IDemux
,IDescrambler
,IFilter
,IDvr
e eILnb
. - Inclui as funções para integrar a HAL do Tuner com outro framework
componentes, como
MediaCodec
eAudioTrack
.
Uma classe Java e uma classe nativa do Tuner são criadas.
- A API Tuner Java permite que os apps acessem a HAL do Tuner usando APIs públicas.
- A classe nativa permite o controle de permissões e o tratamento de grandes quantidades de gravação ou reprodução de dados com o Tuner HAL.
- O módulo Native Tuner é uma ponte entre a classe Java Tuner e a classe Tuner HAL
Uma classe TRM é criada.
- Gerencia recursos limitados do Tuner, como front-end, LNB e sessões CAS e um dispositivo de entrada de TV da 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 CAS HAL foram aprimorados com os recursos abaixo.
- Abre sessões do CAS para diferentes usos e algoritmos.
- Dá suporte a sistemas CAS dinâmicos, como remoção e inserção do 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.
- Suporte configurado para
ES_payload
e o modo de passagem.
Figura 2. Diagrama dos componentes na HAL do Tuner
Fluxo de trabalho geral
Os diagramas abaixo ilustram sequências de chamadas para reprodução de transmissão ao vivo.
Configurar
Figura 3. Sequência de configurações para reprodução de transmissão ao vivo
Como gerenciar áudio e vídeo
Figura 4. Como processar A/V para reprodução de transmissão 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. Processando A/V para a transmissão ao vivo
API Tuner SDK
A API Tuner SDK processa as interações com o Tuner JNI, a HAL Tuner,
e TunerResourceManager
. O app TIS usa a API Tuner SDK para acessar o Tuner
recursos e subcomponentes, como filtro e desembaralhador. 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 da versão 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 da 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 Tuner especificando ouseCase
e ParâmetrossessionId
.tune()
: adquire um recurso de front-end e faz o ajuste 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 buffer tamanho.openDvrPlayback()
: adquire uma instância de reprodução especificando o buffer tamanho.openDescrambler()
: adquire uma instância de descrambler.openLnb()
: adquire uma instância interna do LNB.openLnbByName()
: adquire uma instância externa do LNB.openTimeFilter()
: adquire uma instância de filtro de tempo.
O pacote Tuner oferece funcionalidades não cobertas os 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 relacionadas ao front-end, informações, status, eventos e recursos.
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 o Tuner HAL 1.1 ou mais recente, o padrão DTV abaixo tem suporte.
DtmbFrontendSettings
O FrontendCapabilities
é derivado para diferentes padrões DTV pelas classes
a seguir.
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.
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 possíveis frequências e cria um canal
lineup para os usuários acessarem. O TIS pode usar Tuner.tune
,
Tuner.scan(BLIND_SCAN)
ou Tuner.scan(AUTO_SCAN)
para concluir o canal
durante a verificação.
Se o TIS tiver informações de exibição precisas para o indicador, como frequência,
padrão (por exemplo, T/T2, S/S2) e outras informações necessárias
(por exemplo, PLD ID),
Recomendamos Tuner.tune
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
. - Os relatórios da HAL ajustaram as mensagens
LOCKED
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, você pode chamar stopTune()
ou close()
para pausar ou encerrar a
Tuner.tune
.
Tuner.scan(AUTO_SCAN)
Se o TIS não tiver informações suficientes para usar Tuner.tune
, mas tiver uma frequência
lista e tipo padrão (por exemplo, DVB T/C/S),
recomenda-se 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.Os relatórios da HAL verificam mensagens
LOCKED
se o sinal estiver bloqueado. A HAL pode também reporta outras mensagens de verificação para fornecer informações adicionais sobre o sinal.O TIS usa
Frontend.getStatus
para coletar as informações necessárias.O TIS chama
Tuner.scan
para a HAL continuar para a próxima configuração no mesmo frequência. Se a estruturaFrontendSettings
estiver vazia, a HAL usará o próximo configuração disponível. Caso contrário, a HAL usaráFrontendSettings
apenas uma vez scan 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 de frequência sejam exausto.
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)
de novo até que todas as frequências sejam esgotadas.
Durante a leitura, é possível chamar stopScan()
ou close()
para pausar ou encerrar a
digitalizar.
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;
O horário recomendado é Tuner.scan(BLIND_SCAN)
.
- O TIS usa
Tuner.scan(BLIND_SCAN)
. É possível especificar uma frequênciaFrontendSettings
para a frequência inicial, mas o TIS ignora outras configurações emFrontendSettings
. - A HAL vai enviar 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
de novo para continuar a verificação. (FrontendSettings
é ignorada. - O TIS repete as ações acima até que todas as configurações de frequência sejam
exausto. 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.
A HAL relata 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 do TIS
Android.media.tv.tuner.filter
O pacote de filtros é um conjunto de operações de filtro junto com a 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 filtro e especificam os tipos de dados que o filtro pode excluir.
SectionSettings
AvSettings
PesSettings
RecordSettings
DownloadSettings
O FilterEvent
é derivado das classes abaixo para relatar eventos para diferentes
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 () de DemuxFilterStatus::DATA_OVERFLOW
Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
De acordo com o evento e a programação interna, execute Filter.read(buffer, offset, adjustedSize) um ou mais
vezes.Os dados são copiados do MQ da HAL para o buffer do cliente. |
Um pacote de sessão montado é preenchido em FMQ por outro pacote de sessão. |
isRaw: |
Obrigatório:DemuxFilterEvent::DemuxFilterSectionEvent[n] () de DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW Opcional: DemuxFilterStatus::LOW_WATER () DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ e Os dados são copiados do MQ da HAL para o buffer do cliente. |
||
TS.PES |
isRaw: |
Obrigatório:DemuxFilterStatus::DATA_READY () de DemuxFilterStatus::DATA_OVERFLOW
Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
De acordo com o evento e a programação interna, execute Filter.read(buffer, offset, adjustedSize) um ou mais
vezes.Os dados são copiados do MQ da HAL para o buffer do cliente. |
Um pacote PES montado é preenchido em FMQ por outro PES. |
isRaw: |
Obrigatório:DemuxFilterEvent::DemuxFilterPesEvent[n] () de DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW Opcional: DemuxFilterStatus::LOW_WATER () DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ e Os dados são copiados do MQ da HAL para o buffer do cliente. |
||
MMTP.PES |
isRaw: |
Obrigatório:DemuxFilterStatus::DATA_READY () de DemuxFilterStatus::DATA_OVERFLOW
Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
De acordo com o evento e a programação interna, execute Filter.read(buffer, offset, adjustedSize) um ou mais
vezes.Os dados são copiados do MQ da HAL para o buffer do cliente. |
Um pacote MFU montado é preenchido em FMQ por outro MFU. |
isRaw: |
Obrigatório:DemuxFilterEvent::DemuxFilterPesEvent[n] () de DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW Opcional: DemuxFilterStatus::LOW_WATER () DemuxFilterStatus::HIGH_WATER |
for i=0; i<n; i++ e Os dados são copiados do MQ da HAL para o buffer do cliente. |
||
TS.TS |
N/A | Obrigatório:DemuxFilterStatus::DATA_READY () de DemuxFilterStatus::DATA_OVERFLOW
Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
De acordo com o evento e a programação interna, execute Filter.read(buffer, offset, adjustedSize) um ou mais
vezes.Os dados são copiados do MQ da HAL para o buffer do cliente. |
ts filtrado com o cabeçalho ts está preenchido FMQ. |
TS.Audio TS.Video MMTP.Audio MMTP.Video |
isPassthrough: |
Opcional:DemuxFilterStatus::DATA_READY () de 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] () de DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW Opcional: DemuxFilterStatus::LOW_WATER () DemuxFilterStatus::HIGH_WATER |
Para usar MediaCodec :for i=0; i<n; i++ e Para usar o áudio direto de AudioTrack :for i=0; i<n; i++ |
Dados ES ou parciais de ES 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] () de 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 opções:
|
Para dados de índice: transportados no payload do evento. Para conteúdo gravado: stream de TS alterado preenchido em FMQ. |
TS.TEMI |
N/A | Obrigatório:DemuxFilterEvent::DemuxFilterTemiEvent[n] () Opcional: de 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 () de DemuxFilterStatus::DATA_OVERFLOW
Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
De acordo com o evento e a programação interna, execute Filter.read(buffer, offset, adjustedSize) um ou mais
vezes.Os dados são copiados do MQ da HAL para o buffer do cliente. |
mmtp filtrado com o cabeçalho mmtp está preenchido FMQ. |
MMTP.RECORD |
N/A | Obrigatório:DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n] () de 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 programação interna, execute um dos
seguinte:
|
Para dados de índice: transportados no payload do evento. Para conteúdo gravado:stream gravado com multiplexação preenchida FMQ. Se a origem do filtro para a gravação for de TLV.TLV a
IP.IP com passthrough, o stream gravado tem
TLV e cabeçalho IP. |
MMTP.DOWNLOAD |
N/A | Obrigatório:DemuxFilterEvent::DemuxFilterDownloadEvent[n] () de 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) e Os dados são copiados do MQ da 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] () de 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) e Os dados são copiados do MQ da HAL para o buffer do cliente. |
O pacote de payload de IP é preenchido em FMQ por outro pacote de payload de IP. |
IP.IP TLV.TLV ALP.ALP |
isPassthrough: |
Opcional:DemuxFilterStatus::DATA_READY () de DemuxFilterStatus::DATA_OVERFLOW
|
O subfluxo do protocolo foi filtrado para o próximo filtro corrente | N/A |
isPassthrough: |
Obrigatório:DemuxFilterStatus::DATA_READY () de DemuxFilterStatus::DATA_OVERFLOW
Recomendado: DemuxFilterStatus::LOW_WATER DemuxFilterStatus::HIGH_WATER |
De acordo com o evento e a programação interna, execute Filter.read(buffer, offset, adjustedSize) um 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 está preenchido FMQ. | |
IP.PAYLOAD_THROUGH TLV.PAYLOAD_THROUGH ALP.PAYLOAD_THROUGH |
N/A | Opcional:DemuxFilterStatus::DATA_READY () de DemuxFilterStatus::DATA_OVERFLOW
|
O payload de protocolo filtrado alimenta o próximo filtro no filtro corrente | N/A |
Exemplo de fluxo para usar o filtro na criação de 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();
Processar
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 o MediaEvent do filtro
Figura 11. Fluxo para usar o MediaEvent do filtro
- Abra, configure e inicie os filtros A/V.
- Processar
MediaEvent
. - Receba
MediaEvent
. - Coloque o bloco linear na fila de
codec
. - Libere o identificador A/V quando os dados forem consumidos.
Android.media.tv.tuner.dvr
O DvrRecorder
oferece esses 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 um registro
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 recupere 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 de sintonizador
A HAL Tuner segue o HIDL e define a interface entre o framework e hardware do fornecedor. Os fornecedores usam a interface para implementar a HAL Tuner e o o framework o utiliza para se comunicar com a implementação da Tuner HAL.
Módulos
Sintonizador 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 e 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 de removePid |
IDescrambler.hal |
Tuner HAL 1.1 (derivada 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 Tuner
Vinculação do filtro
A HAL Tuner é compatível com 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. Não é permitido fechar caminhos.
- O nó raiz é demux.
- Os filtros operam 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ários 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
Gerenciador de recursos do Tuner
Antes do Tuner Resource Manager (TRM), alternar entre dois apps exigia a mesmo hardware do Tuner. O TV Input Framework (TIF) usou um "primeiro a ganhar" que significa que o app que receber o recurso primeiro vai mantê-lo. 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 o hardware do Tuner, TVInput
e CAS
recursos para apps. O TRM usa uma "vitória em primeiro plano" mecanismo de atenção,
calcula a prioridade do app com base em primeiro ou segundo plano
status e tipo de caso de uso. O TRM concede ou revoga o recurso com base
a 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 o Tuner
framework, 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 e o valor de prioridade do arquivo de configuração. A prioridade pode também podem ser atualizadas 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
é um app 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 são
listadas 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 uso predefinido casos de uso diferentes. Os usuários podem alterar 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.
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 bom custo-benefício
O TRM fornece updateClientPriority
para que o cliente atualize o valor arbitrário
valor de prioridade e bom valor.
O valor de prioridade arbitrário substitui o valor de prioridade calculado
do tipo de caso de uso e do ID da sessão.
O valor bom indica quão leniente é o comportamento do cliente quando está em conflito com outro cliente. O bom valor diminui a prioridade do cliente valor antes do seu valor de prioridade é comparado com o cliente desafiador.
Mecanismo de recuperação
O diagrama abaixo mostra como os recursos são recuperados e atribuídos quando quando ocorre um conflito de recursos.
Figura 15. Diagrama do mecanismo de recuperação de um conflito entre o Tuner recursos