次の MediaExtractor の例を機能させようとしています:
http://bigflake.com/mediacodec/ - ExtractMpegFramesTest.java (4.1、API 16 が必要)
私が抱えている問題は、outputSurface.awaitNewImage(); です。mFrameSyncObject.wait(TIMEOUT_MS)
呼び出しがタイムアウトするたびにスローされる RuntimeException("frame wait timed out") を常にスローするようです。何を設定TIMEOUT_MS
しても、タイムアウトが発生した直後にonFrameAvailable()
常に呼び出されます。50msと30000msで試してみましたが同じです。
onFrameAvailable()
スレッドがビジー状態の間は呼び出しを実行できないようです。タイムアウトが発生してスレッド コードの実行が終了すると、呼び出しを解析できますonFrameAvailable()
。
この例を機能させることができた人はいますか、または MediaExtractor が GL テクスチャでどのように機能するかを知っていますか?
編集: API 4.4 および 4.1.1 を搭載したデバイスでこれを試したところ、両方で同じことが起こりました。
編集2:
fadden のおかげで 4.4 で動作するようになりました。問題は、ExtractMpegFramesWrapper.runTest()
呼び出されたメソッドth.join();
がメイン スレッドをブロックし、onFrameAvailable()
呼び出しが処理されないことでした。コメントth.join();
すると、4.4で動作します。ExtractMpegFramesWrapper.runTest()
メインスレッドがブロックされないように、それ自体がさらに別のスレッドで実行されるはずだったのかもしれません。
を呼び出すときに 4.1.2 にも小さな問題がありcodec.configure()
、エラーが発生しました。
A/ACodec(2566): frameworks/av/media/libstagefright/ACodec.cpp:1041 CHECK(def.nBufferSize >= size) failed.
A/libc(2566): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 2625 (CodecLooper)
呼び出しの前に次を追加することで解決しました:
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 0);
ただし、4.1.1 (Galaxy S2 GT-I9100) と 4.1.2 (Samsung Galaxy Tab GT-P3110) の両方で現在発生している問題は、すべてのフレームで常に info.size を 0 に設定していることです。ログ出力は次のとおりです。
loop
input buffer not available
no output from decoder available
loop
input buffer not available
no output from decoder available
loop
input buffer not available
no output from decoder available
loop
input buffer not available
no output from decoder available
loop
submitted frame 0 to dec, size=20562
no output from decoder available
loop
submitted frame 1 to dec, size=7193
no output from decoder available
loop
[... skipped 18 lines ...]
submitted frame 8 to dec, size=6531
no output from decoder available
loop
submitted frame 9 to dec, size=5639
decoder output format changed: {height=240, what=1869968451, color-format=19, slice-height=240, crop-left=0, width=320, crop-bottom=239, crop-top=0, mime=video/raw, stride=320, crop-right=319}
loop
submitted frame 10 to dec, size=6272
surface decoder given buffer 0 (size=0)
loop
[... skipped 1211 lines ...]
submitted frame 409 to dec, size=456
surface decoder given buffer 1 (size=0)
loop
sent input EOS
surface decoder given buffer 0 (size=0)
loop
surface decoder given buffer 1 (size=0)
loop
surface decoder given buffer 0 (size=0)
loop
surface decoder given buffer 1 (size=0)
loop
[... skipped 27 lines all with size=0 ...]
surface decoder given buffer 1 (size=0)
loop
surface decoder given buffer 0 (size=0)
output EOS
Saving 0 frames took ? us per frame // edited to avoid division-by-zero error
したがって、画像は保存されません。ただし、同じコードとビデオは 4.3 でも機能します。私が使用しているビデオは、「H264 - MPEG-4 AVC (avc1)」ビデオ コーデックと「MPEG AAAC Audio (mp4a)」オーディオ コーデックの .mp4 ファイルです。
他のビデオ形式も試してみましたが、4.1.x ではもっと早く死んでいるように見えますが、4.3 ではどちらも動作します。
編集3:
あなたが提案したとおりにしましたが、フレーム画像が正しく保存されているようです。ありがとうございました。
KEY_MAX_INPUT_SIZEについては、設定しないか、0, 20, 200, ... 200000000に設定してみましたが、いずれもinfo.size=0と同じ結果になりました。
レイアウトでレンダリングを SurfaceView または TextureView に設定できなくなりました。この行を置き換えてみました:
mSurfaceTexture = new SurfaceTexture(mTextureRender.getTextureId());
これで、surfaceTexture
私のxml-layoutで定義されたSurfaceTextureはどこにありますか:
mSurfaceTexture = textureView.getSurfaceTexture();
mSurfaceTexture.attachToGLContext(mTextureRender.getTextureId());
getMessage()==null
しかし、2行目で奇妙なエラーがスローされます。ある種のビューに描画する他の方法を見つけることができませんでした。フレームを保存する代わりに、Surface/SurfaceView/TextureView にフレームを表示するようにデコーダを変更するにはどうすればよいですか?