HarmonyOS 鸿蒙Next pjsip如何对接audio dev设备?
问题描述 目前我正在做pjsip对于harmonyos的适配,其中涉及到对接audio dev的问题。 我采用了OHAudio的接口,进行音频的获取与播放。其中音频的播放与获取都是harmonyos的提供的线程进行回调,这些线程没有在pjsip中进行注册,会导致harmonyos回调pjsip中的函数失败。 这种问题有办法绕过或者有什么api能够不使用harmonyos的线程进行回调吗?
pjsip: 2.14.1
harmonyos: 5.0.1(13)
code
static OH_AudioData_Callback_Result HOSRenderCallback(OH_AudioRenderer *renderer, void *userData, void *buffer, int32_t bufferLen)
{
// register_thread();
// PJ_LOG(5, (THIS_FILE, "Ready to Render thread started"));
// struct hos_aud_stream *stream = (struct hos_aud_stream*) userData;
// int size = stream->play_buf_size;
// char buf[1024] = {'\0'};
//
// if (!stream->render) {
// goto on_return;
// }
//
// PJ_LOG(5, (THIS_FILE, "Render thread started"));
//
// if (!stream->quit_flag) {
// pjmedia_frame frame;
// pj_status_t status;
// int bytesWritten;
//
// if (!stream->running) {
// //pj_sem_wait(stream->play_sem);
// if (stream->quit_flag)
// goto on_return;
// }
//
// frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
// frame.size = size;
// frame.buf = (void *)buf;
// frame.timestamp.u64 = stream->play_timestamp.u64;
// frame.bit_info = 0;
//
// status = (*stream->play_cb)(stream->user_data, &frame);
// if (status != PJ_SUCCESS)
// goto on_return;
//
// if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO)
// pj_bzero(frame.buf, frame.size);
//
// pj_memcpy(buffer, frame.buf, size);
// stream->play_timestamp.u64 += stream->param.samples_per_frame /
// stream->param.channel_count;
// };
//
//on_return:
// PJ_LOG(5, (THIS_FILE, "Player thread stopped"));
// stream->play_thread_exited = 1;
return AUDIO_DATA_CALLBACK_RESULT_VALID;
}
// 这是代码片段
if (stream->dir & PJMEDIA_DIR_PLAYBACK) {
rs = OH_AudioStreamBuilder_Create(&stream->rendererBuilder, AUDIOSTREAM_TYPE_RENDERER);
if (rs != AUDIOSTREAM_SUCCESS) {
PJ_LOG(3, (THIS_FILE, "Unsupported audio render params"));
status = PJMEDIA_EAUD_INIT;
goto on_error;
}
rs = OH_AudioStreamBuilder_SetSamplingRate(stream->rendererBuilder, param->clock_rate);
if (rs != AUDIOSTREAM_SUCCESS) {
PJ_LOG(3, (THIS_FILE, "Unable to set render builder audio sample rate"));
status = PJMEDIA_EAUD_SYSERR;
goto on_error;
}
rs = OH_AudioStreamBuilder_SetChannelCount(stream->rendererBuilder, param->channel_count);
if (rs != AUDIOSTREAM_SUCCESS) {
PJ_LOG(3, (THIS_FILE, "Unable to set render builder audio channel count"));
status = PJMEDIA_EAUD_SYSERR;
goto on_error;
}
// rs = OH_AudioStreamBuilder_SetSampleFormat(stream->rendererBuilder, AUDIOSTREAM_SAMPLE_S16LE);
// if (rs != AUDIOSTREAM_SUCCESS) {
// PJ_LOG(3, (THIS_FILE, "Unable to set render builder audio sample format"));
// status = PJMEDIA_EAUD_SYSERR;
// goto on_error;
// }
// rs = OH_AudioStreamBuilder_SetEncodingType(stream->rendererBuilder, AUDIOSTREAM_ENCODING_TYPE_RAW);
// if (rs != AUDIOSTREAM_SUCCESS) {
// PJ_LOG(3, (THIS_FILE, "Unable to set render builder audio encoding type"));
// status = PJMEDIA_EAUD_SYSERR;
// goto on_error;
// }
// rs = OH_AudioStreamBuilder_SetRendererInfo(stream->rendererBuilder, AUDIOSTREAM_USAGE_VOICE_COMMUNICATION);
// if (rs != AUDIOSTREAM_SUCCESS) {
// PJ_LOG(3, (THIS_FILE, "Unable to set render builder audio render info"));
// status = PJMEDIA_EAUD_SYSERR;
// goto on_error;
// }
// OH_AudioStreamBuilder_SetFrameSizeInCallback(stream->rendererBuilder, 2500);
rs = OH_AudioStreamBuilder_SetLatencyMode(stream->rendererBuilder, AUDIOSTREAM_LATENCY_MODE_NORMAL);
if (rs != AUDIOSTREAM_SUCCESS) {
PJ_LOG(3, (THIS_FILE, "Unable to set render builder audio latency mode normal"));
status = PJMEDIA_EAUD_SYSERR;
goto on_error;
}
rs = OH_AudioStreamBuilder_SetRendererOutputDeviceChangeCallback(stream->rendererBuilder,
&HOSOutputDeviceChangeCallback,
NULL);
if (rs != AUDIOSTREAM_SUCCESS) {
PJ_LOG(3, (THIS_FILE, "Unable to set render output device change %d", rs));
status = PJMEDIA_EAUD_SYSERR;
goto on_error;
}
// rs = OH_AudioStreamBuilder_SetRendererWriteDataCallback(stream->rendererBuilder, &HOSRenderCallback, &stream);
// if (rs != AUDIOSTREAM_SUCCESS) {
// PJ_LOG(3, (THIS_FILE, "Unable to set write data callback %d", rs));
// status = PJMEDIA_EAUD_SYSERR;
// goto on_error;
// }
}
if (stream->dir & PJMEDIA_DIR_PLAYBACK) {
OH_AudioRenderer_Callbacks rendererCallbacks;
rendererCallbacks.OH_AudioRenderer_OnWriteData = &HOSRenderCallback;
rendererCallbacks.OH_AudioRenderer_OnError = NULL;
rendererCallbacks.OH_AudioRenderer_OnInterruptEvent = NULL;
rendererCallbacks.OH_AudioRenderer_OnStreamEvent = NULL;
rs = OH_AudioStreamBuilder_SetRendererCallback(stream->rendererBuilder, rendererCallbacks, NULL);
if (rs != AUDIOSTREAM_SUCCESS) {
PJ_LOG(3, (THIS_FILE, "Fail to Set Render callback %d.", rs));
status = PJMEDIA_EAUD_INIT;
goto on_error;
}
// create OH_AudioRenderer
rs = OH_AudioStreamBuilder_GenerateRenderer(stream->rendererBuilder, &stream->render);
if (rs != AUDIOSTREAM_SUCCESS) {
PJ_LOG(3, (THIS_FILE, "Failure in initializing render %d.", rs));
status = PJMEDIA_EAUD_INIT;
goto on_error;
}
PJ_LOG(4, (THIS_FILE, "Audio render initialized successfully."));
}
// if (stream->dir & PJMEDIA_DIR_CAPTURE) {
// OH_AudioCapturer_Callbacks callbacks;
// callbacks.OH_AudioCapturer_OnReadData = HOSRecorderCallback;
// callbacks.OH_AudioCapturer_OnStreamEvent = NULL;
// callbacks.OH_AudioCapturer_OnInterruptEvent = NULL;
// callbacks.OH_AudioCapturer_OnError = NULL;
// OH_AudioStreamBuilder_SetCapturerCallback(stream->captureBuilder, callbacks, &stream);
//
// rs = OH_AudioStreamBuilder_GenerateCapturer(stream->captureBuilder, &stream->capturer);
// if (rs != AUDIOSTREAM_SUCCESS) {
// PJ_LOG(3, (THIS_FILE, "Failure in initializing capture %d.", rs));
// status = PJMEDIA_EAUD_INIT;
// goto on_error;
// }
// PJ_LOG(4, (THIS_FILE, "Audio record initialized successfully."));
// }
日志
LastFatalMessage:Assertion failed: !"Calling pjlib from unknown/external thread. You must " "register external threads with pj_thread_register() " "before calling any pjlib functions." (../src/pj/os_core_unix.c: pj_thread_this: 859)IAudioPolicyClient
Fault thread info:
Tid:21976, Name:OS_IPC_2_21976
#00 pc 00000000000fb0fd /system/lib/ld-musl-x86_64.so.1(raise+141)(fb7824806b595afc3892b76169e5e74b)
#01 pc 00000000000a2871 /system/lib/ld-musl-x86_64.so.1(abort+17)(fb7824806b595afc3892b76169e5e74b)
#02 pc 00000000000a2b2c /system/lib/ld-musl-x86_64.so.1(__assert_fail+508)(fb7824806b595afc3892b76169e5e74b)
#03 pc 00000000001158d1 /data/storage/el1/bundle/libs/x86_64/libonesip.so(pj_thread_this+65)(ac37d9ce76eab3b2c5b5ee983077ef9d08d1fa5d)
R
更多关于HarmonyOS 鸿蒙Next pjsip如何对接audio dev设备?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
相应专家正在复现分析、解决中
更多关于HarmonyOS 鸿蒙Next pjsip如何对接audio dev设备?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙系统中,对接pjsip的audio dev设备,需要遵循以下步骤:
-
获取AudioManager:首先,通过系统API获取AudioManager实例,这是管理音频设备的基础。
-
配置Audio Device:使用AudioManager配置音频设备参数,如输入/输出设备类型、采样率、通道数等,确保pjsip的音频数据与设备兼容。
-
pjsip音频回调设置:在pjsip的音频回调函数中,设置音频数据的读取和写入逻辑,通常涉及从AudioManager获取输入数据,以及将pjsip处理后的输出数据写入AudioManager。
-
音频流管理:确保pjsip的音频流与AudioManager管理的音频流同步,避免音频延迟或丢失。
-
错误处理:在对接过程中,加入错误处理逻辑,如设备不可用、参数设置失败等情况,确保系统稳定性。
-
测试与验证:完成对接后,进行充分的测试,验证pjsip与audio dev设备的兼容性、音频质量、延迟等性能指标。
以上步骤是实现pjsip与HarmonyOS鸿蒙系统audio dev设备对接的基本流程。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。