请封装,保留ffmpeg结构体
线程安全处理
获取编码缓冲区数据
请结合 .xencoder.h 中的说明,理解封装。
xencoder.h
#pragma once
#include <mutex>
#include <vector>
struct AVCodecContext;
struct AVPacket;
struct AVFrame;
class XEncode
{
public:
///
// 创建AVFrame,线程安全
// 为什么将这个函数放在第一个呢?因为在createAVCodecContex方法中,要设定 分辨率,pixformat,linesize[0]等必要的参数
// 我们当前的设想是在创建AVFrame的时候,就将这些参数设置进去。
// 然后再逻辑层,得到AVCodecContext后,再将 avframe 的参数 赋值给 AVCodecContext的必要参数
// @param avframewidth 要读文件的分辨率 宽
// @param avframeheight 要读文件的分辨率 高
// @param pixformat 要读取文件的 pixformat
// @param align 要读取文件的 以多少位对齐。必须是4的倍数,或者是0,或者是1,0表示使用ffmepg默认的对齐方式
// 由于 align在windows 默认值是32,该值不能大于64
// 当align的值 =1 的时候,通过 av_frame_get_buffer 得到的linesize[0] = width,linesize[1] = width/2,linesize[0] = width/2,
//根据AVCodecContext 创建一个AVFrame,需要调用者释放av_frame_free
AVFrame* CreateFrame(int avframewidth, int avframeheight, int pixformat, int align);
/// 创建编码器上下文
/// @para codec_id 编码器ID号,对应ffmpeg
/// @return 编码上下文 ,失败返回nullptr
/// 这里将这个函数变成static,原因是不想让 业务层 去维护AVCodeContext的 空间
/// 那么不让 业务层 管理avcodecContex,XEncoder 就要自己管理,因此有了下面的 set_c 函数,
/// 而xencoder内部会维护一个 私有成员变量 avcodeContext_ ,
/// 在需要销毁私有变量 avcodeContext_的时候,调用set_c(nullptr),就可以将 私有成员 avcodeContext_ 清空
/// 请结合 set_c()函数的实现,进一步理解。
static AVCodecContext * Create(int codec_id);
//
/// 设置对象的编码器上下文.
/// 这里将 编码器上下文传递到对象中,目的是让 XEncode维护AVCodecContext的销毁
/// 加锁 线程安全
/// @para avcodecContext 编码器上下文 如果avcodeContext_ 不为nullptr,则先清理资源
void set_c(AVCodecContext* avcodecContext);
/
/// 设置编码参数,线程安全
/// 这里对应在 AVCodecContext 在生成后,调用 avcodec_open2 函数之前,
/// 有可能需要通过 av_opt_set(this->avcodecContext_->priv_data, key, val, 0); 设置avcodecContex的参数。
bool SetOpt(const char* key, const char* val);
/
/// 设置编码参数,线程安全
/// 这里对应在 AVCodecContext 在生成后,调用 avcodec_open2 函数之前,
/// 有可能需要通过 av_opt_set_int(this->avcodecContext_->priv_data, key, val, 0); 设置avcodecContex的参数。
bool SetOpt(const char* key, int val);
//
/// 打开编码器 ,线程安全
/// 对应 ffmepg 中代码为 int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
bool OpenAVCodecContext();
//
/// 编码数据 线程安全 内部实现每次新创建AVPacket