【问题标题】:How to load lots of bitmaps without crashing application in android如何加载大量位图而不会在android中崩溃应用程序
【发布时间】:2011-07-04 14:27:48
【问题描述】:

我正在从网络流式传输视频。我在本机代码中解码视频/音频内容并获取视频的原始像素

我在 java 代码中创建了一个位图,带有表面支架和画布,并从本机代码更新每个位图的像素,然后将位图作为视频流式传输。我的问题是,由于内存不足,视频几秒钟后就崩溃了。

我想知道是否有什么需要确保不让应用崩溃和使用低内存。

这是我的代码。

public CanvasThread(SurfaceHolder surfaceHolder, Panel panel) {
    _surfaceHolder = surfaceHolder;
    _panel = panel;     }
public void setRunning(boolean run) {
    _run = run;    }

@Override
public void run() {
    Canvas c;
    while (_run) {
        c = null;
        try {
            c = _surfaceHolder.lockCanvas(null);
            synchronized (_surfaceHolder) {
                _panel.onDraw(c);
            }
        } finally {
                if (c != null) {
                _surfaceHolder.unlockCanvasAndPost(c);
            }
       }    

  public class Panel extends SurfaceView implements SurfaceHolder.Callback{
    private CanvasThread canvasthread;
    private static Bitmap mBitmap;
    private static boolean ii=false;
       public Panel(Context context, AttributeSet attrs) {
        super(context, attrs); 
        getHolder().addCallback(this);
        canvasthread = new CanvasThread(getHolder(), this);
        setFocusable(true);
       mBitmap=Bitmap.createBitmap(480, 320, Bitmap.Config.RGB_565);//bitmap created in constructor
    }

     public Panel(Context context) {
           super(context);
            getHolder().addCallback(this);
            canvasthread = new CanvasThread(getHolder(), this);
            setFocusable(true);
        }

     private static native void renderbitmap(Bitmap bitmap); //native function
    @Override
    public void onDraw(Canvas canvas) {

        renderbitmap(mBitmap); //Update pixels from native code
        canvas.drawBitmap(mBitmap, 0,0,null);//draw on canvas
}

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {        }
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        canvasthread.setRunning(true);
        canvasthread.start();       }
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        boolean retry = true;
        canvasthread.setRunning(false);
        while (retry) {
            try {
                canvasthread.join();
                retry = false;
            } catch (InterruptedException e) {              }
    }

【问题讨论】:

    标签: android memory-management bitmap android-ndk android-video-player


    【解决方案1】:

    您可以查看 Richard Quirk 的 glbuffer。我在视频播放器应用中使用它。

    一般来说,您希望保留正在接收的视频数据包,并且仅在需要显示之前对其进行解码。将您的代码与 glbuffer 集成并绕过 Java 代码中的任何位图分配应该很容易。

    在任何给定时间,在本机代码和 GL 纹理内存中都会存在一个解码帧,以及您保留用于缓冲的几个编码数据包。

    【讨论】:

    • 我没试过,但我不明白为什么不。
    • 你能用摆动的棕色块运行演示吗?从那里也许您应该尝试一点一点地修改代码并找出错误在哪一步。
    • glbuffer 已经配置为使用 rgb565,您可以通过更改 TEXTURE_{WIDTH,HEIGHT} 来设置纹理大小
    【解决方案2】:

    通过快速扫描您的代码,您的基本问题似乎是每次调用 OnDraw 方法时都会创建一个新位图。相反,注释掉该行,并在启动时为mBitmap 创建一次位图。

    【讨论】:

      【解决方案3】:

      这可能不是因为您的内存量有限。模拟器大概16MB左右。您不应该将所有图像都存储在内存中。你必须选择

      1. 修复您的算法,使其不会 需要记忆中的一切
      2. 或者只在内存中保留一张图像,然后 其余在磁盘上

      【讨论】:

        猜你喜欢
        • 2023-04-11
        • 1970-01-01
        • 1970-01-01
        • 2021-06-20
        • 2020-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多