void CHdmvSub::EnqueuePresentationSegment(REFERENCE_TIME rt) { if (m_pCurrentPresentationSegment) { if (m_pCurrentPresentationSegment->objectCount > 0) { m_pCurrentPresentationSegment->rtStop = rt; m_pCurrentPresentationSegment->CLUT = m_CLUTs[m_pCurrentPresentationSegment->CLUT.id]; // Get the objects' data POSITION pos = m_pCurrentPresentationSegment->objects.GetHeadPosition(); while (pos) { CompositionObject* pObject = m_pCurrentPresentationSegment->objects.GetNext(pos); CompositionObject& pObjectData = m_compositionObjects[pObject->m_object_id_ref]; pObject->m_width = pObjectData.m_width; pObject->m_height = pObjectData.m_height; pObject->SetRLEData(pObjectData.GetRLEData(), pObjectData.GetRLEDataSize(), pObjectData.GetRLEDataSize()); } m_pPresentationSegments.AddTail(m_pCurrentPresentationSegment); TRACE_HDMVSUB( (_T("CHdmvSub: Enqueue Presentation Segment %d - %lS => %lS\n"), m_pCurrentPresentationSegment->composition_descriptor.nNumber, ReftimeToCString(m_pCurrentPresentationSegment->rtStart), ReftimeToCString(m_pCurrentPresentationSegment->rtStop)) ); } else { TRACE_HDMVSUB( (_T("CHdmvSub: Delete empty Presentation Segment %d\n"), m_pCurrentPresentationSegment->composition_descriptor.nNumber) ); delete m_pCurrentPresentationSegment; } m_pCurrentPresentationSegment = NULL; } }
void CHdmvSub::ParseObject(CGolombBuffer* pGBuffer, USHORT nUnitSize) { SHORT object_id = pGBuffer->ReadShort(); if (object_id > _countof(m_ParsedObjects)) { TRACE_HDMVSUB(_T("CHdmvSub::ParseObject() : FAILED, object_id = %d\n"), object_id); return; } CompositionObject &pObject = m_ParsedObjects[object_id]; pObject.m_version_number = pGBuffer->ReadByte(); BYTE m_sequence_desc = pGBuffer->ReadByte(); if (m_sequence_desc & 0x80) { DWORD object_data_length = (DWORD)pGBuffer->BitRead(24); pObject.m_width = pGBuffer->ReadShort(); pObject.m_height = pGBuffer->ReadShort(); pObject.SetRLEData(pGBuffer->GetBufferPos(), nUnitSize-11, object_data_length-4); TRACE_HDMVSUB(_T("CHdmvSub::ParseObject() : NewObject - size = %ld, version = %d, total obj = %d, size = %dx%d\n"), object_data_length, pObject.m_version_number, m_pObjects.GetCount(), pObject.m_width, pObject.m_height); } else { pObject.AppendRLEData(pGBuffer->GetBufferPos(), nUnitSize-4); } }
void CHdmvSub::Render(SubPicDesc& spd, REFERENCE_TIME rt, RECT& bbox) { HDMV_PRESENTATION_SEGMENT* pPresentationSegment = FindPresentationSegment(rt); bbox.left = LONG_MAX; bbox.top = LONG_MAX; bbox.right = 0; bbox.bottom = 0; if (pPresentationSegment) { POSITION pos = pPresentationSegment->objects.GetHeadPosition(); TRACE_HDMVSUB(_T("CHdmvSub:Render Presentation segment %d --> %s - %s\n"), pPresentationSegment->composition_descriptor.nNumber, ReftimeToString(pPresentationSegment->rtStart), ReftimeToString(pPresentationSegment->rtStop)); while (pos) { CompositionObject* pObject = pPresentationSegment->objects.GetNext(pos); if (pObject->GetRLEDataSize() && pObject->m_width > 0 && pObject->m_height > 0 && spd.w >= (pObject->m_horizontal_position + pObject->m_width) && spd.h >= (pObject->m_vertical_position + pObject->m_height)) { pObject->SetPalette(pPresentationSegment->CLUT.size, pPresentationSegment->CLUT.palette, pPresentationSegment->video_descriptor.nVideoWidth > 720); 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); TRACE_HDMVSUB(_T(" --> Object %d (Res=%dx%d, SPDRes=%dx%d)\n"), pObject->m_object_id_ref, pObject->m_width, pObject->m_height, spd.w, spd.h); pObject->RenderHdmv(spd); } else { TRACE_HDMVSUB(_T(" --> Invalid object %d\n"), pObject->m_object_id_ref); } } } }
void CHdmvSub::Render(SubPicDesc& spd, REFERENCE_TIME rt, RECT& bbox) { HDMV_PRESENTATION_SEGMENT* pPresentationSegment = FindPresentationSegment(rt); bbox.left = LONG_MAX; bbox.top = LONG_MAX; bbox.right = 0; bbox.bottom = 0; if (pPresentationSegment) { POSITION pos = pPresentationSegment->objects.GetHeadPosition(); TRACE_HDMVSUB( (_T("CHdmvSub:Render Presentation segment %d --> %lS - %lS\n"), pPresentationSegment->composition_descriptor.nNumber, ReftimeToCString(pPresentationSegment->rtStart), ReftimeToCString(pPresentationSegment->rtStop)) ); while (pos) { CompositionObject* pObject = pPresentationSegment->objects.GetNext(pos); if (pObject->GetRLEDataSize() && pObject->m_width > 0 && pObject->m_height > 0 && spd.w >= (pObject->m_horizontal_position + pObject->m_width) && spd.h >= (pObject->m_vertical_position + pObject->m_height)) { CompositionObject::ColorType color_type = m_colorTypeSetting; if (color_type==CompositionObject::NONE) { color_type = pPresentationSegment->video_descriptor.nVideoWidth > 720 ? CompositionObject::YUV_Rec709 : CompositionObject::YUV_Rec601; } pObject->SetPalette(pPresentationSegment->CLUT.size, pPresentationSegment->CLUT.palette, color_type, m_yuvRangeSetting==CompositionObject::RANGE_NONE ? CompositionObject::RANGE_TV : m_yuvRangeSetting); 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); ASSERT(spd.h>=0); bbox.left = bbox.left > 0 ? bbox.left : 0; bbox.top = bbox.top > 0 ? bbox.top : 0; bbox.right = bbox.right < spd.w ? bbox.right : spd.w; bbox.bottom = bbox.bottom < spd.h ? bbox.bottom : spd.h; pObject->InitColor(spd); TRACE_HDMVSUB( (_T(" --> Object %d (Pos=%dx%d, Res=%dx%d, SPDRes=%dx%d)\n"), pObject->m_object_id_ref, pObject->m_horizontal_position, pObject->m_vertical_position, pObject->m_width, pObject->m_height, spd.w, spd.h) ); pObject->RenderHdmv(spd); } else { TRACE_HDMVSUB( (_T(" --> Invalid object %d\n"), pObject->m_object_id_ref) ); } } } }
int CHdmvSub::ParsePresentationSegment(CGolombBuffer* pGBuffer) { COMPOSITION_DESCRIPTOR CompositionDescriptor; BYTE nObjectNumber; //bool palette_update_flag; //BYTE palette_id_ref; ParseVideoDescriptor(pGBuffer, &m_VideoDescriptor); ParseCompositionDescriptor(pGBuffer, &CompositionDescriptor); pGBuffer->ReadByte(); //palette_update_flag = !!(pGBuffer->ReadByte() & 0x80); pGBuffer->ReadByte(); //palette_id_ref = pGBuffer->ReadByte(); nObjectNumber = pGBuffer->ReadByte(); TRACE_HDMVSUB( "CHdmvSub::ParsePresentationSegment Size = %d, nObjectNumber = %d\n", pGBuffer->GetSize(), nObjectNumber); if (nObjectNumber > 0) { delete m_pCurrentObject; m_pCurrentObject = DNew CompositionObject(); m_pCurrentObject->m_nObjectNumber = nObjectNumber; for (int i=0; i<nObjectNumber; i++) { ParseCompositionObject (pGBuffer, m_pCurrentObject); } } return nObjectNumber; }
void CHdmvSub::ParseObject(CGolombBuffer* pGBuffer, USHORT nUnitSize) // #498 { SHORT object_id = pGBuffer->ReadShort(); UNUSED_ALWAYS(object_id); BYTE m_sequence_desc; ASSERT (m_pCurrentObject != NULL); if (m_pCurrentObject) { // && m_pCurrentObject->m_object_id_ref == object_id) m_pCurrentObject->m_version_number = pGBuffer->ReadByte(); m_sequence_desc = pGBuffer->ReadByte(); if (m_sequence_desc & 0x80) { DWORD object_data_length = (DWORD)pGBuffer->BitRead(24); m_pCurrentObject->m_width = pGBuffer->ReadShort(); m_pCurrentObject->m_height = pGBuffer->ReadShort(); m_pCurrentObject->SetRLEData (pGBuffer->GetBufferPos(), nUnitSize-11, object_data_length-4); TRACE_HDMVSUB ("CHdmvSub:NewObject size=%ld, total obj=%d, %dx%d\n", object_data_length, m_pObjects.GetCount(), m_pCurrentObject->m_width, m_pCurrentObject->m_height); } else { m_pCurrentObject->AppendRLEData (pGBuffer->GetBufferPos(), nUnitSize-4); } } }
void CHdmvSub::RemoveOldSegments(REFERENCE_TIME rt) { // Cleanup the old presentation segments. We keep a 2 min buffer to play nice with the queue. while (!m_pPresentationSegments.IsEmpty() && m_pPresentationSegments.GetHead()->rtStop + 120 * 10000000i64 < rt) { HDMV_PRESENTATION_SEGMENT* pPresentationSegment = m_pPresentationSegments.RemoveHead(); TRACE_HDMVSUB(_T("CHdmvSub::RemoveOldSegments Remove presentation segment %d %s => %s (rt=%s)\n"), pPresentationSegment->composition_descriptor.nNumber, ReftimeToString(pPresentationSegment->rtStart), ReftimeToString(pPresentationSegment->rtStop), ReftimeToString(rt)); delete pPresentationSegment; } }
void CHdmvSub::CleanOld(REFERENCE_TIME rt) { CompositionObject* pObject_old; while (!m_pObjects.IsEmpty()) { pObject_old = m_pObjects.GetHead(); if (pObject_old->m_rtStop < rt) { TRACE_HDMVSUB(_T("CHdmvSub:HDMV remove object, size = %d, %s => %s, (rt = %s)\n"), pObject_old->GetRLEDataSize(), ReftimeToString (pObject_old->m_rtStart), ReftimeToString(pObject_old->m_rtStop), ReftimeToString(rt)); m_pObjects.RemoveHead(); delete pObject_old; } else { break; } } }
POSITION CHdmvSub::GetStartPosition(REFERENCE_TIME rt, double fps /* = 0*/) { HDMV_PRESENTATION_SEGMENT* pPresentationSegment; // Cleanup old PG while (m_pPresentationSegments.GetCount() > 0) { pPresentationSegment = m_pPresentationSegments.GetHead(); if (pPresentationSegment->rtStop < rt) { TRACE_HDMVSUB( (_T("CHdmvSub:HDMV Remove Presentation segment %d %lS => %lS (rt=%lS)\n"), pPresentationSegment->composition_descriptor.nNumber, ReftimeToString(pPresentationSegment->rtStart), ReftimeToString(pPresentationSegment->rtStop), ReftimeToString(rt)) ); m_pPresentationSegments.RemoveHead(); delete pPresentationSegment; } else { break; } } // log first 2 objects // { // POSITION pos = m_pPresentationSegments.GetHeadPosition(); // for (int i=0;i<2 && pos!=NULL; i++) // { // CompositionObject* pObject = m_pPresentationSegments.GetNext(pos); // TRACE_HDMVSUB( (_T("CHdmvSub:HDMV cur %d object %d %lS => %lS\n"), i, pObject->GetRLEDataSize(), // ReftimeToCString (pObject->m_rtStart), ReftimeToCString(pObject->m_rtStop))); // } // } POSITION pos = m_pPresentationSegments.GetHeadPosition(); while (pos) { HDMV_PRESENTATION_SEGMENT* pPresentationSegment = m_pPresentationSegments.GetAt (pos); if (rt >= pPresentationSegment->rtStart && rt < pPresentationSegment->rtStop) { break; } else if( rt < pPresentationSegment->rtStart ) { pos = NULL; break; } m_pPresentationSegments.GetNext(pos); } return pos; }
POSITION CHdmvSub::GetStartPosition(REFERENCE_TIME rt, double fps) { CompositionObject* pObject; // Cleanup old PG while (m_pObjects.GetCount()>0) { pObject = m_pObjects.GetHead(); if (pObject->m_rtStop < rt) { TRACE_HDMVSUB ("CHdmvSub:HDMV remove object %d %S => %S (rt=%S)\n", pObject->GetRLEDataSize(), ReftimeToString (pObject->m_rtStart), ReftimeToString(pObject->m_rtStop), ReftimeToString(rt)); m_pObjects.RemoveHead(); delete pObject; } else { break; } } return m_pObjects.GetHeadPosition(); }
POSITION CHdmvSub::GetStartPosition(REFERENCE_TIME rt, double fps) { HDMV_PRESENTATION_SEGMENT* pPresentationSegment; // Cleanup old PG while (m_pPresentationSegments.GetCount() > 0) { pPresentationSegment = m_pPresentationSegments.GetHead(); if (pPresentationSegment->rtStop < rt) { TRACE_HDMVSUB(_T("CHdmvSub:HDMV Remove Presentation segment %d %s => %s (rt=%s)\n"), pPresentationSegment->composition_descriptor.nNumber, ReftimeToString(pPresentationSegment->rtStart), ReftimeToString(pPresentationSegment->rtStop), ReftimeToString(rt)); m_pPresentationSegments.RemoveHead(); delete pPresentationSegment; } else { break; } } return m_pPresentationSegments.GetHeadPosition(); }
void CHdmvSub::Render(SubPicDesc& spd, REFERENCE_TIME rt, RECT& bbox) { CompositionObject* pObject = FindObject (rt); ASSERT (pObject!=NULL && spd.w >= pObject->m_width && spd.h >= pObject->m_height); if (pObject && spd.w >= pObject->m_width && spd.h >= pObject->m_height) { if (!pObject->HavePalette()) { pObject->SetPalette (m_nDefaultPaletteNbEntry, m_pDefaultPalette, m_VideoDescriptor.nVideoWidth>720); } TRACE_HDMVSUB ("CHdmvSub:Render size=%ld, ObjRes=%dx%d, SPDRes=%dx%d\n", pObject->GetRLEDataSize(), pObject->m_width, pObject->m_height, spd.w, spd.h); pObject->RenderHdmv(spd); bbox.left = 0; bbox.top = 0; bbox.right = bbox.left + pObject->m_width; bbox.bottom = bbox.top + pObject->m_height; } }
void CHdmvSub::ParseCompositionObject(CGolombBuffer* pGBuffer, CompositionObject* pCompositionObject) { pCompositionObject->m_object_id_ref = pGBuffer->ReadShort(); pCompositionObject->m_window_id_ref = (SHORT)pGBuffer->ReadByte(); BYTE bTemp = pGBuffer->ReadByte(); pCompositionObject->m_object_cropped_flag = !!(bTemp & 0x80); pCompositionObject->m_forced_on_flag = !!(bTemp & 0x40); pCompositionObject->m_horizontal_position = pGBuffer->ReadShort(); pCompositionObject->m_vertical_position = pGBuffer->ReadShort(); if (pCompositionObject->m_object_cropped_flag) { pCompositionObject->m_cropping_horizontal_position = pGBuffer->ReadShort(); pCompositionObject->m_cropping_vertical_position = pGBuffer->ReadShort(); pCompositionObject->m_cropping_width = pGBuffer->ReadShort(); pCompositionObject->m_cropping_height = pGBuffer->ReadShort(); } TRACE_HDMVSUB(_T("CHdmvSub::ParseCompositionObject() : m_object_id_ref = %d, m_window_id_ref = %d, pos = %d:%d\n"), pCompositionObject->m_object_id_ref, pCompositionObject->m_window_id_ref, pCompositionObject->m_horizontal_position, pCompositionObject->m_vertical_position); }
void CHdmvSub::ParseObject(CGolombBuffer* pGBuffer, unsigned short nUnitSize) // #498 { short object_id = pGBuffer->ReadShort(); ASSERT(object_id < _countof(m_compositionObjects)); CompositionObject& pObject = m_compositionObjects[object_id]; pObject.m_version_number = pGBuffer->ReadByte(); BYTE m_sequence_desc = pGBuffer->ReadByte(); if (m_sequence_desc & 0x80) { DWORD object_data_length = (DWORD)pGBuffer->BitRead(24); pObject.m_width = pGBuffer->ReadShort(); pObject.m_height = pGBuffer->ReadShort(); pObject.SetRLEData(pGBuffer->GetBufferPos(), nUnitSize - 11, object_data_length - 4); TRACE_HDMVSUB( (_T("CHdmvSub:ParseObject %d (size=%ld, %dx%d)\n"), object_id, object_data_length, pObject.m_width, pObject.m_height) ); } else { pObject.AppendRLEData(pGBuffer->GetBufferPos(), nUnitSize - 4); } }
int CHdmvSub::ParsePresentationSegment(REFERENCE_TIME rt, CGolombBuffer* pGBuffer) { m_pCurrentPresentationSegment = DEBUG_NEW HDMV_PRESENTATION_SEGMENT(); m_pCurrentPresentationSegment->rtStart = rt; m_pCurrentPresentationSegment->rtStop = _I64_MAX; ParseVideoDescriptor(pGBuffer, &m_pCurrentPresentationSegment->video_descriptor); ParseCompositionDescriptor(pGBuffer, &m_pCurrentPresentationSegment->composition_descriptor); m_pCurrentPresentationSegment->palette_update_flag = !!(pGBuffer->ReadByte() & 0x80); m_pCurrentPresentationSegment->CLUT.id = pGBuffer->ReadByte(); m_pCurrentPresentationSegment->objectCount = pGBuffer->ReadByte(); TRACE_HDMVSUB( (_T("CHdmvSub::ParsePresentationSegment Size = %d, state = %#x, nObjectNumber = %d\n"), pGBuffer->GetSize(), m_pCurrentPresentationSegment->composition_descriptor.bState, m_pCurrentPresentationSegment->objectCount) ); for (int i = 0; i < m_pCurrentPresentationSegment->objectCount; i++) { CompositionObject* pCompositionObject = DEBUG_NEW CompositionObject(); ParseCompositionObject(pGBuffer, pCompositionObject); m_pCurrentPresentationSegment->objects.AddTail(pCompositionObject); } return m_pCurrentPresentationSegment->objectCount; }
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; }
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(); unsigned short 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:PALETTE rtStart=%10I64d\n"), rtStart) ); ParsePalette(&SegmentBuffer, m_nSegSize); break; case OBJECT: TRACE_HDMVSUB( (_T("CHdmvSub:OBJECT %lS\n"), ReftimeToCString(rtStart)) ); ParseObject(&SegmentBuffer, m_nSegSize); break; case PRESENTATION_SEG: TRACE_HDMVSUB( (_T("CHdmvSub:PRESENTATION_SEG %lS (size=%d)\n"), ReftimeToCString(rtStart), m_nSegSize) ); // Enqueue the current presentation segment if any EnqueuePresentationSegment(rtStart); // Parse the new presentation segment ParsePresentationSegment(rtStart, &SegmentBuffer); break; case WINDOW_DEF: //TRACE_HDMVSUB( (_T("CHdmvSub:WINDOW_DEF %lS\n"), ReftimeToCString(rtStart)) ); break; case END_OF_DISPLAY: //TRACE_HDMVSUB( (_T("CHdmvSub:END_OF_DISPLAY %lS\n"), ReftimeToCString(rtStart)) ); break; default: TRACE_HDMVSUB( (_T("CHdmvSub:UNKNOWN Seg %d rtStart=0x%10dd\n"), m_nCurSegment, rtStart) ); } m_nCurSegment = NO_SEGMENT; } } } } return hr; }
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::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); }
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]); } } }