File: rdcost.h

package info (click to toggle)
x265 4.1-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 15,452 kB
  • sloc: asm: 187,063; cpp: 118,996; ansic: 741; makefile: 146; sh: 91; python: 11
file content (178 lines) | stat: -rw-r--r-- 7,664 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*****************************************************************************
* Copyright (C) 2013-2020 MulticoreWare, Inc
*
* Authors: Steve Borho <steve@borho.org>
*          Min Chen <chenm003@163.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
*
* This program is also available under a commercial proprietary license.
* For more information, contact us at license @ x265.com.
*****************************************************************************/

#ifndef X265_RDCOST_H
#define X265_RDCOST_H

#include "common.h"
#include "slice.h"

namespace X265_NS {
// private namespace

class RDCost
{
public:

    /* all weights and factors stored as FIX8 */
    uint64_t  m_lambda2;
    uint64_t  m_lambda;
    uint32_t  m_chromaDistWeight[2];
    uint32_t  m_psyRdBase;
    uint32_t  m_psyRd;
    uint32_t  m_ssimRd;
    int       m_qp; /* QP used to configure lambda, may be higher than QP_MAX_SPEC but <= QP_MAX_MAX */

    void setPsyRdScale(double scale)                { m_psyRdBase = (uint32_t)floor(65536.0 * scale * 0.33); }
    void setSsimRd(int ssimRd) { m_ssimRd = ssimRd; };

    void setQP(const Slice& slice, int qp)
    {
        x265_emms(); /* TODO: if the lambda tables were ints, this would not be necessary */
        m_qp = qp;
        setLambda(x265_lambda2_tab[qp], x265_lambda_tab[qp]);

        /* Scale PSY RD factor by a slice type factor */
        static const uint32_t psyScaleFix8[3] = { 300, 256, 96 }; /* B, P, I */
        m_psyRd = (m_psyRdBase * psyScaleFix8[slice.m_sliceType]) >> 8;

        /* Scale PSY RD factor by QP, at high QP psy-rd can cause artifacts */
        if (qp >= 40)
        {
            int scale = qp >= QP_MAX_SPEC ? 0 : (QP_MAX_SPEC - qp) * 23;
            m_psyRd = (m_psyRd * scale) >> 8;
        }

        int qpCb, qpCr;
        if (slice.m_sps->chromaFormatIdc == X265_CSP_I420)
        {
            qpCb = (int)g_chromaScale[x265_clip3(QP_MIN, QP_MAX_MAX, qp + slice.m_pps->chromaQpOffset[0] + slice.m_chromaQpOffset[0])];
            qpCr = (int)g_chromaScale[x265_clip3(QP_MIN, QP_MAX_MAX, qp + slice.m_pps->chromaQpOffset[1] + slice.m_chromaQpOffset[1])];
        }
        else
        {
            qpCb = x265_clip3(QP_MIN, QP_MAX_SPEC, qp + slice.m_pps->chromaQpOffset[0] + slice.m_chromaQpOffset[0]);
            qpCr = x265_clip3(QP_MIN, QP_MAX_SPEC, qp + slice.m_pps->chromaQpOffset[1] + slice.m_chromaQpOffset[1]);
        }

        if (slice.m_sps->chromaFormatIdc == X265_CSP_I444)
        {
            int chroma_offset_idx = X265_MIN(qp - qpCb + 12, MAX_CHROMA_LAMBDA_OFFSET);
            uint16_t lambdaOffset = m_psyRd ? x265_chroma_lambda2_offset_tab[chroma_offset_idx] : 256;
            m_chromaDistWeight[0] = lambdaOffset;

            chroma_offset_idx = X265_MIN(qp - qpCr + 12, MAX_CHROMA_LAMBDA_OFFSET);
            lambdaOffset = m_psyRd ? x265_chroma_lambda2_offset_tab[chroma_offset_idx] : 256;
            m_chromaDistWeight[1] = lambdaOffset;
        }
        else
            m_chromaDistWeight[0] = m_chromaDistWeight[1] = 256;
    }

    void setLambda(double lambda2, double lambda)
    {
        m_lambda2 = (uint64_t)floor(256.0 * lambda2);
        m_lambda = (uint64_t)floor(256.0 * lambda);
    }

    inline uint64_t calcRdCost(sse_t distortion, uint32_t bits) const
    {
#if X265_DEPTH < 10
        X265_CHECK(bits <= (UINT64_MAX - 128) / m_lambda2,
                   "calcRdCost wrap detected dist: %u, bits %u, lambda: " X265_LL "\n",
                   distortion, bits, m_lambda2);
#else
        X265_CHECK(bits <= (UINT64_MAX - 128) / m_lambda2,
                   "calcRdCost wrap detected dist: " X265_LL ", bits %u, lambda: " X265_LL "\n",
                   distortion, bits, m_lambda2);
#endif
        return distortion + ((bits * m_lambda2 + 128) >> 8);
    }

    /* return the difference in energy between the source block and the recon block */
    inline int psyCost(int size, const pixel* source, intptr_t sstride, const pixel* recon, intptr_t rstride) const
    {
        return primitives.cu[size].psy_cost_pp(source, sstride, recon, rstride);
    }

    /* return the RD cost of this prediction, including the effect of psy-rd */
    inline uint64_t calcPsyRdCost(sse_t distortion, uint32_t bits, uint32_t psycost) const
    {
#if X265_DEPTH < 10
        X265_CHECK((bits <= (UINT64_MAX / m_lambda2)) && (psycost <= UINT64_MAX / (m_lambda * m_psyRd)),
                   "calcPsyRdCost wrap detected dist: %u, bits: %u, lambda: " X265_LL ", lambda2: " X265_LL "\n",
                   distortion, bits, m_lambda, m_lambda2);
#else
        X265_CHECK((bits <= (UINT64_MAX / m_lambda2)) && (psycost <= UINT64_MAX / (m_lambda * m_psyRd)),
                   "calcPsyRdCost wrap detected dist: " X265_LL ", bits: %u, lambda: " X265_LL ", lambda2: " X265_LL "\n",
                   distortion, bits, m_lambda, m_lambda2);
#endif
        return distortion + ((m_lambda * m_psyRd * psycost) >> 24) + ((bits * m_lambda2) >> 8);
    }

    inline uint64_t calcSsimRdCost(uint64_t distortion, uint32_t bits, uint32_t ssimCost) const
    {
#if X265_DEPTH < 10
        X265_CHECK((bits <= (UINT64_MAX / m_lambda2)) && (ssimCost <= UINT64_MAX / m_lambda),
                   "calcPsyRdCost wrap detected dist: " X265_LL " bits: %u, lambda: " X265_LL ", lambda2: " X265_LL "\n",
                   distortion, bits, m_lambda, m_lambda2);
#else
        X265_CHECK((bits <= (UINT64_MAX / m_lambda2)) && (ssimCost <= UINT64_MAX / m_lambda),
                   "calcPsyRdCost wrap detected dist: " X265_LL ", bits: %u, lambda: " X265_LL ", lambda2: " X265_LL "\n",
                   distortion, bits, m_lambda, m_lambda2);
#endif
        return distortion + ((m_lambda * ssimCost) >> 14) + ((bits * m_lambda2) >> 8);
    }

    inline uint64_t calcRdSADCost(uint32_t sadCost, uint32_t bits) const
    {
        X265_CHECK(bits <= (UINT64_MAX - 128) / m_lambda,
                   "calcRdSADCost wrap detected dist: %u, bits %u, lambda: " X265_LL "\n", sadCost, bits, m_lambda);
        return sadCost + ((bits * m_lambda + 128) >> 8);
    }

    inline sse_t scaleChromaDist(uint32_t plane, sse_t dist) const
    {
#if X265_DEPTH < 10
        X265_CHECK(dist <= (UINT64_MAX - 128) / m_chromaDistWeight[plane - 1],
                   "scaleChromaDist wrap detected dist: %u, lambda: %u\n",
                   dist, m_chromaDistWeight[plane - 1]);
#else
        X265_CHECK(dist <= (UINT64_MAX - 128) / m_chromaDistWeight[plane - 1],
                   "scaleChromaDist wrap detected dist: " X265_LL " lambda: %u\n",
                   dist, m_chromaDistWeight[plane - 1]);
#endif
        return (sse_t)((dist * (uint64_t)m_chromaDistWeight[plane - 1] + 128) >> 8);
    }

    inline uint32_t getCost(uint32_t bits) const
    {
        X265_CHECK(bits <= (UINT64_MAX - 128) / m_lambda,
                   "getCost wrap detected bits: %u, lambda: " X265_LL "\n", bits, m_lambda);
        return (uint32_t)((bits * m_lambda + 128) >> 8);
    }
};
}

#endif // ifndef X265_TCOMRDCOST_H