即時串流

即時時間戳記

MediaPipe 計算機圖表通常用於處理互動式應用程式的影片或音訊影格串流。MediaPipe 架構只需要為成功的封包指派單調遞增的時間戳記。按照慣例,即時計算機和圖表會使用每個影格的錄製時間或顯示時間做為時間戳記,每個時間戳記都表示自 Jan/1/1970:00:00:00 以來的微秒。這樣一來,您就能以全域一致的序列處理各種來源的封包。

即時排程

通常,每個計算機會在特定時間戳記的所有輸入封包可供使用時,立即執行。一般而言,當計算機已完成前一個影格的處理作業,且產生輸入內容的每個計算工具都處理完目前的影格時,就會發生這種情況。只要滿足這些條件,MediaPipe 排程器就會立即叫用每個計算機。詳情請參閱同步處理

時間戳記範圍

如果計算機未針對特定時間戳記產生任何輸出封包,可改為輸出「時間戳記邊界」,指出該時間戳記不會產生任何封包。您可以允許下游計算器在該時間戳記執行,即使該時間戳記的某些串流尚未送達任何封包。對於互動式應用程式中的即時圖表而言,這點尤其重要,因為每個計算機都必須盡快開始處理。

請參考以下圖表:

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

假設:在時間戳記 T 時,節點 A 不會在輸出串流 alpha 中傳送封包,節點 B 會在 foo 的時間戳記 T 取得封包,且正在等待 alpha 時間戳記 T 的封包。如果 A 未傳送 alpha 的時間戳記範圍更新給 BB 會繼續等待封包抵達 alpha。與此同時,foo 的封包佇列會在 TT+1 等時間點累積封包。

為了在串流中輸出封包,計算機會使用 API 函式 CalculatorContext::OutputsOutputStream::Add。如要改為在串流中輸出時間戳記範圍,計算機可使用 API 函式 CalculatorContext::OutputsCalculatorContext::SetNextTimestampBound。指定的範圍是指定輸出串流中下一個封包的允許最低時間戳記。如果沒有輸出任何封包,計算機通常會執行以下操作:

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

Timestamp::NextAllowedInStream 函式會傳回連續時間戳記。例如 Timestamp(1).NextAllowedInStream() == Timestamp(2)

傳播時間戳記範圍

即時圖表使用的計算機必須根據輸入時間戳記範圍定義輸出時間戳記範圍,才能允許及時排定下游計算機。常見的模式是,計算機輸出的封包時間戳記與輸入封包的時間戳記相同。在這種情況下,只要在每次呼叫 Calculator::Process 時輸出封包就足以定義輸出時間戳記範圍。

不過,計算時間戳記不需要遵循這個通用模式,只需要選擇單調遞增的輸出時間戳記。因此,某些計算機必須明確計算時間戳記邊界。MediaPipe 提供數種工具,可用於為每個計算機計算適當的時間戳記範圍。

1. SetNextTimestampBound() 可用來指定輸出串流的時間戳記界限 t + 1

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

或者,也可以產生時間戳記 t 的空白封包,以指定時間戳記範圍 t + 1

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

輸入串流的時間戳記邊界,以封包或輸入串流上的空白封包表示。

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

2. 您可以指定 TimestampOffset(),以便自動將輸入串流的時間戳記繫結複製到輸出串流。

cc->SetTimestampOffset(0);

此設定有自動傳播時間戳記邊界的優勢,即使只到達時間戳記範圍,且不會叫用「Calculate::Process」。

3. ProcessTimestampBounds() 便可為每個新的「settled timestamp」叫用 Calculator::Process,其中「settled timestamp」是目前時間戳記範圍以下的新最高時間戳記。如果沒有 ProcessTimestampBounds(),則只能透過一或多個抵達的封包叫用 Calculator::Process

cc->SetProcessTimestampBounds(true);

這項設定可讓計算機自行計算時間戳記邊界與傳播,即使只更新輸入的時間戳記也一樣。這可用於複製 TimestampOffset() 的效果,但也可用於計算將其他因素納入考量的時間戳記邊界。

舉例來說,為了複製 SetTimestampOffset(0),計算機可執行以下操作:

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

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

計算機排程:開啟與計算機:關閉

產生所有必要的輸入端封包時,系統會叫用 Calculator::Open。輸入的側封包可以由封閉的應用程式或圖表內的「側封包計算機」提供。您可以使用 API 的 CalculatorGraph::InitializeCalculatorGraph::StartRun,從圖表外指定側邊封包。圖形中的計算工具可以使用 CalculatorGraphConfig::OutputSidePacketsOutputSidePacket::Set 指定側邊封包。

計算機:當所有輸入串流因關閉或達到時間戳記繫結 Timestamp::Done 而變為 Done 時,系統會叫用關閉。

注意:如果圖形完成所有待處理計算器執行作業並變成 Done,則在部分串流變成 Done 之前,MediaPipe 會叫用 Calculator::Close 的其餘呼叫,讓每個計算機都能產生最終輸出內容。

使用 TimestampOffset 會對 Calculator::Close 產生一些影響。指定 SetTimestampOffset(0) 的計算機會設計指示,當所有輸入串流都達到 Timestamp::Done 時,所有輸出串流均已達 Timestamp::Done,因此無法再輸出。這樣可以防止這類計算工具在 Calculator::Close 期間發送任何封包。如果計算機需要在 Calculator::Close 期間產生摘要封包,Calculator::Process 必須指定時間戳記範圍,讓 Calculator::Close 期間至少有一個時間戳記 (例如 Timestamp::Max) 保持可用。這表示這類計算工具通常無法依賴 SetTimestampOffset(0),必須改為使用 SetNextTimestampBounds() 明確指定時間戳記範圍。