# 2.2 数据结构定义
~~~
// 库包含编解码器能力定义
#define MEDIACODEC_CAPABILITY_AUDIOENCODEC 0x00000001 ///< 音频编码器
#define MEDIACODEC_CAPABILITY_AUDIODECODEC 0x00000002 ///< 音频解码器
#define MEDIACODEC_CAPABILITY_VIDEOENCODEC 0x00000004 ///< 视频编码器
#define MEDIACODEC_CAPABILITY_VIDEODECODEC 0x00000008 ///< 视频解码器
#define MEDIACODEC_CAPABILITY_YUV420SPINPUT 0x00000100 ///< 视频编码器支持YUV420SP 数据输入
#define MEDIACODEC_CAPABILITY_YUV420SPOUTPUT 0x00000200 ///< 视频解码器输出数据为 YUV420SP
#define MEDIACODEC_CAPABILITY_DIRECTRENDER 0x00000400 ///< 支持直接视频显示,硬件渲染
// 功能标志定义
#define MEDIACODEC_FLAGS_KEYFRAME 0x00000001 ///< 关键帧标志
#define MEDIACODEC_FLAGS_WANTSPSPPS 0x00000002 ///< 上层应用处理 SPS、PPS 标志, 视频编码使用
#define MEDIACODEC_FLAGS_USEARMV6 0x00000100 ///< 强制使用 ARMv6 指令集
#define MEDIACODEC_FLAGS_NEEDREINIT 0x00000200 ///< 需要重新初始化 Codec
#define MEDIACODEC_MAXCODECNAME 50
// 编解码器 ID 定义
enum MEDIA_CODEC_ID { MEDIA_CODEC_ID_NONE = 0,
/* video codecs */ MEDIA_CODEC_ID_H264, MEDIA_CODEC_ID_MJPEG,
/* audio codecs */ MEDIA_CODEC_ID_AMR_NB = 10, MEDIA_CODEC_ID_AMR_WB, MEDIA_CODEC_ID_MP3, MEDIA_CODEC_ID_AAC, MEDIA_CODEC_ID_MP2, MEDIA_CODEC_ID_CELT, MEDIA_CODEC_ID_SPEEX,
/* user define codecs*/
MEDIA_CODEC_ID_USERSTART = 100, ///< 用户自定义编解码器起始 ID
};
// 音视频数据包结构
typedef struct MediaPacket { CHAR *lpData; DWORD dwSize; DWORD dwFlags; DWORD dwTimeStamp;
}MediaPacket,*LPMediaPacket;
// 编解码器上下文句柄结构
struct MediaCodecContext {
DWORD cbSize; ///< 结构体大小
DWORD dwCodecId;///< 编解码器 ID
DWORD dwFlags; ///< 相关标志
CHAR szCodecName[MEDIACODEC_MAXCODECNAME];///< 编解码器的名称
// 编解码器私有数据
void* lpPrivateData; ///< 私有数据指针
// 音频部分参数
DWORD dwChannels; ///< 音频通道数 DWORD dwSamplesPerSec; ///< 音频采样率 DWORD dwBitsPerSample; ///< 音频量化位数
DWORD dwFrameSize; ///< 音频编码器处理帧长
// 视频部分
DWORD dwWidth; ///< 视频宽度
DWORD dwHeight; ///< 视频高度
DWORD dwFrameRate; ///< 帧率
DWORD dwGopSize; ///< 关键帧间隔
AC_PIX_FMT PixFmt; ///< 视频帧格式
// 编码设置
DWORD dwBitrate; ///< 目标码率,单位:bps
DWORD dwQuality; ///< 质量
DWORD dwPreset; ///< 预设参数
// 显示部分
void* lpGlobalContext; ///< 全局环境,Android 中为 JavaVM*
void* lpSuface; ///< 显示表面句柄
DWORD reserved[20]; ///< 保留
~~~
音视频数据包结构(struct MediaPacket)是 AnyChat 内核与 CODEC 交换数据的基本结构,里面包含了数据域(lpData)、数据长度(dwSize)和标志域(dwFlags),所有数据域的内存均由 AnyChat 内核分配与管理(包括输入类型与输出类型),CODEC 不需要再分配,对于输出类型的数据包,CODEC 内部需要检查 AnyChat 内核分配的内存是否足够(通过 dwSize 来判定),否则可能导致数据越界,形成非法内存访问异常,当 CODEC 内部检查到 AnyChat 内核分配的输出内存大小不足时,需要返回出错代码。标志域需要根据实际情况进行设置,如当视频编码
CODEC 输出的数据是关键帧时,标志域需要设置“MEDIACODEC_FLAGS_KEYFRAME”标志。
编解码器上下文句柄结构(struct MediaCodecContext)是 AnyChat 内核与 CODEC 之间传递参数的重要数据结构,初始化 CODEC 之前,AnyChat 内核会先设置相关的变量(如视频类型 CODEC 的宽度、高度、码率等),初始化 CODEC 之后,CODEC 内部需要设置该结构的相关变量,将信息返回给 AnyChat 内核,如初始化音频编码 CODEC 之后,CODEC 需要设置 dwFrameSize 变量,便于 AnyChat 内核了解每次需要向 CODEC 提交多少数据进行编码,详细信息可参考后面的“音频 CODEC” 和“视频 CODEC”等相关章节的具体说明。
编解码器上下文句柄结构(struct MediaCodecContext)中的“lpPrivateData”非常重要,可用于保存编解码器内部的状态参数,通常在初始化时分配内存,并初始化相关的状态,然后在编码(解码)的过程中使用,最后在关闭时释放内存, 分配内存、释放内存均在 CODEC 内部完成,“lpPrivateData”只是起一个中间桥梁的作用,AnyChat 内核会保障 CODEC 调用(初始化、编解码、关闭)之间的互斥。