关于Android的Mediacodec速度问题和瓶颈

时间:2016-03-03 10:41:20

标签: android mediacodec

目前,我使用Mediacodec对包含90帧的30 FPS视频进行编码需要2100-2400 ms。 我正在使用找到的here代码,但generateSurfaceFrame(i)部分被替换为:

private void generateFrame(Bitmap bitmap, Rect source)
    {
        long drawFrameStartTime = System.currentTimeMillis();
        Canvas canvas = mInputSurface.lockCanvas(null);
        canvas.drawRect(0, 0, mSquareDim, mSquareDim, clearPaint);
        //Process the canvas below
        try
        {
            canvas.drawBitmap(bitmap, source, new Rect(0, 0, mSquareDim, mSquareDim), antiAliasPaint);
        }
        //Process the canvas above
        catch(Exception e) {Log.e("renderExc", e.toString());}
        finally {mInputSurface.unlockCanvasAndPost(canvas);}
        long drawFrameEndTime = System.currentTimeMillis();
        Log.i("frame_draw_time", (drawFrameEndTime - drawFrameStartTime)+"");
    }

将帧放入MediaMuxer部分,找到并改编自here的代码 - 使用Grafika的CircularBuffer类。必须使用该代码独立于其他人释放复用器。

尽管如此,我仍然关注Mediacodec在速度方面的其他瓶颈,而且目前我的目标是API 18(最低)。我的问题是:

  1. 我应该开始使用异步模式吗,它比同步模式快多少?
  2. 使用OpenGL绘制帧的速度比上面描述的Surface-Canvas方法快吗?
  3. 我应该关注Mediacodec的其他瓶颈吗?
  4. 询问时会提供完整的源代码。

2 个答案:

答案 0 :(得分:1)

  1. 异步模式本身并不比同步模式(正确使用)快,但异步接口使得它更清晰地被使用。特别是,无论您使用哪个接口,都不要在将一个缓冲区/表面传递给编码器后直接等待输出缓冲区 - 您可以(并且应该)检查输出,但不要阻止等待一个 - 而是继续提供下一个输入缓冲区/表面(只要输入没有阻止)。

  2. 使用OpenGL而不是Canvas进行渲染最有可能更快。参见例如Android Graphics architecture,其中说:

  3.   

    特别要注意,虽然提供给View的onDraw()方法的Canvas可能是硬件加速的,但当应用程序直接使用lockCanvas()锁定Surface时获得的Canvas永远不会。

答案 1 :(得分:1)

@mstorsjo达到了高点。您可以在Grafika中找到基于GLES的视频生成示例,例如: MovieEightRects使用GeneratedMovie帮助程序类。

如果您测量端到端视频编码时间,您将测量吞吐量和延迟。 MediaCodec通过IPC与一个单独的进程(mediaserver)进行通信,IPC必须通过OMX驱动程序分配硬件资源。这需要一点时间进行预热,并且编解码器中有some amount of latency个推架。

生成帧速度不会影响整体编码速度,只要您生成的速度与编码器可以编码的速度一样快。将数据发送到MediaMuxer时偶尔会出现停顿会堵塞管道,因此Horizo​​n Camera博客文章会发布,因此可以合理地担心(特别是如果您的源在编码管道停止时丢帧)。