HarmonyOS 鸿蒙Next pjsip如何对接audio dev设备?

发布于 1周前 作者 sinazl 最后一次编辑是 5天前 来自 鸿蒙OS

问题描述 目前我正在做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

2 回复

相应专家正在复现分析、解决中

更多关于HarmonyOS 鸿蒙Next pjsip如何对接audio dev设备?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙系统中,对接pjsip的audio dev设备,需要遵循以下步骤:

  1. 获取AudioManager:首先,通过系统API获取AudioManager实例,这是管理音频设备的基础。

  2. 配置Audio Device:使用AudioManager配置音频设备参数,如输入/输出设备类型、采样率、通道数等,确保pjsip的音频数据与设备兼容。

  3. pjsip音频回调设置:在pjsip的音频回调函数中,设置音频数据的读取和写入逻辑,通常涉及从AudioManager获取输入数据,以及将pjsip处理后的输出数据写入AudioManager。

  4. 音频流管理:确保pjsip的音频流与AudioManager管理的音频流同步,避免音频延迟或丢失。

  5. 错误处理:在对接过程中,加入错误处理逻辑,如设备不可用、参数设置失败等情况,确保系统稳定性。

  6. 测试与验证:完成对接后,进行充分的测试,验证pjsip与audio dev设备的兼容性、音频质量、延迟等性能指标。

以上步骤是实现pjsip与HarmonyOS鸿蒙系统audio dev设备对接的基本流程。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。

回到顶部