Mercurial > x265
changeset 12550:5ac4c74c5418 draft
Add option to enable slice-based SAO filter.
author | Pooja Venkatesan <pooja@multicorewareinc.com> |
---|---|
date | Tue, 03 Sep 2019 14:25:44 +0530 |
parents | a092e82e6acf |
children | c525b46b92bb |
files | doc/reST/cli.rst source/CMakeLists.txt source/common/param.cpp source/common/slice.h source/encoder/encoder.cpp source/encoder/entropy.cpp source/encoder/framefilter.cpp source/encoder/framefilter.h source/test/regression-tests.txt source/x265.h source/x265cli.h |
diffstat | 11 files changed, 96 insertions(+-), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/reST/cli.rst Thu Aug 01 22:55:21 2019 +0200 +++ b/doc/reST/cli.rst Tue Sep 03 14:25:44 2019 +0530 @@ -1996,6 +1996,24 @@ Loop filters 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 4. + + +--------------+---------------------------------------+ + | 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 =========================================
--- a/source/CMakeLists.txt Thu Aug 01 22:55:21 2019 +0200 +++ b/source/CMakeLists.txt Tue Sep 03 14:25:44 2019 +0530 @@ -29,7 +29,7 @@ option(NATIVE_BUILD "Target the build CP 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 178) +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"
--- a/source/common/param.cpp Thu Aug 01 22:55:21 2019 +0200 +++ b/source/common/param.cpp Tue Sep 03 14:25:44 2019 +0530 @@ -215,6 +215,7 @@ void x265_param_default(x265_param* para param->bEnableSAO = 1; param->bSaoNonDeblocked = 0; param->bLimitSAO = 0; + param->selectiveSAO = 4; /* Coding Quality */ param->cbQpOffset = 0; @@ -375,6 +376,7 @@ int x265_param_default_preset(x265_param param->subpelRefine = 0; param->searchMethod = X265_DIA_SEARCH; param->bEnableSAO = 0; + param->selectiveSAO = 0; param->bEnableSignHiding = 0; param->bEnableWeightedPred = 0; param->rdLevel = 2; @@ -404,6 +406,7 @@ int x265_param_default_preset(x265_param param->rc.hevcAq = 0; param->rc.qgSize = 32; param->bEnableSAO = 0; + param->selectiveSAO = 0; param->bEnableFastIntra = 1; } else if (!strcmp(preset, "veryfast")) @@ -551,6 +554,7 @@ int x265_param_default_preset(x265_param { param->bEnableLoopFilter = 0; param->bEnableSAO = 0; + param->selectiveSAO = 0; param->bEnableWeightedPred = 0; param->bEnableWeightedBiPred = 0; param->bIntraInBFrames = 0; @@ -578,6 +582,7 @@ int x265_param_default_preset(x265_param param->psyRd = 4.0; param->psyRdoq = 10.0; param->bEnableSAO = 0; + param->selectiveSAO = 0; param->rc.bEnableConstVbv = 1; } else if (!strcmp(tune, "animation")) @@ -1282,6 +1287,10 @@ int x265_param_parse(x265_param* p, cons 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); @@ -1686,6 +1695,8 @@ int x265_check_params(x265_param* param) 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"); @@ -1862,6 +1873,8 @@ void x265_print_params(x265_param* param } TOOLOPT(param->bSaoNonDeblocked, "sao-non-deblock"); TOOLOPT(!param->bSaoNonDeblocked && param->bEnableSAO, "sao"); + if (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"); @@ -1971,6 +1984,7 @@ char *x265_param2string(x265_param* p, i 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"); @@ -2420,6 +2434,7 @@ void x265_copy_params(x265_param* dst, x 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;
--- a/source/common/slice.h Thu Aug 01 22:55:21 2019 +0200 +++ b/source/common/slice.h Tue Sep 03 14:25:44 2019 +0530 @@ -356,6 +356,7 @@ public: 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];
--- a/source/encoder/encoder.cpp Thu Aug 01 22:55:21 2019 +0200 +++ b/source/encoder/encoder.cpp Tue Sep 03 14:25:44 2019 +0530 @@ -1621,6 +1621,28 @@ int Encoder::encode(const x265_picture* } /* 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 @@ void Encoder::configure(x265_param *p) } + 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");
--- a/source/encoder/entropy.cpp Thu Aug 01 22:55:21 2019 +0200 +++ b/source/encoder/entropy.cpp Tue Sep 03 14:25:44 2019 +0530 @@ -641,12 +641,18 @@ void Entropy::codeSliceHeader(const Slic 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 @@ -706,7 +712,7 @@ void Entropy::codeSliceHeader(const Slic 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)
--- a/source/encoder/framefilter.cpp Thu Aug 01 22:55:21 2019 +0200 +++ b/source/encoder/framefilter.cpp Tue Sep 03 14:25:44 2019 +0530 @@ -163,7 +163,7 @@ void FrameFilter::destroy() 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 @@ void FrameFilter::init(Encoder *top, Fra { 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 @@ void FrameFilter::init(Encoder *top, Fra 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 @@ void FrameFilter::start(Frame *frame, En { 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 @@ void FrameFilter::start(Frame *frame, En } // Reset SAO common statistics - if (m_param->bEnableSAO) + if (m_useSao) m_parallelFilter[0].m_sao.resetStats(); } } @@ -472,11 +473,11 @@ void FrameFilter::ParallelFilter::proces 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 @@ void FrameFilter::ParallelFilter::proces 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 @@ void FrameFilter::processRow(int row) 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 @@ void FrameFilter::processRow(int row) 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 @@ void FrameFilter::processRow(int row) if (numRowFinished == m_numRows) { - if (m_param->bEnableSAO) + if (m_useSao) { // Merge numNoSao into RootNode (Node0) for(int i = 1; i < m_numRows; i++)
--- a/source/encoder/framefilter.h Thu Aug 01 22:55:21 2019 +0200 +++ b/source/encoder/framefilter.h Tue Sep 03 14:25:44 2019 +0530 @@ -46,6 +46,7 @@ public: x265_param* m_param; Frame* m_frame; + int m_useSao; FrameEncoder* m_frameEncoder; int m_hChromaShift; int m_vChromaShift;
--- a/source/test/regression-tests.txt Thu Aug 01 22:55:21 2019 +0200 +++ b/source/test/regression-tests.txt Tue Sep 03 14:25:44 2019 +0530 @@ -155,6 +155,7 @@ BasketballDrive_1920x1080_50.y4m, --pres 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
--- a/source/x265.h Thu Aug 01 22:55:21 2019 +0200 +++ b/source/x265.h Tue Sep 03 14:25:44 2019 +0530 @@ -1223,6 +1223,12 @@ typedef struct x265_param * 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
--- a/source/x265cli.h Thu Aug 01 22:55:21 2019 +0200 +++ b/source/x265cli.h Tue Sep 03 14:25:44 2019 +0530 @@ -200,6 +200,7 @@ static const struct option long_options[ { "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 }, @@ -589,6 +590,7 @@ static void showHelp(x265_param *param) 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");