我正在尝试让以下 MediaExtractor 示例正常工作:
http://bigflake.com/mediacodec/ - ExtractMpegFramesTest.java(需要 4.1,API 16)
我遇到的问题是 outputSurface.awaitNewImage();似乎总是抛出 RuntimeException("frame wait timed out"),每当mFrameSyncObject.wait(TIMEOUT_MS)
呼叫超时。不管我设置什么TIMEOUT_MS
to be, onFrameAvailable()
总是被打电话就在之后发生超时。我尝试了 50ms 和 30000ms,结果是一样的。
似乎是onFrameAvailable()
线程繁忙时无法调用,一旦超时结束线程代码执行,它可以解析onFrameAvailable()
call.
有没有人设法让这个例子工作,或者知道 MediaExtractor 应该如何与 GL 纹理一起工作?
Edit:在具有 API 4.4 和 4.1.1 的设备上尝试过此操作,并且在两者上都会发生同样的情况。
Edit 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。我使用的视频是一个 .mp4 文件,带有“H264 - MPEG-4 AVC (avc1)”视频编解码器和“MPEG AAC Audio (mp4a)”音频编解码器。
我也尝试过其他视频格式,但它们似乎在 4.1.x 上消失得更快,而两者都可以在 4.3 上工作。
Edit 3:
我按照你的建议做了,似乎正确保存了帧图像。谢谢。
关于KEY_MAX_INPUT_SIZE,我尝试不设置,或者将其设置为0,20,200,...200000000,所有结果都与info.size=0相同。
我现在无法将渲染设置为布局上的 SurfaceView 或 TextureView。我尝试替换这一行:
mSurfaceTexture = new SurfaceTexture(mTextureRender.getTextureId());
有了这个,哪里surfaceTexture
是我的 xml 布局中定义的 SurfaceTexture:
mSurfaceTexture = textureView.getSurfaceTexture();
mSurfaceTexture.attachToGLContext(mTextureRender.getTextureId());
但它引发了一个奇怪的错误getMessage()==null
在第二行。我找不到任何其他方法让它在某种视图上绘制。如何更改解码器以在 Surface/SurfaceView/TextureView 上显示帧而不是保存它们?