android中是否使用libgdx进行屏幕录制 [英] Screen recording within android using libgdx or not

查看:30
本文介绍了android中是否使用libgdx进行屏幕录制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我设法通过拍摄一系列屏幕截图并使用 ffmpeg 将它们转换为视频来做到这一点(ffmpeg 为 android 编译并包含所有 *so 到断言,将它们全部复制到 data/data/my.package/并执行 ffmpeg从那里)

I managed to do this by taking a series of screenshots and convert them to video using ffmpeg (ffmpeg compiled for android and include all *so to asserts, copy them all to to data/data/my.package/ and execute ffmpeg from there)

但主要问题是截屏对屏幕渲染有很大影响,当应用程序执行这行代码时它会冻结一段时间(~0.1秒):

But the main problem is the taking screenshots have big impact on screen rendering, it freezes a while (~0.1sec) when the app is executing this line of code:

Gdx.gl.glReadPixels(x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixels);

我试图从另一个线程截取屏幕截图,但我只得到黑色屏幕截图.为什么???

I tried to take screenshots from another thread, but i only get black screenshots. Why???

你知道更有效的截图方法吗?

Do you know a more efficient way of taking screenshots?

推荐答案

截屏是一项相当昂贵的任务,当你想把它变成视频时更是如此.

Screen capturing is a fairly expensive task, and more so when you want to turn it into a video.

glReadPixels 方法是从显示缓冲区读回像素值的方法.这就是你想要的;然而,限制因素将是与 GPU 之间的带宽,尤其是对于移动设备.我建议创建一个 FrameBuffer 使用较低的分辨率(可能是宽度/高度的一半),这样您就可以降低带宽要求.然后,您将在应用程序处于活动状态时将其绘制到该缓冲区,然后读回像素值.Libgdx 提供了一个方便的类,用于读取 ScreenUtils 类.(这些方法使用 glReadPixels 进行读取).

The glReadPixels method is the method for reading back pixel values from the display buffer. Which is what you want; however, the limiting factor will be bandwidth to/from the GPU, especially for mobile devices. I would suggest creating a FrameBuffer with a lower resolution (maybe half your width/height) so that you can reduce the bandwidth requirements. You would then draw your app to that buffer while it is active and then read back the pixel values. Libgdx provides a convenience class for reading back the pixel values in the ScreenUtils class. (These methods use glReadPixels to do the reading).

即便如此,它也可能无法在低端设备上正常工作,尤其是当您考虑以每秒 60 帧的速度从设备录制视频并主动渲染复杂场景时.但是,如果其他人知道在 android 设备上有效地执行此操作的方法,我会非常有兴趣看到更好的解决方案.

Even then, it is likely to not work well on lower-end devices especially if you are thinking of recording video from the device at 60 frames a second AND actively rendering a complex scene. However, if someone else knows a way to efficiently do this on android devices I would be very interested in seeing a better solution.

要回答您的其他问题,您不能同时访问 OpenGL 上下文,而只能从渲染线程中访问.这就是为什么你会得到多线程的黑色屏幕截图.

To answer your other question, you can't access the OpenGL context concurrently and should be doing it only from the rendering thread. This is why you are getting black screenshots with multiple threads.

为了跟进您关于如何导出为 PNG 的问题,我提供了您可以使用的代码:

To follow up with your question about how to export to a PNG I have code for that which you may use:

public boolean export(final FileHandle target, final Graphics g) {
        boolean error = false;
        final Pixmap picture = new Pixmap(g.getWidth(), g.getHeight(), Format.RGBA8888);
        final FrameBuffer buffer = new FrameBuffer(Format.RGBA8888, g.getWidth(), g.getHeight(), false);
        try {
            Gdx.graphics.getGL20().glViewport(0, 0, g.getWidth(), g.getHeight());
            buffer.begin();
            g.render(); // Or however you normally draw it
            final byte[] data = this.readData(g.getWidth(), g.getHeight());
            buffer.end();
            picture.getPixels().put(data, 0, data.length);
            PixmapIO.writePNG(target, picture);
        } catch (final Exception e) {
            e.printStackTrace();
            error = true;
        } finally {
            picture.dispose();
            buffer.dispose();
        }
        return error;
    }

    // Adapted from ScreenUtil class
    public byte[] readData(final int width, final int height) {
        final int numBytes = width * height * 4;
        final ByteBuffer pixels = BufferUtils.newByteBuffer(numBytes);
        Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1);
        Gdx.gl.glReadPixels(0, 0, width, height, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, pixels);

        final byte[] lines = new byte[numBytes];
        final int numBytesPerLine = width * 4;
        for (int i = 0; i < height; i++) {
            pixels.position((height - i - 1) * numBytesPerLine);
            pixels.get(lines, i * numBytesPerLine, numBytesPerLine);
        }

        return lines;
    }

这篇关于android中是否使用libgdx进行屏幕录制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆