1

我根据Continuous capture activity写了一个demo。我想将视频的第一帧保存为jpeg文件,所以我使用了Grafika已经准备好的saveFrame()函数。函数源码如下: https ://github.com/google/grafika/blob/master/src/com/android/grafika/gles/EglSurfaceBase.java

但是我发现制作出来的jpeg图片是颠倒的,这不是我想要的。

在我保存框架之前,有没有办法旋转框架?

旋转位图不是一个优雅的解决方案,因为我们可能会遇到一些其他情况,例如视频聊天。视频的每一帧都被发送到远程对等体,然后远程人将看到一个颠倒的视频。所以我们应该在编码之前旋转每一帧。

4

2 回答 2

1

你不想旋转框架,你想翻转框架。

存在这种情况是因为 Bitmap 认为 (0,0) 在左上角,但 GLES 认为 (0,0) 在左下角。 glReadPixels()从顶部开始填充缓冲区,Bitmap 认为这是底部,所以你最终得到一个颠倒的图像。

你有两个选择:

  1. 用 GLES 将框架倒置,然后像现在一样抓住它。这就是ExtractMpegFramesTest代码所做的——注意该drawFrame()函数接受一个invert参数,并修改从 SurfaceTexture 获得的矩阵(如果已设置)。
  2. 像现在一样绘制并提取帧,然后翻转缓冲区中的像素,然后再将它们转换为位图。这是移动字节的简单问题。它会增加一些开销,但由于 JPEG 压缩,你已经有点慢了。(用 Java 代码复制整行System.arrayCopy()可能比用 Java 代码复制单个字节要好。)
于 2015-07-10T03:20:57.803 回答
1

我的实现如下,非常快,不到 10 毫秒。

    private void reverseBuf(ByteBuffer buf, int width, int height)
{
    long ts = System.currentTimeMillis();
    int i = 0;
    byte[] tmp = new byte[width * 4];
    while (i++ < height / 2)
    {
        buf.get(tmp);
        System.arraycopy(buf.array(), buf.limit() - buf.position(), buf.array(), buf.position() - width * 4, width * 4);
        System.arraycopy(tmp, 0, buf.array(), buf.limit() - buf.position(), width * 4);
    }
    buf.rewind();
    Log.d(TAG, "reverseBuf took " + (System.currentTimeMillis() - ts) + "ms");
}
于 2015-07-10T08:10:27.730 回答