mistserver/lib/h265.cpp

342 lines
9 KiB
C++

#include "h265.h"
#include "bitfields.h"
#include "defines.h"
namespace h265 {
std::deque<nalu::nalData> analysePackets(const char * data, unsigned long len){
std::deque<nalu::nalData> res;
int offset = 0;
while (offset < len){
nalu::nalData entry;
entry.nalSize = Bit::btohl(data + offset);
entry.nalType = ((data + offset)[4] & 0x7E) >> 1;
res.push_back(entry);
offset += entry.nalSize + 4;
}
return res;
}
initData::initData() {}
void initData::addUnit(char * data) {
unsigned long nalSize = Bit::btohl(data);
unsigned long nalType = (data[4] & 0x7E) >> 1;
switch (nalType) {
case 32: //vps
case 33: //sps
case 34: //pps
nalUnits[nalType].insert(std::string(data + 4, nalSize));
}
}
bool initData::haveRequired() {
return (nalUnits.count(32) && nalUnits.count(33) && nalUnits.count(34));
}
std::string initData::generateHVCC(){
MP4::HVCC hvccBox;
hvccBox.setConfigurationVersion(1);
hvccBox.setParallelismType(0);
std::set<std::string>::iterator nalIt;
//We first loop over all VPS Units
for (nalIt = nalUnits[32].begin(); nalIt != nalUnits[32].end(); nalIt++){
vpsUnit vps(*nalIt);
vps.updateHVCC(hvccBox);
}
for (nalIt = nalUnits[33].begin(); nalIt != nalUnits[33].end(); nalIt++){
spsUnit sps(*nalIt);
sps.updateHVCC(hvccBox);
}
//NOTE: We dont parse the ppsUnit, as the only information it contains is parallelism mode, which is set to 0 for 'unknown'
std::deque<MP4::HVCCArrayEntry> hvccArrays;
hvccArrays.resize(3);
hvccArrays[0].arrayCompleteness = 0;
hvccArrays[0].nalUnitType = 32;
for (nalIt = nalUnits[32].begin(); nalIt != nalUnits[32].end(); nalIt++){
hvccArrays[0].nalUnits.push_back(*nalIt);
}
hvccArrays[1].arrayCompleteness = 0;
hvccArrays[1].nalUnitType = 33;
for (nalIt = nalUnits[33].begin(); nalIt != nalUnits[33].end(); nalIt++){
hvccArrays[1].nalUnits.push_back(*nalIt);
}
hvccArrays[2].arrayCompleteness = 0;
hvccArrays[2].nalUnitType = 34;
for (nalIt = nalUnits[34].begin(); nalIt != nalUnits[34].end(); nalIt++){
hvccArrays[2].nalUnits.push_back(*nalIt);
}
hvccBox.setArrays(hvccArrays);
hvccBox.setLengthSizeMinus1(3);
return std::string(hvccBox.payload(), hvccBox.payloadSize());
}
void updateProfileTierLevel(Utils::bitstream & bs, MP4::HVCC & hvccBox, unsigned int maxSubLayersMinus1){
hvccBox.setGeneralProfileSpace(bs.get(2));
unsigned int tierFlag = bs.get(1);
hvccBox.setGeneralProfileIdc(std::max((unsigned long long)hvccBox.getGeneralProfileIdc(), bs.get(5)));
hvccBox.setGeneralProfileCompatibilityFlags(hvccBox.getGeneralProfileCompatibilityFlags() & bs.get(32));
hvccBox.setGeneralConstraintIndicatorFlags(hvccBox.getGeneralConstraintIndicatorFlags() & bs.get(48));
unsigned int levelIdc = bs.get(8);
if (tierFlag && !hvccBox.getGeneralTierFlag()) {
hvccBox.setGeneralLevelIdc(levelIdc);
}else {
hvccBox.setGeneralLevelIdc(std::max((unsigned int)hvccBox.getGeneralLevelIdc(),levelIdc));
}
hvccBox.setGeneralTierFlag(tierFlag || hvccBox.getGeneralTierFlag());
//Remainder is for synchronsation of the parser
std::deque<bool> profilePresent;
std::deque<bool> levelPresent;
for (int i = 0; i < maxSubLayersMinus1; i++){
profilePresent.push_back(bs.get(1));
levelPresent.push_back(bs.get(1));
}
if (maxSubLayersMinus1){
for (int i = maxSubLayersMinus1; i < 8; i++){
bs.skip(2);
}
}
for (int i = 0; i < maxSubLayersMinus1; i++){
if (profilePresent[i]){
bs.skip(32);
bs.skip(32);
bs.skip(24);
}
if (levelPresent[i]){
bs.skip(8);
}
}
}
vpsUnit::vpsUnit(const std::string & _data){
data = nalu::removeEmulationPrevention(_data);
}
void vpsUnit::updateHVCC(MP4::HVCC & hvccBox) {
Utils::bitstream bs;
bs.append(data);
bs.skip(16);//Nal Header
bs.skip(12);
unsigned int maxSubLayers = bs.get(3) + 1;
hvccBox.setNumberOfTemporalLayers(std::max((unsigned int)hvccBox.getNumberOfTemporalLayers(), maxSubLayers));
bs.skip(17);
updateProfileTierLevel(bs, hvccBox, maxSubLayers - 1);
}
spsUnit::spsUnit(const std::string & _data){
data = nalu::removeEmulationPrevention(_data);
}
void spsUnit::updateHVCC(MP4::HVCC & hvccBox) {
Utils::bitstream bs;
bs.append(data);
bs.skip(16);//Nal Header
bs.skip(4);
unsigned int maxSubLayers = bs.get(3) + 1;
hvccBox.setNumberOfTemporalLayers(std::max((unsigned int)hvccBox.getNumberOfTemporalLayers(), maxSubLayers));
hvccBox.setTemporalIdNested(bs.get(1));
updateProfileTierLevel(bs, hvccBox, maxSubLayers - 1);
bs.getUExpGolomb();
hvccBox.setChromaFormat(bs.getUExpGolomb());
if (hvccBox.getChromaFormat() == 3){
bs.skip(1);
}
bs.getUExpGolomb();
bs.getUExpGolomb();
if (bs.get(1)){
bs.getUExpGolomb();
bs.getUExpGolomb();
bs.getUExpGolomb();
bs.getUExpGolomb();
}
hvccBox.setBitDepthLumaMinus8(bs.getUExpGolomb());
hvccBox.setBitDepthChromaMinus8(bs.getUExpGolomb());
int log2MaxPicOrderCntLsb = bs.getUExpGolomb() + 4;
for (int i = bs.get(1) ? 0 : (maxSubLayers - 1); i < maxSubLayers; i++){
bs.getUExpGolomb();
bs.getUExpGolomb();
bs.getUExpGolomb();
}
bs.getUExpGolomb();
bs.getUExpGolomb();
bs.getUExpGolomb();
bs.getUExpGolomb();
bs.getUExpGolomb();
bs.getUExpGolomb();
if (bs.get(1) && bs.get(1)){
for (int i = 0; i < 4; i++){
for (int j = 0; j < (i == 3 ? 2 : 6); j++){
if (!bs.get(1)){
bs.getUExpGolomb();
}else{
int numCoeffs = std::min(64, 1 << (4 + (i << 1)));
if (i > 1){
bs.getExpGolomb();
}
for (int k = 0; k < numCoeffs; k++){
bs.getExpGolomb();
}
}
}
}
}
bs.skip(2);
if (bs.get(1)){
bs.skip(8);
bs.getUExpGolomb();
bs.getUExpGolomb();
bs.skip(1);
}
unsigned long long shortTermRefPicSets = bs.getUExpGolomb();
for (int i = 0; i < shortTermRefPicSets; i++){
//parse rps, return if ret < 0
}
if (bs.get(1)){
if (log2MaxPicOrderCntLsb > 16){
log2MaxPicOrderCntLsb = 16;
}
int numLongTermRefPicsSps = bs.getUExpGolomb();
for (int i = 0; i < numLongTermRefPicsSps; i++){
bs.skip(log2MaxPicOrderCntLsb + 1);
}
}
bs.skip(2);
if (bs.get(1)){
//parse vui
if (bs.get(1) && bs.get(8) == 255){ bs.skip(32); }
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();
}
bs.skip(3);
if (bs.get(1)){
bs.getUExpGolomb();
bs.getUExpGolomb();
bs.getUExpGolomb();
bs.getUExpGolomb();
}
if (bs.get(1)){
bs.skip(32);
bs.skip(32);
if (bs.get(1)){
bs.getUExpGolomb();
}
if (bs.get(1)){
int nalHrd = bs.get(1);
int vclHrd = bs.get(1);
int subPicPresent = 0;
if (nalHrd || vclHrd){
subPicPresent = bs.get(1);
if (subPicPresent){
bs.skip(19);
}
bs.skip(8);
if (subPicPresent){
bs.skip(4);
}
bs.skip(15);
}
//
for (int i = 0; i < maxSubLayers; i++){
int cpbCnt = 1;
int lowDelay = 0;
int fixedRateCvs = 0;
int fixedRateGeneral = bs.get(1);
if (fixedRateGeneral){
fixedRateCvs = bs.get(1);
}
if (fixedRateCvs){
bs.getUExpGolomb();
}else{
lowDelay = bs.get(1);
}
if (!lowDelay){
cpbCnt = bs.getUExpGolomb() + 1;
}
if (nalHrd){
for (int i = 0; i < cpbCnt; i++){
bs.getUExpGolomb();
bs.getUExpGolomb();
if (subPicPresent){
bs.getUExpGolomb();
bs.getUExpGolomb();
}
bs.skip(1);
}
}
if (vclHrd){
for (int i = 0; i < cpbCnt; i++){
bs.getUExpGolomb();
bs.getUExpGolomb();
if (subPicPresent){
bs.getUExpGolomb();
bs.getUExpGolomb();
}
bs.skip(1);
}
}
}
}
}
if (bs.get(1)){
bs.skip(3);
int spatialSegmentIdc = bs.getUExpGolomb();
hvccBox.setMinSpatialSegmentationIdc(std::min((int)hvccBox.getMinSpatialSegmentationIdc(),spatialSegmentIdc));
bs.getUExpGolomb();
bs.getUExpGolomb();
bs.getUExpGolomb();
bs.getUExpGolomb();
}
}
}
}