Streaming Real-time

Stempel waktu real-time

Grafik kalkulator MediaPipe sering digunakan untuk memproses streaming frame video atau audio untuk aplikasi interaktif. Framework MediaPipe hanya mengharuskan paket berturut-turut diberi stempel waktu yang meningkat secara monoton. Berdasarkan konvensi, kalkulator dan grafik real-time menggunakan waktu perekaman atau waktu presentasi setiap frame sebagai stempel waktunya, dengan setiap stempel waktu menunjukkan mikrodetik sejak Jan/1/1970:00:00:00. Hal ini memungkinkan paket dari berbagai sumber diproses dalam urutan yang konsisten secara global.

Penjadwalan real-time

Biasanya, setiap Kalkulator berjalan segera setelah semua paket inputnya selama stempel waktu tertentu tersedia. Biasanya, hal ini terjadi ketika kalkulator selesai memproses frame sebelumnya, dan setiap kalkulator yang menghasilkan inputnya telah selesai memproses frame saat ini. Penjadwal MediaPipe memanggil setiap kalkulator segera setelah kondisi ini terpenuhi. Lihat Sinkronisasi untuk detail selengkapnya.

Batas stempel waktu

Jika tidak menghasilkan paket output apa pun untuk stempel waktu tertentu, kalkulator dapat menghasilkan "batas stempel waktu" yang menunjukkan bahwa tidak ada paket yang akan dihasilkan untuk stempel waktu tersebut. Indikasi ini diperlukan agar kalkulator downstream dapat berjalan pada stempel waktu tersebut, meskipun tidak ada paket yang diterima untuk aliran tertentu untuk stempel waktu tersebut. Hal ini sangat penting untuk grafik real-time dalam aplikasi interaktif, karena setiap kalkulator harus mulai memproses sesegera mungkin.

Pertimbangkan grafik seperti berikut:

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

Misalkan: pada stempel waktu T, node A tidak mengirim paket dalam stream output-nya alpha. Node B mendapatkan paket dalam foo pada stempel waktu T dan menunggu paket dalam alpha pada stempel waktu T. Jika A tidak mengirim B pembaruan terikat stempel waktu untuk alpha, B akan terus menunggu paket tiba di alpha. Sementara itu, antrean paket foo akan mengumpulkan paket di T, T+1, dan seterusnya.

Untuk menghasilkan paket pada stream, kalkulator menggunakan fungsi API CalculatorContext::Outputs dan OutputStream::Add. Sebagai gantinya, untuk menghasilkan stempel waktu yang terikat pada aliran data, kalkulator dapat menggunakan fungsi API CalculatorContext::Outputs dan CalculatorContext::SetNextTimestampBound. Batas yang ditentukan adalah stempel waktu terendah yang diizinkan untuk paket berikutnya pada aliran output yang ditentukan. Ketika tidak ada paket yang dihasilkan, kalkulator biasanya akan melakukan sesuatu seperti:

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

Fungsi Timestamp::NextAllowedInStream menampilkan stempel waktu berturut-turut. Misalnya, Timestamp(1).NextAllowedInStream() == Timestamp(2).

Menerapkan batas stempel waktu

Kalkulator yang akan digunakan dalam grafik real-time perlu menentukan batas stempel waktu output berdasarkan batas stempel waktu input agar kalkulator downstream dijadwalkan dengan segera. Pola umumnya adalah kalkulator menghasilkan paket {i> output<i} dengan stempel waktu yang sama dengan paket inputnya. Dalam hal ini, cukup meng-output paket pada setiap panggilan ke Calculator::Process sudah cukup untuk menentukan batas stempel waktu output.

Namun, kalkulator tidak diperlukan untuk mengikuti pola umum ini untuk stempel waktu output, kalkulator tersebut hanya diperlukan untuk memilih stempel waktu output yang meningkat secara monoton. Akibatnya, kalkulator tertentu harus menghitung batas stempel waktu secara eksplisit. MediaPipe menyediakan beberapa alat untuk menghitung stempel waktu yang sesuai untuk setiap kalkulator.

1. SetNextTimestampBound() dapat digunakan untuk menentukan batas stempel waktu, t + 1, untuk streaming output.

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

Atau, paket kosong dengan stempel waktu t dapat dibuat untuk menentukan t + 1 terikat stempel waktu.

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

Batas stempel waktu stream input ditunjukkan oleh paket atau paket kosong pada stream input.

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

2. TimestampOffset() dapat ditentukan untuk otomatis menyalin stempel waktu yang terikat dari aliran input ke aliran output.

cc->SetTimestampOffset(0);

Setelan ini memiliki keuntungan dalam menerapkan batas stempel waktu secara otomatis, meskipun hanya batas stempel waktu yang tiba dan Calculator::Process tidak dipanggil.

3. ProcessTimestampBounds() dapat ditentukan untuk memanggil Calculator::Process untuk setiap "stempel waktu penyelesaian" baru, dengan "stempel waktu yang telah ditetapkan" adalah stempel waktu tertinggi yang baru di bawah batas stempel waktu saat ini. Tanpa ProcessTimestampBounds(), Calculator::Process hanya dipanggil dengan satu atau beberapa paket yang tiba.

cc->SetProcessTimestampBounds(true);

Setelan ini memungkinkan kalkulator melakukan penghitungan dan penerapan batas stempel waktunya sendiri, meskipun hanya stempel waktu input yang diperbarui. Stempel waktu ini dapat digunakan untuk mereplikasi efek TimestampOffset(), tetapi juga dapat digunakan untuk menghitung batasan stempel waktu yang memperhitungkan faktor tambahan.

Misalnya, untuk mereplikasi SetTimestampOffset(0), kalkulator dapat melakukan hal berikut:

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

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

Penjadwalan Kalkulator::Buka dan Kalkulator::Tutup

Calculator::Open dipanggil saat semua paket samping input yang diperlukan telah dibuat. Paket samping input dapat disediakan oleh aplikasi yang menyertakannya atau dengan "kalkulator paket samping" di dalam grafik. Paket samping dapat ditentukan dari luar grafik menggunakan CalculatorGraph::Initialize dan CalculatorGraph::StartRun API. Paket samping dapat ditentukan oleh kalkulator dalam grafik menggunakan CalculatorGraphConfig::OutputSidePackets dan OutputSidePacket::Set.

Kalkulator::Close dipanggil saat semua aliran input telah menjadi Done dengan ditutup atau mencapai stempel waktu Timestamp::Done yang terikat.

Catatan: Jika grafik menyelesaikan semua eksekusi kalkulator yang tertunda dan menjadi Done, sebelum beberapa streaming menjadi Done, MediaPipe akan memanggil sisa panggilan ke Calculator::Close, sehingga setiap kalkulator dapat menghasilkan output akhirnya.

Penggunaan TimestampOffset memiliki beberapa implikasi untuk Calculator::Close. Kalkulator yang menentukan SetTimestampOffset(0) akan memberi sinyal bahwa semua aliran output-nya telah mencapai Timestamp::Done saat semua aliran inputnya telah mencapai Timestamp::Done, sehingga tidak ada output lebih lanjut yang memungkinkan. Hal ini mencegah kalkulator semacam itu memunculkan paket apa pun selama Calculator::Close. Jika kalkulator perlu menghasilkan paket ringkasan selama Calculator::Close, Calculator::Process harus menentukan batas stempel waktu sehingga setidaknya satu stempel waktu (seperti Timestamp::Max) tetap tersedia selama Calculator::Close. Ini berarti kalkulator semacam itu biasanya tidak dapat mengandalkan SetTimestampOffset(0) dan harus menentukan batas stempel waktu secara eksplisit menggunakan SetNextTimestampBounds().