Example #1
0
HRESULT CDVBSub::ParseClut(CGolombBuffer& gb, WORD wSegLength)
{
    HRESULT hr = E_POINTER;

    if (m_pCurrentPage) {
        size_t nExpectedSize = 2;
        size_t nEnd = gb.GetPos() + wSegLength;

        BYTE id = gb.ReadByte();
        POSITION posClut = FindClut(m_pCurrentPage, id);
        if (!posClut) {
            posClut = m_pCurrentPage->CLUTs.AddTail(CAutoPtr<DVB_CLUT>(DEBUG_NEW DVB_CLUT()));
        }
        const auto& pClut = m_pCurrentPage->CLUTs.GetAt(posClut);

        pClut->id = id;
        pClut->version_number = (BYTE)gb.BitRead(4);
        gb.BitRead(4);  // Reserved

        pClut->size = 0;
        while (gb.GetPos() < nEnd) {
            nExpectedSize += 2;
            pClut->palette[pClut->size].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

            if (gb.BitRead(1)) {
                nExpectedSize += 4;
                pClut->palette[pClut->size].Y  = gb.ReadByte();
                pClut->palette[pClut->size].Cr = gb.ReadByte();
                pClut->palette[pClut->size].Cb = gb.ReadByte();
                pClut->palette[pClut->size].T  = 0xff - gb.ReadByte();
            } else {
                nExpectedSize += 2;
                pClut->palette[pClut->size].Y  = (BYTE)gb.BitRead(6) << 2;
                pClut->palette[pClut->size].Cr = (BYTE)gb.BitRead(4) << 4;
                pClut->palette[pClut->size].Cb = (BYTE)gb.BitRead(4) << 4;
                pClut->palette[pClut->size].T  = 0xff - ((BYTE)gb.BitRead(2) << 6);
            }
            if (!pClut->palette[pClut->size].Y) {
                pClut->palette[pClut->size].Cr = 0;
                pClut->palette[pClut->size].Cb = 0;
                pClut->palette[pClut->size].T  = 0;
            }

            pClut->size++;
        }

        hr = (wSegLength == nExpectedSize) ? S_OK : E_UNEXPECTED;
    }

    return hr;
}
Example #2
0
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;
}
Example #3
0
HRESULT CDVBSub::ParseSample(IMediaSample* pSample)
{
    CheckPointer(pSample, E_POINTER);
    HRESULT hr;
    BYTE* pData = nullptr;
    int nSize;
    DVB_SEGMENT_TYPE nCurSegment;

    hr = pSample->GetPointer(&pData);
    if (FAILED(hr) || pData == nullptr) {
        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: {
                        if (m_pCurrentPage != nullptr) {
                            TRACE_DVB(_T("DVB - Force End display"));
                            EnqueuePage(m_rtStart);
                        }
                        UpdateTimeStamp(m_rtStart);

                        CAutoPtr<DVB_PAGE> pPage;
                        ParsePage(gb, wSegLength, pPage);

                        if (pPage->pageState == DPS_ACQUISITION || pPage->pageState == DPS_MODE_CHANGE) {
                            m_pCurrentPage = pPage;
                            m_pCurrentPage->rtStart = m_rtStart;
                            m_pCurrentPage->rtStop  = m_pCurrentPage->rtStart + m_pCurrentPage->pageTimeOut * 10000000;

                            TRACE_DVB(_T("DVB - Page started [pageState = %d] %s, TimeOut = %ds\n"), m_pCurrentPage->pageState, ReftimeToString(m_rtStart), m_pCurrentPage->pageTimeOut);
                        } else if (!m_Pages.IsEmpty()) {
                            m_pCurrentPage = pPage;
                            m_pCurrentPage->rtStart = m_rtStart;
                            m_pCurrentPage->rtStop  = m_pCurrentPage->rtStart + m_pCurrentPage->pageTimeOut * 10000000;

                            // Copy data from the previous page
                            DVB_PAGE* pPrevPage = m_Pages.GetTail();

                            memcpy(m_pCurrentPage->regions, pPrevPage->regions, sizeof(m_pCurrentPage->regions));

                            for (POSITION pos = pPrevPage->objects.GetHeadPosition(); pos;) {
                                m_pCurrentPage->objects.AddTail(pPrevPage->objects.GetNext(pos)->Copy());
                            }

                            for (POSITION pos = pPrevPage->CLUTs.GetHeadPosition(); pos;) {
                                m_pCurrentPage->CLUTs.AddTail(DEBUG_NEW DVB_CLUT(*pPrevPage->CLUTs.GetNext(pos)));
                            }

                            TRACE_DVB(_T("DVB - Page started [update] %s, TimeOut = %ds\n"), ReftimeToString(m_rtStart), m_pCurrentPage->pageTimeOut);
                        } else {
                            TRACE_DVB(_T("DVB - Page update ignored %s\n"), ReftimeToString(m_rtStart));
                        }
                    }
                    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 == nullptr) {
                            TRACE_DVB(_T("DVB - Ignored End display %s: no current page\n"), ReftimeToString(m_rtStart));
                        } else if (m_pCurrentPage->rtStart < m_rtStart) {
                            TRACE_DVB(_T("DVB - End display"));
                            EnqueuePage(m_rtStart);
                        } else {
                            TRACE_DVB(_T("DVB - Ignored End display %s: no information on page duration\n"), ReftimeToString(m_rtStart));
                        }
                        break;
                    default:
                        break;
                }
                nLastPos = gb.GetPos();
            }
        }
        m_nBufferReadPos += nLastPos;
    }

    return hr;
}