Coverage Report

Created: 2025-09-27 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/Simd/src/Simd/SimdSse41BgrToYuvV2.cpp
Line
Count
Source
1
/*
2
* Simd Library (http://ermig1979.github.io/Simd).
3
*
4
* Copyright (c) 2011-2023 Yermalayeu Ihar.
5
*
6
* Permission is hereby granted, free of charge, to any person obtaining a copy
7
* of this software and associated documentation files (the "Software"), to deal
8
* in the Software without restriction, including without limitation the rights
9
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
* copies of the Software, and to permit persons to whom the Software is
11
* furnished to do so, subject to the following conditions:
12
*
13
* The above copyright notice and this permission notice shall be included in
14
* all copies or substantial portions of the Software.
15
*
16
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
* SOFTWARE.
23
*/
24
#include "Simd/SimdMemory.h"
25
#include "Simd/SimdStore.h"
26
#include "Simd/SimdConversion.h"
27
#include "Simd/SimdYuvToBgr.h"
28
#include "Simd/SimdBase.h"
29
30
namespace Simd
31
{
32
#ifdef SIMD_SSE41_ENABLE    
33
    namespace Sse41
34
    {
35
        template <bool align> SIMD_INLINE void LoadBgr(const __m128i * p, __m128i & blue, __m128i & green, __m128i & red)
36
0
        {
37
0
            __m128i bgr[3];
38
0
            bgr[0] = Load<align>(p + 0);
39
0
            bgr[1] = Load<align>(p + 1);
40
0
            bgr[2] = Load<align>(p + 2);
41
0
            blue = BgrToBlue(bgr);
42
0
            green = BgrToGreen(bgr);
43
0
            red = BgrToRed(bgr);
44
0
        }
45
46
        SIMD_INLINE __m128i Average16(const __m128i & s0, const __m128i & s1)
47
0
        {
48
0
            return _mm_srli_epi16(_mm_add_epi16(_mm_add_epi16(_mm_maddubs_epi16(s0, K8_01), _mm_maddubs_epi16(s1, K8_01)), K16_0002), 2);
49
0
        }
50
51
        SIMD_INLINE void Average16(__m128i & a)
52
0
        {
53
0
            a = _mm_srli_epi16(_mm_add_epi16(_mm_maddubs_epi16(a, K8_01), K16_0001), 1);
54
0
        }
55
56
        //-------------------------------------------------------------------------------------------------
57
58
        template <class T> SIMD_INLINE void BgrToYuv420pV2(const uint8_t* bgr0, size_t bgrStride, uint8_t* y0, size_t yStride, uint8_t* u, uint8_t* v)
59
0
        {
60
0
            const uint8_t* bgr1 = bgr0 + bgrStride;
61
0
            uint8_t* y1 = y0 + yStride;
62
63
0
            __m128i blue[2][2], green[2][2], red[2][2];
64
65
0
            LoadBgr<false>((__m128i*)bgr0 + 0, blue[0][0], green[0][0], red[0][0]);
66
0
            _mm_storeu_si128((__m128i*)y0 + 0, BgrToY8<T>(blue[0][0], green[0][0], red[0][0]));
67
68
0
            LoadBgr<false>((__m128i*)bgr0 + 3, blue[0][1], green[0][1], red[0][1]);
69
0
            _mm_storeu_si128((__m128i*)y0 + 1, BgrToY8<T>(blue[0][1], green[0][1], red[0][1]));
70
71
0
            LoadBgr<false>((__m128i*)bgr1 + 0, blue[1][0], green[1][0], red[1][0]);
72
0
            _mm_storeu_si128((__m128i*)y1 + 0, BgrToY8<T>(blue[1][0], green[1][0], red[1][0]));
73
74
0
            LoadBgr<false>((__m128i*)bgr1 + 3, blue[1][1], green[1][1], red[1][1]);
75
0
            _mm_storeu_si128((__m128i*)y1 + 1, BgrToY8<T>(blue[1][1], green[1][1], red[1][1]));
76
77
0
            blue[0][0] = Average16(blue[0][0], blue[1][0]);
78
0
            blue[0][1] = Average16(blue[0][1], blue[1][1]);
79
0
            green[0][0] = Average16(green[0][0], green[1][0]);
80
0
            green[0][1] = Average16(green[0][1], green[1][1]);
81
0
            red[0][0] = Average16(red[0][0], red[1][0]);
82
0
            red[0][1] = Average16(red[0][1], red[1][1]);
83
84
0
            _mm_storeu_si128((__m128i*)u, _mm_packus_epi16(BgrToU16<T>(blue[0][0], green[0][0], red[0][0]), BgrToU16<T>(blue[0][1], green[0][1], red[0][1])));
85
0
            _mm_storeu_si128((__m128i*)v, _mm_packus_epi16(BgrToV16<T>(blue[0][0], green[0][0], red[0][0]), BgrToV16<T>(blue[0][1], green[0][1], red[0][1])));
86
0
        }
Unexecuted instantiation: void Simd::Sse41::BgrToYuv420pV2<Simd::Base::Bt601>(unsigned char const*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned char*)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv420pV2<Simd::Base::Bt709>(unsigned char const*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned char*)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv420pV2<Simd::Base::Bt2020>(unsigned char const*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned char*)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv420pV2<Simd::Base::Trect871>(unsigned char const*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned char*)
87
88
        template <class T>  void BgrToYuv420pV2(const uint8_t* bgr, size_t bgrStride, size_t width, size_t height, uint8_t* y, size_t yStride,
89
            uint8_t* u, size_t uStride, uint8_t* v, size_t vStride)
90
0
        {
91
0
            assert((width % 2 == 0) && (height % 2 == 0) && (width >= DA) && (height >= 2));
92
93
0
            size_t widthDA = AlignLo(width, DA);
94
0
            for (size_t row = 0; row < height; row += 2)
95
0
            {
96
0
                for (size_t colUV = 0, colY = 0, colBgr = 0; colY < widthDA; colY += DA, colUV += A, colBgr += A * 6)
97
0
                    BgrToYuv420pV2<T>(bgr + colBgr, bgrStride, y + colY, yStride, u + colUV, v + colUV);
98
0
                if (width != widthDA)
99
0
                {
100
0
                    size_t colY = width - DA;
101
0
                    BgrToYuv420pV2<T>(bgr + colY * 3, bgrStride, y + colY, yStride, u + colY / 2, v + colY / 2);
102
0
                }
103
0
                y += 2 * yStride;
104
0
                u += uStride;
105
0
                v += vStride;
106
0
                bgr += 2 * bgrStride;
107
0
            }
108
0
        }
Unexecuted instantiation: void Simd::Sse41::BgrToYuv420pV2<Simd::Base::Bt601>(unsigned char const*, unsigned long, unsigned long, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv420pV2<Simd::Base::Bt709>(unsigned char const*, unsigned long, unsigned long, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv420pV2<Simd::Base::Bt2020>(unsigned char const*, unsigned long, unsigned long, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv420pV2<Simd::Base::Trect871>(unsigned char const*, unsigned long, unsigned long, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long)
109
110
        void BgrToYuv420pV2(const uint8_t* bgr, size_t bgrStride, size_t width, size_t height, uint8_t* y, size_t yStride,
111
            uint8_t* u, size_t uStride, uint8_t* v, size_t vStride, SimdYuvType yuvType)
112
0
        {
113
#if defined(SIMD_X86_ENABLE) && defined(NDEBUG) && defined(_MSC_VER) && _MSC_VER <= 1900
114
            Base::BgrToYuv420pV2(bgr, bgrStride, width, height, y, yStride, u, uStride, v, vStride, yuvType);
115
#else
116
0
            switch (yuvType)
117
0
            {
118
0
            case SimdYuvBt601: BgrToYuv420pV2<Base::Bt601>(bgr, bgrStride, width, height, y, yStride, u, uStride, v, vStride); break;
119
0
            case SimdYuvBt709: BgrToYuv420pV2<Base::Bt709>(bgr, bgrStride, width, height, y, yStride, u, uStride, v, vStride); break;
120
0
            case SimdYuvBt2020: BgrToYuv420pV2<Base::Bt2020>(bgr, bgrStride, width, height, y, yStride, u, uStride, v, vStride); break;
121
0
            case SimdYuvTrect871: BgrToYuv420pV2<Base::Trect871>(bgr, bgrStride, width, height, y, yStride, u, uStride, v, vStride); break;
122
0
            default:
123
0
                assert(0);
124
0
            }
125
0
#endif
126
0
        }
127
128
        //-------------------------------------------------------------------------------------------------
129
130
        template <class T> SIMD_INLINE void BgrToYuv422pV2(const uint8_t* bgr, uint8_t* y, uint8_t* u, uint8_t* v)
131
0
        {
132
0
            __m128i blue[2], green[2], red[2];
133
134
0
            LoadBgr<false>((__m128i*)bgr + 0, blue[0], green[0], red[0]);
135
0
            _mm_storeu_si128((__m128i*)y + 0, BgrToY8<T>(blue[0], green[0], red[0]));
136
137
0
            LoadBgr<false>((__m128i*)bgr + 3, blue[1], green[1], red[1]);
138
0
            _mm_storeu_si128((__m128i*)y + 1, BgrToY8<T>(blue[1], green[1], red[1]));
139
140
0
            Average16(blue[0]);
141
0
            Average16(blue[1]);
142
0
            Average16(green[0]);
143
0
            Average16(green[1]);
144
0
            Average16(red[0]);
145
0
            Average16(red[1]);
146
147
0
            _mm_storeu_si128((__m128i*)u, _mm_packus_epi16(BgrToU16<T>(blue[0], green[0], red[0]), BgrToU16<T>(blue[1], green[1], red[1])));
148
0
            _mm_storeu_si128((__m128i*)v, _mm_packus_epi16(BgrToV16<T>(blue[0], green[0], red[0]), BgrToV16<T>(blue[1], green[1], red[1])));
149
0
        }
Unexecuted instantiation: void Simd::Sse41::BgrToYuv422pV2<Simd::Base::Bt601>(unsigned char const*, unsigned char*, unsigned char*, unsigned char*)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv422pV2<Simd::Base::Bt709>(unsigned char const*, unsigned char*, unsigned char*, unsigned char*)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv422pV2<Simd::Base::Bt2020>(unsigned char const*, unsigned char*, unsigned char*, unsigned char*)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv422pV2<Simd::Base::Trect871>(unsigned char const*, unsigned char*, unsigned char*, unsigned char*)
150
151
        template <class T>  void BgrToYuv422pV2(const uint8_t* bgr, size_t bgrStride, size_t width, size_t height, uint8_t* y, size_t yStride,
152
            uint8_t* u, size_t uStride, uint8_t* v, size_t vStride)
153
0
        {
154
0
            assert((width % 2 == 0) && (width >= DA));
155
156
0
            size_t widthDA = AlignLo(width, DA);
157
0
            for (size_t row = 0; row < height; row += 1)
158
0
            {
159
0
                for (size_t colUV = 0, colY = 0, colBgr = 0; colY < widthDA; colY += DA, colUV += A, colBgr += A * 6)
160
0
                    BgrToYuv422pV2<T>(bgr + colBgr, y + colY, u + colUV, v + colUV);
161
0
                if (width != widthDA)
162
0
                {
163
0
                    size_t colY = width - DA;
164
0
                    BgrToYuv422pV2<T>(bgr + colY * 3, y + colY, u + colY / 2, v + colY / 2);
165
0
                }
166
0
                y += yStride;
167
0
                u += uStride;
168
0
                v += vStride;
169
0
                bgr += bgrStride;
170
0
            }
171
0
        }
Unexecuted instantiation: void Simd::Sse41::BgrToYuv422pV2<Simd::Base::Bt601>(unsigned char const*, unsigned long, unsigned long, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv422pV2<Simd::Base::Bt709>(unsigned char const*, unsigned long, unsigned long, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv422pV2<Simd::Base::Bt2020>(unsigned char const*, unsigned long, unsigned long, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv422pV2<Simd::Base::Trect871>(unsigned char const*, unsigned long, unsigned long, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long)
172
173
        void BgrToYuv422pV2(const uint8_t* bgr, size_t bgrStride, size_t width, size_t height, uint8_t* y, size_t yStride,
174
            uint8_t* u, size_t uStride, uint8_t* v, size_t vStride, SimdYuvType yuvType)
175
0
        {
176
#if defined(SIMD_X86_ENABLE) && defined(NDEBUG) && defined(_MSC_VER) && _MSC_VER <= 1900
177
            Base::BgrToYuv422pV2(bgr, bgrStride, width, height, y, yStride, u, uStride, v, vStride, yuvType);
178
#else
179
0
            switch (yuvType)
180
0
            {
181
0
            case SimdYuvBt601: BgrToYuv422pV2<Base::Bt601>(bgr, bgrStride, width, height, y, yStride, u, uStride, v, vStride); break;
182
0
            case SimdYuvBt709: BgrToYuv422pV2<Base::Bt709>(bgr, bgrStride, width, height, y, yStride, u, uStride, v, vStride); break;
183
0
            case SimdYuvBt2020: BgrToYuv422pV2<Base::Bt2020>(bgr, bgrStride, width, height, y, yStride, u, uStride, v, vStride); break;
184
0
            case SimdYuvTrect871: BgrToYuv422pV2<Base::Trect871>(bgr, bgrStride, width, height, y, yStride, u, uStride, v, vStride); break;
185
0
            default:
186
0
                assert(0);
187
0
            }
188
0
#endif
189
0
        }
190
191
        //-------------------------------------------------------------------------------------------------
192
193
        template <class T> SIMD_INLINE void BgrToYuv444pV2(const uint8_t* bgr, uint8_t* y, uint8_t* u, uint8_t* v)
194
0
        {
195
0
            __m128i blue, green, red;
196
0
            LoadBgr<false>((__m128i*)bgr, blue, green, red);
197
0
            _mm_storeu_si128((__m128i*)y, BgrToY8<T>(blue, green, red));
198
0
            _mm_storeu_si128((__m128i*)u, BgrToU8<T>(blue, green, red));
199
0
            _mm_storeu_si128((__m128i*)v, BgrToV8<T>(blue, green, red));
200
0
        }
Unexecuted instantiation: void Simd::Sse41::BgrToYuv444pV2<Simd::Base::Bt601>(unsigned char const*, unsigned char*, unsigned char*, unsigned char*)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv444pV2<Simd::Base::Bt709>(unsigned char const*, unsigned char*, unsigned char*, unsigned char*)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv444pV2<Simd::Base::Bt2020>(unsigned char const*, unsigned char*, unsigned char*, unsigned char*)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv444pV2<Simd::Base::Trect871>(unsigned char const*, unsigned char*, unsigned char*, unsigned char*)
201
202
        template <class T>  void BgrToYuv444pV2(const uint8_t* bgr, size_t bgrStride, size_t width, size_t height, uint8_t* y, size_t yStride,
203
            uint8_t* u, size_t uStride, uint8_t* v, size_t vStride)
204
0
        {
205
0
            assert(width >= A);
206
207
0
            size_t widthA = AlignLo(width, A);
208
0
            for (size_t row = 0; row < height; row += 1)
209
0
            {
210
0
                for (size_t col = 0; col < widthA; col += A)
211
0
                    BgrToYuv444pV2<T>(bgr + col * 3, y + col, u + col, v + col);
212
0
                if (width != widthA)
213
0
                {
214
0
                    size_t col = width - A;
215
0
                    BgrToYuv444pV2<T>(bgr + col * 3, y + col, u + col, v + col);
216
0
                }
217
0
                y += yStride;
218
0
                u += uStride;
219
0
                v += vStride;
220
0
                bgr += bgrStride;
221
0
            }
222
0
        }
Unexecuted instantiation: void Simd::Sse41::BgrToYuv444pV2<Simd::Base::Bt601>(unsigned char const*, unsigned long, unsigned long, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv444pV2<Simd::Base::Bt709>(unsigned char const*, unsigned long, unsigned long, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv444pV2<Simd::Base::Bt2020>(unsigned char const*, unsigned long, unsigned long, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long)
Unexecuted instantiation: void Simd::Sse41::BgrToYuv444pV2<Simd::Base::Trect871>(unsigned char const*, unsigned long, unsigned long, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long, unsigned char*, unsigned long)
223
224
        void BgrToYuv444pV2(const uint8_t* bgr, size_t bgrStride, size_t width, size_t height, uint8_t* y, size_t yStride,
225
            uint8_t* u, size_t uStride, uint8_t* v, size_t vStride, SimdYuvType yuvType)
226
0
        {
227
#if defined(SIMD_X86_ENABLE) && defined(NDEBUG) && defined(_MSC_VER) && _MSC_VER <= 1900
228
            Base::BgrToYuv444pV2(bgr, bgrStride, width, height, y, yStride, u, uStride, v, vStride, yuvType);
229
#else
230
0
            switch (yuvType)
231
0
            {
232
0
            case SimdYuvBt601: BgrToYuv444pV2<Base::Bt601>(bgr, bgrStride, width, height, y, yStride, u, uStride, v, vStride); break;
233
0
            case SimdYuvBt709: BgrToYuv444pV2<Base::Bt709>(bgr, bgrStride, width, height, y, yStride, u, uStride, v, vStride); break;
234
0
            case SimdYuvBt2020: BgrToYuv444pV2<Base::Bt2020>(bgr, bgrStride, width, height, y, yStride, u, uStride, v, vStride); break;
235
0
            case SimdYuvTrect871: BgrToYuv444pV2<Base::Trect871>(bgr, bgrStride, width, height, y, yStride, u, uStride, v, vStride); break;
236
0
            default:
237
                assert(0);
238
0
            }
239
0
#endif
240
0
        }
241
    }
242
#endif
243
}