Esempio n. 1
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)
{
    int error = 0;

    struct mp_audio config;
    mp_audio_buffer_get_format(da->decode_buffer, &config);

    while (mp_audio_buffer_samples(da->decode_buffer) < len) {
        int maxlen = mp_audio_buffer_get_write_available(da->decode_buffer);
        if (maxlen < DECODE_MAX_UNIT)
            break;
        struct mp_audio buffer;
        mp_audio_buffer_get_write_buffer(da->decode_buffer, maxlen, &buffer);
        buffer.samples = 0;
        error = da->ad_driver->decode_audio(da, &buffer, maxlen);
        if (error < 0)
            break;
        // Commit the data just read as valid data
        mp_audio_buffer_finish_write(da->decode_buffer, buffer.samples);
        // Format change
        if (!mp_audio_config_equals(&da->decoded, &config)) {
            // If there are still samples left in the buffer, let them drain
            // first, and don't signal a format change to the caller yet.
            if (mp_audio_buffer_samples(da->decode_buffer) > 0)
                break;
            error = -2;
            break;
        }
    }

    // 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 = filter_data.samples == 0 && error < 0;

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

    mp_audio_buffer_append(outbuf, &filter_data);
    if (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);

    // Assume the filter chain is drained from old data at this point.
    // (If not, the remaining old data is discarded.)
    if (error == -2) {
        if (!reinit_audio_buffer(da))
            error = -1; // switch to invalid format
    }

    return error;
}
Esempio n. 2
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;
}
Esempio n. 3
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;
}