#pragma once #include <deque> #include <string> #include <cstdlib> #include <cstdio> #include "nal.h" #include "bitfields.h" #include "bitstream.h" namespace h264 { std::deque<nalu::nalData> analysePackets(const char * data, unsigned long len); ///Struct containing pre-calculated metadata of an SPS nal unit. Width and height in pixels, fps in Hz struct SPSMeta { unsigned int width; unsigned int height; double fps; uint8_t profile; uint8_t level; bool sep_col_plane; uint8_t cnt_type; bool gaps;///< Gaps in frame num allowed flag bool mbs_only;///<MBS only flag uint16_t log2_max_frame_num; uint16_t log2_max_order_cnt; uint16_t max_ref_frames;///<Maximum number of reference frames }; ///Class for analyzing generic nal units class NAL { public: NAL(); NAL(std::string & InputData); bool ReadData(std::string & InputData, bool raw = false); std::string AnnexB(bool LongIntro = false); std::string SizePrepended(); int Type(); std::string getData(); protected: unsigned int chroma_format_idc;///<the value of chroma_format_idc std::string MyData;///<The h264 nal unit data }; //NAL class ///Special instance of NAL class for analyzing SPS nal units class SPS: public NAL { public: SPS(): NAL() {}; SPS(std::string & InputData, bool raw = false); SPSMeta getCharacteristics(); void analyzeSPS(); }; ///Special instance of NAL class for analyzing PPS nal units class PPS: public NAL { public: PPS(): NAL() {}; PPS(std::string & InputData): NAL(InputData) {}; void analyzePPS(); }; class sequenceParameterSet { public: sequenceParameterSet(const char * _data = NULL, size_t _dataLen = 0); void fromDTSCInit(const std::string & dtscInit); SPSMeta getCharacteristics() const; private: const char * data; size_t dataLen; }; bool isKeyframe(const char * data, uint32_t len); class nalUnit { public: nalUnit(const char * data, size_t len) : payload(data, len) {} uint8_t getType() { return payload[0] & 0x1F; } uint32_t getSize(){return payload.size();} virtual void toPrettyString(std::ostream & out){ out << "Nal unit of type " << (((uint8_t)payload[0]) & 0x1F) << ", " << payload.size() << " bytes long" << std::endl; } void write(std::ostream & out){ //always writes in annex_b style out.write("\000\000\000\001", 4); out.write(payload.data(), payload.size()); } virtual std::string generate() { return ""; } virtual void setSPSNumber(size_t newNumber) {} virtual void setPPSNumber(size_t newNumber) {} protected: std::string payload; }; class hrd_parameters { public: hrd_parameters() {} hrd_parameters(Utils::bitstream & bs); void toPrettyString(std::ostream & out, size_t indent = 0); uint64_t cpbCntMinus1; uint8_t bitRateScale; uint8_t cpbSizeScale; }; class vui_parameters { public: vui_parameters() {}; vui_parameters(Utils::bitstream & bs); void generate(Utils::bitWriter & bw); void toPrettyString(std::ostream & out, size_t indent = 0); bool aspectRatioInfoPresentFlag; uint8_t aspectRatioIdc; uint16_t sarWidth; uint16_t sarHeight; bool overscanInfoPresentFlag; bool overscanAppropriateFlag; bool videoSignalTypePresentFlag; uint8_t videoFormat; bool videoFullRangeFlag; bool colourDescriptionPresentFlag; uint8_t colourPrimaries; uint8_t transferCharacteristics; uint8_t matrixCoefficients; bool chromaLocInfoPresentFlag; uint64_t chromaSampleLocTypeTopField; uint64_t chromaSampleLocTypeBottomField; bool timingInfoPresentFlag; uint32_t numUnitsInTick; uint32_t timeScale; bool fixedFrameRateFlag; bool nalHrdParametersPresentFlag; bool vclHrdParametersPresentFlag; bool lowDelayHrdFlag; bool picStructPresentFlag; bool bitstreamRestrictionFlag; bool motionVectorsOverPicBoundariesFlag; uint64_t maxBytesPerPicDenom; uint64_t maxBitsPerMbDenom; uint64_t log2MaxMvLengthHorizontal; uint64_t log2MaxMvLengthVertical; uint64_t numReorderFrames; uint64_t maxDecFrameBuffering; }; class spsUnit : public nalUnit { public: spsUnit(const char * data, size_t len); ~spsUnit(){ if (scalingListPresentFlags != NULL){ free(scalingListPresentFlags); } } std::string generate(); void toPrettyString(std::ostream & out); void scalingList(uint64_t * scalingList, size_t sizeOfScalingList, bool & useDefaultScalingMatrixFlag, Utils::bitstream & bs); void setSPSNumber(size_t newNumber); uint8_t profileIdc; bool constraintSet0Flag; bool constraintSet1Flag; bool constraintSet2Flag; bool constraintSet3Flag; bool constraintSet4Flag; bool constraintSet5Flag; uint8_t levelIdc; uint64_t seqParameterSetId; uint64_t chromaFormatIdc; bool separateColourPlaneFlag; uint64_t bitDepthLumaMinus8; uint64_t bitDepthChromaMinus8; bool qpprimeYZeroTransformBypassFlag; bool seqScalingMatrixPresentFlag; //Here go scaling lists uint8_t * scalingListPresentFlags; uint64_t ** scalingList4x4; bool * useDefaultScalingMatrix4x4Flag; uint64_t ** scalingList8x8; bool * useDefaultScalingMatrix8x8Flag; uint64_t log2MaxFrameNumMinus4; uint64_t picOrderCntType; uint64_t log2MaxPicOrderCntLsbMinus4; //Here go values for pic_order_cnt_type == 1 uint64_t maxNumRefFrames; bool gapsInFrameNumValueAllowedFlag; uint64_t picWidthInMbsMinus1; uint64_t picHeightInMapUnitsMinus1; bool frameMbsOnlyFlag; bool mbAdaptiveFrameFieldFlag; bool direct8x8InferenceFlag; bool frameCroppingFlag; uint64_t frameCropLeftOffset; uint64_t frameCropRightOffset; uint64_t frameCropTopOffset; uint64_t frameCropBottomOffset; bool vuiParametersPresentFlag; vui_parameters vuiParams; //DERIVATIVE VALUES uint8_t derived_subWidthC; uint8_t derived_subHeightC; uint8_t derived_mbWidthC; uint8_t derived_mbHeightC; uint64_t derived_bitDepth_Y; uint64_t derived_qpBdOffset_Y; uint64_t derived_bitDepth_C; uint64_t derived_qpBdOffset_C; uint64_t derived_rawMbBits; uint64_t derived_maxFrameNum; uint64_t derived_maxPicOrderCntLsb; uint64_t derived_picWidthInMbs; uint64_t derived_picWidthInSamples_L; uint64_t derived_picWidthInSamples_C; uint64_t derived_picHeightInMapUnits; uint64_t derived_picSizeInMapUnits; uint64_t derived_frameHeightInMbs; size_t derived_scalingListSize; size_t derived_scalingList4x4Amount; size_t derived_scalingList8x8Amount; }; class ppsUnit : public nalUnit { public: ppsUnit(const char * data, size_t len, uint8_t chromaFormatIdc = 0); ~ppsUnit(){ if (picScalingMatrixPresentFlags != NULL){ free(picScalingMatrixPresentFlags); } } void scalingList(uint64_t * scalingList, size_t sizeOfScalingList, bool & useDefaultScalingMatrixFlag, Utils::bitstream & bs); void setPPSNumber(size_t newNumber); void setSPSNumber(size_t newNumber); void toPrettyString(std::ostream & out); std::string generate(); uint64_t picParameterSetId; uint64_t seqParameterSetId; bool entropyCodingModeFlag; bool bottomFieldPicOrderInFramePresentFlag; uint64_t numSliceGroupsMinus1; uint64_t numrefIdx10DefaultActiveMinus1; uint64_t numrefIdx11DefaultActiveMinus1; bool weightedPredFlag; uint8_t weightedBipredIdc; int64_t picInitQpMinus26; int64_t picInitQsMinus26; int64_t chromaQpIndexOffset; bool deblockingFilterControlPresentFlag; bool constrainedIntraPredFlag; bool redundantPicCntPresentFlag; bool transform8x8ModeFlag; bool picScalingMatrixPresentFlag; //Here go scaling lists uint8_t * picScalingMatrixPresentFlags; uint64_t ** scalingList4x4; bool * useDefaultScalingMatrix4x4Flag; uint64_t ** scalingList8x8; bool * useDefaultScalingMatrix8x8Flag; int64_t secondChromaQpIndexOffset; size_t derived_scalingListSize; size_t derived_scalingList4x4Amount; size_t derived_scalingList8x8Amount; bool status_moreRBSP; }; class codedSliceUnit : public nalUnit { public: codedSliceUnit(const char * data, size_t len); void setPPSNumber(size_t newNumber); void toPrettyString(std::ostream & out); uint64_t firstMbInSlice; uint64_t sliceType; uint64_t picParameterSetId; }; class seiUnit : public nalUnit { public: seiUnit(const char * data, size_t len); void toPrettyString(std::ostream & out); uint32_t payloadType; uint32_t payloadSize; }; nalUnit * nalFactory(FILE * in, bool annexb = true); nalUnit * nalFactory(const char * data, size_t len, size_t & offset, bool annexb = true); }