Projects
Essentials
x265
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 34
View file
x265.changes
Changed
@@ -1,4 +1,30 @@ ------------------------------------------------------------------- +Tue Oct 01 12:21:19 UTC 2019 - enzokiel@kabelmail.de + +- Update to version 3.2 + New features + * 3-level hierarchical motion estimation using --hme and + --hme-search. + * New AQ mode (--aq-mode 4) with variance and edge information. + * selective-sao to selectively enable SAO at slice level. + Enhancements to existing features + * New implementation of --refine-mv with 3 refinement levels. + Encoder enhancements + * Improved quality in the frames following dark scenes in ABR + mode. + API changes + * Additions to x265_param structure to support the newly added + features --hme, --hme-search and selective-sao. + Bug fixes + * Fixed encoder crash with --zonefile during failures in + encoder_open(). + * Fixed JSON11 build errors with HDR10+ on MacOS high sierra. + * Signalling out of range scaling list data fixed. + * Inconsistent output fix for 2-pass rate-control with cutree ON. + Known issues + * Build dependency on changeset cf37911 of SVT-HEVC. + +------------------------------------------------------------------- Sun Aug 11 09:32:37 UTC 2019 - Luigi Baldoni <aloisio@gmx.com> - Update to version 3.1.2
View file
x265.spec
Changed
@@ -17,11 +17,11 @@ # -%define soname 176 +%define soname 179 %define libname lib%{name} %define libsoname %{libname}-%{soname} Name: x265 -Version: 3.1.2 +Version: 3.2 Release: 0 Summary: A free h265/HEVC encoder - encoder binary License: GPL-2.0-or-later
View file
baselibs.conf
Changed
@@ -1,1 +1,1 @@ -libx265-176 +libx265-179
View file
x265_3.1.2.tar.gz/.hg_archival.txt -> x265_3.2.tar.gz/.hg_archival.txt
Changed
@@ -1,6 +1,4 @@ repo: 09fe40627f03a0f9c3e6ac78b22ac93da23f9fdf -node: 76650bab70f9ef9f06b91ba51926ef560d6fa6ff -branch: Release_3.1 -latesttag: 3.1.2 -latesttagdistance: 1 -changessincelatesttag: 1 +node: 353572437201d551381002aebf20d244bd49ef17 +branch: Release_3.2 +tag: 3.2
View file
x265_3.1.2.tar.gz/.hgtags -> x265_3.2.tar.gz/.hgtags
Changed
@@ -35,6 +35,4 @@ 72188bd2f03447e71e789a5fd2f10364bb232c2c 3.0 113518629fa54ffb491dd479e15c1f00dd39d376 3.1_RC1 b4e38ce16d7c4b37a6482dc7ae61fd31071b6ff1 3.1_RC2 -acce27790559b68f93319cd21b588f90aa93c0b1 3.1 -6f7c2ae0d5bd46506b7a772abebd7eff3fa3bbcb 3.1.1 -4472578f9adfb383e4a479491218f37251c8ab60 3.1.2 +20c9994e8bfbeb9443851b2b3a050cd98c8b147b 3.2_RC1
View file
x265_3.1.2.tar.gz/doc/reST/cli.rst -> x265_3.2.tar.gz/doc/reST/cli.rst
Changed
@@ -1,3 +1,4 @@ + ********************* Command Line Options ********************* @@ -996,11 +997,16 @@ the encoder settings. It is recommended to use :option:`--refine-intra` 4 with dynamic refinement. Default disabled. -.. option:: --refine-mv - +.. option:: --refine-mv <1..3> + Enables refinement of motion vector for scaled video. Evaluates the best - motion vector by searching the surrounding eight integer and subpel pixel - positions. + motion vector based on the level selected. Default 1. + + Level 1 - Search around scaled MV. + + Level 2 - Level 1 + Search around best AMVP cand. + + Level 3 - Level 2 + Search around the other AMVP cand. Options which affect the transform unit quad-tree, sometimes referred to as the residual quad-tree (RQT). @@ -1261,6 +1267,18 @@ Enable motion estimation with source frame pixels, in this mode, motion estimation can be computed independently. Default disabled. +.. option:: --hme, --no-hme + + Enable 3-level Hierarchical motion estimation at One-Sixteenth, + Quarter and Full resolution. Default disabled. + +.. option:: --hme-search <integer|string>,<integer|string>,<integer|string> + + Motion search method for HME Level 0, 1 and 2. Refer to :option:`--me` for values. + Specify search method for each level. Alternatively, specify a single value + which will apply to all levels. Default is hex,umh,umh for + levels 0,1,2 respectively. + Spatial/intra options ===================== @@ -1633,7 +1651,7 @@ ignored. Slower presets will generally achieve better compression efficiency (and generate smaller bitstreams). Default disabled. -.. option:: --aq-mode <0|1|2|3> +.. option:: --aq-mode <0|1|2|3|4> Adaptive Quantization operating mode. Raise or lower per-block quantization based on complexity analysis of the source image. The @@ -1647,6 +1665,7 @@ 3. AQ enabled with auto-variance and bias to dark scenes. This is recommended for 8-bit encodes or low-bitrate 10-bit encodes, to prevent color banding/blocking. + 4. AQ enabled with auto-variance and edge information. .. option:: --aq-strength <float> @@ -1979,6 +1998,25 @@ on inter prediction mode, CTU spatial-domain correlations, and relations between luma and chroma. Default disabled + +.. option:: --selective-sao <0..4> + + Toggles SAO at slice level. Default 0. + + +--------------+------------------------------------------+ + | Level | Description | + +==============+==========================================+ + | 0 | Disable SAO for all slices | + +--------------+------------------------------------------+ + | 1 | Enable SAO only for I-slices | + +--------------+------------------------------------------+ + | 2 | Enable SAO for I-slices & P-slices | + +--------------+------------------------------------------+ + | 3 | Enable SAO for all reference slices | + +--------------+------------------------------------------+ + | 4 | Enable SAO for all slices | + +--------------+------------------------------------------+ + VUI (Video Usability Information) options =========================================
View file
x265_3.1.2.tar.gz/doc/reST/releasenotes.rst -> x265_3.2.tar.gz/doc/reST/releasenotes.rst
Changed
@@ -2,6 +2,40 @@ Release Notes ************* +Version 3.2 +=========== + +Release date - 25th September, 2019. + +New features +------------ +1. 3-level hierarchical motion estimation using :option:`--hme` and :option:`--hme-search`. +2. New AQ mode (:option:`--aq-mode` 4) with variance and edge information. +3. :option:`selective-sao` to selectively enable SAO at slice level. + +Enhancements to existing features +--------------------------------- +1. New implementation of :option:`--refine-mv` with 3 refinement levels. + +Encoder enhancements +-------------------- +1. Improved quality in the frames following dark scenes in ABR mode. + +API changes +----------- +1. Additions to x265_param structure to support the newly added features :option:`--hme`, :option:`--hme-search` and :option:`selective-sao`. + +Bug fixes +--------- +1. Fixed encoder crash with :option:`--zonefile` during failures in encoder_open(). +2. Fixed JSON11 build errors with HDR10+ on MacOS high sierra. +3. Signalling out of range scaling list data fixed. +4. Inconsistent output fix for 2-pass rate-control with cutree ON. + +Known issues +------------ +1. Build dependency on changeset cf37911 of SVT-HEVC. + Version 3.1 ===========
View file
x265_3.1.2.tar.gz/source/CMakeLists.txt -> x265_3.2.tar.gz/source/CMakeLists.txt
Changed
@@ -29,7 +29,7 @@ option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF) mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD) # X265_BUILD must be incremented each time the public API is changed -set(X265_BUILD 176) +set(X265_BUILD 179) configure_file("${PROJECT_SOURCE_DIR}/x265.def.in" "${PROJECT_BINARY_DIR}/x265.def") configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
View file
x265_3.1.2.tar.gz/source/common/lowres.cpp -> x265_3.2.tar.gz/source/common/lowres.cpp
Changed
@@ -55,6 +55,7 @@ heightFullRes = origPic->m_picHeight; width = origPic->m_picWidth / 2; lines = origPic->m_picHeight / 2; + bEnableHME = param->bEnableHME ? 1 : 0; lumaStride = width + 2 * origPic->m_lumaMarginX; if (lumaStride & 31) lumaStride += 32 - (lumaStride & 31); @@ -64,6 +65,7 @@ maxBlocksInColFullRes = maxBlocksInCol * 2; int cuCount = maxBlocksInRow * maxBlocksInCol; int cuCountFullRes = (qgSize > 8) ? cuCount : cuCount << 2; + isHMELowres = param->bEnableHME ? 1 : 0; /* rounding the width to multiple of lowres CU size */ width = maxBlocksInRow * X265_LOWRES_CU_SIZE; @@ -78,6 +80,7 @@ CHECKED_MALLOC_ZERO(qpCuTreeOffset, double, cuCountFullRes); if (qgSize == 8) CHECKED_MALLOC_ZERO(invQscaleFactor8x8, int, cuCount); + CHECKED_MALLOC_ZERO(edgeInclined, int, cuCountFullRes); } if (origPic->m_param->bAQMotion) @@ -137,6 +140,26 @@ lowresPlane[2] = buffer[2] + padoffset; lowresPlane[3] = buffer[3] + padoffset; + if (bEnableHME) + { + intptr_t lumaStrideHalf = lumaStride / 2; + if (lumaStrideHalf & 31) + lumaStrideHalf += 32 - (lumaStrideHalf & 31); + size_t planesizeHalf = planesize / 2; + size_t padoffsetHalf = padoffset / 2; + /* allocate lower-res buffers */ + CHECKED_MALLOC_ZERO(lowerResBuffer[0], pixel, 4 * planesizeHalf); + + lowerResBuffer[1] = lowerResBuffer[0] + planesizeHalf; + lowerResBuffer[2] = lowerResBuffer[1] + planesizeHalf; + lowerResBuffer[3] = lowerResBuffer[2] + planesizeHalf; + + lowerResPlane[0] = lowerResBuffer[0] + padoffsetHalf; + lowerResPlane[1] = lowerResBuffer[1] + padoffsetHalf; + lowerResPlane[2] = lowerResBuffer[2] + padoffsetHalf; + lowerResPlane[3] = lowerResBuffer[3] + padoffsetHalf; + } + CHECKED_MALLOC(intraCost, int32_t, cuCount); CHECKED_MALLOC(intraMode, uint8_t, cuCount); @@ -155,6 +178,16 @@ CHECKED_MALLOC(lowresMvs[1][i], MV, cuCount); CHECKED_MALLOC(lowresMvCosts[0][i], int32_t, cuCount); CHECKED_MALLOC(lowresMvCosts[1][i], int32_t, cuCount); + if (bEnableHME) + { + int maxBlocksInRowLowerRes = ((width/2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS; + int maxBlocksInColLowerRes = ((lines/2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS; + int cuCountLowerRes = maxBlocksInRowLowerRes * maxBlocksInColLowerRes; + CHECKED_MALLOC(lowerResMvs[0][i], MV, cuCountLowerRes); + CHECKED_MALLOC(lowerResMvs[1][i], MV, cuCountLowerRes); + CHECKED_MALLOC(lowerResMvCosts[0][i], int32_t, cuCountLowerRes); + CHECKED_MALLOC(lowerResMvCosts[1][i], int32_t, cuCountLowerRes); + } } return true; @@ -166,6 +199,8 @@ void Lowres::destroy() { X265_FREE(buffer[0]); + if(bEnableHME) + X265_FREE(lowerResBuffer[0]); X265_FREE(intraCost); X265_FREE(intraMode); @@ -184,12 +219,20 @@ X265_FREE(lowresMvs[1][i]); X265_FREE(lowresMvCosts[0][i]); X265_FREE(lowresMvCosts[1][i]); + if (bEnableHME) + { + X265_FREE(lowerResMvs[0][i]); + X265_FREE(lowerResMvs[1][i]); + X265_FREE(lowerResMvCosts[0][i]); + X265_FREE(lowerResMvCosts[1][i]); + } } X265_FREE(qpAqOffset); X265_FREE(invQscaleFactor); X265_FREE(qpCuTreeOffset); X265_FREE(propagateCost); X265_FREE(invQscaleFactor8x8); + X265_FREE(edgeInclined); X265_FREE(qpAqMotionOffset); X265_FREE(blockVariance); if (maxAQDepth > 0) @@ -253,5 +296,18 @@ extendPicBorder(lowresPlane[1], lumaStride, width, lines, origPic->m_lumaMarginX, origPic->m_lumaMarginY); extendPicBorder(lowresPlane[2], lumaStride, width, lines, origPic->m_lumaMarginX, origPic->m_lumaMarginY); extendPicBorder(lowresPlane[3], lumaStride, width, lines, origPic->m_lumaMarginX, origPic->m_lumaMarginY); + + if (origPic->m_param->bEnableHME) + { + primitives.frameInitLowerRes(lowresPlane[0], + lowerResPlane[0], lowerResPlane[1], lowerResPlane[2], lowerResPlane[3], + lumaStride, lumaStride/2, (width / 2), (lines / 2)); + extendPicBorder(lowerResPlane[0], lumaStride/2, width/2, lines/2, origPic->m_lumaMarginX/2, origPic->m_lumaMarginY/2); + extendPicBorder(lowerResPlane[1], lumaStride/2, width/2, lines/2, origPic->m_lumaMarginX/2, origPic->m_lumaMarginY/2); + extendPicBorder(lowerResPlane[2], lumaStride/2, width/2, lines/2, origPic->m_lumaMarginX/2, origPic->m_lumaMarginY/2); + extendPicBorder(lowerResPlane[3], lumaStride/2, width/2, lines/2, origPic->m_lumaMarginX/2, origPic->m_lumaMarginY/2); + fpelLowerResPlane[0] = lowerResPlane[0]; + } + fpelPlane[0] = lowresPlane[0]; }
View file
x265_3.1.2.tar.gz/source/common/lowres.h -> x265_3.2.tar.gz/source/common/lowres.h
Changed
@@ -40,8 +40,13 @@ pixel* lowresPlane[4]; PicYuv* reconPic; + /* 1/16th resolution : Level-0 HME planes */ + pixel* fpelLowerResPlane[3]; + pixel* lowerResPlane[4]; + bool isWeighted; bool isLowres; + bool isHMELowres; intptr_t lumaStride; intptr_t chromaStride; @@ -59,46 +64,58 @@ /* lowres motion compensation, you must provide a buffer and stride for QPEL averaged pixels * in case QPEL is required. Else it returns a pointer to the HPEL pixels */ - inline pixel *lowresMC(intptr_t blockOffset, const MV& qmv, pixel *buf, intptr_t& outstride) + inline pixel *lowresMC(intptr_t blockOffset, const MV& qmv, pixel *buf, intptr_t& outstride, bool hme) { + intptr_t YStride = hme ? lumaStride / 2 : lumaStride; + pixel *plane[4]; + for (int i = 0; i < 4; i++) + { + plane[i] = hme ? lowerResPlane[i] : lowresPlane[i]; + } if ((qmv.x | qmv.y) & 1) { int hpelA = (qmv.y & 2) | ((qmv.x & 2) >> 1); - pixel *frefA = lowresPlane[hpelA] + blockOffset + (qmv.x >> 2) + (qmv.y >> 2) * lumaStride; + pixel *frefA = plane[hpelA] + blockOffset + (qmv.x >> 2) + (qmv.y >> 2) * YStride; int qmvx = qmv.x + (qmv.x & 1); int qmvy = qmv.y + (qmv.y & 1); int hpelB = (qmvy & 2) | ((qmvx & 2) >> 1); - pixel *frefB = lowresPlane[hpelB] + blockOffset + (qmvx >> 2) + (qmvy >> 2) * lumaStride; - primitives.pu[LUMA_8x8].pixelavg_pp[(outstride % 64 == 0) && (lumaStride % 64 == 0)](buf, outstride, frefA, lumaStride, frefB, lumaStride, 32); + pixel *frefB = plane[hpelB] + blockOffset + (qmvx >> 2) + (qmvy >> 2) * YStride; + primitives.pu[LUMA_8x8].pixelavg_pp[(outstride % 64 == 0) && (YStride % 64 == 0)](buf, outstride, frefA, YStride, frefB, YStride, 32); return buf; } else { - outstride = lumaStride; + outstride = YStride; int hpel = (qmv.y & 2) | ((qmv.x & 2) >> 1); - return lowresPlane[hpel] + blockOffset + (qmv.x >> 2) + (qmv.y >> 2) * lumaStride; + return plane[hpel] + blockOffset + (qmv.x >> 2) + (qmv.y >> 2) * YStride; } } - inline int lowresQPelCost(pixel *fenc, intptr_t blockOffset, const MV& qmv, pixelcmp_t comp) + inline int lowresQPelCost(pixel *fenc, intptr_t blockOffset, const MV& qmv, pixelcmp_t comp, bool hme) { + intptr_t YStride = hme ? lumaStride / 2 : lumaStride; + pixel *plane[4]; + for (int i = 0; i < 4; i++) + { + plane[i] = hme ? lowerResPlane[i] : lowresPlane[i]; + } if ((qmv.x | qmv.y) & 1) { ALIGN_VAR_16(pixel, subpelbuf[8 * 8]); int hpelA = (qmv.y & 2) | ((qmv.x & 2) >> 1); - pixel *frefA = lowresPlane[hpelA] + blockOffset + (qmv.x >> 2) + (qmv.y >> 2) * lumaStride; + pixel *frefA = plane[hpelA] + blockOffset + (qmv.x >> 2) + (qmv.y >> 2) * YStride; int qmvx = qmv.x + (qmv.x & 1); int qmvy = qmv.y + (qmv.y & 1); int hpelB = (qmvy & 2) | ((qmvx & 2) >> 1); - pixel *frefB = lowresPlane[hpelB] + blockOffset + (qmvx >> 2) + (qmvy >> 2) * lumaStride; - primitives.pu[LUMA_8x8].pixelavg_pp[NONALIGNED](subpelbuf, 8, frefA, lumaStride, frefB, lumaStride, 32); + pixel *frefB = plane[hpelB] + blockOffset + (qmvx >> 2) + (qmvy >> 2) * YStride; + primitives.pu[LUMA_8x8].pixelavg_pp[NONALIGNED](subpelbuf, 8, frefA, YStride, frefB, YStride, 32); return comp(fenc, FENC_STRIDE, subpelbuf, 8); } else { int hpel = (qmv.y & 2) | ((qmv.x & 2) >> 1); - pixel *fref = lowresPlane[hpel] + blockOffset + (qmv.x >> 2) + (qmv.y >> 2) * lumaStride; - return comp(fenc, FENC_STRIDE, fref, lumaStride); + pixel *fref = plane[hpel] + blockOffset + (qmv.x >> 2) + (qmv.y >> 2) * YStride; + return comp(fenc, FENC_STRIDE, fref, YStride); } } }; @@ -150,6 +167,7 @@ struct Lowres : public ReferencePlanes { pixel *buffer[4]; + pixel *lowerResBuffer[4]; // Level-0 buffer int frameNum; // Presentation frame number int sliceType; // Slice type decided by lookahead @@ -181,6 +199,11 @@ uint32_t maxBlocksInRowFullRes; uint32_t maxBlocksInColFullRes; + /* Hierarchical Motion Estimation */ + bool bEnableHME; + int32_t* lowerResMvCosts[2][X265_BFRAME_MAX + 2]; + MV* lowerResMvs[2][X265_BFRAME_MAX + 2]; + /* used for vbvLookahead */ int plannedType[X265_LOOKAHEAD_MAX + 1]; int64_t plannedSatd[X265_LOOKAHEAD_MAX + 1]; @@ -197,6 +220,8 @@ uint64_t wp_ssd[3]; // This is different than SSDY, this is sum(pixel^2) - sum(pixel)^2 for entire frame uint64_t wp_sum[3]; double frameVariance; + int* edgeInclined; + /* cutree intermediate data */ PicQPAdaptationLayer* pAQLayer;
View file
x265_3.1.2.tar.gz/source/common/param.cpp -> x265_3.2.tar.gz/source/common/param.cpp
Changed
@@ -185,12 +185,12 @@ param->searchMethod = X265_HEX_SEARCH; param->subpelRefine = 2; param->searchRange = 57; - param->maxNumMergeCand = 3; - param->limitReferences = 1; + param->maxNumMergeCand = 3; + param->limitReferences = 1; param->limitModes = 0; param->bEnableWeightedPred = 1; param->bEnableWeightedBiPred = 0; - param->bEnableEarlySkip = 1; + param->bEnableEarlySkip = 1; param->bEnableRecursionSkip = 1; param->bEnableAMP = 0; param->bEnableRectInter = 0; @@ -201,6 +201,9 @@ param->bEnableTSkipFast = 0; param->maxNumReferences = 3; param->bEnableTemporalMvp = 1; + param->bEnableHME = 0; + param->hmeSearchMethod[0] = X265_HEX_SEARCH; + param->hmeSearchMethod[1] = param->hmeSearchMethod[2] = X265_UMH_SEARCH; param->bSourceReferenceEstimation = 0; param->limitTU = 0; param->dynamicRd = 0; @@ -212,6 +215,7 @@ param->bEnableSAO = 1; param->bSaoNonDeblocked = 0; param->bLimitSAO = 0; + param->selectiveSAO = 0; /* Coding Quality */ param->cbQpOffset = 0; @@ -225,7 +229,7 @@ param->analysisReuseFileName = NULL; param->analysisSave = NULL; param->analysisLoad = NULL; - param->bIntraInBFrames = 1; + param->bIntraInBFrames = 1; param->bLossless = 0; param->bCULossless = 0; param->bEnableTemporalSubLayers = 0; @@ -314,7 +318,7 @@ param->intraRefine = 0; param->interRefine = 0; param->bDynamicRefine = 0; - param->mvRefine = 0; + param->mvRefine = 1; param->ctuDistortionRefine = 0; param->bUseAnalysisFile = 1; param->csvfpt = NULL; @@ -361,7 +365,7 @@ if (!strcmp(preset, "ultrafast")) { - param->maxNumMergeCand = 2; + param->maxNumMergeCand = 2; param->bIntraInBFrames = 0; param->lookaheadDepth = 5; param->scenecutThreshold = 0; // disable lookahead @@ -385,7 +389,7 @@ } else if (!strcmp(preset, "superfast")) { - param->maxNumMergeCand = 2; + param->maxNumMergeCand = 2; param->bIntraInBFrames = 0; param->lookaheadDepth = 10; param->maxCUSize = 32; @@ -405,8 +409,8 @@ } else if (!strcmp(preset, "veryfast")) { - param->maxNumMergeCand = 2; - param->limitReferences = 3; + param->maxNumMergeCand = 2; + param->limitReferences = 3; param->bIntraInBFrames = 0; param->lookaheadDepth = 15; param->bFrameAdaptive = 0; @@ -418,8 +422,8 @@ } else if (!strcmp(preset, "faster")) { - param->maxNumMergeCand = 2; - param->limitReferences = 3; + param->maxNumMergeCand = 2; + param->limitReferences = 3; param->bIntraInBFrames = 0; param->lookaheadDepth = 15; param->bFrameAdaptive = 0; @@ -429,9 +433,9 @@ } else if (!strcmp(preset, "fast")) { - param->maxNumMergeCand = 2; - param->limitReferences = 3; - param->bEnableEarlySkip = 0; + param->maxNumMergeCand = 2; + param->limitReferences = 3; + param->bEnableEarlySkip = 0; param->bIntraInBFrames = 0; param->lookaheadDepth = 15; param->bFrameAdaptive = 0; @@ -445,8 +449,8 @@ } else if (!strcmp(preset, "slow")) { - param->limitReferences = 3; - param->bEnableEarlySkip = 0; + param->limitReferences = 3; + param->bEnableEarlySkip = 0; param->bIntraInBFrames = 0; param->bEnableRectInter = 1; param->lookaheadDepth = 25; @@ -1206,7 +1210,7 @@ OPT("scale-factor") p->scaleFactor = atoi(value); OPT("refine-intra")p->intraRefine = atoi(value); OPT("refine-inter")p->interRefine = atoi(value); - OPT("refine-mv")p->mvRefine = atobool(value); + OPT("refine-mv")p->mvRefine = atoi(value); OPT("force-flush")p->forceFlush = atoi(value); OPT("splitrd-skip") p->bEnableSplitRdSkip = atobool(value); OPT("lowpass-dct") p->bLowPassDct = atobool(value); @@ -1279,9 +1283,34 @@ OPT("svt-pred-struct") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name); OPT("svt-fps-in-vps") x265_log(p, X265_LOG_WARNING, "Option %s is SVT-HEVC Encoder specific; Disabling it here \n", name); #endif + OPT("selective-sao") + { + p->selectiveSAO = atoi(value); + } OPT("fades") p->bEnableFades = atobool(value); OPT("field") p->bField = atobool( value ); OPT("cll") p->bEmitCLL = atobool(value); + OPT("hme") p->bEnableHME = atobool(value); + OPT("hme-search") + { + char search[3][5]; + memset(search, '\0', 15 * sizeof(char)); + if(3 == sscanf(value, "%d,%d,%d", &p->hmeSearchMethod[0], &p->hmeSearchMethod[1], &p->hmeSearchMethod[2]) || + 3 == sscanf(value, "%4[^,],%4[^,],%4[^,]", search[0], search[1], search[2])) + { + if(search[0][0]) + for(int level = 0; level < 3; level++) + p->hmeSearchMethod[level] = parseName(search[level], x265_motion_est_names, bError); + } + else if (sscanf(value, "%d", &p->hmeSearchMethod[0]) || sscanf(value, "%s", search[0])) + { + if (search[0][0]) { + p->hmeSearchMethod[0] = parseName(search[0], x265_motion_est_names, bError); + p->hmeSearchMethod[1] = p->hmeSearchMethod[2] = p->hmeSearchMethod[0]; + } + } + p->bEnableHME = true; + } else return X265_PARAM_BAD_NAME; } @@ -1522,7 +1551,7 @@ "Lookahead depth must be less than 256"); CHECK(param->lookaheadSlices > 16 || param->lookaheadSlices < 0, "Lookahead slices must between 0 and 16"); - CHECK(param->rc.aqMode < X265_AQ_NONE || X265_AQ_AUTO_VARIANCE_BIASED < param->rc.aqMode, + CHECK(param->rc.aqMode < X265_AQ_NONE || X265_AQ_EDGE < param->rc.aqMode, "Aq-Mode is out of range"); CHECK(param->rc.aqStrength < 0 || param->rc.aqStrength > 3, "Aq-Strength is out of range"); @@ -1626,6 +1655,8 @@ "Strict-cbr cannot be applied without specifying target bitrate or vbv bufsize"); CHECK((param->analysisSave || param->analysisLoad) && (param->analysisReuseLevel < 1 || param->analysisReuseLevel > 10), "Invalid analysis refine level. Value must be between 1 and 10 (inclusive)"); + CHECK(param->analysisLoad && (param->mvRefine < 1 || param->mvRefine > 3), + "Invalid mv refinement level. Value must be between 1 and 3 (inclusive)"); CHECK(param->scaleFactor > 2, "Invalid scale-factor. Supports factor <= 2"); CHECK(param->rc.qpMax < QP_MIN || param->rc.qpMax > QP_MAX_MAX, "qpmax exceeds supported range (0 to 69)"); @@ -1660,6 +1691,8 @@ CHECK( (param->bFrameAdaptive==0), "Adaptive B-frame decision method should be closed for field feature.\n" ); // to do } + CHECK(param->selectiveSAO < 0 || param->selectiveSAO > 4, + "Invalid SAO tune level. Value must be between 0 and 4 (inclusive)"); #if !X86_64 CHECK(param->searchMethod == X265_SEA && (param->sourceWidth > 840 || param->sourceHeight > 480), "SEA motion search does not support resolutions greater than 480p in 32 bit build"); @@ -1732,8 +1765,13 @@ x265_log(param, X265_LOG_INFO, "Residual QT: max TU size, max depth : %d / %d inter / %d intra\n", param->maxTUSize, param->tuQTMaxInterDepth, param->tuQTMaxIntraDepth); - x265_log(param, X265_LOG_INFO, "ME / range / subpel / merge : %s / %d / %d / %d\n", - x265_motion_est_names[param->searchMethod], param->searchRange, param->subpelRefine, param->maxNumMergeCand); + if (param->bEnableHME) + x265_log(param, X265_LOG_INFO, "HME L0,1,2 / range / subpel / merge : %s, %s, %s / %d / %d / %d\n", + x265_motion_est_names[param->hmeSearchMethod[0]], x265_motion_est_names[param->hmeSearchMethod[1]], x265_motion_est_names[param->hmeSearchMethod[2]], param->searchRange, param->subpelRefine, param->maxNumMergeCand); + else + x265_log(param, X265_LOG_INFO, "ME / range / subpel / merge : %s / %d / %d / %d\n", + x265_motion_est_names[param->searchMethod], param->searchRange, param->subpelRefine, param->maxNumMergeCand); + if (param->keyframeMax != INT_MAX || param->scenecutThreshold) x265_log(param, X265_LOG_INFO, "Keyframe min / max / scenecut / bias: %d / %d / %d / %.2lf\n", param->keyframeMin, param->keyframeMax, param->scenecutThreshold, param->scenecutBias * 100); else @@ -1831,6 +1869,8 @@ } TOOLOPT(param->bSaoNonDeblocked, "sao-non-deblock"); TOOLOPT(!param->bSaoNonDeblocked && param->bEnableSAO, "sao"); + if (param->selectiveSAO && param->selectiveSAO != 4) + TOOLOPT(param->selectiveSAO, "selective-sao"); TOOLOPT(param->rc.bStatWrite, "stats-write"); TOOLOPT(param->rc.bStatRead, "stats-read"); TOOLOPT(param->bSingleSeiNal, "single-sei"); @@ -1928,6 +1968,9 @@ s += sprintf(s, " subme=%d", p->subpelRefine); s += sprintf(s, " merange=%d", p->searchRange); BOOL(p->bEnableTemporalMvp, "temporal-mvp"); + BOOL(p->bEnableHME, "hme"); + if (p->bEnableHME) + s += sprintf(s, " Level 0,1,2=%d,%d,%d", p->hmeSearchMethod[0], p->hmeSearchMethod[1], p->hmeSearchMethod[2]); BOOL(p->bEnableWeightedPred, "weightp"); BOOL(p->bEnableWeightedBiPred, "weightb"); BOOL(p->bSourceReferenceEstimation, "analyze-src-pics"); @@ -1937,6 +1980,7 @@ BOOL(p->bEnableSAO, "sao"); BOOL(p->bSaoNonDeblocked, "sao-non-deblock"); s += sprintf(s, " rd=%d", p->rdLevel); + s += sprintf(s, " selective-sao=%d", p->selectiveSAO); BOOL(p->bEnableEarlySkip, "early-skip"); BOOL(p->bEnableRecursionSkip, "rskip"); BOOL(p->bEnableFastIntra, "fast-intra"); @@ -2030,7 +2074,7 @@ if (p->masteringDisplayColorVolume) s += sprintf(s, " master-display=%s", p->masteringDisplayColorVolume); if (p->bEmitCLL) - s += sprintf(s, "cll=%hu,%hu", p->maxCLL, p->maxFALL); + s += sprintf(s, " cll=%hu,%hu", p->maxCLL, p->maxFALL); s += sprintf(s, " min-luma=%hu", p->minLuma); s += sprintf(s, " max-luma=%hu", p->maxLuma); s += sprintf(s, " log2-max-poc-lsb=%d", p->log2MaxPocLsb); @@ -2215,6 +2259,12 @@ dst->subpelRefine = src->subpelRefine; dst->searchRange = src->searchRange; dst->bEnableTemporalMvp = src->bEnableTemporalMvp; + dst->bEnableHME = src->bEnableHME; + if (src->bEnableHME) + { + for (int level = 0; level < 3; level++) + dst->hmeSearchMethod[level] = src->hmeSearchMethod[level]; + } dst->bEnableWeightedBiPred = src->bEnableWeightedBiPred; dst->bEnableWeightedPred = src->bEnableWeightedPred; dst->bSourceReferenceEstimation = src->bSourceReferenceEstimation; @@ -2380,6 +2430,7 @@ else dst->analysisLoad = NULL; dst->gopLookahead = src->gopLookahead; dst->radl = src->radl; + dst->selectiveSAO = src->selectiveSAO; dst->maxAUSizeFactor = src->maxAUSizeFactor; dst->bEmitIDRRecoverySEI = src->bEmitIDRRecoverySEI; dst->bDynamicRefine = src->bDynamicRefine;
View file
x265_3.1.2.tar.gz/source/common/pixel.cpp -> x265_3.2.tar.gz/source/common/pixel.cpp
Changed
@@ -1309,6 +1309,7 @@ p.scale1D_128to64[NONALIGNED] = p.scale1D_128to64[ALIGNED] = scale1D_128to64; p.scale2D_64to32 = scale2D_64to32; p.frameInitLowres = frame_init_lowres_core; + p.frameInitLowerRes = frame_init_lowres_core; p.ssim_4x4x2_core = ssim_4x4x2_core; p.ssim_end_4 = ssim_end_4;
View file
x265_3.1.2.tar.gz/source/common/primitives.h -> x265_3.2.tar.gz/source/common/primitives.h
Changed
@@ -349,6 +349,7 @@ saoCuStatsE3_t saoCuStatsE3; downscale_t frameInitLowres; + downscale_t frameInitLowerRes; cutree_propagate_cost propagateCost; cutree_fix8_unpack fix8Unpack; cutree_fix8_pack fix8Pack;
View file
x265_3.1.2.tar.gz/source/common/slice.h -> x265_3.2.tar.gz/source/common/slice.h
Changed
@@ -356,6 +356,7 @@ bool m_bCheckLDC; // TODO: is this necessary? bool m_sLFaseFlag; // loop filter boundary flag bool m_colFromL0Flag; // collocated picture from List0 or List1 flag + int m_bUseSao; int m_iPPSQpMinus26; int numRefIdxDefault[2];
View file
x265_3.1.2.tar.gz/source/common/x86/asm-primitives.cpp -> x265_3.2.tar.gz/source/common/x86/asm-primitives.cpp
Changed
@@ -1090,6 +1090,7 @@ LUMA_VSS_FILTERS(sse2); p.frameInitLowres = PFX(frame_init_lowres_core_sse2); + p.frameInitLowerRes = PFX(frame_init_lowres_core_sse2); // TODO: the planecopy_sp is really planecopy_SC now, must be fix it //p.planecopy_sp = PFX(downShift_16_sse2); p.planecopy_sp_shl = PFX(upShift_16_sse2); @@ -1132,6 +1133,7 @@ p.cu[BLOCK_8x8].idct = PFX(idct8_ssse3); p.frameInitLowres = PFX(frame_init_lowres_core_ssse3); + p.frameInitLowerRes = PFX(frame_init_lowres_core_ssse3); ALL_LUMA_PU(convert_p2s[ALIGNED], filterPixelToShort, ssse3); ALL_LUMA_PU(convert_p2s[NONALIGNED], filterPixelToShort, ssse3); @@ -1453,6 +1455,7 @@ p.cu[BLOCK_64x64].copy_sp = (copy_sp_t)PFX(blockcopy_ss_64x64_avx); p.frameInitLowres = PFX(frame_init_lowres_core_avx); + p.frameInitLowerRes = PFX(frame_init_lowres_core_avx); p.pu[LUMA_64x16].copy_pp = (copy_pp_t)PFX(blockcopy_ss_64x16_avx); p.pu[LUMA_64x32].copy_pp = (copy_pp_t)PFX(blockcopy_ss_64x32_avx); @@ -1469,6 +1472,7 @@ #endif LUMA_VAR(xop); p.frameInitLowres = PFX(frame_init_lowres_core_xop); + p.frameInitLowerRes = PFX(frame_init_lowres_core_xop); } if (cpuMask & X265_CPU_AVX2) { @@ -2296,6 +2300,7 @@ p.chroma[X265_CSP_I444].pu[LUMA_64x64].filter_vsp = PFX(interp_4tap_vert_sp_64x64_avx2); p.frameInitLowres = PFX(frame_init_lowres_core_avx2); + p.frameInitLowerRes = PFX(frame_init_lowres_core_avx2); p.propagateCost = PFX(mbtree_propagate_cost_avx2); p.fix8Unpack = PFX(cutree_fix8_unpack_avx2); p.fix8Pack = PFX(cutree_fix8_pack_avx2); @@ -3294,6 +3299,7 @@ //p.frameInitLowres = PFX(frame_init_lowres_core_mmx2); p.frameInitLowres = PFX(frame_init_lowres_core_sse2); + p.frameInitLowerRes = PFX(frame_init_lowres_core_sse2); ALL_LUMA_TU(blockfill_s[NONALIGNED], blockfill_s, sse2); ALL_LUMA_TU(blockfill_s[ALIGNED], blockfill_s, sse2); @@ -3414,6 +3420,7 @@ p.pu[LUMA_8x8].luma_hvpp = PFX(interp_8tap_hv_pp_8x8_ssse3); p.frameInitLowres = PFX(frame_init_lowres_core_ssse3); + p.frameInitLowerRes = PFX(frame_init_lowres_core_ssse3); ASSIGN2(p.scale1D_128to64, scale1D_128to64_ssse3); p.scale2D_64to32 = PFX(scale2D_64to32_ssse3); @@ -3682,6 +3689,7 @@ p.pu[LUMA_48x64].copy_pp = PFX(blockcopy_pp_48x64_avx); p.frameInitLowres = PFX(frame_init_lowres_core_avx); + p.frameInitLowerRes = PFX(frame_init_lowres_core_avx); p.propagateCost = PFX(mbtree_propagate_cost_avx); } if (cpuMask & X265_CPU_XOP) @@ -3693,6 +3701,8 @@ p.cu[BLOCK_8x8].sse_pp = PFX(pixel_ssd_8x8_xop); p.cu[BLOCK_16x16].sse_pp = PFX(pixel_ssd_16x16_xop); p.frameInitLowres = PFX(frame_init_lowres_core_xop); + p.frameInitLowerRes = PFX(frame_init_lowres_core_xop); + } #if X86_64 if (cpuMask & X265_CPU_AVX2) @@ -4667,6 +4677,7 @@ p.chroma[X265_CSP_I444].pu[LUMA_64x16].filter_vpp = PFX(interp_4tap_vert_pp_64x16_avx2); p.frameInitLowres = PFX(frame_init_lowres_core_avx2); + p.frameInitLowerRes = PFX(frame_init_lowres_core_avx2); p.propagateCost = PFX(mbtree_propagate_cost_avx2); p.saoCuStatsE0 = PFX(saoCuStatsE0_avx2); p.saoCuStatsE1 = PFX(saoCuStatsE1_avx2);
View file
x265_3.1.2.tar.gz/source/dynamicHDR10/json11/json11.cpp -> x265_3.2.tar.gz/source/dynamicHDR10/json11/json11.cpp
Changed
@@ -43,11 +43,20 @@ using std::initializer_list; using std::move; + /* Helper for representing null - just a do-nothing struct, plus comparison + * operators so the helpers in JsonValue work. We can't use nullptr_t because + * it may not be orderable. + */ + struct NullStruct { + bool operator==(NullStruct) const { return true; } + bool operator<(NullStruct) const { return false; } + }; + /* * * * * * * * * * * * * * * * * * * * * Serialization */ -static void dump(std::nullptr_t, string &out) { +static void dump(NullStruct, string &out) { out += "null"; } @@ -214,9 +223,9 @@ explicit JsonObject(Json::object &&value) : Value(move(value)) {} }; -class JsonNull final : public Value<Json::NUL, std::nullptr_t> { +class JsonNull final : public Value<Json::NUL, NullStruct> { public: - JsonNull() : Value(nullptr) {} + JsonNull() : Value({}) {} }; /* * * * * * * * * * * * * * * * * * * *
View file
x265_3.1.2.tar.gz/source/encoder/analysis.cpp -> x265_3.2.tar.gz/source/encoder/analysis.cpp
Changed
@@ -2488,14 +2488,18 @@ MV mvp; int numMvc = mode.cu.getPMV(mode.interNeighbours, list, ref, mode.amvpCand[list][ref], mvc); - if (m_param->interRefine != 1) - mvp = mode.amvpCand[list][ref][mode.cu.m_mvpIdx[list][pu.puAbsPartIdx]]; - else - mvp = interDataCTU->mv[list][cuIdx + part].word; + mvp = mode.amvpCand[list][ref][mode.cu.m_mvpIdx[list][pu.puAbsPartIdx]]; if (m_param->mvRefine || m_param->interRefine == 1) { - MV outmv; - searchMV(mode, pu, list, ref, outmv, mvp, numMvc, mvc); + MV outmv, mvpSelect[3]; + mvpSelect[0] = interDataCTU->mv[list][cuIdx + part].word; + if (m_param->mvRefine > 1) + { + mvpSelect[1] = mvp; + if(m_param->mvRefine > 2) + mvpSelect[2] = mode.amvpCand[list][ref][!(mode.cu.m_mvpIdx[list][pu.puAbsPartIdx])]; + } + searchMV(mode, list, ref, outmv, mvpSelect, numMvc, mvc); mode.cu.setPUMv(list, outmv, pu.puAbsPartIdx, part); } mode.cu.m_mvd[list][pu.puAbsPartIdx] = mode.cu.m_mv[list][pu.puAbsPartIdx] - mode.amvpCand[list][ref][mode.cu.m_mvpIdx[list][pu.puAbsPartIdx]]/*mvp*/;
View file
x265_3.1.2.tar.gz/source/encoder/api.cpp -> x265_3.2.tar.gz/source/encoder/api.cpp
Changed
@@ -96,7 +96,12 @@ x265_param* param = PARAM_NS::x265_param_alloc(); x265_param* latestParam = PARAM_NS::x265_param_alloc(); x265_param* zoneParam = PARAM_NS::x265_param_alloc(); - if (!param || !latestParam) + + if(param) PARAM_NS::x265_param_default(param); + if(latestParam) PARAM_NS::x265_param_default(latestParam); + if(zoneParam) PARAM_NS::x265_param_default(zoneParam); + + if (!param || !latestParam || !zoneParam) goto fail; if (p->rc.zoneCount || p->rc.zonefileCount) { @@ -106,6 +111,8 @@ } x265_copy_params(param, p); + x265_copy_params(latestParam, p); + x265_copy_params(zoneParam, p); x265_log(param, X265_LOG_INFO, "HEVC encoder version %s\n", PFX(version_str)); x265_log(param, X265_LOG_INFO, "build info %s\n", PFX(build_info_str)); @@ -212,6 +219,7 @@ delete encoder; PARAM_NS::x265_param_free(param); PARAM_NS::x265_param_free(latestParam); + PARAM_NS::x265_param_free(zoneParam); return NULL; } @@ -944,11 +952,11 @@ void x265_zone_free(x265_param *param) { - if (param->rc.zonefileCount) { + if (param && param->rc.zonefileCount) { for (int i = 0; i < param->rc.zonefileCount; i++) x265_free(param->rc.zones[i].zoneParam); } - if (param->rc.zoneCount || param->rc.zonefileCount) + if (param && (param->rc.zoneCount || param->rc.zonefileCount)) x265_free(param->rc.zones); }
View file
x265_3.1.2.tar.gz/source/encoder/encoder.cpp -> x265_3.2.tar.gz/source/encoder/encoder.cpp
Changed
@@ -1621,6 +1621,28 @@ } /* determine references, setup RPS, etc */ m_dpb->prepareEncode(frameEnc); + if (!!m_param->selectiveSAO) + { + Slice* slice = frameEnc->m_encData->m_slice; + slice->m_bUseSao = curEncoder->m_frameFilter.m_useSao = 1; + switch (m_param->selectiveSAO) + { + case 3: if (!IS_REFERENCED(frameEnc)) + slice->m_bUseSao = curEncoder->m_frameFilter.m_useSao = 0; + break; + case 2: if (!!m_param->bframes && slice->m_sliceType == B_SLICE) + slice->m_bUseSao = curEncoder->m_frameFilter.m_useSao = 0; + break; + case 1: if (slice->m_sliceType != I_SLICE) + slice->m_bUseSao = curEncoder->m_frameFilter.m_useSao = 0; + break; + } + } + else + { + Slice* slice = frameEnc->m_encData->m_slice; + slice->m_bUseSao = curEncoder->m_frameFilter.m_useSao = 0; + } if (m_param->rc.rateControlMode != X265_RC_CQP) m_lookahead->getEstimatedPictureCost(frameEnc); @@ -2891,6 +2913,14 @@ } + if (p->selectiveSAO && !p->bEnableSAO) + { + p->bEnableSAO = 1; + x265_log(p, X265_LOG_WARNING, "SAO turned ON when selective-sao is ON\n"); + } + + if (!p->selectiveSAO && p->bEnableSAO) + p->selectiveSAO = 4; if (p->interlaceMode) x265_log(p, X265_LOG_WARNING, "Support for interlaced video is experimental\n"); @@ -2976,20 +3006,6 @@ p->limitTU = 0; } - if (p->mvRefine) - { - if (!p->analysisLoad || p->analysisReuseLevel < 10) - { - x265_log(p, X265_LOG_WARNING, "MV refinement requires analysis load, analysis-reuse-level 10. Disabling MV refine.\n"); - p->mvRefine = 0; - } - else if (p->interRefine >= 2) - { - x265_log(p, X265_LOG_WARNING, "MVs are recomputed when refine-inter >= 2. MV refinement not applicable. Disabling MV refine\n"); - p->mvRefine = 0; - } - } - if (p->ctuDistortionRefine == CTU_DISTORTION_INTERNAL) { if (!p->analysisLoad && !p->analysisSave) @@ -3379,6 +3395,19 @@ p->bRepeatHeaders = 1; x265_log(p, X265_LOG_WARNING, "Turning on repeat - headers for zone encoding\n"); } + + if (m_param->bEnableHME) + { + if (m_param->sourceHeight < 540) + { + x265_log(p, X265_LOG_WARNING, "Source height < 540p is too low for HME. Disabling HME.\n"); + p->bEnableHME = 0; + } + if (m_param->bEnableHME && m_param->searchMethod != m_param->hmeSearchMethod[2]) + { + m_param->searchMethod = m_param->hmeSearchMethod[2]; + } + } } void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x265_picture* picIn, int paramBytes)
View file
x265_3.1.2.tar.gz/source/encoder/entropy.cpp -> x265_3.2.tar.gz/source/encoder/entropy.cpp
Changed
@@ -530,6 +530,10 @@ for (int i = 0; i < coefNum; i++) { data = src[scan[i]] - nextCoef; + if (data < -128) + data += 256; + if (data > 127) + data -= 256; nextCoef = (nextCoef + data + 256) % 256; WRITE_SVLC(data, "scaling_list_delta_coef"); } @@ -637,12 +641,18 @@ WRITE_FLAG(1, "slice_temporal_mvp_enable_flag"); } const SAOParam *saoParam = encData.m_saoParam; - if (slice.m_sps->bUseSAO) + if (slice.m_bUseSao) { WRITE_FLAG(saoParam->bSaoFlag[0], "slice_sao_luma_flag"); if (encData.m_param->internalCsp != X265_CSP_I400) WRITE_FLAG(saoParam->bSaoFlag[1], "slice_sao_chroma_flag"); } + else if(encData.m_param->selectiveSAO) + { + WRITE_FLAG(0, "slice_sao_luma_flag"); + if (encData.m_param->internalCsp != X265_CSP_I400) + WRITE_FLAG(0, "slice_sao_chroma_flag"); + } // check if numRefIdx match the defaults (1, hard-coded in PPS). If not, override // TODO: this might be a place to optimize a few bits per slice, by using param->refs for L0 default @@ -702,7 +712,7 @@ if (encData.m_param->maxSlices <= 1) { - bool isSAOEnabled = slice.m_sps->bUseSAO ? saoParam->bSaoFlag[0] || saoParam->bSaoFlag[1] : false; + bool isSAOEnabled = slice.m_sps->bUseSAO && slice.m_bUseSao ? saoParam->bSaoFlag[0] || saoParam->bSaoFlag[1] : false; bool isDBFEnabled = !slice.m_pps->bPicDisableDeblockingFilter; if (isSAOEnabled || isDBFEnabled)
View file
x265_3.1.2.tar.gz/source/encoder/frameencoder.cpp -> x265_3.2.tar.gz/source/encoder/frameencoder.cpp
Changed
@@ -634,14 +634,22 @@ if (!m_param->bEnableWavefront) m_backupStreams = new Bitstream[numSubstreams]; m_substreamSizes = X265_MALLOC(uint32_t, numSubstreams); - if (!m_param->bEnableSAO) + if (!slice->m_bUseSao) + { for (uint32_t i = 0; i < numSubstreams; i++) m_rows[i].rowGoOnCoder.setBitstream(&m_outStreams[i]); + } } else { for (uint32_t i = 0; i < numSubstreams; i++) + { m_outStreams[i].resetBits(); + if (!slice->m_bUseSao) + m_rows[i].rowGoOnCoder.setBitstream(&m_outStreams[i]); + else + m_rows[i].rowGoOnCoder.setBitstream(NULL); + } } m_rce.encodeOrder = m_frame->m_encodeOrder; @@ -981,7 +989,7 @@ m_entropyCoder.setBitstream(&m_bs); // finish encode of each CTU row, only required when SAO is enabled - if (m_param->bEnableSAO) + if (slice->m_bUseSao) encodeSlice(0); m_entropyCoder.setBitstream(&m_bs); @@ -1221,7 +1229,7 @@ const uint32_t lastCUAddr = (slice->m_endCUAddr + m_param->num4x4Partitions - 1) / m_param->num4x4Partitions; const uint32_t numSubstreams = m_param->bEnableWavefront ? slice->m_sps->numCuInHeight : 1; - SAOParam* saoParam = slice->m_sps->bUseSAO ? m_frame->m_encData->m_saoParam : NULL; + SAOParam* saoParam = slice->m_sps->bUseSAO && slice->m_bUseSao ? m_frame->m_encData->m_saoParam : NULL; for (uint32_t cuAddr = sliceAddr; cuAddr < lastCUAddr; cuAddr++) { uint32_t col = cuAddr % widthInLCUs; @@ -1515,11 +1523,11 @@ curRow.bufferedEntropy.loadContexts(rowCoder); /* SAO parameter estimation using non-deblocked pixels for CTU bottom and right boundary areas */ - if (m_param->bEnableSAO && m_param->bSaoNonDeblocked) + if (slice->m_bUseSao && m_param->bSaoNonDeblocked) m_frameFilter.m_parallelFilter[row].m_sao.calcSaoStatsCu_BeforeDblk(m_frame, col, row); /* Deblock with idle threading */ - if (m_param->bEnableLoopFilter | m_param->bEnableSAO) + if (m_param->bEnableLoopFilter | slice->m_bUseSao) { // NOTE: in VBV mode, we may reencode anytime, so we can't do Deblock stage-Horizon and SAO if (!bIsVbv) @@ -1833,12 +1841,12 @@ /* flush row bitstream (if WPP and no SAO) or flush frame if no WPP and no SAO */ /* end_of_sub_stream_one_bit / end_of_slice_segment_flag */ - if (!m_param->bEnableSAO && (m_param->bEnableWavefront || bLastRowInSlice)) - rowCoder.finishSlice(); + if (!slice->m_bUseSao && (m_param->bEnableWavefront || bLastRowInSlice)) + rowCoder.finishSlice(); /* Processing left Deblock block with current threading */ - if ((m_param->bEnableLoopFilter | m_param->bEnableSAO) & (rowInSlice >= 2)) + if ((m_param->bEnableLoopFilter | slice->m_bUseSao) & (rowInSlice >= 2)) { /* Check conditional to start previous row process with current threading */ if (m_frameFilter.m_parallelFilter[row - 2].m_lastDeblocked.get() == (int)numCols)
View file
x265_3.1.2.tar.gz/source/encoder/frameencoder.h -> x265_3.2.tar.gz/source/encoder/frameencoder.h
Changed
@@ -150,6 +150,7 @@ uint32_t m_filterRowDelay; uint32_t m_filterRowDelayCus; uint32_t m_refLagRows; + bool m_bUseSao; CTURow* m_rows; uint16_t m_sliceAddrBits;
View file
x265_3.1.2.tar.gz/source/encoder/framefilter.cpp -> x265_3.2.tar.gz/source/encoder/framefilter.cpp
Changed
@@ -163,7 +163,7 @@ if (m_parallelFilter) { - if (m_param->bEnableSAO) + if (m_useSao) { for(int row = 0; row < m_numRows; row++) m_parallelFilter[row].m_sao.destroy((row == 0 ? 1 : 0)); @@ -178,6 +178,7 @@ { m_param = frame->m_param; m_frameEncoder = frame; + m_useSao = 1; m_numRows = numRows; m_numCols = numCols; m_hChromaShift = CHROMA_H_SHIFT(m_param->internalCsp); @@ -196,12 +197,12 @@ if (m_parallelFilter) { - if (m_param->bEnableSAO) + if (m_useSao) { for(int row = 0; row < numRows; row++) { if (!m_parallelFilter[row].m_sao.create(m_param, (row == 0 ? 1 : 0))) - m_param->bEnableSAO = 0; + m_useSao = 0; else { if (row != 0) @@ -235,7 +236,7 @@ { for(int row = 0; row < m_numRows; row++) { - if (m_param->bEnableSAO) + if (m_useSao) m_parallelFilter[row].m_sao.startSlice(frame, initState); m_parallelFilter[row].m_lastCol.set(0); @@ -245,7 +246,7 @@ } // Reset SAO common statistics - if (m_param->bEnableSAO) + if (m_useSao) m_parallelFilter[0].m_sao.resetStats(); } } @@ -472,11 +473,11 @@ deblockCTU(ctuPrev, cuGeoms[ctuGeomMap[cuAddr - 1]], Deblock::EDGE_HOR); // When SAO Disable, setting column counter here - if (!m_frameFilter->m_param->bEnableSAO & !ctuPrev->m_bFirstRowInSlice) + if (!m_frameFilter->m_useSao & !ctuPrev->m_bFirstRowInSlice) m_prevRow->processPostCu(col - 1); } - if (m_frameFilter->m_param->bEnableSAO) + if (m_frameFilter->m_useSao) { // Save SAO bottom row reference pixels copySaoAboveRef(ctuPrev, reconPic, cuAddr - 1, col - 1); @@ -514,12 +515,12 @@ deblockCTU(ctuPrev, cuGeoms[ctuGeomMap[cuAddr]], Deblock::EDGE_HOR); // When SAO Disable, setting column counter here - if (!m_frameFilter->m_param->bEnableSAO & !ctuPrev->m_bFirstRowInSlice) + if (!m_frameFilter->m_useSao & !ctuPrev->m_bFirstRowInSlice) m_prevRow->processPostCu(numCols - 1); } // TODO: move processPostCu() into processSaoUnitCu() - if (m_frameFilter->m_param->bEnableSAO) + if (m_frameFilter->m_useSao) { const CUData* ctu = m_encData->getPicCTU(m_rowAddr + numCols - 2); @@ -570,7 +571,7 @@ m_frameEncoder->m_cuStats.countLoopFilter++; #endif - if (!m_param->bEnableLoopFilter && !m_param->bEnableSAO) + if (!m_param->bEnableLoopFilter && !m_useSao) { processPostRow(row); return; @@ -596,7 +597,7 @@ x265_log(m_param, X265_LOG_WARNING, "detected ParallelFilter race condition on last row\n"); /* Apply SAO on last row of CUs, because we always apply SAO on row[X-1] */ - if (m_param->bEnableSAO) + if (m_useSao) { for(int col = 0; col < m_numCols; col++) { @@ -634,7 +635,7 @@ if (numRowFinished == m_numRows) { - if (m_param->bEnableSAO) + if (m_useSao) { // Merge numNoSao into RootNode (Node0) for(int i = 1; i < m_numRows; i++)
View file
x265_3.1.2.tar.gz/source/encoder/framefilter.h -> x265_3.2.tar.gz/source/encoder/framefilter.h
Changed
@@ -46,6 +46,7 @@ x265_param* m_param; Frame* m_frame; + int m_useSao; FrameEncoder* m_frameEncoder; int m_hChromaShift; int m_vChromaShift;
View file
x265_3.1.2.tar.gz/source/encoder/motion.cpp -> x265_3.2.tar.gz/source/encoder/motion.cpp
Changed
@@ -104,6 +104,8 @@ ctuAddr = -1; absPartIdx = -1; searchMethod = X265_HEX_SEARCH; + searchMethodL0 = X265_HEX_SEARCH; + searchMethodL1 = X265_HEX_SEARCH; subpelRefine = 2; blockwidth = blockheight = 0; blockOffset = 0; @@ -162,7 +164,7 @@ } /* Called by lookahead, luma only, no use of PicYuv */ -void MotionEstimate::setSourcePU(pixel *fencY, intptr_t stride, intptr_t offset, int pwidth, int pheight, const int method, const int refine) +void MotionEstimate::setSourcePU(pixel *fencY, intptr_t stride, intptr_t offset, int pwidth, int pheight, const int method, const int searchL0, const int searchL1, const int refine) { partEnum = partitionFromSizes(pwidth, pheight); X265_CHECK(LUMA_4x4 != partEnum, "4x4 inter partition detected!\n"); @@ -179,6 +181,8 @@ /* Search params */ searchMethod = method; + searchMethodL0 = searchL0; + searchMethodL1 = searchL1; subpelRefine = refine; /* copy PU block into cache */ @@ -363,12 +367,13 @@ int & bPointNr, int & bDistance, int earlyExitIters, - int merange) + int merange, + int hme) { ALIGN_VAR_16(int, costs[16]); pixel* fenc = fencPUYuv.m_buf[0]; - pixel* fref = ref->fpelPlane[0] + blockOffset; - intptr_t stride = ref->lumaStride; + pixel* fref = (hme? ref->fpelLowerResPlane[0] : ref->fpelPlane[0]) + blockOffset; + intptr_t stride = hme? ref->lumaStride / 2 : ref->lumaStride; MV omv = bmv; int saved = bcost; @@ -743,9 +748,10 @@ pixel * srcReferencePlane) { ALIGN_VAR_16(int, costs[16]); + bool hme = srcReferencePlane && srcReferencePlane == ref->fpelLowerResPlane[0]; if (ctuAddr >= 0) blockOffset = ref->reconPic->getLumaAddr(ctuAddr, absPartIdx) - ref->reconPic->getLumaAddr(0); - intptr_t stride = ref->lumaStride; + intptr_t stride = hme ? ref->lumaStride / 2 : ref->lumaStride; pixel* fenc = fencPUYuv.m_buf[0]; pixel* fref = srcReferencePlane == 0 ? ref->fpelPlane[0] + blockOffset : srcReferencePlane + blockOffset; @@ -767,7 +773,7 @@ int bprecost; if (ref->isLowres) - bprecost = ref->lowresQPelCost(fenc, blockOffset, pmv, sad); + bprecost = ref->lowresQPelCost(fenc, blockOffset, pmv, sad, hme); else bprecost = subpelCompare(ref, pmv, sad); @@ -808,7 +814,8 @@ pmv = pmv.roundToFPel(); MV omv = bmv; // current search origin or starting point - switch (searchMethod) + int search = ref->isHMELowres ? (hme ? searchMethodL0 : searchMethodL1) : searchMethod; + switch (search) { case X265_DIA_SEARCH: { @@ -1128,7 +1135,7 @@ int bDistance = 0; const int EarlyExitIters = 3; - StarPatternSearch(ref, mvmin, mvmax, bmv, bcost, bPointNr, bDistance, EarlyExitIters, merange); + StarPatternSearch(ref, mvmin, mvmax, bmv, bcost, bPointNr, bDistance, EarlyExitIters, merange, hme); if (bDistance == 1) { // if best distance was only 1, check two missing points. If no new point is found, stop @@ -1201,7 +1208,7 @@ bDistance = 0; bPointNr = 0; const int MaxIters = 32; - StarPatternSearch(ref, mvmin, mvmax, bmv, bcost, bPointNr, bDistance, MaxIters, merange); + StarPatternSearch(ref, mvmin, mvmax, bmv, bcost, bPointNr, bDistance, MaxIters, merange, hme); if (bDistance == 1) { @@ -1391,11 +1398,20 @@ { // dead slow exhaustive search, but at least it uses sad_x4() MV tmv; - for (tmv.y = mvmin.y; tmv.y <= mvmax.y; tmv.y++) + int32_t mvmin_y = mvmin.y, mvmin_x = mvmin.x, mvmax_y = mvmax.y, mvmax_x = mvmax.x; + if (ref->isHMELowres) + { + merange = (merange < 0 ? -merange : merange); + mvmin_y = X265_MAX(mvmin.y, -merange); + mvmin_x = X265_MAX(mvmin.x, -merange); + mvmax_y = X265_MIN(mvmax.y, merange); + mvmax_x = X265_MIN(mvmax.x, merange); + } + for (tmv.y = mvmin_y; tmv.y <= mvmax_y; tmv.y++) { - for (tmv.x = mvmin.x; tmv.x <= mvmax.x; tmv.x++) + for (tmv.x = mvmin_x; tmv.x <= mvmax_x; tmv.x++) { - if (tmv.x + 3 <= mvmax.x) + if (tmv.x + 3 <= mvmax_x) { pixel *pix_base = fref + tmv.y * stride + tmv.x; sad_x4(fenc, @@ -1463,12 +1479,12 @@ if ((qmv.y < qmvmin.y) | (qmv.y > qmvmax.y)) continue; - int cost = ref->lowresQPelCost(fenc, blockOffset, qmv, sad) + mvcost(qmv); + int cost = ref->lowresQPelCost(fenc, blockOffset, qmv, sad, hme) + mvcost(qmv); COPY2_IF_LT(bcost, cost, bdir, i); } bmv += square1[bdir] * 2; - bcost = ref->lowresQPelCost(fenc, blockOffset, bmv, satd) + mvcost(bmv); + bcost = ref->lowresQPelCost(fenc, blockOffset, bmv, satd, hme) + mvcost(bmv); bdir = 0; for (int i = 1; i <= wl.qpel_dirs; i++) @@ -1479,7 +1495,7 @@ if ((qmv.y < qmvmin.y) | (qmv.y > qmvmax.y)) continue; - int cost = ref->lowresQPelCost(fenc, blockOffset, qmv, satd) + mvcost(qmv); + int cost = ref->lowresQPelCost(fenc, blockOffset, qmv, satd, hme) + mvcost(qmv); COPY2_IF_LT(bcost, cost, bdir, i); }
View file
x265_3.1.2.tar.gz/source/encoder/motion.h -> x265_3.2.tar.gz/source/encoder/motion.h
Changed
@@ -44,6 +44,8 @@ int absPartIdx; // part index of PU, including CU offset within CTU int searchMethod; + int searchMethodL0; + int searchMethodL1; int subpelRefine; int blockwidth; @@ -76,7 +78,7 @@ /* Methods called at slice setup */ - void setSourcePU(pixel *fencY, intptr_t stride, intptr_t offset, int pwidth, int pheight, const int searchMethod, const int subpelRefine); + void setSourcePU(pixel *fencY, intptr_t stride, intptr_t offset, int pwidth, int pheight, const int searchMethod, const int searchL0, const int searchL1, const int subpelRefine); void setSourcePU(const Yuv& srcFencYuv, int ctuAddr, int cuPartIdx, int puPartIdx, int pwidth, int pheight, const int searchMethod, const int subpelRefine, bool bChroma); /* buf*() and motionEstimate() methods all use cached fenc pixels and thus @@ -107,7 +109,8 @@ int & bPointNr, int & bDistance, int earlyExitIters, - int merange); + int merange, + int hme); }; }
View file
x265_3.1.2.tar.gz/source/encoder/ratecontrol.cpp -> x265_3.2.tar.gz/source/encoder/ratecontrol.cpp
Changed
@@ -2116,6 +2116,9 @@ if ((underflow < epsilon || rce->isFadeEnd) && !isFrameDone) { init(*m_curSlice->m_sps); + // Reduce tune complexity factor for scenes that follow blank frames + double tuneCplxFactor = (m_ncu > 3600 && m_param->rc.cuTree && !m_param->rc.hevcAq) ? 2.5 : m_param->rc.hevcAq ? 1.5 : m_isGrainEnabled ? 1.9 : 1.0; + m_cplxrSum /= tuneCplxFactor; m_shortTermCplxSum = rce->lastSatd / (CLIP_DURATION(m_frameDuration) / BASE_FRAME_DURATION); m_shortTermCplxCount = 1; m_isAbrReset = true;
View file
x265_3.1.2.tar.gz/source/encoder/search.cpp -> x265_3.2.tar.gz/source/encoder/search.cpp
Changed
@@ -2096,13 +2096,16 @@ const MV* amvp = interMode.amvpCand[list][ref]; int mvpIdx = selectMVP(interMode.cu, pu, amvp, list, ref); - MV mvmin, mvmax, outmv, mvp = amvp[mvpIdx]; + bool bLowresMVP = false; + MV mvmin, mvmax, outmv, mvp = amvp[mvpIdx], mvp_lowres; if (!m_param->analysisSave && !m_param->analysisLoad) /* Prevents load/save outputs from diverging if lowresMV is not available */ { MV lmv = getLowresMV(interMode.cu, pu, list, ref); if (lmv.notZero()) mvc[numMvc++] = lmv; + if (m_param->bEnableHME) + mvp_lowres = lmv; } setSearchRange(interMode.cu, mvp, m_param->searchRange, mvmin, mvmax); @@ -2110,11 +2113,28 @@ int satdCost = m_me.motionEstimate(&m_slice->m_mref[list][ref], mvmin, mvmax, mvp, numMvc, mvc, m_param->searchRange, outmv, m_param->maxSlices, m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0); + if (m_param->bEnableHME && mvp_lowres.notZero() && mvp_lowres != mvp) + { + MV outmv_lowres; + setSearchRange(interMode.cu, mvp_lowres, m_param->searchRange, mvmin, mvmax); + int lowresMvCost = m_me.motionEstimate(&m_slice->m_mref[list][ref], mvmin, mvmax, mvp_lowres, numMvc, mvc, m_param->searchRange, outmv_lowres, m_param->maxSlices, + m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0); + if (lowresMvCost < satdCost) + { + outmv = outmv_lowres; + satdCost = lowresMvCost; + bLowresMVP = true; + } + } /* Get total cost of partition, but only include MV bit cost once */ bits += m_me.bitcost(outmv); uint32_t mvCost = m_me.mvcost(outmv); uint32_t cost = (satdCost - mvCost) + m_rdCost.getCost(bits); + /* Update LowresMVP to best AMVP cand*/ + if (bLowresMVP) + updateMVP(amvp[mvpIdx], outmv, bits, cost, mvp_lowres); + /* Refine MVP selection, updates: mvpIdx, bits, cost */ mvp = checkBestMVP(amvp, outmv, mvpIdx, bits, cost); @@ -2132,23 +2152,27 @@ bestME[list].mvCost = mvCost; } } -void Search::searchMV(Mode& interMode, const PredictionUnit& pu, int list, int ref, MV& outmv, MV mvp, int numMvc, MV* mvc) +void Search::searchMV(Mode& interMode, int list, int ref, MV& outmv, MV mvp[3], int numMvc, MV* mvc) { CUData& cu = interMode.cu; - const Slice *slice = m_slice; - MV mv; - if (m_param->interRefine == 1) - mv = mvp; - else - mv = cu.m_mv[list][pu.puAbsPartIdx]; + MV mv, mvmin, mvmax; cu.clipMv(mv); - MV mvmin, mvmax; - setSearchRange(cu, mv, m_param->searchRange, mvmin, mvmax); - if (m_param->interRefine == 1) - m_me.motionEstimate(&m_slice->m_mref[list][ref], mvmin, mvmax, mv, numMvc, mvc, m_param->searchRange, outmv, m_param->maxSlices, + int cand = 0, bestcost = INT_MAX; + do + { + if (cand && (mvp[cand] == mvp[cand - 1] || (cand == 2 && mvp[cand] == mvp[cand - 2]))) + continue; + MV bestMV; + mv = mvp[cand]; + setSearchRange(cu, mv, m_param->searchRange, mvmin, mvmax); + int cost = m_me.motionEstimate(&m_slice->m_mref[list][ref], mvmin, mvmax, mv, numMvc, mvc, m_param->searchRange, bestMV, m_param->maxSlices, m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0); - else - m_me.refineMV(&slice->m_mref[list][ref], mvmin, mvmax, mv, outmv); + if (bestcost > cost) + { + bestcost = cost; + outmv = bestMV; + } + }while (++cand < m_param->mvRefine); } /* find the best inter prediction for each PU of specified mode */ void Search::predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bChromaMC, uint32_t refMasks[2]) @@ -2209,7 +2233,6 @@ int ref = -1; if (useAsMVP) ref = interDataCTU->refIdx[list][cuIdx + puIdx]; - else ref = bestME[list].ref; if (ref < 0) @@ -2223,13 +2246,7 @@ const MV* amvp = interMode.amvpCand[list][ref]; int mvpIdx = selectMVP(cu, pu, amvp, list, ref); MV mvmin, mvmax, outmv, mvp; - if (useAsMVP) - { - mvp = interDataCTU->mv[list][cuIdx + puIdx].word; - mvpIdx = interDataCTU->mvpIdx[list][cuIdx + puIdx]; - } - else - mvp = amvp[mvpIdx]; + mvp = amvp[mvpIdx]; if (m_param->searchMethod == X265_SEA) { int puX = puIdx & 1; @@ -2239,11 +2256,47 @@ } setSearchRange(cu, mvp, m_param->searchRange, mvmin, mvmax); MV mvpIn = mvp; + int satdCost; if (m_param->analysisMultiPassRefine && m_param->rc.bStatRead && mvpIdx == bestME[list].mvpIdx) mvpIn = bestME[list].mv; - - int satdCost = m_me.motionEstimate(&slice->m_mref[list][ref], mvmin, mvmax, mvpIn, numMvc, mvc, m_param->searchRange, outmv, m_param->maxSlices, - m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0); + if (useAsMVP) + { + MV bestmv, mvpSel[3]; + int mvpIdxSel[3]; + satdCost = m_me.COST_MAX; + mvpSel[0] = interDataCTU->mv[list][cuIdx + puIdx].word; + mvpIdxSel[0] = interDataCTU->mvpIdx[list][cuIdx + puIdx]; + if (m_param->mvRefine > 1) + { + mvpSel[1] = interMode.amvpCand[list][ref][mvpIdx]; + mvpIdxSel[1] = mvpIdx; + if (m_param->mvRefine > 2) + { + mvpSel[2] = interMode.amvpCand[list][ref][!mvpIdx]; + mvpIdxSel[2] = !mvpIdx; + } + } + for (int cand = 0; cand < m_param->mvRefine; cand++) + { + if (cand && (mvpSel[cand] == mvpSel[cand - 1] || (cand == 2 && mvpSel[cand] == mvpSel[cand - 2]))) + continue; + setSearchRange(cu, mvp, m_param->searchRange, mvmin, mvmax); + int bcost = m_me.motionEstimate(&m_slice->m_mref[list][ref], mvmin, mvmax, mvpSel[cand], numMvc, mvc, m_param->searchRange, bestmv, m_param->maxSlices, + m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0); + if (satdCost > bcost) + { + satdCost = bcost; + outmv = bestmv; + mvp = mvpSel[cand]; + mvpIdx = mvpIdxSel[cand]; + } + } + } + else + { + satdCost = m_me.motionEstimate(&slice->m_mref[list][ref], mvmin, mvmax, mvpIn, numMvc, mvc, m_param->searchRange, outmv, m_param->maxSlices, + m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0); + } /* Get total cost of partition, but only include MV bit cost once */ bits += m_me.bitcost(outmv); @@ -2346,13 +2399,16 @@ const MV* amvp = interMode.amvpCand[list][ref]; int mvpIdx = selectMVP(cu, pu, amvp, list, ref); - MV mvmin, mvmax, outmv, mvp = amvp[mvpIdx]; + MV mvmin, mvmax, outmv, mvp = amvp[mvpIdx], mvp_lowres; + bool bLowresMVP = false; if (!m_param->analysisSave && !m_param->analysisLoad) /* Prevents load/save outputs from diverging when lowresMV is not available */ { MV lmv = getLowresMV(cu, pu, list, ref); if (lmv.notZero()) mvc[numMvc++] = lmv; + if (m_param->bEnableHME) + mvp_lowres = lmv; } if (m_param->searchMethod == X265_SEA) { @@ -2365,10 +2421,27 @@ int satdCost = m_me.motionEstimate(&slice->m_mref[list][ref], mvmin, mvmax, mvp, numMvc, mvc, m_param->searchRange, outmv, m_param->maxSlices, m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0); + if (m_param->bEnableHME && mvp_lowres.notZero() && mvp_lowres != mvp) + { + MV outmv_lowres; + setSearchRange(cu, mvp_lowres, m_param->searchRange, mvmin, mvmax); + int lowresMvCost = m_me.motionEstimate(&slice->m_mref[list][ref], mvmin, mvmax, mvp_lowres, numMvc, mvc, m_param->searchRange, outmv_lowres, m_param->maxSlices, + m_param->bSourceReferenceEstimation ? m_slice->m_refFrameList[list][ref]->m_fencPic->getLumaAddr(0) : 0); + if (lowresMvCost < satdCost) + { + outmv = outmv_lowres; + satdCost = lowresMvCost; + bLowresMVP = true; + } + } + /* Get total cost of partition, but only include MV bit cost once */ bits += m_me.bitcost(outmv); uint32_t mvCost = m_me.mvcost(outmv); uint32_t cost = (satdCost - mvCost) + m_rdCost.getCost(bits); + /* Update LowresMVP to best AMVP cand*/ + if (bLowresMVP) + updateMVP(amvp[mvpIdx], outmv, bits, cost, mvp_lowres); /* Refine MVP selection, updates: mvpIdx, bits, cost */ mvp = checkBestMVP(amvp, outmv, mvpIdx, bits, cost); @@ -2631,6 +2704,15 @@ return amvpCand[mvpIdx]; } +/* Update to default MVP when using an alternative mvp */ +void Search::updateMVP(const MV amvp, const MV& mv, uint32_t& outBits, uint32_t& outCost, const MV& alterMVP) +{ + int diffBits = m_me.bitcost(mv, amvp) - m_me.bitcost(mv, alterMVP); + uint32_t origOutBits = outBits; + outBits = origOutBits + diffBits; + outCost = (outCost - m_rdCost.getCost(origOutBits)) + m_rdCost.getCost(outBits); +} + void Search::setSearchRange(const CUData& cu, const MV& mvp, int merange, MV& mvmin, MV& mvmax) const { MV dist((int32_t)merange << 2, (int32_t)merange << 2);
View file
x265_3.1.2.tar.gz/source/encoder/search.h -> x265_3.2.tar.gz/source/encoder/search.h
Changed
@@ -310,7 +310,7 @@ // estimation inter prediction (non-skip) void predInterSearch(Mode& interMode, const CUGeom& cuGeom, bool bChromaMC, uint32_t masks[2]); - void searchMV(Mode& interMode, const PredictionUnit& pu, int list, int ref, MV& outmv, MV mvp, int numMvc, MV* mvc); + void searchMV(Mode& interMode, int list, int ref, MV& outmv, MV mvp[3], int numMvc, MV* mvc); // encode residual and compute rd-cost for inter mode void encodeResAndCalcRdInterCU(Mode& interMode, const CUGeom& cuGeom); void encodeResAndCalcRdSkipCU(Mode& interMode); @@ -425,6 +425,7 @@ void setSearchRange(const CUData& cu, const MV& mvp, int merange, MV& mvmin, MV& mvmax) const; uint32_t mergeEstimation(CUData& cu, const CUGeom& cuGeom, const PredictionUnit& pu, int puIdx, MergeData& m); static void getBlkBits(PartSize cuMode, bool bPSlice, int puIdx, uint32_t lastMode, uint32_t blockBit[3]); + void updateMVP(const MV amvp, const MV& mv, uint32_t& outBits, uint32_t& outCost, const MV& alterMVP); /* intra helper functions */ enum { MAX_RD_INTRA_MODES = 16 };
View file
x265_3.1.2.tar.gz/source/encoder/slicetype.cpp -> x265_3.2.tar.gz/source/encoder/slicetype.cpp
Changed
@@ -85,6 +85,140 @@ } // end anonymous namespace +void edgeFilter(Frame *curFrame, pixel *pic1, pixel *pic2, pixel *pic3, intptr_t stride, int height, int width) +{ + pixel *src = (pixel*)curFrame->m_fencPic->m_picOrg[0]; + pixel *edgePic = pic1 + curFrame->m_fencPic->m_lumaMarginY * stride + curFrame->m_fencPic->m_lumaMarginX; + pixel *refPic = pic2 + curFrame->m_fencPic->m_lumaMarginY * stride + curFrame->m_fencPic->m_lumaMarginX; + pixel *edgeTheta = pic3 + curFrame->m_fencPic->m_lumaMarginY * stride + curFrame->m_fencPic->m_lumaMarginX; + + for (int i = 0; i < height; i++) + { + memcpy(edgePic, src, width * sizeof(pixel)); + memcpy(refPic, src, width * sizeof(pixel)); + src += stride; + edgePic += stride; + refPic += stride; + } + + //Applying Gaussian filter on the picture + src = (pixel*)curFrame->m_fencPic->m_picOrg[0]; + refPic = pic2 + curFrame->m_fencPic->m_lumaMarginY * stride + curFrame->m_fencPic->m_lumaMarginX; + pixel pixelValue = 0; + + for (int rowNum = 0; rowNum < height; rowNum++) + { + for (int colNum = 0; colNum < width; colNum++) + { + if ((rowNum >= 2) && (colNum >= 2) && (rowNum != height - 2) && (colNum != width - 2)) //Ignoring the border pixels of the picture + { + /* 5x5 Gaussian filter + [2 4 5 4 2] + 1 [4 9 12 9 4] + --- [5 12 15 12 5] + 159 [4 9 12 9 4] + [2 4 5 4 2]*/ + + const intptr_t rowOne = (rowNum - 2)*stride, colOne = colNum - 2; + const intptr_t rowTwo = (rowNum - 1)*stride, colTwo = colNum - 1; + const intptr_t rowThree = rowNum * stride, colThree = colNum; + const intptr_t rowFour = (rowNum + 1)*stride, colFour = colNum + 1; + const intptr_t rowFive = (rowNum + 2)*stride, colFive = colNum + 2; + const intptr_t index = (rowNum*stride) + colNum; + + pixelValue = ((2 * src[rowOne + colOne] + 4 * src[rowOne + colTwo] + 5 * src[rowOne + colThree] + 4 * src[rowOne + colFour] + 2 * src[rowOne + colFive] + + 4 * src[rowTwo + colOne] + 9 * src[rowTwo + colTwo] + 12 * src[rowTwo + colThree] + 9 * src[rowTwo + colFour] + 4 * src[rowTwo + colFive] + + 5 * src[rowThree + colOne] + 12 * src[rowThree + colTwo] + 15 * src[rowThree + colThree] + 12 * src[rowThree + colFour] + 5 * src[rowThree + colFive] + + 4 * src[rowFour + colOne] + 9 * src[rowFour + colTwo] + 12 * src[rowFour + colThree] + 9 * src[rowFour + colFour] + 4 * src[rowFour + colFive] + + 2 * src[rowFive + colOne] + 4 * src[rowFive + colTwo] + 5 * src[rowFive + colThree] + 4 * src[rowFive + colFour] + 2 * src[rowFive + colFive]) / 159); + refPic[index] = pixelValue; + } + } + } + +#if HIGH_BIT_DEPTH //10-bit build + float threshold = 1023; + pixel whitePixel = 1023; +#else + float threshold = 255; + pixel whitePixel = 255; +#endif +#define PI 3.14159265 + + float gradientH = 0, gradientV = 0, radians = 0, theta = 0; + float gradientMagnitude = 0; + pixel blackPixel = 0; + edgePic = pic1 + curFrame->m_fencPic->m_lumaMarginY * stride + curFrame->m_fencPic->m_lumaMarginX; + //Applying Sobel filter on the gaussian filtered picture + for (int rowNum = 0; rowNum < height; rowNum++) + { + for (int colNum = 0; colNum < width; colNum++) + { + edgeTheta[(rowNum*stride) + colNum] = 0; + if ((rowNum != 0) && (colNum != 0) && (rowNum != height - 1) && (colNum != width - 1)) //Ignoring the border pixels of the picture + { + /*Horizontal and vertical gradients + [ -3 0 3 ] [-3 -10 -3 ] + gH = [ -10 0 10] gV = [ 0 0 0 ] + [ -3 0 3 ] [ 3 10 3 ]*/ + + const intptr_t rowOne = (rowNum - 1)*stride, colOne = colNum -1; + const intptr_t rowTwo = rowNum * stride, colTwo = colNum; + const intptr_t rowThree = (rowNum + 1)*stride, colThree = colNum + 1; + const intptr_t index = (rowNum*stride) + colNum; + + gradientH = (float)(-3 * refPic[rowOne + colOne] + 3 * refPic[rowOne + colThree] - 10 * refPic[rowTwo + colOne] + 10 * refPic[rowTwo + colThree] - 3 * refPic[rowThree + colOne] + 3 * refPic[rowThree + colThree]); + gradientV = (float)(-3 * refPic[rowOne + colOne] - 10 * refPic[rowOne + colTwo] - 3 * refPic[rowOne + colThree] + 3 * refPic[rowThree + colOne] + 10 * refPic[rowThree + colTwo] + 3 * refPic[rowThree + colThree]); + + gradientMagnitude = sqrtf(gradientH * gradientH + gradientV * gradientV); + radians = atan2(gradientV, gradientH); + theta = (float)((radians * 180) / PI); + if (theta < 0) + theta = 180 + theta; + edgeTheta[(rowNum*stride) + colNum] = (pixel)theta; + + edgePic[index] = gradientMagnitude >= threshold ? whitePixel : blackPixel; + } + } + } +} + +//Find the angle of a block by averaging the pixel angles +inline void findAvgAngle(const pixel* block, intptr_t stride, uint32_t size, uint32_t &angle) +{ + int sum = 0; + for (uint32_t y = 0; y < size; y++) + { + for (uint32_t x = 0; x < size; x++) + { + sum += block[x]; + } + block += stride; + } + angle = sum / (size*size); +} + +uint32_t LookaheadTLD::edgeDensityCu(Frame* curFrame,pixel *edgeImage, pixel *edgeTheta, uint32_t &avgAngle, uint32_t blockX, uint32_t blockY, uint32_t qgSize) +{ + intptr_t srcStride = curFrame->m_fencPic->m_stride; + intptr_t blockOffsetLuma = blockX + (blockY * srcStride); + int plane = 0; // Sobel filter is applied only on Y component + uint32_t var; + + if (qgSize == 8) + { + findAvgAngle(edgeTheta + blockOffsetLuma, srcStride, qgSize, avgAngle); + var = acEnergyVar(curFrame, primitives.cu[BLOCK_8x8].var(edgeImage + blockOffsetLuma, srcStride), 6, plane); + } + else + { + findAvgAngle(edgeTheta + blockOffsetLuma, srcStride, 16, avgAngle); + var = acEnergyVar(curFrame, primitives.cu[BLOCK_16x16].var(edgeImage + blockOffsetLuma, srcStride), 8, plane); + } + x265_emms(); + return var; +} + /* Find the total AC energy of each block in all planes */ uint32_t LookaheadTLD::acEnergyCu(Frame* curFrame, uint32_t blockX, uint32_t blockY, int csp, uint32_t qgSize) { @@ -303,146 +437,203 @@ curFrame->m_lowres.wp_sum[y] = 0; } - /* Calculate Qp offset for each 16x16 or 8x8 block in the frame */ - if ((param->rc.aqMode == X265_AQ_NONE || param->rc.aqStrength == 0) || (param->rc.bStatRead && param->rc.cuTree && IS_REFERENCED(curFrame))) + if (!(param->rc.bStatRead && param->rc.cuTree && IS_REFERENCED(curFrame))) { - if (param->rc.aqMode && param->rc.aqStrength == 0) + /* Calculate Qp offset for each 16x16 or 8x8 block in the frame */ + if (param->rc.aqMode == X265_AQ_NONE || param->rc.aqStrength == 0) { - if (quantOffsets) + if (param->rc.aqMode && param->rc.aqStrength == 0) { - for (int cuxy = 0; cuxy < blockCount; cuxy++) + if (quantOffsets) + { + for (int cuxy = 0; cuxy < blockCount; cuxy++) + { + curFrame->m_lowres.qpCuTreeOffset[cuxy] = curFrame->m_lowres.qpAqOffset[cuxy] = quantOffsets[cuxy]; + curFrame->m_lowres.invQscaleFactor[cuxy] = x265_exp2fix8(curFrame->m_lowres.qpCuTreeOffset[cuxy]); + } + } + else { - curFrame->m_lowres.qpCuTreeOffset[cuxy] = curFrame->m_lowres.qpAqOffset[cuxy] = quantOffsets[cuxy]; - curFrame->m_lowres.invQscaleFactor[cuxy] = x265_exp2fix8(curFrame->m_lowres.qpCuTreeOffset[cuxy]); + memset(curFrame->m_lowres.qpCuTreeOffset, 0, blockCount * sizeof(double)); + memset(curFrame->m_lowres.qpAqOffset, 0, blockCount * sizeof(double)); + for (int cuxy = 0; cuxy < blockCount; cuxy++) + curFrame->m_lowres.invQscaleFactor[cuxy] = 256; } } - else + + /* Need variance data for weighted prediction and dynamic refinement*/ + if (param->bEnableWeightedPred || param->bEnableWeightedBiPred) { - memset(curFrame->m_lowres.qpCuTreeOffset, 0, blockCount * sizeof(double)); - memset(curFrame->m_lowres.qpAqOffset, 0, blockCount * sizeof(double)); - for (int cuxy = 0; cuxy < blockCount; cuxy++) - curFrame->m_lowres.invQscaleFactor[cuxy] = 256; + for (int blockY = 0; blockY < maxRow; blockY += loopIncr) + for (int blockX = 0; blockX < maxCol; blockX += loopIncr) + acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize); } } - - /* Need variance data for weighted prediction and dynamic refinement*/ - if (param->bEnableWeightedPred || param->bEnableWeightedBiPred) - { - for (int blockY = 0; blockY < maxRow; blockY += loopIncr) - for (int blockX = 0; blockX < maxCol; blockX += loopIncr) - acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize); - } - } - else - { - if (param->rc.hevcAq) - { - // New method for calculating variance and qp offset - xPreanalyze(curFrame); - } else { - int blockXY = 0; - double avg_adj_pow2 = 0, avg_adj = 0, qp_adj = 0; - double bias_strength = 0.f; - double strength = 0.f; - if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE || param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED) + if (param->rc.hevcAq) + { + // New method for calculating variance and qp offset + xPreanalyze(curFrame); + } + else { - double bit_depth_correction = 1.f / (1 << (2 * (X265_DEPTH - 8))); +#define AQ_EDGE_BIAS 0.5 +#define EDGE_INCLINATION 45 + uint32_t numCuInHeight = (maxRow + param->maxCUSize - 1) / param->maxCUSize; + int maxHeight = numCuInHeight * param->maxCUSize; + intptr_t stride = curFrame->m_fencPic->m_stride; + pixel *edgePic = X265_MALLOC(pixel, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2))); + pixel *gaussianPic = X265_MALLOC(pixel, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2))); + pixel *thetaPic = X265_MALLOC(pixel, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2))); + memset(edgePic, 0, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2)) * sizeof(pixel)); + memset(gaussianPic, 0, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2)) * sizeof(pixel)); + memset(thetaPic, 0, stride * (maxHeight + (curFrame->m_fencPic->m_lumaMarginY * 2)) * sizeof(pixel)); + if (param->rc.aqMode == X265_AQ_EDGE) + edgeFilter(curFrame, edgePic, gaussianPic, thetaPic, stride, maxRow, maxCol); + + int blockXY = 0, inclinedEdge = 0; + double avg_adj_pow2 = 0, avg_adj = 0, qp_adj = 0; + double bias_strength = 0.f; + double strength = 0.f; + if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE || param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED || param->rc.aqMode == X265_AQ_EDGE) + { + double bit_depth_correction = 1.f / (1 << (2 * (X265_DEPTH - 8))); + for (int blockY = 0; blockY < maxRow; blockY += loopIncr) + { + for (int blockX = 0; blockX < maxCol; blockX += loopIncr) + { + uint32_t energy, edgeDensity, avgAngle; + energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize); + if (param->rc.aqMode == X265_AQ_EDGE) + { + pixel *edgeImage = edgePic + curFrame->m_fencPic->m_lumaMarginY * stride + curFrame->m_fencPic->m_lumaMarginX; + pixel *edgeTheta = thetaPic + curFrame->m_fencPic->m_lumaMarginY * stride + curFrame->m_fencPic->m_lumaMarginX; + edgeDensity = edgeDensityCu(curFrame, edgeImage, edgeTheta, avgAngle, blockX, blockY, param->rc.qgSize); + if (edgeDensity) + { + qp_adj = pow(edgeDensity * bit_depth_correction + 1, 0.1); + //Increasing the QP of a block if its edge orientation lies around the multiples of 45 degree + if ((avgAngle >= EDGE_INCLINATION - 15 && avgAngle <= EDGE_INCLINATION + 15) || (avgAngle >= EDGE_INCLINATION + 75 && avgAngle <= EDGE_INCLINATION + 105)) + curFrame->m_lowres.edgeInclined[blockXY] = 1; + else + curFrame->m_lowres.edgeInclined[blockXY] = 0; + } + else + { + qp_adj = pow(energy * bit_depth_correction + 1, 0.1); + curFrame->m_lowres.edgeInclined[blockXY] = 0; + } + } + else + qp_adj = pow(energy * bit_depth_correction + 1, 0.1); + curFrame->m_lowres.qpCuTreeOffset[blockXY] = qp_adj; + avg_adj += qp_adj; + avg_adj_pow2 += qp_adj * qp_adj; + blockXY++; + } + } + avg_adj /= blockCount; + avg_adj_pow2 /= blockCount; + strength = param->rc.aqStrength * avg_adj; + avg_adj = avg_adj - 0.5f * (avg_adj_pow2 - modeTwoConst) / avg_adj; + bias_strength = param->rc.aqStrength; + } + else + strength = param->rc.aqStrength * 1.0397f; + X265_FREE(edgePic); + X265_FREE(gaussianPic); + X265_FREE(thetaPic); + blockXY = 0; for (int blockY = 0; blockY < maxRow; blockY += loopIncr) { for (int blockX = 0; blockX < maxCol; blockX += loopIncr) { - uint32_t energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize); - qp_adj = pow(energy * bit_depth_correction + 1, 0.1); + if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED) + { + qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY]; + qp_adj = strength * (qp_adj - avg_adj) + bias_strength * (1.f - modeTwoConst / (qp_adj * qp_adj)); + } + else if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE) + { + qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY]; + qp_adj = strength * (qp_adj - avg_adj); + } + else if (param->rc.aqMode == X265_AQ_EDGE) + { + inclinedEdge = curFrame->m_lowres.edgeInclined[blockXY]; + qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY]; + if(inclinedEdge && (qp_adj - avg_adj > 0)) + qp_adj = ((strength + AQ_EDGE_BIAS) * (qp_adj - avg_adj)); + else + qp_adj = strength * (qp_adj - avg_adj); + } + else + { + uint32_t energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize); + qp_adj = strength * (X265_LOG2(X265_MAX(energy, 1)) - (modeOneConst + 2 * (X265_DEPTH - 8))); + } + + if (param->bHDROpt) + { + uint32_t sum = lumaSumCu(curFrame, blockX, blockY, param->rc.qgSize); + uint32_t lumaAvg = sum / (loopIncr * loopIncr); + if (lumaAvg < 301) + qp_adj += 3; + else if (lumaAvg >= 301 && lumaAvg < 367) + qp_adj += 2; + else if (lumaAvg >= 367 && lumaAvg < 434) + qp_adj += 1; + else if (lumaAvg >= 501 && lumaAvg < 567) + qp_adj -= 1; + else if (lumaAvg >= 567 && lumaAvg < 634) + qp_adj -= 2; + else if (lumaAvg >= 634 && lumaAvg < 701) + qp_adj -= 3; + else if (lumaAvg >= 701 && lumaAvg < 767) + qp_adj -= 4; + else if (lumaAvg >= 767 && lumaAvg < 834) + qp_adj -= 5; + else if (lumaAvg >= 834) + qp_adj -= 6; + } + if (quantOffsets != NULL) + qp_adj += quantOffsets[blockXY]; + curFrame->m_lowres.qpAqOffset[blockXY] = qp_adj; curFrame->m_lowres.qpCuTreeOffset[blockXY] = qp_adj; - avg_adj += qp_adj; - avg_adj_pow2 += qp_adj * qp_adj; + curFrame->m_lowres.invQscaleFactor[blockXY] = x265_exp2fix8(qp_adj); blockXY++; } } - avg_adj /= blockCount; - avg_adj_pow2 /= blockCount; - strength = param->rc.aqStrength * avg_adj; - avg_adj = avg_adj - 0.5f * (avg_adj_pow2 - modeTwoConst) / avg_adj; - bias_strength = param->rc.aqStrength; } - else - strength = param->rc.aqStrength * 1.0397f; + } - blockXY = 0; - for (int blockY = 0; blockY < maxRow; blockY += loopIncr) + if (param->rc.qgSize == 8) + { + for (int cuY = 0; cuY < heightInCU; cuY++) { - for (int blockX = 0; blockX < maxCol; blockX += loopIncr) + for (int cuX = 0; cuX < widthInCU; cuX++) { - if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE_BIASED) - { - qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY]; - qp_adj = strength * (qp_adj - avg_adj) + bias_strength * (1.f - modeTwoConst / (qp_adj * qp_adj)); - } - else if (param->rc.aqMode == X265_AQ_AUTO_VARIANCE) - { - qp_adj = curFrame->m_lowres.qpCuTreeOffset[blockXY]; - qp_adj = strength * (qp_adj - avg_adj); - } - else - { - uint32_t energy = acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize); - qp_adj = strength * (X265_LOG2(X265_MAX(energy, 1)) - (modeOneConst + 2 * (X265_DEPTH - 8))); - } - - if (param->bHDROpt) - { - uint32_t sum = lumaSumCu(curFrame, blockX, blockY, param->rc.qgSize); - uint32_t lumaAvg = sum / (loopIncr * loopIncr); - if (lumaAvg < 301) - qp_adj += 3; - else if (lumaAvg >= 301 && lumaAvg < 367) - qp_adj += 2; - else if (lumaAvg >= 367 && lumaAvg < 434) - qp_adj += 1; - else if (lumaAvg >= 501 && lumaAvg < 567) - qp_adj -= 1; - else if (lumaAvg >= 567 && lumaAvg < 634) - qp_adj -= 2; - else if (lumaAvg >= 634 && lumaAvg < 701) - qp_adj -= 3; - else if (lumaAvg >= 701 && lumaAvg < 767) - qp_adj -= 4; - else if (lumaAvg >= 767 && lumaAvg < 834) - qp_adj -= 5; - else if (lumaAvg >= 834) - qp_adj -= 6; - } - if (quantOffsets != NULL) - qp_adj += quantOffsets[blockXY]; - curFrame->m_lowres.qpAqOffset[blockXY] = qp_adj; - curFrame->m_lowres.qpCuTreeOffset[blockXY] = qp_adj; - curFrame->m_lowres.invQscaleFactor[blockXY] = x265_exp2fix8(qp_adj); - blockXY++; + const int cuXY = cuX + cuY * widthInCU; + curFrame->m_lowres.invQscaleFactor8x8[cuXY] = (curFrame->m_lowres.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4] + + curFrame->m_lowres.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4 + 1] + + curFrame->m_lowres.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4 + curFrame->m_lowres.maxBlocksInRowFullRes] + + curFrame->m_lowres.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4 + curFrame->m_lowres.maxBlocksInRowFullRes + 1]) / 4; } } } } - if (param->rc.qgSize == 8) + if (param->bEnableWeightedPred || param->bEnableWeightedBiPred) { - for (int cuY = 0; cuY < heightInCU; cuY++) + if (param->rc.bStatRead && param->rc.cuTree && IS_REFERENCED(curFrame)) { - for (int cuX = 0; cuX < widthInCU; cuX++) - { - const int cuXY = cuX + cuY * widthInCU; - curFrame->m_lowres.invQscaleFactor8x8[cuXY] = (curFrame->m_lowres.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4] + - curFrame->m_lowres.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4 + 1] + - curFrame->m_lowres.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4 + curFrame->m_lowres.maxBlocksInRowFullRes] + - curFrame->m_lowres.invQscaleFactor[cuX * 2 + cuY * widthInCU * 4 + curFrame->m_lowres.maxBlocksInRowFullRes + 1]) / 4; - } + for (int blockY = 0; blockY < maxRow; blockY += loopIncr) + for (int blockX = 0; blockX < maxCol; blockX += loopIncr) + acEnergyCu(curFrame, blockX, blockY, param->internalCsp, param->rc.qgSize); } - } - if (param->bEnableWeightedPred || param->bEnableWeightedBiPred) - { int hShift = CHROMA_H_SHIFT(param->internalCsp); int vShift = CHROMA_V_SHIFT(param->internalCsp); maxCol = ((maxCol + 8) >> 4) << 4; @@ -664,6 +855,7 @@ weightedRef.lumaStride = fenc.lumaStride; weightedRef.isLowres = true; weightedRef.isWeighted = false; + weightedRef.isHMELowres = ref.bEnableHME; /* epsilon is chosen to require at least a numerator of 127 (with denominator = 128) */ float guessScale, fencMean, refMean; @@ -759,6 +951,8 @@ m_extendGopBoundary = false; m_8x8Height = ((m_param->sourceHeight / 2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS; m_8x8Width = ((m_param->sourceWidth / 2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS; + m_4x4Height = ((m_param->sourceHeight / 4) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS; + m_4x4Width = ((m_param->sourceWidth / 4) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS; m_cuCount = m_8x8Width * m_8x8Height; m_8x8Blocks = m_8x8Width > 2 && m_8x8Height > 2 ? (m_cuCount + 4 - 2 * (m_8x8Width + m_8x8Height)) : m_cuCount; m_isFadeIn = false; @@ -1172,9 +1366,7 @@ ProfileScopeEvent(prelookahead); m_lock.release(); preFrame->m_lowres.init(preFrame->m_fencPic, preFrame->m_poc); - if (m_lookahead.m_param->rc.bStatRead && m_lookahead.m_param->rc.cuTree && IS_REFERENCED(preFrame)) - /* cu-tree offsets were read from stats file */; - else if (m_lookahead.m_bAdaptiveQuant) + if (m_lookahead.m_bAdaptiveQuant) tld.calcAdaptiveQuantFrame(preFrame, m_lookahead.m_param); tld.lowresIntraEstimate(preFrame->m_lowres, m_lookahead.m_param->rc.qgSize); preFrame->m_lowresInit = true; @@ -2782,16 +2974,32 @@ X265_CHECK(i < MAX_COOP_SLICES, "impossible number of coop slices\n"); - int firstY = m_lookahead.m_numRowsPerSlice * i; - int lastY = (i == m_jobTotal - 1) ? m_lookahead.m_8x8Height - 1 : m_lookahead.m_numRowsPerSlice * (i + 1) - 1; + int firstY, lastY; + bool lastRow; + if (m_lookahead.m_param->bEnableHME) + { + int numRowsPerSlice = m_lookahead.m_4x4Height / m_lookahead.m_param->lookaheadSlices; + numRowsPerSlice = X265_MIN(X265_MAX(numRowsPerSlice, 5), m_lookahead.m_4x4Height); + firstY = numRowsPerSlice * i; + lastY = (i == m_jobTotal - 1) ? m_lookahead.m_4x4Height - 1 : numRowsPerSlice * (i + 1) - 1; + lastRow = true; + for (int cuY = lastY; cuY >= firstY; cuY--) + { + for (int cuX = m_lookahead.m_4x4Width - 1; cuX >= 0; cuX--) + estimateCUCost(tld, cuX, cuY, m_coop.p0, m_coop.p1, m_coop.b, m_coop.bDoSearch, lastRow, i, 1); + lastRow = false; + } + } - bool lastRow = true; + firstY = m_lookahead.m_numRowsPerSlice * i; + lastY = (i == m_jobTotal - 1) ? m_lookahead.m_8x8Height - 1 : m_lookahead.m_numRowsPerSlice * (i + 1) - 1; + lastRow = true; for (int cuY = lastY; cuY >= firstY; cuY--) { m_frames[m_coop.b]->rowSatds[m_coop.b - m_coop.p0][m_coop.p1 - m_coop.b][cuY] = 0; for (int cuX = m_lookahead.m_8x8Width - 1; cuX >= 0; cuX--) - estimateCUCost(tld, cuX, cuY, m_coop.p0, m_coop.p1, m_coop.b, m_coop.bDoSearch, lastRow, i); + estimateCUCost(tld, cuX, cuY, m_coop.p0, m_coop.p1, m_coop.b, m_coop.bDoSearch, lastRow, i, 0); lastRow = false; } @@ -2864,13 +3072,25 @@ } else { - bool lastRow = true; + /* Calculate MVs for 1/16th resolution*/ + bool lastRow; + if (param->bEnableHME) + { + lastRow = true; + for (int cuY = m_lookahead.m_4x4Height - 1; cuY >= 0; cuY--) + { + for (int cuX = m_lookahead.m_4x4Width - 1; cuX >= 0; cuX--) + estimateCUCost(tld, cuX, cuY, p0, p1, b, bDoSearch, lastRow, -1, 1); + lastRow = false; + } + } + lastRow = true; for (int cuY = m_lookahead.m_8x8Height - 1; cuY >= 0; cuY--) { fenc->rowSatds[b - p0][p1 - b][cuY] = 0; for (int cuX = m_lookahead.m_8x8Width - 1; cuX >= 0; cuX--) - estimateCUCost(tld, cuX, cuY, p0, p1, b, bDoSearch, lastRow, -1); + estimateCUCost(tld, cuX, cuY, p0, p1, b, bDoSearch, lastRow, -1, 0); lastRow = false; } @@ -2891,23 +3111,27 @@ return score; } -void CostEstimateGroup::estimateCUCost(LookaheadTLD& tld, int cuX, int cuY, int p0, int p1, int b, bool bDoSearch[2], bool lastRow, int slice) +void CostEstimateGroup::estimateCUCost(LookaheadTLD& tld, int cuX, int cuY, int p0, int p1, int b, bool bDoSearch[2], bool lastRow, int slice, bool hme) { Lowres *fref0 = m_frames[p0]; Lowres *fref1 = m_frames[p1]; Lowres *fenc = m_frames[b]; - ReferencePlanes *wfref0 = fenc->weightedRef[b - p0].isWeighted ? &fenc->weightedRef[b - p0] : fref0; + ReferencePlanes *wfref0 = fenc->weightedRef[b - p0].isWeighted && !hme ? &fenc->weightedRef[b - p0] : fref0; - const int widthInCU = m_lookahead.m_8x8Width; - const int heightInCU = m_lookahead.m_8x8Height; + const int widthInCU = hme ? m_lookahead.m_4x4Width : m_lookahead.m_8x8Width; + const int heightInCU = hme ? m_lookahead.m_4x4Height : m_lookahead.m_8x8Height; const int bBidir = (b < p1); const int cuXY = cuX + cuY * widthInCU; + const int cuXY_4x4 = (cuX / 2) + (cuY / 2) * widthInCU / 2; const int cuSize = X265_LOWRES_CU_SIZE; - const intptr_t pelOffset = cuSize * cuX + cuSize * cuY * fenc->lumaStride; + const intptr_t pelOffset = cuSize * cuX + cuSize * cuY * (hme ? fenc->lumaStride/2 : fenc->lumaStride); + + if ((bBidir || bDoSearch[0] || bDoSearch[1]) && hme) + tld.me.setSourcePU(fenc->lowerResPlane[0], fenc->lumaStride / 2, pelOffset, cuSize, cuSize, X265_HEX_SEARCH, m_lookahead.m_param->hmeSearchMethod[0], m_lookahead.m_param->hmeSearchMethod[1], 1); + else if((bBidir || bDoSearch[0] || bDoSearch[1]) && !hme) + tld.me.setSourcePU(fenc->lowresPlane[0], fenc->lumaStride, pelOffset, cuSize, cuSize, X265_HEX_SEARCH, m_lookahead.m_param->hmeSearchMethod[0], m_lookahead.m_param->hmeSearchMethod[1], 1); - if (bBidir || bDoSearch[0] || bDoSearch[1]) - tld.me.setSourcePU(fenc->lowresPlane[0], fenc->lumaStride, pelOffset, cuSize, cuSize, X265_HEX_SEARCH, 1); /* A small, arbitrary bias to avoid VBV problems caused by zero-residual lookahead blocks. */ int lowresPenalty = 4; @@ -2926,7 +3150,7 @@ for (int i = 0; i < 1 + bBidir; i++) { - int& fencCost = fenc->lowresMvCosts[i][listDist[i]][cuXY]; + int& fencCost = hme ? fenc->lowerResMvCosts[i][listDist[i]][cuXY] : fenc->lowresMvCosts[i][listDist[i]][cuXY]; int skipCost = INT_MAX; if (!bDoSearch[i]) @@ -2936,8 +3160,8 @@ } int numc = 0; - MV mvc[4], mvp; - MV* fencMV = &fenc->lowresMvs[i][listDist[i]][cuXY]; + MV mvc[5], mvp; + MV* fencMV = hme ? &fenc->lowerResMvs[i][listDist[i]][cuXY] : &fenc->lowresMvs[i][listDist[i]][cuXY]; ReferencePlanes* fref = i ? fref1 : wfref0; /* Reverse-order MV prediction */ @@ -2952,6 +3176,10 @@ if (cuX < widthInCU - 1) MVC(fencMV[widthInCU + 1]); } + if (fenc->lowerResMvs[0][0] && !hme && fenc->lowerResMvCosts[i][listDist[i]][cuXY_4x4] > 0) + { + MVC((fenc->lowerResMvs[i][listDist[i]][cuXY_4x4]) * 2); + } #undef MVC if (!numc) @@ -2967,7 +3195,7 @@ for (int idx = 0; idx < numc; idx++) { intptr_t stride = X265_LOWRES_CU_SIZE; - pixel *src = fref->lowresMC(pelOffset, mvc[idx], subpelbuf, stride); + pixel *src = fref->lowresMC(pelOffset, mvc[idx], subpelbuf, stride, hme); int cost = tld.me.bufSATD(src, stride); COPY2_IF_LT(mvpcost, cost, mvp, mvc[idx]); /* Except for mv0 case, everyting else is likely to have enough residual to not trigger the skip. */ @@ -2978,7 +3206,10 @@ /* ME will never return a cost larger than the cost @MVP, so we do not * have to check that ME cost is more than the estimated merge cost */ - fencCost = tld.me.motionEstimate(fref, mvmin, mvmax, mvp, 0, NULL, s_merange, *fencMV, m_lookahead.m_param->maxSlices); + if(!hme) + fencCost = tld.me.motionEstimate(fref, mvmin, mvmax, mvp, 0, NULL, s_merange, *fencMV, m_lookahead.m_param->maxSlices); + else + fencCost = tld.me.motionEstimate(fref, mvmin, mvmax, mvp, 0, NULL, s_merange, *fencMV, m_lookahead.m_param->maxSlices, fref->lowerResPlane[0]); if (skipCost < 64 && skipCost < fencCost && bBidir) { fencCost = skipCost; @@ -2986,6 +3217,8 @@ } COPY2_IF_LT(bcost, fencCost, listused, i + 1); } + if (hme) + return; if (bBidir) /* B, also consider bidir */ { @@ -2995,8 +3228,8 @@ ALIGN_VAR_32(pixel, subpelbuf0[X265_LOWRES_CU_SIZE * X265_LOWRES_CU_SIZE]); ALIGN_VAR_32(pixel, subpelbuf1[X265_LOWRES_CU_SIZE * X265_LOWRES_CU_SIZE]); intptr_t stride0 = X265_LOWRES_CU_SIZE, stride1 = X265_LOWRES_CU_SIZE; - pixel *src0 = fref0->lowresMC(pelOffset, fenc->lowresMvs[0][listDist[0]][cuXY], subpelbuf0, stride0); - pixel *src1 = fref1->lowresMC(pelOffset, fenc->lowresMvs[1][listDist[1]][cuXY], subpelbuf1, stride1); + pixel *src0 = fref0->lowresMC(pelOffset, fenc->lowresMvs[0][listDist[0]][cuXY], subpelbuf0, stride0, 0); + pixel *src1 = fref1->lowresMC(pelOffset, fenc->lowresMvs[1][listDist[1]][cuXY], subpelbuf1, stride1, 0); ALIGN_VAR_32(pixel, ref[X265_LOWRES_CU_SIZE * X265_LOWRES_CU_SIZE]); primitives.pu[LUMA_8x8].pixelavg_pp[NONALIGNED](ref, X265_LOWRES_CU_SIZE, src0, stride0, src1, stride1, 32); int bicost = tld.me.bufSATD(ref, X265_LOWRES_CU_SIZE);
View file
x265_3.1.2.tar.gz/source/encoder/slicetype.h -> x265_3.2.tar.gz/source/encoder/slicetype.h
Changed
@@ -92,6 +92,7 @@ protected: uint32_t acEnergyCu(Frame* curFrame, uint32_t blockX, uint32_t blockY, int csp, uint32_t qgSize); + uint32_t edgeDensityCu(Frame*curFrame, pixel *edgeImage, pixel *edgeTheta, uint32_t &avgAngle, uint32_t blockX, uint32_t blockY, uint32_t qgSize); uint32_t lumaSumCu(Frame* curFrame, uint32_t blockX, uint32_t blockY, uint32_t qgSize); uint32_t weightCostLuma(Lowres& fenc, Lowres& ref, WeightParam& wp); bool allocWeightedRef(Lowres& fenc); @@ -124,6 +125,10 @@ int m_inputCount; double m_cuTreeStrength; + /* HME */ + int m_4x4Width; + int m_4x4Height; + bool m_isActive; bool m_sliceTypeBusy; bool m_bAdaptiveQuant; @@ -246,7 +251,7 @@ void processTasks(int workerThreadID); int64_t estimateFrameCost(LookaheadTLD& tld, int p0, int p1, int b, bool intraPenalty); - void estimateCUCost(LookaheadTLD& tld, int cux, int cuy, int p0, int p1, int b, bool bDoSearch[2], bool lastRow, int slice); + void estimateCUCost(LookaheadTLD& tld, int cux, int cuy, int p0, int p1, int b, bool bDoSearch[2], bool lastRow, int slice, bool hme); CostEstimateGroup& operator=(const CostEstimateGroup&); };
View file
x265_3.1.2.tar.gz/source/encoder/weightPrediction.cpp -> x265_3.2.tar.gz/source/encoder/weightPrediction.cpp
Changed
@@ -82,7 +82,7 @@ /* clip MV to available pixels */ MV mv = mvs[cu]; mv = mv.clipped(mvmin, mvmax); - pixel *tmp = ref.lowresMC(pixoff, mv, buf8x8, bstride); + pixel *tmp = ref.lowresMC(pixoff, mv, buf8x8, bstride, 0); primitives.cu[BLOCK_8x8].copy_pp(mcout + pixoff, stride, tmp, bstride); } }
View file
x265_3.1.2.tar.gz/source/test/regression-tests.txt -> x265_3.2.tar.gz/source/test/regression-tests.txt
Changed
@@ -153,6 +153,9 @@ big_buck_bunny_360p24.y4m, --keyint 60 --min-keyint 40 --gop-lookahead 14 BasketballDrive_1920x1080_50.y4m, --preset medium --no-open-gop --keyint 50 --min-keyint 50 --radl 2 --vbv-maxrate 5000 --vbv-bufsize 5000 big_buck_bunny_360p24.y4m, --bitrate 500 --fades +720p50_parkrun_ter.y4m,--preset medium --bitrate 400 --hme +ducks_take_off_420_1_720p50.y4m,--preset medium --aq-mode 4 --crf 22 --no-cutree +ducks_take_off_420_1_720p50.y4m,--preset medium --selective-sao 4 --sao --crf 20 # Main12 intraCost overflow bug test 720p50_parkrun_ter.y4m,--preset medium
View file
x265_3.1.2.tar.gz/source/x265.h -> x265_3.2.tar.gz/source/x265.h
Changed
@@ -561,6 +561,7 @@ #define X265_AQ_VARIANCE 1 #define X265_AQ_AUTO_VARIANCE 2 #define X265_AQ_AUTO_VARIANCE_BIASED 3 +#define X265_AQ_EDGE 4 #define x265_ADAPT_RD_STRENGTH 4 #define X265_REFINE_INTER_LEVELS 3 /* NOTE! For this release only X265_CSP_I420 and X265_CSP_I444 are supported */ @@ -1172,6 +1173,14 @@ /* Enable availability of temporal motion vector for AMVP, default is enabled */ int bEnableTemporalMvp; + /* Enable 3-level Hierarchical motion estimation at One-Sixteenth, Quarter and Full resolution. + * Default is disabled */ + int bEnableHME; + + /* Enable HME search method (DIA, HEX, UMH, STAR, SEA, FULL) for level 0, 1 and 2. + * Default is hex, umh, umh for L0, L1 and L2 respectively. */ + int hmeSearchMethod[3]; + /* Enable weighted prediction in P slices. This enables weighting analysis * in the lookahead, which influences slice decisions, and enables weighting * analysis in the main encoder which allows P reference samples to have a @@ -1214,6 +1223,12 @@ * non-deblocked pixels are used entirely. Default is disabled */ int bSaoNonDeblocked; + /* Select tune rate in which SAO has to be applied. + 1 - Filtering applied only on I-frames(I) [Light tune] + 2 - No Filtering on B frames (I, P) [Medium tune] + 3 - No Filtering on non-ref b frames (I, P, B) [Strong tune] */ + int selectiveSAO; + /*== Analysis tools ==*/ /* A value between 1 and 6 (both inclusive) which determines the level of
View file
x265_3.1.2.tar.gz/source/x265cli.h -> x265_3.2.tar.gz/source/x265cli.h
Changed
@@ -95,6 +95,9 @@ { "max-merge", required_argument, NULL, 0 }, { "no-temporal-mvp", no_argument, NULL, 0 }, { "temporal-mvp", no_argument, NULL, 0 }, + { "hme", no_argument, NULL, 0 }, + { "no-hme", no_argument, NULL, 0 }, + { "hme-search", required_argument, NULL, 0 }, { "rdpenalty", required_argument, NULL, 0 }, { "no-rect", no_argument, NULL, 0 }, { "rect", no_argument, NULL, 0 }, @@ -197,6 +200,7 @@ { "no-deblock", no_argument, NULL, 0 }, { "deblock", required_argument, NULL, 0 }, { "no-sao", no_argument, NULL, 0 }, + { "selective-sao", required_argument, NULL, 0 }, { "sao", no_argument, NULL, 0 }, { "no-sao-non-deblock", no_argument, NULL, 0 }, { "sao-non-deblock", no_argument, NULL, 0 }, @@ -294,8 +298,7 @@ { "dhdr10-opt", no_argument, NULL, 0}, { "no-dhdr10-opt", no_argument, NULL, 0}, { "dolby-vision-profile", required_argument, NULL, 0 }, - { "refine-mv", no_argument, NULL, 0 }, - { "no-refine-mv", no_argument, NULL, 0 }, + { "refine-mv", required_argument, NULL, 0 }, { "refine-ctu-distortion", required_argument, NULL, 0 }, { "force-flush", required_argument, NULL, 0 }, { "splitrd-skip", no_argument, NULL, 0 }, @@ -464,6 +467,8 @@ H0(" --[no-]amp Enable asymmetric motion partitions, requires --rect. Default %s\n", OPT(param->bEnableAMP)); H0(" --[no-]limit-modes Limit rectangular and asymmetric motion predictions. Default %d\n", param->limitModes); H1(" --[no-]temporal-mvp Enable temporal MV predictors. Default %s\n", OPT(param->bEnableTemporalMvp)); + H1(" --[no-]hme Enable Hierarchical Motion Estimation. Default %s\n", OPT(param->bEnableHME)); + H1(" --hme-search <string> Motion search-method for HME L0,L1 and L2. Default(L0,L1,L2) is %d,%d,%d\n", param->hmeSearchMethod[0], param->hmeSearchMethod[1], param->hmeSearchMethod[2]); H0("\nSpatial / intra options:\n"); H0(" --[no-]strong-intra-smoothing Enable strong intra smoothing for 32x32 blocks. Default %s\n", OPT(param->bEnableStrongIntraSmoothing)); H0(" --[no-]constrained-intra Constrained intra prediction (use only intra coded reference pixels) Default %s\n", OPT(param->bEnableConstrainedIntra)); @@ -544,16 +549,16 @@ " - 3 : Functionality of (1) + irrespective of size evaluate all inter modes.\n" " Default:%d\n", param->interRefine); H0(" --[no-]dynamic-refine Dynamically changes refine-inter level for each CU. Default %s\n", OPT(param->bDynamicRefine)); - H0(" --[no-]refine-mv Enable mv refinement for load mode. Default %s\n", OPT(param->mvRefine)); + H0(" --refine-mv <1..3> Enable mv refinement for load mode. Default %d\n", param->mvRefine); H0(" --refine-ctu-distortion Store/normalize ctu distortion in analysis-save/load.\n" " - 0 : Disabled.\n" " - 1 : Store/Load ctu distortion to/from the file specified in analysis-save/load.\n" " Default 0 - Disabled\n"); - H0(" --aq-mode <integer> Mode for Adaptive Quantization - 0:none 1:uniform AQ 2:auto variance 3:auto variance with bias to dark scenes. Default %d\n", param->rc.aqMode); + H0(" --aq-mode <integer> Mode for Adaptive Quantization - 0:none 1:uniform AQ 2:auto variance 3:auto variance with bias to dark scenes 4:auto variance with edge information. Default %d\n", param->rc.aqMode); H0(" --[no-]hevc-aq Mode for HEVC Adaptive Quantization. Default %s\n", OPT(param->rc.hevcAq)); H0(" --aq-strength <float> Reduces blocking and blurring in flat and textured areas (0 to 3.0). Default %.2f\n", param->rc.aqStrength); H0(" --qp-adaptation-range <float> Delta QP range by QP adaptation based on a psycho-visual model (1.0 to 6.0). Default %.2f\n", param->rc.qpAdaptationRange); - H0(" --[no-]aq-motion Adaptive Quantization based on the relative motion of each CU w.r.t., frame. Default %s\n", OPT(param->bOptCUDeltaQP)); + H0(" --[no-]aq-motion Block level QP adaptation based on the relative motion between the block and the frame. Default %s\n", OPT(param->bAQMotion)); H0(" --qg-size <int> Specifies the size of the quantization group (64, 32, 16, 8). Default %d\n", param->rc.qgSize); H0(" --[no-]cutree Enable cutree for Adaptive Quantization. Default %s\n", OPT(param->rc.cuTree)); H0(" --[no-]rc-grain Enable ratecontrol mode to handle grains specifically. turned on with tune grain. Default %s\n", OPT(param->rc.bEnableGrain)); @@ -585,6 +590,7 @@ H0(" --[no-]sao Enable Sample Adaptive Offset. Default %s\n", OPT(param->bEnableSAO)); H1(" --[no-]sao-non-deblock Use non-deblocked pixels, else right/bottom boundary areas skipped. Default %s\n", OPT(param->bSaoNonDeblocked)); H0(" --[no-]limit-sao Limit Sample Adaptive Offset types. Default %s\n", OPT(param->bLimitSAO)); + H0(" --selective-sao <int> Enable slice-level SAO filter. Default %d\n", param->selectiveSAO); H0("\nVUI options:\n"); H0(" --sar <width:height|int> Sample Aspect Ratio, the ratio of width to height of an individual pixel.\n"); H0(" Choose from 0=undef, 1=1:1(\"square\"), 2=12:11, 3=10:11, 4=16:11,\n");
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.