Exemplo n.º 1
0
HRESULT CDVBSub::ParsePage(CGolombBuffer& gb, WORD wSegLength, CAutoPtr<DVB_PAGE>& pPage)
{
	HRESULT		hr		= S_OK;
	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;
}
Exemplo n.º 2
0
HRESULT CDVBSub::ParseRegion(CGolombBuffer& gb, WORD wSegLength)
{
    HRESULT hr = E_POINTER;

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

        BYTE id = gb.ReadByte();
        POSITION posRegion = FindRegion(m_pCurrentPage, id);
        if (!posRegion) {
            posRegion = m_pCurrentPage->regions.AddTail(CAutoPtr<DVB_REGION>(DEBUG_NEW DVB_REGION()));
        }
        const auto& pRegion = m_pCurrentPage->regions.GetAt(posRegion);

        pRegion->id = id;
        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

        while (gb.GetPos() < nEnd) {
            nExpectedSize += 6;
            DVB_OBJECT object;
            object.object_id = gb.ReadShort();
            object.object_type = (BYTE)gb.BitRead(2);
            object.object_provider_flag = (BYTE)gb.BitRead(2);
            object.object_horizontal_position = (short)gb.BitRead(12);
            gb.BitRead(4);  // Reserved
            object.object_vertical_position = (short)gb.BitRead(12);
            if (object.object_type == 0x01 || object.object_type == 0x02) {
                nExpectedSize += 2;
                object.foreground_pixel_code = gb.ReadByte();
                object.background_pixel_code = gb.ReadByte();
            }
            pRegion->objects.AddTail(object);
        }

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

    return hr;
}
Exemplo n.º 3
0
HRESULT CDVBSub::ParseRegion(CGolombBuffer& gb, WORD wSegLength)
{
	HRESULT					hr		= S_OK;
	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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
HRESULT CDVBSub::ParseDisplay(CGolombBuffer& gb, WORD wSegLength)
{
    int nExpectedSize = 5;

    m_displayInfo.version_number = (BYTE)gb.BitRead(4);
    m_displayInfo.display_window_flag = (BYTE)gb.BitRead(1);
    gb.BitRead(3);  // reserved
    m_displayInfo.width = gb.ReadShort() + 1;
    m_displayInfo.height = gb.ReadShort() + 1;
    if (m_displayInfo.display_window_flag) {
        nExpectedSize += 8;
        m_displayInfo.horizontal_position_minimun = gb.ReadShort();
        m_displayInfo.horizontal_position_maximum = gb.ReadShort();
        m_displayInfo.vertical_position_minimun = gb.ReadShort();
        m_displayInfo.vertical_position_maximum = gb.ReadShort();
    }

    return (wSegLength == nExpectedSize) ? S_OK : E_UNEXPECTED;
}
Exemplo n.º 7
0
HRESULT CDVBSub::ParsePage(CGolombBuffer& gb, WORD wSegLength, CAutoPtr<DVB_PAGE>& pPage)
{
    size_t nExpectedSize = 2;
    size_t nEnd = gb.GetPos() + wSegLength;

    pPage = CAutoPtr<DVB_PAGE>(DEBUG_NEW DVB_PAGE());

    pPage->pageTimeOut = gb.ReadByte();
    pPage->pageVersionNumber = (BYTE)gb.BitRead(4);
    pPage->pageState = (BYTE)gb.BitRead(2);
    gb.BitRead(2);  // Reserved
    while (gb.GetPos() < nEnd) {
        nExpectedSize += 6;
        DVB_REGION_POS regionPos;
        regionPos.id = gb.ReadByte();
        gb.ReadByte();  // Reserved
        regionPos.horizAddr = gb.ReadShort();
        regionPos.vertAddr = gb.ReadShort();
        pPage->regionsPos.AddTail(regionPos);
    }

    return (wSegLength == nExpectedSize) ? S_OK : E_UNEXPECTED;
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
0
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 ("CHdmvSub:PALETTE            rtStart=%10I64d\n", rtStart);
							ParsePalette(&SegmentBuffer, m_nSegSize);
							break;
						case OBJECT :
							//TRACE_HDMVSUB ("CHdmvSub:OBJECT             %S\n", ReftimeToString(rtStart));
							ParseObject(&SegmentBuffer, m_nSegSize);
							break;
						case PRESENTATION_SEG :
							TRACE_HDMVSUB ("CHdmvSub:PRESENTATION_SEG   %S (size=%d)\n", ReftimeToString(rtStart), m_nSegSize);

							if (m_pCurrentObject) {
								m_pCurrentObject->m_rtStop = rtStart;
								m_pObjects.AddTail (m_pCurrentObject);
								TRACE_HDMVSUB ("CHdmvSub:HDMV : %S => %S\n", ReftimeToString (m_pCurrentObject->m_rtStart), ReftimeToString(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 ("CHdmvSub:WINDOW_DEF         %S\n", ReftimeToString(rtStart));
							break;
						case END_OF_DISPLAY :
							// TRACE_HDMVSUB ("CHdmvSub:END_OF_DISPLAY     %S\n", ReftimeToString(rtStart));
							break;
						default :
							TRACE_HDMVSUB ("CHdmvSub:UNKNOWN Seg %d     rtStart=0x%10dd\n", m_nCurSegment, rtStart);
					}

					m_nCurSegment = NO_SEGMENT;
				}
			}
		}
	}

	return hr;
}
Exemplo n.º 10
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);
        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<DVB_PAGE>	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", ReftimeToString(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", ReftimeToString(m_pCurrentPage->rtStart), ReftimeToString(m_pCurrentPage->rtStop));
                        m_Pages.AddTail (m_pCurrentPage.Detach());
                    }
                    break;
                default :
                    //					gb.SkipBytes(wSegLength);
                    break;
                }
                nLastPos = gb.GetPos();
            }
        }
        m_nBufferReadPos += nLastPos;
    }

    return hr;
}
Exemplo n.º 11
0
HRESULT CHdmvSub::ParseSample(BYTE* pData, int lSampleLen, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop)
{
	HRESULT hr = S_OK;

	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::ParseSample() : PALETTE\n"));
							ParsePalette(&SegmentBuffer, m_nSegSize);
							break;
						case OBJECT :
							TRACE_HDMVSUB(_T("CHdmvSub::ParseSample() : OBJECT\n"));
							ParseObject(&SegmentBuffer, m_nSegSize);
							break;
						case PRESENTATION_SEG :
							TRACE_HDMVSUB(_T("CHdmvSub::ParseSample() : PRESENTATION_SEG = [%10I64d], %s, size = %d\n"), rtStart, ReftimeToString(rtStart), m_nSegSize);
							ParsePresentationSegment(&SegmentBuffer, rtStart);
							break;
						case WINDOW_DEF :
							//TRACE_HDMVSUB(_T("CHdmvSub::ParseSample() : WINDOW_DEF = %10I64d, %S\n"), rtStart, ReftimeToString(rtStart));
							break;
						case END_OF_DISPLAY :
							//TRACE_HDMVSUB(_T("CHdmvSub::ParseSample() : END_OF_DISPLAY = %10I64d, %S\n"), rtStart, ReftimeToString(rtStart));
							break;
						default :
							TRACE_HDMVSUB(_T("CHdmvSub::ParseSample() : UNKNOWN Seg [%d] = [%10I64d], %s\n"), m_nCurSegment, rtStart, ReftimeToString(rtStart));
					}

					m_nCurSegment = NO_SEGMENT;
				}
			}
		}
	}

	return hr;
}
Exemplo n.º 12
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;
}