สตรีมแบบเรียลไทม์

การประทับเวลาแบบเรียลไทม์

กราฟเครื่องคำนวณ 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 ไม่ได้ส่งการอัปเดตขอบเขตการประทับเวลาของ B สำหรับ alpha B จะยังคงรอให้แพ็กเก็ตมาถึงใน alpha ในขณะเดียวกัน คิวแพ็กเก็ตของ foo จะรวบรวมแพ็กเก็ตที่ T, T+1 และอื่นๆ

หากต้องการแสดงผลแพ็กเก็ตในสตรีม เครื่องคำนวณจะใช้ฟังก์ชัน API CalculatorContext::Outputs และ OutputStream::Add หากต้องการแสดงผลการประทับเวลาที่ผูกกับสตรีมแทน เครื่องคำนวณสามารถใช้ฟังก์ชัน API CalculatorContext::Outputs และ CalculatorContext::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);

การตั้งค่านี้มีข้อดีคือการเผยแพร่ขอบเขตการประทับเวลาโดยอัตโนมัติ แม้ว่าจะมีเพียงขอบเขตของการประทับเวลามาถึงและระบบจะไม่เรียกใช้ Calculator::Process ก็ตาม

3. ระบุ ProcessTimestampBounds() เพื่อเรียก Calculator::Process สำหรับ "การประทับเวลาที่ตกลงแล้ว" ใหม่แต่ละรายการได้ โดยที่ "การประทับเวลาที่ชำระแล้ว" คือการประทับเวลาสูงสุดใหม่ใต้ขอบเขตของการประทับเวลาปัจจุบัน หากไม่มี ProcessTimestampBounds() ระบบจะเรียกใช้ Calculator::Process กับแพ็กเก็ตขาเข้าตั้งแต่ 1 แพ็กขึ้นไปเท่านั้น

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 เมื่อสร้างแพ็กเก็ตด้านข้างของอินพุตที่จำเป็นทั้งหมดแล้ว คุณระบุแพ็กเก็ตด้านข้างได้โดยใช้แอปพลิเคชันที่อยู่รอบๆ หรือโดย "เครื่องคำนวณแพ็กเก็ตด้านข้าง" ภายในกราฟ คุณระบุแพ็กเกตด้านข้างจากนอกกราฟได้โดยใช้ CalculatorGraph::Initialize และ CalculatorGraph::StartRun ของ API เครื่องคำนวณระบุแพ็กเก็ตด้านข้างได้ภายในกราฟโดยใช้ CalculatorGraphConfig::OutputSidePackets และ OutputSidePacket::Set

เครื่องคิดเลข::การปิดจะเรียกใช้เมื่อสตรีมอินพุตทั้งหมดเปลี่ยนเป็น Done โดยการปิดหรือถึงการประทับเวลาที่มีขอบเขต Timestamp::Done

หมายเหตุ: หากกราฟใช้เครื่องคำนวณที่รอดำเนินการทั้งหมดจนเสร็จและกลายเป็น Done ก่อนสตรีมบางรายการจะกลายเป็น Done ทาง MediaPipe จะเรียกใช้ Calculator::Close ที่เหลืออยู่เพื่อให้เครื่องคำนวณทั้งหมดสร้างผลลัพธ์ขั้นสุดท้ายได้

การใช้ TimestampOffset จะมีผลบางอย่างต่อ Calculator::Close เครื่องคำนวณที่ระบุ SetTimestampOffset(0) จะใช้สัญญาณการออกแบบว่าสตรีมเอาต์พุตทั้งหมดถึง Timestamp::Done เมื่อสตรีมอินพุตทั้งหมดถึง Timestamp::Done แล้ว ดังนั้นจึงไม่สามารถเอาต์พุตเพิ่มเติมได้ ซึ่งจะช่วยป้องกันไม่ให้เครื่องคำนวณดังกล่าวส่งแพ็กเก็ตใดๆ ระหว่าง Calculator::Close หากเครื่องคำนวณต้องสร้างแพ็กเก็ตสรุประหว่าง Calculator::Close Calculator::Process ต้องระบุขอบเขตการประทับเวลาเพื่อให้การประทับเวลาอย่างน้อย 1 รายการ (เช่น Timestamp::Max) ยังคงใช้งานได้ระหว่าง Calculator::Close ซึ่งหมายความว่าโดยปกติแล้วเครื่องคำนวณดังกล่าวจะใช้ SetTimestampOffset(0) ไม่ได้ และต้องระบุขอบเขตการประทับเวลาอย่างชัดแจ้งโดยใช้ SetNextTimestampBounds() แทน