Fixed H264 analyser + H264 pretty printing improvements

This commit is contained in:
Thulinma 2021-02-15 21:15:59 +01:00
parent 7124f6070b
commit de0423a9da
4 changed files with 78 additions and 18 deletions

View file

@ -428,16 +428,63 @@ namespace h264{
payload.insert(4, 1, 0x08); payload.insert(4, 1, 0x08);
} }
const char* spsUnit::profile(){
if (profileIdc == 66){
if (constraintSet1Flag){return "Constrained baseline";}
return "Baseline";
}
if (profileIdc == 77){return "Main";}
if (profileIdc == 88){return "Extended";}
if (profileIdc == 100){return "High";}
if (profileIdc == 110){
if (constraintSet3Flag){return "High-10 Intra";}
return "High-10";
}
if (profileIdc == 122){
if (constraintSet3Flag){return "High-4:2:2 Intra";}
return "High-4:2:2";
}
if (profileIdc == 244){
if (constraintSet3Flag){return "High-4:4:4 Intra";}
return "High-4:4:4";
}
if (profileIdc == 44){return "CAVLC 4:4:4 Intra";}
return "Unknown";
}
const char* spsUnit::level(){
if (levelIdc == 9){return "1b";}
if (levelIdc == 10){return "1";}
if (levelIdc == 11){
if (constraintSet3Flag){return "1b";}
return "1.1";
}
if (levelIdc == 12){return "1.2";}
if (levelIdc == 13){return "1.3";}
if (levelIdc == 20){return "2";}
if (levelIdc == 21){return "2.1";}
if (levelIdc == 21){return "2.2";}
if (levelIdc == 30){return "3";}
if (levelIdc == 31){return "3.1";}
if (levelIdc == 31){return "3.2";}
if (levelIdc == 40){return "4";}
if (levelIdc == 41){return "4.1";}
if (levelIdc == 41){return "4.2";}
if (levelIdc == 50){return "5";}
if (levelIdc == 51){return "5.1";}
return "Unknown";
}
void spsUnit::toPrettyString(std::ostream &out){ void spsUnit::toPrettyString(std::ostream &out){
out << "Nal unit of type " << (((uint8_t)payload[0]) & 0x1F) << " [Sequence Parameter Set] , " out << "Nal unit of type " << (((uint8_t)payload[0]) & 0x1F) << " [Sequence Parameter Set] , "
<< payload.size() << " bytes long" << std::endl; << payload.size() << " bytes long" << std::endl;
out << " profile_idc: 0x" << std::setw(2) << std::setfill('0') << std::hex << (int)profileIdc out << " profile_idc: 0x" << std::setw(2) << std::setfill('0') << std::hex << (int)profileIdc
<< std::dec << " (" << (int)profileIdc << ")" << std::endl; << std::dec << " (" << (int)profileIdc << ") = " << profile() << std::endl;
out << " contraints: " << (constraintSet0Flag ? "0 " : "") << (constraintSet1Flag ? "1 " : "") out << " contraints: " << (constraintSet0Flag ? "0 " : "") << (constraintSet1Flag ? "1 " : "")
<< (constraintSet2Flag ? "2 " : "") << (constraintSet3Flag ? "3 " : "") << (constraintSet2Flag ? "2 " : "") << (constraintSet3Flag ? "3 " : "")
<< (constraintSet4Flag ? "4 " : "") << (constraintSet5Flag ? "5" : "") << std::endl; << (constraintSet4Flag ? "4 " : "") << (constraintSet5Flag ? "5" : "") << std::endl;
out << " level_idc: 0x" << std::setw(2) << std::setfill('0') << std::hex << (int)levelIdc out << " level_idc: 0x" << std::setw(2) << std::setfill('0') << std::hex << (int)levelIdc
<< std::dec << " (" << (int)profileIdc << ")" << std::endl; << std::dec << " (" << (int)levelIdc << ") = " << level() << std::endl;
out << " seq_parameter_set_id: " << seqParameterSetId out << " seq_parameter_set_id: " << seqParameterSetId
<< (seqParameterSetId >= 32 ? " INVALID" : "") << std::endl; << (seqParameterSetId >= 32 ? " INVALID" : "") << std::endl;
switch (profileIdc){ switch (profileIdc){
@ -1052,10 +1099,12 @@ namespace h264{
chromaSampleLocTypeBottomField = bs.getUExpGolomb(); chromaSampleLocTypeBottomField = bs.getUExpGolomb();
} }
timingInfoPresentFlag = bs.get(1); timingInfoPresentFlag = bs.get(1);
derived_fps = 0.0;
if (timingInfoPresentFlag){ if (timingInfoPresentFlag){
numUnitsInTick = bs.get(32); numUnitsInTick = bs.get(32);
timeScale = bs.get(32); timeScale = bs.get(32);
fixedFrameRateFlag = bs.get(1); fixedFrameRateFlag = bs.get(1);
derived_fps = (double)timeScale / (2 * numUnitsInTick);
} }
nalHrdParametersPresentFlag = bs.get(1); nalHrdParametersPresentFlag = bs.get(1);
// hrd param nal // hrd param nal

View file

@ -150,6 +150,7 @@ namespace h264{
uint64_t log2MaxMvLengthVertical; uint64_t log2MaxMvLengthVertical;
uint64_t numReorderFrames; uint64_t numReorderFrames;
uint64_t maxDecFrameBuffering; uint64_t maxDecFrameBuffering;
double derived_fps;
}; };
class spsUnit : public nalUnit{ class spsUnit : public nalUnit{
@ -158,6 +159,8 @@ namespace h264{
~spsUnit(){ ~spsUnit(){
if (scalingListPresentFlags != NULL){free(scalingListPresentFlags);} if (scalingListPresentFlags != NULL){free(scalingListPresentFlags);}
} }
const char* profile();
const char* level();
std::string generate(); std::string generate();
void toPrettyString(std::ostream &out); void toPrettyString(std::ostream &out);
void scalingList(uint64_t *scalingList, size_t sizeOfScalingList, void scalingList(uint64_t *scalingList, size_t sizeOfScalingList,

View file

@ -51,7 +51,7 @@ bool Analyser::isOpen(){
int Analyser::run(Util::Config &conf){ int Analyser::run(Util::Config &conf){
isActive = &conf.is_active; isActive = &conf.is_active;
if (!open(conf.getString("filename"))){return 1;} if (!open(conf.getString("filename"))){return 1;}
while (conf.is_active && isOpen()){ while (conf.is_active){
if (!parsePacket()){ if (!parsePacket()){
if (isOpen()){ if (isOpen()){
FAIL_MSG("Could not parse packet!"); FAIL_MSG("Could not parse packet!");

View file

@ -34,26 +34,34 @@ bool AnalyserH264::parsePacket(){
} }
size_t size = 0; size_t size = 0;
h264::nalUnit *nalPtr; h264::nalUnit *nalPtr = h264::nalFactory(dataBuffer.data(), dataBuffer.size(), size, !sizePrepended);
do{ if (!nalPtr){
size = 0;
nalPtr = h264::nalFactory(dataBuffer.data(), dataBuffer.size(), size, !sizePrepended);
if (nalPtr){
HIGH_MSG("Read a %lu-byte NAL unit at position %" PRIu64, size, prePos);
if (detail >= 2){nalPtr->toPrettyString(std::cout);}
dataBuffer.erase(0, size); // erase the NAL unit we just read
prePos += size;
return true;
}
///\TODO update mediaTime with current timestamp
}while (nalPtr);
FAIL_MSG("Could not read a NAL unit at position %" PRIu64, prePos); FAIL_MSG("Could not read a NAL unit at position %" PRIu64, prePos);
return false; return false;
}
HIGH_MSG("Read a %lu-byte NAL unit at position %" PRIu64, size, prePos);
if (detail >= 2){nalPtr->toPrettyString(std::cout);}
//SPS unit? Find the FPS, if any.
if (nalPtr->getType() == 7){
h264::spsUnit *sps = (h264::spsUnit*)nalPtr;
if (sps->vuiParametersPresentFlag && sps->vuiParams.fixedFrameRateFlag){
INFO_MSG("Frame rate: %f", sps->vuiParams.derived_fps);
}else{
INFO_MSG("Frame rate undetermined - assuming 25 FPS");
}
}
dataBuffer.erase(0, size); // erase the NAL unit we just read
prePos += size;
///\TODO update mediaTime with current timestamp
return true;
} }
uint64_t AnalyserH264::neededBytes(){ uint64_t AnalyserH264::neededBytes(){
// We buffer a megabyte if AnnexB // We buffer a megabyte if AnnexB
if (!sizePrepended){return 1024 * 1024;} if (!sizePrepended){
if (isOpen()){return 1024 * 1024;}
return dataBuffer.size();
}
// otherwise, buffer the exact size needed // otherwise, buffer the exact size needed
if (dataBuffer.size() < 4){return 4;} if (dataBuffer.size() < 4){return 4;}
return Bit::btohl(dataBuffer.data()) + 4; return Bit::btohl(dataBuffer.data()) + 4;