From 8406f4a99f461cd1e06c0642acfea04014bf6df4 Mon Sep 17 00:00:00 2001 From: "yuzhuohuang@qq.com" Date: Thu, 4 Oct 2012 16:43:47 +0800 Subject: [PATCH] Merge MPC-HC code(01b8dbf34d6a486fa1cd02d7a123249fec1e4160) [PART 2] (DVBSub) --- src/subtitles/DVBSub.cpp | 1198 ++++++++++++++++++++++++---------------------- src/subtitles/DVBSub.h | 430 ++++++++--------- 2 files changed, 833 insertions(+), 795 deletions(-) rewrite src/subtitles/DVBSub.cpp (86%) rewrite src/subtitles/DVBSub.h (87%) diff --git a/src/subtitles/DVBSub.cpp b/src/subtitles/DVBSub.cpp dissimilarity index 86% index d8a6d53..93dc89f 100644 --- a/src/subtitles/DVBSub.cpp +++ b/src/subtitles/DVBSub.cpp @@ -1,581 +1,617 @@ -/* - * $Id: DVBSub.cpp 3605 2011-08-07 19:52:16Z underground78 $ - * - * (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 "DVBSub.h" -#include "../DSUtil/GolombBuffer.h" - -#if (1) // Set to 1 to activate DVB subtitles traces -#define TRACE_DVB TRACE -#else -#define TRACE_DVB -#endif - -#define BUFFER_CHUNK_GROW 0x1000 - -CDVBSub::CDVBSub(void) - : CBaseSub(ST_DVB) -{ - m_nBufferReadPos = 0; - m_nBufferWritePos = 0; - m_nBufferSize = 0; - m_pBuffer = NULL; -} - -CDVBSub::~CDVBSub(void) -{ - Reset(); - SAFE_DELETE(m_pBuffer); -} - -CDVBSub::DVB_PAGE* CDVBSub::FindPage(REFERENCE_TIME rt) -{ - POSITION pos = m_Pages.GetHeadPosition(); - - while (pos) { - DVB_PAGE* pPage = m_Pages.GetAt (pos); - - if (rt >= pPage->rtStart && rt < pPage->rtStop) { - return pPage; - } - - m_Pages.GetNext(pos); - } - - return NULL; -} - -CDVBSub::DVB_REGION* CDVBSub::FindRegion(DVB_PAGE* pPage, BYTE bRegionId) -{ - if (pPage != NULL) { - for (int i=0; iRegionCount; i++) { - if (pPage->Regions[i].Id == bRegionId) { - return &pPage->Regions[i]; - } - } - } - return NULL; -} - -CDVBSub::DVB_CLUT* CDVBSub::FindClut(DVB_PAGE* pPage, BYTE bClutId) -{ - if (pPage != NULL) { - for (int i=0; iRegionCount; i++) { - if (pPage->Regions[i].CLUT_id == bClutId) { - return &pPage->Regions[i].Clut; - } - } - } - return NULL; -} - -CompositionObject* CDVBSub::FindObject(DVB_PAGE* pPage, SHORT sObjectId) -{ - if (pPage != NULL) { - POSITION pos = pPage->Objects.GetHeadPosition(); - - while (pos) { - CompositionObject* pObject = pPage->Objects.GetAt (pos); - - if (pObject->m_object_id_ref == sObjectId) { - return pObject; - } - - pPage->Objects.GetNext(pos); - } - } - return NULL; -} - -HRESULT CDVBSub::AddToBuffer(BYTE* pData, int nSize) -{ - bool bFirstChunk = (*((LONG*)pData) & 0x00FFFFFF) == 0x000f0020; // DVB sub start with 0x20 0x00 0x0F ... - - if (m_nBufferWritePos > 0 || bFirstChunk) { - if (bFirstChunk) { - m_nBufferWritePos = 0; - m_nBufferReadPos = 0; - } - - if (m_nBufferWritePos+nSize > m_nBufferSize) { - if (m_nBufferWritePos+nSize > 20*BUFFER_CHUNK_GROW) { - // Too big to be a DVB sub ! - TRACE_DVB ("DVB - Too much data receive...\n"); - ASSERT (FALSE); - - Reset(); - return E_INVALIDARG; - } - - BYTE* pPrev = m_pBuffer; - m_nBufferSize = max (m_nBufferWritePos+nSize, m_nBufferSize+BUFFER_CHUNK_GROW); - m_pBuffer = new BYTE[m_nBufferSize]; - if (pPrev != NULL) { - memcpy_s (m_pBuffer, m_nBufferSize, pPrev, m_nBufferWritePos); - SAFE_DELETE (pPrev); - } - } - memcpy_s (m_pBuffer+m_nBufferWritePos, m_nBufferSize, pData, nSize); - m_nBufferWritePos += nSize; - return S_OK; - } - return S_FALSE; -} - -#define MARKER if(gb.BitRead(1) != 1) {ASSERT(0); return(E_FAIL);} - -HRESULT CDVBSub::ParseSample (IMediaSample* pSample) -{ - CheckPointer (pSample, E_POINTER); - HRESULT hr; - BYTE* pData = NULL; - int nSize; - DVB_SEGMENT_TYPE nCurSegment; - - hr = pSample->GetPointer(&pData); - if(FAILED(hr) || pData == NULL) { - return hr; - } - nSize = pSample->GetActualDataLength(); - - if (*((LONG*)pData) == 0xBD010000) { - CGolombBuffer gb (pData, nSize); - - gb.SkipBytes(4); - WORD wLength = (WORD)gb.BitRead(16); - UNUSED_ALWAYS(wLength); - - if (gb.BitRead(2) != 2) { - return E_FAIL; // type - } - - gb.BitRead(2); // scrambling - gb.BitRead(1); // priority - gb.BitRead(1); // alignment - gb.BitRead(1); // copyright - gb.BitRead(1); // original - BYTE fpts = (BYTE)gb.BitRead(1); // fpts - BYTE fdts = (BYTE)gb.BitRead(1); // fdts - gb.BitRead(1); // escr - gb.BitRead(1); // esrate - gb.BitRead(1); // dsmtrickmode - gb.BitRead(1); // morecopyright - gb.BitRead(1); // crc - gb.BitRead(1); // extension - gb.BitRead(8); // hdrlen - - if(fpts) { - BYTE b = (BYTE)gb.BitRead(4); - if(!(fdts && b == 3 || !fdts && b == 2)) { - ASSERT(0); - return(E_FAIL); - } - - REFERENCE_TIME pts = 0; - pts |= gb.BitRead(3) << 30; - MARKER; // 32..30 - pts |= gb.BitRead(15) << 15; - MARKER; // 29..15 - pts |= gb.BitRead(15); - MARKER; // 14..0 - pts = 10000*pts/90; - - m_rtStart = pts; - m_rtStop = pts+1; - } else { - m_rtStart = INVALID_TIME; - m_rtStop = INVALID_TIME; - } - - nSize -= 14; - pData += 14; - pSample->GetTime(&m_rtStart, &m_rtStop); - pSample->GetMediaTime(&m_rtStart, &m_rtStop); - } else if (SUCCEEDED (pSample->GetTime(&m_rtStart, &m_rtStop))) { - pSample->SetTime(&m_rtStart, &m_rtStop); - } - - //FILE* hFile = fopen ("D:\\Sources\\mpc-hc\\A garder\\TestSubRip\\dvbsub.dat", "ab"); - //if(hFile != NULL) - //{ - // //BYTE Buff[5] = {48}; - - // //*((DWORD*)(Buff+1)) = lSampleLen; - // //fwrite (Buff, 1, sizeof(Buff), hFile); - // fwrite (pData, 1, lSampleLen, hFile); - // fclose(hFile); - //} - - if (AddToBuffer (pData, nSize) == S_OK) { - CGolombBuffer gb (m_pBuffer+m_nBufferReadPos, m_nBufferWritePos-m_nBufferReadPos); - int nLastPos = 0; - - while (!gb.IsEOF()) { - if (gb.ReadByte() == 0x0F) { - WORD wPageId; - WORD wSegLength; - - nCurSegment = (DVB_SEGMENT_TYPE) gb.ReadByte(); - wPageId = gb.ReadShort(); - wSegLength = gb.ReadShort(); - - if (gb.RemainingSize() < wSegLength) { - hr = S_FALSE; - break; - } - - switch (nCurSegment) { - case PAGE : { - CAutoPtr pPage; - ParsePage(gb, wSegLength, pPage); - - if (pPage->PageState == DPS_ACQUISITION) { - m_pCurrentPage = pPage; - m_pCurrentPage->rtStart = m_rtStart; - TRACE_DVB ("DVB - Page started %S\n", ReftimeToCString(m_rtStart)); - m_rtStart = INVALID_TIME; - } else { - TRACE_DVB ("DVB - Page update\n"); - } - } - break; - case REGION : - ParseRegion(gb, wSegLength); - TRACE_DVB ("DVB - Region\n"); - break; - case CLUT : - ParseClut(gb, wSegLength); - TRACE_DVB ("DVB - Clut \n"); - break; - case OBJECT : - ParseObject(gb, wSegLength); - TRACE_DVB ("DVB - Object\n"); - break; - case DISPLAY : - ParseDisplay(gb, wSegLength); - break; - case END_OF_DISPLAY : - if (m_pCurrentPage != NULL && m_rtStart != INVALID_TIME) { - m_pCurrentPage->rtStop = m_rtStart; - TRACE_DVB ("DVB - End display %S - %S\n", ReftimeToCString(m_pCurrentPage->rtStart), ReftimeToCString(m_pCurrentPage->rtStop)); - m_Pages.AddTail (m_pCurrentPage.Detach()); - } - break; - default : - // gb.SkipBytes(wSegLength); - break; - } - nLastPos = gb.GetPos(); - } - } - m_nBufferReadPos += nLastPos; - } - - return hr; -} - -void CDVBSub::Render(SubPicDesc& spd, REFERENCE_TIME rt, RECT& bbox) -{ - DVB_PAGE* pPage = FindPage (rt); - - if (pPage != NULL) { - pPage->Rendered = true; - for (int i=0; iRegionCount; i++) { - CDVBSub::DVB_REGION* pRegion = &pPage->Regions[i]; - for (int j=0; jObjectCount; j++) { - CompositionObject* pObject = FindObject (pPage, pRegion->Objects[j].object_id); - if (pObject) { - SHORT nX, nY; - nX = pRegion->HorizAddr + pRegion->Objects[j].object_horizontal_position; - nY = pRegion->VertAddr + pRegion->Objects[j].object_vertical_position; - pObject->m_width = pRegion->width; - pObject->m_height = pRegion->height; - pObject->SetPalette(pRegion->Clut.Size, pRegion->Clut.Palette, false); - pObject->InitColor(spd); - pObject->RenderDvb(spd, nX, nY); - } - } - } - - bbox.left = 0; - bbox.top = 0; - bbox.right = m_Display.width; - bbox.bottom = m_Display.height; - - } -} - -HRESULT CDVBSub::GetTextureSize (POSITION pos, SIZE& MaxTextureSize, SIZE& VideoSize, POINT& VideoTopLeft) -{ - // TODO : limit size for HDTV - - // Texture size should be video size width. Height is limited (to prevent performances issues with - // more than 1024x768 pixels) - MaxTextureSize.cx = min (m_Display.width, 1920); - MaxTextureSize.cy = min (m_Display.height, 1024*768/MaxTextureSize.cx); - - VideoSize.cx = m_Display.width; - VideoSize.cy = m_Display.height; - - VideoTopLeft.x = 0; - VideoTopLeft.y = 0; - - return S_OK; -} - -POSITION CDVBSub::GetStartPosition(REFERENCE_TIME rt, double fps) -{ - DVB_PAGE* pPage; - - // Cleanup old PG - while (m_Pages.GetCount()>0) { - pPage = m_Pages.GetHead(); - if (pPage->rtStop < rt) { - if (!pPage->Rendered) { - TRACE_DVB ("DVB - remove unrendered object, %S - %S\n", ReftimeToCString(pPage->rtStart), ReftimeToCString(pPage->rtStop)); - } - - //TRACE_HDMVSUB ("CHdmvSub:HDMV remove object %d %S => %S (rt=%S)\n", pPage->GetRLEDataSize(), - // ReftimeToCString (pPage->rtStart), ReftimeToCString(pPage->rtStop), ReftimeToCString(rt)); - m_Pages.RemoveHead(); - delete pPage; - } else { - break; - } - } - - POSITION pos = m_Pages.GetHeadPosition(); - - while (pos) { - DVB_PAGE* pPage = m_Pages.GetAt (pos); - - if (rt >= pPage->rtStart && rt < pPage->rtStop) { - break; - } - else if( rt < pPage->rtStart ) - { - pos = NULL; - break; - } - - m_Pages.GetNext(pos); - } - return pos; -} - -POSITION CDVBSub::GetNext(POSITION pos) -{ - m_Pages.GetNext(pos); - return pos; -} - - -REFERENCE_TIME CDVBSub::GetStart(POSITION nPos) -{ - DVB_PAGE* pPage = m_Pages.GetAt(nPos); - return pPage!=NULL ? pPage->rtStart : INVALID_TIME; -} - -REFERENCE_TIME CDVBSub::GetStop(POSITION nPos) -{ - DVB_PAGE* pPage = m_Pages.GetAt(nPos); - return pPage!=NULL ? pPage->rtStop : INVALID_TIME; -} - - -void CDVBSub::Reset() -{ - m_nBufferReadPos = 0; - m_nBufferWritePos = 0; - m_pCurrentPage.Free(); - - DVB_PAGE* pPage; - while (m_Pages.GetCount() > 0) { - pPage = m_Pages.RemoveHead(); - delete pPage; - } - -} - -HRESULT CDVBSub::ParsePage(CGolombBuffer& gb, WORD wSegLength, CAutoPtr& pPage) -{ - WORD wEnd = (WORD)gb.GetPos() + wSegLength; - int nPos = 0; - - pPage.Attach (DNew DVB_PAGE()); - pPage->PageTimeOut = gb.ReadByte(); - pPage->PageVersionNumber = (BYTE)gb.BitRead(4); - pPage->PageState = (BYTE)gb.BitRead(2); - pPage->RegionCount = 0; - gb.BitRead(2); // Reserved - while (gb.GetPos() < wEnd) { - if (nPos < MAX_REGIONS) { - pPage->Regions[nPos].Id = gb.ReadByte(); - gb.ReadByte(); // Reserved - pPage->Regions[nPos].HorizAddr = gb.ReadShort(); - pPage->Regions[nPos].VertAddr = gb.ReadShort(); - pPage->RegionCount++; - } - nPos++; - } - - return S_OK; -} - -HRESULT CDVBSub::ParseDisplay(CGolombBuffer& gb, WORD wSegLength) -{ - m_Display.version_number = (BYTE)gb.BitRead (4); - m_Display.display_window_flag = (BYTE)gb.BitRead (1); - gb.BitRead(3); // reserved - m_Display.width = gb.ReadShort(); - m_Display.height = gb.ReadShort(); - if (m_Display.display_window_flag) { - m_Display.horizontal_position_minimun = gb.ReadShort(); - m_Display.horizontal_position_maximum = gb.ReadShort(); - m_Display.vertical_position_minimun = gb.ReadShort(); - m_Display.vertical_position_maximum = gb.ReadShort(); - } - - return S_OK; -} - -HRESULT CDVBSub::ParseRegion(CGolombBuffer& gb, WORD wSegLength) -{ - WORD wEnd = (WORD)gb.GetPos() + wSegLength; - CDVBSub::DVB_REGION* pRegion; - CDVBSub::DVB_REGION DummyRegion; - - pRegion = FindRegion (m_pCurrentPage, gb.ReadByte()); - - if (pRegion == NULL) { - pRegion = &DummyRegion; - } - - if (pRegion != NULL) { - pRegion->version_number = (BYTE)gb.BitRead(4); - pRegion->fill_flag = (BYTE)gb.BitRead(1); - gb.BitRead(3); // Reserved - pRegion->width = gb.ReadShort(); - pRegion->height = gb.ReadShort(); - pRegion->level_of_compatibility = (BYTE)gb.BitRead(3); - pRegion->depth = (BYTE)gb.BitRead(3); - gb.BitRead(2); // Reserved - pRegion->CLUT_id = gb.ReadByte(); - pRegion->_8_bit_pixel_code = gb.ReadByte(); - pRegion->_4_bit_pixel_code = (BYTE)gb.BitRead(4); - pRegion->_2_bit_pixel_code = (BYTE)gb.BitRead(2); - gb.BitRead(2); // Reserved - - pRegion->ObjectCount = 0; - while (gb.GetPos() < wEnd) { - DVB_OBJECT* pObject = &pRegion->Objects[pRegion->ObjectCount]; - pObject->object_id = gb.ReadShort(); - pObject->object_type = (BYTE)gb.BitRead(2); - pObject->object_provider_flag = (BYTE)gb.BitRead(2); - pObject->object_horizontal_position = (SHORT)gb.BitRead(12); - gb.BitRead(4); // Reserved - pObject->object_vertical_position = (SHORT)gb.BitRead(12); - if (pObject->object_type == 0x01 || pObject->object_type == 0x02) { - pObject->foreground_pixel_code = gb.ReadByte(); - pObject->background_pixel_code = gb.ReadByte(); - } - pRegion->ObjectCount++; - } - } else { - gb.SkipBytes (wSegLength-1); - } - - return S_OK; -} - -HRESULT CDVBSub::ParseClut(CGolombBuffer& gb, WORD wSegLength) -{ - HRESULT hr = S_OK; - WORD wEnd = (WORD)gb.GetPos() + wSegLength; - CDVBSub::DVB_CLUT* pClut; - - pClut = FindClut (m_pCurrentPage, gb.ReadByte()); - // ASSERT (pClut != NULL); - if (pClut != NULL) { - pClut->version_number = (BYTE)gb.BitRead(4); - gb.BitRead(4); // Reserved - - pClut->Size = 0; - while (gb.GetPos() < wEnd) { - BYTE entry_id = gb.ReadByte()+1; - BYTE _2_bit = (BYTE)gb.BitRead(1); - BYTE _4_bit = (BYTE)gb.BitRead(1); - BYTE _8_bit = (BYTE)gb.BitRead(1); - UNUSED_ALWAYS(_2_bit); - UNUSED_ALWAYS(_4_bit); - UNUSED_ALWAYS(_8_bit); - gb.BitRead(4); // Reserved - - pClut->Palette[entry_id].entry_id = entry_id; - if (gb.BitRead(1)) { - pClut->Palette[entry_id].Y = gb.ReadByte(); - pClut->Palette[entry_id].Cr = gb.ReadByte(); - pClut->Palette[entry_id].Cb = gb.ReadByte(); - pClut->Palette[entry_id].T = 255-gb.ReadByte(); - } else { - pClut->Palette[entry_id].Y = (BYTE)gb.BitRead(6)<<2; - pClut->Palette[entry_id].Cr = (BYTE)gb.BitRead(4)<<4; - pClut->Palette[entry_id].Cb = (BYTE)gb.BitRead(4)<<4; - pClut->Palette[entry_id].T = 255-((BYTE)gb.BitRead(2)<<6); - } - pClut->Size = max (pClut->Size, entry_id); - } - } - - return hr; -} - -HRESULT CDVBSub::ParseObject(CGolombBuffer& gb, WORD wSegLength) -{ - HRESULT hr = E_FAIL; - - if (m_pCurrentPage && wSegLength > 2) { - CompositionObject* pObject = DNew CompositionObject(); - BYTE object_coding_method; - - pObject->m_object_id_ref = gb.ReadShort(); - pObject->m_version_number = (BYTE)gb.BitRead(4); - - object_coding_method = (BYTE)gb.BitRead(2); // object_coding_method - gb.BitRead(1); // non_modifying_colour_flag - gb.BitRead(1); // reserved - - if (object_coding_method == 0x00) { - pObject->SetRLEData (gb.GetBufferPos(), wSegLength-3, wSegLength-3); - gb.SkipBytes(wSegLength-3); - m_pCurrentPage->Objects.AddTail (pObject); - hr = S_OK; - } else { - delete pObject; - hr = E_NOTIMPL; - } - } - - - return hr; -} +/* + * (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 "DVBSub.h" +#include "../DSUtil/GolombBuffer.h" + +#if (0) // Set to 1 to activate DVB subtitles traces +#define TRACE_DVB TRACE +#else +#define TRACE_DVB __noop +#endif + +#define BUFFER_CHUNK_GROW 0x1000 + +CDVBSub::CDVBSub(void) + : CBaseSub(ST_DVB) +{ + m_nBufferReadPos = 0; + m_nBufferWritePos = 0; + m_nBufferSize = 0; + m_pBuffer = NULL; +} + +CDVBSub::~CDVBSub(void) +{ + Reset(); + SAFE_DELETE(m_pBuffer); +} + +CDVBSub::DVB_PAGE* CDVBSub::FindPage(REFERENCE_TIME rt) +{ + POSITION pos = m_Pages.GetHeadPosition(); + + while (pos) { + DVB_PAGE* pPage = m_Pages.GetNext(pos); + + if (rt >= pPage->rtStart && rt < pPage->rtStop) { + return pPage; + } + } + + return NULL; +} + +CDVBSub::DVB_REGION* CDVBSub::FindRegion(DVB_PAGE* pPage, BYTE bRegionId) +{ + if (pPage != NULL) { + for (int i = 0; i < pPage->regionCount; i++) { + if (pPage->regions[i].id == bRegionId) { + return &pPage->regions[i]; + } + } + } + return NULL; +} + +CDVBSub::DVB_CLUT* CDVBSub::FindClut(DVB_PAGE* pPage, BYTE bClutId) +{ + if (pPage != NULL) { + POSITION pos = pPage->CLUTs.GetHeadPosition(); + + while (pos) { + DVB_CLUT* pCLUT = pPage->CLUTs.GetNext(pos); + + if (pCLUT->id == bClutId) { + return pCLUT; + } + } + } + return NULL; +} + +CompositionObject* CDVBSub::FindObject(DVB_PAGE* pPage, short sObjectId) +{ + if (pPage != NULL) { + POSITION pos = pPage->objects.GetHeadPosition(); + + while (pos) { + CompositionObject* pObject = pPage->objects.GetNext(pos); + + if (pObject->m_object_id_ref == sObjectId) { + return pObject; + } + } + } + return NULL; +} + +HRESULT CDVBSub::AddToBuffer(BYTE* pData, int nSize) +{ + bool bFirstChunk = (*((LONG*)pData) & 0x00FFFFFF) == 0x000f0020; // DVB sub start with 0x20 0x00 0x0F ... + + if (m_nBufferWritePos > 0 || bFirstChunk) { + if (bFirstChunk) { + m_nBufferWritePos = 0; + m_nBufferReadPos = 0; + } + + if (m_nBufferWritePos + nSize > m_nBufferSize) { + if (m_nBufferWritePos + nSize > 20 * BUFFER_CHUNK_GROW) { + // Too big to be a DVB sub ! + TRACE_DVB(_T("DVB - Too much data received...\n")); + ASSERT(FALSE); + + Reset(); + return E_INVALIDARG; + } + + BYTE* pPrev = m_pBuffer; + m_nBufferSize = max(m_nBufferWritePos + nSize, m_nBufferSize + BUFFER_CHUNK_GROW); + m_pBuffer = DNew BYTE[m_nBufferSize]; + if (pPrev != NULL) { + memcpy_s(m_pBuffer, m_nBufferSize, pPrev, m_nBufferWritePos); + SAFE_DELETE(pPrev); + } + } + memcpy_s(m_pBuffer + m_nBufferWritePos, m_nBufferSize, pData, nSize); + m_nBufferWritePos += nSize; + return S_OK; + } + return S_FALSE; +} + +#define MARKER \ + if (gb.BitRead(1) != 1) \ + { \ + ASSERT(0); \ + return E_FAIL; \ + } + +HRESULT CDVBSub::ParseSample(IMediaSample* pSample) +{ + CheckPointer(pSample, E_POINTER); + HRESULT hr; + BYTE* pData = NULL; + int nSize; + DVB_SEGMENT_TYPE nCurSegment; + + hr = pSample->GetPointer(&pData); + if (FAILED(hr) || pData == NULL) { + return hr; + } + nSize = pSample->GetActualDataLength(); + + if (*((LONG*)pData) == 0xBD010000) { + CGolombBuffer gb(pData, nSize); + + gb.SkipBytes(4); + WORD wLength = (WORD)gb.BitRead(16); + UNREFERENCED_PARAMETER(wLength); + + if (gb.BitRead(2) != 2) { + return E_FAIL; // type + } + + gb.BitRead(2); // scrambling + gb.BitRead(1); // priority + gb.BitRead(1); // alignment + gb.BitRead(1); // copyright + gb.BitRead(1); // original + BYTE fpts = (BYTE)gb.BitRead(1); // fpts + BYTE fdts = (BYTE)gb.BitRead(1); // fdts + gb.BitRead(1); // escr + gb.BitRead(1); // esrate + gb.BitRead(1); // dsmtrickmode + gb.BitRead(1); // morecopyright + gb.BitRead(1); // crc + gb.BitRead(1); // extension + gb.BitRead(8); // hdrlen + + if (fpts) { + BYTE b = (BYTE)gb.BitRead(4); + if (!(fdts && b == 3 || !fdts && b == 2)) { + ASSERT(0); + return E_FAIL; + } + + REFERENCE_TIME pts = 0; + pts |= gb.BitRead(3) << 30; + MARKER; // 32..30 + pts |= gb.BitRead(15) << 15; + MARKER; // 29..15 + pts |= gb.BitRead(15); + MARKER; // 14..0 + pts = 10000 * pts / 90; + + m_rtStart = pts; + m_rtStop = pts + 1; + } else { + m_rtStart = INVALID_TIME; + m_rtStop = INVALID_TIME; + } + + nSize -= 14; + pData += 14; + pSample->GetTime(&m_rtStart, &m_rtStop); + pSample->GetMediaTime(&m_rtStart, &m_rtStop); + } else if (SUCCEEDED(pSample->GetTime(&m_rtStart, &m_rtStop))) { + pSample->SetTime(&m_rtStart, &m_rtStop); + } + + if (AddToBuffer(pData, nSize) == S_OK) { + CGolombBuffer gb(m_pBuffer + m_nBufferReadPos, m_nBufferWritePos - m_nBufferReadPos); + int nLastPos = 0; + + while (gb.RemainingSize() >= 6) { // Ensure there is enough data to parse the entire segment header + if (gb.ReadByte() == 0x0F) { + TRACE_DVB(_T("DVB - ParseSample\n")); + + WORD wPageId; + WORD wSegLength; + + nCurSegment = (DVB_SEGMENT_TYPE) gb.ReadByte(); + wPageId = gb.ReadShort(); + wSegLength = gb.ReadShort(); + + if (gb.RemainingSize() < wSegLength) { + hr = S_FALSE; + break; + } + + switch (nCurSegment) { + case PAGE: { + CAutoPtr pPage; + ParsePage(gb, wSegLength, pPage); + + if (pPage->pageState == DPS_ACQUISITION) { + if (m_pCurrentPage != NULL) { + TRACE_DVB(_T("DVB - Force End display %s (%s - %s)\n"), ReftimeToCString(m_rtStart), ReftimeToCString(m_pCurrentPage->rtStart), ReftimeToCString(m_pCurrentPage->rtStop)); + m_pCurrentPage->rtStop = max(m_pCurrentPage->rtStop, m_rtStart); + m_Pages.AddTail(m_pCurrentPage.Detach()); + } + UpdateTimeStamp(m_rtStart); + + m_pCurrentPage = pPage; + m_pCurrentPage->rtStart = m_rtStart; + m_pCurrentPage->rtStop = m_pCurrentPage->rtStart + m_pCurrentPage->pageTimeOut * 1000000; + + TRACE_DVB(_T("DVB - Page started %s, TimeOut = %d\n"), ReftimeToCString(m_rtStart), m_pCurrentPage->pageTimeOut); + } else { + TRACE_DVB(_T("DVB - Page update %x\n"), pPage->pageState); + + if (m_pCurrentPage && !m_pCurrentPage->regionCount) { + m_pCurrentPage = pPage; + m_pCurrentPage->rtStart = m_rtStart; + m_pCurrentPage->rtStop = m_pCurrentPage->rtStart + m_pCurrentPage->pageTimeOut * 1000000; + + TRACE_DVB(_T("DVB - Page started[update] %s, TimeOut = %d\n"), ReftimeToCString(m_rtStart), m_pCurrentPage->pageTimeOut); + } + } + } + break; + case REGION: + ParseRegion(gb, wSegLength); + TRACE_DVB(_T("DVB - Region\n")); + break; + case CLUT: + ParseClut(gb, wSegLength); + TRACE_DVB(_T("DVB - Clut\n")); + break; + case OBJECT: + ParseObject(gb, wSegLength); + TRACE_DVB(_T("DVB - Object\n")); + break; + case DISPLAY: + ParseDisplay(gb, wSegLength); + TRACE_DVB(_T("DVB - Display\n")); + break; + case END_OF_DISPLAY: + if (m_pCurrentPage != NULL) { + if (m_pCurrentPage->rtStart != m_rtStart) { + m_pCurrentPage->rtStop = max(m_pCurrentPage->rtStop, m_rtStart); + TRACE_DVB(_T("DVB - End display %s - %s\n"), ReftimeToCString(m_pCurrentPage->rtStart), ReftimeToCString(m_pCurrentPage->rtStop)); + m_Pages.AddTail(m_pCurrentPage.Detach()); + } else { + TRACE_DVB(_T("DVB - Ignored End display %s (%s - %s)\n"), ReftimeToCString(m_rtStart), ReftimeToCString(m_pCurrentPage->rtStart), ReftimeToCString(m_pCurrentPage->rtStop)); + } + } else { + TRACE_DVB(_T("DVB - Ignored End display\n")); + } + break; + default: + break; + } + nLastPos = gb.GetPos(); + } + } + m_nBufferReadPos += nLastPos; + } + + return hr; +} + +void CDVBSub::Render(SubPicDesc& spd, REFERENCE_TIME rt, RECT& bbox) +{ + DVB_PAGE* pPage = FindPage(rt); + + if (pPage != NULL) { + pPage->rendered = true; + TRACE_DVB(_T("DVB - Renderer - %s - %s\n"), ReftimeToCString(pPage->rtStart), ReftimeToCString(pPage->rtStop)); + for (int i = 0; i < pPage->regionCount; i++) { + DVB_REGION* pRegion = &pPage->regions[i]; + + DVB_CLUT* pCLUT = FindClut(pPage, pRegion->CLUT_id); + if (pCLUT) { + for (int j = 0; j < pRegion->objectCount; j++) { + CompositionObject* pObject = FindObject(pPage, pRegion->objects[j].object_id); + if (pObject) { + short nX, nY; + nX = pRegion->horizAddr + pRegion->objects[j].object_horizontal_position; + nY = pRegion->vertAddr + pRegion->objects[j].object_vertical_position; + pObject->m_width = pRegion->width; + pObject->m_height = pRegion->height; + pObject->SetPalette(pCLUT->size, pCLUT->palette, m_Display.width > 720); + pObject->InitColor(spd); + pObject->RenderDvb(spd, nX, nY); + TRACE_DVB(_T(" --> %d/%d - %d/%d\n"), i + 1, pPage->regionCount, j + 1, pRegion->objectCount); + } + } + } + } + + bbox.left = 0; + bbox.top = 0; + bbox.right = m_Display.width; + bbox.bottom = m_Display.height; + } +} + +HRESULT CDVBSub::GetTextureSize(POSITION pos, SIZE& MaxTextureSize, SIZE& VideoSize, POINT& VideoTopLeft) +{ + MaxTextureSize.cx = VideoSize.cx = m_Display.width; + MaxTextureSize.cy = VideoSize.cy = m_Display.height; + + VideoTopLeft.x = 0; + VideoTopLeft.y = 0; + + return S_OK; +} + +POSITION CDVBSub::GetStartPosition(REFERENCE_TIME rt, double fps) +{ + DVB_PAGE* pPage; + + // Cleanup old PG + while (m_Pages.GetCount() > 0) { + pPage = m_Pages.GetHead(); + if (pPage->rtStop < rt) { + if (!pPage->rendered) { + TRACE_DVB(_T("DVB - remove unrendered object, %s - %s\n"), ReftimeToCString(pPage->rtStart), ReftimeToCString(pPage->rtStop)); + } + m_Pages.RemoveHead(); + delete pPage; + } else { + break; + } + } + + POSITION pos = m_Pages.GetHeadPosition(); + + while (pos) { + DVB_PAGE* pPage = m_Pages.GetAt (pos); + + if (rt >= pPage->rtStart && rt < pPage->rtStop) { + break; + } + else if( rt < pPage->rtStart ) + { + pos = NULL; + break; + } + + m_Pages.GetNext(pos); + } + return pos; +} + +POSITION CDVBSub::GetNext(POSITION pos) +{ + m_Pages.GetNext(pos); + return pos; +} + +REFERENCE_TIME CDVBSub::GetStart(POSITION nPos) +{ + DVB_PAGE* pPage = m_Pages.GetAt(nPos); + return pPage != NULL ? pPage->rtStart : INVALID_TIME; +} + +REFERENCE_TIME CDVBSub::GetStop(POSITION nPos) +{ + DVB_PAGE* pPage = m_Pages.GetAt(nPos); + return pPage != NULL ? pPage->rtStop : INVALID_TIME; +} + +void CDVBSub::Reset() +{ + m_nBufferReadPos = 0; + m_nBufferWritePos = 0; + m_pCurrentPage.Free(); + + DVB_PAGE* pPage; + while (m_Pages.GetCount() > 0) { + pPage = m_Pages.RemoveHead(); + delete pPage; + } +} + +HRESULT CDVBSub::ParsePage(CGolombBuffer& gb, WORD wSegLength, CAutoPtr& pPage) +{ + int nEnd = gb.GetPos() + wSegLength; + int nPos = 0; + + pPage.Attach(DNew DVB_PAGE()); + pPage->pageTimeOut = gb.ReadByte(); + pPage->pageVersionNumber = (BYTE)gb.BitRead(4); + pPage->pageState = (BYTE)gb.BitRead(2); + pPage->regionCount = 0; + gb.BitRead(2); // Reserved + while (gb.GetPos() < nEnd) { + if (nPos < MAX_REGIONS) { + pPage->regions[nPos].id = gb.ReadByte(); + gb.ReadByte(); // Reserved + pPage->regions[nPos].horizAddr = gb.ReadShort(); + pPage->regions[nPos].vertAddr = gb.ReadShort(); + pPage->regionCount++; + } + nPos++; + } + + return S_OK; +} + +HRESULT CDVBSub::ParseDisplay(CGolombBuffer& gb, WORD wSegLength) +{ + m_Display.version_number = (BYTE)gb.BitRead(4); + m_Display.display_window_flag = (BYTE)gb.BitRead(1); + gb.BitRead(3); // reserved + m_Display.width = gb.ReadShort(); + m_Display.height = gb.ReadShort(); + if (m_Display.display_window_flag) { + m_Display.horizontal_position_minimun = gb.ReadShort(); + m_Display.horizontal_position_maximum = gb.ReadShort(); + m_Display.vertical_position_minimun = gb.ReadShort(); + m_Display.vertical_position_maximum = gb.ReadShort(); + } + + return S_OK; +} + +HRESULT CDVBSub::ParseRegion(CGolombBuffer& gb, WORD wSegLength) +{ + int nEnd = gb.GetPos() + wSegLength; + CDVBSub::DVB_REGION* pRegion; + CDVBSub::DVB_REGION DummyRegion; + + pRegion = FindRegion(m_pCurrentPage, gb.ReadByte()); + + if (pRegion == NULL) { + pRegion = &DummyRegion; + } + + if (pRegion != NULL) { + pRegion->version_number = (BYTE)gb.BitRead(4); + pRegion->fill_flag = (BYTE)gb.BitRead(1); + gb.BitRead(3); // Reserved + pRegion->width = gb.ReadShort(); + pRegion->height = gb.ReadShort(); + pRegion->level_of_compatibility = (BYTE)gb.BitRead(3); + pRegion->depth = (BYTE)gb.BitRead(3); + gb.BitRead(2); // Reserved + pRegion->CLUT_id = gb.ReadByte(); + pRegion->_8_bit_pixel_code = gb.ReadByte(); + pRegion->_4_bit_pixel_code = (BYTE)gb.BitRead(4); + pRegion->_2_bit_pixel_code = (BYTE)gb.BitRead(2); + gb.BitRead(2); // Reserved + + pRegion->objectCount = 0; + while (gb.GetPos() < nEnd) { + DVB_OBJECT* pObject = &pRegion->objects[pRegion->objectCount]; + pObject->object_id = gb.ReadShort(); + pObject->object_type = (BYTE)gb.BitRead(2); + pObject->object_provider_flag = (BYTE)gb.BitRead(2); + pObject->object_horizontal_position = (short)gb.BitRead(12); + gb.BitRead(4); // Reserved + pObject->object_vertical_position = (short)gb.BitRead(12); + if (pObject->object_type == 0x01 || pObject->object_type == 0x02) { + pObject->foreground_pixel_code = gb.ReadByte(); + pObject->background_pixel_code = gb.ReadByte(); + } + pRegion->objectCount++; + } + } else { + gb.SkipBytes(wSegLength - 1); + } + + return S_OK; +} + +HRESULT CDVBSub::ParseClut(CGolombBuffer& gb, WORD wSegLength) +{ + HRESULT hr = E_FAIL; + int nEnd = gb.GetPos() + wSegLength; + + if (m_pCurrentPage && wSegLength > 2) { + DVB_CLUT* pClut = DNew DVB_CLUT(); + if (pClut) { + pClut->id = gb.ReadByte(); + pClut->version_number = (BYTE)gb.BitRead(4); + gb.BitRead(4); // Reserved + + pClut->size = 0; + while (gb.GetPos() < nEnd) { + BYTE entry_id = gb.ReadByte(); + BYTE _2_bit = (BYTE)gb.BitRead(1); + BYTE _4_bit = (BYTE)gb.BitRead(1); + BYTE _8_bit = (BYTE)gb.BitRead(1); + UNREFERENCED_PARAMETER(_2_bit); + UNREFERENCED_PARAMETER(_4_bit); + UNREFERENCED_PARAMETER(_8_bit); + gb.BitRead(4); // Reserved + + pClut->palette[entry_id].entry_id = entry_id; + if (gb.BitRead(1)) { + pClut->palette[entry_id].Y = gb.ReadByte(); + pClut->palette[entry_id].Cr = gb.ReadByte(); + pClut->palette[entry_id].Cb = gb.ReadByte(); + pClut->palette[entry_id].T = 0xff - gb.ReadByte(); + } else { + pClut->palette[entry_id].Y = (BYTE)gb.BitRead(6) << 2; + pClut->palette[entry_id].Cr = (BYTE)gb.BitRead(4) << 4; + pClut->palette[entry_id].Cb = (BYTE)gb.BitRead(4) << 4; + pClut->palette[entry_id].T = 0xff - ((BYTE)gb.BitRead(2) << 6); + } + if (!pClut->palette[entry_id].Y) { + pClut->palette[entry_id].Cr = 0; + pClut->palette[entry_id].Cb = 0; + pClut->palette[entry_id].T = 0; + } + + if (pClut->size <= entry_id) { + pClut->size = entry_id + 1; + } + } + + m_pCurrentPage->CLUTs.AddTail(pClut); + hr = S_OK; + } else { + hr = E_OUTOFMEMORY; + } + } + + return hr; +} + +HRESULT CDVBSub::ParseObject(CGolombBuffer& gb, WORD wSegLength) +{ + HRESULT hr = E_FAIL; + + if (m_pCurrentPage && wSegLength > 2) { + CompositionObject* pObject = DNew CompositionObject(); + BYTE object_coding_method; + + pObject->m_object_id_ref = gb.ReadShort(); + pObject->m_version_number = (BYTE)gb.BitRead(4); + + object_coding_method = (BYTE)gb.BitRead(2); // object_coding_method + gb.BitRead(1); // non_modifying_colour_flag + gb.BitRead(1); // reserved + + if (object_coding_method == 0x00) { + pObject->SetRLEData(gb.GetBufferPos(), wSegLength - 3, wSegLength - 3); + gb.SkipBytes(wSegLength - 3); + m_pCurrentPage->objects.AddTail(pObject); + hr = S_OK; + } else { + delete pObject; + hr = E_NOTIMPL; + } + } + + return hr; +} + +HRESULT CDVBSub::UpdateTimeStamp(REFERENCE_TIME rtStop) +{ + HRESULT hr = E_FAIL; + POSITION pos = m_Pages.GetHeadPosition(); + while (pos) { + DVB_PAGE* pPage = m_Pages.GetNext(pos); + if (pPage->rtStop > rtStop) { + pPage->rtStop = rtStop; + hr = S_OK; + } + } + + return hr; +} diff --git a/src/subtitles/DVBSub.h b/src/subtitles/DVBSub.h dissimilarity index 87% index 3548c2a..cfb8e0a 100644 --- a/src/subtitles/DVBSub.h +++ b/src/subtitles/DVBSub.h @@ -1,214 +1,216 @@ -/* - * $Id: DVBSub.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" - -#define MAX_REGIONS 10 -#define MAX_OBJECTS 10 // Max number of objects per region - -class CGolombBuffer; - -class CDVBSub : public CBaseSub -{ -public: - CDVBSub(void); - ~CDVBSub(void); - - virtual HRESULT ParseSample (IMediaSample* pSample); - virtual void Render(SubPicDesc& spd, REFERENCE_TIME rt, RECT& bbox); - virtual HRESULT GetTextureSize (POSITION pos, SIZE& MaxTextureSize, SIZE& VideoSize, POINT& VideoTopLeft); - virtual POSITION GetStartPosition(REFERENCE_TIME rt, double fps); - virtual POSITION GetNext(POSITION pos); - virtual REFERENCE_TIME GetStart(POSITION nPos); - virtual REFERENCE_TIME GetStop(POSITION nPos); - virtual void Reset(); - - // EN 300-743, table 2 - enum DVB_SEGMENT_TYPE { - NO_SEGMENT = 0xFFFF, - PAGE = 0x10, - REGION = 0x11, - CLUT = 0x12, - OBJECT = 0x13, - DISPLAY = 0x14, - END_OF_DISPLAY = 0x80 - }; - - // EN 300-743, table 6 - enum DVB_OBJECT_TYPE { - OT_BASIC_BITMAP = 0x00, - OT_BASIC_CHAR = 0x01, - OT_COMPOSITE_STRING = 0x02 - }; - - enum DVB_PAGE_STATE { - DPS_NORMAL = 0x00, - DPS_ACQUISITION = 0x01, - DPS_MODE = 0x02, - DPS_RESERVED = 0x03 - }; - - struct DVB_CLUT { - BYTE id; - BYTE version_number; - BYTE Size; - - HDMV_PALETTE Palette[256]; - - DVB_CLUT() { - memset (Palette, 0, sizeof(Palette)); - } - }; - - struct DVB_DISPLAY { - BYTE version_number; - BYTE display_window_flag; - SHORT width; - SHORT height; - SHORT horizontal_position_minimun; - SHORT horizontal_position_maximum; - SHORT vertical_position_minimun; - SHORT vertical_position_maximum; - - DVB_DISPLAY() { - // Default value (�5.1.3) - version_number = 0; - width = 720; - height = 576; - } - }; - - struct DVB_OBJECT { - SHORT object_id; - BYTE object_type; - BYTE object_provider_flag; - SHORT object_horizontal_position; - SHORT object_vertical_position; - BYTE foreground_pixel_code; - BYTE background_pixel_code; - - DVB_OBJECT() { - object_id = 0xFF; - object_type = 0; - object_provider_flag = 0; - object_horizontal_position = 0; - object_vertical_position = 0; - foreground_pixel_code = 0; - background_pixel_code = 0; - } - }; - - struct DVB_REGION { - BYTE Id; - WORD HorizAddr; - WORD VertAddr; - BYTE version_number; - BYTE fill_flag; - WORD width; - WORD height; - BYTE level_of_compatibility; - BYTE depth; - BYTE CLUT_id; - BYTE _8_bit_pixel_code; - BYTE _4_bit_pixel_code; - BYTE _2_bit_pixel_code; - int ObjectCount; - DVB_OBJECT Objects[MAX_OBJECTS]; - - DVB_CLUT Clut; - - DVB_REGION() { - Id = 0; - HorizAddr = 0; - VertAddr = 0; - version_number = 0; - fill_flag = 0; - width = 0; - height = 0; - level_of_compatibility = 0; - depth = 0; - CLUT_id = 0; - _8_bit_pixel_code = 0; - _4_bit_pixel_code = 0; - _2_bit_pixel_code = 0; - } - }; - - class DVB_PAGE - { - public : - REFERENCE_TIME rtStart; - REFERENCE_TIME rtStop; - BYTE PageTimeOut; - BYTE PageVersionNumber; - BYTE PageState; - int RegionCount; - DVB_REGION Regions[MAX_REGIONS]; - CAtlList Objects; - bool Rendered; - - DVB_PAGE() { - PageTimeOut = 0; - PageVersionNumber = 0; - PageState = 0; - RegionCount = 0; - Rendered = false; - } - - ~DVB_PAGE() { - CompositionObject* pPage; - while (Objects.GetCount() > 0) { - pPage = Objects.RemoveHead(); - delete pPage; - } - } - }; - -private: - static const REFERENCE_TIME INVALID_TIME = _I64_MIN; - - int m_nBufferSize; - int m_nBufferReadPos; - int m_nBufferWritePos; - BYTE* m_pBuffer; - CAtlList m_Pages; - CAutoPtr m_pCurrentPage; - DVB_DISPLAY m_Display; - REFERENCE_TIME m_rtStart; - REFERENCE_TIME m_rtStop; - - HRESULT AddToBuffer(BYTE* pData, int nSize); - DVB_PAGE* FindPage(REFERENCE_TIME rt); - DVB_REGION* FindRegion(DVB_PAGE* pPage, BYTE bRegionId); - DVB_CLUT* FindClut(DVB_PAGE* pPage, BYTE bClutId); - CompositionObject* FindObject(DVB_PAGE* pPage, SHORT sObjectId); - - HRESULT ParsePage(CGolombBuffer& gb, WORD wSegLength, CAutoPtr& pPage); - HRESULT ParseDisplay(CGolombBuffer& gb, WORD wSegLength); - HRESULT ParseRegion(CGolombBuffer& gb, WORD wSegLength); - HRESULT ParseClut(CGolombBuffer& gb, WORD wSegLength); - HRESULT ParseObject(CGolombBuffer& gb, WORD wSegLength); - -}; +/* + * (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" + +#define MAX_REGIONS 10 +#define MAX_OBJECTS 10 // Max number of objects per region + +class CGolombBuffer; + +class CDVBSub : public CBaseSub +{ +public: + CDVBSub(void); + ~CDVBSub(void); + + virtual HRESULT ParseSample(IMediaSample* pSample); + virtual void Render(SubPicDesc& spd, REFERENCE_TIME rt, RECT& bbox); + virtual HRESULT GetTextureSize(POSITION pos, SIZE& MaxTextureSize, SIZE& VideoSize, POINT& VideoTopLeft); + virtual POSITION GetStartPosition(REFERENCE_TIME rt, double fps); + virtual POSITION GetNext(POSITION pos); + virtual REFERENCE_TIME GetStart(POSITION nPos); + virtual REFERENCE_TIME GetStop(POSITION nPos); + virtual void Reset(); + + // EN 300-743, table 2 + enum DVB_SEGMENT_TYPE { + NO_SEGMENT = 0xFFFF, + PAGE = 0x10, + REGION = 0x11, + CLUT = 0x12, + OBJECT = 0x13, + DISPLAY = 0x14, + END_OF_DISPLAY = 0x80 + }; + + // EN 300-743, table 6 + enum DVB_OBJECT_TYPE { + OT_BASIC_BITMAP = 0x00, + OT_BASIC_CHAR = 0x01, + OT_COMPOSITE_STRING = 0x02 + }; + + enum DVB_PAGE_STATE { + DPS_NORMAL = 0x00, + DPS_ACQUISITION = 0x01, + DPS_MODE = 0x02, + DPS_RESERVED = 0x03 + }; + + struct DVB_CLUT { + BYTE id; + BYTE version_number; + BYTE size; + + HDMV_PALETTE palette[256]; + + DVB_CLUT() { memset(palette, 0, sizeof(palette)); } + }; + + struct DVB_DISPLAY { + BYTE version_number; + BYTE display_window_flag; + short width; + short height; + short horizontal_position_minimun; + short horizontal_position_maximum; + short vertical_position_minimun; + short vertical_position_maximum; + + DVB_DISPLAY() { + // Default value (§5.1.3) + version_number = 0; + width = 720; + height = 576; + } + }; + + struct DVB_OBJECT { + short object_id; + BYTE object_type; + BYTE object_provider_flag; + short object_horizontal_position; + short object_vertical_position; + BYTE foreground_pixel_code; + BYTE background_pixel_code; + + DVB_OBJECT() { + object_id = 0xFF; + object_type = 0; + object_provider_flag = 0; + object_horizontal_position = 0; + object_vertical_position = 0; + foreground_pixel_code = 0; + background_pixel_code = 0; + } + }; + + struct DVB_REGION { + BYTE id; + WORD horizAddr; + WORD vertAddr; + BYTE version_number; + BYTE fill_flag; + WORD width; + WORD height; + BYTE level_of_compatibility; + BYTE depth; + BYTE CLUT_id; + BYTE _8_bit_pixel_code; + BYTE _4_bit_pixel_code; + BYTE _2_bit_pixel_code; + int objectCount; + DVB_OBJECT objects[MAX_OBJECTS]; + + DVB_REGION() { + id = 0; + horizAddr = 0; + vertAddr = 0; + version_number = 0; + fill_flag = 0; + width = 0; + height = 0; + level_of_compatibility = 0; + depth = 0; + CLUT_id = 0; + _8_bit_pixel_code = 0; + _4_bit_pixel_code = 0; + _2_bit_pixel_code = 0; + } + }; + + class DVB_PAGE + { + public: + REFERENCE_TIME rtStart; + REFERENCE_TIME rtStop; + BYTE pageTimeOut; + BYTE pageVersionNumber; + BYTE pageState; + int regionCount; + DVB_REGION regions[MAX_REGIONS]; + CAtlList objects; + CAtlList CLUTs; + bool rendered; + + DVB_PAGE() { + pageTimeOut = 0; + pageVersionNumber = 0; + pageState = 0; + regionCount = 0; + rendered = false; + } + + ~DVB_PAGE() { + CompositionObject* pObject; + while (objects.GetCount() > 0) { + pObject = objects.RemoveHead(); + delete pObject; + } + + DVB_CLUT* pCLUT; + while (CLUTs.GetCount() > 0) { + pCLUT = CLUTs.RemoveHead(); + delete pCLUT; + } + } + }; + +private: + static const REFERENCE_TIME INVALID_TIME = _I64_MIN; + + int m_nBufferSize; + int m_nBufferReadPos; + int m_nBufferWritePos; + BYTE* m_pBuffer; + CAtlList m_Pages; + CAutoPtr m_pCurrentPage; + DVB_DISPLAY m_Display; + REFERENCE_TIME m_rtStart; + REFERENCE_TIME m_rtStop; + + HRESULT AddToBuffer(BYTE* pData, int nSize); + DVB_PAGE* FindPage(REFERENCE_TIME rt); + DVB_REGION* FindRegion(DVB_PAGE* pPage, BYTE bRegionId); + DVB_CLUT* FindClut(DVB_PAGE* pPage, BYTE bClutId); + CompositionObject* FindObject(DVB_PAGE* pPage, short sObjectId); + + HRESULT ParsePage(CGolombBuffer& gb, WORD wSegLength, CAutoPtr& pPage); + HRESULT ParseDisplay(CGolombBuffer& gb, WORD wSegLength); + HRESULT ParseRegion(CGolombBuffer& gb, WORD wSegLength); + HRESULT ParseClut(CGolombBuffer& gb, WORD wSegLength); + HRESULT ParseObject(CGolombBuffer& gb, WORD wSegLength); + + HRESULT UpdateTimeStamp(REFERENCE_TIME rtStop); + +}; -- 2.11.4.GIT