Boolean MPEG2TransportStreamIndexFile::rewindToVSH(unsigned long&ixFound) { Boolean success = False; while (ixFound > 0) { if (!readIndexRecord(ixFound)) break; u_int8_t recordType = recordTypeFromBuf(); if ((recordType&0x80) != 0 && (recordType&0x7F) <= 2/*GOP*/) { if ((recordType&0x7F) == 2) { // This is a GOP. Hack: If the preceding record is for a Video Sequence Header, // then use it instead: unsigned long newIxFound = ixFound; while (--newIxFound > 0) { if (!readIndexRecord(newIxFound)) break; recordType = recordTypeFromBuf(); if ((recordType&0x7F) != 1) break; // not a Video Sequence Header if ((recordType&0x80) != 0) { // this is the start of the VSH; use it ixFound = newIxFound; break; } } } // Record 'ixFound' as appropriate to return: success = True; break; } --ixFound; } if (ixFound == 0) success = True; // use record 0 anyway return success; }
Boolean MPEG2TransportStreamIndexFile::rewindToCleanPoint(unsigned long&ixFound) { Boolean success = False; // until we learn otherwise while (ixFound > 0) { if (!readIndexRecord(ixFound)) break; u_int8_t recordType = recordTypeFromBuf(); setMPEGVersionFromRecordType(recordType); // A 'clean point' is the start of a 'frame' from which a decoder can cleanly resume // handling the stream. For H.264, this is a SPS. For H.265, this is a VPS. // For MPEG-2, this is a Video Sequence Header, or a GOP. if ((recordType&0x80) != 0) { // This is the start of a 'frame' recordType &=~ 0x80; // remove the 'start of frame' bit if (fMPEGVersion == 5) { // H.264 if (recordType == 5/*SPS*/) { success = True; break; } } else if (fMPEGVersion == 6) { // H.265 if (recordType == 11/*VPS*/) { success = True; break; } } else { // MPEG-1, 2, or 4 if (recordType == 1/*VSH*/) { success = True; break; } else if (recordType == 2/*GOP*/) { // Hack: If the preceding record is for a Video Sequence Header, then use it instead: unsigned long newIxFound = ixFound; while (--newIxFound > 0) { if (!readIndexRecord(newIxFound)) break; recordType = recordTypeFromBuf(); if ((recordType&0x7F) != 1) break; // not a Video Sequence Header if ((recordType&0x80) != 0) { // this is the start of the VSH; use it ixFound = newIxFound; break; } } } success = True; break; } } // Keep checking, from the previous record: --ixFound; } if (ixFound == 0) success = True; // use record 0 anyway return success; }
int MPEG2TransportStreamIndexFile::mpegVersion() { if (fMPEGVersion != 0) return fMPEGVersion; // we already know it // Read the first index record, and figure out the MPEG version from its type: if (!readOneIndexRecord(0)) return 0; // unknown; perhaps the indecx file is empty? setMPEGVersionFromRecordType(recordTypeFromBuf()); return fMPEGVersion; }
Boolean MPEG2TransportStreamIndexFile ::readIndexRecordValues(unsigned long indexRecordNum, unsigned long& transportPacketNum, u_int8_t& offset, u_int8_t& size, float& pcr, u_int8_t& recordType) { if (!readIndexRecord(indexRecordNum)) return False; transportPacketNum = tsPacketNumFromBuf(); offset = offsetFromBuf(); size = sizeFromBuf(); pcr = pcrFromBuf(); recordType = recordTypeFromBuf(); return True; }