1.C语言中使用FFmpeg捕获视频文件流的基本流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <libavformat/avformat.h>  
#include <libavcodec/avcodec.h>

int main() {
AVFormatContext* fmt_ctx = NULL;
AVCodecParameters* codec_params = NULL;
const AVCodec* codec = NULL;
AVCodecContext* codec_ctx = NULL;
int video_stream_index = -1;

// 注册所有组件(新版本可能不需要)
avformat_network_init();

// 打开输入文件
if (avformat_open_input(&fmt_ctx, "copy111.mp4", NULL, NULL) != 0) {
fprintf(stderr, "Could not open file\n");
return -1;
}

// 获取流信息
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
fprintf(stderr, "Could not find stream information\n");
return -1;
}

// 查找视频流
for (int i = 0; i < fmt_ctx->nb_streams; i++) {
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
video_stream_index = i;
break;
}
}

if (video_stream_index == -1) {
fprintf(stderr, "Could not find video stream\n");
return -1;
}

// 获取编解码器参数
codec_params = fmt_ctx->streams[video_stream_index]->codecpar;

// 查找解码器
codec = avcodec_find_decoder(codec_params->codec_id);
if (!codec) {
fprintf(stderr, "Unsupported codec\n");
return -1;
}

// 创建解码器上下文
codec_ctx = avcodec_alloc_context3(codec);
avcodec_parameters_to_context(codec_ctx, codec_params);

// 打开解码器
if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
fprintf(stderr, "Could not open codec\n");
return -1;
}

AVPacket* pkt = av_packet_alloc();
AVFrame* frame = av_frame_alloc();
int frame_number = 0; // Add frame_number variable

// 读取数据包
while (av_read_frame(fmt_ctx, pkt) >= 0) {
if (pkt->stream_index == video_stream_index) {
// 发送数据包到解码器
if (avcodec_send_packet(codec_ctx, pkt) == 0) {
// 接收解码后的帧
while (avcodec_receive_frame(codec_ctx, frame) == 0) {
// 处理视频帧(这里只是打印信息)
printf("Frame %d (pts=%ld) [%dx%d]\n", frame_number++, frame->pts, frame->width, frame->height);
}
}
}
av_packet_unref(pkt);
}

// 清理资源
av_frame_free(&frame);
av_packet_free(&pkt);
avcodec_free_context(&codec_ctx);
avformat_close_input(&fmt_ctx);

return 0;
}