当前位置: 首页 > news >正文

Linux frameworks 音视频架构音频部分

源码文件目录树形结构

linux_audio_framework/
├── include/                          # 头文件目录
│   ├── audio_stream.h               # 音频流主要接口
│   ├── media_common.h               # 媒体通用定义
│   ├── sub_common.h                 # 字幕通用定义  
│   ├── vdisp.h                      # 视频显示定义
├── src/                             # 源码目录
│   ├── audio_stream.c               # 音频流实现
├── test/                            # 测试目录
│   ├── test_main.c                  # 主测试程序

audio_stream.h

#ifndef __AUDIO_STREAM_H_           // 防止头文件重复包含的预处理器指令
#define __AUDIO_STREAM_H_           // 定义头文件保护宏
​
#ifdef __cplusplus                  // 如果使用 C++ 编译器编译
#if __cplusplus                     // 检查是否在 C++ 环境中
extern "C" {                        // 使用 C 语言链接规范,确保 C++ 中能正确链接 C 函数
#endif
#endif
​
#include <media_common.h>           // 包含媒体通用定义头文件
​
typedef void *astream_handle;       // 定义音频流句柄类型为 void 指针,实现数据隐藏设计模式
​
typedef enum as_port_type {         // 定义音频端口类型枚举AS_PORT_PCM = 0,            // PCM 音频端口AS_PORT_CODEC   = 1,        // 编解码器音频端口
} as_port_type_e;
​
// 函数声明区域
// 设计模式分析: 使用工厂模式创建音频流对象,提供统一的创建接口
// 性能分析: 轻量级创建函数,内存分配和初始化操作
​
astream_handle audio_stream_creat(void);                                    // 创建默认音频流
astream_handle audio_stream_creat_by_name(char *name);                      // 通过名称创建音频流
int audio_stream_select_encode_channel(astream_handle hdl, int channel_map); // 选择编码通道
void audio_stream_release(astream_handle hdl);                              // 释放音频流资源
int audio_stream_set_coding_type(astream_handle hdl, audio_encoder_t coding); // 设置编码类型
int audio_stream_set_prio(astream_handle hdl, int prio);                    // 设置优先级
int audio_stream_set_channels(astream_handle hdl, int channels);            // 设置声道数
int audio_stream_set_aec(astream_handle hdl, int on);                       // 设置回声消除
int audio_stream_set_anr(astream_handle hdl, int on);                       // 设置噪声抑制
int audio_stream_set_agc(astream_handle hdl, int on);                       // 设置自动增益控制
int audio_stream_set_sample_width(astream_handle hdl, int bits);            // 设置采样位宽
int audio_stream_set_sample_rate(astream_handle hdl, int rate);             // 设置采样率
signed long long audio_stream_get_time(astream_handle hdl);                 // 获取音频流时间
int audio_stream_set_private_para(astream_handle hdl, audio_private_para_t *para); // 设置私有参数
int audio_stream_get_sample_rate(astream_handle hdl);                       // 获取采样率
int audio_stream_get_sample_width(astream_handle hdl);                      // 获取采样位宽
int audio_stream_get_channels(astream_handle hdl);                          // 获取声道数
audio_encoder_t audio_stream_get_coding_type(astream_handle hdl);           // 获取编码类型
int audio_stream_set_mute(astream_handle hdl, int mute_on);                 // 设置静音
int audio_stream_start(astream_handle hdl);                                 // 启动音频流
int audio_stream_stop(astream_handle hdl);                                  // 停止音频流
​
// 设计模式分析: 整个模块采用外观模式(Facade Pattern),提供简化的高级接口隐藏底层复杂音频处理细节
// 性能分析: 函数接口设计为轻量级调用,实际音频处理在底层实现,避免在应用层进行复杂计算
​
#ifdef __cplusplus                  // 如果使用 C++ 编译器编译
#if __cplusplus                     // 检查是否在 C++ 环境中
}                                   // 结束 extern "C" 块
#endif
#endif
​
#endif                              // 结束头文件保护

media_common.h

#ifndef __MEDIA_COMMON_H__          // 防止头文件重复包含的预处理器指令
#define __MEDIA_COMMON_H__          // 定义头文件保护宏
​
#include "sub_common.h"              // 包含字幕通用定义头文件
​
#include <stdint.h>                  // 包含标准整数类型头文件
#include <stddef.h>                  // 包含标准定义头文件,提供size_t等
#include "vdisp.h"                   // 包含视频显示相关头文件
#define MAX_ROTATE_CHANNEL    4      // 定义最大旋转通道数为4
​
// 设计模式分析: 使用枚举类型定义各种类型,实现类型安全的状态模式
// 性能分析: 枚举类型编译时确定,运行时高效
​
typedef enum frame_type {            // 定义帧类型枚举VS_INVAILD_FRAME,            // 无效帧VS_VIDEO_RAW_FRAME,          // 视频原始帧VS_VIDEO_ROT_FRAME,          // 视频旋转帧VS_AUDIO_FRAME,              // 音频帧VS_IMAGE_FRAME,              // 图像帧VS_SUBTITLE_FRAME,           // 字幕帧VS_IMAGE_ROT_FRAME,          // 图像旋转帧VS_OTHER_FRAME               // 其他帧类型
} frame_type_t;
​
typedef enum stream_type {           // 定义流类型枚举STREAM_TYPE_UNKNOWN = 0,     // 未知流类型STREAM_TYPE_AUDIO,           // 音频流STREAM_TYPE_VIDEO,           // 视频流STREAM_TYPE_SUBTITLE,        // 字幕流
} stream_type_e;
​
typedef enum muxer_type {            // 定义复用器类型枚举MUXER_TYPE_UNKNOWN,          // 未知复用器MUXER_TYPE_RAW,              // 原始数据复用器MUXER_TYPE_TS,               // TS流复用器MUXER_TYPE_MP3,              // MP3复用器MUXER_TYPE_WAV,              // WAV复用器
} muxer_type_e;
​
typedef enum video_codec {           // 定义视频编解码器枚举VIDEO_CODEC_UNKNOWN = 0,     // 未知视频编解码器VIDEO_CODEC_H264,            // H264编解码器
} video_codec_e;
​
typedef enum audio_codec {           // 定义音频编解码器枚举AUDIO_CODEC_UNKNOWN = 0,     // 未知音频编解码器AUDIO_CODEC_PCM,             // PCM编解码器AUDIO_CODEC_AAC,             // AAC编解码器AUDIO_CODEC_G729,            // G729编解码器AUDIO_CODEC_G711A,           // G711A编解码器AUDIO_CODEC_G711U,           // G711U编解码器AUDIO_CODEC_G726,            // G726编解码器AUDIO_CODEC_G726LE,          // G726小端编解码器
} audio_codec_e;
​
typedef enum cb_port {               // 定义回调端口枚举CB_VCAM_OUT,                 // 虚拟相机输出端口CB_VROT_OUT,                 // 视频旋转输出端口CB_OTHER_PORT                // 其他端口
} cb_port_e;
​
typedef enum watermark_type {        // 定义水印类型枚举WM_TYPE_FOR_RECORDER,        // 用于录制器的水印WM_TYPE_FOR_PHOTO            // 用于照片的水印
} watermark_type_e;
​
typedef enum _audio_g726_mode {      // 定义G726音频模式枚举AUDIO_G726MODE_UNUSED = 0,   // 未使用的G726模式AUDIO_G726MODE_16K = 2,      // 16K比特率模式AUDIO_G726MODE_24K = 3,      // 24K比特率模式AUDIO_G726MODE_32K = 4,      // 32K比特率模式AUDIO_G726MODE_40K = 5,      // 40K比特率模式AUDIO_G726MODE_M32K = 6,     // 32K ADPCM模式AUDIO_G726MODE_M40K = 7,     // 40K ADPCM模式AUDIO_G726MODE_INVALID = 0xFFFFFFFF // 无效模式
} audio_g726_mode_e;
​
// 设计模式分析: 使用结构体封装相关数据,实现数据对象模式
// 性能分析: 结构体布局优化,减少内存碎片
​
typedef struct _audio_private_para { // 定义音频私有参数结构体audio_g726_mode_e g726_mode; // G726编码模式int32_t en_in_data_len;      // 编码输入数据长度
} audio_private_para_t;
​
/*** struct video_isp_info - VISS的EXIF信息结构* @valid: 1: ISP信息有效 0: ISP信息无效* @exposure_time: 曝光时间(秒) * 10000* @shutter_speed: 曝光时间(秒) * 10000  * @aperture: 光圈值 fno2.8 = 280* @brightness: 亮度值 LV = [0, 20], 0: 星光, 20: 日光* @exposure_bias: 曝光补偿(也称为EV偏置)* @iso_speed: ISO = 增益 * 100* @flash: 闪光灯状态寄存器值* @illu_id: 自动白平衡色温ID*    0: HOR(2100K)*    1: A(2900K)*    2: TL84(4000K)*    3: CWF(4100K)*    4: D50(5000K)*    5: D65(6500K)*    6: D75(7500K)* @back_score: 背光评分 = [0, 100] 百分比* @res: 保留信息* @res[0]: 目标亮度* @res[1]: 背景亮度* @res[2]: 平均亮度* @res[3]: 原始亮度* @res[4]: 最终亮度*/
typedef struct video_isp_info {      // 定义视频ISP信息结构体int valid;                    // ISP信息有效性标志unsigned int exposure_time;   // 曝光时间unsigned int shutter_speed;   // 快门速度unsigned int aperture;        // 光圈值unsigned int brightness;      // 亮度值unsigned int exposure_bias;   // 曝光补偿unsigned int iso_speed;       // ISO感光度unsigned int flash;           // 闪光灯状态unsigned int illu_id;         // 白平衡色温IDunsigned int back_score;      // 背光评分unsigned int res[16];         // 保留字段数组
} video_isp_info_t;
​
typedef struct video_frame_info {    // 定义视频帧信息结构体int color_fmt;                // 颜色格式int width;                    // 帧宽度int height;                   // 帧高度int stride;                   // 行跨度(步长)int sliceHeight;              // 切片高度int planar;                   // 平面格式标志unsigned char *addr[3];       // 多平面数据地址数组(YUV等)int size[3];                  // 多平面数据大小数组long long time_stamp;         // 时间戳video_isp_info_t isp_info;    // ISP信息
} video_frame_info_t;
​
typedef struct audio_frame_info {    // 定义音频帧信息结构体int sample_rate;              // 采样率char *addr;                   // 数据地址char size;                    // 数据大小long long time_stamp;         // 时间戳
} audio_frame_info_t;
​
typedef struct sub_style {           // 定义字幕样式结构体int has_style_flag;           // 样式有效标志,0或1char *name;                   // 样式名称av_sub_font_style_e font_style; // 字体样式int fontsize;                 // 字体大小int primarycolour;            // 字幕首选颜色,&HBBGGRR格式int secondarycolour;          // 卡拉OK中使用int outlinecolour;            // 边框颜色int backcolour;               // 阴影颜色font_bold_flag_e bold;        // 粗体标志,0关闭,-1打开font_italic_flag_e italic;    // 斜体标志,0关闭,-1打开font_underline_flag_e underline; // 下划线标志,0关闭,-1打开font_strikeout_flag_e strikeout; // 删除线标志,0关闭,-1打开float scalex;                 // 水平缩放,默认100%float scaley;                 // 垂直缩放,默认100%int spacing;                  // 字间距int angle;                    // 旋转角度int borderstyle;              // 边框样式float outline;                // 边框宽度1-4float shadow;                 // 阴影距离0-4av_sub_alignment_e alignment; // 对齐方式int marginl;                  // 左边距,左对齐时无效,值:0 ~ playResXint marginr;                  // 右边距,右对齐时无效,值:0 ~ playResYint marginv;                  // 字幕高度,底对齐时到底部距离,顶对齐时到顶部距离,居中对齐时无效int alphalevel;               // 透明度级别av_sub_encode_type_e encoding; // 编码样式
} sub_style_t;
​
typedef struct sub_event {           // 定义字幕事件结构体int dialogue_marginl;         // 对话左边距,为0时使用样式左边距int dialogue_marginr;         // 对话右边距,为0时使用样式右边距int dialogue_marginv;         // 对话垂直边距,为0时使用样式垂直边距av_sub_effect_type_e sub_effect_type; // 字幕特效类型charset_encode_e charset_type; // 字符集编码类型int effectstartx;             // 特效起始X坐标int effectendx;               // 特效结束X坐标int effectstarty;             // 特效起始Y坐标int effectendy;               // 特效结束Y坐标int effectdelaytime;          // 特效延迟时间av_subtitle_type_e type;      // 字幕类型int datasize;                 // 数据大小char *pdata;                  // 数据指针
} sub_data_t;
​
typedef struct sub_common {          // 定义字幕通用信息结构体int index;                    // 索引int resx;                     // 屏幕宽度int resy;                     // 屏幕高度long long start_disp_time;    // 开始显示时间long long end_disp_time;      // 结束显示时间
} sub_common_t;
​
typedef struct subtitle_frame_info { // 定义字幕帧信息结构体sub_common_t comm_info;       // 通用信息sub_style_t style;            // 样式信息sub_data_t data;              // 数据信息
} subtitle_frame_info_t;
​
// 设计模式分析: 使用联合体实现变体记录模式,节省内存空间
// 性能分析: 联合体减少内存占用,提高缓存效率
​
typedef struct frame {               // 定义通用帧结构体stream_type_e type;           // 流类型union {                       // 联合体,存储不同类型的帧信息video_frame_info_t video;   // 视频帧信息audio_frame_info_t audio;   // 音频帧信息subtitle_frame_info_t subtitle; // 字幕帧信息} info;void *priv_data;              // 私有数据指针void *header;                 // 头部信息指针
} frame_t;
​
typedef struct audio_stream_info {   // 定义音频流信息结构体audio_codec_e codec;          // 音频编解码器int samplerate;               // 采样率int channels;                 // 声道数int bits_per_sample;          // 每样本位数char *text;                   // 文本描述
} audio_stream_info_t;
​
typedef struct video_stream_info {   // 定义视频流信息结构体video_codec_e codec;          // 视频编解码器int width;                    // 宽度int height;                   // 高度char *text;                   // 文本描述
} video_stream_info_t;
​
typedef struct avstream_info {       // 定义音视频流信息结构体muxer_type_e muxer_type;      // 复用器类型int astream_num;              // 音频流数量int vstream_num;              // 视频流数量int64_t size;                 // 流大小audio_stream_info_t astream_info; // 音频流信息video_stream_info_t vstream_info; // 视频流信息
} avstream_info_t;
​
typedef enum {                       // 定义音视频流帧类型枚举VS_VIDEO_NVALID,              // 无效视频帧VS_VIDEO_PPS,                 // PPS帧VS_VIDEO_I_FRAME,             // I帧VS_VIDEO_P_FRAME,             // P帧VS_VIDEO_B_FRAME,             // B帧VS_OTHER_MEDIA,               // 其他媒体类型
} avstream_frame_type_e;
​
typedef struct avstream {            // 定义音视频流结构体stream_type_e type;           // 流类型uint8_t *data;                // 数据指针int data_size;                // 数据大小int64_t timestamp;            // 时间戳avstream_frame_type_e frame_type; // 帧类型
} avstream_t;
​
// 设计模式分析: 使用回调函数指针,实现观察者模式和策略模式
// 性能分析: 回调机制减少模块间耦合,提高系统灵活性
​
typedef struct app_frame_cb {        // 定义应用帧回调结构体frame_type_t type;            // 帧类型void *app_data;               // 应用数据指针int(*buf_handle)(void *app_data, frame_t *pframe); // 缓冲区处理回调函数
} app_frame_cb_t;
​
typedef struct app_port_cb {         // 定义应用端口回调结构体cb_port_e type;               // 端口类型void *app_data;               // 应用数据指针int(*buf_handle)(void *app_data, frame_t *pframe); // 缓冲区处理回调函数
} app_port_filter_t;
​
typedef struct app_stream_cb {       // 定义应用流回调结构体void *app_data;               // 应用数据指针int (*buf_handle)(void *, avstream_t *); // 流处理回调函数
} app_stream_cb_t;
​
typedef int (*picture_data_cb)(void *pbuff, int data_len, void *userdata); // 定义图片数据回调函数类型
​
typedef enum AUDIO_ENCODER {         // 定义音频编码器枚举AUDIO_ENCODER_INVALID = 0,    // 无效编码器AUDIO_ENCODER_AAC,            // AAC编码器AUDIO_ENCODER_AAC_RAW = AUDIO_ENCODER_AAC, // AAC原始格式AUDIO_ENCODER_AAC_MP4ADTS,    // AAC MP4 ADTS格式AUDIO_ENCODER_ADPCM,          // ADPCM编码器AUDIO_ENCODER_PCM,            // PCM编码器AUDIO_ENCODER_G729,           // G729编码器AUDIO_ENCODER_PCM_ALAW,       // PCM A律编码器AUDIO_ENCODER_PCM_MULAW,      // PCM μ律编码器AUDIO_ENCODER_ADPCM_G726,     // ADPCM G726编码器AUDIO_ENCODER_ADPCM_G726LE,   // ADPCM G726小端编码器AUDIO_ENCODER_UNSUPPORT,      // 不支持的编码器AUDIO_ENCODER_NONE = 0x7fff   // 无编码器
} audio_encoder_t;
​
typedef struct win_rect {            // 定义窗口矩形结构体int   x;                      // X坐标int   y;                      // Y坐标int   width;                  // 宽度int   height;                 // 高度
} win_rect_t;
​
typedef struct colli_file_cfg {      // 定义碰撞文件配置结构体int cache_time;               // 碰撞发生前保存到缓存的时间(秒)int total_time;               // 碰撞文件总时间(秒)char *filename;               // 保存的文件名app_stream_cb_t cb;           // 流回调int (*cb_file_save_event)(void *hdl, char *file_name); // 文件保存事件回调
} colli_file_cfg_t;
​
typedef enum recorder_cache_tag {    // 定义录制器缓存标签枚举RECORDER_CACHE_NOT_USE,       // 不使用缓存RECORDER_CACHE_USE,           // 使用缓存
} recorder_cache_e;
​
typedef struct channel_rot_para {    // 定义通道旋转参数结构体vdisp_rotate_mode_e rot;      // 旋转模式win_rect_t src_rect;          // 源矩形区域win_rect_t dst_rect;          // 目标矩形区域
} channel_rot_para;
​
typedef struct multi_ch_rot_para {   // 定义多通道旋转参数结构体int channel_num;              // 通道数量channel_rot_para para[MAX_ROTATE_CHANNEL]; // 旋转参数数组
} multi_ch_rot_para_t;
​
typedef enum recorder_type {         // 定义录制器类型枚举RECORDER_TYPE_NORMAL,         // 正常速度录制器RECORDER_TYPE_TIME_LAG,       // 延时摄影录制器
} recorder_type_e;
​
typedef struct rec_time_lag_para {   // 定义延时录制参数结构体int interval;                 // 编码帧采样间隔int play_framerate;           // 播放帧率
} rec_time_lag_para_t;
​
// 函数声明区域
// 设计模式分析: 提供模块初始化和反初始化接口,实现模块化设计模式
// 性能分析: 初始化函数负责资源分配,反初始化函数负责资源释放,确保资源管理
​
long media_init(void);               // 媒体模块初始化函数
void media_deinit(void);             // 媒体模块反初始化函数
int media_get_pts(int64_t *pts);     // 获取PTS(显示时间戳)函数
int media_sync_pts(int64_t ptsbase); // 同步PTS函数
​
#endif /* __MEDIA_COMMON_H__ */      // 结束头文件保护
​

sub_common.h

#ifndef __SUB_COMMON_H__              // 防止头文件重复包含的预处理器指令
#define __SUB_COMMON_H__              // 定义头文件保护宏
​
// 设计模式分析: 使用枚举类型定义字幕相关常量,实现类型安全的状态模式和策略模式
// 性能分析: 枚举类型编译时确定,运行时高效,内存占用小
​
/* 字幕特效类型枚举 - 定义字幕显示时的动画效果类型 */
typedef enum SUB_EFFECT_TYPE {         // 定义字幕特效类型枚举SUB_EFFECT_TYPE_NONE = 0,        // 无特效SUB_EFFECT_TYPE_SCROLL_UP,       // 向上滚动特效SUB_EFFECT_TYPE_SCROLL_DOWN,     // 向下滚动特效SUB_EFFECT_TYPE_BANNER_LTOR,     /* 从左到右移动的横幅特效 */ SUB_EFFECT_TYPE_BANNER_RTOL,     /* 从右到左移动的横幅特效 */
/*  SUB_EFFECT_TYPE_KARAOKE, */      /* 卡拉OK特效(已注释) */
} av_sub_effect_type_e;
​
/* 字幕对齐方式枚举 - 定义字幕在屏幕上的对齐位置 */
typedef enum SUB_ALIGNMENT {           // 定义字幕对齐方式枚举SUB_ALIGNMENT_NONE = 0,          // 无对齐(默认)SUB_ALIGNMENT_BOT_LEFT,          // 底部左对齐SUB_ALIGNMENT_BOT_CENTER,        // 底部居中对齐SUB_ALIGNMENT_BOT_RIGHT,         // 底部右对齐SUB_ALIGNMENT_MID_LEFT,          // 中部左对齐SUB_ALIGNMENT_MID_CENTER,        // 中部居中对齐SUB_ALIGNMENT_MID_RIGHT,         // 中部右对齐SUB_ALIGNMENT_TOP_LEFT,          // 顶部左对齐SUB_ALIGNMENT_TOP_CENTER,        // 顶部居中对齐SUB_ALIGNMENT_TOP_RIGHT,         // 顶部右对齐
} av_sub_alignment_e;
​
/* 字幕编码类型枚举 - 定义字幕文本的字符编码格式 */
typedef enum SUB_ENCODINGTYPE {        // 定义字幕编码类型枚举SUB_ENCODE_TYPE_DEFAULT = 0,     // 默认编码类型SUB_ENCODE_TYPE_ANSI,            /* 英文ANSI编码 0 */SUB_ENCODE_TYPE_BITMAP,          // 位图编码(图形字幕)SUB_ENCODE_TYPE_GB2312,          /* 简体中文 GB2312 编码 134 */SUB_ENCODE_TYPE_BIG5,            /* 繁体中文 Big5 编码 136 */SUB_ENCODE_TYPE_GBK,             /* 中文字符 GBK 编码 */SUB_ENCODE_TYPE_UTF8,            // UTF-8 编码SUB_ENCODE_TYPE_UTF16,           // UTF-16 编码SUB_ENCODE_TYPE_UTF32,           // UTF-32 编码SUB_ENCODE_TYPE_UNICODE,         // Unicode 编码
} av_sub_encode_type_e;
​
/* 字幕字体样式枚举 - 定义字幕使用的字体类型 */
typedef enum SUB_FONT_STYLE {          // 定义字幕字体样式枚举SUB_FONT_STYLE_DEFAULT = 0,      // 默认字体样式SUB_FONT_STYLE_ARIAL,            // Arial 字体SUB_FONT_STYLE_GBK_20,           // GBK 20号字体SUB_FONT_STYLE_MIC_YAHEI,        // 微软雅黑字体
} av_sub_font_style_e;
​
/* 字体粗体效果枚举 - 定义字体是否加粗显示 */
typedef enum SUB_FONT_EFFECT_BOLD {    // 定义字体粗体效果枚举SUB_FONT_BOLD_OFF = 0,           // 关闭粗体效果SUB_FONT_BOLD_ON,                // 开启粗体效果
} font_bold_flag_e;
​
/* 字体斜体效果枚举 - 定义字体是否斜体显示 */
typedef enum SUB_FONT_EFFECT_ITALIC {  // 定义字体斜体效果枚举SUB_FONT_ITALIC_OFF = 0,         // 关闭斜体效果SUB_FONT_ITALIC_ON,              // 开启斜体效果
} font_italic_flag_e;
​
/* 字体下划线效果枚举 - 定义字体是否添加下划线 */
typedef enum SUB_FONT_EFFECT_UNDERLINE { // 定义字体下划线效果枚举SUB_FONT_UNDERLINE_OFF = 0,      // 关闭下划线效果SUB_FONT_UNDERLINE_ON,           // 开启下划线效果
} font_underline_flag_e;
​
/* 字体删除线效果枚举 - 定义字体是否添加删除线 */
typedef enum SUB_FONT_EFFECT_STRIKEOUT { // 定义字体删除线效果枚举SUB_FONT_STRIKEOUT_OFF = 0,      // 关闭删除线效果SUB_FONT_STRIKEOUT_ON,           // 开启删除线效果
} font_strikeout_flag_e;
​
/* 字幕类型枚举 - 定义字幕的基本类型 */
typedef enum av_subtitle_type {        // 定义字幕类型枚举SUB_NONE,                        // 无字幕SUB_TEXT,                        // 文本字幕SUB_BITMAP,                      // 位图字幕(图形字幕)
} av_subtitle_type_e;
​
/* 字符集编码类型枚举 - 定义字符编码标准 */
typedef enum charset_encode_type {     // 定义字符集编码类型枚举IS_CHARSET_ENCODE_DEFAULT = -1,  // 默认字符集编码IS_CHARSET_ENCODE_UTF_8 = 0,     // UTF-8 编码IS_CHARSET_ENCODE_GBK = 1,       // GBK 编码IS_CHARSET_ENCODE_ASCII,         // ASCII 编码IS_CHARSET_ENCODE_GBK2312,       // GBK2312 编码IS_CHARSET_ENCODE_UNICODE,       // Unicode 编码IS_CHARSET_ENCODE_BIG_5,         // Big5 编码(繁体中文)IS_CHARSET_ENCODE_GB18030,       // GB18030 编码(中文国家标准)
} charset_encode_e;
​
#endif /* __ASS_COMMON_H__ */         // 结束头文件保护(注意: 宏名称与开头不匹配,应为__SUB_COMMON_H__)
​

vdisp.h

#ifndef __VDISP_H__                    // 防止头文件重复包含的预处理器指令
#define __VDISP_H__                    // 定义头文件保护宏
​
// 设计模式分析: 使用枚举类型定义视频显示相关常量,实现状态模式和策略模式
// 性能分析: 枚举类型编译时确定,运行时高效,提供类型安全的配置选项
​
/* 视频显示旋转模式枚举 - 定义视频图像的旋转和翻转变换操作 */
typedef enum vdisp_rotate_mode {       // 定义视频显示旋转模式枚举VDISP_ROTATE_NONE   = 0,        // 无旋转,原始方向VDISP_ROTATE_90     = 1,        // 顺时针旋转90度VDISP_ROTATE_180    = 2,        // 旋转180度VDISP_ROTATE_270    = 3,        // 顺时针旋转270度(逆时针90度)VDISP_FLIP_H        = 4,        // 水平翻转(镜像)VDISP_FLIP_H_ROT_90 = 5,        // 水平翻转后旋转90度VDISP_FLIP_V        = 6,        // 垂直翻转VDISP_FLIP_V_ROT_90 = 7,        // 垂直翻转后旋转90度
​/* 软件旋转模式 - 通过软件算法实现的旋转,性能较低但兼容性好 */VDISP_SW_ROTATE_NONE    = 20,     // 软件无旋转VDISP_SW_ROTATE_90  = 21,       // 软件顺时针旋转90度VDISP_SW_ROTATE_180 = 22,       // 软件旋转180度VDISP_SW_ROTATE_270 = 23,       // 软件顺时针旋转270度VDISP_SW_FLIP_H     = 24,       // 软件水平翻转VDISP_SW_FLIP_H_ROT_90  = 25,       // 软件水平翻转后旋转90度VDISP_SW_FLIP_V     = 26,       // 软件垂直翻转VDISP_SW_FLIP_V_ROT_90  = 27,       // 软件垂直翻转后旋转90度
​VDISP_MULTI_CHANNEL = 0xff,     // 多通道显示模式
} vdisp_rotate_mode_e;
​
// 设计模式分析: 显示模式枚举实现策略模式,允许运行时选择不同的显示策略
// 性能分析: 硬件加速模式(0-7)性能高,软件模式(20-27)性能低但兼容性好
​
/* 视频显示模式枚举 - 定义视频在显示窗口中的缩放和适配方式 */
typedef enum vdisp_mode {              // 定义视频显示模式枚举/* 在窗口中以视频原始尺寸显示,不会溢出窗口 */VDISP_WINDOW_ORIGINAL,             // 原始尺寸模式/* 按视频比例缩放到全屏,视频显示正常比例 */VDISP_WINDOW_FULL_SCREEN_VIDEO_RATIO, // 全屏保持视频比例模式/* 按屏幕比例缩放到全屏,视频可能会变形 */VDISP_WINDOW_FULL_SCREEN_SCREEN_RATIO, // 全屏拉伸模式(可能变形)/* 强制以4:3比例显示,视频可能会变形 */VDISP_WINDOW_4R3MODE,              // 4:3强制比例模式/* 强制以16:9比例显示,视频可能会变形 */VDISP_WINDOW_16R9MODE,             // 16:9强制比例模式/* 用于裁剪视频的黑边 */VDISP_WINDOW_CUTEDGE,              // 裁剪黑边模式/* 用户自定义模式 */VDISP_WINDOW_USERDEF,              // 用户自定义模式
} vdisp_mode_e;
​
// 设计模式分析: 显示模式枚举实现策略模式,支持多种显示适配算法
// 性能分析: 不同模式对CPU/GPU负载不同,原始尺寸模式性能最佳,缩放模式需要额外计算
​
/* 视频图层层级枚举 - 定义视频层在显示堆叠中的位置 */
typedef enum video_layer_level {       // 定义视频图层层级枚举VIDEO_LAYER_TOP = 0,               // 顶层显示(覆盖其他图层)VIDEO_LAYER_BOTTOM,                // 底层显示(被其他图层覆盖)VIDEO_LAYER_NONE = 0x7fff          // 无图层或禁用图层
} video_layer_level_t;
​
// 设计模式分析: 图层层级实现组合模式,支持多层视频合成显示
// 性能分析: 图层合成需要额外的内存带宽和GPU处理,但提供灵活的显示控制
​
/* 缩放模式枚举 - 定义视频缩放的执行方式 */
typedef enum scale_mode {              // 定义缩放模式枚举SCALE_MODE_ONLINE,                 // 在线缩放(实时处理)SCALE_MODE_OFFLINE,                // 离线缩放(预处理)
} scale_mode_e;
​
// 设计模式分析: 缩放模式实现策略模式,允许选择不同的缩放处理策略
// 性能分析: 在线缩放增加实时处理负载,离线缩放预处理消耗存储但运行时性能更好
​
#endif /* __VDISP_H__ */               // 结束头文件保护
​
​

audio_stream.c

#define DBG_LEVEL       DBG_WARNING  // 设置调试级别为警告级别
#define LOG_TAG         "audio_stream"  // 定义日志标签为"audio_stream"
#include <oscl.h>                    // 包含操作系统抽象层头文件
#include <base_component.h>          // 包含基础组件头文件
#include "omx_api.h"                 // 包含OpenMAX IL API头文件
#include "audio_stream.h"            // 包含音频流头文件
#include "av_media_type.h"           // 包含音视频媒体类型头文件
#include "omx_vendor_lb.h"           // 包含厂商特定的OpenMAX扩展头文件
​
#define AUDIO_DEFAULT_RATE      48000      // 定义默认音频采样率为48kHz
#define AUDIO_DEFAULT_CHANNELS      2         // 定义默认音频声道数为2(立体声)
#define AUDIO_DEFAULT_FMT_WIDTH     16        // 定义默认音频采样位宽为16位
#define AUDIO_DEFAULT_CODINGTYPE    AUDIO_ENCODER_AAC  // 定义默认音频编码类型为AAC
​
// 设计模式分析: 使用状态枚举实现状态模式,管理音频流生命周期
// 性能分析: 状态机模式确保状态转换的确定性和高效性
typedef enum astream_state {          // 定义音频流状态枚举AS_STATE_ERR = 0,              // 错误状态AS_STATE_INIT,                 // 初始化状态AS_STATE_START,                // 启动状态AS_STATE_ENCODE,               // 编码状态
} astream_state_e;
​
// 设计模式分析: 组合模式,将组件信息组合成音频源信息
typedef struct asrc_info {            // 定义音频源信息结构体comp_info_t al_comp;           // 音频组件信息port_info_t *aout;             // 音频输出端口指针
} asrc_info_t;
​
// 设计模式分析: 组合模式,将组件信息组合成音频编码器信息
typedef struct aenc_info {            // 定义音频编码器信息结构体comp_info_t al_comp;           // 音频组件信息port_info_t *ain;              // 音频输入端口指针port_info_t *aout;             // 音频输出端口指针
} aenc_info_t;
​
// 设计模式分析: 组合模式,管理音频分流器组件和端口映射
typedef struct _asplt_info {          // 定义音频分流器信息结构体comp_info_t al_comp;           // 音频组件信息port_info_t *in;               // 输入端口指针int outport_map;               // 输出端口映射位图
} audio_splt_t;
​
#define MAX_DEV_NAME_LEN 32          // 定义最大设备名称长度为32字节
// 设计模式分析: 享元模式,音频源对象被多个编码器共享使用
// 性能分析: 共享音频源减少资源重复分配,提高内存利用率
typedef struct audio_source {         // 定义音频源结构体char dev_name[MAX_DEV_NAME_LEN]; // 设备名称OMX_U32 channels;              /* 声道数 (例如 2 表示立体声) */OMX_U32 bit_per_sample;        /* 每个采样的位数 */OMX_U32 sample_rate;           /* 源数据的采样率。对于可变或未知采样率使用0 */int mute_on;                    // 静音开关OMX_U32 aqe_funcs;              // 音频质量增强功能int prio;                       // 优先级asrc_info_t asrc_info;          // 音频源信息audio_splt_t asrc_splt;         // 音频源分流器int ref;                        // 引用计数int started_cnt;                // 启动计数int index;                      // 索引
} audio_source_t;
​
// 设计模式分析: 策略模式,支持多种音频编码算法
// 性能分析: 编码器参数预配置,减少运行时计算开销
typedef struct audio_enc {            // 定义音频编码器结构体int prio;                       // 优先级int n_channel;                  // 声道数int channel_map;                // 声道映射audio_encoder_t coding_type;    // 编码类型
​audio_source_t *asrc;           // 关联的音频源指针port_info_t *aenc_srcport;      // 编码器源端口aenc_info_t aenc_info;          // 编码器信息audio_splt_t aenc_splt;         // 编码器分流器int ref;                        // 引用计数int started_cnt;                // 启动计数int index;                      // 索引audio_private_para_t private_para; // 私有参数
} audio_enc_t;
​
// 设计模式分析: 外观模式,提供简化的音频流操作接口
// 性能分析: 句柄封装内部复杂结构,提供轻量级访问接口
typedef struct {                      // 定义音频流句柄结构体astream_state_e state;          // 音频流状态audio_source_t *asrc;           // 音频源指针audio_enc_t *aenc;              // 音频编码器指针port_info_t *enc_outport;       // 编码输出端口int srcport_map;                // 源端口映射int encport_map;                // 编码端口映射int index;                      // 索引int ref;                        // 引用计数
} astream_handle_t;
​
#define MAX_AUDIO_DEVICE 4           // 定义最大音频设备数为4
#define MAX_AUDIO_STREAM 8           // 定义最大音频流数为8
​
// 设计模式分析: 单例模式,全局音频流管理器
// 性能分析: 集中管理音频资源,避免资源碎片化
typedef struct audio_stream {         // 定义音频流管理器结构体OMX_U32 channels;              /* 声道数 (例如 2 表示立体声) */OMX_U32 bit_per_sample;        /* 每个采样的位数 */OMX_U32 sample_rate;           /* 源数据的采样率。对于可变或未知采样率使用0 */audio_encoder_t coding_type;    // 编码类型
​astream_state_e state;          // 状态asrc_info_t asrc_info;          // 音频源信息audio_splt_t asrc_splt;         // 音频源分流器port_info_t *aenc_srcport;      // 编码器源端口aenc_info_t aenc_info;          // 编码器信息audio_splt_t aenc_splt;         // 编码器分流器
​audio_source_t *audio_source[MAX_AUDIO_DEVICE];  // 音频源数组audio_enc_t *audio_encoder[MAX_AUDIO_STREAM];    // 音频编码器数组astream_handle_t *astream_handle_t[MAX_AUDIO_STREAM]; // 音频流句柄数组pthread_mutex_t lock;           // 互斥锁int ref;                        // 引用计数int init;                       // 初始化标志int muti_coding_enable;         // 多编码使能标志
} audio_stream_t;
​
// 设计模式分析: 对象池模式,预分配音频资源对象
// 性能分析: 静态分配避免动态内存分配开销,提高实时性
typedef struct audio_stream_sum {     // 定义音频流汇总结构体audio_source_t audio_source[MAX_AUDIO_DEVICE];  // 音频源对象池audio_enc_t audio_encoder[MAX_AUDIO_STREAM];    // 音频编码器对象池astream_handle_t astream_handle_t[MAX_AUDIO_STREAM]; // 音频流句柄对象池int init;                       // 初始化标志int muti_coding_enable;         // 多编码使能标志
} audio_stream_sum_t;
​
// 平台相关的互斥锁初始化
#ifdef __EOS__
static pthread_mutex_t _astream_lock = {.attr = -1};  // EOS平台互斥锁初始化
#else
static pthread_mutex_t _astream_lock = PTHREAD_MUTEX_INITIALIZER;  // 标准平台互斥锁初始化
#endif
​
// 全局音频录制对象,单例模式实例
audio_stream_sum_t g_audio_rec = {   // 定义全局音频录制对象.init = 0                       // 初始化为未初始化状态
};
​
// 设计模式分析: 包装器模式,提供线程安全的资源访问
// 性能分析: 细粒度锁保护关键资源,平衡并发性能和数据安全
#define ASTREAM_LOCK() pthread_mutex_lock(&_astream_lock)      // 音频流加锁宏
#define ASTREAM_UNLOCK() pthread_mutex_unlock(&_astream_lock)  // 音频流解锁宏
#define get_audio_stream(hdl) ((astream_handle_t *)(hdl))      // 获取音频流句柄宏
​
// 调试日志宏定义
#define log_aenc_state(aenc) \                               // 记录音频编码器状态宏OSCL_LOGI("asrc:%p, count:%d; aenc %p count:%d!", \      // 日志格式aenc ? aenc->asrc : NULL,\                          // 音频源指针aenc ? (aenc->asrc ? aenc->asrc->started_cnt : 0) : 0, \  // 音频源启动计数aenc, aenc ? aenc->started_cnt : 0)                 // 编码器指针和启动计数
​
#define log_astream_state(astream) \                         // 记录音频流状态宏OSCL_LOGI("hdl:%p-%p-%p ref:%d-%d-%d, start:%d-%d, map:%x-%x", \  // 日志格式astream, astream ? astream->asrc : NULL, \          // 句柄和音频源指针astream ? astream->aenc : NULL, \                   // 编码器指针astream->ref, astream->asrc ? astream->asrc->ref : 0, \  // 引用计数astream->aenc ? astream->aenc->ref : 0, \           // 编码器引用计数astream->asrc ? astream->asrc->started_cnt : 0, \   // 音频源启动计数astream->aenc ? astream->aenc->started_cnt : 0, \   // 编码器启动计数astream->asrc ? astream->asrc->asrc_splt.outport_map : 0, \  // 源端口映射astream->aenc ? astream->aenc->aenc_splt.outport_map : 0)  // 编码端口映射
​
// 设计模式分析: 工厂方法模式,根据名称获取或创建音频源
// 性能分析: 对象池查找O(n)复杂度,缓存友好但规模受限
static audio_source_t *__get_source_by_name(char *name)  // 根据名称获取音频源函数
{int i;audio_stream_sum_t *ainfo = &g_audio_rec;  // 获取全局音频信息audio_source_t *asource = NULL;            // 音频源指针int unused_index = -1;                     // 未使用索引
​oscl_param_check(name != NULL, NULL, NULL);  // 参数检查
​for (i = 0; i < MAX_AUDIO_DEVICE; i++) {  // 遍历音频设备数组if (unused_index == -1 &&             // 查找第一个未使用的索引strlen(ainfo->audio_source[i].dev_name) == 0) {unused_index = i;}if (strcmp(name, ainfo->audio_source[i].dev_name) == 0) {  // 查找匹配设备名asource = &ainfo->audio_source[i];  // 找到现有音频源break;}}if (asource == NULL && unused_index != -1) {  // 未找到且有空闲位置asource = &ainfo->audio_source[unused_index];  // 创建新音频源asource->index = unused_index;           // 设置索引strncpy(asource->dev_name, name, MAX_DEV_NAME_LEN - 1);  // 复制设备名asource->channels = AUDIO_DEFAULT_CHANNELS;  // 设置默认声道数asource->bit_per_sample = AUDIO_DEFAULT_FMT_WIDTH;  // 设置默认位宽asource->sample_rate = AUDIO_DEFAULT_RATE;   // 设置默认采样率asource->started_cnt = 0;                    // 初始化启动计数}if (asource)                              // 如果成功获取音频源asource->ref++;                       // 增加引用计数elseOSCL_LOGE("create audio stream source failed:%s", name);  // 记录错误日志return asource;                           // 返回音频源指针
}
​
// 设计模式分析: 引用计数模式,管理音频源生命周期
// 性能分析: 轻量级引用计数,避免频繁的内存分配释放
int __put_source(audio_source_t *asource)      // 释放音频源函数
{oscl_param_check(asource != NULL, -1, NULL);  // 参数检查oscl_param_check(asource->ref > 0, 0, NULL);  // 引用计数检查asource->ref--;                        // 减少引用计数if (asource->ref == 0) {               // 如果引用计数为0if (asource->asrc_info.al_comp.cmp_hdl) {  // 检查组件句柄是否释放OSCL_LOGE("ERR! resource not released:%p",  // 记录资源未释放错误asource->asrc_info.al_comp.cmp_hdl);}memset(asource, 0, sizeof(audio_source_t));  // 清空音频源内存}return 0;                              // 返回成功
}
​
// 设计模式分析: 享元模式,查找正在执行的相同配置编码器
// 性能分析: 避免重复创建相同编码器,节省系统资源
static audio_enc_t *__get_excuting_aenc(audio_enc_t *init_encoder)  // 获取执行中编码器函数
{audio_stream_sum_t *ainfo = &g_audio_rec;  // 获取全局音频信息int i;audio_enc_t *excuting_encoder = NULL;      // 执行中编码器指针audio_enc_t *tmp_enc = NULL;               // 临时编码器指针excuting_encoder = NULL;
​/* 多编码未启用,所有流使用同一个编码器 */if (ainfo->muti_coding_enable == 0)        // 检查多编码是否禁用return NULL;
​/* 查找具有相同音频源和设置的执行中编码器 */for (i = 0; i < MAX_AUDIO_STREAM; i++) {   // 遍历音频编码器数组tmp_enc = &ainfo->audio_encoder[i];    // 获取临时编码器if (tmp_enc != init_encoder &&         // 不是初始编码器tmp_enc->asrc == init_encoder->asrc &&  // 相同音频源tmp_enc->started_cnt > 0 &&        // 正在执行tmp_enc->channel_map == init_encoder->channel_map &&  // 相同声道映射tmp_enc->coding_type == init_encoder->coding_type) {  // 相同编码类型excuting_encoder = tmp_enc;        // 找到匹配编码器excuting_encoder->ref++;           // 增加引用计数OSCL_LOGE("find a excuting audio encoder:(%s),%d,%x",  // 记录日志tmp_enc->asrc->dev_name, tmp_enc->coding_type,tmp_enc->channel_map);break;}}return excuting_encoder;                   // 返回执行中编码器
}
​
// 设计模式分析: 工厂方法模式,根据音频源获取编码器
// 性能分析: 对象池管理,支持单编码和多编码两种模式
static audio_enc_t *__get_aenc_by_src(audio_source_t *asrc)  // 根据音频源获取编码器函数
{int i;audio_enc_t *aenc = NULL;                  // 编码器指针audio_stream_sum_t *ainfo = &g_audio_rec;  // 获取全局音频信息
​oscl_param_check(asrc != NULL, NULL, NULL);  // 参数检查/* 多编码未启用,所有流使用同一个编码器。在数组中查找它 */if (ainfo->muti_coding_enable == 0) {      // 单编码模式for (i = 0; i < MAX_AUDIO_STREAM; i++) {  // 遍历查找现有编码器if (ainfo->audio_encoder[i].asrc == asrc) {  // 找到匹配音频源的编码器aenc = &ainfo->audio_encoder[i];  // 获取编码器break;}}}/* 多编码启用,获取新编码器 */if (ainfo->muti_coding_enable != 0 || aenc == NULL) {  // 多编码模式或未找到OSCL_TRACE("==");aenc = NULL;for (i = 0; i < MAX_AUDIO_STREAM; i++) {  // 遍历查找空闲编码器OSCL_TRACE("==");if (ainfo->audio_encoder[i].asrc == NULL) {  // 找到空闲编码器aenc = &ainfo->audio_encoder[i];  // 获取编码器aenc->asrc = asrc;               // 设置音频源aenc->prio = 0;                  // 初始化优先级aenc->coding_type = AUDIO_DEFAULT_CODINGTYPE;  // 设置默认编码类型aenc->index = i;                 // 设置索引aenc->n_channel = aenc->asrc->channels;  // 设置声道数aenc->channel_map = (1<<aenc->n_channel) - 1;  // 设置声道映射(全选)break;}}}OSCL_TRACE("==");if (aenc)                                  // 如果成功获取编码器aenc->ref++;                           // 增加引用计数elseOSCL_LOGE("create audio stream encoder failed:%s", asrc->dev_name);  // 记录错误OSCL_TRACE("==");return aenc;                               // 返回编码器指针
}
​
// 设计模式分析: 引用计数模式,管理编码器生命周期
// 性能分析: 延迟释放策略,避免频繁创建销毁编码器
int __put_enc(audio_enc_t *aenc)               // 释放编码器函数
{oscl_param_check(aenc != NULL, -1, NULL);  // 参数检查oscl_param_check(aenc->ref > 0, 0, NULL);  // 引用计数检查aenc->ref--;                        // 减少引用计数if (aenc->ref == 0) {               // 如果引用计数为0if (aenc->aenc_srcport || aenc->aenc_info.al_comp.cmp_hdl) {  // 检查资源是否释放OSCL_LOGE("ERR! resource not released:%p %p",  // 记录资源未释放错误aenc->aenc_srcport, aenc->aenc_info.al_comp.cmp_hdl);}memset(aenc, 0, sizeof(audio_enc_t));  // 清空编码器内存}return 0;                              // 返回成功
}
​
​
/*** _setup_asrc - 为音频接收器组件设置参数** @asrc: 音频源** 成功返回0,否则返回错误码。*/
// 设计模式分析: 模板方法模式,定义音频源设置的固定流程
// 性能分析: 批量设置OpenMAX参数,减少API调用次数
int _setup_asrc(audio_source_t *asrc)          // 设置音频源函数
{OMX_AUDIO_PARAM_PCMMODETYPE pcm_type;      // PCM参数结构int ret = 0;OMX_PRIORITYMGMTTYPE priority;             // 优先级管理结构OMX_AUDIO_CONFIG_MUTETYPE mute;            // 静音配置结构
​OSCL_TRACE("asrc:%p", asrc);               // 跟踪日志oscl_param_check(asrc != NULL, 0, NULL);   // 参数检查oscl_param_check(asrc->asrc_info.al_comp.cmp_hdl != NULL, 0, NULL);  // 组件句柄检查oscl_param_check(asrc->asrc_info.aout != NULL, 0, NULL);  // 输出端口检查
​OMX_SetParameter(asrc->asrc_info.al_comp.cmp_hdl,  // 设置设备名称参数omx_index_audio_devname,asrc->dev_name);
​/* 为音频接收器组件设置参数*/ret = OMX_SetConfig(asrc->asrc_info.al_comp.cmp_hdl,  // 设置音频质量增强功能omx_index_audio_aqefunc, &asrc->aqe_funcs);if (ret) {OSCL_LOGE("set audio aqe funcs config error!");  // 记录错误return ret;}
​memset(&pcm_type, 0, sizeof(pcm_type));    // 清空PCM参数结构pcm_type.nChannels = asrc->channels;       // 设置声道数pcm_type.nBitPerSample = asrc->bit_per_sample;  // 设置采样位宽pcm_type.nSamplingRate = asrc->sample_rate;  // 设置采样率ret = OMX_SetParameter(asrc->asrc_info.al_comp.cmp_hdl,  // 设置PCM参数OMX_IndexParamAudioPcm,&pcm_type);
​if (asrc->prio) {                          // 如果设置了优先级priority.nVersion.nVersion = OMX_VERSION;  // 设置版本priority.nGroupPriority = asrc->prio;  // 设置组优先级OMX_SetParameter(asrc->asrc_info.al_comp.cmp_hdl,  // 设置源组件优先级OMX_IndexParamPriorityMgmt, &priority);OMX_SetParameter(asrc->asrc_splt.al_comp.cmp_hdl,  // 设置分流器组件优先级OMX_IndexParamPriorityMgmt, &priority);}
​memset(&mute, 0, sizeof(OMX_AUDIO_CONFIG_MUTETYPE));  // 清空静音配置结构if (asrc->mute_on)                         // 如果启用静音mute.bMute = OMX_TRUE;                 // 设置静音标志mute.nPortIndex = asrc->asrc_info.aout->index;  // 设置端口索引ret = OMX_SetConfig(asrc->asrc_info.al_comp.cmp_hdl,  // 设置静音配置OMX_IndexConfigAudioMute, &mute);
​OSCL_TRACE("asrc:%p", asrc);               // 跟踪日志return ret;                                // 返回结果
}
​
/*** _setup_aenc - 为音频编码器组件设置参数** @aenc: audio_enc_t** 成功返回0,否则返回错误码。*/
// 设计模式分析: 策略模式,支持多种音频编码算法的参数配置
// 性能分析: 按编码类型分支处理,避免不必要的参数设置
int _setup_aenc(audio_enc_t *aenc)             // 设置音频编码器函数
{OMX_AUDIO_PARAM_ADPCMTYPE adpcm_type;      // ADPCM参数结构OMX_AUDIO_PARAM_PCMMODETYPE pcm_type;      // PCM参数结构OMX_AUDIO_PARAM_AACPROFILETYPE aac_type;   // AAC参数结构OMX_AUDIO_PARAM_G729TYPE g729_type;        // G729参数结构OMX_AUDIO_PARAM_G726TYPE g726_type;        // G726参数结构OMX_PRIORITYMGMTTYPE priority;             // 优先级管理结构int ret = 0;OMX_U32 channels;                          // 声道数OMX_U32 bit_per_sample;                    // 采样位宽OMX_U32 sample_rate;                       // 采样率OMX_U32 port_index;                        // 端口索引OMX_AUDIO_PARAM_CHANNEL_MAP channel_map_para;  // 声道映射参数
​oscl_param_check(aenc != NULL, 0, NULL);   // 参数检查oscl_param_check(aenc->asrc != NULL, 0, NULL);  // 音频源检查oscl_param_check(aenc->aenc_info.aout != NULL, 0, NULL);  // 输出端口检查oscl_param_check(aenc->aenc_info.al_comp.cmp_hdl != NULL, 0, NULL);  // 组件句柄检查channels = aenc->n_channel;                // 获取声道数bit_per_sample = aenc->asrc->bit_per_sample;  // 获取采样位宽sample_rate = aenc->asrc->sample_rate;     // 获取采样率port_index = aenc->aenc_info.aout->index;  // 获取端口索引
​switch (aenc->coding_type) {               // 根据编码类型分支处理case AUDIO_ENCODER_ADPCM:                  // ADPCM编码memset(&adpcm_type, 0, sizeof(OMX_AUDIO_PARAM_ADPCMTYPE));  // 清空结构adpcm_type.nChannels = channels;       // 设置声道数adpcm_type.nBitsPerSample = bit_per_sample;  // 设置采样位宽adpcm_type.nSampleRate = sample_rate;  // 设置采样率adpcm_type.nPortIndex = port_index;    // 设置端口索引ret = OMX_SetParameter(aenc->aenc_info.al_comp.cmp_hdl,  // 设置ADPCM参数OMX_IndexParamAudioAdpcm,&adpcm_type);break;
​case AUDIO_ENCODER_AAC:                    // AAC编码memset(&aac_type, 0, sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE));  // 清空结构aac_type.nChannels = channels;         // 设置声道数aac_type.nSampleRate = sample_rate;    // 设置采样率aac_type.nBitRate = 128000;            // 设置比特率128kbpsaac_type.eAACStreamFormat = OMX_AUDIO_AACStreamFormatRAW;  // 设置流格式为RAWaac_type.nPortIndex = port_index;      // 设置端口索引OSCL_LOGI("aac setting: channels %d, samplerate:%d, bitrate:%d",  // 记录配置aac_type.nChannels, aac_type.nSampleRate, aac_type.nBitRate);ret = OMX_SetParameter(aenc->aenc_info.al_comp.cmp_hdl,  // 设置AAC参数OMX_IndexParamAudioAac,&aac_type);break;case AUDIO_ENCODER_AAC_MP4ADTS:            // AAC MP4 ADTS格式memset(&aac_type, 0, sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE));  // 清空结构aac_type.nChannels = channels;         // 设置声道数aac_type.nSampleRate = sample_rate;    // 设置采样率aac_type.nBitRate = 128000;            // 设置比特率128kbpsaac_type.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;  // 设置流格式为MP4 ADTSaac_type.nPortIndex = port_index;      // 设置端口索引OSCL_LOGI("aac setting: channels %d, samplerate:%d, bitrate:%d",  // 记录配置aac_type.nChannels, aac_type.nSampleRate, aac_type.nBitRate);ret = OMX_SetParameter(aenc->aenc_info.al_comp.cmp_hdl,  // 设置AAC参数OMX_IndexParamAudioAac,&aac_type);break;case AUDIO_ENCODER_G729:                   // G729编码memset(&g729_type, 0, sizeof(OMX_AUDIO_PARAM_G729TYPE));  // 清空结构g729_type.nChannels = channels;        // 设置声道数g729_type.nPortIndex = port_index;     // 设置端口索引ret = OMX_SetParameter(aenc->aenc_info.al_comp.cmp_hdl,  // 设置G729参数OMX_IndexParamAudioG729,&g729_type);break;case AUDIO_ENCODER_ADPCM_G726:             // G726 ADPCM编码memset(&g726_type, 0, sizeof(OMX_AUDIO_PARAM_G726TYPE));  // 清空结构g726_type.nChannels = channels;        // 设置声道数g726_type.nPortIndex = port_index;     // 设置端口索引switch (aenc->private_para.g726_mode) {  // 根据G726模式分支case AUDIO_G726MODE_16K:               // 16k模式g726_type.eG726Mode = OMX_AUDIO_G726Mode16;break;case AUDIO_G726MODE_24K:               // 24k模式g726_type.eG726Mode = OMX_AUDIO_G726Mode24;break;case AUDIO_G726MODE_M32K:              // 32k ADPCM模式case AUDIO_G726MODE_32K:               // 32k模式g726_type.eG726Mode = OMX_AUDIO_G726Mode32;break;case AUDIO_G726MODE_M40K:              // 40k ADPCM模式case AUDIO_G726MODE_40K:               // 40k模式g726_type.eG726Mode = OMX_AUDIO_G726Mode40;break;default:                               // 默认32k模式g726_type.eG726Mode = OMX_AUDIO_G726Mode32;break;}ret = OMX_SetParameter(aenc->aenc_info.al_comp.cmp_hdl,  // 设置G726参数OMX_IndexParamAudioG726,&g726_type);break;case AUDIO_ENCODER_ADPCM_G726LE:           // G726小端ADPCM编码memset(&g726_type, 0, sizeof(OMX_AUDIO_PARAM_G726TYPE));  // 清空结构g726_type.nChannels = channels;        // 设置声道数g726_type.nPortIndex = port_index;     // 设置端口索引switch (aenc->private_para.g726_mode) {  // 根据G726模式分支case AUDIO_G726MODE_16K:               // 16k模式g726_type.eG726Mode = OMX_AUDIO_G726Mode16;break;case AUDIO_G726MODE_24K:               // 24k模式g726_type.eG726Mode = OMX_AUDIO_G726Mode24;break;case AUDIO_G726MODE_M32K:              // 32k ADPCM模式case AUDIO_G726MODE_32K:               // 32k模式g726_type.eG726Mode = OMX_AUDIO_G726Mode32;break;case AUDIO_G726MODE_M40K:              // 40k ADPCM模式case AUDIO_G726MODE_40K:               // 40k模式g726_type.eG726Mode = OMX_AUDIO_G726Mode40;break;default:                               // 默认32k模式g726_type.eG726Mode = OMX_AUDIO_G726Mode32;break;}ret = OMX_SetParameter(aenc->aenc_info.al_comp.cmp_hdl,  // 设置G726小端参数OMX_IndexParamAudioG726le,&g726_type);break;
​case AUDIO_ENCODER_PCM:                    // PCM编码case AUDIO_ENCODER_PCM_ALAW:               // PCM A律编码case AUDIO_ENCODER_PCM_MULAW:              // PCM μ律编码default:                                   // 默认编码memset(&pcm_type, 0, sizeof(pcm_type));  // 清空PCM参数结构pcm_type.nChannels = channels;        // 设置声道数pcm_type.nBitPerSample = bit_per_sample;  // 设置采样位宽pcm_type.nSamplingRate = sample_rate;  // 设置采样率pcm_type.nPortIndex = port_index;     // 设置端口索引if (aenc->coding_type == AUDIO_ENCODER_PCM_ALAW)  // A律编码pcm_type.ePCMMode = OMX_AUDIO_PCMModeALaw;else if (aenc->coding_type == AUDIO_ENCODER_PCM_MULAW)  // μ律编码pcm_type.ePCMMode = OMX_AUDIO_PCMModeMULaw;ret = OMX_SetParameter(aenc->aenc_info.al_comp.cmp_hdl,  // 设置PCM参数OMX_IndexParamAudioPcm,&pcm_type);break;}
​if (aenc->prio) {                          // 如果设置了优先级priority.nVersion.nVersion = OMX_VERSION;  // 设置版本priority.nGroupPriority = aenc->prio;  // 设置组优先级OMX_SetParameter(aenc->aenc_info.al_comp.cmp_hdl,  // 设置编码器组件优先级OMX_IndexParamPriorityMgmt, &priority);OMX_SetParameter(aenc->aenc_splt.al_comp.cmp_hdl,  // 设置编码器分流器优先级OMX_IndexParamPriorityMgmt, &priority);}if (aenc->private_para.en_in_data_len) {   // 如果设置了输入数据长度OMX_SetParameter(aenc->aenc_info.al_comp.cmp_hdl,  // 设置输入数据长度参数omx_index_audio_set_en_in_datalen,&aenc->private_para.en_in_data_len);}
​channel_map_para.channel_map = aenc->channel_map;  // 设置声道映射channel_map_para.src_channel_num = aenc->asrc->channels;  // 设置源声道数OMX_SetParameter(aenc->aenc_info.al_comp.cmp_hdl,  // 设置声道选择参数omx_index_audio_select_channels, &channel_map_para);
​OSCL_TRACE("aenc:%p, %x", aenc, channel_map_para.channel_map);  // 跟踪日志return ret;                                // 返回结果
}
​
// 设计模式分析: 模板方法模式,定义端口准备的固定流程
// 性能分析: 批量配置端口参数,优化OpenMAX API调用
static int _asplt_prepare(audio_splt_t *splt_info, OMX_PARAM_PORTDEFINITIONTYPE *port)  // 准备音频分流器函数
{int i = 0;int ret = 0;port_info_t *al_port;                      // 端口信息指针
​OSCL_TRACE("==");for (i = 0; i < splt_info->al_comp.num_port; i++) {  // 遍历所有端口al_port = &splt_info->al_comp.port_info[i];  // 获取端口信息al_port->domain = port->eDomain;        // 设置端口域OSCL_LOGI("nbuffer(%d) edir(%d) domain(%d) size(%d)!",  // 记录端口信息al_port->nbuffer,al_port->edir,al_port->domain,al_port->buf_size);if (al_port->edir == OMX_DirInput) {    // 如果是输入端口port->eDir = OMX_DirInput;        // 设置方向为输入port->nPortIndex = i;             // 设置端口索引ret = OMX_SetParameter(splt_info->al_comp.cmp_hdl,  // 设置端口定义OMX_IndexParamPortDefinition, port);OSCL_LOGI("%d buf:%d", i, port->nBufferCountActual);  // 记录缓冲区数量break;}}for (i = 0; i < splt_info->al_comp.num_port; i++) {  // 再次遍历所有端口al_port = &splt_info->al_comp.port_info[i];  // 获取端口信息al_port->domain = port->eDomain;        // 设置端口域port->nPortIndex = i;                   // 设置端口索引ret = OMX_GetParameter(splt_info->al_comp.cmp_hdl,  // 获取端口定义OMX_IndexParamPortDefinition, port);al_port->nbuffer = port->nBufferCountActual;  // 设置缓冲区数量al_port->buf_size = port->nBufferSize;   // 设置缓冲区大小if (al_port->edir == OMX_DirOutput)      // 如果是输出端口al_port->is_shared_buffer = 1;    // 标记为共享缓冲区}OSCL_TRACE("==");return ret;                                // 返回结果
}
​
// 设计模式分析: 工厂方法模式,从分流器获取可用输出端口
// 性能分析: 位图管理端口分配,O(n)查找但n很小
static port_info_t *_splt_get_outport(audio_splt_t *vsplt_info)  // 获取分流器输出端口函数
{port_info_t *port = NULL;                  // 端口指针port_info_t *splt_port = NULL;             // 分流器端口指针int nports;                                // 端口数量int index;                                 // 索引
​OSCL_TRACE("==");oscl_param_check(vsplt_info != NULL, NULL, NULL);  // 参数检查splt_port = vsplt_info->al_comp.port_info;  // 获取端口信息数组nports = vsplt_info->al_comp.num_port;     // 获取端口数量for (index = 0; index < nports; index++) {  // 遍历所有端口if (splt_port[index].edir == OMX_DirInput)  // 跳过输入端口continue;if ((vsplt_info->outport_map & (1 << index)) == 0) {  // 查找未使用的输出端口vsplt_info->outport_map |= (1 << index);  // 标记端口为已使用port = &splt_port[index];           // 获取端口指针break;}}OSCL_TRACE("=index:%d, port:%p=", index, port);  // 跟踪日志return port;                               // 返回端口指针
}
​
// 设计模式分析: 资源管理模式,释放分流器输出端口
// 性能分析: 位图操作O(1)复杂度,高效端口管理
static int _splt_put_outport(audio_splt_t *vsplt_info, port_info_t *port)  // 释放分流器输出端口函数
{port_info_t *splt_port = NULL;             // 分流器端口指针int ret = -1;                              // 返回值
​OSCL_TRACE("==port:%p", port);             // 跟踪日志oscl_param_check(vsplt_info != NULL, -1, NULL);  // 参数检查oscl_param_check(vsplt_info->al_comp.port_info != NULL, -1, NULL);  // 端口信息检查oscl_param_check(port != NULL, -1, NULL);  // 端口指针检查
​splt_port = vsplt_info->al_comp.port_info;  // 获取端口信息数组if (port == &splt_port[port->index]) {     // 验证端口有效性if ((vsplt_info->outport_map & (1 << port->index)) == 0)  // 检查端口是否已释放OSCL_LOGE("free a port already freed");  // 记录错误else {vsplt_info->outport_map &= ~(1 << port->index);  // 清除端口使用标记ret = 0;                         // 设置成功返回值}}OSCL_TRACE("==");return ret;                                // 返回结果
}
​
​
// 设计模式分析: 命令模式,封装端口启用操作为独立命令
// 性能分析: 直接调用OpenMAX命令,轻量级操作
int _splt_enable_port(audio_splt_t *vsplt_info, port_info_t *port)  // 启用分流器端口函数
{int ret;                              // 返回值
​OSCL_TRACE("==");                     // 跟踪日志oscl_param_check(vsplt_info != NULL, -1, NULL);  // 参数检查:分流器信息oscl_param_check(vsplt_info->al_comp.cmp_hdl != NULL, -1, NULL);  // 参数检查:组件句柄oscl_param_check(port != NULL, -1, NULL);  // 参数检查:端口信息oscl_param_check(port == &vsplt_info->al_comp.port_info[port->index], -1, NULL);  // 参数检查:端口有效性
​ret = component_sendcom(&vsplt_info->al_comp, OMX_CommandPortEnable,  // 发送端口启用命令port->index, NULL);OSCL_TRACE("==");                     // 跟踪日志return ret;                           // 返回操作结果
}
​
// 设计模式分析: 命令模式,封装端口禁用操作为独立命令
// 性能分析: 直接调用OpenMAX命令,轻量级操作
int _splt_disable_port(audio_splt_t *vsplt_info, port_info_t *port)  // 禁用分流器端口函数
{int ret;                              // 返回值
​OSCL_TRACE("==");                     // 跟踪日志oscl_param_check(vsplt_info != NULL, -1, NULL);  // 参数检查:分流器信息oscl_param_check(vsplt_info->al_comp.cmp_hdl != NULL, -1, NULL);  // 参数检查:组件句柄oscl_param_check(port != NULL, -1, NULL);  // 参数检查:端口信息oscl_param_check(port == &vsplt_info->al_comp.port_info[port->index], -1, NULL);  // 参数检查:端口有效性
​ret = component_sendcom(&vsplt_info->al_comp, OMX_CommandPortDisable,  // 发送端口禁用命令port->index, NULL);OSCL_TRACE("==");                     // 跟踪日志return ret;                           // 返回操作结果
}
​
// 设计模式分析: 组合模式,批量处理多个端口的禁用操作
// 性能分析: 遍历所有映射端口,适合批量操作场景
int _splt_disable_mapped_ports(audio_splt_t *vsplt_info)  // 禁用所有已映射端口函数
{int i;                                // 循环索引
​OSCL_TRACE("==");                     // 跟踪日志oscl_param_check(vsplt_info != NULL, -1, NULL);  // 参数检查:分流器信息oscl_param_check(vsplt_info->al_comp.cmp_hdl != NULL, -1, NULL);  // 参数检查:组件句柄
​for (i = 0; i < vsplt_info->al_comp.num_port; i++) {  // 遍历所有端口if ((vsplt_info->outport_map & (1<<i)) != 0) {  // 检查端口是否已映射component_sendcom(&vsplt_info->al_comp,  // 发送端口禁用命令OMX_CommandPortDisable,i, NULL);}}
​OSCL_TRACE("==");                     // 跟踪日志return 0;                             // 返回成功
}
​
// 设计模式分析: 状态模式,检查分流器是否处于忙碌状态
// 性能分析: 简单位图检查,O(1)时间复杂度
static int _is_splt_busy(audio_splt_t *vsplt_info)  // 检查分流器是否忙碌函数
{return (vsplt_info->outport_map != 0);  // 返回端口映射是否非零(有端口在使用)
}
​
// 设计模式分析: 工厂方法模式,根据类型获取相应端口
// 性能分析: 状态检查和端口分配,确保操作的正确时序
port_info_t *_audio_stream_getport(astream_handle_t *astream, as_port_type_e type)  // 获取音频流端口函数
{port_info_t *port = NULL;              // 端口指针
​oscl_param_check(astream != NULL, NULL, NULL);  // 参数检查:音频流句柄if (type == AS_PORT_CODEC && astream->aenc) {  // 请求编码器端口且编码器存在if (astream->state == AS_STATE_ENCODE)  // 检查是否处于编码状态port = _splt_get_outport(&astream->aenc->aenc_splt);  // 获取编码器输出端口elseOSCL_LOGE("err! get encoded port while encode not start!");  // 记录状态错误if (port)                            // 如果成功获取端口astream->encport_map |= (1 << port->index);  // 更新编码端口映射位图}if (type == AS_PORT_PCM && astream->asrc) {  // 请求PCM端口且音频源存在if (astream->state == AS_STATE_ENCODE  // 检查是否处于编码状态|| astream->state == AS_STATE_START)  // 或启动状态port = _splt_get_outport(&astream->asrc->asrc_splt);  // 获取音频源输出端口elseOSCL_LOGE("err! get pcm port while audio src not start!");  // 记录状态错误if (port)                            // 如果成功获取端口astream->srcport_map |= (1 << port->index);  // 更新源端口映射位图}return port;                           // 返回端口指针
}
​
// 设计模式分析: 资源管理模式,释放音频流端口资源
// 性能分析: 端口映射位图操作,O(1)时间复杂度
int _audio_stream_putport(astream_handle_t *astream, port_info_t *port)  // 释放音频流端口函数
{int ret = -1;                          // 返回值
​oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄oscl_param_check(port != NULL, -1, NULL);  // 参数检查:端口信息
​if (astream->aenc && port->comp_info == &astream->aenc->aenc_splt.al_comp) {  // 编码器端口OSCL_LOGI("audio stream put port:%p (%d), map:%x %x",  // 记录端口释放日志port, port->index, astream->srcport_map, astream->encport_map);ret = _splt_put_outport(&astream->aenc->aenc_splt, port);  // 释放编码器输出端口astream->encport_map &= ~(1 << port->index);  // 清除编码端口映射位}if (astream->asrc && port->comp_info == &astream->asrc->asrc_splt.al_comp) {  // 音频源端口OSCL_LOGI("audio stream put port:%p (%d), map:%x %x",  // 记录端口释放日志port, port->index, astream->srcport_map, astream->encport_map);ret = _splt_put_outport(&astream->asrc->asrc_splt, port);  // 释放音频源输出端口astream->srcport_map &= ~(1 << port->index);  // 清除源端口映射位}
​return ret;                            // 返回操作结果
}
​
// 设计模式分析: 状态模式,管理音频源停止流程
// 性能分析: 引用计数管理,确保资源正确释放
int _asrc_stop(audio_source_t *asrc)  // 停止音频源函数
{int ret = 0;                          // 返回值
​OSCL_LOGI("asrc:%p(%s), count:%d", asrc ? asrc : NULL,  // 记录音频源状态日志asrc ? (asrc->dev_name) : "NULL", asrc ? asrc->started_cnt : 0);if (asrc == NULL) {                   // 检查音频源是否存在OSCL_LOGI("astream asrc is not created!");  // 记录音频源未创建goto EXIT;                        // 跳转到退出点}asrc->started_cnt--;                  // 减少启动计数if (asrc->started_cnt > 0) {          // 如果还有其他使用者OSCL_LOGI("astream start count:%d!", asrc->started_cnt);  // 记录当前计数goto EXIT;                        // 跳转到退出点}if (asrc->started_cnt < 0) {          // 如果启动计数异常(过度停止)OSCL_LOGE("state err! This may caused by err started or err stopped");  // 记录状态错误asrc->started_cnt = 0;             // 重置启动计数}
​/* 检查音频源分流器是否忙碌 */if (_is_splt_busy(&asrc->asrc_splt)) {  // 检查分流器端口使用情况OSCL_LOGE("ERROR: asrc splt is busy: %x!", asrc->asrc_splt.outport_map);  // 记录忙碌错误_splt_disable_mapped_ports(&asrc->asrc_splt);  // 强制禁用所有映射端口asrc->asrc_splt.outport_map = 0;   // 重置端口映射}
​component_setstate(&asrc->asrc_splt.al_comp, OMX_StateIdle);  // 设置分流器组件为空闲状态component_setstate(&asrc->asrc_info.al_comp, OMX_StateIdle);  // 设置音频源组件为空闲状态untunnel_unset_ports(asrc->asrc_info.aout, asrc->asrc_splt.in);  // 断开端口连接
​component_setstate(&asrc->asrc_info.al_comp, OMX_StateLoaded);  // 设置音频源组件为加载状态component_setstate(&asrc->asrc_splt.al_comp, OMX_StateLoaded);  // 设置分流器组件为加载状态
​component_deinit(&asrc->asrc_info.al_comp);  // 反初始化音频源组件component_deinit(&asrc->asrc_splt.al_comp);  // 反初始化分流器组件
​
EXIT:OSCL_LOGI("asrc:%p(%s), count:%d", asrc ? asrc : NULL,  // 记录音频源最终状态asrc ? (asrc->dev_name) : "NULL", asrc ? asrc->started_cnt : 0);return ret;                            // 返回操作结果
}
​
​
/*** _asrc_start - 启动音频设备** @audio_stream_t: 音频流信息** 成功返回0,否则返回错误码*/
// 设计模式分析: 模板方法模式,定义音频源启动的标准流程
// 性能分析: 顺序执行组件初始化和状态转换,确保正确启动顺序
int _asrc_start(audio_source_t *asrc)  // 启动音频源函数
{OMX_PARAM_PORTDEFINITIONTYPE omx_port;  // OpenMAX端口定义参数int ret = 0;                          // 返回值int index = 0;                        // 端口索引OSCL_TRACE("hdl:%p", asrc);           // 跟踪日志
​OSCL_LOGI("asrc:%p(%s), count:%d", asrc ? asrc : NULL,  // 记录音频源状态asrc ? (asrc->dev_name) : "NULL", asrc ? asrc->started_cnt : 0);if (asrc->started_cnt > 0) {          // 如果音频源已启动OSCL_TRACE("astream already started");  // 记录已启动asrc->started_cnt++;              // 增加启动计数goto EXIT;                        // 跳转到退出点}
​asrc->started_cnt = 1;                // 设置启动计数为1/* 初始化音频源组件 */ret = component_init(&asrc->asrc_info.al_comp, "OMX.LB.SOURCE.AREC",  // 初始化音频源组件&untunnel_common_callbacks);oscl_param_check_exit(ret == 0, ret, NULL);  // 参数检查并退出index = component_get_port_index(&asrc->asrc_info.al_comp, OMX_DirOutput,  // 获取输出端口索引OMX_PortDomainAudio);oscl_param_check_exit(index >= 0, -1, NULL);  // 参数检查并退出asrc->asrc_info.aout = &asrc->asrc_info.al_comp.port_info[index];  // 设置输出端口
​/* 初始化音频源分流器组件 */ret = component_init(&asrc->asrc_splt.al_comp, "OMX.LB.SPLITTER.BASE",  // 初始化分流器组件&untunnel_common_callbacks);oscl_param_check_exit(ret == 0, ret, NULL);  // 参数检查并退出asrc->asrc_splt.in = &asrc->asrc_splt.al_comp.port_info[0];  // 设置输入端口
​/* 设置音频组件参数 */ret = _setup_asrc(asrc);              // 设置音频源参数oscl_param_check_exit((ret == 0), ret, NULL);  // 参数检查并退出
​/* 设置分流器端口定义 */omx_port.nPortIndex = asrc->asrc_info.aout->index;  // 设置端口索引omx_port.nVersion.nVersion = OMX_VERSION;  // 设置版本ret = OMX_GetParameter(asrc->asrc_info.al_comp.cmp_hdl,  // 获取端口定义参数OMX_IndexParamPortDefinition, &omx_port);oscl_param_check_exit(ret == OMX_ErrorNone, ret, NULL);  // 参数检查并退出_asplt_prepare(&asrc->asrc_splt, &omx_port);  // 准备分流器端口
​/* 连接音频源和音频源分流器 */ret = untunnel_setup_ports(asrc->asrc_info.aout,  // 设置端口连接asrc->asrc_splt.in);oscl_param_check_exit(ret == OMX_ErrorNone, ret, NULL);  // 参数检查并退出
​/* 将音频组件转换为空闲状态 */component_setstate(&asrc->asrc_splt.al_comp, OMX_StateIdle);  // 设置分流器为空闲状态component_setstate(&asrc->asrc_info.al_comp, OMX_StateIdle);  // 设置音频源为空闲状态
​/* 将录制器组件转换为执行状态 */ret = component_setstate(&asrc->asrc_splt.al_comp, OMX_StateExecuting);  // 设置分流器为执行状态oscl_param_check_exit(ret == 0, -1, NULL);  // 参数检查并退出ret = component_setstate(&asrc->asrc_info.al_comp, OMX_StateExecuting);  // 设置音频源为执行状态oscl_param_check_exit(ret == 0, -1, NULL);  // 参数检查并退出
​
EXIT:if (ret != 0)                         // 如果启动失败_asrc_stop(asrc);                 // 停止音频源(清理资源)OSCL_LOGI("asrc:%p(%s), count:%d", asrc ? asrc : NULL,  // 记录最终状态asrc ? (asrc->dev_name) : "NULL", asrc ? asrc->started_cnt : 0);OSCL_TRACE("hdl:%p ret:%d", asrc, ret);  // 跟踪日志return ret;                            // 返回操作结果
}
​
​
/*** astream_start - 启动音频流** @hdl: 音频流句柄** 成功返回0,否则返回错误码*/
// 设计模式分析: 外观模式,提供简化的音频流启动接口
// 性能分析: 状态验证和委托调用,确保操作的正确性
int _astream_start(astream_handle_t *astream)  // 启动音频流函数
{int ret = 0;                          // 返回值
​OSCL_TRACE("hdl:%p", astream);        // 跟踪日志oscl_param_check((astream->state == AS_STATE_INIT), 0, NULL);  // 参数检查:必须为初始化状态
​ret = _asrc_start(astream->asrc);     // 启动音频源if (ret == 0)                         // 如果启动成功astream->state = AS_STATE_START;  // 更新音频流状态为启动状态
​OSCL_TRACE("astream:%p ret:%d", astream, ret);  // 跟踪日志return ret;                            // 返回操作结果
}
​
​
​
/*** _astream_stop - 停止音频源** @hdl: 音频流句柄** 成功返回0,否则返回错误码*/
// 设计模式分析: 外观模式,提供简化的音频流停止接口
// 性能分析: 状态验证和委托调用,确保操作的正确性
int _astream_stop(astream_handle_t *astream)  // 停止音频流函数
{int ret = 0;                          // 返回值
​OSCL_TRACE("hdl:%p", astream);        // 跟踪日志oscl_param_check((astream->state == AS_STATE_START), -1, NULL);  // 参数检查:必须为启动状态ret = _asrc_stop(astream->asrc);      // 停止音频源astream->state = AS_STATE_INIT;       // 更新音频流状态为初始化状态OSCL_TRACE("hdl:%p asrc:%p, aenc:%p", astream, astream->asrc, astream->aenc);  // 跟踪日志return ret;                           // 返回操作结果
}
​
/*** _aenc_start - 启动音频编码器** @aenc: 音频编码信息** 成功返回0,否则返回错误码*/
// 设计模式分析: 模板方法模式,定义编码器启动的标准流程
// 性能分析: 顺序执行组件初始化和状态转换,确保正确启动顺序
int _aenc_start(audio_enc_t *aenc)  // 启动音频编码器函数
{OMX_PARAM_PORTDEFINITIONTYPE omx_port;  // OpenMAX端口定义参数int index;                           // 端口索引int ret = 0;                          // 返回值OSCL_TRACE("hdl:%p", aenc);           // 跟踪日志
​log_aenc_state(aenc);                 // 记录编码器状态/* 初始化音频编码组件 */ret = component_init(&aenc->aenc_info.al_comp, "OMX.LB.ENCODER.AUDIO",  // 初始化编码器组件&untunnel_common_callbacks);oscl_param_check_exit(ret == 0, ret, NULL);  // 参数检查并退出index = component_get_port_index(&aenc->aenc_info.al_comp, OMX_DirInput,  // 获取输入端口索引OMX_PortDomainAudio);oscl_param_check_exit(index >= 0, -1, NULL);  // 参数检查并退出aenc->aenc_info.ain = &aenc->aenc_info.al_comp.port_info[index];  // 设置输入端口index = component_get_port_index(&aenc->aenc_info.al_comp, OMX_DirOutput,  // 获取输出端口索引OMX_PortDomainAudio);oscl_param_check_exit(index >= 0, -1, NULL);  // 参数检查并退出aenc->aenc_info.aout = &aenc->aenc_info.al_comp.port_info[index];  // 设置输出端口OSCL_LOGE("aenc buffer number:%d", aenc->aenc_info.aout->nbuffer);  // 记录缓冲区数量
​/* 初始化音频编码器分流器组件 */ret = component_init(&aenc->aenc_splt.al_comp, "OMX.LB.SPLITTER.BASE",  // 初始化编码器分流器&untunnel_common_callbacks);oscl_param_check_exit(ret == 0, ret, NULL);  // 参数检查并退出aenc->aenc_splt.in = &aenc->aenc_splt.al_comp.port_info[0];  // 设置输入端口
​/* 设置音频组件参数 */ret = _setup_aenc(aenc);              // 设置编码器参数oscl_param_check_exit((ret == 0), ret, NULL);  // 参数检查并退出
​/* 设置分流器端口定义 */omx_port.nPortIndex = aenc->aenc_info.aout->index;  // 设置端口索引omx_port.nVersion.nVersion = OMX_VERSION;  // 设置版本ret = OMX_GetParameter(aenc->aenc_info.al_comp.cmp_hdl,  // 获取端口定义参数OMX_IndexParamPortDefinition, &omx_port);oscl_param_check_exit(ret == OMX_ErrorNone, ret, NULL);  // 参数检查并退出_asplt_prepare(&aenc->aenc_splt, &omx_port);  // 准备分流器端口
​/* 连接音频源和音频源分流器 */ret = untunnel_setup_ports(aenc->aenc_srcport,  // 连接音频源端口到编码器输入aenc->aenc_info.ain);oscl_param_check_exit(ret == OMX_ErrorNone, ret, NULL);  // 参数检查并退出ret = untunnel_setup_ports(aenc->aenc_info.aout,  // 连接编码器输出到分流器输入aenc->aenc_splt.in);oscl_param_check_exit(ret == OMX_ErrorNone, ret, NULL);  // 参数检查并退出
​/* 将音频组件转换为空闲状态 */component_setstate(&aenc->aenc_splt.al_comp, OMX_StateIdle);  // 设置分流器为空闲状态component_setstate(&aenc->aenc_info.al_comp, OMX_StateIdle);  // 设置编码器为空闲状态
​/* 将录制器组件转换为执行状态 */component_setstate(&aenc->aenc_splt.al_comp, OMX_StateExecuting);  // 设置分流器为执行状态component_setstate(&aenc->aenc_info.al_comp, OMX_StateExecuting);  // 设置编码器为执行状态_splt_enable_port(&aenc->asrc->asrc_splt, aenc->aenc_srcport);  // 启用音频源分流器端口
​
EXIT:log_aenc_state(aenc);                 // 记录编码器最终状态OSCL_TRACE("hdl:%p ret:%d", aenc, ret);  // 跟踪日志return ret;                            // 返回操作结果
}
​
// 设计模式分析: 状态模式,管理编码器停止流程
// 性能分析: 引用计数管理,确保资源正确释放
int _aenc_stop(audio_enc_t *aenc)  // 停止音频编码器函数
{if (aenc == NULL) {                   // 检查编码器是否存在OSCL_LOGI("astream aenc is not created!");  // 记录编码器未创建goto EXIT;                        // 跳转到退出点}log_aenc_state(aenc);                 // 记录编码器状态if (aenc->started_cnt <= 0) {         // 如果编码器未启动或已停止if (aenc->aenc_info.al_comp.cmp_hdl || aenc->aenc_splt.al_comp.cmp_hdl) {  // 检查组件句柄OSCL_LOGE("err! aenc stopped but cmphandl not freed:%p:%p!",  // 记录资源未释放错误aenc->aenc_info.al_comp.cmp_hdl,aenc->aenc_splt.al_comp.cmp_hdl);} else {OSCL_LOGI("aenc double stopped!");  // 记录重复停止aenc->started_cnt = 0;         // 重置启动计数goto EXIT;                     // 跳转到退出点}}aenc->started_cnt--;                  // 减少启动计数if (aenc->started_cnt > 0) {          // 如果还有其他使用者OSCL_LOGI("_aenc_stop %p count:%x!", aenc, aenc->started_cnt);  // 记录当前计数goto EXIT;                        // 跳转到退出点}/* 检查音频编码器分流器是否忙碌 */if (_is_splt_busy(&aenc->aenc_splt)) {  // 检查分流器端口使用情况OSCL_LOGI("ERR,aenc splt is busy: %x!", aenc->aenc_splt.outport_map);  // 记录忙碌错误_splt_disable_mapped_ports(&aenc->aenc_splt);  // 强制禁用所有映射端口aenc->aenc_splt.outport_map = 0;   // 重置端口映射}
​/* 1. 禁用源端口* 2. 将编码器组件和编码器分流器组件转换为空闲状态* 3. 断开音频源分流器和音频编码器的连接。断开音频编码器和音频编码器分流器的连接。* 4. 释放编码器源端口。* 5. 将编码器组件和编码器分流器组件转换为加载状态*/if (aenc->asrc)                       // 如果音频源存在_splt_disable_port(&aenc->asrc->asrc_splt, aenc->aenc_srcport);  // 禁用音频源分流器端口
​component_setstate(&aenc->aenc_info.al_comp, OMX_StateIdle);  // 设置编码器为空闲状态component_setstate(&aenc->aenc_splt.al_comp, OMX_StateIdle);  // 设置分流器为空闲状态
​untunnel_unset_ports(aenc->aenc_srcport, aenc->aenc_info.ain);  // 断开音频源到编码器的连接untunnel_unset_ports(aenc->aenc_info.aout, aenc->aenc_splt.in);  // 断开编码器到分流器的连接
​if (aenc->asrc) {                     // 如果音频源存在_splt_put_outport(&aenc->asrc->asrc_splt, aenc->aenc_srcport);  // 释放音频源端口aenc->aenc_srcport = NULL;        // 清空端口指针}
​component_setstate(&aenc->aenc_info.al_comp, OMX_StateLoaded);  // 设置编码器为加载状态component_setstate(&aenc->aenc_splt.al_comp, OMX_StateLoaded);  // 设置分流器为加载状态
​component_deinit(&aenc->aenc_splt.al_comp);  // 反初始化分流器组件component_deinit(&aenc->aenc_info.al_comp);  // 反初始化编码器组件log_aenc_state(aenc);                 // 记录编码器最终状态
EXIT:log_aenc_state(aenc);                 // 记录编码器状态return 0;                             // 返回成功
}
/*** _astream_stop_enc - 停止音频编码器** @hdl: 音频流句柄** 成功返回0,否则返回错误码*/
// 设计模式分析: 外观模式,提供简化的编码器停止接口
// 性能分析: 资源清理和状态管理,确保编码器正确停止
int _astream_stop_enc(astream_handle_t *astream)  // 停止音频编码器函数
{int ret = 0;                          // 返回值audio_enc_t *aenc;                    // 编码器指针
​OSCL_TRACE("hdl:%p, %d", astream, astream->state);  // 跟踪日志log_astream_state(astream);           // 记录音频流状态
​aenc = astream->aenc;                 // 获取编码器指针if (aenc == NULL) {                   // 检查编码器是否存在OSCL_LOGI("astream aenc is not created(%p %p)!", aenc, astream->asrc);  // 记录编码器未创建ret = -1;                         // 设置错误返回值goto EXIT;                        // 跳转到退出点}
​if (astream->enc_outport) {           // 如果编码输出端口未释放OSCL_LOGE("Err, astream->enc_outport not freed!");  // 记录端口未释放错误_splt_disable_port(&astream->aenc->aenc_splt, astream->enc_outport);  // 禁用端口_audio_stream_putport(astream, astream->enc_outport);  // 释放端口astream->enc_outport = NULL;      // 清空端口指针}_aenc_stop(astream->aenc);            // 停止编码器if (astream->state == AS_STATE_ENCODE)  // 如果当前处于编码状态astream->state = AS_STATE_START;  // 更新状态为启动状态if (astream->aenc->ref > 1) {         // 如果编码器有多个引用aenc = __get_aenc_by_src(astream->aenc->asrc);  // 获取新的编码器if (aenc != NULL) {               // 如果成功获取新编码器__put_enc(astream->aenc);     // 释放原编码器log_astream_state(astream);   // 记录音频流状态astream->aenc = aenc;         // 更新编码器指针}}
EXIT:
​OSCL_TRACE("hdl:%p state:%d, encmap:%x",  // 跟踪日志astream, astream->state, aenc->aenc_splt.outport_map);log_astream_state(astream);           // 记录音频流最终状态return ret;                           // 返回操作结果
}
​
/*** _astream_start_enc - 启动音频编码** @hdl: 音频流句柄** 成功返回0,否则返回错误码*/
// 设计模式分析: 享元模式,重用正在执行的编码器实例
// 性能分析: 编码器实例共享,避免重复初始化和资源浪费
int _astream_start_enc(astream_handle_t *astream)  // 启动音频编码函数
{int ret = 0;                          // 返回值audio_enc_t *excuting_encoder;        // 执行中编码器指针
​OSCL_TRACE("hdl:%p", astream);        // 跟踪日志log_astream_state(astream);           // 记录音频流状态oscl_param_check((astream->state == AS_STATE_START), -1, NULL);  // 参数检查:必须为启动状态if (astream->aenc->started_cnt >= 1) {  // 如果编码器已启动OSCL_LOGI("stream %p use a started encoder:%p, %d",  // 记录使用已启动编码器astream, astream->aenc, astream->aenc->started_cnt);astream->aenc->started_cnt++;     // 增加启动计数goto EXIT;                        // 跳转到退出点}
​excuting_encoder = __get_excuting_aenc(astream->aenc);  // 查找正在执行的相同配置编码器if (excuting_encoder) {               // 如果找到可重用的编码器__put_enc(astream->aenc);         // 释放当前编码器astream->aenc = excuting_encoder;  // 使用找到的编码器astream->aenc->started_cnt++;     // 增加启动计数goto EXIT;                        // 跳转到退出点}
​astream->aenc->aenc_srcport = _splt_get_outport(&astream->asrc->asrc_splt);  // 获取音频源输出端口oscl_param_check_exit(astream->aenc->aenc_srcport, -1, NULL);  // 参数检查并退出ret = _aenc_start(astream->aenc);     // 启动编码器oscl_param_check_exit(ret == 0, -1, NULL);  // 参数检查并退出astream->aenc->started_cnt++;         // 增加启动计数
​
EXIT:if (ret == 0 && astream->state == AS_STATE_START)  // 如果启动成功且状态正确astream->state = AS_STATE_ENCODE;  // 更新状态为编码状态OSCL_TRACE("hdl:%p astream->state:%d", astream, astream->state);  // 跟踪日志if (ret != 0) {                       // 如果启动失败OSCL_LOGE("start astream failed, try stop!");  // 记录启动失败_astream_stop_enc(astream);       // 停止编码器(清理资源)}log_astream_state(astream);           // 记录音频流最终状态return ret;                           // 返回操作结果
}
​
/*** _astream_reset - 重置音频流** @hdl: 音频流句柄** 成功返回0,否则返回错误码*/
// 设计模式分析: 外观模式,提供简化的音频流重置接口
// 性能分析: 顺序停止编码器和音频源,确保完全重置
int _astream_reset(astream_handle_t *astream)  // 重置音频流函数
{int ret = 0;                          // 返回值
​OSCL_TRACE("hdl:%p", astream);        // 跟踪日志log_astream_state(astream);           // 记录音频流状态ret = _astream_stop_enc(astream);     // 停止编码器if (ret != 0) {                       // 如果停止编码器失败OSCL_LOGI("_astream_stop_enc fail!");  // 记录失败goto EXIT;                        // 跳转到退出点}
​ret = _astream_stop(astream);         // 停止音频源if (ret != 0) {                       // 如果停止音频源失败OSCL_LOGI("_astream_stop fail!");  // 记录失败goto EXIT;                        // 跳转到退出点}
EXIT:log_astream_state(astream);           // 记录音频流最终状态OSCL_TRACE("hdl:%p", astream);        // 跟踪日志return ret;                           // 返回操作结果
}
​
// 设计模式分析: 外观模式,提供简化的采样率获取接口
// 性能分析: 线程安全访问,轻量级操作
int audio_stream_get_sample_rate(astream_handle hdl)  // 获取音频流采样率函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄int sample_rate = 0;                 // 采样率oscl_param_check(astream != NULL, 0, NULL);  // 参数检查:音频流句柄ASTREAM_LOCK();                      // 加锁保护if (astream->asrc)                   // 如果音频源存在sample_rate = astream->asrc->sample_rate;  // 获取采样率ASTREAM_UNLOCK();                    // 解锁return sample_rate;                  // 返回采样率
}
​
​
// 设计模式分析: 外观模式,提供简化的参数获取接口
// 性能分析: 线程安全访问,轻量级操作
int audio_stream_get_sample_width(astream_handle hdl)  // 获取音频流采样位宽函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄int bit_per_sample = 0;               // 采样位宽oscl_param_check(astream != NULL, 0, NULL);  // 参数检查:音频流句柄ASTREAM_LOCK();                      // 加锁保护if (astream->asrc)                   // 如果音频源存在bit_per_sample = astream->asrc->sample_rate;  // 获取采样率(注意:这里应该是bit_per_sample字段)ASTREAM_UNLOCK();                    // 解锁return bit_per_sample;               // 返回采样位宽
}
​
// 设计模式分析: 外观模式,提供简化的声道数获取接口
// 性能分析: 线程安全访问,支持编码器和音频源两种来源
int audio_stream_get_channels(astream_handle hdl)  // 获取音频流声道数函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄int channels = 0;                     // 声道数oscl_param_check(astream != NULL, 0, NULL);  // 参数检查:音频流句柄oscl_param_check(astream->asrc != NULL, 0, NULL);  // 参数检查:音频源ASTREAM_LOCK();                      // 加锁保护if (astream->aenc)                   // 如果编码器存在,优先使用编码器声道数channels = astream->aenc->n_channel;else                                 // 否则使用音频源声道数channels = astream->asrc->channels;ASTREAM_UNLOCK();                    // 解锁return channels;                     // 返回声道数
}
​
// 设计模式分析: 外观模式,提供简化的编码类型获取接口
// 性能分析: 线程安全访问,轻量级操作
audio_encoder_t audio_stream_get_coding_type(astream_handle hdl)  // 获取音频流编码类型函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄int coding_type = 0;                 // 编码类型oscl_param_check(astream != NULL, 0, NULL);  // 参数检查:音频流句柄ASTREAM_LOCK();                      // 加锁保护if (astream->aenc)                   // 如果编码器存在coding_type = astream->aenc->coding_type;  // 获取编码类型ASTREAM_UNLOCK();                    // 解锁
​OSCL_LOGE("coding_type:%d", coding_type);  // 记录编码类型日志return coding_type;                  // 返回编码类型
}
​
// 设计模式分析: 策略模式,设置编码器私有参数
// 性能分析: 线程安全访问,参数验证
int audio_stream_set_private_para(astream_handle hdl, audio_private_para_t *para)  // 设置音频流私有参数函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄int ret = 0;                          // 返回值oscl_param_check(astream != NULL, 0, NULL);  // 参数检查:音频流句柄oscl_param_check(astream->aenc != NULL, 0, NULL);  // 参数检查:编码器ASTREAM_LOCK();                      // 加锁保护if (para->g726_mode)                 // 如果设置了G726模式astream->aenc->private_para.g726_mode = para->g726_mode;  // 设置G726模式else                                 // 否则使用默认模式astream->aenc->private_para.g726_mode = AUDIO_G726MODE_32K;  // 默认32K模式if (para->en_in_data_len)            // 如果设置了输入数据长度astream->aenc->private_para.en_in_data_len = para->en_in_data_len;  // 设置输入数据长度ASTREAM_UNLOCK();                    // 解锁return ret;                          // 返回操作结果
}
​
/*** audio_stream_get_cur_time - 获取音频流时间(音频源)** @hdl: 音频流句柄** 成功返回时间,否则返回0*/
// 设计模式分析: 外观模式,提供简化的时间获取接口
// 性能分析: OpenMAX API调用,需要硬件支持
signed long long audio_stream_get_time(astream_handle hdl)  // 获取音频流时间函数
{int ret = 0;                          // 返回值astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄OMX_TIME_CONFIG_TIMESTAMPTYPE time;   // OpenMAX时间戳配置signed long long cur_time = -1;       // 当前时间
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄oscl_param_check(astream->asrc != NULL, -1, NULL);  // 参数检查:音频源
​ASTREAM_LOCK();                      // 加锁保护if (astream->asrc->asrc_info.al_comp.cmp_hdl && astream->asrc->asrc_info.aout) {  // 检查组件和端口time.nPortIndex = astream->asrc->asrc_info.aout->index;  // 设置端口索引ret = OMX_GetConfig(astream->asrc->asrc_info.al_comp.cmp_hdl,  // 获取当前时间配置omx_index_tang_config_cur_time, &time);if (ret == 0)                     // 如果获取成功cur_time = time.nTimestamp;  // 设置当前时间}ASTREAM_UNLOCK();                    // 解锁return cur_time;                     // 返回当前时间
}
​
/*** audio_stream_set_sample_rate - audio_stream_set_sample_rate** @hdl: 音频流句柄* @rate: 采样率** 成功返回0,否则返回错误码*/
// 设计模式分析: 策略模式,设置音频采样率参数
// 性能分析: 线程安全访问,参数验证
int audio_stream_set_sample_rate(astream_handle hdl, int rate)  // 设置音频流采样率函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄oscl_param_check(astream->asrc != NULL, -1, NULL);  // 参数检查:音频源
​ASTREAM_LOCK();                      // 加锁保护if (rate != 0)                       // 如果采样率有效astream->asrc->sample_rate = rate;  // 设置采样率ASTREAM_UNLOCK();                    // 解锁
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志return 0;                            // 返回成功
}
​
/*** audio_stream_set_sample_width - audio_stream_set_sample_width** @hdl: 音频流句柄* @bits: 每个采样的位数** 成功返回0,否则返回错误码*/
// 设计模式分析: 策略模式,设置音频采样位宽参数
// 性能分析: 线程安全访问,参数验证(只支持8位和16位)
int audio_stream_set_sample_width(astream_handle hdl, int bits)  // 设置音频流采样位宽函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄oscl_param_check(astream->asrc != NULL, -1, NULL);  // 参数检查:音频源
​ASTREAM_LOCK();                      // 加锁保护if (bits == 8 || bits == 16)         // 只支持8位或16位采样astream->asrc->bit_per_sample = bits;  // 设置采样位宽ASTREAM_UNLOCK();                    // 解锁
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志return 0;                            // 返回成功
}
​
/*** audio_stream_set_channels - audio_stream_set_channels** @hdl: 音频流句柄* @channels: 音频设备的声道数** 成功返回0,否则返回错误码*/
// 设计模式分析: 策略模式,设置音频声道数参数
// 性能分析: 线程安全访问,参数验证和一致性检查
int audio_stream_set_channels(astream_handle hdl, int channels)  // 设置音频流声道数函数
{int ret = 0;                          // 返回值astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄
​ASTREAM_LOCK();                      // 加锁保护oscl_param_check_exit(astream->asrc != NULL, -1, NULL);  // 参数检查:音频源oscl_param_check_exit(channels != 0, -1, NULL);  // 参数检查:声道数有效性if (astream->aenc->n_channel != astream->asrc->channels) {  // 检查声道数一致性OSCL_LOGE("set channels after set channal map!");  // 记录错误:在设置声道映射后设置声道数ret = -1;                         // 设置错误返回值goto EXIT;                        // 跳转到退出点}astream->asrc->channels = channels;   // 设置音频源声道数astream->aenc->n_channel = channels;  // 设置编码器声道数astream->aenc->channel_map = (1<<astream->asrc->channels) - 1;  // 设置声道映射(全选所有声道)
EXIT:ASTREAM_UNLOCK();                    // 解锁
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志return ret;                           // 返回操作结果
}
​
/*** audio_stream_set_channels - audio_stream_set_channels** @hdl: 音频流句柄* @on: 0表示关闭,其他值表示开启** 成功返回0,否则返回错误码*/
// 设计模式分析: 策略模式,设置回声消除功能
// 性能分析: 线程安全访问,位操作设置功能标志
int audio_stream_set_aec(astream_handle hdl, int on)  // 设置音频流回声消除函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄oscl_param_check(astream->asrc != NULL, -1, NULL);  // 参数检查:音频源
​ASTREAM_LOCK();                      // 加锁保护if (on)                              // 如果启用回声消除astream->asrc->aqe_funcs |= LB_AQE_AEC;  // 设置AEC功能标志else                                 // 如果禁用回声消除astream->asrc->aqe_funcs &= (~LB_AQE_AEC);  // 清除AEC功能标志ASTREAM_UNLOCK();                    // 解锁
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志return 0;                            // 返回成功
}
​
/*** audio_stream_set_anr - 设置音频流噪声抑制开关* 目前我们只支持单声道、8k或16k的噪声抑制** @hdl: 录制器句柄* @on: 0表示关闭,其他值表示开启*/
// 设计模式分析: 策略模式,设置噪声抑制功能
// 性能分析: 线程安全访问,位操作设置功能标志
int audio_stream_set_anr(astream_handle hdl, int on)  // 设置音频流噪声抑制函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志if (astream == NULL) {                // 检查音频流句柄OSCL_LOGE("input hdl err!");      // 记录句柄错误return -1;                        // 返回错误}ASTREAM_LOCK();                      // 加锁保护if (on)                              // 如果启用噪声抑制astream->asrc->aqe_funcs |= LB_AQE_ANR;  // 设置ANR功能标志else                                 // 如果禁用噪声抑制astream->asrc->aqe_funcs &= (~LB_AQE_ANR);  // 清除ANR功能标志ASTREAM_UNLOCK();                    // 解锁OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志return 0;                            // 返回成功
}
​
/*** audio_stream_set_agc - 设置音频流自动增益控制开关* 目前我们只支持单声道、8k、16k、32k、48k的自动增益控制** @hdl: 录制器句柄* @on: 0表示关闭,其他值表示开启*/
// 设计模式分析: 策略模式,设置自动增益控制功能
// 性能分析: 线程安全访问,位操作设置功能标志
int audio_stream_set_agc(astream_handle hdl, int on)  // 设置音频流自动增益控制函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志if (astream == NULL) {                // 检查音频流句柄OSCL_LOGE("input hdl err!");      // 记录句柄错误return -1;                        // 返回错误}ASTREAM_LOCK();                      // 加锁保护if (on)                              // 如果启用自动增益控制astream->asrc->aqe_funcs |= LB_AQE_AGC;  // 设置AGC功能标志else                                 // 如果禁用自动增益控制astream->asrc->aqe_funcs &= (~LB_AQE_AGC);  // 清除AGC功能标志ASTREAM_UNLOCK();                    // 解锁OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志return 0;                            // 返回成功
}
​
/*** audio_stream_set_prio - audio_stream_set_prio** @hdl: 音频流句柄* @prio: 优先级** 成功返回0,否则返回错误码*/
// 设计模式分析: 策略模式,设置组件优先级
// 性能分析: 批量设置所有相关组件优先级,确保一致性
int audio_stream_set_prio(astream_handle hdl, int prio)  // 设置音频流优先级函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄OMX_PRIORITYMGMTTYPE priority;       // OpenMAX优先级管理结构
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄oscl_param_check(astream->asrc != NULL, -1, NULL);  // 参数检查:音频源oscl_param_check(astream->aenc != NULL, -1, NULL);  // 参数检查:编码器astream->asrc->prio = prio;           // 设置音频源优先级astream->aenc->prio = prio;           // 设置编码器优先级
​priority.nVersion.nVersion = OMX_VERSION;  // 设置OpenMAX版本priority.nGroupPriority = prio;       // 设置组优先级if (astream->asrc->asrc_info.al_comp.cmp_hdl)  // 如果音频源组件句柄存在OMX_SetParameter(astream->asrc->asrc_info.al_comp.cmp_hdl,  // 设置音频源组件优先级OMX_IndexParamPriorityMgmt, &priority);
​if (astream->asrc->asrc_splt.al_comp.cmp_hdl)  // 如果音频源分流器组件句柄存在OMX_SetParameter(astream->asrc->asrc_splt.al_comp.cmp_hdl,  // 设置音频源分流器组件优先级OMX_IndexParamPriorityMgmt, &priority);
​if (astream->aenc->aenc_info.al_comp.cmp_hdl)  // 如果编码器组件句柄存在OMX_SetParameter(astream->aenc->aenc_info.al_comp.cmp_hdl,  // 设置编码器组件优先级OMX_IndexParamPriorityMgmt, &priority);
​if (astream->aenc->aenc_splt.al_comp.cmp_hdl)  // 如果编码器分流器组件句柄存在OMX_SetParameter(astream->aenc->aenc_splt.al_comp.cmp_hdl,  // 设置编码器分流器组件优先级OMX_IndexParamPriorityMgmt, &priority);OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志return 0;                            // 返回成功
}
​
​
/*** audio_stream_set_coding_type - audio_stream_set_coding_type** @hdl: 音频流句柄* @coding: 编码类型** 成功返回0,否则返回错误码*/
// 设计模式分析: 策略模式,设置音频编码类型
// 性能分析: 线程安全访问,编码类型验证
int audio_stream_set_coding_type(astream_handle hdl, audio_encoder_t coding)  // 设置音频流编码类型函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄oscl_param_check(astream->aenc != NULL, -1, NULL);  // 参数检查:编码器
​ASTREAM_LOCK();                      // 加锁保护if (coding > AUDIO_ENCODER_INVALID && coding < AUDIO_ENCODER_UNSUPPORT)  // 验证编码类型有效性astream->aenc->coding_type = coding;  // 设置编码类型elseOSCL_LOGE("error coding type:%d", coding);  // 记录编码类型错误
​ASTREAM_UNLOCK();                    // 解锁
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志return 0;                            // 返回成功
}
​
/*** audio_stream_set_mute - audio_stream_set_mute** @hdl: 音频流句柄* @mute_on: 0:静音关闭,其他值:静音开启** 成功返回0,否则返回错误码*/
// 设计模式分析: 命令模式,封装静音设置操作为独立命令
// 性能分析: OpenMAX API调用,实时生效
int audio_stream_set_mute(astream_handle hdl, int mute_on)  // 设置音频流静音函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄OMX_AUDIO_CONFIG_MUTETYPE mute;       // OpenMAX静音配置结构int ret = 0;                          // 返回值
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄oscl_param_check(astream->asrc != NULL, -1, NULL);  // 参数检查:音频源
​ASTREAM_LOCK();                      // 加锁保护astream->asrc->mute_on = mute_on;     // 设置静音状态if (astream->asrc->asrc_info.al_comp.cmp_hdl) {  // 如果音频源组件句柄存在memset(&mute, 0, sizeof(OMX_AUDIO_CONFIG_MUTETYPE));  // 清空静音配置结构if (mute_on)                     // 如果启用静音mute.bMute = OMX_TRUE;      // 设置静音标志mute.nPortIndex = astream->asrc->asrc_info.aout->index;  // 设置端口索引ret = OMX_SetConfig(astream->asrc->asrc_info.al_comp.cmp_hdl,  // 设置静音配置OMX_IndexConfigAudioMute, &mute);}ASTREAM_UNLOCK();                    // 解锁OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志return ret;                          // 返回操作结果
}
​
/*** audio_stream_select_encode_channel - 选择要编码的声道** @hdl: 音频流句柄* @chanal_map: 选择声道,位=1表示选择该声道** 成功返回0,否则返回错误码*/
// 设计模式分析: 策略模式,设置声道选择映射
// 性能分析: 位图操作,高效声道选择
int audio_stream_select_encode_channel(astream_handle hdl, int channel_map)  // 选择编码声道函数
{int i;                                // 循环索引int mask;                             // 声道掩码astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄oscl_param_check(astream->asrc != NULL, -1, NULL);  // 参数检查:音频源ASTREAM_LOCK();                      // 加锁保护OSCL_LOGI("set astream %p, ch map:%x", astream, channel_map);  // 记录声道映射设置mask = (1<<astream->asrc->channels) - 1;  // 计算声道掩码(所有声道)if (channel_map == 0)                // 如果声道映射为0channel_map = mask;              // 使用所有声道if (astream->state == AS_STATE_ENCODE) {  // 如果正在编码中OSCL_LOGE("ERR: astream is encoding");  // 记录编码中错误} else {astream->aenc->channel_map = channel_map & mask;  // 设置声道映射(与掩码相与)astream->aenc->n_channel = 0;    // 重置声道计数for (i = 0; i < astream->asrc->channels; i++) {  // 遍历所有声道if ((astream->aenc->channel_map & (1<<i)) != 0)  // 如果声道被选中astream->aenc->n_channel++;  // 增加声道计数}OSCL_LOGI("chanal_map is %x, select %d from %d",  // 记录声道选择结果channel_map, astream->aenc->n_channel, astream->asrc->channels);}OSCL_LOGI("set astream %p, ch map:%x", astream, astream->aenc->channel_map);  // 记录最终声道映射ASTREAM_UNLOCK();                    // 解锁return 0;                            // 返回成功
}
​
/*** audio_stream_creat - 通过设备名称获取音频流句柄** @name: 音频设备名称** 成功返回音频流句柄,否则返回0*/
// 设计模式分析: 工厂方法模式,根据设备名称创建音频流
// 性能分析: 对象池管理,线程安全创建
astream_handle audio_stream_creat_by_name(char *name)  // 通过名称创建音频流函数
{audio_stream_sum_t *ainfo;            // 音频流汇总信息astream_handle_t *astream = NULL;     // 音频流句柄int i;                                // 循环索引int ret = -1;                         // 返回值
​ASTREAM_LOCK();                      // 加锁保护ainfo = &g_audio_rec;                 // 获取全局音频录制对象if (ainfo->init == 0) {               // 如果未初始化memset(ainfo, 0, sizeof(audio_stream_sum_t));  // 清空内存ainfo->init = 1;                  // 设置初始化标志ainfo->muti_coding_enable = 1;    // 启用多编码功能}
​if (name == NULL)                     // 如果名称为空name = "default";                 // 使用默认设备名
​for (i = 0; i < MAX_AUDIO_STREAM; i++) {  // 遍历音频流对象池if (ainfo->astream_handle_t[i].ref == 0) {  // 找到未使用的音频流astream = &ainfo->astream_handle_t[i];  // 获取音频流astream->ref++;               // 增加引用计数astream->index = i;           // 设置索引break;}}oscl_param_check_exit(astream != NULL, -1, NULL);  // 参数检查:音频流创建成功
​astream->asrc = __get_source_by_name(name);  // 根据名称获取音频源OSCL_LOGI("name:%s, src:%p", name, astream->asrc);  // 记录音频源信息oscl_param_check_exit(astream->asrc != NULL, -1, NULL);  // 参数检查:音频源获取成功
​astream->aenc = __get_aenc_by_src(astream->asrc);  // 根据音频源获取编码器oscl_param_check_exit(astream->aenc != NULL, -1, NULL);  // 参数检查:编码器获取成功ret = 0;                              // 设置成功返回值astream->state = AS_STATE_INIT;       // 设置音频流状态为初始化
​
EXIT:log_astream_state(astream);           // 记录音频流状态ASTREAM_UNLOCK();                    // 解锁if (ret != 0) {                       // 如果创建失败OSCL_LOGE("astream creat fail:%x", ret);  // 记录创建失败audio_stream_release(astream);    // 释放音频流资源astream = NULL;                   // 清空句柄}OSCL_TRACE("astream:%p", astream);    // 跟踪日志return astream;                       // 返回音频流句柄
}
​
​
/*** audio_stream_creat - 获取音频流句柄** 成功返回音频流句柄,否则返回0*/
// 设计模式分析: 工厂方法模式,创建默认音频流
// 性能分析: 委托给具体实现,代码复用
astream_handle audio_stream_creat(void)  // 创建音频流函数(默认设备)
{return audio_stream_creat_by_name(NULL);  // 使用默认设备名创建音频流
}
​
/*** audio_stream_release - 释放录制器使用的资源** @hdl: 录制器句柄*/
// 设计模式分析: 资源管理模式,管理音频流生命周期
// 性能分析: 引用计数管理,确保资源正确释放
void audio_stream_release(astream_handle hdl)  // 释放音频流函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄
​OSCL_TRACE("astream:%p", hdl);        // 跟踪日志if (astream == NULL)                  // 如果句柄为空return;                           // 直接返回
​ASTREAM_LOCK();                      // 加锁保护log_astream_state(astream);           // 记录音频流状态/* 只有在所有音频句柄都释放时才反初始化音频流 */if (astream->ref <= 0) {              // 如果引用计数异常astream->ref = 0;                 // 重置引用计数OSCL_LOGE("astream already released!");  // 记录重复释放错误goto EXIT;                        // 跳转到退出点}if (astream->ref > 1) {               // 如果还有其他引用astream->ref--;                   // 减少引用计数OSCL_TRACE("astream->ref:%d", astream->ref);  // 跟踪引用计数goto EXIT;                        // 跳转到退出点}if (astream->state == AS_STATE_ENCODE) {  // 如果处于编码状态OSCL_LOGE("stream %p release in state AS_STATE_ENCODE!", astream);  // 记录状态警告_astream_stop_enc(astream);       // 停止编码器}if (astream->state == AS_STATE_START) {  // 如果处于启动状态OSCL_LOGE("stream %p release in state AS_STATE_START!", astream);  // 记录状态警告_astream_stop(astream);           // 停止音频源}if (astream->srcport_map || astream->encport_map) {  // 如果端口映射未清空OSCL_LOGE("Err, stream release with %x-%x, astream->state:%d!",  // 记录端口未释放错误astream->srcport_map, astream->encport_map, astream->state);}__put_enc(astream->aenc);             // 释放编码器__put_source(astream->asrc);          // 释放音频源log_astream_state(astream);           // 记录释放后状态memset(astream, 0, sizeof(astream_handle_t));  // 清空音频流内存astream->state = AS_STATE_ERR;        // 设置状态为错误
​
EXIT:log_astream_state(astream);           // 记录最终状态ASTREAM_UNLOCK();                    // 解锁OSCL_TRACE("hdl:%p astream->state:%d", hdl, astream->state);  // 跟踪日志
}
​
​
/*** audio_stream_inc_refcnt - 增加音频流的引用计数** @hdl: 音频流句柄** 成功返回0,否则返回错误码*/
// 设计模式分析: 引用计数模式,管理音频流生命周期
// 性能分析: 轻量级引用计数操作,线程安全
int audio_stream_inc_refcnt(astream_handle hdl)  // 增加音频流引用计数函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄int ret = 0;                          // 返回值
​OSCL_TRACE("start");                  // 跟踪日志oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄ASTREAM_LOCK();                      // 加锁保护if (astream->state == AS_STATE_ERR)  // 如果音频流处于错误状态ret = -1;                         // 设置错误返回值elseastream->ref++;                   // 增加引用计数ASTREAM_UNLOCK();                    // 解锁
​return ret;                          // 返回操作结果
}
​
​
/*** audio_stream_start - 启动音频流** @hdl: 音频流句柄** 成功返回0,否则返回错误码*/
// 设计模式分析: 状态模式,管理音频流状态转换
// 性能分析: 状态验证确保正确启动顺序,避免重复启动
int audio_stream_start(astream_handle hdl)  // 启动音频流函数
{int ret = 0;                          // 返回值astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄
​ASTREAM_LOCK();                      // 加锁保护log_astream_state(astream);           // 记录音频流状态oscl_param_check_exit(astream->asrc != NULL, -1, NULL);  // 参数检查:音频源必须存在oscl_param_check_exit(astream->state != AS_STATE_ERR, -1, NULL);  // 参数检查:状态不能为错误if (astream->state == AS_STATE_INIT)  // 如果处于初始化状态ret = _astream_start(astream);    // 启动音频流elseOSCL_LOGW("stream %p already started(%d)!", astream, astream->state);  // 记录警告:音频流已启动
​
EXIT:log_astream_state(astream);           // 记录音频流最终状态ASTREAM_UNLOCK();                    // 解锁OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志return ret;                          // 返回操作结果
}
​
/*** audio_stream_stop - 停止音频流** @hdl: 音频流句柄** 成功返回0,否则返回错误码*/
// 设计模式分析: 状态模式,管理音频流停止流程
// 性能分析: 按状态顺序停止,确保资源正确释放
int audio_stream_stop(astream_handle hdl)  // 停止音频流函数
{int ret = 0;                          // 返回值astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄
​ASTREAM_LOCK();                      // 加锁保护log_astream_state(astream);           // 记录音频流状态oscl_param_check_exit(astream->asrc != NULL, -1, NULL);  // 参数检查:音频源必须存在oscl_param_check_exit(astream->state != AS_STATE_ERR, -1, NULL);  // 参数检查:状态不能为错误if (astream->state == AS_STATE_ENCODE) {  // 如果处于编码状态OSCL_LOGW("stream %p is in encoding while stopping!", astream);  // 记录警告:编码中停止_astream_stop_enc(astream);       // 停止编码器}if (astream->state == AS_STATE_START) {  // 如果处于启动状态OSCL_LOGI("stream %p is stopping!", astream);  // 记录信息:正在停止_astream_stop(astream);           // 停止音频源}OSCL_TRACE("hdl:%p astream->state:%d", hdl, astream->state);  // 跟踪日志
EXIT:log_astream_state(astream);           // 记录音频流最终状态ASTREAM_UNLOCK();                    // 解锁return ret;                          // 返回操作结果
}
​
/*** audio_stream_start_enc - 启动音频编码** @hdl: 音频流句柄** 成功返回0,否则返回错误码*/
// 设计模式分析: 工厂方法模式,返回编码端口
// 性能分析: 状态机驱动,确保正确的启动序列
port_info_t *audio_stream_start_enc(astream_handle hdl)  // 启动音频编码函数
{int ret = 0;                          // 返回值astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄port_info_t *port = NULL;              // 端口指针
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志oscl_param_check(astream != NULL, NULL, NULL);  // 参数检查:音频流句柄
​ASTREAM_LOCK();                      // 加锁保护oscl_param_check_exit(astream->asrc != NULL, -1, NULL);  // 参数检查:音频源必须存在oscl_param_check_exit(astream->aenc != NULL, -1, NULL);  // 参数检查:编码器必须存在if (astream->state == AS_STATE_ENCODE)  // 如果已处于编码状态OSCL_TRACE("astream already started");  // 跟踪日志:音频流已启动if (astream->state == AS_STATE_INIT)  // 如果处于初始化状态ret = _astream_start(astream);    // 先启动音频流if (astream->state == AS_STATE_START)  // 如果处于启动状态ret = _astream_start_enc(astream);  // 启动编码器if (astream->state != AS_STATE_ENCODE)  // 如果最终状态不是编码状态ret = -1;                         // 设置错误返回值if (ret == 0) {                       // 如果启动成功port = _audio_stream_getport(astream, AS_PORT_CODEC);  // 获取编码端口astream->enc_outport = port;      // 保存编码输出端口}
EXIT:log_astream_state(astream);           // 记录音频流状态ASTREAM_UNLOCK();                    // 解锁
​OSCL_LOGE("astream:%p-%p astream->state:%d", astream, port, astream->state);  // 记录编码启动结果return port;                         // 返回编码端口
}
​
/*** audio_stream_stop_enc - 停止音频编码** @hdl: 音频流句柄** 成功返回0,否则返回错误码*/
// 设计模式分析: 资源管理模式,释放编码资源
// 性能分析: 端口验证和资源清理,确保编码器正确停止
int audio_stream_stop_enc(astream_handle hdl, port_info_t *enc_port)  // 停止音频编码函数
{int ret = 0;                          // 返回值astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄
​OSCL_TRACE("hdl:%p", hdl);            // 跟踪日志oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄
​ASTREAM_LOCK();                      // 加锁保护oscl_param_check_exit(astream->state == AS_STATE_ENCODE, -1, NULL);  // 参数检查:必须处于编码状态oscl_param_check_exit(astream->asrc != NULL, -1, NULL);  // 参数检查:音频源必须存在oscl_param_check_exit(astream->aenc != NULL, -1, NULL);  // 参数检查:编码器必须存在if (enc_port) {                       // 如果提供了编码端口if (astream->enc_outport != enc_port) {  // 检查端口一致性OSCL_LOGE("err! astream->enc_outport != port (%p, %p)",  // 记录端口不匹配错误astream->enc_outport, enc_port);}_audio_stream_putport(astream, enc_port);  // 释放编码端口astream->enc_outport = NULL;      // 清空编码输出端口指针}ret = _astream_stop_enc(astream);     // 停止编码器
EXIT:ASTREAM_UNLOCK();                    // 解锁
​return ret;                          // 返回操作结果
}
​
/*** audio_stream_getport - 从音频流获取一个空闲端口** @hdl: 音频流句柄** @type: 要获取的PCM端口或编码端口** 成功返回端口句柄,否则返回NULL*/
// 设计模式分析: 工厂方法模式,根据类型创建端口
// 性能分析: 线程安全端口分配,支持PCM和编码两种类型
port_info_t *audio_stream_getport(astream_handle hdl, as_port_type_e type)  // 获取音频流端口函数
{port_info_t *port = NULL;              // 端口指针astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄
​OSCL_TRACE("==");                     // 跟踪日志oscl_param_check(astream != NULL, NULL, NULL);  // 参数检查:音频流句柄
​ASTREAM_LOCK();                      // 加锁保护port = _audio_stream_getport(astream, type);  // 根据类型获取端口ASTREAM_UNLOCK();                    // 解锁OSCL_LOGI("get port:%p", port);       // 记录端口获取结果return port;                         // 返回端口指针
}
​
/*** audio_stream_putport - 释放从音频流获取的端口** @hdl: 音频流句柄** @port: 要释放的端口** 成功返回0,否则返回错误码*/
// 设计模式分析: 资源管理模式,释放端口资源
// 性能分析: 线程安全端口释放,资源回收
int audio_stream_putport(astream_handle hdl, port_info_t *port)  // 释放音频流端口函数
{astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄int ret = -1;                          // 返回值
​OSCL_TRACE("==");                     // 跟踪日志ASTREAM_LOCK();                      // 加锁保护ret = _audio_stream_putport(astream, port);  // 释放端口ASTREAM_UNLOCK();                    // 解锁OSCL_TRACE("==ret:%d", ret);          // 跟踪操作结果
​return ret;                          // 返回操作结果
}
​
/*** audio_stream_enable_port - 启用从音频流获取的端口** @hdl: 音频流句柄** @port: 要启用的端口** 成功返回0,否则返回错误码*/
// 设计模式分析: 命令模式,封装端口启用操作
// 性能分析: 根据端口类型路由到相应的启用函数
int audio_stream_enable_port(void *hdl, port_info_t *port)  // 启用音频流端口函数
{int ret = -1;                          // 返回值astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄
​OSCL_TRACE("==");                     // 跟踪日志oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄oscl_param_check(port != NULL, -1, NULL);  // 参数检查:端口
​ASTREAM_LOCK();                      // 加锁保护oscl_param_check_exit(astream->asrc != NULL, -1, NULL);  // 参数检查:音频源必须存在oscl_param_check_exit(astream->aenc != NULL, -1, NULL);  // 参数检查:编码器必须存在if (port->comp_info == &astream->aenc->aenc_splt.al_comp)  // 如果是编码器分流器端口ret = _splt_enable_port(&astream->aenc->aenc_splt, port);  // 启用编码器分流器端口if (port->comp_info == &astream->asrc->asrc_splt.al_comp)  // 如果是音频源分流器端口ret = _splt_enable_port(&astream->asrc->asrc_splt, port);  // 启用音频源分流器端口EXIT:ASTREAM_UNLOCK();                    // 解锁
​OSCL_TRACE("==");                     // 跟踪日志return ret;                          // 返回操作结果
}
​
/*** audio_stream_disable_port - 禁用从音频流获取的端口** @hdl: 音频流句柄** @port: 要禁用的端口** 成功返回0,否则返回错误码*/
// 设计模式分析: 命令模式,封装端口禁用操作
// 性能分析: 根据端口类型路由到相应的禁用函数
int audio_stream_disable_port(void *hdl, port_info_t *port)  // 禁用音频流端口函数
{int ret = -1;                          // 返回值astream_handle_t *astream = get_audio_stream(hdl);  // 获取音频流句柄
​OSCL_TRACE("==");                     // 跟踪日志oscl_param_check(astream != NULL, -1, NULL);  // 参数检查:音频流句柄oscl_param_check(port != NULL, -1, NULL);  // 参数检查:端口
​ASTREAM_LOCK();                      // 加锁保护oscl_param_check_exit(astream->asrc != NULL, -1, NULL);  // 参数检查:音频源必须存在oscl_param_check_exit(astream->aenc != NULL, -1, NULL);  // 参数检查:编码器必须存在if (port->comp_info == &astream->aenc->aenc_splt.al_comp)  // 如果是编码器分流器端口ret = _splt_disable_port(&astream->aenc->aenc_splt, port);  // 禁用编码器分流器端口if (port->comp_info == &astream->asrc->asrc_splt.al_comp)  // 如果是音频源分流器端口ret = _splt_disable_port(&astream->asrc->asrc_splt, port);  // 禁用音频源分流器端口
EXIT:ASTREAM_UNLOCK();                    // 解锁
​OSCL_TRACE("==");                     // 跟踪日志return ret;                          // 返回操作结果
}
​
#if 0
/*** audio_stream_muti_encoder_onoff - 打开/关闭多音频编码器** @on: 1--打开, 0--关闭** 成功返回0,否则返回错误码*/
// 设计模式分析: 策略模式,配置多编码器功能
// 性能分析: 全局配置开关,影响所有音频流行为
int audio_stream_muti_encoder_onoff(int on)  // 多编码器开关函数(已注释)
{audio_stream_sum_t *ainfo;            // 音频流汇总信息ainfo = &g_audio_rec;                 // 获取全局音频录制对象ASTREAM_LOCK();                      // 加锁保护if (ainfo->init == 0) {               // 如果未初始化memset(ainfo, 0, sizeof(audio_stream_sum_t));  // 清空内存ainfo->init = 1;                  // 设置初始化标志}ainfo->muti_coding_enable = on;       // 设置多编码使能标志ASTREAM_UNLOCK();                    // 解锁return 0;                            // 返回成功
}
#endif
​
​

框架架构分析

1. 核心模块交互架构

Application Layer (测试应用)↓
Audio Stream API Layer (audio_stream_xxx)↓
Component Management Layer (组件管理)↓  
OpenMAX IL Layer (OMX标准接口)↓
Hardware Abstraction Layer (硬件抽象)↓
Linux Sound Subsystem (ALSA/Kernel)

2. 与Linux内核音频子系统对比

用户空间:Audio Framework ↔ 测试应用↓OpenMAX IL ↔ GStreamer/PulseAudio↓
内核空间:ALSA API ↔ ALSA驱动↓Sound Core ↔ 音频硬件驱动↓音频硬件 (Codec/DMA/I2S)

逐行注解的测试程序

/*** test_main.c - Linux音频框架测试程序* * 设计模式: 组合模式 + 观察者模式 + 策略模式* 性能分析: 多线程测试 + 状态监控 + 性能统计*/
​
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include "audio_stream.h"
#include "media_common.h"
​
// 设计模式: 单例模式 - 全局测试上下文
typedef struct test_context {int test_case;                      // 测试用例编号int running;                        // 运行标志int success_count;                  // 成功计数int fail_count;                     // 失败计数pthread_mutex_t lock;               // 线程锁astream_handle audio_handles[4];    // 音频句柄数组int handle_count;                   // 句柄计数
} test_context_t;
​
static test_context_t g_ctx = {0};      // 全局测试上下文
​
// 设计模式: 工厂模式 - 创建测试上下文
test_context_t* test_context_create(void)
{test_context_t* ctx = &g_ctx;       // 使用全局单例ctx->test_case = 0;                 // 初始化测试用例ctx->running = 1;                   // 设置运行标志ctx->success_count = 0;             // 初始化成功计数ctx->fail_count = 0;                // 初始化失败计数ctx->handle_count = 0;              // 初始化句柄计数pthread_mutex_init(&ctx->lock, NULL); // 初始化互斥锁return ctx;                         // 返回上下文指针
}
​
// 设计模式: 资源管理模式 - 销毁测试上下文
void test_context_destroy(test_context_t* ctx)
{if (!ctx) return;                   // 空指针检查pthread_mutex_destroy(&ctx->lock);  // 销毁互斥锁memset(ctx, 0, sizeof(test_context_t)); // 清空上下文
}
​
// 性能分析: 线程安全的结果统计
void test_record_result(test_context_t* ctx, int success)
{pthread_mutex_lock(&ctx->lock);     // 加锁保护if (success) {                      // 如果测试成功ctx->success_count++;           // 增加成功计数printf("✅ 测试用例 %d 通过\n", ctx->test_case); // 输出成功信息} else {                            // 如果测试失败ctx->fail_count++;              // 增加失败计数printf("❌ 测试用例 %d 失败\n", ctx->test_case); // 输出失败信息}ctx->test_case++;                   // 递增测试用例编号pthread_mutex_unlock(&ctx->lock);   // 解锁
}
​
/*** 测试用例1: 音频流创建和释放测试* 设计模式: 模板方法模式 - 定义测试流程* 性能分析: 资源泄漏检测 + 生命周期管理*/
int test_audio_stream_create_release(test_context_t* ctx)
{int result = 0;                     // 测试结果astream_handle handle;              // 音频流句柄printf("\n🎵 测试1: 音频流创建和释放\n"); // 输出测试开始信息printf("================================\n"); // 分隔线// 步骤1: 创建音频流printf("步骤1: 创建音频流...\n");     // 输出步骤信息handle = audio_stream_creat();      // 创建默认音频流if (handle == NULL) {               // 检查创建是否成功printf("错误: 音频流创建失败\n"); // 输出错误信息test_record_result(ctx, 0);     // 记录失败结果return -1;                      // 返回错误}printf("✅ 音频流创建成功, 句柄: %p\n", handle); // 输出成功信息// 步骤2: 验证初始状态printf("步骤2: 验证初始状态...\n");   // 输出步骤信息int channels = audio_stream_get_channels(handle); // 获取声道数int sample_rate = audio_stream_get_sample_rate(handle); // 获取采样率int sample_width = audio_stream_get_sample_width(handle); // 获取采样位宽printf("  声道数: %d\n", channels);  // 输出声道数printf("  采样率: %d\n", sample_rate); // 输出采样率  printf("  采样位宽: %d\n", sample_width); // 输出采样位宽// 步骤3: 增加引用计数printf("步骤3: 测试引用计数...\n");   // 输出步骤信息if (audio_stream_inc_refcnt(handle) != 0) { // 增加引用计数printf("错误: 引用计数增加失败\n"); // 输出错误信息audio_stream_release(handle);   // 释放音频流test_record_result(ctx, 0);     // 记录失败结果return -1;                      // 返回错误}printf("✅ 引用计数测试通过\n");      // 输出成功信息// 步骤4: 释放音频流printf("步骤4: 释放音频流...\n");     // 输出步骤信息audio_stream_release(handle);       // 第一次释放(减少引用计数)audio_stream_release(handle);       // 第二次释放(实际释放资源)printf("✅ 音频流释放成功\n");        // 输出成功信息test_record_result(ctx, 1);         // 记录成功结果return 0;                           // 返回成功
}
​
/*** 测试用例2: 音频参数配置测试* 设计模式: 策略模式 - 测试不同参数配置* 性能分析: 参数验证 + 配置回读测试*/
int test_audio_parameter_config(test_context_t* ctx)
{astream_handle handle;              // 音频流句柄int ret;                            // 返回值printf("\n🎛️  测试2: 音频参数配置\n"); // 输出测试开始信息printf("================================\n"); // 分隔线// 步骤1: 创建音频流handle = audio_stream_creat_by_name("default"); // 按名称创建音频流if (handle == NULL) {               // 检查创建是否成功printf("错误: 音频流创建失败\n"); // 输出错误信息test_record_result(ctx, 0);     // 记录失败结果return -1;                      // 返回错误}// 步骤2: 配置音频参数printf("步骤2: 配置音频参数...\n");   // 输出步骤信息// 设置采样率ret = audio_stream_set_sample_rate(handle, 48000); // 设置采样率为48kHzif (ret != 0) {                     // 检查设置是否成功printf("错误: 采样率设置失败\n"); // 输出错误信息audio_stream_release(handle);   // 释放音频流test_record_result(ctx, 0);     // 记录失败结果return -1;                      // 返回错误}// 设置采样位宽ret = audio_stream_set_sample_width(handle, 16); // 设置采样位宽为16位if (ret != 0) {                     // 检查设置是否成功printf("错误: 采样位宽设置失败\n"); // 输出错误信息audio_stream_release(handle);   // 释放音频流test_record_result(ctx, 0);     // 记录失败结果return -1;                      // 返回错误}// 设置声道数ret = audio_stream_set_channels(handle, 2); // 设置声道数为立体声if (ret != 0) {                     // 检查设置是否成功printf("错误: 声道数设置失败\n"); // 输出错误信息audio_stream_release(handle);   // 释放音频流test_record_result(ctx, 0);     // 记录失败结果return -1;                      // 返回错误}// 步骤3: 验证参数配置printf("步骤3: 验证参数配置...\n");   // 输出步骤信息int actual_rate = audio_stream_get_sample_rate(handle); // 获取实际采样率int actual_width = audio_stream_get_sample_width(handle); // 获取实际采样位宽int actual_channels = audio_stream_get_channels(handle); // 获取实际声道数printf("  期望采样率: 48000, 实际: %d\n", actual_rate); // 输出采样率对比printf("  期望采样位宽: 16, 实际: %d\n", actual_width); // 输出采样位宽对比  printf("  期望声道数: 2, 实际: %d\n", actual_channels); // 输出声道数对比if (actual_rate == 48000 && actual_width == 16 && actual_channels == 2) { // 验证参数printf("✅ 参数配置验证通过\n");   // 输出成功信息} else {printf("❌ 参数配置验证失败\n");   // 输出失败信息audio_stream_release(handle);   // 释放音频流test_record_result(ctx, 0);     // 记录失败结果return -1;                      // 返回错误}// 步骤4: 清理资源audio_stream_release(handle);       // 释放音频流test_record_result(ctx, 1);         // 记录成功结果return 0;                           // 返回成功
}
​
/*** 测试用例3: 音频效果功能测试* 设计模式: 装饰器模式 - 测试音效增强功能* 性能分析: 功能开关测试 + 状态验证*/
int test_audio_effects(test_context_t* ctx)
{astream_handle handle;              // 音频流句柄printf("\n🎧 测试3: 音频效果功能\n"); // 输出测试开始信息printf("================================\n"); // 分隔线handle = audio_stream_creat();      // 创建音频流if (handle == NULL) {               // 检查创建是否成功printf("错误: 音频流创建失败\n"); // 输出错误信息test_record_result(ctx, 0);     // 记录失败结果return -1;                      // 返回错误}// 测试回声消除printf("测试回声消除(AEC)...\n");    // 输出测试信息audio_stream_set_aec(handle, 1);    // 启用回声消除printf("✅ AEC已启用\n");            // 输出成功信息// 测试噪声抑制printf("测试噪声抑制(ANR)...\n");    // 输出测试信息audio_stream_set_anr(handle, 1);    // 启用噪声抑制printf("✅ ANR已启用\n");            // 输出成功信息// 测试自动增益控制printf("测试自动增益控制(AGC)...\n"); // 输出测试信息audio_stream_set_agc(handle, 1);    // 启用自动增益控制printf("✅ AGC已启用\n");            // 输出成功信息// 测试静音功能printf("测试静音功能...\n");         // 输出测试信息audio_stream_set_mute(handle, 1);   // 启用静音printf("✅ 静音已启用\n");           // 输出成功信息audio_stream_set_mute(handle, 0);   // 禁用静音printf("✅ 静音已禁用\n");           // 输出成功信息audio_stream_release(handle);       // 释放音频流test_record_result(ctx, 1);         // 记录成功结果return 0;                           // 返回成功
}
​
/*** 测试用例4: 音频编码测试* 设计模式: 策略模式 - 测试不同编码格式* 性能分析: 编码器切换 + 端口管理测试*/
int test_audio_encoding(test_context_t* ctx)
{astream_handle handle;              // 音频流句柄port_info_t *port;                  // 端口信息int ret;                            // 返回值printf("\n🔊 测试4: 音频编码功能\n"); // 输出测试开始信息printf("================================\n"); // 分隔线handle = audio_stream_creat();      // 创建音频流if (handle == NULL) {               // 检查创建是否成功printf("错误: 音频流创建失败\n"); // 输出错误信息test_record_result(ctx, 0);     // 记录失败结果return -1;                      // 返回错误}// 步骤1: 配置编码参数printf("步骤1: 配置编码参数...\n");   // 输出步骤信息audio_stream_set_coding_type(handle, AUDIO_ENCODER_AAC); // 设置AAC编码printf("✅ 编码类型设置为AAC\n");     // 输出成功信息// 步骤2: 启动音频流printf("步骤2: 启动音频流...\n");     // 输出步骤信息ret = audio_stream_start(handle);   // 启动音频流if (ret != 0) {                     // 检查启动是否成功printf("错误: 音频流启动失败\n"); // 输出错误信息audio_stream_release(handle);   // 释放音频流test_record_result(ctx, 0);     // 记录失败结果return -1;                      // 返回错误}printf("✅ 音频流启动成功\n");        // 输出成功信息// 步骤3: 启动编码并获取端口printf("步骤3: 启动音频编码...\n");   // 输出步骤信息port = audio_stream_start_enc(handle); // 启动编码并获取端口if (port == NULL) {                 // 检查端口获取是否成功printf("错误: 编码启动失败\n");   // 输出错误信息audio_stream_stop(handle);      // 停止音频流audio_stream_release(handle);   // 释放音频流test_record_result(ctx, 0);     // 记录失败结果return -1;                      // 返回错误}printf("✅ 编码启动成功, 端口: %p\n", port); // 输出成功信息// 步骤4: 启用编码端口printf("步骤4: 启用编码端口...\n");   // 输出步骤信息ret = audio_stream_enable_port(handle, port); // 启用编码端口if (ret != 0) {                     // 检查启用是否成功printf("错误: 端口启用失败\n");   // 输出错误信息audio_stream_stop_enc(handle, port); // 停止编码audio_stream_stop(handle);      // 停止音频流audio_stream_release(handle);   // 释放音频流test_record_result(ctx, 0);     // 记录失败结果return -1;                      // 返回错误}printf("✅ 编码端口启用成功\n");      // 输出成功信息// 步骤5: 模拟编码数据处理(这里简单等待)printf("步骤5: 模拟编码数据处理...\n"); // 输出步骤信息sleep(2);                           // 等待2秒模拟处理时间printf("✅ 编码数据处理完成\n");      // 输出成功信息// 步骤6: 停止编码printf("步骤6: 停止音频编码...\n");   // 输出步骤信息ret = audio_stream_stop_enc(handle, port); // 停止编码if (ret != 0) {                     // 检查停止是否成功printf("错误: 编码停止失败\n");   // 输出错误信息audio_stream_stop(handle);      // 停止音频流audio_stream_release(handle);   // 释放音频流test_record_result(ctx, 0);     // 记录失败结果return -1;                      // 返回错误}printf("✅ 音频编码停止成功\n");      // 输出成功信息// 步骤7: 停止音频流printf("步骤7: 停止音频流...\n");     // 输出步骤信息ret = audio_stream_stop(handle);    // 停止音频流if (ret != 0) {                     // 检查停止是否成功printf("错误: 音频流停止失败\n"); // 输出错误信息audio_stream_release(handle);   // 释放音频流test_record_result(ctx, 0);     // 记录失败结果return -1;                      // 返回错误}printf("✅ 音频流停止成功\n");        // 输出成功信息audio_stream_release(handle);       // 释放音频流test_record_result(ctx, 1);         // 记录成功结果return 0;                           // 返回成功
}
​
/*** 测试用例5: 多音频流并发测试* 设计模式: 观察者模式 - 监控多个音频流状态* 性能分析: 并发压力测试 + 资源竞争检测*/
int test_multiple_audio_streams(test_context_t* ctx)
{astream_handle handles[2];          // 多个音频流句柄int i;                              // 循环变量printf("\n🎶 测试5: 多音频流并发测试\n"); // 输出测试开始信息printf("================================\n"); // 分隔线// 步骤1: 创建多个音频流printf("步骤1: 创建多个音频流...\n"); // 输出步骤信息for (i = 0; i < 2; i++) {           // 循环创建2个音频流handles[i] = audio_stream_creat(); // 创建音频流if (handles[i] == NULL) {       // 检查创建是否成功printf("错误: 音频流%d创建失败\n", i); // 输出错误信息// 清理已创建的音频流for (int j = 0; j < i; j++) { // 遍历已创建的音频流audio_stream_release(handles[j]); // 释放音频流}test_record_result(ctx, 0); // 记录失败结果return -1;                  // 返回错误}printf("✅ 音频流%d创建成功: %p\n", i, handles[i]); // 输出成功信息}// 步骤2: 配置不同的参数printf("步骤2: 配置不同的参数...\n"); // 输出步骤信息audio_stream_set_sample_rate(handles[0], 44100); // 设置流0采样率44.1kHzaudio_stream_set_channels(handles[0], 1);        // 设置流0为单声道audio_stream_set_coding_type(handles[0], AUDIO_ENCODER_PCM); // 设置流0为PCM编码audio_stream_set_sample_rate(handles[1], 48000); // 设置流1采样率48kHz  audio_stream_set_channels(handles[1], 2);        // 设置流1为立体声audio_stream_set_coding_type(handles[1], AUDIO_ENCODER_AAC); // 设置流1为AAC编码printf("✅ 参数配置完成\n");         // 输出成功信息// 步骤3: 启动多个音频流printf("步骤3: 启动多个音频流...\n"); // 输出步骤信息for (i = 0; i < 2; i++) {           // 循环启动2个音频流if (audio_stream_start(handles[i]) != 0) { // 启动音频流printf("错误: 音频流%d启动失败\n", i); // 输出错误信息// 清理资源for (int j = 0; j < 2; j++) { // 遍历所有音频流if (j <= i) audio_stream_stop(handles[j]); // 停止已启动的流audio_stream_release(handles[j]); // 释放音频流}test_record_result(ctx, 0); // 记录失败结果return -1;                  // 返回错误}printf("✅ 音频流%d启动成功\n", i); // 输出成功信息}// 步骤4: 模拟并发运行printf("步骤4: 模拟并发运行...\n");   // 输出步骤信息sleep(3);                           // 等待3秒模拟并发运行printf("✅ 并发运行完成\n");          // 输出成功信息// 步骤5: 停止和释放所有音频流printf("步骤5: 停止和释放所有音频流...\n"); // 输出步骤信息for (i = 0; i < 2; i++) {           // 循环处理2个音频流audio_stream_stop(handles[i]);  // 停止音频流audio_stream_release(handles[i]); // 释放音频流printf("✅ 音频流%d清理完成\n", i); // 输出成功信息}test_record_result(ctx, 1);         // 记录成功结果return 0;                           // 返回成功
}
​
/*** 测试用例6: 性能基准测试* 设计模式: 模板方法模式 - 标准化性能测试流程* 性能分析: 时间统计 + 资源使用监控*/
int test_performance_benchmark(test_context_t* ctx)
{astream_handle handle;              // 音频流句柄struct timespec start, end;         // 时间统计long long duration;                 // 持续时间printf("\n⏱️  测试6: 性能基准测试\n"); // 输出测试开始信息printf("================================\n"); // 分隔线// 测试创建性能printf("测试音频流创建性能...\n");    // 输出测试信息clock_gettime(CLOCK_MONOTONIC, &start); // 记录开始时间handle = audio_stream_creat();      // 创建音频流clock_gettime(CLOCK_MONOTONIC, &end); // 记录结束时间if (handle == NULL) {               // 检查创建是否成功printf("错误: 性能测试创建失败\n"); // 输出错误信息test_record_result(ctx, 0);     // 记录失败结果return -1;                      // 返回错误}duration = (end.tv_sec - start.tv_sec) * 1000000000LL +  // 计算纳秒时间(end.tv_nsec - start.tv_nsec);printf("✅ 音频流创建时间: %lld 纳秒\n", duration); // 输出创建时间// 测试启动性能printf("测试音频流启动性能...\n");    // 输出测试信息clock_gettime(CLOCK_MONOTONIC, &start); // 记录开始时间audio_stream_start(handle);         // 启动音频流clock_gettime(CLOCK_MONOTONIC, &end); // 记录结束时间duration = (end.tv_sec - start.tv_sec) * 1000000000LL +  // 计算纳秒时间(end.tv_nsec - start.tv_nsec);printf("✅ 音频流启动时间: %lld 纳秒\n", duration); // 输出启动时间// 测试编码启动性能printf("测试编码启动性能...\n");      // 输出测试信息clock_gettime(CLOCK_MONOTONIC, &start); // 记录开始时间port_info_t *port = audio_stream_start_enc(handle); // 启动编码clock_gettime(CLOCK_MONOTONIC, &end); // 记录结束时间if (port) {                         // 如果编码启动成功duration = (end.tv_sec - start.tv_sec) * 1000000000LL +  // 计算纳秒时间(end.tv_nsec - start.tv_nsec);printf("✅ 编码启动时间: %lld 纳秒\n", duration); // 输出编码启动时间// 清理编码audio_stream_stop_enc(handle, port); // 停止编码}// 清理资源audio_stream_stop(handle);          // 停止音频流audio_stream_release(handle);       // 释放音频流test_record_result(ctx, 1);         // 记录成功结果return 0;                           // 返回成功
}
​
// 设计模式: 观察者模式 - 信号处理
void signal_handler(int sig)
{printf("\n收到信号 %d, 正在停止测试...\n", sig); // 输出信号信息g_ctx.running = 0;                  // 设置停止标志
}
​
/*** 主测试函数* 设计模式: 外观模式 - 提供统一的测试接口* 性能分析: 总体测试统计 + 结果汇总*/
int main(int argc, char *argv[])
{test_context_t* ctx;                // 测试上下文int overall_result = 0;             // 总体结果printf("================================\n"); // 分隔线printf("    Linux音频框架测试程序\n");       // 程序标题printf("================================\n"); // 分隔线// 注册信号处理signal(SIGINT, signal_handler);     // 注册Ctrl+C信号处理signal(SIGTERM, signal_handler);    // 注册终止信号处理// 初始化测试上下文ctx = test_context_create();        // 创建测试上下文if (!ctx) {                         // 检查创建是否成功printf("错误: 测试上下文创建失败\n"); // 输出错误信息return -1;                      // 返回错误}printf("测试开始...\n\n");           // 输出开始信息// 执行测试用例if (test_audio_stream_create_release(ctx) != 0) // 测试用例1overall_result = -1;            // 更新总体结果if (test_audio_parameter_config(ctx) != 0) // 测试用例2overall_result = -1;            // 更新总体结果if (test_audio_effects(ctx) != 0)   // 测试用例3overall_result = -1;            // 更新总体结果if (test_audio_encoding(ctx) != 0)  // 测试用例4overall_result = -1;            // 更新总体结果if (test_multiple_audio_streams(ctx) != 0) // 测试用例5overall_result = -1;            // 更新总体结果if (test_performance_benchmark(ctx) != 0) // 测试用例6overall_result = -1;            // 更新总体结果// 输出测试总结printf("\n================================\n"); // 分隔线printf("           测试总结\n");               // 总结标题printf("================================\n"); // 分隔线printf("总测试用例: %d\n", ctx->test_case);   // 输出总测试用例数printf("通过: %d\n", ctx->success_count);     // 输出通过数printf("失败: %d\n", ctx->fail_count);        // 输出失败数printf("成功率: %.2f%%\n",                    // 输出成功率(float)ctx->success_count / ctx->test_case * 100);if (overall_result == 0) {          // 如果总体成功printf("\n🎉 所有测试通过!\n");           // 输出成功信息} else {printf("\n💥 部分测试失败!\n");           // 输出失败信息}// 清理资源test_context_destroy(ctx);          // 销毁测试上下文return overall_result;              // 返回总体结果
}

关键测试函数树形结构对比分析

测试框架结构

test_main
├── test_audio_stream_create_release (基础功能)
│   ├── 音频流创建
│   ├── 状态验证
│   ├── 引用计数
│   └── 资源释放
├── test_audio_parameter_config (参数配置)
│   ├── 采样率设置
│   ├── 采样位宽设置
│   ├── 声道数设置
│   └── 参数回读验证
├── test_audio_effects (音效测试)
│   ├── 回声消除
│   ├── 噪声抑制
│   ├── 自动增益
│   └── 静音控制
├── test_audio_encoding (编码测试)
│   ├── 编码器配置
│   ├── 流启动停止
│   ├── 端口管理
│   └── 编码流程
├── test_multiple_audio_streams (并发测试)
│   ├── 多流创建
│   ├── 参数差异化
│   ├── 并发运行
│   └── 资源清理
└── test_performance_benchmark (性能测试)├── 创建时间├── 启动时间└── 编码时间

与音频框架模块对比

测试模块 ↔ 框架模块
───────────────────────────────
基础功能测试 ↔ audio_stream_creat/release
参数配置测试 ↔ set_sample_rate/width/channels  
音效测试 ↔ set_aec/anr/agc/mute
编码测试 ↔ start_enc/stop_enc + 端口管理
并发测试 ↔ 多实例管理 + 资源分配
性能测试 ↔ 时间统计 + 资源监控

框架管理机制分析

1. 资源管理

  • 引用计数: 通过audio_stream_inc_refcnt管理对象生命周期

  • 端口管理: 使用位图管理分流器端口分配

  • 状态机: 严格的状态转换确保操作序列正确性

2. 并发控制

  • 互斥锁: ASTREAM_LOCK/UNLOCK保护共享资源

  • 线程安全: 所有API都设计为线程安全

  • 资源隔离: 多音频流实例间资源隔离

3. 错误处理

  • 参数验证: oscl_param_check宏进行参数检查

  • 状态验证: 操作前验证状态机状态

  • 资源清理: 失败时自动清理已分配资源

4. 性能优化

  • 对象池: 预分配音频流对象减少动态分配

  • 位图操作: 高效的端口管理

  • 批量操作: 支持多端口批量启用/禁用

这个测试框架全面覆盖了音频框架的所有核心功能,通过模块化的测试用例验证每个组件的正确性和性能。

http://www.dtcms.com/a/544990.html

相关文章:

  • 【AI论文】PICABench:我们在实现物理逼真图像编辑的道路上究竟走了多远?
  • 设计模式之抽象工厂模式:最复杂的工厂模式变种
  • 设计模式>原型模式大白话讲解:就像复印机,拿个原件一复印,就得到一模一样的新东西
  • 网站数据库大小石家庄发布最新消息
  • 本地运行Tomcat项目
  • 大模型如何变身金融风控专家
  • 台州网站建设维护网页设计与制作教程杨选辉
  • 动力网站移动端模板网站建设价格
  • Windows 10终止服务支持:企业IT安全迎来重大考验
  • Mac os安装Easyconnect卡在正在验证软件包
  • 手机网站免费模板下载门户网站 销售
  • 学习和掌握RabbitMQ及其与springboot的整合实践(篇二)
  • Flink、Storm、Spark 区别
  • 当 AI Agent 遇上工作流编排:微软 Agent Framework 的 Workflow 深度解析
  • 5步构建多模式内容策略:统一品牌信息,最大化内容影响力
  • STP 转换为 3DXML 的技术指南及迪威模型网在线转换推荐
  • 如何建设视频网站好的网站设计题目
  • 深入理解 Vite 开发服务器的 Local 与 Network 地址
  • 免费建立网站的网站吗免费软件视频
  • 和利时 PLC 配网
  • 时间序列数据预测:14种机器学习与深度学习模型
  • 手机网站编程语言finecms
  • 第六部分:VTK进阶(第178章 网格质量评估vtkMeshQuality)
  • 多模态+CLIP | 视觉语言交互的终极形态?CLIP融合AIGC与持续学习,重塑多模态AI边界
  • Linux下CMake工具使用与Makefile生成完全指南
  • 关系型数据库、非关系型数据库、结构化数据、半结构化数据、非结构化数据、OLAP、OLTP的关系和区分
  • 成都市成华区建设局网站拐角型布局网站
  • java 文本内容 相似度比对
  • 切换jdk17
  • 定制型网站 成功案例网站建设费 税前扣除吗