测试代码:
代码语言:javascript复制HANDLE hReadPipe, hWritePipe;
SECURITY_ATTRIBUTES sa;
int testFfmpegPipe() // 测试ffmpeg管道io
{
char cmdString[200]{ "ffmpeg -i D:\vc\images\small.mp4 -f image2pipe -pix_fmt bgr24 -vcodec rawvideo -" };
// 创建管道
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL; //使用系统默认的安全描述符
sa.bInheritHandle = TRUE; //一定要为TRUE,不然句柄不能被继承。
CreatePipe(&hReadPipe, &hWritePipe, &sa, 0); //创建pipe内核对象,设置好hReadPipe,hWritePipe.
// 创建dos子进程
STARTUPINFO si;
PROCESS_INFORMATION pi;
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = hWritePipe; //设定其标准错误输出为hWritePipe
si.hStdOutput = hWritePipe; //设定其标准输出为hWritePipe
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
if (!CreateProcess(NULL, cmdString
, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi)) {
//MessageBox("Error on CreateProcess()");
return 1;
}
CloseHandle(hWritePipe);
Mat rgba = Mat::zeros(cv::Size(560,320), CV_8UC3);
const uint32_t framebytes = 560 * 320 * 3 * 1.1;
char buffer[framebytes] = { 0 };
DWORD bytesRead;
uint32_t a = 0;
while (true) {
if (ReadFile(hReadPipe, buffer, framebytes, &bytesRead, NULL) == NULL)//从hReadPipe中读出数据.
break;
if (bytesRead<5000) {
cout << buffer << endl;
}
cout << bytesRead << endl;
}
return 0;
}
视频是 560*320,166帧
上面主进程读取的字节数如下:共,2834行,与理想的166帧166行相差甚远,每帧560*320*3=537600也和下面的不一样。
代码语言:javascript复制44
1686
67
701
17
93
34
391
32768
32768
32768
32768
32768
32768
32768
32768
32768
32768
32768
32768
32768
32768
32768
32768
13312
...
32768
32768
32768
32768
13312
100
104
开头和结果这些小字节的都是解码的什么鬼哦
打印出来才发现,是ffmpeg的各种提示信息。。。。
代码语言:javascript复制ffmpeg version 4.3.1-full_build-www.gyan.dev
Copyright (c) 2000-2020 the FFmpeg developers
built with gcc 10.2.0 (Rev1, Built by MSYS2 project)
configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-lzma --enable-libsnappy --enable-zlib --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libdav1d --enable-libzvbi --enable-librav1e --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-libaom --enable-libopenjpeg --enable-libvpx --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libmfx --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libwavpack --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint
libavutil 56. 51.100 / 56. 51.100
libavcodec 58. 91.100 / 58. 91.100
libavformat 58. 45.100 / 58. 45.100
libavdevice 58. 10.100 / 58. 10.100
libavfilter 7. 85.100 / 7. 85.100
libswscale 5. 7.100 / 5. 7.100
libswresample 3. 7.100 / 3. 7.100
libpostproc 55. 7.100 / 55. 7.100
把头尾的这些小字节去掉,总数刚好对的上,看来这个buffer是固定了32768=2^15不够一帧,要自己循环处理。
上面16个32768 13312 刚好等于一帧大小。
好了,需要ffmpeg屏蔽中间提示信息,加上这个就好了:
代码语言:javascript复制 -loglevel quiet
加上帧大小,循环读出,满足一帧容量后输出,最终代码如下:
代码语言:javascript复制HANDLE hReadPipe, hWritePipe;
SECURITY_ATTRIBUTES sa;
int testFfmpegPipe() // 测试ffmpeg管道io
{
char cmdString[200]{ "ffmpeg -loglevel quiet -i D:\vc\images\small.mp4 -f image2pipe -pix_fmt bgr24 -vcodec rawvideo -" };
// 创建管道
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL; //使用系统默认的安全描述符
sa.bInheritHandle = TRUE; //一定要为TRUE,不然句柄不能被继承。
CreatePipe(&hReadPipe, &hWritePipe, &sa, 0); //创建pipe内核对象,设置好hReadPipe,hWritePipe.
// 创建dos子进程
STARTUPINFO si;
PROCESS_INFORMATION pi;
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = hWritePipe; //设定其标准错误输出为hWritePipe
si.hStdOutput = hWritePipe; //设定其标准输出为hWritePipe
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
if (!CreateProcess(NULL, cmdString
, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi)) {
//MessageBox("Error on CreateProcess()");
return 1;
}
CloseHandle(hWritePipe);
Mat rgba = Mat::zeros(cv::Size(560,320), CV_8UC3);
const uint32_t framebytes = 560 * 320 * 3;
char buffer[framebytes] = { 0 };
uint32_t readCount = 0;
DWORD bytesRead;
while (true) {
if (ReadFile(hReadPipe, buffer, framebytes, &bytesRead, NULL) == NULL) { //从hReadPipe中读出数据.
break;
}
memcpy(rgba.data readCount, buffer, bytesRead);
readCount = bytesRead;
if (readCount == framebytes) { // 拿到完整一帧了
cout << "frame finished." << endl;
readCount = 0;
waitKey(100);
imshow("frame", rgba);
//imwrite("D:\vc\images\xx.bmp", rgba);
}
}
return 0;
}