From patchwork Fri Mar 4 11:39:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Dawid Kozinski X-Patchwork-Id: 34602 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6838:d078:0:0:0:0 with SMTP id x24csp1508393nkx; Fri, 4 Mar 2022 03:39:49 -0800 (PST) X-Google-Smtp-Source: ABdhPJxPLmHWj6bgHDKqlGcNmaQrNkI1BfK8ZE7fRH0oDIM0W3xbErMK1zAKSNQ0xg74/QCNQw7s X-Received: by 2002:a05:6402:278f:b0:410:d242:465e with SMTP id b15-20020a056402278f00b00410d242465emr39179983ede.292.1646393989389; Fri, 04 Mar 2022 03:39:49 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1646393989; cv=none; d=google.com; s=arc-20160816; b=LMFxIMyJO7/kd510w6tg83pYbk8KmrfNbGyVlNW7ICcImoBJSGv5KRn6CubOp3m7mn R9x548tZjwl0R4zeVU9yVxgcQ7a/EywTj5bGrlaFuc9SphdpzXKs1KDtG+2Ss851zIwu dLHFblpZ+Ak/0iOM/6wHYzdOyxtsN0kUg/PwFQvTiKZ46PV8qzskj2fubkH5X8rcnYpt 9KAJ7NqtTRtFByWS23GrP5voMqztabisxt51oxEU6wNWY7EV0vysvwSIKLUjBUOTbZqw E9unQPmr0/doHArr5JSs6bcK/NvCcIStKyn+gst5PnxQbQMXvto7QIyNqgC70FGuvse4 yInw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:cms-type:content-language :thread-index:mime-version:message-id:date:to:from:dkim-signature :dkim-filter:delivered-to; bh=XhW2+H2j6K1W449Ui9ESxoO5s+BpEm5dPNpQ54hS15E=; b=WWBnEcHpeyObhoyIL8saN94n94kka6ruLd9PUTypK6L7KQBgscAXoERyxP4Gblmcck Ux2oek++s7bfbbmTWchv0+Ck3RMDbj3JAe8IIy4Ecj81rT5fk0mOMECCQeMvSgDD31QX OLfAfL2d3vILkyZZXKFze2qaD6ew7n1IGW3gBqigLp2avoshA104nPgXCM7U5oZn5DN/ eFOW01MJnMn3+NWxlR8QBcAMSAiVoMwrSwneCOCTitjbBUdu4kNfGt1i4ff+IJ6svOcL BhRDHM+Tr2sT5+B0DEDTt21ZILMBNbo2wk9TbCPjLyw0q1TFNptRyYgKjC64SjI8EdnV 9CnQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@samsung.com header.s=mail20170921 header.b=b6Rp4HOY; 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=NONE dis=NONE) header.from=samsung.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id hh17-20020a170906a95100b006d6db02de7bsi2972931ejb.863.2022.03.04.03.39.48; Fri, 04 Mar 2022 03:39:49 -0800 (PST) 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=@samsung.com header.s=mail20170921 header.b=b6Rp4HOY; 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=NONE dis=NONE) header.from=samsung.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 4EF8E68B0D3; Fri, 4 Mar 2022 13:39:43 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mailout1.w1.samsung.com (mailout1.w1.samsung.com [210.118.77.11]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2EEE768AEAD for ; Fri, 4 Mar 2022 13:39:36 +0200 (EET) Received: from eucas1p1.samsung.com (unknown [182.198.249.206]) by mailout1.w1.samsung.com (KnoxPortal) with ESMTP id 20220304113933euoutp01d8e8307724cab625c8edd733a8fc2935~ZKph1yEcC3232332323euoutp01j for ; Fri, 4 Mar 2022 11:39:33 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.w1.samsung.com 20220304113933euoutp01d8e8307724cab625c8edd733a8fc2935~ZKph1yEcC3232332323euoutp01j DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1646393973; bh=ytcL16cl9It7PxBKaWEjJm0w1cb2uAjuj+jOY/1fGLo=; h=From:To:Cc:Subject:Date:References:From; b=b6Rp4HOYpMT/l8aF+FUo/cPG0BT0yOpSS7hmyXXF/5ZyYac6Xcic3U0Jfis+OSOOp dTcvpUslymnpe4IvGPMo7730Dwt5lHVfEtGby/TZIM5FuxzVH2Dw7DaSiWFQYwzuSL zagGnCe5Kq73E95NoEXeZdpPkAYmfhFv5MZ51ipQ= Received: from eusmges2new.samsung.com (unknown [203.254.199.244]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20220304113932eucas1p26f8f227c1f3612a64af5716a4f6918ce~ZKphSFveb0359603596eucas1p23; Fri, 4 Mar 2022 11:39:32 +0000 (GMT) Received: from eucas1p2.samsung.com ( [182.198.249.207]) by eusmges2new.samsung.com (EUCPMTA) with SMTP id 19.84.09887.47AF1226; Fri, 4 Mar 2022 11:39:32 +0000 (GMT) Received: from eusmtrp2.samsung.com (unknown [182.198.249.139]) by eucas1p1.samsung.com (KnoxPortal) with ESMTPA id 20220304113931eucas1p1933f1dcea20d4f5f871c438b94bcb6b8~ZKpgesB5k1438514385eucas1p1I; Fri, 4 Mar 2022 11:39:31 +0000 (GMT) Received: from eusmgms1.samsung.com (unknown [182.198.249.179]) by eusmtrp2.samsung.com (KnoxPortal) with ESMTP id 20220304113931eusmtrp25165b6ccdd7c18a1b7a4cd832a04da2e~ZKpgbreES1827418274eusmtrp2G; Fri, 4 Mar 2022 11:39:31 +0000 (GMT) X-AuditID: cbfec7f4-45bff7000000269f-d7-6221fa748022 Received: from eusmtip1.samsung.com ( [203.254.199.221]) by eusmgms1.samsung.com (EUCPMTA) with SMTP id BD.18.09522.37AF1226; Fri, 4 Mar 2022 11:39:31 +0000 (GMT) Received: from AMDN3260 (unknown [106.210.132.171]) by eusmtip1.samsung.com (KnoxPortal) with ESMTPA id 20220304113930eusmtip1cf1c0a050513d6387a70cd1d8b27bd77~ZKpfyw4ma0923609236eusmtip1X; Fri, 4 Mar 2022 11:39:30 +0000 (GMT) From: "Dawid Kozinski" To: Date: Fri, 4 Mar 2022 12:39:30 +0100 Message-ID: <034901d82fbc$8342f470$89c8dd50$@samsung.com> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 16.0 Thread-Index: AdgvnF4+biejfekiRmycjbRhbFOmBQ== Content-Language: pl X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrCIsWRmVeSWpSXmKPExsWy7djP87olvxSTDP5/EbX4cu0Ls8W3T2eY HZg8/izazOLRt2UVYwBTFJdNSmpOZllqkb5dAlfG9JtXGAsmHxGrOLH9CFsD46/1ol2MnBwS AiYSl263sXcxcnEICaxglNh0vJMRwvnCKPHk+GeozGdGiflb/zJ1MXKAtVy7rQERX84osXHP NVYI5wWjRGd3BzvIXDYBfYmZiz6xgdgiArISq/9NYQNpZgZqnr8nG8QUFgiUmHLWHaSCRUBF Ys7JRkYQm1fAUmLd0vVQtqDEyZlPWEBsZgFtiWULXzNDXK0g8fPpMlaQMSICehInrylDlIhI 3HjUAna/hMBMDonXTw6zQ9S7SDzZsJkRwhaWeHV8C1RcRuL/zvlMEA3NQN8vPs4GkZjAKDHn GweEbS3xtvE4I8T5mhLrd+lDhB0lNv58zQoJEj6JG28FIW7gk5i0bTozRJhXoqNNCMJUkejr FINolJJ4umwO8wRGpVlIfpyF5MdZSJ6ZhbB2ASPLKkbx1NLi3PTUYqO81HK94sTc4tK8dL3k /NxNjMCEcfrf8S87GJe/+qh3iJGJg/EQowQHs5IIr6WmQpIQb0piZVVqUX58UWlOavEhRmkO FiVx3uTMDYlCAumJJanZqakFqUUwWSYOTqkGpskvV+ryz33P3b2jvuJg9q6ljxOfhKfKFspy NVbNVVhe2XRve8CfW0YK+vMVKo8+uRalNTOuuy6zVTBgbu3lO4/rz3pdO3tXolDB7uy/hczp pnIK85bLM99mmHtz71zz/en3/nAcemDJlpr5L05/2c1oB7M8W9eV65fEszypmrf+0tfnD989 jnnXmbH8O1/XAT9dtzO/mkQVnvoul1+aqvj3vLelwT3dCabnthRa5FbHcqxM0j7YtrnZeaaw veoXbveuvpOvTy62OmsWwm7p1Xx6wlvGKoPO5Lb+Zobp6bacB382nb6gxZfE/qkzoUv/scvp R/qe8Q9WJhouPfePWciIUyOLf+lhh4uplnNTlViKMxINtZiLihMBZjVSaocDAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrFLMWRmVeSWpSXmKPExsVy+t/xu7rFvxSTDE7PlLH4cu0Ls8W3T2eY HZg8/izazOLRt2UVYwBTlJ5NUX5pSapCRn5xia1StKGFkZ6hpYWekYmlnqGxeayVkamSvp1N SmpOZllqkb5dgl7GqRkTWQuOnuetuP0vtIFxWRNnFyMHh4SAicS12xpdjJwcQgJLGSU27LcH sSUEpCSWLl3ECGELS/y51sXWxcgFVPOMUaLv5jwmkASbgL7EzEWf2EBsEQFZidX/prCBzGQG mjl/TzZIWFjAX6Jv41Z2EJtFQEVizslGsJm8ApYS65auh7IFJU7OfMICYjMLaEv0PmxlhLGX LXzNDHGDgsTPp8tYQcaLCOhJnLymDFEiInHjUQvjBEbBWUgmzUIyaRaSSbOQtCxgZFnFKJJa WpybnltsqFecmFtcmpeul5yfu4kRGAnbjv3cvINx3quPeocYmTgYDzFKcDArifBaaiokCfGm JFZWpRblxxeV5qQWH2I0BXptIrOUaHI+MBbzSuINzQxMDU3MLA1MLc2MlcR5PQs6EoUE0hNL UrNTUwtSi2D6mDg4pRqYNuqIPag3+mDDveyv005h60e2959aGnmF3H5+Z2n0Xv2FMUqffj/q 6izdd8doiVarbsKX52e4F2kFJ1VmsZwy27SjKcG1ZPqZlNPSOqtlQ2y7rv59d/7Kyd1fvS4u ezfh8WT3re/a/vG3LliRMvvDK6uArEMZ4mk6l5vqd65Y2n0pbM85o71B87/Hp008OO3O5ZBP RvG99dJL7FwsTj9IKluibxC5ecWmt3cmfRB+FP7SXuayuad+ZcpZrcNHV+S0e75eYTPVfJbN 9XTG8rbPv96ukGh+Z8Xcw8DhuzqPYcWuJzrWkVUld9/oxJ1bvLJ54tp3NvkNl6/kzDzCuKjk yJsw7coNNr6vTUsZvDdziSqxFGckGmoxFxUnAgAQ8qD6DQMAAA== X-CMS-MailID: 20220304113931eucas1p1933f1dcea20d4f5f871c438b94bcb6b8 X-Msg-Generator: CA X-RootMTR: 20220304113931eucas1p1933f1dcea20d4f5f871c438b94bcb6b8 X-EPHeader: CA CMS-TYPE: 201P X-CMS-RootMailID: 20220304113931eucas1p1933f1dcea20d4f5f871c438b94bcb6b8 References: Subject: [FFmpeg-devel] [PATCH] Provided support for MPEG-5 EVC (Essential Video Coding) codec 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: Dariusz Frankiewicz Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 8UOKG3VFtG6h Hi, The eXtra-fast Essential Video Decoder (XEVD) is an opensource and fast MPEG-5 EVC decoder. (https://github.com/mpeg5/xevd) eXtra-fast Essential Video Encoder (XEVE) The eXtra-fast Essential Video Encoder (XEVE) is an opensource and fast MPEG-5 EVC encoder. ####################################### 1. Genaral info ####################################### The patch provided below contains integration layer between ffmpeg framework and EVC codec implementation. In nutshell it enable using EVC codec (encoding, decoding) by the means of ffmpeg API. I'd like to emphasize one more time, that (as mentioned before) that it isn't codec implementation. The provided implementation serves as integration layer between ffmpeg framework and EVC codec. EVC codec has been published as two separate libraries. The first one called XEVE (eXtra-fast Essential Video Encoder) is an opensource MPEG-5 EVC encoder. The second one called XEVD (eXtra-fast Essential Video Decoder ) is an opensource MPEG-5 EVC decoder. For more information on both libraries please follow the links below: * https://github.com/mpeg5/xeve * https://github.com/mpeg5/xevd The patch provided below should be apply to FFmpeg 5.0 release (commit 911d7f167c30f27a042b8558dfcf012b3c20e858 release/5.0) ####################################### 2. Fate ####################################### Since we have fate tests included in the patch, fate samples are needed before running fate tests. The samples are available in https://drive.google.com/drive/folders/1YtCLlSuTAjpLziTKI_QBuQrIOm2ss9LB?usp=sharing . Both samples Test_Video_cif.mp4 and Test_Video_cif.yuv should be placed into ffmpeg/fate-suite/evc directory. If you skip this step fate tests will fail. ####################################### 3. Building ####################################### 3.1. Download, build and install dependencies Dependencies: * eXtra-fast Essential Video Encoder (XEVE) (https://github.com/mpeg5/xeve) * eXtra-fast Essential Video Decoder (XEVD) (https://github.com/mpeg5/xevd) ------------------- 3.1.1. XEVE ------------------- git clone git@github.com:mpeg5/xeve.git cd xeve ------------------- base profile ------------------- mkdir build_base cd buid_base cmake .. -DSET_PROF=BASE make make install ------------------- main profile ------------------- mkdir build_main cd buid_base cmake .. -DSET_PROF=MAIN make make install ------------------- 3.1.2. XEVD ------------------- git clone git@github.com:mpeg5/xeve.git cd xeve ------------------- base profile ------------------- mkdir build_base cd buid_base cmake .. -DSET_PROF=BASE make make install ------------------- main profile ------------------- mkdir build_main cd buid_base cmake .. -DSET_PROF=MAIN make make install --------------------------------------- 3.2. Build ffmpeg with libxeve and libxevd --------------------------------------- It is required ffmpeg to be configfured with --enable-libxeve and --enable-libxevd Please find below exaple configuration. PATH="$HOME/bin:$PATH" PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" ./configure \ --prefix="$HOME/ffmpeg_build" \ --pkg-config-flags="--static" \ --extra-cflags="-I$HOME/ffmpeg_build/include" \ --extra-ldflags="-L$HOME/ffmpeg_build/lib" \ --extra-libs="-lpthread -lm" \ --bindir="$HOME/bin" \ --enable-gpl \ --enable-gnutls \ --enable-libaom \ --enable-libass \ --enable-libfdk-aac \ --enable-libfreetype \ --enable-libmp3lame \ --enable-libopus \ --enable-libdav1d \ --enable-libvorbis \ --enable-libvpx \ --enable-libx264 \ --enable-libx265 \ --enable-libxeve \ --enable-libxevd \ --enable-nonfree && \ PATH="$HOME/bin:$PATH" make -j $(nproc) make install ####################################### 4. Examples ####################################### Please find below examples on how to use EVC coded with ffmpeg commandline tool. (All samples are available in https://drive.google.com/drive/folders/1YtCLlSuTAjpLziTKI_QBuQrIOm2ss9LB?usp=sharing ) #!/bin/bash #======================================= #(YUV420P) -> (EVC) #======================================= ffmpeg -f rawvideo -pix_fmt yuv420p -s:v 352x288 -r 30 -i Test_Video_cif.yuv -c:v libxeve -f rawvideo Test_Video_cif.yuv.evc ffplay -autoexit Test_Video_cif.yuv.evc #======================================= #(YUV420P10LE) -> (EVC) #======================================= ffmpeg -f rawvideo -pix_fmt yuv420p10le -s:v 352x288 -r 30 -i Test_Video_cif_10le.yuv -c:v libxeve -f rawvideo Test_Video_cif_10le.yuv.evc ffplay -autoexit Test_Video_cif_10le.yuv.evc #======================================= #(EVC) -> (YUV420P) #======================================= ffmpeg -i Test_Video_cif.yuv.evc -pix_fmt yuv420p Test_Video_cif.evc.yuv ffplay -autoexit -f rawvideo -pixel_format yuv420p -video_size 352x288 Test_Video_cif.evc.yuv #======================================= #(EVC) -> (YUV420Pi10LE) #======================================= ffmpeg -i Test_Video_cif_10le.yuv.evc -pix_fmt yuv420p10le Test_Video_cif_10le.evc.yuv ffplay -autoexit -f rawvideo -pixel_format yuv420p10le -video_size 352x288 Test_Video_cif_10le.evc.yuv #======================================= #(YUV420P) -> (MP4) #======================================= ffmpeg -f rawvideo -pix_fmt yuv420p -s:v 352x288 -r 30 -i Test_Video_cif.yuv -c:v libxeve -f rawvideo Test_Video_cif.yuv.mp4 ffplay -autoexit Test_Video_cif.yuv.mp4 #======================================= #(YUV420P10LE) -> (MP4) #======================================= ffmpeg -f rawvideo -pix_fmt yuv420p10le -s:v 352x288 -r 30 -i Test_Video_cif_10le.yuv -c:v libxeve -f rawvideo Test_Video_cif_10le.yuv.mp4 ffplay -autoexit Test_Video_cif_10le.yuv.mp4 #======================================= #(MP4) -> (YUV420P) #======================================= ffmpeg -i Test_Video_cif.yuv.mp4 -f rawvideo -pix_fmt yuv420p Test_Video_cif.mp4.yuv ffplay -autoexit -f rawvideo -pixel_format yuv420p -video_size 352x288 Test_Video_cif.mp4.yuv #======================================= #(MP4) -> (YUV420P10LE) #======================================= ffmpeg -i Test_Video_cif_10le.yuv.mp4 -f rawvideo -pix_fmt yuv420p10le Test_Video_cif_10le.mp4.yuv ffplay -autoexit -f rawvideo -pixel_format yuv420p10le -video_size 352x288 Test_Video_cif_10le.mp4.yuv #======================================= #(EVC) -> (MP4) #======================================= ffmpeg -i Test_Video_cif.yuv.evc -c:v copy Test_Video_cif.evc.mp4 ffplay -autoexit Test_Video_cif.evc.mp4 #======================================= #(MP4) -> (EVC) #======================================= ffmpeg -i Test_Video_cif.evc.mp4 -vcodec copy -an -f rawvideo Test_Video_cif.evc.mp4.evc ffplay -autoexit Test_Video_cif.evc.mp4.evc #======================================= #(MP4 [h264,aac]) -> (MP4 [evc,aac]) #======================================= ffmpeg -i Test_Video_cif.mp4 -c:v libxeve Test_Video_cif_evc.mp4 ffplay -autoexit Test_Video_cif_evc.mp4 Signed-off-by: Dawid Kozinski --- Changelog | 3 +- configure | 10 + libavcodec/Makefile | 4 + libavcodec/allcodecs.c | 2 + libavcodec/avcodec.h | 3 + libavcodec/codec_desc.c | 8 + libavcodec/codec_id.h | 1 + libavcodec/evc_parser.c | 347 ++++++++ libavcodec/libxevd.c | 713 +++++++++++++++ libavcodec/libxeve.c | 1213 ++++++++++++++++++++++++++ libavcodec/parsers.c | 1 + libavcodec/profiles.c | 6 + libavcodec/profiles.h | 1 + libavcodec/version.h | 2 +- libavformat/Makefile | 2 + libavformat/allformats.c | 2 + libavformat/evcdec.c | 125 +++ libavformat/isom_tags.c | 2 + libavformat/mov.c | 2 +- libavformat/movenc.c | 30 + libavformat/rawenc.c | 14 + tests/Makefile | 1 + tests/fate/evc.mak | 37 + tests/ref/fate/evc | 4 + tests/ref/fate/evc-mp4 | 1762 ++++++++++++++++++++++++++++++++++++++ 25 files changed, 4292 insertions(+), 3 deletions(-) create mode 100644 libavcodec/evc_parser.c create mode 100644 libavcodec/libxevd.c create mode 100644 libavcodec/libxeve.c create mode 100644 libavformat/evcdec.c create mode 100644 tests/fate/evc.mak create mode 100644 tests/ref/fate/evc create mode 100644 tests/ref/fate/evc-mp4 diff --git a/Changelog b/Changelog index f8fcdb244d..a8957b39c3 100644 --- a/Changelog +++ b/Changelog @@ -45,7 +45,8 @@ version 5.0: - VideoToolbox ProRes encoder - anlmf audio filter - IMF demuxer (experimental) - +- eXtra-fast Essential Video Encoder (XEVE) +- eXtra-fast Essential Video Decoder (XEVD) version 4.4: - AudioToolbox output device diff --git a/configure b/configure index 7a62f0c248..7491d3af6b 100755 --- a/configure +++ b/configure @@ -289,6 +289,8 @@ External library support: --enable-libwebp enable WebP encoding via libwebp [no] --enable-libx264 enable H.264 encoding via x264 [no] --enable-libx265 enable HEVC encoding via x265 [no] + --enable-libxeve enable XEVE encoding via xeve [no] + --enable-libxevd enable XEVD decoding via xevd [no] --enable-libxavs enable AVS encoding via xavs [no] --enable-libxavs2 enable AVS2 encoding via xavs2 [no] --enable-libxcb enable X11 grabbing using XCB [autodetect] @@ -1880,6 +1882,8 @@ EXTERNAL_LIBRARY_LIST=" openssl pocketsphinx vapoursynth + libxeve + libxevd " HWACCEL_AUTODETECT_LIBRARY_LIST=" @@ -2453,6 +2457,7 @@ CONFIG_EXTRA=" h264pred h264qpel hevcparse + evcparse hpeldsp huffman huffyuvdsp @@ -3252,6 +3257,7 @@ mpegaudio_parser_select="mpegaudioheader" mpegvideo_parser_select="mpegvideo" mpeg4video_parser_select="h263dsp mpegvideo qpeldsp" vc1_parser_select="vc1dsp" +evc_parser_select="evcparse" # bitstream_filters aac_adtstoasc_bsf_select="adts_header mpeg4audio" @@ -3377,6 +3383,8 @@ libx264_encoder_select="atsc_a53" libx264rgb_encoder_deps="libx264" libx264rgb_encoder_select="libx264_encoder" libx265_encoder_deps="libx265" +libxeve_encoder_deps="libxeve" +libxevd_decoder_deps="libxevd" libxavs_encoder_deps="libxavs" libxavs2_encoder_deps="libxavs2" libxvid_encoder_deps="libxvid" @@ -6659,6 +6667,8 @@ enabled libx264 && { check_pkg_config libx264 x264 "stdint.h x264.h" x check_cpp_condition libx262 x264.h "X264_MPEG2" enabled libx265 && require_pkg_config libx265 x265 x265.h x265_api_get && require_cpp_condition libx265 x265.h "X265_BUILD >= 70" +enabled libxeve && require_pkg_config libxeve "xeve >= 1.0.0" "xeve.h" xeve_encode +enabled libxevd && require_pkg_config libxevd "xevd >= 1.0.0" "xevd.h" xevd_decode enabled libxavs && require libxavs "stdint.h xavs.h" xavs_encoder_encode "-lxavs $pthreads_extralibs $libm_extralibs" enabled libxavs2 && require_pkg_config libxavs2 "xavs2 >= 1.3.0" "stdint.h xavs2.h" xavs2_api_get enabled libxvid && require libxvid xvid.h xvid_global -lxvidcore diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3adf1536d8..ab38b0127f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1087,6 +1087,8 @@ OBJS-$(CONFIG_LIBWEBP_ANIM_ENCODER) += libwebpenc_common.o libwebpenc_anim OBJS-$(CONFIG_LIBX262_ENCODER) += libx264.o OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o OBJS-$(CONFIG_LIBX265_ENCODER) += libx265.o +OBJS-$(CONFIG_LIBXEVE_ENCODER) += libxeve.o +OBJS-$(CONFIG_LIBXEVD_DECODER) += libxevd.o OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o OBJS-$(CONFIG_LIBXAVS2_ENCODER) += libxavs2.o OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o @@ -1152,6 +1154,8 @@ OBJS-$(CONFIG_VP9_PARSER) += vp9_parser.o OBJS-$(CONFIG_WEBP_PARSER) += webp_parser.o OBJS-$(CONFIG_XBM_PARSER) += xbm_parser.o OBJS-$(CONFIG_XMA_PARSER) += xma_parser.o +OBJS-$(CONFIG_EVC_PARSER) += evc_parser.o + # bitstream filters OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index d1e10197de..12e6c92f65 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -783,6 +783,8 @@ extern LIBX264_CONST AVCodec ff_libx264_encoder; #endif extern const AVCodec ff_libx264rgb_encoder; extern AVCodec ff_libx265_encoder; +extern const AVCodec ff_libxeve_encoder; +extern const AVCodec ff_libxevd_decoder; extern const AVCodec ff_libxavs_encoder; extern const AVCodec ff_libxavs2_encoder; extern const AVCodec ff_libxvid_encoder; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 7ee8bc2b7c..a070e0f1d7 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1643,6 +1643,9 @@ typedef struct AVCodecContext { #define FF_PROFILE_KLVA_SYNC 0 #define FF_PROFILE_KLVA_ASYNC 1 +#define FF_PROFILE_EVC_BASELINE 0 +#define FF_PROFILE_EVC_MAIN 1 + /** * level * - encoding: Set by user. diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 0974ee03de..058f28bd67 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1269,6 +1269,14 @@ static const AVCodecDescriptor codec_descriptors[] = { .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, .profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), }, + { + .id = AV_CODEC_ID_EVC, + .type = AVMEDIA_TYPE_VIDEO, + .name = "evc", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-5 EVC (Essential Video Coding)"), + .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER, + .profiles = NULL_IF_CONFIG_SMALL(ff_evc_profiles), + }, { .id = AV_CODEC_ID_FIC, .type = AVMEDIA_TYPE_VIDEO, diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index ab265ec584..597a2bc4a0 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -222,6 +222,7 @@ enum AVCodecID { AV_CODEC_ID_WEBP, AV_CODEC_ID_HNM4_VIDEO, AV_CODEC_ID_HEVC, + AV_CODEC_ID_EVC, #define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC AV_CODEC_ID_FIC, AV_CODEC_ID_ALIAS_PIX, diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c new file mode 100644 index 0000000000..78ee96f2a0 --- /dev/null +++ b/libavcodec/evc_parser.c @@ -0,0 +1,347 @@ +/* + * EVC AVC format parser + * + * Copyright (C) 2021 Dawid Kozinski + * + * 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 "libavutil/common.h" + +#include "golomb.h" +#include "parser.h" +#include + +#define EVC_NAL_HEADER_SIZE 2 /* byte */ +#define MAX_SPS_CNT 16 /* defined value in EVC standard */ + +#define EVC_NAL_UNIT_LENGTH_BYTE (4) +#define EVC_NUT_NONIDR (0) +#define EVC_NUT_IDR (1) +#define EVC_NUT_SPS (24) +#define EVC_NUT_PPS (25) +#define EVC_NUT_APS (26) +#define EVC_NUT_FD (27) +#define EVC_NUT_SEI (28) + + +#define EVC_ST_UNKNOWN (-1) +#define EVC_ST_B (0) +#define EVC_ST_P (1) +#define EVC_ST_I (2) + +typedef struct _EVCParserSPS { + int sps_id; + int profile_idc; + int level_idc; + int chroma_format_idc; + int pic_width_in_luma_samples; + int pic_height_in_luma_samples; + int bit_depth_luma; + int bit_depth_chroma; + + int picture_cropping_flag; + int picture_crop_left_offset; + int picture_crop_right_offset; + int picture_crop_top_offset; + int picture_crop_bottom_offset; +} EVCParserSPS; + +typedef struct EVCParserContext { + ParseContext pc; + EVCParserSPS sps[MAX_SPS_CNT]; + int is_avc; + int nal_length_size; + int to_read; + + int parsed_extradata; + + int poc; + int pocTid0; + + int got_sps; + int got_pps; + int got_sei; + int got_slice; +} EVCParserContext; + +static int get_nalu_type(const uint8_t *bs, int bs_size) +{ + GetBitContext gb; + int fzb, nut; + init_get_bits(&gb, bs, bs_size * 8); + fzb = get_bits1(&gb); + if(fzb != 0) { + av_log(NULL, AV_LOG_DEBUG, "forbidden_zero_bit is not clear\n"); + } + nut = get_bits(&gb, 6); /* nal_unit_type_plus1 */ + return nut - 1; +} + +static EVCParserSPS * parse_sps(const uint8_t *bs, int bs_size, EVCParserContext *ev) +{ + GetBitContext gb; + EVCParserSPS *sps; + int sps_id; + + init_get_bits(&gb, bs, bs_size*8); + + sps_id = get_ue_golomb(&gb); + if(sps_id >= MAX_SPS_CNT) goto ERR; + sps = &ev->sps[sps_id]; + sps->sps_id = sps_id; + av_log(NULL, AV_LOG_DEBUG, "[EVC Parser] sps_id=%d\n", sps->sps_id); + + sps->profile_idc = get_bits(&gb, 8); + av_log(NULL, AV_LOG_DEBUG, "[EVC Parser] profile=%d\n", sps->profile_idc); + sps->level_idc = get_bits(&gb, 8); + + skip_bits_long(&gb, 32); /* skip toolset_idc_h */ + skip_bits_long(&gb, 32); /* skip toolset_idc_l */ + + sps->chroma_format_idc = get_ue_golomb(&gb); + sps->pic_width_in_luma_samples = get_ue_golomb(&gb); + av_log(NULL, AV_LOG_DEBUG, "[EVC Parser] width=%d\n", sps->pic_width_in_luma_samples); + sps->pic_height_in_luma_samples = get_ue_golomb(&gb); + + av_log(NULL, AV_LOG_DEBUG, "[EVC Parser] height=%d\n", sps->pic_height_in_luma_samples); + sps->bit_depth_luma = get_ue_golomb(&gb); + sps->bit_depth_chroma = get_ue_golomb(&gb); + + // @todo we need to parse crop and vui information here + + return sps; + +ERR: + return NULL; +} + + +#if 0 +static void print_nalu_info(int nalu_type, int stype) { + if(nalu_type == EVC_NUT_IDR || nalu_type == EVC_NUT_NONIDR) { + av_log(NULL, AV_LOG_DEBUG, "%c-slice\n", stype == EVC_ST_I ? 'I' : stype == EVC_ST_P ? 'P' : 'B'); + } else if(nalu_type == EVC_NUT_SPS) { + av_log(NULL, AV_LOG_DEBUG, "EVC_NUT_SPS \n"); + } else if (nalu_type == EVC_NUT_PPS) { + av_log(NULL, AV_LOG_DEBUG, "EVC_NUT_PPS \n"); + } else if (nalu_type == EVC_NUT_SEI) { + av_log(NULL, AV_LOG_DEBUG, "EVC_NUT_SEI \n"); + } else { + av_log(NULL, AV_LOG_DEBUG, "Unknown bitstream !!!! \n"); + } +} +#endif + +static int read_nal_unit_size(const uint8_t *bs, int bs_size) +{ + int nal_unit_size = 0; + memcpy(&nal_unit_size, bs, EVC_NAL_UNIT_LENGTH_BYTE); + return nal_unit_size; +} + +static int parse_nal_units(AVCodecParserContext *s, const uint8_t *bs, + int bs_size, AVCodecContext *ctx) +{ + EVCParserContext *ev = s->priv_data; + int nalu_type, nalu_size; + unsigned char * bits = (unsigned char *)bs; + int bits_size = bs_size; + + ctx->codec_id = AV_CODEC_ID_EVC; + + nalu_size = read_nal_unit_size(bits, bs_size); + bits += EVC_NAL_UNIT_LENGTH_BYTE; + bits_size -= EVC_NAL_UNIT_LENGTH_BYTE; + + nalu_type = get_nalu_type(bits, bits_size); + bits += EVC_NAL_HEADER_SIZE; + bits_size -= EVC_NAL_HEADER_SIZE; + + + if (nalu_type == EVC_NUT_SPS) { + EVCParserSPS * sps; + + sps = parse_sps(bits, bits_size, ev); + + ctx->coded_width = sps->pic_width_in_luma_samples; + ctx->coded_height = sps->pic_height_in_luma_samples; + ctx->width = sps->pic_width_in_luma_samples; + ctx->height = sps->pic_height_in_luma_samples; + + if(sps->profile_idc == 0) ctx->profile = FF_PROFILE_EVC_BASELINE; + else if (sps->profile_idc == 1) ctx->profile = FF_PROFILE_EVC_MAIN; + else{ + av_log(ctx, AV_LOG_ERROR, "not supported profile (%d)\n", sps->profile_idc); + return -1; + } + + switch(sps->chroma_format_idc) + { + case 0: /* YCBCR400_10LE */ + /* @todo support this */ + ctx->pix_fmt = AV_PIX_FMT_GRAY10LE; + return -1; + break; + case 1: /* YCBCR420_10LE */ + ctx->pix_fmt = AV_PIX_FMT_YUV420P10LE; + break; + case 2: /* YCBCR422_10LE */ + /* @todo support this */ + ctx->pix_fmt = AV_PIX_FMT_YUV422P10LE; + return -1; + break; + case 3: /* YCBCR444_10LE */ + /* @todo support this */ + ctx->pix_fmt = AV_PIX_FMT_YUV444P10LE; + return -1; + break; + default: + ctx->pix_fmt = AV_PIX_FMT_NONE; + av_log(NULL, AV_LOG_ERROR, "unknown color space\n"); + return -1; + } + + //avctx->has_b_frames = 1; // @todo FIX-ME + + ev->got_sps = 1; + + } + else if (nalu_type == EVC_NUT_PPS) { + av_log(NULL, AV_LOG_DEBUG, "EVC_NUT_PPS \n"); + ev->got_pps = 1; + } + else if(nalu_type == EVC_NUT_SEI) { + av_log(NULL, AV_LOG_DEBUG, "EVC_NUT_SEI \n"); + ev->got_sei = 1; + } + else if (nalu_type == EVC_NUT_IDR || nalu_type == EVC_NUT_NONIDR) { + av_log(ctx, AV_LOG_DEBUG, "EVC_NUT_NONIDR\n"); + ev->got_slice++; + } + return 0; +} + + +/** + * Find the end of the current frame in the bitstream. + * @return the position of the first byte of the next frame, or END_NOT_FOUND + */ +static int evc_find_frame_end(AVCodecParserContext *s, const uint8_t *buf, + int buf_size) +{ + EVCParserContext *ev = s->priv_data; + + if(!ev->to_read) + { + int next = END_NOT_FOUND; + int nal_unit_size = read_nal_unit_size(buf, buf_size); + + next = nal_unit_size + EVC_NAL_UNIT_LENGTH_BYTE; + ev->to_read = next; + if(nextto_read > buf_size) { + return END_NOT_FOUND; + } else { + return ev->to_read; + } + return END_NOT_FOUND; +} + +static int evc_parser_init(AVCodecParserContext *s) { + + EVCParserContext *ev = s->priv_data; + + av_log(NULL, AV_LOG_DEBUG, "eXtra-fast Essential Video Parser\n"); + + ev->got_sps = 0; + ev->got_pps = 0; + ev->got_sei = 0; + ev->got_slice = 0; + return 0; +} + +static int evc_parse(AVCodecParserContext *s, AVCodecContext *ctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + int next; + EVCParserContext *ev = s->priv_data; + ParseContext *pc = &ev->pc; + int is_dummy_buf = !buf_size; + const uint8_t *dummy_buf = buf; + + if (ctx->extradata && !ev->parsed_extradata) { + // @todo consider handling extradata + // + // ff_evc_decode_extradata(avctx->extradata, avctx->extradata_size, &ctx->ps, &ctx->sei, + // &ctx->is_avc, &ctx->nal_length_size, avctx->err_recognition, + // 1, avctx); + ev->parsed_extradata = 1; + } + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + next = evc_find_frame_end(s, buf, buf_size); + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + ev->to_read -= buf_size; + return buf_size; + } + } +#if 1 + is_dummy_buf &= (dummy_buf == buf); + + if (!is_dummy_buf) { + parse_nal_units(s, buf, buf_size, ctx); + } +#else + if(next != END_NOT_FOUND) { + parse_nal_units(s, buf, buf_size, avctx); + } +#endif + + *poutbuf = buf; + *poutbuf_size = buf_size; + ev->to_read -= next; + return next; +} + +// Split after the parameter sets at the beginning of the stream if they exist. +static int evc_split(AVCodecContext *ctx, const uint8_t *bs, int bs_size) +{ + return 0; +} + +static av_cold void evc_parser_close(AVCodecParserContext *s) +{ + /* EVCParserContext *ctx = s->priv_data; */ +} + +AVCodecParser ff_evc_parser = { + .codec_ids = { AV_CODEC_ID_EVC }, + .priv_data_size = sizeof(EVCParserContext), + .parser_init = evc_parser_init, + .parser_parse = evc_parse, + .parser_close = evc_parser_close, + .split = evc_split, +}; diff --git a/libavcodec/libxevd.c b/libavcodec/libxevd.c new file mode 100644 index 0000000000..b0bd85cc63 --- /dev/null +++ b/libavcodec/libxevd.c @@ -0,0 +1,713 @@ +/* + * libxevd decoder + * EVC (MPEG-5 Essential Video Coding) decoding using XEVD MPEG-5 EVC decoder library + * + * Copyright (C) 2021 Dawid Kozinski + * + * 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 + */ + +#if defined(_MSC_VER) +#define XEVD_API_IMPORTS 1 +#endif + +#include + +#include +#include + +#include "libavutil/internal.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/pixfmt.h" +#include "libavutil/imgutils.h" + +// #define USE_EXP_GOLOMB_STUFF +#ifdef USE_EXP_GOLOMB_STUFF +#include "golomb.h" +#endif + +#include "avcodec.h" +#include "internal.h" +#include "packet_internal.h" + +#define UNUSED(x) (void)(x) + +#define XEVD_PARAM_BAD_NAME -1 +#define XEVD_PARAM_BAD_VALUE -2 + +/** + * The structure stores all the state associated with the instance of Xeve MPEG-5 EVC decoder + * The first field is a pointer to an AVClass struct (@see https://ffmpeg.org/doxygen/trunk/structAVClass.html#details). + */ +typedef struct XevdContext { + const AVClass *class; + + XEVD id; // XEVD instance identifier @see xevd.h + XEVD_CDSC cdsc; // decoding parameters @see xevd.h + XEVD_OPL opl; // @see xevd.h + + int decod_frames; // number of decoded frames + int packet_count; // number of packets created by decoder + + // configuration parameters + AVDictionary *xevd_opts; // xevd configuration read from a :-separated list of key=value parameters + +} XevdContext; + +static int op_threads = 1; // Default value + +#ifdef USE_EXP_GOLOMB_STUFF +static int get_nalu_type(const uint8_t *bs, int bs_size) +{ + GetBitContext gb; + int fzb, nut; + init_get_bits(&gb, bs, bs_size * 8); + fzb = get_bits1(&gb); + if(fzb != 0) { + av_log(NULL, AV_LOG_DEBUG, "forbidden_zero_bit is not clear\n"); + } + nut = get_bits(&gb, 6); /* nal_unit_type_plus1 */ + return nut - 1; +} +#endif + +#ifdef PRINT_NALU_INFO +static void print_nalu_info(XEVD_STAT * stat) +{ + if(stat->nalu_type < XEVD_NUT_SPS) { + av_log(NULL, AV_LOG_DEBUG, "XEVD_NUT_SPS \n"); + + av_log(NULL, AV_LOG_DEBUG, "%c-slice\n", stat->stype == XEVD_ST_I ? 'I' : stat->stype == XEVD_ST_P ? 'P' : 'B'); + + av_log(NULL, AV_LOG_DEBUG, " %d bytes\n", stat->read); + av_log(NULL, AV_LOG_DEBUG, ", poc=%d, tid=%d, ", (int)stat->poc, (int)stat->tid); + + for (int i = 0; i < 2; i++) { + av_log(NULL, AV_LOG_DEBUG, "[L%d ", i); + for (int j = 0; j < stat->refpic_num[i]; j++) av_log(NULL, AV_LOG_DEBUG,"%d ", stat->refpic[i][j]); + av_log(NULL, AV_LOG_DEBUG,"] \n"); + } + } else if(stat->nalu_type == XEVD_NUT_SPS) { + av_log(NULL, AV_LOG_DEBUG, "XEVD_NUT_SPS \n"); + } else if (stat->nalu_type == XEVD_NUT_PPS) { + av_log(NULL, AV_LOG_DEBUG, "XEVD_NUT_PPS \n"); + } else if (stat->nalu_type == XEVD_NUT_SEI) { + av_log(NULL, AV_LOG_DEBUG, "XEVD_NUT_SEI \n"); + } else { + av_log(NULL, AV_LOG_DEBUG, "Unknown bitstream !!!! \n"); + } +} +#endif + +// @todo consider moving following function to separate file containing helper functions for EVC decoder +#ifdef PRINT_FRAME_INFO +static void print_frame_info(const AVFrame* f) +{ + int level = AV_LOG_DEBUG; + av_log(NULL, level, "frame->width: %d\n", f->width); + av_log(NULL, level, "frame->height: %d\n", f->height); + + av_log(NULL, level, "frame->linesize[0]: %d\n", f->linesize[0]); + av_log(NULL, level, "frame->linesize[1]: %d\n", f->linesize[1]); + av_log(NULL, level, "frame->linesize[2]: %d\n", f->linesize[2]); + av_log(NULL, level, "frame->buf[0]: %p\n", f->buf[0]); + av_log(NULL, level, "frame->buf[1]: %p\n", f->buf[1]); + av_log(NULL, level, "frame->buf[2]: %p\n", f->buf[2]); + av_log(NULL, level, "frame->data[0]: %p\n", f->data[0]); + av_log(NULL, level, "frame->data[1]: %p\n", f->data[1]); + av_log(NULL, level, "frame->data[2]: %p\n", f->data[2]); +} +#endif + +// @todo consider moving following function to separate file containing helper functions for EVC decoder +#ifdef PRINT_XEVD_IMGB_INFO +static void print_xevd_imgb_info(const XEVD_IMGB* imgb) +{ + av_log(NULL, AV_LOG_DEBUG, "imgb->np: %d\n", imgb->np); + av_log(NULL, AV_LOG_DEBUG, "imgb->bsize[0]: %d\n", imgb->bsize[0]); + av_log(NULL, AV_LOG_DEBUG, "imgb->bsize[1]: %d\n", imgb->bsize[1]); + av_log(NULL, AV_LOG_DEBUG, "imgb->bsize[2]: %d\n", imgb->bsize[2]); +} +#endif + +// @todo consider moving following function to separate file containing helper functions for EVC decoder +#ifdef PRINT_AVCTX +static void print_avctx(const AVCodecContext *avctx) +{ + if( AVMEDIA_TYPE_UNKNOWN == avctx->codec_type) { + av_log(NULL, AV_LOG_DEBUG, "avctx->codec_type: AVMEDIA_TYPE_UNKNOWN\n"); + } else if(AVMEDIA_TYPE_VIDEO == avctx->codec_type) + av_log(NULL, AV_LOG_DEBUG, "avctx->codec_type: AVMEDIA_TYPE_VIDEO \n"); + else { + av_log(NULL, AV_LOG_DEBUG, "avctx->codec_type: AVMEDIA_TYPE_UNKNOWN\n"); + } + + av_log(NULL, AV_LOG_DEBUG, "avctx->codec_id: %s\n",avcodec_get_name(avctx->codec_id)); + av_log(NULL, AV_LOG_DEBUG, "avctx->width: %d\n", avctx->width); + av_log(NULL, AV_LOG_DEBUG, "avctx->height: %d\n", avctx->height); + av_log(NULL, AV_LOG_DEBUG, "avctx->pix_fmt: %d\n", avctx->pix_fmt); +} +#endif + +/** + * Read options + * + * @param avctx codec context + * @return 0 on success + */ +static int read_options(const AVCodecContext* avctx) +{ + + op_threads = (avctx->thread_count>0)?avctx->thread_count:1; + + return 0; +} + +/** + * Parse :-separated list of key=value parameters + * + * @param key + * @param value + * + * @return 0 on success, negative value on failure + * + * @todo Consider removing the function + */ +static int xevd_params_parse(const char* key, const char* value) +{ + if(!key) { + av_log(NULL, AV_LOG_ERROR, "Ivalid argument: key string is NULL\n"); + return XEVD_ERR_INVALID_ARGUMENT; + } + if(!value) { + av_log(NULL, AV_LOG_ERROR, "Ivalid argument: value string is NULL\n"); + return XEVD_ERR_INVALID_ARGUMENT; + } + + else { + av_log(NULL, AV_LOG_ERROR, "Unknown xevd codec option: %s\n", key); + return XEVD_PARAM_BAD_NAME; + } + return 0; +} + +/** + * The function returns a pointer to variable of type XEVD_CDSC. + * XEVD_CDSC contains all decoder parameters that should be initialized before its use. + * + * The field values of the XEVD_CDSC structure are populated based on: + * - the corresponding field values of the AvCodecConetxt structure, + * - the xevd decoder specific option values, + * (the full list of options available for xevd encoder is displayed after executing the command ./ffmpeg --help decoder = libxevd) + * - and the xevd encoder options specified as a list of key value pairs following xevd-params option + * + * Order of input processing and populating the XEVD_CDSC structure + * 1. first, the corresponding fields of the AVCodecContext structure are processed, (i.e -threads 4) + * 2. then xevd-specific options added as AVOption to the xevd AVCodec implementation (i.e -threads 3) + * 3. finally, the options specified after the xevd-params option as the parameter list of type key value are processed (i.e -xevd-params "m=2") + * + * There are options that can be set in different ways. In this case, please follow the above-mentioned order of processing. + * The most recent assignments overwrite the previous values. + * + * @param avctx codec context + * @param cdsc contains all encoder parameters that should be initialized before its use. + * + * @return 0 on success, negative error code on failure + */ +static int get_conf(const AVCodecContext* avctx, XEVD_CDSC* cdsc) +{ + int cpu_count = av_cpu_count(); + + /* read options from AVCodecContext & from XEVD_CDSC */ + read_options(avctx); + + /* parse :-separated list of key=value parameters and set values for created descriptor (XEVD_CDSC) */ + { + XevdContext *ctx = avctx->priv_data; + AVDictionaryEntry *en = NULL; + while ((en = av_dict_get(ctx->xevd_opts, "", en, AV_DICT_IGNORE_SUFFIX))) { + int parse_ret = xevd_params_parse(en->key, en->value); + + switch (parse_ret) { + case XEVD_PARAM_BAD_NAME: + av_log((AVCodecContext*)avctx, AV_LOG_WARNING, + "Unknown option: %s.\n", en->key); + break; + case XEVD_PARAM_BAD_VALUE: + av_log((AVCodecContext*)avctx, AV_LOG_WARNING, + "Invalid value for %s: %s.\n", en->key, en->value); + break; + default: + break; + } + } + } + + /* clear XEVS_CDSC structure */ + memset(cdsc, 0, sizeof(XEVD_CDSC)); + + /* init XEVD_CDSC */ + if(avctx->thread_count <= 0) { + cdsc->threads = (cpu_countthread_count > XEVD_MAX_TASK_CNT) { + cdsc->threads = XEVD_MAX_TASK_CNT; + } else { + cdsc->threads = avctx->thread_count; + } + + return XEVD_OK; +} + +/** + * Read NAL unit size + * @param data input data + * @return size of NAL unit on success, negative value on failure + */ +static int read_nal_unit_size(void * data) +{ + int nalu_size; + memcpy(&nalu_size, data, XEVD_NAL_UNIT_LENGTH_BYTE); + if(nalu_size <= 0) { + return -1; + } + return nalu_size; +} + +/** + * @param avctx codec context + * @param ctx the structure that stores all the state associated with the instance of Xeve MPEG-5 EVC decoder + * @return 0 on success, negative value on failure + */ +static int export_stream_params(AVCodecContext *avctx, const XevdContext *ctx) +{ + // unsigned int num = 0, den = 0; + // @todo support other formats + + int ret; + int size; + int color_space; + + avctx->pix_fmt = AV_PIX_FMT_YUV420P10; + + // @todo The AVCodecContext should be initialized here using data from the object of XEVD_SPS type. + // + // It seems to be impossible right now since XEVD API limitation. + // The extension for the XEVD API is needed. + // To be more precise, what we need is access to the object of XEVD_SPS type being a part of XEVD_CTX object. + // The object of XEVD_CTX type is created while the function xevd_create() being a part of public API is called. + // + // @todo remove the following hardoced has_b_frames; consider using sps->num_reorder_pics value instead + // + // avctx->has_b_frames = 1; // (sps->num_reorder_pics)?1:0; + size = 4; + ret = xevd_config(ctx->id, XEVD_CFG_GET_CODED_WIDTH, &avctx->coded_width, &size); + if (XEVD_FAILED(ret)) { + av_log(NULL, AV_LOG_ERROR, "failed to get coded_width\n"); + return -1; + } + + ret = xevd_config(ctx->id, XEVD_CFG_GET_CODED_HEIGHT, &avctx->coded_height, &size); + if (XEVD_FAILED(ret)) { + av_log(NULL, AV_LOG_ERROR, "failed to get coded_height\n"); + return -1; + } + + ret = xevd_config(ctx->id, XEVD_CFG_GET_WIDTH, &avctx->width, &size); + if (XEVD_FAILED(ret)) { + av_log(NULL, AV_LOG_ERROR, "failed to get width\n"); + return -1; + } + + ret = xevd_config(ctx->id, XEVD_CFG_GET_HEIGHT, &avctx->height, &size); + if (XEVD_FAILED(ret)) { + av_log(NULL, AV_LOG_ERROR, "failed to get height\n"); + return -1; + } + + ret = xevd_config(ctx->id, XEVD_CFG_GET_COLOR_SPACE, &color_space, &size); + if (XEVD_FAILED(ret)) { + av_log(NULL, AV_LOG_ERROR, "failed to get color_space\n"); + return -1; + } + switch(color_space) { + case XEVD_CS_YCBCR400_10LE: + av_log(NULL, AV_LOG_DEBUG, "color_space = XEVD_CS_YCBCR400_10LE\n"); + avctx->pix_fmt = AV_PIX_FMT_GRAY10LE; + break; + case XEVD_CS_YCBCR420_10LE: + av_log(NULL, AV_LOG_DEBUG, "color_space = XEVD_CS_YCBCR420_10LE\n"); + avctx->pix_fmt = AV_PIX_FMT_YUV420P10LE; + break; + case XEVD_CS_YCBCR422_10LE: + av_log(NULL, AV_LOG_DEBUG, "color_space = XEVD_CS_YCBCR422_10LE\n"); + avctx->pix_fmt = AV_PIX_FMT_YUV422P10LE; + break; + case XEVD_CS_YCBCR444_10LE: + av_log(NULL, AV_LOG_DEBUG, "color_space = XEVD_CS_YCBCR444_10LE\n"); + avctx->pix_fmt = AV_PIX_FMT_YUV444P10LE; + break; + default: + av_log(NULL, AV_LOG_ERROR, "unknown color space\n"); + avctx->pix_fmt = AV_PIX_FMT_NONE; + return -1; + } + +// @todo Use _XEVD_SPS fields to initialize AVCodecContext when it is possible +#ifdef USE_XEVD_SPS_FIELDS + avctx->profile = sps->profile_idc; + avctx->level = sps->level_idc; + + ff_set_sar(avctx, sps->vui_parameters.sar); + + if (sps->vui_parametersvui.video_signal_type_present_flag) + avctx->color_range = sps->vui_parameters.video_full_range_flag ? AVCOL_RANGE_JPEG + : AVCOL_RANGE_MPEG; + else + avctx->color_range = AVCOL_RANGE_MPEG; + + if (sps->vui_parameters.colour_description_present_flag) { + avctx->color_primaries = sps->vui_parameters.colour_primaries; + avctx->color_trc = sps->vui_parameters.transfer_characteristic; + avctx->colorspace = sps->vui_parameters.matrix_coeffs; + } else { + avctx->color_primaries = AVCOL_PRI_UNSPECIFIED; + avctx->color_trc = AVCOL_TRC_UNSPECIFIED; + avctx->colorspace = AVCOL_SPC_UNSPECIFIED; + } + + if (sps->vui_parameters.timing_info_present_flag) { + num = sps->vui_parameters.num_units_in_tick; + den = sps->vui_parameters.time_scale; + } + + 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; + } +#else + avctx->color_primaries = AVCOL_PRI_UNSPECIFIED; + avctx->color_trc = AVCOL_TRC_UNSPECIFIED; + avctx->colorspace = AVCOL_SPC_UNSPECIFIED; + +#endif + return 0; +} + +/** + * Initialize decoder static data + * + * @todo Consider removing unused function + */ +static av_cold void libxevd_init_static_data(AVCodec *codec) +{ + UNUSED(codec); +} + +/** + * Initialize decoder + * Create decoder instance and allocate all the needed resources + * + * @param avctx codec context + * @return 0 on success, negative error code on failure + */ +static av_cold int libxevd_init(AVCodecContext *avctx) +{ + XevdContext *ctx = avctx->priv_data; + int val = 0; + XEVD_CDSC *cdsc = &(ctx->cdsc); + + av_log(NULL, AV_LOG_DEBUG, "eXtra-fast Essential Video Decoder\n"); +#ifdef PRINT_AVCTX + print_avctx(avctx); +#endif + + /* read configurations and set values for created descriptor (XEVD_CDSC) */ + val = get_conf(avctx, cdsc); + if (val != XEVD_OK) { + av_log(NULL, AV_LOG_ERROR,"Cannot get configuration\n"); + return -1; + } + + /* create decoder */ + ctx->id = xevd_create(&(ctx->cdsc), NULL); + if(ctx->id == NULL) { + av_log(NULL, AV_LOG_ERROR, "cannot create XEVD encoder\n"); + return -1; + } + + ctx->packet_count = 0; + ctx->decod_frames = 0; + return 0; +} + +/** + * Dncode picture + * + * @param avctx codec context + * @param data codec type dependent output struct + * @param[out] got_frame decoder sets to 0 or 1 to indicate that a + * non-empty frame or subtitle was returned in + * outdata. + * @param[in] pkt AVPacket containing the data to be decoded + * @return amount of bytes read from the packet on success, negative error + * code on failure + */ +static int libxevd_decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *pkt) +{ + AVFrame *frame = data; + XevdContext *ctx = NULL; + XEVD_IMGB * imgb = NULL; + XEVD_STAT stat; + XEVD_BITB bitb; + int ret, nalu_size, bs_read_pos; + + if(avctx == NULL) { + av_log(NULL, AV_LOG_ERROR, "Invalid input parameter: AVCodecContext\n"); + return -1; + } + ctx = avctx->priv_data; + if(ctx == NULL) { + av_log(avctx, AV_LOG_ERROR, "Invalid XEVD context\n"); + return -1; + } + + if(pkt->size > 0) { + bs_read_pos = 0; + imgb = NULL; + while(pkt->size > (bs_read_pos + XEVD_NAL_UNIT_LENGTH_BYTE)) { + int nal_type = 0; + + memset(&stat, 0, sizeof(XEVD_STAT)); + memset(&bitb, 0, sizeof(XEVD_BITB)); + + nalu_size = read_nal_unit_size(pkt->data + bs_read_pos); + if(nalu_size <= 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid bitstream\n"); + goto ERR; + } + bs_read_pos += XEVD_NAL_UNIT_LENGTH_BYTE; + + bitb.addr = pkt->data + bs_read_pos; + bitb.ssize = nalu_size; + + // Read NAL Unit Type from NAL Unit Header + // + // The structure of NAL Unit Header looks like follows + // + //Â +---------------+---------------+ + //Â |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7| + //Â +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + //Â |F| Type | TID | Reserve |E| + //Â +-------------+-----------------+ + // + // F: 1 bit - forbidden_zero_bit. Required to be zero in [EVC]. + // Type: 6 bits - nal_unit_type_plus1 (This field specifies the NAL unit type as defined in Table 4 of [EVC]) + // TID: 3 bits - nuh_temporal_id. This field specifies the temporal identifier of the NAL unit. + // Reserve: 5 bits - nuh_reserved_zero_5bits. This field shall be equal to the version of the [EVC] specification. + // E: 1 bit - nuh_extension_flag. This field shall be equal the version of the [EVC] specification. + // + // @see https://datatracker.ietf.org/doc/html/draft-ietf-avtcore-rtp-evc-01#section-1.1.4 + +#ifdef USE_EXP_GOLOMB_STUFF + nal_type = get_nalu_type(bitb.addr, 1); + av_log(avctx, AV_LOG_DEBUG, "NALU Type: %d\n", nal_type); +#else + memcpy(&nal_type,bitb.addr,1); + nal_type = nal_type & 0x7E; + nal_type = nal_type >> 1; + nal_type -= 1; + av_log(avctx, AV_LOG_DEBUG, "NALU Type: %d\n", nal_type); +#endif + + /* main decoding block */ + ret = xevd_decode(ctx->id, &bitb, &stat); + if(XEVD_FAILED(ret)) { + av_log(avctx, AV_LOG_ERROR, "failed to decode bitstream\n"); + goto ERR; + } + + bs_read_pos += nalu_size; + +#ifdef PRINT_NALU_INFO + print_nalu_info(ctx); +#endif + + if(stat.nalu_type == XEVD_NUT_SPS) { + av_log(avctx, AV_LOG_DEBUG, "EVC stream parameters changed\n"); + + if(export_stream_params(avctx, ctx)!=0) { + goto ERR; + } + av_log(avctx, AV_LOG_DEBUG, "width: %d\n",avctx->width); + av_log(avctx, AV_LOG_DEBUG, "height: %d\n",avctx->height); + + } + + if(stat.read != nalu_size) { + av_log(avctx, AV_LOG_INFO, "different reading of bitstream (in:%d, read:%d)\n,", nalu_size, stat.read); + } + if(stat.fnum >= 0) { + if (imgb) { /* already has a decoded image */ + imgb->release(imgb); + imgb = NULL; + } + ret = xevd_pull(ctx->id, &imgb, &(ctx->opl)); + if(XEVD_FAILED(ret)) { + av_log(avctx, AV_LOG_ERROR, "failed to pull the decoded image (err:%d, frame#=%d)\n", ret, stat.fnum); + goto ERR; + } else if (ret == XEVD_OK_FRM_DELAYED) { + av_log(avctx, AV_LOG_DEBUG, "delayed frame\n"); + if(imgb) { + imgb->release(imgb); + imgb = NULL; + } + } + } + } + } else { + av_log(NULL, AV_LOG_DEBUG, "bumping ...\n"); + ret = xevd_pull(ctx->id, &(imgb), &(ctx->opl)); + if(ret == XEVD_ERR_UNEXPECTED) { + av_log(avctx, AV_LOG_DEBUG, "Bumping process completed\n"); + *got_frame = 0; + return 0; + } else if(XEVD_FAILED(ret)) { + av_log(avctx, AV_LOG_ERROR, "failed to pull the decoded image (err:%d)\n", ret); + goto ERR; + } else { + av_log(avctx, AV_LOG_DEBUG, "bumping success\n"); + } + } + + if(imgb) { + /* @todo supports other color space and bit depth */ + if(imgb->cs != XEVD_CS_YCBCR420_10LE) { + av_log(avctx, AV_LOG_ERROR, "Not supported pixel format: %s\n", av_get_pix_fmt_name(avctx->pix_fmt)); + goto ERR; + } + + if (imgb->w[0] != avctx->width || imgb->h[0] != avctx->height) { + av_log(avctx, AV_LOG_DEBUG, "resolution changed %dx%d -> %dx%d\n", + avctx->width, avctx->height, imgb->w[0], imgb->h[0]); + if(ff_set_dimensions(avctx, imgb->w[0], imgb->h[0]) < 0) { + av_log(avctx, AV_LOG_ERROR, "cannot set new dimension\n"); + goto ERR; + } + } + + frame->coded_picture_number++; + frame->display_picture_number++; + frame->format = AV_PIX_FMT_YUV420P10LE; + +#ifdef PRINT_XEVD_IMGB_INFO + print_xevd_imgb_info(imgb); +#endif + + if (ff_get_buffer(avctx, frame, 0) < 0) { + av_log(avctx, AV_LOG_ERROR, "cannot get AV buffer\n"); + goto ERR; + } + + frame->pts = pkt->pts; + av_log(avctx, AV_LOG_DEBUG, "frame->pts = %ld\n", frame->pts); + + av_image_copy(frame->data, frame->linesize, (const uint8_t **)imgb->a, + imgb->s, avctx->pix_fmt, + imgb->w[0], imgb->h[0]); + + ctx->decod_frames++; + *got_frame = 1; + +#ifdef PRINT_FRAME_INFO + print_frame_info(frame); +#endif + imgb->release(imgb); + imgb = NULL; + } else { + *got_frame = 0; + } + + ctx->packet_count++; + return pkt->size; + +ERR: + if(imgb) { + imgb->release(imgb); + imgb = NULL; + } + *got_frame = 0; + return -1; +} + +/** + * Destroy decoder + * + * @param avctx codec context + * @return 0 on success + */ +static av_cold int libxevd_close(AVCodecContext *avctx) +{ + XevdContext *ctx = avctx->priv_data; + if(ctx->id) { + xevd_delete(ctx->id); + ctx->id = NULL; + } + + return 0; +} + +#define OFFSET(x) offsetof(XevdContext, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM + +// @todo consider using following options (./ffmpeg --help decoder=libxevd) +// +static const AVOption options[] = { + { "xevd-params", "override the xevd configuration using a :-separated list of key=value parameters", OFFSET(xevd_opts), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VD }, + { NULL } +}; + +static const AVClass xevd_class = { + .class_name = "libxevd", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +/// @todo provide implementation +static const AVCodecDefault xevd_defaults[] = { + { "b", "0" }, + { NULL }, +}; + +AVCodec ff_libxevd_decoder = { + .name = "evc", + .long_name = NULL_IF_CONFIG_SMALL("EVC / MPEG-5 Essential Video Coding (EVC)"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_EVC, + .init = libxevd_init, + .init_static_data = libxevd_init_static_data, + .decode = libxevd_decode, + .close = libxevd_close, + .priv_data_size = sizeof(XevdContext), + .priv_class = &xevd_class, + .defaults = xevd_defaults, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_AVOID_PROBING, + .wrapper_name = "libxevd", +}; diff --git a/libavcodec/libxeve.c b/libavcodec/libxeve.c new file mode 100644 index 0000000000..7d78e32f81 --- /dev/null +++ b/libavcodec/libxeve.c @@ -0,0 +1,1213 @@ +/* + * libxeve encoder + * EVC (MPEG-5 Essential Video Coding) encoding using XEVE MPEG-5 EVC encoder library + * + * Copyright (C) 2021 Dawid Kozinski + * + * 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 + */ + +#if defined(_MSC_VER) +#define XEVE_API_IMPORTS 1 +#endif + +#include + +#include +#include + +#include "libavutil/internal.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/pixfmt.h" +#include "libavutil/time.h" + +#include "avcodec.h" +#include "internal.h" +#include "packet_internal.h" + +#define MAX_BS_BUF (16*1024*1024) + +/** + * Error codes + */ +#define XEVE_PARAM_BAD_NAME -100 +#define XEVE_PARAM_BAD_VALUE -200 + +/** + * Macro for eliminating the unused variable warning + */ +#define UNUSED(x) (void)(x) + +/** + * Encoder states + * + * STATE_ENCODING - the encoder receives and processes input frames + * STATE_BUMPING - there are no more input frames, however the encoder still processes previously received data + * STATE_SKIPPING - skipping input frames + */ +typedef enum State { + STATE_ENCODING, + STATE_BUMPING, + STATE_SKIPPING +} State; + +/** + * The structure stores all the state associated with the instance of Xeve MPEG-5 EVC encoder + * The first field is a pointer to an AVClass struct (@see https://ffmpeg.org/doxygen/trunk/structAVClass.html#details). + */ +typedef struct XeveContext { + const AVClass *class; + + XEVE id; // XEVE instance identifier + XEVE_CDSC cdsc; // coding parameters i.e profile, width & height of input frame, num of therads, frame rate ... + XEVE_BITB bitb; // bitstream buffer (output) + XEVE_STAT stat; // encoding status (output) + XEVE_IMGB imgb; // image buffer (input) + + State state; // encoder state (skipping, encoding, bumping) + + int encod_frames; // num of encoded frames + double bytes_total; // encoded bitstream byte size + double bitrate; // bits per second + int packet_count; // num of packets created by encoder + + // Chroma subsampling + int width_luma; + int height_luma; + int width_chroma; + int height_chroma; + + int profile_id; // encoder profile (main, baseline) + int preset_id; // preset of xeve ( fast, medium, slow, placebo) + int tune_id; // tune of xeve (psnr, zerolatency) + int input_depth; // input bit-depth: 8bit, 10bit + int hash; + + /* variables for input parameter */ + char * op_preset; + char * op_tune; + int op_qp; + int op_crf; + + // configuration parameters + // xeve configuration read from a :-separated list of key=value parameters + AVDictionary *xeve_params; +} XeveContext; + +/** + * Gets Xeve encoder pre-defined profile + * + * @param profile string describing Xeve encoder profile (baseline, main) + * @return XEVE pre-defined profile on success, negative value on failure + */ +static int get_profile_id(const char * profile) +{ + if (!strcmp(profile, "baseline")) { + return XEVE_PROFILE_BASELINE; + } else if (!strcmp(profile, "main")) { + return XEVE_PROFILE_MAIN; + } else { + return -1; + } +} + +/** + * Gets Xeve pre-defined preset + * + * @param preset string describing Xeve encoder preset (fast, medium, slow, placebo ) + * @return XEVE pre-defined profile on success, negative value on failure + */ +static int get_preset_id(const char * preset) +{ + if((!strcmp(preset, "fast"))) { + return XEVE_PRESET_FAST; + } else if (!strcmp(preset, "medium")) { + return XEVE_PRESET_MEDIUM; + } else if (!strcmp(preset, "slow")) { + return XEVE_PRESET_SLOW; + } else if (!strcmp(preset, "placebo")) { + return XEVE_PRESET_PLACEBO; + } else { + return -1; + } +} + +/** + * Gets Xeve pre-defined tune id + * + * @param preset string describing Xeve encoder preset (fast, medium, slow, placebo ) + * @return XEVE pre-defined profile on success, negative value on failure + */ +static int get_tune_id(const char * tune) +{ + if((!strcmp(tune, "psnr"))) { + return XEVE_TUNE_PSNR; + } else if (!strcmp(tune, "zerolatency")) { + return XEVE_TUNE_ZEROLATENCY; + } else { + return -1; + } +} + +static int kbps_str_to_int(char *str) +{ + int kbps = 0; + if (strchr(str, 'K') || strchr(str, 'k')) { + char *tmp = strtok(str, "Kk "); + kbps = (int)(atof(tmp)); + } else if (strchr(str, 'M') || strchr(str, 'm')) { + char *tmp = strtok(str, "Mm "); + kbps = (int)(atof(tmp) * 1000); + } else { + kbps = atoi(str); + } + return kbps; +} + +/** + * Parse :-separated list of key=value parameters + * + * @param key + * @param value + * @param xe pointer to the structure that stores all the state associated with + * the instance of Xeve MPEG-5 EVC encoder + * @param param coding parameters + * + * @return 0 on success, negative value on failure + */ +static int parse_xeve_params(const char* key, const char* value, XeveContext* xe, XEVE_PARAM* param) +{ + if(!key) { + av_log(NULL, AV_LOG_ERROR, "Ivalid argument: key string is NULL\n"); + return XEVE_PARAM_BAD_VALUE; + } + if(!value) { + if (strcmp(key, "hash") == 0) { + xe->hash = 1; + av_log(NULL, AV_LOG_INFO, "embedding signature is enabled\n"); + } else { + av_log(NULL, AV_LOG_ERROR, "Ivalid argument: value string is NULL\n"); + return XEVE_PARAM_BAD_VALUE; + } + } else if (strcmp(key, "vbv-bufsize") == 0 ) { + param->vbv_bufsize = kbps_str_to_int((char*)value); + av_log(NULL, AV_LOG_INFO, "VBV buffer size: %dkbits\n", param->vbv_bufsize); + } else if (strcmp(key, "rc-type") == 0 ) { + int rc_type = atoi(value); + if(rc_type < 0 || rc_type > 2) { + av_log(NULL, AV_LOG_ERROR, "Rate control type [ 0(rc_off) / 1(CBR) ] bad value: %d\n", rc_type); + return XEVE_PARAM_BAD_VALUE; + } + param->rc_type = rc_type; + av_log(NULL, AV_LOG_INFO, "Rate control type [ 0(rc_off) / 1(CBR) ] : %d\n", rc_type); + } else if (strcmp(key, "bframes") == 0 ) { + int bframes = atoi(value); + if(bframes < 0) { + av_log(NULL, AV_LOG_ERROR, "bframes: bad value: %d\n", bframes); + return XEVE_PARAM_BAD_VALUE; + } + param->bframes = bframes; + av_log(NULL, AV_LOG_INFO, "bframes : %d\n", bframes); + } else if (strcmp(key, "profile") == 0 ) { + const char* profile = value; + int profile_id; + av_log(NULL, AV_LOG_INFO, "profile (baseline, main): %s\n", profile); + profile_id = get_profile_id(profile); + if (profile_id < 0) { + av_log(NULL, AV_LOG_ERROR, "Invalid xeve param: profile(%s)\n", profile); + return XEVE_PARAM_BAD_VALUE; + } + xe->profile_id = profile_id; + } else if (strcmp(key, "preset") == 0 ) { + const char* preset = value; + int preset_id; + av_log(NULL, AV_LOG_INFO, "Preset of xeve (fast, medium, slow, placebo): %s\n", preset); + preset_id = get_preset_id(preset); + if( preset_id < 0) { + av_log(NULL, AV_LOG_ERROR, "Invalid xeve param: preset(%s)\n", preset); + return XEVE_PARAM_BAD_VALUE; + } + xe->preset_id = preset_id; + } else if (strcmp(key, "tune") == 0 ) { + const char* tune = value; + int tune_id; + av_log(NULL, AV_LOG_INFO, "Tune of xeve (psnr, zerolatency): %s\n", tune); + tune_id= get_tune_id(tune); + if( tune_id < 0) { + av_log(NULL, AV_LOG_ERROR, "Invalid xeve param: tune(%s)\n", tune); + return XEVE_PARAM_BAD_VALUE; + } + xe->tune_id = tune_id; + } else if (strcmp(key, "bitrate") == 0 ) { + param->bitrate = kbps_str_to_int((char *)value); + av_log(NULL, AV_LOG_INFO, "Bitrate = %dkbps\n", param->bitrate); + } else if (strcmp(key, "q") == 0 || strcmp(key, "qp") == 0) { + int qp = atoi(value); + if(qp < 0 || qp > 51) { + av_log(NULL, AV_LOG_ERROR, "Invalid QP value (0~51) :%d\n", qp); + return XEVE_PARAM_BAD_VALUE; + } + param->qp = qp; + av_log(NULL, AV_LOG_INFO, "QP value (0~51): %d\n", param->qp); + } else { + av_log(NULL, AV_LOG_ERROR, "Unknown xeve codec option: %s\n", key); + return XEVE_PARAM_BAD_NAME; + } + return 0; +} + +/** + * Convert ffmpeg pixel format (AVPixelFormat) to XEVE pre-defined color format + * + * @param[in] px_fmt pixel format (@see https://ffmpeg.org/doxygen/trunk/pixfmt_8h.html#a9a8e335cf3be472042bc9f0cf80cd4c5) + * @param[out] color_format XEVE pre-defined color format (@see xeve.h) + * @param[out] bit_depth bit depth + * + * @return 0 on success, negative value on failure + */ +static int get_pix_fmt(enum AVPixelFormat pix_fmt, int *color_format, int *bit_depth) +{ + switch (pix_fmt) { + case AV_PIX_FMT_YUV420P: + *color_format = XEVE_CF_YCBCR420; + *bit_depth = 8; + break; + case AV_PIX_FMT_YUV422P: + *color_format = XEVE_CF_YCBCR422; + *bit_depth = 8; + break; + case AV_PIX_FMT_YUV444P: + *color_format = XEVE_CF_YCBCR444; + *bit_depth = 8; + break; + case AV_PIX_FMT_YUV420P10: + *color_format = XEVE_CF_YCBCR420; + *bit_depth = 10; + break; + case AV_PIX_FMT_YUV422P10: + *color_format = XEVE_CF_YCBCR422; + *bit_depth = 10; + break; + case AV_PIX_FMT_YUV444P10: + *color_format = XEVE_CF_YCBCR444; + *bit_depth = 10; + break; + default: + *color_format = XEVE_CF_UNKNOWN; + return -1; + } + return 0; +} + +/** + * The function returns a pointer to variable of type XEVE_CDSC. + * XEVE_CDSC contains all encoder parameters that should be initialized before its use. + * + * The field values of the XEVE_CDSC structure are populated based on: + * - the corresponding field values of the AvCodecConetxt structure, + * - the xeve encoder specific option values, + * (the full list of options available for xeve encoder is displayed after executing the command ./ffmpeg --help encoder = libxeve) + * - and the xeve encoder options specified as a list of key value pairs following xeve-params option + * + * Order of input processing and populating the XEVE_CDSC structure + * 1. first, the corresponding fields of the AVCodecContext structure are processed, (i.e -pix_fmt yuv420p -s:v 1920x1080 -r 30 -profile:v 0) + * 2. then xeve-specific options added as AVOption to the xeve AVCodec implementation (i.e -threads_cnt 3 -preset 0) + * 3. finally, the options specified after the xeve-params option as the parameter list of type key value are processed (i.e -xeve-params "m=2:q=17") + * + * There are options that can be set in different ways. In this case, please follow the above-mentioned order of processing. + * The most recent assignments overwrite the previous values. + * + * @param ctx codec context + * @param cdsc contains all encoder parameters that should be initialized before its use. + * + * @return 0 on success, negative error code on failure + */ +static int get_conf(const AVCodecContext *ctx, XEVE_CDSC *cdsc) +{ + XEVE_PARAM * param = NULL; + XeveContext *xe = NULL; + int color_format; + int cpu_count = av_cpu_count(); + int ret; + + xe = ctx->priv_data; + param = &cdsc->param; + + /* set defualt value in priv_data */ + memset(cdsc, 0, sizeof(XEVE_CDSC)); + xe->hash = 0; + + /* set default parameters */ + ret = xeve_param_default(param); + if (XEVE_FAILED(ret)) { + av_log(NULL, AV_LOG_ERROR, "cannot set_default parameter\n"); + goto ERR; + } + + /* read options from AVCodecContext */ + if(ctx->width > 0) { + param->w = ctx->width; + xe->width_luma = ctx->width; + } + + if(ctx->height > 0) { + param->h = ctx->height; + xe->height_luma = ctx->height; + } + + if(ctx->framerate.num > 0) { + /* @todo: fps can be float number, but xeve API doesn't support it */ + param->fps = (int)(((float)ctx->framerate.num / ctx->framerate.den) + 0.5); + } + + if(ctx->gop_size >= 0) { /* key-frame interval */ + param->keyint = ctx->gop_size; // 0: only one I-frame at the first time; 1: every frame is coded in I-frame + av_log(NULL, AV_LOG_INFO, "GOP size (key-frame interval): %d\n", ctx->gop_size); + } + if (ctx->max_b_frames == 0 || ctx->max_b_frames == 1 || ctx->max_b_frames == 3 || + ctx->max_b_frames == 7 || ctx->max_b_frames == 15) { /* number of b-frame */ + param->bframes = ctx->max_b_frames; + av_log(NULL, AV_LOG_INFO, "Number of max b-frames: %d\n", ctx->max_b_frames); + } else { + av_log(NULL, AV_LOG_ERROR, "Incorrect value for maximum number of B frames: (%d) \n" + "Acceptable values for bf option (maximum number of B frames) are 0,1,3,7 or 15\n", ctx->max_b_frames); + goto ERR; + } + + if (ctx->level >= 0) { + param->level_idc = ctx->level; + } + ret = get_pix_fmt(ctx->pix_fmt, &color_format, &xe->input_depth); + if (ret!=0) { + av_log((AVCodecContext*)ctx, AV_LOG_ERROR, "Unsupported pixel format.\n"); + goto ERR; + } + param->cs = XEVE_CS_SET(color_format, xe->input_depth, 0); + + if (ctx->rc_buffer_size > 0) { + param->vbv_bufsize = (int)(ctx->rc_buffer_size/ 1000); + av_log(NULL, AV_LOG_INFO, "VBV buf size: %d\n", ctx->rc_buffer_size); + } + if (ctx->bit_rate > 0) { + if (ctx->bit_rate / 1000 > INT_MAX || ctx->rc_max_rate / 1000 > INT_MAX) { + av_log(NULL, AV_LOG_ERROR, "not supported bitrate bit_rate and rc_max_rate > %d000\n", INT_MAX); + goto ERR; + } + param->bitrate = (int)(ctx->bit_rate / 1000); + param->rc_type = XEVE_RC_ABR; + } + if (xe->op_crf >= 0) { + param->crf = xe->op_crf; + param->rc_type = XEVE_RC_CRF; + } + + if(ctx->thread_count <= 0) { + av_log(NULL, AV_LOG_DEBUG, "cpu_count: %d\n", cpu_count); + param->threads = (cpu_count < XEVE_MAX_THREADS)? cpu_count: XEVE_MAX_THREADS; + } else if(ctx->thread_count > XEVE_MAX_THREADS) { + param->threads = XEVE_MAX_THREADS; + } else { + param->threads = ctx->thread_count; + } + av_log(NULL, AV_LOG_INFO, "param->threads: %d\n", param->threads); + + cdsc->param.cs = XEVE_CS_SET(color_format, param->codec_bit_depth, 0); + cdsc->max_bs_buf_size = MAX_BS_BUF; + + if(ctx->profile == FF_PROFILE_EVC_BASELINE) { + xe->profile_id = XEVE_PROFILE_BASELINE; + } else if(ctx->profile == FF_PROFILE_EVC_MAIN) { + xe->profile_id = XEVE_PROFILE_MAIN; + } else { + av_log(NULL, AV_LOG_ERROR, "Unknown encoder profile (%d)\n" + "Acceptable values for profile option are 0 and 1 (0: baseline profile; 1: main profile)\n", ctx->profile); + goto ERR; + } + if (xe->op_preset) { + xe->preset_id = get_preset_id(xe->op_preset); + av_log(NULL, AV_LOG_INFO, "Preset : %s\n", xe->op_preset); + } + if (xe->op_tune) { + xe->tune_id = get_tune_id(xe->op_tune); + av_log(NULL, AV_LOG_INFO, "Tune : %s\n", xe->op_tune); + } + + ret = xeve_param_ppt(param, xe->profile_id, xe->preset_id, xe->tune_id); + if (XEVE_FAILED(ret)) { + av_log(NULL, AV_LOG_ERROR, "cannot set profile(%d), preset(%d), tune(%d)\n", xe->profile_id, xe->preset_id, xe->tune_id); + goto ERR; + } + + /* parse :-separated list of key=value parameters and set values for created descriptor (XEVE_CDSC) */ + { + AVDictionaryEntry *en = NULL; + av_log(NULL, AV_LOG_INFO, "### Start to parse xeve_params ###\n"); + while ((en = av_dict_get(xe->xeve_params, "", en, AV_DICT_IGNORE_SUFFIX))) { + int parse_ret = parse_xeve_params(en->key, en->value, xe, param); + + switch (parse_ret) { + case XEVE_PARAM_BAD_NAME: + av_log((AVCodecContext*)ctx, AV_LOG_WARNING, + "Unknown option: %s.\n", en->key); + break; + case XEVE_PARAM_BAD_VALUE: + av_log((AVCodecContext*)ctx, AV_LOG_WARNING, + "Invalid value for %s: %s.\n", en->key, en->value); + break; + default: + break; + } + } + av_log(NULL, AV_LOG_INFO, "### End of parsing xeve_params ###\n"); + } + + av_log(NULL, AV_LOG_INFO, "Rate control type [ 0(CQP) / 1(ABR) / 2(CRF) ] : %d\n", param->rc_type); + av_log(NULL, AV_LOG_INFO, "crf=%d, bitrate=%d, vbv_bufsize=%d, fps=%d\n", param->crf, param->bitrate, param->vbv_bufsize, param->fps); + + return 0; + +ERR: + return AVERROR(EINVAL); +} + +/** + * Check codec configuration + * + * @param ctx codec context + * @param cdsc contains all encoder parameters that should be initialized before its use. + * + * @return 0 on success, negative error code on failure + */ +static int check_conf(AVCodecContext *ctx, XEVE_CDSC *cdsc) +{ + int ret = 0; + int min_block_size = 4; + int pic_m; + + if(cdsc->param.profile == XEVE_PROFILE_BASELINE) { + if (cdsc->param.tool_amvr == 1) { + av_log(ctx, AV_LOG_ERROR, "AMVR cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.tool_mmvd == 1) { + av_log(ctx, AV_LOG_ERROR, "MMVD cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.tool_affine == 1) { + av_log(ctx, AV_LOG_ERROR, "Affine cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.tool_dmvr == 1) { + av_log(ctx, AV_LOG_ERROR, "DMVR cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.tool_admvp == 1) { + av_log(ctx, AV_LOG_ERROR, "ADMVP cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.tool_hmvp == 1) { + av_log(ctx, AV_LOG_ERROR, "HMVP cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.tool_addb == 1) { + av_log(ctx, AV_LOG_ERROR, "ADDB cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.tool_alf == 1) { + av_log(ctx, AV_LOG_ERROR, "ALF cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.tool_htdf == 1) { + av_log(ctx, AV_LOG_ERROR, "HTDF cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.btt == 1) { + av_log(ctx, AV_LOG_ERROR, "BTT cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.suco == 1) { + av_log(ctx, AV_LOG_ERROR, "SUCO cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.tool_eipd == 1) { + av_log(ctx, AV_LOG_ERROR, "EIPD cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.tool_iqt == 1) { + av_log(ctx, AV_LOG_ERROR, "IQT cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.tool_cm_init == 1) { + av_log(ctx, AV_LOG_ERROR, "CM_INIT cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.tool_adcc == 1) { + av_log(ctx, AV_LOG_ERROR, "ADCC cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.tool_ats == 1) { + av_log(ctx, AV_LOG_ERROR, "ATS_INTRA cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.ibc_flag == 1) { + av_log(ctx, AV_LOG_ERROR, "IBC cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.tool_rpl == 1) { + av_log(ctx, AV_LOG_ERROR, "RPL cannot be on in base profile\n"); + ret = -1; + } + if (cdsc->param.tool_pocs == 1) { + av_log(ctx, AV_LOG_ERROR, "POCS cannot be on in base profile\n"); + ret = -1; + } + } else { + if (cdsc->param.tool_admvp == 0 && cdsc->param.tool_affine == 1) { + av_log(ctx, AV_LOG_ERROR, "AFFINE cannot be on when ADMVP is off\n"); + ret = -1; + } + if (cdsc->param.tool_admvp == 0 && cdsc->param.tool_amvr == 1) { + av_log(ctx, AV_LOG_ERROR, "AMVR cannot be on when ADMVP is off\n"); + ret = -1; + } + if (cdsc->param.tool_admvp == 0 && cdsc->param.tool_dmvr == 1) { + av_log(ctx, AV_LOG_ERROR, "DMVR cannot be on when ADMVP is off\n"); + ret = -1; + } + if (cdsc->param.tool_admvp == 0 && cdsc->param.tool_mmvd == 1) { + av_log(ctx, AV_LOG_ERROR, "MMVD cannot be on when ADMVP is off\n"); + ret = -1; + } + if (cdsc->param.tool_eipd == 0 && cdsc->param.ibc_flag == 1) { + av_log(ctx, AV_LOG_ERROR, "IBC cannot be on when EIPD is off\n"); + ret = -1; + } + if (cdsc->param.tool_iqt == 0 && cdsc->param.tool_ats == 1) { + av_log(ctx, AV_LOG_ERROR, "ATS cannot be on when IQT is off\n"); + ret = -1; + } + if (cdsc->param.tool_cm_init == 0 && cdsc->param.tool_adcc == 1) { + av_log(ctx, AV_LOG_ERROR, "ADCC cannot be on when CM_INIT is off\n"); + ret = -1; + } + } + + if (cdsc->param.btt == 1) { + if (cdsc->param.framework_cb_max && cdsc->param.framework_cb_max < 5) { + av_log(NULL, AV_LOG_ERROR, "Maximun Coding Block size cannot be smaller than 5\n"); + ret = -1; + } + if (cdsc->param.framework_cb_max > 7) { + av_log(NULL, AV_LOG_ERROR, "Maximun Coding Block size cannot be greater than 7\n"); + ret = -1; + } + if (cdsc->param.framework_cb_min && cdsc->param.framework_cb_min < 2) { + av_log(NULL, AV_LOG_ERROR, "Minimum Coding Block size cannot be smaller than 2\n"); + ret = -1; + } + if ((cdsc->param.framework_cb_max || cdsc->param.framework_cb_min) && + cdsc->param.framework_cb_min > cdsc->param.framework_cb_max) { + av_log(NULL, AV_LOG_ERROR, "Minimum Coding Block size cannot be greater than Maximum coding Block size\n"); + ret = -1; + } + if (cdsc->param.framework_cu14_max > 6) { + av_log(NULL, AV_LOG_ERROR, "Maximun 1:4 Coding Block size cannot be greater than 6\n"); + ret = -1; + } + if ((cdsc->param.framework_cb_max || cdsc->param.framework_cu14_max) && + cdsc->param.framework_cu14_max > cdsc->param.framework_cb_max) { + av_log(NULL, AV_LOG_ERROR, "Maximun 1:4 Coding Block size cannot be greater than Maximum coding Block size\n"); + ret = -1; + } + if (cdsc->param.framework_tris_max > 6) { + av_log(NULL, AV_LOG_ERROR, "Maximun Tri-split Block size be greater than 6\n"); + ret = -1; + } + if ((cdsc->param.framework_tris_max || cdsc->param.framework_cb_max) && + cdsc->param.framework_tris_max > cdsc->param.framework_cb_max) { + av_log(NULL, AV_LOG_ERROR, "Maximun Tri-split Block size cannot be greater than Maximum coding Block size\n"); + ret = -1; + } + if ((cdsc->param.framework_tris_min || cdsc->param.framework_cb_min) && + cdsc->param.framework_tris_min < cdsc->param.framework_cb_min + 2) { + av_log(NULL, AV_LOG_ERROR, "Maximun Tri-split Block size cannot be smaller than Minimum Coding Block size plus two\n"); + ret = -1; + } + if(cdsc->param.framework_cb_min) min_block_size = 1 << cdsc->param.framework_cb_min; + else min_block_size = 8; + } + + if (cdsc->param.suco == 1) { + if (cdsc->param.framework_suco_max > 6) { + av_log(NULL, AV_LOG_ERROR, "Maximun SUCO size cannot be greater than 6\n"); + ret = -1; + } + if (cdsc->param.framework_cb_max && cdsc->param.framework_suco_max > cdsc->param.framework_cb_max) { + av_log(NULL, AV_LOG_ERROR,"Maximun SUCO size cannot be greater than Maximum coding Block size\n"); + ret = -1; + } + if (cdsc->param.framework_suco_min < 4) { + av_log(NULL, AV_LOG_ERROR, "Minimun SUCO size cannot be smaller than 4\n"); + ret = -1; + } + if (cdsc->param.framework_cb_min && cdsc->param.framework_suco_min < cdsc->param.framework_cb_min) { + av_log(NULL, AV_LOG_ERROR,"Minimun SUCO size cannot be smaller than Minimum coding Block size\n"); + ret = -1; + } + if (cdsc->param.framework_suco_min > cdsc->param.framework_suco_max) { + av_log(NULL, AV_LOG_ERROR, "Minimum SUCO size cannot be greater than Maximum SUCO size\n"); + ret = -1; + } + } + + pic_m = (8 > min_block_size) ? min_block_size : 8; + if ((cdsc->param.w & (pic_m - 1)) != 0) { + av_log(NULL, AV_LOG_ERROR, "Current encoder does not support picture width, not multiple of max(8, minimum CU size)\n"); + ret = -1; + } + if ((cdsc->param.h & (pic_m - 1)) != 0) { + av_log(NULL, AV_LOG_ERROR, "Current encoder does not support picture height, not multiple of max(8, minimum CU size)\n"); + ret = -1; + } + + return ret; +} + +/** + * Set XEVE_CFG_SET_USE_PIC_SIGNATURE for encoder + * + * @param id XEVE instance identifier + * @param ctx the structure stores all the state associated with the instance of Xeve MPEG-5 EVC encoder + * @return XEVE pre-defined color space (@see xeve.h) on success, XEVE_CF_UNKNOWN on failure + * + * @todo consider removing the function + */ +static int set_extra_config(XEVE id, XeveContext *ctx) +{ + int ret, size, value; + + if(ctx->hash) { + value = 1; + size = 4; + ret = xeve_config(id, XEVE_CFG_SET_USE_PIC_SIGNATURE, &value, &size); + if(XEVE_FAILED(ret)) { + av_log(NULL, AV_LOG_ERROR, "failed to set config for picture signature\n"); + return -1; + } + } + + return 0; +} + +/** + * Convert ffmpeg pixel format (AVPixelFormat) into XEVE pre-defined color space + * + * @param px_fmt pixel format (@see https://ffmpeg.org/doxygen/trunk/pixfmt_8h.html#a9a8e335cf3be472042bc9f0cf80cd4c5) + * @return XEVE pre-defined color space (@see xeve.h) on success, XEVE_CF_UNKNOWN on failure + */ +static int xeve_color_space(enum AVPixelFormat pix_fmt) +{ + /* color space of input image */ + int cs = XEVE_CF_UNKNOWN; + + switch (pix_fmt) { + case AV_PIX_FMT_YUV420P: + cs = XEVE_CS_YCBCR420; + break; + case AV_PIX_FMT_YUV420P10: +#if AV_HAVE_BIGENDIAN + cs = XEVE_CS_SET(XEVE_CF_YCBCR420, 10, 1); +#else + cs = XEVE_CS_YCBCR420_10LE; +#endif + + break; + case AV_PIX_FMT_YUV420P12: +#if AV_HAVE_BIGENDIAN + cs = XEVE_CS_SET(XEVE_CF_YCBCR420, 12, 1); +#else + cs = XEVE_CS_YCBCR420_12LE; +#endif + + break; + case AV_PIX_FMT_YUV422P: + cs = XEVE_CS_YCBCR422; + break; + case AV_PIX_FMT_YUV422P10: +#if AV_HAVE_BIGENDIAN + cs = XEVE_CS_SET(XEVE_CF_YCBCR422, 10, 1); +#else + cs = XEVE_CS_YCBCR422_10LE; +#endif + + break; + case AV_PIX_FMT_YUV422P12: +#if AV_HAVE_BIGENDIAN + cs = XEVE_CS_SET(XEVE_CF_YCBCR422, 12, 1); +#else + cs = XEVE_CS_SET(XEVE_CF_YCBCR422, 12, 0); +#endif + + break; + case AV_PIX_FMT_GBRP: + case AV_PIX_FMT_GBRP10: + case AV_PIX_FMT_GBRP12: + cs = XEVE_CF_UNKNOWN; + break; + case AV_PIX_FMT_YUV444P: + cs = XEVE_CF_YCBCR444; + break; + case AV_PIX_FMT_YUV444P10: +#if AV_HAVE_BIGENDIAN + cs = XEVE_CS_SET(XEVE_CF_YCBCR444, 10, 1); +#else + cs = XEVE_CS_YCBCR444_10LE; +#endif + + break; + case AV_PIX_FMT_YUV444P12: +#if AV_HAVE_BIGENDIAN + cs = XEVE_CS_SET(XEVE_CF_YCBCR444, 12, 1); +#else + cs = XEVE_CS_SET(XEVE_CF_YCBCR444, 12, 0); +#endif + + break; + case AV_PIX_FMT_GRAY8: + cs = XEVE_CF_YCBCR400; + break; + case AV_PIX_FMT_GRAY10: +#if AV_HAVE_BIGENDIAN + cs = XEVE_CS_SET(XEVE_CF_YCBCR400, 10, 1); +#else + cs = XEVE_CS_YCBCR400_10LE; +#endif + + break; + case AV_PIX_FMT_GRAY12: +#if AV_HAVE_BIGENDIAN + cs = XEVE_CS_SET(XEVE_CF_YCBCR400, 12, 1); +#else + cs = XEVE_CS_YCBCR400_12LE; +#endif + + break; + default: + cs = XEVE_CF_UNKNOWN; + break; + } + return cs; +} + +static int setup_bumping(XEVE id) +{ + int val, size; + val = 1; + size = sizeof(int); + if(XEVE_FAILED(xeve_config(id, XEVE_CFG_SET_FORCE_OUT, (void *)(&val), &size))) { + return -1; + } + return 0; +} + +/// @todo provide implementation +/* in 100-nanosec unit */ +static XEVE_MTIME timestamp(int frame_idx, int fps) +{ + // return (frame_idx*10000000/fps); + return frame_idx; +} + +/** + * Initialize codec static data + * + * @todo consider removing unused function + */ +static av_cold void libxeve_init_static_data(AVCodec *codec) +{ + UNUSED(codec); +} + +/** + * Initialize codec + * Create encoder instance and allocate all the needed resources + * + * @param ctx codec context + * @return 0 on success, negative error code on failure + */ +static av_cold int libxeve_init(AVCodecContext *ctx) +{ + XeveContext *xe = ctx->priv_data; + unsigned char *bs_buf = NULL; + int i, val = 0; + int shift_h = 0; + int shift_v = 0; + XEVE_IMGB * imgb = NULL; + XEVE_PARAM * param = NULL; + + XEVE_CDSC *cdsc = &(xe->cdsc); + + av_log(NULL, AV_LOG_DEBUG, "eXtra-fast Essential Video Encoder\n"); + + if(ctx->pix_fmt != AV_PIX_FMT_YUV420P && ctx->pix_fmt != AV_PIX_FMT_YUV420P10) { + av_log(ctx, AV_LOG_ERROR, "Invalid pixel format: %s\n", av_get_pix_fmt_name(ctx->pix_fmt)); + goto ERR; + } + + /* allocate bitstream buffer */ + bs_buf = (unsigned char*)malloc(MAX_BS_BUF); + if(bs_buf == NULL) { + av_log(NULL, AV_LOG_ERROR, "cannot allocate bitstream buffer, size=%d", MAX_BS_BUF); + goto ERR; + } + + /* read configurations and set values for created descriptor (XEVE_CDSC) */ + val = get_conf(ctx, cdsc); + if (val != XEVE_OK) { + av_log(NULL, AV_LOG_ERROR,"cannot get configuration\n"); + goto ERR; + } + + if (check_conf(ctx, cdsc) != 0) { + av_log(NULL, AV_LOG_ERROR,"invalid configuration\n"); + goto ERR; + } + + /* create encoder */ + xe->id = xeve_create(cdsc, NULL); + if(xe->id == NULL) { + av_log(NULL, AV_LOG_ERROR, "cannot create XEVE encoder\n"); + goto ERR; + } + + if(set_extra_config(xe->id, xe)) { + av_log(NULL, AV_LOG_ERROR, "cannot set extra configurations\n"); + goto ERR; + } + + xe->bitb.addr = bs_buf; + xe->bitb.bsize = MAX_BS_BUF; + + if(av_pix_fmt_get_chroma_sub_sample(ctx->pix_fmt, &shift_h, &shift_v)) { + av_log(ctx, AV_LOG_ERROR, "failed to get chroma shift\n"); + goto ERR; + } + // YUV format explanation + // shift_h == 1 && shift_v == 1 : YUV420 + // shift_h == 1 && shift_v == 0 : YUV422 + // shift_h == 0 && shift_v == 0 : YUV444 + // + xe->width_chroma = AV_CEIL_RSHIFT(ctx->width, shift_h); + xe->height_chroma = AV_CEIL_RSHIFT(ctx->height, shift_v); + + /* set default values for input image buffer */ + imgb = &xe->imgb; + imgb->cs = xeve_color_space(ctx->pix_fmt); + imgb->np = 3; /* only for yuv420p, yuv420ple */ + for (i=0; inp; i++) { + imgb->x[i] = imgb->y[i] = 0; + } + imgb->w[0] = imgb->aw[0] = xe->width_luma; + imgb->w[1] = imgb->w[2] = imgb->aw[1]= imgb->aw[2] = xe->width_chroma; + imgb->h[0] = imgb->ah[0] = xe->height_luma; + imgb->h[1] = imgb->h[2] = imgb->ah[1] = imgb->ah[2] = xe->height_chroma; + + xe->encod_frames = 0; + xe->bytes_total = 0; + xe->state = STATE_ENCODING; + xe->packet_count = 0; + xe->bitrate = 0; + return 0; + +ERR: + if(bs_buf) free(bs_buf); + return -1; +} + +/** + * Encode data to an AVPacket. + * + * @param ctx codec context + * @param pkt output AVPacket + * @param[in] frame AVFrame containing the raw data to be encoded + * @param[out] got_packet encoder sets to 0 or 1 to indicate that a + * non-empty packet was returned in avpkt. + * @return 0 on success, negative error code on failure + */ +static int libxeve_encode(AVCodecContext *ctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + XeveContext *xe = NULL; + int ret = -1; + int xeve_cs; + + if(ctx == NULL || pkt == NULL || got_packet==NULL) { + av_log(ctx, AV_LOG_ERROR, "Invalid arguments\n"); + return -1; + } + xe = ctx->priv_data; + if(xe == NULL) { + av_log(ctx, AV_LOG_ERROR, "Invalid XEVE context\n"); + return -1; + } + + if(xe->state == STATE_SKIPPING) { + xe->state = STATE_ENCODING; + } else if(xe->state == STATE_ENCODING) { + if(frame) { + const AVPixFmtDescriptor *pixel_fmt_desc = av_pix_fmt_desc_get (frame->format); + if(!pixel_fmt_desc) { + av_log(NULL, AV_LOG_ERROR, "Invalid pixel format descriptor for pixel format: %s\n", av_get_pix_fmt_name(ctx->pix_fmt)); + return -1; + } + + xeve_cs = xeve_color_space(ctx->pix_fmt); + if(xeve_cs != XEVE_CS_YCBCR420 && xeve_cs != XEVE_CS_YCBCR420_10LE) { + av_log(ctx, AV_LOG_ERROR, "Invalid pixel format: %s\n", av_get_pix_fmt_name(ctx->pix_fmt)); + return -1; + } + + { + int i; + XEVE_IMGB * imgb = NULL; + XEVE_MTIME ts; + + int xeve_byte_depth = 0; + + imgb = &xe->imgb; + + xeve_byte_depth = XEVE_CS_GET_BYTE_DEPTH(xeve_cs); + av_log(ctx, AV_LOG_DEBUG, "byte depth: %d\n",xeve_byte_depth); + + for (i=0; inp; i++) { + imgb->a[i] = frame->data[i]; + imgb->s[i] = frame->linesize[i]; + } + + if(xe->id == NULL) { + av_log(ctx, AV_LOG_ERROR, "Invalid XEVE encoder\n"); + return -1; + } + + ts = timestamp(xe->encod_frames, xe->cdsc.param.fps); + imgb->ts[0] = ts; + imgb->ts[1] = ts; + imgb->ts[2] = ts; + imgb->ts[3] = ts; + + /* push image to encoder */ + ret = xeve_push(xe->id, imgb); + if(XEVE_FAILED(ret)) { + av_log(ctx, AV_LOG_ERROR, "xeve_push() failed\n"); + return -1; + } + + /* encoding */ + ret = xeve_encode(xe->id, &(xe->bitb), &(xe->stat)); + if(XEVE_FAILED(ret)) { + av_log(ctx, AV_LOG_ERROR, "xeve_encode() failed\n"); + return -1; + } + + xe->encod_frames++; + + /* store bitstream */ + if (ret == XEVE_OK_OUT_NOT_AVAILABLE) { + av_log(ctx, AV_LOG_DEBUG, "RETURN OK BUT PICTURE IS NOT AVAILABLE YET (%d) frame: %d\n", ret, xe->encod_frames); + *got_packet = 0; + return 0; + } else if(ret == XEVE_OK) { + int pic_type; + + if(xe->stat.write > 0) { + xe->bytes_total+=xe->stat.write; + av_log(ctx, AV_LOG_DEBUG, "frame: %d | Bytes written: %d | bytes total: %f | %lld | %lld | %lld | %lld |\n", xe->encod_frames, xe->stat.write, xe->bytes_total, xe->bitb.ts[0],xe->bitb.ts[1],xe->bitb.ts[2],xe->bitb.ts[3]); + + ret = av_grow_packet(pkt, xe->stat.write); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Can't allocate memory for AVPacket data\n"); + return ret; + } + + memcpy(pkt->data, xe->bitb.addr, xe->stat.write); + + // @todo consider using ctx->bitb.ts[0] instead of ctx->packet_count i.e pkt->dts = pkt->pts = ctx->packet_count ctx->bitb.ts[0]; + // However keep in mind that it causes ffmpeg warning: Application provided invalid, non monotonically increasing dts to muxer in stream 0 + // + pkt->dts = pkt->pts = xe->packet_count; + + xe->bitrate += (xe->stat.write - xe->stat.sei_size); + + switch(xe->stat.stype) { + case XEVE_ST_I: + pic_type = AV_PICTURE_TYPE_I; + pkt->flags |= AV_PKT_FLAG_KEY; + break; + case XEVE_ST_P: + pic_type = AV_PICTURE_TYPE_P; + break; + case XEVE_ST_B: + pic_type = AV_PICTURE_TYPE_B; + break; + case XEVE_ST_UNKNOWN: + av_log(NULL, AV_LOG_ERROR, "unknown slice type\n"); + return -1; + } + ff_side_data_set_encoder_stats(pkt, xe->stat.qp*FF_QP2LAMBDA, NULL, 0, pic_type); + + *got_packet = 1; + xe->packet_count++; + } + } else if (ret == XEVE_OK_NO_MORE_FRM) { + av_log(ctx, AV_LOG_ERROR, "Return OK but no more frames (%d)\n", ret); + return 0; + } else { + av_log(ctx, AV_LOG_DEBUG, "invalid return value (%d)\n", ret); + return -1; + } + } + } else { + if(xe->state==STATE_ENCODING) { + av_log(ctx, AV_LOG_DEBUG, "Empty frame -> Entering bumping process...\n"); + if (setup_bumping(xe->id)) { + av_log(ctx, AV_LOG_ERROR,"failed to setup bumping\n"); + } else { + xe->state = STATE_BUMPING; + } + } + } + } else if(xe->state == STATE_BUMPING) { + /* encoding */ + ret = xeve_encode(xe->id, &(xe->bitb), &(xe->stat)); + if(XEVE_FAILED(ret)) { + av_log(ctx, AV_LOG_ERROR, "xeve_encode() failed\n"); + return -1; + } + + /* store bitstream */ + if (ret == XEVE_OK_OUT_NOT_AVAILABLE) { + av_log(ctx, AV_LOG_DEBUG, "RETURN OK BUT PICTURE IS NOT AVAILABLE YET (%d) frame: %d\n", ret, xe->encod_frames); + *got_packet = 0; + return 0; + } else if(ret == XEVE_OK) { + if(xe->stat.write > 0) { + xe->bytes_total+=xe->stat.write; + av_log(ctx, AV_LOG_DEBUG, "frame: %d | Bytes written: %d | bytes total: %f | %lld | %lld | %lld | %lld |\n", xe->encod_frames, xe->stat.write, xe->bytes_total, xe->bitb.ts[0],xe->bitb.ts[1],xe->bitb.ts[2],xe->bitb.ts[3]); + ret = av_grow_packet(pkt, xe->stat.write); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Can't allocate memory for AVPacket data\n"); + return ret; + } + + memcpy(pkt->data, xe->bitb.addr, xe->stat.write); + + // @todo consider using ctx->bitb.ts[0] instead of ctx->packet_count i.e pkt->dts = pkt->pts = ctx->packet_count ctx->bitb.ts[0]; + // However keep in mind that it causes ffmpeg warning: Application provided invalid, non monotonically increasing dts to muxer in stream 0 + // + pkt->dts = pkt->pts = xe->packet_count; + + + xe->bitrate += (xe->stat.write - xe->stat.sei_size); + + *got_packet = 1; + xe->packet_count++; + return 0; + } + } else if (ret == XEVE_OK_NO_MORE_FRM) { + av_log(ctx, AV_LOG_DEBUG, "Return OK but no more frames (%d)\n", ret); + return 0; + } else { + av_log(ctx, AV_LOG_ERROR, "invalid return value (%d)\n", ret); + return -1; + } + } else { + av_log(NULL, AV_LOG_ERROR, "Udefined state: %d\n", xe->state); + return -1; + } + return 0; +} + +/** + * Destroy encoder and release all the allocated resources + * + * @param ctx codec context + * @return 0 on success, negative error code on failure + */ +static av_cold int libxeve_close(AVCodecContext *ctx) +{ + XeveContext *xe = ctx->priv_data; + + xeve_delete(xe->id); + + if(xe->bitb.addr) free(xe->bitb.addr); /* release bitstream buffer */ + + return 0; +} + +#define OFFSET(x) offsetof(XeveContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM + +// Example of using: ./ffmpeg -xeve-params "m=2:q=17" +// Consider using following options (./ffmpeg --help encoder=libxeve) +// +static const AVOption xeve_options[] = { + { "preset", "Encoding preset for setting encoding speed [fast, medium, slow, placebo]", OFFSET(op_preset), AV_OPT_TYPE_STRING, { .str = "medium" }, 0, 0, VE }, + { "tune", "Tuneing parameter for special purpose operation [psnr, zerolatency]", OFFSET(op_tune), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE}, + { "qp", "quantization parameter qp <0..51> [default: 32]", OFFSET(op_qp), AV_OPT_TYPE_INT, { .i64 = 32 }, 0, 51, VE }, + { "crf", "constant rate factor <-1..51> [default: 32]", OFFSET(op_crf), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "xeve-params", "override the xeve configuration using a :-separated list of key=value parameters", OFFSET(xeve_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, + { NULL } +}; + +static const AVClass xeve_class = { + .class_name = "libxeve", + .item_name = av_default_item_name, + .option = xeve_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +/** + * libavcodec generic global options, which can be set on all the encoders and decoders + * @see https://www.ffmpeg.org/ffmpeg-codecs.html#Codec-Options + */ +static const AVCodecDefault xeve_defaults[] = { + { "b", "0" }, // bitrate + { "g", "0" }, // gop_size (key-frame interval 0: only one I-frame at the first time; 1: every frame is coded in I-frame) + { "bf", "15"}, // bframes (0: no B-frames) + { "profile", "0"}, // encoder codec profile (0: baselie; 1: main) + { "threads", "0"}, // number of threads to be used (0: automatically select the number of threads to set) + { NULL }, +}; + +AVCodec ff_libxeve_encoder = { + .name = "libxeve", + .long_name = NULL_IF_CONFIG_SMALL("libxeve MPEG-5 EVC"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_EVC, + .init = libxeve_init, + .init_static_data = libxeve_init_static_data, + .encode2 = libxeve_encode, + .close = libxeve_close, + .priv_data_size = sizeof(XeveContext), + .priv_class = &xeve_class, + .defaults = xeve_defaults, + .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS | + AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + .wrapper_name = "libxeve", +}; diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index 6b40c18d80..295fa33f52 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -73,6 +73,7 @@ extern const AVCodecParser ff_vp9_parser; extern const AVCodecParser ff_webp_parser; extern const AVCodecParser ff_xbm_parser; extern const AVCodecParser ff_xma_parser; +extern const AVCodecParser ff_evc_parser; #include "libavcodec/parser_list.c" diff --git a/libavcodec/profiles.c b/libavcodec/profiles.c index 7af7fbeb13..a31244e0db 100644 --- a/libavcodec/profiles.c +++ b/libavcodec/profiles.c @@ -181,4 +181,10 @@ const AVProfile ff_arib_caption_profiles[] = { { FF_PROFILE_UNKNOWN } }; +const AVProfile ff_evc_profiles[] = { + { FF_PROFILE_EVC_BASELINE, "Baseline" }, + { FF_PROFILE_EVC_MAIN, "Main" }, + { FF_PROFILE_UNKNOWN }, +}; + #endif /* !CONFIG_SMALL */ diff --git a/libavcodec/profiles.h b/libavcodec/profiles.h index 41a19aa9ad..cf92b5f126 100644 --- a/libavcodec/profiles.h +++ b/libavcodec/profiles.h @@ -72,5 +72,6 @@ extern const AVProfile ff_sbc_profiles[]; extern const AVProfile ff_prores_profiles[]; extern const AVProfile ff_mjpeg_profiles[]; extern const AVProfile ff_arib_caption_profiles[]; +extern const AVProfile ff_evc_profiles[]; #endif /* AVCODEC_PROFILES_H */ diff --git a/libavcodec/version.h b/libavcodec/version.h index 4d77431842..fb1a0feec6 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 59 -#define LIBAVCODEC_VERSION_MINOR 18 +#define LIBAVCODEC_VERSION_MINOR 19 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavformat/Makefile b/libavformat/Makefile index 84e73e3c63..db461e79b7 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -241,6 +241,8 @@ OBJS-$(CONFIG_HCOM_DEMUXER) += hcom.o pcm.o OBJS-$(CONFIG_HDS_MUXER) += hdsenc.o OBJS-$(CONFIG_HEVC_DEMUXER) += hevcdec.o rawdec.o OBJS-$(CONFIG_HEVC_MUXER) += rawenc.o +OBJS-$(CONFIG_EVC_DEMUXER) += evcdec.o rawdec.o +OBJS-$(CONFIG_EVC_MUXER) += rawenc.o OBJS-$(CONFIG_HLS_DEMUXER) += hls.o hls_sample_encryption.o OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o hlsplaylist.o avc.o OBJS-$(CONFIG_HNM_DEMUXER) += hnm.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index d066a7745b..1148024e71 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -145,6 +145,8 @@ extern const AVInputFormat ff_ea_cdata_demuxer; extern const AVInputFormat ff_eac3_demuxer; extern const AVOutputFormat ff_eac3_muxer; extern const AVInputFormat ff_epaf_demuxer; +extern const AVInputFormat ff_evc_demuxer; +extern const AVOutputFormat ff_evc_muxer; extern const AVOutputFormat ff_f4v_muxer; extern const AVInputFormat ff_ffmetadata_demuxer; extern const AVOutputFormat ff_ffmetadata_muxer; diff --git a/libavformat/evcdec.c b/libavformat/evcdec.c new file mode 100644 index 0000000000..d8e80514ff --- /dev/null +++ b/libavformat/evcdec.c @@ -0,0 +1,125 @@ +/* + * RAW EVC video demuxer + * + * Copyright (c) 2021 Dawid Kozinski + * + * 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 "libavcodec/get_bits.h" +#include "libavcodec/golomb.h" +#include "avformat.h" +#include "rawdec.h" +#include "libavcodec/internal.h" + +#define EVC_NAL_UNIT_LENGTH_BYTE (4) +#define EVC_NUT_NONIDR (0) +#define EVC_NUT_IDR (1) +#define EVC_NUT_SPS (24) +#define EVC_NUT_PPS (25) +#define EVC_NUT_APS (26) +#define EVC_NUT_FD (27) +#define EVC_NUT_SEI (28) + + +typedef struct EVCParserContext { + int got_sps; + int got_pps; + int got_idr; + int got_nonidr; +} EVCParserContext; + +static int get_nalu_type(const uint8_t *bs, int bs_size) +{ + GetBitContext gb; + int fzb, nut; + init_get_bits(&gb, bs, bs_size * 8); + fzb = get_bits1(&gb); + if(fzb != 0) { + av_log(NULL, AV_LOG_DEBUG, "forbidden_zero_bit is not clear\n"); + } + nut = get_bits(&gb, 6); /* nal_unit_type_plus1 */ + return nut - 1; +} + +static size_t read_nal_unit_size(const unsigned char *bs, int bs_size) +{ + size_t nal_unit_size = 0; + memcpy(&nal_unit_size, bs, EVC_NAL_UNIT_LENGTH_BYTE); + + return nal_unit_size; +} + +static int parse_nal_units(const AVProbeData *p, EVCParserContext *ev) +{ + int nalu_type; + size_t nalu_size; + unsigned char* bits = (unsigned char *)p->buf; + int bytes_to_read = p->buf_size; + + av_log(NULL, AV_LOG_DEBUG, "bytes_to_read: %d \n", bytes_to_read); + + while(bytes_to_read > EVC_NAL_UNIT_LENGTH_BYTE) { + + nalu_size = read_nal_unit_size(bits, p->buf_size); + + bits += EVC_NAL_UNIT_LENGTH_BYTE; + bytes_to_read -= EVC_NAL_UNIT_LENGTH_BYTE; + + av_log(NULL, AV_LOG_DEBUG, "nalu_size: %ld \n", nalu_size); + + if(bytes_to_read < nalu_size) break; + + nalu_type = get_nalu_type(bits, bytes_to_read); + + bits += nalu_size; + bytes_to_read -= nalu_size; + + if (nalu_type == EVC_NUT_SPS) { + av_log(NULL, AV_LOG_DEBUG, "EVC_NUT_SPS \n"); + ev->got_sps++; + } + else if (nalu_type == EVC_NUT_PPS) { + av_log(NULL, AV_LOG_DEBUG, "EVC_NUT_PPS \n"); + ev->got_pps++; + } + else if (nalu_type == EVC_NUT_IDR ) { + av_log(NULL, AV_LOG_DEBUG, "EVC_NUT_IDR\n"); + ev->got_idr++; + } + else if (nalu_type == EVC_NUT_NONIDR) { + av_log(NULL, AV_LOG_DEBUG, "EVC_NUT_NONIDR\n"); + ev->got_nonidr++; + } + } + return 0; +} + +static int evc_probe(const AVProbeData *p) +{ + EVCParserContext ev = {}; + int ret = parse_nal_units(p, &ev); + + av_log(NULL, AV_LOG_DEBUG, "sps:%d pps:%d idr:%d sli:%d\n", ev.got_sps, ev.got_pps, ev.got_idr, ev.got_nonidr); + + if (ret == 0 && ev.got_sps && ev.got_pps && (ev.got_idr || ev.got_nonidr > 3)) + return AVPROBE_SCORE_EXTENSION + 1; // 1 more than .mpg + + return 0; +} + +FF_DEF_RAWVIDEO_DEMUXER(evc, "raw EVC video", evc_probe, "evc", AV_CODEC_ID_EVC) diff --git a/libavformat/isom_tags.c b/libavformat/isom_tags.c index 62e60470a8..0245cfb999 100644 --- a/libavformat/isom_tags.c +++ b/libavformat/isom_tags.c @@ -145,6 +145,8 @@ const AVCodecTag ff_codec_movvideo_tags[] = { { AV_CODEC_ID_H264, MKTAG('d', 'v', 'a', '1') }, /* AVC-based Dolby Vision derived from avc1 */ { AV_CODEC_ID_H264, MKTAG('d', 'v', 'a', 'v') }, /* AVC-based Dolby Vision derived from avc3 */ + { AV_CODEC_ID_EVC, MKTAG('e', 'v', 'c', '1') }, /* EVC/MPEG-5 */ + { AV_CODEC_ID_VP8, MKTAG('v', 'p', '0', '8') }, /* VP8 */ { AV_CODEC_ID_VP9, MKTAG('v', 'p', '0', '9') }, /* VP9 */ { AV_CODEC_ID_AV1, MKTAG('a', 'v', '0', '1') }, /* AV1 */ diff --git a/libavformat/mov.c b/libavformat/mov.c index e401cd39b5..a86919e61a 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -8562,7 +8562,7 @@ const AVInputFormat ff_mov_demuxer = { .long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"), .priv_class = &mov_class, .priv_data_size = sizeof(MOVContext), - .extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v", + .extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v,evc", .flags_internal = FF_FMT_INIT_CLEANUP, .read_probe = mov_probe, .read_header = mov_read_header, diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 4c868919ae..30e5037f06 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -1342,6 +1342,16 @@ static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track) return update_size(pb, pos); } +static int mov_write_evcc_tag(AVIOContext *pb, MOVTrack *track) +{ + int64_t pos = avio_tell(pb); + + avio_wb32(pb, 0); + ffio_wfourcc(pb, "evcC"); + ff_isom_write_avcc(pb, track->vos_data, track->vos_len); + return update_size(pb, pos); +} + /* also used by all avid codecs (dv, imx, meridien) and their variants */ static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track) { @@ -1591,6 +1601,19 @@ static int mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track) return tag; } +static int mov_get_evc_codec_tag(AVFormatContext *s, MOVTrack *track) +{ + int tag = track->par->codec_tag; + int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE; + AVStream *st = track->st; + int rate = defined_frame_rate(s, st); + + if (!tag) + tag = MKTAG('e', 'v', 'c', 'i'); //fallback tag + + return tag; +} + static const struct { enum AVPixelFormat pix_fmt; uint32_t tag; @@ -1672,6 +1695,8 @@ static unsigned int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track) tag = mov_get_mpeg2_xdcam_codec_tag(s, track); else if (track->par->codec_id == AV_CODEC_ID_H264) tag = mov_get_h264_codec_tag(s, track); + else if (track->par->codec_id == AV_CODEC_ID_EVC) + tag = mov_get_evc_codec_tag(s, track); else if (track->par->codec_id == AV_CODEC_ID_DNXHD) tag = mov_get_dnxhd_codec_tag(s, track); else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { @@ -2208,6 +2233,9 @@ static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex mov_write_avcc_tag(pb, track); if (track->mode == MODE_IPOD) mov_write_uuid_tag_ipod(pb); + } + else if (track->par->codec_id ==AV_CODEC_ID_EVC) { + mov_write_evcc_tag(pb, track); } else if (track->par->codec_id == AV_CODEC_ID_VP9) { mov_write_vpcc_tag(mov->fc, pb, track); } else if (track->par->codec_id == AV_CODEC_ID_AV1) { @@ -5737,6 +5765,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) if ((par->codec_id == AV_CODEC_ID_DNXHD || par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_HEVC || + par->codec_id == AV_CODEC_ID_EVC || par->codec_id == AV_CODEC_ID_TRUEHD || par->codec_id == AV_CODEC_ID_AC3) && !trk->vos_len && !TAG_IS_AVCI(trk->tag)) { @@ -7311,6 +7340,7 @@ static const AVCodecTag codec_mp4_tags[] = { { AV_CODEC_ID_H264, MKTAG('a', 'v', 'c', '3') }, { AV_CODEC_ID_HEVC, MKTAG('h', 'e', 'v', '1') }, { AV_CODEC_ID_HEVC, MKTAG('h', 'v', 'c', '1') }, + { AV_CODEC_ID_EVC, MKTAG('e', 'v', 'c', '1') }, { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', '4', 'v') }, { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', '4', 'v') }, { AV_CODEC_ID_MJPEG, MKTAG('m', 'p', '4', 'v') }, diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index 4bbae7717b..322ab583ab 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -386,6 +386,20 @@ const AVOutputFormat ff_hevc_muxer = { }; #endif +#if CONFIG_EVC_MUXER +AVOutputFormat ff_evc_muxer = { + .name = "evc", + .long_name = NULL_IF_CONFIG_SMALL("raw EVC video"), + .extensions = "evc", + .audio_codec = AV_CODEC_ID_NONE, + .video_codec = AV_CODEC_ID_EVC, + .write_header = force_one_stream, + .write_packet = ff_raw_write_packet, + .flags = AVFMT_NOTIMESTAMPS, +}; +#endif + + #if CONFIG_M4V_MUXER const AVOutputFormat ff_m4v_muxer = { .name = "m4v", diff --git a/tests/Makefile b/tests/Makefile index 87807ed31f..eb265657b9 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -197,6 +197,7 @@ include $(SRC_PATH)/tests/fate/vqf.mak include $(SRC_PATH)/tests/fate/wavpack.mak include $(SRC_PATH)/tests/fate/wma.mak include $(SRC_PATH)/tests/fate/xvid.mak +include $(SRC_PATH)/tests/fate/evc.mak FATE_FFMPEG += $(FATE_FFMPEG-yes) $(FATE_AVCONV) $(FATE_AVCONV-yes) FATE-$(CONFIG_FFMPEG) += $(FATE_FFMPEG) diff --git a/tests/fate/evc.mak b/tests/fate/evc.mak new file mode 100644 index 0000000000..26179e5e1e --- /dev/null +++ b/tests/fate/evc.mak @@ -0,0 +1,37 @@ +FATE_EVC-$(call DEMDEC, EVC) += fate-evc + +fate-evc: CODEC = libxeve +fate-evc: SRC = $(TARGET_SAMPLES)/evc/Test_Video_cif.yuv +fate-evc: FMT = evc +fate-evc: RAWDECOPTS = -r 30 +fate-evc: CMD = enc_dec \ + "rawvideo -s 352x288 -pix_fmt yuv420p $(RAWDECOPTS)" \ + $(SRC) \ + $(FMT) \ + "-c:v $(CODEC) $(ENCOPTS)" \ + rawvideo \ + "-s 352x288 -pix_fmt yuv420p -vsync passthrough $(DECOPTS)" \ + "$(KEEP_OVERRIDE)" \ + "$(DECINOPTS)" + +fate-evc: CMP = oneoff +fate-evc: CMP_UNIT = f32 +fate-evc: FUZZ = 18 + + +FATE_EVC-$(call DEMDEC, EVC) += fate-evc-mp4 + +fate-evc-mp4: CODEC = libxeve +fate-evc-mp4: SRC = $(TARGET_SAMPLES)/evc/Test_Video_cif.mp4 +fate-evc-mp4: FMT = mp4 +fate-evc-mp4: RAWDECOPTS = -r 30 +fate-evc-mp4: CMD = transcode mp4 $(SRC) \ + mp4 "-c:a copy -c:v libxeve" "-af aresample" + +fate-evc-mp4: CMP = oneoff +fate-evc-mp4: CMP_UNIT = f32 +fate-evc-mp4: FUZZ = 18 + +FATE_EVC += $(FATE_EVC-yes) +FATE_SAMPLES_FFMPEG += $(FATE_EVC) + diff --git a/tests/ref/fate/evc b/tests/ref/fate/evc new file mode 100644 index 0000000000..044a089cb6 --- /dev/null +++ b/tests/ref/fate/evc @@ -0,0 +1,4 @@ +f385865d5f08245e0715fdb41dbce7c6 *tests/data/fate/evc.evc +21310 tests/data/fate/evc.evc +2eb3e1a88b12964b30012ec5c0ccb1bc *tests/data/fate/evc.out.rawvideo +stddev: nan PSNR: nan MAXDIFF: 0 bytes: 91238400/ 87284736 diff --git a/tests/ref/fate/evc-mp4 b/tests/ref/fate/evc-mp4 new file mode 100644 index 0000000000..40c397b00b --- /dev/null +++ b/tests/ref/fate/evc-mp4 @@ -0,0 +1,1762 @@ +7374f514663ee1074e2ae4f884de2121 *tests/data/fate/evc-mp4.mp4 +554534 tests/data/fate/evc-mp4.mp4 +#tb 0: 1/24 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 1/1 +#tb 1: 1/48000 +#media_type 1: audio +#codec_id 1: pcm_s16le +#sample_rate 1: 48000 +#channel_layout 1: 3 +#channel_layout_name 1: stereo +0, 0, 0, 1, 304128, 0x3e5091dc +1, 0, 0, 1024, 4096, 0x3deea486 +1, 1024, 1024, 1024, 4096, 0xa062dac3 +1, 2048, 2048, 1024, 4096, 0xe5542eae +1, 3072, 3072, 1024, 4096, 0x903e2614 +1, 4096, 4096, 1024, 4096, 0x1bc62b44 +1, 5120, 5120, 1024, 4096, 0x459510ca +1, 6144, 6144, 1024, 4096, 0x660cc18b +1, 7168, 7168, 1024, 4096, 0xcb55c135 +1, 8192, 8192, 1024, 4096, 0x64d7c27b +1, 9216, 9216, 1024, 4096, 0x67560066 +1, 10240, 10240, 1024, 4096, 0x33662418 +1, 11264, 11264, 1024, 4096, 0x91c0282a +1, 12288, 12288, 1024, 4096, 0x8c553f2c +1, 13312, 13312, 1024, 4096, 0x17a5d67d +1, 14336, 14336, 1024, 4096, 0x751ebeb5 +1, 15360, 15360, 1024, 4096, 0x2629c769 +1, 16384, 16384, 1024, 4096, 0x86b0c54f +1, 17408, 17408, 1024, 4096, 0xd3e73e1e +0, 9, 9, 1, 304128, 0x3e5091dc +1, 18432, 18432, 1024, 4096, 0xe21421cc +1, 19456, 19456, 1024, 4096, 0x3c9732e4 +0, 10, 10, 1, 304128, 0x3e5091dc +1, 20480, 20480, 1024, 4096, 0x77fb10ec +1, 21504, 21504, 1024, 4096, 0x8edcc249 +0, 11, 11, 1, 304128, 0x3e5091dc +1, 22528, 22528, 1024, 4096, 0x578bc8b3 +1, 23552, 23552, 1024, 4096, 0x410fc077 +0, 12, 12, 1, 304128, 0x3e5091dc +1, 24576, 24576, 1024, 4096, 0xf859fea7 +1, 25600, 25600, 1024, 4096, 0xafd02764 +0, 13, 13, 1, 304128, 0x3e5091dc +1, 26624, 26624, 1024, 4096, 0x2cc627f6 +1, 27648, 27648, 1024, 4096, 0x3478413a +0, 14, 14, 1, 304128, 0x3e5091dc +1, 28672, 28672, 1024, 4096, 0xe930d705 +1, 29696, 29696, 1024, 4096, 0x1ec6b5d1 +0, 15, 15, 1, 304128, 0x3e5091dc +1, 30720, 30720, 1024, 4096, 0x2a56c515 +1, 31744, 31744, 1024, 4096, 0xc1d8b7cb +0, 16, 16, 1, 304128, 0x3e5091dc +1, 32768, 32768, 1024, 4096, 0xcd7932b8 +1, 33792, 33792, 1024, 4096, 0x196b2866 +0, 17, 17, 1, 304128, 0x3e5091dc +1, 34816, 34816, 1024, 4096, 0xd78632e2 +1, 35840, 35840, 1024, 4096, 0xf3460cf8 +0, 18, 18, 1, 304128, 0x3e5091dc +1, 36864, 36864, 1024, 4096, 0x8889c52d +1, 37888, 37888, 1024, 4096, 0x0fd3c5e9 +0, 19, 19, 1, 304128, 0x3e5091dc +1, 38912, 38912, 1024, 4096, 0x2c84d84f +1, 39936, 39936, 1024, 4096, 0xdadc09ea +0, 20, 20, 1, 304128, 0x3e5091dc +1, 40960, 40960, 1024, 4096, 0xe90e2c70 +1, 41984, 41984, 1024, 4096, 0xd6da296e +0, 21, 21, 1, 304128, 0x90fe64bf +1, 43008, 43008, 1024, 4096, 0x39e838be +0, 22, 22, 1, 304128, 0xdbd9ece9 +1, 44032, 44032, 1024, 4096, 0x02dcd7b3 +1, 45056, 45056, 1024, 4096, 0xb1e7b829 +0, 23, 23, 1, 304128, 0x2798fa32 +1, 46080, 46080, 1024, 4096, 0x3e98c425 +1, 47104, 47104, 1024, 4096, 0x5c4dbd59 +0, 24, 24, 1, 304128, 0x06215e8f +1, 48128, 48128, 1024, 4096, 0x19ad3220 +1, 49152, 49152, 1024, 4096, 0x81392ad8 +0, 25, 25, 1, 304128, 0x3e4a13c6 +1, 50176, 50176, 1024, 4096, 0x4abe32be +1, 51200, 51200, 1024, 4096, 0x2a5412ea +0, 26, 26, 1, 304128, 0x84efdcee +1, 52224, 52224, 1024, 4096, 0x507ec433 +1, 53248, 53248, 1024, 4096, 0x60ecc4d5 +0, 27, 27, 1, 304128, 0x030aaf7f +1, 54272, 54272, 1024, 4096, 0x8d58b645 +1, 55296, 55296, 1024, 4096, 0xabe9fbff +0, 28, 28, 1, 304128, 0x0268af64 +1, 56320, 56320, 1024, 4096, 0x817e24bc +1, 57344, 57344, 1024, 4096, 0xbc1e2950 +0, 29, 29, 1, 304128, 0x4e74ae45 +1, 58368, 58368, 1024, 4096, 0x49a734ca +1, 59392, 59392, 1024, 4096, 0xe189dc53 +0, 30, 30, 1, 304128, 0x5146ae64 +1, 60416, 60416, 1024, 4096, 0xc024d077 +1, 61440, 61440, 1024, 4096, 0x0facc99f +0, 31, 31, 1, 304128, 0x59a3ae50 +1, 62464, 62464, 1024, 4096, 0xea1bbc1f +1, 63488, 63488, 1024, 4096, 0xb5d33282 +0, 32, 32, 1, 304128, 0xb6abae77 +1, 64512, 64512, 1024, 4096, 0x2a5c20be +1, 65536, 65536, 1024, 4096, 0xd150324a +0, 33, 33, 1, 304128, 0xd06eae5b +1, 66560, 66560, 1024, 4096, 0xd1821328 +1, 67584, 67584, 1024, 4096, 0x964bc131 +0, 34, 34, 1, 304128, 0x6373af5f +1, 68608, 68608, 1024, 4096, 0x60aac5e3 +1, 69632, 69632, 1024, 4096, 0x27c0c0ff +0, 35, 35, 1, 304128, 0xe911b039 +1, 70656, 70656, 1024, 4096, 0x3f41f0f1 +1, 71680, 71680, 1024, 4096, 0xee1524e4 +0, 36, 36, 1, 304128, 0x63a1ac5a +1, 72704, 72704, 1024, 4096, 0x9b572976 +1, 73728, 73728, 1024, 4096, 0x5fff328a +0, 37, 37, 1, 304128, 0xfb74ac54 +1, 74752, 74752, 1024, 4096, 0x2323d935 +1, 75776, 75776, 1024, 4096, 0x5317c501 +0, 38, 38, 1, 304128, 0xf63fa848 +1, 76800, 76800, 1024, 4096, 0xb796cb91 +1, 77824, 77824, 1024, 4096, 0x1f42bed3 +0, 39, 39, 1, 304128, 0x7da1a81c +1, 78848, 78848, 1024, 4096, 0x763a271e +1, 79872, 79872, 1024, 4096, 0xf7912d0a +0, 40, 40, 1, 304128, 0x88a6a449 +1, 80896, 80896, 1024, 4096, 0x79fe2d5c +1, 81920, 81920, 1024, 4096, 0xdc730228 +0, 41, 41, 1, 304128, 0x0727a628 +1, 82944, 82944, 1024, 4096, 0xc89bb8ef +1, 83968, 83968, 1024, 4096, 0x848bba81 +0, 42, 42, 1, 304128, 0x51caa636 +1, 84992, 84992, 1024, 4096, 0xed61bf3b +0, 43, 43, 1, 304128, 0x47c9ab0a +1, 86016, 86016, 1024, 4096, 0x6b97ece1 +1, 87040, 87040, 1024, 4096, 0xd1c024da +0, 44, 44, 1, 304128, 0x7402ab3f +1, 88064, 88064, 1024, 4096, 0x72f02946 +1, 89088, 89088, 1024, 4096, 0x073434f6 +0, 45, 45, 1, 304128, 0x74d6af0d +1, 90112, 90112, 1024, 4096, 0x1991e15f +1, 91136, 91136, 1024, 4096, 0x38b9b317 +0, 46, 46, 1, 304128, 0x4dd4ae33 +1, 92160, 92160, 1024, 4096, 0x2149d559 +1, 93184, 93184, 1024, 4096, 0x8beab29d +0, 47, 47, 1, 304128, 0xce6dae24 +1, 94208, 94208, 1024, 4096, 0xbe363bc8 +1, 95232, 95232, 1024, 4096, 0x29be2394 +0, 48, 48, 1, 304128, 0x43ceaf5a +1, 96256, 96256, 1024, 4096, 0x12a7303c +1, 97280, 97280, 1024, 4096, 0xdd071522 +0, 49, 49, 1, 304128, 0x4082af1c +1, 98304, 98304, 1024, 4096, 0x05d0ca11 +1, 99328, 99328, 1024, 4096, 0x849cc5b9 +0, 50, 50, 1, 304128, 0xea4fe28c +1, 100352, 100352, 1024, 4096, 0xfe48c5e1 +1, 101376, 101376, 1024, 4096, 0xaae20744 +0, 51, 51, 1, 304128, 0x1f4b6df2 +1, 102400, 102400, 1024, 4096, 0xc73f3dbc +1, 103424, 103424, 1024, 4096, 0x563d2b60 +0, 52, 52, 1, 304128, 0x639cc557 +1, 104448, 104448, 1024, 4096, 0x10c332ee +1, 105472, 105472, 1024, 4096, 0xd023d96f +0, 53, 53, 1, 304128, 0x88a5bcef +1, 106496, 106496, 1024, 4096, 0xd346bbcd +1, 107520, 107520, 1024, 4096, 0xf970d06d +0, 54, 54, 1, 304128, 0x20f7d4ce +1, 108544, 108544, 1024, 4096, 0x0597b131 +1, 109568, 109568, 1024, 4096, 0x093039f0 +0, 55, 55, 1, 304128, 0x9343de47 +1, 110592, 110592, 1024, 4096, 0x82aa2560 +1, 111616, 111616, 1024, 4096, 0x40b32dfa +0, 56, 56, 1, 304128, 0xc43d4b9d +1, 112640, 112640, 1024, 4096, 0x1dd7117a +1, 113664, 113664, 1024, 4096, 0x2a16b231 +0, 57, 57, 1, 304128, 0xdb3e233b +1, 114688, 114688, 1024, 4096, 0xea19c729 +1, 115712, 115712, 1024, 4096, 0x5f3dc3f1 +0, 58, 58, 1, 304128, 0x77756d4d +1, 116736, 116736, 1024, 4096, 0x6744f33b +1, 117760, 117760, 1024, 4096, 0x56151cd4 +0, 59, 59, 1, 304128, 0x827ac201 +1, 118784, 118784, 1024, 4096, 0x10f53272 +1, 119808, 119808, 1024, 4096, 0x02ad3036 +0, 60, 60, 1, 304128, 0xef10cfa8 +1, 120832, 120832, 1024, 4096, 0x12bcdaab +1, 121856, 121856, 1024, 4096, 0xebe7cfbd +0, 61, 61, 1, 304128, 0x6007c11c +1, 122880, 122880, 1024, 4096, 0x8562c355 +1, 123904, 123904, 1024, 4096, 0x5e98c541 +0, 62, 62, 1, 304128, 0x88cdcec9 +1, 124928, 124928, 1024, 4096, 0x52bc1bba +1, 125952, 125952, 1024, 4096, 0x0d3023ec +0, 63, 63, 1, 304128, 0x2a98bf55 +1, 126976, 126976, 1024, 4096, 0xc5a72a12 +0, 64, 64, 1, 304128, 0x5797ce6e +1, 128000, 128000, 1024, 4096, 0xd73b1168 +1, 129024, 129024, 1024, 4096, 0x8a25b57d +0, 65, 65, 1, 304128, 0x42f4bf51 +1, 130048, 130048, 1024, 4096, 0xba0bb903 +1, 131072, 131072, 1024, 4096, 0x3b5ecd67 +0, 66, 66, 1, 304128, 0xc9e7cef1 +1, 132096, 132096, 1024, 4096, 0xf281f25f +1, 133120, 133120, 1024, 4096, 0x3df120cc +0, 67, 67, 1, 304128, 0x88c5bd3a +1, 134144, 134144, 1024, 4096, 0x95612fc0 +1, 135168, 135168, 1024, 4096, 0x0bb8337a +0, 68, 68, 1, 304128, 0x152acb61 +1, 136192, 136192, 1024, 4096, 0x88b3d661 +1, 137216, 137216, 1024, 4096, 0xab58be1d +0, 69, 69, 1, 304128, 0x0e99bc80 +1, 138240, 138240, 1024, 4096, 0x2fb4bfe3 +1, 139264, 139264, 1024, 4096, 0x60f0ce69 +0, 70, 70, 1, 304128, 0x59f2cc34 +1, 140288, 140288, 1024, 4096, 0xe84429ea +1, 141312, 141312, 1024, 4096, 0x373327b4 +0, 71, 71, 1, 304128, 0x4048bc3c +1, 142336, 142336, 1024, 4096, 0xbf89369e +1, 143360, 143360, 1024, 4096, 0xc15b1014 +0, 72, 72, 1, 304128, 0x5cb8c7c6 +1, 144384, 144384, 1024, 4096, 0xf451b935 +1, 145408, 145408, 1024, 4096, 0x97e6caaf +0, 73, 73, 1, 304128, 0x0177ca4b +1, 146432, 146432, 1024, 4096, 0xaa75ba39 +1, 147456, 147456, 1024, 4096, 0xac6bf0df +0, 74, 74, 1, 304128, 0x1378f56c +1, 148480, 148480, 1024, 4096, 0xfcb32d5a +1, 149504, 149504, 1024, 4096, 0x2fa92810 +0, 75, 75, 1, 304128, 0xf5a3f762 +1, 150528, 150528, 1024, 4096, 0x489d35a4 +1, 151552, 151552, 1024, 4096, 0x38f7d199 +0, 76, 76, 1, 304128, 0x954304da +1, 152576, 152576, 1024, 4096, 0xb2c7be45 +1, 153600, 153600, 1024, 4096, 0x46d3b517 +0, 77, 77, 1, 304128, 0xa57a049d +1, 154624, 154624, 1024, 4096, 0x473dcb1d +1, 155648, 155648, 1024, 4096, 0xf5312786 +0, 78, 78, 1, 304128, 0xf38e0415 +1, 156672, 156672, 1024, 4096, 0x437a2d8e +1, 157696, 157696, 1024, 4096, 0x323d309a +0, 79, 79, 1, 304128, 0xcaddd766 +1, 158720, 158720, 1024, 4096, 0x5fa9144a +1, 159744, 159744, 1024, 4096, 0x6faab64f +0, 80, 80, 1, 304128, 0x7c01db9e +1, 160768, 160768, 1024, 4096, 0x7c6bc7c1 +1, 161792, 161792, 1024, 4096, 0x3756c8a7 +0, 81, 81, 1, 304128, 0x40a100e0 +1, 162816, 162816, 1024, 4096, 0xe8090998 +1, 163840, 163840, 1024, 4096, 0xc79f25d6 +0, 82, 82, 1, 304128, 0x1fd55ddb +1, 164864, 164864, 1024, 4096, 0x44172a32 +1, 165888, 165888, 1024, 4096, 0x72462f06 +0, 83, 83, 1, 304128, 0x886aa083 +1, 166912, 166912, 1024, 4096, 0x1a10d057 +1, 167936, 167936, 1024, 4096, 0x4648c83d +0, 84, 84, 1, 304128, 0x84ebb033 +1, 168960, 168960, 1024, 4096, 0xfc4daf21 +1, 169984, 169984, 1024, 4096, 0x3f2ecf17 +0, 85, 85, 1, 304128, 0xffa2d1cc +1, 171008, 171008, 1024, 4096, 0x93f12524 +0, 86, 86, 1, 304128, 0xb6186489 +1, 172032, 172032, 1024, 4096, 0xbeb330b2 +1, 173056, 173056, 1024, 4096, 0xdb4e30b8 +0, 87, 87, 1, 304128, 0xf2541c1e +1, 174080, 174080, 1024, 4096, 0x6d680e4a +1, 175104, 175104, 1024, 4096, 0xa1dcb5e9 +0, 88, 88, 1, 304128, 0xef32be7e +1, 176128, 176128, 1024, 4096, 0x7b24c5d7 +1, 177152, 177152, 1024, 4096, 0x6c92c5dd +0, 89, 89, 1, 304128, 0x7440c421 +1, 178176, 178176, 1024, 4096, 0x82ecfccb +1, 179200, 179200, 1024, 4096, 0xaea63348 +0, 90, 90, 1, 304128, 0x6bfad59c +1, 180224, 180224, 1024, 4096, 0x927144ca +1, 181248, 181248, 1024, 4096, 0xb5ab268e +0, 91, 91, 1, 304128, 0xd51dd90c +1, 182272, 182272, 1024, 4096, 0xf920e743 +1, 183296, 183296, 1024, 4096, 0xd100e43d +0, 92, 92, 1, 304128, 0x457dda78 +1, 184320, 184320, 1024, 4096, 0x3feeb317 +1, 185344, 185344, 1024, 4096, 0x8814c941 +0, 93, 93, 1, 304128, 0x10bbdbab +1, 186368, 186368, 1024, 4096, 0xf18130ba +1, 187392, 187392, 1024, 4096, 0xd9a123a2 +0, 94, 94, 1, 304128, 0x8592da9e +1, 188416, 188416, 1024, 4096, 0x71ad30e2 +1, 189440, 189440, 1024, 4096, 0xb80d0a44 +0, 95, 95, 1, 304128, 0x618fbfe5 +1, 190464, 190464, 1024, 4096, 0x86c1cac1 +1, 191488, 191488, 1024, 4096, 0xe94fb4f1 +0, 96, 96, 1, 304128, 0x9735ce85 +1, 192512, 192512, 1024, 4096, 0x5d31c21b +1, 193536, 193536, 1024, 4096, 0xe1c3fabb +0, 97, 97, 1, 304128, 0xf6a294b7 +1, 194560, 194560, 1024, 4096, 0x4cb92f4c +1, 195584, 195584, 1024, 4096, 0xf3c92e9a +0, 98, 98, 1, 304128, 0x944c9e6e +1, 196608, 196608, 1024, 4096, 0x46e42c36 +1, 197632, 197632, 1024, 4096, 0xb5eeca85 +0, 99, 99, 1, 304128, 0x932fa014 +1, 198656, 198656, 1024, 4096, 0x17a9bf45 +1, 199680, 199680, 1024, 4096, 0x0325c277 +0, 100, 100, 1, 304128, 0x45f89c36 +1, 200704, 200704, 1024, 4096, 0x5e16c923 +1, 201728, 201728, 1024, 4096, 0x86b23098 +0, 101, 101, 1, 304128, 0xeaa99a6d +1, 202752, 202752, 1024, 4096, 0x843321cc +1, 203776, 203776, 1024, 4096, 0xe74f351e +0, 102, 102, 1, 304128, 0x36259595 +1, 204800, 204800, 1024, 4096, 0xde2110d6 +1, 205824, 205824, 1024, 4096, 0x1f58b873 +0, 103, 103, 1, 304128, 0x94469994 +1, 206848, 206848, 1024, 4096, 0x2d80ced3 +1, 207872, 207872, 1024, 4096, 0xdce0cf6b +0, 104, 104, 1, 304128, 0x18a9e6f1 +1, 208896, 208896, 1024, 4096, 0x87ec0c8c +1, 209920, 209920, 1024, 4096, 0xf4d23b7c +0, 105, 105, 1, 304128, 0xb83fc100 +1, 210944, 210944, 1024, 4096, 0x74e4308a +1, 211968, 211968, 1024, 4096, 0x7b313290 +0, 106, 106, 1, 304128, 0x3787bae1 +1, 212992, 212992, 1024, 4096, 0x9ea4d805 +0, 107, 107, 1, 304128, 0xc0f38c54 +1, 214016, 214016, 1024, 4096, 0xfb66c043 +1, 215040, 215040, 1024, 4096, 0x1d04c8d3 +0, 108, 108, 1, 304128, 0xed3c9437 +1, 216064, 216064, 1024, 4096, 0x96acc8f3 +1, 217088, 217088, 1024, 4096, 0xfc10378a +0, 109, 109, 1, 304128, 0x9b3e6473 +1, 218112, 218112, 1024, 4096, 0xf8842c78 +1, 219136, 219136, 1024, 4096, 0x215a37b2 +0, 110, 110, 1, 304128, 0xd382754e +1, 220160, 220160, 1024, 4096, 0x2fb914aa +1, 221184, 221184, 1024, 4096, 0x0f70c077 +0, 111, 111, 1, 304128, 0xc5b26d34 +1, 222208, 222208, 1024, 4096, 0x722acefd +1, 223232, 223232, 1024, 4096, 0x2df7d0b9 +0, 112, 112, 1, 304128, 0x1629f231 +1, 224256, 224256, 1024, 4096, 0xf6b200f6 +1, 225280, 225280, 1024, 4096, 0x9a792b84 +0, 113, 113, 1, 304128, 0x13a43c1d +1, 226304, 226304, 1024, 4096, 0xb712308c +1, 227328, 227328, 1024, 4096, 0x909e2cf0 +0, 114, 114, 1, 304128, 0x88b58ca1 +1, 228352, 228352, 1024, 4096, 0xf8a6d3b7 +1, 229376, 229376, 1024, 4096, 0xffb9c4bd +0, 115, 115, 1, 304128, 0x03f2205a +1, 230400, 230400, 1024, 4096, 0x8646c561 +1, 231424, 231424, 1024, 4096, 0x7a5bbc8f +0, 116, 116, 1, 304128, 0x0c504dcb +1, 232448, 232448, 1024, 4096, 0x531f29ae +1, 233472, 233472, 1024, 4096, 0x97c620f0 +0, 117, 117, 1, 304128, 0xafd44d0d +1, 234496, 234496, 1024, 4096, 0xdb1c379a +1, 235520, 235520, 1024, 4096, 0xa73117b8 +0, 118, 118, 1, 304128, 0xf4b510e1 +1, 236544, 236544, 1024, 4096, 0xe9c0c67d +1, 237568, 237568, 1024, 4096, 0x88f9ca0d +0, 119, 119, 1, 304128, 0xcafdff49 +1, 238592, 238592, 1024, 4096, 0xcfe8cce1 +1, 239616, 239616, 1024, 4096, 0xfb17055c +0, 120, 120, 1, 304128, 0x4b3a9fae +1, 240640, 240640, 1024, 4096, 0x68d924f4 +1, 241664, 241664, 1024, 4096, 0x921f28d2 +0, 121, 121, 1, 304128, 0x0defa1e8 +1, 242688, 242688, 1024, 4096, 0xefa51366 +1, 243712, 243712, 1024, 4096, 0xf21ec2cb +0, 122, 122, 1, 304128, 0x429ea16d +1, 244736, 244736, 1024, 4096, 0x591fcf39 +1, 245760, 245760, 1024, 4096, 0x5559fe4b +0, 123, 123, 1, 304128, 0xd522a18a +1, 246784, 246784, 1024, 4096, 0x88adfa89 +1, 247808, 247808, 1024, 4096, 0x8f6adc9b +0, 124, 124, 1, 304128, 0xd5fec158 +1, 248832, 248832, 1024, 4096, 0x68a72b2a +1, 249856, 249856, 1024, 4096, 0x65a0e8e9 +0, 125, 125, 1, 304128, 0x2aeeb9ed +1, 250880, 250880, 1024, 4096, 0x9bb814d0 +1, 251904, 251904, 1024, 4096, 0xdc650e40 +0, 126, 126, 1, 304128, 0x68f1d94d +1, 252928, 252928, 1024, 4096, 0x7ed2c3dd +1, 253952, 253952, 1024, 4096, 0xea221032 +0, 127, 127, 1, 304128, 0x569cf8ab +1, 254976, 254976, 1024, 4096, 0x4691e20d +0, 128, 128, 1, 304128, 0xf60b1938 +1, 256000, 256000, 1024, 4096, 0x8d82fc95 +1, 257024, 257024, 1024, 4096, 0x4f9c1800 +0, 129, 129, 1, 304128, 0x211187e7 +1, 258048, 258048, 1024, 4096, 0xa14bdb59 +1, 259072, 259072, 1024, 4096, 0xa323207c +0, 130, 130, 1, 304128, 0x9a7b88ae +1, 260096, 260096, 1024, 4096, 0x501ad9df +1, 261120, 261120, 1024, 4096, 0x2301e7a9 +0, 131, 131, 1, 304128, 0x0a458876 +1, 262144, 262144, 1024, 4096, 0x67921730 +1, 263168, 263168, 1024, 4096, 0x8e9ada21 +0, 132, 132, 1, 304128, 0xc7ea82b7 +1, 264192, 264192, 1024, 4096, 0x50721dda +1, 265216, 265216, 1024, 4096, 0xfacf055e +0, 133, 133, 1, 304128, 0x15adb7c4 +1, 266240, 266240, 1024, 4096, 0xbe6acc21 +1, 267264, 267264, 1024, 4096, 0x3327f0bb +0, 134, 134, 1, 304128, 0xbe11d8eb +1, 268288, 268288, 1024, 4096, 0x3271cc39 +1, 269312, 269312, 1024, 4096, 0x6274faaf +0, 135, 135, 1, 304128, 0x978e84f5 +1, 270336, 270336, 1024, 4096, 0x50f418ac +1, 271360, 271360, 1024, 4096, 0x4d04dfb5 +0, 136, 136, 1, 304128, 0x47c215f0 +1, 272384, 272384, 1024, 4096, 0x68cd27ce +1, 273408, 273408, 1024, 4096, 0x0549df9f +0, 137, 137, 1, 304128, 0x64aa240c +1, 274432, 274432, 1024, 4096, 0x37eedb17 +1, 275456, 275456, 1024, 4096, 0x4cb506ba +0, 138, 138, 1, 304128, 0x092bcf11 +1, 276480, 276480, 1024, 4096, 0x6aecda1b +1, 277504, 277504, 1024, 4096, 0x6abe23d8 +0, 139, 139, 1, 304128, 0x28c9c7a2 +1, 278528, 278528, 1024, 4096, 0x69de0122 +1, 279552, 279552, 1024, 4096, 0x4e4fecdd +0, 140, 140, 1, 304128, 0xac4f043c +1, 280576, 280576, 1024, 4096, 0xd395190e +1, 281600, 281600, 1024, 4096, 0x9054c345 +0, 141, 141, 1, 304128, 0xc56660ce +1, 282624, 282624, 1024, 4096, 0x1696f8b5 +1, 283648, 283648, 1024, 4096, 0x4b7ffc1d +0, 142, 142, 1, 304128, 0x33c64fdc +1, 284672, 284672, 1024, 4096, 0x84f4dd63 +1, 285696, 285696, 1024, 4096, 0xb4482b76 +0, 143, 143, 1, 304128, 0x972541b3 +1, 286720, 286720, 1024, 4096, 0xeff1e917 +1, 287744, 287744, 1024, 4096, 0xed33ee4d +0, 144, 144, 1, 304128, 0x94372336 +1, 288768, 288768, 1024, 4096, 0xc98ff727 +1, 289792, 289792, 1024, 4096, 0xfd4bc7c3 +0, 145, 145, 1, 304128, 0xe4574b12 +1, 290816, 290816, 1024, 4096, 0x93042a6a +1, 291840, 291840, 1024, 4096, 0x79380f6a +0, 146, 146, 1, 304128, 0xdec94122 +1, 292864, 292864, 1024, 4096, 0x3628f041 +1, 293888, 293888, 1024, 4096, 0x7ae3186c +0, 147, 147, 1, 304128, 0x8c7e404f +1, 294912, 294912, 1024, 4096, 0xd3b6ca71 +1, 295936, 295936, 1024, 4096, 0xa90b05f2 +0, 148, 148, 1, 304128, 0x22e4726b +1, 296960, 296960, 1024, 4096, 0x8820ed55 +1, 297984, 297984, 1024, 4096, 0x1597f403 +0, 149, 149, 1, 304128, 0xbc43727d +1, 299008, 299008, 1024, 4096, 0x8d8d2d66 +0, 150, 150, 1, 304128, 0xd9216863 +1, 300032, 300032, 1024, 4096, 0x910a0434 +1, 301056, 301056, 1024, 4096, 0x3e72f0a3 +0, 151, 151, 1, 304128, 0xbbaa5e9d +1, 302080, 302080, 1024, 4096, 0xee18054c +1, 303104, 303104, 1024, 4096, 0xac58d5c7 +0, 152, 152, 1, 304128, 0x3046a2fb +1, 304128, 304128, 1024, 4096, 0xf897268c +1, 305152, 305152, 1024, 4096, 0xf4cdf271 +0, 153, 153, 1, 304128, 0x9a686805 +1, 306176, 306176, 1024, 4096, 0xded1f877 +1, 307200, 307200, 1024, 4096, 0x0d221a4e +0, 154, 154, 1, 304128, 0xacce7f1d +1, 308224, 308224, 1024, 4096, 0x2208cc9b +1, 309248, 309248, 1024, 4096, 0xe5a0f3e7 +0, 155, 155, 1, 304128, 0xb7d7792b +1, 310272, 310272, 1024, 4096, 0x9363ef9d +1, 311296, 311296, 1024, 4096, 0xc45bd939 +0, 156, 156, 1, 304128, 0xffc356a1 +1, 312320, 312320, 1024, 4096, 0xe29d1af6 +1, 313344, 313344, 1024, 4096, 0x31a2ea89 +0, 157, 157, 1, 304128, 0x0e785ace +1, 314368, 314368, 1024, 4096, 0xb53d076a +1, 315392, 315392, 1024, 4096, 0x72dafe2b +0, 158, 158, 1, 304128, 0x9b9f6d6b +1, 316416, 316416, 1024, 4096, 0x6f3bc793 +1, 317440, 317440, 1024, 4096, 0x3c620454 +0, 159, 159, 1, 304128, 0xb1ec60ab +1, 318464, 318464, 1024, 4096, 0x1108f8db +1, 319488, 319488, 1024, 4096, 0x5a7905fa +0, 160, 160, 1, 304128, 0xfd3f5540 +1, 320512, 320512, 1024, 4096, 0x7c5722c0 +1, 321536, 321536, 1024, 4096, 0x88f6d0f3 +0, 161, 161, 1, 304128, 0x6739533c +1, 322560, 322560, 1024, 4096, 0xf04c0294 +1, 323584, 323584, 1024, 4096, 0xc9e8ee59 +0, 162, 162, 1, 304128, 0x2b1d4f9d +1, 324608, 324608, 1024, 4096, 0x244be3eb +1, 325632, 325632, 1024, 4096, 0x051b3080 +0, 163, 163, 1, 304128, 0xb7204eff +1, 326656, 326656, 1024, 4096, 0x44f9dbd5 +1, 327680, 327680, 1024, 4096, 0xcfc218ee +0, 164, 164, 1, 304128, 0x47464d10 +1, 328704, 328704, 1024, 4096, 0x903a05ea +1, 329728, 329728, 1024, 4096, 0x87f1dae3 +0, 165, 165, 1, 304128, 0xf93e4ec9 +1, 330752, 330752, 1024, 4096, 0x952d1384 +1, 331776, 331776, 1024, 4096, 0x1099eb7f +0, 166, 166, 1, 304128, 0xfc7a4f3d +1, 332800, 332800, 1024, 4096, 0x9e99eb65 +1, 333824, 333824, 1024, 4096, 0x711e20d2 +0, 167, 167, 1, 304128, 0x8c974f8e +1, 334848, 334848, 1024, 4096, 0xe915d85b +1, 335872, 335872, 1024, 4096, 0xa55a146a +0, 168, 168, 1, 304128, 0xff284c6a +1, 336896, 336896, 1024, 4096, 0x67bee9b9 +1, 337920, 337920, 1024, 4096, 0x2b3beecd +0, 169, 169, 1, 304128, 0x73214c88 +1, 338944, 338944, 1024, 4096, 0xb3290aa8 +1, 339968, 339968, 1024, 4096, 0x3e16cfc9 +0, 170, 170, 1, 304128, 0x73214c88 +1, 340992, 340992, 1024, 4096, 0xb2e90432 +0, 171, 171, 1, 304128, 0x73214c88 +1, 342016, 342016, 1024, 4096, 0x418ff8fd +1, 343040, 343040, 1024, 4096, 0xe9e7d1b9 +0, 172, 172, 1, 304128, 0x73214c88 +1, 344064, 344064, 1024, 4096, 0x8ddb1618 +1, 345088, 345088, 1024, 4096, 0x9a78de8b +0, 173, 173, 1, 304128, 0x73214c88 +1, 346112, 346112, 1024, 4096, 0xaea3fbdd +1, 347136, 347136, 1024, 4096, 0x7b4e0a74 +0, 174, 174, 1, 304128, 0x73214c88 +1, 348160, 348160, 1024, 4096, 0xa51ae403 +1, 349184, 349184, 1024, 4096, 0x824f19dc +0, 175, 175, 1, 304128, 0x73214c88 +1, 350208, 350208, 1024, 4096, 0xb34eeed9 +1, 351232, 351232, 1024, 4096, 0x34d0dbe5 +0, 176, 176, 1, 304128, 0x73214c88 +1, 352256, 352256, 1024, 4096, 0x8fc213bc +1, 353280, 353280, 1024, 4096, 0xcb13aac9 +0, 177, 177, 1, 304128, 0x73214c88 +1, 354304, 354304, 1024, 4096, 0x9254149c +1, 355328, 355328, 1024, 4096, 0x4e24ebaf +0, 178, 178, 1, 304128, 0x73214c88 +1, 356352, 356352, 1024, 4096, 0x8192ef03 +1, 357376, 357376, 1024, 4096, 0xfb9a12ce +0, 179, 179, 1, 304128, 0x73214c88 +1, 358400, 358400, 1024, 4096, 0x0965cc21 +1, 359424, 359424, 1024, 4096, 0xb746f71b +0, 180, 180, 1, 304128, 0x73214c88 +1, 360448, 360448, 1024, 4096, 0x7119fc29 +1, 361472, 361472, 1024, 4096, 0xea94d949 +0, 181, 181, 1, 304128, 0x73214c88 +1, 362496, 362496, 1024, 4096, 0xa4c82bd4 +1, 363520, 363520, 1024, 4096, 0xbe4defc1 +0, 182, 182, 1, 304128, 0x73214c88 +1, 364544, 364544, 1024, 4096, 0x0fb2e897 +1, 365568, 365568, 1024, 4096, 0x37fa04ec +0, 183, 183, 1, 304128, 0x73214c88 +1, 366592, 366592, 1024, 4096, 0x027ec39d +1, 367616, 367616, 1024, 4096, 0xcc8a286a +0, 184, 184, 1, 304128, 0x73214c88 +1, 368640, 368640, 1024, 4096, 0xe072f461 +1, 369664, 369664, 1024, 4096, 0x85d9f331 +0, 185, 185, 1, 304128, 0x73214c88 +1, 370688, 370688, 1024, 4096, 0x6a4b2560 +1, 371712, 371712, 1024, 4096, 0xd637d3eb +0, 186, 186, 1, 304128, 0x73214c88 +1, 372736, 372736, 1024, 4096, 0xda880eb6 +1, 373760, 373760, 1024, 4096, 0xc0ccfa37 +0, 187, 187, 1, 304128, 0x73214c88 +1, 374784, 374784, 1024, 4096, 0xb7f2e2af +1, 375808, 375808, 1024, 4096, 0x06b83578 +0, 188, 188, 1, 304128, 0x73214c88 +1, 376832, 376832, 1024, 4096, 0xca84122a +1, 377856, 377856, 1024, 4096, 0x6fafd739 +0, 189, 189, 1, 304128, 0x73214c88 +1, 378880, 378880, 1024, 4096, 0xf5d30624 +1, 379904, 379904, 1024, 4096, 0x9670c211 +0, 190, 190, 1, 304128, 0x73214c88 +1, 380928, 380928, 1024, 4096, 0x4a5418e4 +1, 381952, 381952, 1024, 4096, 0xdaa2e461 +0, 191, 191, 1, 304128, 0x73214c88 +1, 382976, 382976, 1024, 4096, 0xdc7deccb +0, 192, 192, 1, 304128, 0x73214c88 +1, 384000, 384000, 1024, 4096, 0x81c524aa +1, 385024, 385024, 1024, 4096, 0x3ea6e16f +0, 193, 193, 1, 304128, 0x73214c88 +1, 386048, 386048, 1024, 4096, 0xe075ef33 +1, 387072, 387072, 1024, 4096, 0x8a54ef85 +0, 194, 194, 1, 304128, 0x73214c88 +1, 388096, 388096, 1024, 4096, 0x85fcd947 +1, 389120, 389120, 1024, 4096, 0xc5dd4ad6 +0, 195, 195, 1, 304128, 0x73214c88 +1, 390144, 390144, 1024, 4096, 0x1025e8bb +1, 391168, 391168, 1024, 4096, 0x8b9a037c +0, 196, 196, 1, 304128, 0x73214c88 +1, 392192, 392192, 1024, 4096, 0x09e507d0 +1, 393216, 393216, 1024, 4096, 0xe3e3ca6d +0, 197, 197, 1, 304128, 0x73214c88 +1, 394240, 394240, 1024, 4096, 0xbff312de +1, 395264, 395264, 1024, 4096, 0x2abfeed9 +0, 198, 198, 1, 304128, 0x73214c88 +1, 396288, 396288, 1024, 4096, 0xf059ff2d +1, 397312, 397312, 1024, 4096, 0xbb172292 +0, 199, 199, 1, 304128, 0x73214c88 +1, 398336, 398336, 1024, 4096, 0x20e1e33b +1, 399360, 399360, 1024, 4096, 0x519b0b54 +0, 200, 200, 1, 304128, 0x73214c88 +1, 400384, 400384, 1024, 4096, 0xa0e3f713 +1, 401408, 401408, 1024, 4096, 0xfa63daa3 +0, 201, 201, 1, 304128, 0x73214c88 +1, 402432, 402432, 1024, 4096, 0x2c9120ce +1, 403456, 403456, 1024, 4096, 0xcbdcdda1 +0, 202, 202, 1, 304128, 0x73214c88 +1, 404480, 404480, 1024, 4096, 0x8f5e1af8 +1, 405504, 405504, 1024, 4096, 0x24c70122 +0, 203, 203, 1, 304128, 0x73214c88 +1, 406528, 406528, 1024, 4096, 0x2b82c98d +1, 407552, 407552, 1024, 4096, 0xadee0a8a +0, 204, 204, 1, 304128, 0x73214c88 +1, 408576, 408576, 1024, 4096, 0xe36adae5 +1, 409600, 409600, 1024, 4096, 0x6aece99b +0, 205, 205, 1, 304128, 0x73214c88 +1, 410624, 410624, 1024, 4096, 0x91dc1f16 +1, 411648, 411648, 1024, 4096, 0x0b0ddc43 +0, 206, 206, 1, 304128, 0x73214c88 +1, 412672, 412672, 1024, 4096, 0xa81f234a +1, 413696, 413696, 1024, 4096, 0x93adebab +0, 207, 207, 1, 304128, 0x73214c88 +1, 414720, 414720, 1024, 4096, 0x4494d751 +1, 415744, 415744, 1024, 4096, 0xb0ea0574 +0, 208, 208, 1, 304128, 0x73214c88 +1, 416768, 416768, 1024, 4096, 0xb99ae65d +1, 417792, 417792, 1024, 4096, 0x31910d26 +0, 209, 209, 1, 304128, 0x73214c88 +1, 418816, 418816, 1024, 4096, 0xbb18f2f1 +1, 419840, 419840, 1024, 4096, 0x88d0df11 +0, 210, 210, 1, 304128, 0x73214c88 +1, 420864, 420864, 1024, 4096, 0x18ce04e6 +1, 421888, 421888, 1024, 4096, 0x8b66d587 +0, 211, 211, 1, 304128, 0x73214c88 +1, 422912, 422912, 1024, 4096, 0x17acf6c9 +1, 423936, 423936, 1024, 4096, 0x67ea1b64 +0, 212, 212, 1, 304128, 0x73214c88 +1, 424960, 424960, 1024, 4096, 0x2bbcda9b +1, 425984, 425984, 1024, 4096, 0xf4231a4e +0, 213, 213, 1, 304128, 0x73214c88 +1, 427008, 427008, 1024, 4096, 0x0a87e821 +0, 214, 214, 1, 304128, 0x73214c88 +1, 428032, 428032, 1024, 4096, 0x0707e5f9 +1, 429056, 429056, 1024, 4096, 0x5761fcf5 +0, 215, 215, 1, 304128, 0x73214c88 +1, 430080, 430080, 1024, 4096, 0xa3f2c7d5 +1, 431104, 431104, 1024, 4096, 0x0c2f1482 +0, 216, 216, 1, 304128, 0x73214c88 +1, 432128, 432128, 1024, 4096, 0xe5c50116 +1, 433152, 433152, 1024, 4096, 0xf892ef33 +0, 217, 217, 1, 304128, 0x2e624d89 +1, 434176, 434176, 1024, 4096, 0xbe2a1758 +1, 435200, 435200, 1024, 4096, 0x1df3cbbd +0, 218, 218, 1, 304128, 0xf6504c42 +1, 436224, 436224, 1024, 4096, 0xdb28f077 +1, 437248, 437248, 1024, 4096, 0x707603fc +0, 219, 219, 1, 304128, 0x25713c9b +1, 438272, 438272, 1024, 4096, 0x729ae505 +1, 439296, 439296, 1024, 4096, 0x2b7f1f9c +0, 220, 220, 1, 304128, 0x54123a9a +1, 440320, 440320, 1024, 4096, 0x6327e8dd +1, 441344, 441344, 1024, 4096, 0x79bdf507 +0, 221, 221, 1, 304128, 0x356c39e4 +1, 442368, 442368, 1024, 4096, 0x83cb0308 +1, 443392, 443392, 1024, 4096, 0xedadd3af +0, 222, 222, 1, 304128, 0xe653369b +1, 444416, 444416, 1024, 4096, 0xb3711892 +1, 445440, 445440, 1024, 4096, 0x86c2059a +0, 223, 223, 1, 304128, 0x974a3437 +1, 446464, 446464, 1024, 4096, 0x3ef80224 +1, 447488, 447488, 1024, 4096, 0x59db27d0 +0, 224, 224, 1, 304128, 0xb2446840 +1, 448512, 448512, 1024, 4096, 0x055fc365 +1, 449536, 449536, 1024, 4096, 0x2d230404 +0, 225, 225, 1, 304128, 0x974a3437 +1, 450560, 450560, 1024, 4096, 0x5a150a28 +1, 451584, 451584, 1024, 4096, 0x5a70e9d3 +0, 226, 226, 1, 304128, 0xe653369b +1, 452608, 452608, 1024, 4096, 0x4fef18f6 +1, 453632, 453632, 1024, 4096, 0x7104f62d +0, 227, 227, 1, 304128, 0x356c39e4 +1, 454656, 454656, 1024, 4096, 0x035507ee +1, 455680, 455680, 1024, 4096, 0xe65e0416 +0, 228, 228, 1, 304128, 0x54123a9a +1, 456704, 456704, 1024, 4096, 0x7456c847 +1, 457728, 457728, 1024, 4096, 0x24ea1c00 +0, 229, 229, 1, 304128, 0x25713c9b +1, 458752, 458752, 1024, 4096, 0xd098fa11 +1, 459776, 459776, 1024, 4096, 0x1863f8fb +0, 230, 230, 1, 304128, 0xf6504c42 +1, 460800, 460800, 1024, 4096, 0xf6b1242e +1, 461824, 461824, 1024, 4096, 0xe462cd79 +0, 231, 231, 1, 304128, 0x2e624d89 +1, 462848, 462848, 1024, 4096, 0xaf03ec63 +1, 463872, 463872, 1024, 4096, 0xab6ae305 +0, 232, 232, 1, 304128, 0x73214c88 +1, 464896, 464896, 1024, 4096, 0x3271e93b +1, 465920, 465920, 1024, 4096, 0xf173ffd9 +0, 233, 233, 1, 304128, 0x5bd94e3e +1, 466944, 466944, 1024, 4096, 0x8320e89d +1, 467968, 467968, 1024, 4096, 0xd0980a5c +0, 234, 234, 1, 304128, 0xe9804e57 +1, 468992, 468992, 1024, 4096, 0x590b0298 +0, 235, 235, 1, 304128, 0x6e934e9f +1, 470016, 470016, 1024, 4096, 0xd21cc753 +1, 471040, 471040, 1024, 4096, 0xae88060c +0, 236, 236, 1, 304128, 0xe3444deb +1, 472064, 472064, 1024, 4096, 0x90c4ec29 +1, 473088, 473088, 1024, 4096, 0x77befc77 +0, 237, 237, 1, 304128, 0xd0c64ee8 +1, 474112, 474112, 1024, 4096, 0x0c840a1a +1, 475136, 475136, 1024, 4096, 0x3681e01d +0, 238, 238, 1, 304128, 0xb27f4edd +1, 476160, 476160, 1024, 4096, 0xed65157a +1, 477184, 477184, 1024, 4096, 0x96c6da73 +0, 239, 239, 1, 304128, 0x74b24f02 +1, 478208, 478208, 1024, 4096, 0x69b6d155 +1, 479232, 479232, 1024, 4096, 0x452815a4 +0, 240, 240, 1, 304128, 0x82035d58 +1, 480256, 480256, 1024, 4096, 0xcb79e9eb +1, 481280, 481280, 1024, 4096, 0x5222e559 +0, 241, 241, 1, 304128, 0xfdf7592f +1, 482304, 482304, 1024, 4096, 0x2b251c12 +1, 483328, 483328, 1024, 4096, 0xcc95d2cb +0, 242, 242, 1, 304128, 0x055e4ab3 +1, 484352, 484352, 1024, 4096, 0xd6d3096a +1, 485376, 485376, 1024, 4096, 0x1eaaed0d +0, 243, 243, 1, 304128, 0xab9b4004 +1, 486400, 486400, 1024, 4096, 0x639818e0 +1, 487424, 487424, 1024, 4096, 0x5a06f849 +0, 244, 244, 1, 304128, 0xc84a3ac1 +1, 488448, 488448, 1024, 4096, 0xb0a5f211 +1, 489472, 489472, 1024, 4096, 0xd68b04ea +0, 245, 245, 1, 304128, 0x98553ad0 +1, 490496, 490496, 1024, 4096, 0xeb7af5a9 +1, 491520, 491520, 1024, 4096, 0xfe52efb5 +0, 246, 246, 1, 304128, 0xed413a9c +1, 492544, 492544, 1024, 4096, 0xd83707ae +1, 493568, 493568, 1024, 4096, 0x1043f5af +0, 247, 247, 1, 304128, 0xd1c53a9d +1, 494592, 494592, 1024, 4096, 0x4abef027 +1, 495616, 495616, 1024, 4096, 0x4eab0518 +0, 248, 248, 1, 304128, 0x004a8988 +1, 496640, 496640, 1024, 4096, 0x1578f1db +1, 497664, 497664, 1024, 4096, 0xd16bef29 +0, 249, 249, 1, 304128, 0x58686b2b +1, 498688, 498688, 1024, 4096, 0x9f490a12 +1, 499712, 499712, 1024, 4096, 0xadf4f5c5 +0, 250, 250, 1, 304128, 0xcda56c8f +1, 500736, 500736, 1024, 4096, 0x853dfd95 +1, 501760, 501760, 1024, 4096, 0xe38907b2 +0, 251, 251, 1, 304128, 0x2cb8664c +1, 502784, 502784, 1024, 4096, 0x029df099 +1, 503808, 503808, 1024, 4096, 0x5e70f08d +0, 252, 252, 1, 304128, 0x2f88616a +1, 504832, 504832, 1024, 4096, 0x3cd20486 +1, 505856, 505856, 1024, 4096, 0xa30cf037 +0, 253, 253, 1, 304128, 0x534ef48c +1, 506880, 506880, 1024, 4096, 0x99acf029 +1, 507904, 507904, 1024, 4096, 0x6bb20438 +0, 254, 254, 1, 304128, 0x5b0c5fbf +1, 508928, 508928, 1024, 4096, 0xb900f443 +1, 509952, 509952, 1024, 4096, 0x1686ee2f +0, 255, 255, 1, 304128, 0x7769189f +1, 510976, 510976, 1024, 4096, 0x0b20044c +0, 256, 256, 1, 304128, 0x6fbe0237 +1, 512000, 512000, 1024, 4096, 0x1f25f165 +1, 513024, 513024, 1024, 4096, 0xa5b0f343 +0, 257, 257, 1, 304128, 0xf0bbed88 +1, 514048, 514048, 1024, 4096, 0x5bd00242 +1, 515072, 515072, 1024, 4096, 0x3d00ef67 +0, 258, 258, 1, 304128, 0x7a3dd8ee +1, 516096, 516096, 1024, 4096, 0x6b5cf1ab +1, 517120, 517120, 1024, 4096, 0x37e00652 +0, 259, 259, 1, 304128, 0x57d477c4 +1, 518144, 518144, 1024, 4096, 0x5617f901 +1, 519168, 519168, 1024, 4096, 0xa767f31f +0, 260, 260, 1, 304128, 0x85eeb1a5 +1, 520192, 520192, 1024, 4096, 0x07d804a6 +1, 521216, 521216, 1024, 4096, 0x7eebfaf9 +0, 261, 261, 1, 304128, 0x6a811b8d +1, 522240, 522240, 1024, 4096, 0xc2fcf721 +1, 523264, 523264, 1024, 4096, 0x8b4d049a +0, 262, 262, 1, 304128, 0xacd848de +1, 524288, 524288, 1024, 4096, 0x9338f8f5 +1, 525312, 525312, 1024, 4096, 0x9b2ef1ad +0, 263, 263, 1, 304128, 0xa2851c63 +1, 526336, 526336, 1024, 4096, 0x56440a00 +1, 527360, 527360, 1024, 4096, 0x8b47eaa3 +0, 264, 264, 1, 304128, 0x08551181 +1, 528384, 528384, 1024, 4096, 0x6c35e9fb +1, 529408, 529408, 1024, 4096, 0x80f405f0 +0, 265, 265, 1, 304128, 0xb2abfda9 +1, 530432, 530432, 1024, 4096, 0x1a34f55d +1, 531456, 531456, 1024, 4096, 0x66b0f3b3 +0, 266, 266, 1, 304128, 0x0badf639 +1, 532480, 532480, 1024, 4096, 0x325903f8 +1, 533504, 533504, 1024, 4096, 0xd092f307 +0, 267, 267, 1, 304128, 0xd6f0e162 +1, 534528, 534528, 1024, 4096, 0xb44eef0f +1, 535552, 535552, 1024, 4096, 0x4a3c04bc +0, 268, 268, 1, 304128, 0x7486ddea +1, 536576, 536576, 1024, 4096, 0x4ba2f111 +1, 537600, 537600, 1024, 4096, 0x2c3eeef9 +0, 269, 269, 1, 304128, 0xda72dae4 +1, 538624, 538624, 1024, 4096, 0x76c206b6 +1, 539648, 539648, 1024, 4096, 0xd256f30b +0, 270, 270, 1, 304128, 0x06fad03a +1, 540672, 540672, 1024, 4096, 0xf79fef13 +1, 541696, 541696, 1024, 4096, 0x4f9a085c +0, 271, 271, 1, 304128, 0xc0e9e09c +1, 542720, 542720, 1024, 4096, 0x6293f14b +1, 543744, 543744, 1024, 4096, 0x95dcf107 +0, 272, 272, 1, 304128, 0x7cc1e665 +1, 544768, 544768, 1024, 4096, 0x12c606a0 +1, 545792, 545792, 1024, 4096, 0xec1df359 +0, 273, 273, 1, 304128, 0xa5afd18f +1, 546816, 546816, 1024, 4096, 0x2896ef07 +1, 547840, 547840, 1024, 4096, 0x93320686 +0, 274, 274, 1, 304128, 0xe4e7bb32 +1, 548864, 548864, 1024, 4096, 0xbcaff32d +1, 549888, 549888, 1024, 4096, 0xf936f107 +0, 275, 275, 1, 304128, 0x1e2aae08 +1, 550912, 550912, 1024, 4096, 0x1a630890 +1, 551936, 551936, 1024, 4096, 0x2ab6f32d +0, 276, 276, 1, 304128, 0x4e46ab59 +1, 552960, 552960, 1024, 4096, 0xd2ddf127 +1, 553984, 553984, 1024, 4096, 0x77690898 +0, 277, 277, 1, 304128, 0x74c1abec +1, 555008, 555008, 1024, 4096, 0x0b36f151 +0, 278, 278, 1, 304128, 0xdc99a7a3 +1, 556032, 556032, 1024, 4096, 0x253aefb1 +1, 557056, 557056, 1024, 4096, 0x6f3c05c2 +0, 279, 279, 1, 304128, 0x8b3bad21 +1, 558080, 558080, 1024, 4096, 0xee13f221 +1, 559104, 559104, 1024, 4096, 0xdda2f025 +0, 280, 280, 1, 304128, 0x5299a8a0 +1, 560128, 560128, 1024, 4096, 0x5e59047a +1, 561152, 561152, 1024, 4096, 0xb3aff51d +0, 281, 281, 1, 304128, 0xbf84a221 +1, 562176, 562176, 1024, 4096, 0x5d8ae8e7 +1, 563200, 563200, 1024, 4096, 0x419a04a0 +0, 282, 282, 1, 304128, 0x3eb597d7 +1, 564224, 564224, 1024, 4096, 0x6917f205 +1, 565248, 565248, 1024, 4096, 0x19f9f027 +0, 283, 283, 1, 304128, 0x1007976d +1, 566272, 566272, 1024, 4096, 0x60c40460 +1, 567296, 567296, 1024, 4096, 0x92d5f409 +0, 284, 284, 1, 304128, 0x1e3497b9 +1, 568320, 568320, 1024, 4096, 0x97cfefd3 +1, 569344, 569344, 1024, 4096, 0x8e2e06f0 +0, 285, 285, 1, 304128, 0x5d5d7f78 +1, 570368, 570368, 1024, 4096, 0xfe2ef283 +1, 571392, 571392, 1024, 4096, 0x76e1ed47 +0, 286, 286, 1, 304128, 0xed817679 +1, 572416, 572416, 1024, 4096, 0x1902088e +1, 573440, 573440, 1024, 4096, 0xf611f2cb +0, 287, 287, 1, 304128, 0x5b887842 +1, 574464, 574464, 1024, 4096, 0xbb07efeb +1, 575488, 575488, 1024, 4096, 0xa9f30626 +0, 288, 288, 1, 304128, 0xa72d7277 +1, 576512, 576512, 1024, 4096, 0x0bdcf2cf +1, 577536, 577536, 1024, 4096, 0x219defcd +0, 289, 289, 1, 304128, 0xe6f27460 +1, 578560, 578560, 1024, 4096, 0x7a3605fc +1, 579584, 579584, 1024, 4096, 0x6034f2df +0, 290, 290, 1, 304128, 0x9fc4720f +1, 580608, 580608, 1024, 4096, 0x69aaefdf +1, 581632, 581632, 1024, 4096, 0x6076067c +0, 291, 291, 1, 304128, 0x2ed37986 +1, 582656, 582656, 1024, 4096, 0x8b7cf28d +1, 583680, 583680, 1024, 4096, 0x4a49efd9 +0, 292, 292, 1, 304128, 0x4a3c7b4e +1, 584704, 584704, 1024, 4096, 0x85ba06ae +1, 585728, 585728, 1024, 4096, 0x9c0ef24d +0, 293, 293, 1, 304128, 0xda6e7674 +1, 586752, 586752, 1024, 4096, 0x55edefd5 +1, 587776, 587776, 1024, 4096, 0xfe970614 +0, 294, 294, 1, 304128, 0x3085742e +1, 588800, 588800, 1024, 4096, 0x7bfaf2bb +1, 589824, 589824, 1024, 4096, 0x8d14f05d +0, 295, 295, 1, 304128, 0xca9f71d8 +1, 590848, 590848, 1024, 4096, 0x99bd05fa +1, 591872, 591872, 1024, 4096, 0xc942f2cb +0, 296, 296, 1, 304128, 0x5b4598cb +1, 592896, 592896, 1024, 4096, 0x0fceefdb +1, 593920, 593920, 1024, 4096, 0x5d050616 +0, 297, 297, 1, 304128, 0x7ac3a344 +1, 594944, 594944, 1024, 4096, 0x8ce3f2c9 +1, 595968, 595968, 1024, 4096, 0x4770f059 +0, 298, 298, 1, 304128, 0xbfbda603 +1, 596992, 596992, 1024, 4096, 0x2edc05fa +0, 299, 299, 1, 304128, 0xd033a2c7 +1, 598016, 598016, 1024, 4096, 0x156ff619 +1, 599040, 599040, 1024, 4096, 0x9f6de385 +0, 300, 300, 1, 304128, 0x4d5c9dd9 +1, 600064, 600064, 1024, 4096, 0x9fca0630 +1, 601088, 601088, 1024, 4096, 0xf7adf2b1 +0, 301, 301, 1, 304128, 0x71689f1e +1, 602112, 602112, 1024, 4096, 0xc6c2efc9 +1, 603136, 603136, 1024, 4096, 0xa2f605dc +0, 302, 302, 1, 304128, 0x5dc09f75 +1, 604160, 604160, 1024, 4096, 0x4880f381 +1, 605184, 605184, 1024, 4096, 0xda03ef71 +0, 303, 303, 1, 304128, 0xf0d4ac32 +1, 606208, 606208, 1024, 4096, 0xc9a70622 +1, 607232, 607232, 1024, 4096, 0xa2b0f381 +0, 304, 304, 1, 304128, 0x07afaede +1, 608256, 608256, 1024, 4096, 0xcac5f595 +1, 609280, 609280, 1024, 4096, 0xd49d03ae +0, 305, 305, 1, 304128, 0xb284adaa +1, 610304, 610304, 1024, 4096, 0x2ae7f4a1 +1, 611328, 611328, 1024, 4096, 0xd041f8a7 +0, 306, 306, 1, 304128, 0x4420aeb7 +1, 612352, 612352, 1024, 4096, 0x64dc0784 +1, 613376, 613376, 1024, 4096, 0x56def411 +0, 307, 307, 1, 304128, 0xebe9aefc +1, 614400, 614400, 1024, 4096, 0x68dfebef +1, 615424, 615424, 1024, 4096, 0x6e1dfcbd +0, 308, 308, 1, 304128, 0x96a4b4a8 +1, 616448, 616448, 1024, 4096, 0xc251f40f +1, 617472, 617472, 1024, 4096, 0x640aee87 +0, 309, 309, 1, 304128, 0xb2c2b52b +1, 618496, 618496, 1024, 4096, 0xc9d705fe +1, 619520, 619520, 1024, 4096, 0x9037f459 +0, 310, 310, 1, 304128, 0x8f96b613 +1, 620544, 620544, 1024, 4096, 0xb3fbef2f +1, 621568, 621568, 1024, 4096, 0x07980588 +0, 311, 311, 1, 304128, 0xb1c4b53a +1, 622592, 622592, 1024, 4096, 0xac9ff9af +1, 623616, 623616, 1024, 4096, 0x8453ea81 +0, 312, 312, 1, 304128, 0x5422b4b9 +1, 624640, 624640, 1024, 4096, 0xa66f07f6 +1, 625664, 625664, 1024, 4096, 0xd7d7f4d7 +0, 313, 313, 1, 304128, 0xa6f6b4c0 +1, 626688, 626688, 1024, 4096, 0xa1bef00f +1, 627712, 627712, 1024, 4096, 0x199f05e6 +0, 314, 314, 1, 304128, 0x9214b4bf +1, 628736, 628736, 1024, 4096, 0x135df4a9 +1, 629760, 629760, 1024, 4096, 0xd210f02d +0, 315, 315, 1, 304128, 0xa6f6b4c0 +1, 630784, 630784, 1024, 4096, 0x04b605fe +1, 631808, 631808, 1024, 4096, 0xe38af4bd +0, 316, 316, 1, 304128, 0x7d34b4be +1, 632832, 632832, 1024, 4096, 0x435df00f +1, 633856, 633856, 1024, 4096, 0x638007ca +0, 317, 317, 1, 304128, 0xa6f6b4c0 +1, 634880, 634880, 1024, 4096, 0x109ff317 +1, 635904, 635904, 1024, 4096, 0x1f27f2cf +0, 318, 318, 1, 304128, 0x9214b4bf +1, 636928, 636928, 1024, 4096, 0x84a90576 +1, 637952, 637952, 1024, 4096, 0xd68af2f1 +0, 319, 319, 1, 304128, 0xa6f6b4c0 +1, 638976, 638976, 1024, 4096, 0x183ff1af +0, 320, 320, 1, 304128, 0x6856b4bd +1, 640000, 640000, 1024, 4096, 0x89e1042a +1, 641024, 641024, 1024, 4096, 0x29fef4fd +0, 321, 321, 1, 304128, 0xa6f6b4c0 +1, 642048, 642048, 1024, 4096, 0x4271f067 +1, 643072, 643072, 1024, 4096, 0x2f4f09aa +0, 322, 322, 1, 304128, 0x9214b4bf +1, 644096, 644096, 1024, 4096, 0x27c5f2ed +1, 645120, 645120, 1024, 4096, 0x3f46f293 +0, 323, 323, 1, 304128, 0xa6f6b4c0 +1, 646144, 646144, 1024, 4096, 0x2d9b06e2 +1, 647168, 647168, 1024, 4096, 0xa2cdf581 +0, 324, 324, 1, 304128, 0x7d34b4be +1, 648192, 648192, 1024, 4096, 0xd11bef69 +1, 649216, 649216, 1024, 4096, 0x9eb605d4 +0, 325, 325, 1, 304128, 0xa6f6b4c0 +1, 650240, 650240, 1024, 4096, 0x769ef3bd +1, 651264, 651264, 1024, 4096, 0x5b4eef5d +0, 326, 326, 1, 304128, 0x9214b4bf +1, 652288, 652288, 1024, 4096, 0x982d07ae +1, 653312, 653312, 1024, 4096, 0x15bcf3ad +0, 327, 327, 1, 304128, 0xa6f6b4c0 +1, 654336, 654336, 1024, 4096, 0xfc14eda9 +1, 655360, 655360, 1024, 4096, 0x3dd60802 +0, 328, 328, 1, 304128, 0x68fcb4ba +1, 656384, 656384, 1024, 4096, 0xb0dbf33d +1, 657408, 657408, 1024, 4096, 0x50cdedaf +0, 329, 329, 1, 304128, 0xd15cb4bf +1, 658432, 658432, 1024, 4096, 0xe64409e2 +1, 659456, 659456, 1024, 4096, 0x1cd1f31f +0, 330, 330, 1, 304128, 0xbc78b4be +1, 660480, 660480, 1024, 4096, 0xc800ed9d +1, 661504, 661504, 1024, 4096, 0xfa1605de +0, 331, 331, 1, 304128, 0xd15cb4bf +1, 662528, 662528, 1024, 4096, 0xc7fdf33b +1, 663552, 663552, 1024, 4096, 0x9ba4ee11 +0, 332, 332, 1, 304128, 0xa796b4bd +1, 664576, 664576, 1024, 4096, 0x1f910594 +1, 665600, 665600, 1024, 4096, 0x2f0ef375 +0, 333, 333, 1, 304128, 0xd15cb4bf +1, 666624, 666624, 1024, 4096, 0x7746ed9f +1, 667648, 667648, 1024, 4096, 0x2ed205a0 +0, 334, 334, 1, 304128, 0xbc78b4be +1, 668672, 668672, 1024, 4096, 0x3310f383 +1, 669696, 669696, 1024, 4096, 0xb7f7ee07 +0, 335, 335, 1, 304128, 0xd15cb4bf +1, 670720, 670720, 1024, 4096, 0xfcb4058a +1, 671744, 671744, 1024, 4096, 0x7da5f395 +0, 336, 336, 1, 304128, 0x92b6b4bc +1, 672768, 672768, 1024, 4096, 0xe0a3ed63 +1, 673792, 673792, 1024, 4096, 0x0fcf05ee +0, 337, 337, 1, 304128, 0xd15cb4bf +1, 674816, 674816, 1024, 4096, 0x7451f499 +1, 675840, 675840, 1024, 4096, 0x8804ec0f +0, 338, 338, 1, 304128, 0xbc78b4be +1, 676864, 676864, 1024, 4096, 0xb12b07ca +1, 677888, 677888, 1024, 4096, 0x575df42b +0, 339, 339, 1, 304128, 0xd15cb4bf +1, 678912, 678912, 1024, 4096, 0x6c8aeec5 +1, 679936, 679936, 1024, 4096, 0x52910600 +0, 340, 340, 1, 304128, 0xa796b4bd +1, 680960, 680960, 1024, 4096, 0xf8ecf655 +1, 681984, 681984, 1024, 4096, 0xab44eebb +0, 341, 341, 1, 304128, 0xd15cb4bf +1, 683008, 683008, 1024, 4096, 0xd7ad061c +0, 342, 342, 1, 304128, 0xbc78b4be +1, 684032, 684032, 1024, 4096, 0x34caf22f +1, 685056, 685056, 1024, 4096, 0x16d7ea0d +0, 343, 343, 1, 304128, 0xd15cb4bf +1, 686080, 686080, 1024, 4096, 0x89e307b8 +1, 687104, 687104, 1024, 4096, 0x6e06f323 +0, 344, 344, 1, 304128, 0x7dd8b4bb +1, 688128, 688128, 1024, 4096, 0xdb77e563 +1, 689152, 689152, 1024, 4096, 0xbb080786 +0, 345, 345, 1, 304128, 0xe642b4c0 +1, 690176, 690176, 1024, 4096, 0x6242f4e9 +1, 691200, 691200, 1024, 4096, 0x33e3ee05 +0, 346, 346, 1, 304128, 0xd15cb4bf +1, 692224, 692224, 1024, 4096, 0x7fc20808 +1, 693248, 693248, 1024, 4096, 0xdd20f4bf +0, 347, 347, 1, 304128, 0xe642b4c0 +1, 694272, 694272, 1024, 4096, 0x2883ea95 +1, 695296, 695296, 1024, 4096, 0xd8d9094c +0, 348, 348, 1, 304128, 0xbc78b4be +1, 696320, 696320, 1024, 4096, 0x3d88f713 +1, 697344, 697344, 1024, 4096, 0xf12ef1f7 +0, 349, 349, 1, 304128, 0xe642b4c0 +1, 698368, 698368, 1024, 4096, 0xff1d07d0 +1, 699392, 699392, 1024, 4096, 0x8e0ff507 +0, 350, 350, 1, 304128, 0xd15cb4bf +1, 700416, 700416, 1024, 4096, 0xa4a2f1f3 +1, 701440, 701440, 1024, 4096, 0x9c1f05c0 +0, 351, 351, 1, 304128, 0xe642b4c0 +1, 702464, 702464, 1024, 4096, 0xdc34f30d +1, 703488, 703488, 1024, 4096, 0xe03bec9d +0, 352, 352, 1, 304128, 0xa796b4bd +1, 704512, 704512, 1024, 4096, 0x6cf0076e +1, 705536, 705536, 1024, 4096, 0x33cdf505 +0, 353, 353, 1, 304128, 0xe642b4c0 +1, 706560, 706560, 1024, 4096, 0x6bfaf3f1 +1, 707584, 707584, 1024, 4096, 0x383305be +0, 354, 354, 1, 304128, 0xd15cb4bf +1, 708608, 708608, 1024, 4096, 0xb53cf70f +1, 709632, 709632, 1024, 4096, 0x89a5fc63 +0, 355, 355, 1, 304128, 0xe642b4c0 +1, 710656, 710656, 1024, 4096, 0xb8d2eec7 +1, 711680, 711680, 1024, 4096, 0x7f74f79f +0, 356, 356, 1, 304128, 0xbc78b4be +1, 712704, 712704, 1024, 4096, 0x0538f00f +1, 713728, 713728, 1024, 4096, 0x69a705a6 +0, 357, 357, 1, 304128, 0xe642b4c0 +1, 714752, 714752, 1024, 4096, 0x1a32f363 +1, 715776, 715776, 1024, 4096, 0xe5c4f1e3 +0, 358, 358, 1, 304128, 0xd15cb4bf +1, 716800, 716800, 1024, 4096, 0x587705d4 +1, 717824, 717824, 1024, 4096, 0xbfbdf7bb +0, 359, 359, 1, 304128, 0xe642b4c0 +1, 718848, 718848, 1024, 4096, 0x013ce913 +1, 719872, 719872, 1024, 4096, 0xfdbf09c2 +0, 360, 360, 1, 304128, 0x92b6b4bc +1, 720896, 720896, 1024, 4096, 0x5807f401 +1, 721920, 721920, 1024, 4096, 0x9f92ef1b +0, 361, 361, 1, 304128, 0x3a8fb5f6 +1, 722944, 722944, 1024, 4096, 0x90fe05ba +1, 723968, 723968, 1024, 4096, 0x70870cc6 +0, 362, 362, 1, 304128, 0x43efb5f4 +1, 724992, 724992, 1024, 4096, 0x88100ad6 +0, 363, 363, 1, 304128, 0xc079b614 +1, 726016, 726016, 1024, 4096, 0x8483ed01 +1, 727040, 727040, 1024, 4096, 0x51f4ffb5 +0, 364, 364, 1, 304128, 0xea43d4c0 +1, 728064, 728064, 1024, 4096, 0xc554f8ed +1, 729088, 729088, 1024, 4096, 0x3a11f151 +0, 365, 365, 1, 304128, 0x3424d451 +1, 730112, 730112, 1024, 4096, 0xcfc5ff63 +1, 731136, 731136, 1024, 4096, 0x3205f8fb +0, 366, 366, 1, 304128, 0xc71ee62f +1, 732160, 732160, 1024, 4096, 0x3b08f30d +1, 733184, 733184, 1024, 4096, 0x13e3ffe5 +0, 367, 367, 1, 304128, 0x1562e680 +1, 734208, 734208, 1024, 4096, 0xcf75f8c5 +1, 735232, 735232, 1024, 4096, 0x85a7f0ff +0, 368, 368, 1, 304128, 0xb3060af1 +1, 736256, 736256, 1024, 4096, 0x05e0ffa3 +1, 737280, 737280, 1024, 4096, 0xcc4ef8a5 +0, 369, 369, 1, 304128, 0xf5c84cc9 +1, 738304, 738304, 1024, 4096, 0x672cee85 +1, 739328, 739328, 1024, 4096, 0x19aef90d +0, 370, 370, 1, 304128, 0xf3b5644b +1, 740352, 740352, 1024, 4096, 0x6836f8d3 +1, 741376, 741376, 1024, 4096, 0x2566f2f5 +0, 371, 371, 1, 304128, 0xd9e577cf +1, 742400, 742400, 1024, 4096, 0x7ab3ffe9 +1, 743424, 743424, 1024, 4096, 0x256bfc5d +0, 372, 372, 1, 304128, 0xd5efdf14 +1, 744448, 744448, 1024, 4096, 0xc3c7f0b9 +1, 745472, 745472, 1024, 4096, 0x9f1affd7 +0, 373, 373, 1, 304128, 0x60372b9c +1, 746496, 746496, 1024, 4096, 0xf882f91f +1, 747520, 747520, 1024, 4096, 0x74e1f0af +0, 374, 374, 1, 304128, 0xf22acca4 +1, 748544, 748544, 1024, 4096, 0x1b41ffe7 +1, 749568, 749568, 1024, 4096, 0xa42df91b +0, 375, 375, 1, 304128, 0x5a63f2ed +1, 750592, 750592, 1024, 4096, 0xef5cf0dd +1, 751616, 751616, 1024, 4096, 0xbcf9ffa3 +0, 376, 376, 1, 304128, 0xfa012828 +1, 752640, 752640, 1024, 4096, 0xbd0ef8fb +1, 753664, 753664, 1024, 4096, 0x4ccff0e1 +0, 377, 377, 1, 304128, 0x93f0f48b +1, 754688, 754688, 1024, 4096, 0x1018ffb3 +1, 755712, 755712, 1024, 4096, 0xc8a2f8ff +0, 378, 378, 1, 304128, 0x4a0393ae +1, 756736, 756736, 1024, 4096, 0xb64af0ed +1, 757760, 757760, 1024, 4096, 0xf3eeff9d +0, 379, 379, 1, 304128, 0x1b2c2483 +1, 758784, 758784, 1024, 4096, 0xcf2af8ff +1, 759808, 759808, 1024, 4096, 0x09fcee15 +0, 380, 380, 1, 304128, 0x920f4c93 +1, 760832, 760832, 1024, 4096, 0x208afb35 +1, 761856, 761856, 1024, 4096, 0x7ed0f91f +0, 381, 381, 1, 304128, 0xa0764298 +1, 762880, 762880, 1024, 4096, 0x5f05f0eb +1, 763904, 763904, 1024, 4096, 0xec7cff67 +0, 382, 382, 1, 304128, 0xcce4341e +1, 764928, 764928, 1024, 4096, 0xebc5f95f +1, 765952, 765952, 1024, 4096, 0x3ffef0f1 +0, 383, 383, 1, 304128, 0x0b735362 +1, 766976, 766976, 1024, 4096, 0x47d9ff59 +0, 384, 384, 1, 304128, 0x0b23eca1 +1, 768000, 768000, 1024, 4096, 0xa0a8f9a9 +1, 769024, 769024, 1024, 4096, 0xf368f0bb +0, 385, 385, 1, 304128, 0x828d1f0c +1, 770048, 770048, 1024, 4096, 0xffb4ff11 +1, 771072, 771072, 1024, 4096, 0x0493f98f +0, 386, 386, 1, 304128, 0xe78601d6 +1, 772096, 772096, 1024, 4096, 0x8f75f0bd +1, 773120, 773120, 1024, 4096, 0x3b65ff45 +0, 387, 387, 1, 304128, 0x0de1c94f +1, 774144, 774144, 1024, 4096, 0x292cf987 +1, 775168, 775168, 1024, 4096, 0x90e2f0b1 +0, 388, 388, 1, 304128, 0x7185c6f3 +1, 776192, 776192, 1024, 4096, 0x7416ff45 +1, 777216, 777216, 1024, 4096, 0x1ecdf967 +0, 389, 389, 1, 304128, 0xcd59ada1 +1, 778240, 778240, 1024, 4096, 0xea79f08b +1, 779264, 779264, 1024, 4096, 0x9b34ff7d +0, 390, 390, 1, 304128, 0xc63dbd7c +1, 780288, 780288, 1024, 4096, 0x4e75fe25 +1, 781312, 781312, 1024, 4096, 0x6e54f457 +0, 391, 391, 1, 304128, 0xb6d2baeb +1, 782336, 782336, 1024, 4096, 0xa85c0126 +1, 783360, 783360, 1024, 4096, 0x6155f995 +0, 392, 392, 1, 304128, 0x41ecc8be +1, 784384, 784384, 1024, 4096, 0xcd17f1a1 +1, 785408, 785408, 1024, 4096, 0x09c6f70b +0, 393, 393, 1, 304128, 0x654ab84c +1, 786432, 786432, 1024, 4096, 0x94d8f975 +1, 787456, 787456, 1024, 4096, 0x200cf0b7 +0, 394, 394, 1, 304128, 0x0c0fdb0a +1, 788480, 788480, 1024, 4096, 0x7692ff61 +1, 789504, 789504, 1024, 4096, 0x1291f973 +0, 395, 395, 1, 304128, 0x5c52be51 +1, 790528, 790528, 1024, 4096, 0x3a7df0cd +1, 791552, 791552, 1024, 4096, 0x6ebcff67 +0, 396, 396, 1, 304128, 0x263ec3ac +1, 792576, 792576, 1024, 4096, 0xa5e4f979 +1, 793600, 793600, 1024, 4096, 0x0146f087 +0, 397, 397, 1, 304128, 0xbc2798d4 +1, 794624, 794624, 1024, 4096, 0x0f83ff5f +1, 795648, 795648, 1024, 4096, 0xc41af98b +0, 398, 398, 1, 304128, 0x1fd3a527 +1, 796672, 796672, 1024, 4096, 0xc4f1f08d +1, 797696, 797696, 1024, 4096, 0x54270108 +0, 399, 399, 1, 304128, 0xe96fa934 +1, 798720, 798720, 1024, 4096, 0x64edfa53 +1, 799744, 799744, 1024, 4096, 0x6a0cf099 +0, 400, 400, 1, 304128, 0x6284c905 +1, 800768, 800768, 1024, 4096, 0xf620ff3b +1, 801792, 801792, 1024, 4096, 0x6e01f9f7 +0, 401, 401, 1, 304128, 0xb7468c58 +1, 802816, 802816, 1024, 4096, 0xcf48f057 +1, 803840, 803840, 1024, 4096, 0x065bff1f +0, 402, 402, 1, 304128, 0xa34f852a +1, 804864, 804864, 1024, 4096, 0x6a6df9b5 +1, 805888, 805888, 1024, 4096, 0x3d82f065 +0, 403, 403, 1, 304128, 0xb02975a9 +1, 806912, 806912, 1024, 4096, 0xe4a4fee3 +1, 807936, 807936, 1024, 4096, 0x9b6b025c +0, 404, 404, 1, 304128, 0x4c4265ae +1, 808960, 808960, 1024, 4096, 0x1902f2ab +1, 809984, 809984, 1024, 4096, 0x64e8ff23 +0, 405, 405, 1, 304128, 0xda7f56f4 +1, 811008, 811008, 1024, 4096, 0x4b38f9c9 +0, 406, 406, 1, 304128, 0x3e775d8d +1, 812032, 812032, 1024, 4096, 0x1816f08f +1, 813056, 813056, 1024, 4096, 0xdcd8ff23 +0, 407, 407, 1, 304128, 0x5086549b +1, 814080, 814080, 1024, 4096, 0xfbf5f9bd +1, 815104, 815104, 1024, 4096, 0x0de7f09d +0, 408, 408, 1, 304128, 0x7f8b4e14 +1, 816128, 816128, 1024, 4096, 0x2ce7ff3b +1, 817152, 817152, 1024, 4096, 0x4c01f9b7 +0, 409, 409, 1, 304128, 0x220c49fe +1, 818176, 818176, 1024, 4096, 0x4707f0eb +1, 819200, 819200, 1024, 4096, 0xb1cffeff +0, 410, 410, 1, 304128, 0x588719eb +1, 820224, 820224, 1024, 4096, 0xc66af9bf +1, 821248, 821248, 1024, 4096, 0x5a14f0df +0, 411, 411, 1, 304128, 0xda4b299c +1, 822272, 822272, 1024, 4096, 0xf638fcfb +1, 823296, 823296, 1024, 4096, 0x7059fc05 +0, 412, 412, 1, 304128, 0x8b521b59 +1, 824320, 824320, 1024, 4096, 0xc2dff0cd +1, 825344, 825344, 1024, 4096, 0xfa71fee1 +0, 413, 413, 1, 304128, 0x79070b00 +1, 826368, 826368, 1024, 4096, 0x9fe3faa1 +1, 827392, 827392, 1024, 4096, 0x6e62ef69 +0, 414, 414, 1, 304128, 0x9146094e +1, 828416, 828416, 1024, 4096, 0xa485fb27 +1, 829440, 829440, 1024, 4096, 0xce5af9bf +0, 415, 415, 1, 304128, 0xf600fab9 +1, 830464, 830464, 1024, 4096, 0xfc21f0e3 +1, 831488, 831488, 1024, 4096, 0x6335010a +0, 416, 416, 1, 304128, 0x4a8df489 +1, 832512, 832512, 1024, 4096, 0x688cfc1b +1, 833536, 833536, 1024, 4096, 0xe96ef775 +0, 417, 417, 1, 304128, 0x3b3bdeed +1, 834560, 834560, 1024, 4096, 0x2c85f90d +1, 835584, 835584, 1024, 4096, 0xb7cffa15 +0, 418, 418, 1, 304128, 0xe23ad7a9 +1, 836608, 836608, 1024, 4096, 0xafc5f0a1 +1, 837632, 837632, 1024, 4096, 0x7375fee9 +0, 419, 419, 1, 304128, 0xcad4d143 +1, 838656, 838656, 1024, 4096, 0x2cf10246 +1, 839680, 839680, 1024, 4096, 0xfa60f2ad +0, 420, 420, 1, 304128, 0xd21fc470 +1, 840704, 840704, 1024, 4096, 0xc99ffecf +1, 841728, 841728, 1024, 4096, 0x023dfa8d +0, 421, 421, 1, 304128, 0x1941c49b +1, 842752, 842752, 1024, 4096, 0x5d08f2d3 +1, 843776, 843776, 1024, 4096, 0xf5a3fecb +0, 422, 422, 1, 304128, 0x2dd5bee4 +1, 844800, 844800, 1024, 4096, 0xceedf9e9 +1, 845824, 845824, 1024, 4096, 0x2122f0c9 +0, 423, 423, 1, 304128, 0xc35fbdff +1, 846848, 846848, 1024, 4096, 0xab05fea9 +1, 847872, 847872, 1024, 4096, 0xee26f845 +0, 424, 424, 1, 304128, 0xd122cbbf +1, 848896, 848896, 1024, 4096, 0x351af281 +1, 849920, 849920, 1024, 4096, 0x5d6efed7 +0, 425, 425, 1, 304128, 0x7a72b87b +1, 850944, 850944, 1024, 4096, 0x8eb9fa1b +1, 851968, 851968, 1024, 4096, 0x2cffeec5 +0, 426, 426, 1, 304128, 0x21efb8bc +1, 852992, 852992, 1024, 4096, 0xd3f6fca7 +0, 427, 427, 1, 304128, 0x43b9bb5f +1, 854016, 854016, 1024, 4096, 0xf070f7ff +1, 855040, 855040, 1024, 4096, 0x8a78f0bd +0, 428, 428, 1, 304128, 0xa3ddbd8c +1, 856064, 856064, 1024, 4096, 0xbe5f06c2 +1, 857088, 857088, 1024, 4096, 0x4dc0f82d +0, 429, 429, 1, 304128, 0x23f1bc3b +1, 858112, 858112, 1024, 4096, 0xb012f2b9 +1, 859136, 859136, 1024, 4096, 0x3d83fec7 +0, 430, 430, 1, 304128, 0x5c9ab610 +1, 860160, 860160, 1024, 4096, 0x67cbfa21 +1, 861184, 861184, 1024, 4096, 0x065deecf +0, 431, 431, 1, 304128, 0x2543bbeb +1, 862208, 862208, 1024, 4096, 0x48ec00bc +1, 863232, 863232, 1024, 4096, 0xeaecf839 +0, 432, 432, 1, 304128, 0xc5fcb819 +1, 864256, 864256, 1024, 4096, 0x1c31f2a7 +1, 865280, 865280, 1024, 4096, 0x547302b2 +0, 433, 433, 1, 304128, 0x51beb8e3 +1, 866304, 866304, 1024, 4096, 0xf42af833 +1, 867328, 867328, 1024, 4096, 0xba92f2a9 +0, 434, 434, 1, 304128, 0x9dc9b3e7 +1, 868352, 868352, 1024, 4096, 0xdd96f193 +1, 869376, 869376, 1024, 4096, 0x4b47feb5 +0, 435, 435, 1, 304128, 0xe061b909 +1, 870400, 870400, 1024, 4096, 0xf522f22f +1, 871424, 871424, 1024, 4096, 0xc66a0090 +0, 436, 436, 1, 304128, 0x78bcc53f +1, 872448, 872448, 1024, 4096, 0x6b56f84d +1, 873472, 873472, 1024, 4096, 0x4bf3eeb1 +0, 437, 437, 1, 304128, 0x432bc504 +1, 874496, 874496, 1024, 4096, 0xcec4fc79 +1, 875520, 875520, 1024, 4096, 0x9b6cf8d1 +0, 438, 438, 1, 304128, 0xff75c2d8 +1, 876544, 876544, 1024, 4096, 0x0b2bf01f +1, 877568, 877568, 1024, 4096, 0xe445f7ed +0, 439, 439, 1, 304128, 0xa18cc7c3 +1, 878592, 878592, 1024, 4096, 0x6d84feb1 +1, 879616, 879616, 1024, 4096, 0xd191f755 +0, 440, 440, 1, 304128, 0xf9a7d16e +1, 880640, 880640, 1024, 4096, 0x3986fe7b +1, 881664, 881664, 1024, 4096, 0x2793fa8d +0, 441, 441, 1, 304128, 0x278dd416 +1, 882688, 882688, 1024, 4096, 0x21f6f105 +1, 883712, 883712, 1024, 4096, 0xe941fc21 +0, 442, 442, 1, 304128, 0xbdefd33b +1, 884736, 884736, 1024, 4096, 0xcfe7faa7 +1, 885760, 885760, 1024, 4096, 0x6c1df0e3 +0, 443, 443, 1, 304128, 0x7383d36d +1, 886784, 886784, 1024, 4096, 0x2ecefe09 +1, 887808, 887808, 1024, 4096, 0x14c1f86d +0, 444, 444, 1, 304128, 0x7cfdd09a +1, 888832, 888832, 1024, 4096, 0x3c79f0e7 +1, 889856, 889856, 1024, 4096, 0x60500858 +0, 445, 445, 1, 304128, 0x3d08d03f +1, 890880, 890880, 1024, 4096, 0x85f7f555 +1, 891904, 891904, 1024, 4096, 0x66aff125 +0, 446, 446, 1, 304128, 0x6ea4cd3f +1, 892928, 892928, 1024, 4096, 0xaa44f7c3 +1, 893952, 893952, 1024, 4096, 0x4eb0fcb3 +0, 447, 447, 1, 304128, 0x8805d0db +1, 894976, 894976, 1024, 4096, 0x6aa3ee39 +0, 448, 448, 1, 304128, 0x390bd161 +1, 896000, 896000, 1024, 4096, 0x84310452 +1, 897024, 897024, 1024, 4096, 0x2d3ffb07 +0, 449, 449, 1, 304128, 0x8805d0db +1, 898048, 898048, 1024, 4096, 0xdd8bef71 +1, 899072, 899072, 1024, 4096, 0x6764f6a9 +0, 450, 450, 1, 304128, 0x6ea4cd3f +1, 900096, 900096, 1024, 4096, 0x816af8bb +1, 901120, 901120, 1024, 4096, 0x2089f089 +0, 451, 451, 1, 304128, 0x5013d034 +1, 902144, 902144, 1024, 4096, 0xceadfab7 +1, 903168, 903168, 1024, 4096, 0x2788fca3 +0, 452, 452, 1, 304128, 0x4259d089 +1, 904192, 904192, 1024, 4096, 0xaa80f083 +1, 905216, 905216, 1024, 4096, 0x24a7fc37 +0, 453, 453, 1, 304128, 0x5013d034 +1, 906240, 906240, 1024, 4096, 0xff33f8e1 +1, 907264, 907264, 1024, 4096, 0xc99af31d +0, 454, 454, 1, 304128, 0x6ea4cd3f +1, 908288, 908288, 1024, 4096, 0xae52f677 +1, 909312, 909312, 1024, 4096, 0x4db2f8e9 +0, 455, 455, 1, 304128, 0x8805d0db +1, 910336, 910336, 1024, 4096, 0xa560f40b +1, 911360, 911360, 1024, 4096, 0x015a0422 +0, 456, 456, 1, 304128, 0xb6d8d15d +1, 912384, 912384, 1024, 4096, 0xd6a8fcc9 +1, 913408, 913408, 1024, 4096, 0xae4bf09f +0, 457, 457, 1, 304128, 0x4d89d0dd +1, 914432, 914432, 1024, 4096, 0xc90afe55 +1, 915456, 915456, 1024, 4096, 0xafe5faab +0, 458, 458, 1, 304128, 0x3424cd41 +1, 916480, 916480, 1024, 4096, 0x2c65f08d +1, 917504, 917504, 1024, 4096, 0x849bfe35 +0, 459, 459, 1, 304128, 0x1597d036 +1, 918528, 918528, 1024, 4096, 0x169cfac3 +1, 919552, 919552, 1024, 4096, 0xb299f0b9 +0, 460, 460, 1, 304128, 0xe990d08c +1, 920576, 920576, 1024, 4096, 0x89f0000a +1, 921600, 921600, 1024, 4096, 0x2530f8db +0, 461, 461, 1, 304128, 0x1597d036 +1, 922624, 922624, 1024, 4096, 0x0e00f09b +1, 923648, 923648, 1024, 4096, 0x2618ffdb +0, 462, 462, 1, 304128, 0x472fcd36 +1, 924672, 924672, 1024, 4096, 0xd658f93f +1, 925696, 925696, 1024, 4096, 0x03e8f211 +0, 463, 463, 1, 304128, 0x6094d0d2 +1, 926720, 926720, 1024, 4096, 0x17d5fbff +1, 927744, 927744, 1024, 4096, 0x693cf90d +0, 464, 464, 1, 304128, 0x8093d154 +1, 928768, 928768, 1024, 4096, 0xbd91f083 +1, 929792, 929792, 1024, 4096, 0x0e3b0274 +0, 465, 465, 1, 304128, 0x6094d0d2 +1, 930816, 930816, 1024, 4096, 0x289e02c6 +1, 931840, 931840, 1024, 4096, 0x8797eb1b +0, 466, 466, 1, 304128, 0x472fcd36 +1, 932864, 932864, 1024, 4096, 0x4264fe55 +1, 933888, 933888, 1024, 4096, 0xe146fd7b +0, 467, 467, 1, 304128, 0x0a76d02c +1, 934912, 934912, 1024, 4096, 0xfedbf091 +1, 935936, 935936, 1024, 4096, 0x2d050014 +0, 468, 468, 1, 304128, 0xfc9bd081 +1, 936960, 936960, 1024, 4096, 0x5b08f8eb +1, 937984, 937984, 1024, 4096, 0xb201f08b +0, 469, 469, 1, 304128, 0x0a76d02c +1, 939008, 939008, 1024, 4096, 0x1ccd000c +0, 470, 470, 1, 304128, 0x472fcd36 +1, 940032, 940032, 1024, 4096, 0x41bef90b +1, 941056, 941056, 1024, 4096, 0x711ff085 +0, 471, 471, 1, 304128, 0x6094d0d2 +1, 942080, 942080, 1024, 4096, 0x85b80002 +1, 943104, 943104, 1024, 4096, 0x090ffa0b +0, 472, 472, 1, 304128, 0xfe58d150 +1, 944128, 944128, 1024, 4096, 0xcc55ee0b +1, 945152, 945152, 1024, 4096, 0x7480ffeb +0, 473, 473, 1, 304128, 0x3ecdca24 +1, 946176, 946176, 1024, 4096, 0x890af8f1 +1, 947200, 947200, 1024, 4096, 0xc2b7f085 +0, 474, 474, 1, 304128, 0x0e8db6c6 +1, 948224, 948224, 1024, 4096, 0xc14e000c +1, 949248, 949248, 1024, 4096, 0x0f60f929 +0, 475, 475, 1, 304128, 0x649db188 +1, 950272, 950272, 1024, 4096, 0xc187f095 +1, 951296, 951296, 1024, 4096, 0xf6a0000a +0, 476, 476, 1, 304128, 0xb3beefe2 +1, 952320, 952320, 1024, 4096, 0x0cfbf927 +1, 953344, 953344, 1024, 4096, 0x3531f093 +0, 477, 477, 1, 304128, 0xea41f062 +1, 954368, 954368, 1024, 4096, 0xfa0a0000 +1, 955392, 955392, 1024, 4096, 0x171bf91f +0, 478, 478, 1, 304128, 0xac4f0405 +1, 956416, 956416, 1024, 4096, 0x29c5f089 +1, 957440, 957440, 1024, 4096, 0x49c4fc47 +0, 479, 479, 1, 304128, 0x1f6cf041 +1, 958464, 958464, 1024, 4096, 0x466d0134 +1, 959488, 959488, 1024, 4096, 0x1d8fd525 +0, 480, 480, 1, 304128, 0xadf851f9 +1, 960512, 960512, 1024, 4096, 0xaa0601ba +1, 961536, 961536, 1024, 4096, 0x816f1432 +0, 481, 481, 1, 304128, 0xdc923c4f +1, 962560, 962560, 1024, 4096, 0x54fb2da8 +1, 963584, 963584, 1024, 4096, 0x0ca4ce57 +0, 482, 482, 1, 304128, 0x607a37d8 +1, 964608, 964608, 1024, 4096, 0xaeccec2d +1, 965632, 965632, 1024, 4096, 0x2806c2b5 +0, 483, 483, 1, 304128, 0x34073b9e +1, 966656, 966656, 1024, 4096, 0x6876085e +1, 967680, 967680, 1024, 4096, 0x7bd901ba +0, 484, 484, 1, 304128, 0x750850a3 +1, 968704, 968704, 1024, 4096, 0x4b7bd15f +1, 969728, 969728, 1024, 4096, 0x9394e0df +0, 485, 485, 1, 304128, 0x87864d95 +1, 970752, 970752, 1024, 4096, 0xadc40606 +1, 971776, 971776, 1024, 4096, 0x4e3a05ca +0, 486, 486, 1, 304128, 0x27d4507e +1, 972800, 972800, 1024, 4096, 0xda3def5f +1, 973824, 973824, 1024, 4096, 0x2e470edc +0, 487, 487, 1, 304128, 0x6c88507b +1, 974848, 974848, 1024, 4096, 0x3fa9c14d +1, 975872, 975872, 1024, 4096, 0xfe1f1390 +0, 488, 488, 1, 304128, 0xa6f84dbf +1, 976896, 976896, 1024, 4096, 0x178f1a28 +1, 977920, 977920, 1024, 4096, 0xe5591398 +0, 489, 489, 1, 304128, 0xf299004a +1, 978944, 978944, 1024, 4096, 0x76d2e5f5 +1, 979968, 979968, 1024, 4096, 0x0e2e0666 +0, 490, 490, 1, 304128, 0xc7504689 +1, 980992, 980992, 1024, 4096, 0x6314feb1 +0, 491, 491, 1, 304128, 0xcad8eae6 +1, 982016, 982016, 1024, 4096, 0x7b061612 +1, 983040, 983040, 1024, 4096, 0x8cf41536 +0, 492, 492, 1, 304128, 0x53b34d96 +1, 984064, 984064, 1024, 4096, 0x532feef5 +1, 985088, 985088, 1024, 4096, 0x359626bc +0, 493, 493, 1, 304128, 0x2f7958e4 +1, 986112, 986112, 1024, 4096, 0x3016d891 +1, 987136, 987136, 1024, 4096, 0x3f911ef6 +0, 494, 494, 1, 304128, 0x54ab8efa +1, 988160, 988160, 1024, 4096, 0x765dfd4b +1, 989184, 989184, 1024, 4096, 0x9e632608 +0, 495, 495, 1, 304128, 0x794d48a0 +1, 990208, 990208, 1024, 4096, 0x17b3e7cb +1, 991232, 991232, 1024, 4096, 0x6be8ebdb +0, 496, 496, 1, 304128, 0x238155b9 +1, 992256, 992256, 1024, 4096, 0x2fa0e441 +1, 993280, 993280, 1024, 4096, 0xab089ecb +0, 497, 497, 1, 304128, 0x39e7b705 +1, 994304, 994304, 1024, 4096, 0xca88f9d1 +1, 995328, 995328, 1024, 4096, 0x11cae12f +0, 498, 498, 1, 304128, 0x7a0bcc5a +1, 996352, 996352, 1024, 4096, 0x7d47cbd1 +1, 997376, 997376, 1024, 4096, 0x90f53580 +0, 499, 499, 1, 304128, 0x506dfd93 +1, 998400, 998400, 1024, 4096, 0x2d5015a2 +1, 999424, 999424, 1024, 4096, 0xbe72ce11 +0, 500, 500, 1, 304128, 0x7f3d9ea0 +1, 1000448, 1000448, 1024, 4096, 0x474be3bf +1, 1001472, 1001472, 1024, 4096, 0xcdf61c0c +0, 501, 501, 1, 304128, 0x723c59b3 +1, 1002496, 1002496, 1024, 4096, 0xcc13e295 +1, 1003520, 1003520, 1024, 4096, 0xb4a20030 +0, 502, 502, 1, 304128, 0x62ca7f68 +1, 1004544, 1004544, 1024, 4096, 0x483911ae +1, 1005568, 1005568, 1024, 4096, 0x6ad61f22 +0, 503, 503, 1, 304128, 0xa657ccba +1, 1006592, 1006592, 1024, 4096, 0x547bddb7 +1, 1007616, 1007616, 1024, 4096, 0x04c3e21f +0, 504, 504, 1, 304128, 0x0df99027 +1, 1008640, 1008640, 1024, 4096, 0x947f1992 +1, 1009664, 1009664, 1024, 4096, 0x9f620a32 +0, 505, 505, 1, 304128, 0x4b69d596 +1, 1010688, 1010688, 1024, 4096, 0x823d0b02 +1, 1011712, 1011712, 1024, 4096, 0xdd658fe2 +0, 506, 506, 1, 304128, 0x5da3db6e +1, 1012736, 1012736, 1024, 4096, 0xaf7d04ec +1, 1013760, 1013760, 1024, 4096, 0x0d61dff3 +0, 507, 507, 1, 304128, 0xcf53e0e3 +1, 1014784, 1014784, 1024, 4096, 0x87c4db19 +1, 1015808, 1015808, 1024, 4096, 0x4d6f2d22 +0, 508, 508, 1, 304128, 0x3031b466 +1, 1016832, 1016832, 1024, 4096, 0x6546fa7f +1, 1017856, 1017856, 1024, 4096, 0x93acc18b +0, 509, 509, 1, 304128, 0x59449cea +1, 1018880, 1018880, 1024, 4096, 0x41861bbc +1, 1019904, 1019904, 1024, 4096, 0xab63f85d +0, 510, 510, 1, 304128, 0x2be6c5d5 +1, 1020928, 1020928, 1024, 4096, 0x21c21b5a +1, 1021952, 1021952, 1024, 4096, 0x160b0992 +0, 511, 511, 1, 304128, 0xb750ba6e +1, 1022976, 1022976, 1024, 4096, 0x1ad825c8 +0, 512, 512, 1, 304128, 0x7031ca12 +1, 1024000, 1024000, 1024, 4096, 0xb9080728 +1, 1025024, 1025024, 1024, 4096, 0xae1a05a2 +0, 513, 513, 1, 304128, 0x39e1c337 +1, 1026048, 1026048, 1024, 4096, 0x5389d0c5 +1, 1027072, 1027072, 1024, 4096, 0xa5630626 +0, 514, 514, 1, 304128, 0x9207afbd +1, 1028096, 1028096, 1024, 4096, 0x2e1cc12b +1, 1029120, 1029120, 1024, 4096, 0xfd040fc0 +0, 515, 515, 1, 304128, 0x340ec447 +1, 1030144, 1030144, 1024, 4096, 0x0591dbfb +1, 1031168, 1031168, 1024, 4096, 0x54ef32e2 +0, 516, 516, 1, 304128, 0xfc3db656 +1, 1032192, 1032192, 1024, 4096, 0x37430004 +1, 1033216, 1033216, 1024, 4096, 0x46e2e779 +0, 517, 517, 1, 304128, 0x06c4c1d7 +1, 1034240, 1034240, 1024, 4096, 0x47292120 +1, 1035264, 1035264, 1024, 4096, 0xe918f78d +0, 518, 518, 1, 304128, 0xf190c9aa +1, 1036288, 1036288, 1024, 4096, 0x3a890a88 +1, 1037312, 1037312, 1024, 4096, 0xfc9ced79 +0, 519, 519, 1, 304128, 0x1b10ae04 +1, 1038336, 1038336, 1024, 4096, 0x75b11d72 +1, 1039360, 1039360, 1024, 4096, 0x28e1e263 +0, 520, 520, 1, 304128, 0x0ab23e88 +1, 1040384, 1040384, 1024, 4096, 0x179cff65 +1, 1041408, 1041408, 1024, 4096, 0x1f221462 +0, 521, 521, 1, 304128, 0x4fdbb453 +1, 1042432, 1042432, 1024, 4096, 0x02d60c54 +1, 1043456, 1043456, 1024, 4096, 0xbc87ed57 +0, 522, 522, 1, 304128, 0x2d63d400 +1, 1044480, 1044480, 1024, 4096, 0x6d8d0a12 +1, 1045504, 1045504, 1024, 4096, 0x0c930582 +0, 523, 523, 1, 304128, 0x01a5de59 +1, 1046528, 1046528, 1024, 4096, 0x28f7d065 +1, 1047552, 1047552, 1024, 4096, 0xe85fd961 +0, 524, 524, 1, 304128, 0x2e6fc42a +1, 1048576, 1048576, 1024, 4096, 0x4d1d12a4 +1, 1049600, 1049600, 1024, 4096, 0x28b2e2fb +0, 525, 525, 1, 304128, 0xc4c3d1e7 +1, 1050624, 1050624, 1024, 4096, 0xe9e6cecd +1, 1051648, 1051648, 1024, 4096, 0xb69baa1b +0, 526, 526, 1, 304128, 0xd111c650 +1, 1052672, 1052672, 1024, 4096, 0xed98fc9f +1, 1053696, 1053696, 1024, 4096, 0xac83d167 +0, 527, 527, 1, 304128, 0x2fc1d24f +1, 1054720, 1054720, 1024, 4096, 0x2b27dd61 +1, 1055744, 1055744, 1024, 4096, 0x0012d407 +0, 528, 528, 1, 304128, 0x63f3c506 +1, 1056768, 1056768, 1024, 4096, 0x10501032 +1, 1057792, 1057792, 1024, 4096, 0xed4100d6 +0, 529, 529, 1, 304128, 0xf40fe5db +1, 1058816, 1058816, 1024, 4096, 0x0723e6fd +1, 1059840, 1059840, 1024, 4096, 0x20011472 +0, 530, 530, 1, 304128, 0x6292e1e3 +1, 1060864, 1060864, 1024, 4096, 0x89f102ae +1, 1061888, 1061888, 1024, 4096, 0x40e4da41 +0, 531, 531, 1, 304128, 0xd76defc4 +1, 1062912, 1062912, 1024, 4096, 0x94bfe78b +1, 1063936, 1063936, 1024, 4096, 0x95860a2e +0, 532, 532, 1, 304128, 0x0617dd71 +1, 1064960, 1064960, 1024, 4096, 0xa262e641 +1, 1065984, 1065984, 1024, 4096, 0xc92b257e +0, 533, 533, 1, 304128, 0x7ec706cc +1, 1067008, 1067008, 1024, 4096, 0x6e40e703 +0, 534, 534, 1, 304128, 0x30f3faa7 +1, 1068032, 1068032, 1024, 4096, 0x143d1214 +1, 1069056, 1069056, 1024, 4096, 0x9e7017ea +0, 535, 535, 1, 304128, 0x52befd07 +1, 1070080, 1070080, 1024, 4096, 0x300a15e4 +1, 1071104, 1071104, 1024, 4096, 0x3145fe99 +0, 536, 536, 1, 304128, 0x0b57dd65 +1, 1072128, 1072128, 1024, 4096, 0x896db1bd +1, 1073152, 1073152, 1024, 4096, 0xb8702220 +0, 537, 537, 1, 304128, 0x0a38f825 +1, 1074176, 1074176, 1024, 4096, 0x2d37ee87 +1, 1075200, 1075200, 1024, 4096, 0xc5940ec2 +0, 538, 538, 1, 304128, 0xa566f4bd +1, 1076224, 1076224, 1024, 4096, 0x3c92f125 +1, 1077248, 1077248, 1024, 4096, 0x3c8deb31 +0, 539, 539, 1, 304128, 0x9aa7f677 +1, 1078272, 1078272, 1024, 4096, 0x13a600da +1, 1079296, 1079296, 1024, 4096, 0x3ab0f31f +0, 540, 540, 1, 304128, 0xc54f03f5 +1, 1080320, 1080320, 1024, 4096, 0x176b0318 +1, 1081344, 1081344, 1024, 4096, 0x08cfe6b3 +0, 541, 541, 1, 304128, 0x6b139602 +1, 1082368, 1082368, 1024, 4096, 0x75d80b22 +1, 1083392, 1083392, 1024, 4096, 0x0fa00602 +0, 542, 542, 1, 304128, 0x13e61714 +1, 1084416, 1084416, 1024, 4096, 0x0dc3d6e9 +1, 1085440, 1085440, 1024, 4096, 0x8406e0c3 +0, 543, 543, 1, 304128, 0xf194a14e +1, 1086464, 1086464, 1024, 4096, 0x13acf819 +1, 1087488, 1087488, 1024, 4096, 0x3e7acd21 +0, 544, 544, 1, 304128, 0xe6eb2abe +1, 1088512, 1088512, 1024, 4096, 0x47d4f1e9 +1, 1089536, 1089536, 1024, 4096, 0x88050aa8 +0, 545, 545, 1, 304128, 0x7fc4c898 +1, 1090560, 1090560, 1024, 4096, 0x7719196a +1, 1091584, 1091584, 1024, 4096, 0xf68ddb01 +0, 546, 546, 1, 304128, 0xad124aab +1, 1092608, 1092608, 1024, 4096, 0xb631bd1b +1, 1093632, 1093632, 1024, 4096, 0xa4ced3dd +0, 547, 547, 1, 304128, 0x8aa3d0cd +1, 1094656, 1094656, 1024, 4096, 0xe01a3b76 +1, 1095680, 1095680, 1024, 4096, 0x1b5a3ae8 +0, 548, 548, 1, 304128, 0x26a85f3b +1, 1096704, 1096704, 1024, 4096, 0x087bf831 +1, 1097728, 1097728, 1024, 4096, 0x0fa6148e +0, 549, 549, 1, 304128, 0xe9c8ec91 +1, 1098752, 1098752, 1024, 4096, 0x6fc6e95b +1, 1099776, 1099776, 1024, 4096, 0x35b708de +0, 550, 550, 1, 304128, 0xc0ee6ffd +1, 1100800, 1100800, 1024, 4096, 0xcb8db3ab +1, 1101824, 1101824, 1024, 4096, 0x47fe0864 +0, 551, 551, 1, 304128, 0x87b5724e +1, 1102848, 1102848, 1024, 4096, 0xfd6b2516 +1, 1103872, 1103872, 1024, 4096, 0xc341164a +0, 552, 552, 1, 304128, 0x71fe7f03 +1, 1104896, 1104896, 1024, 4096, 0x36dbfbd5 +1, 1105920, 1105920, 1024, 4096, 0x08d32c32 +0, 553, 553, 1, 304128, 0x63069f82 +1, 1106944, 1106944, 1024, 4096, 0x1729c703 +1, 1107968, 1107968, 1024, 4096, 0x832c15a0 +0, 554, 554, 1, 304128, 0x47ba9c49 +1, 1108992, 1108992, 1024, 4096, 0xe6923604 +0, 555, 555, 1, 304128, 0x027f2423 +1, 1110016, 1110016, 1024, 4096, 0x81eaf835 +1, 1111040, 1111040, 1024, 4096, 0xf731cd2d +0, 556, 556, 1, 304128, 0x9dc490fe +1, 1112064, 1112064, 1024, 4096, 0xf0d60fbe +1, 1113088, 1113088, 1024, 4096, 0xd3f7de13 +0, 557, 557, 1, 304128, 0x796326a4 +1, 1114112, 1114112, 1024, 4096, 0xdeeff991 +1, 1115136, 1115136, 1024, 4096, 0xc13b2448 +0, 558, 558, 1, 304128, 0xd32120f0 +1, 1116160, 1116160, 1024, 4096, 0xfa51e915 +1, 1117184, 1117184, 1024, 4096, 0xa0ccf8c5 +0, 559, 559, 1, 304128, 0xce0c25bc +1, 1118208, 1118208, 1024, 4096, 0xb453ffa5 +1, 1119232, 1119232, 1024, 4096, 0x88bf1c40 +0, 560, 560, 1, 304128, 0xb8fa85db +1, 1120256, 1120256, 1024, 4096, 0x36f53a58 +1, 1121280, 1121280, 1024, 4096, 0x62158b42 +0, 561, 561, 1, 304128, 0x29da26b1 +1, 1122304, 1122304, 1024, 4096, 0xdcc6015c +1, 1123328, 1123328, 1024, 4096, 0x43cbd5eb +0, 562, 562, 1, 304128, 0x89e021f1 +1, 1124352, 1124352, 1024, 4096, 0x96fa1396 +1, 1125376, 1125376, 1024, 4096, 0x48f2ddc7 +0, 563, 563, 1, 304128, 0xef252715 +1, 1126400, 1126400, 1024, 4096, 0x93bbd4d5 +1, 1127424, 1127424, 1024, 4096, 0xbff3f543 +0, 564, 564, 1, 304128, 0xcf5416a0 +1, 1128448, 1128448, 1024, 4096, 0xd3c4f61f +1, 1129472, 1129472, 1024, 4096, 0xe1f91138 +0, 565, 565, 1, 304128, 0x9a6b249c +1, 1130496, 1130496, 1024, 4096, 0x7334f2d7 +1, 1131520, 1131520, 1024, 4096, 0xf0aad5cb +0, 566, 566, 1, 304128, 0xebe72267 +1, 1132544, 1132544, 1024, 4096, 0x343fb071 +1, 1133568, 1133568, 1024, 4096, 0x98b90462 +0, 567, 567, 1, 304128, 0xf92824a5 +1, 1134592, 1134592, 1024, 4096, 0x754e1344 +1, 1135616, 1135616, 1024, 4096, 0x86f3d9d5 +0, 568, 568, 1, 304128, 0xb79c80f8 +1, 1136640, 1136640, 1024, 4096, 0xffe53c58 +1, 1137664, 1137664, 1024, 4096, 0xb79408ac +0, 569, 569, 1, 304128, 0x704615a6 +1, 1138688, 1138688, 1024, 4096, 0xacdae329 +1, 1139712, 1139712, 1024, 4096, 0xd134fa97 +0, 570, 570, 1, 304128, 0xdc601389 +1, 1140736, 1140736, 1024, 4096, 0xa508ecb3 +1, 1141760, 1141760, 1024, 4096, 0x716e1146 +0, 571, 571, 1, 304128, 0x78cb1497 +1, 1142784, 1142784, 1024, 4096, 0xb01adb43 +1, 1143808, 1143808, 1024, 4096, 0xb425e43b +0, 572, 572, 1, 304128, 0x6e520301 +1, 1144832, 1144832, 1024, 4096, 0xa6020b4c +1, 1145856, 1145856, 1024, 4096, 0x733cfcd9 +0, 573, 573, 1, 304128, 0xb6020dd0 +1, 1146880, 1146880, 1024, 4096, 0x6b7df93d +1, 1147904, 1147904, 1024, 4096, 0xc27ac97f +0, 574, 574, 1, 304128, 0x0442fe6f +1, 1148928, 1148928, 1024, 4096, 0x3f4ae2e5 +1, 1149952, 1149952, 1024, 4096, 0xda2feaf9 +0, 575, 575, 1, 304128, 0xa13802e8 +1, 1150976, 1150976, 1024, 4096, 0x3b6ffd0d +0, 576, 576, 1, 304128, 0x2b6211da +1, 1152000, 1152000, 1024, 4096, 0x5499f26d +1, 1153024, 1153024, 1024, 4096, 0xcb3fd72b +0, 577, 577, 1, 304128, 0x950d07fd +1, 1154048, 1154048, 1024, 4096, 0x37d2f25f +1, 1155072, 1155072, 1024, 4096, 0x6f9df8b3 +0, 578, 578, 1, 304128, 0xc754033f +1, 1156096, 1156096, 1024, 4096, 0x4d600ad6 +1, 1157120, 1157120, 1024, 4096, 0x047c28d2 +0, 579, 579, 1, 304128, 0x50c5124d +1, 1158144, 1158144, 1024, 4096, 0x43211fb2 +1, 1159168, 1159168, 1024, 4096, 0xd9ed12fa +0, 580, 580, 1, 304128, 0xf6fa12dc +1, 1160192, 1160192, 1024, 4096, 0xa859f01d +1, 1161216, 1161216, 1024, 4096, 0xc11a2816 +0, 581, 581, 1, 304128, 0x88af0c80 +1, 1162240, 1162240, 1024, 4096, 0xc36c2ccc +1, 1163264, 1163264, 1024, 4096, 0xc53aee75 +0, 582, 582, 1, 304128, 0x4bd7fb67 +1, 1164288, 1164288, 1024, 4096, 0x2c4dec1b +1, 1165312, 1165312, 1024, 4096, 0x499fef51 +0, 583, 583, 1, 304128, 0xb0f913de +1, 1166336, 1166336, 1024, 4096, 0xa29dbee9 +1, 1167360, 1167360, 1024, 4096, 0x0e64000e +0, 584, 584, 1, 304128, 0xda3ea774 +1, 1168384, 1168384, 1024, 4096, 0xbc62194e +1, 1169408, 1169408, 1024, 4096, 0x3251fb37 +1, 1170432, 1170432, 1024, 4096, 0xe54dfe3f +1, 1171456, 1171456, 1024, 4096, 0x27b4fa39 +1, 1172480, 1172480, 1024, 4096, 0xb31512c2 +1, 1173504, 1173504, 1024, 4096, 0x96570d5e +1, 1174528, 1174528, 1024, 4096, 0x33fab693 +1, 1175552, 1175552, 1024, 4096, 0x3d4e250a +1, 1176576, 1176576, 1024, 4096, 0x0a23cf1b +1, 1177600, 1177600, 1024, 4096, 0xbf4bebeb +1, 1178624, 1178624, 1024, 4096, 0x4b7ff6bb +1, 1179648, 1179648, 1024, 4096, 0xb0281ff8 +1, 1180672, 1180672, 1024, 4096, 0x55fedf21 +1, 1181696, 1181696, 1024, 4096, 0xc1683c4e +1, 1182720, 1182720, 1024, 4096, 0xb32a1cbe +1, 1183744, 1183744, 1024, 4096, 0x3ca2f4e1 +1, 1184768, 1184768, 1024, 4096, 0x0332ffa9 +1, 1185792, 1185792, 1024, 4096, 0xcb3f0a12 +1, 1186816, 1186816, 1024, 4096, 0xf4bc18f8 +1, 1187840, 1187840, 1024, 4096, 0x03941252 +1, 1188864, 1188864, 1024, 4096, 0x9440cc8d +1, 1189888, 1189888, 1024, 4096, 0x9ebd41be +1, 1190912, 1190912, 1024, 4096, 0x859d95fb +1, 1191936, 1191936, 1024, 4096, 0x4d6b10a0 +1, 1192960, 1192960, 1024, 4096, 0x7451d2bb +1, 1193984, 1193984, 1024, 4096, 0x07a928b0 +1, 1195008, 1195008, 1024, 4096, 0x629fd9cd +1, 1196032, 1196032, 1024, 4096, 0x8228ec99 +1, 1197056, 1197056, 1024, 4096, 0x4f9c1cd8 +1, 1198080, 1198080, 1024, 4096, 0xc50ee52f +1, 1199104, 1199104, 1024, 4096, 0x01a21680