使用ffmpeg对摄像头拉流后再推流RTMP
需要在Linux下执行命令,之前想的的用system这个函数来执行推流命令,但是使用这个函数后,程序会一直卡在system推流这个进程中,无法用代码关掉这个进程,后面在网上查找了一下,就用了system函数封装下的execl函数和execlp函数,使用这个方法就需要用fork( )一个子进程
我的需求是需求是建立在socket通信下的,我需要接受服务端的一个指令,然后开启推流,服务端不需要查看实时视频后,再发送一个结束指令,然后我就需要程序关闭这个推流进程,下面的代码可以实现,杀掉这个推流子进程,具体通信代码自己可以完善,推流然后再杀掉这个推流进程并且不影响父进程这个功能可以实现,代码如下(亲测可用):
exec 函数簇功能
提供了一种在一个进程中启动另一个程序的方法。另一个程序可以是一个二进制文件,也可以是一个脚本。 需要读者自己去了解exec函数簇的使用。
- 当当前进程已经不能再为系统和用户做事情时,它就可以调用exec函数簇,去执行新的程序。(当fork的子进程没用的时候调用exec)
- 当某个进程想要执行另一个程序,它就可以在fork一个子进程后,在子进程中直接调用exec函数簇去执行想要执行的程序(执行fork 后马上调用exec)
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
/* code */
int s;
pid_t pid_clild;
pid_t pid;
pid = fork();
if(pid < 0)
{
printf("error in fork");
}else if(pid == 0){
printf("pid_clild=%d\n",getpid());
// system("ffmpeg -re -rtsp_transport tcp -i rtsp://admin:HaiKang123@192.168.203.64 -f flv -vcodec copy -acodec copy -f flv -q 10 rtmp://192.168.203.243:2676/live/test &");
pid_clild = getpid();
// execl("/bin/sh", "sh", "-c", "./Mec_test", (char *)0);
execlp("ffmpeg","-re","-rtsp_transport","tcp",...,NULL); //同上system补全
//推流命令
}else{
sleep(1);
printf("pid3=%d\n",getpid());
printf("pid = %d\n", pid); //测试pid_clild和pid的值是否一样,后面会在主进程中杀掉
/*****笔者自己的进程操作****/
int i = 0;
for(i;i<50;i++)
{
printf("i = %d\n",i);
}
/*****笔者自己的进程操作****/
sleep(10);
//这里设置为延时只是为了测试,具体在socket通信时,可以将此处改为if(recv()== 某某指令),如果是结束推流指令,然后执行下面的kill函数,杀掉推流进程
kill(pid,SIGTERM);
}
return 0;
}
/*
C语言execl()函数:执行文件函数
头文件:
#include <unistd.h>
定义函数:
int execl(const char * path,const char * arg,...);
函数说明:execl()用来执行参数path 字符串所代表的文件路径,接下来的参数代表执行该文件时传递过去的argv(0),argv[1],...,
最后一个参数必须用空指针(NULL)作结束.
返回值:如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno 中.
范例
#include <unistd.h>
main()
{
execl("/bin/ls","ls","-al","/etc/passwd",(char *)0);
}
执行:
// 执行/bin/ls -al /etc/passwd
-rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd
*/
/*
C语言execlp()函数:从PATH 环境变量中查找文件并执行
头文件:
#include <unistd.h>
定义函数:
int execlp(const char * file,...);
函数说明:execlp()会从PATH 环境变量所指的目录中查找符合参数file 的文件名,找到后便执行该文件,
然后将第二个以后的参数当做该文件的argv[0],失败原因存于errno 中.
范例
// 执行ls -al /etc/passwd execlp()会依PATH 变量中的/bin 找到/bin/ls
#include <unistd.h>
main()
{
execlp("ls",(char *)0);
}
执行:
-rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd
*/