void ac_iterate(ACSession *ac) { if (!ac) { return; } /* TODO(mannol): fix this and jitter buffering */ /* Enough space for the maximum frame size (120 ms 48 KHz stereo audio) */ int16_t tmp[5760 * 2]; struct RTPMessage *msg; int rc = 0; pthread_mutex_lock(ac->queue_mutex); while ((msg = jbuf_read((struct JitterBuffer *)ac->j_buf, &rc)) || rc == 2) { pthread_mutex_unlock(ac->queue_mutex); if (rc == 2) { LOGGER_DEBUG(ac->log, "OPUS correction"); int fs = (ac->lp_sampling_rate * ac->lp_frame_duration) / 1000; rc = opus_decode(ac->decoder, NULL, 0, tmp, fs, 1); } else { /* Get values from packet and decode. */ /* NOTE: This didn't work very well */ #if 0 rc = convert_bw_to_sampling_rate(opus_packet_get_bandwidth(msg->data)); if (rc != -1) { cs->last_packet_sampling_rate = rc; } else { LOGGER_WARNING(ac->log, "Failed to load packet values!"); rtp_free_msg(msg); continue; } #endif /* Pick up sampling rate from packet */ memcpy(&ac->lp_sampling_rate, msg->data, 4); ac->lp_sampling_rate = net_ntohl(ac->lp_sampling_rate); ac->lp_channel_count = opus_packet_get_nb_channels(msg->data + 4); /** NOTE: even though OPUS supports decoding mono frames with stereo decoder and vice versa, * it didn't work quite well. */ if (!reconfigure_audio_decoder(ac, ac->lp_sampling_rate, ac->lp_channel_count)) { LOGGER_WARNING(ac->log, "Failed to reconfigure decoder!"); free(msg); continue; } rc = opus_decode(ac->decoder, msg->data + 4, msg->len - 4, tmp, 5760, 0); free(msg); } if (rc < 0) { LOGGER_WARNING(ac->log, "Decoding error: %s", opus_strerror(rc)); } else if (ac->acb.first) { ac->lp_frame_duration = (rc * 1000) / ac->lp_sampling_rate; ac->acb.first(ac->av, ac->friend_number, tmp, rc, ac->lp_channel_count, ac->lp_sampling_rate, ac->acb.second); } return; } pthread_mutex_unlock(ac->queue_mutex); }
void cs_do(CSSession *cs) { /* Codec session should always be protected by call mutex so no need to check for cs validity */ if (!cs) return; Payload *p; int rc; int success = 0; pthread_mutex_lock(cs->queue_mutex); RTPMessage *msg; while ((msg = jbuf_read(cs->j_buf, &success)) || success == 2) { pthread_mutex_unlock(cs->queue_mutex); uint16_t fsize = ((cs->audio_decoder_sample_rate * cs->audio_decoder_frame_duration) / 1000); int16_t tmp[fsize * cs->audio_decoder_channels]; if (success == 2) { rc = opus_decode(cs->audio_decoder, 0, 0, tmp, fsize, 1); } else { rc = opus_decode(cs->audio_decoder, msg->data, msg->length, tmp, fsize, 0); rtp_free_msg(NULL, msg); } if (rc < 0) { LOGGER_WARNING("Decoding error: %s", opus_strerror(rc)); } else if (cs->acb.first) { /* Play */ cs->acb.first(cs->agent, cs->call_idx, tmp, rc, cs->acb.second); } pthread_mutex_lock(cs->queue_mutex); } if (cs->vbuf_raw && !buffer_empty(cs->vbuf_raw)) { /* Decode video */ buffer_read(cs->vbuf_raw, &p); /* Leave space for (possibly) other thread to queue more data after we read it here */ pthread_mutex_unlock(cs->queue_mutex); rc = vpx_codec_decode(&cs->v_decoder, p->data, p->size, NULL, MAX_DECODE_TIME_US); free(p); if (rc != VPX_CODEC_OK) { LOGGER_ERROR("Error decoding video: %s", vpx_codec_err_to_string(rc)); } else { vpx_codec_iter_t iter = NULL; vpx_image_t *dest = vpx_codec_get_frame(&cs->v_decoder, &iter); /* Play decoded images */ for (; dest; dest = vpx_codec_get_frame(&cs->v_decoder, &iter)) { if (cs->vcb.first) cs->vcb.first(cs->agent, cs->call_idx, dest, cs->vcb.second); vpx_img_free(dest); } } return; } pthread_mutex_unlock(cs->queue_mutex); }