【问题标题】:Android: Bitmap Decode java.lang.OutofMemoryError errorAndroid:位图解码 java.lang.OutofMemoryError 错误
【发布时间】:2012-12-17 13:23:22
【问题描述】:

我当前的 android 应用程序的主要功能是使用内置摄像头从录制的视频中提取帧 (10fps)。每当用户选择视频时,我都会调用我的类“FrameCollector”,它会循环播放视频并将帧拉出并将它们存储到位图的 ArrayList 中。让这项工作好几天让我认为我走在正确的轨道上,但现在我得到了可怕的“java.lang.OutofMemoryError”

我的代码如下:

这里将 MediaMetaDataRetriever 设置为从主类传递的视频路径中选择每秒 10 帧

public class FrameCollector {

MediaMetadataRetriever _mmr;

double _fps;
double _duration;
long _counter = 0;
long _incrementer;

public FrameCollector(String path, Context context) 
{
    try
    {
    _mmr = new MediaMetadataRetriever();
    _mmr.setDataSource(path);

    SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
    String fpsString = pref.getString("prefFPS", "10");
    _fps = Double.parseDouble(fpsString);
    _incrementer = (long) (1000000 / _fps);

    String stringDuration = _mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
    _duration = Double.parseDouble(stringDuration) * 1000;
    }
    catch(Exception ex)
    {
        ex.printStackTrace();
    }
}

下面的方法然后将当时的帧添加到位图中,并将位图添加到位图“bitFrames”的arraylist

public ArrayList<Bitmap> getBitmaps() 
{
    try 
    {
        ArrayList<Bitmap> bitFrames = new ArrayList<Bitmap>();


        Bitmap b = _mmr.getFrameAtTime(_counter);

        while (_counter < _duration && b != null) 
        {
            bitFrames.add(b);
            _counter += _incrementer;
            b = _mmr.getFrameAtTime(_counter);
        }
        return bitFrames;   
    }
    catch (Exception ex) 
    {
        ex.printStackTrace();
        return null;
    }
}

我认为我的问题在于这种方法。我相信我需要在将位图存储到 ArrayList 之前对其进行解码,但我不确定如何作为

Bitmap b = BitmapFactory.decode____(_mmr.getFrameAtTime(_counter)); 
-- Whether it be decodeStream, decodeResource, decodeFile all bring errors.

任何帮助将不胜感激

非常感谢,

【问题讨论】:

  • 您应该检查保存在该数组中的每个位图的大小。因为你的应用程序在 android 中没有很多可用的 RAM,所以如果你存储了太多的大位图,你就会内存不足。

标签: android bitmap out-of-memory bitmapfactory


【解决方案1】:

除非位图的数量非常少,否则切勿将位图存储在 ArrayList 中。位图占用大量内存。

我以前没有处理过视频录制,但我建议你尝试获取一个像 ffmpeg 这样的原生编解码器库来为你做这件事。

但是,如果您必须自己抓取帧,我建议将它们存储在相机内存中固定大小的缓冲区中,并有一个后台线程从缓冲区中提取位图并将其并行存储到磁盘中。

【讨论】:

    【解决方案2】:

    在 RAM 中存储位图的 ArrayList 是不好的。

    无论如何,如果您需要超过默认堆大小来在 ArrayList 中存储位图,您可以尝试这个技巧。 http://habrahabr.ru/post/139717/ 它是俄文的,但我想代码很容易理解。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-14
      相关资源
      最近更新 更多