📄 smlparse.cpp
字号:
if (parser) { parser->AddRef(); } else { rc = HXR_OUTOFMEMORY; } if (SUCCEEDED(rc)) { m_pResponse = new CSmil1ParserResponse(this); m_pResponse->AddRef(); rc = parser->Init(m_pResponse, NULL, TRUE); // strict parser } if (m_bStoreErrors && parser) { parser->InitErrorNotifier(m_pResponse); } m_pParser = (IHXXMLParser*)parser;#endif return rc;}HX_RESULTCSmil1Parser::parse(IHXBuffer* pBuffer, BOOL bIsFinal){ HX_RESULT rc = HXR_OK; rc = m_pParser->Parse(pBuffer, bIsFinal); if(HXR_OK != rc) { m_pParser->GetCurrentLineNumber(m_ulErrorLineNumber); m_pParser->GetCurrentColumnNumber(m_ulErrorColumnNumber); HX_RELEASE(m_pErrorText); m_pParser->GetCurrentErrorText(m_pErrorText); } return rc;}HX_RESULTCSmil1Parser::durationResolved(const char* pID, UINT32 ulDuration){ SMIL1Node* pNode = NULL; IHXBuffer* pBuf = NULL; if(m_pIDMap->Lookup(pID, (void*&)pNode)) { if (pNode->m_pElement->m_bIndefiniteDuration) { goto cleanup; } // add duration to parent element if(pNode && pNode->m_pElement && pNode->m_pElement->m_pTimelineElement) { pNode->m_pElement->m_pTimelineElement->setDuration(ulDuration); } }cleanup: HX_RELEASE(pBuf); return HXR_OK;}BOOL AncestorEventsAreResolved(SMIL1Node* pNode){ if (!pNode || !pNode->m_pElement || !pNode->m_pElement->m_pTimelineElement || pNode->m_tag == SMILBody) { return TRUE; } //Now, look to see if its duration and delay events, if any, are // resolved: if ( ( (pNode->m_pElement->m_pTimelineElement->durationEvent() && !pNode->m_pElement->m_pTimelineElement->durationSet()) || (pNode->m_pElement->m_pTimelineElement->delayEvent() && !pNode->m_pElement->m_pTimelineElement->initialDelaySet()) ) && //[SMIL 1.0 compliance] Helps fix PR 32578: //However, if we have a duration event and it's based on a child's // timing (as can happen via endsync="id(child)", then we want to // avoid this element waiting for its parent to be resolved while // the parent is waiting for this element to be resolved: (!pNode->m_pElement->m_pTimelineElement->durationEvent() || SMILEventSourceID != pNode->m_pElement->m_nEndsyncEventSourceTag) ) { return FALSE; //We still need to await event resolution. } //pNode is ok but its dependency ancestors may still be unresolved and // thus pNode may still have timing constraints from its dependency // ancestors due to their unresolved event(s): return AncestorEventsAreResolved(pNode->m_pParent);}voidCSmil1Parser::insertTimelineElement(const char* pID, UINT32 ulDelay){ SMIL1Node* pNode = 0; if(m_pIDMap->Lookup(pID, (void*&)pNode)) { if(pNode && pNode->m_pElement && !pNode->m_pElement->m_bInsertedIntoTimeline && //[SMIL 1.0 compliance] Helps fix PR 16629: // We don't want to insert a node into the timeline if // its begin or end is dependent on another (not-yet- // resolved) element: ( (!pNode->m_pElement->m_pTimelineElement->durationEvent() || pNode->m_pElement->m_pTimelineElement->durationSet()) && (!pNode->m_pElement->m_pTimelineElement->delayEvent() || pNode->m_pElement->m_pTimelineElement->initialDelaySet()) ) //[SMIL 1.0 compliance] Helps fix 14420: // First, we need to look all the way up the tree of ancestors // to see if any of them have event-based delays or durations // and to make sure the appropriate time(s) are resolved. If // not, we'll have to await those event resolutions before // inserting this element into the timeline: && AncestorEventsAreResolved(pNode) ) { // /[SMIL 1.0 Compliance] Fixes PR 27644: // if our begin offset is same or greater than our parent's // end offset, then we should be ignored: if ( pNode->m_pParent && pNode->m_pParent->m_pElement && pNode->m_pElement->m_ulBeginOffset != ((UINT32)-1) && pNode->m_pParent->m_pElement->m_ulEndOffset != ((UINT32)-1) && (pNode->m_pElement->m_ulBeginOffset > pNode->m_pParent->m_pElement->m_ulEndOffset) ) { return; //Don't insert this because it can't ever play. } // skip the element if its duration == 0 if (0 == pNode->m_pElement->m_ulDuration) { durationResolved(pNode->m_id, 0); } else { pNode->m_pElement->m_ulDelay = ulDelay; pNode->m_pElement->m_ulTimestamp = INITIAL_STREAM1_TIMESTAMP; pNode->m_pElement->m_bInsertedIntoTimeline = TRUE; insertElementByTimestamp(pNode->m_pElement); } } }}voidCSmil1Parser::resetTimelineElementDuration(const char* pID, UINT32 ulDuration){ SMIL1Node* pNode = NULL; if(m_pIDMap->Lookup(pID, (void*&)pNode)) { CSmil1SourceUpdate* pUpdate = new CSmil1SourceUpdate; pUpdate->m_ulTimestamp = INITIAL_STREAM1_TIMESTAMP; pUpdate->m_srcID = pID; pUpdate->m_ulUpdatedDuration = ulDuration; if(!m_pSourceUpdateList) { m_pSourceUpdateList = new CHXSimpleList; } m_pSourceUpdateList->AddTail(pUpdate); insertElementByTimestamp(pUpdate); }}CSmil1Element*CSmil1Parser::findElement(const char* pID){ SMIL1Node* pNode = NULL; if(m_pIDMap->Lookup(pID, (void*&)pNode)) { return pNode->m_pElement; } return NULL;}const char*CSmil1Parser::assignID(const char* pPrefix){ SafeSprintf(m_pVarName, 256, "%s_%ld", pPrefix, GetUniqueNumber()); return m_pVarName;}UINT16CSmil1Parser::getFragmentGroup(const char* pFragment){ if(pFragment) { SMIL1Node* pNode = 0; if(m_pIDMap->Lookup(pFragment, (void*&)pNode)) { if(!pNode->m_bDelete) { if(pNode->m_tag == SMILAAnchor || pNode->m_tag == SMILSwitch) { SMIL1Node* pChildNode = getTimelineDescendent(pNode, NULL); while(pChildNode) { if(!pChildNode->m_bDelete) { return pChildNode->m_nGroup; } pChildNode = getTimelineDescendent(pNode, pChildNode); } } else if(pNode->m_tag == SMILAnchor) { SMIL1Node* pParentNode = pNode->m_pParent; if(pParentNode && !pParentNode->m_bDelete) { return pParentNode->m_nGroup; } } else { return pNode->m_nGroup; } } } } return 0;}UINT32CSmil1Parser::getFragmentOffset(const char* pFragment, //This BOOL will be set to FALSE if the fragment // does not exist or does not yet have a resolved // begin time. This was necessary to fix PR 22655: BOOL& bFragFoundAndResolved){ bFragFoundAndResolved = FALSE; if(pFragment) { UINT32 ulAnchorBegin = 0; SMIL1Node* pNode = NULL; CSmil1Element* pElement = NULL; CSmil1Element* pActualElement = NULL; if(m_pIDMap->Lookup(pFragment, (void*&)pNode) && pNode->m_pElement) { pElement = pNode->m_pElement; if(pNode->m_tag == SMILSwitch || pNode->m_tag == SMILAAnchor) { SMIL1Node* pChildNode = getTimelineDescendent( pNode, NULL); while(pChildNode) { if(!pChildNode->m_bDelete) { pActualElement = pChildNode->m_pElement; break; } pChildNode = getTimelineDescendent( pNode, pChildNode); } } else if(pNode->m_tag == SMILAnchor) { if(pElement->m_ulBeginOffset != (UINT32)-1) { ulAnchorBegin = pElement->m_ulBeginOffset; } SMIL1Node* pParent = pNode->m_pParent; if(pParent) { pActualElement = pParent->m_pElement; } } else { pActualElement = pElement; } if(pActualElement) { //[SMIL 1.0 Compliance] Fixes PR 26464: // Use delay (which already includes begin offset) // if it's a valid value, else use begin offset // without delay added (see comment below): if(pActualElement->m_ulDelay != (UINT32)-1) { bFragFoundAndResolved = TRUE; return pActualElement->m_ulDelay + ulAnchorBegin; } else if(pActualElement->m_ulBeginOffset != (UINT32)-1) { bFragFoundAndResolved = TRUE; //Changed this while fixing PR 26464: // This used to return pActualElement->m_ulDelay + // pActualElement->m_ulBeginOffset + ulAnchorBegin but // the delay can already account for the begin if both // are set so we'd end up seeking past where we were // supposed to go by the amount of the begin offset. // Also, we weren't even checking to see // if delay was valid before using it (and now we're // sure it is invalid per check above): return pActualElement->m_ulBeginOffset + ulAnchorBegin; } else { return 0; } } } } return 0;}SMIL1Node*CSmil1Parser::findFirstNode(SMIL1NodeList* pNodeList, SMIL1NodeTag tag){ if(!pNodeList) { return 0; } SMIL1Node* pFoundNode = 0; CHXSimpleList::Iterator i; for(i=pNodeList->Begin();i!=pNodeList->End();++i) { SMIL1Node* pNode = (SMIL1Node*)(*i); if(pNode->m_tag == tag) { pFoundNode = pNode; } else { pFoundNode = findFirstNode(pNode->m_pNodeList, tag); } if(pFoundNode) { break; } } return pFoundNode;}SMIL1Node*CSmil1Parser::findFirstNode(SMIL1NodeTag tag){ return findFirstNode(m_pNodeList, tag);}SMIL1Node*CSmil1Parser::getFirstNodeChild(SMIL1Node* pNode){ m_pCurNode = pNode; if(!m_pCurNode) { return 0; } return m_pCurNode->getFirstChild();}SMIL1Node*CSmil1Parser::getNextNodeChild(){ if(!m_pCurNode) { return 0; } return m_pCurNode->getNextChild();}HX_RESULTCSmil1Parser::parseClockValue(const char* pValue, UINT32& ulTimeValue){ // try npt char* pPtr = (char *)strstr(pValue, "npt="); if(pPtr) { pPtr += 4; // point to beginning of clock value //[SMIL 1.0 compliance] fixes PR 26445: if "npt=4h" is specified, // we need to convert to "14400s" otherwise the 4 is treated as // seconds: char* pHourChar = strchr(pPtr, 'h'); if (pHourChar && !strchr(pPtr, ':')) //then it's hours without ':' { IHXBuffer* pBuf = new CHXBuffer; if (pBuf) { pBuf->AddRef(); *pHourChar = '\0'; //get rid of the 'h' in pPtr. pBuf->Set((const unsigned char *)pPtr, strlen(pPtr) + strlen(":00:00") + 1); char* pTmp = (char*)pBuf->GetBuffer(); strcat(pTmp, ":00:00"); /* Flawfinder: ignore */ NPTime clockTime((const char*)pTmp); ulTimeValue = (UINT32)clockTime; pBuf->Release(); } else { return HXR_OUTOFMEMORY; } } //END fix for PR 26445. else { NPTime clockTime(pPtr); ulTimeValue = (UINT32)clockTime; } return HXR_OK; } // try smpte pPtr = (char *)strstr(pValue, "smpte="); if(pPtr) { pPtr += 6; // point to beginning of clock value SMPTETimeCode clockTime(pPtr); ulTimeValue = (UINT32)clockTime; return HXR_OK; } pPtr = (char *)strstr(pValue, "smpte-30-drop="); if(pPtr) { pPtr += 14; // point to beginning of clock value SMPTETimeCode clockTime(pPtr); ulTimeValue = (UINT32)clockTime; return HXR_OK; } pPtr = (char *)strstr(pValue, "smpte-25="); if(pPtr) { pPtr += 9; // point to beginning of clock value SMPTETimeCode clockTime; clockTime.m_framesPerSec = SMPTETimeCode::FPS_25; clockTime.fromString(pPtr); ulTimeValue = (UINT32)clockTime; return HXR_OK; } else if(strchr(pValue, ':')) // try just hh:mm:ss with no prefix/suffix { NPTime clockTime(pValue); ulTimeValue = (UINT32)clockTime; return HXR_OK; } // ok, try h/min/s/ms char* pEndPtr = 0; double dVal = strtod(pValue, &pEndPtr); if(strcmp(pEndPtr, "h") == 0) { ulTimeValue = (UINT32)(dVal * 60.0 * 60.0 * 1000.0); return HXR_OK; } else if(strcmp(pEndPtr, "min") == 0) { ulTimeValue = (UINT32)(dVal * 60.0 * 1000.0); return HXR_OK; } else if(strcmp(pEndPtr, "s") == 0 || //[SMIL 1.0 compliance] Fixes PR 22673: the SMIL doc says that we // need to default to seconds if no unit-type is given: // Timecount-val ::= Timecount ("." Fraction)? // ("h" | "min" | "s" | "ms")? ; default is "s" (!strlen(pEndPtr)) ) { ulTimeValue = (UINT32)(dVal * 1000.0); return HXR_OK; } else if(strcmp(pEndPtr, "ms") == 0) { ulTimeValue = (UINT32)(dVal); return HXR_OK; } //else something other than "h", "min", "s", "", or "ms" was specified: else { return HXR_FAIL; }}HX_RESULTCSmil1Parser::parseAnchorCoords(const char* pCoords, CSmil1AnchorElement* pAnchor){ HX_RESULT rc = HXR_OK; double coordArray[4]; BOOL percentArray[4]; int i = 0; for(i=0; i<4; ++i) { coordArray[i] = 0.0; percentArray[i] = FALSE; } char* pCoordCopy = new_string(pCoords); char* pTok = strtok(pCoordCopy, ","); for(i=0;i<4,pTok;++i) { char* pEndPtr = 0; double dVal = strtod(pTok, &pEndPtr); coordArray[i] = dVal; percentArray[i] = (*pEndPtr == '%') ? TRUE: FALSE; pTok = strtok(NULL, ","); } delete[] pCoordCopy; pAnchor->m_ulOriginalLeftX = pAnchor->m_ulLeftX = (UINT32)coordArray[0]; pAnchor->m_bLeftXIsPercent = percentArray[0]; pAnchor->m_ulOriginalTopY = pAnchor->m_ulTopY = (UINT32)coordArray[1]; pAnchor->m_bTopYIsPercent = percentArray[1]; pAnchor->m_ulOriginalRightX = pAnchor->m_ulRightX = (UINT32)coordArray[2]; pAnchor->m_bRightXIsPercent = percentArray[2]; pAnchor->m_ulOriginalBottomY = pAnchor->m_ulBottomY = (UINT32)coordArray[3]; pAnchor->m_bBottomYIsPercent = percentArray[3]; pAnchor->m_bCoordsSet = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -