-
Notifications
You must be signed in to change notification settings - Fork 429
Expand file tree
/
Copy pathPixelFormatYUV.h
More file actions
270 lines (232 loc) · 9.86 KB
/
Copy pathPixelFormatYUV.h
File metadata and controls
270 lines (232 loc) · 9.86 KB
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/* This file is part of YUView - The YUV player with advanced analytics toolset
* <https://github.com/IENT/YUView>
* Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY
*
* 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 3 of the License, or
* (at your option) any later version.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*
* You must obey the GNU General Public License in all respects for all
* of the code used other than OpenSSL. If you modify file(s) with this
* exception, you may extend this exception to your version of the
* file(s), but you are not obligated to do so. If you do not wish to do
* so, delete this exception statement from your version. If you delete
* this exception statement from all source files in the program, then
* also delete it here.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <common/EnumMapper.h>
#include <common/Offset.h>
#include <common/Size.h>
#include <common/Typedef.h>
#include <video/PixelFormat.h>
// The YUV_Internals namespace. We use this namespace because of the dialog. We want to be able to
// pass a PixelFormatYUV to the dialog and keep the global namespace clean but we are not able to
// use nested classes because of the Q_OBJECT macro. So the dialog and the PixelFormatYUV is inside
// of this namespace.
namespace video::yuv
{
enum class Component
{
Luma = 0,
Chroma = 1
};
/*
kr/kg/kb matrix (Rec. ITU-T H.264 03/2010, p. 379):
R = Y + V*(1-Kr)
G = Y - U*(1-Kb)*Kb/Kg - V*(1-Kr)*Kr/Kg
B = Y + U*(1-Kb)
To respect value range of Y in [16:235] and U/V in [16:240], the matrix entries need to be scaled
by 255/219 for Y and 255/224 for U/V In this software color conversion is performed with 16bit
precision. Thus, further scaling with 2^16 is performed to get all factors as integers.
*/
enum class ColorConversion
{
BT709_LimitedRange,
BT709_FullRange,
BT601_LimitedRange,
BT601_FullRange,
BT2020_LimitedRange,
BT2020_FullRange,
};
constexpr EnumMapper<ColorConversion, 6> ColorConversionMapper = {
std::make_pair(ColorConversion::BT709_LimitedRange, "ITU-R.BT709"),
std::make_pair(ColorConversion::BT709_FullRange, "ITU-R.BT709 Full Range"),
std::make_pair(ColorConversion::BT601_LimitedRange, "ITU-R.BT601"),
std::make_pair(ColorConversion::BT601_FullRange, "ITU-R.BT601 Full Range"),
std::make_pair(ColorConversion::BT2020_LimitedRange, "ITU-R.BT2020"),
std::make_pair(ColorConversion::BT2020_FullRange, "ITU-R.BT2020 Full Range")};
void getColorConversionCoefficients(ColorConversion colorConversion, int RGBConv[5]);
// How to perform up-sampling (chroma subsampling)
enum class ChromaInterpolation
{
NearestNeighbor,
Bilinear,
Interstitial
};
constexpr EnumMapper<ChromaInterpolation, 3> ChromaInterpolationMapper = {
std::make_pair(ChromaInterpolation::NearestNeighbor, "Nearest Neighbor"),
std::make_pair(ChromaInterpolation::Bilinear, "Bilinear"),
std::make_pair(ChromaInterpolation::Interstitial, "Interstitial")};
class MathParameters
{
public:
MathParameters() = default;
MathParameters(int scale, int offset, bool invert) : scale(scale), offset(offset), invert(invert)
{
}
// Do we need to apply any transform to the raw YUV data before conversion to RGB?
bool mathRequired() const { return scale != 1 || invert; }
int scale{1};
int offset{128};
bool invert{};
};
enum class PredefinedPixelFormat
{
// https://developer.apple.com/library/archive/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG8-V210__4_2_2_COMPRESSION_TYPE
// Packed 422 format with 12 10 bit values in 16 bytes
V210
};
constexpr EnumMapper<PredefinedPixelFormat, 1> PredefinedPixelFormatMapper = {
std::make_pair(PredefinedPixelFormat::V210, "V210")};
enum class PackingOrder
{
YUV, // 444
YVU, // 444
AYUV, // 444
YUVA, // 444
VUYA, // 444
UYVY, // 422
VYUY, // 422
YUYV, // 422
YVYU, // 422
// YYYYUV, // 420
// YYUYYV, // 420
// UYYVYY, // 420
// VYYUYY // 420
UNKNOWN
};
constexpr EnumMapper<PackingOrder, 9> PackingOrderMapper = {
std::make_pair(PackingOrder::YUV, "YUV"),
std::make_pair(PackingOrder::YVU, "YVU"),
std::make_pair(PackingOrder::AYUV, "AYUV"),
std::make_pair(PackingOrder::YUVA, "YUVA"),
std::make_pair(PackingOrder::VUYA, "VUYA"),
std::make_pair(PackingOrder::UYVY, "UYVY"),
std::make_pair(PackingOrder::VYUY, "VYUY"),
std::make_pair(PackingOrder::YUYV, "YUYV"),
std::make_pair(PackingOrder::YVYU, "YVYU")};
enum class Subsampling
{
YUV_444, // No subsampling
YUV_422, // Chroma: half horizontal resolution
YUV_420, // Chroma: half vertical and horizontal resolution
YUV_440, // Chroma: half vertical resolution
YUV_410, // Chroma: quarter vertical, quarter horizontal resolution
YUV_411, // Chroma: quarter horizontal resolution
YUV_400, // Luma only
UNKNOWN
};
constexpr EnumMapper<Subsampling, 7> SubsamplingMapper = {
std::make_pair(Subsampling::YUV_444, "444"),
std::make_pair(Subsampling::YUV_422, "422"),
std::make_pair(Subsampling::YUV_420, "420"),
std::make_pair(Subsampling::YUV_440, "440"),
std::make_pair(Subsampling::YUV_410, "410"),
std::make_pair(Subsampling::YUV_411, "411"),
std::make_pair(Subsampling::YUV_400, "400")};
std::string formatSubsamplingWithColons(const Subsampling &subsampling);
int getMaxPossibleChromaOffsetValues(bool horizontal, Subsampling subsampling);
std::vector<PackingOrder> getSupportedPackingFormats(Subsampling subsampling);
enum class PlaneOrder
{
YUV,
YVU,
YUVA,
YVUA
};
constexpr EnumMapper<PlaneOrder, 4> PlaneOrderMapper = {std::make_pair(PlaneOrder::YUV, "YUV"),
std::make_pair(PlaneOrder::YVU, "YVU"),
std::make_pair(PlaneOrder::YUVA, "YUVA"),
std::make_pair(PlaneOrder::YVUA, "YVUA")};
const auto BitDepthList = std::vector<unsigned>({8, 9, 10, 12, 14, 16});
// This class defines a specific YUV format with all properties like pixels per sample, subsampling
// of chroma components and so on.
class PixelFormatYUV
{
public:
PixelFormatYUV() = default;
PixelFormatYUV(const std::string_view name); // Set the pixel format by name. The name should have
// the format that is returned by getName().
PixelFormatYUV(Subsampling subsampling,
unsigned bitsPerSample,
PlaneOrder planeOrder = PlaneOrder::YUV,
bool bigEndian = false,
Offset chromaOffset = {},
bool uvInterleaved = false);
PixelFormatYUV(Subsampling subsampling,
unsigned bitsPerSample,
PackingOrder packingOrder,
bool bytePacking = false,
bool bigEndian = false,
Offset chromaOffset = {});
PixelFormatYUV(PredefinedPixelFormat predefinedPixelFormat);
std::optional<PredefinedPixelFormat> getPredefinedFormat() const;
bool isValid() const;
bool canConvertToRGB(Size frameSize, std::string *whyNot = nullptr) const;
int64_t bytesPerFrame(const Size &frameSize) const;
std::string getName() const;
unsigned getNrPlanes() const;
void setDefaultChromaOffset();
Subsampling getSubsampling() const;
int getSubsamplingHor(Component component = Component::Chroma) const;
int getSubsamplingVer(Component component = Component::Chroma) const;
bool isChromaSubsampled() const;
unsigned getBitsPerSample() const;
bool isBigEndian() const;
bool isPlanar() const;
bool hasAlpha() const;
Offset getChromaOffset() const;
PlaneOrder getPlaneOrder() const { return this->planeOrder; }
bool isUVInterleaved() const { return this->uvInterleaved; }
PackingOrder getPackingOrder() const { return this->packingOrder; }
bool isBytePacking() const;
bool operator==(const PixelFormatYUV &a) const { return getName() == a.getName(); }
bool operator!=(const PixelFormatYUV &a) const { return getName() != a.getName(); }
bool operator==(const std::string &a) const { return getName() == a; }
bool operator!=(const std::string &a) const { return getName() != a; }
operator bool() const { return this->isValid(); }
private:
// If this is set, the format is defined according to a specific standard and does not
// conform to the definition below (using subsampling/bitDepht/planes/packed)
// If this is set, none of the values below matter.
std::optional<PredefinedPixelFormat> predefinedPixelFormat;
Subsampling subsampling{Subsampling::YUV_420};
unsigned bitsPerSample{};
bool bigEndian{};
bool planar{};
// The chroma offset in x and y direction. The vales (0...4) define the offsets [0, 1/2, 1, 3/2]
// samples towards the right and bottom.
Offset chromaOffset;
PlaneOrder planeOrder{PlaneOrder::YUV};
bool uvInterleaved{}; //< If set, the UV (and A if present) planes are interleaved
// if planar is not set
PackingOrder packingOrder{PackingOrder::YUV};
bool bytePacking{};
};
} // namespace video::yuv