From patchwork Wed Jan 23 23:01:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Thompson X-Patchwork-Id: 11848 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 6212D44EBC8 for ; Thu, 24 Jan 2019 01:08:19 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 843EF68AC87; Thu, 24 Jan 2019 01:08:07 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f68.google.com (mail-wm1-f68.google.com [209.85.128.68]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id C8A0F68AC32 for ; Thu, 24 Jan 2019 01:08:00 +0200 (EET) Received: by mail-wm1-f68.google.com with SMTP id m22so1087145wml.3 for ; Wed, 23 Jan 2019 15:08:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jkqxz-net.20150623.gappssmtp.com; s=20150623; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=K+ckRE1InY365w4yXViDKBEk8tQjY9J3x51Zk4s9l3I=; b=jsK3e8oexXFBu9Pq/UkNGGAv2zBoNp/b2wr5Rcc/cvIy/mpleRZB/4Ew2ELT2bMAyX mis9c+LlzfEoTjFScaiq4t7bAAE+jfUCejZpz+Vpk+E4BUt395Bb28jiZ9YzrQDgB73e /zEIaFqgUsj2kZHUjD0saZPWAsWmqrAGEacLXXYMkzB9jNdgrt/ekWqkBc/6PtRfzAXg ntQ7f2ASgn45x3hjF0L4e1VK7GsQR9LDNaDKMtMxhg01jqqsIhNMXeU1i2gJPzDR55KM dRgkSr9oNxtBjmWmFiOtrGrZ+PdBAI7vxiVtqz/Id+JVvgrASP/NQOhdHKeqLETF/a0W /bCQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=K+ckRE1InY365w4yXViDKBEk8tQjY9J3x51Zk4s9l3I=; b=eCdvlhd6+8VWkTVHI6HWQiUzAQBY9oIvSydy1MLGmh5J+LTLy2ir0Q469VIjIB99Vo zp2QI3Js/F6l8v3Bc0fUSwWqbC4KWJA807t1mtFQHavgs8yRvZLPfMqZpCs0pe9sdmbZ LDCmgY4bvbd8ImfJssTxB3iZVtKPTgjeGfGA4YH4UmqIITIxbYrxmKOBwgF1YuUfDeuE OBraLvTwi+gFWHfKMUUH7Lz86yGTC//QpE7euBSwyNIaKnGPhYEoGfUYINZJ2PrtFBi8 IAIdt9ewmmIylPz8tXDx7tqvHcHP5iCKUYvTN4gZqp+2vSv2d7hShAbAYRY5wUuRVXdn aHvQ== X-Gm-Message-State: AJcUukeu2WztIRZPgjWMDvIAFlnR4IZZUR/miNhr1k9BX0LZVtfJfXpr Mv5y9C0aCBhFkA4jOpZ83f+JqDi+o10= X-Google-Smtp-Source: ALg8bN4iOxZe2w6xkBsTsVsqyERJb0tsu8VWO8eoql+q/Mx7mJRLv2FqeOEUjPzETDhUzRkgFhQjZQ== X-Received: by 2002:a1c:1a43:: with SMTP id a64mr51946wma.136.1548284481336; Wed, 23 Jan 2019 15:01:21 -0800 (PST) Received: from rywe.jkqxz.net (cpc91242-cmbg18-2-0-cust650.5-4.cable.virginm.net. [82.8.130.139]) by smtp.gmail.com with ESMTPSA id a62sm48786478wmf.47.2019.01.23.15.01.19 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 23 Jan 2019 15:01:20 -0800 (PST) From: Mark Thompson To: ffmpeg-devel@ffmpeg.org Date: Wed, 23 Jan 2019 23:01:09 +0000 Message-Id: <20190123230114.1086-3-sw@jkqxz.net> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20190123230114.1086-1-sw@jkqxz.net> References: <20190123230114.1086-1-sw@jkqxz.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/7] cbs: Describe allocate/free methods in tabular form X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Unit types are split into three categories, depending on how their content is managed: * POD structure - these require no special treatment. * Structure containing direct internal references to other structures - these can use a common free function when the offsets of all the internal references are known. * More complex structures - these still require ad-hoc treatment. For each codec we can then maintain a table of descriptors for each unit type, defining the mechanism needed to allocate/free that unit content. This is not required to be used immediately - a new alloc function supports this, but does not replace the old one which works without referring to these tables. --- libavcodec/cbs.c | 59 +++++++++++++++++++++++++++++++++++++++ libavcodec/cbs.h | 16 +++++++++++ libavcodec/cbs_internal.h | 31 ++++++++++++++++++++ 3 files changed, 106 insertions(+) diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index ecbf57c293..deabf5dde5 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -665,3 +665,62 @@ int ff_cbs_delete_unit(CodedBitstreamContext *ctx, return 0; } + +static void cbs_default_free_unit_content(void *opaque, uint8_t *data) +{ + const CodedBitstreamUnitTypeDescriptor *desc = opaque; + if (desc->content_type == CBS_CONTENT_TYPE_INTERNAL_REFS) { + int i; + for (i = 0; i < desc->nb_ref_offsets; i++) + av_buffer_unref((AVBufferRef**)(data + desc->ref_offsets[i])); + } + av_free(data); +} + +static const CodedBitstreamUnitTypeDescriptor + *cbs_find_unit_type_desc(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + const CodedBitstreamUnitTypeDescriptor *desc; + int i; + + if (!ctx->codec->unit_types) + return NULL; + + for (i = 0;; i++) { + desc = &ctx->codec->unit_types[i]; + if (desc->unit_type == CBS_INVALID_UNIT_TYPE) + break; + if (desc->unit_type == unit->type) + return desc; + } + return NULL; +} + +int ff_cbs_alloc_unit_content2(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + const CodedBitstreamUnitTypeDescriptor *desc; + + av_assert0(!unit->content && !unit->content_ref); + + desc = cbs_find_unit_type_desc(ctx, unit); + if (!desc) + return AVERROR(ENOSYS); + + unit->content = av_mallocz(desc->content_size); + if (!unit->content) + return AVERROR(ENOMEM); + + unit->content_ref = + av_buffer_create(unit->content, desc->content_size, + desc->content_free ? desc->content_free + : cbs_default_free_unit_content, + (void*)desc, 0); + if (!unit->content_ref) { + av_freep(&unit->content); + return AVERROR(ENOMEM); + } + + return 0; +} diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h index 053eccffde..1079f625bf 100644 --- a/libavcodec/cbs.h +++ b/libavcodec/cbs.h @@ -54,6 +54,13 @@ struct CodedBitstreamType; */ typedef uint32_t CodedBitstreamUnitType; +/** + * Value which is never valid as a unit type. + * + * This can be used as a sentinel. + */ +#define CBS_INVALID_UNIT_TYPE (UINT32_MAX) + /** * Coded bitstream unit structure. * @@ -312,6 +319,15 @@ int ff_cbs_alloc_unit_content(CodedBitstreamContext *ctx, size_t size, void (*free)(void *unit, uint8_t *content)); +/** + * Allocate a new internal content buffer matching the type of the unit. + * + * The content will be zeroed. + */ +int ff_cbs_alloc_unit_content2(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit); + + /** * Allocate a new internal data buffer of the given size in the unit. * diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h index 53f2e5d187..667c90cb14 100644 --- a/libavcodec/cbs_internal.h +++ b/libavcodec/cbs_internal.h @@ -25,11 +25,42 @@ #include "put_bits.h" +enum { + // Unit content is a simple structure. + CBS_CONTENT_TYPE_POD, + // Unit content contains some references to other structures, but all + // managed via buffer reference counting. The descriptor defines the + // structure offsets of every reference. + CBS_CONTENT_TYPE_INTERNAL_REFS, + // Unit content is something more complex. The descriptor defines + // special functions to manage the content. + CBS_CONTENT_TYPE_COMPLEX, +}; + +// Maximum number of reference buffer offsets in any one unit. +#define CBS_MAX_REF_OFFSETS 1 + +typedef struct CodedBitstreamUnitTypeDescriptor { + CodedBitstreamUnitType unit_type; + + int content_type; + size_t content_size; + + int nb_ref_offsets; + size_t ref_offsets[CBS_MAX_REF_OFFSETS]; + + void (*content_free)(void *opaque, uint8_t *data); +} CodedBitstreamUnitTypeDescriptor; + typedef struct CodedBitstreamType { enum AVCodecID codec_id; size_t priv_data_size; + // List of unit type descriptors for this codec. + // Terminated by a descriptor with type CBS_INVALID_UNIT_TYPE. + const CodedBitstreamUnitTypeDescriptor *unit_types; + // Split frag->data into coded bitstream units, creating the // frag->units array. Fill data but not content on each unit. // The header argument should be set if the fragment came from