📄 ps2ts.cpp
字号:
// Build the TS header to put this date *pPosInTs = pPacket->BuildAdaptionField(iSCR); } else { // Parse the SCR (MPEG2 format) u64 iHighBits = m_bBuff[START_CODE_LEN] & 0x38; u64 iMiddleBits = U32_AT(m_bBuff[START_CODE_LEN]) & 0x03FFF800; u64 iLowBits = U32_AT(m_bBuff[START_CODE_LEN+2]) & 0x03FFF800; ASSERT((m_bBuff[START_CODE_LEN] & 0x4)); ASSERT((m_bBuff[START_CODE_LEN+2] & 0x4)); ASSERT((m_bBuff[START_CODE_LEN+4] & 0x4)); u64 iSCR = iHighBits << 27 | iMiddleBits << 4 | iLowBits >> 11; // Kludge pour tester horloge// struct timeval sTimeval;// gettimeofday(&sTimeval, NULL);// printf("Date mpeg2: %Ld, date systeme %d (en s)\n", iSCR, sTimeval.tv_sec); // Build the TS header to put this date *pPosInTs = pPacket->BuildAdaptionField(iSCR);// if(iSCR - m_iPrevSCR > 800)// printf("time : %Ld ; delta : %Ld\n", iSCR, iSCR - m_iPrevSCR); if(m_iPrevSCR >= iSCR) { printf("Time discontinuity in PS stream\n"); m_bDiscontinuity = true; } m_iPrevSCR = iSCR; // Read additional stuffing bytes if any (MPEG2 only) if(m_iPackHeaderLen == 10 + START_CODE_LEN) { iStuffLen = m_bBuff[m_iPackHeaderLen-1] & 0x7; if(iStuffLen && !iRc) { iRc = m_pReader->Read(m_bBuff+LOOK_AHEAD_LEN+m_iPackHeaderLen, iStuffLen); ASSERT(iRc >= 0); iRc = (iRc != iStuffLen); }// printf("Stuffing of size %d found: actual length is: %d\n", iStuffLen, m_iPackHeaderLen+iStuffLen); } } // Look Ahead of 6 m_iDataType = U32_AT(m_bBuff[m_iPackHeaderLen+iStuffLen]); m_pCurrentData = m_cPgrmDescriptor.GetDescriptor(m_iDataType & 0xFF); m_iDataLen = U16_AT(m_bBuff[m_iPackHeaderLen+iStuffLen+START_CODE_LEN]); m_bPESStart = true; //printf("Next data will be: %X (len: %d)\n", m_iNextData, m_iNextLength);// printf("Next data will be: %X (len: %d)\n", m_iDataType, m_iDataLen); return iRc;}//------------------------------------------------------------------------------////------------------------------------------------------------------------------template <class Reader, class TsProvider> int C_Ps2Ts<Reader, TsProvider>::ParseSystemHeader(C_TsPacket* pPacket, u8* iPosInTs){// printf("Parsing SYSTEM_HEADER\n"); int iRc = m_pReader->Read(m_bBuff, m_iDataLen+LOOK_AHEAD_LEN); ASSERT(iRc >= 0); iRc = (iRc != m_iDataLen+LOOK_AHEAD_LEN);// printf("Length: %d\n", m_iDataLen); m_iDataType = U32_AT(m_bBuff[m_iDataLen]); m_pCurrentData = m_cPgrmDescriptor.GetDescriptor(m_iDataType & 0xFF); m_iDataLen = U16_AT(m_bBuff[m_iDataLen+START_CODE_LEN]); return iRc;}//------------------------------------------------------------------------------////------------------------------------------------------------------------------template <class Reader, class TsProvider> int C_Ps2Ts<Reader, TsProvider>::ParsePES(C_TsPacket* pPacket, u8* pPosInTs){ ASSERT(pPacket); ASSERT(pPosInTs); // Pour le debug uniquement// if(m_bPESStart)// {// printf("Parsing PES of type %x\n", m_iDataType);// printf("PES Length: %d (without the 6 first bytes)\n", m_iDataLen);// }// else// printf("Continuing to parse PES (remaining length: %d)\n", m_iDataLen); // This variable only exists to speed up the process of looking the value of // pPosInTs u8 iPos; // Write the data in the TS that depends on our position in the PES if(m_bPESStart) { // Write the header with the bUnitStart flag set to true ASSERT(m_pCurrentData); ASSERT(m_pCurrentData->GetId() == (m_iDataType&0xFF)); u8 iCounter = m_pCurrentData->GetCounter(); u16 iPid = m_pCurrentData->GetPid(); iPos = pPacket->BuildHeader(iPid, true, iCounter); // We can have parsed an adaption field if the PES comes just after a // pack header if(iPos < *pPosInTs) { if(iPid == m_cPgrmDescriptor.GetPcrPid()) { // The adaption_field_control has been overwritten so that the bit // which indicates an adaption_field is no more set to 1 byte* pTsPayload = (byte*)(*pPacket); pTsPayload[iPos-1] |= 0x20; // Set the right position iPos = *pPosInTs; if(m_bDiscontinuity) { ASSERT(pPacket->HasPCR()); ASSERT(pPacket->SetDiscontinuityFlag()); pPacket->SetDiscontinuityFlag(); m_bDiscontinuity = false; } } } // Write the beginning of the PES packet (corresponds to the look ahead) byte* pTsPayload = (byte*)(*pPacket); SET_U32_TO(pTsPayload[iPos], m_iDataType); SET_U16_TO(pTsPayload[iPos+START_CODE_LEN], m_iDataLen); iPos += START_CODE_LEN + PES_SIZE_LEN; } else { // We shouldn't have any adaption field ASSERT(*pPosInTs == 0); // Write the header with the bUnitStart flag set to false ASSERT(m_pCurrentData); ASSERT(m_pCurrentData->GetId() == (m_iDataType&0xFF)); u8 iCounter = m_pCurrentData->GetCounter(); u16 iPid = m_pCurrentData->GetPid(); iPos = pPacket->BuildHeader(iPid, false, iCounter); } // Now read the data carried in the PES for(unsigned int i = 0; i < m_iMaxBufferedTs; i++) { // Fill the Ts packet if(m_iDataLen >= TS_PACKET_LEN - iPos) { // Fill the remaining payload of the TS packet m_iStatus = m_pReader->Read(((byte*)(*pPacket)+iPos), TS_PACKET_LEN-iPos); ASSERT(m_iStatus >= 0); m_iStatus = (m_iStatus != TS_PACKET_LEN-iPos); m_iDataLen -= (TS_PACKET_LEN-iPos); //----------------- if(m_bPESStart) { if(*((byte*)(*pPacket) + iPos - 3) == PES_ID_PRIVATE_1) {// printf("Id : 0x%x", *((byte*)(*pPacket) + iPos - 3)); u8 iOffset = *((byte*)(*pPacket) + iPos + 2);// printf(" Offset : 0x%x", iOffset); u8 iPrivateId = *((byte*)(*pPacket) + iPos + 3 + iOffset);// printf(" PrivateId : 0x%x", iPrivateId);/* if((iPrivateId & 0xf0) == 0x80) {*/ m_pCurrentData = m_cPgrmDescriptor.GetDescriptor(m_iDataType & 0xFF, iPrivateId); u16 iPid = m_pCurrentData->GetPid(); u16 iData = U16_AT(*((byte*)(pPacket) + 1));// printf(" Data : 0x%x", iData); iPid = (iPid & 0x1fff) | (iData & 0xe000);// printf(" NewPid : 0x%x", iPid); SET_U16_TO(*((byte*)(pPacket) + 1), iPid); *((byte*)(pPacket) + 3) = (m_pCurrentData->GetCounter() & 0x0f) | (*((byte*)(pPacket) + 3) & 0xf0);/* }*/// printf("\n"); } } //----------------- } else { // m_iDataLen shouldn't be null ASSERT(m_iDataLen > 0);// printf("Stuffing needed: iPos=%d, DataLen=%d\n", iPos, m_iDataLen); // Write the end of the PES packet in the TS packet if(m_bPESStart) { // We have already written the PES start code and the pes length at the // beginning of the TS packet, which will be erased by the stuffing bytes: // we must rewrite them iPos = pPacket->AddStuffingBytes(m_iDataLen+START_CODE_LEN+PES_SIZE_LEN); byte* pTsPayload = (byte*)(*pPacket); SET_U32_TO(pTsPayload[iPos], m_iDataType); SET_U16_TO(pTsPayload[iPos+START_CODE_LEN], m_iDataLen); iPos += START_CODE_LEN+PES_SIZE_LEN; } else { // Simply add the stuffing bytes at the end of the TS header iPos = pPacket->AddStuffingBytes(m_iDataLen); } m_iStatus = m_pReader->Read(((byte*)(*pPacket)+iPos), m_iDataLen); ASSERT(m_iStatus >= 0); m_iStatus = (m_iStatus != m_iDataLen); //----------------- if(m_bPESStart) { if(*((byte*)(*pPacket) + iPos - 3) == PES_ID_PRIVATE_1) {// printf("Id : 0x%x", *((byte*)(*pPacket) + iPos - 3)); u8 iOffset = *((byte*)(*pPacket) + iPos + 2);// printf(" Offset : 0x%x", iOffset); u8 iPrivateId = *((byte*)(*pPacket) + iPos + 3 + iOffset);// printf(" PrivateId : 0x%x", iPrivateId);/* if((iPrivateId & 0xf0) == 0x80) {*/ m_pCurrentData = m_cPgrmDescriptor.GetDescriptor(m_iDataType & 0xFF, iPrivateId); u16 iPid = m_pCurrentData->GetPid(); u16 iData = U16_AT(*((byte*)(pPacket) + 1));// printf(" Data : 0x%x", iData); iPid = (iPid & 0x1fff) | (iData & 0xe000);// printf(" NewPid : 0x%x", iPid); SET_U16_TO(*((byte*)(pPacket) + 1), iPid); *((byte*)(pPacket) + 3) = (m_pCurrentData->GetCounter() & 0x0f) | (*((byte*)(pPacket) + 3) & 0xf0);/* }*/// printf("\n"); } } //----------------- // All data have been read m_iDataLen = 0; } // We are no more at the beginning of the PES yet m_bPESStart = false; // Increase the number of TS packets that have been build m_pCurrentData->IncreaseCounter(); m_iTSCounter++; if(m_cPgrmDescriptor.m_bNewPmt) { // Delay this packet to send PSI first ASSERT(!m_pDelayedPacket); m_pDelayedPacket = pPacket; m_bSendPSI = m_bGenPmt = m_bResetPSI = true; m_cPgrmDescriptor.m_bNewPmt = false; i = m_iMaxBufferedTs - 1; } else { // Put the TS packet in the list of pending TS m_cPendingTS.PushEnd(pPacket); } ZERO(pPacket); // Prepare the next iteration if we must loop if(m_iDataLen > 0) { // There is a second condition for looping since we don't read // the complete PES in a single operation if(i < m_iMaxBufferedTs - 1) { // Get another TS packet to fill pPacket = m_pTsProvider->GetPacket(); ASSERT(pPacket); // Build the new TS header ASSERT(m_pCurrentData); ASSERT(m_pCurrentData->GetId() == (m_iDataType&0xFF)); u8 iCounter = m_pCurrentData->GetCounter(); u16 iPid = m_pCurrentData->GetPid(); iPos = pPacket->BuildHeader(iPid, false, iCounter); } } else { // Look ahead for next iteration m_iStatus = m_pReader->Read(m_bBuff, LOOK_AHEAD_LEN); ASSERT(m_iStatus >= 0); m_iStatus = (m_iStatus != LOOK_AHEAD_LEN); m_iDataType = U32_AT(m_bBuff[0]); m_pCurrentData = m_cPgrmDescriptor.GetDescriptor(m_iDataType & 0xFF); m_iDataLen = U16_AT(m_bBuff[4]); m_bPESStart = true;// printf("Next data will be: %x (len = %d)\n", m_iDataType, m_iDataLen); // Don't loop break; } } return m_iStatus;}//------------------------------------------------------------------------------////------------------------------------------------------------------------------template <class Reader, class TsProvider> int C_Ps2Ts<Reader, TsProvider>::SkipPES(C_TsPacket* pPacket, u8* iPosInTs){ // Release the TS packet, we won't need it m_pTsProvider->ReleasePacket(pPacket); int iRc = m_pReader->Seek(m_iDataLen, SEEK_CUR); if(iRc) m_iStatus = FILE_ERR; else { // Look ahead for next iteration m_iStatus = m_pReader->Read(m_bBuff, LOOK_AHEAD_LEN); ASSERT(m_iStatus >= 0); m_iStatus = (m_iStatus != LOOK_AHEAD_LEN); m_iDataType = U32_AT(m_bBuff[0]); m_pCurrentData = m_cPgrmDescriptor.GetDescriptor(m_iDataType & 0xFF); m_iDataLen = U16_AT(m_bBuff[4]); m_bPESStart = true;// printf("Next data will be: %x (len = %d)\n", m_iDataType, m_iDataLen); if(m_iStatus == NO_ERR) m_iStatus = SKIPPED_DATA; } return m_iStatus;}//------------------------------------------------------------------------------////------------------------------------------------------------------------------template <class Reader, class TsProvider> int C_Ps2Ts<Reader, TsProvider>::ParsePgrmMap(C_TsPacket* pPacket, u8* iPosInTs){// printf("Parsing pgrm map PES: WARNING, code never tested\n");// printf("Pgrm map length: %d\n", m_iDataLen); ASSERT(false); while(m_iDataLen >= sizeof(m_bBuff)) {/* int iRc = */m_pReader->Read(m_bBuff, sizeof(m_bBuff)); m_iDataLen -= sizeof(m_bBuff); } // push PAT et PMT dans la liste des pendingpackets return NO_ERR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -