static void on_call_media_state(pjsua_call_id call_id)
{
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
#ifdef USE_DYNAMIC_AUDIO_RATE
pjsua_call_media_info *media = &ci.media;
if (media->type == PJMEDIA_TYPE_AUDIO) {
pjmedia_port *media_port = NULL;
media_port = pjsua_var.calls[call_id].media.strm.a.media_port;
if (media_port) {
// Получаем частоту, которую согласовал кодек (например, 8000 или 16000)
unsigned negotiated_rate = media_port->info.fmt.det.aud.clock_rate;
// Получаем текущую частоту звукового устройства (Port 0)
pjmedia_conf_port_info port0_info;
if (pjmedia_conf_get_port_info(pjsua_var.mconf, 0, &port0_info) == PJ_SUCCESS) {
/*
* Если согласованная частота кодека отличается от текущей частоты звуковой карты,
* мы принудительно переоткрываем аудио-девайс Zephyr на новой частоте.
*/
if (port0_info.clock_rate != negotiated_rate) {
printf("[MEDIA_ALIGN] Rate mismatch: Audio Device=%u Hz, Codec=%u Hz. Reopening...\n",
port0_info.clock_rate, negotiated_rate);
// 1. Фиксируем новую частоту в глобальной конфигурации медиа
pjsua_var.media_cfg.snd_clock_rate = negotiated_rate;
// Если кодек поменял SPF (Samples Per Frame), тоже обновляем его
unsigned negotiated_spf = media_port->info.fmt.det.aud.frame_time_usec * negotiated_rate / 1000000;
pjsua_var.media_cfg.samples_per_frame = negotiated_spf;
// 2. Вызываем легальное переоткрытие звукового устройства PJSIP.
// Эта функция закроет старый звуковой порт, перенастроит I2S на плате IMXRT1064
// и создаст новый звуковой порт с правильным clock_rate.
pj_status_t snd_status = pjsua_set_snd_dev(pjsua_var.cap_dev, pjsua_var.play_dev);
if (snd_status != PJ_SUCCESS) {
printf("[MEDIA_ALIGN] Error: Failed to reopen sound device: %d\n", snd_status);
} else {
printf("[MEDIA_ALIGN] Sound device successfully restarted at %u Hz!\n", negotiated_rate);
}
}
}
}
}
#endif
// Теперь, когда звуковое устройство гарантированно работает на той же частоте,
// что и кодек, выполняем коммутацию в мосту. Ресемплинг не включится!
pjsua_conf_connect(ci.conf_slot, 0);
pjsua_conf_connect(0, ci.conf_slot);
}
}