7 #include <packager/media/formats/dvb/dvb_image.h>
13 #include <absl/log/check.h>
14 #include <absl/log/log.h>
22 constexpr
const uint8_t k4To2ReductionMap[] = {
23 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
24 0x2, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3,
29 constexpr
const RgbaColor kNoColor{145, 92, 47, 0};
33 #define COLOR(r, g, b, t) \
35 static_cast<uint8_t>(255 * (r) / 100), \
36 static_cast<uint8_t>(255 * (g) / 100), \
37 static_cast<uint8_t>(255 * (b) / 100), \
38 static_cast<uint8_t>(255 * (100 - t) / 100) \
41 constexpr
const RgbaColor k2BitDefaultColors[] = {
43 COLOR(100, 100, 100, 0),
48 constexpr
const RgbaColor k4BitDefaultColors[] = {
52 COLOR(100, 100, 0, 0),
54 COLOR(100, 0, 100, 0),
55 COLOR(0, 100, 100, 0),
56 COLOR(100, 100, 100, 0),
68 #define GET_BIT(n) ((entry_id >> (8 - (n))) & 0x1)
70 RgbaColor Get8BitDefaultColor(uint8_t entry_id) {
73 return COLOR(0, 0, 0, 100);
74 }
else if ((entry_id & 0xf8) == 0) {
79 }
else if (!GET_BIT(1)) {
80 r = (33 * GET_BIT(8)) + (67 * GET_BIT(4));
81 g = (33 * GET_BIT(7)) + (67 * GET_BIT(3));
82 b = (33 * GET_BIT(6)) + (67 * GET_BIT(2));
83 t = GET_BIT(5) ? 50 : 0;
85 r = (17 * GET_BIT(8)) + (33 * GET_BIT(4)) + (GET_BIT(5) ? 0 : 50);
86 g = (17 * GET_BIT(7)) + (33 * GET_BIT(3)) + (GET_BIT(5) ? 0 : 50);
87 b = (17 * GET_BIT(6)) + (33 * GET_BIT(2)) + (GET_BIT(5) ? 0 : 50);
90 return COLOR(r, g, b, t);
97 DvbImageColorSpace::DvbImageColorSpace() {
98 for (
auto& item : color_map_2_)
100 for (
auto& item : color_map_4_)
102 for (
auto& item : color_map_8_)
106 DvbImageColorSpace::~DvbImageColorSpace() {}
108 RgbaColor DvbImageColorSpace::GetColor(BitDepth bit_depth,
109 uint8_t entry_id)
const {
110 auto color = GetColorRaw(bit_depth, entry_id);
111 if (color != kNoColor)
116 RgbaColor default_color, alt1, alt2;
118 case BitDepth::k2Bit:
119 DCHECK_LT(entry_id, 4u);
120 alt1 = GetColorRaw(BitDepth::k4Bit, bit_depth_2_to_4_[entry_id]);
121 alt2 = GetColorRaw(BitDepth::k8Bit, bit_depth_2_to_8_[entry_id]);
122 default_color = k2BitDefaultColors[entry_id];
124 case BitDepth::k4Bit:
125 DCHECK_LT(entry_id, 16u);
126 alt1 = GetColorRaw(BitDepth::k8Bit, bit_depth_4_to_8_[entry_id]);
127 alt2 = GetColorRaw(BitDepth::k2Bit, k4To2ReductionMap[entry_id]);
128 default_color = k4BitDefaultColors[entry_id];
130 case BitDepth::k8Bit:
132 alt1 = GetColorRaw(BitDepth::k4Bit, entry_id & 0xf);
133 alt2 = GetColorRaw(BitDepth::k2Bit, k4To2ReductionMap[entry_id & 0xf]);
134 default_color = Get8BitDefaultColor(entry_id);
142 if (alt1 != kNoColor)
144 if (alt2 != kNoColor)
146 return default_color;
149 void DvbImageColorSpace::SetColor(BitDepth bit_depth,
152 DCHECK(color != kNoColor);
154 case BitDepth::k2Bit:
155 DCHECK_LT(entry_id, 4u);
156 color_map_2_[entry_id] = color;
158 case BitDepth::k4Bit:
159 DCHECK_LT(entry_id, 16u);
160 color_map_4_[entry_id] = color;
162 case BitDepth::k8Bit:
163 color_map_8_[entry_id] = color;
169 memcpy(bit_depth_2_to_4_, map,
sizeof(bit_depth_2_to_4_));
173 memcpy(bit_depth_2_to_8_, map,
sizeof(bit_depth_2_to_8_));
177 memcpy(bit_depth_4_to_8_, map,
sizeof(bit_depth_4_to_8_));
180 RgbaColor DvbImageColorSpace::GetColorRaw(BitDepth bit_depth,
181 uint8_t entry_id)
const {
183 case BitDepth::k2Bit:
184 return color_map_2_[entry_id];
185 case BitDepth::k4Bit:
186 return color_map_4_[entry_id];
187 case BitDepth::k8Bit:
188 return color_map_8_[entry_id];
194 DvbImageBuilder::DvbImageBuilder(
const DvbImageColorSpace* color_space,
195 const RgbaColor& default_color,
198 : pixels_(new RgbaColor[max_width * max_height]),
199 color_space_(color_space),
202 max_width_(max_width),
203 max_height_(max_height),
205 for (
size_t i = 0; i < static_cast<size_t>(max_width) * max_height; i++)
206 pixels_[i] = default_color;
209 DvbImageBuilder::~DvbImageBuilder() {}
211 bool DvbImageBuilder::AddPixel(BitDepth bit_depth,
214 auto& pos = is_top_rows ? top_pos_ : bottom_pos_;
215 if (pos.x >= max_width_ || pos.y >= max_height_) {
216 LOG(ERROR) <<
"DVB-sub image cannot fit in region/window";
220 pixels_[pos.y * max_width_ + pos.x++] =
221 color_space_->GetColor(bit_depth, byte_code);
227 void DvbImageBuilder::NewRow(
bool is_top_rows) {
228 auto& pos = is_top_rows ? top_pos_ : bottom_pos_;
234 for (
size_t line = 0; line < max_height_ - 1u; line += 2) {
235 std::memcpy(&pixels_[(line + 1) * max_width_], &pixels_[line * max_width_],
238 bottom_pos_ = top_pos_;
239 if (max_height_ % 2 == 0)
247 uint16_t* height)
const {
249 std::tie(min_y, max_y) = std::minmax(top_pos_.y, bottom_pos_.y);
250 if (max_y == 1 || max_y != min_y + 1) {
253 LOG(ERROR) <<
"Incomplete DVB-sub image";
259 *height =
static_cast<uint16_t
>(max_y - 1);
260 *pixels = pixels_.get();
261 if (*height > max_height_) {
262 LOG(ERROR) <<
"DVB-sub image cannot fit in region/window";
All the methods that are virtual are virtual for mocking.