android - SurfaceView Canvas 在 4K Android TV 上以 1080p 渲染
问题描述
我正在尝试使用 aSurfaceView
在 4K Android TV 设备(运行 Android 9 的 Nvidia Shield TV)上以原始分辨率呈现 3840x2160 位图。
根据Android 6 发行说明,我应该能够设置preferredDisplayModeId
为Display.Mode
支持 4K 分辨率的,以便让我SurfaceView
以 4K 渲染。但是,似乎即使设置后preferredDisplayModeId
,Canvas
提供给onDraw
我的视图的方法也只有1920x1080。尝试将 3840x2160 位图绘制到它会导致图像缩小到 1080p,然后再放大到 2160p,在此过程中会丢失信息。
这是我的相关代码Activity
:
windowManager.defaultDisplay.supportedModes.forEach {
if (it.physicalHeight == 2160 && it.refreshRate > 60) {
val params = window.attributes
params.preferredDisplayModeId = it.modeId
window.attributes = params
}
}
setContentView(R.layout.main)
我的布局包含一个扩展的自定义视图SurfaceView
。自定义视图有一个如下所示的onDraw
方法:
override fun onDraw(canvas: Canvas) {
canvas.drawBitmap(
currentImage,
Rect(0, 0, currentImage!!.width, currentImage!!.height),
canvas.clipBounds,
null
)
}
canvas.clipBounds
是Rect(0, 0 - 1920, 1080)
,所以当它试图渲染完整的位图时,它必须缩小它以适应。
这是渲染adb shell dumpsys SurfaceFlinger
my 时的一些输出:SurfaceView
Display 0 HWC layers:
-------------------------------------------------------------------------------
Layer name
Z | Comp Type | Disp Frame (LTRB) | Source Crop (LTRB)
-------------------------------------------------------------------------------
com.google.android.tvlauncher/com.google.android.tvlauncher.MainActivity#0
rel 0 | Device | 0 0 3840 2160 | 0.0 0.0 1920.0 1080.0
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Dim Layer for - Task=580#0
rel -1 | Client | 0 0 3840 2160 | 0.0 0.0 -1.0 -1.0
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
com.android.tv.settings/com.android.tv.settings.MainSettings#0
rel 0 | Client | 0 0 3840 2160 | 0.0 0.0 1920.0 1080.0
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Background for -SurfaceView - Sys2023:dream#0
rel -3 | Client | 0 0 3840 2160 | 0.0 0.0 -1.0 -1.0
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Sys2023:dream#0
rel 0 | Client | 0 0 3840 2160 | 0.0 0.0 1920.0 1080.0
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Allocated buffers:
0x513aff00: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | Sys2023:dream#0
0x5333f300: 4.00 KiB | 16 ( 64) x 16 | 1 | 1 | 0x1a00 | FakeFramebuffer
0x53340f80: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | com.android.tv.settings/com.android.tv.settings.MainSettings#0
0x53341280: 32400.00 KiB | 3840 (3840) x 2160 | 1 | 1 | 0x1b00 | FramebufferSurface
0x53341700: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | com.google.android.tvlauncher/com.google.android.tvlauncher.MainActivity#0
0x53341880: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | com.google.android.tvlauncher/com.google.android.tvlauncher.MainActivity#0
0x53341d00: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | com.android.tv.settings/com.android.tv.settings.MainSettings#0
0x53341e80: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | com.google.android.tvlauncher/com.google.android.tvlauncher.MainActivity#0
0x55d35480: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | com.android.systemui.ImageWallpaper#0
0x55d35900: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | com.android.tv.settings/com.android.tv.settings.MainSettings#0
0x55d35d80: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | Sys2023:dream#0
0x55d37580: 32400.00 KiB | 3840 (3840) x 2160 | 1 | 1 | 0x1b00 | FramebufferSurface
Total allocated (estimate): 137704.00 KB
为了比较,当我的应用程序渲染ExoPlayer
视图时,这是相同的输出,它正确地渲染了 4K SurfaceView
:
Display 0 HWC layers:
-------------------------------------------------------------------------------
Layer name
Z | Comp Type | Disp Frame (LTRB) | Source Crop (LTRB)
-------------------------------------------------------------------------------
SurfaceView - Sys2023:dream#0
rel -2 | Device | 0 0 3840 2160 | 0.0 0.0 3840.0 2160.0
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Sys2023:dream#0
rel 0 | Device | 0 0 3840 2160 | 0.0 0.0 1920.0 1080.0
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Allocated buffers:
0x513af180: unknown | 3840 (3840) x 2160 | 1 | 12B | 0x900 | SurfaceView - Sys2023:dream#0
0x513af300: unknown | 3840 (3840) x 2160 | 1 | 12B | 0x900 | SurfaceView - Sys2023:dream#0
0x513afc00: unknown | 3840 (3840) x 2160 | 1 | 12B | 0x900 | SurfaceView - Sys2023:dream#0
0x513afd80: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | Sys2023:dream#0
0x5333f300: 4.00 KiB | 16 ( 64) x 16 | 1 | 1 | 0x1a00 | FakeFramebuffer
0x53340f80: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | com.android.tv.settings/com.android.tv.settings.MainSettings#0
0x53341280: unknown | 3840 (3840) x 2160 | 1 | 12B | 0x900 | SurfaceView - Sys2023:dream#0
0x53341400: unknown | 3840 (3840) x 2160 | 1 | 12B | 0x900 | SurfaceView - Sys2023:dream#0
0x53341700: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | com.google.android.tvlauncher/com.google.android.tvlauncher.MainActivity#0
0x53341880: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | com.google.android.tvlauncher/com.google.android.tvlauncher.MainActivity#0
0x53341a00: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | Sys2023:dream#0
0x53341d00: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | com.android.tv.settings/com.android.tv.settings.MainSettings#0
0x53341e80: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | com.google.android.tvlauncher/com.google.android.tvlauncher.MainActivity#0
0x55d35480: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | com.android.systemui.ImageWallpaper#0
0x55d35900: 8100.00 KiB | 1920 (1920) x 1080 | 1 | 1 | 0xb00 | com.android.tv.settings/com.android.tv.settings.MainSettings#0
0x55d35f00: unknown | 3840 (3840) x 2160 | 1 | 12B | 0x900 | SurfaceView - Sys2023:dream#0
0x55d36080: unknown | 3840 (3840) x 2160 | 1 | 12B | 0x900 | SurfaceView - Sys2023:dream#0
0x55d36200: unknown | 3840 (3840) x 2160 | 1 | 12B | 0x900 | SurfaceView - Sys2023:dream#0
0x55d36380: unknown | 3840 (3840) x 2160 | 1 | 12B | 0x900 | SurfaceView - Sys2023:dream#0
0x55d36500: unknown | 3840 (3840) x 2160 | 1 | 12B | 0x900 | SurfaceView - Sys2023:dream#0
0x55d36680: unknown | 3840 (3840) x 2160 | 1 | 12B | 0x900 | SurfaceView - Sys2023:dream#0
0x55d36800: unknown | 3840 (3840) x 2160 | 1 | 12B | 0x900 | SurfaceView - Sys2023:dream#0
0x55d36f80: unknown | 3840 (3840) x 2160 | 1 | 12B | 0x900 | SurfaceView - Sys2023:dream#0
0x55d37100: unknown | 3840 (3840) x 2160 | 1 | 12B | 0x900 | SurfaceView - Sys2023:dream#0
0x55d37280: unknown | 3840 (3840) x 2160 | 1 | 12B | 0x900 | SurfaceView - Sys2023:dream#0
Total allocated (estimate): 72904.00 KB
您可以看到SurfaceView
显示时的缓冲区是正确的 3840x2160,但在使用我的自定义视图时ExoPlayer
似乎没有分配任何缓冲区。SurfaceView
解决方案
在尝试使用画布进行绘制之前设置 SurfaceView 的分辨率。
getHolder().setFixedSize(3840, 2160);
推荐阅读
- javascript - 未捕获的 SyntaxError:使用 JSON.stringify() 的意外标识符
- linux - Ansible 得到错误运行命令,如果我手动输入它没有错误
- typescript - 在一个简单的 Firebase 函数中将循环结构转换为 JSON
- google-cloud-platform - 没有名为 torch.distributed 的模块
- css - Creating a new string literal type based on another
- java - com.google.firebase.database.DatabaseException:无法将 java.lang.String 类型的对象转换为 com.pasarkaget.fajar.pasarkaget.Model.Payments 类型
- c# - 值元组从 WebAPI 公开错误的参数名称
- java - Overriding spring @Configuration in an integration test
- javascript - I can alert the value but can not return as a value from the function
- javascript - 为什么我的正则表达式不能与 Validators.pattern 一起使用?