AVFilterBufferRef *avfilter_null_get_audio_buffer(AVFilterLink *link, int perms, enum AVSampleFormat sample_fmt, int size, uint64_t channel_layout, int packed) { return avfilter_get_audio_buffer(link->dst->outputs[0], perms, sample_fmt, size, channel_layout, packed); }
static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref) { AResampleContext *aresample = inlink->dst->priv; AVFilterLink * const outlink = inlink->dst->outputs[0]; int i, in_nb_samples = insamplesref->audio->nb_samples, cached_nb_samples = in_nb_samples + aresample->unconsumed_nb_samples, requested_out_nb_samples = aresample->ratio * cached_nb_samples, nb_channels = av_get_channel_layout_nb_channels(inlink->channel_layout); if (cached_nb_samples > aresample->max_cached_nb_samples) { for (i = 0; i < nb_channels; i++) { aresample->cached_data[i] = av_realloc(aresample->cached_data[i], cached_nb_samples * sizeof(int16_t)); aresample->resampled_data[i] = av_realloc(aresample->resampled_data[i], FFALIGN(sizeof(int16_t) * requested_out_nb_samples, 16)); if (aresample->cached_data[i] == NULL || aresample->resampled_data[i] == NULL) return; } aresample->max_cached_nb_samples = cached_nb_samples; if (aresample->outsamplesref) avfilter_unref_buffer(aresample->outsamplesref); aresample->outsamplesref = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, requested_out_nb_samples); outlink->out_buf = aresample->outsamplesref; } avfilter_copy_buffer_ref_props(aresample->outsamplesref, insamplesref); aresample->outsamplesref->audio->sample_rate = outlink->sample_rate; aresample->outsamplesref->pts = av_rescale(outlink->sample_rate, insamplesref->pts, inlink->sample_rate); /* av_resample() works with planar audio buffers */ if (!inlink->planar && nb_channels > 1) { int16_t *out[8]; for (i = 0; i < nb_channels; i++) out[i] = aresample->cached_data[i] + aresample->unconsumed_nb_samples; deinterleave(out, (int16_t *)insamplesref->data[0], nb_channels, in_nb_samples); } else { for (i = 0; i < nb_channels; i++) memcpy(aresample->cached_data[i] + aresample->unconsumed_nb_samples, insamplesref->data[i], in_nb_samples * sizeof(int16_t)); } for (i = 0; i < nb_channels; i++) { int consumed_nb_samples; const int is_last = i+1 == nb_channels; aresample->outsamplesref->audio->nb_samples = av_resample(aresample->resample, aresample->resampled_data[i], aresample->cached_data[i], &consumed_nb_samples, cached_nb_samples, requested_out_nb_samples, is_last); /* move unconsumed data back to the beginning of the cache */ aresample->unconsumed_nb_samples = cached_nb_samples - consumed_nb_samples; memmove(aresample->cached_data[i], aresample->cached_data[i] + consumed_nb_samples, aresample->unconsumed_nb_samples * sizeof(int16_t)); } /* copy resampled data to the output samplesref */ if (!inlink->planar && nb_channels > 1) { interleave((int16_t *)aresample->outsamplesref->data[0], aresample->resampled_data, nb_channels, aresample->outsamplesref->audio->nb_samples); } else { for (i = 0; i < nb_channels; i++) memcpy(aresample->outsamplesref->data[i], aresample->resampled_data[i], aresample->outsamplesref->audio->nb_samples * sizeof(int16_t)); } avfilter_filter_samples(outlink, avfilter_ref_buffer(aresample->outsamplesref, ~0)); avfilter_unref_buffer(insamplesref); }
static int init_buffers(AVFilterLink *inlink, int nb_samples) { AConvertContext *aconvert = inlink->dst->priv; AVFilterLink * const outlink = inlink->dst->outputs[0]; int i, packed_stride = 0; const unsigned packing_conv = inlink->planar != outlink->planar && aconvert->out_nb_channels != 1, format_conv = inlink->format != outlink->format; int nb_channels = aconvert->out_nb_channels; uninit(inlink->dst); aconvert->max_nb_samples = nb_samples; if (aconvert->convert_chlayout) { /* allocate buffer for storing intermediary mixing samplesref */ uint8_t *data[8]; int linesize[8]; int nb_channels = av_get_channel_layout_nb_channels(outlink->channel_layout); if (av_samples_alloc(data, linesize, nb_channels, nb_samples, inlink->format, inlink->planar, 16) < 0) goto fail_no_mem; aconvert->mix_samplesref = avfilter_get_audio_buffer_ref_from_arrays(data, linesize, AV_PERM_WRITE, nb_samples, inlink->format, outlink->channel_layout, inlink->planar); if (!aconvert->mix_samplesref) goto fail_no_mem; } // if there's a format/packing conversion we need an audio_convert context if (format_conv || packing_conv) { aconvert->out_samplesref = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples); if (!aconvert->out_samplesref) goto fail_no_mem; aconvert->in_strides [0] = av_get_bytes_per_sample(inlink ->format); aconvert->out_strides[0] = av_get_bytes_per_sample(outlink->format); aconvert->out_conv = aconvert->out_samplesref->data; if (aconvert->mix_samplesref) aconvert->in_conv = aconvert->mix_samplesref->data; if (packing_conv) { // packed -> planar if (outlink->planar == AVFILTER_PLANAR) { if (aconvert->mix_samplesref) aconvert->packed_data[0] = aconvert->mix_samplesref->data[0]; aconvert->in_conv = aconvert->packed_data; packed_stride = aconvert->in_strides[0]; aconvert->in_strides[0] *= nb_channels; // planar -> packed } else { aconvert->packed_data[0] = aconvert->out_samplesref->data[0]; aconvert->out_conv = aconvert->packed_data; packed_stride = aconvert->out_strides[0]; aconvert->out_strides[0] *= nb_channels; } } else if (outlink->planar == AVFILTER_PACKED) { /* If there's no packing conversion, and the stream is packed * then we treat the entire stream as one big channel */ nb_channels = 1; } for (i = 1; i < nb_channels; i++) { aconvert->packed_data[i] = aconvert->packed_data[i-1] + packed_stride; aconvert->in_strides[i] = aconvert->in_strides[0]; aconvert->out_strides[i] = aconvert->out_strides[0]; } aconvert->audioconvert_ctx = av_audio_convert_alloc(outlink->format, nb_channels, inlink->format, nb_channels, NULL, 0); if (!aconvert->audioconvert_ctx) goto fail_no_mem; } return 0; fail_no_mem: av_log(inlink->dst, AV_LOG_ERROR, "Could not allocate memory.\n"); return AVERROR(ENOMEM); }
AVFilterBufferRef *avfilter_null_get_audio_buffer(AVFilterLink *link, int perms, int nb_samples) { return avfilter_get_audio_buffer(link->dst->outputs[0], perms, nb_samples); }