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/>.
22 #include "CompositionObject.h"
23 #include "../DSUtil/GolombBuffer.h"
24 #include "../subpic/color_conv_table.h"
27 CompositionObject::CompositionObject()
33 memsetd(m_Colors
, 0xFF000000, sizeof(m_Colors
));
36 CompositionObject::~CompositionObject()
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
;
48 m_Palette
.SetCount(nNbEntry
>0?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
)
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
;
77 XY_LOG_ERROR("Not supported");
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
;
91 XY_LOG_ERROR("Not supported");
96 m_colorType
= spd
.type
;
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
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
);
171 XY_LOG_ERROR("Not supported");
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
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
);
249 XY_LOG_ERROR("Not supported");
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
;
297 XY_LOG_ERROR("Not supported");
303 XY_LOG_ERROR("Not supported");
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
;
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
);
330 void CompositionObject::RenderHdmv(SubPicDesc
& spd
)
332 if (!m_pRLEData
|| !HavePalette()) {
336 CGolombBuffer
GBuffer(m_pRLEData
, m_nRLEDataSize
);
339 BYTE nPaletteIndex
= 0;
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();
347 nPaletteIndex
= bTemp
;
350 bSwitch
= GBuffer
.ReadByte();
351 if (!(bSwitch
& 0x80)) {
352 if (!(bSwitch
& 0x40)) {
353 nCount
= bSwitch
& 0x3F;
358 nCount
= (bSwitch
& 0x3F) << 8 | (short)GBuffer
.ReadByte();
362 if (!(bSwitch
& 0x40)) {
363 nCount
= bSwitch
& 0x3F;
364 nPaletteIndex
= GBuffer
.ReadByte();
366 nCount
= (bSwitch
& 0x3F) << 8 | (short)GBuffer
.ReadByte();
367 nPaletteIndex
= GBuffer
.ReadByte();
373 if (nPaletteIndex
!= 0xFF) { // Fully transparent (§9.14.4.2.2.1.1)
374 FillSolidRect(spd
, nX
, nY
, nCount
, 1, m_Colors
[nPaletteIndex
]);
379 nX
= m_horizontal_position
;
385 void CompositionObject::RenderDvb(SubPicDesc
& spd
, short nX
, short nY
)
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%
411 int nEnd
= gb
.GetPos() + nLength
;
412 while (gb
.GetPos() < nEnd
) {
413 BYTE bType
= gb
.ReadByte();
416 Dvb2PixelsCodeString(spd
, gb
, nX
, nY
);
419 Dvb4PixelsCodeString(spd
, gb
, nX
, nY
);
422 Dvb8PixelsCodeString(spd
, gb
, nX
, nY
);
445 void CompositionObject::Dvb2PixelsCodeString(SubPicDesc
& spd
, CGolombBuffer
& gb
, short& nX
, short& nY
)
448 BYTE nPaletteIndex
= 0;
452 while (!bQuit
&& !gb
.IsEOF()) {
455 bTemp
= (BYTE
)gb
.BitRead(2);
457 nPaletteIndex
= bTemp
;
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);
464 if (gb
.BitRead(1) == 0) { // switch_2
465 switch (gb
.BitRead(2)) { // switch_3
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
477 nCount
= 29 + gb
.ReadByte(); // run_length_29-284
478 nPaletteIndex
= (BYTE
)gb
.BitRead(2); // 4-bit_pixel-code
487 if (nX
+ nCount
> m_width
) {
493 FillSolidRect(spd
, nX
, nY
, nCount
, 1, m_Colors
[nPaletteIndex
]);
501 void CompositionObject::Dvb4PixelsCodeString(SubPicDesc
& spd
, CGolombBuffer
& gb
, short& nX
, short& nY
)
504 BYTE nPaletteIndex
= 0;
508 while (!bQuit
&& !gb
.IsEOF()) {
511 bTemp
= (BYTE
)gb
.BitRead(4);
513 nPaletteIndex
= bTemp
;
516 if (gb
.BitRead(1) == 0) { // switch_1
517 nCount
= (short)gb
.BitRead(3); // run_length_3-9
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
528 switch (gb
.BitRead(2)) { // switch_3
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
540 nCount
= 25 + gb
.ReadByte(); // run_length_25-280
541 nPaletteIndex
= (BYTE
)gb
.BitRead(4); // 4-bit_pixel-code
549 if (nX
+ nCount
> m_width
) {
556 FillSolidRect(spd
, nX
, nY
, nCount
, 1, m_Colors
[nPaletteIndex
]);
564 void CompositionObject::Dvb8PixelsCodeString(SubPicDesc
& spd
, CGolombBuffer
& gb
, short& nX
, short& nY
)
567 BYTE nPaletteIndex
= 0;
571 while (!bQuit
&& !gb
.IsEOF()) {
574 bTemp
= gb
.ReadByte();
576 nPaletteIndex
= bTemp
;
579 if (gb
.BitRead(1) == 0) { // switch_1
580 nCount
= (short)gb
.BitRead(7); // run_length_1-127
585 nCount
= (short)gb
.BitRead(7); // run_length_3-127
586 nPaletteIndex
= gb
.ReadByte();
590 if (nX
+ nCount
> m_width
) {
596 FillSolidRect(spd
, nX
, nY
, nCount
, 1, m_Colors
[nPaletteIndex
]);