在 C++ 中通过 Windows 视频将 4:2:0 YUV-Rawdata 写入 AVI 文件
我正在尝试将从采集卡接收到的一些 4:2:0 原始数据写入 AVI 文件。对于每个像素,字符缓冲区包含 2 个字节(16 位)。数据的顺序与 FOURCC UYVY: YUV 4:2:2 相同(Y 在每个像素处采样,U 和 V 在每行水平方向上每隔一个像素采样一次)。一个宏像素在 1 个 u_int32 中包含 2 个像素。
首先我尝试了 OpenCV Videowriter。但对于如此大量的视频数据来说,这实在是太慢了(我正在捕获 2 个视频流,每个视频流都是 1080p25 格式),所以我切换到“Video for Windows”-Windows 库。我的 C++ - 算法包含以下源代码:
首先,我初始化 AVIFile avi_left & AVIStream avi_left_s:
HRESULT hr = S_OK;
AVIFileInit();
hr=AVIFileOpen(&avi_left,L"Test.avi",OF_WRITE|OF_CREATE, NULL);
if (hr != 0)
{
printf("AVI ERROR");
Sleep(3000);
exit(0);
}
//No compression output with 25 fps
al_info.fccType = streamtypeVIDEO;
al_info.fccHandler = 0;
al_info.dwScale = 1;
al_info.dwRate = 25;
al_info.dwSuggestedBufferSize = 0;
al_info.dwSampleSize = 0;
SetRect( &al_info.rcFrame, 0, 0,1920,1080);
//Define Header for the YUV-Rawdata
BITMAPINFO bi;
ZeroMemory(&bi,sizeof(bi));
BITMAPINFOHEADER &bmi = bi.bmiHeader;
bmi.biSize=sizeof(bmi);
bmi.biWidth=1920;
bmi.biHeight=1080;
bmi.biPlanes=1;
bmi.biBitCount=16;
bmi.biCompression=0x59565955;
bmi.biSizeImage = bmi.biWidth*bmi.biHeight*2;
bmi.biXPelsPerMeter=10000;
bmi.biYPelsPerMeter=10000;
bmi.biClrUsed=0;
bmi.biClrImportant=0;
hr = AVIFileCreateStream(avi_left,&avi_left_s,&al_info);
hr = AVIStreamSetFormat(avi_left_s, 0,&bmi,sizeof(bmi));
如果有新数据到达:
//m_byteBufferleft = rawdata as char array in UYVY-order
BYTE* bufferleft=(BYTE*)m_byteBufferleft;
// Writing Data
long size = width * height * 2;
HRESULT hr = AVIStreamWrite(avi_left_s,frameCount-1,1,bufferleft,size,AVIIF_KEYFRAME,NULL,NULL);
如果捕获已结束:
//Closing AVIStream & AVIFile
AVIStreamClose(avi_left_s);
AVIFileClose(avi_left);
AVIFileExit();
但是此代码无法正常工作。当最后一部分运行时,我收到错误消息:Unbehandelte Ausnahme bei 0x5ee36266 in XsensDecklinkCapture.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0xcdcdcdcd。也许你有什么想法?我的代码中有什么大错误吗?
I'm trying to write some 4:2:0 rawdata received from a capture card into an AVI-File. For every pixel the char buffer contains 2 Bytes (16 Bit). The order of the data is the same as FOURCC UYVY: YUV 4:2:2 (Y sample at every pixel, U and V sampled at every second pixel horizontally on each line). A macropixel contains 2 pixels in 1 u_int32.
First I tried the OpenCV Videowriter. But this is simply slow for this huge amount of video data (I'm capturing 2 video streams, each is 1080p25 format), so I switched to the "Video for Windows"-Library by Windows. My C++ - algorithm contains the following source code:
First I initialise the AVIFile avi_left & AVIStream avi_left_s:
HRESULT hr = S_OK;
AVIFileInit();
hr=AVIFileOpen(&avi_left,L"Test.avi",OF_WRITE|OF_CREATE, NULL);
if (hr != 0)
{
printf("AVI ERROR");
Sleep(3000);
exit(0);
}
//No compression output with 25 fps
al_info.fccType = streamtypeVIDEO;
al_info.fccHandler = 0;
al_info.dwScale = 1;
al_info.dwRate = 25;
al_info.dwSuggestedBufferSize = 0;
al_info.dwSampleSize = 0;
SetRect( &al_info.rcFrame, 0, 0,1920,1080);
//Define Header for the YUV-Rawdata
BITMAPINFO bi;
ZeroMemory(&bi,sizeof(bi));
BITMAPINFOHEADER &bmi = bi.bmiHeader;
bmi.biSize=sizeof(bmi);
bmi.biWidth=1920;
bmi.biHeight=1080;
bmi.biPlanes=1;
bmi.biBitCount=16;
bmi.biCompression=0x59565955;
bmi.biSizeImage = bmi.biWidth*bmi.biHeight*2;
bmi.biXPelsPerMeter=10000;
bmi.biYPelsPerMeter=10000;
bmi.biClrUsed=0;
bmi.biClrImportant=0;
hr = AVIFileCreateStream(avi_left,&avi_left_s,&al_info);
hr = AVIStreamSetFormat(avi_left_s, 0,&bmi,sizeof(bmi));
If some new Data is arriving:
//m_byteBufferleft = rawdata as char array in UYVY-order
BYTE* bufferleft=(BYTE*)m_byteBufferleft;
// Writing Data
long size = width * height * 2;
HRESULT hr = AVIStreamWrite(avi_left_s,frameCount-1,1,bufferleft,size,AVIIF_KEYFRAME,NULL,NULL);
If Capturing has ended:
//Closing AVIStream & AVIFile
AVIStreamClose(avi_left_s);
AVIFileClose(avi_left);
AVIFileExit();
But this code doesn't works fine. While the last part is running I receive the error message: Unbehandelte Ausnahme bei 0x5ee36266 in XsensDecklinkCapture.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0xcdcdcdcd. Maybe you have any ideas? Are there any big mistakes in my code?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在检查视频代码本身之前,一旦出现访问冲突异常,您就应该直接解决这个问题。您有异常 - 您可以检查异常位置的调用堆栈,并且您应该将其发布到此处以提供导致问题的代码行。
使用
0xcdcdcdcd
,您可能会遇到未初始化指针被当作有效指针来访问的问题。Before even checking the video code per se, as soon you have access violation exception you should address this problem directly. You have exception - you can check call stack at exception position, and you should post it here to provide the code line which causes the problem.
With
0xcdcdcdcd
you are likely to have a problem with an uninitialized pointer being accessed as if it is valid.