From patchwork Wed Jan 23 23:01:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Thompson X-Patchwork-Id: 11849 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 220EF44EDBD for ; Thu, 24 Jan 2019 01:09:25 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 47CD768ACA9; Thu, 24 Jan 2019 01:09:13 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f67.google.com (mail-wm1-f67.google.com [209.85.128.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 35BAC68AC89 for ; Thu, 24 Jan 2019 01:09:07 +0200 (EET) Received: by mail-wm1-f67.google.com with SMTP id g67so1097374wmd.2 for ; Wed, 23 Jan 2019 15:09:25 -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=WQZL5nUlI5zfMD10yuPfSvj67Tl5khaMUPEgv9aUKrY=; b=2JTeZNGV96KcpBJf4R1UfivkUDaTuc0AhxiWuoTgv92GqzJCypWUSz102sL1Ev5RaE Uf86/rXU8NGfHU2oZCge8Kiu42eG7/+Deq1+v+QnWXkAPcO512iDZ6tG6LVPv7tIENds c1R22uadnbv+p0X89wZRR4PjApEG+8G1inKqMVA3kbNskRrdRKpsPbVeqRK6e3012DfJ Qd1BtKayMPgqjE5uhbDkW14Iv56lSm8HgHaq3UGwIF31/ezVbYkrhvmC/qQxU5IeiFRc VZccs7CsN0a+ZrS7oOx1UvuK3fpo8vOCvpik6tf4KnKWux5TPUbo03g0052Z1XI7aHTM Ltyg== 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=WQZL5nUlI5zfMD10yuPfSvj67Tl5khaMUPEgv9aUKrY=; b=rVlAIs1Z3W/gJUJiD4nuYWgPmQvxgk4qfCfp2bzSrpH+dhQzawmKg21iP0k7h/XBhU 3InkhV7xR07eHTZD4FY79M/TrUzvjPReMAksmdli5bLa6qecHDMfH2JFpC48Z9WZ+cil PkENwnmhnDDutbAhpsnNU20QY7Guo0lm1CtgbCFul1sdi2wAai5CUaCeOotIm05qddH1 ikKrRkN8YTt6Um0M1nz6iwIhCCFmVyv82VTn3LV9LLLzfvV0hOt76bDg3Nw5u3r/59No BtrICsq1PLdkaupl9bJvU2CORGgN/Gc5gFjal3ISj5e1SixYpHGY7swUj3WDq2bQ6ScL 2DXw== X-Gm-Message-State: AJcUukdZ8GOIX92g29rSar6yWkyOT+tnN5npnz/fel9rK54/MeE5oCtk A/fVyAop3x7cI2vIAy4ChABUv7fzI4k= X-Google-Smtp-Source: ALg8bN7xN87naiLSh119lt6qCgD6TmiLkGD7sZ3mIs04AuFh/FcihjBg8Grxz7m2gpsAkXIUZn6yTg== X-Received: by 2002:a1c:6e06:: with SMTP id j6mr53845wmc.3.1548284485998; Wed, 23 Jan 2019 15:01:25 -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.24 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 23 Jan 2019 15:01:25 -0800 (PST) From: Mark Thompson To: ffmpeg-devel@ffmpeg.org Date: Wed, 23 Jan 2019 23:01:13 +0000 Message-Id: <20190123230114.1086-7-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 6/7] cbs: Add a function to make content of a unit writable 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" Use the unit type table to determine what we need to do to clone the internals of the unit content. (Will still fail for units with complex content if they do not have a defined clone function.) Setup and naming from a patch by Andreas Rheinhardt , but with the implementation changed to use the unit type information if possible rather than requiring a codec-specific function. --- libavcodec/cbs.c | 92 +++++++++++++++++++++++++++++++++++++++ libavcodec/cbs.h | 13 ++++++ libavcodec/cbs_internal.h | 1 + 3 files changed, 106 insertions(+) diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index deabf5dde5..cbf107528c 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -724,3 +724,95 @@ int ff_cbs_alloc_unit_content2(CodedBitstreamContext *ctx, return 0; } + +static int cbs_clone_unit_content(AVBufferRef **clone_ref, + CodedBitstreamUnit *unit, + const CodedBitstreamUnitTypeDescriptor *desc) +{ + uint8_t *src, *copy; + AVBufferRef **src_buf, **copy_buf; + int err, i = 0; + + av_assert0(unit->type == desc->unit_type); + av_assert0(unit->content); + src = unit->content; + + copy = av_malloc(desc->content_size); + if (!copy) + goto fail; + memcpy(copy, src, desc->content_size); + + for (i = 0; i < desc->nb_ref_offsets; i++) { + src_buf = (AVBufferRef**)(src + desc->ref_offsets[i]); + copy_buf = (AVBufferRef**)(copy + desc->ref_offsets[i]); + + if (!*src_buf) + continue; + + *copy_buf = av_buffer_ref(*src_buf); + if (!*copy_buf) + goto fail; + + err = av_buffer_make_writable(copy_buf); + if (err < 0) { + av_buffer_unref(copy_buf); + goto fail; + } + } + + *clone_ref = av_buffer_create(copy, desc->content_size, + desc->content_free ? desc->content_free : + cbs_default_free_unit_content, + (void*)desc, 0); + if (!*clone_ref) + goto fail; + + return 0; + +fail: + for (--i; i >= 0; i--) + av_buffer_unref((AVBufferRef**)(copy + desc->ref_offsets[i])); + av_freep(©); + *clone_ref = NULL; + return AVERROR(ENOMEM); +} + +int ff_cbs_make_unit_writable(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit) +{ + const CodedBitstreamUnitTypeDescriptor *desc; + AVBufferRef *ref; + int err; + + if (av_buffer_is_writable(unit->content_ref)) + return 0; + + desc = cbs_find_unit_type_desc(ctx, unit); + if (!desc) + return AVERROR(ENOSYS); + + switch (desc->content_type) { + case CBS_CONTENT_TYPE_POD: + return av_buffer_make_writable(&unit->content_ref); + + case CBS_CONTENT_TYPE_INTERNAL_REFS: + err = cbs_clone_unit_content(&ref, unit, desc); + break; + + case CBS_CONTENT_TYPE_COMPLEX: + if (!desc->content_clone) + return AVERROR_PATCHWELCOME; + err = desc->content_clone(&ref, unit); + break; + + default: + av_assert0(0 && "Invalid content type."); + } + if (err < 0) + return err; + + av_buffer_unref(&unit->content_ref); + unit->content_ref = ref; + unit->content = ref->data; + return 0; +} diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h index 1079f625bf..7e8f63139d 100644 --- a/libavcodec/cbs.h +++ b/libavcodec/cbs.h @@ -371,4 +371,17 @@ int ff_cbs_delete_unit(CodedBitstreamContext *ctx, int position); +/** + * Make the content of a unit writable so that internal fields can be + * modified. + * + * If there are no other references to the content of the unit, does + * nothing and returned success. Otherwise, it does a full clone of the + * content (including any internal buffers) to make a new copy, and + * replaces the existing references inside the unit with that. + */ +int ff_cbs_make_unit_writable(CodedBitstreamContext *ctx, + CodedBitstreamUnit *unit); + + #endif /* AVCODEC_CBS_H */ diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h index aefe1a81e7..c7cf7f2192 100644 --- a/libavcodec/cbs_internal.h +++ b/libavcodec/cbs_internal.h @@ -50,6 +50,7 @@ typedef struct CodedBitstreamUnitTypeDescriptor { size_t ref_offsets[CBS_MAX_REF_OFFSETS]; void (*content_free)(void *opaque, uint8_t *data); + int (*content_clone)(AVBufferRef **ref, CodedBitstreamUnit *unit); } CodedBitstreamUnitTypeDescriptor; typedef struct CodedBitstreamType {