sygnatury czasowe w czasie rzeczywistym;
Wykresy kalkulatora MediaPipe są często używane do przetwarzania strumieni wideo lub audio
dla aplikacji interaktywnych. Struktura MediaPipe wymaga tylko tych
kolejne pakiety otrzymują monotonicznie rosnące sygnatury czasowe. Według
kalkulatory i wykresy czasu rzeczywistego korzystają z czasu rejestrowania lub
czas prezentacji każdej klatki jako jej sygnaturę czasową, przy czym każda sygnatura czasowa wskazuje
w mikrosekundach od Jan/1/1970:00:00:00
. Pozwala to na przesyłanie pakietów z różnych
muszą być przetworzone w spójnej globalnie kolejności.
Planowanie w czasie rzeczywistym
Zwykle kalkulator uruchamia się, gdy tylko wszystkie jego pakiety wejściowe dla danego sygnatura czasowa jest dostępna. Zwykle dzieje się tak, gdy kalkulator i zakończenie przetwarzania poprzedniej klatki, a każdy kalkulator generuje jego dane wejściowe zakończyły przetwarzanie bieżącej klatki. Algorytm szeregowania MediaPipe wywołuje każdy kalkulator, gdy tylko te warunki zostaną spełnione. Zobacz Synchronizacja: więcej szczegółów.
Granice sygnatury czasowej
Jeśli kalkulator nie wygeneruje pakietów wyjściowych dla danej sygnatury czasowej, może zamiast tego wyświetlać „powiązanie z sygnaturą czasową” co oznacza, że żaden pakiet nie zostanie dla danej sygnatury czasowej. To oznaczenie jest konieczne, aby umożliwić pobieranie aby kalkulatory uruchamiały się z tą sygnaturą czasową, nawet jeśli nie odebrano żadnego pakietu dla wybranych strumieni z danej sygnatury czasowej. Jest to szczególnie ważne w przypadku reklam w czasie rzeczywistym w interaktywnych aplikacjach, w których każdy kalkulator jak najszybciej rozpocząć przetwarzanie.
Weźmy pod uwagę taki wykres:
node {
calculator: "A"
input_stream: "alpha_in"
output_stream: "alpha"
}
node {
calculator: "B"
input_stream: "alpha"
input_stream: "foo"
output_stream: "beta"
}
Załóżmy, że w sygnaturze czasowej T
węzeł A
nie wysyła pakietu w strumieniu wyjściowym
alpha
Węzeł B
otrzymuje pakiet w folderze foo
w sygnaturze czasowej T
i czeka na
pakiet w alpha
w sygnaturze czasowej T
. Jeśli A
nie wysyła elementu B
powiązany z sygnaturą czasową
aktualizacja pakietu alpha
, B
będzie nadal czekać na pakiet w: alpha
.
W międzyczasie kolejka pakietów foo
będzie gromadzić pakiety w punktach T
, T+1
oraz
i tak dalej.
Aby wyświetlić pakiet ze strumieniem, kalkulator korzysta z funkcji interfejsu API
CalculatorContext::Outputs
i OutputStream::Add
. Aby zamiast tego wysłać błąd
w postaci sygnatury czasowej związanej ze strumieniem, kalkulator może korzystać z funkcji interfejsu API
CalculatorContext::Outputs
i CalculatorContext::SetNextTimestampBound
.
określona granica to najniższa dopuszczalna sygnatura czasowa następnego pakietu w
określony strumień wyjściowy. Kiedy nie zostanie wysłany żaden pakiet, kalkulator zwykle
zrób coś takiego:
cc->Outputs().Tag("output_frame").SetNextTimestampBound(
cc->InputTimestamp().NextAllowedInStream());
Funkcja Timestamp::NextAllowedInStream
zwraca kolejne sygnatury czasowe.
Na przykład: Timestamp(1).NextAllowedInStream() == Timestamp(2)
.
Propaguję granice sygnatury czasowej
Kalkulatory, które będą używane na wykresach w czasie rzeczywistym, muszą określać dane wyjściowe.
granice sygnatury czasowej na podstawie granic wejściowej sygnatury czasowej, aby umożliwić pobieranie
aby szybko planować ich generowanie. Typowym wzorcem są kalkulatory do
pakiety wyjściowe o tych samych sygnaturach czasowych co pakiety wejściowe. W tym przypadku
wystarczy wysłać pakiet przy każdym wywołaniu do Calculator::Process
aby zdefiniować granice
sygnatury czasowej wyjściowej.
ale kalkulatory nie muszą opierać się na tym wspólnym wzorcu danych wyjściowych sygnatur czasowych, są one wymagane tylko do wybierania danych wyjściowych o rosnącej monotonicznie sygnatury czasowe. W efekcie niektóre kalkulatory muszą obliczać granice sygnatury czasowej bezpośrednio. MediaPipe udostępnia kilka narzędzi do obliczania odpowiednich sygnatur czasowych dla każdego kalkulatora.
1. Funkcja SetNextTimestampBound() może służyć do określania sygnatury czasowej strumienia wyjściowego (t +
1
).
cc->Outputs.Tag("OUT").SetNextTimestampBound(t.NextAllowedInStream());
Można też utworzyć pusty pakiet z sygnaturą czasową t
w celu określenia
powiązany z sygnaturą czasową t + 1
.
cc->Outputs.Tag("OUT").Add(Packet(), t);
Powiązanie z sygnaturą czasową strumienia wejściowego jest wskazywane przez pakiet lub pusty w strumieniu wejściowym.
Timestamp bound = cc->Inputs().Tag("IN").Value().Timestamp();
2. Można określić TimestampOffset(), aby automatycznie skopiować parametr sygnatura czasowa powiązana ze strumieniami wejściowymi do strumieni wyjściowych;
cc->SetTimestampOffset(0);
Zaletą tego ustawienia jest automatyczne propagowanie granic sygnatur czasowych, nawet jeśli dotarły tylko granice sygnatury czasowej, a kalkulator::Proces nie został wywołany.
3. W celu wywołania można określić metodę ProcessTimestampBounds()
Calculator::Process
dla każdej nowej „ustalonej sygnatury czasowej”, gdzie „rozliczone
timestamp” to nowa najwyższa sygnatura czasowa poniżej bieżących granic sygnatury czasowej.
Bez metody ProcessTimestampBounds()
funkcja Calculator::Process
jest wywoływana tylko z
co najmniej jedna przesyłka.
cc->SetProcessTimestampBounds(true);
To ustawienie pozwala kalkulatorowi samodzielnie obliczać granice sygnatur czasowych
i rozpowszechniania, nawet wtedy, gdy aktualizowane są tylko sygnatury czasowe. Może służyć do:
powieli efekt TimestampOffset()
, ale może też być używany do
obliczać ograniczenie sygnatury czasowej, które uwzględnia dodatkowe czynniki.
Aby na przykład powielić zmienną SetTimestampOffset(0)
, kalkulator może:
wykonaj te czynności:
absl::Status Open(CalculatorContext* cc) {
cc->SetProcessTimestampBounds(true);
}
absl::Status Process(CalculatorContext* cc) {
cc->Outputs.Tag("OUT").SetNextTimestampBound(
cc->InputTimestamp().NextAllowedInStream());
}
Harmonogram Kalkulatora::Otwórz i Kalkulator::Zamknij
Pole Calculator::Open
jest wywoływane, gdy wszystkie wymagane wejściowe pakiety poboczne zostały
z całego świata. Wejściowe pakiety boczne mogą zostać dostarczone przez aplikację otaczającą lub przez
„kalkulatory pakietów bocznych” wewnątrz wykresu. Pakiety boczne można określić z:
poza wykresem za pomocą funkcji CalculatorGraph::Initialize
i interfejsów API
CalculatorGraph::StartRun
Pakiety boczne mogą być określane przez kalkulatory w
wykres za pomocą funkcji CalculatorGraphConfig::OutputSidePackets
i
OutputSidePacket::Set
Kalkulator::Zamknij jest wywoływany, gdy wszystkie strumienie wejściowe mają wartość Done
przez
jest zamykana lub osiąga wartość powiązaną z sygnaturą czasową Timestamp::Done
.
Uwaga: jeśli wykres zakończy wszystkie oczekujące wykonanie kalkulatora i stanie się
Done
, zanim niektóre strumienie zmienią się na Done
, MediaPipe wywoła metodę
pozostałych wywołań funkcji Calculator::Close
, by każdy kalkulator mógł wygenerować
z wynikami końcowymi.
Używanie właściwości TimestampOffset
może mieć wpływ na działanie funkcji Calculator::Close
. O
kalkulator określający SetTimestampOffset(0)
będzie z projektowania zasygnalizuje, że wszystkie
strumienie wyjściowe osiągnęły Timestamp::Done
, gdy wszystkie strumienie wejściowe
osiągnięto Timestamp::Done
, dlatego dalsze dane wyjściowe nie są dostępne.
Dzięki temu kalkulator nie będzie wysyłać pakietów podczas
Calculator::Close
Jeśli kalkulator musi wygenerować pakiet podsumowania podczas
Calculator::Close
, Calculator::Process
musi określać granice sygnatury czasowej takie jak
że co najmniej jedna sygnatura czasowa (np. Timestamp::Max
) jest dostępna
Calculator::Close
Oznacza to, że kalkulator zwykle nie może polegać na
SetTimestampOffset(0)
i muszą w sposób jawny określić granice sygnatury czasowej
za pomocą: SetNextTimestampBounds()
.