Re: [libav-devel] [PATCH] AVBuffer: add a new API for buffer pools
On Mon, Jan 28, 2013 at 7:53 AM, Anton Khirnov an...@khirnov.net wrote: --- Improved the API so that the pool itself is refcounted, so the caller safely uninit it at any time. The pool itself is then actually freed when the last buffer is returned to it. --- libavutil/buffer.c | 156 +++ libavutil/buffer.h | 75 + libavutil/buffer_internal.h | 32 + 3 files changed, 263 insertions(+) diff --git a/libavutil/buffer.c b/libavutil/buffer.c index 44262f1..6fc19be 100644 --- a/libavutil/buffer.c +++ b/libavutil/buffer.c @@ -192,3 +192,159 @@ int av_buffer_realloc(AVBufferRef **pbuf, int size) buf-buffer-size = buf-size = size; return 0; } + +AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size)) +{ +AVBufferPool *pool = av_mallocz(sizeof(*pool)); +if (!pool) +return NULL; + +pool-size = size; +pool-alloc= alloc ? alloc : av_buffer_alloc; + +avpriv_atomic_int_set(pool-refcount, 1); + +return pool; +} + +/* + * This function gets called when the pool has been uninited and + * all the buffers returned to it. + */ +static void buffer_pool_free(AVBufferPool *pool) +{ +while (pool-pool) { +BufferPoolEntry *buf = pool-pool; +pool-pool = buf-next; + +buf-free(buf-opaque, buf-data); +av_freep(buf); +} +av_freep(pool); +} + +void av_buffer_pool_uninit(AVBufferPool **ppool) +{ +AVBufferPool *pool; + +if (!ppool || !*ppool) +return; +pool = *ppool; +*ppool = NULL; + +if (!avpriv_atomic_int_add_and_fetch(pool-refcount, -1)) +buffer_pool_free(pool); +} + +/* remove the whole buffer list from the pool and return it */ +static BufferPoolEntry *get_pool(AVBufferPool *pool) +{ +BufferPoolEntry *cur, *last = NULL; + +cur = avpriv_atomic_ptr_cas((void * volatile *)pool-pool, NULL, NULL); +if (!cur) +return NULL; + +while (cur != last) { +FFSWAP(BufferPoolEntry*, cur, last); +cur = avpriv_atomic_ptr_cas((void * volatile *)pool-pool, last, NULL); +} I think a do {} while() would make this look a bit less weird. + +return cur; +} + +static void add_to_pool(BufferPoolEntry *buf) +{ +AVBufferPool *pool; +BufferPoolEntry *cur, *end = buf; + +if (!buf) +return; +pool = buf-pool; + +while (end-next) +end = end-next; + +while ((cur = avpriv_atomic_ptr_cas((void * volatile *)pool-pool, NULL, buf))) { +/* pool is not empty, retrieve it and append it to our list */ +cur = get_pool(pool); +end-next = cur; +while (end-next) +end = end-next; +} +} + +static void pool_release_buffer(void *opaque, uint8_t *data) +{ +BufferPoolEntry *buf = opaque; +AVBufferPool *pool = buf-pool; +add_to_pool(buf); +if (!avpriv_atomic_int_add_and_fetch(pool-refcount, -1)) +buffer_pool_free(pool); +} + +/* allocate a new buffer and override its free() callback so that + * it is returned to the pool on free */ +static AVBufferRef *pool_alloc_buffer(AVBufferPool *pool) +{ +BufferPoolEntry *buf; +AVBufferRef *ret; + +ret = pool-alloc(pool-size); +if (!ret) +return NULL; + +buf = av_mallocz(sizeof(*buf)); +if (!buf) { +av_buffer_unref(ret); +return NULL; +} + +buf-data = ret-buffer-data; +buf-opaque = ret-buffer-opaque; +buf-free = ret-buffer-free; +buf-pool = pool; + +ret-buffer-opaque = buf; +ret-buffer-free = pool_release_buffer; + +avpriv_atomic_int_add_and_fetch(pool-refcount, 1); + +return ret; +} + +AVBufferRef *av_buffer_alloc_pool(AVBufferPool *pool) +{ +AVBufferRef *ret; +BufferPoolEntry *buf; + +/* check whether the pool is empty */ +buf = get_pool(pool); +if (!buf) +return pool_alloc_buffer(pool); + +/* keep the first entry, return the rest of the list to the pool */ +add_to_pool(buf-next); +buf-next = NULL; + +ret = av_buffer_create(buf-data, pool-size, pool_release_buffer, + buf, 0); +if (!ret) { +add_to_pool(buf); +return NULL; +} +avpriv_atomic_int_add_and_fetch(pool-refcount, 1); + +return ret; +} + +AVBufferRef *av_buffer_allocz_pool(AVBufferPool *pool) +{ +AVBufferRef *ret = av_buffer_alloc_pool(pool); + +if (!ret) +return NULL; + +memset(ret-data, 0, ret-size); +return ret; +} diff --git a/libavutil/buffer.h b/libavutil/buffer.h index 9b23bc3..d0b3db5 100644 --- a/libavutil/buffer.h +++ b/libavutil/buffer.h @@ -192,4 +192,79 @@ int av_buffer_realloc(AVBufferRef **buf, int size); * @} */ +/** + * @defgroup lavu_bufferpool AVBufferPool + *
Re: [libav-devel] [PATCH] lavf: Bump minor version to distinguish branch and master version numbers
On Wed, 09 Jan 2013 01:48:15 -0800, Reinhard Tartler siret...@gmail.com wrote: Btw, this is because of the ffmpegsource drama, right? Does this patch actually help the ffmpegsource developers? I would be happy to include additional #defines if, and only if, that would help them. Not particularly. In general we try to support every reasonably recent released version, so it's too late to fix it now. Having 53.21.1 and 53.21.0 be significantly different versions is an improvement over having two 51.21.0s, but it's still pretty terrible since it ignores even the most basic parts of semantic versioning like bigger numbers come after smaller numbers. API version numbers are inherently not very compatible with making API changes on multiple branches. One possible solution would be to have separate non-sequential defines for each API change, so that they can be reordered or cherry-picked willy-nilly. A simpler solution would be to just not change the API in minor releases of stable versions, since that's generally one of the main points of stable branches. ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
[libav-devel] [PATCH] Fix atrac3 broken in e55d53905f34f8e8747f6d321e9a695dc02ebb2f
Signed-off-by: Michael Karcher ffm...@mkarcher.dialup.fu-berlin.de --- libavcodec/atrac3.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/atrac3.c b/libavcodec/atrac3.c index 312b283..a46b0b1 100644 --- a/libavcodec/atrac3.c +++ b/libavcodec/atrac3.c @@ -517,7 +517,7 @@ static int add_tonal_components(float *spectrum, int num_components, output = spectrum[components[i].pos]; for (j = 0; j components[i].num_coefs; j++) -output[i] += input[i]; +output[j] += input[j]; } return last_pos; -- 1.7.10.4 ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
Re: [libav-devel] [PATCH] Fix atrac3 broken in e55d53905f34f8e8747f6d321e9a695dc02ebb2f
On Fri, Jan 25, 2013 at 09:06:11PM +0100, Michael Karcher wrote: Signed-off-by: Michael Karcher ffm...@mkarcher.dialup.fu-berlin.de --- libavcodec/atrac3.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/atrac3.c b/libavcodec/atrac3.c index 312b283..a46b0b1 100644 --- a/libavcodec/atrac3.c +++ b/libavcodec/atrac3.c @@ -517,7 +517,7 @@ static int add_tonal_components(float *spectrum, int num_components, output = spectrum[components[i].pos]; for (j = 0; j components[i].num_coefs; j++) -output[i] += input[i]; +output[j] += input[j]; } return last_pos; -- looks correct ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
Re: [libav-devel] [PATCH] hpel: split off halfpel MC from dsputil into new DSP context.
On 28/01/13 16:24, Ronald S. Bultje wrote: From: Ronald S. Bultje rsbul...@gmail.com This allows objects to use just halfpel MC without depending on all of dsputil. E.g. indeo3, interplayvideo and svq1dec become dsputil- independent. The fine-grained HAVE_HPEL_* flags allow only compiling a subset of the HPEL functions if a codec only uses a subset of them. Currently, only the C code uses this, I'll add this to the assembly at a later point. In addition, I rewrote the C code, it's a little faster on 32bit x86 and a lot faster on x86-64. The HAVE_HPEL_* flags could be moved to configure so they can accessed from assembly as well to conditionally compile optimizations, thus allowing further tuning of binary size. This huge monster had been compiled-tested on alpha, bfin, ppc, sh4 and sparc many times and I'm about to give it yet another run to make sure there aren't latest moment glitches. Help reviewing it chunk by chunk welcome =) --- configure | 14 +- libavcodec/Makefile|1 + libavcodec/alpha/Makefile |3 + libavcodec/alpha/dsputil_alpha.c | 187 +- libavcodec/alpha/dsputil_alpha.h |2 - libavcodec/alpha/dsputil_alpha_asm.S | 92 - .../alpha/{dsputil_alpha.c = hpeldsp_alpha.c} | 142 +- libavcodec/alpha/hpeldsp_asm.S | 135 + libavcodec/arm/Makefile|8 + libavcodec/arm/dsputil_arm.S | 584 libavcodec/arm/dsputil_armv6.S | 238 -- libavcodec/arm/dsputil_init_arm.c | 39 - libavcodec/arm/dsputil_init_armv6.c| 41 - libavcodec/arm/dsputil_init_neon.c | 59 - libavcodec/arm/dsputil_neon.S | 388 --- libavcodec/arm/{dsputil_arm.S = hpeldsp_arm.S}| 98 - libavcodec/arm/hpeldsp_arm.h | 29 + libavcodec/arm/hpeldsp_armv6.S | 259 ++ libavcodec/arm/hpeldsp_init_arm.c | 68 + libavcodec/arm/hpeldsp_init_armv6.c| 66 + libavcodec/arm/hpeldsp_init_neon.c | 87 + libavcodec/arm/{dsputil_neon.S = hpeldsp_neon.S} | 187 -- libavcodec/bfin/Makefile |8 +- libavcodec/bfin/dsputil_bfin.c | 98 +- .../bfin/{pixels_bfin.S = hpel_pixels_bfin.S} | 361 -- libavcodec/bfin/hpeldsp_bfin.c | 134 + libavcodec/bfin/pixels_bfin.S | 357 -- libavcodec/bink.c | 17 +- libavcodec/dsputil.c | 20 +- libavcodec/dsputil.h | 48 - libavcodec/dsputil_template.c | 201 -- libavcodec/hpelavg_template.c | 55 + libavcodec/hpeldsp.c | 238 ++ libavcodec/hpeldsp.h | 132 + libavcodec/hpeldsp_template.c | 174 + libavcodec/indeo3.c|9 +- libavcodec/interplayvideo.c| 10 +- libavcodec/mimic.c |7 +- libavcodec/motion_est.c| 28 +- libavcodec/mpegvideo.c | 15 +- libavcodec/mpegvideo.h | 10 +- libavcodec/mpegvideo_enc.c | 14 +- libavcodec/mpegvideo_motion.c | 26 +- libavcodec/ppc/Makefile|1 + libavcodec/ppc/dsputil_altivec.c | 421 --- libavcodec/ppc/hpeldsp_altivec.c | 471 +++ libavcodec/sh4/Makefile|2 + libavcodec/sh4/dsputil_align.c | 1221 +-- libavcodec/sh4/dsputil_align.h | 112 + libavcodec/sh4/hpeldsp_align.c | 227 ++ libavcodec/sh4/qpel.c | 951 -- libavcodec/sparc/Makefile |2 + libavcodec/sparc/dsputil_vis.c | 3504 +--- libavcodec/sparc/{dsputil_vis.c = hpeldsp_vis.c} | 73 +- libavcodec/svq1dec.c | 12 +- libavcodec/svq1enc.c | 15 +- libavcodec/svq3.c | 14 +- libavcodec/vc1dec.c| 16 +- libavcodec/vp3.c | 14 +- libavcodec/vp56.c | 15 +- libavcodec/vp56.h |2 + libavcodec/wmv2.c |2 +- libavcodec/x86/Makefile|2 + libavcodec/x86/dsputil.asm |
[libav-devel] [PATCH] AVBuffer: add a new API for buffer pools
--- libavutil/buffer.c | 154 +++ libavutil/buffer.h | 75 + libavutil/buffer_internal.h | 32 + 3 files changed, 261 insertions(+) diff --git a/libavutil/buffer.c b/libavutil/buffer.c index 44262f1..0c00a44 100644 --- a/libavutil/buffer.c +++ b/libavutil/buffer.c @@ -192,3 +192,157 @@ int av_buffer_realloc(AVBufferRef **pbuf, int size) buf-buffer-size = buf-size = size; return 0; } + +AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size)) +{ +AVBufferPool *pool = av_mallocz(sizeof(*pool)); +if (!pool) +return NULL; + +pool-size = size; +pool-alloc= alloc ? alloc : av_buffer_alloc; + +avpriv_atomic_int_set(pool-refcount, 1); + +return pool; +} + +/* + * This function gets called when the pool has been uninited and + * all the buffers returned to it. + */ +static void buffer_pool_free(AVBufferPool *pool) +{ +while (pool-pool) { +BufferPoolEntry *buf = pool-pool; +pool-pool = buf-next; + +buf-free(buf-opaque, buf-data); +av_freep(buf); +} +av_freep(pool); +} + +void av_buffer_pool_uninit(AVBufferPool **ppool) +{ +AVBufferPool *pool; + +if (!ppool || !*ppool) +return; +pool = *ppool; +*ppool = NULL; + +if (!avpriv_atomic_int_add_and_fetch(pool-refcount, -1)) +buffer_pool_free(pool); +} + +/* remove the whole buffer list from the pool and return it */ +static BufferPoolEntry *get_pool(AVBufferPool *pool) +{ +BufferPoolEntry *cur = NULL, *last = NULL; + +do { +FFSWAP(BufferPoolEntry*, cur, last); +cur = avpriv_atomic_ptr_cas((void * volatile *)pool-pool, last, NULL); +if (!cur) +return NULL; +} while (cur != last); + +return cur; +} + +static void add_to_pool(BufferPoolEntry *buf) +{ +AVBufferPool *pool; +BufferPoolEntry *cur, *end = buf; + +if (!buf) +return; +pool = buf-pool; + +while (end-next) +end = end-next; + +while ((cur = avpriv_atomic_ptr_cas((void * volatile *)pool-pool, NULL, buf))) { +/* pool is not empty, retrieve it and append it to our list */ +cur = get_pool(pool); +end-next = cur; +while (end-next) +end = end-next; +} +} + +static void pool_release_buffer(void *opaque, uint8_t *data) +{ +BufferPoolEntry *buf = opaque; +AVBufferPool *pool = buf-pool; +add_to_pool(buf); +if (!avpriv_atomic_int_add_and_fetch(pool-refcount, -1)) +buffer_pool_free(pool); +} + +/* allocate a new buffer and override its free() callback so that + * it is returned to the pool on free */ +static AVBufferRef *pool_alloc_buffer(AVBufferPool *pool) +{ +BufferPoolEntry *buf; +AVBufferRef *ret; + +ret = pool-alloc(pool-size); +if (!ret) +return NULL; + +buf = av_mallocz(sizeof(*buf)); +if (!buf) { +av_buffer_unref(ret); +return NULL; +} + +buf-data = ret-buffer-data; +buf-opaque = ret-buffer-opaque; +buf-free = ret-buffer-free; +buf-pool = pool; + +ret-buffer-opaque = buf; +ret-buffer-free = pool_release_buffer; + +avpriv_atomic_int_add_and_fetch(pool-refcount, 1); + +return ret; +} + +AVBufferRef *av_buffer_alloc_pool(AVBufferPool *pool) +{ +AVBufferRef *ret; +BufferPoolEntry *buf; + +/* check whether the pool is empty */ +buf = get_pool(pool); +if (!buf) +return pool_alloc_buffer(pool); + +/* keep the first entry, return the rest of the list to the pool */ +add_to_pool(buf-next); +buf-next = NULL; + +ret = av_buffer_create(buf-data, pool-size, pool_release_buffer, + buf, 0); +if (!ret) { +add_to_pool(buf); +return NULL; +} +avpriv_atomic_int_add_and_fetch(pool-refcount, 1); + +return ret; +} + +AVBufferRef *av_buffer_allocz_pool(AVBufferPool *pool) +{ +AVBufferRef *ret = av_buffer_alloc_pool(pool); + +if (!ret) +return NULL; + +memset(ret-data, 0, ret-size); +return ret; +} diff --git a/libavutil/buffer.h b/libavutil/buffer.h index 9b23bc3..d0b3db5 100644 --- a/libavutil/buffer.h +++ b/libavutil/buffer.h @@ -192,4 +192,79 @@ int av_buffer_realloc(AVBufferRef **buf, int size); * @} */ +/** + * @defgroup lavu_bufferpool AVBufferPool + * @ingroup lavu_data + * + * @{ + * AVBufferPool is an API for a lock-free thread-safe pool of AVBuffers. + * + * Frequently allocating and freeing large buffers may be slow. AVBufferPool is + * meant to solve this in cases when the caller needs a set of buffers of the + * same size (the most obvious use case being buffers for raw video or audio + * frames). + * + * At the beginning, the user must call av_buffer_pool_init() to create the + * buffer pool. Then whenever a buffer is needed, call av_buffer_alloc_pool() to + * get a reference to a new buffer, similar
Re: [libav-devel] [PATCH] AVBuffer: add a new API for buffer pools
On Mon, 28 Jan 2013 11:21:17 +0100, Reinhard Tartler siret...@gmail.com wrote: On Mon, Jan 28, 2013 at 7:53 AM, Anton Khirnov an...@khirnov.net wrote: +/* remove the whole buffer list from the pool and return it */ +static BufferPoolEntry *get_pool(AVBufferPool *pool) +{ +BufferPoolEntry *cur, *last = NULL; + +cur = avpriv_atomic_ptr_cas((void * volatile *)pool-pool, NULL, NULL); +if (!cur) +return NULL; + +while (cur != last) { +FFSWAP(BufferPoolEntry*, cur, last); +cur = avpriv_atomic_ptr_cas((void * volatile *)pool-pool, last, NULL); +} I think a do {} while() would make this look a bit less weird. Fixed +/** + * @defgroup lavu_bufferpool AVBufferPool + * @ingroup lavu_data + * + * @{ + * AVBufferPool is an API for a lock-free thread-safe pool of AVBuffers. + * + * Frequently allocating and freeing large buffers may be slow. AVBufferPool is + * meant to solve this in cases when the caller needs a set of buffers of the + * same size (the most obvious use case being buffers for raw video or audio + * frames). + * + * At the beginning, the user must call av_buffer_pool_init() to create the + * buffer pool. Then whenever a buffer is needed, call av_buffer_alloc_pool() to + * get a reference to a new buffer, similar to av_buffer_alloc(). This new + * reference works in all aspects the same way as the one created by + * av_buffer_alloc(). However, when the last reference to this buffer is + * unreferenced, it is returned to the pool instead of being freed and will be + * reused for subsequent av_buffer_alloc_pool() calls. + * + * When the caller is done with the pool and no longer needs to allocate any new + * buffers, av_buffer_pool_uninit() must be called to mark the pool as freeable. + * Once all the buffers are released, it will automatically be freed. + * + * Allocating and releasing buffers with this API is thread-safe as long as + * either the default alloc callback is used, or the user-supplied one is + * thread-safe. + */ + +/** + * The buffer pool. This structure is opaque and not meant to be accessed + * directly. It is allocated with av_buffer_pool_init() and freed with + * av_buffer_pool_uninit(). + */ +typedef struct AVBufferPool AVBufferPool; + +/** + * Allocate and initialize a buffer pool. + * + * @param size size of each buffer in this pool + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. May be NULL, then the default allocator will be used + * (av_buffer_alloc()). + * @return newly created buffer pool on success, NULL on error. + */ +AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size)); + +/** + * Mark the pool as being available for freeing. It will actually be freed only + * once all the allocated buffers associated with the pool are released. Thus it + * is safe to call this function while some of the allocated buffers are still + * in use. + * + * @param pool pointer to the pool to be freed. It will be set to NULL. + * @see av_buffer_pool_can_uninit() + */ +void av_buffer_pool_uninit(AVBufferPool **pool); + +/** + * Allocate a new AVBuffer, reusing an old buffer from the pool when available. + * + * @return a reference to the new buffer on success, NULL on error. + */ +AVBufferRef *av_buffer_alloc_pool(AVBufferPool *pool); + +/** + * Same as av_buffer_allocz_pool(), except the data in the returned buffer will + * be initialized to zero. + */ +AVBufferRef *av_buffer_allocz_pool(AVBufferPool *pool); + +/** + * @} + */ The documentation should elaborate a bit more what methods support what kind of concurrency situation. Which of them may be called from different threads simultanously, and which not? Wel...the whole API is just 3.5 functions (alloc/allocz are the same thing with a different flavor). init and uninit it only makes sense to call once, so the question of concurrency does not even arise. alloc is thread-safe, as the documentation explicitly says. So I don't see what more could be said here. -- Anton Khirnov ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
Re: [libav-devel] [PATCH] AVBuffer: add a new API for buffer pools
On Mon, Jan 28, 2013 at 5:20 PM, Anton Khirnov an...@khirnov.net wrote: On Mon, 28 Jan 2013 11:21:17 +0100, Reinhard Tartler siret...@gmail.com wrote: On Mon, Jan 28, 2013 at 7:53 AM, Anton Khirnov an...@khirnov.net wrote: +/* remove the whole buffer list from the pool and return it */ +static BufferPoolEntry *get_pool(AVBufferPool *pool) +{ +BufferPoolEntry *cur, *last = NULL; + +cur = avpriv_atomic_ptr_cas((void * volatile *)pool-pool, NULL, NULL); +if (!cur) +return NULL; + +while (cur != last) { +FFSWAP(BufferPoolEntry*, cur, last); +cur = avpriv_atomic_ptr_cas((void * volatile *)pool-pool, last, NULL); +} I think a do {} while() would make this look a bit less weird. Fixed +/** + * @defgroup lavu_bufferpool AVBufferPool + * @ingroup lavu_data + * + * @{ + * AVBufferPool is an API for a lock-free thread-safe pool of AVBuffers. + * + * Frequently allocating and freeing large buffers may be slow. AVBufferPool is + * meant to solve this in cases when the caller needs a set of buffers of the + * same size (the most obvious use case being buffers for raw video or audio + * frames). + * + * At the beginning, the user must call av_buffer_pool_init() to create the + * buffer pool. Then whenever a buffer is needed, call av_buffer_alloc_pool() to + * get a reference to a new buffer, similar to av_buffer_alloc(). This new + * reference works in all aspects the same way as the one created by + * av_buffer_alloc(). However, when the last reference to this buffer is + * unreferenced, it is returned to the pool instead of being freed and will be + * reused for subsequent av_buffer_alloc_pool() calls. + * + * When the caller is done with the pool and no longer needs to allocate any new + * buffers, av_buffer_pool_uninit() must be called to mark the pool as freeable. + * Once all the buffers are released, it will automatically be freed. + * + * Allocating and releasing buffers with this API is thread-safe as long as + * either the default alloc callback is used, or the user-supplied one is + * thread-safe. + */ + +/** + * The buffer pool. This structure is opaque and not meant to be accessed + * directly. It is allocated with av_buffer_pool_init() and freed with + * av_buffer_pool_uninit(). + */ +typedef struct AVBufferPool AVBufferPool; + +/** + * Allocate and initialize a buffer pool. + * + * @param size size of each buffer in this pool + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. May be NULL, then the default allocator will be used + * (av_buffer_alloc()). + * @return newly created buffer pool on success, NULL on error. + */ +AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size)); + +/** + * Mark the pool as being available for freeing. It will actually be freed only + * once all the allocated buffers associated with the pool are released. Thus it + * is safe to call this function while some of the allocated buffers are still + * in use. + * + * @param pool pointer to the pool to be freed. It will be set to NULL. + * @see av_buffer_pool_can_uninit() + */ +void av_buffer_pool_uninit(AVBufferPool **pool); + +/** + * Allocate a new AVBuffer, reusing an old buffer from the pool when available. + * + * @return a reference to the new buffer on success, NULL on error. + */ +AVBufferRef *av_buffer_alloc_pool(AVBufferPool *pool); + +/** + * Same as av_buffer_allocz_pool(), except the data in the returned buffer will + * be initialized to zero. + */ +AVBufferRef *av_buffer_allocz_pool(AVBufferPool *pool); + +/** + * @} + */ The documentation should elaborate a bit more what methods support what kind of concurrency situation. Which of them may be called from different threads simultanously, and which not? Wel...the whole API is just 3.5 functions (alloc/allocz are the same thing with a different flavor). init and uninit it only makes sense to call once, so the question of concurrency does not even arise. alloc is thread-safe, as the documentation explicitly says. So I don't see what more could be said here. The general description does, but not the documentation for the actual methods. AFAIUI, calling init multiple times is not only pointless, but also harmful. I would prefer either the documentation to state this, or the implementation to cover such misbehavior. I will not fight for both points, as said, these things caught my eye. -- regards, Reinhard ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
Re: [libav-devel] [PATCH] AVBuffer: add a new API for buffer pools
On Mon, 28 Jan 2013 17:39:34 +0100, Reinhard Tartler siret...@gmail.com wrote: On Mon, Jan 28, 2013 at 5:20 PM, Anton Khirnov an...@khirnov.net wrote: On Mon, 28 Jan 2013 11:21:17 +0100, Reinhard Tartler siret...@gmail.com wrote: On Mon, Jan 28, 2013 at 7:53 AM, Anton Khirnov an...@khirnov.net wrote: +/* remove the whole buffer list from the pool and return it */ +static BufferPoolEntry *get_pool(AVBufferPool *pool) +{ +BufferPoolEntry *cur, *last = NULL; + +cur = avpriv_atomic_ptr_cas((void * volatile *)pool-pool, NULL, NULL); +if (!cur) +return NULL; + +while (cur != last) { +FFSWAP(BufferPoolEntry*, cur, last); +cur = avpriv_atomic_ptr_cas((void * volatile *)pool-pool, last, NULL); +} I think a do {} while() would make this look a bit less weird. Fixed +/** + * @defgroup lavu_bufferpool AVBufferPool + * @ingroup lavu_data + * + * @{ + * AVBufferPool is an API for a lock-free thread-safe pool of AVBuffers. + * + * Frequently allocating and freeing large buffers may be slow. AVBufferPool is + * meant to solve this in cases when the caller needs a set of buffers of the + * same size (the most obvious use case being buffers for raw video or audio + * frames). + * + * At the beginning, the user must call av_buffer_pool_init() to create the + * buffer pool. Then whenever a buffer is needed, call av_buffer_alloc_pool() to + * get a reference to a new buffer, similar to av_buffer_alloc(). This new + * reference works in all aspects the same way as the one created by + * av_buffer_alloc(). However, when the last reference to this buffer is + * unreferenced, it is returned to the pool instead of being freed and will be + * reused for subsequent av_buffer_alloc_pool() calls. + * + * When the caller is done with the pool and no longer needs to allocate any new + * buffers, av_buffer_pool_uninit() must be called to mark the pool as freeable. + * Once all the buffers are released, it will automatically be freed. + * + * Allocating and releasing buffers with this API is thread-safe as long as + * either the default alloc callback is used, or the user-supplied one is + * thread-safe. + */ + +/** + * The buffer pool. This structure is opaque and not meant to be accessed + * directly. It is allocated with av_buffer_pool_init() and freed with + * av_buffer_pool_uninit(). + */ +typedef struct AVBufferPool AVBufferPool; + +/** + * Allocate and initialize a buffer pool. + * + * @param size size of each buffer in this pool + * @param alloc a function that will be used to allocate new buffers when the + * pool is empty. May be NULL, then the default allocator will be used + * (av_buffer_alloc()). + * @return newly created buffer pool on success, NULL on error. + */ +AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size)); + +/** + * Mark the pool as being available for freeing. It will actually be freed only + * once all the allocated buffers associated with the pool are released. Thus it + * is safe to call this function while some of the allocated buffers are still + * in use. + * + * @param pool pointer to the pool to be freed. It will be set to NULL. + * @see av_buffer_pool_can_uninit() + */ +void av_buffer_pool_uninit(AVBufferPool **pool); + +/** + * Allocate a new AVBuffer, reusing an old buffer from the pool when available. + * + * @return a reference to the new buffer on success, NULL on error. + */ +AVBufferRef *av_buffer_alloc_pool(AVBufferPool *pool); + +/** + * Same as av_buffer_allocz_pool(), except the data in the returned buffer will + * be initialized to zero. + */ +AVBufferRef *av_buffer_allocz_pool(AVBufferPool *pool); + +/** + * @} + */ The documentation should elaborate a bit more what methods support what kind of concurrency situation. Which of them may be called from different threads simultanously, and which not? Wel...the whole API is just 3.5 functions (alloc/allocz are the same thing with a different flavor). init and uninit it only makes sense to call once, so the question of concurrency does not even arise. alloc is thread-safe, as the documentation explicitly says. So I don't see what more could be said here. The general description does, but not the documentation for the actual methods. Ok, added a note about this to av_buffer_alloc() locally. AFAIUI, calling init multiple times is not only pointless, but also harmful. I would prefer either the documentation to state this, or the implementation to cover such misbehavior. No, it's not. Calling init multiple times will simply give you multiple completely independent buffer pools. --
[libav-devel] [PATCH] x86: Simplify some arch conditionals
--- libavcodec/x86/h264_qpel.c |2 +- libavcodec/x86/idct_sse2_xvid.c |2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/x86/h264_qpel.c b/libavcodec/x86/h264_qpel.c index 64af8fe..be4eaa9 100644 --- a/libavcodec/x86/h264_qpel.c +++ b/libavcodec/x86/h264_qpel.c @@ -544,7 +544,7 @@ void ff_h264qpel_init_x86(H264QpelContext *c, int bit_depth) SET_QPEL_FUNCS(avg_h264_qpel, 1, 8, mmxext, ); SET_QPEL_FUNCS(avg_h264_qpel, 2, 4, mmxext, ); } else if (bit_depth == 10) { -#if !ARCH_X86_64 +#if ARCH_X86_32 SET_QPEL_FUNCS(avg_h264_qpel, 0, 16, 10_mmxext, ff_); SET_QPEL_FUNCS(put_h264_qpel, 0, 16, 10_mmxext, ff_); SET_QPEL_FUNCS(put_h264_qpel, 1, 8, 10_mmxext, ff_); diff --git a/libavcodec/x86/idct_sse2_xvid.c b/libavcodec/x86/idct_sse2_xvid.c index fe2478e..f083a2c 100644 --- a/libavcodec/x86/idct_sse2_xvid.c +++ b/libavcodec/x86/idct_sse2_xvid.c @@ -377,7 +377,7 @@ inline void ff_idct_xvid_sse2(short *block) JZ(%%esi, 1f) 5: \n\t iMTX_MULT(7*16(%0), MANGLE(iTab2), ROUND(walkenIdctRounders+5*16), PUT_ODD(ROW7)) -#if !ARCH_X86_64 +#if ARCH_X86_32 iLLM_HEAD #endif iLLM_PASS(%0) -- 1.7.1 ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
Re: [libav-devel] [PATCH] bfin: vp3: Separate VP3 initialization code
On Thu, Jan 24, 2013 at 11:44:00AM +0100, Diego Biurrun wrote: On Wed, Jan 23, 2013 at 04:45:22PM +0100, Luca Barbato wrote: From: Diego Biurrun di...@biurrun.de Signed-off-by: Luca Barbato lu_z...@gentoo.org --- Rebased after the move to int16_t. En passant, adding the missing memsets as pointed by Ronald. Please separate those, patch LGTM otherwise. .. ping .. This conflicts with and thus holds up hpeldsp. Diego ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
Re: [libav-devel] [PATCH] bfin: vp3: Separate VP3 initialization code
On 28/01/13 20:00, Diego Biurrun wrote: On Thu, Jan 24, 2013 at 11:44:00AM +0100, Diego Biurrun wrote: On Wed, Jan 23, 2013 at 04:45:22PM +0100, Luca Barbato wrote: From: Diego Biurrun di...@biurrun.de Signed-off-by: Luca Barbato lu_z...@gentoo.org --- Rebased after the move to int16_t. En passant, adding the missing memsets as pointed by Ronald. Please separate those, patch LGTM otherwise. .. ping .. This conflicts with and thus holds up hpeldsp. I'll split it now, first memsets then the rest, ok? ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
Re: [libav-devel] [PATCH] lavf: Bump minor version to distinguish branch and master version numbers
On Mon, Jan 28, 2013 at 05:47:13PM +0100, Reinhard Tartler wrote: On Wed, Jan 9, 2013 at 5:32 PM, Thomas Goyne tgo...@gmail.com wrote: On Wed, 09 Jan 2013 01:48:15 -0800, Reinhard Tartler siret...@gmail.com wrote: Btw, this is because of the ffmpegsource drama, right? Does this patch actually help the ffmpegsource developers? I would be happy to include additional #defines if, and only if, that would help them. Not particularly. In general we try to support every reasonably recent released version, so it's too late to fix it now. Having 53.21.1 and 53.21.0 be significantly different versions is an improvement over having two 51.21.0s, but it's still pretty terrible since it ignores even the most basic parts of semantic versioning like bigger numbers come after smaller numbers. API version numbers are inherently not very compatible with making API changes on multiple branches. One possible solution would be to have separate non-sequential defines for each API change, so that they can be reordered or cherry-picked willy-nilly. A simpler solution would be to just not change the API in minor releases of stable versions, since that's generally one of the main points of stable branches. What has been done in this case is that ffmpegsource needed this specific API and decided to backport it themselves in a way that clashed the backport in the stable release branch (i.e., by using function names in the ff_*/ av_* namespace). Other options would have also been available, but that's not the point here. From this story, I do think that in some cases, API backports are called for, the challenge is that we need to provide a way to reliably check for their presence. And above all, to communicate/announce these changes more aggressively to avoid such an embarrassing drama. We use FF_API functions to schedule deprecations/removals. Maybe we can also use them for backported APIs? If done properly, this would allow to significantly simplify the #ifdefery in ffmpegsource. How would you use FF_API defines to solve the issue? Diego ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
Re: [libav-devel] [PATCH] bfin: vp3: Separate VP3 initialization code
Hi, On Mon, Jan 28, 2013 at 11:01 AM, Luca Barbato lu_z...@gentoo.org wrote: On 28/01/13 20:00, Diego Biurrun wrote: On Thu, Jan 24, 2013 at 11:44:00AM +0100, Diego Biurrun wrote: On Wed, Jan 23, 2013 at 04:45:22PM +0100, Luca Barbato wrote: From: Diego Biurrun di...@biurrun.de Signed-off-by: Luca Barbato lu_z...@gentoo.org --- Rebased after the move to int16_t. En passant, adding the missing memsets as pointed by Ronald. Please separate those, patch LGTM otherwise. .. ping .. This conflicts with and thus holds up hpeldsp. I'll split it now, first memsets then the rest, ok? No, just commit it. I'm really bright enough to do a trivial rebase. Please review each patch on its own merits. Ronald ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
Re: [libav-devel] [PATCH] x86: Simplify some arch conditionals
Hi, On Mon, Jan 28, 2013 at 10:53 AM, Diego Biurrun di...@biurrun.de wrote: --- libavcodec/x86/h264_qpel.c |2 +- libavcodec/x86/idct_sse2_xvid.c |2 +- 2 files changed, 2 insertions(+), 2 deletions(-) OK. Ronald ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
[libav-devel] [PATCH 1/2] bfin: update VP3 idct
The block must be set to 0. --- Already approved, sent for reference. libavcodec/bfin/vp3_bfin.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/bfin/vp3_bfin.c b/libavcodec/bfin/vp3_bfin.c index 962d383..267918c 100644 --- a/libavcodec/bfin/vp3_bfin.c +++ b/libavcodec/bfin/vp3_bfin.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include string.h + #include libavcodec/avcodec.h #include libavcodec/dsputil.h #include dsputil_bfin.h @@ -33,6 +35,8 @@ void ff_bfin_vp3_idct_put (uint8_t *dest, int line_size, int16_t *block) for (i=0;i8;i++) for (j=0;j8;j++) dest[line_size*i+j]=cm[block[i*8+j]]; + +memset(block, 0, 128); } /* Inter iDCT */ @@ -40,4 +44,6 @@ void ff_bfin_vp3_idct_add (uint8_t *dest, int line_size, int16_t *block) { ff_bfin_vp3_idct (block); ff_bfin_add_pixels_clamped (block, dest, line_size); + +memset(block, 0, 128); } -- 1.8.0.2 ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
[libav-devel] [PATCH 2/2] bfin: Separate VP3 initialization code
From: Diego Biurrun di...@biurrun.de --- Already approved, sent for reference. libavcodec/bfin/Makefile | 4 ++-- libavcodec/bfin/dsputil_bfin.c | 8 +--- libavcodec/bfin/dsputil_bfin.h | 3 --- libavcodec/bfin/vp3_bfin.c | 9 - libavcodec/vp3dsp.c| 2 ++ libavcodec/vp3dsp.h| 1 + 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/libavcodec/bfin/Makefile b/libavcodec/bfin/Makefile index be81e6c..d1b41bc 100644 --- a/libavcodec/bfin/Makefile +++ b/libavcodec/bfin/Makefile @@ -2,7 +2,7 @@ OBJS += bfin/dsputil_bfin.o \ bfin/fdct_bfin.o\ bfin/idct_bfin.o\ bfin/pixels_bfin.o \ -bfin/vp3_bfin.o \ -bfin/vp3_idct_bfin.o\ OBJS-$(CONFIG_MPEGVIDEOENC) += bfin/mpegvideo_bfin.o +OBJS-$(CONFIG_VP3DSP) += bfin/vp3_bfin.o \ + bfin/vp3_idct_bfin.o diff --git a/libavcodec/bfin/dsputil_bfin.c b/libavcodec/bfin/dsputil_bfin.c index 5d60184..896a3c5 100644 --- a/libavcodec/bfin/dsputil_bfin.c +++ b/libavcodec/bfin/dsputil_bfin.c @@ -257,13 +257,7 @@ void ff_dsputil_init_bfin( DSPContext* c, AVCodecContext *avctx ) if (avctx-dct_algo == FF_DCT_AUTO) c-fdct = ff_bfin_fdct; -// FIXME convert to VP3DSPContext -if (0) { // avctx-idct_algo == FF_IDCT_VP3) { -c-idct_permutation_type = FF_NO_IDCT_PERM; -c-idct = ff_bfin_vp3_idct; -c-idct_add = ff_bfin_vp3_idct_add; -c-idct_put = ff_bfin_vp3_idct_put; -} else if (avctx-idct_algo == FF_IDCT_AUTO) { +if (avctx-idct_algo == FF_IDCT_AUTO) { c-idct_permutation_type = FF_NO_IDCT_PERM; c-idct = ff_bfin_idct; c-idct_add = bfin_idct_add; diff --git a/libavcodec/bfin/dsputil_bfin.h b/libavcodec/bfin/dsputil_bfin.h index a7c5863..238c73c 100644 --- a/libavcodec/bfin/dsputil_bfin.h +++ b/libavcodec/bfin/dsputil_bfin.h @@ -38,9 +38,6 @@ void ff_bfin_idct (int16_t *block) attribute_l1_text; void ff_bfin_fdct (int16_t *block) attribute_l1_text; -void ff_bfin_vp3_idct (int16_t *block); -void ff_bfin_vp3_idct_put (uint8_t *dest, int line_size, int16_t *block); -void ff_bfin_vp3_idct_add (uint8_t *dest, int line_size, int16_t *block); void ff_bfin_add_pixels_clamped (const int16_t *block, uint8_t *dest, int line_size) attribute_l1_text; void ff_bfin_put_pixels_clamped (const int16_t *block, uint8_t *dest, int line_size) attribute_l1_text; void ff_bfin_diff_pixels (int16_t *block, const uint8_t *s1, const uint8_t *s2, int stride) attribute_l1_text; diff --git a/libavcodec/bfin/vp3_bfin.c b/libavcodec/bfin/vp3_bfin.c index 267918c..68c17ee 100644 --- a/libavcodec/bfin/vp3_bfin.c +++ b/libavcodec/bfin/vp3_bfin.c @@ -21,8 +21,9 @@ #include string.h #include libavcodec/avcodec.h -#include libavcodec/dsputil.h +#include libavcodec/vp3dsp.h #include dsputil_bfin.h +#include vp3_bfin.h /* Intra iDCT offset 128 */ void ff_bfin_vp3_idct_put (uint8_t *dest, int line_size, int16_t *block) @@ -47,3 +48,9 @@ void ff_bfin_vp3_idct_add (uint8_t *dest, int line_size, int16_t *block) memset(block, 0, 128); } + +void ff_vp3dsp_init_bfin(VP3DSPContext *c, int flags) +{ +c-idct_add = ff_bfin_vp3_idct_add; +c-idct_put = ff_bfin_vp3_idct_put; +} diff --git a/libavcodec/vp3dsp.c b/libavcodec/vp3dsp.c index f6d2c2a..01649f0 100644 --- a/libavcodec/vp3dsp.c +++ b/libavcodec/vp3dsp.c @@ -310,6 +310,8 @@ av_cold void ff_vp3dsp_init(VP3DSPContext *c, int flags) if (ARCH_ARM) ff_vp3dsp_init_arm(c, flags); +if (ARCH_BFIN) +ff_vp3dsp_init_bfin(c, flags); if (ARCH_PPC) ff_vp3dsp_init_ppc(c, flags); if (ARCH_X86) diff --git a/libavcodec/vp3dsp.h b/libavcodec/vp3dsp.h index a5e25ec..755271d 100644 --- a/libavcodec/vp3dsp.h +++ b/libavcodec/vp3dsp.h @@ -49,6 +49,7 @@ typedef struct VP3DSPContext { void ff_vp3dsp_init(VP3DSPContext *c, int flags); void ff_vp3dsp_init_arm(VP3DSPContext *c, int flags); +void ff_vp3dsp_init_bfin(VP3DSPContext *c, int flags); void ff_vp3dsp_init_ppc(VP3DSPContext *c, int flags); void ff_vp3dsp_init_x86(VP3DSPContext *c, int flags); -- 1.8.0.2 ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
[libav-devel] [PATCH] dsputil: remove unused functions copy_block{2, 4, 8, 16}.
From: Ronald S. Bultje rsbul...@gmail.com --- libavcodec/dsputil_template.c | 48 --- 1 file changed, 48 deletions(-) diff --git a/libavcodec/dsputil_template.c b/libavcodec/dsputil_template.c index f5811c1..a8e4e0b 100644 --- a/libavcodec/dsputil_template.c +++ b/libavcodec/dsputil_template.c @@ -29,54 +29,6 @@ #include bit_depth_template.c -static inline void FUNC(copy_block2)(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, int h) -{ -int i; -for(i=0; ih; i++) -{ -AV_WN2P(dst , AV_RN2P(src )); -dst+=dstStride; -src+=srcStride; -} -} - -static inline void FUNC(copy_block4)(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, int h) -{ -int i; -for(i=0; ih; i++) -{ -AV_WN4P(dst , AV_RN4P(src )); -dst+=dstStride; -src+=srcStride; -} -} - -static inline void FUNC(copy_block8)(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, int h) -{ -int i; -for(i=0; ih; i++) -{ -AV_WN4P(dst, AV_RN4P(src)); -AV_WN4P(dst+4*sizeof(pixel), AV_RN4P(src+4*sizeof(pixel))); -dst+=dstStride; -src+=srcStride; -} -} - -static inline void FUNC(copy_block16)(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, int h) -{ -int i; -for(i=0; ih; i++) -{ -AV_WN4P(dst , AV_RN4P(src )); -AV_WN4P(dst+ 4*sizeof(pixel), AV_RN4P(src+ 4*sizeof(pixel))); -AV_WN4P(dst+ 8*sizeof(pixel), AV_RN4P(src+ 8*sizeof(pixel))); -AV_WN4P(dst+12*sizeof(pixel), AV_RN4P(src+12*sizeof(pixel))); -dst+=dstStride; -src+=srcStride; -} -} - /* draw the edges of width 'w' of an image of size width, height */ //FIXME check that this is ok for mpeg4 interlaced static void FUNCC(draw_edges)(uint8_t *_buf, int _wrap, int width, int height, int w, int h, int sides) -- 1.7.11.3 ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
Re: [libav-devel] [PATCH] dsputil: remove unused functions copy_block{2, 4, 8, 16}.
On Mon, 28 Jan 2013 19:56:55 -0800, Ronald S. Bultje rsbul...@gmail.com wrote: From: Ronald S. Bultje rsbul...@gmail.com --- libavcodec/dsputil_template.c | 48 --- 1 file changed, 48 deletions(-) Looks ok. -- Anton Khirnov ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel
Re: [libav-devel] [PATCH] hpel: split off halfpel MC from dsputil into new DSP context.
On 28/01/13 20:32, Ronald S. Bultje wrote: From: Ronald S. Bultje rsbul...@gmail.com This allows objects to use just halfpel MC without depending on all of dsputil. E.g. indeo3, interplayvideo and svq1dec become dsputil- independent. The fine-grained HAVE_HPEL_* flags allow only compiling a subset of the HPEL functions if a codec only uses a subset of them. Currently, only the C code uses this, I'll add this to the assembly at a later point. PPC had a mismatch in the headers int vs ptrdiff_t fixed locally. It needs a small rebase to fit the bfin changes, The rest builds fine on all the arches I could try. lu ___ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel