ffmpeg 混音处理源码
ffmpeger 发布于 2022-12-25

上一篇提到的命令行实现混音处理,这篇文章主要从源码角度理解混音处理的细节,源码在\libavfilter\af_amix.c文件,

核心处理逻辑在以下函数,看注释,从输入的FIFOs中读取样本,混合,写到到输出的AVFilterLink

/**

 * Read samples from the input FIFOs, mix, and write to the output link.

 */

static int output_frame(AVFilterLink *outlink)

 

其中数据处理在以下循环中,用av_audio_fifo_read从各个输入的FIFOs中读取数据,保存到AVFrame的extended_data中,然后进行向量的乘法处理(vector_fmac_scalar或者vector_dmac_scalar)。

    for (i = 0; i < s->nb_inputs; i++) {
        if (s->input_state[i] & INPUT_ON) {
            int planes, plane_size, p;

            av_audio_fifo_read(s->fifos[i], (void **)in_buf->extended_data,
                               nb_samples);

            planes     = s->planar ? s->nb_channels : 1;
            plane_size = nb_samples * (s->planar ? 1 : s->nb_channels);
            plane_size = FFALIGN(plane_size, 16);

            if (out_buf->format == AV_SAMPLE_FMT_FLT ||
                out_buf->format == AV_SAMPLE_FMT_FLTP) {
                for (p = 0; p < planes; p++) {
                    s->fdsp->vector_fmac_scalar((float *)out_buf->extended_data[p],
                                                (float *) in_buf->extended_data[p],
                                                s->input_scale[i], plane_size);
                }
            } else {
                for (p = 0; p < planes; p++) {
                    s->fdsp->vector_dmac_scalar((double *)out_buf->extended_data[p],
                                                (double *) in_buf->extended_data[p],
                                                s->input_scale[i], plane_size);
                }
            }
        }
    }

 

函数的最后执行ff_filter_frame(outlink, out_buf);这个函数在avfilter.c文件中,

int ff_filter_frame(AVFilterLink *link, AVFrame *frame),该函数中核心的处理在于 ret = ff_framequeue_add(&link->fifo, frame);在framequeue.c文件中

int ff_framequeue_add(FFFrameQueue *fq, AVFrame *frame)
{
    FFFrameBucket *b;

    check_consistency(fq);
    if (fq->queued == fq->allocated) {
        if (fq->allocated == 1) {
            size_t na = 8;
            FFFrameBucket *nq = av_realloc_array(NULL, na, sizeof(*nq));
            if (!nq)
                return AVERROR(ENOMEM);
            nq[0] = fq->queue[0];
            fq->queue = nq;
            fq->allocated = na;
        } else {
            size_t na = fq->allocated << 1;
            FFFrameBucket *nq = av_realloc_array(fq->queue, na, sizeof(*nq));
            if (!nq)
                return AVERROR(ENOMEM);
            if (fq->tail + fq->queued > fq->allocated)
                memmove(nq + fq->allocated, nq,
                        (fq->tail + fq->queued - fq->allocated) * sizeof(*nq));
            fq->queue = nq;
            fq->allocated = na;
        }
    }
    b = bucket(fq, fq->queued);
    b->frame = frame;
    fq->queued++;
    fq->total_frames_head++;
    fq->total_samples_head += frame->nb_samples;
    check_consistency(fq);
    return 0;
}

 

ffmpeger
关注 私信
文章
63
关注
0
粉丝
0