Projects
Essentials
x265
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
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); +
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);
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 - {
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
.