📄 rtffplin.cpp
字号:
if (GetDuration() > 0) { ulAvgBitRate = (ULONG32)( HEADER_OVERHEAD_FACTOR * (double((8.0 * m_ulTotalFileSizeInBytes) / ((double)GetDuration() / 1000.0)))); } if(ulAvgBitRate < 8) ulAvgBitRate = 9; ulMaxBitRate = ulAvgBitRate * 2;#endif ///XXXEH- Unfinished code: ///If no '>' found, back up until the first '=' found /// and then go forward until the the first /// non-space/tab/newline char is found and then go /// forward until the 1st space/tab/newline and then /// put a '>' there and send that: /// (For now, just do the following:) /// Go to just past the first carriage return: pCommonClassFactory->CreateInstance( CLSID_IHXBuffer,(void**)&pLoppedHdr); // /Only treat this as header if this is not plain text: if (!m_bIsTextPlainStreamMimeType) { pLoppedHdr->Set( (const UCHAR*)szLoppedHdr,m_ulHeaderSize+1); // Fill in the Header with the relevant data... pHeader->SetPropertyBuffer ("OpaqueData", pLoppedHdr); } pHeader->SetPropertyULONG32("StreamNumber", uStreamNumber);#if OLD_SCHOOL_AVGBITRATE_CALCULATION pHeader->SetPropertyULONG32("MaxBitRate", 9);//ulMaxBitRate); pHeader->SetPropertyULONG32("AvgBitRate", 9);//ulAvgBitRate);#else pHeader->SetPropertyULONG32("MaxBitRate", ulMaxBitRate); pHeader->SetPropertyULONG32("AvgBitRate", ulAvgBitRate);#endif pHeader->SetPropertyULONG32("MaxPacketSize", 9);//ulMaxPacketSize); pHeader->SetPropertyULONG32("AvgPacketSize", 9);//ulAvgPacketSize); pHeader->SetPropertyULONG32("StartTime", ulStartTime); pHeader->SetPropertyULONG32("Preroll", ulPreroll); pHeader->SetPropertyULONG32("Duration", GetDuration()); // /Needed for fixing PR 78150: pHeader->SetPropertyULONG32("SourceFileSize", m_ulTotalFileSizeInBytes); if (m_bIsTextPlainStreamMimeType) { pHeader->SetPropertyULONG32("MaxPlainTextBytesToBeSent", MAX_ALLOWED_PLAINTEXT_CHARS_TO_SEND); } // /Treat .txt files as discrete media, but only when // played in a SMIL 2.0 (or higher) presentation; // we don't want to break old content so leave the // 60000-millisec duration as is and let the SMIL // renderer look for the intrinsicDurationType value: IHXBuffer* pIntrDurTypeBuf = NULL; if (HXR_OK == pCommonClassFactory->CreateInstance( CLSID_IHXBuffer, (void**)&pIntrDurTypeBuf) ) { HX_RESULT retVal = HXR_FAIL; if (txt_extension == m_RTSourceFileExtension || 0 == stricmp(szMimeType, "text/plain")) { HX_ASSERT(m_bIsTextPlainStreamMimeType); retVal = pIntrDurTypeBuf->Set( (const UCHAR *) "intrinsicDurationDiscrete", 1 + strlen( "intrinsicDurationDiscrete") ); } else { retVal = pIntrDurTypeBuf->Set( (const UCHAR *) "intrinsicDurationContinuous", 1 + strlen( "intrinsicDurationContinuous") ); } if (HXR_OK == retVal) { pHeader->SetPropertyCString( "intrinsicDurationType",pIntrDurTypeBuf); } HX_RELEASE(pIntrDurTypeBuf); } //The following is sent by the RT file format to the // RT renderer to notify it what "parsing" version to // use. This is done via the stream header properties // "RTMarkupParsing[Major|Minor]Version". // This must be done so that the ff and the renderer // are in sync as far as how they deal with new tags, // e.g., if the file format ignores a tag it doesn't // recognize but the renderer is newer and recognizes // the tag, the renderer should behave as does the ff // and ignore the tag otherwise the renderer might // display the text in a different place than the ff // thinks it is and the next packet sent by the ff // will tell the renderer to draw in a place that // might overlap the prior packet's text due to this // discrepancy. pHeader->SetPropertyULONG32( "RTMarkupParsingMajorVersion", REAL_TEXT_MARKUP_PARSING_MAJOR_VERSION); pHeader->SetPropertyULONG32( "RTMarkupParsingMinorVersion", REAL_TEXT_MARKUP_PARSING_MINOR_VERSION); //Check if the content version is something that this // file format recognizes: BOOL bVersionIsRecognizedByThisFF = TRUE; if((m_pTextWindow->getMajorContentVersion() > REAL_TEXT_CONTENT_MAJOR_VERSION) || (m_pTextWindow->getMajorContentVersion() == REAL_TEXT_CONTENT_MAJOR_VERSION && m_pTextWindow->getMinorContentVersion() > REAL_TEXT_CONTENT_MINOR_VERSION) ) { bVersionIsRecognizedByThisFF = FALSE; } ULONG32 ulMinRTMajorVersion = 0L; ULONG32 ulMinRTMinorVersion = 0L; //Check if the content version is something that an // older, pre-"version=..."-handling rtrender (which // means any pre-April 1999 public release) can // handle: if((m_pTextWindow->getMajorContentVersion() > REAL_TEXT_1ST_MAJ_VER_POST_VER_TAG) || (m_pTextWindow->getMajorContentVersion() == REAL_TEXT_1ST_MAJ_VER_POST_VER_TAG && m_pTextWindow->getMinorContentVersion() >= REAL_TEXT_1ST_MNR_VER_POST_VER_TAG) ) { if((ulMinRTMajorVersion < REAL_TEXT_1ST_MAJ_VER_POST_VER_TAG) || (REAL_TEXT_1ST_MAJ_VER_POST_VER_TAG== ulMinRTMajorVersion && ulMinRTMinorVersion < REAL_TEXT_1ST_MNR_VER_POST_VER_TAG) ) { //Use these to force auto-upgrade in the // older rtrenders: ulMinRTMajorVersion = REAL_TEXT_1ST_MAJ_VER_POST_VER_TAG; ulMinRTMinorVersion = REAL_TEXT_1ST_MNR_VER_POST_VER_TAG; } } //These (put together) are the minimum version that // the renderer must know about. If the renderer is // older, it must fire auto-upgrade (but note: pre- // Gold renderers (i.e., pre 11/23/1998 release) // don't handle this and may render poorly if // the following values are greater than 1.0: // New note: all pre-gold renderers have expired // as of 3/1999, so no worries. pHeader->SetPropertyULONG32("MinRTMajorVersion", ulMinRTMajorVersion); pHeader->SetPropertyULONG32("MinRTMinorVersion", ulMinRTMinorVersion); //These (put together) are the version that the rt // file's author has declared for the file contents. // If omitted from the file, it is 0.0: Note: this // allows us to properly deal with future changes to // the header and other tags in the rt file, namely: // force auto-upgrade of renderer: pHeader->SetPropertyULONG32("RTMajorContentVersion", m_pTextWindow->getMajorContentVersion() ); pHeader->SetPropertyULONG32("RTMinorContentVersion", m_pTextWindow->getMinorContentVersion() ); pSNBuf->Set((const BYTE*)szStreamName, strlen(szStreamName)+1); pMTBuf->Set((const BYTE*)szMimeType, strlen(szMimeType)+1); pHeader->SetPropertyCString("StreamName", pSNBuf); pHeader->SetPropertyCString("MimeType", pMTBuf); IHXBuffer* pASM = 0; char pBook[256]; /* Flawfinder: ignore */#ifdef _DEBUG#if defined(RT_OUTPUT_LOGFILE) if(m_txtWin.getDebugFlags()&RT_FF_DEBUG_FLAGS_MASK && !m_logfile) //Only create log for 1st stream. {#if defined(_UNIX) || defined(_WINDOWS) char logfilename[32]; /* Flawfinder: ignore */#endif char slashChar = '\\';#if defined(_UNIX) slashChar = '/';#endif#if defined(_MACINTOSH) fopen("Macintosh HD:RT Debug:rtff_0.log", "w");#endif#if defined(_UNIX) || defined(_WINDOWS) sprintf(logfilename,"c:%crtff_%u.log", slashChar, /* Flawfinder: ignore */ uStreamNumber); m_logfile=fopen(logfilename,"w");#endif if(m_logfile) { fprintf(m_logfile,"Stream number %u\n", uStreamNumber); fprintf(m_logfile,"Max bit rate %lu\n", ulMaxBitRate); fprintf(m_logfile,"Avg bit rate %lu\n", ulAvgBitRate); fprintf(m_logfile,"Max packet size %lu\n", ulMaxPacketSize); fprintf(m_logfile,"Avg packet size %lu\n", ulAvgPacketSize); fprintf(m_logfile,"Start time %lu ms\n", ulStartTime); fprintf(m_logfile,"Preroll %lu ms\n", ulPreroll); fprintf(m_logfile,"Duration %lu ms\n", GetDuration()); fprintf(m_logfile,"Stream name: %s\n", szStreamName); fprintf(m_logfile,"Header opaque data length: %lu\n", pLoppedHdr->GetSize()); fprintf(m_logfile,"Header opaque data:{{{%s}}}\n", pLoppedHdr->GetBuffer()); fflush(m_logfile); } }#endif#endif //Priority=10 is for all packets that contain any // text marked as <REQUIRED>. Priority=9 is for all // other packets: sprintf(pBook, "priority=9,timestampdelivery=true; priority=10,timestampdelivery=true;"); /* Flawfinder: ignore */ if (HXR_OK == pCommonClassFactory->CreateInstance( CLSID_IHXBuffer, (void**)&pASM)) { pASM->Set((const unsigned char *)pBook, sizeof(pBook)); pHeader->SetPropertyCString("ASMRuleBook", pASM); pASM->Release(); } // Tell the FormatResponse of our success in // getting the header. if(bVersionIsRecognizedByThisFF) { m_pFFResponse->StreamHeaderReady(status, pHeader); } else { IHXErrorMessages* pErrorMessages; if (m_pContext && HXR_OK != m_pContext->QueryInterface( IID_IHXErrorMessages, (void**)&pErrorMessages)) { pErrorMessages = NULL; } if (pErrorMessages) { const char* pFilename = "[rt file]"; if(m_pFileObject) { m_pFileObject->GetFilename(pFilename); } char* pTmp; pTmp = new char[256]; sprintf(pTmp, /* Flawfinder: ignore */ "Version in \"%s\" is not recognized by installed" " RealText file format", pFilename); pErrorMessages->Report(HXLOG_ERR, HXR_INVALID_VERSION, 0, (const char*) pTmp, NULL); HX_RELEASE(pErrorMessages); delete [] pTmp; } // Tell the FormatResponse that we found content // we can't handle: m_pFFResponse->StreamHeaderReady( HXR_INVALID_VERSION, NULL); } // Release our reference on the header! pHeader->Release(); pSNBuf->Release(); pMTBuf->Release(); pLoppedHdr->Release(); } pCommonClassFactory->Release(); } } else {#ifdef _DEBUG#if defined(RT_OUTPUT_LOGFILE) if(m_logfile && m_txtWin.getDebugFlags()&RT_FF_DEBUG_FLAGS_MASK) { fprintf(m_logfile,"StreamHeader read failed.\n"); fflush(m_logfile); }#endif#endif // Tell the FormatResponse that the read failed so we're // at the end of the file: m_pFFResponse->StreamHeaderReady(HXR_INVALID_FILE, NULL); } } break; case GetPacketSeekTooFarFwdReadPending: case GetPacketReadPending: { // We are in the process of responding to a GetPacket() // request and the read has completed, which means we // are done and can go back to the ready state... m_state = Ready; if (status == HXR_OK) { // We now need to form a "packet" object and pass it // off to our controller. Notice since our packet data // comes straight out of the file as is, we don't need // to copy data at all, the IHXBuffer returned by read // can be placed into the packet object and passed off. // Create packet object here, notice that we call the // CreateInstance method of the controller, but we could // have implemented our own object that exposed the IHXPacket // interface. IHXPacket* pPacket; IHXCommonClassFactory* pCommonClassFactory; if (HXR_OK == m_pContext->QueryInterface( IID_IHXCommonClassFactory, (void **)&pCommonClassFactory)) { if (HXR_OK == pCommonClassFactory-> CreateInstance(CLSID_IHXPacket, (void**)&pPacket)) { IHXBuffer* pLoppedPkt = NULL; char szLoppedPkt[MAX_PACKET_SIZE+MAX_PKT_HDR_SZ+1] = /* Flawfinder: ignore */ { 0 }; // Go through the pBuffer from the end and look for // a '<' or a '>'; if a '>' comes first, send the // whole packet (since we're not inside a <..> tag. // If a '<' comes first, send everything that comes // before it. ULONG32 ulBufSize = pBuffer->GetSize(); if(ulBufSize > MAX_PACKET_SIZE) { //this line should never get hit: ulBufSize = MAX_PACKET_SIZE; } memcpy(szLoppedPkt, /* Flawfinder: ignore */ (char*)(pBuffer->GetBuffer()), ulBufSize); szLoppedPkt[ulBufSize] = '\0'; //XXXEH-: how do we know what charset // we're in if we haven't parsed it yet? This is // probably the reason HTML makes you declare the // solo charset for the whole doc in the header... //Added this DBCS-friendly version // of the search code. Now, the code has to search // from the start of the buffer to find out where the // last '<' and '>' are, if any: ULONG32 indx; LONG32 lHighestLessThanCharIndex = -1L; LONG32 lHighestGreaterThanCharIndex = -1L; LONG32 lHighestSpaceTabNewlineCharOutsideTagIndex = -1L; LONG32 lHighestBRorPtagStartIndx = -1L; //for contiguous-BR-determining: LONG32 lMostRecentBRorPTagStartIndx = -1L; BOOL bIsInsideTag = FALSE; BOOL bEndsOnALeadByteOfDualByteChar = FALSE; for(indx=0L; indx<ulBufSize; indx++) { char ch = szLoppedPkt[indx]; if((UCHAR)ch >= DBCS_MIN_LEAD_BYTE_VAL) { indx++; if(indx==ulBufSize) { //lead byte w/no trail byte, so back up: bEndsOnALeadByteOfDualByteChar = TRUE; break; } continue; //skip over DBCS chars. } else if('>' == ch) { lHighestGreaterThanCharIndex = (LONG32)indx; bIsInsideTag = FALSE; continue; } else if('<' == ch) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -