Real-time Streams

Real-time timestmaps

Mediapipe calculator 그래프는 interactive 어플리케이션을 위한 비디오 또는 오디오 프레임의 스트림을 처리하는 데 자주 사용됩니다. Mediapipe 프레임워크는 연속적 패킷에 단조롭게 증가하는 타임스탬프를 할당하기만 하면 됩니다. 관례에 따라 실시간 Calculator와 그래프는 기록 시간 또는 각 프레임의 표시 시간을 타임스탬프로 사용하며, 각 타임스탬프는 1월 1일 이후 마이크로초를 나타냅니다.


Real-time shceduling

일반적으로 각 Calculator는 주어진 타임스탬프에 대한 모든 입력 패킷을 사용할 수 있게 되는 즉시 실행됩니다. 일반적으로 이것은 Calculator가 이전 프레임 처리를 완료하고 입력을 생성하는 각 Calculator가 현재 프레임 처리를 완료했을 때 발생합니다. Mediapipe 스케쥴러는 이러한 조건이 충족되는 즉시 각 Calculator를 호출합니다.


Timestamp bounds

Calculator가 주어진 타임스탬프에 대해 출력 패킷을 생성하지 않으면 대신 해당 타임스탬프에 대해 패킷이 새성되지 않음을 나타내는 Timestamp bounds를 출력할 수 있습니다. 이 표시는 해당 타임스탬프의 특정 스트림에 대해 패킷이 도착하지 않은 경우에도 다운스트림 Calculator가 해당 타임스탬프에서 실행되도록 하는데 필요합니다. 이는 각 계산기가 가능한 한 빨리 처리를 시작하는 것이 중요한 interactive 어플리케이션의 실시간 그래프에 특히 중요합니다.

그래프가 다음을 따름을 생각하십시오.

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

가정 : 타임스탬프 T에서 노드 A는 출력 스틀미 알파로 패킷을 보내지 않습니다. 노드 B는 타임스탬프 T에서 foo 패킷을 받고 타임스탬프 T에서 알파 패킷을 기다리고 있습니다. AB에게 알파에 대한 타임스탬프 바운드 업데이트를 보내지 않으면 B는 패킷이 알파로 도착할 때까지 계속 기다립니다. 한편, foo 패킷 큐는 T, T+1 등에서 패킷을 누적합니다.

스트림에서 패킷을 출력하기 위해 Calcualtor는 API 함수 CalculatorContext::OutputsOutputStream::Add를 사용합니다. 대신 스트림에 바인딩된 타임스탬프를 출력하기 위해 Calculator는 API 함수 CalculatorContext::OutputsCalcualtorContext::SetNextTimestmapBound를 사용할 수 있습니다. 지정된 경계는 지정된 출력 스트림 다음 패킷에 대해 허용되는 가장 낮은 타임스탬프입니다. 패킷이 출력되지 않으면 Calcualtor는 일반적으로 다음과 같은 작업을 수행합니다.

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

Timestamp::NextAllowedInStream 함수는 연속적인 타임스탬프를 반환합니다. ex) Timestamp(1).NextAllowedInStream() == Timestamp(2)


Propagating timestamp bound

실시간 그래프에 사용되는 Calculator는 다운스트림 Calculator를 즉시 예약할 수 있도록 입력 타임스탬프 경계를 기반으로 출력 타임스탬프 경게를 정의해야 합니다. 일반적 패턴은 Calculator가 입력 패킷과 동일한 타임스탬프를 가진 패킷을 출력하는 것입니다. 이 경우 Calcualtor::Process를 호출할 때마다 패킷을 출력하는 것만으로도 출력 타임스탬프 경계를 정의하기에 충분합니다.

그러나 Calculator는 출력 타임스탬프에 대해 이 일반적 패턴을 따를 필요가 없으며 단조롭게 증가하는 출력 타임스탬프를 선택하기만 하면 됩니다. 결과적으로 특정 Calculator는 타임스탬프 경계를 명시적으로 계산해야 합니다. 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();
  1. TimestampOffset() 입력 스트림에서 출력 스트림으로 바인딩된 타임스탬프를 자동으로 복사하기 위해 지정할 수 있습니다.
cc->SetTimestampOffset(0);
  1. ProcessTimestampBounds() 는 각각 새로운 정착된 타임스탬프 (현재 타임스탬프 경계 아래 새로운 최고 타임스태믚)에 대해 Calculator::Process를 호출하기 위해 지정할 수 있습니다. ProcessTimestampBoudns() 가 없으면 Calculator::Process는 하나 이상의 도착 패킷으로만 호출됩니다.
cc->SetProcessTimestampBounds(true);

이 설정을 사용하면 입력 타임스탬프만 업데이트된 경우에도 Calculator가 자체 타임스탬프 경계 계산 및 전파를 수행할 수 있습니다. TimestampOffset()의 효과를 복제하는 데 사용할 수 있지만 추가 요소를 고려하는 타임스탬프 경계를 계산하는 데 사용할 수도 있습니다.

예를 들어, SetTimestampOffset(0)을 복제하기 위해 Calculator는 다음을 수행할 수 있습니다.

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

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

Scheduling of Calculator::Open and Calculator::Close

Calculator::Open은 필요한 모든 사이드 패킷이 생성되면 호출됩니다. 입력 사이드 패킷은 인클로징 어플리케이션 또는 그래프 내부의 사이드 패킷 Calculator 에서 제공할 수 있습니다.
API의 CalculatorGraph::InitializeCalculatorGraph::StartRun을 사용해 그래프 외부에서 사이드 패킷을 지정할 수 있습니다.
CalculatorGraphConfig::OutputSidePacketsOutputSidePacket::Set을 사용해 그래프 내 Calculator에서 사이드 패킷을 지정할 수 있습니다.

CalculatorGraph::Close는 모든 입력 스트림이 닫히거나 타임스탬프 바운드 Timestamp::Done에 도달하여 Done이 되면 호출됩니다.

참고 : 그래프가 보류 중인 모든 Calculator 실행을 완료하고 완료되면 일부 스트림이 완료되기 전에 MediaPipe가 Calculator::Close에 대한 나머지 호출을 호출해 모든 Calculator가 최종 출력을 생성할 수 있도록 합니다.

TimestampOffset을 사용하면 Calculator::Close에 몇 가지 의미가 생깁니다. SetTimestampOffset(0)을 지정하는 Calculator는 모든 입력 스트림이 Timestamp::Done에 도달했을 때 모든 출력 스트림이 TimeStamp::Done에 도달했음을 신호로 표시하므로 더 이상의 출력이 불가능합니다. 이렇게 하면 이러한 Calculator가 Calculator::Close동안 패킷을 내보내는 것을 방지할 수 있습니다. Calculator가 Calculator::Close 중에 요약 패킷을 생성해야 하는 경우 Calculator::ProcessCalculator::Close 중에 최소한 하나의 타임스탬프를 사용할 수 있도록 타임스탬프 경계를 지정해야 합니다. 즉, 이러한 Calculator는 일반적으로 SetTimestampOffset(0)에 의존할 수 없으며 대신 SetNextTimestampBounds()를 사용해 명시적으로 타임스탬프 경계를 지정해야 합니다.

+ Recent posts