Пример #1
0
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"), ReftimeToString(pPage->rtStart), ReftimeToString(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->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;
    }
}
Пример #2
0
void CDVBSub::EndOfStream()
{
    // Enqueue the last page if necessary.
    TRACE_DVB(_T("DVB - EndOfStream"));
    if (m_pCurrentPage) {
        TRACE_DVB(_T(": Enqueue last page"));
        EnqueuePage(INVALID_TIME);
    } else {
        TRACE_DVB(_T(" ignored: no page to enqueue\n"));
    }
}
Пример #3
0
STDMETHODIMP CDVBSub::Render(SubPicDesc& spd, REFERENCE_TIME rt, double fps, RECT& bbox)
{
    CAutoLock cAutoLock(&m_csCritSec);

    rt -= m_rtCurrentSegmentStart; // Make sure the timing are relative to the current segment start
    RemoveOldPages(rt);

    if (POSITION posPage = FindPage(rt)) {
        const auto& pPage = m_pages.GetAt(posPage);
        bool BT709 = m_infoSourceTarget.sourceMatrix == BT_709 ? true : m_infoSourceTarget.sourceMatrix == NONE ? (m_displayInfo.width > 720) : false;

        pPage->rendered = true;
        TRACE_DVB(_T("DVB - Renderer - %s - %s\n"),
                  ReftimeToString(pPage->rtStart + m_rtCurrentSegmentStart), ReftimeToString(pPage->rtStop + m_rtCurrentSegmentStart));

        int nRegion = 1, nObject = 1;
        for (POSITION pos = pPage->regionsPos.GetHeadPosition(); pos; nRegion++) {
            DVB_REGION_POS regionPos = pPage->regionsPos.GetNext(pos);

            if (POSITION posRegion = FindRegion(pPage, regionPos.id)) {
                const auto& pRegion = pPage->regions.GetAt(posRegion);

                if (POSITION posCLUT = FindClut(pPage, pRegion->CLUT_id)) {
                    const auto& pCLUT = pPage->CLUTs.GetAt(posCLUT);

                    for (POSITION posO = pRegion->objects.GetHeadPosition(); posO; nObject++) {
                        DVB_OBJECT objectPos = pRegion->objects.GetNext(posO);

                        if (POSITION posObject = FindObject(pPage, objectPos.object_id)) {
                            const auto& pObject = pPage->objects.GetAt(posObject);

                            short nX = regionPos.horizAddr + objectPos.object_horizontal_position;
                            short nY = regionPos.vertAddr + objectPos.object_vertical_position;
                            pObject->m_width = pRegion->width;
                            pObject->m_height = pRegion->height;
                            pObject->SetPalette(pCLUT->size, pCLUT->palette, BT709,
                                                m_infoSourceTarget.sourceBlackLevel, m_infoSourceTarget.sourceWhiteLevel, m_infoSourceTarget.targetBlackLevel, m_infoSourceTarget.targetWhiteLevel);
                            pObject->RenderDvb(spd, nX, nY);

                            TRACE_DVB(_T(" --> %d/%d - %d/%d\n"), nRegion, pPage->regionsPos.GetCount(), nObject, pRegion->objects.GetCount());
                        }
                    }
                }
            }
        }

        bbox.left = 0;
        bbox.top = 0;
        bbox.right = m_displayInfo.width;
        bbox.bottom = m_displayInfo.height;
    }

    return S_OK;
}
Пример #4
0
void CDVBSub::EndOfStream()
{
    CAutoLock cAutoLock(&m_csCritSec);

    // Enqueue the last page if necessary.
    if (m_pCurrentPage) {
        TRACE_DVB(_T("DVB - EndOfStream: Enqueue last page\n"));
        EnqueuePage(INVALID_TIME);
    } else {
        TRACE_DVB(_T("DVB - EndOfStream ignored: no page to enqueue\n"));
    }
}
Пример #5
0
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 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;
}
Пример #6
0
HRESULT CDVBSub::EndOfStream()
{
	if (m_pCurrentPage != NULL) {
		TRACE_DVB (_T("DVB - EndOfStream() : %ws => %ws\n"), ReftimeToString(m_pCurrentPage->rtStart), ReftimeToString(m_pCurrentPage->rtStop));
		m_Pages.AddTail (m_pCurrentPage.Detach());
	}

	return S_OK;
}
Пример #7
0
HRESULT CDVBSub::EnqueuePage(REFERENCE_TIME rtStop)
{
    if (m_pCurrentPage->rtStart < rtStop && m_pCurrentPage->rtStop > rtStop) {
        m_pCurrentPage->rtStop = rtStop;
    }
    TRACE_DVB(_T(" %s (%s - %s)\n"), ReftimeToString(rtStop), ReftimeToString(m_pCurrentPage->rtStart), ReftimeToString(m_pCurrentPage->rtStop));
    m_Pages.AddTail(m_pCurrentPage.Detach());

    return S_OK;
}
Пример #8
0
void CDVBSub::RemoveOldPages(REFERENCE_TIME rt)
{
    // Cleanup the old pages. We keep a 2 min buffer to play nice with the queue.
    while (!m_pages.IsEmpty() && m_pages.GetHead()->rtStop + 120 * 10000000i64 < rt) {
        auto pPage = m_pages.RemoveHead();
        if (!pPage->rendered) {
            TRACE_DVB(_T("DVB - remove unrendered object, %s - %s\n"),
                      ReftimeToString(pPage->rtStart + m_rtCurrentSegmentStart), ReftimeToString(pPage->rtStop + m_rtCurrentSegmentStart));
        }
    }
}
Пример #9
0
HRESULT CDVBSub::EnqueuePage(REFERENCE_TIME rtStop)
{
    ASSERT(m_pCurrentPage != nullptr);
    if (m_pCurrentPage->rtStart < rtStop && m_pCurrentPage->rtStop > rtStop) {
        m_pCurrentPage->rtStop = rtStop;
    }
    TRACE_DVB(_T("DVB - Enqueue page %s (%s - %s)\n"), ReftimeToString(rtStop), ReftimeToString(m_pCurrentPage->rtStart), ReftimeToString(m_pCurrentPage->rtStop));
    m_pages.AddTail(m_pCurrentPage);

    return S_OK;
}
Пример #10
0
HRESULT CDVBSub::UpdateTimeStamp(REFERENCE_TIME rtStop)
{
    HRESULT hr = S_FALSE;
    POSITION pos = m_Pages.GetTailPosition();
    while (pos) {
        DVB_PAGE* pPage = m_Pages.GetPrev(pos);
        if (pPage->rtStop > rtStop) {
            TRACE_DVB(_T("DVB - Updated end of display %s - %s --> %s - %s\n"), ReftimeToString(pPage->rtStart), ReftimeToString(pPage->rtStop),
                                                                                ReftimeToString(pPage->rtStart), ReftimeToString(rtStop));
            pPage->rtStop = rtStop;
            hr = S_OK;
        } else {
            break;
        }
    }

    return hr;
}
Пример #11
0
void CDVBSub::CleanOld(REFERENCE_TIME rt)
{
	// Cleanup old PG
	DVB_PAGE* pPage_old;
	while (m_Pages.GetCount()>0) {
		pPage_old = m_Pages.GetHead();
		if (pPage_old->rtStop < rt) {
			if (!pPage_old->Rendered) {
				TRACE_DVB (_T("DVB - remove unrendered object, %ws => %ws, (rt = %ws)\n"),
							ReftimeToString(pPage_old->rtStart), ReftimeToString(pPage_old->rtStop),
							ReftimeToString(rt));
			}
			m_Pages.RemoveHead();
			delete pPage_old;
		} else {
			break;
		}
	}
}
Пример #12
0
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", ReftimeToString(pPage->rtStart), ReftimeToString(pPage->rtStop));
            }
            m_Pages.RemoveHead();
            delete pPage;
        } else {
            break;
        }
    }

    return m_Pages.GetHeadPosition();
}
Пример #13
0
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; i<pPage->RegionCount; i++) {
			CDVBSub::DVB_REGION* pRegion = &pPage->Regions[i];
			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;
					CDVBSub::DVB_CLUT* pClut = FindClut(pPage, pRegion->CLUT_id);
					if (pClut != NULL) {
						pObject->SetPalette(pClut->Size, pClut->Palette, m_Display.width > 720);
					}

					TRACE_DVB (_T("CDVBSub::Render() : size = %ld, %d:%d, ObjRes = %dx%d, SPDRes = %dx%d, %I64d = %ws, [%ws => %ws]\n"),
									pObject->GetRLEDataSize(),
									nX, nY,
									pObject->m_width, pObject->m_height, spd.w, spd.h,
									rt, ReftimeToString(rt),
									ReftimeToString(pPage->rtStart), ReftimeToString(pPage->rtStop));

					
					pObject->RenderDvb(spd, nX, nY);
				}
			}
		}

		bbox.left	= 0;
		bbox.top	= 0;
		bbox.right	= m_Display.width < spd.w ? m_Display.width : spd.w;
		ASSERT(spd.h >= 0);
		bbox.bottom	= m_Display.height < spd.h ? m_Display.height : spd.h;
	}
}
Пример #14
0
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", ReftimeToString(pPage->rtStart), ReftimeToString(pPage->rtStop));
            }

            //TRACE_HDMVSUB ("CHdmvSub:HDMV remove object %d  %S => %S (rt=%S)\n", pPage->GetRLEDataSize(),
            //			   ReftimeToString (pPage->rtStart), ReftimeToString(pPage->rtStop), ReftimeToString(rt));
            m_Pages.RemoveHead();
            delete pPage;
        } else {
            break;
        }
    }

    return m_Pages.GetHeadPosition();
}
Пример #15
0
HRESULT CDVBSub::ParseObject(CGolombBuffer& gb, WORD wSegLength)
{
    HRESULT hr = E_POINTER;

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

        short id = gb.ReadShort();
        POSITION posObject = FindObject(m_pCurrentPage, id);
        if (!posObject) {
            posObject = m_pCurrentPage->objects.AddTail(CAutoPtr<CompositionObject>(DEBUG_NEW CompositionObject()));
        }
        const auto& pObject = m_pCurrentPage->objects.GetAt(posObject);

        pObject->m_object_id_ref  = id;
        pObject->m_version_number = (BYTE)gb.BitRead(4);

        BYTE 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 - nExpectedSize, wSegLength - nExpectedSize);
            gb.SkipBytes(wSegLength - 3);

            hr = (wSegLength >= nExpectedSize) ? S_OK : E_UNEXPECTED;
        } else {
            TRACE_DVB(_T("DVB - Text subtitles are currently not supported\n"));
            m_pCurrentPage->objects.RemoveTail();
            hr = E_NOTIMPL;
        }
    }

    return hr;
}
Пример #16
0
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.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;
				}

				TRACE_DVB (_T("DVB - ParseSample, Segment = [%ws], PageId = [%d], SegLength/Buffer = [%d]/[%d]\n"), GetSegmentType(nCurSegment), wPageId, wSegLength, gb.RemainingSize());

				switch (nCurSegment) {
					case PAGE : {
						CAutoPtr<DVB_PAGE>	pPage;
						ParsePage(gb, wSegLength, pPage);

						if (pPage->PageState == DPS_ACQUISITION || pPage->PageState == DPS_MODE) {
							TRACE_DVB (_T("DVB - Page start\n"));

							if (m_pCurrentPage != NULL) {
								m_pCurrentPage->rtStop = min(m_pCurrentPage->rtStop, m_rtStart);
								TRACE_DVB (_T("DVB - store Page : %ws => %ws\n"), ReftimeToString(m_pCurrentPage->rtStart), ReftimeToString(m_pCurrentPage->rtStop));
								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 * UNITS; // TODO - need to limit the duration of the segment

							TRACE_DVB (_T("DVB - Page started : %ws, TimeOut = %d\n"), ReftimeToString(m_pCurrentPage->rtStart), m_pCurrentPage->PageTimeOut);
						} else if (pPage->PageState == DPS_NORMAL) {
							TRACE_DVB (_T("DVB - Page update\n"));

							if (m_pCurrentPage && !m_pCurrentPage->RegionCount && pPage->RegionCount) {
								m_pCurrentPage = pPage;
								m_pCurrentPage->rtStart	= m_rtStart;
								m_pCurrentPage->rtStop	= m_pCurrentPage->rtStart + m_pCurrentPage->PageTimeOut * UNITS; // TODO - need to limit the duration of the segment

								TRACE_DVB (_T("DVB - Page started[update] : %ws, TimeOut = %d\n"), ReftimeToString(m_pCurrentPage->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 && (m_pCurrentPage->rtStart != m_rtStart)) {
							m_pCurrentPage->rtStop = max(m_pCurrentPage->rtStop, m_rtStart);
							TRACE_DVB (_T("DVB - End display : %ws => %ws\n"), ReftimeToString(m_pCurrentPage->rtStart), ReftimeToString(m_pCurrentPage->rtStop));
							m_Pages.AddTail (m_pCurrentPage.Detach());
						}
						*/
						TRACE_DVB (_T("DVB - End display\n"));
						break;
					default :
						TRACE_DVB (_T("DVB - unknown Segment\n"));
						break;
				}
				nLastPos = gb.GetPos();
			}
		}
		m_nBufferReadPos += nLastPos;
	}

	return hr;
}
Пример #17
0
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);
    }

    //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) {
                TRACE_DVB("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<DVB_PAGE>  pPage;
                    ParsePage(gb, wSegLength, pPage);

                    if (pPage->PageState == DPS_ACQUISITION) {
                        if (m_pCurrentPage != NULL) {
                            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("DVB - Page started %S, TimeOut = %d\n", ReftimeToString(m_rtStart), m_pCurrentPage->PageTimeOut);
                    } else {
                        TRACE_DVB("DVB - Page update\n");

                        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("DVB - Page started[update] %S, TimeOut = %d\n", ReftimeToString(m_rtStart), m_pCurrentPage->PageTimeOut);
                        }
                    }
                }
                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);
                    TRACE_DVB("DVB - Display\n");
                    break;
                case END_OF_DISPLAY:
                    if (m_pCurrentPage != NULL && (m_pCurrentPage->rtStart != m_rtStart)) {
                        m_pCurrentPage->rtStop = max(m_pCurrentPage->rtStop, m_rtStart);
                        TRACE_DVB("DVB - End display %S - %S\n", ReftimeToString(m_pCurrentPage->rtStart), ReftimeToString(m_pCurrentPage->rtStop));
                        m_Pages.AddTail(m_pCurrentPage.Detach());
                    }
                    break;
                default:
                    break;
                }
                nLastPos = gb.GetPos();
            }
        }
        m_nBufferReadPos += nLastPos;
    }

    return hr;
}
Пример #18
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;
}