我想用一个包含yuv数据的采样器将yuv转换为opengl es shader中的rgb.我的代码如下:
1)我将yuv数据发送到纹理:
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE,
mData.w, mData.h * 3 / 2, 0, GLES20.GL_LUMINANCE,
GLES20.GL_UNSIGNED_BYTE, ByteBuffer.wrap(mData.yuv));
Run Code Online (Sandbox Code Playgroud)
2)我的顶点着色器:
attribute vec4 position;
attribute vec2 inputTextureCoordinate;
attribute mediump float width;
varying vec2 v_texCoord;
varying mediump vec2 v_vuTexCoord;
varying mediump float x_coord;
void main()
{
gl_Position = position;
v_texCoord = vec2(inputTextureCoordinate.x, inputTextureCoordinate.y * 0.6666667);
v_vuTexCoord = vec2(inputTextureCoordinate.x, inputTextureCoordinate.y * 0.333333 + 0.6666667);
x_coord = floor(inputTextureCoordinate.x * width);
}
Run Code Online (Sandbox Code Playgroud)
3)我的片段着色器:
uniform sampler2D inputImageTexture;
varying mediump vec2 v_texCoord;
varying mediump vec2 v_vuTexCoord;
varying mediump float …Run Code Online (Sandbox Code Playgroud) 我正在与之合作AVCaptureVideoDataOutput并希望转换CMSampleBufferRef为UIImage.许多答案都是一样的,比如从CMSampleBufferRef创建的UIImage没有在UIImageView中显示?和AVCaptureSession有多个预览
如果我将VideoDataOutput颜色空间设置为BGRA,则可以正常工作(记入此答案CGBitmapContextCreateImage错误)
NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;
NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];
[dataOutput setVideoSettings:videoSettings];
Run Code Online (Sandbox Code Playgroud)
如果没有上述视频设置,我将收到以下错误
CGBitmapContextCreate: invalid data bytes/row: should be at least 2560 for 8 integer bits/component, 3 components, kCGImageAlphaPremultipliedFirst.
<Error>: CGBitmapContextCreateImage: invalid context 0x0
Run Code Online (Sandbox Code Playgroud)
使用BGRA不是一个好的选择,因为从YUV(默认的AVCaptureSession颜色空间)到BGRA有转换开销,如Brad和Codo在如何从AVCaptureSession中获取CMSampleBuffer中的Y组件所述?
那么,有没有办法转换CMSampleBufferRef到UIImage与YUV色彩空间的工作?
在我的项目中,我使用OpenH264编解码器,据说以YUV 4:2:0 planar格式输出数据.解码后,我得到一个带有width * height * 1.5元素的数组,在显示时,看起来像这个图像:
http://o3d.googlecode.com/svn/trunk/samples_webgl/assets/shaving_cream.png
为什么主要的一个下面有四个区域(包含Y-负责灰度 - 元素),而不是两个,就像我的第二张图片一样?这是否意味着格式不同或我错了,我的世界崩溃了?
我认为resoult应该是这样的:

我尝试将图像从YUV_420_888转换为rgb,我对输出图像有些麻烦.在ImageReader中,我以YUV_420_888格式获取图像(使用相机2 api获取此图像预览).
imageReader = ImageReader.newInstance(1920,1080,ImageFormat.YUV_420_888,10);
Run Code Online (Sandbox Code Playgroud)
在android sdk中为YuvImage类编写,即YuvImage仅使用NV21,YUY2.
因为我们可以看到N21和yuv420之间的差异不大,我尝试将数据转换为N21
在onImageAvailable中我单独获得每个Planes并将它们放在正确的位置(如图像所示)
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ByteBuffer bufferY = image.getPlanes()[0].getBuffer();
byte[] data0 = new byte[bufferY.remaining()];
bufferY.get(data0);
ByteBuffer bufferU = image.getPlanes()[1].getBuffer();
byte[] data1 = new byte[bufferU.remaining()];
bufferU.get(data1);
ByteBuffer bufferV = image.getPlanes()[2].getBuffer();
byte[] data2 = new byte[bufferV.remaining()];
bufferV.get(data2);
...
outputStream.write(data0);
for (int i=0;i<bufferV.remaining();i++) {
outputStream.write(data1[i]);
outputStream.write(data2[i]);
}
Run Code Online (Sandbox Code Playgroud)
创建YuvImage后,转换为Bitmap,查看并保存
final YuvImage yuvImage = new YuvImage(outputStream.toByteArray(), ImageFormat.NV21, 1920,1080, null);
ByteArrayOutputStream outBitmap = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0, 0,1920, 1080), 95, outBitmap);
byte[] …Run Code Online (Sandbox Code Playgroud) 我正在编写一个代码,以使用桌面复制捕获桌面,并使用英特尔hardwareMFT将其编码为h264。编码器仅接受NV12格式作为输入。我有一个DXGI_FORMAT_B8G8R8A8_UNORM到NV12转换器(https://github.com/NVIDIA/video-sdk-samples/blob/master/nvEncDXGIOutputDuplicationSample/Preproc.cpp)可以正常工作,并且基于DirectX VideoProcessor。
问题是某些英特尔图形硬件上的VideoProcessor仅支持从DXGI_FORMAT_B8G8R8A8_UNORM到YUY2的转换,但不支持NV12的转换,我已经通过GetVideoProcessorOutputFormats枚举支持的格式来确认了相同的转换。尽管VideoProcessor Blt成功实现,没有任何错误,而且我可以看到输出视频中的帧有些像素化,但是如果仔细观察它,我会注意到它。
我猜想,VideoProcessor只是故障转移到了下一个受支持的输出格式(YUY2),而我在不知不觉中将其馈送到认为输入已按照配置在NV12中的编码器。NV12和YUY2之间几乎没有像字节顺序和子采样之类的差异,因此不会出现帧故障或严重损坏的情况。另外,在支持NV12转换的硬件上我也没有像素化问题。
所以我决定使用基于此代码的像素着色器进行颜色转换(https://github.com/bavulapati/DXGICaptureDXColorSpaceConversionIntelEncode/blob/master/DXGICaptureDXColorSpaceConversionIntelEncode/DuplicationManager.cpp)。我能够使像素着色器正常工作,我也已经在这里上传了我的代码(https://codeshare.io/5PJjxP)供参考(尽可能简化了它)。
现在,我剩下两个通道,分别是色度和亮度(ID3D11Texture2D纹理)。对于将两个独立的通道有效地打包到一个ID3D11Texture2D纹理中,以便将其提供给编码器,我确实感到困惑。有没有一种方法可以将Y和UV通道有效地打包到GPU中的单个ID3D11Texture2D中?我非常厌倦基于CPU的方法,因为它价格昂贵,并且无法提供最佳的帧速率。实际上,我什至不愿意将纹理复制到CPU。我正在考虑一种在GPU中执行此操作的方法,而无需在CPU和GPU之间来回复制。
我已经对此进行了相当长时间的研究,没有任何进展,我们将不胜感激。
/**
* This method is incomplete. It's just a template of what I want to achieve.
*/
HRESULT CreateNV12TextureFromLumaAndChromaSurface(ID3D11Texture2D** pOutputTexture)
{
HRESULT hr = S_OK;
try
{
//Copying from GPU to CPU. Bad :(
m_pD3D11DeviceContext->CopyResource(m_CPUAccessibleLuminanceSurf, m_LuminanceSurf);
D3D11_MAPPED_SUBRESOURCE resource;
UINT subresource = D3D11CalcSubresource(0, 0, 0);
HRESULT hr = m_pD3D11DeviceContext->Map(m_CPUAccessibleLuminanceSurf, subresource, D3D11_MAP_READ, 0, &resource);
BYTE* sptr = reinterpret_cast<BYTE*>(resource.pData);
BYTE* dptrY = nullptr; // point to the address of …Run Code Online (Sandbox Code Playgroud) 我们有一个应用程序可以读取GigE YUV视频流并将其显示在屏幕上.通过分析,我们了解到,将每个帧从YUV(UYVY)转换为RGB24的功能至少比我们的相机到屏幕管道的任何其他部分都要多一个数量级的时间和CPU.
我们使用的转换功能由GigE软件供应商(Pleora)提供,并且比我们自己的' 天真 '(非优化)实现略快.我们在其余的管道中使用DirectShow."任务管理器基准测试"显示我们的1080p 30fps流,当我们跳过转换时(当然会出现乱码图像)的CPU使用率为4-5%,当我们调用转换功能时,CPU使用率为15-19%.
我们的问题是:
谢谢!埃里克.
我有一个FFMPEG AVFrame中YUVJ420P,我想将其转换为一个CVPixelBufferRef带CVPixelBufferCreateWithBytes.我想这样做的原因是使用AVFoundation来显示/编码帧.
我选择kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange并尝试转换它,因为AVFrame有三个平面的数据
Y480 Cb240 Cr240.根据我所研究的内容,这与所选的相匹配kCVPixelFormatType.通过双平面我需要将其转换为包含Y480和CbCr480Interleaved 的缓冲区.
我尝试用2个平面创建一个缓冲区:
frame->data[0] 在第一架飞机上,frame->data[1]并frame->data[2]在第二个平面上交错.但是,我收到的返回错误-6661 (invalid a)来自CVPixelBufferCreateWithBytes:
"Invalid function parameter. For example, out of range or the wrong type."
Run Code Online (Sandbox Code Playgroud)
我根本没有关于图像处理的专业知识,所以任何指向文档的指针都可以让我从正确的方法开始解决这个问题.我的C技能也不是最重要的,所以也许我在这里犯了一个基本错误.
uint8_t **buffer = malloc(2*sizeof(int *));
buffer[0] = frame->data[0];
buffer[1] = malloc(frame->linesize[0]*sizeof(int));
for(int i = 0; i<frame->linesize[0]; i++){
if(i%2){
buffer[1][i]=frame->data[1][i/2];
}else{
buffer[1][i]=frame->data[2][i/2];
}
}
int ret = CVPixelBufferCreateWithBytes(NULL, frame->width, frame->height, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, …Run Code Online (Sandbox Code Playgroud) 我有一个缓冲区,其中包含YV12格式的图像.现在我要将此缓冲区转换为RGB格式或直接从中创建Mat对象!有人能帮我吗?我试过这段代码:
cv::Mat input(widthOfImg, heightOfImg, CV_8UC1, vy12Buffer);
cv::Mat converted;
cv::cvtColor(input, converted, CV_YUV2RGB_YV12);
Run Code Online (Sandbox Code Playgroud) 
我是HLSL的新手.我正在尝试将使用DXGI桌面复制API从BGRA捕获的图像的色彩空间转换为使用纹理作为渲染目标的YUV444.
我已设置像素着色器以执行所需的转换.从渲染目标纹理中取4:2:0子采样YUV并使用ffmpeg将其编码为H264,我可以看到图像.
问题是 - 它是绿色的.
着色器的输入颜色信息是浮点数据类型,但RGB到YUV转换的系数矩阵假定整数颜色信息.
如果我使用钳位功能并将整数从输入颜色中取出,我将失去准确性.
欢迎任何建议和指示.如果有任何其他信息有帮助,请告诉我.
我怀疑我写的Pixel着色器,因为我第一次使用它.这是像素着色器.
float3 rgb_to_yuv(float3 RGB)
{
float y = dot(RGB, float3(0.29900f, -0.16874f, 0.50000f));
float u = dot(RGB, float3(0.58700f, -0.33126f, -0.41869f));
float v = dot(RGB, float3(0.11400f, 0.50000f, -0.08131f));
return float3(y, u, v);
}
float4 PS(PS_INPUT input) : SV_Target
{
float4 rgba, yuva;
rgba = tx.Sample(samLinear, input.Tex);
float3 ctr = float3(0, 0, .5f);
return float4(rgb_to_yuv(rgba.rgb) + ctr, rgba.a);
}
Run Code Online (Sandbox Code Playgroud)
渲染目标映射到CPU可读纹理,并将YUV444数据复制到3个BYTE阵列并提供给ffmpeg libx264编码器.编码器将编码的数据包写入视频文件.
在这里,我考虑每个2X2像素矩阵一个U(Cb)和一个V(Cr)和4个Y值.
我从纹理中检索yuv420数据: …
我正在使用本机实现 (org.webrtc:google-webrtc:1.0.24064) 开发基于 WebRTC 的 Android 应用程序,我需要发送一系列位图以及相机流。
据我了解,我可以从org.webrtc.VideoCapturer一个单独的线程派生并进行渲染,并将视频帧发送给观察者;但是它希望它们是 YUV420,我不确定我是否在进行正确的转换。
这是我目前拥有的:CustomCapturer.java
有没有我可以做这种事情的例子?谢谢。