프레임 속도

프레임 속도 API를 사용하면 앱이 의도한 프레임을 Android 플랫폼에 알릴 수 있습니다. Android 11 (API 수준 30) 이상을 타겟팅하는 앱에서 사용할 수 있습니다. 일반적으로 대부분의 기기는 단일 디스플레이 화면 재생 빈도만 지원했습니다. 그러나 이것은 변화하고 있습니다. 이제 많은 기기에서 추가 화면 재생 빈도(예: 90Hz 또는 120Hz) 일부 기기에서는 원활한 새로고침 빈도 지원 스위치가 있는 반면, 보통 1초 동안 잠시 검은색 화면이 표시되는 경우도 있습니다.

API의 주된 목적은 앱이 모든 종류의 이점을 더 잘 활용할 수 있도록 하는 것입니다. 디스플레이 새로고침 빈도를 설정할 수 있습니다 예를 들어 24Hz 동영상을 재생하는 앱은 setFrameRate()를 호출하면 기기에서 디스플레이가 변경될 수 있습니다. 화면 재생 빈도를 60Hz에서 120Hz로 이 새로운 새로고침 빈도를 사용하면 24Hz 동영상을 흔들림 없이 재생하며 3:2 풀다운 없이 동일한 동영상을 재생하는 데 필요한 최소 사양입니다. 이렇게 하면 경험해 볼 수 있습니다

기본 사용법

Android는 노출 영역에 액세스하고 이를 제어하는 여러 방법을 노출하므로 여러 버전의 setFrameRate() API API의 각 버전은 다른 것과 동일하게 작동합니다.

앱은 실제로 지원되는 디스플레이 화면 재생 빈도를 고려할 필요가 없습니다. 이는 Display.getSupportedModes()님, setFrameRate()를 안전하게 호출하기 위해서입니다. 예를 들어 기기가 60Hz를 지원하는 경우 앱에서 선호하는 프레임 속도로 setFrameRate()를 호출합니다. 앱의 프레임 속도에 더 잘 맞지 않는 기기는 표시할 수 있습니다.

setFrameRate() 호출로 인해 디스플레이 새로고침이 변경되는지 확인하는 방법 비율, 호출로 디스플레이 변경 알림 등록 DisplayManager.registerDisplayListener() 또는 AChoreographer_registerRefreshRateCallback()입니다.

setFrameRate()를 호출할 때는 더 효율적입니다. 예를 들어, 사이트에서 녹화된 동영상을 29.97Hz의 경우, 30으로 반올림하지 않고 29.97로 전달합니다.

동영상 앱의 경우 setFrameRate()에 전달된 호환성 매개변수를 설정해야 합니다. Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE로 설정하여 앱이 일치하지 않는 항목에 적응하기 위해 풀다운을 사용할 Android 플랫폼입니다. 화면 재생 빈도 (떨림이 발생할 수 있음)

일부 시나리오에서는 동영상 표시 경로에서 프레임 제출이 중지되지만 표시될 수 있습니다. 일반적으로 동영상 재생 중에 동영상 끝부분에 도달하거나 사용자가 재생을 일시중지할 때 발생합니다. 이 경우 프레임 속도 매개변수를 0으로 설정하고 setFrameRate()를 호출하여 노출 영역 콘텐츠를 지웁니다. 기본 값으로 다시 설정해야 합니다 프레임 속도 설정 삭제 표면을 파괴하거나 표면을 파괴하거나 사용자가 다른 앱으로 전환했기 때문에 표시되지 않습니다. 프레임 속도 지우기 표면을 사용하지 않고 계속 표시할 때만 설정을 적용할 수 있습니다.

매끄럽지 않은 프레임 속도 스위치

일부 기기에서 화면 재생 빈도 전환 시 검은색 화면과 같은 시각적인 방해 요소가 있을 수 있습니다. 1~2초 정도 화면에 나타납니다. 일반적으로 셋톱 박스, TV 패널, 기타 유사한 기기를 보호합니다. 기본적으로 Android 프레임워크는 모드를 전환하지 않음 Surface.setFrameRate()의 경우 API가 호출됩니다.

일부 사용자는 시작 부분에 시각적인 방해 요소를 긴 동영상의 끝부분 이렇게 하면 디스플레이의 화면 재생 빈도가 3:2와 같은 프레임 속도 변환 아티팩트가 발생하지 않도록 하세요. 영화 재생을 위한 풀다운 떨림입니다.

따라서 화면과 프레임 속도 모두 사용자 및 앱의 수신 동의:

항상 CHANGE_FRAME_RATE_ALWAYS를 사용하는 것이 좋습니다. 긴 형식 동영상에 사용할 수 있습니다. 이는 일치 타겟팅의 이점이 동영상 프레임 속도가 새로고침 빈도

추가 권장사항

일반적인 시나리오에 대한 다음 권장사항을 따르세요.

여러 표면

Android 플랫폼은 특정 Android 또는 다른 운영체제가 존재하는 여러 표면의 프레임 속도 설정이 다를 수 있습니다. 앱에 표면의 프레임 속도가 다른 경우 올바른 값으로 setFrameRate()를 호출합니다. 확인할 수 있습니다 기기에서 여러 앱을 실행 중인 경우에도 한 번만 화면 분할 또는 PIP 모드를 사용하여 각 앱에서 안전하게 setFrameRate()

플랫폼이 앱의 프레임 속도로 변경되지 않음

기기가 앱이 호출에서 지정하는 프레임 속도를 지원하더라도 setFrameRate(), 기기가 디스플레이를 전환하지 않는 경우도 있습니다. 새로고침 빈도를 측정합니다 예를 들어 우선순위가 높은 노출 경로에서는 설정되어 있지 않거나 기기가 절전 모드( 디스플레이 화면 재생 빈도 제한). 앱은 여전히 기기가 디스플레이 화면 재생 빈도를 기기의 프레임 속도가 정상으로 전환되더라도 살펴봤습니다

화면 재생 빈도가 전환될 때 응답하는 방법은 앱에서 결정합니다. 일치하지 않을 때 발생합니다. 동영상의 경우 프레임 속도는 선택해야 하며, 동영상 콘텐츠를 표시하려면 풀다운이 필요합니다. 가 기본 화면 재생 빈도에서 실행되도록 선택할 수 있으며, 기본 프레임 속도를 유지하는 것이 좋습니다 앱에서 값을 변경해서는 안 됩니다. 플랫폼의 기능에 따라 setFrameRate()에 전달합니다. 설정된 상태로 유지되어야 합니다. 기본 프레임 속도보다 속도가 훨씬 빠를 수 있습니다. 플랫폼이 앱의 요청에 맞게 조정되지 않습니다. 이렇게 하면 디스플레이 새로고침 빈도를 추가로 사용할 수 있도록 하려면 플랫폼에 앱의 기본 프레임으로 전환하기 위한 올바른 정보가 있음 있습니다.

앱이 디스플레이 화면 재생 빈도에서 실행되지 않거나 실행될 수 없는 경우 는 플랫폼의 메커니즘은 다음과 같습니다.

이러한 타임스탬프를 사용하면 플랫폼에서 앱 프레임도 표시하지 않음 조기에 울리면 불필요한 떨림이 발생할 수 있습니다. 프레임의 올바른 사용 타임스탬프는 약간 까다롭습니다. 게임의 경우 프레임 속도 가이드 떨림을 방지하는 방법을 자세히 알아보고, Android Frame Pacing 라이브러리.

경우에 따라 플랫폼이 앱의 프레임 속도의 배수로 전환될 수 있습니다. setFrameRate()에 지정됩니다. 예를 들어 앱에서 setFrameRate()를 호출할 수 있습니다. 기기가 디스플레이를 120Hz로 전환할 수 있습니다 이것이 다른 앱에 프레임 속도가 24Hz로 설정된 노출 영역이 있는 경우입니다. 포함 이 경우 디스플레이를 120Hz에서 실행하면 60Hz 표면과 풀다운 없이 실행할 수 있는 24Hz 표면

디스플레이가 앱 프레임 속도의 배수로 실행되는 경우 앱은 불필요하지 않도록 각 프레임의 프레젠테이션 타임스탬프를 지정해야 함 떨림 게임의 경우 Android Frame Pacing 라이브러리가 프레임 표시 타임스탬프를 설정합니다.

setFrameRate() 대 PreferredDisplayModeId 비교

WindowManager.LayoutParams.preferredDisplayModeId 드림 는 앱이 플랫폼에 프레임 속도를 나타낼 수 있는 또 다른 방법입니다. 다소 유용함 앱의 다른 화면 재생 빈도를 변경하지 않고 화면 재생 빈도만 변경하려고 함 디스플레이 모드 설정을 변경할 수 있습니다. 일반적으로 preferredDisplayModeId 대신 setFrameRate() setFrameRate() 함수를 더 쉽게 사용할 수 있습니다. 디스플레이 모드 목록을 사용하여 특정 프레임 속도가 있는 모드를 찾습니다.

setFrameRate()를 사용하면 플랫폼에서 호환되는 여러 표면이 동일한 프레임 속도의 속도가 다를 수 있습니다. 예를 들어 두 개의 앱이 하나의 앱에서 24Hz 동영상을 재생하는 Pixel 4의 화면 분할 모드로 실행 다른 하나는 사용자에게 스크롤 가능한 목록을 표시합니다. Pixel 4는 화면 재생 빈도: 60Hz 및 90Hz preferredDisplayModeId API를 사용하면 동영상 표면이 60Hz 또는 90Hz를 강제로 선택해야 합니다. 호출 setFrameRate(): 동영상 표면이 플랫폼에 더 많은 기능을 제공합니다. 소스 동영상의 프레임 속도에 대한 정보를 제공하여 플랫폼에서 화면 재생 빈도로는 90Hz를 선택합니다. 여기서는 사용할 수 있습니다

하지만 preferredDisplayModeId를 사용해야 하는 시나리오가 있습니다. 다음과 같이 setFrameRate() 대신 사용합니다.

  • 앱에서 해상도 또는 다른 디스플레이 모드 설정을 변경하려고 하면 preferredDisplayModeId를 사용합니다.
  • 플랫폼은 setFrameRate(): 모드 스위치가 가볍고 작동 가능성이 낮은 경우 크게 상회한다고 판단되는 경우에만 사용됩니다 앱이 화면 새로고침 전환을 원하는 경우 과중한 모드 전환 (예: Android TV preferredDisplayModeId를 사용합니다.
  • 앱 프레임의 배수에서 실행되는 디스플레이를 처리할 수 없는 앱 각 프레임에 프레젠테이션 타임스탬프를 설정해야 하므로 preferredDisplayModeId를 사용합니다.

setFrameRate()와 PreferredRefreshRate 비교

WindowManager.LayoutParams#preferredRefreshRate 드림 앱 창에서 기본 프레임 속도를 설정하며 속도가 겹쳐 놓으면 안 됩니다. 앱에서 기본 설정을 지정해야 합니다. 기기의 지원 화면 재생 빈도와 관계없이 setFrameRate(): 스케줄러에 앱이 의도하는 더 나은 힌트 제공 지정할 수도 있습니다

setFrameRate()를 사용하는 노출 영역에서는 preferredRefreshRate가 무시됩니다. 포함 가능하다면 setFrameRate()를 일반적으로 사용합니다.

PreferredRefreshRate vs PreferredDisplayModeId 비교

앱에서 기본 새로고침 빈도만 변경하려는 경우 preferredDisplayModeId가 아닌 preferredRefreshRate입니다.

setFrameRate()를 너무 자주 호출하지 않기

setFrameRate() 호출은 성능 측면에서 많은 비용이 들지 않지만 앱은 프레임마다 또는 프레임당 여러 번 setFrameRate()를 호출하지 않아야 함 둘째, setFrameRate()를 호출하면 화면 재생 빈도로 인해 전환 중에 프레임 드롭이 발생할 수 있습니다. 올바른 프레임 속도를 미리 파악하고 setFrameRate() 한 번.

게임 또는 기타 동영상 이외의 앱에서 사용

동영상은 setFrameRate() API의 기본 사용 사례이지만, 다른 앱에도 사용됩니다. 예를 들어 60Hz (전력 사용량을 줄이고 재생 세션 시간을 늘리기 위해)는 Surface.setFrameRate(60, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT) 이 이런 식으로, 기본적으로 90Hz에서 실행되는 장치는 대신 60Hz에서 실행되지만 떨림을 방지할 수 있기 때문에 게임 시 떨림을 피할 수 있습니다. 게임이 60Hz에서 실행되었고 디스플레이는 90Hz에서 실행되었습니다.

FRAME_RATE_COMPATIBILITY_FIXED_SOURCE 사용

FRAME_RATE_COMPATIBILITY_FIXED_SOURCE는 동영상 앱 전용입니다. 대상 동영상이 아닌 경우 FRAME_RATE_COMPATIBILITY_DEFAULT를 사용합니다.

프레임 속도 변경 전략 선택

  • 앱에서 다음과 같이 장기 실행 동영상을 표시할 때는 영화, setFrameRate(fps, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS) 호출 여기서 fps는 동영상의 프레임 속도입니다.
  • CHANGE_FRAME_RATE_ALWAYSsetFrameRate()를 호출하는 앱은 사용하지 않는 것이 좋습니다. 몇 분 이내로 재생될 것으로 예상되는 경우

동영상 재생 앱 통합의 예

동영상 재생 앱에 화면 재생 빈도 전환을 통합하려면 다음 단계를 따르는 것이 좋습니다.

  1. changeFrameRateStrategy를 결정합니다. <ph type="x-smartling-placeholder">
      </ph>
    1. 영화와 같이 오래 실행되는 동영상을 재생하는 경우 MATCH_CONTENT_FRAMERATE_ALWAYS를 사용합니다.
    2. 무브 트레일러와 같은 짧은 동영상을 재생하는 경우 CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS를 사용합니다.
  2. changeFrameRateStrategyCHANGE_FRAME_RATE_ONLY_IF_SEAMLESS인 경우 4단계로 이동합니다.
  3. 다음을 확인하여 매끄러운 화면 재생 빈도 전환이 발생할 것인지 확신할 수 있습니다. <ph type="x-smartling-placeholder">
      </ph>
    1. 현재 화면 재생 빈도에서 원활한 모드 전환이 불가능합니다. C) 동영상의 프레임 속도 (V)로 설정합니다. 이렇게 하면 C와 V가 다르고 Display.getMode().getAlternativeRefreshRates 드림 는 V의 배수를 포함하지 않습니다.
    2. 사용자가 끊김 없는 새로고침 빈도 변경을 선택했습니다. 탐지 및 차단과 같은 DisplayManager.getMatchContentFrameRateUserPreference가 은 MATCH_CONTENT_FRAMERATE_ALWAYS를 반환합니다.
  4. 원활하게 전환하려면 다음 단계를 따르세요. <ph type="x-smartling-placeholder">
      </ph>
    1. setFrameRate를 호출합니다. 그런 다음 fps, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE를 전달합니다. changeFrameRateStrategy(여기서 fps는 동영상의 프레임 속도)
    2. 동영상 재생 시작
  5. 원활하지 않은 모드 변경이 곧 발생할 경우 다음 단계를 따르세요. <ph type="x-smartling-placeholder">
      </ph>
    1. UX를 표시하여 사용자에게 알립니다. 참고: 사용자가 이 UX를 닫고 5.d단계에서 추가 지연을 건너뛰도록 합니다. 이것은 Google의 권장 지연이 디스플레이에 필요한 것보다 더 길기 때문입니다. 전환 시간이 더 빨라집니다.
    2. setFrameRate를 호출합니다. 그런 다음 fps, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE를 전달합니다. 및 CHANGE_FRAME_RATE_ALWAYS 여기서 fps는 동영상의 프레임 속도입니다.
    3. onDisplayChanged 대기 있습니다.
    4. 모드 전환이 완료될 때까지 2초간 기다립니다.
    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();
}