VideoSurfaceView - 渲染到文件

时间:2013-10-31 09:50:54

标签: android opengl-es surfaceview glsurfaceview

我正在使用VideoSurfaceView来渲染已过滤的视频。我正在根据我的需要购买更改片段着色器。现在我想在更改相同格式的文件(例如mp4 - h264)后保存/渲染视频,但找不到如何操作。

PS - 将纹理保存为位图并将位图保存到文件很简单,但我可以找到如何使用视频...

这里有专家吗?

1 个答案:

答案 0 :(得分:0)

正如您已经发现并在评论中说的,OpenGL无法将多个帧导出为视频。

虽然如果您只想过滤/处理视频的每一帧,那么您根本不需要OpenGL,并且您不需要片段着色器,您可以自己循环遍历所有像素。

现在假设您一次处理一帧视频,每帧都是BufferedImage您可以使用任何您想要或提供的内容,只要您拥有获取和设置像素的选项。

我只是为您提供计算和应用过滤器的方法,您必须自己对视频文件进行解码和编码。

但回到BufferedImage,首先我们要获取BufferedImage中的所有像素,我们使用以下内容完成此操作。

BufferedImage bi = ...; // Here you would get a frame from the video

int width = bi.getWidth();
int height = bi.getHeight();

int[] pixels = ((DataBufferInt) bi.getRaster().getDataBuffer()).getData();

请注意,根据图片类型以及图片是否包含透明度,DataBuffer可能会因DataBufferIntDataBufferByte等而异。您可以在Oracle文档中了解不同的DataBuffersclick here

现在只需循环显示图像中的像素,我们就可以应用并创建任何类型的效果和过滤。

假设我们要创建一个grayscale效果,也称为black-and-white效果,您可以通过以下方式进行此操作。

for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
        final int index = x + y * width;

        final int pixel = pixels[index];

        final int alpha = (pixel >> 24) & 0xFF;
        final int red = (pixel >> 16) & 0xFF;
        final int green = (pixel >> 8) & 0xFF;
        final int blue = pixel & 0xFF;

        final int gray = (red + green + blue) / 3;

        pixels[index] = alpha << 24 | gray << 16 | gray << 8 | gray;
    }
}

现在您可以再次保存图像,或者做任何您想做的事情。虽然您也可以使用并绘制BufferedImage,因为BufferedImage提供的像素数组当然也会更改BufferedImage

重要如果您想要执行模糊效果,那么在计算每个像素将其存储到另一个数组后,因为执行模糊效果,需要周围的像素。因此,在计算所有像素时,您将替换旧的一次,一些像素将使用计算值而不是实际值。

上述代码当然也适用于图像。

附加

如果您想获得存储在单个int中的RGBA值,那么您可以执行以下操作。

int pixel = 0xFFFF8040; // This is a random testing value

int alpha = (pixel >> 24) & 0xFF; // Would equal 255 using the testing value
int red = (pixel >> 16) & 0xFF; // ... 255 ...
int green = (pixel >> 8) & 0xFF; // ... 128 ...
int blue = pixel & 0xFF; // ... 64 ...

然后,如果你有RGBA值并希望将它们组合成一个int,那么你可以执行以下操作。

int alpha = 255;
int red = 255;
int green = 128;
int blue = 64;

int pixel = alpha << 24 | red << 16 | green << 8 | blue;

如果您只有RGB值,那么您可以red << 16 | green << 8 | blue255 << 24 | red << 16 | green << 8 | blue