From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id 439AD473C6 for ; Fri, 6 Oct 2023 18:23:50 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 579B468CA38; Fri, 6 Oct 2023 21:23:47 +0300 (EEST) Received: from EUR05-DB8-obe.outbound.protection.outlook.com (mail-db8eur05olkn2033.outbound.protection.outlook.com [40.92.89.33]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8A82B68C935 for ; Fri, 6 Oct 2023 21:23:41 +0300 (EEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=J3yOQmF6++YxS3ir3I9SeCP2wSFNwtrLUnaU/TRkt6ZPIvqjkNSdnrl3DQAoH/G2JTNLXJ9vtSZjiArOGb6UrFnxC6JVckGMD1vRScUF0aEBYfw+uBqe6zC6xKR45f25+SpqhMvQz+dEFt9KAwStx9mKOqpHVQfNXzXlxFIN9kyKAul7ccqJs2rL0AqnexHcXXBOmKqxOdIisI9IXue4h3HU/MrnE6PtM5/K2tC4zy983b5EmRrg5r75dBoMq7UGZHpe1mkMihBndY1xDMzj5p8o5iPZymf3pFUqmhnXwXTQs97ej+fFDW9xhqkiTMYP9ticTyVn68UyghB1fambHg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=IikyX5ZNgluTCKsj1q0bsDnztO8TTZ6zErgsogg3y0Q=; b=Efo0psrBVtdsfksk2xNLPYpQPQrd+QcuzVP3tBfLS8Zz0nU3TG+nioovDYh/AeCvn9iJG6jFQSU0w3Ly4PX1pEpVPdvelLOl5liOzMlA/SDm2IJ/Xcj6qEya3k8c7KdE6hI465XoOK76MvYzu3BbquyXqGX37pyJI5MNiX6lmDRwc7GnkN6JYbt0FySCqLmBWobogn0uqlC4c+OGTzArrkHsOTRQVtY39M8etiWzsUpAVfBiSwsYawgb20TbsVZUTRKimdpwqujBXbsG3iovxe0ztIio01YKnK6KIkwSSbD0ssA8loSqlxK+QMnfGHgTNWgW4PJfHR+F0nWjYDCZ4w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=outlook.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=IikyX5ZNgluTCKsj1q0bsDnztO8TTZ6zErgsogg3y0Q=; b=Uf9gBQvabG+eU88piBgn+cpYdHE8UFmv2HutatcGAweIJJCwYu+wSmOMFXC4AJfLBp6HBvt3RuXdIreZ/s6uSqR7ui4ADGbnZasSufaiPCC+UJV2kRASoQdFH8yBkglNyuxXuiLBWsiycXC9t9IEuVeNK20YapkT2DRx/IZY42UFPdLxd5c7//32kUaVgE1QG+p9oRTD0SWjbBYrk8pcGyGB8xWIbMbsdolMTvN2o8itK+Me98Ac7tpv0c2k8Et295iSMnNQCnx9SF7/eA2Yv7ddcQ/WQIJTFBY0oN2hlJm8I3LtWFfswFpvlxONfnmyFnmerswNhT+toqM6WGGK7A== Received: from AS8P250MB0744.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:541::14) by AS1P250MB0405.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:4ad::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6838.33; Fri, 6 Oct 2023 18:23:39 +0000 Received: from AS8P250MB0744.EURP250.PROD.OUTLOOK.COM ([fe80::5e01:aea5:d3a8:cafa]) by AS8P250MB0744.EURP250.PROD.OUTLOOK.COM ([fe80::5e01:aea5:d3a8:cafa%3]) with mapi id 15.20.6792.026; Fri, 6 Oct 2023 18:23:39 +0000 Message-ID: Date: Fri, 6 Oct 2023 20:24:53 +0200 User-Agent: Mozilla Thunderbird To: ffmpeg-devel@ffmpeg.org References: Content-Language: en-US From: Andreas Rheinhardt In-Reply-To: X-TMN: [q0sprm6u+HCrmPpBR26dg4Glprn5UE15] X-ClientProxiedBy: FR4P281CA0041.DEUP281.PROD.OUTLOOK.COM (2603:10a6:d10:c7::11) To AS8P250MB0744.EURP250.PROD.OUTLOOK.COM (2603:10a6:20b:541::14) X-Microsoft-Original-Message-ID: MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AS8P250MB0744:EE_|AS1P250MB0405:EE_ X-MS-Office365-Filtering-Correlation-Id: fe04e1de-caf3-4fed-1281-08dbc6995ca4 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: xEfFfDiDPQLyj8KyCDC/CeOkOXfBd1N1kXMltbxrjGUHLocpalMJeq2WyW2z7xpdqIXlDOTPwS3xE8VClTx/GsnjKZcirDvwzbYY6AytAwjdxWANXSvsR2N4sgm70ICLUqYVVQjC0zBwDy/9EgE18Whl2Z1dYTLmUToylbtMQ1ZQsQ3UQyppT0QAxtWwZzLR/tRgZ3OOxtKzia68Uw3obyKwsZWVQQBabOaC+xOhiiZnitbKUm4pB7PA1ITuwP/geYgkdUrncEOxB7pOTssZwuCo+j6yCxOgTTdEGVo4mxDQbaLFgC/pPVq7Pi8QIjckpjVEks+JrW3tk4Y6RWKWN32rtF3mCpwNXGrkf74jq2OtYhUIKk7reL7Oeg3xOJd0M4L1bKUBEank8isiDVRFyJVhYFLnmcPf/xyhrpyIh6OAIyuVWeduveMPIdpGQm1qGALtz+LcJIjkswG2hteTWlKGom/dX7cDxaz7kauMMQdX0HNwnCpAMEiMoWQqF3azf0lS0LgmNqRsJ7lXOOo50L2fyk6PUDqiAhBsb7ELavFfgjAQ9EGYWejFr3Kh3pls X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?T1hwOUlORXpIMisydjc3Qkh0cEh6U0s1WWdMcmNzUDhtdlJwSzB1d010QkdV?= =?utf-8?B?VVVCSE5qa2lHWW9pV2pzcSs3eTdYd2REVU1KdDZYYWRjQmJpdEFQVnFka0pt?= =?utf-8?B?aTFEbis4cDViSVMzYXVQSW1LVUpESmhzOStKcDQzYW5Vcnp4US9hUXg3UVdW?= =?utf-8?B?SXRFLzRNQ3lueGtMRmE1VHlLdkQwZmpsbHllektiTXN0bzJ1a0Q1ajZpVXdE?= =?utf-8?B?L1FVcmFCS1Zsa0o3S1ZCbENGNFJVeWp6Vno3MmlpMldrWEQ2L040S1NqZzdq?= =?utf-8?B?eUZZYnZFNFpkakNGd1QraVNrUnZLUG5KVksxRUVtQVltVVJ2djBHQytFRnFx?= =?utf-8?B?S2ZOT3hjemowUTdSc3ZRV2svRTg3dE84OG1rbTZJSnpTejZNSkt6MVdSZ0xi?= =?utf-8?B?WnF0dC94WC85c0lRU21RNmhOSURudFRrVkdjMnlLV1h0T0R1dnp5K3N3eXpw?= =?utf-8?B?K3BjVTRqUWQ4K2l6S1Q2aWdSZ2F0Tng1VTd3RnBtZmZoM3BQWjBYcHdZMjZE?= =?utf-8?B?YUJuT2VoSlhlajdHaEtKWi9FUkVIakZoMlBLTFZtTnlaRGIzOTBxdEJFSW92?= =?utf-8?B?QXZqRzYrNHNuK2lGRTZZSDlxcVNCYVZ3VzZjcndXWGFER3N2Smdha0VqeGxJ?= =?utf-8?B?a1lMV2JRRVRFRnB5VTVNeTJVY0p2RXFjWmY1UTVIeC9qUllYczFRTnYrZXFC?= =?utf-8?B?MjdITWd3VWx3dGl5d2kvN1YwWXZ5b3V3K3poaHNhSUJwOGhkNDJWVXRPRWhY?= =?utf-8?B?QU1NUVZQZW83L2dmclFaRFpQaTEvYlJsQ0RzVC8yWDZzTi9PNzFiNFB6Rnhj?= =?utf-8?B?RWFOaEFMUWRzTTNsSW5lSjl2WTlDUTV4RzZZR2o5Z09RblNGWUxXMzVzdDRy?= =?utf-8?B?dGJZbXhubjRGcHJMTVphUStUWEJIOHFBbnNPdUYxYThjTDRHd0oxYmFOMVlv?= =?utf-8?B?TFhab3NXRk5vV3JSOUp2TWo0Z0NXSW1ITFBxckFFWjBWUmhGa0Fqd3JLNWhW?= =?utf-8?B?L1hRQ0JCUUJzT3ppQ0YwdTk1bDV4ZjJWckdwK0RkWW1hOS90ckJOQk5ESjBD?= =?utf-8?B?dVp6bW1BYURuc01DRkZOT0RoeE91OUM0VGNhdVQ3U3B1Mkc2L09NODJOcE1v?= =?utf-8?B?am55YUtlbjJXUjVvM3lUN2hZTFNYdlAvOTBtektsZExtYlZseUdVU29HV3FJ?= =?utf-8?B?OGZ1MnNMMHVrencyYlRzMS9kejcvR1pTQ1FsbDR5emJNNnM5aDBqQ3ZhY1E0?= =?utf-8?B?dE5QYVl3d3FhdnZtQk93NEpxbzRWeThzZjVvck0yWE8yaStYaS9xLzF3b3ho?= =?utf-8?B?ZWgyUUJJMUtYTWkwb1l2WXM1QWdXNUxrK1B4bHZ3LzBrZXpPZDEzeThOenYw?= =?utf-8?B?dTFaWmtzenRyQ2RiQ3dncXdjdHJVcFp5dzJlaVNFSkxnaTJhL2F6K1E3dFBp?= =?utf-8?B?R3U4TFZMU1NDaFVzdjY4Z2VCUlM3cWRNWmFKSTF5MWxEcmdLbVpOK0lNSlhC?= =?utf-8?B?TjNxaUZDQ0JmaWtHUGdXT0pyRGhla0g1ZkttSE1meEhVOUI2UHhrMm0xQ2ls?= =?utf-8?B?bUFScnZNVXR2VjNZODdHV2JDeG9BNUF5MFdQTXcveDU0MmNIOFAxcUh1d3dI?= =?utf-8?B?Z0pUeW1vY0Y3SklZTHcraHlqaVhweWR5aFZWdUdHdVc2eDIyT0duVnJ2MUtV?= =?utf-8?Q?Pgi0LQLWgCV4TB7opTC9?= X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: fe04e1de-caf3-4fed-1281-08dbc6995ca4 X-MS-Exchange-CrossTenant-AuthSource: AS8P250MB0744.EURP250.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Oct 2023 18:23:39.2918 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS1P250MB0405 Subject: Re: [FFmpeg-devel] [PATCH 02/42] avcodec/refstruct: Add simple API for refcounted objects X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: Andreas Rheinhardt: > For now, this API is supposed to replace all the internal uses > of reference counted objects in libavcodec; "internal" here > means that the object is created in libavcodec and is never > put directly in the hands of anyone outside of it. > > It is intended to be made public eventually, but for now > I enjoy the ability to modify it freely. > > Several shortcomings of the AVBuffer API motivated this API: > a) The unnecessary allocations (and ensuing error checks) > when using the API. Besides the need for runtime checks it > imposes upon the developer the burden of thinking through > what happens in case an error happens. Furthermore, these > error paths are typically not covered by FATE. > b) The AVBuffer API is designed with buffers and not with > objects in mind: The type for the actual buffers used > is uint8_t*; it pretends to be able to make buffers > writable, but this is wrong in case the buffer is not a POD. > Another instance of this thinking is the lack of a reset > callback in the AVBufferPool API. > c) The AVBuffer API incurs unnecessary indirections by > going through the AVBufferRef.data pointer. In case the user > tries to avoid this indirection and stores a pointer to > AVBuffer.data separately (which also allows to use the correct > type), the user has to keep these two pointers in sync > in case they can change (and in any case has two pointers > occupying space in the containing context). See the following > commit using this API for H.264 parameter sets for an example > of the removal of such syncing code as well as the casts > involved in the parts where only the AVBufferRef* pointer > was stored. > d) Given that the AVBuffer API allows custom allocators, > creating refcounted objects with dedicated free functions > often involves a lot of boilerplate like this: > obj = av_mallocz(sizeof(*obj)); > ref = av_buffer_create((uint8_t*)obj, sizeof(*obj), free_func, opaque, 0); > if (!ref) { > av_free(obj); > return AVERROR(ENOMEM); > } > (There is also a corresponding av_free() at the end of free_func().) > This is now just > obj = ff_refstruct_alloc_ext(sizeof(*obj), 0, opaque, free_func); > if (!obj) > return AVERROR(ENOMEM); > See the subsequent patch for the framepool (i.e. get_buffer.c) > for an example. > > This API does things differently; it is designed to be lightweight* > as well as geared to the common case where the allocator of the > underlying object does not matter as long as it is big enough and > suitably aligned. This allows to allocate the user data together > with the API's bookkeeping data which avoids an allocation as well > as the need for separate pointers to the user data and the API's > bookkeeping data. This entails that the actual allocation of the > object is performed by refstruct, not the user. This is responsible > for avoiding the boilerplate code mentioned in d). > > As a downside, custom allocators are not supported, but it will > become apparent in subsequent commits that there are enough > usecases to make it worthwhile. > > Another advantage of this API is that one only needs to include > the relevant header if one uses the API and not when one includes > the header or some other component that uses it. This is because there > is no refstruct type analog of AVBufferRef. This brings with it > one further downside: It is not apparent from the pointer itself > whether the underlying object is managed by the refstruct API > or whether this pointer is a reference to it (or merely a pointer > to it). > > Finally, this API supports const-qualified opaque pointees; > this will allow to avoid casting const away by the CBS code. > > *: Basically the only exception to the you-only-pay-for-what-you-use > rule is that it always uses atomics for the refcount. > > Signed-off-by: Andreas Rheinhardt > --- > I am the most unsure about whether to use FFRefStructOpaque > at all or not just a void*; the only beneficiary of this > is CBS where it saves casting one const away. > > I am also open to other naming suggestions like RefObject > (RefObj?) for this API. > > libavcodec/Makefile | 1 + > libavcodec/refstruct.c | 139 +++++++++++++++++++++++++++++++++++++++ > libavcodec/refstruct.h | 145 +++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 285 insertions(+) > create mode 100644 libavcodec/refstruct.c > create mode 100644 libavcodec/refstruct.h > > diff --git a/libavcodec/Makefile b/libavcodec/Makefile > index bf3b0a93f9..7541f38535 100644 > --- a/libavcodec/Makefile > +++ b/libavcodec/Makefile > @@ -55,6 +55,7 @@ OBJS = ac3_parser.o \ > profiles.o \ > qsv_api.o \ > raw.o \ > + refstruct.o \ > utils.o \ > version.o \ > vlc.o \ > diff --git a/libavcodec/refstruct.c b/libavcodec/refstruct.c > new file mode 100644 > index 0000000000..917cf6b7ac > --- /dev/null > +++ b/libavcodec/refstruct.c > @@ -0,0 +1,139 @@ > +/* > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > + */ > + > +#include > +#include > +#include > + > +#include "internal.h" > +#include "refstruct.h" > + > +#include "libavutil/macros.h" > +#include "libavutil/mem.h" > + > +typedef struct RefCount { > + /** > + * An uintptr_t is big enough to hold the address of every reference, > + * so no overflow can happen when incrementing the refcount as long as > + * the user does not throw away references. > + */ > + atomic_uintptr_t refcount; > + FFRefStructOpaque opaque; > + void (*free_cb)(FFRefStructOpaque opaque, void *obj); > +} RefCount; > + > +#if __STDC_VERSION__ >= 201112L > +#define REFCOUNT_OFFSET FFALIGN(sizeof(RefCount), FFMAX3(STRIDE_ALIGN, 16, _Alignof(max_align_t))) > +#else > +#define REFCOUNT_OFFSET FFALIGN(sizeof(RefCount), FFMAX(STRIDE_ALIGN, 16)) > +#endif > + > +static RefCount *get_refcount(void *obj) > +{ > + return (RefCount*)((char*)obj - REFCOUNT_OFFSET); > +} > + > +static void *get_userdata(void *buf) > +{ > + return (char*)buf + REFCOUNT_OFFSET; > +} > + > +static void refcount_init(RefCount *ref, FFRefStructOpaque opaque, > + void (*free_cb)(FFRefStructOpaque opaque, void *obj)) > +{ > + atomic_init(&ref->refcount, 1); > + ref->opaque = opaque; > + ref->free_cb = free_cb; > +} > + > +void *ff_refstruct_alloc_ext_c(size_t size, unsigned flags, FFRefStructOpaque opaque, > + void (*free_cb)(FFRefStructOpaque opaque, void *obj)) > +{ > + void *buf, *obj; > + > + if (size > SIZE_MAX - REFCOUNT_OFFSET) > + return NULL; > + buf = av_malloc(size + REFCOUNT_OFFSET); > + if (!buf) > + return NULL; > + refcount_init(buf, opaque, free_cb); > + obj = get_userdata(buf); > + if (!(flags & FF_REFSTRUCT_FLAG_NO_ZEROING)) > + memset(obj, 0, size); > + > + return obj; > +} > + > +void *ff_refstruct_allocz(size_t size) > +{ > + return ff_refstruct_alloc_ext(size, 0, NULL, NULL); > +} > + > +void ff_refstruct_unref(void *objp) > +{ > + void *obj; > + RefCount *ref; > + > + memcpy(&obj, objp, sizeof(obj)); > + if (!obj) > + return; > + memcpy(objp, &(void *){ NULL }, sizeof(obj)); > + > + ref = get_refcount(obj); > + if (atomic_fetch_sub_explicit(&ref->refcount, 1, memory_order_acq_rel) == 1) { > + if (ref->free_cb) > + ref->free_cb(ref->opaque, obj); > + av_free(ref); > + } > + > + return; > +} > + > +void *ff_refstruct_ref(void *obj) > +{ > + RefCount *ref = get_refcount(obj); > + > + atomic_fetch_add_explicit(&ref->refcount, 1, memory_order_relaxed); > + > + return obj; > +} > + > +const void *ff_refstruct_ref_c(const void *obj) > +{ > + /* Casting const away here is fine, as it is only supposed > + * to apply to the user's data and not our bookkeeping data. */ > + RefCount *ref = get_refcount((void*)obj); > + > + atomic_fetch_add_explicit(&ref->refcount, 1, memory_order_relaxed); > + > + return obj; > +} > + > +void ff_refstruct_replace(void *dstp, const void *src) > +{ > + const void *dst; > + memcpy(&dst, dstp, sizeof(dst)); > + > + if (src == dst) > + return; > + ff_refstruct_unref(dstp); > + if (src) { > + dst = ff_refstruct_ref_c(src); > + memcpy(dstp, &dst, sizeof(dst)); > + } > +} > diff --git a/libavcodec/refstruct.h b/libavcodec/refstruct.h > new file mode 100644 > index 0000000000..0086717c17 > --- /dev/null > +++ b/libavcodec/refstruct.h > @@ -0,0 +1,145 @@ > +/* > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > + */ > + > +#ifndef AVCODEC_REFSTRUCT_H > +#define AVCODEC_REFSTRUCT_H > + > +#include > + > +/** > + * RefStruct is an API for creating reference-counted objects > + * with minimal overhead. The API is designed for objects, > + * not buffers like the AVBuffer API. The main differences > + * to the AVBuffer API are as follows: > + * > + * - It uses void* instead of uint8_t* as its base type due to > + * its focus on objects. > + * - There are no equivalents of AVBuffer and AVBufferRef. > + * E.g. there is no way to get the usable size of the object: > + * The user is supposed to know what is at the other end of > + * the pointer. It also avoids one level of indirection. > + * - Custom allocators are not supported. This allows to simplify > + * the implementation and reduce the amount of allocations. > + * - It also has the advantage that the user's free callback need > + * only free the resources owned by the object, but not the > + * object itself. > + * - Because referencing (and replacing) an object managed by the > + * RefStruct API does not involve allocations, they can not fail > + * and therefore need not be checked. > + * > + * @note Referencing and unreferencing the buffers is thread-safe and thus > + * may be done from multiple threads simultaneously without any need for > + * additional locking. > + */ > + > +/** > + * This union is used for all opaque parameters in this API to spare the user > + * to cast const away in case the opaque to use is const-qualified. > + * > + * The functions provided by this API with an FFRefStructOpaque come in pairs > + * named foo_c and foo. The foo function accepts void* as opaque and is just > + * a wrapper around the foo_c function; "_c" means "(potentially) const". > + */ > +typedef union { > + void *nc; > + const void *c; > +} FFRefStructOpaque; > + > +/** > + * If this flag is set in ff_refstruct_alloc_ext_c(), the object will not > + * be initially zeroed. > + */ > +#define FF_REFSTRUCT_FLAG_NO_ZEROING (1 << 0) > + > +/** > + * Allocate a refcounted object of usable size `size` managed via > + * the RefStruct API. > + * > + * By default (in the absence of flags to the contrary), > + * the returned object is initially zeroed. > + * > + * @param size Desired usable size of the returned object. > + * @param flags A bitwise combination of FF_REFSTRUCT_FLAG_* flags. > + * @param opaque A pointer that will be passed to the free_cb callback. > + * @param free_cb A callback for freeing this object's content > + * when its reference count reaches zero; > + * it must not free the object itself. > + * @return A pointer to an object of the desired size or NULL on failure. > + */ > +void *ff_refstruct_alloc_ext_c(size_t size, unsigned flags, FFRefStructOpaque opaque, > + void (*free_cb)(FFRefStructOpaque opaque, void *obj)); > + > +/** > + * A wrapper around ff_refstruct_alloc_ext_c() for the common case > + * of a non-const qualified opaque. > + * > + * @see ff_refstruct_alloc_ext_c() > + */ > +static inline > +void *ff_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque, > + void (*free_cb)(FFRefStructOpaque opaque, void *obj)) > +{ > + return ff_refstruct_alloc_ext_c(size, flags, (FFRefStructOpaque){.nc = opaque}, > + free_cb); > +} > + > +/** > + * Equivalent to ff_refstruct_alloc_ext(size, 0, NULL, NULL) > + */ > +void *ff_refstruct_allocz(size_t size); > + > +/** > + * Decrement the reference count of the underlying object and automatically > + * free the object if there are no more references to it. > + * > + * `*objp == NULL` is legal and a no-op. > + * > + * @param objp Pointer to a pointer that is either NULL or points to an object > + * managed via this API. `*objp` is set to NULL on return. > + */ > +void ff_refstruct_unref(void *objp); > + > +/** > + * Create a new reference to an object managed via this API, > + * i.e. increment the reference count of the underlying object > + * and return obj. > + * @return a pointer equal to obj. > + */ > +void *ff_refstruct_ref(void *obj); > + > +/** > + * Analog of ff_refstruct_ref(), but for constant objects. > + * @see ff_refstruct_ref() > + */ > +const void *ff_refstruct_ref_c(const void *obj); > + > +/** > + * Ensure `*dstp` refers to the same object as src. > + * > + * If `*dstp` is already equal to src, do nothing. Otherwise unreference `*dstp` > + * and replace it with a new reference to src in case `src != NULL` (this > + * involves incrementing the reference count of src's underlying object) or > + * with NULL otherwise. > + * > + * @param dstp Pointer to a pointer that is either NULL or points to an object > + * managed via this API. > + * @param src A pointer to an object managed via this API or NULL. > + */ > +void ff_refstruct_replace(void *dstp, const void *src); > + > +#endif /* AVCODEC_REFSTRUCT_H */ Will apply patches 2-16 (i.e. up to the pool API) tomorrow unless there are objections. - Andreas _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".