• 【QT项目——视频播放器——解码】5.1decoder-5.10音频重采样


    5.1 avcodec_find_decoder、AVCodecContext、avcodec_parameters_to_context

    1、确定解码器,通过avcodec_find_decoder获取解码器,返回AVCodec这个结构体

    avcodec_register_all();  // 注册 所有解码器
    AVCodec *avcodec_find_decoder(enum AVCodecID id) // 通过传递id号来获取对应的解码器
    AVCodec *avcodec_find_decoder_by_name(const char * name) // 通过字符串获取解码器————硬解码
    avcodec_find_decoder_by_name("h264_mediacodec"); // 通过名字
    

    2、解码时候还需要解码上下文 AVCodecContext(本次解码的信息)

    AVCodecContext *avcodec_alloc_context3(const AVCodec *codec)   // 申请创建上下文空间
    void avcodec_free_context(AVCodecContext **avctx)  // 空间释放
    int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec,AVDictionary **options);  // 打开解码器
    /libavcodec/options_table.h  参数设置
    int thread_count;   // 多线程解码,充分利用CPU资源
    time_base; // 时间基数
    

    3、参数设置,除了手动设置,还可以通过函数avcodec_parameters_to_context

    avcodec_parameters_to_context,将参数设置直接进行拷贝,从AVStream里面进行拷贝
    

    5.3 AVFrame (在打开解码器上下文之后开始逐帧进行解码,解码前需要先关注AVFrame这个结构体,用于存放解码后的数据)

    AVFrame就是一幅独立的图像!!!

    AVFrame * frame = av_frame_alloc()    // 分配空间(分配和释放与AVPacket相同)
    void av_frame_free(AVFrame **frame)  // 空间释放
    int av_frame_ref(AVFrame *dst, const AVFrame *src);   // 引用计数
    AVFrame *av_frame_clone(const AVFrame *src);  // 复制,重新创建空间,引用空间+1
    void av_frame_unref(AVFrame *frame);  // 直接引用计数减一(空间释放方法二)
    
    uint8_t *data[AV_NUM_DATA_POINTERS];
    int linesize[AV_NUM_DATA_POINTERS];
    int width,height; int nb_samples;  // nb_samples单通道的样本数量,一个样本2字节
    int64_t pts; int64_t pkt_dts;  
    int sample_rate; uint64_t channel_layout; int channels;
    int format;  // AVPixelFormat AVSapleFormat;  // 像素格式 
    

    linesize:存放大小,目的是为了对齐
    宽度一行数据的大小
    通道一行数据的大小
    在这里插入图片描述

    5.4 解码函数

    avcodec_send_packet,将packet写到解码队列中去

    int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);   // 内存开销问题
    

    avcodec_receive_frame,从已解码成功的数据中取出一个frame

    int avcodec_receive_frame(AVCodecContext *avctx,AVFrame *frame);  
    

    ps:send一次,receive不一定是一次

    问题集锦:1、播放最后几帧显示不了,那是缓冲帧的问题。传null,(解决播放时候最后几帧不显示的问题)

    // 发送packet 到解码线程,send传NULL(将pkt换成null)后调用多次receive,会取出所有的缓冲帧
    re = avcodec_send_packet(cc,pkt);    
    

    2、要加头文件

    在这里插入图片描述
    包含了库之后要把对应的头文件也包含进来
    在这里插入图片描述

    3 重采样有报错

    在这里插入图片描述

    5.6 视频像素格式转换和尺寸转换(可以用GPU来做,效率更高)ffmpeg接口简单(唯一优势),但性能开销大

    sws_getContext   像素格式转换上下文,每次都会新创建
    struct SwsContext *sws_getCachedContext(struct SwsContext *context(传格式转换上下文地址), 
    	int srcW(原宽), int srcH(原高), enum AVPixelForamt srcFormat(原像素格式), 
    	int dstW(目标宽), int dstH(目标高), enum AVPixelFormat dstFormat(目标像素格式),
    	int flags, SwsFilter * srcFilter,
    	SwsFilter *dstFilter, const double *param );
    第一个函数sws_getCachedContext只是创建好像素格式转换的上下文,具体的逐帧转换用sws_scale
    
    int sws_scale(struct Swscontext * c, const uint8_t *const srcSlice[],
    	const int srcStride[](linesize,一行大小,宽度), int srcSliceY(0, int srcSliceH(图像高度);
    	uint8_t *const dst[](目标地址), const int dstStride[](输出的一行大小,linesize));
    	
    void sws_freeContext(struct SwsContext *swsContext);  // 释放上下文,传地址就可以
    
    

    int flags, SwsFilter * srcFilter, 这里的flag指的是各种算法,主要是针对尺寸的变化,不涉及像素格式转化,具体如下
    在这里插入图片描述

    5.9 音频重采样

    SwrContext

    音频解码出来不能直接播放,需要重采样(解码出来是32位,声卡不支持,所以需要重采样)
    ffmpeg所有处理都需要上下文,因为是C 语言的一个特点,上下文,不像C++ 有个对象就行了,而C语言需要有个指针贯穿前后,将他们关联起来,所以有这么一个结构体的上下文

    SwrContext *swr_alloc(void);  // 分配和初始化
    SwrContext *swr_alloc_set_opts(
    	struct SwrContext *s,  //重采样上下文 
    	int64_t out_ch_layout,  // 输出的声道标准
    	AVSampleFormat out_sample_fmt,  // 输出的样本格式
    	int out_sample_rate,  // 输出的样本率
    	int64_t in_ch_layout,  
    	AVSampleFormat in_sample_fmt, // 输入的格式
    	int in_sample_rate, // 输入的样本率
    	int log_offset,void *log_ctx); // 两个日志传0就行
    int swr_init(struct SwrContext *s); // 初始化上下文,然后进行格式转换
    void swr_free
  • 相关阅读:
    Web测试如何让IT门外汉更好的入门篇
    大疆无人机
    自学的程序员一点竞争力都没有吗?投了5天简历,一个面试通知都没有怎么办?
    Redis 布隆过滤器的相关命令的使用
    数据结构与算法_part_8_二叉树
    KNN和K-means算法复习
    【C++】list容器的基本操作
    Spring动态修改bean属性的value
    js 代理事件理解及应用场景
    【hive-解决】HiveAccessControlException Permission denied: CREATEFUNCTION
  • 原文地址:https://blog.csdn.net/weixin_42427696/article/details/127031530