重编译 microsip 和 pjsip 支持 mp3 录音

23 篇文章 1 订阅
4 篇文章 1 订阅

前言

使用 MicroSip 源码编译后,在录音配置界面虽然有 mp3 格式选项,但是实际录音后不会生成mp3 文件夹,而选择wav格式却可以正常生成 wav 文件。

经测试发现需要重新编译 pjsip 工程,加入 mp3 编码才可以。

操作步骤大概如下:

1.pjmedia 项目加入如下 pjsip2.12.1版本 third_party/mp3 文件夹中的3个文件

pjsip2.12.1 third_party/mp3 文件夹文件

2.在pjmedia.h 文件中包含刚引入的 mp3_port.h

//...
#include <pjmedia/wav_port.h>
#include <pjmedia/wave.h>
#include <pjmedia/wsola.h>
//增加mp3编码 [2022-7-28 By Pafey]
#include "../../third_party/mp3/mp3_port.h"
//...

3.修改 pjsua_lib 项目的 pjsua_aud.c 文件中的 pjsua_recorder_create 函数

在录音格式判断那里,源码只有处理wav格式,需要多加个mp3格式进去。

需要注意的是第七个参数 pjmedia_mp3_encoder_option param_option;

主要是跟mp3文件的质量有关:

vbr:指定是否应使用可变比特率。可变比特率通常会产生更好的质量,但代价可能是文件更大。

bit_rate:目标比特率,单位为bps。如果启用了VBR,此设置指定请求的平均比特率,并将使编码器忽略质量设置。对于CBR,这指定了实际的比特率,如果该选项为零,它将被设置为采样率乘以通道数量。

quality:编码质量,0-9,以0为最高质量。对于VBR,质量设置只在bit_rate设置为零时生效。

关键代码如下:
    if (file_format == FMT_WAV) {
	status = pjmedia_wav_writer_port_create(pool, path,
						pjsua_var.media_cfg.clock_rate,
						pjsua_var.mconf_cfg.channel_count,
						pjsua_var.mconf_cfg.samples_per_frame,
						pjsua_var.mconf_cfg.bits_per_sample,
						options, 0, &port);
    }
     else if (file_format == FMT_MP3)
    {
    	//增加mp3编码 [2022-7-28 By Pafey]
		pjmedia_mp3_encoder_option param_option;
		param_option.vbr = PJ_TRUE;
		param_option.bit_rate = 0;
		param_option.quality = 6;//0-9,0质量最高,vbr启用时,仅bit_rate为0时有效
		
		status = pjmedia_mp3_writer_port_create(pool, path,
			pjsua_var.media_cfg.clock_rate,
			pjsua_var.mconf_cfg.channel_count,
			pjsua_var.mconf_cfg.samples_per_frame,
			pjsua_var.mconf_cfg.bits_per_sample,
			&param_option, &port);

    } else {
	PJ_UNUSED_ARG(enc_param);
	port = NULL;
	status = PJ_ENOTSUP;
    }
pjsua_recorder_create 函数完整代码:
/*
 * Create a file recorder, and automatically connect this recorder to
 * the conference bridge.
 */
PJ_DEF(pj_status_t) pjsua_recorder_create( const pj_str_t *filename,
					   unsigned enc_type,
					   void *enc_param,
					   pj_ssize_t max_size,
					   unsigned options,
					   pjsua_recorder_id *p_id)
{
    enum Format
    {
	FMT_UNKNOWN,
	FMT_WAV,
	FMT_MP3,
    };
    unsigned slot, file_id;
    char path[PJ_MAXPATH];
    pj_str_t ext;
    int file_format;
    pj_pool_t *pool = NULL;
    pjmedia_port *port;
    pj_status_t status = PJ_SUCCESS;

    /* Filename must present */
    PJ_ASSERT_RETURN(filename != NULL, PJ_EINVAL);

    /* Don't support max_size at present */
    PJ_ASSERT_RETURN(max_size == 0 || max_size == -1, PJ_EINVAL);

    /* Don't support encoding type at present */
    PJ_ASSERT_RETURN(enc_type == 0, PJ_EINVAL);

    if (filename->slen >= PJ_MAXPATH)
    	return PJ_ENAMETOOLONG;
    if (filename->slen < 4)
    	return PJ_EINVALIDOP;

    PJ_LOG(4,(THIS_FILE, "Creating recorder %.*s..",
	      (int)filename->slen, filename->ptr));
    pj_log_push_indent();

    if (pjsua_var.rec_cnt >= PJ_ARRAY_SIZE(pjsua_var.recorder)) {
	pj_log_pop_indent();
	return PJ_ETOOMANY;
    }

    /* Determine the file format */
    ext.ptr = filename->ptr + filename->slen - 4;
    ext.slen = 4;

    if (pj_stricmp2(&ext, ".wav") == 0)
	file_format = FMT_WAV;
    else if (pj_stricmp2(&ext, ".mp3") == 0)
	file_format = FMT_MP3;
    else {
	PJ_LOG(1,(THIS_FILE, "pjsua_recorder_create() error: unable to "
			     "determine file format for %.*s",
			     (int)filename->slen, filename->ptr));
	pj_log_pop_indent();
	return PJ_ENOTSUP;
    }

    PJSUA_LOCK();

    for (file_id=0; file_id<PJ_ARRAY_SIZE(pjsua_var.recorder); ++file_id) {
	if (pjsua_var.recorder[file_id].port == NULL)
	    break;
    }

    if (file_id == PJ_ARRAY_SIZE(pjsua_var.recorder)) {
	/* This is unexpected */
	pj_assert(0);
	status = PJ_EBUG;
	goto on_return;
    }

    pj_memcpy(path, filename->ptr, filename->slen);
    path[filename->slen] = '\0';

    pool = pjsua_pool_create(get_basename(path, (unsigned)filename->slen), 1000, 
			     1000);
    if (!pool) {
	status = PJ_ENOMEM;
	goto on_return;
    }

    if (file_format == FMT_WAV) {
	status = pjmedia_wav_writer_port_create(pool, path,
						pjsua_var.media_cfg.clock_rate,
						pjsua_var.mconf_cfg.channel_count,
						pjsua_var.mconf_cfg.samples_per_frame,
						pjsua_var.mconf_cfg.bits_per_sample,
						options, 0, &port);
    }else if (file_format == FMT_MP3)
    {
		pjmedia_mp3_encoder_option param_option;
		param_option.vbr = PJ_TRUE;
		param_option.bit_rate = 0;
		param_option.quality = 6;//0-9,0质量最高,vbr启用时,仅bit_rate为0时有效
		//增加mp3编码 [2022-7-28 By Pafey]
		status = pjmedia_mp3_writer_port_create(pool, path,
			pjsua_var.media_cfg.clock_rate,
			pjsua_var.mconf_cfg.channel_count,
			pjsua_var.mconf_cfg.samples_per_frame,
			pjsua_var.mconf_cfg.bits_per_sample,
			&param_option, &port);

    } else {
	PJ_UNUSED_ARG(enc_param);
	port = NULL;
	status = PJ_ENOTSUP;
    }

    if (status != PJ_SUCCESS) {
	pjsua_perror(THIS_FILE, "Unable to open file for recording", status);
	goto on_return;
    }

    status = pjmedia_conf_add_port(pjsua_var.mconf, pool,
				   port, filename, &slot);
    if (status != PJ_SUCCESS) {
	pjmedia_port_destroy(port);
	goto on_return;
    }

    pjsua_var.recorder[file_id].port = port;
    pjsua_var.recorder[file_id].slot = slot;
    pjsua_var.recorder[file_id].pool = pool;

    if (p_id) *p_id = file_id;

    ++pjsua_var.rec_cnt;

    PJSUA_UNLOCK();

    PJ_LOG(4,(THIS_FILE, "Recorder created, id=%d, slot=%d", file_id, slot));

    pj_log_pop_indent();
    return PJ_SUCCESS;

on_return:
    PJSUA_UNLOCK();
    if (pool) pj_pool_release(pool);
    pj_log_pop_indent();
    return status;
}

4.编译 libpjproject 项目

生成 libpjproject-i386-Win32-vc14-Release.lib 库文件。就可以被sip软电话引入使用了。我这里用的是MicroSip,在配置界面录音选择 mp3

在这里插入图片描述
打个电话就可以生成mp3文件了,搞了一天终于完美收工。
在这里插入图片描述

问题记录

pjsip编译完成后,引入库文件依然不能生成mp3文件,后面调试进

pjmedia_mp3_writer_port_create -> init_blade_dll 

这个初始化需要加载 LAME_ENC.DLL
去 microsip 安装文件夹内拷一个出来放到自己编译的microsip exe所在路径就成功了
文末放了下载地址

#include <windows.h>
#define DLL_NAME    PJ_T("LAME_ENC.DLL")

/*
 * Load BladeEncoder DLL.
 */
static pj_status_t init_blade_dll(void)
{
    if (BladeDLL.refCount == 0) {
	#define GET_PROC(type, name)  \
	    BladeDLL.name = (type)GetProcAddress(BladeDLL.hModule, PJ_T(#name)); \
	    if (BladeDLL.name == NULL) { \
		PJ_LOG(1,(THIS_FILE, "Unable to find %s in %s", #name, DLL_NAME)); \
		return PJ_RETURN_OS_ERROR(GetLastError()); \
	    }

	BE_VERSION beVersion;
	BladeDLL.hModule = (void*)LoadLibrary(DLL_NAME);
	if (BladeDLL.hModule == NULL) {
	    pj_status_t status = PJ_RETURN_OS_ERROR(GetLastError());
	    char errmsg[PJ_ERR_MSG_SIZE];

	    pj_strerror(status, errmsg, sizeof(errmsg));
	    PJ_LOG(1,(THIS_FILE, "Unable to load %s: %s", DLL_NAME, errmsg));
	    return status;
	}
//...
	}

编译的库文件

库文件和编码dll下载地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要创建一个可编译的工程,我们需要按照以下步骤进行: 1. 下载和安装Visual Studio 2017。确保选择的是支持C++的版本,并选择安装适用于开发桌面应用程序的组件。 2. 下载pjsip 2.7.1,ffmpeg 3.2.4,sdl2.0.7 和MicroSIP3.16.4的源代码。 3. 解压缩下载的源代码文件。 4. 打开Visual Studio 2017,选择“文件”菜单中的“新建”和“项目”。 5. 在“新建项目”对话框中,选择“Visual C++”和“空项目”,然后为项目命名并选择保存。 6. 在“解决方案资源管理器”窗口中,右键单击新建的项目并选择“属性”。 7. 在“属性页”中,选择“C/C++”、“常规”,然后将pjsip、ffmpeg、sdl2和MicroSIP的头文件路径添加到“附加包含目录”中。 8. 在同一属性页上,选择“链接器”、“常规”,并将pjsip、ffmpeg、sdl2和MicroSIP的库文件路径添加到“附加库目录”中。 9. 继续在“链接器”下选择“输入”,将pjsip、ffmpeg、sdl2和MicroSIP的库文件名添加到“附加依赖项”中。 10. 单击“应用”按钮保存更改并关闭“属性页”。 11. 在“解决方案资源管理器”窗口中,右键单击“源文件”文件夹,并选择“添加”和“现有项”。 12. 在“添加现有项”对话框中,选择pjsip、ffmpeg、sdl2和MicroSIP的源代码文件,并单击“添加”。 13. 右键单击项目,选择“生成”和“生成解决方案”。 14. 如果没有任何错误,那么你的项目应该被编译成功了。 以上步骤应该可以帮助你在Visual Studio 2017中创建一个可编译的工程,包含pjsip 2.7.1,ffmpeg 3.2.4,sdl2.0.7和MicroSIP3.16.4的资源。如果你遇到任何问题,请仔细检查每个步骤是否正确执行,并确保所有的依赖项都正确配置。 ### 回答2: 要在VS2017中创建一个可编译工程,包括pjsip 2.7.1、ffmpeg 3.2.4、sdl2.0.7和microsip 3.16.4,需要按照以下步骤进行操作: 1. 下载并安装Visual Studio 2017。确保选择了正确的版本(Community、Professional或Enterprise),并安装C++开发工具。 2. 下载并解压pjsip 2.7.1、ffmpeg 3.2.4、sdl2.0.7和microsip 3.16.4的源代码。确保解压的文件夹路径没有中文或特殊字符。 3. 打开Visual Studio 2017,并选择“新建项目”。 4. 在新建项目窗口的左侧面板中选择“Visual C++”节点,并选择“空项目”。 5. 输入项目名称,并选择项目的保存路径。 6. 单击“确定”按钮。 7. 在解决方案资源管理器中,右键单击项目,选择“属性”。 8. 在属性管理器中,选择“平台”和“所有配置”,然后选择“VC++目录”。 9. 在“包含目录”中,添加pjsip、ffmpeg、sdl2和microsip的源代码路径。 10. 在“库目录”中,添加pjsip、ffmpeg、sdl2和microsip的库文件路径。 11. 在“链接器”下的“输入”中,添加以下附加依赖项: pjsua2.lib pjmedia-codec.lib ffmpeg.lib sdl2.lib microsip.lib 12. 单击“应用”按钮,然后关闭属性管理器。 13. 在解决方案资源管理器中,右键单击项目,选择“添加”->“现有项”。 14. 选择pjsip、ffmpeg、sdl2和microsip的源代码文件,并将其添加到项目中。 15. 在解决方案资源管理器中,右键单击项目,选择“生成”。 16. 等待编译和链接完成。 17. 如果没有错误和警告,说明编译成功。 总结: 以上是在VS2017中创建一个可编译工程,包括pjsip 2.7.1、ffmpeg 3.2.4、sdl2.0.7和microsip 3.16.4的步骤。确保按照指定的顺序安装和配置所需的软件和库,并确保路径设置正确,以避免编译错误。 ### 回答3: 要在VS2017上创建一个可编译的工程,使用以下步骤: 1. 首先,确保已经正确安装了VS2017,并且安装了所有必需的组件和工具。 2. 下载并安装对应版本的pjsip、ffmpeg、sdl2和microsip。将它们解压到适当的位置。 3. 打开VS2017,并创建一个新的空项目。 4. 在项目资源管理器中,右键单击项目名称,选择“属性”。 5. 在“属性”窗口中,选择“VC++目录”选项卡。 6. 在“包含目录”中,添加pjsip、ffmpeg、sdl2和microsip的头文件目录。 7. 在“库目录”中,添加pjsip、ffmpeg、sdl2和microsip的库文件目录。 8. 在“链接器”选项卡下的“输入”中,添加pjsip、ffmpeg、sdl2和microsip的库文件。 9. 选择“编译”选项卡,将“C++”->“常规”->“附加包含目录”设置为pjsip、ffmpeg、sdl2和microsip的头文件目录。 10. 在“链接器”选项卡下,将“输入”->“附加依赖项”设置为pjsip、ffmpeg、sdl2和microsip的库文件。 11. 确认所有设置后,编译并运行项目。 这样,你就可以在VS2017中创建一个可编译的工程,使用pjsip 2.7.1、ffmpeg 3.2.4、sdl2.0.7和microsip 3.16.4。请注意,根据你的项目需求,你可能还需要稍作调整和配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值