/* Callback called by the library when call's media state has changed */
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;
// В новых версиях PJSIP доступ идет через медиа-индекс,
// используем ваш рабочий вариант обращения к порту стрима:
media_port = pjsua_var.calls[call_id].media[0].strm.a.media_port;
if (!media_port) {
printf("[MEDIA] Error: Failed to get call media port\n");
return;
}
unsigned negotiated_rate = media_port->info.fmt.det.aud.clock_rate;
/*
* ИСПРАВЛЕНИЕ: Получаем конфигурацию моста через официальный API,
* чтобы избежать ошибки incomplete typedef 'pjmedia_conf'
*/
pjsua_media_config media_cfg;
pjsua_media_config_default(&media_cfg);
if (pjsua_conf_get_config(&media_cfg) == PJ_SUCCESS) {
unsigned current_bridge_rate = media_cfg.clock_rate;
printf("Detected sound codec rate=%u Hz (Current Bridge=%u Hz)\n",
negotiated_rate, current_bridge_rate);
// Проверяем рассинхронизацию частот
if (negotiated_rate != current_bridge_rate) {
printf("[MEDIA_ALIGN] Rate mismatch! Scheduling async pjsua_call_reinvite...\n");
struct reinvite_ctx *ctx = malloc(sizeof(struct reinvite_ctx));
pj_timer_entry *timer_entry = malloc(sizeof(pj_timer_entry));
if (ctx && timer_entry) {
ctx->call_id = call_id;
pj_timer_entry_init(timer_entry, 0, ctx, &async_reinvite_cb);
// Задержка 10 мс
pj_time_val delay = {0, 10};
pjsua_schedule_timer(timer_entry, &delay);
} else {
printf("[MEDIA_ALIGN] Error: OOM allocation for reinvite task failed\n");
}
} else {
pjsua_var.media_cfg.snd_clock_rate = negotiated_rate;
printf("Rates match. Set snd_clock_rate=%u\n", pjsua_var.media_cfg.snd_clock_rate);
}
} else {
printf("[MEDIA_ALIGN] Error: Failed to get bridge config\n");
}
}
#endif
// When media is active, connect call to sound device.
pjsua_conf_connect(ci.conf_slot, 0);
pjsua_conf_connect(0, ci.conf_slot);
}
}