Picture produced by saveFrame of Grafika is upside

2019-04-15 07:54发布

I wrote a demo according to Continuous capture activity.I wanted to save the first frame of the video as a jpeg file, so I used the saveFrame() function which was already prepared by Grafika. The source code of the function is as follows: https://github.com/google/grafika/blob/master/src/com/android/grafika/gles/EglSurfaceBase.java

But I found that the jpeg picture produced was upside-down.This is not what I want.

Is there a way of rotating the frame before I save the frame?

Rotating the bitmap is not a graceful solution,because we might encounter some other situations such as video chatting. Each frame of the video is sent to the remote peer, then the remote person will see a upside-up video. So we should rotate every frame before it is encoded.

2条回答
放荡不羁爱自由
2楼-- · 2019-04-15 08:35

You don't want to rotate the frame, you want to flip the frame.

The situation exists because Bitmap thinks (0,0) is in the top-left corner, but GLES thinks (0,0) is in the bottom-left corner. glReadPixels() starts filling the buffer from the top, which Bitmap thinks is the bottom, so you end up with an upside-down image.

You have two options:

  1. Draw the frame upside-down with GLES, then grab it as you are now. This is what the ExtractMpegFramesTest code does -- note the drawFrame() function takes an invert argument, and modifies the matrix obtained from the SurfaceTexture if it's set.
  2. Draw and extract the frame as you are now, then flip the pixels in the buffer before converting them to a Bitmap. This is a simple matter of moving bytes around. It will add some overhead, but you're already kind of slow because of the JPEG compression. (Copying whole lines with System.arrayCopy() might be better than copying individual bytes with Java code.)
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-04-15 08:54

My implementation is as follows which is very fast, less than 10ms.

    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");
}
查看更多
登录 后发表回答