FFmpeg小白学习记录

FFmpeg小白学习记录(一)信息查看

2022-06-03  本文已影响0人  oddly

FFmpeg

libavformat

用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能;音视频的格式解析协议,为 libavcodec 分析码流提供独立的音频或视频码流源

libavcodec

用于各种类型声音/图像编解码;该库是音视频编解码核心,实现了市面上可见的绝大部分解码器的功能,libavcodec 库被其他各大解码器 ffdshow,Mplayer 等所包含或应用

libavfilter

音视频滤镜库,该模块提供了包括音频特效和视频特效的处理,在使用FFmpeg的API进行编解码的过程中,直接使用该模块为音视频数据做特效处理是非常方便和高效的方式

libavutil

核心工具库,该模块是最基础的模块之一,许多其他模块都会依赖该库做一些基本的音视频处理操作

libswresample

该模块可用于音频重采样,可以对数字音频进行音声道、数据格式、采样率等多种进本信息的转换

libswscale

(原始视频格式转换)用于视频场景比例缩放、色彩映射转换;图像颜色空间或格式转换,如 rgb565,rgb888 等与 yuv420 等之间转换。

版本查看

int main(){
    unsigned codecVer = avcodec_version();
    int ver_major,ver_minor,ver_micro;
    ver_major = (codecVer>>16)&0xff;
    ver_minor = (codecVer>>8)&0xff;
    ver_micro = (codecVer)&0xff;
    printf("FFmpeg version is: %s .\navcodec version is: %d=%d.%d.%d.\n",FFMPEG_VERSION,codecVer,ver_major,ver_minor,ver_micro);

    return 0;
}

FFmpeg分为各个模块,每个模块的版本都不一致且与FFmpeg的主版本号没有关联,不过我们可以查看各个模块的版本号,如:avcodec,然后根据模块的版本号去官网查看对应的主版本号

version = [major:minor:micro]

每个各占8位

查看视频流信息

我们可以将多媒体文件看作是一个容器,其中存放着各种流(视频流、音频流、字幕流)

每种流都是由不同的编码器进行编码,比如视频流编码有h.264、MPEG4、H.265等,这些信息我们都可以通过FFmpegav_dump_format函数打印

示例代码

extern "C"{
#include"libavformat/avformat.h"
}

int main() {
    AVFormatContext* fmt_ctx = avformat_alloc_context();//创建对象并初始化
    int ret = 0;
    //文件地址
    const char* filePath = ".\\target.mp4";

    do {
        //打开文件
        if ((ret = avformat_open_input(&fmt_ctx, filePath, NULL, NULL)) < 0)
            break;//Cannot open video file

        //查找流信息(音频流和视频流)
        if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {
            printf("Cannot find stream information\n");
            break;
        }

        av_dump_format(fmt_ctx, 0, filePath, 0);//输出视频信息
    } while (0);

    avformat_close_input(&fmt_ctx);//关闭文件

    return 0;
}

输出结果:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'target.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.48.100
  Duration: 00:03:10.36, start: 0.000000, bitrate: 773 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720, 442 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 325 kb/s (default)
    Metadata:
      handler_name    : SoundHandler

文件使用完成之后要及时关闭。可以使用goto语句进行错误处理,但是在开发C++时不推荐使用goto语句

可以使用do{}while(0),实现类似效果,此语句只会执行{}中的代码一次,将释放资源的代码放在do-while代码段之外,出现异常就进行break即可

代码解析

结构体

avformat_alloc_context用于创建AVFormatContext结构体的方法,AVFormatContext是结构上下文,内部存放着描述媒体文件或媒体流的构成和基本信息,贯穿ffmpeg使用整个流程

// 截取出部分较为重要的数据
typedef struct AVFormatContext {
    struct AVInputFormat *iformat;
    struct AVOutputFormat *oformat;//输入或者输出流的格式(只能存在一个)
    
    AVIOContext *pb;//管理输入输出数据
        
    unsigned int nb_streams;//音视频流的个数
    AVStream **streams;//音视频流       
    
    char *url;//文件名
    int64_t duration;//时长
    int bit_rate;//比特率(单位bite/s)
    
    AVDictionary *metadata;//元数据(查看元数据:ffprobe filename)
    ...
}

其中存放着AVStream结构体,存储音频流或视频流

// 截取出部分较为重要的数据
typedef struct AVStream {
    int index;//音频流或视频流的索引
    AVRational time_base;//计算pts或dts是使用的时间戳基本单位(显示时间:pt = av_q2d(video_stream->time_base) * frame->pts)
    int64_t duration;//该视频||音频流长度
    AVRational avg_frame_rate;//平均帧率(对于视频来说,frame_rate=avg_frame_rate.num / avg_frame_rate.den)
    AVCodecParameters *codecpar;//解码器参数
    ...
} AVStream;
函数

avformat_open_input函数用于打开一个多媒体文件,可以是本地文件也可以是网络文件

int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);

参数:

return:

返回0则代表成功,失败则会返回一个负数

与之对应的就是avformat_close_input,该函数会去释放AVFormatContext所持有的资源


avformat_find_stream_info函数用于查找流信息(音频流和视频流)

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);

参数:

return:

返回数值 ≥ 0时代表成功,其余则代表失败


av_dump_format函数会打印多媒体文件中的Meta信息,如:时长、比特率、编解码器等

void av_dump_format(AVFormatContext *ic,
                    int index,
                    const char *url,
                    int is_output);

参数:

注意:有的流需要经过avformat_find_stream_info才能打印出信息,有些流则不需要

上一篇 下一篇

猜你喜欢

热点阅读