基本上我正在做的事情:
我有一个视频流(YUV格式)。每帧被提取到缓冲区(frameBytes
)。之后,此缓冲区用于进行YUV-> RGB转换,然后转换为IplImage
。然后IplImage
被转移到cv::Mat
并显示在OpenGL上下文中。一切正常。
我想要做的是绕过IplImage
和cv::Mat
部分直接使用OpenGL中的frameBytes
缓冲区,并在着色器中进行转换。
这个解释仅适用于上下文,因为我遇到的问题更简单。
要查看我是否可以使用缓冲区,我尝试使用memcpy复制它,然后将其保存在QImage
然后保存在文件中。
以下是此部分的代码:
unsigned char *mycopy = new unsigned char[1920*1080*3];
memcpy(mycopy, frameBytes, sizeof(1920*1080*3));
QImage *img = new QImage(mycopy, 1920, 1080, QImage::Format_RGB888);
img->save("image.jpg",0,-1);
frameBytes包含来自视频流的YUV数据。我知道它的YUV和我试图创建一个RGB888格式的QImage,但由于QImage不支持格式,我没有在那里进行转换,我认为它仍然会保存图像,但颜色错误,所以我不在乎当下(也许这个假设是错误的?)。
问题是,保存的图像为黑色。
仅供参考,以下是我使用frameBytes
进行YUV-> RGB转换的示例。
void DeckLinkCaptureDelegate::convertFrameToOpenCV(void* frameBytes, IplImage * m_RGB){
if(!m_RGB) m_RGB = cvCreateImage(cvSize(1920, 1080), IPL_DEPTH_8U, 3);
unsigned char* pData = (unsigned char *) frameBytes;
for(int i = 0, j=0; i < 1920 * 1080 * 3; i+=6, j+=4)
{
unsigned char u = pData[j];
unsigned char y = pData[j+1];
unsigned char v = pData[j+2];
//fprintf(stderr, "%d\n", v);
m_RGB->imageData[i+2] = 1.0*y + 8 + 1.402*(v-128); // r
m_RGB->imageData[i+1] = 1.0*y - 0.34413*(u-128) - 0.71414*(v-128); // g
m_RGB->imageData[i] = 1.0*y + 1.772*(u-128) + 0; // b
y = pData[j+3];
m_RGB->imageData[i+5] = 1.0*y + 8 + 1.402*(v-128); // r
m_RGB->imageData[i+4] = 1.0*y - 0.34413*(u-128) - 0.71414*(v-128); // g
m_RGB->imageData[i+3] = 1.0*y + 1.772*(u-128) + 0;
}
}
答案 0 :(得分:0)
您没有将所有数据复制到新缓冲区:
unsigned char *mycopy = new unsigned char[1920*1080*3];
memcpy(mycopy, frameBytes, sizeof(1920*1080*3));
那里的sizeof
意味着您只复制int
大小的块,而不是6MB。它看起来像是使用静态数组的意外保留?替换为
const size_t bufsize = 1920*1080*3;
auto *mycopy = new unsigned char[bufsize];
memcpy(mycopy, frameBytes, bufsize);
或者,不是自己进行内存分配(并且在delete[]
被破坏后负责QImage
),您可以复制图像:
const unsigned char *bytes = frameBytes;
QImage img = QImage(bytes, 1920, 1080, QImage::Format_RGB888).copy();
这样做的方法是我们使用QImage
创建一个临时frameBytes
作为源(我们将其作为指针传递给const
以坚持它是只读的)。然后我们copy()
将整个QImage
转移到新的copy()
,扔掉临时的。{1}}。 QImage
执行类似于上面代码的操作,但现在我们不必进行计算,从而消除了一些随之而来的错误。
另请注意,我更喜欢按值传递{{1}}。虽然这看起来效率低下,但大多数(可复制的)Qt类型都被设计为引用计数的写时复制结构,并且可以通过这种方式安全地使用,从而消除了另一类错误(内存管理)。对于Qt的集合类型也是如此,并且非常有用。