From patchwork Thu Apr 30 21:50:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 19409 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 AA6EE44B653 for ; Fri, 1 May 2020 00:52:35 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8669568C7CB; Fri, 1 May 2020 00:52:35 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qt1-f194.google.com (mail-qt1-f194.google.com [209.85.160.194]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 0302768C3FD for ; Fri, 1 May 2020 00:52:28 +0300 (EEST) Received: by mail-qt1-f194.google.com with SMTP id b1so6480208qtt.1 for ; Thu, 30 Apr 2020 14:52:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=SNvBALe8PlyKDkBGtPiHPQOOT4Q8nZ6Ut3g85HBK3YY=; b=k8oriMSMQ/fZGNhCXz6zeJ6JoRxlE3i2tpOc5lWF6JdJ+STlx/I3VLNNJiwLfider0 GDsosUnaxNaaShfWhpQ8n/WbUrtNkk3au3f6Uh1QngBU7p0it4les08Y0mPAcMYfCI1f crAzNZimk7XtrMzJmJzR7k6z6m9uRC1l5ewl73XQKMArnS1qqMTbR21NDDr0XEQ6fmDq +mYFY55RbMgAIoYQ5IxQ0N0El/T26zPZWj9SZuxca5K2GXXEriAg/LqDaL7+MWaqxfrr yJgUWvrVWyb25xrZIlSkYWVJyG/G6mvZkV4c6Gqv10N05T2A1NGOyHBHe6vwSa5cADaL 1JhA== 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=SNvBALe8PlyKDkBGtPiHPQOOT4Q8nZ6Ut3g85HBK3YY=; b=jlwR0VmPHhFBh8QBl3rP6NLJZgwweqnIfikniJ+5eRB2D52OQeA3KDkjD0ekttkgUN l3BA8ElTkJrBzYGITMQbVeAlLN+8M7dNfhxge1syk8/EJ63x33f7KF7QBsk+vflvkPBH bAANfvi2D75aoqjj4hmkQrEV7lLAPSFrgJnf3TOxobG7WD1sPx3OckveFu0E/2anlu1e DaFdomDQiHgExIddpqCKuLZZfkYiHb9qPCkC+MGDBV3XApKNTqYPp+fzEqDuJ3id3QiY hqwCg+sqEiNhqQ7T9Qqn+dTclZV2Hc/Xgr0iaB3JEx22DgO32o99ayCJJ0z0dTwuY6jg Hseg== X-Gm-Message-State: AGi0PuYc+nAInn3fROyWk7xvbSPa69TAKmoubCP9x9dGniUg2JLbaNBu F5exmDh1pXwKbmabPNFWAhgqLJ8k X-Google-Smtp-Source: APiQypK7O/2+UzBLD+oTo/EwwxoP2oD6VPMj3tgWMIWntZdn/M970qCyESwgLi+0KV+JYLgik/Brxg== X-Received: by 2002:aed:33e5:: with SMTP id v92mr607773qtd.315.1588283547084; Thu, 30 Apr 2020 14:52:27 -0700 (PDT) Received: from localhost.localdomain ([181.23.93.37]) by smtp.gmail.com with ESMTPSA id u35sm835388qtd.88.2020.04.30.14.52.25 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Apr 2020 14:52:26 -0700 (PDT) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Thu, 30 Apr 2020 18:50:54 -0300 Message-Id: <20200430215054.3703-1-jamrial@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <4c5eea99-9020-b62b-fa4b-fe818a08d8ce@gmail.com> References: <4c5eea99-9020-b62b-fa4b-fe818a08d8ce@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/3 v4] avcodec/cbs_h265: add missing support for reserved_payload_extension_data SEI bits 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" Fixes ticket #8622 Signed-off-by: James Almer --- libavcodec/cbs_h2645.c | 1 + libavcodec/cbs_h265.h | 1 + libavcodec/cbs_h265_syntax_template.c | 85 +++++++++++++++++++++------ 3 files changed, 70 insertions(+), 17 deletions(-) diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 095e449ddc..b432921ecc 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -553,6 +553,7 @@ static void cbs_h265_free_sei_payload(H265RawSEIPayload *payload) av_buffer_unref(&payload->payload.other.data_ref); break; } + av_buffer_unref(&payload->extension_data.data_ref); } static void cbs_h265_free_sei(void *opaque, uint8_t *content) diff --git a/libavcodec/cbs_h265.h b/libavcodec/cbs_h265.h index 2c1e153ad9..73897f77a4 100644 --- a/libavcodec/cbs_h265.h +++ b/libavcodec/cbs_h265.h @@ -715,6 +715,7 @@ typedef struct H265RawSEIPayload { AVBufferRef *data_ref; } other; } payload; + H265RawExtensionData extension_data; } H265RawSEIPayload; typedef struct H265RawSEI { diff --git a/libavcodec/cbs_h265_syntax_template.c b/libavcodec/cbs_h265_syntax_template.c index ed08b06e9c..d3ac618db6 100644 --- a/libavcodec/cbs_h265_syntax_template.c +++ b/libavcodec/cbs_h265_syntax_template.c @@ -1564,7 +1564,8 @@ static int FUNC(slice_segment_header)(CodedBitstreamContext *ctx, RWContext *rw, static int FUNC(sei_buffering_period)(CodedBitstreamContext *ctx, RWContext *rw, H265RawSEIBufferingPeriod *current, - uint32_t *payload_size) + uint32_t *payload_size, + int *more_data) { CodedBitstreamH265Context *h265 = ctx->priv_data; const H265RawSPS *sps; @@ -1658,8 +1659,15 @@ static int FUNC(sei_buffering_period)(CodedBitstreamContext *ctx, RWContext *rw, else infer(use_alt_cpb_params_flag, 0); #else - if (current->use_alt_cpb_params_flag) + // If unknown extension data exists, then use_alt_cpb_params_flag is + // coded in the bitstream and must be written even if it's 0. + if (current->use_alt_cpb_params_flag || *more_data) { flag(use_alt_cpb_params_flag); + // Ensure this bit is not the last in the payload by making the + // more_data_in_payload() check evaluate to true, so it may not + // be mistaken as something else by decoders. + *more_data = 1; + } #endif return 0; @@ -2057,11 +2065,48 @@ static int FUNC(sei_alpha_channel_info)(CodedBitstreamContext *ctx, return 0; } +static int FUNC(payload_extension)(CodedBitstreamContext *ctx, RWContext *rw, + H265RawExtensionData *current, uint32_t payload_size, + int cur_pos) +{ + int err; + size_t byte_length, k; + +#ifdef READ + GetBitContext tmp; + int bits_left, payload_zero_bits; + + if (!cbs_h265_payload_extension_present(rw, payload_size, cur_pos)) + return 0; + + bits_left = 8 * payload_size - cur_pos; + tmp = *rw; + if (bits_left > 8) + skip_bits_long(&tmp, bits_left - 8); + payload_zero_bits = get_bits(&tmp, FFMIN(bits_left, 8)); + if (!payload_zero_bits) + return AVERROR_INVALIDDATA; + payload_zero_bits = ff_ctz(payload_zero_bits); + current->bit_length = bits_left - payload_zero_bits - 1; + allocate(current->data, (current->bit_length + 7) / 8); +#endif + + byte_length = (current->bit_length + 7) / 8; + for (k = 0; k < byte_length; k++) { + int length = FFMIN(current->bit_length - k * 8, 8); + xu(length, reserved_payload_extension_data, current->data[k], + 0, MAX_UINT_BITS(length), 0); + } + + return 0; +} + static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw, H265RawSEIPayload *current, int prefix) { int err, i; - int start_position, end_position; + int start_position, current_position; + int more_data = !!current->extension_data.bit_length; #ifdef READ start_position = get_bits_count(rw); @@ -2093,8 +2138,15 @@ static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw, CHECK(FUNC(sei_ ## name)(ctx, rw, ¤t->payload.name, \ ¤t->payload_size)); \ break +#define SEI_TYPE_E(type, prefix_valid, suffix_valid, name) \ + case HEVC_SEI_TYPE_ ## type: \ + SEI_TYPE_CHECK_VALID(name, prefix_valid, suffix_valid); \ + CHECK(FUNC(sei_ ## name)(ctx, rw, ¤t->payload.name, \ + ¤t->payload_size, \ + &more_data)); \ + break - SEI_TYPE_S(BUFFERING_PERIOD, 1, 0, buffering_period); + SEI_TYPE_E(BUFFERING_PERIOD, 1, 0, buffering_period); SEI_TYPE_N(PICTURE_TIMING, 1, 0, pic_timing); SEI_TYPE_N(PAN_SCAN_RECT, 1, 0, pan_scan_rect); SEI_TYPE_S(USER_DATA_REGISTERED_ITU_T_T35, @@ -2125,24 +2177,23 @@ static int FUNC(sei_payload)(CodedBitstreamContext *ctx, RWContext *rw, } } - if (byte_alignment(rw)) { + // more_data_in_payload() +#ifdef READ + current_position = get_bits_count(rw) - start_position; + if (current_position < 8 * current->payload_size) { +#else + current_position = put_bits_count(rw) - start_position; + if (byte_alignment(rw) || more_data) { +#endif + CHECK(FUNC(payload_extension)(ctx, rw, ¤t->extension_data, + current->payload_size, current_position)); fixed(1, bit_equal_to_one, 1); while (byte_alignment(rw)) fixed(1, bit_equal_to_zero, 0); } -#ifdef READ - end_position = get_bits_count(rw); - if (end_position < start_position + 8 * current->payload_size) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Incorrect SEI payload length: " - "header %"PRIu32" bits, actually %d bits.\n", - 8 * current->payload_size, - end_position - start_position); - return AVERROR_INVALIDDATA; - } -#else - end_position = put_bits_count(rw); - current->payload_size = (end_position - start_position) >> 3; +#ifdef WRITE + current->payload_size = (put_bits_count(rw) - start_position) >> 3; #endif return 0;