Support for TREX boxes in MP4::Stream parser and all binaries that use it
This commit is contained in:
parent
57655f1b21
commit
0e26d49bec
7 changed files with 71 additions and 25 deletions
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue