ffmpeg linux 摄像头 加视频水印 C语言完整代码
时间: 2023-08-01 07:12:07 浏览: 148
下面是一个完整的C语言代码示例,使用FFmpeg库在Linux上将摄像头流与视频水印合并:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#define WIDTH 640
#define HEIGHT 480
#define FPS 30
#define WATERMARK_FILE "watermark.png"
#define OUTPUT_FILE "output.mp4"
int main(void) {
int fd;
struct v4l2_format fmt;
struct v4l2_requestbuffers req;
struct v4l2_buffer buf;
enum v4l2_buf_type type;
FILE *pipein;
FILE *pipeout;
char command[256];
int frame_size = WIDTH * HEIGHT * 3;
// 打开摄像头设备
fd = open("/dev/video0", O_RDWR);
if (fd == -1) {
perror("Error opening video device");
return -1;
}
// 配置摄像头格式
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = WIDTH;
fmt.fmt.pix.height = HEIGHT;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
fmt.fmt.pix.field = V4L2_FIELD_NONE;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) {
perror("Error setting video format");
close(fd);
return -1;
}
// 请求摄像头缓冲区
memset(&req, 0, sizeof(req));
req.count = 1;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
perror("Error requesting buffers");
close(fd);
return -1;
}
// 映射摄像头缓冲区到用户空间
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = 0;
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {
perror("Error querying buffer");
close(fd);
return -1;
}
void *buffer_start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
if (buffer_start == MAP_FAILED) {
perror("Error mapping buffer");
close(fd);
return -1;
}
// 开始摄像头流捕获
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_STREAMON, &type) == -1) {
perror("Error starting streaming");
munmap(buffer_start, buf.length);
close(fd);
return -1;
}
// 构建FFmpeg命令
sprintf(command, "ffmpeg -f rawvideo -pixel_format rgb24 -video_size %dx%d -framerate %d -i - -i %s -filter_complex overlay=W-w-10:H-h-10 -c:v libx264 %s", WIDTH, HEIGHT, FPS, WATERMARK_FILE, OUTPUT_FILE);
// 打开管道
pipein = popen(command, "w");
if (pipein == NULL) {
perror("Error opening pipe for input");
munmap(buffer_start, buf.length);
close(fd);
return -1;
}
// 循环读取摄像头帧并写入pipein以合并水印
while (1) {
// 从摄像头获取帧
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {
perror("Error queuing buffer");
break;
}
// 开始采集帧
if (ioctl(fd, VIDIOC_DQBUF, &buf) == -1) {
perror("Error dequeuing buffer");
break;
}
// 将帧数据写入pipein以合并水印
if (fwrite(buffer_start, 1, frame_size, pipein) != frame_size) {
perror("Error writing to pipe");
break;
}
// 重新将帧放回摄像头缓冲区队列
if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {
perror("Error requeuing buffer");
break;
}
}
// 停止摄像头流捕获
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_STREAMOFF, &type) == -1) {
perror("Error stopping streaming");
}
// 释放资源
pclose(pipein);
munmap(buffer_start, buf.length);
close(fd);
return 0;
}
```
在上述代码中,我们通过FFmpeg的`overlay`滤镜将摄像头流与指定的视频水印合并,并输出到指定的文件中。你需要将`/dev/video0`替换为你的摄像头设备文件路径,`WATERMARK_FILE`替换为你的水印文件路径,以及将`OUTPUT_FILE`替换为你想要输出的文件路径。请确保你已经安装了FFmpeg库和相关的编译工具链。
相关推荐
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)