Esempio n. 1
0
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;
}
Esempio n. 2
0
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));
                }
        }
}