服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言结合ffmpeg打印音视频信息

C语言结合ffmpeg打印音视频信息

2022-07-29 10:43TrueDei C/C++

这篇文章主要介绍了如何通过C语言或者C++编程语言结合ffmpeg拿到一些音视频的关键信息,例如:帧率等。感兴趣的小伙伴可以跟随小编一起学习一下

一、通过此文可以得到什么

通过此练习:

1、知道了如何计算一个音频和视频的播放时间;

2、知道了音视频解码的思路的大体流程,之后无非就是在这个流程上进行扩充细节;

3、知道了如何通过C语言或者C++编程语言结合ffmpeg拿到一些音视频的关键信息,例如:帧率等;

二、实现思路

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
zhenghui@zh-pc:/data/project/VSCProject/ffmpegStudy$ make
make all
make[1]: 进入目录“/data/project/VSCProject/ffmpegStudy/src
Compiling main.cpp to main.o ..
cp hello /data/project/VSCProject/ffmpegStudy/src/../
# make 【hello】 finish !!!  
make[1]: 离开目录“/data/project/VSCProject/ffmpegStudy/src
zhenghui@zh-pc:/data/project/VSCProject/ffmpegStudy$
zhenghui@zh-pc:/data/project/VSCProject/ffmpegStudy$ ./hello
Hello World !
decode video fileName=/home/zhenghui/视频/1080P.mp4
[NULL @ 0x5654cc332d80] Opening '/home/zhenghui/视频/1080P.mp4' for reading
[file @ 0x5654cc333380] Setting default whitelist 'file,crypto,data'
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Format mov,mp4,m4a,3gp,3g2,mj2 probed with size=2048 and score=100
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] ISO: File Type Major Brand: isom
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Unknown dref type 0x206c7275 size 12
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Processing st: 0, edit list 0 - media time: 1072, duration: 3621888
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Offset DTS by 1072 to make first pts zero.
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Setting codecpar->delay to 2 for stream st: 0
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Unknown dref type 0x206c7275 size 12
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Processing st: 1, edit list 0 - media time: 0, duration: 9990149
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] rfps: 29.916667 0.006250
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] rfps: 30.000000 0.000066
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] rfps: 60.000000 0.000265
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] rfps: 120.000000 0.001061
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] rfps: 240.000000 0.004244
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] rfps: 29.970030 0.000868
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] rfps: 59.940060 0.003473
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Before avformat_find_stream_info() pos: 87425182 bytes read:315205 seeks:1 nb_streams:2
[h264 @ 0x5654cc3340c0] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x5654cc3340c0] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x5654cc3340c0] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x5654cc3340c0] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x5654cc3340c0] nal_unit_type: 6(SEI), nal_ref_idc: 0
[h264 @ 0x5654cc3340c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x5654cc3340c0] Format yuv420p chosen by get_format().
[h264 @ 0x5654cc3340c0] Reinit context to 1920x1088, pix_fmt: yuv420p
[h264 @ 0x5654cc3340c0] no picture
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] All info found
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] After avformat_find_stream_info() pos: 53231 bytes read:393067 seeks:2 frames:4
video_index=0
audio_index=1
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/zhenghui/视频/1080P.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.29.100
    description     : Packed by Bilibili XCoder v2.0.2
  Duration: 00:03:46.53, start: 0.000000, bitrate: 3087 kb/s
  Stream #0:0[0x1](und), 3, 1/16000: Video: h264 (High), 1 reference frame (avc1 / 0x31637661), yuv420p(progressive, left), 1920x1080 (1920x1088) [SAR 1:1 DAR 16:9], 0/1, 2951 kb/s, 30 fps, 30 tbr, 16k tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
  Stream #0:1[0x2](und), 1, 1/44100: Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
media name =/home/zhenghui/视频/1080P.mp4
stream number: 2
media average ratio: 3015 kbps
media total time: 0:3:46
######## Video info: ########
stream index : 0
fps:29.999914 fps
video codec : H264
video_time : 00:03:46
######## Audio info: ########
stream index : 1
stream sample_rate : 44100 Hz
stream format : AV_SAMPLE_FMT_FLTP
channels number:2
audio codec:AAC
audio_time : 00:03:46
[AVIOContext @ 0x5654cc33b7c0] Statistics: 393067 bytes read, 2 seeks
zhenghui@zh-pc:/data/project/VSCProject/ffmpegStudy$

四、实现源代码

视频教程

?
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include <iostream>
#include <stdio.h>
 
 
#ifdef __cplusplus //表示是一个c++程序
extern "C"{
#endif
 
#include <libavdevice/avdevice.h>
#include <libavutil/frame.h>
#include <libavutil/imgutils.h>
#include <libavutil/log.h>
#include <libswscale/swscale.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
 
#ifdef __cplusplus
}
#endif
 
 
//g++ -I ../include/ hello_world.cpp -o hello_world -L../lib/ -lavcodec -lavdevice -lavfilter -lavformat -lavutil
void decode()
{
    char *fileName = "/home/zhenghui/视频/1080P.mp4";
 
    printf("decode video fileName=%s \n",fileName);
 
    int ret = 0;
    // 1、分配解复用器上下文
    AVFormatContext *ctx = NULL;
    ctx = avformat_alloc_context();
 
    // 2、根据url打开本地文件或网络流
    ret = avformat_open_input(&ctx,fileName,NULL,NULL);
 
    if(ret < 0)
    {
        printf("打开%s失败 ! \n",fileName);
        return;
    }
 
    // 3、读取媒体的部分数据包,获取码流信息
    ret = avformat_find_stream_info(ctx,NULL);
    if(ret < 0){
        printf("获取码流信息失败 !\n");
        return;
    }
 
    // 3、获取音频流和视频流的索引
    int video_index = -1;
    int audio_index = -1;
 
    video_index = av_find_best_stream(ctx,AVMEDIA_TYPE_VIDEO,-1,-1,NULL,0);
    printf("video_index=%d \n",video_index);
 
    audio_index = av_find_best_stream(ctx,AVMEDIA_TYPE_AUDIO,-1,-1,NULL,0);
    printf("audio_index=%d \n",audio_index);
 
    // 打印流信息
    av_dump_format(ctx,0,fileName,0);
 
    //打印媒体文件url
    printf("media name =%s \n",ctx->url);
    //打印流数量
    printf("stream number: %d \n",ctx->nb_streams);
    //打印码率
    printf("media average ratio: %lld kbps\n",(int64_t)(ctx->bit_rate/1024));
 
    //打印时长
    int total_seconds,hour,minute,second;
    //ctx->duration的单位是微妙,先转换成秒,再进行转换成其他的时间单位就比较简单了
    total_seconds = (ctx->duration) / AV_TIME_BASE;
    hour = total_seconds / 3600;
    minute = (total_seconds % 3600) /60;
    second = (total_seconds % 60);
 
    // 文件总时长
    printf("media total time: %d:%d:%d \n",hour,minute,second);
 
    //老版本查找流索引
    for(int i = 0;i < ctx->nb_streams;i++){
        AVStream  *av_stream = ctx->streams[i];
 
        //判断流是什么类型
        //视频流
        if( AVMEDIA_TYPE_VIDEO == av_stream->codecpar->codec_type)
        {
            printf("######## Video info: ######## \n");
            // 流索引
            printf("stream index : %d \n",av_stream->index);
            //帧率
            printf("fps:%lf fps\n",av_q2d(av_stream->avg_frame_rate));
 
            if(AV_CODEC_ID_MPEG4 == av_stream->codecpar->codec_id)
            {
                printf("video codec : MPEG4 \n");
            }
            else if(AV_CODEC_ID_H264 == av_stream->codecpar->codec_id)
            {
                printf("video codec : H264 \n");
            }else
            {
                printf("video codec other value=%d \n", av_stream->codecpar->codec_id);
            }
 
            //获取视频总时长
            if(AV_NOPTS_VALUE != av_stream->duration)
            {
                int video_time =av_stream->duration * av_q2d(av_stream->time_base);
                printf("video_time : %02d:%02d:%02d\n" ,
                (video_time / 3600),
                (video_time % 3600) / 60,
                (video_time % 60)
                );
            }
            else{
                printf("audio duration unknown ! \n");
            }
        }
        //音频流
        else if(AVMEDIA_TYPE_AUDIO == av_stream->codecpar->codec_type)
        {
            printf("######## Audio info: ######## \n");
            // 流索引
            printf("stream index : %d \n",av_stream->index);
 
            // 音频编解码器的采样率 单位Hz
            printf("stream sample_rate : %d Hz \n",av_stream->codecpar->sample_rate);
 
            //音频采样格式
            if(AV_SAMPLE_FMT_FLTP == av_stream->codecpar->format)
            {
                printf("stream format : AV_SAMPLE_FMT_FLTP \n");
            }
            else  if(AV_SAMPLE_FMT_S16P == av_stream->codecpar->format)
            {
                printf("stream format : AV_SAMPLE_FMT_S16P \n");
            }else{
                printf("stream format : other; value=%d \n",av_stream->codecpar->format);
            }
 
            // 音频信道数目
            printf("channels number:%d \n",av_stream->codecpar->channels);
 
            //音频压缩编码格式
            if(AV_CODEC_ID_AAC == av_stream->codecpar->codec_id)
            {
                printf("audio codec:AAC \n");
            }else if(AV_CODEC_ID_MP3 == av_stream->codecpar->codec_id)
            {
                printf("audio codec:MP3 \n");
            }else{
                printf("audio codec : other; value=%d \n",av_stream->codecpar->codec_id);
            }
 
            //获取视频总时长
            if(AV_NOPTS_VALUE != av_stream->duration)
            {
                int audio_time =av_stream->duration * av_q2d(av_stream->time_base);
                printf("audio_time : %02d:%02d:%02d\n" ,
                (audio_time / 3600),
                (audio_time % 3600) / 60,
                (audio_time % 60)
                );
            }
            else{
                printf("audio duration unknown ! \n");
            }
 
            audio_index = i;
        }
 
    }
 
    if(ctx)
        avformat_close_input(&ctx);
}
 
int main() {
    // 设置控制台输出级别
    av_log_set_level(AV_LOG_DEBUG);
    // // 打印输出字符串Hello World !
    av_log(NULL, AV_LOG_DEBUG, "%s", "Hello World !\n");
 
    decode();
    return 0;
}
<font face="Arial, Verdana, sans-serif"><span style="white-space: normal;"> </span></font>

到此这篇关于C语言结合ffmpeg打印音视频信息的文章就介绍到这了,更多相关C语言打印音视频信息内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/qq_17623363/article/details/122151819

延伸 · 阅读

精彩推荐
  • C/C++C语言数据结构 link 链表反转的实现

    C语言数据结构 link 链表反转的实现

    这篇文章主要介绍了C语言数据结构 link 链表反转的实现的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下...

    阳光岛主9112021-06-03
  • C/C++C语言每日练习之字符串反转

    C语言每日练习之字符串反转

    这篇文章主要介绍了C语言字符串反转,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来...

    小辉_Super5342022-02-21
  • C/C++C语言函数指针的老生常谈

    C语言函数指针的老生常谈

    这篇文章主要为大家介绍了C语言函数指针,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助...

    青锋杨5712022-03-02
  • C/C++C++中int类型按字节打印输出的方法

    C++中int类型按字节打印输出的方法

    这篇文章主要给大家介绍了关于C++中int类型按字节打印输出的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用C++具有一定的参考学习价...

    shell_nut7542021-07-28
  • C/C++基于欧几里德算法的使用

    基于欧几里德算法的使用

    本篇文章介绍了,基于欧几里德算法的使用。需要的朋友参考下...

    C语言教程网5192020-11-22
  • C/C++C++ 获取URL内容的实例

    C++ 获取URL内容的实例

    这篇文章主要介绍了C++ 获取URL内容的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    iYAO11232021-10-11
  • C/C++C++ 自定义控件的移植问题

    C++ 自定义控件的移植问题

    这篇文章主要介绍了C++ 自定义控件的移植问题,十分的简单实用,有需要的小伙伴可以参考下。...

    C++教程网8732021-02-28
  • C/C++C++ Log日志类轻量级支持格式化输出变量实现代码

    C++ Log日志类轻量级支持格式化输出变量实现代码

    这篇文章主要介绍了C++ Log日志类轻量级支持格式化输出变量实现代码,需要的朋友可以参考下...

    C++教程网11292021-07-26