From patchwork Sat Jul 2 22:21:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 36602 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:8b27:b0:88:1bbf:7fd2 with SMTP id l39csp1883897pzh; Sat, 2 Jul 2022 15:23:01 -0700 (PDT) X-Google-Smtp-Source: AGRyM1u8gbhfwfDh/C/KEGkwOw4CouejgzXoC+HKs9Kn8SxBe8W5z0VCng4ZUyZiZEpALhT6D6wf X-Received: by 2002:a05:6402:298b:b0:435:20fd:d65d with SMTP id eq11-20020a056402298b00b0043520fdd65dmr28097834edb.190.1656800581447; Sat, 02 Jul 2022 15:23:01 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id l15-20020a056402254f00b004357a6c5e3bsi1321976edb.151.2022.07.02.15.23.01; Sat, 02 Jul 2022 15:23:01 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@outlook.com header.s=selector1 header.b="GWeJj5P/"; arc=fail (body hash mismatch); spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=outlook.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id CCDB168B974; Sun, 3 Jul 2022 01:22:38 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from EUR04-HE1-obe.outbound.protection.outlook.com (mail-oln040092073040.outbound.protection.outlook.com [40.92.73.40]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3B49068B969 for ; Sun, 3 Jul 2022 01:22:36 +0300 (EEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=dlBXhX9nnQf5rgqdK/Q76Rf+I36k8CN9Xq72uV11XIyrEqWVWQD6fummDA5ymgeX2wjl0XCtr8xuCf1A9yD7PVjPiPLTCsBALPrNtOqp88D9t2mxfrlbD+TlGPY8ddjatmRIxdzHYDV+62r+6BmCCGIKaTx58s3Iawc1AFuL/9urnUvo2rQLwXVy1WfYqbzyfoMEddVr5Ki6zRyP2+6F/emBZQZnvJxW4d+R+hzo3jui36KOcYrMtYbuJX4YeEj4b+NIf2ZvwBZcfVsyto0pJLIR//eNCGXn9MRgo6dkdpiaepmdUebjNTCE40fdgDWRSQ+z7PFbu2BMHPuS6EtSFQ== 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=dT+dhgoIP9aE2ZZby+4L2fcrX/GXWRryoty8iqR75lM=; b=TwE2TXNuPTMY6Q+I0QIio8NetMP641CRSumHLXw9nqh0EeNnK7Lh6buR2bzvJH5SLZWYwLwvaKGVFCDQy8YA+rPYWUyot8+taw652vrruuBPUyWWAfNoKwaUHVsmes9vXhfZUzSzHwh10xEyTa+Qi+HIAO9q/+amNDfLWvZVDyHkmTjsFNEwv7bHiSx3SZMb9JFvDAcScMZUEAgx72tVBlU/X2HiMrGq7AXmrdhEzjOiZShSSKTsohgc/UarF2aWy+MLcrCF6BUpsO/TG7eecdzhmCmQMmwsI/MnzZgT3jDg6l+GEA8A0FqDW7FaAhzW73Jnnyde4ylFx/c98n/R5Q== 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=dT+dhgoIP9aE2ZZby+4L2fcrX/GXWRryoty8iqR75lM=; b=GWeJj5P/iFnuLQ1qjgF0xMMFSCdXaGfddI/cT7aME8b+QpCcEc5wGzWUcPReHrl2qNPbz95ADK32n7VgJzqN3dn5tEt3PWJg+7D5y3kp3m/s9IJgUHKDFV0jdXAryIScSOna6yjQyPS2hDQlnSkt0ewf9Flv5DJB+ZUqzi1JKiR6kOBaV+aVXqKDXb01ayjBuNqo9JYt7dZVxN2flFT1AOxrlTKHmsiDascXrnqDQpkLVNtZzzbsDFV4imVk5kgZoEc1qARi5c844u77xIV9NORVxS3i2T9c5Uc/8LMk4q8xAgwM2p9XGCAbHSR3IytP6cFk7/N5fhWHJGH4Z/vvaw== Received: from DB6PR0101MB2214.eurprd01.prod.exchangelabs.com (2603:10a6:4:42::27) by VI1PR01MB4240.eurprd01.prod.exchangelabs.com (2603:10a6:803:6e::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5395.14; Sat, 2 Jul 2022 22:22:26 +0000 Received: from DB6PR0101MB2214.eurprd01.prod.exchangelabs.com ([fe80::60b9:9f29:40cc:f01c]) by DB6PR0101MB2214.eurprd01.prod.exchangelabs.com ([fe80::60b9:9f29:40cc:f01c%10]) with mapi id 15.20.5395.018; Sat, 2 Jul 2022 22:22:26 +0000 From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Sun, 3 Jul 2022 00:21:47 +0200 Message-ID: X-Mailer: git-send-email 2.34.1 In-Reply-To: References: X-TMN: [m+LOOrSoYi7IARNeM5yGAfrVcViFgMxt] X-ClientProxiedBy: FR3P281CA0089.DEUP281.PROD.OUTLOOK.COM (2603:10a6:d10:1f::18) To DB6PR0101MB2214.eurprd01.prod.exchangelabs.com (2603:10a6:4:42::27) X-Microsoft-Original-Message-ID: <20220702222200.169681-6-andreas.rheinhardt@outlook.com> MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: a343eb27-7959-4007-a32d-08da5c7957b0 X-MS-Exchange-SLBlob-MailProps: gjx25WM8ZNXwBRntoGkOsgo00FNZK4Ol70TRaQZQZqIQAKU7WSqhSIOIok1EW6DjCq3jSnO57o9ckjfCmvxwJIGCmMbt148GjOq5c6IceMjyzEjTE7eSBeOVhXEUm1PNZXsQ9o7397zxHb/EAxcBCyIZgLizuIOdoHzI70EPB28T0ayv/LdUESIxk+BrzX0JYGKpbd8KLZF+J+KZlrCn3j6a4vAN2LTPNB04AzXrJqb9k+v0StxJmDkBC1hosX/2xOlSdOz3oQSHlNe52u2AwaImRxuLancl3Mhbcl7AI1ugGydvXaaGGHzMZ6oLihryiqR2NQXdKMjXDcvi8BzUoRz+YprWwrIxQLkvUCK4N1LfDq5lbrTnIYLohu1fQEMYjiqswt7VqUUPasvMpbhYzVGUY08lrf3InZd/3bCA4StJMDNw0MY6VSqlFcwRhOUIeuMtmqG0mGenWxqgQOzp8Ta4iHch61RKa5UxwPiuF4+LKKYPzcZFzKDIpKO0VWiGfbE0JyXaw/oYUofODxmDUJ+qy9332YPbfbttLVTr2G2rUa/8dJKGLE8QtCjngLCXojqB1czKboufxe0Lsr4tdELJb2aMwAFoK3AC8CM65KiPK+Ijz5i8RmYYBCsM7M7XhAWqmzkAN/HRuwcQzkdrL3rj4N9uUTI/IZfXvnCr/OnV0Y/oLSMERqIaYx37X70iViE+du4oo6aiaYYTPo+jIS0iC79/j2Ln1j06AExMQFY= X-MS-TrafficTypeDiagnostic: VI1PR01MB4240:EE_ X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: DJA7HqX6cU0xDKXx6R+DDpmCl1EffPKrmDi8GjldO0B12c4jfyF0oPxuHE+PaV46UTXP8ZXrYsgGB5/9TVTg2HtIdyAsd4O4w3rA+7/XBsAYt9mw0oWCx8dMO1URF3zKJ+FM5NJd740SLgJm/TROnq05J3MbhFX3lu3WyiMmRFGWITfm7y4XKi8cz1dEMnF2X1J+DLX1K+KmXOtbkzjG6hLk+EymDKRQiSYSbUlWvjkmeUZLEYffOmYGg/p8266XQYcUbT+jWjyV6KpbRxjhkJWAz83R5MBTt4Mwx4FK8smzLVEVLebY8U1qYhjfCIC4/puknkDe7Qj4lxecj7pnSKBu+SFHV8gh8Znqs3DC+fVdmSPRzJq3NVIvdAkh914gTXWbp74hb1EohHEVTcgoKVUGfGMfYDvO6gIC6EZAbK1kd+lDMvSvKpi2A+G0d0K/coCfzDEKvpNShY82SvdLvKa/4cOz1HhG4jGw89166AMwTvHZAGEhiOrUGQsenS4xtxFvYlMsWZmE2ZzYZDIlrXwoXLZmeqaMlk/XjRO4vklsmx/HWxTBPjy1D8n4QziI9FMzjiwaDOe24Dk3eQq/4JEB5EjfiZGgNTu6Xzigrc41Kt33FsSfTz5FUrY/d6pdEyp1xIECKMVx4isDpG4w5Q== X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: 1VH1K1An26Vqo45cdLJzlOjeaV/y6cYN3sfpovQsWqaTnk5dgMaGmo6y8r+Pfr5nXJPnFECxOcUQ1N6TlDr4OzIZG9kzQ1AlFiU1pKYrIRmjOEx8fVluOCSAHwSilhy9DftIFGKlQtlG3qI/oz/CBp3+KzUAiS8TcOnHLzB4qFTmz3iBos1YLHIobFXJ2Us9gwyWekCWLb347ZXGLSIBgFSdbBiGX4znkQaVaxaHofOOCQzjMe6RVHSS6o5OnCGtlgDmlQjioyuGKCtYSGoC3SQh4297SNDMN0alqXuqYWkIY84+rDOhDrXiENdkbIMD5Vj1pf4QWUYpW4RMngqYGP5iyZkemcI8WZgzo5b4JXZMtanMDPAI3NIqp17KBStpqnr5YnW5IE3kNZuyL8WcEc7dp08wrHRi+hE2b0gItRE4icz5bF7E+0dOEJbNzU+rSSK8OE6YVrwBYajzLKBhBpg/B4eejsN9rO5HImlrSoIC9njxcpPxWWkmVuFUF8N7Dfv9MfTIsbFjS65jh6zRBkqsnF8NECXEuKPAtxB5GfvZDtSCm5zSlUlIJMUqK4l8CupYJXbn2fqckF1f6A8A2T890wW7vWud1cjjSyYfFD8fIl434hJfshKFhNHU4h/Y/7heGDT+jypGbdZpqwCqeNiLfmMX+MkAlyOcUnHkahBzGuklWB2iDuGuKWG9IYBEYiPQyxPwXaBi4KOadZK1WXas0KOE+Rdsui91lnOy4P5hiVNJNJy0bb56/A1Fe89ocOyyvNoVzH5eFioL6h+aojFiTq93+1Zpr/V37lQQ/wLnsFvrI/EKz2vQk4OW+DRyeMuqqzuoN/38mWeAuIlLMQMlNqx11mpT5dHnobXtQWc/Lne7WbhlKM4IVIUc9vvUXaCCT7cpuJ6nbThp4EQfBJSDNZOqvsvWDVJCWdFPksC64MIvPPWLOgOdg4CJEH3cOF5E4idAeTDyjEN20Lzep8x6j1XZgDLAG0W8pBot6bhjbQv3XoQreTA6SCSqqfa8yqfNLhmNSdJc8JFpDL0+aI37M9zyT9Ajj6VtKvAEvseFfmVjicVjwIY7ga5MEiFuMFKawlIlJLusHCyWZLSXQgJXs95Heci4+yI4SUM+oJaZqZBWnrnwIoRF28JmuDlwzwie7GLg0nfhn9BF0rp9IKHF0Us6WBcKe3t5hmLdu6AiGgOWulBzSZi6Ypw3np/CX8F39nb0e3Kxiu41Imjm1mDmN4y3j8aG7QNMbloAF2MQAL0NUH2tJOEh93A+aDH8xHqTGMyRSGXZW/jM6BsVOnxjN3xqV1oWislJUPPnBl0= X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: a343eb27-7959-4007-a32d-08da5c7957b0 X-MS-Exchange-CrossTenant-AuthSource: DB6PR0101MB2214.eurprd01.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 02 Jul 2022 22:22:26.1782 (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: VI1PR01MB4240 Subject: [FFmpeg-devel] [PATCH 07/20] avcodec/h2645_sei: Factor parsing common SEI messages out 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 Cc: Andreas Rheinhardt Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: zVCI5A1lrGsZ Signed-off-by: Andreas Rheinhardt --- libavcodec/Makefile | 4 +- libavcodec/h2645_sei.c | 391 +++++++++++++++++++++++++++++++++++++++ libavcodec/h2645_sei.h | 133 +++++++++++++ libavcodec/h264_parser.c | 6 +- libavcodec/h264_sei.c | 259 ++------------------------ libavcodec/h264_sei.h | 69 +------ libavcodec/h264_slice.c | 81 ++++---- libavcodec/h264dec.c | 6 +- libavcodec/hevc_sei.c | 304 ++---------------------------- libavcodec/hevc_sei.h | 54 +----- libavcodec/hevcdec.c | 109 +++++------ 11 files changed, 664 insertions(+), 752 deletions(-) create mode 100644 libavcodec/h2645_sei.c create mode 100644 libavcodec/h2645_sei.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 52ea46e645..c86184f9fd 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -100,9 +100,9 @@ OBJS-$(CONFIG_H264DSP) += h264dsp.o h264idct.o OBJS-$(CONFIG_H264PARSE) += h264_parse.o h2645_parse.o h264_ps.o OBJS-$(CONFIG_H264PRED) += h264pred.o OBJS-$(CONFIG_H264QPEL) += h264qpel.o -OBJS-$(CONFIG_H264_SEI) += h264_sei.o +OBJS-$(CONFIG_H264_SEI) += h264_sei.o h2645_sei.o OBJS-$(CONFIG_HEVCPARSE) += hevc_parse.o h2645_parse.o hevc_ps.o hevc_data.o -OBJS-$(CONFIG_HEVC_SEI) += hevc_sei.o dynamic_hdr10_plus.o dynamic_hdr_vivid.o +OBJS-$(CONFIG_HEVC_SEI) += hevc_sei.o h2645_sei.o dynamic_hdr10_plus.o dynamic_hdr_vivid.o OBJS-$(CONFIG_HPELDSP) += hpeldsp.o OBJS-$(CONFIG_HUFFMAN) += huffman.o OBJS-$(CONFIG_HUFFYUVDSP) += huffyuvdsp.o diff --git a/libavcodec/h2645_sei.c b/libavcodec/h2645_sei.c new file mode 100644 index 0000000000..5ff62bfac1 --- /dev/null +++ b/libavcodec/h2645_sei.c @@ -0,0 +1,391 @@ +/* + * Common H.264 and HEVC Supplementary Enhancement Information messages + * + * Copyright (c) 2003 Michael Niedermayer + * Copyright (C) 2012 - 2013 Guillaume Martres + * Copyright (C) 2012 - 2013 Gildas Cocherel + * Copyright (C) 2013 Vittorio Giovara + * + * 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 "config_components.h" + +#include "libavutil/display.h" +#include "libavutil/film_grain_params.h" +#include "libavutil/pixdesc.h" + +#include "atsc_a53.h" +#include "avcodec.h" +#include "dynamic_hdr10_plus.h" +#include "dynamic_hdr_vivid.h" +#include "get_bits.h" +#include "golomb.h" +#include "h2645_sei.h" + +#define IS_H264(codec_id) (CONFIG_H264_SEI && CONFIG_HEVC_SEI ? codec_id == AV_CODEC_ID_H264 : CONFIG_H264_SEI) +#define IS_HEVC(codec_id) (CONFIG_H264_SEI && CONFIG_HEVC_SEI ? codec_id == AV_CODEC_ID_HEVC : CONFIG_HEVC_SEI) + +#if CONFIG_HEVC_SEI +static int decode_registered_user_data_dynamic_hdr_plus(HEVCSEIDynamicHDRPlus *s, + GetByteContext *gb) +{ + size_t meta_size; + int err; + AVDynamicHDRPlus *metadata = av_dynamic_hdr_plus_alloc(&meta_size); + if (!metadata) + return AVERROR(ENOMEM); + + err = ff_parse_itu_t_t35_to_dynamic_hdr10_plus(metadata, gb->buffer, + bytestream2_get_bytes_left(gb)); + if (err < 0) { + av_free(metadata); + return err; + } + + av_buffer_unref(&s->info); + s->info = av_buffer_create((uint8_t *)metadata, meta_size, NULL, NULL, 0); + if (!s->info) { + av_free(metadata); + return AVERROR(ENOMEM); + } + + return 0; +} + +static int decode_registered_user_data_dynamic_hdr_vivid(HEVCSEIDynamicHDRVivid *s, + GetByteContext *gb) +{ + size_t meta_size; + int err; + AVDynamicHDRVivid *metadata = av_dynamic_hdr_vivid_alloc(&meta_size); + if (!metadata) + return AVERROR(ENOMEM); + + err = ff_parse_itu_t_t35_to_dynamic_hdr_vivid(metadata, + gb->buffer, bytestream2_get_bytes_left(gb)); + if (err < 0) { + av_free(metadata); + return err; + } + + av_buffer_unref(&s->info); + s->info = av_buffer_create((uint8_t *)metadata, meta_size, NULL, NULL, 0); + if (!s->info) { + av_free(metadata); + return AVERROR(ENOMEM); + } + + return 0; +} +#endif + +static int decode_registered_user_data_afd(H264SEIAFD *h, GetByteContext *gb) +{ + int flag; + + if (bytestream2_get_bytes_left(gb) <= 0) + return AVERROR_INVALIDDATA; + + flag = !!(bytestream2_get_byteu(gb) & 0x40); // active_format_flag + + if (flag) { + if (bytestream2_get_bytes_left(gb) <= 0) + return AVERROR_INVALIDDATA; + h->active_format_description = bytestream2_get_byteu(gb) & 0xF; + h->present = 1; + } + + return 0; +} + +static int decode_registered_user_data_closed_caption(H2645SEIA53Caption *h, + GetByteContext *gb) +{ + return ff_parse_a53_cc(&h->buf_ref, gb->buffer, + bytestream2_get_bytes_left(gb)); +} + +static int decode_registered_user_data(H2645SEI *h, GetByteContext *gb, + enum AVCodecID codec_id, void *logctx) +{ + int country_code, provider_code; + + if (bytestream2_get_bytes_left(gb) < 3) + return AVERROR_INVALIDDATA; + + country_code = bytestream2_get_byteu(gb); // itu_t_t35_country_code + if (country_code == 0xFF) { + if (bytestream2_get_bytes_left(gb) < 3) + return AVERROR_INVALIDDATA; + + bytestream2_skipu(gb, 1); // itu_t_t35_country_code_extension_byte + } + + if (country_code != 0xB5 && country_code != 0x26) { // usa_country_code and cn_country_code + av_log(logctx, AV_LOG_VERBOSE, + "Unsupported User Data Registered ITU-T T35 SEI message (country_code = %d)\n", + country_code); + return 0; + } + + /* itu_t_t35_payload_byte follows */ + provider_code = bytestream2_get_be16u(gb); + + switch (provider_code) { + case 0x31: { // atsc_provider_code + uint32_t user_identifier; + + if (bytestream2_get_bytes_left(gb) < 4) + return AVERROR_INVALIDDATA; + + user_identifier = bytestream2_get_be32u(gb); + switch (user_identifier) { + case MKBETAG('D', 'T', 'G', '1'): // afd_data + if (!IS_H264(codec_id)) + goto unsupported; + return decode_registered_user_data_afd(&h->afd, gb); + case MKBETAG('G', 'A', '9', '4'): // closed captions + return decode_registered_user_data_closed_caption(&h->a53_caption, gb); + default: + unsupported: + av_log(logctx, AV_LOG_VERBOSE, + "Unsupported User Data Registered ITU-T T35 SEI message (atsc user_identifier = 0x%04x)\n", + user_identifier); + break; + } + break; + } +#if CONFIG_HEVC_SEI + case 0x04: { // cuva_provider_code + const uint16_t cuva_provider_oriented_code = 0x0005; + uint16_t provider_oriented_code; + + if (!IS_HEVC(codec_id)) + goto unsupported_provider_code; + + if (bytestream2_get_bytes_left(gb) < 2) + return AVERROR_INVALIDDATA; + + provider_oriented_code = bytestream2_get_be16u(gb); + if (provider_oriented_code == cuva_provider_oriented_code) { + return decode_registered_user_data_dynamic_hdr_vivid(&h->dynamic_hdr_vivid, gb); + } + break; + } + case 0x3C: { // smpte_provider_code + // A/341 Amendment - 2094-40 + const uint16_t smpte2094_40_provider_oriented_code = 0x0001; + const uint8_t smpte2094_40_application_identifier = 0x04; + uint16_t provider_oriented_code; + uint8_t application_identifier; + + if (!IS_HEVC(codec_id)) + goto unsupported_provider_code; + + if (bytestream2_get_bytes_left(gb) < 3) + return AVERROR_INVALIDDATA; + + provider_oriented_code = bytestream2_get_be16u(gb); + application_identifier = bytestream2_get_byteu(gb); + if (provider_oriented_code == smpte2094_40_provider_oriented_code && + application_identifier == smpte2094_40_application_identifier) { + return decode_registered_user_data_dynamic_hdr_plus(&h->dynamic_hdr_plus, gb); + } + break; + } + unsupported_provider_code: +#endif + default: + av_log(logctx, AV_LOG_VERBOSE, + "Unsupported User Data Registered ITU-T T35 SEI message (provider_code = %d)\n", + provider_code); + break; + } + + return 0; +} + +static int decode_unregistered_user_data(H2645SEIUnregistered *h, + GetByteContext *gb, + enum AVCodecID codec_id) +{ + uint8_t *user_data; + int size = bytestream2_get_bytes_left(gb); + AVBufferRef *buf_ref, **tmp; + + if (size < 16 || size >= INT_MAX - 1) + return AVERROR_INVALIDDATA; + + tmp = av_realloc_array(h->buf_ref, h->nb_buf_ref + 1, sizeof(*h->buf_ref)); + if (!tmp) + return AVERROR(ENOMEM); + h->buf_ref = tmp; + + buf_ref = av_buffer_alloc(size + 1); + if (!buf_ref) + return AVERROR(ENOMEM); + user_data = buf_ref->data; + + bytestream2_get_bufferu(gb, user_data, size); + user_data[size] = 0; + buf_ref->size = size; + h->buf_ref[h->nb_buf_ref++] = buf_ref; + + if (IS_H264(codec_id)) { + int e, build; + e = sscanf(user_data + 16, "x264 - core %d", &build); + if (e == 1 && build > 0) + h->x264_build = build; + if (e == 1 && build == 1 && !strncmp(user_data+16, "x264 - core 0000", 16)) + h->x264_build = 67; + } + + return 0; +} + +static int decode_display_orientation(H2645SEIDisplayOrientation *h, + GetBitContext *gb) +{ + h->present = !get_bits1(gb); // display_orientation_cancel_flag + + if (h->present) { + h->hflip = get_bits1(gb); // hor_flip + h->vflip = get_bits1(gb); // ver_flip + + h->anticlockwise_rotation = get_bits(gb, 16); + // This is followed by display_orientation_repetition_period + // and display_orientation_extension_flag for H.264 + // and by display_orientation_persistence_flag for HEVC. + } + + return 0; +} + +static int decode_frame_packing_arrangement(H2645SEIFramePacking *h, + GetBitContext *gb, + enum AVCodecID codec_id) +{ + h->arrangement_id = get_ue_golomb_long(gb); + h->arrangement_cancel_flag = get_bits1(gb); + h->present = !h->arrangement_cancel_flag; + + if (h->present) { + h->arrangement_type = get_bits(gb, 7); + h->quincunx_sampling_flag = get_bits1(gb); + h->content_interpretation_type = get_bits(gb, 6); + + // spatial_flipping_flag, frame0_flipped_flag, field_views_flag + skip_bits(gb, 3); + h->current_frame_is_frame0_flag = get_bits1(gb); + // frame0_self_contained_flag, frame1_self_contained_flag + skip_bits(gb, 2); + + if (!h->quincunx_sampling_flag && h->arrangement_type != 5) + skip_bits(gb, 16); // frame[01]_grid_position_[xy] + skip_bits(gb, 8); // frame_packing_arrangement_reserved_byte + if (IS_H264(codec_id)) + h->arrangement_repetition_period = get_ue_golomb_long(gb); + else + skip_bits1(gb); // frame_packing_arrangement_persistence_flag + } + // H.264: frame_packing_arrangement_extension_flag, + // HEVC: upsampled_aspect_ratio_flag + skip_bits1(gb); + + return 0; +} + +static int decode_alternative_transfer(H2645SEIAlternativeTransfer *s, + GetByteContext *gb) +{ + if (bytestream2_get_bytes_left(gb) < 1) + return AVERROR_INVALIDDATA; + + s->present = 1; + s->preferred_transfer_characteristics = bytestream2_get_byteu(gb); + + return 0; +} + +static int decode_film_grain_characteristics(H2645SEIFilmGrainCharacteristics *h, + enum AVCodecID codec_id, GetBitContext *gb) +{ + h->present = !get_bits1(gb); // film_grain_characteristics_cancel_flag + + if (h->present) { + memset(h, 0, sizeof(*h)); + h->model_id = get_bits(gb, 2); + h->separate_colour_description_present_flag = get_bits1(gb); + if (h->separate_colour_description_present_flag) { + h->bit_depth_luma = get_bits(gb, 3) + 8; + h->bit_depth_chroma = get_bits(gb, 3) + 8; + h->full_range = get_bits1(gb); + h->color_primaries = get_bits(gb, 8); + h->transfer_characteristics = get_bits(gb, 8); + h->matrix_coeffs = get_bits(gb, 8); + } + h->blending_mode_id = get_bits(gb, 2); + h->log2_scale_factor = get_bits(gb, 4); + for (int c = 0; c < 3; c++) + h->comp_model_present_flag[c] = get_bits1(gb); + for (int c = 0; c < 3; c++) { + if (h->comp_model_present_flag[c]) { + h->num_intensity_intervals[c] = get_bits(gb, 8) + 1; + h->num_model_values[c] = get_bits(gb, 3) + 1; + if (h->num_model_values[c] > 6) + return AVERROR_INVALIDDATA; + for (int i = 0; i < h->num_intensity_intervals[c]; i++) { + h->intensity_interval_lower_bound[c][i] = get_bits(gb, 8); + h->intensity_interval_upper_bound[c][i] = get_bits(gb, 8); + for (int j = 0; j < h->num_model_values[c]; j++) + h->comp_model_value[c][i][j] = get_se_golomb_long(gb); + } + } + } + if (IS_HEVC(codec_id)) + h->persistence_flag = get_bits1(gb); + else + h->repetition_period = get_ue_golomb_long(gb); + + h->present = 1; + } + + return 0; +} + +int ff_h2645_sei_message_decode(H2645SEI *h, enum SEIType type, + enum AVCodecID codec_id, GetBitContext *gb, + GetByteContext *gbyte, void *logctx) +{ + switch (type) { + case SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35: + return decode_registered_user_data(h, gbyte, codec_id, logctx); + case SEI_TYPE_USER_DATA_UNREGISTERED: + return decode_unregistered_user_data(&h->unregistered, gbyte, codec_id); + case SEI_TYPE_DISPLAY_ORIENTATION: + return decode_display_orientation(&h->display_orientation, gb); + case SEI_TYPE_FILM_GRAIN_CHARACTERISTICS: + return decode_film_grain_characteristics(&h->film_grain_characteristics, codec_id, gb); + case SEI_TYPE_FRAME_PACKING_ARRANGEMENT: + return decode_frame_packing_arrangement(&h->frame_packing, gb, codec_id); + case SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS: + return decode_alternative_transfer(&h->alternative_transfer, gbyte); + default: + return FF_H2645_SEI_MESSAGE_UNHANDLED; + } +} diff --git a/libavcodec/h2645_sei.h b/libavcodec/h2645_sei.h new file mode 100644 index 0000000000..4128ff7940 --- /dev/null +++ b/libavcodec/h2645_sei.h @@ -0,0 +1,133 @@ +/* + * 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_H2645_SEI_H +#define AVCODEC_H2645_SEI_H + +#include + +#include "libavutil/buffer.h" +#include "libavutil/frame.h" + +#include "avcodec.h" +#include "bytestream.h" +#include "codec_id.h" +#include "get_bits.h" +#include "sei.h" + +typedef struct H2645SEIA53Caption { + AVBufferRef *buf_ref; +} H2645SEIA53Caption; + +typedef struct H264SEIAFD { + int present; + uint8_t active_format_description; +} H264SEIAFD; + +typedef struct HEVCSEIDynamicHDRPlus { + AVBufferRef *info; +} HEVCSEIDynamicHDRPlus; + +typedef struct HEVCSEIDynamicHDRVivid { + AVBufferRef *info; +} HEVCSEIDynamicHDRVivid; + +typedef struct H2645SEIUnregistered { + AVBufferRef **buf_ref; + unsigned nb_buf_ref; + int x264_build; //< H.264 only +} H2645SEIUnregistered; + +typedef struct H2645SEIFramePacking { + int present; + int arrangement_id; + int arrangement_cancel_flag; ///< is previous arrangement canceled, -1 if never received (currently H.264 only) + int arrangement_type; + int arrangement_repetition_period; + int content_interpretation_type; + int quincunx_sampling_flag; + int current_frame_is_frame0_flag; +} H2645SEIFramePacking; + +typedef struct H2645SEIDisplayOrientation { + int present; + int anticlockwise_rotation; + int hflip, vflip; +} H2645SEIDisplayOrientation; + +typedef struct H2645SEIAlternativeTransfer { + int present; + int preferred_transfer_characteristics; +} H2645SEIAlternativeTransfer; + +typedef struct H2645SEIFilmGrainCharacteristics { + int present; + int model_id; + int separate_colour_description_present_flag; + int bit_depth_luma; + int bit_depth_chroma; + int full_range; + int color_primaries; + int transfer_characteristics; + int matrix_coeffs; + int blending_mode_id; + int log2_scale_factor; + int comp_model_present_flag[3]; + uint16_t num_intensity_intervals[3]; + uint8_t num_model_values[3]; + uint8_t intensity_interval_lower_bound[3][256]; + uint8_t intensity_interval_upper_bound[3][256]; + int16_t comp_model_value[3][256][6]; + int repetition_period; //< H.264 only + int persistence_flag; //< HEVC only +} H2645SEIFilmGrainCharacteristics; + +typedef struct H2645SEI { + H2645SEIA53Caption a53_caption; + H264SEIAFD afd; //< H.264 only + HEVCSEIDynamicHDRPlus dynamic_hdr_plus; //< HEVC only + HEVCSEIDynamicHDRVivid dynamic_hdr_vivid; //< HEVC only + H2645SEIUnregistered unregistered; + H2645SEIFramePacking frame_packing; + H2645SEIDisplayOrientation display_orientation; + H2645SEIAlternativeTransfer alternative_transfer; + H2645SEIFilmGrainCharacteristics film_grain_characteristics; +} H2645SEI; + +enum { + FF_H2645_SEI_MESSAGE_HANDLED = 0, + FF_H2645_SEI_MESSAGE_UNHANDLED, +}; + +/** + * Decode a single SEI message. + * + * This function may either use gb or gbyte to decode the SEI message. + * + * @param[in, out] gb GetBitContext that needs to be at the start + * of the payload (i.e. after the payload_size bytes); + * it needs to be initially byte-aligned + * @param[in, out] gbyte a GetByteContext for the same data as gb + * @return < 0 on error, FF_H2645_SEI_MESSAGE_HANDLED if the SEI message + * has been handled or FF_H2645_SEI_MESSAGE_UNHANDLED if not. + */ +int ff_h2645_sei_message_decode(H2645SEI *h, enum SEIType type, + enum AVCodecID codec_id, GetBitContext *gb, + GetByteContext *gbyte, void *logctx); + +#endif /* AVCODEC_H2645_SEI_H */ diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index 50810f1789..3ed23fb9ca 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -274,8 +274,8 @@ static inline int parse_nal_units(AVCodecParserContext *s, s->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN; ff_h264_sei_uninit(&p->sei); - p->sei.frame_packing.arrangement_cancel_flag = -1; - p->sei.unregistered.x264_build = -1; + p->sei.common.frame_packing.arrangement_cancel_flag = -1; + p->sei.common.unregistered.x264_build = -1; if (!buf_size) return 0; @@ -565,7 +565,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, } if (sps->timing_info_present_flag) { int64_t den = sps->time_scale; - if (p->sei.unregistered.x264_build < 44U) + if (p->sei.common.unregistered.x264_build < 44U) den *= 2; av_reduce(&avctx->framerate.den, &avctx->framerate.num, sps->num_units_in_tick * avctx->ticks_per_frame, den, 1 << 30); diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c index d62a276779..c62aef9246 100644 --- a/libavcodec/h264_sei.c +++ b/libavcodec/h264_sei.c @@ -32,7 +32,6 @@ #include "libavutil/log.h" #include "libavutil/macros.h" #include "libavutil/mem.h" -#include "atsc_a53.h" #include "bytestream.h" #include "get_bits.h" #include "golomb.h" @@ -55,16 +54,16 @@ void ff_h264_sei_uninit(H264SEIContext *h) h->picture_timing.present = 0; h->buffering_period.present = 0; - h->frame_packing.present = 0; - h->film_grain_characteristics.present = 0; - h->display_orientation.present = 0; - h->afd.present = 0; - - av_buffer_unref(&h->a53_caption.buf_ref); - for (int i = 0; i < h->unregistered.nb_buf_ref; i++) - av_buffer_unref(&h->unregistered.buf_ref[i]); - h->unregistered.nb_buf_ref = 0; - av_freep(&h->unregistered.buf_ref); + h->common.frame_packing.present = 0; + h->common.film_grain_characteristics.present = 0; + h->common.display_orientation.present = 0; + h->common.afd.present = 0; + + av_buffer_unref(&h->common.a53_caption.buf_ref); + for (int i = 0; i < h->common.unregistered.nb_buf_ref; i++) + av_buffer_unref(&h->common.unregistered.buf_ref[i]); + h->common.unregistered.nb_buf_ref = 0; + av_freep(&h->common.unregistered.buf_ref); } int ff_h264_sei_process_picture_timing(H264SEIPictureTiming *h, const SPS *sps, @@ -153,123 +152,6 @@ static int decode_picture_timing(H264SEIPictureTiming *h, GetByteContext *gb, return 0; } -static int decode_registered_user_data_afd(H264SEIAFD *h, GetByteContext *gb) -{ - int flag; - - if (bytestream2_get_bytes_left(gb) <= 0) - return AVERROR_INVALIDDATA; - - flag = !!(bytestream2_get_byteu(gb) & 0x40); // active_format_flag - - if (flag) { - if (bytestream2_get_bytes_left(gb) <= 0) - return AVERROR_INVALIDDATA; - h->active_format_description = bytestream2_get_byteu(gb) & 0xF; - h->present = 1; - } - - return 0; -} - -static int decode_registered_user_data_closed_caption(H264SEIA53Caption *h, - GetByteContext *gb) -{ - return ff_parse_a53_cc(&h->buf_ref, gb->buffer, - bytestream2_get_bytes_left(gb)); -} - -static int decode_registered_user_data(H264SEIContext *h, GetByteContext *gb, - void *logctx) -{ - int country_code, provider_code; - - if (bytestream2_get_bytes_left(gb) < 3) - return AVERROR_INVALIDDATA; - - country_code = bytestream2_get_byteu(gb); // itu_t_t35_country_code - if (country_code == 0xFF) { - if (bytestream2_get_bytes_left(gb) < 3) - return AVERROR_INVALIDDATA; - - bytestream2_skipu(gb, 1); // itu_t_t35_country_code_extension_byte - } - - if (country_code != 0xB5) { // usa_country_code - av_log(logctx, AV_LOG_VERBOSE, - "Unsupported User Data Registered ITU-T T35 SEI message (country_code = %d)\n", - country_code); - return 0; - } - - /* itu_t_t35_payload_byte follows */ - provider_code = bytestream2_get_be16u(gb); - - switch (provider_code) { - case 0x31: { // atsc_provider_code - uint32_t user_identifier; - - if (bytestream2_get_bytes_left(gb) < 4) - return AVERROR_INVALIDDATA; - - user_identifier = bytestream2_get_be32u(gb); - switch (user_identifier) { - case MKBETAG('D', 'T', 'G', '1'): // afd_data - return decode_registered_user_data_afd(&h->afd, gb); - case MKBETAG('G', 'A', '9', '4'): // closed captions - return decode_registered_user_data_closed_caption(&h->a53_caption, gb); - default: - av_log(logctx, AV_LOG_VERBOSE, - "Unsupported User Data Registered ITU-T T35 SEI message (atsc user_identifier = 0x%04x)\n", - user_identifier); - break; - } - break; - } - default: - av_log(logctx, AV_LOG_VERBOSE, - "Unsupported User Data Registered ITU-T T35 SEI message (provider_code = %d)\n", - provider_code); - break; - } - - return 0; -} - -static int decode_unregistered_user_data(H264SEIUnregistered *h, GetByteContext *gb, - void *logctx) -{ - uint8_t *user_data; - int e, build, size = bytestream2_get_bytes_left(gb); - AVBufferRef *buf_ref, **tmp; - - if (size < 16 || size >= INT_MAX - 1) - return AVERROR_INVALIDDATA; - - tmp = av_realloc_array(h->buf_ref, h->nb_buf_ref + 1, sizeof(*h->buf_ref)); - if (!tmp) - return AVERROR(ENOMEM); - h->buf_ref = tmp; - - buf_ref = av_buffer_alloc(size + 1); - if (!buf_ref) - return AVERROR(ENOMEM); - user_data = buf_ref->data; - - bytestream2_get_bufferu(gb, user_data, size); - user_data[size] = 0; - buf_ref->size = size; - h->buf_ref[h->nb_buf_ref++] = buf_ref; - - e = sscanf(user_data + 16, "x264 - core %d", &build); - if (e == 1 && build > 0) - h->x264_build = build; - if (e == 1 && build == 1 && !strncmp(user_data+16, "x264 - core 0000", 16)) - h->x264_build = 67; - - return 0; -} - static int decode_recovery_point(H264SEIRecoveryPoint *h, GetBitContext *gb, void *logctx) { unsigned recovery_frame_cnt = get_ue_golomb_long(gb); @@ -325,51 +207,6 @@ static int decode_buffering_period(H264SEIBufferingPeriod *h, GetBitContext *gb, return 0; } -static int decode_frame_packing_arrangement(H264SEIFramePacking *h, - GetBitContext *gb) -{ - h->arrangement_id = get_ue_golomb_long(gb); - h->arrangement_cancel_flag = get_bits1(gb); - h->present = !h->arrangement_cancel_flag; - - if (h->present) { - h->arrangement_type = get_bits(gb, 7); - h->quincunx_sampling_flag = get_bits1(gb); - h->content_interpretation_type = get_bits(gb, 6); - - // spatial_flipping_flag, frame0_flipped_flag, field_views_flag - skip_bits(gb, 3); - h->current_frame_is_frame0_flag = get_bits1(gb); - // frame0_self_contained_flag, frame1_self_contained_flag - skip_bits(gb, 2); - - if (!h->quincunx_sampling_flag && h->arrangement_type != 5) - skip_bits(gb, 16); // frame[01]_grid_position_[xy] - skip_bits(gb, 8); // frame_packing_arrangement_reserved_byte - h->arrangement_repetition_period = get_ue_golomb_long(gb); - } - skip_bits1(gb); // frame_packing_arrangement_extension_flag - - return 0; -} - -static int decode_display_orientation(H264SEIDisplayOrientation *h, - GetBitContext *gb) -{ - h->present = !get_bits1(gb); - - if (h->present) { - h->hflip = get_bits1(gb); // hor_flip - h->vflip = get_bits1(gb); // ver_flip - - h->anticlockwise_rotation = get_bits(gb, 16); - get_ue_golomb_long(gb); // display_orientation_repetition_period - skip_bits1(gb); // display_orientation_extension_flag - } - - return 0; -} - static int decode_green_metadata(H264SEIGreenMetaData *h, GetByteContext *gb) { h->green_metadata_type = bytestream2_get_byte(gb); @@ -395,57 +232,6 @@ static int decode_green_metadata(H264SEIGreenMetaData *h, GetByteContext *gb) return 0; } -static int decode_alternative_transfer(H264SEIAlternativeTransfer *h, - GetByteContext *gb) -{ - h->present = 1; - h->preferred_transfer_characteristics = bytestream2_get_byte(gb); - return 0; -} - -static int decode_film_grain_characteristics(H264SEIFilmGrainCharacteristics *h, - GetBitContext *gb) -{ - h->present = !get_bits1(gb); // film_grain_characteristics_cancel_flag - - if (h->present) { - memset(h, 0, sizeof(*h)); - h->model_id = get_bits(gb, 2); - h->separate_colour_description_present_flag = get_bits1(gb); - if (h->separate_colour_description_present_flag) { - h->bit_depth_luma = get_bits(gb, 3) + 8; - h->bit_depth_chroma = get_bits(gb, 3) + 8; - h->full_range = get_bits1(gb); - h->color_primaries = get_bits(gb, 8); - h->transfer_characteristics = get_bits(gb, 8); - h->matrix_coeffs = get_bits(gb, 8); - } - h->blending_mode_id = get_bits(gb, 2); - h->log2_scale_factor = get_bits(gb, 4); - for (int c = 0; c < 3; c++) - h->comp_model_present_flag[c] = get_bits1(gb); - for (int c = 0; c < 3; c++) { - if (h->comp_model_present_flag[c]) { - h->num_intensity_intervals[c] = get_bits(gb, 8) + 1; - h->num_model_values[c] = get_bits(gb, 3) + 1; - if (h->num_model_values[c] > 6) - return AVERROR_INVALIDDATA; - for (int i = 0; i < h->num_intensity_intervals[c]; i++) { - h->intensity_interval_lower_bound[c][i] = get_bits(gb, 8); - h->intensity_interval_upper_bound[c][i] = get_bits(gb, 8); - for (int j = 0; j < h->num_model_values[c]; j++) - h->comp_model_value[c][i][j] = get_se_golomb_long(gb); - } - } - } - h->repetition_period = get_ue_golomb_long(gb); - - h->present = 1; - } - - return 0; -} - int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb, const H264ParamSets *ps, void *logctx) { @@ -490,35 +276,20 @@ int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb, case SEI_TYPE_PIC_TIMING: // Picture timing SEI ret = decode_picture_timing(&h->picture_timing, &gbyte_payload, logctx); break; - case SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35: - ret = decode_registered_user_data(h, &gbyte_payload, logctx); - break; - case SEI_TYPE_USER_DATA_UNREGISTERED: - ret = decode_unregistered_user_data(&h->unregistered, &gbyte_payload, logctx); - break; case SEI_TYPE_RECOVERY_POINT: ret = decode_recovery_point(&h->recovery_point, &gb_payload, logctx); break; case SEI_TYPE_BUFFERING_PERIOD: ret = decode_buffering_period(&h->buffering_period, &gb_payload, ps, logctx); break; - case SEI_TYPE_FRAME_PACKING_ARRANGEMENT: - ret = decode_frame_packing_arrangement(&h->frame_packing, &gb_payload); - break; - case SEI_TYPE_DISPLAY_ORIENTATION: - ret = decode_display_orientation(&h->display_orientation, &gb_payload); - break; case SEI_TYPE_GREEN_METADATA: ret = decode_green_metadata(&h->green_metadata, &gbyte_payload); break; - case SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS: - ret = decode_alternative_transfer(&h->alternative_transfer, &gbyte_payload); - break; - case SEI_TYPE_FILM_GRAIN_CHARACTERISTICS: - ret = decode_film_grain_characteristics(&h->film_grain_characteristics, &gb_payload); - break; default: - av_log(logctx, AV_LOG_DEBUG, "unknown SEI type %d\n", type); + ret = ff_h2645_sei_message_decode(&h->common, type, AV_CODEC_ID_H264, + &gb_payload, &gbyte_payload, logctx); + if (ret == FF_H2645_SEI_MESSAGE_UNHANDLED) + av_log(logctx, AV_LOG_DEBUG, "unknown SEI type %d\n", type); } if (ret < 0 && ret != AVERROR_PS_NOT_FOUND) return ret; @@ -536,7 +307,7 @@ int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb, return master_ret; } -const char *ff_h264_sei_stereo_mode(const H264SEIFramePacking *h) +const char *ff_h264_sei_stereo_mode(const H2645SEIFramePacking *h) { if (h->arrangement_cancel_flag == 0) { switch (h->arrangement_type) { diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h index d7866f42ad..7a53d01ac5 100644 --- a/libavcodec/h264_sei.h +++ b/libavcodec/h264_sei.h @@ -20,6 +20,7 @@ #define AVCODEC_H264_SEI_H #include "get_bits.h" +#include "h2645_sei.h" #include "h264_ps.h" #include "sei.h" @@ -99,21 +100,6 @@ typedef struct H264SEIPictureTiming { int timecode_cnt; } H264SEIPictureTiming; -typedef struct H264SEIAFD { - int present; - uint8_t active_format_description; -} H264SEIAFD; - -typedef struct H264SEIA53Caption { - AVBufferRef *buf_ref; -} H264SEIA53Caption; - -typedef struct H264SEIUnregistered { - int x264_build; - AVBufferRef **buf_ref; - int nb_buf_ref; -} H264SEIUnregistered; - typedef struct H264SEIRecoveryPoint { /** * recovery_frame_cnt @@ -130,23 +116,6 @@ typedef struct H264SEIBufferingPeriod { int initial_cpb_removal_delay[32]; ///< Initial timestamps for CPBs } H264SEIBufferingPeriod; -typedef struct H264SEIFramePacking { - int present; - int arrangement_id; - int arrangement_cancel_flag; ///< is previous arrangement canceled, -1 if never received - H264_SEI_FpaType arrangement_type; - int arrangement_repetition_period; - int content_interpretation_type; - int quincunx_sampling_flag; - int current_frame_is_frame0_flag; -} H264SEIFramePacking; - -typedef struct H264SEIDisplayOrientation { - int present; - int anticlockwise_rotation; - int hflip, vflip; -} H264SEIDisplayOrientation; - typedef struct H264SEIGreenMetaData { uint8_t green_metadata_type; uint8_t period_type; @@ -160,44 +129,12 @@ typedef struct H264SEIGreenMetaData { uint16_t xsd_metric_value; } H264SEIGreenMetaData; -typedef struct H264SEIAlternativeTransfer { - int present; - int preferred_transfer_characteristics; -} H264SEIAlternativeTransfer; - -typedef struct H264SEIFilmGrainCharacteristics { - int present; - int model_id; - int separate_colour_description_present_flag; - int bit_depth_luma; - int bit_depth_chroma; - int full_range; - int color_primaries; - int transfer_characteristics; - int matrix_coeffs; - int blending_mode_id; - int log2_scale_factor; - int comp_model_present_flag[3]; - uint16_t num_intensity_intervals[3]; - uint8_t num_model_values[3]; - uint8_t intensity_interval_lower_bound[3][256]; - uint8_t intensity_interval_upper_bound[3][256]; - int16_t comp_model_value[3][256][6]; - int repetition_period; -} H264SEIFilmGrainCharacteristics; - typedef struct H264SEIContext { + H2645SEI common; H264SEIPictureTiming picture_timing; - H264SEIAFD afd; - H264SEIA53Caption a53_caption; - H264SEIUnregistered unregistered; H264SEIRecoveryPoint recovery_point; H264SEIBufferingPeriod buffering_period; - H264SEIFramePacking frame_packing; - H264SEIDisplayOrientation display_orientation; H264SEIGreenMetaData green_metadata; - H264SEIAlternativeTransfer alternative_transfer; - H264SEIFilmGrainCharacteristics film_grain_characteristics; } H264SEIContext; struct H264ParamSets; @@ -213,7 +150,7 @@ void ff_h264_sei_uninit(H264SEIContext *h); /** * Get stereo_mode string from the h264 frame_packing_arrangement */ -const char *ff_h264_sei_stereo_mode(const H264SEIFramePacking *h); +const char *ff_h264_sei_stereo_mode(const H2645SEIFramePacking *h); /** * Parse the contents of a picture timing message given an active SPS. diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index d56722a5c2..a6d8d2bdac 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -433,29 +433,30 @@ int ff_h264_update_thread_context(AVCodecContext *dst, h->frame_recovered = h1->frame_recovered; - ret = av_buffer_replace(&h->sei.a53_caption.buf_ref, h1->sei.a53_caption.buf_ref); + ret = av_buffer_replace(&h->sei.common.a53_caption.buf_ref, + h1->sei.common.a53_caption.buf_ref); if (ret < 0) return ret; - for (i = 0; i < h->sei.unregistered.nb_buf_ref; i++) - av_buffer_unref(&h->sei.unregistered.buf_ref[i]); - h->sei.unregistered.nb_buf_ref = 0; + for (i = 0; i < h->sei.common.unregistered.nb_buf_ref; i++) + av_buffer_unref(&h->sei.common.unregistered.buf_ref[i]); + h->sei.common.unregistered.nb_buf_ref = 0; - if (h1->sei.unregistered.nb_buf_ref) { - ret = av_reallocp_array(&h->sei.unregistered.buf_ref, - h1->sei.unregistered.nb_buf_ref, - sizeof(*h->sei.unregistered.buf_ref)); + if (h1->sei.common.unregistered.nb_buf_ref) { + ret = av_reallocp_array(&h->sei.common.unregistered.buf_ref, + h1->sei.common.unregistered.nb_buf_ref, + sizeof(*h->sei.common.unregistered.buf_ref)); if (ret < 0) return ret; - for (i = 0; i < h1->sei.unregistered.nb_buf_ref; i++) { - h->sei.unregistered.buf_ref[i] = av_buffer_ref(h1->sei.unregistered.buf_ref[i]); - if (!h->sei.unregistered.buf_ref[i]) + for (i = 0; i < h1->sei.common.unregistered.nb_buf_ref; i++) { + h->sei.common.unregistered.buf_ref[i] = av_buffer_ref(h1->sei.common.unregistered.buf_ref[i]); + if (!h->sei.common.unregistered.buf_ref[i]) return AVERROR(ENOMEM); - h->sei.unregistered.nb_buf_ref++; + h->sei.common.unregistered.nb_buf_ref++; } } - h->sei.unregistered.x264_build = h1->sei.unregistered.x264_build; + h->sei.common.unregistered.x264_build = h1->sei.common.unregistered.x264_build; if (!h->cur_pic_ptr) return 0; @@ -528,7 +529,7 @@ static int h264_frame_start(H264Context *h) pic->f->crop_top = h->crop_top; pic->f->crop_bottom = h->crop_bottom; - pic->needs_fg = h->sei.film_grain_characteristics.present && !h->avctx->hwaccel && + pic->needs_fg = h->sei.common.film_grain_characteristics.present && !h->avctx->hwaccel && !(h->avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN); if ((ret = alloc_picture(h, pic)) < 0) @@ -579,8 +580,8 @@ static int h264_frame_start(H264Context *h) h->mb_aff_frame = h->ps.sps->mb_aff && (h->picture_structure == PICT_FRAME); - if (h->sei.unregistered.x264_build >= 0) - h->x264_build = h->sei.unregistered.x264_build; + if (h->sei.common.unregistered.x264_build >= 0) + h->x264_build = h->sei.common.unregistered.x264_build; assert(h->cur_pic_ptr->long_ref == 0); @@ -1114,10 +1115,10 @@ static int h264_init_ps(H264Context *h, const H264SliceContext *sl, int first_sl } } - if (h->sei.alternative_transfer.present && - av_color_transfer_name(h->sei.alternative_transfer.preferred_transfer_characteristics) && - h->sei.alternative_transfer.preferred_transfer_characteristics != AVCOL_TRC_UNSPECIFIED) { - h->avctx->color_trc = h->sei.alternative_transfer.preferred_transfer_characteristics; + if (h->sei.common.alternative_transfer.present && + av_color_transfer_name(h->sei.common.alternative_transfer.preferred_transfer_characteristics) && + h->sei.common.alternative_transfer.preferred_transfer_characteristics != AVCOL_TRC_UNSPECIFIED) { + h->avctx->color_trc = h->sei.common.alternative_transfer.preferred_transfer_characteristics; } } h->avctx->chroma_sample_location = sps->chroma_location; @@ -1243,11 +1244,11 @@ static int h264_export_frame_props(H264Context *h) } } - if (h->sei.frame_packing.present && - h->sei.frame_packing.arrangement_type <= 6 && - h->sei.frame_packing.content_interpretation_type > 0 && - h->sei.frame_packing.content_interpretation_type < 3) { - H264SEIFramePacking *fp = &h->sei.frame_packing; + if (h->sei.common.frame_packing.present && + h->sei.common.frame_packing.arrangement_type <= 6 && + h->sei.common.frame_packing.content_interpretation_type > 0 && + h->sei.common.frame_packing.content_interpretation_type < 3) { + H2645SEIFramePacking *fp = &h->sei.common.frame_packing; AVStereo3D *stereo = av_stereo3d_create_side_data(out); if (stereo) { switch (fp->arrangement_type) { @@ -1289,11 +1290,11 @@ static int h264_export_frame_props(H264Context *h) } } - if (h->sei.display_orientation.present && - (h->sei.display_orientation.anticlockwise_rotation || - h->sei.display_orientation.hflip || - h->sei.display_orientation.vflip)) { - H264SEIDisplayOrientation *o = &h->sei.display_orientation; + if (h->sei.common.display_orientation.present && + (h->sei.common.display_orientation.anticlockwise_rotation || + h->sei.common.display_orientation.hflip || + h->sei.common.display_orientation.vflip)) { + H2645SEIDisplayOrientation *o = &h->sei.common.display_orientation; double angle = o->anticlockwise_rotation * 360 / (double) (1 << 16); AVFrameSideData *rotation = av_frame_new_side_data(out, AV_FRAME_DATA_DISPLAYMATRIX, @@ -1314,18 +1315,18 @@ static int h264_export_frame_props(H264Context *h) } } - if (h->sei.afd.present) { + if (h->sei.common.afd.present) { AVFrameSideData *sd = av_frame_new_side_data(out, AV_FRAME_DATA_AFD, sizeof(uint8_t)); if (sd) { - *sd->data = h->sei.afd.active_format_description; - h->sei.afd.present = 0; + *sd->data = h->sei.common.afd.active_format_description; + h->sei.common.afd.present = 0; } } - if (h->sei.a53_caption.buf_ref) { - H264SEIA53Caption *a53 = &h->sei.a53_caption; + if (h->sei.common.a53_caption.buf_ref) { + H2645SEIA53Caption *a53 = &h->sei.common.a53_caption; AVFrameSideData *sd = av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_A53_CC, a53->buf_ref); if (!sd) @@ -1335,8 +1336,8 @@ static int h264_export_frame_props(H264Context *h) h->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; } - for (int i = 0; i < h->sei.unregistered.nb_buf_ref; i++) { - H264SEIUnregistered *unreg = &h->sei.unregistered; + for (int i = 0; i < h->sei.common.unregistered.nb_buf_ref; i++) { + H2645SEIUnregistered *unreg = &h->sei.common.unregistered; if (unreg->buf_ref[i]) { AVFrameSideData *sd = av_frame_new_side_data_from_buf(out, @@ -1347,10 +1348,10 @@ static int h264_export_frame_props(H264Context *h) unreg->buf_ref[i] = NULL; } } - h->sei.unregistered.nb_buf_ref = 0; + h->sei.common.unregistered.nb_buf_ref = 0; - if (h->sei.film_grain_characteristics.present) { - H264SEIFilmGrainCharacteristics *fgc = &h->sei.film_grain_characteristics; + if (h->sei.common.film_grain_characteristics.present) { + H2645SEIFilmGrainCharacteristics *fgc = &h->sei.common.film_grain_characteristics; AVFilmGrainParams *fgp = av_film_grain_params_create_side_data(out); if (!fgp) return AVERROR(ENOMEM); diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index d80bc6b17f..49f4db90e3 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -296,8 +296,8 @@ static int h264_init_context(AVCodecContext *avctx, H264Context *h) h->recovery_frame = -1; h->frame_recovered = 0; h->poc.prev_frame_num = -1; - h->sei.frame_packing.arrangement_cancel_flag = -1; - h->sei.unregistered.x264_build = -1; + h->sei.common.frame_packing.arrangement_cancel_flag = -1; + h->sei.common.unregistered.x264_build = -1; h->next_outputed_poc = INT_MIN; for (i = 0; i < FF_ARRAY_ELEMS(h->last_pocs); i++) @@ -848,7 +848,7 @@ static int output_frame(H264Context *h, AVFrame *dst, H264Picture *srcp) if (srcp->needs_fg && (ret = av_frame_copy_props(dst, srcp->f)) < 0) return ret; - av_dict_set(&dst->metadata, "stereo_mode", ff_h264_sei_stereo_mode(&h->sei.frame_packing), 0); + av_dict_set(&dst->metadata, "stereo_mode", ff_h264_sei_stereo_mode(&h->sei.common.frame_packing), 0); if (srcp->sei_recovery_frame_cnt == 0) dst->key_frame = 1; diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index 631373e06f..b0a4a8b035 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -22,10 +22,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "atsc_a53.h" #include "bytestream.h" -#include "dynamic_hdr10_plus.h" -#include "dynamic_hdr_vivid.h" #include "golomb.h" #include "hevc_ps.h" #include "hevc_sei.h" @@ -98,38 +95,6 @@ static int decode_nal_sei_content_light_info(HEVCSEIContentLight *s, return 0; } -static int decode_nal_sei_frame_packing_arrangement(HEVCSEIFramePacking *s, GetBitContext *gb) -{ - get_ue_golomb_long(gb); // frame_packing_arrangement_id - s->present = !get_bits1(gb); - - if (s->present) { - s->arrangement_type = get_bits(gb, 7); - s->quincunx_subsampling = get_bits1(gb); - s->content_interpretation_type = get_bits(gb, 6); - - // spatial_flipping_flag, frame0_flipped_flag, field_views_flag - skip_bits(gb, 3); - s->current_frame_is_frame0_flag = get_bits1(gb); - } - return 0; -} - -static int decode_nal_sei_display_orientation(HEVCSEIDisplayOrientation *s, GetBitContext *gb) -{ - s->present = !get_bits1(gb); - - if (s->present) { - s->hflip = get_bits1(gb); // hor_flip - s->vflip = get_bits1(gb); // ver_flip - - s->anticlockwise_rotation = get_bits(gb, 16); - // skip_bits1(gb); // display_orientation_persistence_flag - } - - return 0; -} - static int decode_nal_sei_pic_timing(HEVCSEI *s, GetBitContext *gb, const HEVCParamSets *ps, void *logctx) { @@ -161,182 +126,6 @@ static int decode_nal_sei_pic_timing(HEVCSEI *s, GetBitContext *gb, return 0; } -static int decode_registered_user_data_closed_caption(HEVCSEIA53Caption *s, - GetByteContext *gb) -{ - int ret; - - ret = ff_parse_a53_cc(&s->buf_ref, gb->buffer, - bytestream2_get_bytes_left(gb)); - if (ret < 0) - return ret; - - return 0; -} - -static int decode_nal_sei_user_data_unregistered(HEVCSEIUnregistered *s, - GetByteContext *gb) -{ - AVBufferRef *buf_ref, **tmp; - int size = bytestream2_get_bytes_left(gb); - - if (size < 16 || size >= INT_MAX - 1) - return AVERROR_INVALIDDATA; - - tmp = av_realloc_array(s->buf_ref, s->nb_buf_ref + 1, sizeof(*s->buf_ref)); - if (!tmp) - return AVERROR(ENOMEM); - s->buf_ref = tmp; - - buf_ref = av_buffer_alloc(size + 1); - if (!buf_ref) - return AVERROR(ENOMEM); - - bytestream2_get_bufferu(gb, buf_ref->data, size); - buf_ref->data[size] = 0; - buf_ref->size = size; - s->buf_ref[s->nb_buf_ref++] = buf_ref; - - return 0; -} - -static int decode_registered_user_data_dynamic_hdr_plus(HEVCSEIDynamicHDRPlus *s, - GetByteContext *gb) -{ - size_t meta_size; - int err; - AVDynamicHDRPlus *metadata = av_dynamic_hdr_plus_alloc(&meta_size); - if (!metadata) - return AVERROR(ENOMEM); - - err = ff_parse_itu_t_t35_to_dynamic_hdr10_plus(metadata, gb->buffer, - bytestream2_get_bytes_left(gb)); - if (err < 0) { - av_free(metadata); - return err; - } - - av_buffer_unref(&s->info); - s->info = av_buffer_create((uint8_t *)metadata, meta_size, NULL, NULL, 0); - if (!s->info) { - av_free(metadata); - return AVERROR(ENOMEM); - } - - return 0; -} - -static int decode_registered_user_data_dynamic_hdr_vivid(HEVCSEIDynamicHDRVivid *s, - GetByteContext *gb) -{ - size_t meta_size; - int err; - AVDynamicHDRVivid *metadata = av_dynamic_hdr_vivid_alloc(&meta_size); - if (!metadata) - return AVERROR(ENOMEM); - - err = ff_parse_itu_t_t35_to_dynamic_hdr_vivid(metadata, - gb->buffer, bytestream2_get_bytes_left(gb)); - if (err < 0) { - av_free(metadata); - return err; - } - - av_buffer_unref(&s->info); - s->info = av_buffer_create((uint8_t *)metadata, meta_size, NULL, NULL, 0); - if (!s->info) { - av_free(metadata); - return AVERROR(ENOMEM); - } - - return 0; -} - -static int decode_nal_sei_user_data_registered_itu_t_t35(HEVCSEI *s, GetByteContext *gb, - void *logctx) -{ - int country_code, provider_code; - - if (bytestream2_get_bytes_left(gb) < 3) - return AVERROR_INVALIDDATA; - - country_code = bytestream2_get_byteu(gb); - if (country_code == 0xFF) { - if (bytestream2_get_bytes_left(gb) < 3) - return AVERROR_INVALIDDATA; - - bytestream2_skipu(gb, 1); - } - - if (country_code != 0xB5 && country_code != 0x26) { // usa_country_code and cn_country_code - av_log(logctx, AV_LOG_VERBOSE, - "Unsupported User Data Registered ITU-T T35 SEI message (country_code = 0x%x)\n", - country_code); - return 0; - } - - provider_code = bytestream2_get_be16u(gb); - - switch (provider_code) { - case 0x04: { // cuva_provider_code - const uint16_t cuva_provider_oriented_code = 0x0005; - uint16_t provider_oriented_code; - - if (bytestream2_get_bytes_left(gb) < 2) - return AVERROR_INVALIDDATA; - - provider_oriented_code = bytestream2_get_be16u(gb); - if (provider_oriented_code == cuva_provider_oriented_code) { - return decode_registered_user_data_dynamic_hdr_vivid(&s->dynamic_hdr_vivid, gb); - } - break; - } - case 0x3C: { // smpte_provider_code - // A/341 Amendment - 2094-40 - const uint16_t smpte2094_40_provider_oriented_code = 0x0001; - const uint8_t smpte2094_40_application_identifier = 0x04; - uint16_t provider_oriented_code; - uint8_t application_identifier; - - if (bytestream2_get_bytes_left(gb) < 3) - return AVERROR_INVALIDDATA; - - provider_oriented_code = bytestream2_get_be16u(gb); - application_identifier = bytestream2_get_byteu(gb); - if (provider_oriented_code == smpte2094_40_provider_oriented_code && - application_identifier == smpte2094_40_application_identifier) { - return decode_registered_user_data_dynamic_hdr_plus(&s->dynamic_hdr_plus, gb); - } - break; - } - case 0x31: { // atsc_provider_code - uint32_t user_identifier; - - if (bytestream2_get_bytes_left(gb) < 4) - return AVERROR_INVALIDDATA; - - user_identifier = bytestream2_get_be32u(gb); - switch (user_identifier) { - case MKBETAG('G', 'A', '9', '4'): - return decode_registered_user_data_closed_caption(&s->a53_caption, gb); - default: - av_log(logctx, AV_LOG_VERBOSE, - "Unsupported User Data Registered ITU-T T35 SEI message (atsc user_identifier = 0x%04x)\n", - user_identifier); - break; - } - break; - } - default: - av_log(logctx, AV_LOG_VERBOSE, - "Unsupported User Data Registered ITU-T T35 SEI message (provider_code = %d)\n", - provider_code); - break; - } - - return 0; -} - static int decode_nal_sei_active_parameter_sets(HEVCSEI *s, GetBitContext *gb, void *logctx) { int num_sps_ids_minus1; @@ -362,18 +151,6 @@ static int decode_nal_sei_active_parameter_sets(HEVCSEI *s, GetBitContext *gb, v return 0; } -static int decode_nal_sei_alternative_transfer(HEVCSEIAlternativeTransfer *s, - GetByteContext *gb) -{ - if (bytestream2_get_bytes_left(gb) < 1) - return AVERROR_INVALIDDATA; - - s->present = 1; - s->preferred_transfer_characteristics = bytestream2_get_byteu(gb); - - return 0; -} - static int decode_nal_sei_timecode(HEVCSEITimeCode *s, GetBitContext *gb) { s->num_clock_ts = get_bits(gb, 2); @@ -420,49 +197,6 @@ static int decode_nal_sei_timecode(HEVCSEITimeCode *s, GetBitContext *gb) return 0; } -static int decode_film_grain_characteristics(HEVCSEIFilmGrainCharacteristics *h, - GetBitContext *gb) -{ - h->present = !get_bits1(gb); // film_grain_characteristics_cancel_flag - - if (h->present) { - memset(h, 0, sizeof(*h)); - h->model_id = get_bits(gb, 2); - h->separate_colour_description_present_flag = get_bits1(gb); - if (h->separate_colour_description_present_flag) { - h->bit_depth_luma = get_bits(gb, 3) + 8; - h->bit_depth_chroma = get_bits(gb, 3) + 8; - h->full_range = get_bits1(gb); - h->color_primaries = get_bits(gb, 8); - h->transfer_characteristics = get_bits(gb, 8); - h->matrix_coeffs = get_bits(gb, 8); - } - h->blending_mode_id = get_bits(gb, 2); - h->log2_scale_factor = get_bits(gb, 4); - for (int c = 0; c < 3; c++) - h->comp_model_present_flag[c] = get_bits1(gb); - for (int c = 0; c < 3; c++) { - if (h->comp_model_present_flag[c]) { - h->num_intensity_intervals[c] = get_bits(gb, 8) + 1; - h->num_model_values[c] = get_bits(gb, 3) + 1; - if (h->num_model_values[c] > 6) - return AVERROR_INVALIDDATA; - for (int i = 0; i < h->num_intensity_intervals[c]; i++) { - h->intensity_interval_lower_bound[c][i] = get_bits(gb, 8); - h->intensity_interval_upper_bound[c][i] = get_bits(gb, 8); - for (int j = 0; j < h->num_model_values[c]; j++) - h->comp_model_value[c][i][j] = get_se_golomb_long(gb); - } - } - } - h->persistence_flag = get_bits1(gb); - - h->present = 1; - } - - return 0; -} - static int decode_nal_sei_prefix(GetBitContext *gb, GetByteContext *gbyte, void *logctx, HEVCSEI *s, const HEVCParamSets *ps, int type) @@ -470,10 +204,6 @@ static int decode_nal_sei_prefix(GetBitContext *gb, GetByteContext *gbyte, switch (type) { case 256: // Mismatched value from HM 8.1 return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gbyte); - case SEI_TYPE_FRAME_PACKING_ARRANGEMENT: - return decode_nal_sei_frame_packing_arrangement(&s->frame_packing, gb); - case SEI_TYPE_DISPLAY_ORIENTATION: - return decode_nal_sei_display_orientation(&s->display_orientation, gb); case SEI_TYPE_PIC_TIMING: return decode_nal_sei_pic_timing(s, gb, ps, logctx); case SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME: @@ -482,19 +212,15 @@ static int decode_nal_sei_prefix(GetBitContext *gb, GetByteContext *gbyte, return decode_nal_sei_content_light_info(&s->content_light, gbyte); case SEI_TYPE_ACTIVE_PARAMETER_SETS: return decode_nal_sei_active_parameter_sets(s, gb, logctx); - case SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35: - return decode_nal_sei_user_data_registered_itu_t_t35(s, gbyte, logctx); - case SEI_TYPE_USER_DATA_UNREGISTERED: - return decode_nal_sei_user_data_unregistered(&s->unregistered, gbyte); - case SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS: - return decode_nal_sei_alternative_transfer(&s->alternative_transfer, gbyte); case SEI_TYPE_TIME_CODE: return decode_nal_sei_timecode(&s->timecode, gb); - case SEI_TYPE_FILM_GRAIN_CHARACTERISTICS: - return decode_film_grain_characteristics(&s->film_grain_characteristics, gb); - default: - av_log(logctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type); - return 0; + default: { + int ret = ff_h2645_sei_message_decode(&s->common, type, AV_CODEC_ID_HEVC, + gb, gbyte, logctx); + if (ret == FF_H2645_SEI_MESSAGE_UNHANDLED) + av_log(logctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type); + return ret; + } } } @@ -569,12 +295,12 @@ int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s, void ff_hevc_reset_sei(HEVCSEI *s) { - av_buffer_unref(&s->a53_caption.buf_ref); - - for (int i = 0; i < s->unregistered.nb_buf_ref; i++) - av_buffer_unref(&s->unregistered.buf_ref[i]); - s->unregistered.nb_buf_ref = 0; - av_freep(&s->unregistered.buf_ref); - av_buffer_unref(&s->dynamic_hdr_plus.info); - av_buffer_unref(&s->dynamic_hdr_vivid.info); + av_buffer_unref(&s->common.a53_caption.buf_ref); + + for (int i = 0; i < s->common.unregistered.nb_buf_ref; i++) + av_buffer_unref(&s->common.unregistered.buf_ref[i]); + s->common.unregistered.nb_buf_ref = 0; + av_freep(&s->common.unregistered.buf_ref); + av_buffer_unref(&s->common.dynamic_hdr_plus.info); + av_buffer_unref(&s->common.dynamic_hdr_vivid.info); } diff --git a/libavcodec/hevc_sei.h b/libavcodec/hevc_sei.h index ef987f6781..8ea0245802 100644 --- a/libavcodec/hevc_sei.h +++ b/libavcodec/hevc_sei.h @@ -27,6 +27,7 @@ #include "get_bits.h" #include "hevc.h" +#include "h2645_sei.h" #include "sei.h" @@ -48,25 +49,10 @@ typedef struct HEVCSEIFramePacking { int current_frame_is_frame0_flag; } HEVCSEIFramePacking; -typedef struct HEVCSEIDisplayOrientation { - int present; - int anticlockwise_rotation; - int hflip, vflip; -} HEVCSEIDisplayOrientation; - typedef struct HEVCSEIPictureTiming { int picture_struct; } HEVCSEIPictureTiming; -typedef struct HEVCSEIA53Caption { - AVBufferRef *buf_ref; -} HEVCSEIA53Caption; - -typedef struct HEVCSEIUnregistered { - AVBufferRef **buf_ref; - int nb_buf_ref; -} HEVCSEIUnregistered; - typedef struct HEVCSEIMasteringDisplay { int present; uint16_t display_primaries[3][2]; @@ -75,14 +61,6 @@ typedef struct HEVCSEIMasteringDisplay { uint32_t min_luminance; } HEVCSEIMasteringDisplay; -typedef struct HEVCSEIDynamicHDRPlus { - AVBufferRef *info; -} HEVCSEIDynamicHDRPlus; - -typedef struct HEVCSEIDynamicHDRVivid { - AVBufferRef *info; -} HEVCSEIDynamicHDRVivid; - typedef struct HEVCSEIContentLight { int present; uint16_t max_content_light_level; @@ -114,42 +92,14 @@ typedef struct HEVCSEITimeCode { int32_t time_offset_value[3]; } HEVCSEITimeCode; -typedef struct HEVCSEIFilmGrainCharacteristics { - int present; - int model_id; - int separate_colour_description_present_flag; - int bit_depth_luma; - int bit_depth_chroma; - int full_range; - int color_primaries; - int transfer_characteristics; - int matrix_coeffs; - int blending_mode_id; - int log2_scale_factor; - int comp_model_present_flag[3]; - uint16_t num_intensity_intervals[3]; - uint8_t num_model_values[3]; - uint8_t intensity_interval_lower_bound[3][256]; - uint8_t intensity_interval_upper_bound[3][256]; - int16_t comp_model_value[3][256][6]; - int persistence_flag; -} HEVCSEIFilmGrainCharacteristics; - typedef struct HEVCSEI { + H2645SEI common; HEVCSEIPictureHash picture_hash; - HEVCSEIFramePacking frame_packing; - HEVCSEIDisplayOrientation display_orientation; HEVCSEIPictureTiming picture_timing; - HEVCSEIA53Caption a53_caption; - HEVCSEIUnregistered unregistered; HEVCSEIMasteringDisplay mastering_display; - HEVCSEIDynamicHDRPlus dynamic_hdr_plus; - HEVCSEIDynamicHDRVivid dynamic_hdr_vivid; HEVCSEIContentLight content_light; int active_seq_parameter_set_id; - HEVCSEIAlternativeTransfer alternative_transfer; HEVCSEITimeCode timecode; - HEVCSEIFilmGrainCharacteristics film_grain_characteristics; } HEVCSEI; struct HEVCParamSets; diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index f222f20706..69e65482dd 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -382,16 +382,16 @@ static int export_stream_params_from_sei(HEVCContext *s) { AVCodecContext *avctx = s->avctx; - if (s->sei.a53_caption.buf_ref) + if (s->sei.common.a53_caption.buf_ref) s->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; - if (s->sei.alternative_transfer.present && - av_color_transfer_name(s->sei.alternative_transfer.preferred_transfer_characteristics) && - s->sei.alternative_transfer.preferred_transfer_characteristics != AVCOL_TRC_UNSPECIFIED) { - avctx->color_trc = s->sei.alternative_transfer.preferred_transfer_characteristics; + if (s->sei.common.alternative_transfer.present && + av_color_transfer_name(s->sei.common.alternative_transfer.preferred_transfer_characteristics) && + s->sei.common.alternative_transfer.preferred_transfer_characteristics != AVCOL_TRC_UNSPECIFIED) { + avctx->color_trc = s->sei.common.alternative_transfer.preferred_transfer_characteristics; } - if (s->sei.film_grain_characteristics.present) + if (s->sei.common.film_grain_characteristics.present) avctx->properties |= FF_CODEC_PROPERTY_FILM_GRAIN; return 0; @@ -2731,18 +2731,18 @@ static int set_side_data(HEVCContext *s) AVFrame *out = s->ref->frame; int ret; - if (s->sei.frame_packing.present && - s->sei.frame_packing.arrangement_type >= 3 && - s->sei.frame_packing.arrangement_type <= 5 && - s->sei.frame_packing.content_interpretation_type > 0 && - s->sei.frame_packing.content_interpretation_type < 3) { + if (s->sei.common.frame_packing.present && + s->sei.common.frame_packing.arrangement_type >= 3 && + s->sei.common.frame_packing.arrangement_type <= 5 && + s->sei.common.frame_packing.content_interpretation_type > 0 && + s->sei.common.frame_packing.content_interpretation_type < 3) { AVStereo3D *stereo = av_stereo3d_create_side_data(out); if (!stereo) return AVERROR(ENOMEM); - switch (s->sei.frame_packing.arrangement_type) { + switch (s->sei.common.frame_packing.arrangement_type) { case 3: - if (s->sei.frame_packing.quincunx_subsampling) + if (s->sei.common.frame_packing.quincunx_sampling_flag) stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX; else stereo->type = AV_STEREO3D_SIDEBYSIDE; @@ -2755,21 +2755,21 @@ static int set_side_data(HEVCContext *s) break; } - if (s->sei.frame_packing.content_interpretation_type == 2) + if (s->sei.common.frame_packing.content_interpretation_type == 2) stereo->flags = AV_STEREO3D_FLAG_INVERT; - if (s->sei.frame_packing.arrangement_type == 5) { - if (s->sei.frame_packing.current_frame_is_frame0_flag) + if (s->sei.common.frame_packing.arrangement_type == 5) { + if (s->sei.common.frame_packing.current_frame_is_frame0_flag) stereo->view = AV_STEREO3D_VIEW_LEFT; else stereo->view = AV_STEREO3D_VIEW_RIGHT; } } - if (s->sei.display_orientation.present && - (s->sei.display_orientation.anticlockwise_rotation || - s->sei.display_orientation.hflip || s->sei.display_orientation.vflip)) { - double angle = s->sei.display_orientation.anticlockwise_rotation * 360 / (double) (1 << 16); + if (s->sei.common.display_orientation.present && + (s->sei.common.display_orientation.anticlockwise_rotation || + s->sei.common.display_orientation.hflip || s->sei.common.display_orientation.vflip)) { + double angle = s->sei.common.display_orientation.anticlockwise_rotation * 360 / (double) (1 << 16); AVFrameSideData *rotation = av_frame_new_side_data(out, AV_FRAME_DATA_DISPLAYMATRIX, sizeof(int32_t) * 9); @@ -2784,12 +2784,12 @@ static int set_side_data(HEVCContext *s) * an arbitatry axis and O(phi) is the proper rotation by phi) * we can create display matrices as desired by negating * the degree once for every flip applied. */ - angle = -angle * (1 - 2 * !!s->sei.display_orientation.hflip) - * (1 - 2 * !!s->sei.display_orientation.vflip); + angle = -angle * (1 - 2 * !!s->sei.common.display_orientation.hflip) + * (1 - 2 * !!s->sei.common.display_orientation.vflip); av_display_rotation_set((int32_t *)rotation->data, angle); av_display_matrix_flip((int32_t *)rotation->data, - s->sei.display_orientation.hflip, - s->sei.display_orientation.vflip); + s->sei.common.display_orientation.hflip, + s->sei.common.display_orientation.vflip); } // Decrement the mastering display flag when IRAP frame has no_rasl_output_flag=1 @@ -2861,8 +2861,8 @@ static int set_side_data(HEVCContext *s) metadata->MaxCLL, metadata->MaxFALL); } - if (s->sei.a53_caption.buf_ref) { - HEVCSEIA53Caption *a53 = &s->sei.a53_caption; + if (s->sei.common.a53_caption.buf_ref) { + H2645SEIA53Caption *a53 = &s->sei.common.a53_caption; AVFrameSideData *sd = av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_A53_CC, a53->buf_ref); if (!sd) @@ -2870,8 +2870,8 @@ static int set_side_data(HEVCContext *s) a53->buf_ref = NULL; } - for (int i = 0; i < s->sei.unregistered.nb_buf_ref; i++) { - HEVCSEIUnregistered *unreg = &s->sei.unregistered; + for (int i = 0; i < s->sei.common.unregistered.nb_buf_ref; i++) { + H2645SEIUnregistered *unreg = &s->sei.common.unregistered; if (unreg->buf_ref[i]) { AVFrameSideData *sd = av_frame_new_side_data_from_buf(out, @@ -2882,7 +2882,7 @@ static int set_side_data(HEVCContext *s) unreg->buf_ref[i] = NULL; } } - s->sei.unregistered.nb_buf_ref = 0; + s->sei.common.unregistered.nb_buf_ref = 0; if (s->sei.timecode.present) { uint32_t *tc_sd; @@ -2910,8 +2910,8 @@ static int set_side_data(HEVCContext *s) s->sei.timecode.num_clock_ts = 0; } - if (s->sei.film_grain_characteristics.present) { - HEVCSEIFilmGrainCharacteristics *fgc = &s->sei.film_grain_characteristics; + if (s->sei.common.film_grain_characteristics.present) { + H2645SEIFilmGrainCharacteristics *fgc = &s->sei.common.film_grain_characteristics; AVFilmGrainParams *fgp = av_film_grain_params_create_side_data(out); if (!fgp) return AVERROR(ENOMEM); @@ -2965,8 +2965,8 @@ static int set_side_data(HEVCContext *s) fgc->present = fgc->persistence_flag; } - if (s->sei.dynamic_hdr_plus.info) { - AVBufferRef *info_ref = av_buffer_ref(s->sei.dynamic_hdr_plus.info); + if (s->sei.common.dynamic_hdr_plus.info) { + AVBufferRef *info_ref = av_buffer_ref(s->sei.common.dynamic_hdr_plus.info); if (!info_ref) return AVERROR(ENOMEM); @@ -2987,8 +2987,8 @@ static int set_side_data(HEVCContext *s) if ((ret = ff_dovi_attach_side_data(&s->dovi_ctx, out)) < 0) return ret; - if (s->sei.dynamic_hdr_vivid.info) { - AVBufferRef *info_ref = av_buffer_ref(s->sei.dynamic_hdr_vivid.info); + if (s->sei.common.dynamic_hdr_vivid.info) { + AVBufferRef *info_ref = av_buffer_ref(s->sei.common.dynamic_hdr_vivid.info); if (!info_ref) return AVERROR(ENOMEM); @@ -3034,7 +3034,7 @@ static int hevc_frame_start(HEVCContext *s) s->ref->frame->key_frame = IS_IRAP(s); - s->ref->needs_fg = s->sei.film_grain_characteristics.present && + s->ref->needs_fg = s->sei.common.film_grain_characteristics.present && !(s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) && !s->avctx->hwaccel; @@ -3745,30 +3745,32 @@ static int hevc_update_thread_context(AVCodecContext *dst, s->max_ra = INT_MAX; } - ret = av_buffer_replace(&s->sei.a53_caption.buf_ref, s0->sei.a53_caption.buf_ref); + ret = av_buffer_replace(&s->sei.common.a53_caption.buf_ref, + s0->sei.common.a53_caption.buf_ref); if (ret < 0) return ret; - for (i = 0; i < s->sei.unregistered.nb_buf_ref; i++) - av_buffer_unref(&s->sei.unregistered.buf_ref[i]); - s->sei.unregistered.nb_buf_ref = 0; + for (i = 0; i < s->sei.common.unregistered.nb_buf_ref; i++) + av_buffer_unref(&s->sei.common.unregistered.buf_ref[i]); + s->sei.common.unregistered.nb_buf_ref = 0; - if (s0->sei.unregistered.nb_buf_ref) { - ret = av_reallocp_array(&s->sei.unregistered.buf_ref, - s0->sei.unregistered.nb_buf_ref, - sizeof(*s->sei.unregistered.buf_ref)); + if (s0->sei.common.unregistered.nb_buf_ref) { + ret = av_reallocp_array(&s->sei.common.unregistered.buf_ref, + s0->sei.common.unregistered.nb_buf_ref, + sizeof(*s->sei.common.unregistered.buf_ref)); if (ret < 0) return ret; - for (i = 0; i < s0->sei.unregistered.nb_buf_ref; i++) { - s->sei.unregistered.buf_ref[i] = av_buffer_ref(s0->sei.unregistered.buf_ref[i]); - if (!s->sei.unregistered.buf_ref[i]) + for (i = 0; i < s0->sei.common.unregistered.nb_buf_ref; i++) { + s->sei.common.unregistered.buf_ref[i] = av_buffer_ref(s0->sei.common.unregistered.buf_ref[i]); + if (!s->sei.common.unregistered.buf_ref[i]) return AVERROR(ENOMEM); - s->sei.unregistered.nb_buf_ref++; + s->sei.common.unregistered.nb_buf_ref++; } } - ret = av_buffer_replace(&s->sei.dynamic_hdr_plus.info, s0->sei.dynamic_hdr_plus.info); + ret = av_buffer_replace(&s->sei.common.dynamic_hdr_plus.info, + s0->sei.common.dynamic_hdr_plus.info); if (ret < 0) return ret; @@ -3780,15 +3782,16 @@ static int hevc_update_thread_context(AVCodecContext *dst, if (ret < 0) return ret; - ret = av_buffer_replace(&s->sei.dynamic_hdr_vivid.info, s0->sei.dynamic_hdr_vivid.info); + ret = av_buffer_replace(&s->sei.common.dynamic_hdr_vivid.info, + s0->sei.common.dynamic_hdr_vivid.info); if (ret < 0) return ret; - s->sei.frame_packing = s0->sei.frame_packing; - s->sei.display_orientation = s0->sei.display_orientation; + s->sei.common.frame_packing = s0->sei.common.frame_packing; + s->sei.common.display_orientation = s0->sei.common.display_orientation; + s->sei.common.alternative_transfer = s0->sei.common.alternative_transfer; s->sei.mastering_display = s0->sei.mastering_display; s->sei.content_light = s0->sei.content_light; - s->sei.alternative_transfer = s0->sei.alternative_transfer; ret = export_stream_params_from_sei(s); if (ret < 0)