(这是由于我将使用的服务器软件的限制,如果我可以改变它,我会)。
我通过套接字接收一系列720x480 JPEG文件(大小约为6kb)。我对网络进行了基准测试,发现我能够以60FPS顺利接收这些JPEG。
我当前的绘图操作是在2560x1600的Nexus 10显示器上,这是我的解码方法,一旦我从套接字接收到字节数组:
public static void decode(byte[] tmp, Long time) {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferQualityOverSpeed = false;
options.inDither = false;
Bitmap bitmap = BitmapFactory.decodeByteArray(tmp, 0, tmp.length, options);
Bitmap background = Bitmap.createScaledBitmap
(bitmap, MainActivity.screenwidth, MainActivity.screenheight, false);
background.setHasAlpha(false);
Canvas canvas = MainActivity.surface.getHolder().lockCanvas();
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(background, 0, 0, new Paint());
MainActivity.surface.getHolder().unlockCanvasAndPost(canvas);
} catch (Exception e) {
e.printStackTrace();
}
}
如您所见,我正在从SurfaceView清除画布,然后将Bitmap绘制到SurfaceView。我的问题是它非常非常缓慢。
基于在锁定操作之前和之后添加System.currentTimeMillis()的一些测试导致获取画布,绘制位图,然后再推回画布之间的差异大约为30ms。显示的SurfaceView 非常滞后,有时会来回跳跃,帧速率很差。
是否有这样的参考方法?同样,我无法修改我从服务器获得的内容,但我希望在可能的情况下以60FPS显示位图。
(我已尝试设置ImageView的内容,并收到类似的结果)。我在SurfaceView中没有其他可能影响它的代码。我已将持有者设置为RGBA_8888格式:
getHolder().setFormat(PixelFormat.RGBA_8888);
是否可以将此位图流转换为VideoView?会更快吗?
感谢。
答案 0 :(得分:3)
每当遇到性能问题时,请使用Traceview确定问题的确切位置。使用System.currentTimeMillis()
就像试图用锤子修剪牛排一样。
她的第一件事是从主应用程序线程中解码位图。在后台线程中执行此操作。您的主应用程序线程应只是绘制位图,将它们从该后台线程填充的队列中拉出。 Android的主应用程序线程设置为在Android 4.1(又称“Project Butter”)的基础上以60fps为基础进行渲染,因此只要您可以在几毫秒内绘制Bitmap
,并假设您的网络并且解码可以使你的队列保持最新状态,你应该得到60fps的结果。
此外,当您拥有一致大小的图片时,始终在Android 3.0+上使用inBitmap
和BitmapFactory.Options
,因为问题的一部分将是GC窃取CPU时间。处理您旋转的Bitmap
个对象池,这样可以减少垃圾堆积,并且不会过多地碎片堆。
我怀疑让你更好地让Android在ImageView
(或仅通过绘制到View
画布)缩放图像,而不是让BitmapFactory
缩放图像,因为Android可以利用硬件图形加速进行渲染,BitmapFactory
不能。 Traceview再次成为你的朋友。
关于:
并且发现我能够以60FPS顺利接收这些JPEG。
有时只会是真的。移动设备往往是移动的。假设“6kb”表示6KB(6千字节),那么假设连接速度为~3Mbps(每秒3兆比特),这远非确定。
关于:
是否可以将此位图流转换为VideoView?
VideoView
是一个播放视频的小部件,但您没有视频。
推送来推,你可能需要下载到NDK并在本机代码中执行此操作,但我希望不会。