【专题2:qt工程师】 之 【43.使用ffmpeg对视频解码、视频像素和尺寸转换、重采样】

  笔者在嵌入式领域深耕6年,对嵌入式项目构建,BLDC电机控制,产品上位机开发以及产品量产和产品售后维护有多年工作经验。经验分享,从0到1, 让我带你从实际工作的角度走进嵌入式成长之路。

  原创不易欢迎大家关注我的微信公众号嵌入式工程师成长之路扫下面二维码
                     在这里插入图片描述
所有文章总目录:【电子工程师 qt工程师】

原创视频总目录:【电子工程师 qt工程师】

1.解码相关的函数

  大概步骤:通过解码器ID找到对应的解码器,然后再创建一个解码器上下文,再通过解码器上下文打开解码器。
(1)void avcodec_register_all(void):注册所有的解码器。

(2)AVCodec *avcodec_find_decoder(enum AVCodecID id):通过解码器ID找到对应的解码器。

(3)AVCodec *avcodec_find_decoder_by_name(const char *name):通过名字找到对应的解码器,硬解码方式时,一般会使用这种方式。

  AVCodec结构体仅仅是一些解码相关的配置信息,真正解码时,还需要一个解码器上下文AVCodecContext,解码器上下文存放的是本次解码的参数信息。

(4)AVCodecContext *avcodec_alloc_context3(const AVCodec *codec):根据解码创建解码器上下文。老版本的ffmpeg不需要这一步,这一步耦合在解封装的函数内部。但新版本的将解封装和解码进行了分离,所以需要先分配一个上下文空间。

(5)void avcodec_free_context(AVCodecContext **avctx):清理解码器上下文空间。

(6)int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options):打开解码器。第二个参数可以直接传NULL,因为在avcodec_alloc_context3函数中已经指定了。第三个参数指解码过程的参数(所有的参数在:/libavcodec/options_table.h中),一般直接使用默认即可。

(7)int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par):将AVStreame中的codecpar参数复制到解码器上下文结构体来。

2.视频像素和尺寸转换相关函数

  硬解码出来的视频格式和软解码出来的视频格式是不一样的,或者解码出来的是YUV444格式的,需要转换为YUV420的,或者解码出来的是BGR的,需要转换为RGB的,这里都涉及到像素格式的转换。

  直接使用ffmpeg接口来转换,用ffmpeg的好处就是接口简单,但性能开销还是比较大。这部分可以用gpu来做,效率会更高;实际产品中,建议还是用GPU来做。

① struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,int dstW, int dstH, enum AVPixelFormat dstFormat,int flags, SwsFilter *srcFilter,SwsFilter *dstFilter, const double *param):获得一个像素格式转换的上下文。

struct SwsContext *sws_getContext(
	int srcW,//原宽
	int srcH,//原高
	enum AVPixelFormat srcFormat,//原来的格式
	int dstW,//目标宽
	int dstH,//目标高
	enum AVPixelFormat dstFormat,//目标格式
	int flags,//只针对尺寸转换的算法,一般选择SWS_FAST_BILINEAR就可以了
	SwsFilter *srcFilter,//过滤器一般用不到,直接传NULL
	SwsFilter *dstFilter,//过滤器一般用不到,直接传NULL
	const double *param);//这个是和转换算法有关的,譬如使用矩阵算法进行转换,可以通过
	//param传递一个矩阵,我们直接作用默认就可以了,即直接传NULL
#define SWS_FAST_BILINEAR     1	//一般直接使用这种方式就可以了
#define SWS_BILINEAR          2
#define SWS_BICUBIC           4
#define SWS_X                 8
#define SWS_POINT          0x10
#define SWS_AREA           0x20
#define SWS_BICUBLIN       0x40
#define SWS_GAUSS          0x80
#define SWS_SINC          0x100
#define SWS_LANCZOS       0x200
#define SWS_SPLINE        0x400

② int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],const int srcStride[], int srcSliceY, int srcSliceH,uint8_t *const dst[], const int dstStride[]):sws_getContext这个函数仅仅是获得一个转换上下文,而真正的转换则需要使用sws_scale函数。
③ void sws_freeContext(struct SwsContext *swsContext):释放转换上下文空间,这里传递的不是指针的指针,也就是sws_freeContext函数内部没有将swsContext置为NULL,所以需要手动置为NULL。

3.重采样相关函数

  只有解码之后的音频数据才需要重采样,因为直接解码出来的音频数据是32bit的,即不能直接播放的,需要进行转换,一般是转为16bit的。

① struct SwrContext *swr_alloc(void):设置重采样上下文。
② struct SwrContext *swr_alloc_set_opts(struct SwrContext *s,int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate,int log_offset, void *log_ctx):设置重采样上下文参数。

struct SwrContext *swr_alloc_set_opts(
                struct SwrContext *s,
                //输出格式设置
                int64_t out_ch_layout,//声道类型,是立体声,还是其他
                enum AVSampleFormat out_sample_fmt, //输出的样本格式,有float的也有s16的
                int out_sample_rate,//样本率可以不变,输出和输入一样。当然可以改变采样率是播放速度变快
                //但这种变速会使声音失真
                //输入格式设置
                int64_t  in_ch_layout, 
                enum AVSampleFormat  in_sample_fmt, 
                int  in_sample_rate,
                int log_offset, 
                void *log_ctx
            );

③ int swr_init(struct SwrContext *s):设置好参数之后,就进行初始化。
④ void swr_free(struct SwrContext **s):释放空间。
⑤ int swr_convert(struct SwrContext *s, uint8_t **out, int out_count,const uint8_t **in , int in_count):将一帧一帧的音频数据进行重采样。

int swr_convert(struct SwrContext *s, 
                uint8_t **out, 
                int out_count,//单通道的样本数量
                const uint8_t **in, //输入的数据,直接使用avframe->data即可
                int in_count);//单通道的样本数量

你可能感兴趣的:(专题2:qt工程师)