From d2d4b72d40b69d1c4bcbafd9995e9119a31816a8 Mon Sep 17 00:00:00 2001 From: "yuzhuohuang@qq.com" Date: Wed, 3 Oct 2012 13:02:09 +0800 Subject: [PATCH] Merge MPC-HC code(01b8dbf34d6a486fa1cd02d7a123249fec1e4160) [PART 2] (HdmvSub) --- src/subtitles/CompositionObject.cpp | 549 ++++++++++++------------ src/subtitles/CompositionObject.h | 200 +++++---- src/subtitles/HdmvSub.cpp | 829 +++++++++++++++++++----------------- src/subtitles/HdmvSub.h | 272 ++++++------ 4 files changed, 948 insertions(+), 902 deletions(-) rewrite src/subtitles/CompositionObject.h (71%) rewrite src/subtitles/HdmvSub.cpp (84%) rewrite src/subtitles/HdmvSub.h (80%) diff --git a/src/subtitles/CompositionObject.cpp b/src/subtitles/CompositionObject.cpp index b10778c..40e7193 100644 --- a/src/subtitles/CompositionObject.cpp +++ b/src/subtitles/CompositionObject.cpp @@ -1,16 +1,14 @@ /* - * $Id: CompositionObject.cpp 3056 2011-04-29 21:07:44Z nevcairiel $ + * (C) 2006-2012 see Authors.txt * - * (C) 2006-2010 see AUTHORS + * This file is part of MPC-HC. * - * This file is part of mplayerc. - * - * Mplayerc is free software; you can redistribute it and/or modify + * MPC-HC is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * - * Mplayerc is distributed in the hope that it will be useful, + * MPC-HC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. @@ -28,22 +26,20 @@ CompositionObject::CompositionObject() { - m_rtStart = 0; - m_rtStop = 0; - m_pRLEData = NULL; - m_nRLEDataSize = 0; - m_nRLEPos = 0; + m_pRLEData = NULL; + m_nRLEDataSize = 0; + m_nRLEPos = 0; - memsetd (m_Colors, 0xFF000000, sizeof(m_Colors)); + memsetd(m_Colors, 0xFF000000, sizeof(m_Colors)); } CompositionObject::~CompositionObject() { - delete[] m_pRLEData; + delete [] m_pRLEData; } -void CompositionObject::SetPalette (int nNbEntry, HDMV_PALETTE* pPalette, bool bIsHD) -{ +void CompositionObject::SetPalette(int nNbEntry, HDMV_PALETTE* pPalette, bool bIsHD) +{ m_OriginalColorType = bIsHD ? YUV_Rec709 : YUV_Rec601; m_colorType = -1; @@ -85,7 +81,7 @@ void CompositionObject::InitColor(const SubPicDesc& spd) { DWORD argb = ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT709(m_Palette[i].T, m_Palette[i].Y, m_Palette[i].Cr, m_Palette[i].Cb); m_Colors[m_Palette[i].entry_id] = ColorConvTable::Argb2Ayuv(argb); - } + } } else if (m_OriginalColorType==YUV_Rec601) { @@ -164,295 +160,296 @@ void CompositionObject::InitColor(const SubPicDesc& spd) } } -void CompositionObject::SetRLEData(BYTE* pBuffer, int nSize, int nTotalSize) +void CompositionObject::SetRLEData(const BYTE* pBuffer, int nSize, int nTotalSize) { - delete[] m_pRLEData; - m_pRLEData = DNew BYTE[nTotalSize]; - m_nRLEDataSize = nTotalSize; - m_nRLEPos = nSize; + delete [] m_pRLEData; + m_pRLEData = DNew BYTE[nTotalSize]; + m_nRLEDataSize = nTotalSize; + m_nRLEPos = nSize; - memcpy (m_pRLEData, pBuffer, nSize); + memcpy(m_pRLEData, pBuffer, nSize); } -void CompositionObject::AppendRLEData(BYTE* pBuffer, int nSize) +void CompositionObject::AppendRLEData(const BYTE* pBuffer, int nSize) { - ASSERT (m_nRLEPos+nSize <= m_nRLEDataSize); - if (m_nRLEPos+nSize <= m_nRLEDataSize) { - memcpy (m_pRLEData+m_nRLEPos, pBuffer, nSize); - m_nRLEPos += nSize; - } + ASSERT(m_nRLEPos + nSize <= m_nRLEDataSize); + if (m_nRLEPos + nSize <= m_nRLEDataSize) { + memcpy(m_pRLEData + m_nRLEPos, pBuffer, nSize); + m_nRLEPos += nSize; + } } void CompositionObject::RenderHdmv(SubPicDesc& spd) { - if (!m_pRLEData) { - return; - } - - CGolombBuffer GBuffer (m_pRLEData, m_nRLEDataSize); - BYTE bTemp; - BYTE bSwitch; - - BYTE nPaletteIndex = 0; - SHORT nCount; - SHORT nX = m_horizontal_position; - SHORT nY = m_vertical_position; - - while ((nY < (m_vertical_position + m_height)) && !GBuffer.IsEOF()) { - bTemp = GBuffer.ReadByte(); - if (bTemp != 0) { - nPaletteIndex = bTemp; - nCount = 1; - } else { - bSwitch = GBuffer.ReadByte(); - if (!(bSwitch & 0x80)) { - if (!(bSwitch & 0x40)) { - nCount = bSwitch & 0x3F; - if (nCount > 0) { - nPaletteIndex = 0; - } - } else { - nCount = (bSwitch&0x3F) <<8 | (SHORT)GBuffer.ReadByte(); - nPaletteIndex = 0; - } - } else { - if (!(bSwitch & 0x40)) { - nCount = bSwitch & 0x3F; - nPaletteIndex = GBuffer.ReadByte(); - } else { - nCount = (bSwitch&0x3F) <<8 | (SHORT)GBuffer.ReadByte(); - nPaletteIndex = GBuffer.ReadByte(); - } - } - } - - if (nCount>0) { - if (nPaletteIndex != 0xFF) { // Fully transparent (�9.14.4.2.2.1.1) - FillSolidRect (spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]); - } - nX += nCount; - } else { - nY++; - nX = m_horizontal_position; - } - } + if (!m_pRLEData) { + return; + } + + CGolombBuffer GBuffer(m_pRLEData, m_nRLEDataSize); + BYTE bTemp; + BYTE bSwitch; + BYTE nPaletteIndex = 0; + short nCount; + short nX = m_horizontal_position; + short nY = m_vertical_position; + + while ((nY < (m_vertical_position + m_height)) && !GBuffer.IsEOF()) { + bTemp = GBuffer.ReadByte(); + if (bTemp != 0) { + nPaletteIndex = bTemp; + nCount = 1; + } else { + bSwitch = GBuffer.ReadByte(); + if (!(bSwitch & 0x80)) { + if (!(bSwitch & 0x40)) { + nCount = bSwitch & 0x3F; + if (nCount > 0) { + nPaletteIndex = 0; + } + } else { + nCount = (bSwitch & 0x3F) << 8 | (short)GBuffer.ReadByte(); + nPaletteIndex = 0; + } + } else { + if (!(bSwitch & 0x40)) { + nCount = bSwitch & 0x3F; + nPaletteIndex = GBuffer.ReadByte(); + } else { + nCount = (bSwitch & 0x3F) << 8 | (short)GBuffer.ReadByte(); + nPaletteIndex = GBuffer.ReadByte(); + } + } + } + + if (nCount > 0) { + if (nPaletteIndex != 0xFF) { // Fully transparent (§9.14.4.2.2.1.1) + FillSolidRect(spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]); + } + nX += nCount; + } else { + nY++; + nX = m_horizontal_position; + } + } } -void CompositionObject::RenderDvb(SubPicDesc& spd, SHORT nX, SHORT nY) +void CompositionObject::RenderDvb(SubPicDesc& spd, short nX, short nY) { - if (!m_pRLEData) { - return; - } + if (!m_pRLEData) { + return; + } - CGolombBuffer gb (m_pRLEData, m_nRLEDataSize); - SHORT sTopFieldLength; - SHORT sBottomFieldLength; + CGolombBuffer gb(m_pRLEData, m_nRLEDataSize); + short sTopFieldLength; + short sBottomFieldLength; - sTopFieldLength = gb.ReadShort(); - sBottomFieldLength = gb.ReadShort(); + sTopFieldLength = gb.ReadShort(); + sBottomFieldLength = gb.ReadShort(); - DvbRenderField (spd, gb, nX, nY, sTopFieldLength); - DvbRenderField (spd, gb, nX, nY+1, sBottomFieldLength); + DvbRenderField(spd, gb, nX, nY, sTopFieldLength); + DvbRenderField(spd, gb, nX, nY + 1, sBottomFieldLength); } -void CompositionObject::DvbRenderField(SubPicDesc& spd, CGolombBuffer& gb, SHORT nXStart, SHORT nYStart, SHORT nLength) +void CompositionObject::DvbRenderField(SubPicDesc& spd, CGolombBuffer& gb, short nXStart, short nYStart, short nLength) { - //FillSolidRect (spd, 0, 0, 300, 10, 0xFFFF0000); // Red opaque - //FillSolidRect (spd, 0, 10, 300, 10, 0xCC00FF00); // Green 80% - //FillSolidRect (spd, 0, 20, 300, 10, 0x100000FF); // Blue 60% - //return; - SHORT nX = nXStart; - SHORT nY = nYStart; - INT64 nEnd = gb.GetPos()+nLength; - while (gb.GetPos() < nEnd) { - BYTE bType = gb.ReadByte(); - switch (bType) { - case 0x10 : - Dvb2PixelsCodeString(spd, gb, nX, nY); - break; - case 0x11 : - Dvb4PixelsCodeString(spd, gb, nX, nY); - break; - case 0x12 : - Dvb8PixelsCodeString(spd, gb, nX, nY); - break; - case 0x20 : - gb.SkipBytes (2); - break; - case 0x21 : - gb.SkipBytes (4); - break; - case 0x22 : - gb.SkipBytes (16); - break; - case 0xF0 : - nX = nXStart; - nY += 2; - break; - default : - ASSERT(FALSE); - break; - } - } + //FillSolidRect(spd, nXStart, nYStart, m_width, m_height, 0xFFFF0000); // Red opaque + //FillSolidRect(spd, nXStart, nYStart, m_width, m_height, 0xCC00FF00); // Green 80% + //FillSolidRect(spd, nXStart, nYStart, m_width, m_height, 0x100000FF); // Blue 60% + //return; + short nX = nXStart; + short nY = nYStart; + int nEnd = gb.GetPos() + nLength; + while (gb.GetPos() < nEnd) { + BYTE bType = gb.ReadByte(); + switch (bType) { + case 0x10: + Dvb2PixelsCodeString(spd, gb, nX, nY); + break; + case 0x11: + Dvb4PixelsCodeString(spd, gb, nX, nY); + break; + case 0x12: + Dvb8PixelsCodeString(spd, gb, nX, nY); + break; + case 0x20: + gb.SkipBytes(2); + break; + case 0x21: + gb.SkipBytes(4); + break; + case 0x22: + gb.SkipBytes(16); + break; + case 0xF0: + nX = nXStart; + nY += 2; + break; + default: + ASSERT(FALSE); + break; + } + } } -void CompositionObject::Dvb2PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, SHORT& nX, SHORT& nY) +void CompositionObject::Dvb2PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, short& nX, short& nY) { - BYTE bTemp; - BYTE nPaletteIndex = 0; - SHORT nCount; - bool bQuit = false; - - while (!bQuit && !gb.IsEOF()) { - nCount = 0; - nPaletteIndex = 0; - bTemp = (BYTE)gb.BitRead(2); - if (bTemp != 0) { - nPaletteIndex = bTemp; - nCount = 1; - } else { - if (gb.BitRead(1) == 1) { // switch_1 - nCount = 3 + (SHORT)gb.BitRead(3); // run_length_3-9 - nPaletteIndex = (BYTE)gb.BitRead(2); - } else { - if (gb.BitRead(1) == 0) { // switch_2 - switch (gb.BitRead(2)) { // switch_3 - case 0 : - bQuit = true; - break; - case 1 : - nCount = 2; - break; - case 2 : // if (switch_3 == '10') - nCount = 12 + (SHORT)gb.BitRead(4); // run_length_12-27 - nPaletteIndex = (BYTE)gb.BitRead(2); // 4-bit_pixel-code - break; - case 3 : - nCount = 29 + gb.ReadByte(); // run_length_29-284 - nPaletteIndex = (BYTE)gb.BitRead(2); // 4-bit_pixel-code - break; - } - } else { - nCount = 1; - } - } - } - - if (nX+nCount > m_width) { - ASSERT (FALSE); - break; - } - - if (nCount>0) { - FillSolidRect (spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]); - nX += nCount; - } - } - - gb.BitByteAlign(); + BYTE bTemp; + BYTE nPaletteIndex = 0; + short nCount; + bool bQuit = false; + + while (!bQuit && !gb.IsEOF()) { + nCount = 0; + nPaletteIndex = 0; + bTemp = (BYTE)gb.BitRead(2); + if (bTemp != 0) { + nPaletteIndex = bTemp; + nCount = 1; + } else { + if (gb.BitRead(1) == 1) { // switch_1 + nCount = 3 + (short)gb.BitRead(3); // run_length_3-9 + nPaletteIndex = (BYTE)gb.BitRead(2); + } else { + if (gb.BitRead(1) == 0) { // switch_2 + switch (gb.BitRead(2)) { // switch_3 + case 0: + bQuit = true; + break; + case 1: + nCount = 2; + break; + case 2: // if (switch_3 == '10') + nCount = 12 + (short)gb.BitRead(4); // run_length_12-27 + nPaletteIndex = (BYTE)gb.BitRead(2); // 4-bit_pixel-code + break; + case 3: + nCount = 29 + gb.ReadByte(); // run_length_29-284 + nPaletteIndex = (BYTE)gb.BitRead(2); // 4-bit_pixel-code + break; + } + } else { + nCount = 1; + } + } + } + + if (nX + nCount > m_width) { + ASSERT(FALSE); + break; + } + + if (nCount > 0) { + FillSolidRect(spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]); + nX += nCount; + } + } + + gb.BitByteAlign(); } -void CompositionObject::Dvb4PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, SHORT& nX, SHORT& nY) +void CompositionObject::Dvb4PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, short& nX, short& nY) { - BYTE bTemp; - BYTE nPaletteIndex = 0; - SHORT nCount; - bool bQuit = false; - - while (!bQuit && !gb.IsEOF()) { - nCount = 0; - nPaletteIndex = 0; - bTemp = (BYTE)gb.BitRead(4); - if (bTemp != 0) { - nPaletteIndex = bTemp; - nCount = 1; - } else { - if (gb.BitRead(1) == 0) { // switch_1 - nCount = (SHORT)gb.BitRead(3); // run_length_3-9 - if (nCount != 0) { - nCount += 2; - } else { - bQuit = true; - } - } else { - if (gb.BitRead(1) == 0) { // switch_2 - nCount = 4 + (SHORT)gb.BitRead(2); // run_length_4-7 - nPaletteIndex = (BYTE)gb.BitRead(4); // 4-bit_pixel-code - } else { - switch (gb.BitRead(2)) { // switch_3 - case 0 : - nCount = 1; - break; - case 1 : - nCount = 2; - break; - case 2 : // if (switch_3 == '10') - nCount = 9 + (SHORT)gb.BitRead(4); // run_length_9-24 - nPaletteIndex = (BYTE)gb.BitRead(4); // 4-bit_pixel-code - break; - case 3 : - nCount = 25 + gb.ReadByte(); // run_length_25-280 - nPaletteIndex = (BYTE)gb.BitRead(4); // 4-bit_pixel-code - break; - } - } - } - } - - if (nX+nCount > m_width) { - ASSERT (FALSE); - break; - } - - if (nCount>0) { - FillSolidRect (spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]); - nX += nCount; - } - } - - gb.BitByteAlign(); + BYTE bTemp; + BYTE nPaletteIndex = 0; + short nCount; + bool bQuit = false; + + while (!bQuit && !gb.IsEOF()) { + nCount = 0; + nPaletteIndex = 0; + bTemp = (BYTE)gb.BitRead(4); + if (bTemp != 0) { + nPaletteIndex = bTemp; + nCount = 1; + } else { + if (gb.BitRead(1) == 0) { // switch_1 + nCount = (short)gb.BitRead(3); // run_length_3-9 + if (nCount != 0) { + nCount += 2; + } else { + bQuit = true; + } + } else { + if (gb.BitRead(1) == 0) { // switch_2 + nCount = 4 + (short)gb.BitRead(2); // run_length_4-7 + nPaletteIndex = (BYTE)gb.BitRead(4); // 4-bit_pixel-code + } else { + switch (gb.BitRead(2)) { // switch_3 + case 0: + nCount = 1; + break; + case 1: + nCount = 2; + break; + case 2: // if (switch_3 == '10') + nCount = 9 + (short)gb.BitRead(4); // run_length_9-24 + nPaletteIndex = (BYTE)gb.BitRead(4); // 4-bit_pixel-code + break; + case 3: + nCount = 25 + gb.ReadByte(); // run_length_25-280 + nPaletteIndex = (BYTE)gb.BitRead(4); // 4-bit_pixel-code + break; + } + } + } + } + +#if 0 + if (nX + nCount > m_width) { + ASSERT(FALSE); + break; + } +#endif + + if (nCount > 0) { + FillSolidRect(spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]); + nX += nCount; + } + } + + gb.BitByteAlign(); } -void CompositionObject::Dvb8PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, SHORT& nX, SHORT& nY) +void CompositionObject::Dvb8PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, short& nX, short& nY) { - BYTE bTemp; - BYTE nPaletteIndex = 0; - SHORT nCount; - bool bQuit = false; - - while (!bQuit && !gb.IsEOF()) { - nCount = 0; - nPaletteIndex = 0; - bTemp = gb.ReadByte(); - if (bTemp != 0) { - nPaletteIndex = bTemp; - nCount = 1; - } else { - if (gb.BitRead(1) == 0) { // switch_1 - nCount = (SHORT)gb.BitRead(7); // run_length_1-127 - if (nCount == 0) { - bQuit = true; - } - } else { - nCount = (SHORT)gb.BitRead(7); // run_length_3-127 - nPaletteIndex = gb.ReadByte(); - } - } - - if (nX+nCount > m_width) { - ASSERT (FALSE); - break; - } - - if (nCount>0) { - FillSolidRect (spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]); - nX += nCount; - } - } - - gb.BitByteAlign(); + BYTE bTemp; + BYTE nPaletteIndex = 0; + short nCount; + bool bQuit = false; + + while (!bQuit && !gb.IsEOF()) { + nCount = 0; + nPaletteIndex = 0; + bTemp = gb.ReadByte(); + if (bTemp != 0) { + nPaletteIndex = bTemp; + nCount = 1; + } else { + if (gb.BitRead(1) == 0) { // switch_1 + nCount = (short)gb.BitRead(7); // run_length_1-127 + if (nCount == 0) { + bQuit = true; + } + } else { + nCount = (short)gb.BitRead(7); // run_length_3-127 + nPaletteIndex = gb.ReadByte(); + } + } + + if (nX + nCount > m_width) { + ASSERT(FALSE); + break; + } + + if (nCount > 0) { + FillSolidRect(spd, nX, nY, nCount, 1, m_Colors[nPaletteIndex]); + nX += nCount; + } + } + + gb.BitByteAlign(); } diff --git a/src/subtitles/CompositionObject.h b/src/subtitles/CompositionObject.h dissimilarity index 71% index c9a6438..b7549c7 100644 --- a/src/subtitles/CompositionObject.h +++ b/src/subtitles/CompositionObject.h @@ -1,105 +1,95 @@ -/* - * $Id: CompositionObject.h 3720 2011-09-12 00:30:00Z aleksoid $ - * - * (C) 2006-2010 see AUTHORS - * - * This file is part of mplayerc. - * - * Mplayerc is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Mplayerc is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - - -#pragma once - -#include "Rasterizer.h" - - -struct HDMV_PALETTE { - BYTE entry_id; - BYTE Y; - BYTE Cr; - BYTE Cb; - BYTE T; // HDMV rule : 0 transparent, 255 opaque (compatible DirectX) -}; - -class CGolombBuffer; - -class CompositionObject : Rasterizer -{ -public : - SHORT m_object_id_ref; - BYTE m_window_id_ref; - bool m_object_cropped_flag; - bool m_forced_on_flag; - BYTE m_version_number; - BYTE m_nObjectNumber; - - SHORT m_horizontal_position; - SHORT m_vertical_position; - SHORT m_width; - SHORT m_height; - - SHORT m_cropping_horizontal_position; - SHORT m_cropping_vertical_position; - SHORT m_cropping_width; - SHORT m_cropping_height; - - REFERENCE_TIME m_rtStart; - REFERENCE_TIME m_rtStop; - - CompositionObject(); - ~CompositionObject(); - - void SetRLEData(BYTE* pBuffer, int nSize, int nTotalSize); - void AppendRLEData(BYTE* pBuffer, int nSize); - int GetRLEDataSize() { - return m_nRLEDataSize; - }; - bool IsRLEComplete() { - return m_nRLEPos >= m_nRLEDataSize; - }; - void RenderHdmv(SubPicDesc& spd); - void RenderDvb(SubPicDesc& spd, SHORT nX, SHORT nY); - void WriteSeg (SubPicDesc& spd, SHORT nX, SHORT nY, SHORT nCount, SHORT nPaletteIndex); - void InitColor(const SubPicDesc& spd); - void SetPalette (int nNbEntry, HDMV_PALETTE* pPalette, bool bIsHD); - void SetPalette (int nNbEntry, DWORD* dwColors); - bool HavePalette() { - return !m_Palette.IsEmpty(); - }; - -private : - BYTE* m_pRLEData; - int m_nRLEDataSize; - int m_nRLEPos; - - CAtlArray m_Palette; - enum ColorType - { - NONE, - YUV_Rec601, - YUV_Rec709, - RGB - }; - ColorType m_OriginalColorType; - - DWORD m_Colors[256]; - int m_colorType; - - void DvbRenderField(SubPicDesc& spd, CGolombBuffer& gb, SHORT nXStart, SHORT nYStart, SHORT nLength); - void Dvb2PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, SHORT& nX, SHORT& nY); - void Dvb4PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, SHORT& nX, SHORT& nY); - void Dvb8PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, SHORT& nX, SHORT& nY); -}; +/* + * (C) 2006-2012 see Authors.txt + * + * This file is part of MPC-HC. + * + * MPC-HC is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * MPC-HC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include "Rasterizer.h" + + +struct HDMV_PALETTE { + BYTE entry_id; + BYTE Y; + BYTE Cr; + BYTE Cb; + BYTE T; // HDMV rule : 0 transparent, 255 opaque (compatible DirectX) +}; + +class CGolombBuffer; + +class CompositionObject : Rasterizer +{ +public: + short m_object_id_ref; + BYTE m_window_id_ref; + bool m_object_cropped_flag; + bool m_forced_on_flag; + BYTE m_version_number; + + short m_horizontal_position; + short m_vertical_position; + short m_width; + short m_height; + + short m_cropping_horizontal_position; + short m_cropping_vertical_position; + short m_cropping_width; + short m_cropping_height; + + CompositionObject(); + ~CompositionObject(); + + void SetRLEData(const BYTE* pBuffer, int nSize, int nTotalSize); + void AppendRLEData(const BYTE* pBuffer, int nSize); + const BYTE* GetRLEData() { return m_pRLEData; }; + int GetRLEDataSize() { return m_nRLEDataSize; }; + bool IsRLEComplete() { return m_nRLEPos >= m_nRLEDataSize; }; + void RenderHdmv(SubPicDesc& spd); + void RenderDvb(SubPicDesc& spd, short nX, short nY); + void WriteSeg(SubPicDesc& spd, short nX, short nY, short nCount, short nPaletteIndex); + void InitColor(const SubPicDesc& spd); + void SetPalette(int nNbEntry, HDMV_PALETTE* pPalette, bool bIsHD); + void SetPalette(int nNbEntry, DWORD* dwColors); + bool HavePalette() { + return !m_Palette.IsEmpty(); + }; + +private: + BYTE* m_pRLEData; + int m_nRLEDataSize; + int m_nRLEPos; + + CAtlArray m_Palette; + enum ColorType + { + NONE, + YUV_Rec601, + YUV_Rec709, + RGB + }; + ColorType m_OriginalColorType; + + DWORD m_Colors[256]; + int m_colorType; + + void DvbRenderField(SubPicDesc& spd, CGolombBuffer& gb, short nXStart, short nYStart, short nLength); + void Dvb2PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, short& nX, short& nY); + void Dvb4PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, short& nX, short& nY); + void Dvb8PixelsCodeString(SubPicDesc& spd, CGolombBuffer& gb, short& nX, short& nY); +}; diff --git a/src/subtitles/HdmvSub.cpp b/src/subtitles/HdmvSub.cpp dissimilarity index 84% index f323766..01ea727 100644 --- a/src/subtitles/HdmvSub.cpp +++ b/src/subtitles/HdmvSub.cpp @@ -1,400 +1,429 @@ -/* - * $Id: HdmvSub.cpp 3720 2011-09-12 00:30:00Z aleksoid $ - * - * (C) 2006-2010 see AUTHORS - * - * This file is part of mplayerc. - * - * Mplayerc is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Mplayerc is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#include "stdafx.h" -#include "HdmvSub.h" -#include "../DSUtil/GolombBuffer.h" - -#if (0) // Set to 1 to activate HDMV subtitles traces -#define TRACE_HDMVSUB(_x_) {CString tmp;tmp.Format _x_; XY_LOG_INFO( tmp.GetString() );} -#else - #define TRACE_HDMVSUB(_x_) -#endif - -CHdmvSub::CHdmvSub(void) - : CBaseSub(ST_HDMV) -{ - m_nColorNumber = 0; - - m_nCurSegment = NO_SEGMENT; - m_pSegBuffer = NULL; - m_nTotalSegBuffer = 0; - m_nSegBufferPos = 0; - m_nSegSize = 0; - m_pCurrentObject = NULL; - m_pDefaultPalette = NULL; - m_nDefaultPaletteNbEntry = 0; - - memset (&m_VideoDescriptor, 0, sizeof(VIDEO_DESCRIPTOR)); -} - -CHdmvSub::~CHdmvSub() -{ - Reset(); - - delete[] m_pSegBuffer; - delete[] m_pDefaultPalette; - delete m_pCurrentObject; -} - - -void CHdmvSub::AllocSegment(int nSize) -{ - if (nSize > m_nTotalSegBuffer) { - delete[] m_pSegBuffer; - m_pSegBuffer = DNew BYTE[nSize]; - m_nTotalSegBuffer = nSize; - } - m_nSegBufferPos = 0; - m_nSegSize = nSize; -} - -POSITION CHdmvSub::GetStartPosition(REFERENCE_TIME rt, double fps) -{ - CompositionObject* pObject; - TRACE_HDMVSUB( (_T("CHdmvSub:GetStartPosition rt=%lS\n"), ReftimeToCString(rt)) ); - // Cleanup old PG - while (m_pObjects.GetCount()>0) { - pObject = m_pObjects.GetHead(); - if (pObject->m_rtStop < rt) { - TRACE_HDMVSUB( (_T("CHdmvSub:HDMV remove object %d %lS => %lS (rt=%lS)\n"), pObject->GetRLEDataSize(), - ReftimeToCString (pObject->m_rtStart), ReftimeToCString(pObject->m_rtStop), ReftimeToCString(rt))); - m_pObjects.RemoveHead(); - delete pObject; - } else { - break; - } - } - // log first 2 objects - // { - // POSITION pos = m_pObjects.GetHeadPosition(); - // for (int i=0;i<2 && pos!=NULL; i++) - // { - // CompositionObject* pObject = m_pObjects.GetNext(pos); - // TRACE_HDMVSUB( (_T("CHdmvSub:HDMV cur %d object %d %lS => %lS\n"), i, pObject->GetRLEDataSize(), - // ReftimeToCString (pObject->m_rtStart), ReftimeToCString(pObject->m_rtStop))); - // } - // } - - POSITION pos = m_pObjects.GetHeadPosition(); - - while (pos) { - CompositionObject* pObject = m_pObjects.GetAt (pos); - - if (rt >= pObject->m_rtStart && rt < pObject->m_rtStop) { - break; - } - else if( rt < pObject->m_rtStart ) - { - pos = NULL; - break; - } - - m_pObjects.GetNext(pos); - } - return pos; -} - -HRESULT CHdmvSub::ParseSample(IMediaSample* pSample) -{ - CheckPointer (pSample, E_POINTER); - HRESULT hr; - REFERENCE_TIME rtStart = INVALID_TIME, rtStop = INVALID_TIME; - BYTE* pData = NULL; - int lSampleLen; - - hr = pSample->GetPointer(&pData); - if(FAILED(hr) || pData == NULL) { - return hr; - } - lSampleLen = pSample->GetActualDataLength(); - - pSample->GetTime(&rtStart, &rtStop); - if (pData) { - CGolombBuffer SampleBuffer (pData, lSampleLen); - - while (!SampleBuffer.IsEOF()) { - if (m_nCurSegment == NO_SEGMENT) { - HDMV_SEGMENT_TYPE nSegType = (HDMV_SEGMENT_TYPE)SampleBuffer.ReadByte(); - USHORT nUnitSize = SampleBuffer.ReadShort(); - lSampleLen -=3; - - switch (nSegType) { - case PALETTE : - case OBJECT : - case PRESENTATION_SEG : - case END_OF_DISPLAY : - m_nCurSegment = nSegType; - AllocSegment (nUnitSize); - break; - - case WINDOW_DEF : - case INTERACTIVE_SEG : - case HDMV_SUB1 : - case HDMV_SUB2 : - // Ignored stuff... - SampleBuffer.SkipBytes(nUnitSize); - break; - default : - return VFW_E_SAMPLE_REJECTED; - } - } - - if (m_nCurSegment != NO_SEGMENT) { - if (m_nSegBufferPos < m_nSegSize) { - int nSize = min (m_nSegSize-m_nSegBufferPos, lSampleLen); - SampleBuffer.ReadBuffer (m_pSegBuffer+m_nSegBufferPos, nSize); - m_nSegBufferPos += nSize; - } - - if (m_nSegBufferPos >= m_nSegSize) { - CGolombBuffer SegmentBuffer (m_pSegBuffer, m_nSegSize); - - switch (m_nCurSegment) { - case PALETTE : - TRACE_HDMVSUB( (_T("CHdmvSub:PALETTE rtStart=%10I64d\n"), rtStart)); - ParsePalette(&SegmentBuffer, m_nSegSize); - break; - case OBJECT : - TRACE_HDMVSUB( (_T("CHdmvSub:OBJECT %lS\n"), ReftimeToCString(rtStart))); - ParseObject(&SegmentBuffer, m_nSegSize); - break; - case PRESENTATION_SEG : - TRACE_HDMVSUB( (_T("CHdmvSub:PRESENTATION_SEG %lS (size=%d)\n"), ReftimeToCString(rtStart), m_nSegSize)); - - if (m_pCurrentObject) { - TRACE_HDMVSUB( (_T("CHdmvSub:PRESENTATION_SEG %d\n"), m_pCurrentObject->m_nObjectNumber)); - if(m_pCurrentObject->m_nObjectNumber > 1) { - m_pCurrentObject->m_nObjectNumber--; - break; - } - m_pCurrentObject->m_rtStop = rtStart; - m_pObjects.AddTail (m_pCurrentObject); - TRACE_HDMVSUB( (_T("CHdmvSub:HDMV : %lS => %lS\n"), ReftimeToCString (m_pCurrentObject->m_rtStart), ReftimeToCString(rtStart))); - m_pCurrentObject = NULL; - } - - if (ParsePresentationSegment(&SegmentBuffer) > 0) { - m_pCurrentObject->m_rtStart = rtStart; - m_pCurrentObject->m_rtStop = _I64_MAX; - } - break; - case WINDOW_DEF : - // TRACE_HDMVSUB( (_T("CHdmvSub:WINDOW_DEF %S\n", ReftimeToCString(rtStart)); - break; - case END_OF_DISPLAY : - // TRACE_HDMVSUB( (_T("CHdmvSub:END_OF_DISPLAY %S\n", ReftimeToCString(rtStart)); - break; - default : - TRACE_HDMVSUB( (_T("CHdmvSub:UNKNOWN Seg %d rtStart=0x%10dd\n"), m_nCurSegment, rtStart)); - } - - m_nCurSegment = NO_SEGMENT; - } - } - } - } - - return hr; -} - -int CHdmvSub::ParsePresentationSegment(CGolombBuffer* pGBuffer) -{ - COMPOSITION_DESCRIPTOR CompositionDescriptor; - BYTE nObjectNumber; - //bool palette_update_flag; - //BYTE palette_id_ref; - - ParseVideoDescriptor(pGBuffer, &m_VideoDescriptor); - ParseCompositionDescriptor(pGBuffer, &CompositionDescriptor); - pGBuffer->ReadByte(); //palette_update_flag = !!(pGBuffer->ReadByte() & 0x80); - pGBuffer->ReadByte(); //palette_id_ref = pGBuffer->ReadByte(); - nObjectNumber = pGBuffer->ReadByte(); - - TRACE_HDMVSUB( (_T("CHdmvSub::ParsePresentationSegment Size = %d, nObjectNumber = %d\n"), pGBuffer->GetSize(), nObjectNumber)); - - if (nObjectNumber > 0) { - delete m_pCurrentObject; - m_pCurrentObject = DNew CompositionObject(); - m_pCurrentObject->m_nObjectNumber = nObjectNumber; - for(int i=0; iReadByte(); - BYTE palette_version_number = pGBuffer->ReadByte(); - UNUSED_ALWAYS(palette_id); - UNUSED_ALWAYS(palette_version_number); - - ASSERT ((nSize-2) % sizeof(HDMV_PALETTE) == 0); - nNbEntry = (nSize-2) / sizeof(HDMV_PALETTE); - HDMV_PALETTE* pPalette = (HDMV_PALETTE*)pGBuffer->GetBufferPos(); - - if (m_pDefaultPalette == NULL || m_nDefaultPaletteNbEntry != nNbEntry) { - delete[] m_pDefaultPalette; - m_pDefaultPalette = new HDMV_PALETTE[nNbEntry]; - m_nDefaultPaletteNbEntry = nNbEntry; - } - memcpy (m_pDefaultPalette, pPalette, nNbEntry*sizeof(HDMV_PALETTE)); - - if (m_pCurrentObject) { - m_pCurrentObject->SetPalette (nNbEntry, pPalette, m_VideoDescriptor.nVideoWidth>720); - } -} - -void CHdmvSub::ParseObject(CGolombBuffer* pGBuffer, USHORT nUnitSize) // #498 -{ - SHORT object_id = pGBuffer->ReadShort(); - UNUSED_ALWAYS(object_id); - BYTE m_sequence_desc; - - ASSERT (m_pCurrentObject != NULL); - if (m_pCurrentObject) { // && m_pCurrentObject->m_object_id_ref == object_id) - m_pCurrentObject->m_version_number = pGBuffer->ReadByte(); - m_sequence_desc = pGBuffer->ReadByte(); - - if (m_sequence_desc & 0x80) { - DWORD object_data_length = (DWORD)pGBuffer->BitRead(24); - - m_pCurrentObject->m_width = pGBuffer->ReadShort(); - m_pCurrentObject->m_height = pGBuffer->ReadShort(); - - m_pCurrentObject->SetRLEData (pGBuffer->GetBufferPos(), nUnitSize-11, object_data_length-4); - - TRACE_HDMVSUB( (_T("CHdmvSub:NewObject size=%ld, total obj=%d, %dx%d\n"), object_data_length, m_pObjects.GetCount(), - m_pCurrentObject->m_width, m_pCurrentObject->m_height)); - } else { - m_pCurrentObject->AppendRLEData (pGBuffer->GetBufferPos(), nUnitSize-4); - } - } -} - -void CHdmvSub::ParseCompositionObject(CGolombBuffer* pGBuffer, CompositionObject* pCompositionObject) -{ - BYTE bTemp; - pCompositionObject->m_object_id_ref = pGBuffer->ReadShort(); - pCompositionObject->m_window_id_ref = pGBuffer->ReadByte(); - bTemp = pGBuffer->ReadByte(); - pCompositionObject->m_object_cropped_flag = !!(bTemp & 0x80); - pCompositionObject->m_forced_on_flag = !!(bTemp & 0x40); - pCompositionObject->m_horizontal_position = pGBuffer->ReadShort(); - pCompositionObject->m_vertical_position = pGBuffer->ReadShort(); - - if (pCompositionObject->m_object_cropped_flag) { - pCompositionObject->m_cropping_horizontal_position = pGBuffer->ReadShort(); - pCompositionObject->m_cropping_vertical_position = pGBuffer->ReadShort(); - pCompositionObject->m_cropping_width = pGBuffer->ReadShort(); - pCompositionObject->m_cropping_height = pGBuffer->ReadShort(); - } -} - -void CHdmvSub::ParseVideoDescriptor(CGolombBuffer* pGBuffer, VIDEO_DESCRIPTOR* pVideoDescriptor) -{ - pVideoDescriptor->nVideoWidth = pGBuffer->ReadShort(); - pVideoDescriptor->nVideoHeight = pGBuffer->ReadShort(); - pVideoDescriptor->bFrameRate = pGBuffer->ReadByte(); -} - -void CHdmvSub::ParseCompositionDescriptor(CGolombBuffer* pGBuffer, COMPOSITION_DESCRIPTOR* pCompositionDescriptor) -{ - pCompositionDescriptor->nNumber = pGBuffer->ReadShort(); - pCompositionDescriptor->bState = pGBuffer->ReadByte(); -} - -void CHdmvSub::Render(SubPicDesc& spd, REFERENCE_TIME rt, RECT& bbox) -{ - CompositionObject* pObject = FindObject (rt); - - ASSERT (pObject!=NULL && spd.w >= (pObject->m_horizontal_position + pObject->m_width) && spd.h >= (pObject->m_vertical_position + pObject->m_height)); - - if (pObject && pObject->GetRLEDataSize() && pObject->m_width > 0 && pObject->m_height > 0 && - spd.w >= (pObject->m_horizontal_position + pObject->m_width) && - spd.h >= (pObject->m_vertical_position + pObject->m_height)) { - if (!pObject->HavePalette()) { - pObject->SetPalette (m_nDefaultPaletteNbEntry, m_pDefaultPalette, m_VideoDescriptor.nVideoWidth>720); - } - pObject->InitColor(spd); - TRACE_HDMVSUB( (_T("CHdmvSub:Render size=%ld, ObjRes=%dx%d, SPDRes=%dx%d\n"), pObject->GetRLEDataSize(), - pObject->m_width, pObject->m_height, spd.w, spd.h)); - pObject->RenderHdmv(spd); - - bbox.left = pObject->m_horizontal_position; - bbox.top = pObject->m_vertical_position; - bbox.right = bbox.left + pObject->m_width; - bbox.bottom = bbox.top + pObject->m_height; - } -} - -HRESULT CHdmvSub::GetTextureSize (POSITION pos, SIZE& MaxTextureSize, SIZE& VideoSize, POINT& VideoTopLeft) -{ - CompositionObject* pObject = m_pObjects.GetAt (pos); - if (pObject) { - MaxTextureSize.cx = m_VideoDescriptor.nVideoWidth; - MaxTextureSize.cy = m_VideoDescriptor.nVideoHeight; - - VideoSize.cx = m_VideoDescriptor.nVideoWidth; - VideoSize.cy = m_VideoDescriptor.nVideoHeight; - - // The subs will be directly rendered into the proper position! - VideoTopLeft.x = 0; //pObject->m_horizontal_position; - VideoTopLeft.y = 0; //pObject->m_vertical_position; - - return S_OK; - } - - ASSERT (FALSE); - return E_INVALIDARG; -} - - -void CHdmvSub::Reset() -{ - CompositionObject* pObject; - while (m_pObjects.GetCount() > 0) { - pObject = m_pObjects.RemoveHead(); - delete pObject; - } -} - -CompositionObject* CHdmvSub::FindObject(REFERENCE_TIME rt) -{ - POSITION pos = m_pObjects.GetHeadPosition(); - - while (pos) { - CompositionObject* pObject = m_pObjects.GetAt (pos); - - if (rt >= pObject->m_rtStart && rt < pObject->m_rtStop) { - return pObject; - } - - m_pObjects.GetNext(pos); - } - - return NULL; -} +/* + * (C) 2006-2012 see Authors.txt + * + * This file is part of MPC-HC. + * + * MPC-HC is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * MPC-HC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "stdafx.h" +#include "HdmvSub.h" +#include "../DSUtil/GolombBuffer.h" + +#if (0) // Set to 1 to activate HDMV subtitles traces +#define TRACE_HDMVSUB(_x_) {CString tmp;tmp.Format _x_; XY_LOG_INFO( tmp.GetString() );} +#else +#define TRACE_HDMVSUB __noop +#endif + + +CHdmvSub::CHdmvSub(void) + : CBaseSub(ST_HDMV) + , m_nCurSegment(NO_SEGMENT) + , m_pSegBuffer(NULL) + , m_nTotalSegBuffer(0) + , m_nSegBufferPos(0) + , m_nSegSize(0) + , m_pCurrentPresentationSegment(NULL) +{ +} + +CHdmvSub::~CHdmvSub() +{ + Reset(); + + delete [] m_pSegBuffer; + delete m_pCurrentPresentationSegment; +} + + +void CHdmvSub::AllocSegment(int nSize) +{ + if (nSize > m_nTotalSegBuffer) { + delete [] m_pSegBuffer; + m_pSegBuffer = DNew BYTE[nSize]; + m_nTotalSegBuffer = nSize; + } + m_nSegBufferPos = 0; + m_nSegSize = nSize; +} + +POSITION CHdmvSub::GetStartPosition(REFERENCE_TIME rt, double fps) +{ + HDMV_PRESENTATION_SEGMENT* pPresentationSegment; + + // Cleanup old PG + while (m_pPresentationSegments.GetCount() > 0) { + pPresentationSegment = m_pPresentationSegments.GetHead(); + if (pPresentationSegment->rtStop < rt) { + TRACE_HDMVSUB( (_T("CHdmvSub:HDMV Remove Presentation segment %d %lS => %lS (rt=%lS)\n"), pPresentationSegment->composition_descriptor.nNumber, + ReftimeToString(pPresentationSegment->rtStart), ReftimeToString(pPresentationSegment->rtStop), ReftimeToString(rt)) ); + m_pPresentationSegments.RemoveHead(); + delete pPresentationSegment; + } else { + break; + } + } + // log first 2 objects + // { + // POSITION pos = m_pPresentationSegments.GetHeadPosition(); + // for (int i=0;i<2 && pos!=NULL; i++) + // { + // CompositionObject* pObject = m_pPresentationSegments.GetNext(pos); + // TRACE_HDMVSUB( (_T("CHdmvSub:HDMV cur %d object %d %lS => %lS\n"), i, pObject->GetRLEDataSize(), + // ReftimeToCString (pObject->m_rtStart), ReftimeToCString(pObject->m_rtStop))); + // } + // } + + POSITION pos = m_pPresentationSegments.GetHeadPosition(); + + while (pos) { + HDMV_PRESENTATION_SEGMENT* pPresentationSegment = m_pPresentationSegments.GetAt (pos); + + if (rt >= pPresentationSegment->rtStart && rt < pPresentationSegment->rtStop) { + break; + } + else if( rt < pPresentationSegment->rtStart ) + { + pos = NULL; + break; + } + + m_pPresentationSegments.GetNext(pos); + } + return pos; +} + +HRESULT CHdmvSub::ParseSample(IMediaSample* pSample) +{ + CheckPointer(pSample, E_POINTER); + HRESULT hr; + REFERENCE_TIME rtStart = INVALID_TIME, rtStop = INVALID_TIME; + BYTE* pData = NULL; + int lSampleLen; + + hr = pSample->GetPointer(&pData); + if (FAILED(hr) || pData == NULL) { + return hr; + } + lSampleLen = pSample->GetActualDataLength(); + + pSample->GetTime(&rtStart, &rtStop); + if (pData) { + CGolombBuffer SampleBuffer(pData, lSampleLen); + + while (!SampleBuffer.IsEOF()) { + if (m_nCurSegment == NO_SEGMENT) { + HDMV_SEGMENT_TYPE nSegType = (HDMV_SEGMENT_TYPE)SampleBuffer.ReadByte(); + unsigned short nUnitSize = SampleBuffer.ReadShort(); + lSampleLen -= 3; + + switch (nSegType) { + case PALETTE: + case OBJECT: + case PRESENTATION_SEG: + case END_OF_DISPLAY: + m_nCurSegment = nSegType; + AllocSegment(nUnitSize); + break; + + case WINDOW_DEF: + case INTERACTIVE_SEG: + case HDMV_SUB1: + case HDMV_SUB2: + // Ignored stuff... + SampleBuffer.SkipBytes(nUnitSize); + break; + default: + return VFW_E_SAMPLE_REJECTED; + } + } + + if (m_nCurSegment != NO_SEGMENT) { + if (m_nSegBufferPos < m_nSegSize) { + int nSize = min(m_nSegSize - m_nSegBufferPos, lSampleLen); + SampleBuffer.ReadBuffer(m_pSegBuffer + m_nSegBufferPos, nSize); + m_nSegBufferPos += nSize; + } + + if (m_nSegBufferPos >= m_nSegSize) { + CGolombBuffer SegmentBuffer(m_pSegBuffer, m_nSegSize); + + switch (m_nCurSegment) { + case PALETTE: + TRACE_HDMVSUB( (_T("CHdmvSub:PALETTE rtStart=%10I64d\n"), rtStart) ); + ParsePalette(&SegmentBuffer, m_nSegSize); + break; + case OBJECT: + TRACE_HDMVSUB( (_T("CHdmvSub:OBJECT %lS\n"), ReftimeToCString(rtStart)) ); + ParseObject(&SegmentBuffer, m_nSegSize); + break; + case PRESENTATION_SEG: + TRACE_HDMVSUB( (_T("CHdmvSub:PRESENTATION_SEG %lS (size=%d)\n"), ReftimeToCString(rtStart), m_nSegSize) ); + + // Enqueue the current presentation segment if any + EnqueuePresentationSegment(rtStart); + // Parse the new presentation segment + ParsePresentationSegment(rtStart, &SegmentBuffer); + + break; + case WINDOW_DEF: + //TRACE_HDMVSUB( (_T("CHdmvSub:WINDOW_DEF %lS\n"), ReftimeToCString(rtStart)) ); + break; + case END_OF_DISPLAY: + //TRACE_HDMVSUB( (_T("CHdmvSub:END_OF_DISPLAY %lS\n"), ReftimeToCString(rtStart)) ); + break; + default: + TRACE_HDMVSUB( (_T("CHdmvSub:UNKNOWN Seg %d rtStart=0x%10dd\n"), m_nCurSegment, rtStart) ); + } + + m_nCurSegment = NO_SEGMENT; + } + } + } + } + + return hr; +} + +int CHdmvSub::ParsePresentationSegment(REFERENCE_TIME rt, CGolombBuffer* pGBuffer) +{ + m_pCurrentPresentationSegment = new HDMV_PRESENTATION_SEGMENT(); + + m_pCurrentPresentationSegment->rtStart = rt; + m_pCurrentPresentationSegment->rtStop = _I64_MAX; + + ParseVideoDescriptor(pGBuffer, &m_pCurrentPresentationSegment->video_descriptor); + ParseCompositionDescriptor(pGBuffer, &m_pCurrentPresentationSegment->composition_descriptor); + m_pCurrentPresentationSegment->palette_update_flag = !!(pGBuffer->ReadByte() & 0x80); + m_pCurrentPresentationSegment->CLUT.id = pGBuffer->ReadByte(); + m_pCurrentPresentationSegment->objectCount = pGBuffer->ReadByte(); + + TRACE_HDMVSUB( (_T("CHdmvSub::ParsePresentationSegment Size = %d, state = %#x, nObjectNumber = %d\n"), pGBuffer->GetSize(), + m_pCurrentPresentationSegment->composition_descriptor.bState, m_pCurrentPresentationSegment->objectCount) ); + + for (int i = 0; i < m_pCurrentPresentationSegment->objectCount; i++) { + CompositionObject* pCompositionObject = new CompositionObject(); + ParseCompositionObject(pGBuffer, pCompositionObject); + m_pCurrentPresentationSegment->objects.AddTail(pCompositionObject); + } + + return m_pCurrentPresentationSegment->objectCount; +} + +void CHdmvSub::EnqueuePresentationSegment(REFERENCE_TIME rt) +{ + if (m_pCurrentPresentationSegment) { + if (m_pCurrentPresentationSegment->objectCount > 0) { + m_pCurrentPresentationSegment->rtStop = rt; + m_pCurrentPresentationSegment->CLUT = m_CLUTs[m_pCurrentPresentationSegment->CLUT.id]; + + // Get the objects' data + POSITION pos = m_pCurrentPresentationSegment->objects.GetHeadPosition(); + while (pos) { + CompositionObject* pObject = m_pCurrentPresentationSegment->objects.GetNext(pos); + + CompositionObject& pObjectData = m_compositionObjects[pObject->m_object_id_ref]; + + pObject->m_width = pObjectData.m_width; + pObject->m_height = pObjectData.m_height; + + pObject->SetRLEData(pObjectData.GetRLEData(), pObjectData.GetRLEDataSize(), pObjectData.GetRLEDataSize()); + } + + m_pPresentationSegments.AddTail(m_pCurrentPresentationSegment); + TRACE_HDMVSUB( (_T("CHdmvSub: Enqueue Presentation Segment %d - %lS => %lS\n"), m_pCurrentPresentationSegment->composition_descriptor.nNumber, + ReftimeToCString(m_pCurrentPresentationSegment->rtStart), ReftimeToCString(m_pCurrentPresentationSegment->rtStop)) ); + } else { + TRACE_HDMVSUB( (_T("CHdmvSub: Delete empty Presentation Segment %d\n"), m_pCurrentPresentationSegment->composition_descriptor.nNumber) ); + delete m_pCurrentPresentationSegment; + } + + m_pCurrentPresentationSegment = NULL; + } +} + +void CHdmvSub::ParsePalette(CGolombBuffer* pGBuffer, unsigned short nSize) // #497 +{ + BYTE palette_id = pGBuffer->ReadByte(); + HDMV_CLUT& CLUT = m_CLUTs[palette_id]; + + CLUT.id = palette_id; + CLUT.version_number = pGBuffer->ReadByte(); + + ASSERT((nSize - 2) % sizeof(HDMV_PALETTE) == 0); + CLUT.size = (nSize - 2) / sizeof(HDMV_PALETTE); + + for (int i = 0; i < CLUT.size; i++) { + BYTE entry_id = pGBuffer->ReadByte(); + + CLUT.palette[entry_id].entry_id = entry_id; + + CLUT.palette[entry_id].Y = pGBuffer->ReadByte(); + CLUT.palette[entry_id].Cr = pGBuffer->ReadByte(); + CLUT.palette[entry_id].Cb = pGBuffer->ReadByte(); + CLUT.palette[entry_id].T = pGBuffer->ReadByte(); + } +} + +void CHdmvSub::ParseObject(CGolombBuffer* pGBuffer, unsigned short nUnitSize) // #498 +{ + short object_id = pGBuffer->ReadShort(); + ASSERT(object_id < _countof(m_compositionObjects)); + + CompositionObject& pObject = m_compositionObjects[object_id]; + + pObject.m_version_number = pGBuffer->ReadByte(); + BYTE m_sequence_desc = pGBuffer->ReadByte(); + + if (m_sequence_desc & 0x80) { + DWORD object_data_length = (DWORD)pGBuffer->BitRead(24); + + pObject.m_width = pGBuffer->ReadShort(); + pObject.m_height = pGBuffer->ReadShort(); + + pObject.SetRLEData(pGBuffer->GetBufferPos(), nUnitSize - 11, object_data_length - 4); + + TRACE_HDMVSUB( (_T("CHdmvSub:ParseObject %d (size=%ld, %dx%d)\n"), object_id, object_data_length, pObject.m_width, pObject.m_height) ); + } else { + pObject.AppendRLEData(pGBuffer->GetBufferPos(), nUnitSize - 4); + } +} + +void CHdmvSub::ParseCompositionObject(CGolombBuffer* pGBuffer, CompositionObject* pCompositionObject) +{ + BYTE bTemp; + pCompositionObject->m_object_id_ref = pGBuffer->ReadShort(); + pCompositionObject->m_window_id_ref = pGBuffer->ReadByte(); + bTemp = pGBuffer->ReadByte(); + pCompositionObject->m_object_cropped_flag = !!(bTemp & 0x80); + pCompositionObject->m_forced_on_flag = !!(bTemp & 0x40); + pCompositionObject->m_horizontal_position = pGBuffer->ReadShort(); + pCompositionObject->m_vertical_position = pGBuffer->ReadShort(); + + if (pCompositionObject->m_object_cropped_flag) { + pCompositionObject->m_cropping_horizontal_position = pGBuffer->ReadShort(); + pCompositionObject->m_cropping_vertical_position = pGBuffer->ReadShort(); + pCompositionObject->m_cropping_width = pGBuffer->ReadShort(); + pCompositionObject->m_cropping_height = pGBuffer->ReadShort(); + } +} + +void CHdmvSub::ParseVideoDescriptor(CGolombBuffer* pGBuffer, VIDEO_DESCRIPTOR* pVideoDescriptor) +{ + pVideoDescriptor->nVideoWidth = pGBuffer->ReadShort(); + pVideoDescriptor->nVideoHeight = pGBuffer->ReadShort(); + pVideoDescriptor->bFrameRate = pGBuffer->ReadByte(); +} + +void CHdmvSub::ParseCompositionDescriptor(CGolombBuffer* pGBuffer, COMPOSITION_DESCRIPTOR* pCompositionDescriptor) +{ + pCompositionDescriptor->nNumber = pGBuffer->ReadShort(); + pCompositionDescriptor->bState = pGBuffer->ReadByte() >> 6; +} + +void CHdmvSub::Render(SubPicDesc& spd, REFERENCE_TIME rt, RECT& bbox) +{ + HDMV_PRESENTATION_SEGMENT* pPresentationSegment = FindPresentationSegment(rt); + + bbox.left = LONG_MAX; + bbox.top = LONG_MAX; + bbox.right = 0; + bbox.bottom = 0; + + if (pPresentationSegment) { + POSITION pos = pPresentationSegment->objects.GetHeadPosition(); + + TRACE_HDMVSUB( (_T("CHdmvSub:Render Presentation segment %d --> %lS - %lS\n"), pPresentationSegment->composition_descriptor.nNumber, + ReftimeToCString(pPresentationSegment->rtStart), ReftimeToCString(pPresentationSegment->rtStop)) ); + + while (pos) { + CompositionObject* pObject = pPresentationSegment->objects.GetNext(pos); + + if (pObject->GetRLEDataSize() && pObject->m_width > 0 && pObject->m_height > 0 + && spd.w >= (pObject->m_horizontal_position + pObject->m_width) && spd.h >= (pObject->m_vertical_position + pObject->m_height)) { + pObject->SetPalette(pPresentationSegment->CLUT.size, pPresentationSegment->CLUT.palette, pPresentationSegment->video_descriptor.nVideoWidth > 720); + + bbox.left = min(pObject->m_horizontal_position, bbox.left); + bbox.top = min(pObject->m_vertical_position, bbox.top); + bbox.right = max(pObject->m_horizontal_position + pObject->m_width, bbox.right); + bbox.bottom = max(pObject->m_vertical_position + pObject->m_height, bbox.bottom); + + pObject->InitColor(spd); + TRACE_HDMVSUB( (_T(" --> Object %d (Res=%dx%d, SPDRes=%dx%d)\n"), pObject->m_object_id_ref, pObject->m_width, pObject->m_height, spd.w, spd.h) ); + pObject->RenderHdmv(spd); + } else { + TRACE_HDMVSUB( (_T(" --> Invalid object %d\n"), pObject->m_object_id_ref) ); + } + } + } +} + +HRESULT CHdmvSub::GetTextureSize(POSITION pos, SIZE& MaxTextureSize, SIZE& VideoSize, POINT& VideoTopLeft) +{ + HDMV_PRESENTATION_SEGMENT* pPresentationSegment = m_pPresentationSegments.GetAt(pos); + if (pPresentationSegment) { + MaxTextureSize.cx = VideoSize.cx = pPresentationSegment->video_descriptor.nVideoWidth; + MaxTextureSize.cy = VideoSize.cy = pPresentationSegment->video_descriptor.nVideoHeight; + + // The subs will be directly rendered into the proper position! + VideoTopLeft.x = 0; //pObject->m_horizontal_position; + VideoTopLeft.y = 0; //pObject->m_vertical_position; + + return S_OK; + } + + ASSERT(FALSE); + return E_INVALIDARG; +} + +void CHdmvSub::Reset() +{ + HDMV_PRESENTATION_SEGMENT* pPresentationSegment; + while (m_pPresentationSegments.GetCount() > 0) { + pPresentationSegment = m_pPresentationSegments.RemoveHead(); + delete pPresentationSegment; + } +} + +CHdmvSub::HDMV_PRESENTATION_SEGMENT* CHdmvSub::FindPresentationSegment(REFERENCE_TIME rt) +{ + POSITION pos = m_pPresentationSegments.GetHeadPosition(); + + while (pos) { + HDMV_PRESENTATION_SEGMENT* pPresentationSegment = m_pPresentationSegments.GetNext(pos); + + if (pPresentationSegment->rtStart <= rt && pPresentationSegment->rtStop > rt) { + return pPresentationSegment; + } + } + + return NULL; +} + +CompositionObject* CHdmvSub::FindObject(HDMV_PRESENTATION_SEGMENT* pPresentationSegment, short sObjectId) +{ + POSITION pos = pPresentationSegment->objects.GetHeadPosition(); + + while (pos) { + CompositionObject* pObject = pPresentationSegment->objects.GetNext(pos); + + if (pObject->m_object_id_ref == sObjectId) { + return pObject; + } + } + + return NULL; +} diff --git a/src/subtitles/HdmvSub.h b/src/subtitles/HdmvSub.h dissimilarity index 80% index 858eadf..7cd7d76 100644 --- a/src/subtitles/HdmvSub.h +++ b/src/subtitles/HdmvSub.h @@ -1,121 +1,151 @@ -/* - * $Id: HdmvSub.h 2786 2010-12-17 16:42:55Z XhmikosR $ - * - * (C) 2006-2010 see AUTHORS - * - * This file is part of mplayerc. - * - * Mplayerc is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Mplayerc is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#pragma once - -#include "BaseSub.h" - -class CGolombBuffer; - -class CHdmvSub : public CBaseSub -{ -public: - - static const REFERENCE_TIME INVALID_TIME = _I64_MIN; - - enum HDMV_SEGMENT_TYPE { - NO_SEGMENT = 0xFFFF, - PALETTE = 0x14, - OBJECT = 0x15, - PRESENTATION_SEG = 0x16, - WINDOW_DEF = 0x17, - INTERACTIVE_SEG = 0x18, - END_OF_DISPLAY = 0x80, - HDMV_SUB1 = 0x81, - HDMV_SUB2 = 0x82 - }; - - - struct VIDEO_DESCRIPTOR { - SHORT nVideoWidth; - SHORT nVideoHeight; - BYTE bFrameRate; // <= Frame rate here! - }; - - struct COMPOSITION_DESCRIPTOR { - SHORT nNumber; - BYTE bState; - }; - - struct SEQUENCE_DESCRIPTOR { - BYTE bFirstIn : 1; - BYTE bLastIn : 1; - BYTE bReserved : 8; - }; - - CHdmvSub(); - ~CHdmvSub(); - - HRESULT ParseSample (IMediaSample* pSample); - - - POSITION GetStartPosition(REFERENCE_TIME rt, double fps); - POSITION GetNext(POSITION pos) { - m_pObjects.GetNext(pos); - return pos; - }; - - - virtual REFERENCE_TIME GetStart(POSITION nPos) { - CompositionObject* pObject = m_pObjects.GetAt(nPos); - return pObject!=NULL ? pObject->m_rtStart : INVALID_TIME; - }; - virtual REFERENCE_TIME GetStop(POSITION nPos) { - CompositionObject* pObject = m_pObjects.GetAt(nPos); - return pObject!=NULL ? pObject->m_rtStop : INVALID_TIME; - }; - - void Render(SubPicDesc& spd, REFERENCE_TIME rt, RECT& bbox); - HRESULT GetTextureSize (POSITION pos, SIZE& MaxTextureSize, SIZE& VideoSize, POINT& VideoTopLeft); - void Reset(); - -private : - - HDMV_SEGMENT_TYPE m_nCurSegment; - BYTE* m_pSegBuffer; - int m_nTotalSegBuffer; - int m_nSegBufferPos; - int m_nSegSize; - - VIDEO_DESCRIPTOR m_VideoDescriptor; - - CompositionObject* m_pCurrentObject; - CAtlList m_pObjects; - - HDMV_PALETTE* m_pDefaultPalette; - int m_nDefaultPaletteNbEntry; - - int m_nColorNumber; - - - int ParsePresentationSegment(CGolombBuffer* pGBuffer); - void ParsePalette(CGolombBuffer* pGBuffer, USHORT nSize); - void ParseObject(CGolombBuffer* pGBuffer, USHORT nUnitSize); - - void ParseVideoDescriptor(CGolombBuffer* pGBuffer, VIDEO_DESCRIPTOR* pVideoDescriptor); - void ParseCompositionDescriptor(CGolombBuffer* pGBuffer, COMPOSITION_DESCRIPTOR* pCompositionDescriptor); - void ParseCompositionObject(CGolombBuffer* pGBuffer, CompositionObject* pCompositionObject); - - void AllocSegment(int nSize); - - CompositionObject* FindObject(REFERENCE_TIME rt); -}; +/* + * (C) 2006-2012 see Authors.txt + * + * This file is part of MPC-HC. + * + * MPC-HC is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * MPC-HC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include "BaseSub.h" + +class CGolombBuffer; + +class CHdmvSub : public CBaseSub +{ +public: + + static const REFERENCE_TIME INVALID_TIME = _I64_MIN; + + enum HDMV_SEGMENT_TYPE { + NO_SEGMENT = 0xFFFF, + PALETTE = 0x14, + OBJECT = 0x15, + PRESENTATION_SEG = 0x16, + WINDOW_DEF = 0x17, + INTERACTIVE_SEG = 0x18, + END_OF_DISPLAY = 0x80, + HDMV_SUB1 = 0x81, + HDMV_SUB2 = 0x82 + }; + + + struct VIDEO_DESCRIPTOR { + short nVideoWidth; + short nVideoHeight; + BYTE bFrameRate; // <= Frame rate here! + }; + + struct COMPOSITION_DESCRIPTOR { + short nNumber; + BYTE bState; + }; + + struct SEQUENCE_DESCRIPTOR { + BYTE bFirstIn : 1; + BYTE bLastIn : 1; + BYTE bReserved : 6; + }; + + struct HDMV_CLUT { + BYTE id; + BYTE version_number; + BYTE size; + + HDMV_PALETTE palette[256]; + + HDMV_CLUT() { memset(palette, 0, sizeof(palette)); } + }; + + struct HDMV_PRESENTATION_SEGMENT { + REFERENCE_TIME rtStart; + REFERENCE_TIME rtStop; + + VIDEO_DESCRIPTOR video_descriptor; + COMPOSITION_DESCRIPTOR composition_descriptor; + + byte palette_update_flag; + HDMV_CLUT CLUT; + + int objectCount; + + CAtlList objects; + + ~HDMV_PRESENTATION_SEGMENT() { + CompositionObject* pObject; + while (objects.GetCount() > 0) { + pObject = objects.RemoveHead(); + delete pObject; + } + } + }; + + CHdmvSub(); + ~CHdmvSub(); + + HRESULT ParseSample(IMediaSample* pSample); + + + POSITION GetStartPosition(REFERENCE_TIME rt, double fps); + POSITION GetNext(POSITION pos) { + m_pPresentationSegments.GetNext(pos); + return pos; + }; + + + virtual REFERENCE_TIME GetStart(POSITION nPos) { + HDMV_PRESENTATION_SEGMENT* pPresentationSegment = m_pPresentationSegments.GetAt(nPos); + return pPresentationSegment != NULL ? pPresentationSegment->rtStart : INVALID_TIME; + }; + virtual REFERENCE_TIME GetStop(POSITION nPos) { + HDMV_PRESENTATION_SEGMENT* pPresentationSegment = m_pPresentationSegments.GetAt(nPos); + return pPresentationSegment != NULL ? pPresentationSegment->rtStop : INVALID_TIME; + }; + + void Render(SubPicDesc& spd, REFERENCE_TIME rt, RECT& bbox); + HRESULT GetTextureSize(POSITION pos, SIZE& MaxTextureSize, SIZE& VideoSize, POINT& VideoTopLeft); + void Reset(); + +private: + + HDMV_SEGMENT_TYPE m_nCurSegment; + BYTE* m_pSegBuffer; + int m_nTotalSegBuffer; + int m_nSegBufferPos; + int m_nSegSize; + + HDMV_PRESENTATION_SEGMENT* m_pCurrentPresentationSegment; + CAtlList m_pPresentationSegments; + + HDMV_CLUT m_CLUTs[256]; + CompositionObject m_compositionObjects[64]; + + + int ParsePresentationSegment(REFERENCE_TIME rt, CGolombBuffer* pGBuffer); + void EnqueuePresentationSegment(REFERENCE_TIME rt); + + void ParsePalette(CGolombBuffer* pGBuffer, unsigned short nSize); + void ParseObject(CGolombBuffer* pGBuffer, unsigned short nUnitSize); + + void ParseVideoDescriptor(CGolombBuffer* pGBuffer, VIDEO_DESCRIPTOR* pVideoDescriptor); + void ParseCompositionDescriptor(CGolombBuffer* pGBuffer, COMPOSITION_DESCRIPTOR* pCompositionDescriptor); + void ParseCompositionObject(CGolombBuffer* pGBuffer, CompositionObject* pCompositionObject); + + void AllocSegment(int nSize); + + HDMV_PRESENTATION_SEGMENT* FindPresentationSegment(REFERENCE_TIME rt); + CompositionObject* FindObject(HDMV_PRESENTATION_SEGMENT* pPresentationSegment, short sObjectId); +}; -- 2.11.4.GIT