我们有一个应用程序可以读取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) 我已经复制粘贴了我在 stackoverflow 上找到的一些代码,将默认的相机预览 YUV 转换为 RGB 格式,然后将其上传到 OpenGL 进行处理。效果很好,问题是大部分 CPU 都忙于将 YUV 图像转换为 RGB 格式,结果变成了瓶颈。
我想将 YUV 图像上传到 GPU,然后在片段着色器中将其转换为 RGB。我采用了相同的 Java YUV 到 RGB 函数,我发现它在 CPU 上工作,并试图让它在 GPU 上工作。
它变成了一个相当小的噩梦,因为在 Java 和 GPU 上进行计算存在一些差异。首先,预览图像在 Java 中以 byte[] 形式出现,但字节是有符号的,因此可能存在负值。
此外,片段着色器通常处理 [0..1] 浮点值而不是字节。
我确信这是可以解决的,我几乎解决了。但我花了几个小时试图找出我做错了什么,但无法让它发挥作用。
最重要的是,我要求某人编写此着色器函数并最好对其进行测试。对我来说,这将是一项乏味的猴子工作,因为我真的不明白为什么这种转换会以这样的方式工作,而我只是尝试在 GPU 上模仿相同的功能。
这与我在 Java 上使用的功能非常相似: Displaying YUV Image in Android
我在CPU上做了一些工作,比如把1.5*w h bytes的YUV格式变成aw h*YUV,如下:
static public void decodeYUV420SP(int[] rgba, byte[] yuv420sp, int width,
int height) {
final int frameSize = width * height;
for (int j = …Run Code Online (Sandbox Code Playgroud) 我想从任何图像在Ubuntu上创建一个示例YUV422帧,这样我就可以为了学习而编写YUV422到RGB888的功能.我真的希望能够使用可信任的工具来创建示例并转换回jpeg.
我尝试过ImageMagick,但显然做错了:
convert -size 640x480 -depth 24 test.jpg -colorspace YUV -size 640x480 -depth 16 -sampling-factor 4:2:2 tmp422.yuv
Run Code Online (Sandbox Code Playgroud)

convert -colorspace YUV -size 640x480 -depth 16 -sampling-factor 4:2:2 tmp422.yuv -size 640x480 -depth 24 -colorspace RGB test2.jpg
Run Code Online (Sandbox Code Playgroud)

我还在Ubuntu上安装了mpegtools包,以便使用jpeg2yuv:
>> jpeg2yuv -f 1 test.jpg
INFO: [jpeg2yuv] Reading jpeg filenames from stdin.
INFO: [jpeg2yuv] Parsing & checking input files.
**ERROR: [jpeg2yuv] System error while opening: "": No such file or directory
Run Code Online (Sandbox Code Playgroud)
显然,别的东西是错的.请问有人可以说明如何实现这一目标吗?谢谢 -
我一直希望一些代码会出现在互联网上,但一无所获;)
WebRTC传入的I420Frame对象似乎有3个yuvPlanes数组
典型的 Android 相机应用程序将 PreviewCallback.onPreviewFrame byte[] 作为单个字节数组获取。
有人可以帮助我如何将 I420Frames yuvPlanes 转换为单个 byte[] 数组,如 PreviewCallback.onPreviewFrame byte[] YCbCr_420_SP (NV21)?
作为参考,VideoStreamsView.java 有此代码可以渲染到 OpenGL - 但我只想像相机预览一样;)来自: https: //code.google.com/p/libjingle/source/browse/trunk/talk/examples/ android/src/org/appspot/apprtc/VideoStreamsView.java?r=286
// Upload the YUV planes from |frame| to |textures|.
private void texImage2D(I420Frame frame, int[] textures) {
for (int i = 0; i < 3; ++i) {
ByteBuffer plane = frame.yuvPlanes[i];
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[i]);
int w = i == 0 ? frame.width : frame.width / 2;
int h = i == 0 ? …Run Code Online (Sandbox Code Playgroud) 我在 Android 中使用 NV21 图像已经有一段时间了,我一直在跟踪一个错误,该错误可能是由 NV21 图像中的不正确索引字节引起的。
这个问题的答案中的图像很好地概述了 Y、U 和 V 字节在图像缓冲区中的位置。不确定是否允许,但我将其嵌入如下:
我正在开发自定义相机API 2应用程序,我注意到当我使用ImageReader回调时,某些设备上的捕获格式转换是不同的.
例如在Nexus 4中工作不正常并且在Nexus5X中看起来没问题,这是输出.
我以这种形式初始化ImageReader:
mImageReader = ImageReader.newInstance(320, 240, ImageFormat.YUV_420_888,2);
Run Code Online (Sandbox Code Playgroud)
而我的回调是简单的回调ImageReader回调.
mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable( ImageReader reader) {
try {
mBackgroundHandler.post(
new ImageController(reader.acquireNextImage())
);
}
catch(Exception e)
{
//exception
}
}
Run Code Online (Sandbox Code Playgroud)
};
在Nexus 4的情况下:我有这个错误.
D/qdgralloc: gralloc_lock_ycbcr: Invalid format passed: 0x32315659
Run Code Online (Sandbox Code Playgroud)
当我尝试在两个设备中编写原始文件时,我有这些不同的图像.所以我知道Nexus 5X图像具有NV21编码,而Nexus 4具有YV12编码.

我找到了图像格式的规范,我尝试在ImageReader中获取格式.有YV12和NV21选项,但显然,当我尝试获取格式时,我得到YUV_420_888格式.
int test=mImageReader.getImageFormat();
Run Code Online (Sandbox Code Playgroud)
那么有没有办法让相机输入格式(NV21或YV12)区分相机类中的这种编码类型?CameraCharacteristics可能吗?
提前致谢.
垂发.PD:我使用OpenGL显示RGB图像,我使用Opencv进行转换为YUV_420_888.
我正在使用 DirectX 来绘制视频。通过Intel Media SDK解码后。然后我通过以下英特尔代码绘制它:
mfxStatus CD3D11Device::RenderFrame(mfxFrameSurface1 * pSrf, mfxFrameAllocator * pAlloc)
{
HRESULT hres = S_OK;
mfxStatus sts;
sts = CreateVideoProcessor(pSrf);
MSDK_CHECK_STATUS(sts, "CreateVideoProcessor failed");
hres = m_pSwapChain->GetBuffer(0, __uuidof( ID3D11Texture2D ), (void**)&m_pDXGIBackBuffer.p);
if (FAILED(hres))
return MFX_ERR_DEVICE_FAILED;
D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC OutputViewDesc;
if (2 == m_nViews)
{
m_pVideoContext->VideoProcessorSetStreamStereoFormat(m_pVideoProcessor, 0, TRUE,D3D11_VIDEO_PROCESSOR_STEREO_FORMAT_SEPARATE,
TRUE, TRUE, D3D11_VIDEO_PROCESSOR_STEREO_FLIP_NONE, NULL);
m_pVideoContext->VideoProcessorSetOutputStereoMode(m_pVideoProcessor,TRUE);
OutputViewDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2DARRAY;
OutputViewDesc.Texture2DArray.ArraySize = 2;
OutputViewDesc.Texture2DArray.MipSlice = 0;
OutputViewDesc.Texture2DArray.FirstArraySlice = 0;
}
else
{
OutputViewDesc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
OutputViewDesc.Texture2D.MipSlice = 0;
}
if (1 == m_nViews || 0 == …Run Code Online (Sandbox Code Playgroud) 我想用openCV阅读YUV视频。YUV视频为1920 * 1080,并使用YUV422格式(我已经尝试使用yuviewer读取此视频,并且可以正常工作)
我正在将Python3.6.4与带有OpenCV 3.3.1的Anaconda环境一起使用
首先我尝试了这个脚本/sf/answers/3347076981/但是这行
cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR_Y422)
Run Code Online (Sandbox Code Playgroud)
给我这个错误。
File "read-yuv-video.py", line 29, in <module>
bgr = cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR_UYVY)
cv2.error: C:\ci\opencv_1512688052760\work\modules\imgproc\src\color.cpp:11228: error: (-215) scn == 2 && depth == 0 in function cv::cvtColor
Run Code Online (Sandbox Code Playgroud)
当尝试从Y444或Y420转换为RGB或RGBA或GREY时,我也遇到此错误。我在Google或stackoverflow上找不到完全相同的错误。我试图重新安装opencv软件包,但没有成功。
在我下面的脚本中,除最后一个之外,所有cvtColor均有效。通过工作,我的意思是它显示图像但颜色错误。
import numpy as np
import cv2
# filename = r'C:\myPath\voile.yuv'
filename = r'C:\myPath\credits.yuv'
yuv_file = open(filename, 'rb')
frame_len = 1920 * 1080 * 3/2
shape = (int(1080 * 1.5), 1920)
raw = yuv_file.read(int(frame_len))
yuv = np.frombuffer(raw, dtype=np.uint8)
yuv = yuv.reshape(shape)
yuv = cv2.resize(yuv, …Run Code Online (Sandbox Code Playgroud) 我一直在尝试在 Vulkan 中对 YCbCr 图像进行采样,但我一直得到不正确的结果,我希望有人能够发现我的错误。
我有一个 NV12 YCbCr 图像,我想将其渲染到形成四边形的两个三角形上。如果我理解正确,对应于 NV12 的 VkFormat 是 VK_FORMAT_G8_B8R8_2PLANE_420_UNORM。下面是我希望工作的代码,但我也会尝试解释我正在尝试做的事情:
代码:
VkSamplerYcbcrConversion ycbcr_sampler_conversion;
VkSamplerYcbcrConversionInfo ycbcr_info;
VkSampler ycbcr_sampler;
VkImage image;
VkDeviceMemory image_memory;
VkDeviceSize memory_offset_plane0, memory_offset_plane1;
VkImageView image_view;
enum YCbCrStorageFormat
{
NV12
};
unsigned char* ReadYCbCrFile(const std::string& filename, YCbCrStorageFormat storage_format, VkFormat vulkan_format, uint32_t* buffer_size, uint32_t* buffer_offset_plane1, uint32_t* buffer_offset_plane2)
{ …Run Code Online (Sandbox Code Playgroud) yuv ×10
android ×4
rgb ×4
c++ ×2
gpu ×2
avfoundation ×1
directshow ×1
directx-11 ×1
ffmpeg ×1
image ×1
ios ×1
java ×1
nv12-nv21 ×1
opencv ×1
python ×1
python-3.x ×1
texture2d ×1
ubuntu ×1
vulkan ×1
webrtc ×1