视频缩放丢像素问题

一、问题描述

1、分辨率为1900*960的视频源缩放到144*240的分辨率后播放,显示效果有丢像素现象。

2、我们的播放器软件是使用TextureView方法实现。

3、使用瑞芯微自带的播放器播放效果稍好(还是有丢像素现象),他们使用SurfaceView实现。

二、问题解决方法

  1. 修改缩放算法

位置:kernel/driver/video/rockchip/lcdc/rk3368_lcdc.c

视频缩放丢像素问题

 

2、打补丁和增加代码

①librga的源码解压到hardware/rockchip/目录下编译即可得到librga.so。

解压会产生librga文件夹,里面是相应源码

视频缩放丢像素问题

②libgui.so的补丁打在framework/native目录下。

补丁文件名:Add_rga_to_gui.patch(内容过多不呈现了,具体见源码)

3、引入的其他问题及解决

①奇数行重启播放视频全绿:原因是rga的yuv格式输出有偶数对齐限制,修改为rgba输出。

②播放图片显示全黑:原因是图片和视频播放格式不同,播放图片的输入format为rgba,会被原先的代码过滤掉。需要补上判断逻辑。

解决:这两个问题需要在framework/native目录下打上补丁文件:rga_use_rgba_and_fixup_some_bug.patch

视频缩放丢像素问题

图2 rga_use_rgba_and_fixup_some_bug.patch补丁内容

三、问题总结

1、方案实现原理

解码端(900x1600 YUV)— rga 缩放(144x240 YUV) — 纹理上传 — gpu 渲染输出(144x240 RGBA)

2、问题产生的原因

在上传纹理的地方之前采用了ImageOES 的扩展,无法配置采用滤波器,而导致效果不好。

 

四、相关知识点梳理

1、SurfaceView和TextureView

Android普通窗口的视图绘制机制是一层一层的,任何一个子元素或者是局部的刷新都会导致整个视图结构全部重绘一次,因此效率相对较低。视频或者opengl内容往往是显示在SurfaceView中的,SurfaceView的工作方式是:创建一个置于应用窗口之后的新窗口。因为SurfaceView窗口刷新的时候不需要重绘应用程序的窗口,所以这种方式的效率非常高。

但是SurfaceView也有一些非常不便的限制,因为SurfaceView的内容不在应用窗口上,所以不能使用平移、缩放、旋转等变换操作,也难以放在ListView或者ScrollView中,同样不能使用UI控件的一些特性,比如View.setAlpha()。

为了解决这个问题 Android 4.0 中引入了TextureView,与SurfaceView相比,TextureView并没有创建一个单独的 Surface 用来绘制,这使得它可以像一般的View一样执行一些变换操作,设置透明度等。

TextureView的使用非常简单,你唯一要做的就是获取用于渲染内容的SurfaceTexture。

Textureview必须在硬件加速开启的窗口中。

 

2、SurfaceTexture

SurfaceTexture是从Android3.0(API 11)加入的一个新类。这个类跟SurfaceView很像,可以从camera preview或者video decode里面获取图像流(image stream)。

当指定Camera或MediaPlayer对象的输出目标时,SurfaceTexture可以取代SurfaceHolder,这样将使得从图像流中得到的所有帧都输出到SurfaceTexture对象,而不是用于在设备上显示。当调用updateTexImage()时,用来创建SurfaceTexture的纹理对象内容被更新为包含图像流中最近的图片。