Exemple #1
0
static int filter_out(struct af_instance *af)
{
    struct priv *p = af->priv;

    while (rubberband_available(p->rubber) <= 0) {
        const float *dummy[MP_NUM_CHANNELS] = {0};
        const float **in_data = dummy;
        size_t in_samples = 0;
        if (p->pending) {
            if (!p->pending->samples)
                break;

            // recover from previous EOF
            if (p->needs_reset) {
                rubberband_reset(p->rubber);
                p->rubber_delay = 0;
            }
            p->needs_reset = false;

            size_t needs = rubberband_get_samples_required(p->rubber);
            in_data = (void *)&p->pending->planes;
            in_samples = MPMIN(p->pending->samples, needs);
        }

        if (p->needs_reset)
            break; // previous EOF
        p->needs_reset = !p->pending; // EOF

        rubberband_process(p->rubber, in_data, in_samples, p->needs_reset);
        p->rubber_delay += in_samples;

        if (!p->pending)
            break;
        mp_audio_skip_samples(p->pending, in_samples);
    }

    int out_samples = rubberband_available(p->rubber);
    if (out_samples > 0) {
        struct mp_audio *out =
            mp_audio_pool_get(af->out_pool, af->data, out_samples);
        if (!out)
            return -1;
        if (p->pending)
            mp_audio_copy_config(out, p->pending);

        float **out_data = (void *)&out->planes;
        out->samples = rubberband_retrieve(p->rubber, out_data, out->samples);
        p->rubber_delay -= out->samples * p->speed;

        af_add_output_frame(af, out);
    }

    int delay_samples = p->rubber_delay;
    if (p->pending)
        delay_samples += p->pending->samples;
    af->delay = delay_samples / (af->data->rate * p->speed);

    return 0;
}
Exemple #2
0
// Copy data from input frame to encode frame (because libavcodec wants a full
// AC3 frame for encoding, while filter input frames can be smaller or larger).
// Return true if the frame is complete.
static bool fill_buffer(struct af_instance *af)
{
    af_ac3enc_t *s = af->priv;

    af->delay = 0;

    if (s->pending) {
        int copy = MPMIN(s->in_samples - s->input->samples, s->pending->samples);
        s->input->samples += copy;
        mp_audio_copy(s->input, s->input->samples - copy, s->pending, 0, copy);
        mp_audio_skip_samples(s->pending, copy);
    }
    update_delay(af);
    return s->input->samples >= s->in_samples;
}
Exemple #3
0
// Copy data from input frame to encode frame (because libavcodec wants a full
// AC3 frame for encoding, while filter input frames can be smaller or larger).
// Return true if the frame is complete.
static bool fill_buffer(struct af_instance *af)
{
    af_ac3enc_t *s = af->priv;

    af->delay = 0;

    if (s->pending) {
        if (!mp_audio_is_writeable(s->input))
            assert(s->input->samples == 0); // we can't have sent a partial frame
        mp_audio_realloc_min(s->input, s->in_samples);
        int copy = MPMIN(s->in_samples - s->input->samples, s->pending->samples);
        s->input->samples += copy;
        mp_audio_copy(s->input, s->input->samples - copy, s->pending, 0, copy);
        mp_audio_skip_samples(s->pending, copy);
    }
    update_delay(af);
    return s->input->samples >= s->in_samples;
}
Exemple #4
0
// Filter data through filter
static int filter(struct af_instance* af, struct mp_audio* audio, int flags)
{
    struct mp_audio *out = af->data;
    af_ac3enc_t *s = af->priv;
    int num_frames = (audio->samples + mp_audio_buffer_samples(s->pending))
                     / s->in_samples;

    int max_out_samples = s->out_samples * num_frames;
    mp_audio_realloc_min(out, max_out_samples);
    out->samples = 0;

    while (audio->samples > 0) {
        int ret;

        int consumed_pending = 0;
        struct mp_audio in_frame;
        int pending = mp_audio_buffer_samples(s->pending);
        if (pending == 0 && audio->samples >= s->in_samples) {
            in_frame = *audio;
            mp_audio_skip_samples(audio, s->in_samples);
        } else {
            if (pending > 0 && pending < s->in_samples) {
                struct mp_audio tmp = *audio;
                tmp.samples = MPMIN(tmp.samples, s->in_samples);
                mp_audio_buffer_append(s->pending, &tmp);
                mp_audio_skip_samples(audio, tmp.samples);
            }
            mp_audio_buffer_peek(s->pending, &in_frame);
            if (in_frame.samples < s->in_samples)
                break;
            consumed_pending = s->in_samples;
        }
        in_frame.samples = s->in_samples;

        AVFrame *frame = av_frame_alloc();
        if (!frame) {
            MP_FATAL(af, "Could not allocate memory \n");
            return -1;
        }
        frame->nb_samples = s->in_samples;
        frame->format = s->lavc_actx->sample_fmt;
        frame->channel_layout = s->lavc_actx->channel_layout;
        assert(in_frame.num_planes <= AV_NUM_DATA_POINTERS);
        frame->extended_data = frame->data;
        for (int n = 0; n < in_frame.num_planes; n++)
            frame->data[n] = in_frame.planes[n];
        frame->linesize[0] = s->in_samples * audio->sstride;

        int ok;
        ret = avcodec_encode_audio2(s->lavc_actx, &s->pkt, frame, &ok);
        av_frame_free(&frame);
        if (ret < 0 || !ok) {
            MP_FATAL(af, "Encode failed.\n");
            return -1;
        }

        mp_audio_buffer_skip(s->pending, consumed_pending);

        MP_DBG(af, "avcodec_encode_audio got %d, pending %d.\n",
               s->pkt.size, mp_audio_buffer_samples(s->pending));

        int frame_size = s->pkt.size;
        int header_len = 0;
        char hdr[8];

        if (s->cfg_add_iec61937_header && s->pkt.size > 5) {
            int bsmod = s->pkt.data[5] & 0x7;
            int len = frame_size;

            frame_size = AC3_FRAME_SIZE * 2 * 2;
            header_len = 8;

            AV_WB16(hdr,     0xF872);   // iec 61937 syncword 1
            AV_WB16(hdr + 2, 0x4E1F);   // iec 61937 syncword 2
            hdr[4] = bsmod;             // bsmod
            hdr[5] = 0x01;              // data-type ac3
            AV_WB16(hdr + 6, len << 3); // number of bits in payload
        }

        size_t max_size = (max_out_samples - out->samples) * out->sstride;
        if (frame_size > max_size)
            abort();

        char *buf = (char *)out->planes[0] + out->samples * out->sstride;
        memcpy(buf, hdr, header_len);
        memcpy(buf + header_len, s->pkt.data, s->pkt.size);
        memset(buf + header_len + s->pkt.size, 0,
               frame_size - (header_len + s->pkt.size));
        out->samples += frame_size / out->sstride;
    }

    mp_audio_buffer_append(s->pending, audio);

    *audio = *out;
    return 0;
}
Exemple #5
0
// Filter len bytes of input, put result into outbuf.
static int filter_n_bytes(struct dec_audio *da, struct mp_audio_buffer *outbuf,
                          int len)
{
    bool format_change = false;
    int error = 0;

    assert(len > 0); // would break EOF logic below

    while (mp_audio_buffer_samples(da->decode_buffer) < len) {
        // Check for a format change
        struct mp_audio config;
        mp_audio_buffer_get_format(da->decode_buffer, &config);
        format_change = !mp_audio_config_equals(&da->decoded, &config);
        if (format_change) {
            error = AD_EOF; // drain remaining data left in the current buffer
            break;
        }
        if (da->decoded.samples > 0) {
            int copy = MPMIN(da->decoded.samples, len);
            struct mp_audio append = da->decoded;
            append.samples = copy;
            mp_audio_buffer_append(da->decode_buffer, &append);
            mp_audio_skip_samples(&da->decoded, copy);
            da->pts_offset += copy;
            continue;
        }
        error = da->ad_driver->decode_packet(da);
        if (error < 0)
            break;
    }

    if (error == AD_WAIT)
        return error;

    // Filter
    struct mp_audio filter_data;
    mp_audio_buffer_peek(da->decode_buffer, &filter_data);
    filter_data.rate = da->afilter->input.rate; // due to playback speed change
    len = MPMIN(filter_data.samples, len);
    filter_data.samples = len;
    bool eof = error == AD_EOF && filter_data.samples == 0;

    if (af_filter(da->afilter, &filter_data, eof ? AF_FILTER_FLAG_EOF : 0) < 0)
        return AD_ERR;

    mp_audio_buffer_append(outbuf, &filter_data);
    if (error == AD_EOF && filter_data.samples > 0)
        error = 0; // don't end playback yet

    // remove processed data from decoder buffer:
    mp_audio_buffer_skip(da->decode_buffer, len);

    // if format was changed, and all data was drained, execute the format change
    if (format_change && eof) {
        error = AD_NEW_FMT;
        if (!reinit_audio_buffer(da))
            error = AD_ERR; // switch to invalid format
    }

    return error;
}