【原】AMR音频解码插件开发总结
近段时间一直在忙碌AMR音频解码插件的开发,由于对驱动开发和音频编解码知识了解不是很多,加之自身经验欠缺,致使开发过程中碰到太多棘手的问题。经过努力学习和领导的大力帮助下终于完成了插件的开发,现将开发过程中得来的经验总结下来,为近段时间自己学来的东西理个头绪,也为今后有类似开发的朋友一个参考。
AMR解码插件开发之环境配置
本文开发此插件是在Windows XP环境下进行,需要安装WinXPDDK进行编译,另外需要AMR-NB(Adaptive Multi-Rate Narrowband)编解码相对应的动态链接库。(由于WinDDK的调试非常困难,在开发过程中经常弄不清楚问题出在什么地方,所以使用写文件日志和MessageBox的方法进行跟踪调试,但是此调试手段实在太耗神。。。有文章介绍可以安装WindDbg来进行调试,由于时间紧任务急没来得及研究,以后研究学习。。)
安装及配置步骤:
1. 安装WinXPDDK(最好按照默认的路径进行安装,要进行Audio音频插件开发,所以对应的audio组建最好选上)
2. 在C:\WINDDK\2600\src\wdm\audio下创建AMR工程
3. 配置工程对应的编译环境:修改\audio目录下对应的dirs文件,将编译路径设为amr文件夹;sources文件中规定了编译生成的文件名、文件类型、链接库配置、编译的对应文件*.c等文件;另外需要改动的配置文件有:amr.def指明了工程入口;camr.inf安装配置文件;这些文件的配置按照安装的Audio模板修改相应的参数即可。
4. 编译:开始->程序->Development Kits->Windows DDK 2600->Build Enviroments->Win XP Checked Build Environment,在弹出的窗口中输入build即可。
5. 编译后生成的文件在..\AMR\\objchk\i386中,文件名为*.acm,将camr.inf文件拷入此文件夹下,鼠标选中右键点击安装即可,相应的信息便写入注册表。(查看是否正确安装:控制面板的设备管理器->声音、视频和游戏控制器->音频编码解码器->属性,查看对应的音频编解码器列表中是否存在)
AMR解码插件开发之ACM音频编解码管理器
ACM是通用的音频编解码管理器,固定的接口函数为:DriverProc,通过不同的消息uMsg来调用不同的函数,下面列出在开发过程中可能需要改动的函数:
DRV_LOAD 驱动加载
DRV_FREE 驱动退出
DRV_OPEN 打开插件
DRV_CLOSE 关闭插件
DRV_CONFIGURE 配置插件
ACMDM_FORMAT_DETAILS 根据FormatTag设置文件存储的音频参数
ACMDM_FORMATTAG_DETAILS 得到指定的FormatTag的ACMFORMATTAGDETAILS
ACMDM_STREAM_OPEN 音频流打开,确定是编码流还是解码流,做相应的初始化工作,调用相对应的编\解码初始化函数、
ACMDM_STREAM_CLOSE 关闭音频流,做相对应的内存释放工作和对应的编\解码退出函数
ACMDM_STREAM_SIZE 设置音频流的SrcLength和DstLength
ACMDM_STREAM_CONVERT 调用编\解码函数。
具体的工作需要具体解决。
AMR解码插件开发之动态调用DLL
众所周之,动态链接库在VC中的方法有很多种,因为在开发过程中碰到了动态链接库的调用问题,所以将标准库调用方法总结一下。
VC中常使用方法:
方法一:直接在Project->Settings->Link中进行添加
方法二:使用#pragma comment(lib, “*.lib”)进行调用
方法三:动态LoadLibrary进行调用(1.LoadLibrary,装载动态库;2.GetProcAddress:获取要引入的函数,将符号名或标识号转换为DLL内部地址;3.FreeLibrary,释放动态链接库)
可能是提供给的AMR动态链接库和静态链接库存在一些错误,在Sources文件中TARGETLIBS直接添加对应的链接库后进行函数调用总是编译报错,所以经过尝试后终于用动态Load方式解决的标准库无法调用的问题。
本文方法如下:
首先在头文件中定义动态加载DLL的变量和需要使用的函数指针:
// 动态加载Dll
HMODULE hDllLib;
// 定义函数指针,用于动态加载dll来调用函数
typedef HI_S32 (*AMRDecodeInit)(HI_VOID **);
typedef HI_S32 (*AMRDecodeFrame)(HI_VOID *, HI_U8 *, HI_S16 *, enum Format);
typedef HI_S32 (*AMRGetLength)(enum Format, HI_U8);
typedef HI_VOID (*AMRDecodeExit)(HI_VOID **);
//标准库中对应函数的地址
AMRDecodeInit amr_Decode_init;
AMRDecodeFrame amr_Decode_Frame;
AMRDecodeExit amr_Decode_Exit;
AMRGetLength amr_Get_Length;
然后初始化时进行动态加载Dll和记录对应函数的地址
//动态加载用到的Dll
hDllLib = LoadLibrary("lib_amr_dll.dll");
if (hDllLib != NULL)
{
amr_Decode_init = (AMRDecodeInit)GetProcAddress(hDllLib, "AMR_Decode_Init");
…
}
在结束时要释放动态链接库:
// 释放动态加载的Dll
if (NULL != hDllLib)
{
FreeLibrary(hDllLib);
hDllLib = NULL;
}