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; }
void CHdmvSub::ParsePresentationSegment(CGolombBuffer* pGBuffer, REFERENCE_TIME rtTime) { COMPOSITION_DESCRIPTOR CompositionDescriptor; BYTE nObjectNumber; bool palette_update_flag; BYTE palette_id_ref; ParseVideoDescriptor(pGBuffer, &m_VideoDescriptor); ParseCompositionDescriptor(pGBuffer, &CompositionDescriptor); palette_update_flag = !!(pGBuffer->ReadByte() & 0x80); UNREFERENCED_PARAMETER(palette_update_flag); palette_id_ref = pGBuffer->ReadByte(); nObjectNumber = pGBuffer->ReadByte(); TRACE_HDMVSUB(_T("CHdmvSub::ParsePresentationSegment() : Size = %d, nObjectNumber = %d, palette_id_ref = %d, compositionNumber = %d\n"), pGBuffer->GetSize(), nObjectNumber, palette_id_ref, CompositionDescriptor.nNumber); if (m_pCurrentWindow && m_pCurrentWindow->m_nObjectNumber && m_pCurrentWindow->m_compositionNumber != -1) { for (int i = 0; i < m_pCurrentWindow->m_nObjectNumber; i++) { if (m_pCurrentWindow->Objects[i]) { CompositionObject* pObject = m_pCurrentWindow->Objects[i]; CompositionObject& pObjectData = m_ParsedObjects[pObject->m_object_id_ref]; if (pObjectData.m_width) { pObject->m_rtStop = rtTime; pObject->m_width = pObjectData.m_width; pObject->m_height = pObjectData.m_height; pObject->SetRLEData(pObjectData.GetRLEData(), pObjectData.GetRLEDataSize(), pObjectData.GetRLEDataSize()); if (!pObject->HavePalette() && m_CLUT[palette_id_ref].Palette) { pObject->SetPalette(m_CLUT[palette_id_ref].pSize, m_CLUT[palette_id_ref].Palette, m_VideoDescriptor.nVideoWidth > 720); } TRACE_HDMVSUB(_T(" store Segment : m_object_id_ref = %d, m_window_id_ref = %d, compositionNumber = %d, [%10I64d -> %10I64d], [%s -> %s]\n"), m_pCurrentWindow->Objects[i]->m_object_id_ref, m_pCurrentWindow->Objects[i]->m_window_id_ref, m_pCurrentWindow->Objects[i]->m_compositionNumber, m_pCurrentWindow->Objects[i]->m_rtStart, m_pCurrentWindow->Objects[i]->m_rtStop, ReftimeToString(m_pCurrentWindow->Objects[i]->m_rtStart), ReftimeToString(m_pCurrentWindow->Objects[i]->m_rtStop)); m_pObjects.AddTail (m_pCurrentWindow->Objects[i]); } else { delete m_pCurrentWindow->Objects[i]; } } m_pCurrentWindow->Objects[i] = NULL; } } if (!m_pCurrentWindow) { m_pCurrentWindow = DNew HDMV_WindowDefinition(); } else { m_pCurrentWindow->Reset(); } if (nObjectNumber > 0) { m_pCurrentWindow->m_nObjectNumber = nObjectNumber; m_pCurrentWindow->m_palette_id_ref = (SHORT)palette_id_ref; m_pCurrentWindow->m_compositionNumber = CompositionDescriptor.nNumber; for (int i = 0; i < nObjectNumber; i++) { m_pCurrentWindow->Objects[i] = DNew CompositionObject(); m_pCurrentWindow->Objects[i]->m_rtStart = rtTime; m_pCurrentWindow->Objects[i]->m_rtStop = _I64_MAX; m_pCurrentWindow->Objects[i]->m_compositionNumber = CompositionDescriptor.nNumber; ParseCompositionObject(pGBuffer, m_pCurrentWindow->Objects[i]); } } }
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; }
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; }
void CHdmvSub::Render(SubPicDesc& spd, REFERENCE_TIME rt, RECT& bbox) { bbox.left = LONG_MAX; bbox.top = LONG_MAX; bbox.right = 0; bbox.bottom = 0; POSITION pos = m_pObjects.GetHeadPosition(); while (pos) { CompositionObject* pObject = m_pObjects.GetAt (pos); if (pObject && rt >= pObject->m_rtStart && rt < pObject->m_rtStop) { if (pObject->GetRLEDataSize() && pObject->m_width > 0 && pObject->m_height > 0 && m_VideoDescriptor.nVideoWidth >= (pObject->m_horizontal_position + pObject->m_width) && m_VideoDescriptor.nVideoHeight >= (pObject->m_vertical_position + pObject->m_height)) { if (g_bForcedSubtitle && !pObject->m_forced_on_flag) { TRACE_HDMVSUB(_T("CHdmvSub::Render() : skip non forced subtitle - forced = %d, %I64d = %s"), pObject->m_forced_on_flag, rt, ReftimeToString(rt)); return; } if (!pObject->HavePalette() && m_DefaultCLUT.Palette) { pObject->SetPalette(m_DefaultCLUT.pSize, m_DefaultCLUT.Palette, m_VideoDescriptor.nVideoWidth > 720); } if (!pObject->HavePalette()) { TRACE_HDMVSUB(_T("CHdmvSub::Render() : The palette is missing - cancel rendering\n")); return; } bbox.left = min(pObject->m_horizontal_position, bbox.left); bbox.top = min(pObject->m_vertical_position, bbox.top); bbox.right = max(pObject->m_horizontal_position + pObject->m_width, bbox.right); bbox.bottom = max(pObject->m_vertical_position + pObject->m_height, bbox.bottom); bbox.left = bbox.left > 0 ? bbox.left : 0; bbox.top = bbox.top > 0 ? bbox.top : 0; if (m_VideoDescriptor.nVideoWidth > spd.w) { bbox.left = MulDiv(bbox.left, spd.w, m_VideoDescriptor.nVideoWidth); bbox.right = MulDiv(bbox.right, spd.w, m_VideoDescriptor.nVideoWidth); } if (m_VideoDescriptor.nVideoHeight > spd.h) { bbox.top = MulDiv(bbox.top, spd.h, m_VideoDescriptor.nVideoHeight); bbox.bottom = MulDiv(bbox.bottom, spd.h, m_VideoDescriptor.nVideoHeight); } TRACE_HDMVSUB(_T("CHdmvSub::Render() : size = %ld, ObjRes = %dx%d, SPDRes = %dx%d, %I64d = %s\n"), pObject->GetRLEDataSize(), pObject->m_width, pObject->m_height, spd.w, spd.h, rt, ReftimeToString(rt)); InitSpd(spd, m_VideoDescriptor.nVideoWidth, m_VideoDescriptor.nVideoHeight); pObject->RenderHdmv(spd, m_bResizedRender ? &m_spd : NULL); } } m_pObjects.GetNext(pos); } FinalizeRender(spd); }
HRESULT CMpegSplitterFile::SearchStreams(__int64 start, __int64 stop, IAsyncReader* pAsyncReader, BOOL CalcDuration) { Seek(start); stop = min(stop, GetLength()); while (GetPos() < stop) { BYTE b; if (m_type == mpeg_ps || m_type == mpeg_es) { if (!NextMpegStartCode(b)) { continue; } if (b == 0xba) { // program stream header pshdr h; if (!Read(h)) { continue; } m_rate = int(h.bitrate / 8); } else if (b == 0xbb) { // program stream system header pssyshdr h; if (!Read(h)) { continue; } } else if ((b >= 0xbd && b < 0xf0) || (b == 0xfd)) { // pes packet peshdr h; if (!Read(h, b) || !h.len) { continue; } if (h.type == mpeg2 && h.scrambling) { ASSERT(0); return E_FAIL; } if (h.fpts) { if (m_rtMin == _I64_MAX) { m_rtMin = h.pts; m_posMin = GetPos(); TRACE(_T("m_rtMin(SearchStreams)=%s\n"), ReftimeToString(m_rtMin)); } if (m_rtMin < h.pts && m_rtMax < h.pts) { m_rtMax = h.pts; m_posMax = GetPos(); TRACE(_T("m_rtMax(SearchStreams)=%s\n"), ReftimeToString(m_rtMax)); } } __int64 pos = GetPos(); AddStream(0, b, h.id_ext, h.len); if (h.len) { Seek(pos + h.len); } } } else if (m_type == mpeg_ts) { tshdr h; if (!Read(h)) { continue; } __int64 pos = GetPos(); //UpdatePrograms(h); if (h.payload && ISVALIDPID(h.pid)) { peshdr h2; if (h.payloadstart && NextMpegStartCode(b, 4) && Read(h2, b)) { // pes packet if (h2.type == mpeg2 && h2.scrambling) { ASSERT(0); return E_FAIL; } if (h2.fpts && CalcDuration && (m_AlternativeDuration || (GetMasterStream() && GetMasterStream()->GetHead() == h.pid))) { if (m_rtPrec != _I64_MIN && abs(h2.pts - m_rtPrec) >= PTS_MAX_BEFORE_WRAP / 2) { m_bPTSWrap = true; m_rtMax = h2.pts; m_posMax = GetPos(); TRACE(_T("PTS Wrap detected --> m_rtMax(SearchStreams)=%s\n"), ReftimeToString(m_rtMax)); } m_rtPrec = h2.pts; if ((m_rtMin == _I64_MAX) || (m_rtMin > h2.pts && m_rtMax > h2.pts && !m_bPTSWrap)) { m_rtMin = h2.pts; m_posMin = GetPos(); TRACE(_T("m_rtMin(SearchStreams)=%s, PID=%d\n"), ReftimeToString(m_rtMin), h.pid); } if (m_rtMax < h2.pts && (m_rtMin < h2.pts || m_bPTSWrap)) { m_rtMax = h2.pts; m_posMax = GetPos(); TRACE(_T("m_rtMax(SearchStreams)=%s, PID=%d\n"), ReftimeToString(m_rtMax), h.pid); // Ugly code : to support BRD H264 seamless playback, CMultiFiles need to update m_rtPTSOffset variable // each time a new part is open... // use this code only if Blu-ray is detected if (m_ClipInfo.IsHdmv()) { for (size_t i = 0; i < m_ClipInfo.GetStreamNumber(); i++) { CHdmvClipInfo::Stream* stream = m_ClipInfo.GetStreamByIndex(i); if (stream->m_Type == VIDEO_STREAM_H264 && m_rtMin == 116506666) { CComQIPtr<ISyncReader> pReader = pAsyncReader; if (pReader) { pReader->SetPTSOffset(&m_rtPTSOffset); } //TRACE(_T("UPDATE m_rtPTSOffset(SearchStreams)=%s\n"), ReftimeToString(m_rtPTSOffset)); //TRACE(_T("m_rtMin(Boucle)=%s\n"), ReftimeToString(m_rtMin)); //TRACE(_T("stream=%d\n"), stream->m_Type); //TRACE(_T("m_rtMax(Boucle)=%s\n"), ReftimeToString(m_rtMax)); //TRACE(_T("m_rtMax - m_rtMin(Boucle)=%s\n"), ReftimeToString(m_rtMax - m_rtMin)); } } } } } } else { b = 0; } if (!CalcDuration) { AddStream(h.pid, b, 0, DWORD(h.bytes - (GetPos() - pos))); } } Seek(h.next); } else if (m_type == mpeg_pva) { pvahdr h; if (!Read(h)) { continue; } if (h.fpts) { if (m_rtMin == _I64_MAX) { m_rtMin = h.pts; m_posMin = GetPos(); } if (m_rtMin < h.pts && m_rtMax < h.pts) { m_rtMax = h.pts; m_posMax = GetPos(); } } __int64 pos = GetPos(); if (h.streamid == 1) { AddStream(h.streamid, 0xe0, 0, h.length); } else if (h.streamid == 2) { AddStream(h.streamid, 0xc0, 0, h.length); } if (h.length) { Seek(pos + h.length); } } } return S_OK; }
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; }
HRESULT CPGSSub::ParseSample(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, BYTE* pData, size_t nLen) { CheckPointer(pData, E_POINTER); CAutoLock cAutoLock(&m_csCritSec); CGolombBuffer sampleBuffer(pData, nLen); while (!sampleBuffer.IsEOF()) { if (m_nCurSegment == NO_SEGMENT) { HDMV_SEGMENT_TYPE nSegType = (HDMV_SEGMENT_TYPE)sampleBuffer.ReadByte(); unsigned short nUnitSize = sampleBuffer.ReadShort(); nLen -= 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) { size_t nSize = std::min(m_nSegSize - m_nSegBufferPos, nLen); 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_PGSSUB(_T("CPGSSub:PALETTE %s\n"), ReftimeToString(rtStart)); ParsePalette(&SegmentBuffer, m_nSegSize); break; case OBJECT: TRACE_PGSSUB(_T("CPGSSub:OBJECT %s\n"), ReftimeToString(rtStart)); ParseObject(&SegmentBuffer, m_nSegSize); break; case PRESENTATION_SEG: TRACE_PGSSUB(_T("CPGSSub:PRESENTATION_SEG %s (size=%d)\n"), ReftimeToString(rtStart), m_nSegSize); if (rtStart == INVALID_TIME) { break; } // Update the timestamp for the previous segment UpdateTimeStamp(rtStart); // Parse the new presentation segment ParsePresentationSegment(rtStart, &SegmentBuffer); break; case WINDOW_DEF: //TRACE_PGSSUB(_T("CPGSSub:WINDOW_DEF %s\n"), ReftimeToString(rtStart)); break; case END_OF_DISPLAY: TRACE_PGSSUB(_T("CPGSSub:END_OF_DISPLAY %s\n"), ReftimeToString(rtStart)); // Enqueue the current presentation segment if any EnqueuePresentationSegment(); break; default: TRACE_PGSSUB(_T("CPGSSub:UNKNOWN Seg %d %s\n"), m_nCurSegment, ReftimeToString(rtStart)); } m_nCurSegment = NO_SEGMENT; } } } return S_OK; }
CString CClip::GetOut() const { return (m_rtOut == _I64_MIN) ? _T("") : ReftimeToString(m_rtOut); }
CString CClip::GetIn() const { return (m_rtIn == _I64_MIN) ? _T("") : ReftimeToString(m_rtIn); }
HRESULT CHdmvClipInfo::ReadPlaylist(CString strPlaylistFile, REFERENCE_TIME& rtDuration, CPlaylist& Playlist, BOOL bFullInfoRead) { BYTE Buff[5]; CPath Path (strPlaylistFile); bool bDuplicate = false; rtDuration = 0; // Get BDMV folder Path.RemoveFileSpec(); Path.RemoveFileSpec(); m_hFile = CreateFile(strPlaylistFile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY|FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (m_hFile != INVALID_HANDLE_VALUE) { DbgLog((LOG_TRACE, 3, _T("CHdmvClipInfo::ReadPlaylist() : %s"), strPlaylistFile)); ReadBuffer(Buff, 4); if (memcmp(Buff, "MPLS", 4)) { return CloseFile(VFW_E_INVALID_FILE_FORMAT); } ReadBuffer(Buff, 4); if ((memcmp(Buff, "0200", 4)) && (memcmp(Buff, "0100", 4))) { return CloseFile(VFW_E_INVALID_FILE_FORMAT); } LARGE_INTEGER Pos = {0, 0}; DWORD dwTemp; USHORT nPlaylistItems; Pos.QuadPart = ReadDword(); // PlayList_start_address ReadDword(); // PlayListMark_start_address // PlayList() SetFilePointerEx(m_hFile, Pos, NULL, FILE_BEGIN); ReadDword(); // length ReadShort(); // reserved_for_future_use nPlaylistItems = ReadShort(); // number_of_PlayItems ReadShort(); // number_of_SubPaths Pos.QuadPart += 10; __int64 TotalSize = 0; for (size_t i = 0; i < nPlaylistItems; i++) { CAutoPtr<PlaylistItem> Item(DNew PlaylistItem); SetFilePointerEx(m_hFile, Pos, NULL, FILE_BEGIN); Pos.QuadPart += ReadShort() + 2; ReadBuffer(Buff, 5); Item->m_strFileName.Format(_T("%s\\STREAM\\%c%c%c%c%c.M2TS"), CString(Path), Buff[0], Buff[1], Buff[2], Buff[3], Buff[4]); ReadBuffer(Buff, 4); if (memcmp(Buff, "M2TS", 4)) { return CloseFile(VFW_E_INVALID_FILE_FORMAT); } if (!::PathFileExists(Item->m_strFileName)) { DbgLog((LOG_TRACE, 3, _T(" ==> %s is missing, skip it"), Item->m_strFileName)); continue; } ReadBuffer(Buff, 3); dwTemp = ReadDword(); Item->m_rtIn = REFERENCE_TIME(20000.0f*dwTemp/90); dwTemp = ReadDword(); Item->m_rtOut = REFERENCE_TIME(20000.0f*dwTemp/90); Item->m_rtStartTime = rtDuration; rtDuration += (Item->m_rtOut - Item->m_rtIn); if (bFullInfoRead) { LARGE_INTEGER size = {0, 0}; HANDLE hFile = CreateFile(Item->m_strFileName, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY|FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile != INVALID_HANDLE_VALUE) { GetFileSizeEx(hFile, &size); CloseHandle(hFile); } Item->m_SizeIn = TotalSize; TotalSize += size.QuadPart; Item->m_SizeOut = TotalSize; } POSITION pos = Playlist.GetHeadPosition(); while (pos) { PlaylistItem* pItem = Playlist.GetNext(pos); if (*pItem == *Item) { bDuplicate = true; break; } } DbgLog((LOG_TRACE, 3, _T(" ==> %s, Duration : %s [%15I64d], Total duration : %s, Size : %I64d"), Item->m_strFileName, ReftimeToString(Item->Duration()), Item->Duration(), ReftimeToString(rtDuration), Item->Size())); Playlist.AddTail(Item); } CloseFile(S_OK); if (bFullInfoRead) { POSITION pos = Playlist.GetHeadPosition(); while (pos) { PlaylistItem* pItem = Playlist.GetNext(pos); CString fname = pItem->m_strFileName; fname.Replace(L"\\STREAM\\", L"\\CLIPINF\\"); fname.Replace(L".M2TS", L".CLPI"); ReadInfo(fname, &pItem->m_sps); } } return Playlist.IsEmpty() ? E_FAIL : bDuplicate ? S_FALSE : S_OK; } return AmHresultFromWin32(GetLastError()); }
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; }