音视频(FFmpeg) - 3 ffprobe 源码
这里是 main 函数流程,删了一些代码
//** 这个开头的注释添加说明 ```C int main(int argc, char *argv) { const AVTextFormatter *f; AVTextFormatContext *tctx; AVTextWriterContext *wctx; char *buf; char *f_name = NULL, *f_args = NULL; int ret, input_ret, i; init_dynload(); setvbuf(stderr, NULL, _IONBF, 0); / win32 runtime needs this */ av_log_set_flags(AV_LOG_SKIP_REPEATED);
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
options = real_options;
parse_loglevel(argc, argv, options);
avformat_network_init(); #if CONFIG_AVDEVICE
avdevice_register_all(); #endif
show_banner(argc, argv, options);
//****** 解析 option
ret = parse_options(NULL, argc, argv, options, opt_input_file);
if (ret < 0) {
ret = (ret == AVERROR_EXIT) ? 0 : ret;
goto end;
}
if (do_show_log)
av_log_set_callback(log_callback);
/* mark things to show, based on -show_entries */
SET_DO_SHOW(CHAPTERS, chapters); //****** 这里一堆 set
if (do_bitexact && (do_show_program_version || do_show_library_versions)) {
av_log(NULL, AV_LOG_ERROR,
"-bitexact and -show_program_version or -show_library_versions "
"options are incompatible\n");
ret = AVERROR(EINVAL);
goto end;
}
if (!output_format)
output_format = av_strdup("default");
if (!output_format) {
ret = AVERROR(ENOMEM);
goto end;
}
f_name = av_strtok(output_format, "=", &buf);
if (!f_name) {
av_log(NULL, AV_LOG_ERROR,
"No name specified for the output format\n");
ret = AVERROR(EINVAL);
goto end;
}
f_args = buf;
f = avtext_get_formatter_by_name(f_name);
if (!f) {
av_log(NULL, AV_LOG_ERROR, "Unknown output format with name '%s'\n", f_name);
ret = AVERROR(EINVAL);
goto end;
}
if (output_filename) {
ret = avtextwriter_create_file(&wctx, output_filename);
} else
ret = avtextwriter_create_stdout(&wctx);
if (ret < 0)
goto end;
AVTextFormatOptions tf_options = {
.show_optional_fields = show_optional_fields,
.show_value_unit = show_value_unit,
.use_value_prefix = use_value_prefix,
.use_byte_value_binary_prefix = use_byte_value_binary_prefix,
.use_value_sexagesimal_format = use_value_sexagesimal_format,
};
if ((ret = avtext_context_open(&tctx, f, wctx, f_args, sections, FF_ARRAY_ELEMS(sections), tf_options, show_data_hash)) >= 0) {
if (f == &avtextformatter_xml)
tctx->string_validation_utf8_flags |= AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES;
avtext_print_section_header(tctx, NULL, SECTION_ID_ROOT);
if (do_show_program_version)
ffprobe_show_program_version(tctx);
if (do_show_library_versions)
ffprobe_show_library_versions(tctx);
if (do_show_pixel_formats)
ffprobe_show_pixel_formats(tctx);
if (!input_filename &&
((do_show_format || do_show_programs || do_show_stream_groups || do_show_streams || do_show_chapters || do_show_packets || do_show_error) ||
(!do_show_program_version && !do_show_library_versions && !do_show_pixel_formats))) {
show_usage();
av_log(NULL, AV_LOG_ERROR, "You have to specify one input file.\n");
av_log(NULL, AV_LOG_ERROR, "Use -h to get full help or, even better, run 'man %s'.\n", program_name);
ret = AVERROR(EINVAL);
} else if (input_filename) {
//****** 解析音视频
ret = probe_file(tctx, input_filename, print_input_filename);
if (ret < 0 && do_show_error)
show_error(tctx, ret);
}
input_ret = ret;
avtext_print_section_footer(tctx);
ret = avtextwriter_context_close(&wctx);
if (ret < 0)
av_log(NULL, AV_LOG_ERROR, "Writing output failed (closing writer): %s\n", av_err2str(ret));
ret = avtext_context_close(&tctx);
if (ret < 0)
av_log(NULL, AV_LOG_ERROR, "Writing output failed (closing formatter): %s\n", av_err2str(ret));
ret = FFMIN(ret, input_ret);
}
end: av_freep(&output_format); av_freep(&output_filename); av_freep(&input_filename); av_freep(&print_input_filename); av_freep(&read_intervals);
1
2
3
4
5
6
7
uninit_opts();
for (i = 0; i < FF_ARRAY_ELEMS(sections); i++)
av_dict_free(&(sections[i].entries_to_show));
avformat_network_deinit();
return ret < 0; } ``` ## 参数解析 parse_options 这个方法做了参数解析
主要是 OptionDef real_options[] 这个变量,预设了 options 和对于处理方法(都是全局变量赋值)
解析音视频信息
probe_file
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
87
88
89
90
static int probe_file(AVTextFormatContext *tfc, const char *filename,
const char *print_filename)
{
InputFile ifile = { 0 };
int ret, i;
int section_id;
do_analyze_frames = do_analyze_frames && do_show_streams;
do_read_frames = do_show_frames || do_count_frames || do_analyze_frames;
do_read_packets = do_show_packets || do_count_packets;
ret = open_input_file(&ifile, filename, print_filename);
if (ret < 0)
goto end;
#define CHECK_END if (ret < 0) goto end
nb_streams = ifile.fmt_ctx->nb_streams;
REALLOCZ_ARRAY_STREAM(nb_streams_frames,0,ifile.fmt_ctx->nb_streams);
REALLOCZ_ARRAY_STREAM(nb_streams_packets,0,ifile.fmt_ctx->nb_streams);
REALLOCZ_ARRAY_STREAM(selected_streams,0,ifile.fmt_ctx->nb_streams);
REALLOCZ_ARRAY_STREAM(streams_with_closed_captions,0,ifile.fmt_ctx->nb_streams);
REALLOCZ_ARRAY_STREAM(streams_with_film_grain,0,ifile.fmt_ctx->nb_streams);
for (i = 0; i < ifile.fmt_ctx->nb_streams; i++) {
if (stream_specifier) {
ret = avformat_match_stream_specifier(ifile.fmt_ctx,
ifile.fmt_ctx->streams[i],
stream_specifier);
CHECK_END;
else
selected_streams[i] = ret;
ret = 0;
} else {
selected_streams[i] = 1;
}
if (!selected_streams[i])
ifile.fmt_ctx->streams[i]->discard = AVDISCARD_ALL;
}
if (do_read_frames || do_read_packets) {
if (do_show_frames && do_show_packets &&
tfc->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT)
section_id = SECTION_ID_PACKETS_AND_FRAMES;
else if (do_show_packets && !do_show_frames)
section_id = SECTION_ID_PACKETS;
else // (!do_show_packets && do_show_frames)
section_id = SECTION_ID_FRAMES;
if (do_show_frames || do_show_packets)
avtext_print_section_header(tfc, NULL, section_id);
ret = read_packets(tfc, &ifile);
if (do_show_frames || do_show_packets)
avtext_print_section_footer(tfc);
CHECK_END;
}
if (do_show_programs) {
ret = show_programs(tfc, &ifile);
CHECK_END;
}
if (do_show_stream_groups) {
ret = show_stream_groups(tfc, &ifile);
CHECK_END;
}
if (do_show_streams) {
ret = show_streams(tfc, &ifile);
CHECK_END;
}
if (do_show_chapters) {
ret = show_chapters(tfc, &ifile);
CHECK_END;
}
if (do_show_format) {
ret = show_format(tfc, &ifile);
CHECK_END;
}
end:
if (ifile.fmt_ctx)
close_input_file(&ifile);
av_freep(&nb_streams_frames);
av_freep(&nb_streams_packets);
av_freep(&selected_streams);
av_freep(&streams_with_closed_captions);
av_freep(&streams_with_film_grain);
return ret;
}
Reference
本文由作者按照 CC BY 4.0 进行授权