On date Monday 2011-05-23 19:48:53 +0200, Stefano Sabatini encoded: > On date Monday 2011-05-23 16:51:25 +0200, Stefano Sabatini encoded: [...] > Elaborating more: this patches is basically changing the layout of the > samples buffer. > > My objective is getting a layout as similiar as possible with that of > the video buffer. > > So this was my idea: > pointers -> contain pointers to each samples plane > linesizes -> the linesize of each plane > > This looks simpler and generally easier to manage. > > Currently we have: > * data[c] points to the first sample of channel c. > * data[c] + linesize[0] points to the second sample of channel c > > This has a slight advantage for accessing the samples for each channel > but it has the disadvantage that: > * misuse the term "linesize" (with a different semantics depending on > planar/packed mode) > * creates an asymmetry between audio and video data layout
Updated patchset in attachment. This is the base of the audio-filters changes, and will possibly affect also how audio in AVFrame is dealt with. I'm adding libav-devel to recipients in case they're interested in discussing (av_samples_* functions were never integrated in libav). -- FFmpeg = Friendly and Fierce Monstrous Pacific Efficient Goblin
>From 6443ffdcac7a2d6cb8e0266adb24c30155fb08f4 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini <[email protected]> Date: Tue, 22 Mar 2011 13:29:28 +0100 Subject: [PATCH] samplefmt: change layout for arrays created by av_samples_alloc() and _fill_arrays() The new layout is consistent with that of the av_image_() API, and simplifies understanding and copy operations, it also preserves alignment information which was lost with the previous layout. This breaks API/ABI, but since the function was never referenced in the code (and it isn't unlikely already used by someone) then this should not be a problem. --- libavutil/samplefmt.c | 22 ++++++++++++---------- libavutil/samplefmt.h | 4 ++-- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/libavutil/samplefmt.c b/libavutil/samplefmt.c index ea004d9..ca669da 100644 --- a/libavutil/samplefmt.c +++ b/libavutil/samplefmt.c @@ -76,28 +76,30 @@ int av_samples_fill_arrays(uint8_t *pointers[8], int linesizes[8], uint8_t *buf, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int planar, int align) { - int i, step_size = 0; + int i, linesize; int sample_size = av_get_bits_per_sample_fmt(sample_fmt) >> 3; - int channel_step = planar ? FFALIGN(nb_samples*sample_size, align) : sample_size; - if(nb_channels * (uint64_t)nb_samples * sample_size >= INT_MAX - align*(uint64_t)nb_channels) + if (nb_channels * (uint64_t)nb_samples * sample_size >= INT_MAX - align*(uint64_t)nb_channels) return AVERROR(EINVAL); + linesize = planar ? FFALIGN(nb_samples*sample_size, align) : + FFALIGN(nb_samples*sample_size*nb_channels, align); if (pointers) { pointers[0] = buf; - for (i = 0; i < nb_channels; i++) { - pointers[i] = buf + step_size; - step_size += channel_step; + for (i = 1; planar && i < nb_channels; i++) { + pointers[i] = pointers[i-1] + linesize; } - memset(&pointers[nb_channels], 0, (8-nb_channels) * sizeof(pointers[0])); + memset(&pointers[i], 0, (8-i) * sizeof(pointers[0])); } if (linesizes) { - linesizes[0] = planar ? sample_size : nb_channels*sample_size; - memset(&linesizes[1], 0, (8-1) * sizeof(linesizes[0])); + linesizes[0] = linesize; + for (i = 1; planar && i < nb_channels; i++) + linesizes[i] = linesizes[0]; + memset(&linesizes[i], 0, (8-i) * sizeof(linesizes[0])); } - return planar ? channel_step * nb_channels : FFALIGN(nb_channels*sample_size*nb_samples, align); + return planar ? linesize * nb_channels : linesize; } int av_samples_alloc(uint8_t *pointers[8], int linesizes[8], diff --git a/libavutil/samplefmt.h b/libavutil/samplefmt.h index 9b9c0d4..f1e66d0 100644 --- a/libavutil/samplefmt.h +++ b/libavutil/samplefmt.h @@ -74,8 +74,8 @@ int av_get_bits_per_sample_fmt(enum AVSampleFormat sample_fmt); * format sample_fmt. * * The pointers array is filled with the pointers to the samples data: - * data[c] points to the first sample of channel c. - * data[c] + linesize[0] points to the second sample of channel c + * for planar, set the start point of each plane's data within the buffer, + * for packed, set the start point of the entire buffer only. * * @param pointers array to be filled with the pointer for each plane, may be NULL * @param linesizes array to be filled with the linesize, may be NULL -- 1.7.2.3
>From 317651c4e15b36a9196ea6622c7456e78d299ab1 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini <[email protected]> Date: Thu, 2 Jun 2011 11:14:24 +0200 Subject: [PATCH] samplefmt: switch nb_channels/nb_samples params order in av_samples_alloc() This is consistent with the order of parameters in av_samples_fill_arrays(). --- libavutil/samplefmt.c | 2 +- libavutil/samplefmt.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libavutil/samplefmt.c b/libavutil/samplefmt.c index ca669da..041aaea 100644 --- a/libavutil/samplefmt.c +++ b/libavutil/samplefmt.c @@ -103,7 +103,7 @@ int av_samples_fill_arrays(uint8_t *pointers[8], int linesizes[8], } int av_samples_alloc(uint8_t *pointers[8], int linesizes[8], - int nb_samples, int nb_channels, + int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int planar, int align) { diff --git a/libavutil/samplefmt.h b/libavutil/samplefmt.h index f1e66d0..ed14802 100644 --- a/libavutil/samplefmt.h +++ b/libavutil/samplefmt.h @@ -96,6 +96,7 @@ int av_samples_fill_arrays(uint8_t *pointers[8], int linesizes[8], * The allocated samples buffer has to be freed by using * av_freep(&pointers[0]). * + * @param nb_channels number of audio channels * @param nb_samples number of samples per channel * @param planar 1 if the samples layout is planar, 0 if packed, * @param align the value to use for buffer size alignment @@ -104,7 +105,7 @@ int av_samples_fill_arrays(uint8_t *pointers[8], int linesizes[8], * @see av_samples_fill_arrays() */ int av_samples_alloc(uint8_t *pointers[8], int linesizes[8], - int nb_samples, int nb_channels, + int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int planar, int align); -- 1.7.2.3
>From fa3b19c5c08374e3146cf6a4d17b6875a91bc117 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini <[email protected]> Date: Tue, 1 Feb 2011 12:34:23 +0100 Subject: [PATCH] lavfi: prefer nb_samples over size in AVFilterBufferRefAudioProps Remove AVFilterBufferRefAudioProps.size, and use nb_samples in avfilter_get_audio_buffer() and avfilter_default_get_audio_buffer() in place of size. This is required as the size in the audio buffer may be aligned, so it may not contain a well defined number of samples. --- libavfilter/avfilter.c | 15 ++++++++------- libavfilter/avfilter.h | 11 +++++------ libavfilter/defaults.c | 11 +++++------ 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 72e0a87..79326a0 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -280,10 +280,9 @@ static void ff_dlog_ref(void *ctx, AVFilterBufferRef *ref, int end) av_get_picture_type_char(ref->video->pict_type)); } if (ref->audio) { - av_dlog(ctx, " cl:%"PRId64"d sn:%d s:%d sr:%d p:%d", + av_dlog(ctx, " cl:%"PRId64"d n:%d r:%d p:%d", ref->audio->channel_layout, ref->audio->nb_samples, - ref->audio->size, ref->audio->sample_rate, ref->audio->planar); } @@ -380,16 +379,16 @@ fail: } AVFilterBufferRef *avfilter_get_audio_buffer(AVFilterLink *link, int perms, - enum AVSampleFormat sample_fmt, int size, + enum AVSampleFormat sample_fmt, int nb_samples, int64_t channel_layout, int planar) { AVFilterBufferRef *ret = NULL; if (link->dstpad->get_audio_buffer) - ret = link->dstpad->get_audio_buffer(link, perms, sample_fmt, size, channel_layout, planar); + ret = link->dstpad->get_audio_buffer(link, perms, sample_fmt, nb_samples, channel_layout, planar); if (!ret) - ret = avfilter_default_get_audio_buffer(link, perms, sample_fmt, size, channel_layout, planar); + ret = avfilter_default_get_audio_buffer(link, perms, sample_fmt, nb_samples, channel_layout, planar); if (ret) ret->type = AVMEDIA_TYPE_AUDIO; @@ -520,6 +519,7 @@ void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) { void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); AVFilterPad *dst = link->dstpad; + int i; FF_DPRINTF_START(NULL, filter_samples); ff_dlog_link(NULL, link, 1); @@ -536,14 +536,15 @@ void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) link->cur_buf = avfilter_default_get_audio_buffer(link, dst->min_perms, samplesref->format, - samplesref->audio->size, + samplesref->audio->nb_samples, samplesref->audio->channel_layout, samplesref->audio->planar); link->cur_buf->pts = samplesref->pts; link->cur_buf->audio->sample_rate = samplesref->audio->sample_rate; /* Copy actual data into new samples buffer */ - memcpy(link->cur_buf->data[0], samplesref->data[0], samplesref->audio->size); + for (i = 0; samplesref->data[i]; i++) + memcpy(link->cur_buf->data[i], samplesref->data[i], samplesref->linesize[0]); avfilter_unref_buffer(samplesref); } else diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 602b243..b7d82a5 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -98,8 +98,7 @@ typedef struct AVFilterBuffer { */ typedef struct AVFilterBufferRefAudioProps { int64_t channel_layout; ///< channel layout of audio buffer - int nb_samples; ///< number of audio samples - int size; ///< audio buffer size + int nb_samples; ///< number of audio samples per channel uint32_t sample_rate; ///< audio buffer sample rate int planar; ///< audio buffer - planar or packed } AVFilterBufferRefAudioProps; @@ -372,7 +371,7 @@ struct AVFilterPad { * Input audio pads only. */ AVFilterBufferRef *(*get_audio_buffer)(AVFilterLink *link, int perms, - enum AVSampleFormat sample_fmt, int size, + enum AVSampleFormat sample_fmt, int nb_samples, int64_t channel_layout, int planar); /** @@ -461,7 +460,7 @@ AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, /** default handler for get_audio_buffer() for audio inputs */ AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, int perms, - enum AVSampleFormat sample_fmt, int size, + enum AVSampleFormat sample_fmt, int nb_samples, int64_t channel_layout, int planar); /** @@ -679,14 +678,14 @@ avfilter_get_video_buffer_ref_from_arrays(uint8_t *data[4], int linesize[4], int * be requested * @param perms the required access permissions * @param sample_fmt the format of each sample in the buffer to allocate - * @param size the buffer size in bytes + * @param nb_samples the number of samples per channel * @param channel_layout the number and type of channels per sample in the buffer to allocate * @param planar audio data layout - planar or packed * @return A reference to the samples. This must be unreferenced with * avfilter_unref_buffer when you are finished with it. */ AVFilterBufferRef *avfilter_get_audio_buffer(AVFilterLink *link, int perms, - enum AVSampleFormat sample_fmt, int size, + enum AVSampleFormat sample_fmt, int nb_samples, int64_t channel_layout, int planar); /** diff --git a/libavfilter/defaults.c b/libavfilter/defaults.c index 9ee23e5..854a105 100644 --- a/libavfilter/defaults.c +++ b/libavfilter/defaults.c @@ -79,7 +79,7 @@ AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int per } AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, int perms, - enum AVSampleFormat sample_fmt, int size, + enum AVSampleFormat sample_fmt, int nb_samples, int64_t channel_layout, int planar) { AVFilterBuffer *samples = av_mallocz(sizeof(AVFilterBuffer)); @@ -98,7 +98,7 @@ AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, int per goto fail; ref->audio->channel_layout = channel_layout; - ref->audio->size = size; + ref->audio->nb_samples = nb_samples; ref->audio->planar = planar; /* make sure the buffer gets read permission or it's useless for output */ @@ -110,8 +110,7 @@ AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, int per sample_size = av_get_bits_per_sample_fmt(sample_fmt) >>3; chans_nb = av_get_channel_layout_nb_channels(channel_layout); - per_channel_size = size/chans_nb; - ref->audio->nb_samples = per_channel_size/sample_size; + per_channel_size = nb_samples * sample_size; /* Set the number of bytes to traverse to reach next sample of a particular channel: * For planar, this is simply the sample size. @@ -122,7 +121,7 @@ AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, int per memset(&samples->linesize[chans_nb], 0, (8-chans_nb) * sizeof(samples->linesize[0])); /* Calculate total buffer size, round to multiple of 16 to be SIMD friendly */ - bufsize = (size + 15)&~15; + bufsize = (nb_samples * chans_nb * sample_size + 15)&~15; buf = av_malloc(bufsize); if (!buf) goto fail; @@ -210,7 +209,7 @@ void avfilter_default_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *sa if (outlink) { outlink->out_buf = avfilter_default_get_audio_buffer(inlink, AV_PERM_WRITE, samplesref->format, - samplesref->audio->size, + samplesref->audio->nb_samples, samplesref->audio->channel_layout, samplesref->audio->planar); outlink->out_buf->pts = samplesref->pts; -- 1.7.2.3
>From 712e7f1158306637ca087691bc15d51c95d486aa Mon Sep 17 00:00:00 2001 From: Stefano Sabatini <[email protected]> Date: Sat, 15 Jan 2011 18:48:37 +0100 Subject: [PATCH] lavfi: use av_samples_alloc() in avfilter_default_get_audio_buffer() --- libavfilter/defaults.c | 38 ++++---------------------------------- 1 files changed, 4 insertions(+), 34 deletions(-) diff --git a/libavfilter/defaults.c b/libavfilter/defaults.c index 854a105..0ef0d2f 100644 --- a/libavfilter/defaults.c +++ b/libavfilter/defaults.c @@ -84,8 +84,7 @@ AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, int per { AVFilterBuffer *samples = av_mallocz(sizeof(AVFilterBuffer)); AVFilterBufferRef *ref = NULL; - int i, sample_size, chans_nb, bufsize, per_channel_size, step_size = 0; - char *buf; + int nb_channels = av_get_channel_layout_nb_channels(channel_layout); if (!samples || !(ref = av_mallocz(sizeof(AVFilterBufferRef)))) goto fail; @@ -107,41 +106,12 @@ AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, int per samples->refcount = 1; samples->free = ff_avfilter_default_free_buffer; - sample_size = av_get_bits_per_sample_fmt(sample_fmt) >>3; - chans_nb = av_get_channel_layout_nb_channels(channel_layout); - - per_channel_size = nb_samples * sample_size; - - /* Set the number of bytes to traverse to reach next sample of a particular channel: - * For planar, this is simply the sample size. - * For packed, this is the number of samples * sample_size. - */ - for (i = 0; i < chans_nb; i++) - samples->linesize[i] = planar > 0 ? per_channel_size : sample_size; - memset(&samples->linesize[chans_nb], 0, (8-chans_nb) * sizeof(samples->linesize[0])); - /* Calculate total buffer size, round to multiple of 16 to be SIMD friendly */ - bufsize = (nb_samples * chans_nb * sample_size + 15)&~15; - buf = av_malloc(bufsize); - if (!buf) + if (av_samples_alloc(samples->data, samples->linesize, + nb_channels, nb_samples, sample_fmt, + planar, 15) < 0) goto fail; - /* For planar, set the start point of each channel's data within the buffer - * For packed, set the start point of the entire buffer only - */ - samples->data[0] = buf; - if (buf && planar) { - for (i = 1; i < chans_nb; i++) { - step_size += per_channel_size; - samples->data[i] = buf + step_size; - } - } else { - for (i = 1; i < chans_nb; i++) - samples->data[i] = buf; - } - - memset(&samples->data[chans_nb], 0, (8-chans_nb) * sizeof(samples->data[0])); - memcpy(ref->data, samples->data, sizeof(ref->data)); memcpy(ref->linesize, samples->linesize, sizeof(ref->linesize)); -- 1.7.2.3
_______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
