Carimbos de data/hora em tempo real
Os gráficos da calculadora MediaPipe costumam ser usados para processar streams de vídeo ou áudio
frames para aplicativos interativos. O framework MediaPipe exige apenas que
pacotes sucessivos sejam atribuídos a carimbos de data/hora monotonicamente crescentes. De
calculadoras em tempo real e gráficos usam o tempo de gravação ou o
hora de apresentação de cada frame como o carimbo de data/hora, com cada marcação indicando
os microssegundos desde Jan/1/1970:00:00:00
. Isso permite que os pacotes de vários
as fontes de dados sejam processadas
em uma sequência globalmente consistente.
Programação em tempo real
Normalmente, cada calculadora é executada assim que todos os pacotes de entrada de um determinado o carimbo de data/hora fica disponível. Normalmente, isso acontece quando a calculadora tem terminou de processar o frame anterior, e cada uma das calculadoras que produzem suas entradas tenham concluído o processamento do frame atual. Programador do MediaPipe invoca cada calculadora assim que essas condições são atendidas. Consulte Sincronização para mais detalhes.
Limites de carimbo de data/hora
Quando uma calculadora não produz pacotes de saída para um determinado carimbo de data/hora, ela pode gerar um "limite de carimbo de data/hora" indicando que nenhum pacote será para o carimbo de data/hora. Essa indicação é necessária para permitir o uso de calculadora para execução nesse carimbo de data/hora, mesmo que nenhum pacote tenha chegado para determinados streams para esse carimbo de data/hora. Isso é importante principalmente para casos de uso gráficos em aplicativos interativos, em que é crucial que cada calculadora inicie o processamento o mais rápido possível.
Considere um gráfico como este:
node {
calculator: "A"
input_stream: "alpha_in"
output_stream: "alpha"
}
node {
calculator: "B"
input_stream: "alpha"
input_stream: "foo"
output_stream: "beta"
}
Suponha que no carimbo de data/hora T
, o nó A
não envie um pacote no stream de saída
alpha
O nó B
recebe um pacote em foo
no carimbo de data/hora T
e está aguardando uma
pacote em alpha
no carimbo de data/hora T
. Se A
não enviar a B
um limite de carimbo de data/hora
atualização para alpha
, B
vai continuar aguardando a chegada de um pacote em alpha
.
Enquanto isso, a fila de pacotes de foo
vai acumular pacotes em T
, T+1
e
assim por diante.
Para gerar um pacote em um stream, uma calculadora usa as funções da API
CalculatorContext::Outputs
e OutputStream::Add
. Em vez disso, para gerar uma
limite de carimbo de data/hora em um fluxo, uma calculadora pode usar as funções da API
CalculatorContext::Outputs
e CalculatorContext::SetNextTimestampBound
. A
o limite especificado é o menor carimbo de data/hora permitido para o próximo pacote no
de saída especificado. Quando nenhum pacote é enviado, uma calculadora
faça algo como:
cc->Outputs().Tag("output_frame").SetNextTimestampBound(
cc->InputTimestamp().NextAllowedInStream());
A função Timestamp::NextAllowedInStream
retorna o carimbo de data/hora sucessivo.
Por exemplo, Timestamp(1).NextAllowedInStream() == Timestamp(2)
.
Propagação de limites de carimbo de data/hora
As calculadoras que serão usadas em gráficos em tempo real precisam definir os resultados
limites de carimbo de data/hora com base nos limites de carimbo de data/hora de entrada para permitir o uso
calculadoras para agendamento rápido. Um padrão comum é que as calculadoras
pacotes de saída com os mesmos carimbos de data/hora dos pacotes de entrada. Nesse caso,
a saída de um pacote em cada chamada para Calculator::Process
é suficiente
para definir limites de carimbo de data/hora de saída.
No entanto, as calculadoras não precisam seguir esse padrão comum os carimbos de data/hora, eles só precisam escolher valores de saída crescentes carimbos de data/hora. Como resultado, algumas calculadoras precisam calcular os limites de carimbo de data/hora. explicitamente. O MediaPipe fornece várias ferramentas para calcular o carimbo de data/hora apropriado limite para cada calculadora.
1. SetNextTimestampBound() pode ser usado para especificar o limite de carimbo de data/hora, t +
1
, para um stream de saída.
cc->Outputs.Tag("OUT").SetNextTimestampBound(t.NextAllowedInStream());
Como alternativa, é possível produzir um pacote vazio com o carimbo de data/hora t
para especificar o
limite de carimbo de data/hora t + 1
.
cc->Outputs.Tag("OUT").Add(Packet(), t);
O limite de carimbo de data/hora de um fluxo de entrada é indicado pelo no fluxo de entrada.
Timestamp bound = cc->Inputs().Tag("IN").Value().Timestamp();
2. TimestampOffset() pode ser especificado para copiar automaticamente o limite de carimbo de data/hora dos streams de entrada para os de saída.
cc->SetTimestampOffset(0);
Essa configuração tem a vantagem de propagar limites de carimbo de data/hora automaticamente, mesmo quando apenas limites de carimbo de data/hora chegam e Calculator::Process não é invocado.
3. ProcessTimestampBounds() pode ser especificado para invocar
Calculator::Process
para cada novo "carimbo de data/hora definido", em que os valores
carimbo de data/hora" é o novo carimbo de data/hora mais alto abaixo dos limites atuais.
Sem ProcessTimestampBounds()
, Calculator::Process
é invocado apenas com
de um ou mais pacotes que chegam.
cc->SetProcessTimestampBounds(true);
Essa configuração permite que uma calculadora realize o próprio cálculo de limites de carimbo de data/hora
e propagação, mesmo quando apenas carimbos de data/hora de entrada são atualizados. Ela pode ser usada para
replicar o efeito de TimestampOffset()
, mas também pode ser usado para
calcular um limite de carimbo de data/hora que considera fatores adicionais.
Por exemplo, para replicar SetTimestampOffset(0)
, uma calculadora poderia
faça o seguinte:
absl::Status Open(CalculatorContext* cc) {
cc->SetProcessTimestampBounds(true);
}
absl::Status Process(CalculatorContext* cc) {
cc->Outputs.Tag("OUT").SetNextTimestampBound(
cc->InputTimestamp().NextAllowedInStream());
}
Programação da Calculadora::Aberta e Calculadora::Fechar
Calculator::Open
é invocado quando todos os pacotes secundários de entrada necessários foram
produzidos. Os pacotes secundários de entrada podem ser fornecidos pelo aplicativo de inclusão ou pelo
"calculadoras de pacote secundário" no gráfico. É possível especificar pacotes laterais
fora do gráfico usando o CalculatorGraph::Initialize
da API e
CalculatorGraph::StartRun
. Os pacotes laterais podem ser especificados por calculadoras
o gráfico usando CalculatorGraphConfig::OutputSidePackets
e
OutputSidePacket::Set
.
Calculadora::Fechar é invocado quando todos os streams de entrada se tornam Done
por
estar fechado ou chegar ao limite de carimbo de data/hora Timestamp::Done
.
Observação:se o gráfico terminar todas as execuções de calculadora pendentes e se tornar
Done
, antes que alguns streams se tornem Done
, o MediaPipe invocará a
chamadas restantes para Calculator::Close
, de modo que cada calculadora possa produzir os
as saídas finais.
O uso de TimestampOffset
tem algumas implicações para Calculator::Close
. Um
calculadora que especifica SetTimestampOffset(0)
sinalizará, por design, que todos
os streams de saída atingiram Timestamp::Done
quando todos os streams de entrada
atingiu Timestamp::Done
e, portanto, nenhuma outra saída é possível.
Isso impede que a calculadora emita pacotes durante
Calculator::Close
: Se uma calculadora precisar produzir um pacote de resumo durante
Calculator::Close
, Calculator::Process
precisa especificar limites de carimbo de data/hora, como
que pelo menos um carimbo de data/hora (como Timestamp::Max
) permanece disponível durante
Calculator::Close
: Isso significa que essa calculadora normalmente não pode confiar
SetTimestampOffset(0)
e precisa especificar explicitamente os limites do carimbo de data/hora
usando SetNextTimestampBounds()
.