রিয়েল-টাইম স্ট্রীম

রিয়েল-টাইম টাইমস্ট্যাম্প

মিডিয়াপাইপ ক্যালকুলেটর গ্রাফগুলি প্রায়ই ইন্টারেক্টিভ অ্যাপ্লিকেশনগুলির জন্য ভিডিও বা অডিও ফ্রেমের স্ট্রিমগুলি প্রক্রিয়া করতে ব্যবহৃত হয়। 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 টাইমস্ট্যাম্প T তে foo তে একটি প্যাকেট পায় এবং টাইমস্ট্যাম্প Talpha তে একটি প্যাকেটের জন্য অপেক্ষা করছে। 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. ইনপুট স্ট্রীম থেকে আউটপুট স্ট্রীমে আবদ্ধ টাইমস্ট্যাম্প স্বয়ংক্রিয়ভাবে অনুলিপি করার জন্য টাইমস্ট্যাম্পঅফসেট() নির্দিষ্ট করা যেতে পারে।

cc->SetTimestampOffset(0);

এই সেটিংটিতে টাইমস্ট্যাম্প সীমানা স্বয়ংক্রিয়ভাবে প্রচার করার সুবিধা রয়েছে, এমনকি যখন শুধুমাত্র টাইমস্ট্যাম্প সীমানা আসে এবং ক্যালকুলেটর::প্রক্রিয়া চালু করা হয় না।

3. Calculator::Process প্রতিটি নতুন "সেটেলড টাইমস্ট্যাম্প" চালু করার জন্য ProcessTimestampBounds() নির্দিষ্ট করা যেতে পারে, যেখানে "সেটেলড টাইমস্ট্যাম্প" হল বর্তমান টাইমস্ট্যাম্প সীমার নিচের নতুন সর্বোচ্চ টাইমস্ট্যাম্প। 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::Initialize এবং CalculatorGraph::StartRun ব্যবহার করে গ্রাফের বাইরে থেকে সাইড-প্যাকেটগুলি নির্দিষ্ট করা যেতে পারে। CalculatorGraphConfig::OutputSidePackets এবং OutputSidePacket::Set ব্যবহার করে গ্রাফের মধ্যে ক্যালকুলেটর দ্বারা সাইড প্যাকেটগুলি নির্দিষ্ট করা যেতে পারে।

ক্যালকুলেটর::ক্লোজ আহ্বান করা হয় যখন সমস্ত ইনপুট স্ট্রীম বন্ধ হয়ে বা টাইমস্ট্যাম্প বাউন্ড Timestamp::Done পৌঁছানোর মাধ্যমে Done হয়ে যায়।

দ্রষ্টব্য: যদি গ্রাফটি সমস্ত মুলতুবি থাকা ক্যালকুলেটর সম্পাদন শেষ করে এবং কিছু স্ট্রীম Done হওয়ার আগে Done হয়ে যায়, তাহলে MediaPipe বাকি কলগুলি Calculator::Close এ আহ্বান করবে, যাতে প্রতিটি ক্যালকুলেটর তার চূড়ান্ত আউটপুট তৈরি করতে পারে।

TimestampOffset ব্যবহারে Calculator::Close এর জন্য কিছু প্রভাব রয়েছে। SetTimestampOffset(0) নির্দিষ্ট করা একটি ক্যালকুলেটর ডিজাইনের মাধ্যমে সংকেত দেবে যে এর সমস্ত আউটপুট স্ট্রীম Timestamp::Done যখন এর সমস্ত ইনপুট স্ট্রীম Timestamp::Done , এবং তাই আর কোনও আউটপুট সম্ভব নয়৷ এটি এই ধরনের ক্যালকুলেটরকে Calculator::Close সময় কোনো প্যাকেট নির্গত হতে বাধা দেয়। যদি Calculator::Close সময় একটি ক্যালকুলেটরকে একটি সারাংশ প্যাকেট তৈরি করতে হয়, Calculator::Process অবশ্যই টাইমস্ট্যাম্প সীমা নির্দিষ্ট করতে হবে যাতে কমপক্ষে একটি টাইমস্ট্যাম্প (যেমন Timestamp::Max ) Calculator::Close সময় উপলব্ধ থাকে। এর মানে হল যে এই ধরনের একটি ক্যালকুলেটর সাধারণত SetTimestampOffset(0) এর উপর নির্ভর করতে পারে না এবং এর পরিবর্তে SetNextTimestampBounds() ব্যবহার করে স্পষ্টভাবে টাইমস্ট্যাম্প সীমা নির্দিষ্ট করতে হবে।