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

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

问题描述

我设法通过拍摄一系列屏幕截图并使用ffmpeg将其转换为视频(ffmpeg为android编译并包括所有* so到asserts,将它们全部复制到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提供了一个便利类,用于读取

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;
    }

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

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