Added SPS/PPS validation functions, RTP lib now only updates SPS/PPS when valid
This commit is contained in:
parent
b1740e9bd3
commit
53698eaa49
3 changed files with 137 additions and 3 deletions
124
lib/h264.cpp
124
lib/h264.cpp
|
@ -75,6 +75,91 @@ namespace h264{
|
|||
}
|
||||
}
|
||||
|
||||
bool sequenceParameterSet::validate() const{
|
||||
Utils::bitstream bs;
|
||||
for (size_t i = 1; i < dataLen; i++){
|
||||
if (i + 2 < dataLen && (memcmp(data + i, "\000\000\003", 3) == 0)){// Emulation prevention bytes
|
||||
// Yes, we increase i here
|
||||
bs.append(data + i, 2);
|
||||
i += 2;
|
||||
}else{
|
||||
// No we don't increase i here
|
||||
bs.append(data + i, 1);
|
||||
}
|
||||
}
|
||||
if (bs.size() < 24){return false;}//static size data
|
||||
char profileIdc = bs.get(8);
|
||||
bs.skip(16);
|
||||
bs.getUExpGolomb();//ID
|
||||
if (profileIdc == 100 || profileIdc == 110 || profileIdc == 122 || profileIdc == 244 ||
|
||||
profileIdc == 44 || profileIdc == 83 || profileIdc == 86 || profileIdc == 118 || profileIdc == 128){
|
||||
// chroma format idc
|
||||
char chromaFormatIdc = bs.getUExpGolomb();
|
||||
if (chromaFormatIdc == 3){bs.get(1);}
|
||||
bs.getUExpGolomb(); // luma
|
||||
bs.getUExpGolomb(); // chroma
|
||||
bs.skip(1); // transform bypass
|
||||
if (bs.get(1)){// Scaling matrix is present
|
||||
char listSize = (chromaFormatIdc == 3 ? 12 : 8);
|
||||
for (size_t i = 0; i < listSize; i++){
|
||||
bool thisListPresent = bs.get(1);
|
||||
if (thisListPresent){
|
||||
if (i < 6){
|
||||
skipScalingList(bs, 16);
|
||||
}else{
|
||||
skipScalingList(bs, 64);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bs.getUExpGolomb();
|
||||
size_t cnt_type = bs.getUExpGolomb();
|
||||
if (!cnt_type){
|
||||
bs.getUExpGolomb();
|
||||
}else if (cnt_type == 1){
|
||||
ERROR_MSG("This part of the implementation is incomplete(2), to be continued. If this "
|
||||
"message is shown, contact developers immediately.");
|
||||
}
|
||||
if (!bs.size()){return false;}
|
||||
bs.getUExpGolomb(); // max_num_ref_frames
|
||||
bs.get(1);
|
||||
bs.getUExpGolomb();
|
||||
bs.getUExpGolomb();
|
||||
if (!bs.size()){return false;}
|
||||
bool mbs_only = (bs.get(1) == 1); // Gets used in height calculation
|
||||
if (!mbs_only){bs.skip(1);}
|
||||
bs.skip(1);
|
||||
// cropping flag
|
||||
if (bs.get(1)){
|
||||
bs.getUExpGolomb(); // leftOffset
|
||||
bs.getUExpGolomb(); // rightOffset
|
||||
bs.getUExpGolomb(); // topOffset
|
||||
bs.getUExpGolomb(); // bottomOffset
|
||||
}
|
||||
|
||||
if (!bs.size()){return false;}
|
||||
if (bs.get(1)){
|
||||
if (bs.get(1)){bs.skip(8);}
|
||||
if (bs.get(1)){bs.skip(1);}
|
||||
if (bs.get(1)){
|
||||
bs.skip(4);
|
||||
if (bs.get(1)){bs.skip(24);}
|
||||
}
|
||||
if (bs.get(1)){
|
||||
bs.getUExpGolomb();
|
||||
bs.getUExpGolomb();
|
||||
}
|
||||
|
||||
// Decode timing info
|
||||
if (!bs.size()){return false;}
|
||||
if (bs.get(1)){
|
||||
return (bs.size() >= 65);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SPSMeta sequenceParameterSet::getCharacteristics() const{
|
||||
SPSMeta result;
|
||||
result.sep_col_plane = false;
|
||||
|
@ -662,6 +747,45 @@ namespace h264{
|
|||
lastScale = scalingList[i];
|
||||
}
|
||||
}
|
||||
|
||||
bool ppsValidate(const char *data, size_t len){
|
||||
Utils::bitstream bs;
|
||||
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
|
||||
bs.append(data + i, 2);
|
||||
i += 2;
|
||||
}else{
|
||||
// No we don't increase i here
|
||||
bs.append(data + i, 1);
|
||||
}
|
||||
}
|
||||
bs.getUExpGolomb();
|
||||
bs.getUExpGolomb();
|
||||
bs.get(2);
|
||||
if (bs.getUExpGolomb() > 0){
|
||||
WARN_MSG("num_slice_groups_minus1 > 0, unimplemented structure");
|
||||
return false;
|
||||
}
|
||||
bs.getUExpGolomb();
|
||||
bs.getUExpGolomb();
|
||||
bs.get(3);
|
||||
bs.getExpGolomb();
|
||||
bs.getExpGolomb();
|
||||
bs.getExpGolomb();
|
||||
bs.get(2);
|
||||
if (!bs.size()){return false;}
|
||||
bs.get(1);
|
||||
if (!more_rbsp_data(bs)){return true;}
|
||||
bs.get(1);
|
||||
if (bs.get(1)){
|
||||
//tricky scaling stuff, assume we're good.
|
||||
/// \TODO Maybe implement someday? Do we care? Doubt.
|
||||
return true;
|
||||
}
|
||||
return bs.size();
|
||||
}
|
||||
|
||||
ppsUnit::ppsUnit(const char *data, size_t len, uint8_t chromaFormatIdc) : nalUnit(data, len){
|
||||
picScalingMatrixPresentFlags = NULL;
|
||||
Utils::bitstream bs;
|
||||
|
|
|
@ -67,6 +67,7 @@ namespace h264{
|
|||
sequenceParameterSet(const char *_data = NULL, size_t _dataLen = 0);
|
||||
void fromDTSCInit(const std::string &dtscInit);
|
||||
SPSMeta getCharacteristics() const;
|
||||
bool validate() const;
|
||||
|
||||
private:
|
||||
const char *data;
|
||||
|
@ -234,6 +235,7 @@ namespace h264{
|
|||
size_t derived_scalingList4x4Amount;
|
||||
size_t derived_scalingList8x8Amount;
|
||||
};
|
||||
bool ppsValidate(const char *data, size_t len);
|
||||
class ppsUnit : public nalUnit{
|
||||
public:
|
||||
ppsUnit(const char *data, size_t len, uint8_t chromaFormatIdc = 0);
|
||||
|
|
14
lib/rtp.cpp
14
lib/rtp.cpp
|
@ -1017,9 +1017,13 @@ namespace RTP{
|
|||
return;
|
||||
case 7: // SPS
|
||||
if (spsData.size() != len - 4 || memcmp(buffer + 4, spsData.data(), len - 4) != 0){
|
||||
HIGH_MSG("Updated SPS from RTP data");
|
||||
h264::sequenceParameterSet sps(buffer + 4, len - 4);
|
||||
if (!sps.validate()){
|
||||
WARN_MSG("Ignoring invalid SPS packet! (%" PRIu32 "b)", len-4);
|
||||
return;
|
||||
}
|
||||
HIGH_MSG("Updated SPS from RTP data: %" PRIu32 "b", len-4);
|
||||
spsData.assign(buffer + 4, len - 4);
|
||||
h264::sequenceParameterSet sps(spsData.data(), spsData.size());
|
||||
h264::SPSMeta hMeta = sps.getCharacteristics();
|
||||
fps = hMeta.fps;
|
||||
|
||||
|
@ -1041,7 +1045,11 @@ namespace RTP{
|
|||
return;
|
||||
case 8: // PPS
|
||||
if (ppsData.size() != len - 4 || memcmp(buffer + 4, ppsData.data(), len - 4) != 0){
|
||||
HIGH_MSG("Updated PPS from RTP data");
|
||||
if (!h264::ppsValidate(buffer+4, len-4)){
|
||||
WARN_MSG("Ignoring invalid PPS packet! (%" PRIu32 "b)", len-4);
|
||||
return;
|
||||
}
|
||||
HIGH_MSG("Updated PPS from RTP data: %" PRIu32 "b", len-4);
|
||||
ppsData.assign(buffer + 4, len - 4);
|
||||
MP4::AVCC avccBox;
|
||||
avccBox.setVersion(1);
|
||||
|
|
Loading…
Add table
Reference in a new issue