การประทับเวลาแบบเรียลไทม์
กราฟเครื่องคำนวณ 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()
แทน