int audio_device_reconfigure(session_t *sp) { audio_config prev_config, *curr_config, *new_config; audio_port_t iport = 0, oport = 0; int change_req; assert(sp->new_config != NULL); new_config = sp->new_config; change_req = FALSE; if (new_config->device == 0) { /* No request to change audio device */ new_config->device = sp->audio_device; } else if (new_config->device != sp->audio_device) { /* Request to change device */ change_req = TRUE; debug_msg("Change device requested.\n"); } if (sp->audio_device) { iport = audio_get_iport(sp->audio_device); oport = audio_get_oport(sp->audio_device); } if (new_config->primary == 0) { /* No request to change primary encoding */ new_config->primary = codec_get_by_payload(sp->encodings[0]); } else if (codec_audio_formats_compatible(new_config->primary, codec_get_by_payload(sp->encodings[0])) == FALSE) { /* Request to change primary and format incompatible so * device needs rejigging */ change_req = TRUE; debug_msg("Change primary requested.\n"); } else { /* Request to change primary to compatible coding. */ sp->encodings[0] = codec_get_payload(new_config->primary); } if (new_config->render_3d == -1) { /* No request to change 3d rendering */ new_config->render_3d = sp->render_3d; } else if (new_config->render_3d != sp->render_3d) { change_req = TRUE; debug_msg("Change 3d rendering enabled requested.\n"); } if (change_req) { /* Store current config in case it reconfig attempt fails */ prev_config.device = sp->audio_device; prev_config.primary = codec_get_by_payload(sp->encodings[0]); prev_config.render_3d = sp->render_3d; if (sp->audio_device) { audio_device_release(sp, sp->audio_device); } if (audio_device_attempt_config(sp, new_config)) { /* New config acceptable */ curr_config = new_config; } else if (audio_device_attempt_config(sp, &prev_config)) { /* else attempt to fallback to previous config */ curr_config = &prev_config; debug_msg("Fellback to old dev config\n"); } else { /* Fallback to guaranteed config - something * went badly wrong */ ac_destroy(&new_config); audio_device_get_safe_config(&new_config); assert(new_config); if (audio_device_attempt_config(sp, new_config) == FALSE) { /* should never get here */ abort(); } curr_config = new_config; debug_msg("Fell back to safe config\n"); } debug_msg("0x%08x 0x%08x\n", prev_config.device, curr_config->device); if (prev_config.device == curr_config->device) { debug_msg("Restoring ports\n"); audio_set_iport(curr_config->device, iport); audio_set_oport(curr_config->device, oport); } else { const audio_port_details_t *papd; /* Ports will be squiffy */ papd = audio_get_iport_details(curr_config->device, 0); audio_set_iport(curr_config->device, papd->port); papd = audio_get_oport_details(curr_config->device, 0); audio_set_oport(curr_config->device, papd->port); } audio_loopback(curr_config->device, sp->loopback_gain); sp->audio_device = curr_config->device; sp->encodings[0] = codec_get_payload(curr_config->primary); /* If using redundancy check it is still relevent */ if (sp->num_encodings > 1 && !codec_audio_formats_compatible(curr_config->primary, codec_get_by_payload(sp->encodings[1]))) { const cc_details_t *ccd; channel_encoder_destroy(&sp->channel_coder); ccd = channel_get_null_coder(); channel_encoder_create(ccd->descriptor, &sp->channel_coder); sp->num_encodings = 1; } sp->render_3d = curr_config->render_3d; } else { debug_msg("audio device reconfigure - nothing to do.\n"); if (tx_is_sending(sp->tb)) { tx_stop(sp->tb); tx_start(sp->tb); } } tx_igain_update(sp->tb); ac_destroy(&sp->new_config); return change_req; }
static void red_split_unit(u_char ppt, /* Primary payload type */ u_char bpt, /* Block payload type */ u_char *b, /* Block pointer */ uint32_t blen, /* Block len */ timestamp_t playout, /* Block playout time */ struct s_pb *out) /* media buffer */ { const codec_format_t *cf; media_data *md; codec_id_t cid, pid; coded_unit *cu; u_char *p,*pe; timestamp_t step; pid = codec_get_by_payload(ppt); if (!pid) { debug_msg("Payload not recognized\n"); return; } cid = codec_get_by_payload(bpt); if (!cid) { debug_msg("Payload not recognized\n"); return; } if (!codec_audio_formats_compatible(pid, cid)) { debug_msg("Primary (%d) and redundant (%d) not compatible\n", ppt, bpt); return; } cf = codec_get_format(cid); assert(cf != NULL); step = ts_map32(cf->format.sample_rate, codec_get_samples_per_frame(cid)); p = b; pe = b + blen; while(p < pe) { cu = (coded_unit*)block_alloc(sizeof(coded_unit)); cu->id = cid; if (p == b && cf->mean_per_packet_state_size) { cu->state_len = cf->mean_per_packet_state_size; cu->state = block_alloc(cu->state_len); memcpy(cu->state, p, cu->state_len); p += cu->state_len; } else { cu->state = NULL; cu->state_len = 0; } cu->data_len = (uint16_t)codec_peek_frame_size(cid, p, (uint16_t)(pe - p)); cu->data = block_alloc(cu->data_len); memcpy(cu->data, p, cu->data_len); p += cu->data_len; md = red_media_data_create_or_get(out, playout); if (md->nrep == MAX_MEDIA_UNITS) continue; if (place_unit(md, cu) == TRUE) { playout = ts_add(playout, step); } else { /* unit could not be placed - destroy */ if (cu->state_len) { block_free(cu->state, cu->state_len); } block_free(cu->data, cu->data_len); block_free(cu, sizeof(coded_unit)); } } }