Allow for multiple SPS/PPS in AVCC Box
This commit is contained in:
parent
4f7b902453
commit
373b9afd32
3 changed files with 115 additions and 61 deletions
|
@ -558,89 +558,128 @@ namespace MP4 {
|
||||||
return getInt8(3);
|
return getInt8(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVCC::setSPSNumber(uint32_t newSPSNumber) {
|
void AVCC::setSPSCount(uint32_t _count){
|
||||||
setInt8(newSPSNumber, 5);
|
setInt8(_count | 0xE0, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AVCC::getSPSNumber() {
|
uint32_t AVCC::getSPSCount() {
|
||||||
return getInt8(5);
|
return getInt8(5) & 0x1F;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVCC::setSPS(std::string newSPS) {
|
void AVCC::setSPS(std::string newSPS, size_t index) {
|
||||||
setInt16(newSPS.size(), 6);
|
if (index >= getSPSCount()){
|
||||||
|
WARN_MSG("Cannot set entry at position %zu/%u: Out of bounds", index, getSPSCount());
|
||||||
|
}
|
||||||
|
size_t offset = 6;
|
||||||
|
for (size_t i = 0; i < index; i++){
|
||||||
|
offset += getInt16(offset) + 2;
|
||||||
|
}
|
||||||
|
setInt16(newSPS.size(), offset);
|
||||||
for (unsigned int i = 0; i < newSPS.size(); i++) {
|
for (unsigned int i = 0; i < newSPS.size(); i++) {
|
||||||
setInt8(newSPS[i], 8 + i);
|
setInt8(newSPS[i], offset + 2 + i);
|
||||||
} //not null-terminated
|
} //not null-terminated
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AVCC::getSPSLen() {
|
uint32_t AVCC::getSPSLen(size_t index) {
|
||||||
uint16_t len = getInt16(6);
|
if (index >= getSPSCount()){
|
||||||
if (len > payloadSize() - 8){
|
|
||||||
WARN_MSG("SPS length of %u is more than AVCC box size %lu", len, payloadSize());
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return len;
|
size_t offset = 6;
|
||||||
|
for (size_t i = 0; i < index; i++){
|
||||||
|
offset += getInt16(offset) + 2;
|
||||||
|
}
|
||||||
|
return getInt16(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
char * AVCC::getSPS() {
|
char * AVCC::getSPS(size_t index) {
|
||||||
return payload() + 8;
|
if (index >= getSPSCount()){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t offset = 6;
|
||||||
|
for (size_t i = 0; i < index; i++){
|
||||||
|
offset += getInt16(offset) + 2;
|
||||||
|
}
|
||||||
|
return payload() + offset + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AVCC::hexSPS(){
|
std::string AVCC::hexSPS(size_t index){
|
||||||
|
if (index >= getPPSCount()){
|
||||||
|
return "INVALID INDEX";
|
||||||
|
}
|
||||||
std::stringstream res;
|
std::stringstream res;
|
||||||
char * data = getSPS();
|
char * data = getSPS(index);
|
||||||
uint32_t len = getSPSLen();
|
uint32_t len = getSPSLen(index);
|
||||||
for (int i = 0; i < len; i++){
|
for (int i = 0; i < len; i++){
|
||||||
res << std::hex << std::setw(2) << std::setfill('0') << (int)data[i];
|
res << std::hex << std::setw(2) << std::setfill('0') << (int)data[i];
|
||||||
}
|
}
|
||||||
return res.str();
|
return res.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AVCC::hexPPS(){
|
std::string AVCC::hexPPS(size_t index){
|
||||||
|
if (index >= getPPSCount()){
|
||||||
|
return "INVALID INDEX";
|
||||||
|
}
|
||||||
std::stringstream res;
|
std::stringstream res;
|
||||||
char * data = getPPS();
|
char * data = getPPS(index);
|
||||||
uint32_t len = getPPSLen();
|
uint32_t len = getPPSLen(index);
|
||||||
for (int i = 0; i < len; i++){
|
for (int i = 0; i < len; i++){
|
||||||
res << std::hex << std::setw(2) << std::setfill('0') << (int)data[i];
|
res << std::hex << std::setw(2) << std::setfill('0') << (int)data[i];
|
||||||
}
|
}
|
||||||
return res.str();
|
return res.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVCC::setPPSNumber(uint32_t newPPSNumber) {
|
size_t AVCC::PPSCountOffset() {
|
||||||
int offset = 8 + getSPSLen();
|
size_t offset = 6;
|
||||||
setInt8(newPPSNumber, offset);
|
size_t spsCount = getSPSCount();
|
||||||
|
for (size_t i = 0; i < spsCount; i++){
|
||||||
|
offset += getInt16(offset) + 2;
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AVCC::getPPSNumber() {
|
void AVCC::setPPSCount(uint32_t _count) {
|
||||||
int offset = 8 + getSPSLen();
|
setInt8(_count, PPSCountOffset());
|
||||||
return getInt8(offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVCC::setPPS(std::string newPPS) {
|
uint32_t AVCC::getPPSCount() {
|
||||||
int offset = 8 + getSPSLen() + 1;
|
return getInt8(PPSCountOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AVCC::setPPS(std::string newPPS, size_t index) {
|
||||||
|
if (index >= getPPSCount()){
|
||||||
|
WARN_MSG("Cannot set entry at position %zu/%u: Out of bounds", index, getPPSCount());
|
||||||
|
}
|
||||||
|
int offset = PPSCountOffset() + 1;
|
||||||
|
for (size_t i = 0; i < index; i++){
|
||||||
|
offset += getInt16(offset) + 2;
|
||||||
|
}
|
||||||
setInt16(newPPS.size(), offset);
|
setInt16(newPPS.size(), offset);
|
||||||
for (unsigned int i = 0; i < newPPS.size(); i++) {
|
for (unsigned int i = 0; i < newPPS.size(); i++) {
|
||||||
setInt8(newPPS[i], offset + 2 + i);
|
setInt8(newPPS[i], offset + 2 + i);
|
||||||
} //not null-terminated
|
} //not null-terminated
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AVCC::getPPSLen() {
|
uint32_t AVCC::getPPSLen(size_t index) {
|
||||||
int offset = 8 + getSPSLen() + 1;
|
if (index >= getPPSCount()){
|
||||||
if (offset > payloadSize() - 2){
|
|
||||||
WARN_MSG("Invalid PPS length offset! Aborting PPS read.");
|
WARN_MSG("Invalid PPS length offset! Aborting PPS read.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
uint16_t len = getInt16(offset);
|
int offset = PPSCountOffset() + 1;
|
||||||
if (len > payloadSize() - offset - 2){
|
for (size_t i = 0; i < index; i++){
|
||||||
WARN_MSG("PPS length of %u is more than AVCC box size %lu", len, payloadSize());
|
offset += getInt16(offset) + 2;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return len;
|
return getInt16(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
char * AVCC::getPPS() {
|
char * AVCC::getPPS(size_t index) {
|
||||||
int offset = 8 + getSPSLen() + 3;
|
if (index >= getPPSCount()){
|
||||||
return payload() + offset;
|
return 0;
|
||||||
|
}
|
||||||
|
int offset = PPSCountOffset() + 1;
|
||||||
|
for (size_t i = 0; i < index; i++){
|
||||||
|
offset += getInt16(offset) + 2;
|
||||||
|
}
|
||||||
|
return payload() + offset + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AVCC::toPrettyString(uint32_t indent) {
|
std::string AVCC::toPrettyString(uint32_t indent) {
|
||||||
|
@ -650,19 +689,31 @@ namespace MP4 {
|
||||||
r << std::string(indent + 1, ' ') << "Profile: " << getProfile() << std::endl;
|
r << std::string(indent + 1, ' ') << "Profile: " << getProfile() << std::endl;
|
||||||
r << std::string(indent + 1, ' ') << "Compatible Profiles: " << getCompatibleProfiles() << std::endl;
|
r << std::string(indent + 1, ' ') << "Compatible Profiles: " << getCompatibleProfiles() << std::endl;
|
||||||
r << std::string(indent + 1, ' ') << "Level: " << getLevel() << std::endl;
|
r << std::string(indent + 1, ' ') << "Level: " << getLevel() << std::endl;
|
||||||
r << std::string(indent + 1, ' ') << "SPS Number: " << getSPSNumber() << std::endl;
|
size_t spsCount = getSPSCount();
|
||||||
r << std::string(indent + 2, ' ') << getSPSLen() << " of SPS data: " << hexSPS() << std::endl;
|
r << std::string(indent + 1, ' ') << "SPS Count: " << spsCount << std::endl;
|
||||||
r << std::string(indent + 1, ' ') << "PPS Number: " << getPPSNumber() << std::endl;
|
for (size_t i = 0; i < spsCount; i++){
|
||||||
r << std::string(indent + 2, ' ') << getPPSLen() << " of PPS data: " << hexPPS() << std::endl;
|
r << std::string(indent + 2, ' ') << getSPSLen(i) << " bytes of SPS data: " << hexSPS(i) << std::endl;
|
||||||
|
}
|
||||||
|
size_t ppsCount = getPPSCount();
|
||||||
|
r << std::string(indent + 1, ' ') << "PPS Count: " << ppsCount << std::endl;
|
||||||
|
for (size_t i = 0; i < ppsCount; i++){
|
||||||
|
r << std::string(indent + 2, ' ') << getPPSLen(i) << " bytes of PPS data: " << hexPPS(i) << std::endl;
|
||||||
|
}
|
||||||
return r.str();
|
return r.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AVCC::asAnnexB() {
|
std::string AVCC::asAnnexB() {
|
||||||
std::stringstream r;
|
std::stringstream r;
|
||||||
|
size_t count = getSPSCount();
|
||||||
|
for (size_t i = 0; i < count; ++i){
|
||||||
r << (char)0x00 << (char)0x00 << (char)0x00 << (char)0x01;
|
r << (char)0x00 << (char)0x00 << (char)0x00 << (char)0x01;
|
||||||
r.write(getSPS(), getSPSLen());
|
r.write(getSPS(i), getSPSLen(i));
|
||||||
|
}
|
||||||
|
count = getPPSCount();
|
||||||
|
for (size_t i = 0; i < count; ++i){
|
||||||
r << (char)0x00 << (char)0x00 << (char)0x00 << (char)0x01;
|
r << (char)0x00 << (char)0x00 << (char)0x00 << (char)0x01;
|
||||||
r.write(getPPS(), getPPSLen());
|
r.write(getPPS(i), getPPSLen(i));
|
||||||
|
}
|
||||||
return r.str();
|
return r.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,18 +107,21 @@ namespace MP4 {
|
||||||
uint32_t getCompatibleProfiles();
|
uint32_t getCompatibleProfiles();
|
||||||
void setLevel(uint32_t newLevel);
|
void setLevel(uint32_t newLevel);
|
||||||
uint32_t getLevel();
|
uint32_t getLevel();
|
||||||
void setSPSNumber(uint32_t newSPSNumber);
|
|
||||||
uint32_t getSPSNumber();
|
void setSPSCount(uint32_t _count);
|
||||||
void setSPS(std::string newSPS);
|
uint32_t getSPSCount();
|
||||||
uint32_t getSPSLen();
|
void setSPS(std::string newSPS, size_t index = 0);
|
||||||
char * getSPS();
|
uint32_t getSPSLen(size_t index = 0);
|
||||||
std::string hexSPS();
|
char * getSPS(size_t index = 0);
|
||||||
void setPPSNumber(uint32_t newPPSNumber);
|
std::string hexSPS(size_t index = 0);
|
||||||
uint32_t getPPSNumber();
|
|
||||||
void setPPS(std::string newPPS);
|
size_t PPSCountOffset();
|
||||||
uint32_t getPPSLen();
|
void setPPSCount(uint32_t _count);
|
||||||
char * getPPS();
|
uint32_t getPPSCount();
|
||||||
std::string hexPPS();
|
void setPPS(std::string newPPS, size_t index = 0);
|
||||||
|
uint32_t getPPSLen(size_t index = 0);
|
||||||
|
char * getPPS(size_t index = 0);
|
||||||
|
std::string hexPPS(size_t index = 0);
|
||||||
std::string asAnnexB();
|
std::string asAnnexB();
|
||||||
void setPayload(std::string newPayload);
|
void setPayload(std::string newPayload);
|
||||||
std::string toPrettyString(uint32_t indent = 0);
|
std::string toPrettyString(uint32_t indent = 0);
|
||||||
|
|
|
@ -104,9 +104,9 @@ namespace Mist{
|
||||||
avccBox.setProfile(spsInfo[1]);
|
avccBox.setProfile(spsInfo[1]);
|
||||||
avccBox.setCompatibleProfiles(spsInfo[2]);
|
avccBox.setCompatibleProfiles(spsInfo[2]);
|
||||||
avccBox.setLevel(spsInfo[3]);
|
avccBox.setLevel(spsInfo[3]);
|
||||||
avccBox.setSPSNumber(1);
|
avccBox.setSPSCount(1);
|
||||||
avccBox.setSPS(spsInfo);
|
avccBox.setSPS(spsInfo);
|
||||||
avccBox.setPPSNumber(1);
|
avccBox.setPPSCount(1);
|
||||||
avccBox.setPPS(ppsInfo);
|
avccBox.setPPS(ppsInfo);
|
||||||
myMeta.tracks[1].init = std::string(avccBox.payload(), avccBox.payloadSize());
|
myMeta.tracks[1].init = std::string(avccBox.payload(), avccBox.payloadSize());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue