Livestreams in Echtzeit

Echtzeit-Zeitstempel

Die Grafiken des MediaPipe-Rechners werden häufig zur Verarbeitung von Video- oder Audiostreams verwendet. Frames für interaktive Anwendungen. Für das MediaPipe-Framework ist nur Folgendes erforderlich: aufeinanderfolgende Pakete erhalten monoton ansteigende Zeitstempel. Von verwenden Echtzeitrechner und Grafiken die Aufzeichnungszeit oder die Präsentationszeit jedes Frames als Zeitstempel, wobei jeder Zeitstempel Mikrosekunden seit Jan/1/1970:00:00:00. Dadurch werden Pakete von verschiedenen in einer global konsistenten Reihenfolge verarbeitet werden.

Terminplanung in Echtzeit

Normalerweise wird jeder Rechner sofort ausgeführt, sobald alle Eingabepakete verfügbar. Normalerweise geschieht dies, wenn der Rechner die Verarbeitung des vorherigen Frames abgeschlossen und alle Rechner, die sie produziert haben, die Verarbeitung des aktuellen Frames abgeschlossen ist. MediaPipe-Planer Ruft jeden Rechner auf, sobald diese Bedingungen erfüllt sind. Weitere Informationen finden Sie unter Synchronisierung.

Zeitstempelgrenzen

Wenn ein Rechner keine Ausgabepakete für einen bestimmten Zeitstempel erzeugt, kann stattdessen eine „Zeitstempelgrenze“ deutet darauf hin, dass kein Paket die für diesen Zeitstempel produziert wurden. Diese Angabe ist notwendig, um zu diesem Zeitpunkt ausgeführt werden, obwohl kein Paket für bestimmte Streams für diesen Zeitstempel. Das ist besonders wichtig für Echtzeit- in interaktiven Anwendungen darstellen. Dabei ist es wichtig, so schnell wie möglich mit der Verarbeitung begonnen.

Stellen Sie sich ein Diagramm wie das folgende vor:

node {
   calculator: "A"
   input_stream: "alpha_in"
   output_stream: "alpha"
}
node {
   calculator: "B"
   input_stream: "alpha"
   input_stream: "foo"
   output_stream: "beta"
}

Angenommen: Beim Zeitstempel T sendet Knoten A in seinem Ausgabestream kein Paket. alpha Knoten B erhält ein Paket in foo mit dem Zeitstempel T und wartet auf Paket in alpha mit dem Zeitstempel T. Wenn A keine Zeitstempelgrenze an B sendet Update für alpha wartet B weiter auf das Eintreffen eines Pakets in alpha. In der Zwischenzeit sammelt die Paketwarteschlange von foo Pakete unter T, T+1 und so weiter.

Zur Ausgabe eines Pakets in einen Stream verwendet ein Rechner die API-Funktionen CalculatorContext::Outputs und OutputStream::Add. Um stattdessen eine Ausgabe von an einen Stream gebunden ist, kann ein Rechner die API-Funktionen CalculatorContext::Outputs und CalculatorContext::SetNextTimestampBound. Die angegebene Grenze ist der niedrigste zulässige Zeitstempel für das nächste Paket im angegebenen Ausgabestream. Wenn kein Paket ausgegeben wird, beispielsweise:

cc->Outputs().Tag("output_frame").SetNextTimestampBound(
  cc->InputTimestamp().NextAllowedInStream());

Die Funktion Timestamp::NextAllowedInStream gibt den aufeinanderfolgenden Zeitstempel zurück. Beispiel: Timestamp(1).NextAllowedInStream() == Timestamp(2).

Zeitstempelgrenzen weitergeben

Rechner, die in Echtzeitgrafiken verwendet werden, müssen die Ausgabe definieren Zeitstempelgrenzen basierend auf Eingabezeitstempelgrenzen, um Downstream- um schnell einen Termin zu vereinbaren. Ein gängiges Muster ist, Ausgabepakete mit denselben Zeitstempeln wie ihre Eingabepakete. In diesem Fall Es reicht aus, einfach bei jedem Aufruf von Calculator::Process ein Paket auszugeben. um Zeitstempelgrenzen für die Ausgabe zu definieren.

Rechner müssen sich bei der Ausgabe jedoch nicht an dieses allgemeine Muster halten. müssen nur monoton ansteigende Ausgabewerte Zeitstempel. Daher müssen bestimmte Rechner Zeitstempelgrenzen berechnen, explizit auf. MediaPipe bietet verschiedene Tools zur Berechnung des geeigneten Zeitstempels für jeden Rechner definiert.

1. SetNextTimestampBound() kann zur Angabe der Zeitstempelgrenze t + 1 für einen Ausgabestream verwendet werden.

cc->Outputs.Tag("OUT").SetNextTimestampBound(t.NextAllowedInStream());

Alternativ kann ein leeres Paket mit dem Zeitstempel t erzeugt werden, um den Wert für Zeitstempelgrenze von t + 1.

cc->Outputs.Tag("OUT").Add(Packet(), t);

Die Zeitstempelgrenze eines Eingabestreams wird durch das Paket oder das leere Feld angegeben Paket im Eingabestream.

Timestamp bound = cc->Inputs().Tag("IN").Value().Timestamp();

2. TimestampOffset() angeben, um den Parameter Zeitstempel, der von Eingabestreams zu Ausgabestreams gebunden ist.

cc->SetTimestampOffset(0);

Diese Einstellung hat den Vorteil, dass Zeitstempelgrenzen automatisch weitergegeben werden, auch wenn nur Zeitstempelgrenzen eintreffen und Calculator::Process nicht aufgerufen wird.

3. ProcessTimestampBounds() zum Aufrufen von Calculator::Process für jeden neuen „settled timestamp“, wobei der „settled timestamp“ Zeitstempel“ ist der neue höchste Zeitstempel unterhalb der aktuellen Zeitstempelgrenzen. Ohne ProcessTimestampBounds() wird Calculator::Process nur mit ein oder mehrere eingehende Pakete.

cc->SetProcessTimestampBounds(true);

Mit dieser Einstellung kann ein Rechner seine eigenen Zeitstempelgrenzen berechnen auch wenn nur Zeitstempel der Eingabe aktualisiert werden. Sie kann verwendet werden, um die Wirkung von TimestampOffset() nachbilden, aber sie kann auch verwendet werden, eine Zeitstempelgrenze berechnen, die zusätzliche Faktoren berücksichtigt.

Um beispielsweise SetTimestampOffset(0) zu replizieren, könnte ein Rechner Gehen Sie so vor:

absl::Status Open(CalculatorContext* cc) {
  cc->SetProcessTimestampBounds(true);
}

absl::Status Process(CalculatorContext* cc) {
  cc->Outputs.Tag("OUT").SetNextTimestampBound(
      cc->InputTimestamp().NextAllowedInStream());
}

Planung von Rechner::Öffnen und Rechner::Schließen

Calculator::Open wird aufgerufen, wenn alle erforderlichen Eingabe-Seitenpakete erstellt wurden produziert wurden. Eingabe-Seitenpakete können von der einschließenden Anwendung oder durch „side-packet rechner“ im Diagramm. Nebenpakete können über außerhalb des Diagramms mit CalculatorGraph::Initialize der API und CalculatorGraph::StartRun. Nebenpakete können mithilfe von Rechnern in das Diagramm mit CalculatorGraphConfig::OutputSidePackets und OutputSidePacket::Set.

Rechner::Close wird aufgerufen, wenn alle Eingabestreams Done durch geschlossen wird oder die Zeitstempelgrenze von Timestamp::Done erreicht.

Hinweis:Wenn für die Grafik alle ausstehenden Rechnerausführungen abgeschlossen sind und Done festlegen, bevor einige Streams zu Done werden, ruft MediaPipe den verbleibende Aufrufe an Calculator::Close, sodass jeder Rechner und die Endergebnisse.

Die Verwendung von TimestampOffset hat einige Auswirkungen auf Calculator::Close. A Der Rechner mit SetTimestampOffset(0) signalisiert, dass alle seine Ausgabestreams haben Timestamp::Done erreicht, wenn alle Eingabestreams haben Timestamp::Done erreicht, daher sind keine weiteren Ausgaben mehr möglich. So wird verhindert, dass ein solcher Rechner während der Calculator::Close Wenn ein Rechner während der Laufzeit Calculator::Close, Calculator::Process muss Zeitstempelgrenzen angeben wie dass mindestens ein Zeitstempel (z. B. Timestamp::Max) im Zeitraum Calculator::Close Daher kann sich ein solcher Rechner normalerweise nicht darauf verlassen, SetTimestampOffset(0) und muss stattdessen Zeitstempelgrenzen explizit angeben mit SetNextTimestampBounds().