MPC-HC 19f3afdfa6586b556af5886f8eaf1f1390f06612 Properly enable memory leak detection.
[xy_vsfilter.git] / src / subtitles / CompositionObject.cpp
blobc37e2a05e51fd3cea349e0d0b3d588196a6e9da3
1 /*
2 * (C) 2006-2012 see Authors.txt
4 * This file is part of MPC-HC.
6 * MPC-HC is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * MPC-HC is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "stdafx.h"
22 #include "CompositionObject.h"
23 #include "../DSUtil/GolombBuffer.h"
24 #include "../subpic/color_conv_table.h"
27 CompositionObject::CompositionObject()
29 m_pRLEData = NULL;
30 m_nRLEDataSize = 0;
31 m_nRLEPos = 0;
33 memsetd(m_Colors, 0xFF000000, sizeof(m_Colors));
36 CompositionObject::~CompositionObject()
38 delete [] m_pRLEData;
41 void CompositionObject::SetPalette(int nNbEntry, HDMV_PALETTE* pPalette, ColorType color_type, YuvRangeType yuv_range)
43 m_OriginalColorType = color_type;
44 m_OriginalYuvRangeType = yuv_range;
46 m_colorType = -1;
48 m_Palette.SetCount(nNbEntry>0?nNbEntry:0);
49 if(nNbEntry>0)
51 memcpy(m_Palette.GetData(), pPalette, nNbEntry*sizeof(pPalette[0]));
55 void CompositionObject::InitColor(const SubPicDesc& spd)
57 #define COMBINE_AYUV(a, y, u, v) ((((((((int)(a))<<8)|y)<<8)|u)<<8)|v)
58 //fix me: move all color conv function into color_conv_table or dsutil
59 #define FULL_TYPE(x,y) (((x)<<8)|y)
61 int paletteNumber = m_Palette.GetCount();
62 if (m_colorType!=spd.type)
64 m_colorType = -1;
65 ColorConvTable::YuvMatrixType cur_type;
66 ColorConvTable::YuvRangeType cur_range;
67 if (m_OriginalColorType==YUV_Rec601)
69 cur_type = ColorConvTable::BT601;
71 else if (m_OriginalColorType==YUV_Rec709)
73 cur_type = ColorConvTable::BT709;
75 else
77 XY_LOG_ERROR("Not supported");
78 ASSERT(0);
79 return;
81 if (m_OriginalYuvRangeType==RANGE_TV)
83 cur_range = ColorConvTable::RANGE_TV;
85 else if (m_OriginalYuvRangeType==RANGE_PC)
87 cur_range = ColorConvTable::RANGE_PC;
89 else
91 XY_LOG_ERROR("Not supported");
92 ASSERT(0);
93 return;
96 m_colorType = spd.type;
97 switch(spd.type)
99 case MSP_AYUV_PLANAR:
100 case MSP_AYUV:
101 if (FULL_TYPE(cur_type,cur_range)==
102 FULL_TYPE(ColorConvTable::GetDefaultYUVType(), ColorConvTable::GetDefaultRangeType()))
104 for (int i=0;i<paletteNumber;i++)
106 m_Colors[m_Palette[i].entry_id] = COMBINE_AYUV(m_Palette[i].T, m_Palette[i].Y, m_Palette[i].Cb
107 , m_Palette[i].Cr);
110 else if (cur_type==ColorConvTable::GetDefaultYUVType())
112 if (cur_range==ColorConvTable::RANGE_PC)
114 for (int i=0;i<paletteNumber;i++)
116 m_Colors[m_Palette[i].entry_id] = ColorConvTable::A8Y8U8V8_PC_To_TV(m_Palette[i].T, m_Palette[i].Y
117 , m_Palette[i].Cb, m_Palette[i].Cr);
120 else if (cur_range==ColorConvTable::RANGE_TV)
122 for (int i=0;i<paletteNumber;i++)
124 m_Colors[m_Palette[i].entry_id] = ColorConvTable::A8Y8U8V8_TV_To_PC(m_Palette[i].T, m_Palette[i].Y
125 , m_Palette[i].Cb, m_Palette[i].Cr);
129 else if (FULL_TYPE(cur_type,cur_range)==
130 FULL_TYPE(ColorConvTable::BT709, ColorConvTable::RANGE_TV))
132 for (int i=0;i<paletteNumber;i++)
134 DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT709(m_Palette[i].T, m_Palette[i].Y
135 , m_Palette[i].Cb, m_Palette[i].Cr);
136 m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Ayuv(argb);
139 else if (FULL_TYPE(cur_type,cur_range)==
140 FULL_TYPE(ColorConvTable::BT709, ColorConvTable::RANGE_PC))
142 for (int i=0;i<paletteNumber;i++)
144 DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_PC_BT709(m_Palette[i].T, m_Palette[i].Y
145 , m_Palette[i].Cb, m_Palette[i].Cr);
146 m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Ayuv(argb);
149 else if (FULL_TYPE(cur_type,cur_range)==
150 FULL_TYPE(ColorConvTable::BT601, ColorConvTable::RANGE_TV))
152 for (int i=0;i<paletteNumber;i++)
154 DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT601(m_Palette[i].T, m_Palette[i].Y
155 , m_Palette[i].Cb, m_Palette[i].Cr);
156 m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Ayuv(argb);
159 else if (FULL_TYPE(cur_type,cur_range)==
160 FULL_TYPE(ColorConvTable::BT601, ColorConvTable::RANGE_PC))
162 for (int i=0;i<paletteNumber;i++)
164 DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_PC_BT601(m_Palette[i].T, m_Palette[i].Y
165 , m_Palette[i].Cb, m_Palette[i].Cr);
166 m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Ayuv(argb);
169 else
171 XY_LOG_ERROR("Not supported");
172 ASSERT(0);
173 return;
175 break;
176 case MSP_XY_AUYV:
177 if (FULL_TYPE(cur_type,cur_range)==
178 FULL_TYPE(ColorConvTable::GetDefaultYUVType(), ColorConvTable::GetDefaultRangeType()))
180 for (int i=0;i<paletteNumber;i++)
182 m_Colors[m_Palette[i].entry_id] = COMBINE_AYUV(m_Palette[i].T, m_Palette[i].Cb, m_Palette[i].Y
183 , m_Palette[i].Cr);
186 else if (cur_type==ColorConvTable::GetDefaultYUVType())
188 if (cur_range==ColorConvTable::RANGE_PC)
190 for (int i=0;i<paletteNumber;i++)
192 DWORD ayuv = ColorConvTable::A8Y8U8V8_PC_To_TV(m_Palette[i].T, m_Palette[i].Y
193 , m_Palette[i].Cb, m_Palette[i].Cr);
194 m_Colors[m_Palette[i].entry_id] = ColorConvTable::Ayuv2Auyv(ayuv);
197 else if (cur_range==ColorConvTable::RANGE_TV)
199 for (int i=0;i<paletteNumber;i++)
201 DWORD ayuv = ColorConvTable::A8Y8U8V8_TV_To_PC(m_Palette[i].T, m_Palette[i].Y
202 , m_Palette[i].Cb, m_Palette[i].Cr);
203 m_Colors[m_Palette[i].entry_id] = ColorConvTable::Ayuv2Auyv(ayuv);
207 else if (FULL_TYPE(cur_type,cur_range)==
208 FULL_TYPE(ColorConvTable::BT709, ColorConvTable::RANGE_TV))
210 for (int i=0;i<paletteNumber;i++)
212 DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT709(m_Palette[i].T, m_Palette[i].Y
213 , m_Palette[i].Cb, m_Palette[i].Cr);
214 m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Auyv(argb);
217 else if (FULL_TYPE(cur_type,cur_range)==
218 FULL_TYPE(ColorConvTable::BT709, ColorConvTable::RANGE_PC))
220 for (int i=0;i<paletteNumber;i++)
222 DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_PC_BT709(m_Palette[i].T, m_Palette[i].Y
223 , m_Palette[i].Cb, m_Palette[i].Cr);
224 m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Auyv(argb);
227 else if (FULL_TYPE(cur_type,cur_range)==
228 FULL_TYPE(ColorConvTable::BT601, ColorConvTable::RANGE_TV))
230 for (int i=0;i<paletteNumber;i++)
232 DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT601(m_Palette[i].T, m_Palette[i].Y
233 , m_Palette[i].Cb, m_Palette[i].Cr);
234 m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Auyv(argb);
237 else if (FULL_TYPE(cur_type,cur_range)==
238 FULL_TYPE(ColorConvTable::BT601, ColorConvTable::RANGE_PC))
240 for (int i=0;i<paletteNumber;i++)
242 DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_PC_BT601(m_Palette[i].T, m_Palette[i].Y
243 , m_Palette[i].Cb, m_Palette[i].Cr);
244 m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Auyv(argb);
247 else
249 XY_LOG_ERROR("Not supported");
250 ASSERT(0);
251 return;
253 break;
254 case MSP_RGBA:
255 if (FULL_TYPE(cur_type,cur_range)==
256 FULL_TYPE(ColorConvTable::BT709, ColorConvTable::RANGE_TV))
258 for (int i=0;i<paletteNumber;i++)
260 DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT709(m_Palette[i].T, m_Palette[i].Y
261 , m_Palette[i].Cb, m_Palette[i].Cr);
262 m_Colors[m_Palette[i].entry_id] = argb;
265 else if (FULL_TYPE(cur_type,cur_range)==
266 FULL_TYPE(ColorConvTable::BT709, ColorConvTable::RANGE_PC))
268 for (int i=0;i<paletteNumber;i++)
270 DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_PC_BT709(m_Palette[i].T, m_Palette[i].Y
271 , m_Palette[i].Cb, m_Palette[i].Cr);
272 m_Colors[m_Palette[i].entry_id] = argb;
275 else if (FULL_TYPE(cur_type,cur_range)==
276 FULL_TYPE(ColorConvTable::BT601, ColorConvTable::RANGE_TV))
278 for (int i=0;i<paletteNumber;i++)
280 DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT601(m_Palette[i].T, m_Palette[i].Y
281 , m_Palette[i].Cb, m_Palette[i].Cr);
282 m_Colors[m_Palette[i].entry_id] = argb;
285 else if (FULL_TYPE(cur_type,cur_range)==
286 FULL_TYPE(ColorConvTable::BT601, ColorConvTable::RANGE_PC))
288 for (int i=0;i<paletteNumber;i++)
290 DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_PC_BT601(m_Palette[i].T, m_Palette[i].Y
291 , m_Palette[i].Cb, m_Palette[i].Cr);
292 m_Colors[m_Palette[i].entry_id] = argb;
295 else
297 XY_LOG_ERROR("Not supported");
298 ASSERT(0);
299 return;
301 break;
302 default:
303 XY_LOG_ERROR("Not supported");
304 ASSERT(0);
305 return;
310 void CompositionObject::SetRLEData(const BYTE* pBuffer, int nSize, int nTotalSize)
312 delete [] m_pRLEData;
313 m_pRLEData = DEBUG_NEW BYTE[nTotalSize];
314 m_nRLEDataSize = nTotalSize;
315 m_nRLEPos = nSize;
317 memcpy(m_pRLEData, pBuffer, nSize);
320 void CompositionObject::AppendRLEData(const BYTE* pBuffer, int nSize)
322 ASSERT(m_nRLEPos + nSize <= m_nRLEDataSize);
323 if (m_nRLEPos + nSize <= m_nRLEDataSize) {
324 memcpy(m_pRLEData + m_nRLEPos, pBuffer, nSize);
325 m_nRLEPos += nSize;
330 void CompositionObject::RenderHdmv(SubPicDesc& spd)
332 if (!m_pRLEData || !HavePalette()) {
333 return;
336 CGolombBuffer GBuffer(m_pRLEData, m_nRLEDataSize);
337 BYTE bTemp;
338 BYTE bSwitch;
339 BYTE nPaletteIndex = 0;
340 short nCount;
341 short nX = m_horizontal_position;
342 short nY = m_vertical_position;
344 while ((nY < (m_vertical_position + m_height)) && !GBuffer.IsEOF()) {
345 bTemp = GBuffer.ReadByte();
346 if (bTemp != 0) {
347 nPaletteIndex = bTemp;
348 nCount = 1;
349 } else {
350 bSwitch = GBuffer.ReadByte();
351 if (!(bSwitch & 0x80)) {
352 if (!(bSwitch & 0x40)) {
353 nCount = bSwitch & 0x3F;
354 if (nCount > 0) {
355 nPaletteIndex = 0;
357 } else {
358 nCount = (bSwitch & 0x3F) << 8 | (short)GBuffer.ReadByte();
359 nPaletteIndex = 0;
361 } else {
362 if (!(bSwitch & 0x40)) {
363 nCount = bSwitch & 0x3F;
364 nPaletteIndex = GBuffer.ReadByte();
365 } else {
366 nCount = (bSwitch & 0x3F) << 8 | (short)GBuffer.ReadByte();
367 nPaletteIndex = GBuffer.ReadByte();
372 if (nCount > 0) {
373 if (nPaletteIndex != 0xFF) { // Fully transparent (§9.14.4.2.2.1.1)
374 FillSolidRect(spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]);
376 nX += nCount;
377 } else {
378 nY++;
379 nX = m_horizontal_position;
385 void CompositionObject::RenderDvb(SubPicDesc& spd, short nX, short nY)
387 if (!m_pRLEData) {
388 return;
391 CGolombBuffer gb(m_pRLEData, m_nRLEDataSize);
392 short sTopFieldLength;
393 short sBottomFieldLength;
395 sTopFieldLength = gb.ReadShort();
396 sBottomFieldLength = gb.ReadShort();
398 DvbRenderField(spd, gb, nX, nY, sTopFieldLength);
399 DvbRenderField(spd, gb, nX, nY + 1, sBottomFieldLength);
403 void CompositionObject::DvbRenderField(SubPicDesc& spd, CGolombBuffer& gb, short nXStart, short nYStart, short nLength)
405 //FillSolidRect(spd, nXStart, nYStart, m_width, m_height, 0xFFFF0000); // Red opaque
406 //FillSolidRect(spd, nXStart, nYStart, m_width, m_height, 0xCC00FF00); // Green 80%
407 //FillSolidRect(spd, nXStart, nYStart, m_width, m_height, 0x100000FF); // Blue 60%
408 //return;
409 short nX = nXStart;
410 short nY = nYStart;
411 int nEnd = gb.GetPos() + nLength;
412 while (gb.GetPos() < nEnd) {
413 BYTE bType = gb.ReadByte();
414 switch (bType) {
415 case 0x10:
416 Dvb2PixelsCodeString(spd, gb, nX, nY);
417 break;
418 case 0x11:
419 Dvb4PixelsCodeString(spd, gb, nX, nY);
420 break;
421 case 0x12:
422 Dvb8PixelsCodeString(spd, gb, nX, nY);
423 break;
424 case 0x20:
425 gb.SkipBytes(2);
426 break;
427 case 0x21:
428 gb.SkipBytes(4);
429 break;
430 case 0x22:
431 gb.SkipBytes(16);
432 break;
433 case 0xF0:
434 nX = nXStart;
435 nY += 2;
436 break;
437 default:
438 ASSERT(FALSE);
439 break;
445 void CompositionObject::Dvb2PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, short& nX, short& nY)
447 BYTE bTemp;
448 BYTE nPaletteIndex = 0;
449 short nCount;
450 bool bQuit = false;
452 while (!bQuit && !gb.IsEOF()) {
453 nCount = 0;
454 nPaletteIndex = 0;
455 bTemp = (BYTE)gb.BitRead(2);
456 if (bTemp != 0) {
457 nPaletteIndex = bTemp;
458 nCount = 1;
459 } else {
460 if (gb.BitRead(1) == 1) { // switch_1
461 nCount = 3 + (short)gb.BitRead(3); // run_length_3-9
462 nPaletteIndex = (BYTE)gb.BitRead(2);
463 } else {
464 if (gb.BitRead(1) == 0) { // switch_2
465 switch (gb.BitRead(2)) { // switch_3
466 case 0:
467 bQuit = true;
468 break;
469 case 1:
470 nCount = 2;
471 break;
472 case 2: // if (switch_3 == '10')
473 nCount = 12 + (short)gb.BitRead(4); // run_length_12-27
474 nPaletteIndex = (BYTE)gb.BitRead(2); // 4-bit_pixel-code
475 break;
476 case 3:
477 nCount = 29 + gb.ReadByte(); // run_length_29-284
478 nPaletteIndex = (BYTE)gb.BitRead(2); // 4-bit_pixel-code
479 break;
481 } else {
482 nCount = 1;
487 if (nX + nCount > m_width) {
488 ASSERT(FALSE);
489 break;
492 if (nCount > 0) {
493 FillSolidRect(spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]);
494 nX += nCount;
498 gb.BitByteAlign();
501 void CompositionObject::Dvb4PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, short& nX, short& nY)
503 BYTE bTemp;
504 BYTE nPaletteIndex = 0;
505 short nCount;
506 bool bQuit = false;
508 while (!bQuit && !gb.IsEOF()) {
509 nCount = 0;
510 nPaletteIndex = 0;
511 bTemp = (BYTE)gb.BitRead(4);
512 if (bTemp != 0) {
513 nPaletteIndex = bTemp;
514 nCount = 1;
515 } else {
516 if (gb.BitRead(1) == 0) { // switch_1
517 nCount = (short)gb.BitRead(3); // run_length_3-9
518 if (nCount != 0) {
519 nCount += 2;
520 } else {
521 bQuit = true;
523 } else {
524 if (gb.BitRead(1) == 0) { // switch_2
525 nCount = 4 + (short)gb.BitRead(2); // run_length_4-7
526 nPaletteIndex = (BYTE)gb.BitRead(4); // 4-bit_pixel-code
527 } else {
528 switch (gb.BitRead(2)) { // switch_3
529 case 0:
530 nCount = 1;
531 break;
532 case 1:
533 nCount = 2;
534 break;
535 case 2: // if (switch_3 == '10')
536 nCount = 9 + (short)gb.BitRead(4); // run_length_9-24
537 nPaletteIndex = (BYTE)gb.BitRead(4); // 4-bit_pixel-code
538 break;
539 case 3:
540 nCount = 25 + gb.ReadByte(); // run_length_25-280
541 nPaletteIndex = (BYTE)gb.BitRead(4); // 4-bit_pixel-code
542 break;
548 #if 0
549 if (nX + nCount > m_width) {
550 ASSERT(FALSE);
551 break;
553 #endif
555 if (nCount > 0) {
556 FillSolidRect(spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]);
557 nX += nCount;
561 gb.BitByteAlign();
564 void CompositionObject::Dvb8PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, short& nX, short& nY)
566 BYTE bTemp;
567 BYTE nPaletteIndex = 0;
568 short nCount;
569 bool bQuit = false;
571 while (!bQuit && !gb.IsEOF()) {
572 nCount = 0;
573 nPaletteIndex = 0;
574 bTemp = gb.ReadByte();
575 if (bTemp != 0) {
576 nPaletteIndex = bTemp;
577 nCount = 1;
578 } else {
579 if (gb.BitRead(1) == 0) { // switch_1
580 nCount = (short)gb.BitRead(7); // run_length_1-127
581 if (nCount == 0) {
582 bQuit = true;
584 } else {
585 nCount = (short)gb.BitRead(7); // run_length_3-127
586 nPaletteIndex = gb.ReadByte();
590 if (nX + nCount > m_width) {
591 ASSERT(FALSE);
592 break;
595 if (nCount > 0) {
596 FillSolidRect(spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]);
597 nX += nCount;
601 gb.BitByteAlign();