Transmissões em tempo real

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().