linux C 语言 ffmpeg 摄像头 保存 mp4 视频 完整代码
时间: 2024-04-15 13:25:07 浏览: 212
ffmpeg源代码,用C编写
以下是一个简单的示例代码,使用FFmpeg在Linux上捕获摄像头视频并保存为MP4文件:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
#define OUTPUT_FILE "output.mp4"
#define WIDTH 640
#define HEIGHT 480
#define FPS 30
int main() {
int ret;
AVFormatContext *formatContext = NULL;
AVCodecContext *codecContext = NULL;
AVCodec *codec = NULL;
AVStream *stream = NULL;
AVFrame *frame = NULL;
AVPacket packet;
// 初始化FFmpeg
av_register_all();
avformat_network_init();
// 打开摄像头
AVInputFormat *inputFormat = av_find_input_format("video4linux2");
AVDictionary *options = NULL;
av_dict_set(&options, "framerate", "30", 0);
av_dict_set(&options, "video_size", "640x480", 0);
av_dict_set(&options, "input_format", "mjpeg", 0);
if (avformat_open_input(&formatContext, "/dev/video0", inputFormat, &options) < 0) {
fprintf(stderr, "无法打开摄像头\n");
return -1;
}
// 查找解码器
codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
if (!codec) {
fprintf(stderr, "找不到解码器\n");
return -1;
}
// 创建解码器上下文
codecContext = avcodec_alloc_context3(codec);
if (!codecContext) {
fprintf(stderr, "无法创建解码器上下文\n");
return -1;
}
// 打开解码器
if (avcodec_open2(codecContext, codec, NULL) < 0) {
fprintf(stderr, "无法打开解码器\n");
return -1;
}
// 创建输出格式上下文
avformat_alloc_output_context2(&formatContext, NULL, NULL, OUTPUT_FILE);
if (!formatContext) {
fprintf(stderr, "无法创建输出格式上下文\n");
return -1;
}
// 创建视频流
stream = avformat_new_stream(formatContext, NULL);
if (!stream) {
fprintf(stderr, "无法创建视频流\n");
return -1;
}
// 设置视频流参数
codecContext->pix_fmt = AV_PIX_FMT_YUV420P;
codecContext->width = WIDTH;
codecContext->height = HEIGHT;
codecContext->time_base = (AVRational){1, FPS};
codecContext->framerate = (AVRational){FPS, 1};
// 复制解码器上下文到视频流
if (avcodec_parameters_from_context(stream->codecpar, codecContext) < 0) {
fprintf(stderr, "无法复制解码器上下文到视频流\n");
return -1;
}
// 打开输出文件
if (avio_open(&formatContext->pb, OUTPUT_FILE, AVIO_FLAG_WRITE) < 0) {
fprintf(stderr, "无法打开输出文件\n");
return -1;
}
// 写入文件头
if (avformat_write_header(formatContext, NULL) < 0) {
fprintf(stderr, "无法写入文件头\n");
return -1;
}
// 创建帧
frame = av_frame_alloc();
if (!frame) {
fprintf(stderr, "无法创建帧\n");
return -1;
}
frame->format = codecContext->pix_fmt;
frame->width = codecContext->width;
frame->height = codecContext->height;
// 分配帧数据空间
ret = av_image_alloc(frame->data, frame->linesize, codecContext->width, codecContext->height, codecContext->pix_fmt, 32);
if (ret < 0) {
fprintf(stderr, "无法分配帧数据空间\n");
return -1;
}
// 初始化像素格式转换上下文
struct SwsContext *swsContext = sws_getContext(codecContext->width, codecContext->height, codecContext->pix_fmt,
codecContext->width, codecContext->height, AV_PIX_FMT_YUV420P,
0, NULL, NULL, NULL);
// 读取摄像头数据并写入文件
while (1) {
// 读取摄像头数据
if (av_read_frame(formatContext, &packet) < 0)
break;
// 解码帧
if (avcodec_send_packet(codecContext, &packet) < 0) {
fprintf(stderr, "解码错误\n");
break;
}
while (avcodec_receive_frame(codecContext, frame) == 0) {
// 转换像素格式
sws_scale(swsContext, frame->data, frame->linesize, 0, codecContext->height, frame->data, frame->linesize);
// 写入文件
av_write_frame(formatContext, &packet);
}
av_packet_unref(&packet);
}
// 写入文件尾
av_write_trailer(formatContext);
// 清理资源
av_frame_free(&frame);
avcodec_free_context(&codecContext);
avformat_close_input(&formatContext);
avio_close(formatContext->pb);
avformat_free_context(formatContext);
return 0;
}
```
请注意,这只是一个基本的示例代码,可能还需要进行一些错误处理和其他的功能扩展。在编译代码之前,请确保已经安装了FFmpeg开发库,并使用适当的编译选项链接所需的库。
编译命令示例:
```shell
gcc -o capture_video capture_video.c -lavformat -lavcodec -lavutil -lswscale
```
运行生成的可执行文件即可开始捕获摄像头视频并将其保存为MP4文件。
阅读全文