5

1/10秒ごとにビデオからフレームを抽出しようとしているループがあります。しかし、19フレーム(ビデオの1.9秒)後、Logcatで次のエラーが発生します。

01-22 11:59:15.498: E/OMXCodec(38): [OMX.google.h264.decoder] Timed out waiting for output buffers: 0/0
01-22 11:59:15.598: E/MetadataRetrieverClient(38): failed to capture a video frame
01-22 11:59:15.598: E/MediaMetadataRetrieverJNI(572): getFrameAtTime: videoFrame is a NULL pointer
01-22 11:59:15.598: D/AndroidRuntime(572): Shutting down VM
01-22 11:59:15.598: W/dalvikvm(572): threadid=1: thread exiting with uncaught exception (group=0x409961f8)
01-22 11:59:15.608: E/AndroidRuntime(572): FATAL EXCEPTION: main
01-22 11:59:15.608: E/AndroidRuntime(572): java.lang.NullPointerException

これは私が使用しているコードです:

File videoPath = new File(Environment.getExternalStorageDirectory(), "test.mp4");
String video = videoPath.getAbsolutePath();
MediaMetadataRetriever vidFile = new MediaMetadataRetriever();
vidFile.setDataSource(video);

//Create folder to store images
String storageFolder = "/Storage";
String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
File newFolder = new File(extStorageDirectory + storageFolder);
newFolder.mkdir();

String value = vidFile.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long vidLength = (Long.parseLong(value)/1000); //Returns milliseconds - divide by 1,000
//Video length = 30037ms - result is 30.037s

for(int i = 0; i <= 10*vidLength; i++, image++) //10*vidLength since I'm getting frames every 1/10th sec
{
    Bitmap bmp = vidFile.getFrameAtTime(100000*i, MediaMetadataRetriever.OPTION_CLOSEST);
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    bmp.compress(Bitmap.CompressFormat.PNG, 100, bytes);
    String imagename = String.format(Locale.ENGLISH, "%03d", image);
    File f = new File(Environment.getExternalStorageDirectory() + storageFolder + File.separator + imagename + ".png");
    f.createNewFile();
    FileOutputStream fo = new FileOutputStream(f);
    fo.write(bytes.toByteArray());
    fo.close();

    //Don't seem to make a difference one way or the other
    bytes.flush(); 
    bytes.close();  
}

私が言ったように、それは最大300フレームを取得するはずですが、クラッシュする前に19フレームしか抽出できませんが、NULLポインターエラーが発生している理由がわかりません。

前もって感謝します

4

5 に答える 5

1

Android 4.0 を実行している Evo V でも同様の動作が発生します。テスト ビデオの最初の 6 フレームは問題なく変換されますが、新しい MediaMetadataRetriever を作成して再試行しても、null ポインターが返され始めます。

私のログには、「MediaMetadataRetriever サーバーが停止しました!」も表示されます。

この問題を回避する方法があり、何をしようとしているのかによっては、それが適切かもしれません: OPTION_CLOSEST の代わりに MediaMetadataRetriever.OPTION_CLOSEST_SYNC を渡します。

私のテストでは、OPTION_CLOSEST_SYNC を使用すると、クラッシュは常になくなります。

指定された「同期フレーム」だけでなく、実際には非常に近い間隔でフレームが必要になるため、これは私のアプリケーションにとってはあまり役に立ちません。しかし、それはあなたにとってより受け入れられるかもしれません。

于 2013-03-03T17:31:23.200 に答える
0

OPTION_CLOSEST バグが報告されました。https://code.google.com/p/android/issues/detail?id=193194 を参照してください。

2016 年 8 月 31 日の Google の対応

こんにちは、開発チームはあなたが報告した問題を修正しました。今後のビルドで利用できるようになります ありがとう ステータス: FutureRelease

于 2016-09-17T02:52:39.933 に答える
0

乗算ではなく除算している間違いを見つけました..ミリをマイクロに変換するには、除算をしているときに1000を掛ける必要があります...

MediaPlayer を使用してビデオの長さを取得します。

 file = new File(Environment.getExternalStorageDirectory(), "myvideo.mp4");
 MediaPlayer mp = MediaPlayer.create(MainActivity.this,Uri.parse(file.getAbsolutePath()));
            int duration = mp.getDuration();// it gives duration in milliseconds 
            mp.release();

掛けるduration*1000

までループする

     for(int i=0 ;i <5; i++)
                {
                  if(looper < duration *1000)
                  {
                      ImageView imageView = (ImageView)findViewById(ids_of_images[i]);


imageView.setImageBitmap(retriever.getFrameAtTime(looper,MediaMetadataRetriever.OPTION_CLOSEST));

                        looper +=1000000;  
                  }

                }
于 2014-06-19T13:05:49.950 に答える