عدد اللقطات في الثانية

تسمح واجهة برمجة التطبيقات لعدد اللقطات في الثانية للتطبيقات بإعلام نظام Android الأساسي بالإطار المقصود. يتوفّر في التطبيقات التي تستهدف الإصدار 11 من نظام التشغيل Android (المستوى 30 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث. عادةً، لا تتيح معظم الأجهزة سوى معدل تحديث واحد للشاشة، 60 هرتز عادةً، لكن هذا يتغير. تتوافق العديد من الأجهزة الآن مع معدلات التحديث مثل 90 هرتز أو 120 هرتز توافق بعض الأجهزة مع معدّل التحديث السلس. مفاتيح التبديل، بينما يعرض البعض الآخر شاشة سوداء لفترة وجيزة، وتستمر عادةً لمدة ثانية.

إن الغرض الأساسي من واجهة برمجة التطبيقات هو تمكين التطبيقات من الاستفادة بشكل أفضل من جميع معدلات تحديث الشاشة المتوافقة. على سبيل المثال، عند تشغيل تطبيق لفيديو بتردد 24 هرتز قد يؤدي استدعاء setFrameRate() إلى تغيير الشاشة في الجهاز. معدل التحديث من 60 هرتز إلى 120 هرتز. يتيح معدل التحديث الجديد هذا الحصول على تشغيل فيديو 24 هرتز بدون اهتزاز، بدون الحاجة إلى السحب بنسبة 3:2 كما هو الحال مطلوب لتشغيل الفيديو نفسه على شاشة بتردد 60 هرتز. يؤدي هذا إلى تجربة مستخدم أفضل المستخدم.

الاستخدام الأساسي

يوفّر Android طرقًا عديدة للوصول إلى الأسطح والتحكم فيها، لذلك هناك عدة إصدارات من واجهة برمجة تطبيقات setFrameRate(). يأخذ كل إصدار من واجهة برمجة التطبيقات المعلمات نفسها وتعمل بنفس طريقة عمل المعلَمات الأخرى:

لا يحتاج التطبيق إلى مراعاة معدلات تحديث الشاشة الفعلية المعتمدة، والذي يمكن الحصول عليه من خلال استدعاء Display.getSupportedModes()، للاتصال بـ setFrameRate() بأمان. على سبيل المثال، حتى إذا كان الجهاز يتوافق مع 60 هرتز، ويمكنك الاتصال بـ setFrameRate() مع ذِكر عدد اللقطات في الثانية الذي يفضّله تطبيقك. ستظل الأجهزة التي لا تتطابق بشكل أفضل مع عدد اللقطات في الثانية للتطبيق معدّل تحديث الشاشة الحالي

لمعرفة ما إذا كانت المكالمة إلى setFrameRate() تؤدي إلى تغيير في إعادة تحميل الشاشة تقييم التطبيق، والتسجيل لعرض إشعارات التغيير عبر الاتصال DisplayManager.registerDisplayListener() أو AChoreographer_registerRefreshRateCallback().

عند استدعاء الدالة setFrameRate()، من الأفضل ضبط عدد اللقطات في الثانية بدقة بدلاً من من التقريب إلى عدد صحيح. على سبيل المثال، عند عرض فيديو تم تسجيله في 29.97 هرتز، يمكنك اجتياز 29.97 بدلاً من التقريب إلى 30.

بالنسبة إلى تطبيقات الفيديو، يجب ضبط معلَمة التوافق التي تم ضبطها على setFrameRate(). إلى Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE لمنح تلميح إضافي نظام Android الأساسي الذي سيستخدمه التطبيق القائمة المنسدلة للتكيف مع نظام Android الأساسي معدّل تحديث الشاشة (مما سيؤدي إلى حدوث اهتزاز).

في بعض السيناريوهات، سيتوقف عرض الفيديو عن إرسال الإطارات، ولكنه سيبقى معروضًا. على الشاشة لبعض الوقت. وتتضمن السيناريوهات الشائعة عند التشغيل إلى نهاية الفيديو أو عندما يوقف المستخدم التشغيل مؤقتًا. في هذه الحالات، طلب setFrameRate() مع ضبط معلَمة عدد اللقطات في الثانية على 0 لمحو مساحة العرض إعادة ضبط عدد اللقطات في الثانية على القيمة التلقائية جارٍ محو إعداد عدد اللقطات في الثانية مثل هذا ليس ضروريًا عند تدمير السطح أو عندما مخفية لأن المستخدم ينتقل إلى تطبيق مختلف. محو عدد اللقطات في الثانية فقط عندما يظل السطح مرئيًا بدون استخدامه.

تبديل عدد اللقطات في الثانية غير السلس

في بعض الأجهزة، قد يؤدي التبديل بين معدل التحديث إلى انقطاعات مرئية، مثل اللون الأسود. الشاشة لمدة ثانية أو اثنتين. ويحدث هذا عادةً في أجهزة الاستقبال الرقمية ولوحات التلفزيون والأجهزة المشابهة. لا يبدِّل إطار عمل Android الأوضاع تلقائيًا. عندما يبدأ Surface.setFrameRate() يتم استدعاء واجهة برمجة التطبيقات لتجنب مثل هذه المقاطعات المرئية.

يفضل بعض المستخدمين مقاطعة بصرية في البداية نهاية مقاطع الفيديو الأطول. يتيح هذا الإجراء مطابقة معدّل تحديث الشاشة. عدد اللقطات في الثانية للفيديو، وتجنَّب عناصر تحويل عدد اللقطات في الثانية، مثل 3:2. وأداة الاهتزاز المنسدلة لتشغيل الفيلم.

ولهذا السبب، يمكن تفعيل مفاتيح تبديل معدل التحديث غير السلس إذا كانت موافقة المستخدمين والتطبيقات:

ننصحك باستخدام CHANGE_FRAME_RATE_ALWAYS دائمًا. بالنسبة إلى الفيديوهات الطويلة، مثل الأفلام هذا لأن فائدة مطابقة أن يكون عدد اللقطات في الثانية في الفيديو أكبر من مدة الانقطاع التي تحدث عند تغيير معدل التحديث.

اقتراحات إضافية

اتبع هذه التوصيات للسيناريوهات الشائعة.

مساحات عرض متعددة

تم تصميم نظام Android الأساسي للتعامل بشكل صحيح مع السيناريوهات التي مساحات عرض متعدّدة ذات إعدادات مختلفة لعدد اللقطات في الثانية عندما يحتوي تطبيقك على العديد من الأسطح التي تحتوي على معدلات عرض إطارات مختلفة، اطلب setFrameRate() بالأرقام الصحيحة عدد اللقطات في الثانية لكل مساحة عرض حتى إذا كان الجهاز يشغِّل تطبيقات متعددة في باستخدام وضع "تقسيم الشاشة" أو وضع "نافذة ضمن النافذة"، يمكن لكل تطبيق إجراء مكالمة setFrameRate() لمساحات العرض الخاصة بهم.

لا يتغيّر النظام الأساسي لعدد اللقطات في الثانية للتطبيق

حتى إذا كان الجهاز متوافقًا مع عدد اللقطات في الثانية الذي يحدّده التطبيق في طلب setFrameRate()، في بعض الحالات لا يمكن للجهاز تبديل الشاشة إليها. معدّل التحديث هذا على سبيل المثال، قد يختلف السطح ذي الأولوية الأعلى عدد اللقطات في الثانية، أو قد يكون الجهاز في وضع توفير شحن البطارية فرض قيود على معدّل تحديث الشاشة للحفاظ على مستوى شحن البطارية). يجب أن يظل التطبيق تعمل بشكل صحيح عندما لا يبدّل الجهاز معدل تحديث الشاشة إلى إعداد عدد اللقطات في الثانية في التطبيق، حتى إذا تم تبديل الجهاز ضمن المعدّل العادي الظروف.

يعود إلى التطبيق تحديد كيفية الاستجابة عند معدَّل تحديث الشاشة. لا يتطابق مع عدد اللقطات في الثانية للتطبيق. بالنسبة إلى الفيديو، يتم تثبيت عدد اللقطات في الثانية على عدد اللقطات في الثانية الفيديو المصدر، وستكون القائمة المنسدلة مطلوبة لعرض محتوى الفيديو. حاسمة قد تختار اللعبة تشغيل اللعبة بمعدل إعادة تحميل الشاشة بدلاً من مع الاحتفاظ بعدد اللقطات الذي يفضّله في الثانية. يجب ألا يغيّر التطبيق القيمة التي يعرضها يتم نقله إلى setFrameRate() استنادًا إلى نشاط المنصة. يجب أن يبقى الجهاز مضبوطًا. إلى عدد اللقطات في الثانية المفضَّل للتطبيق، بغض النظر عن طريقة تعامل التطبيق مع الحالات التي عدم توافق النظام الأساسي مع طلب التطبيق. بهذه الطريقة، إذا كان الجهاز للسماح باستخدام معدلات إعادة تحميل إضافية للشاشة، لدى التطبيق المعلومات الصحيحة للتبديل إلى الإطار المفضل للتطبيق المعدل.

في الحالات التي يتعذر فيها تشغيل التطبيق أو يتعذّر تشغيله بمعدل تحديث الشاشة، يغير التطبيق تحديد الطوابع الزمنية للعرض التقديمي لكل إطار، وذلك باستخدام أحد آليات النظام الأساسي لضبط الطوابع الزمنية للعرض التقديمي:

يؤدي استخدام هذه الطوابع الزمنية إلى منع المنصة من عرض إطار التطبيق أيضًا. في وقت مبكر، مما قد يؤدي إلى إحداث اهتزاز غير ضروري. الاستخدام الصحيح للإطار الطوابع الزمنية للعرض التقديمي أمرًا صعبًا بعض الشيء. بالنسبة إلى الألعاب، يمكنك الاطّلاع على دليل سرعة تحميل الإطارات لمزيد من المعلومات حول تجنب الهرم، وفكّر في استخدام مكتبة سرعة إطارات Android.

في بعض الحالات، قد يبدّل النظام الأساسي إلى مضاعفات عدد اللقطات في الثانية الذي يستخدمه التطبيق. المحددة في setFrameRate(). على سبيل المثال، قد يتصل أحد التطبيقات بالرقم setFrameRate() مع 60 هرتز وقد يبدّل الجهاز الشاشة إلى 120 هرتز. أحد الأسباب التي قد تجعل إذا كان تطبيق آخر يتضمّن سطحًا تم ضبط عدد اللقطات في الثانية عليه على 24 هرتز. ضِمن في هذه الحالة، فإن تشغيل الشاشة بتردد 120 هرتز سيسمح لكل من سطح 60 هرتز سطح 24 هرتز للتشغيل بدون الحاجة إلى السحب للأسفل.

عندما يتم تشغيل الشاشة بمعدّل مضاعف لعدد اللقطات في الثانية في التطبيق، يمكن للتطبيق تحديد الطوابع الزمنية للعرض التقديمي لكل إطار لتجنّب الحاجة إلى ذلك اهتزاز. بالنسبة إلى الألعاب، تُعد مكتبة Android Frame Pacing مفيدة تعيين الطوابع الزمنية للعرض التقديمي للإطار.

setFrameRate() مقابل PreferredDisplayModeId

WindowManager.LayoutParams.preferredDisplayModeId هو طريقة أخرى يمكن للتطبيقات من خلالها أن توضِّح للنظام الأساسي عدد اللقطات في الثانية. بعض الإشعارات فقط في تغيير معدل تحديث الشاشة بدلاً من تغيير إعدادات وضع العرض، مثل درجة دقة العرض. بشكل عام، استخدم setFrameRate() بدلاً من preferredDisplayModeId setFrameRate() أسهل في الاستخدام لأن التطبيق لا يحتاج إلى البحث في قائمة بأوضاع العرض للعثور على وضع بعدد لقطات محدد في الثانية.

يمنح setFrameRate() المنصة المزيد من الفرص لاختيار نموذج متوافق عدد اللقطات في الثانية في السيناريوهات التي تكون فيها هناك مساحات عرض متعددة يتم تشغيلها بمعدل عرض إطارات مختلف. على سبيل المثال، ضع في اعتبارك سيناريو يكون فيه تطبيقان تشغيل فيديو في وضع تقسيم الشاشة على هاتف Pixel 4 حيث يشغّل أحد التطبيقات فيديو بتردد 24 هرتز والآخر يعرض للمستخدم قائمة قابلة للتمرير يتوافق هاتف Pixel 4 مع اثنين معدلات تحديث الشاشة: 60 هرتز و90 هرتز. باستخدام واجهة برمجة التطبيقات preferredDisplayModeId يجب أن يختار عرض الفيديو إما 60 هرتز أو 90 هرتز. من خلال الاتصال setFrameRate() مع 24 هرتز، يمنح سطح الفيديو المنصة مساحة أكبر معلومات حول عدد اللقطات في الثانية للفيديو المصدر، ما يتيح للمنصة اختَر 90 هرتز لمعدّل تحديث الشاشة، وهو أفضل من 60 هرتز في هذه الحالة. السيناريو.

في المقابل، هناك سيناريوهات يجب فيها استخدام السمة preferredDisplayModeId. بدلاً من setFrameRate()، كما يلي:

  • فإذا أراد التطبيق تغيير درجة الدقة أو إعدادات وضع العرض الأخرى، استخدام preferredDisplayModeId.
  • لن تبدِّل المنصة أوضاع العرض إلا استجابةً لاستدعاء setFrameRate() إذا كان مفتاح الوضع خفيفًا ومن غير المرجّح أن يتم تغييره ملحوظة للمستخدم. في حال كان التطبيق يفضّل تغيير خيار إعادة تحميل الشاشة حتى إذا احتاجت إلى التبديل إلى الوضع الثقيل (على سبيل المثال، على Android TV )، استخدِم preferredDisplayModeId.
  • التطبيقات التي لا يمكنها التعامل مع الشاشة التي تعمل في إطار متعدد لإطار التطبيق الذي يتطلب ضبط طوابع زمنية للعرض التقديمي على كل إطار، استخدام preferredDisplayModeId.

setFrameRate() مقابل PreferredRefreshRate

WindowManager.LayoutParams#preferredRefreshRate تحدد العدد المفضّل للقطات في الثانية في نافذة التطبيق، ويطبّق المعدل على كل مساحات العرض في النافذة يجب أن يحدد التطبيق خياراته المفضّلة عدد اللقطات في الثانية بغض النظر عن معدلات التحديث المتوافقة مع الجهاز، على غرار setFrameRate()، لمنح أداة الجدولة تلميحًا أفضل عن الغرض من التطبيق عدد اللقطات في الثانية

يتم تجاهل preferredRefreshRate على مساحات العرض التي تستخدم setFrameRate(). ضِمن الاستخدام العام setFrameRate() إن أمكن.

bestRefreshRate مقابل PreferredDisplayModeId

إذا كانت التطبيقات تريد تغيير معدّل التحديث المفضّل فقط، من المفضّل استخدامها. preferredRefreshRate، بدلاً من preferredDisplayModeId

تجنُّب استدعاء setFrameRate() بشكل متكرر جدًا

رغم أن المكالمة setFrameRate() ليست مكلفة للغاية من حيث الأداء، يجب أن تتجنّب التطبيقات الاتصال برقم setFrameRate() كل إطار أو عدة مرات لكل إطار ثانيًا. من المرجح أن تؤدي المكالمات إلى setFrameRate() إلى تغيير في معدّل تحديث الشاشة، ما قد يؤدي إلى انخفاض عدد اللقطات في الثانية أثناء عملية الانتقال. يجب أن تعرف عدد اللقطات في الثانية الصحيح مسبقًا setFrameRate() مرة واحدة.

استخدام الألعاب أو تطبيقات أخرى غير الفيديو

وعلى الرغم من أنّ الفيديو هو حالة الاستخدام الأساسية لواجهة برمجة تطبيقات setFrameRate()، يمكن أن يكون استخدامه للتطبيقات الأخرى. على سبيل المثال، اللعبة التي لا تهدف إلى تحقيق سعر أعلى من بتردد 60 هرتز (لتقليل استخدام الطاقة والحصول على جلسات تشغيل أطول) يمكن الاتصال Surface.setFrameRate(60, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT) في هذه الدورة، فإن الجهاز الذي يعمل بمعدل 90 هرتز بشكل افتراضي سيتم تشغيله بسرعة 60 هرتز، في حين أن اللعبة نشطة، وهذا يؤدي إلى تجنب الاهتزاز الذي قد يحدث لولا ذلك في حالة تشغيل اللعبة على 60 هرتز مع تشغيل الشاشة على 90 هرتز.

استخدام iframe_RATE_COMPATIBILITY_FIXED_SOURCE

"FRAME_RATE_COMPATIBILITY_FIXED_SOURCE" مخصّص لتطبيقات الفيديو فقط. بالنسبة استخدام المحتوى بخلاف الفيديوهات، يُرجى استخدام FRAME_RATE_COMPATIBILITY_DEFAULT.

اختيار استراتيجية لتغيير عدد اللقطات في الثانية

  • ننصح بشدّة بأن تضمّ هذه التطبيقات، عند عرض فيديوهات طويلة الأمد، مثل الأفلام، اتصل setFrameRate(لقطات في الثانية, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS) حيث يكون عدد اللقطات في الثانية هو عدد اللقطات في الثانية للفيديو
  • ننصح بشدة بعدم اتصال التطبيقات بالرقم setFrameRate() من خلال الرقم CHANGE_FRAME_RATE_ALWAYS. عندما تتوقع أن يستمر تشغيل الفيديو عدة دقائق أو أقل.

مثال على دمج تطبيقات تشغيل الفيديو

ننصحك باتّباع الخطوات التالية لدمج مفاتيح تبديل معدّل إعادة التحميل في التطبيقات التي تشغّل الفيديو:

  1. تحديد الخيار "changeFrameRateStrategy":
    1. في حال تشغيل فيديو طويل، مثل فيلم، استخدِم MATCH_CONTENT_FRAMERATE_ALWAYS.
    2. في حال تشغيل فيديو قصير، مثل مقطع دعائي، استخدِم CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS.
  2. إذا كانت قيمة السمة changeFrameRateStrategy هي CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS ، انتقِل إلى الخطوة 4.
  3. اكتشاف ما إذا كان سيتم تبديل معدّل التحديث غير السلس أم لا من خلال التحقّق أن كلتا هاتين المواتين صحيحتان:
    1. لا يمكن التبديل في الوضع السلس من معدّل التحديث الحالي ( ونسميه C) بعدد اللقطات في الثانية للفيديو (لنطلق عليه V). سيؤدي هذا إلى هي الحالة إذا كان C وV مختلفين Display.getMode().getAlternativeRefreshRates لا يحتوي على مضاعف لـ V.
    2. وافق المستخدم على إجراء تغييرات غير سلسة في معدّل إعادة التحميل. يمكنك اكتشاف من خلال التحقّق ممّا إذا كان DisplayManager.getMatchContentFrameRateUserPreference إرجاع MATCH_CONTENT_FRAMERATE_ALWAYS
  4. إذا كان التبديل سلسًا، عليك اتّباع الخطوات التالية:
    1. الاتصال بالرقم setFrameRate وتمرير fps، FRAME_RATE_COMPATIBILITY_FIXED_SOURCE، وchangeFrameRateStrategy، حيث يشير fps إلى عدد اللقطات في الثانية للفيديو.
    2. بدء تشغيل الفيديو
  5. في حال كان على وشك الحدوث تغيير في الوضع غير السلس، عليك إجراء ما يلي:
    1. عرض تجربة المستخدم لإعلام المستخدم. لاحظ أننا نوصي بتنفيذ طريقة أن يتجاهل المستخدم تجربة المستخدم هذه وتخطي التأخير الإضافي في الخطوة 5 (د). هذا هو لأن التأخير الذي ننصح به أكبر من اللازم على الشاشات التي تعرض أوقات تبديل أسرع.
    2. الاتصال بالرقم setFrameRate وتمرير fps، FRAME_RATE_COMPATIBILITY_FIXED_SOURCE، وCHANGE_FRAME_RATE_ALWAYS، حيث يكون fps هو عدد اللقطات في الثانية للفيديو.
    3. انتظار onDisplayChanged معاودة الاتصال.
    4. انتظِر لمدة ثانيتين إلى أن تكتمل عملية تبديل الوضع.
    5. بدء تشغيل الفيديو

في ما يلي الرمز الزائف لإتاحة التبديل السلس فقط:

SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
transaction.setFrameRate(surfaceControl,
    contentFrameRate,
    FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
    CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
transaction.apply();
beginPlayback();

في ما يلي الرمز الزائف الذي يمكن استخدامه لإتاحة التبديل السلس وغير السلس كما هو موضّح أعلاه:

SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
if (isSeamlessSwitch(contentFrameRate)) {
  transaction.setFrameRate(surfaceControl,
      contentFrameRate,
      FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
      CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
  transaction.apply();
  beginPlayback();
} else if (displayManager.getMatchContentFrameRateUserPreference()
      == MATCH_CONTENT_FRAMERATE_ALWAYS) {
  showRefreshRateSwitchUI();
  sleep(shortDelaySoUserSeesUi);
  displayManager.registerDisplayListener();
  transaction.setFrameRate(surfaceControl,
      contentFrameRate,
      FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
      CHANGE_FRAME_RATE_ALWAYS);
  transaction.apply();
  waitForOnDisplayChanged();
  sleep(twoSeconds);
  hideRefreshRateSwitchUI();
  beginPlayback();
}