本次例子使用的是AVFoundation
提供的AVCaptureVideoDataOutput
获取每一帧的CVPixelBufferRef
,详细步骤就不说了,网上有很多例子,这篇文章主要是介绍Metal中实现YUV转RGB格式的一些主要步骤,和OpenGL中的步骤差不多,主要是API和着色器不同,思路是一样的,这篇文章适合熟悉OpenGL
视频渲染和有Metal
基础的人观看,代码就不一一注释了,主要是本人理解的也不是很深,怕误人子弟。
1 首先是shader上的片元着色器转换YUV到RGB
#include <metal_stdlib>
using namespace metal;
#define YUV_SHADER_ARGS VertexOut inFrag [[ stage_in ]],\
texture2d<float> lumaTex [[ texture(0) ]],\
texture2d<float> chromaTex [[ texture(1) ]],\
sampler bilinear [[ sampler(0) ]], \
constant ColorParameters *colorParameters [[ buffer(0) ]]// RGB到YUV的转换矩阵
struct VertexIn{
packed_float3 position;
packed_float4 color;
packed_float2 st;
};
struct VertexOut{
float4 position [[position]]; //1
float4 color;
float2 st;
};
struct ColorParameters
{
float3x3 yuvToRGB;
};
vertex VertexOut texture_vertex(
const device VertexIn* vertex_array [[ buffer(0) ]], //1
unsigned int vid [[ vertex_id ]]) {
VertexIn VertexIn = vertex_array[vid];
VertexOut VertexOut;
VertexOut.position = float4(VertexIn.position,1); //3
VertexOut.color = VertexIn.color;
VertexOut.st = VertexIn.st;
return VertexOut;
}
fragment half4 yuv_rgb(YUV_SHADER_ARGS)
{
float3 yuv;
yuv.x = lumaTex.sample(bilinear, inFrag.st).r;
yuv.yz = chromaTex.sample(bilinear,inFrag.st).rg - float2(0.5);
return half4(h