1

私の現在の Android アプリケーションの主な機能は、内蔵カメラを使用して録画したビデオからフレーム (10fps) を引き出すことです。ユーザーがビデオを選択するたびに、クラス「FrameCollector」を呼び出します。このクラスは、ビデオをループしてフレームを取り出し、ビットマップの ArrayList に格納します。これが数日間うまく機能したことで、私は正しい軌道に乗っていると思いましたが、今では恐ろしい「java.lang.OutofMemoryError」が発生しています

私のコードは次のとおりです。

ここでは、メイン クラスから渡されたビデオ パスから 1 秒あたり 10 フレームを選択するように MediaMetaDataRetriever を設定しています。

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」に追加します。

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.

どんな助けでも大歓迎です

どうもありがとう、

4

2 に答える 2

0

ビットマップの数が非常に少ない場合を除き、ビットマップを ArrayList に格納しないでください。ビットマップは大量のメモリを占有します。

以前にビデオ録画を行ったことはありませんが、ffmpegのようなネイティブ コーデック ライブラリを取得してみてください。

ただし、自分でフレームを取得する必要がある場合は、カメラからメモリ内の固定サイズのバッファーにフレームを保存し、バッファーからビットマップを取得してディスクに並行して保存するバックグラウンド スレッドを用意することをお勧めします。

于 2012-12-17T13:30:09.240 に答える
0

ビットマップの ArrayList を RAM に保存するのは良くありません。

とにかく、ビットマップを ArrayList に格納するためにデフォルトのヒープ サイズ以上が必要な場合は、このハックを試すことができます。 http://habrahabr.ru/post/139717/ ロシア語ですが、コードは非常にわかりやすいと思います。

于 2012-12-17T13:31:33.800 に答える