Marcas de tiempo en tiempo real
Los gráficos de la calculadora de MediaPipe se usan a menudo para procesar transmisiones de video o audio.
o marcos para aplicaciones interactivas. El framework de MediaPipe solo requiere que
a paquetes sucesivos y marcas de tiempo que aumentan monótonamente. De
convención, las calculadoras y los gráficos en tiempo real usan el tiempo de registro o el
la hora de presentación de cada fotograma como su marca de tiempo, donde cada marca de tiempo indica
los microsegundos desde Jan/1/1970:00:00:00
. Esto permite que los paquetes de varios
fuentes de datos se procesen en una secuencia coherente a nivel global.
Programación en tiempo real
Por lo general, cada calculadora se ejecuta en cuanto todos sus paquetes de entrada para un y marca de tiempo estén disponibles. Por lo general, esto sucede cuando la calculadora terminó de procesar el fotograma anterior, y cada una de las calculadoras produjo cuando sus entradas terminan de procesar el fotograma actual. El programador de MediaPipe Invoca cada calculadora en cuanto se cumplen estas condiciones. Consulta Sincronización para obtener más detalles.
Límites de marcas de tiempo
Cuando una calculadora no produce ningún paquete de salida para una marca de tiempo determinada, puede mostrar un “límite de marca de tiempo” lo que indica que no se enviará ningún paquete producido para esa marca de tiempo. Esta indicación es necesaria para permitir se ejecuten en esa marca de tiempo, aunque no haya llegado ningún paquete para ciertas transmisiones para esa marca de tiempo. Esto es especialmente importante para las operaciones en tiempo real gráficos en aplicaciones interactivas, donde es crucial que cada calculadora comiencen a procesarse lo antes posible.
Considera un gráfico como el siguiente:
node {
calculator: "A"
input_stream: "alpha_in"
output_stream: "alpha"
}
node {
calculator: "B"
input_stream: "alpha"
input_stream: "foo"
output_stream: "beta"
}
Supongamos que, en la marca de tiempo T
, el nodo A
no envía un paquete en su transmisión de salida.
alpha
El nodo B
recibe un paquete en foo
en la marca de tiempo T
y espera un
paquete en alpha
en la marca de tiempo T
. Si A
no envía a B
un límite de marca de tiempo
actualización de alpha
. B
seguirá esperando la llegada de un paquete en alpha
.
Mientras tanto, la cola de paquetes de foo
acumulará paquetes en T
, T+1
y
y así sucesivamente.
Para la salida de un paquete en una transmisión, una calculadora usa las funciones de API
CalculatorContext::Outputs
y OutputStream::Add
. Como alternativa, para obtener una
marca de tiempo vinculada a una transmisión, una calculadora puede usar las funciones de API
CalculatorContext::Outputs
y CalculatorContext::SetNextTimestampBound
. El
el límite especificado es la marca de tiempo más baja permitida para el siguiente paquete de la
flujo de salida especificado. Cuando no se muestra ningún paquete, por lo general, la calculadora
hacer algo como:
cc->Outputs().Tag("output_frame").SetNextTimestampBound(
cc->InputTimestamp().NextAllowedInStream());
La función Timestamp::NextAllowedInStream
muestra la marca de tiempo sucesiva.
Por ejemplo, Timestamp(1).NextAllowedInStream() == Timestamp(2)
Propaga límites de marca de tiempo
Las calculadoras que se usarán en gráficos en tiempo real deben definir el resultado.
basados en los límites de marca de tiempo de entrada para permitir
programar calculadoras de forma oportuna. Un patrón común es que las calculadoras
los paquetes de salida con las mismas marcas de tiempo que sus paquetes de entrada. En este caso,
enviar un paquete por cada llamada a Calculator::Process
es suficiente
para definir los límites de marca de tiempo de salida.
Sin embargo, no es necesario que las calculadoras sigan este patrón común para los resultados. marcas de tiempo, solo deben elegir valores de salida monótonamente y marcas de tiempo. Como resultado, ciertas calculadoras deben calcular los límites de marca de tiempo. de forma explícita. MediaPipe proporciona varias herramientas para calcular las marcas de tiempo para cada calculadora.
1. SetNextTimestampBound() se puede usar para especificar el límite de marca de tiempo, t +
1
, para una transmisión de salida.
cc->Outputs.Tag("OUT").SetNextTimestampBound(t.NextAllowedInStream());
Como alternativa, se puede producir un paquete vacío con la marca de tiempo t
para especificar el
vinculado a la marca de tiempo t + 1
.
cc->Outputs.Tag("OUT").Add(Packet(), t);
El límite de marca de tiempo de una transmisión de entrada se indica mediante el paquete o la fuente paquete en la transmisión de entrada.
Timestamp bound = cc->Inputs().Tag("IN").Value().Timestamp();
2. TimestampOffset() puede especificarse para copiar automáticamente el marca de tiempo vinculada de transmisiones de entrada a transmisiones de salida.
cc->SetTimestampOffset(0);
Este parámetro de configuración tiene la ventaja de propagar automáticamente los límites de la marca de tiempo incluso cuando solo llegan los límites de la marca de tiempo y no se invoca a Calculadora::Process.
3. ProcessTimestampBounds() puede especificarse para invocar
Calculator::Process
para cada nueva “marca de tiempo liquidada”, en la que el valor
marca de tiempo es la nueva marca de tiempo más alta debajo de los límites de la marca de tiempo actual.
Sin ProcessTimestampBounds()
, Calculator::Process
solo se invoca con
uno o más paquetes entrantes.
cc->SetProcessTimestampBounds(true);
Este parámetro de configuración permite que una calculadora realice su propio cálculo de límites de marca de tiempo.
y propagación, incluso cuando solo se actualizan
las marcas de tiempo de entrada. Se puede usar para
replicar el efecto de TimestampOffset()
, pero también se puede usar para
calcular un límite de marca de tiempo que tenga en cuenta factores adicionales.
Por ejemplo, para replicar SetTimestampOffset(0)
, una calculadora podría
haz lo siguiente:
absl::Status Open(CalculatorContext* cc) {
cc->SetProcessTimestampBounds(true);
}
absl::Status Process(CalculatorContext* cc) {
cc->Outputs.Tag("OUT").SetNextTimestampBound(
cc->InputTimestamp().NextAllowedInStream());
}
Programación de Calculadora::Abrir y Calculadora::Cerrar
Se invoca Calculator::Open
cuando todos los paquetes de entrada adicionales necesarios
producidos. Los paquetes de entrada adicionales se pueden proporcionar mediante la aplicación contenedora o
"calculadoras de paquetes adicionales" dentro del gráfico. Los paquetes adicionales se pueden especificar desde
fuera del gráfico con el CalculatorGraph::Initialize
de la API y
CalculatorGraph::StartRun
Los paquetes laterales pueden especificarse con calculadoras dentro
el gráfico con CalculatorGraphConfig::OutputSidePackets
y
OutputSidePacket::Set
Calculator::Close se invoca cuando todas las transmisiones de entrada se vuelven Done
se está cerrando o alcanzando el límite de marca de tiempo Timestamp::Done
.
Nota: Si el gráfico finaliza toda la ejecución pendiente de la calculadora y se convierte en
Done
, antes de que algunas transmisiones pasen a ser Done
, MediaPipe invocará la
llamadas restantes a Calculator::Close
, de modo que cada calculadora pueda producir su
los resultados finales.
El uso de TimestampOffset
tiene algunas implicaciones para Calculator::Close
. R
que especifique SetTimestampOffset(0)
indicará de por qué todos
las transmisiones de salida alcanzaron el Timestamp::Done
cuando todas las transmisiones de entrada
llegaron a Timestamp::Done
, por lo que no es posible obtener más resultados.
Esto evita que esa calculadora emita paquetes durante
Calculator::Close
Si una calculadora debe producir un paquete de resumen durante
Calculator::Close
y Calculator::Process
deben especificar límites de marca de tiempo, como
que al menos una marca de tiempo (como Timestamp::Max
) permanezca disponible durante
Calculator::Close
Esto significa que una calculadora normalmente no puede basarse en
SetTimestampOffset(0)
y, en su lugar, debe especificar explícitamente los límites de marca de tiempo
usando SetNextTimestampBounds()
.