From patchwork Mon Nov 5 15:25:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Thompson X-Patchwork-Id: 10938 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 1057244C9F7 for ; Mon, 5 Nov 2018 17:25:34 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 828A668A8F2; Mon, 5 Nov 2018 17:25:05 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f65.google.com (mail-wm1-f65.google.com [209.85.128.65]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 1D50E68A613 for ; Mon, 5 Nov 2018 17:24:59 +0200 (EET) Received: by mail-wm1-f65.google.com with SMTP id 124-v6so3855574wmw.0 for ; Mon, 05 Nov 2018 07:25:33 -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=6O6uIiHo3+irPyiGPBZkJcz0R1tbVmsxw7KNNAyM5r0=; b=CzzPO9Ia8E4Ihx29rNLpxHdRmv10QZFbomFlBYB3nIDd1+ZrDTRnLLRvAXDS3MLODj tv0WLkkQy5jhZX2NcDNP2+pbFyhanj2sN86jpDTMlZhfvoerOlKGgmvrzpcjr7RyFlU4 +rvUAyzSehc8Z9/5IL92pb3/RU+eAHxgSakVu6JdoDLk6bwU8ncc0ut6dLmH8ZgqBFDt CfqYmGbmQf9xvVuXV8Sliujpz8qidzzL1TFzsdSjatOcbaz+Z1Mi9Ozutcfjwp2mm/Mm caLBcMOTIgxvJvZNQEMl35mncRvqj9fY4QtUnPcqV2RFgwsr8g1wysUyI1Jj8BA7yOYi nGZA== 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=6O6uIiHo3+irPyiGPBZkJcz0R1tbVmsxw7KNNAyM5r0=; b=jRvKpnGPBU5oj7V66gZiuITufw7TLdjPqTB8VJnV7m3CkmaV3wPrK3fOODPTK4dg7X 9GGPs/KTJlhJ4eFj4UhefDv9XLucDUC+oIPKdb3vQUbivALN7TQYJeuOlKB2qr0sfBbt nw3he1njFlujWlntTQD821AlaQ3jZZxbhH/sbTtD+v7zKG0rs7CqJevvtVhjKDi+vPfw hlN5olg5DYEd7rJ8cVeyBNbK8o6+k8c6KRNDq/VpCDFi+Yk0IVS17STOoUl4874E021F u7Ym/bE5RfDuGIkQ1Nu6fPtAyC+yuohVubjwj+LhiAHdOtsUXGM0zI+28GeyT5dIKE/+ WJ+g== X-Gm-Message-State: AGRZ1gKpO1MnVl0AyEl8toNEtguldpXTsVzmDToQeFbxSFru7k/RmS0k qHwH0TDFnnJYMpxaDlFazOPem/NxuN0= X-Google-Smtp-Source: AJdET5cNkNZDphXwbmLrHHiwOnGMDIFv6lMr7w4BTA+w/+ZLyqEZM/uhHFFCMFOqaiIYDwZUzuTq5w== X-Received: by 2002:a1c:48c2:: with SMTP id v185-v6mr6760485wma.1.1541431532201; Mon, 05 Nov 2018 07:25:32 -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 g1-v6sm2470782wmg.2.2018.11.05.07.25.31 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 05 Nov 2018 07:25:31 -0800 (PST) From: Mark Thompson To: ffmpeg-devel@ffmpeg.org Date: Mon, 5 Nov 2018 15:25:26 +0000 Message-Id: <20181105152526.16457-2-sw@jkqxz.net> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181105152526.16457-1-sw@jkqxz.net> References: <20181105152526.16457-1-sw@jkqxz.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2 2/2] cbs_av1: Support redundant frame headers 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" --- On 05/11/18 00:55, James Almer wrote: > On 11/4/2018 9:10 PM, Mark Thompson wrote: >> ... >> + xf(1, frame_header_copy[k], b, b, b, 1, k); > > This is making a lot of noise in the trace output for no real gain, > since it prints every single bit as its own line. Can you silence it? I think it's sensible to keep some trace output here to reflect what's actually happening, so I've made it go by bytes rather than bits to be less spammy. >> + priv->frame_header_size = fh_bits; >> + priv->frame_header = >> + av_mallocz(fh_bytes + AV_INPUT_BUFFER_PADDING_SIZE); >> + if (!priv->frame_header) >> + return AVERROR(ENOMEM); >> + memcpy(priv->frame_header, fh_start, fh_bytes); > > No way to use AVBufferRef for this? Refcounting added only for reading. It's a bit nasty because it passes the bufferref down into the template code which shouldn't really have it, but I don't see any better way to make that work. >> ... Also fixed the memory leak. Thanks, - Mark libavcodec/cbs_av1.c | 16 ++++-- libavcodec/cbs_av1.h | 5 +- libavcodec/cbs_av1_syntax_template.c | 82 +++++++++++++++++++++++++--- 3 files changed, 91 insertions(+), 12 deletions(-) diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c index 1c49d90f51..ff32a6fca5 100644 --- a/libavcodec/cbs_av1.c +++ b/libavcodec/cbs_av1.c @@ -996,7 +996,10 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx, case AV1_OBU_REDUNDANT_FRAME_HEADER: { err = cbs_av1_read_frame_header_obu(ctx, &gbc, - &obu->obu.frame_header); + &obu->obu.frame_header, + obu->header.obu_type == + AV1_OBU_REDUNDANT_FRAME_HEADER, + unit->data_ref); if (err < 0) return err; } @@ -1016,7 +1019,8 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx, break; case AV1_OBU_FRAME: { - err = cbs_av1_read_frame_obu(ctx, &gbc, &obu->obu.frame); + err = cbs_av1_read_frame_obu(ctx, &gbc, &obu->obu.frame, + unit->data_ref); if (err < 0) return err; @@ -1124,7 +1128,10 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx, case AV1_OBU_REDUNDANT_FRAME_HEADER: { err = cbs_av1_write_frame_header_obu(ctx, pbc, - &obu->obu.frame_header); + &obu->obu.frame_header, + obu->header.obu_type == + AV1_OBU_REDUNDANT_FRAME_HEADER, + NULL); if (err < 0) return err; } @@ -1141,7 +1148,7 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx, break; case AV1_OBU_FRAME: { - err = cbs_av1_write_frame_obu(ctx, pbc, &obu->obu.frame); + err = cbs_av1_write_frame_obu(ctx, pbc, &obu->obu.frame, NULL); if (err < 0) return err; @@ -1302,6 +1309,7 @@ static void cbs_av1_close(CodedBitstreamContext *ctx) CodedBitstreamAV1Context *priv = ctx->priv_data; av_buffer_unref(&priv->sequence_header_ref); + av_buffer_unref(&priv->frame_header_ref); av_freep(&priv->write_buffer); } diff --git a/libavcodec/cbs_av1.h b/libavcodec/cbs_av1.h index 614a0bf108..f662265f75 100644 --- a/libavcodec/cbs_av1.h +++ b/libavcodec/cbs_av1.h @@ -399,7 +399,10 @@ typedef struct CodedBitstreamAV1Context { AV1RawSequenceHeader *sequence_header; AVBufferRef *sequence_header_ref; - int seen_frame_header; + int seen_frame_header; + AVBufferRef *frame_header_ref; + uint8_t *frame_header; + size_t frame_header_size; int temporal_id; int spatial_id; diff --git a/libavcodec/cbs_av1_syntax_template.c b/libavcodec/cbs_av1_syntax_template.c index e146bbf8bb..0da79b615d 100644 --- a/libavcodec/cbs_av1_syntax_template.c +++ b/libavcodec/cbs_av1_syntax_template.c @@ -1463,24 +1463,90 @@ static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext *rw, } static int FUNC(frame_header_obu)(CodedBitstreamContext *ctx, RWContext *rw, - AV1RawFrameHeader *current) + AV1RawFrameHeader *current, int redundant, + AVBufferRef *rw_buffer_ref) { CodedBitstreamAV1Context *priv = ctx->priv_data; - int err; - - HEADER("Frame Header"); + int start_pos, fh_bits, fh_bytes, err; + uint8_t *fh_start; if (priv->seen_frame_header) { - // Nothing to do. + if (!redundant) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid repeated " + "frame header OBU.\n"); + return AVERROR_INVALIDDATA; + } else { + GetBitContext fh; + size_t i, b; + uint32_t val; + + HEADER("Redundant Frame Header"); + + av_assert0(priv->frame_header_ref && priv->frame_header); + + init_get_bits(&fh, priv->frame_header, + priv->frame_header_size); + for (i = 0; i < priv->frame_header_size; i += 8) { + b = FFMIN(priv->frame_header_size - i, 8); + val = get_bits(&fh, b); + xf(b, frame_header_copy[i], + val, val, val, 1, i / 8); + } + } } else { + if (redundant) + HEADER("Redundant Frame Header (used as Frame Header)"); + else + HEADER("Frame Header"); + priv->seen_frame_header = 1; +#ifdef READ + start_pos = get_bits_count(rw); +#else + start_pos = put_bits_count(rw); +#endif + CHECK(FUNC(uncompressed_header)(ctx, rw, current)); if (current->show_existing_frame) { priv->seen_frame_header = 0; } else { priv->seen_frame_header = 1; + + av_buffer_unref(&priv->frame_header_ref); + +#ifdef READ + fh_bits = get_bits_count(rw) - start_pos; + fh_start = (uint8_t*)rw->buffer + start_pos / 8; +#else + // Need to flush the bitwriter so that we can copy its output, + // but use a copy so we don't affect the caller's structure. + { + PutBitContext tmp = *rw; + flush_put_bits(&tmp); + } + + fh_bits = put_bits_count(rw) - start_pos; + fh_start = rw->buf + start_pos / 8; +#endif + fh_bytes = (fh_bits + 7) / 8; + + priv->frame_header_size = fh_bits; + + if (rw_buffer_ref) { + priv->frame_header_ref = av_buffer_ref(rw_buffer_ref); + if (!priv->frame_header_ref) + return AVERROR(ENOMEM); + priv->frame_header = fh_start; + } else { + priv->frame_header_ref = + av_buffer_alloc(fh_bytes + AV_INPUT_BUFFER_PADDING_SIZE); + if (!priv->frame_header_ref) + return AVERROR(ENOMEM); + priv->frame_header = priv->frame_header_ref->data; + memcpy(priv->frame_header, fh_start, fh_bytes); + } } } @@ -1524,11 +1590,13 @@ static int FUNC(tile_group_obu)(CodedBitstreamContext *ctx, RWContext *rw, } static int FUNC(frame_obu)(CodedBitstreamContext *ctx, RWContext *rw, - AV1RawFrame *current) + AV1RawFrame *current, + AVBufferRef *rw_buffer_ref) { int err; - CHECK(FUNC(frame_header_obu)(ctx, rw, ¤t->header)); + CHECK(FUNC(frame_header_obu)(ctx, rw, ¤t->header, + 0, rw_buffer_ref)); CHECK(FUNC(byte_alignment)(ctx, rw));