Support for TREX boxes in MP4::Stream parser and all binaries that use it

This commit is contained in:
Thulinma 2024-04-22 15:02:11 +02:00
parent 57655f1b21
commit 0e26d49bec
7 changed files with 71 additions and 25 deletions

View file

@ -125,7 +125,7 @@ namespace MP4{
if (getSampleInformationCount() < no + 1){setInt32(no + 1, 4);}
}
trunSampleInformation TRUN::getSampleInformation(uint32_t no, TFHD * tfhd) const{
trunSampleInformation TRUN::getSampleInformation(uint32_t no, TFHD * tfhd, TREX * trex) const{
trunSampleInformation ret;
ret.sampleDuration = 0;
ret.sampleSize = 0;
@ -148,22 +148,34 @@ namespace MP4{
if (flags & trunsampleDuration){
ret.sampleDuration = getInt32(offset + no * sampInfoSize + innerOffset);
innerOffset += 4;
}else if (tfhd){
}else if (tfhd && (tfhd->getFlags() & tfhdSampleDura)){
ret.sampleDuration = tfhd->getDefaultSampleDuration();
}else if (trex){
ret.sampleDuration = trex->getDefaultSampleDuration();
}else{
WARN_MSG("Could not get sample duration from TRUN, TFHD or TREX box(es)!");
}
if (flags & trunsampleSize){
ret.sampleSize = getInt32(offset + no * sampInfoSize + innerOffset);
innerOffset += 4;
}else if (tfhd){
}else if (tfhd && (tfhd->getFlags() & tfhdSampleSize)){
ret.sampleSize = tfhd->getDefaultSampleSize();
}else if (trex){
ret.sampleSize = trex->getDefaultSampleSize();
}else{
WARN_MSG("Could not get sample size from TRUN, TFHD or TREX box(es)!");
}
if (flags & trunsampleFlags){
ret.sampleFlags = getInt32(offset + no * sampInfoSize + innerOffset);
innerOffset += 4;
}else if ((flags & trunfirstSampleFlags) && !no){
ret.sampleFlags = getFirstSampleFlags();
}else if (tfhd){
}else if (tfhd && (tfhd->getFlags() & tfhdSampleFlag)){
ret.sampleFlags = tfhd->getDefaultSampleFlags();
}else if (trex){
ret.sampleFlags = trex->getDefaultSampleFlags();
}else{
WARN_MSG("Could not get sample flags from TRUN, TFHD or TREX box(es)!");
}
if (flags & trunsampleOffsets){
ret.sampleOffset = getInt32(offset + no * sampInfoSize + innerOffset);

View file

@ -69,6 +69,23 @@ namespace MP4{
std::string toPrettyString(uint32_t indent = 0);
};
class TREX : public fullBox{
public:
TREX(unsigned int trackId = 0);
void setTrackID(uint32_t newTrackID);
uint32_t getTrackID();
void setDefaultSampleDescriptionIndex(uint32_t newDefaultSampleDescriptionIndex);
uint32_t getDefaultSampleDescriptionIndex();
void setDefaultSampleDuration(uint32_t newDefaultSampleDuration);
uint32_t getDefaultSampleDuration();
void setDefaultSampleSize(uint32_t newDefaultSampleSize);
uint32_t getDefaultSampleSize();
void setDefaultSampleFlags(uint32_t newDefaultSampleFlags);
uint32_t getDefaultSampleFlags();
std::string toPrettyString(uint32_t indent = 0);
};
struct trunSampleInformation {
uint32_t sampleDuration;
uint32_t sampleSize;
@ -106,7 +123,7 @@ namespace MP4{
uint32_t getFirstSampleFlags() const;
uint32_t getSampleInformationCount() const;
void setSampleInformation(trunSampleInformation newSample, uint32_t no);
trunSampleInformation getSampleInformation(uint32_t no, TFHD * tfhd = 0) const;
trunSampleInformation getSampleInformation(uint32_t no, TFHD * tfhd = 0, TREX * trex = 0) const;
std::string toPrettyString(uint32_t indent = 0) const;
};
@ -312,22 +329,6 @@ namespace MP4{
MVEX();
};
class TREX : public fullBox{
public:
TREX(unsigned int trackId = 0);
void setTrackID(uint32_t newTrackID);
uint32_t getTrackID();
void setDefaultSampleDescriptionIndex(uint32_t newDefaultSampleDescriptionIndex);
uint32_t getDefaultSampleDescriptionIndex();
void setDefaultSampleDuration(uint32_t newDefaultSampleDuration);
uint32_t getDefaultSampleDuration();
void setDefaultSampleSize(uint32_t newDefaultSampleSize);
uint32_t getDefaultSampleSize();
void setDefaultSampleFlags(uint32_t newDefaultSampleFlags);
uint32_t getDefaultSampleFlags();
std::string toPrettyString(uint32_t indent = 0);
};
class MFRA : public containerBox{
public:
MFRA();

View file

@ -69,6 +69,8 @@ namespace MP4{
co64Box.clear();
stscBox.clear();
stssBox.clear();
trexBox.clear();
trexPtr = 0;
stco64 = false;
trafMode = false;
trackId = 0;
@ -94,6 +96,11 @@ namespace MP4{
trafs.clear();
}
void TrackHeader::read(TREX &_trexBox){
trexBox.copyFrom(_trexBox);
if (trexBox.isType("trex")){trexPtr = &trexBox;}
}
void TrackHeader::read(TRAK &trakBox){
vidWidth = vidHeight = audChannels = audRate = audSize = 0;
codec.clear();
@ -428,7 +435,7 @@ namespace MP4{
// Okay, our index is inside this TRUN!
// Let's pull the TFHD box into this as well...
TFHD tfhd = ((TRAF)(*t)).getChild<TFHD>();
trunSampleInformation si = r->getSampleInformation(index - skipped, &tfhd);
trunSampleInformation si = r->getSampleInformation(index - skipped, &tfhd, trexPtr);
if (byteOffset){
size_t offset = 0;
if (tfhd.getDefaultBaseIsMoof()){
@ -438,7 +445,7 @@ namespace MP4{
offset += r->getDataOffset();
size_t target = index - skipped;
for (size_t i = 0; i < target; ++i){
offset += r->getSampleInformation(i, &tfhd).sampleSize;
offset += r->getSampleInformation(i, &tfhd, trexPtr).sampleSize;
}
}else{
FAIL_MSG("Unimplemented: trun box does not contain a data offset!");
@ -458,7 +465,7 @@ namespace MP4{
while (timeSample < index){
// Most common case: timeSample is in the current TRUN box
if (timeSample >= skipped && timeSample < skipped + count){
trunSampleInformation i = r->getSampleInformation(timeSample - skipped, &tfhd);
trunSampleInformation i = r->getSampleInformation(timeSample - skipped, &tfhd, trexPtr);
increaseTime(i.sampleDuration);
continue;
}
@ -475,7 +482,7 @@ namespace MP4{
break;
}
// Cool, now we know it's valid, increase the time accordingly.
trunSampleInformation i = runIt->getSampleInformation(timeSample - locSkipped, &tfhd);
trunSampleInformation i = runIt->getSampleInformation(timeSample - locSkipped, &tfhd, trexPtr);
increaseTime(i.sampleDuration);
}
*time = (timeTotal * 1000) / timeScale;

View file

@ -31,6 +31,8 @@ namespace MP4{
/// Reads (new) track header information for processing
void read(TRAK &trakBox);
/// Reads (new) track header information for processing
void read(TREX &trexBox);
/// Reads (new) track header information for processing
void read(TRAF &trafBox);
/// Signal that we're going to be reading the next moof box now.
@ -87,6 +89,8 @@ namespace MP4{
STTS sttsBox; ///< packet durations
CTTS cttsBox; ///< packet time offsets (optional)
STSC stscBox; ///< packet count per chunk
TREX trexBox; ///< packet count per chunk
TREX * trexPtr; ///< Either 0 or pointer to trexBox member
std::deque<TRAF> trafs; ///< Current traf boxes, if any
bool stco64; // 64 bit chunk offsets?
bool hasOffsets; ///< Are time offsets present?

View file

@ -200,6 +200,12 @@ namespace Mist{
mp4Headers.rbegin()->read(*trakIt);
mp4PacksLeft += mp4Headers.rbegin()->size();
}
std::deque<MP4::TREX> trex = ((MP4::MOOV*)&moovBox)->getChild<MP4::MVEX>().getChildren<MP4::TREX>();
for (std::deque<MP4::TREX>::iterator trexIt = trex.begin(); trexIt != trex.end(); trexIt++){
for (std::deque<MP4::TrackHeader>::iterator it = mp4Headers.begin(); it != mp4Headers.end(); ++it){
if (it->trackId == trexIt->getTrackID()){it->read(*trexIt);}
}
}
MEDIUM_MSG("Read moov box");
}
if (boxType == "moof"){
@ -262,6 +268,12 @@ namespace Mist{
mp4Headers.rbegin()->read(*trakIt);
mp4PacksLeft += mp4Headers.rbegin()->size();
}
std::deque<MP4::TREX> trex = ((MP4::MOOV*)&moovBox)->getChild<MP4::MVEX>().getChildren<MP4::TREX>();
for (std::deque<MP4::TREX>::iterator trexIt = trex.begin(); trexIt != trex.end(); trexIt++){
for (std::deque<MP4::TrackHeader>::iterator it = mp4Headers.begin(); it != mp4Headers.end(); ++it){
if (it->trackId == trexIt->getTrackID()){it->read(*trexIt);}
}
}
MEDIUM_MSG("Read moov box");
}
offset += boxSize;

View file

@ -97,6 +97,10 @@ bool AnalyserMP4::parsePacket(){
// Regardless of support, we now put it in our track header array (after all, even unsupported tracks can be analysed!)
hdrs[tHdr.trackId].read(*trakIt);
}
std::deque<MP4::TREX> trex = ((MP4::MOOV*)&mp4Data)->getChild<MP4::MVEX>().getChildren<MP4::TREX>();
for (std::deque<MP4::TREX>::iterator trexIt = trex.begin(); trexIt != trex.end(); trexIt++){
hdrs[trexIt->getTrackID()].read(*trexIt);
}
// If we stored an mdat earlier, we can now analyse and then wipe it
if (mdat.size()){
MP4::Box mdatBox(mdat, false);

View file

@ -130,6 +130,12 @@ namespace Mist{
trackHeaders.push_back(MP4::TrackHeader());
trackHeaders.rbegin()->read(*trakIt);
}
std::deque<MP4::TREX> trex = ((MP4::MOOV*)&moovBox)->getChild<MP4::MVEX>().getChildren<MP4::TREX>();
for (std::deque<MP4::TREX>::iterator trexIt = trex.begin(); trexIt != trex.end(); trexIt++){
for (std::deque<MP4::TrackHeader>::iterator it = trackHeaders.begin(); it != trackHeaders.end(); it++){
if (it->trackId == trexIt->getTrackID()){it->read(*trexIt);}
}
}
hasMoov = true;
}
activityCounter = Util::bootSecs();