Пример #1
0
static unsigned trivial_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
    unsigned i_index, o_index;
    void *src, *dst;
    struct trivial_data *trivial_data;

    pa_assert(r);
    pa_assert(input);
    pa_assert(output);
    pa_assert(out_n_frames);

    trivial_data = r->impl.data;

    src = pa_memblock_acquire_chunk(input);
    dst = pa_memblock_acquire_chunk(output);

    for (o_index = 0;; o_index++, trivial_data->o_counter++) {
        i_index = ((uint64_t) trivial_data->o_counter * r->i_ss.rate) / r->o_ss.rate;
        i_index = i_index > trivial_data->i_counter ? i_index - trivial_data->i_counter : 0;

        if (i_index >= in_n_frames)
            break;

        pa_assert_fp(o_index * r->w_fz < pa_memblock_get_length(output->memblock));

        memcpy((uint8_t*) dst + r->w_fz * o_index, (uint8_t*) src + r->w_fz * i_index, (int) r->w_fz);
    }

    pa_memblock_release(input->memblock);
    pa_memblock_release(output->memblock);

    *out_n_frames = o_index;

    trivial_data->i_counter += in_n_frames;

    /* Normalize counters */
    while (trivial_data->i_counter >= r->i_ss.rate) {
        pa_assert(trivial_data->o_counter >= r->o_ss.rate);

        trivial_data->i_counter -= r->i_ss.rate;
        trivial_data->o_counter -= r->o_ss.rate;
    }

    return 0;
}
/*** sink_input callbacks ***/
static int cmtspeech_sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
    struct userdata *u;
    int queue_counter = 0;

    pa_assert_fp(i);
    pa_sink_input_assert_ref(i);
    pa_assert_se(u = i->userdata);
    pa_assert_fp(chunk);

    if (u->cmt_connection.dl_frame_queue) {
        cmtspeech_dl_buf_t *buf;
        while ((buf = pa_asyncq_pop(u->cmt_connection.dl_frame_queue, FALSE))) {
            pa_memchunk cmtchunk;
            if (cmtspeech_buffer_to_memchunk(u, buf, &cmtchunk) < 0)
                continue;
            queue_counter++;
            if (pa_memblockq_push(u->dl_memblockq, &cmtchunk) < 0) {
                pa_log_debug("Failed to push DL frame to dl_memblockq (len %zu max %zu)",
                             pa_memblockq_get_length(u->dl_memblockq),
                             pa_memblockq_get_maxlength(u->dl_memblockq));
            }
            else {
                cmtspeech_dl_sideinfo_push(buf->spc_flags, cmtchunk.length, u);
            }
            pa_memblock_unref(cmtchunk.memblock);
        }
    }

    /* More than one DL frame in queue means that sink has not asked for more
     * data for over 20ms and something may be wrong. */
    if (queue_counter > 1) {
        pa_log_info("%d frames found from queue (dl buf size %zu)", queue_counter,
                    pa_memblockq_get_length(u->dl_memblockq));
    }

    if (pa_memblockq_get_length(u->dl_memblockq) > 3*u->dl_frame_size) {
        size_t drop_bytes =
            pa_memblockq_get_length(u->dl_memblockq) - 3*u->dl_frame_size;
        pa_memblockq_drop(u->dl_memblockq, drop_bytes);
        cmtspeech_dl_sideinfo_drop(u, drop_bytes);
        pa_log_debug("Too much data in DL buffer dropped %zu bytes",
                     drop_bytes);
    }

    pa_assert_fp((pa_memblockq_get_length(u->dl_memblockq) % u->dl_frame_size) == 0);

    if (util_memblockq_to_chunk(u->core->mempool, u->dl_memblockq, chunk, u->dl_frame_size)) {
        ONDEBUG_TOKENS(fprintf(stderr, "d"));
        cmtspeech_dl_sideinfo_forward(u);
    }
    else {
        if (u->cmt_connection.first_dl_frame_received)
            pa_log_debug("No DL audio: %zu bytes in queue %zu needed",
                         pa_memblockq_get_length(u->dl_memblockq), u->dl_frame_size);
        cmtspeech_dl_sideinfo_bogus(u);
        pa_silence_memchunk_get(&u->core->silence_cache,
                                u->core->mempool,
                                chunk,
                                &u->ss,
                                u->dl_frame_size);
    }

    return 0;
}