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 sequenceParameterSet::getCharacteristics() const{
|
||||||
SPSMeta result;
|
SPSMeta result;
|
||||||
result.sep_col_plane = false;
|
result.sep_col_plane = false;
|
||||||
|
@ -662,6 +747,45 @@ namespace h264{
|
||||||
lastScale = scalingList[i];
|
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){
|
ppsUnit::ppsUnit(const char *data, size_t len, uint8_t chromaFormatIdc) : nalUnit(data, len){
|
||||||
picScalingMatrixPresentFlags = NULL;
|
picScalingMatrixPresentFlags = NULL;
|
||||||
Utils::bitstream bs;
|
Utils::bitstream bs;
|
||||||
|
|
|
@ -67,6 +67,7 @@ namespace h264{
|
||||||
sequenceParameterSet(const char *_data = NULL, size_t _dataLen = 0);
|
sequenceParameterSet(const char *_data = NULL, size_t _dataLen = 0);
|
||||||
void fromDTSCInit(const std::string &dtscInit);
|
void fromDTSCInit(const std::string &dtscInit);
|
||||||
SPSMeta getCharacteristics() const;
|
SPSMeta getCharacteristics() const;
|
||||||
|
bool validate() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char *data;
|
const char *data;
|
||||||
|
@ -234,6 +235,7 @@ namespace h264{
|
||||||
size_t derived_scalingList4x4Amount;
|
size_t derived_scalingList4x4Amount;
|
||||||
size_t derived_scalingList8x8Amount;
|
size_t derived_scalingList8x8Amount;
|
||||||
};
|
};
|
||||||
|
bool ppsValidate(const char *data, size_t len);
|
||||||
class ppsUnit : public nalUnit{
|
class ppsUnit : public nalUnit{
|
||||||
public:
|
public:
|
||||||
ppsUnit(const char *data, size_t len, uint8_t chromaFormatIdc = 0);
|
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;
|
return;
|
||||||
case 7: // SPS
|
case 7: // SPS
|
||||||
if (spsData.size() != len - 4 || memcmp(buffer + 4, spsData.data(), len - 4) != 0){
|
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);
|
spsData.assign(buffer + 4, len - 4);
|
||||||
h264::sequenceParameterSet sps(spsData.data(), spsData.size());
|
|
||||||
h264::SPSMeta hMeta = sps.getCharacteristics();
|
h264::SPSMeta hMeta = sps.getCharacteristics();
|
||||||
fps = hMeta.fps;
|
fps = hMeta.fps;
|
||||||
|
|
||||||
|
@ -1041,7 +1045,11 @@ namespace RTP{
|
||||||
return;
|
return;
|
||||||
case 8: // PPS
|
case 8: // PPS
|
||||||
if (ppsData.size() != len - 4 || memcmp(buffer + 4, ppsData.data(), len - 4) != 0){
|
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);
|
ppsData.assign(buffer + 4, len - 4);
|
||||||
MP4::AVCC avccBox;
|
MP4::AVCC avccBox;
|
||||||
avccBox.setVersion(1);
|
avccBox.setVersion(1);
|
||||||
|
|
Loading…
Add table
Reference in a new issue