android - 为什么不同设备的 ANativeWindow_Buffer.stride 不同
问题描述
我正在使用 ffmpeg for android 编写简单的视频播放器。以下是我遵循的步骤
- 从文件中读取 AVFrame
- 使用将 AVFrame 转换为 RGB565 格式
sws_scale
- 从使用中获取缓冲区
av_image_copy_to_buffer
SurfaceView
通过将缓冲区复制到来显示此缓冲区ANativeWindow_Buffer
大多数视频都可以正常播放,但是分辨率低于窗口的视频存在问题。例如,当我在我的 OnePlus 7T (2206x1080) 上播放 656x480 视频时,视频看起来失真。相同的视频在模拟器 (2160x1080) 上播放良好。
当我调试整个管道时,我发现在 OP7T 上,锁定ANativeWindow
后ANativeWindow_Buffer.stride
设置为 704 而不是 656。对于所有正常播放的视频,步幅与缓冲区的宽度相同。Android模拟器并非如此。
我做了一些试验并尝试将宽度缩放到 600,然后步幅跳到 640,视频失真了。当我将宽度缩放到 640 时,视频垂直显示一半正确。
谁能帮我理解,步幅是如何计算的?错误计算步幅的原因是什么?
我在这里发现了一个同样的问题:Simple FFMpeg player for Android OP 提到视频适用于 640、1280、1920。
解决方案
似乎因为我的设备是 arm64-v8a,所以步幅总是对齐到 64。为了克服这个问题,我在锁定窗口并使用ANative_WindowBuffer
. 然后我用它windowbuffer.stride
来计算 dst_slice sws_scale
。
AVFrame dummy;
if ((ret = ANativeWindow_lock(window, &windowBuffer, nullptr)) < 0) {
log_error("cannot lock window: %d", ret);
} else {
dummy.data[0] = (uint8_t *) windowBuffer.bits;
dummy.linesize[0] = windowBuffer.stride * 2 // For RGB565;
}
接着:
sws_scale(renderer->sws_ctx,
(const uint8_t* const *) frame->data,
frame->linesize,
0,
codecpar->height,
dummy.data,
dummy.linesize)
这将直接将缩放的帧数据渲染到窗口缓冲区。
推荐阅读
- github - 如何始终链接到 GitHub 上文件的最新原始版本?
- python - Python 上没有任何库的 CSV 计算
- python - 如何在 tkinter 窗口中只接受用户输入一分钟
- javascript - 刷新页面 React JS 后的问题
- dependency-injection - 应用层和领域层之间的依赖关系
- node.js - 保存的媒体文件在nodejs中使用sharp的类型不受支持
- pandas - 在 Pandas plot() 中指定 y_label
- java - spark-submit 在线程“main”java.lang.IllegalStateException 中抛出异常:找不到任何构建目录
- zip - 以递归方式提取 ZIP 文件和 ZIP... 压缩文件,然后删除原始档案
- wordpress - WordPress 自定义帖子类型前端