在 C++ 中从 execve 调用时,ffmpeg 产生错误的输出
ffmpeg produces bad output when called from execve in c++
我正在编写一个涉及从 C++ 程序调用 ffmpeg 的 C++ 程序。几天前,我使用 std::system
让它工作
std::system("ffmpeg -threads auto -y -r 1.74659 -i /mnt/ev_ramdsk/1/%05d-capture.jpg -px_fmt yuv420p -preset ultrafast -r 10 /mnt/ev_ramdsk/1/video.mp4");
但这只工作了一次,它产生了 8MB 左右的 .mp4 视频,无法在任何地方播放。所以由于上一个问题中的建议,我转到了 execve。
这是我的代码
child_pid = fork();
if(child_pid < 0){
syslog(LOG_ERR, "ERROR: ffmpeg forking failed");
return false;
}
else if(child_pid > 0){
syslog(LOG_DEBUG, "DEBUG: forking succeeded, pid: %d", child_pid);
}
else if(child_pid == 0){
char *newargv[16];
for(int i=0; i < 15; i++) newargv[i] = (char *)malloc(sizeof(char) * 60); //allocate the array in memory
strcpy(newargv[0], "/usr/bin/ffmpeg");
strcpy(newargv[1], "-threads");
strcpy(newargv[2], "auto");
strcpy(newargv[3], "-y");
strcpy(newargv[4], "-framerate");
tempSS << fps;
strcpy(newargv[5], tempSS.str().c_str());
tempSS.str(std::string());
strcpy(newargv[6], "-i");
strcpy(newargv[7], std::string(conf->dir_ram + dest + "%05d-capture.jpg").c_str());
strcpy(newargv[8], "-pix_fmt");
strcpy(newargv[9], "yuv420p");
strcpy(newargv[10], "-preset");
strcpy(newargv[11], "ultrafast");
strcpy(newargv[12], "-r");
strcpy(newargv[13], "25");
strcpy(newargv[14], std::string(conf->dir_ram + dest + "video.mp4").c_str());
newargv[15] = NULL;
for(int i=0; i < 15; i++){
tempSS << "newargv[" << i << "] = \"" << newargv[i] << "\", ";
}
syslog(LOG_DEBUG, "DEBUG:newargv: %s", tempSS.str().c_str());
tempSS.str(std::string());
char *newenviron[] = { NULL };
if(execve(newargv[0], newargv, newenviron) == -1){
syslog(LOG_ERR, "ERROR: execve returned -1");
exit(EXIT_SUCCESS);
}
}
wpid = wait(&status);
syslog(LOG_DEBUG, "DEBUG: ffmpeg child terminated, pid: %d, status: %d", wpid, status);
系统日志的输出是:
May 28 00:25:03 SERVER dt_ev_maker[10471]: DEBUG: forking succeeded, pid: 10658
May 28 00:25:03 SERVER dt_ev_maker[10658]: DEBUG:newargv:
newargv[0] = "/usr/bin/ffmpeg",
newargv[1] = "-threads",
newargv[2] = "auto",
newargv[3] = "-y",
newargv[4] = "-framerate",
newargv[5] = "1.45097",
newargv[6] = "-i",
newargv[7] = "/mnt/ev_ramdsk/1/%05d-capture.jpg",
newargv[8] = "-pix_fmt",
newargv[9] = "yuv420p",
newargv[10] = "-preset",
newargv[11] = "ultrafast",
newargv[12] = "-r",
newargv[13] = "25",
newargv[14] = "/mnt/ev_ramdsk/1/video.mp4",
May 28 00:25:03 SERVER dt_ev_maker[10471]: DEBUG: ffmpeg child terminated, pid: 10658, status: 256
在这种情况下,视频的大小约为 90B,并且也已损坏。
注意:如果我 运行 从命令行执行相同的命令,视频可以正常播放。
我做错了什么?
提前致谢!
编辑
感谢 ouroborus(上面提交的更改),我可以制作 18MB 的视频,但我无法播放它们。
似乎 execve()
需要它的数组有最后一个元素 NULL
。将 newargv
数组扩展一个并将最后一个元素设置为 NULL
,然后再将其传递到 execve()
.
所以,最终有效的代码是:
pid_t wpid, child_pid;
int status;
int fd = open(std::string(conf->dir_ram + "ffmpeg.txt").c_str(), O_CREAT | O_WRONLY, 0777);
if(fd < 0){
syslog(LOG_ERR, "ERROR: open returned -1");
return false;
}
child_pid = fork();
if(child_pid < 0){
syslog(LOG_ERR, "ERROR: ffmpeg forking failed");
return false;
}
else if(child_pid > 0){
syslog(LOG_DEBUG, "DEBUG: forking succeeded, pid: %d", child_pid);
}
else if(child_pid == 0){
if( close(1) < 0 ){
syslog(LOG_ERR, "ERROR: close returned -1");
return false;
}
if( dup2(fd, 1) < 0 ){
syslog(LOG_ERR, "ERROR: dup2 returned -1");
return false;
}
char *newargv[18];
for(int i=0; i < 17; i++) newargv[i] = (char *)malloc(sizeof(char) * 60); //allocate the array in memory
strcpy(newargv[0], conf->ffmpeg_path.c_str());
strcpy(newargv[1], "-threads");
strcpy(newargv[2], "auto");
strcpy(newargv[3], "-y");
strcpy(newargv[4], "-r");
tempSS << fps;
strcpy(newargv[5], tempSS.str().c_str());
tempSS.str(std::string());
strcpy(newargv[6], "-i");
strcpy(newargv[7], std::string(conf->dir_ram + dest + "%05d-capture.jpg").c_str());
strcpy(newargv[8], "-pix_fmt");
strcpy(newargv[9], "yuv420p");
strcpy(newargv[10], "-c:v");
strcpy(newargv[11], "libx264");
strcpy(newargv[12], "-preset");
strcpy(newargv[13], "ultrafast");
strcpy(newargv[14], "-r");
strcpy(newargv[15], conf->ffmpeg_rate.c_str());
strcpy(newargv[16], std::string(conf->dir_ram + dest + "video.mp4").c_str());
newargv[17] = NULL;
char *newenviron[] = { NULL };
if(execve(newargv[0], newargv, newenviron) == -1){
syslog(LOG_ERR, "ERROR: execve returned -1");
exit(EXIT_SUCCESS);
}
}
wpid = wait(&status);
如果我评论整个 open() 和 dup2() 部分,视频就会损坏。我不知道为什么,但没有它是行不通的。
我正在编写一个涉及从 C++ 程序调用 ffmpeg 的 C++ 程序。几天前,我使用 std::system
让它工作std::system("ffmpeg -threads auto -y -r 1.74659 -i /mnt/ev_ramdsk/1/%05d-capture.jpg -px_fmt yuv420p -preset ultrafast -r 10 /mnt/ev_ramdsk/1/video.mp4");
但这只工作了一次,它产生了 8MB 左右的 .mp4 视频,无法在任何地方播放。所以由于上一个问题中的建议,我转到了 execve。
这是我的代码
child_pid = fork();
if(child_pid < 0){
syslog(LOG_ERR, "ERROR: ffmpeg forking failed");
return false;
}
else if(child_pid > 0){
syslog(LOG_DEBUG, "DEBUG: forking succeeded, pid: %d", child_pid);
}
else if(child_pid == 0){
char *newargv[16];
for(int i=0; i < 15; i++) newargv[i] = (char *)malloc(sizeof(char) * 60); //allocate the array in memory
strcpy(newargv[0], "/usr/bin/ffmpeg");
strcpy(newargv[1], "-threads");
strcpy(newargv[2], "auto");
strcpy(newargv[3], "-y");
strcpy(newargv[4], "-framerate");
tempSS << fps;
strcpy(newargv[5], tempSS.str().c_str());
tempSS.str(std::string());
strcpy(newargv[6], "-i");
strcpy(newargv[7], std::string(conf->dir_ram + dest + "%05d-capture.jpg").c_str());
strcpy(newargv[8], "-pix_fmt");
strcpy(newargv[9], "yuv420p");
strcpy(newargv[10], "-preset");
strcpy(newargv[11], "ultrafast");
strcpy(newargv[12], "-r");
strcpy(newargv[13], "25");
strcpy(newargv[14], std::string(conf->dir_ram + dest + "video.mp4").c_str());
newargv[15] = NULL;
for(int i=0; i < 15; i++){
tempSS << "newargv[" << i << "] = \"" << newargv[i] << "\", ";
}
syslog(LOG_DEBUG, "DEBUG:newargv: %s", tempSS.str().c_str());
tempSS.str(std::string());
char *newenviron[] = { NULL };
if(execve(newargv[0], newargv, newenviron) == -1){
syslog(LOG_ERR, "ERROR: execve returned -1");
exit(EXIT_SUCCESS);
}
}
wpid = wait(&status);
syslog(LOG_DEBUG, "DEBUG: ffmpeg child terminated, pid: %d, status: %d", wpid, status);
系统日志的输出是:
May 28 00:25:03 SERVER dt_ev_maker[10471]: DEBUG: forking succeeded, pid: 10658
May 28 00:25:03 SERVER dt_ev_maker[10658]: DEBUG:newargv:
newargv[0] = "/usr/bin/ffmpeg",
newargv[1] = "-threads",
newargv[2] = "auto",
newargv[3] = "-y",
newargv[4] = "-framerate",
newargv[5] = "1.45097",
newargv[6] = "-i",
newargv[7] = "/mnt/ev_ramdsk/1/%05d-capture.jpg",
newargv[8] = "-pix_fmt",
newargv[9] = "yuv420p",
newargv[10] = "-preset",
newargv[11] = "ultrafast",
newargv[12] = "-r",
newargv[13] = "25",
newargv[14] = "/mnt/ev_ramdsk/1/video.mp4",
May 28 00:25:03 SERVER dt_ev_maker[10471]: DEBUG: ffmpeg child terminated, pid: 10658, status: 256
在这种情况下,视频的大小约为 90B,并且也已损坏。
注意:如果我 运行 从命令行执行相同的命令,视频可以正常播放。
我做错了什么?
提前致谢!
编辑
感谢 ouroborus(上面提交的更改),我可以制作 18MB 的视频,但我无法播放它们。
似乎 execve()
需要它的数组有最后一个元素 NULL
。将 newargv
数组扩展一个并将最后一个元素设置为 NULL
,然后再将其传递到 execve()
.
所以,最终有效的代码是:
pid_t wpid, child_pid;
int status;
int fd = open(std::string(conf->dir_ram + "ffmpeg.txt").c_str(), O_CREAT | O_WRONLY, 0777);
if(fd < 0){
syslog(LOG_ERR, "ERROR: open returned -1");
return false;
}
child_pid = fork();
if(child_pid < 0){
syslog(LOG_ERR, "ERROR: ffmpeg forking failed");
return false;
}
else if(child_pid > 0){
syslog(LOG_DEBUG, "DEBUG: forking succeeded, pid: %d", child_pid);
}
else if(child_pid == 0){
if( close(1) < 0 ){
syslog(LOG_ERR, "ERROR: close returned -1");
return false;
}
if( dup2(fd, 1) < 0 ){
syslog(LOG_ERR, "ERROR: dup2 returned -1");
return false;
}
char *newargv[18];
for(int i=0; i < 17; i++) newargv[i] = (char *)malloc(sizeof(char) * 60); //allocate the array in memory
strcpy(newargv[0], conf->ffmpeg_path.c_str());
strcpy(newargv[1], "-threads");
strcpy(newargv[2], "auto");
strcpy(newargv[3], "-y");
strcpy(newargv[4], "-r");
tempSS << fps;
strcpy(newargv[5], tempSS.str().c_str());
tempSS.str(std::string());
strcpy(newargv[6], "-i");
strcpy(newargv[7], std::string(conf->dir_ram + dest + "%05d-capture.jpg").c_str());
strcpy(newargv[8], "-pix_fmt");
strcpy(newargv[9], "yuv420p");
strcpy(newargv[10], "-c:v");
strcpy(newargv[11], "libx264");
strcpy(newargv[12], "-preset");
strcpy(newargv[13], "ultrafast");
strcpy(newargv[14], "-r");
strcpy(newargv[15], conf->ffmpeg_rate.c_str());
strcpy(newargv[16], std::string(conf->dir_ram + dest + "video.mp4").c_str());
newargv[17] = NULL;
char *newenviron[] = { NULL };
if(execve(newargv[0], newargv, newenviron) == -1){
syslog(LOG_ERR, "ERROR: execve returned -1");
exit(EXIT_SUCCESS);
}
}
wpid = wait(&status);
如果我评论整个 open() 和 dup2() 部分,视频就会损坏。我不知道为什么,但没有它是行不通的。