为啥TextureView比SurfaceView表现还差呢?

从原理上面讲,我们大众的认知就是TextureView比SurfaceView的性能要好。硬的比软的好。但是其实这种是片面的。最近就遇到一个奇怪的现象:在3399上面通过ffmpeg拉rtsp流,然后通过mediacodec解码后渲染。渲染到TextureView上会比较频繁的出现马赛克的现象。但是换用SurfaceView立马就变好了。

以下3点是我用Raccoon小熊搜出来的答案。

TextureView 和 SurfaceView 都有各自的优势和局限性,所以它们的性能表现也会因应用的具体需求和使用场景而异。 在某些情况下,TextureView 的性能可能会比 SurfaceView 差,原因可能有以下几点:

  1. 渲染管道的差异:TextureView 是基于 OpenGL ES 的,它使用图形渲染管道来渲染内容。而 SurfaceView 则使用传统的 Android 渲染管道,这与 Android 的视图系统更加紧密集成。在某些情况下,这可能会导致 SurfaceView 的性能更好。

  2. 线程管理:SurfaceView 使用一个独立的线程来渲染内容,这可以提供更平滑的渲染性能,尤其是在处理复杂动画或游戏时。而 TextureView 则在主线程上渲染内容,这可能会导致性能下降,尤其是在处理大量数据或复杂渲染时。

  3. 硬件加速:虽然 TextureView 支持硬件加速,但在某些情况下,硬件加速可能会导致性能问题,尤其是在低端设备上。SurfaceView 则更多地依赖于软件渲染,这可能在某些情况下会提供更稳定的性能。

需要注意的是,性能差异可能会因设备和应用而异,因此在实际开发中应该根据具体需求和性能测试结果来选择合适的视图。无论选择哪种视图,都应该优化代码以提高性能,并确保在不同设备上进行充分的测试。

于是,我针对上面的3点的结论做了一个实验,在3399上面ffmpeg硬解码居然比软解码帧率要低。看来3399的CPU性能比其他硬件确实要抢。这就证明了标题中的疑惑了。

下面贴出一段出马赛克的代码,换上SurfaceView就好了。

java 复制代码
public class IPCameraPreviewFragment extends Fragment implements TextureView.SurfaceTextureListener{

    public static final String TAG = "IPCameraPreviewFragment";
	public static final boolean DEBUG = true;
	
	private TextureView mPreview;
	private SurfaceTexture mSurfaceTexture;
	private Handler mUiHandler = new Handler();
	private Runnable mRunnable = new Runnable() {
        
        @Override
        public void run() {
            if(mPreview == null || mSurfaceTexture == null) return;
            Play.getInstances().startPreivew(new Surface(mSurfaceTexture));
        }
    };
    private IErrorCallback mErrorCallback = new IErrorCallback() {
        
        @Override
        public void onError(int error) {
            Log.d(TAG, "onError = " + error);
            if(null == mUiHandler || null == mRunnable) return;
            mUiHandler.removeCallbacks(mRunnable);
            mUiHandler.postDelayed(mRunnable, 5000);
        }
    };
	
	public void setDataSource(String source){
	    Play.getInstances().setErrorCallback(mErrorCallback);
		Play.getInstances().setDataSource(source);
	}
	
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		View view = inflater.inflate(R.layout.preview_fragment, container,false);
		mPreview =  (TextureView)view.findViewById(R.id.preview);
		mPreview.setSurfaceTextureListener(this);
		return view;
	}
	
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
            int height) {
        mSurfaceTexture = surface;
        Play.getInstances().startPreivew(new Surface(surface));
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
            int height) {
        
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        mSurfaceTexture = null;
        Play.getInstances().releaseMediaPlay();
        if(null == mUiHandler || null == mRunnable) return false;
        mUiHandler.removeCallbacks(mRunnable);
        mUiHandler = null;
        mRunnable = null;
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        
    }

}
相关推荐
三少爷的鞋几秒前
Repository 方法设计:suspend 与 Flow 的决选择指南(以朋友圈为例)
android
阿里云云原生32 分钟前
Android App 崩溃排查指南:阿里云 RUM 如何让你快速从告警到定位根因?
android·java
cmdch20173 小时前
手持机安卓新增推送按钮功能
android
攻城狮20153 小时前
【rk3528/rk3518 android14 kernel-6.10 emcp sdk】
android
何妨呀~3 小时前
mysql 8服务器实验
android·mysql·adb
QuantumLeap丶4 小时前
《Flutter全栈开发实战指南:从零到高级》- 25 -性能优化
android·flutter·ios
木易 士心5 小时前
MVC、MVP 与 MVVM:Android 架构演进之路
android·架构·mvc
百锦再5 小时前
国产数据库的平替亮点——关系型数据库架构适配
android·java·前端·数据库·sql·算法·数据库架构
走在路上的菜鸟5 小时前
Android学Dart学习笔记第十三节 注解
android·笔记·学习·flutter
介一安全6 小时前
【Frida Android】实战篇15:Frida检测与绕过——基于/proc/self/maps的攻防实战
android·网络安全·逆向·安全性测试·frida