gpt4 book ai didi

android - 有效绘制字节数组流以在 Android 中显示的选项

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:57:46 24 4
gpt4 key购买 nike

简单来说,我需要做的就是在 Android 中显示视频帧的实时流(每帧都是 YUV420 格式)。我有一个回调函数,我将单个帧作为字节数组接收。看起来像这样的东西:

public void onFrameReceived(byte[] frame, int height, int width, int format) {
// display this frame to surfaceview/textureview.
}

一个可行但速度较慢的选择是将字节数组转换为位图并在 SurfaceView 上绘制到 Canvas 上。将来,我希望能够改变此帧的亮度、对比度等,因此我希望我可以使用 OpenGL-ES 来实现同样的效果。我还有哪些其他选择可以有效地做到这一点?

请记住,与 CameraMediaPlayer 类的实现不同,我无法使用 camera.setPreviewTexture(surfaceTexture) 将我的输出定向到 surfaceview/textureview ; 因为我在 C 中使用 Gstreamer 接收单个帧。

最佳答案

我在我的项目中使用 ffmpeg,但渲染 YUV 帧的原则应该与您自己相同。

例如,如果一个框架是 756 x 576,则 Y 框架将是该尺寸。 U 和 V 框架的宽度和高度是 Y 框架的一半,因此您必须确保考虑到尺寸差异。

我不知道相机 API,但我从 DVB 源获得的帧有一个宽度,而且每行都有一个跨度。帧中每行末尾的额外像素。以防万一您的相同,然后在计算纹理坐标时考虑到这一点。

调整纹理坐标以考虑宽度和步幅(线宽):

float u = 1.0f / buffer->y_linesize * buffer->wid; // adjust texture coord for edge

我使用的顶点着色器采用从 0.0 到 1.0 的屏幕坐标,但您可以更改这些以适应。它还接受纹理坐标和颜色输入。我使用了颜色输入,以便我可以添加褪色等。

顶点着色器:

#ifdef GL_ES
precision mediump float;
const float c1 = 1.0;
const float c2 = 2.0;
#else
const float c1 = 1.0f;
const float c2 = 2.0f;
#endif

attribute vec4 a_vertex;
attribute vec2 a_texcoord;
attribute vec4 a_colorin;
varying vec2 v_texcoord;
varying vec4 v_colorout;



void main(void)
{
v_texcoord = a_texcoord;
v_colorout = a_colorin;

float x = a_vertex.x * c2 - c1;
float y = -(a_vertex.y * c2 - c1);

gl_Position = vec4(x, y, a_vertex.z, c1);
}

fragment 着色器采用三个统一纹理,每个 Y、U 和 V 帧一个,并转换为 RGB。这也乘以从顶点着色器传入的颜色:

#ifdef GL_ES
precision mediump float;
#endif

uniform sampler2D u_texturey;
uniform sampler2D u_textureu;
uniform sampler2D u_texturev;
varying vec2 v_texcoord;
varying vec4 v_colorout;

void main(void)
{
float y = texture2D(u_texturey, v_texcoord).r;
float u = texture2D(u_textureu, v_texcoord).r - 0.5;
float v = texture2D(u_texturev, v_texcoord).r - 0.5;
vec4 rgb = vec4(y + 1.403 * v,
y - 0.344 * u - 0.714 * v,
y + 1.770 * u,
1.0);
gl_FragColor = rgb * v_colorout;
}

使用的顶点在:

float   x, y, z;    // coords
float s, t; // texture coords
uint8_t r, g, b, a; // colour and alpha

希望这对您有所帮助!

编辑:

对于 NV12 格式,您仍然可以使用 fragment 着色器,尽管我自己还没有尝试过。它将交错的 UV 作为亮度-alpha channel 或类似 channel 。

请参阅此处了解某人如何回答此问题:https://stackoverflow.com/a/22456885/2979092

关于android - 有效绘制字节数组流以在 Android 中显示的选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41651387/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com