如何分别运行 ffmpeg 和您的应用程序并使用管道数据传输图像?
将视频输入 opencv 程序,
ffmpeg -i input.mp4 -vcodec mjpeg -f image2pipe -pix_fmt yuvj420p -r 10 -|program.exe
和录音等
program.exe|ffmpeg -r 10 -vcodec mjpeg -f image2pipe -i - -vcodec h264 output.mp4
program.exe 应该能够从标准输入读取连接的 jpeg 图像并将其写入标准输出,并且上述工作流程将起作用。这是一些从标准输入读取并显示视频的代码。
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
#if defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \
|| defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
# include <io.h>
# include <fcntl.h>
# define SET_BINARY_MODE(handle) setmode(handle, O_BINARY)
#else
# define SET_BINARY_MODE(handle) ((void)0)
#endif
#define BUFSIZE 10240
int main ( int argc, char **argv )
{
SET_BINARY_MODE(fileno(stdin));
std::vector<char> data;
bool skip=true;
bool imgready=false;
bool ff=false;
int readbytes=-1;
while (1)
{
char ca[BUFSIZE];
uchar c;
if (readbytes!=0)
{
readbytes=read(fileno(stdin),ca,BUFSIZE);
for(int i=0;i<readbytes;i++)
{
c=ca[i];
if(ff && c==(uchar)0xd8)
{
skip=false;
data.push_back((uchar)0xff);
}
if(ff && c==0xd9)
{
imgready=true;
data.push_back((uchar)0xd9);
skip=true;
}
ff=c==0xff;
if(!skip)
{
data.push_back(c);
}
if(imgready)
{
if(data.size()!=0)
{
cv::Mat data_mat(data);
cv::Mat frame(imdecode(data_mat,1));
imshow("frame",frame);
waitKey(1);
}else
{
printf("warning");
}
imgready=false;
skip=true;
data.clear();
}
}
}
else
{
throw std::string("zero byte read");
}
}
}
写输出这样的东西应该可以工作。
void saveFramestdout(cv::Mat& frame,int compression)
{
SET_BINARY_MODE(fileno(stdout));
cv::Mat towrite;
if(frame.type()==CV_8UC1)
{
cvtColor(frame,towrite,CV_GRAY2BGR);
}else if(frame.type()==CV_32FC3)
{
double minVal, maxVal;
minMaxLoc(frame, &minVal, &maxVal);
frame.convertTo(towrite, CV_8U, 255.0/(maxVal - minVal), -minVal * 255.0/(maxVal - minVal));
}
else{
towrite=frame;
}
std::vector<uchar> buffer;
std::vector<int> param(2);
param[0]=CV_IMWRITE_JPEG_QUALITY;
param[1]=compression;//default(95) 0-100
imencode(".jpg",towrite,buffer,param);
uchar* a = &buffer[0];
::write(fileno(stdout),a,buffer.size());
}
上面的问题是jpegs的多重编码/解码,可以通过与libjpeg-turbo链接部分解决。或者可以去弄清楚如何直接从 ffmpeg 和 opencv 传递原始数据。就我而言,这是完全可以接受的,因为大部分开销都在编码或视频处理中。