7 #include "packager/media/formats/dvb/dvb_sub_parser.h"
11 #include "packager/base/logging.h"
12 #include "packager/media/formats/mp2t/mp2t_common.h"
19 RgbaColor ConvertYuv(uint8_t Y, uint8_t Cr, uint8_t Cb, uint8_t T) {
28 const double y_transform = 255.0 / 219 * (std::max<uint8_t>(Y, 16) - 16);
29 const double cb_transform = 255.0 / 244 * 1.772 * (Cb - 128);
30 const double cr_transform = 255.0 / 244 * 1.402 * (Cr - 128);
31 const double f1 = 0.114 / 0.587;
32 const double f2 = 0.299 / 0.587;
33 color.r =
static_cast<uint8_t
>(y_transform + cr_transform);
35 static_cast<uint8_t
>(y_transform - cb_transform * f1 - cr_transform * f2);
36 color.b =
static_cast<uint8_t
>(y_transform + cb_transform);
37 color.a = Y == 0 ? 0 : (T == 0 ? 255 : 256 - T);
43 DvbSubParser::DvbSubParser() : last_pts_(0), timeout_(0) {}
45 DvbSubParser::~DvbSubParser() {}
47 bool DvbSubParser::Parse(DvbSubSegmentType segment_type,
49 const uint8_t* payload,
51 std::vector<std::shared_ptr<TextSample>>* samples) {
52 switch (segment_type) {
53 case DvbSubSegmentType::kPageComposition:
54 return ParsePageComposition(pts, payload, size, samples);
55 case DvbSubSegmentType::kRegionComposition:
56 return ParseRegionComposition(payload, size);
57 case DvbSubSegmentType::kClutDefinition:
58 return ParseClutDefinition(payload, size);
59 case DvbSubSegmentType::kObjectData:
60 return ParseObjectData(pts, payload, size);
61 case DvbSubSegmentType::kDisplayDefinition:
62 return ParseDisplayDefinition(payload, size);
63 case DvbSubSegmentType::kEndOfDisplay:
68 LOG(WARNING) <<
"Unknown DVB-sub segment_type=0x" << std::hex
69 <<
static_cast<uint32_t
>(segment_type);
74 bool DvbSubParser::Flush(std::vector<std::shared_ptr<TextSample>>* samples) {
75 RCHECK(composer_.GetSamples(last_pts_, last_pts_ + timeout_ * kMpeg2Timescale,
77 composer_.ClearObjects();
81 const DvbImageColorSpace* DvbSubParser::GetColorSpace(uint8_t clut_id) {
82 return composer_.GetColorSpace(clut_id);
85 const DvbImageBuilder* DvbSubParser::GetImageForObject(uint16_t object_id) {
86 return composer_.GetObjectImage(object_id);
89 bool DvbSubParser::ParsePageComposition(
93 std::vector<std::shared_ptr<TextSample>>* samples) {
95 BitReader reader(data, size);
98 RCHECK(reader.ReadBits(8, &timeout_));
99 RCHECK(reader.SkipBits(4));
100 RCHECK(reader.ReadBits(2, &page_state));
101 RCHECK(reader.SkipBits(2));
102 if (page_state == 0x1 || page_state == 0x2) {
105 RCHECK(composer_.GetSamples(last_pts_, pts, samples));
106 composer_.ClearObjects();
110 while (reader.bits_available() > 0u) {
113 RCHECK(reader.ReadBits(8, ®ion_id));
114 RCHECK(reader.SkipBits(8));
115 RCHECK(reader.ReadBits(16, &x));
116 RCHECK(reader.ReadBits(16, &y));
118 RCHECK(composer_.SetRegionPosition(region_id, x, y));
124 bool DvbSubParser::ParseRegionComposition(
const uint8_t* data,
size_t size) {
126 BitReader reader(data, size);
128 uint8_t region_id, clut_id;
129 uint16_t region_width, region_height;
130 bool region_fill_flag;
131 int background_pixel_code;
132 RCHECK(reader.ReadBits(8, ®ion_id));
133 RCHECK(reader.SkipBits(4));
134 RCHECK(reader.ReadBits(1, ®ion_fill_flag));
135 RCHECK(reader.SkipBits(3));
136 RCHECK(reader.ReadBits(16, ®ion_width));
137 RCHECK(reader.ReadBits(16, ®ion_height));
138 RCHECK(reader.SkipBits(3));
139 RCHECK(reader.SkipBits(3));
140 RCHECK(reader.SkipBits(2));
141 RCHECK(reader.ReadBits(8, &clut_id));
142 RCHECK(reader.ReadBits(8, &background_pixel_code));
143 RCHECK(reader.SkipBits(4));
144 RCHECK(reader.SkipBits(2));
145 RCHECK(reader.SkipBits(2));
147 composer_.SetRegionInfo(region_id, clut_id, region_width, region_height));
148 if (!region_fill_flag)
149 background_pixel_code = -1;
151 while (reader.bits_available() > 0) {
152 uint16_t object_id, x, y;
154 RCHECK(reader.ReadBits(16, &object_id));
155 RCHECK(reader.ReadBits(2, &object_type));
156 RCHECK(reader.SkipBits(2));
157 RCHECK(reader.ReadBits(12, &x));
158 RCHECK(reader.SkipBits(4));
159 RCHECK(reader.ReadBits(12, &y));
161 if (object_type == 0x01 || object_type == 0x02) {
162 RCHECK(reader.SkipBits(8));
163 RCHECK(reader.SkipBits(8));
165 RCHECK(composer_.SetObjectInfo(object_id, region_id, x, y,
166 background_pixel_code));
172 bool DvbSubParser::ParseClutDefinition(
const uint8_t* data,
size_t size) {
174 BitReader reader(data, size);
177 RCHECK(reader.ReadBits(8, &clut_id));
178 auto* color_space = composer_.GetColorSpace(clut_id);
179 RCHECK(reader.SkipBits(4));
180 RCHECK(reader.SkipBits(4));
181 while (reader.bits_available() > 0) {
182 uint8_t clut_entry_id;
186 uint8_t full_range_flag;
187 RCHECK(reader.ReadBits(8, &clut_entry_id));
188 RCHECK(reader.ReadBits(1, &has_2_bit));
189 RCHECK(reader.ReadBits(1, &has_4_bit));
190 RCHECK(reader.ReadBits(1, &has_8_bit));
191 RCHECK(reader.SkipBits(4));
192 RCHECK(reader.ReadBits(1, &full_range_flag));
194 if (has_2_bit + has_4_bit + has_8_bit != 1) {
195 LOG(ERROR) <<
"Must specify exactly one bit depth in CLUT definition";
198 const BitDepth bit_depth =
199 has_2_bit ? BitDepth::k2Bit
200 : (has_4_bit ? BitDepth::k4Bit : BitDepth::k8Bit);
202 uint8_t Y, Cr, Cb, T;
203 if (full_range_flag) {
204 RCHECK(reader.ReadBits(8, &Y));
205 RCHECK(reader.ReadBits(8, &Cr));
206 RCHECK(reader.ReadBits(8, &Cb));
207 RCHECK(reader.ReadBits(8, &T));
210 RCHECK(reader.ReadBits(6, &Y));
212 RCHECK(reader.ReadBits(4, &Cr));
214 RCHECK(reader.ReadBits(4, &Cb));
216 RCHECK(reader.ReadBits(2, &T));
219 color_space->SetColor(bit_depth, clut_entry_id, ConvertYuv(Y, Cr, Cb, T));
225 bool DvbSubParser::ParseObjectData(int64_t pts,
229 BitReader reader(data, size);
232 uint8_t object_coding_method;
233 RCHECK(reader.ReadBits(16, &object_id));
234 RCHECK(reader.SkipBits(4));
235 RCHECK(reader.ReadBits(2, &object_coding_method));
236 RCHECK(reader.SkipBits(1));
237 RCHECK(reader.SkipBits(1));
239 auto* image = composer_.GetObjectImage(object_id);
240 auto* color_space = composer_.GetColorSpaceForObject(object_id);
241 if (!image || !color_space)
244 if (object_coding_method == 0) {
245 uint16_t top_field_length;
246 uint16_t bottom_field_length;
247 RCHECK(reader.ReadBits(16, &top_field_length));
248 RCHECK(reader.ReadBits(16, &bottom_field_length));
250 RCHECK(ParsePixelDataSubObject(top_field_length,
true, &reader, color_space,
252 RCHECK(ParsePixelDataSubObject(bottom_field_length,
false, &reader,
253 color_space, image));
256 if (bottom_field_length == 0) {
259 image->MirrorToBottomRows();
262 LOG(ERROR) <<
"Unsupported DVB-sub object coding method: "
263 <<
static_cast<int>(object_coding_method);
269 bool DvbSubParser::ParseDisplayDefinition(
const uint8_t* data,
size_t size) {
271 BitReader reader(data, size);
273 uint16_t width, height;
274 RCHECK(reader.SkipBits(4));
275 RCHECK(reader.SkipBits(1));
276 RCHECK(reader.SkipBits(3));
277 RCHECK(reader.ReadBits(16, &width));
278 RCHECK(reader.ReadBits(16, &height));
280 composer_.SetDisplaySize(width + 1, height + 1);
285 bool DvbSubParser::ParsePixelDataSubObject(
size_t sub_object_length,
288 DvbImageColorSpace* color_space,
289 DvbImageBuilder* image) {
290 const size_t start = reader->bit_position() / 8;
291 while (reader->bit_position() / 8 < start + sub_object_length) {
294 RCHECK(reader->ReadBits(8, &data_type));
298 RCHECK(Parse2BitPixelData(is_top_fields, reader, image));
299 reader->SkipToNextByte();
302 RCHECK(Parse4BitPixelData(is_top_fields, reader, image));
303 reader->SkipToNextByte();
306 RCHECK(Parse8BitPixelData(is_top_fields, reader, image));
309 for (
int i = 0; i < 4; i++) {
310 RCHECK(reader->ReadBits(4, &temp[i]));
312 color_space->Set2To4BitDepthMap(temp);
315 for (
int i = 0; i < 4; i++) {
316 RCHECK(reader->ReadBits(8, &temp[i]));
318 color_space->Set2To8BitDepthMap(temp);
321 for (
int i = 0; i < 16; i++) {
322 RCHECK(reader->ReadBits(8, &temp[i]));
324 color_space->Set4To8BitDepthMap(temp);
327 image->NewRow(is_top_fields);
330 LOG(ERROR) <<
"Unsupported DVB-sub pixel data format: 0x" << std::hex
331 <<
static_cast<int>(data_type);
338 bool DvbSubParser::Parse2BitPixelData(
bool is_top_fields,
340 DvbImageBuilder* image) {
344 RCHECK(reader->ReadBits(2, &peek));
346 RCHECK(image->AddPixel(BitDepth::k2Bit, peek, is_top_fields));
349 RCHECK(reader->ReadBits(1, &switch_1));
351 uint8_t count_minus_3;
352 RCHECK(reader->ReadBits(3, &count_minus_3));
353 RCHECK(reader->ReadBits(2, &peek));
354 for (uint8_t i = 0; i < count_minus_3 + 3; i++)
355 RCHECK(image->AddPixel(BitDepth::k2Bit, peek, is_top_fields));
358 RCHECK(reader->ReadBits(1, &switch_2));
360 RCHECK(image->AddPixel(BitDepth::k2Bit, 0, is_top_fields));
363 RCHECK(reader->ReadBits(2, &switch_3));
366 }
else if (switch_3 == 1) {
367 RCHECK(image->AddPixel(BitDepth::k2Bit, 0, is_top_fields));
368 RCHECK(image->AddPixel(BitDepth::k2Bit, 0, is_top_fields));
369 }
else if (switch_3 == 2) {
370 uint8_t count_minus_12;
371 RCHECK(reader->ReadBits(4, &count_minus_12));
372 RCHECK(reader->ReadBits(2, &peek));
373 for (uint8_t i = 0; i < count_minus_12 + 12; i++)
374 RCHECK(image->AddPixel(BitDepth::k2Bit, peek, is_top_fields));
375 }
else if (switch_3 == 3) {
376 uint8_t count_minus_29;
377 RCHECK(reader->ReadBits(8, &count_minus_29));
378 RCHECK(reader->ReadBits(2, &peek));
379 for (uint8_t i = 0; i < count_minus_29 + 29; i++)
380 RCHECK(image->AddPixel(BitDepth::k2Bit, peek, is_top_fields));
390 bool DvbSubParser::Parse4BitPixelData(
bool is_top_fields,
392 DvbImageBuilder* image) {
394 DCHECK(reader->bits_available() % 8 == 0);
397 RCHECK(reader->ReadBits(4, &peek));
399 RCHECK(image->AddPixel(BitDepth::k4Bit, peek, is_top_fields));
402 RCHECK(reader->ReadBits(1, &switch_1));
404 RCHECK(reader->ReadBits(3, &peek));
406 for (
int i = 0; i < peek + 2; i++)
407 RCHECK(image->AddPixel(BitDepth::k4Bit, 0, is_top_fields));
413 RCHECK(reader->ReadBits(1, &switch_2));
415 RCHECK(reader->ReadBits(2, &peek));
417 RCHECK(reader->ReadBits(4, &code));
418 for (
int i = 0; i < peek + 4; i++)
419 RCHECK(image->AddPixel(BitDepth::k4Bit, code, is_top_fields));
422 RCHECK(reader->ReadBits(2, &switch_3));
424 RCHECK(image->AddPixel(BitDepth::k4Bit, 0, is_top_fields));
425 }
else if (switch_3 == 1) {
426 RCHECK(image->AddPixel(BitDepth::k4Bit, 0, is_top_fields));
427 RCHECK(image->AddPixel(BitDepth::k4Bit, 0, is_top_fields));
428 }
else if (switch_3 == 2) {
429 RCHECK(reader->ReadBits(4, &peek));
431 RCHECK(reader->ReadBits(4, &code));
432 for (
int i = 0; i < peek + 9; i++)
433 RCHECK(image->AddPixel(BitDepth::k4Bit, code, is_top_fields));
436 RCHECK(reader->ReadBits(8, &peek));
438 RCHECK(reader->ReadBits(4, &code));
439 for (
int i = 0; i < peek + 25; i++)
440 RCHECK(image->AddPixel(BitDepth::k4Bit, code, is_top_fields));
449 bool DvbSubParser::Parse8BitPixelData(
bool is_top_fields,
451 DvbImageBuilder* image) {
455 RCHECK(reader->ReadBits(8, &peek));
457 RCHECK(image->AddPixel(BitDepth::k8Bit, peek, is_top_fields));
460 RCHECK(reader->ReadBits(1, &switch_1));
462 RCHECK(reader->ReadBits(7, &peek));
464 for (uint8_t i = 0; i < peek; i++)
465 RCHECK(image->AddPixel(BitDepth::k8Bit, 0, is_top_fields));
471 RCHECK(reader->ReadBits(7, &count));
472 RCHECK(reader->ReadBits(8, &peek));
473 for (uint8_t i = 0; i < count; i++)
474 RCHECK(image->AddPixel(BitDepth::k8Bit, peek, is_top_fields));
All the methods that are virtual are virtual for mocking.