diff --git a/lib/h264.cpp b/lib/h264.cpp index 04856bab..924db003 100644 --- a/lib/h264.cpp +++ b/lib/h264.cpp @@ -801,6 +801,7 @@ namespace h264 { seiUnit::seiUnit(const char * data, size_t len) : nalUnit(data, len) { Utils::bitstream bs; + payloadOffset = 1; for (size_t i = 1; i < len; i++) { if (i + 2 < len && (memcmp(data + i, "\000\000\003", 3) == 0)){//Emulation prevention bytes //Yes, we increase i here @@ -812,25 +813,45 @@ namespace h264 { } } uint8_t tmp = bs.get(8); + ++payloadOffset; payloadType = 0; while (tmp == 0xFF){ payloadType += tmp; tmp = bs.get(8); + ++payloadOffset; } payloadType += tmp; tmp = bs.get(8); + ++payloadOffset; payloadSize = 0; while (tmp == 0xFF){ payloadSize += tmp; tmp = bs.get(8); + ++payloadOffset; } payloadSize += tmp; } void seiUnit::toPrettyString(std::ostream & out) { out << "Nal unit of type " << (((uint8_t)payload[0]) & 0x1F) << " [Supplemental Enhancement Unit] , " << payload.size() << " bytes long" << std::endl; - out << " Message of type " << payloadType << ", " << payloadSize << " bytes long" << std::endl; + switch (payloadType){ + case 5:{//User data, unregistered + out << " Type 5: User data, unregistered." << std::endl; + std::stringstream uuid; + for (uint32_t i = payloadOffset; i < payloadOffset+16; ++i){ + uuid << std::setw(2) << std::setfill('0') << std::hex << (int)(payload.data()[i]); + } + if (uuid.str() == "dc45e9bde6d948b7962cd820d923eeef"){ + uuid.str("x264 encoder configuration"); + } + out << " UUID: " << uuid.str() << std::endl; + out << " Payload: " << std::string(payload.data()+payloadOffset+16, payloadSize - 17) << std::endl; + } + break; + default: + out << " Message of type " << payloadType << ", " << payloadSize << " bytes long" << std::endl; + } } nalUnit * nalFactory(const char * _data, size_t _len, size_t & offset, bool annexb) { @@ -855,7 +876,7 @@ namespace h264 { if (!annexb){ //read the 4b size in front pktLen = Bit::btohl(_data+offset); - if (_len < 4 + pktLen){ + if (_len - offset < 4 + pktLen){ WARN_MSG("Not at least 4+%lu bytes available - cancelling", pktLen); return 0; } @@ -867,9 +888,9 @@ namespace h264 { //search for the next start marker for (size_t i = 1; i < len-2; ++i){ if (data[i] == 0 && data[i+1] == 0 && data[i+2] == 1){ - offset += i+3; while (i && !data[i]){--i;} - pktLen = i + 1; + pktLen = i+1; + offset += pktLen; break; } } @@ -883,6 +904,7 @@ namespace h264 { switch (data[0] & 0x1F){ case 1: case 5: + case 19: return new codedSliceUnit(data, pktLen); case 6: return new seiUnit(data, pktLen); @@ -920,6 +942,7 @@ namespace h264 { switch (data[0] & 0x1F){ case 1: case 5: + case 19: result = new codedSliceUnit(data, nextPos); break; case 6: diff --git a/lib/h264.h b/lib/h264.h index d54748c9..6e2bb2f0 100644 --- a/lib/h264.h +++ b/lib/h264.h @@ -294,6 +294,7 @@ namespace h264 { uint32_t payloadType; uint32_t payloadSize; + uint32_t payloadOffset; }; diff --git a/src/analysers/analyser_h264.cpp b/src/analysers/analyser_h264.cpp index dc6f55f3..d92b03b9 100644 --- a/src/analysers/analyser_h264.cpp +++ b/src/analysers/analyser_h264.cpp @@ -22,7 +22,6 @@ AnalyserH264::AnalyserH264(Util::Config &conf) : Analyser(conf){ } bool AnalyserH264::parsePacket(){ - prePos = curPos; // Read in smart bursts until we have enough data while (isOpen() && dataBuffer.size() < neededBytes()){ uint64_t needed = neededBytes(); @@ -35,16 +34,22 @@ bool AnalyserH264::parsePacket(){ } size_t size = 0; - h264::nalUnit *nalPtr = - h264::nalFactory(dataBuffer.data(), dataBuffer.size(), size, !sizePrepended); + h264::nalUnit *nalPtr; + do { + size = 0; + nalPtr = h264::nalFactory(dataBuffer.data(), dataBuffer.size(), size, !sizePrepended); + if (nalPtr){ + HIGH_MSG("Read a %lu-byte NAL unit at position %llu", size, prePos); + if (detail >= 2){nalPtr->toPrettyString(std::cout);} + dataBuffer.erase(0, size); // erase the NAL unit we just read + prePos += size; + } + ///\TODO update mediaTime with current timestamp + } while(nalPtr); if (!nalPtr){ FAIL_MSG("Could not read a NAL unit at position %llu", prePos); return false; } - HIGH_MSG("Read a %lu-byte NAL unit at position %llu", size, prePos); - dataBuffer.erase(0, size); // erase the NAL unit we just read - if (detail >= 2){nalPtr->toPrettyString(std::cout);} - ///\TODO update mediaTime with current timestamp return true; }