Merge with MPC-HC 6d1472b2f18266d92e5bc068667de348c0cd3b3b.
[xy_vsfilter.git] / src / subtitles / CompositionObject.cpp
bloba96f34b8dc9f187fa8c00f48736d962b4d0dc72b
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, bool bIsHD)
43 m_OriginalColorType = bIsHD ? YUV_Rec709 : YUV_Rec601;
45 m_colorType = -1;
47 m_Palette.SetCount(nNbEntry>0?nNbEntry:0);
48 if(nNbEntry>0)
50 memcpy(m_Palette.GetData(), pPalette, nNbEntry*sizeof(pPalette[0]));
54 void CompositionObject::InitColor(const SubPicDesc& spd)
56 #define COMBINE_AYUV(a, y, u, v) ((((((((int)(a))<<8)|y)<<8)|u)<<8)|v)
57 //fix me: move all color conv function into color_conv_table or dsutil
59 int paletteNumber = m_Palette.GetCount();
60 if (m_colorType!=spd.type)
62 m_colorType = -1;
63 if(m_OriginalColorType!=NONE)
65 m_colorType = spd.type;
66 switch(spd.type)
68 case MSP_AYUV_PLANAR:
69 case MSP_AYUV:
70 if ((m_OriginalColorType==YUV_Rec709 && ColorConvTable::GetDefaultYUVType()==ColorConvTable::BT709) ||
71 (m_OriginalColorType==YUV_Rec601 && ColorConvTable::GetDefaultYUVType()==ColorConvTable::BT601))
73 for (int i=0;i<paletteNumber;i++)
75 m_Colors[m_Palette[i].entry_id] = COMBINE_AYUV(m_Palette[i].T, m_Palette[i].Y, m_Palette[i].Cr, m_Palette[i].Cb);
78 else if (m_OriginalColorType==YUV_Rec709)
80 for (int i=0;i<paletteNumber;i++)
82 DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT709(m_Palette[i].T, m_Palette[i].Y, m_Palette[i].Cr, m_Palette[i].Cb);
83 m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Ayuv(argb);
86 else if (m_OriginalColorType==YUV_Rec601)
88 for (int i=0;i<paletteNumber;i++)
90 DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT601(m_Palette[i].T, m_Palette[i].Y, m_Palette[i].Cr, m_Palette[i].Cb);
91 m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Ayuv(argb);
94 else
96 m_colorType = -1;
98 break;
99 case MSP_XY_AUYV:
100 if ((m_OriginalColorType==YUV_Rec709 && ColorConvTable::GetDefaultYUVType()==ColorConvTable::BT709) ||
101 (m_OriginalColorType==YUV_Rec601 && ColorConvTable::GetDefaultYUVType()==ColorConvTable::BT601))
103 for (int i=0;i<paletteNumber;i++)
105 m_Colors[m_Palette[i].entry_id] = COMBINE_AYUV(m_Palette[i].T, m_Palette[i].Cr, m_Palette[i].Y, m_Palette[i].Cb);
108 else if (m_OriginalColorType==YUV_Rec709)
110 for (int i=0;i<paletteNumber;i++)
112 DWORD argb = YCrCbToRGB_Rec709(m_Palette[i].T, m_Palette[i].Y, m_Palette[i].Cr, m_Palette[i].Cb);
113 m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Auyv(argb);
116 else if (m_OriginalColorType==YUV_Rec601)
118 for (int i=0;i<paletteNumber;i++)
120 DWORD argb = YCrCbToRGB_Rec601(m_Palette[i].T, m_Palette[i].Y, m_Palette[i].Cr, m_Palette[i].Cb);
121 m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Auyv(argb);
124 else
126 m_colorType = -1;
128 break;
129 case MSP_RGBA:
130 if (m_OriginalColorType==YUV_Rec709)
132 for (int i=0;i<paletteNumber;i++)
134 DWORD argb = YCrCbToRGB_Rec709(m_Palette[i].T, m_Palette[i].Y, m_Palette[i].Cr, m_Palette[i].Cb);
135 m_Colors[m_Palette[i].entry_id] = argb;
138 else if (m_OriginalColorType==YUV_Rec601)
140 for (int i=0;i<paletteNumber;i++)
142 DWORD argb = YCrCbToRGB_Rec601(m_Palette[i].T, m_Palette[i].Y, m_Palette[i].Cr, m_Palette[i].Cb);
143 m_Colors[m_Palette[i].entry_id] = argb;
146 else
148 m_colorType = -1;
150 break;
151 default:
152 m_colorType = -1;
153 break;
156 if (m_colorType == -1)
158 //todo fixme: log error
163 void CompositionObject::SetRLEData(const BYTE* pBuffer, int nSize, int nTotalSize)
165 delete [] m_pRLEData;
166 m_pRLEData = DNew BYTE[nTotalSize];
167 m_nRLEDataSize = nTotalSize;
168 m_nRLEPos = nSize;
170 memcpy(m_pRLEData, pBuffer, nSize);
173 void CompositionObject::AppendRLEData(const BYTE* pBuffer, int nSize)
175 ASSERT(m_nRLEPos + nSize <= m_nRLEDataSize);
176 if (m_nRLEPos + nSize <= m_nRLEDataSize) {
177 memcpy(m_pRLEData + m_nRLEPos, pBuffer, nSize);
178 m_nRLEPos += nSize;
183 void CompositionObject::RenderHdmv(SubPicDesc& spd)
185 if (!m_pRLEData || !HavePalette()) {
186 return;
189 CGolombBuffer GBuffer(m_pRLEData, m_nRLEDataSize);
190 BYTE bTemp;
191 BYTE bSwitch;
192 BYTE nPaletteIndex = 0;
193 short nCount;
194 short nX = m_horizontal_position;
195 short nY = m_vertical_position;
197 while ((nY < (m_vertical_position + m_height)) && !GBuffer.IsEOF()) {
198 bTemp = GBuffer.ReadByte();
199 if (bTemp != 0) {
200 nPaletteIndex = bTemp;
201 nCount = 1;
202 } else {
203 bSwitch = GBuffer.ReadByte();
204 if (!(bSwitch & 0x80)) {
205 if (!(bSwitch & 0x40)) {
206 nCount = bSwitch & 0x3F;
207 if (nCount > 0) {
208 nPaletteIndex = 0;
210 } else {
211 nCount = (bSwitch & 0x3F) << 8 | (short)GBuffer.ReadByte();
212 nPaletteIndex = 0;
214 } else {
215 if (!(bSwitch & 0x40)) {
216 nCount = bSwitch & 0x3F;
217 nPaletteIndex = GBuffer.ReadByte();
218 } else {
219 nCount = (bSwitch & 0x3F) << 8 | (short)GBuffer.ReadByte();
220 nPaletteIndex = GBuffer.ReadByte();
225 if (nCount > 0) {
226 if (nPaletteIndex != 0xFF) { // Fully transparent (§9.14.4.2.2.1.1)
227 FillSolidRect(spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]);
229 nX += nCount;
230 } else {
231 nY++;
232 nX = m_horizontal_position;
238 void CompositionObject::RenderDvb(SubPicDesc& spd, short nX, short nY)
240 if (!m_pRLEData) {
241 return;
244 CGolombBuffer gb(m_pRLEData, m_nRLEDataSize);
245 short sTopFieldLength;
246 short sBottomFieldLength;
248 sTopFieldLength = gb.ReadShort();
249 sBottomFieldLength = gb.ReadShort();
251 DvbRenderField(spd, gb, nX, nY, sTopFieldLength);
252 DvbRenderField(spd, gb, nX, nY + 1, sBottomFieldLength);
256 void CompositionObject::DvbRenderField(SubPicDesc& spd, CGolombBuffer& gb, short nXStart, short nYStart, short nLength)
258 //FillSolidRect(spd, nXStart, nYStart, m_width, m_height, 0xFFFF0000); // Red opaque
259 //FillSolidRect(spd, nXStart, nYStart, m_width, m_height, 0xCC00FF00); // Green 80%
260 //FillSolidRect(spd, nXStart, nYStart, m_width, m_height, 0x100000FF); // Blue 60%
261 //return;
262 short nX = nXStart;
263 short nY = nYStart;
264 int nEnd = gb.GetPos() + nLength;
265 while (gb.GetPos() < nEnd) {
266 BYTE bType = gb.ReadByte();
267 switch (bType) {
268 case 0x10:
269 Dvb2PixelsCodeString(spd, gb, nX, nY);
270 break;
271 case 0x11:
272 Dvb4PixelsCodeString(spd, gb, nX, nY);
273 break;
274 case 0x12:
275 Dvb8PixelsCodeString(spd, gb, nX, nY);
276 break;
277 case 0x20:
278 gb.SkipBytes(2);
279 break;
280 case 0x21:
281 gb.SkipBytes(4);
282 break;
283 case 0x22:
284 gb.SkipBytes(16);
285 break;
286 case 0xF0:
287 nX = nXStart;
288 nY += 2;
289 break;
290 default:
291 ASSERT(FALSE);
292 break;
298 void CompositionObject::Dvb2PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, short& nX, short& nY)
300 BYTE bTemp;
301 BYTE nPaletteIndex = 0;
302 short nCount;
303 bool bQuit = false;
305 while (!bQuit && !gb.IsEOF()) {
306 nCount = 0;
307 nPaletteIndex = 0;
308 bTemp = (BYTE)gb.BitRead(2);
309 if (bTemp != 0) {
310 nPaletteIndex = bTemp;
311 nCount = 1;
312 } else {
313 if (gb.BitRead(1) == 1) { // switch_1
314 nCount = 3 + (short)gb.BitRead(3); // run_length_3-9
315 nPaletteIndex = (BYTE)gb.BitRead(2);
316 } else {
317 if (gb.BitRead(1) == 0) { // switch_2
318 switch (gb.BitRead(2)) { // switch_3
319 case 0:
320 bQuit = true;
321 break;
322 case 1:
323 nCount = 2;
324 break;
325 case 2: // if (switch_3 == '10')
326 nCount = 12 + (short)gb.BitRead(4); // run_length_12-27
327 nPaletteIndex = (BYTE)gb.BitRead(2); // 4-bit_pixel-code
328 break;
329 case 3:
330 nCount = 29 + gb.ReadByte(); // run_length_29-284
331 nPaletteIndex = (BYTE)gb.BitRead(2); // 4-bit_pixel-code
332 break;
334 } else {
335 nCount = 1;
340 if (nX + nCount > m_width) {
341 ASSERT(FALSE);
342 break;
345 if (nCount > 0) {
346 FillSolidRect(spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]);
347 nX += nCount;
351 gb.BitByteAlign();
354 void CompositionObject::Dvb4PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, short& nX, short& nY)
356 BYTE bTemp;
357 BYTE nPaletteIndex = 0;
358 short nCount;
359 bool bQuit = false;
361 while (!bQuit && !gb.IsEOF()) {
362 nCount = 0;
363 nPaletteIndex = 0;
364 bTemp = (BYTE)gb.BitRead(4);
365 if (bTemp != 0) {
366 nPaletteIndex = bTemp;
367 nCount = 1;
368 } else {
369 if (gb.BitRead(1) == 0) { // switch_1
370 nCount = (short)gb.BitRead(3); // run_length_3-9
371 if (nCount != 0) {
372 nCount += 2;
373 } else {
374 bQuit = true;
376 } else {
377 if (gb.BitRead(1) == 0) { // switch_2
378 nCount = 4 + (short)gb.BitRead(2); // run_length_4-7
379 nPaletteIndex = (BYTE)gb.BitRead(4); // 4-bit_pixel-code
380 } else {
381 switch (gb.BitRead(2)) { // switch_3
382 case 0:
383 nCount = 1;
384 break;
385 case 1:
386 nCount = 2;
387 break;
388 case 2: // if (switch_3 == '10')
389 nCount = 9 + (short)gb.BitRead(4); // run_length_9-24
390 nPaletteIndex = (BYTE)gb.BitRead(4); // 4-bit_pixel-code
391 break;
392 case 3:
393 nCount = 25 + gb.ReadByte(); // run_length_25-280
394 nPaletteIndex = (BYTE)gb.BitRead(4); // 4-bit_pixel-code
395 break;
401 #if 0
402 if (nX + nCount > m_width) {
403 ASSERT(FALSE);
404 break;
406 #endif
408 if (nCount > 0) {
409 FillSolidRect(spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]);
410 nX += nCount;
414 gb.BitByteAlign();
417 void CompositionObject::Dvb8PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, short& nX, short& nY)
419 BYTE bTemp;
420 BYTE nPaletteIndex = 0;
421 short nCount;
422 bool bQuit = false;
424 while (!bQuit && !gb.IsEOF()) {
425 nCount = 0;
426 nPaletteIndex = 0;
427 bTemp = gb.ReadByte();
428 if (bTemp != 0) {
429 nPaletteIndex = bTemp;
430 nCount = 1;
431 } else {
432 if (gb.BitRead(1) == 0) { // switch_1
433 nCount = (short)gb.BitRead(7); // run_length_1-127
434 if (nCount == 0) {
435 bQuit = true;
437 } else {
438 nCount = (short)gb.BitRead(7); // run_length_3-127
439 nPaletteIndex = gb.ReadByte();
443 if (nX + nCount > m_width) {
444 ASSERT(FALSE);
445 break;
448 if (nCount > 0) {
449 FillSolidRect(spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]);
450 nX += nCount;
454 gb.BitByteAlign();