From d9b8f7c7f05e0721ea4a73217d0a7f16a894e3ed Mon Sep 17 00:00:00 2001 From: Thulinma Date: Tue, 25 Sep 2012 12:42:55 +0200 Subject: [PATCH] Implemented TFHD box - fixed TRUN namespace pollution. --- lib/mp4.cpp | 207 ++++++++++++++++++++++++++++++++++++++++++---------- lib/mp4.h | 43 +++++++++-- 2 files changed, 203 insertions(+), 47 deletions(-) diff --git a/lib/mp4.cpp b/lib/mp4.cpp index 8e78fdf3..f7a318f3 100644 --- a/lib/mp4.cpp +++ b/lib/mp4.cpp @@ -897,13 +897,13 @@ namespace MP4{ } void TRUN::setDataOffset(long newOffset){ - if (getFlags() & dataOffset){ + if (getFlags() & trundataOffset){ setInt32(newOffset, 8); } } long TRUN::getDataOffset(){ - if (getFlags() & dataOffset){ + if (getFlags() & trundataOffset){ return getInt32(8); }else{ return 0; @@ -911,8 +911,8 @@ namespace MP4{ } void TRUN::setFirstSampleFlags(long newSampleFlags){ - if (!(getFlags() & firstSampleFlags)){return;} - if (getFlags() & dataOffset){ + if (!(getFlags() & trunfirstSampleFlags)){return;} + if (getFlags() & trundataOffset){ setInt32(newSampleFlags, 12); }else{ setInt32(newSampleFlags, 8); @@ -920,8 +920,8 @@ namespace MP4{ } long TRUN::getFirstSampleFlags(){ - if (!(getFlags() & firstSampleFlags)){return 0;} - if (getFlags() & dataOffset){ + if (!(getFlags() & trunfirstSampleFlags)){return 0;} + if (getFlags() & trundataOffset){ return getInt32(12); }else{ return getInt32(8); @@ -935,27 +935,27 @@ namespace MP4{ void TRUN::setSampleInformation(trunSampleInformation newSample, long no){ long flags = getFlags(); long sampInfoSize = 0; - if (flags & sampleDuration){sampInfoSize += 4;} - if (flags & sampleSize){sampInfoSize += 4;} - if (flags & sampleFlags){sampInfoSize += 4;} - if (flags & sampleOffsets){sampInfoSize += 4;} + if (flags & trunsampleDuration){sampInfoSize += 4;} + if (flags & trunsampleSize){sampInfoSize += 4;} + if (flags & trunsampleFlags){sampInfoSize += 4;} + if (flags & trunsampleOffsets){sampInfoSize += 4;} long offset = 8; - if (flags & dataOffset){offset += 4;} - if (flags & firstSampleFlags){offset += 4;} + if (flags & trundataOffset){offset += 4;} + if (flags & trunfirstSampleFlags){offset += 4;} long innerOffset = 0; - if (flags & sampleDuration){ + if (flags & trunsampleDuration){ setInt32(newSample.sampleDuration, offset + no*sampInfoSize + innerOffset); innerOffset += 4; } - if (flags & sampleSize){ + if (flags & trunsampleSize){ setInt32(newSample.sampleSize, offset + no*sampInfoSize + innerOffset); innerOffset += 4; } - if (flags & sampleFlags){ + if (flags & trunsampleFlags){ setInt32(newSample.sampleFlags, offset + no*sampInfoSize + innerOffset); innerOffset += 4; } - if (flags & sampleOffsets){ + if (flags & trunsampleOffsets){ setInt32(newSample.sampleOffset, offset + no*sampInfoSize + innerOffset); innerOffset += 4; } @@ -973,27 +973,27 @@ namespace MP4{ if (getSampleInformationCount() < no+1){return ret;} long flags = getFlags(); long sampInfoSize = 0; - if (flags & sampleDuration){sampInfoSize += 4;} - if (flags & sampleSize){sampInfoSize += 4;} - if (flags & sampleFlags){sampInfoSize += 4;} - if (flags & sampleOffsets){sampInfoSize += 4;} + if (flags & trunsampleDuration){sampInfoSize += 4;} + if (flags & trunsampleSize){sampInfoSize += 4;} + if (flags & trunsampleFlags){sampInfoSize += 4;} + if (flags & trunsampleOffsets){sampInfoSize += 4;} long offset = 8; - if (flags & dataOffset){offset += 4;} - if (flags & firstSampleFlags){offset += 4;} + if (flags & trundataOffset){offset += 4;} + if (flags & trunfirstSampleFlags){offset += 4;} long innerOffset = 0; - if (flags & sampleDuration){ + if (flags & trunsampleDuration){ ret.sampleDuration = getInt32(offset + no*sampInfoSize + innerOffset); innerOffset += 4; } - if (flags & sampleSize){ + if (flags & trunsampleSize){ ret.sampleSize = getInt32(offset + no*sampInfoSize + innerOffset); innerOffset += 4; } - if (flags & sampleFlags){ + if (flags & trunsampleFlags){ ret.sampleFlags = getInt32(offset + no*sampInfoSize + innerOffset); innerOffset += 4; } - if (flags & sampleOffsets){ + if (flags & trunsampleOffsets){ ret.sampleOffset = getInt32(offset + no*sampInfoSize + innerOffset); innerOffset += 4; } @@ -1007,31 +1007,31 @@ namespace MP4{ long flags = getFlags(); r << std::string(indent+1, ' ') << "Flags"; - if (flags & dataOffset){r << " dataOffset";} - if (flags & firstSampleFlags){r << " firstSampleFlags";} - if (flags & sampleDuration){r << " sampleDuration";} - if (flags & sampleSize){r << " sampleSize";} - if (flags & sampleFlags){r << " sampleFlags";} - if (flags & sampleOffsets){r << " sampleOffsets";} + if (flags & trundataOffset){r << " dataOffset";} + if (flags & trunfirstSampleFlags){r << " firstSampleFlags";} + if (flags & trunsampleDuration){r << " sampleDuration";} + if (flags & trunsampleSize){r << " sampleSize";} + if (flags & trunsampleFlags){r << " sampleFlags";} + if (flags & trunsampleOffsets){r << " sampleOffsets";} r << std::endl; - if (flags & dataOffset){r << std::string(indent+1, ' ') << "Data Offset " << getDataOffset() << std::endl;} - if (flags & dataOffset){r << std::string(indent+1, ' ') << "Sample Flags" << prettyFlags(getFirstSampleFlags()) << std::endl;} + if (flags & trundataOffset){r << std::string(indent+1, ' ') << "Data Offset " << getDataOffset() << std::endl;} + if (flags & trundataOffset){r << std::string(indent+1, ' ') << "Sample Flags" << prettySampleFlags(getFirstSampleFlags()) << std::endl;} r << std::string(indent+1, ' ') << "SampleInformation (" << getSampleInformationCount() << "):" << std::endl; for (int i = 0; i < getSampleInformationCount(); ++i){ r << std::string(indent+2, ' ') << "[" << i << "]" << std::endl; trunSampleInformation samp = getSampleInformation(i); - if (flags & sampleDuration){ + if (flags & trunsampleDuration){ r << std::string(indent+2, ' ') << "Duration " << samp.sampleDuration << std::endl; } - if (flags & sampleSize){ + if (flags & trunsampleSize){ r << std::string(indent+2, ' ') << "Size " << samp.sampleSize << std::endl; } - if (flags & sampleFlags){ - r << std::string(indent+2, ' ') << "Flags " << prettyFlags(samp.sampleFlags) << std::endl; + if (flags & trunsampleFlags){ + r << std::string(indent+2, ' ') << "Flags " << prettySampleFlags(samp.sampleFlags) << std::endl; } - if (flags & sampleOffsets){ + if (flags & trunsampleOffsets){ r << std::string(indent+2, ' ') << "Offset " << samp.sampleOffset << std::endl; } } @@ -1039,7 +1039,7 @@ namespace MP4{ return r.str(); } - std::string TRUN::prettyFlags(long flag){ + std::string prettySampleFlags(long flag){ std::stringstream r; if (flag & noIPicture){r << " noIPicture";} if (flag & isIPicture){r << " isIPicture";} @@ -1051,5 +1051,132 @@ namespace MP4{ return r.str(); } + TFHD::TFHD(){ + memcpy(data + 4, "tfhd", 4); + } + + void TFHD::setFlags(long newFlags){ + setInt24(newFlags,1); + } + + long TFHD::getFlags(){ + return getInt24(1); + } + + void TFHD::setTrackID(long newID){ + setInt32(newID,4); + } + + long TFHD::getTrackID(){ + return getInt32(4); + } + + void TFHD::setBaseDataOffset(long long newOffset){ + if (getFlags() & tfhdBaseOffset){ + setInt64(newOffset, 8); + } + } + + long long TFHD::getBaseDataOffset(){ + if (getFlags() & tfhdBaseOffset){ + return getInt64(8); + }else{ + return 0; + } + } + + void TFHD::setSampleDescriptionIndex(long newIndex){ + if (!(getFlags() & tfhdSampleDesc)){return;} + int offset = 8; + if (getFlags() & tfhdBaseOffset){offset += 8;} + setInt32(newIndex, offset); + } + + long TFHD::getSampleDescriptionIndex(){ + if (!(getFlags() & tfhdSampleDesc)){return 0;} + int offset = 8; + if (getFlags() & tfhdBaseOffset){offset += 8;} + return getInt32(offset); + } + + void TFHD::setDefaultSampleDuration(long newDuration){ + if (!(getFlags() & tfhdSampleDura)){return;} + int offset = 8; + if (getFlags() & tfhdBaseOffset){offset += 8;} + if (getFlags() & tfhdSampleDesc){offset += 4;} + setInt32(newDuration, offset); + } + + long TFHD::getDefaultSampleDuration(){ + if (!(getFlags() & tfhdSampleDura)){return 0;} + int offset = 8; + if (getFlags() & tfhdBaseOffset){offset += 8;} + if (getFlags() & tfhdSampleDesc){offset += 4;} + return getInt32(offset); + } + + void TFHD::setDefaultSampleSize(long newSize){ + if (!(getFlags() & tfhdSampleSize)){return;} + int offset = 8; + if (getFlags() & tfhdBaseOffset){offset += 8;} + if (getFlags() & tfhdSampleDesc){offset += 4;} + if (getFlags() & tfhdSampleDura){offset += 4;} + setInt32(newSize, offset); + } + + long TFHD::getDefaultSampleSize(){ + if (!(getFlags() & tfhdSampleSize)){return 0;} + int offset = 8; + if (getFlags() & tfhdBaseOffset){offset += 8;} + if (getFlags() & tfhdSampleDesc){offset += 4;} + if (getFlags() & tfhdSampleDura){offset += 4;} + return getInt32(offset); + } + + void TFHD::setDefaultSampleFlags(long newFlags){ + if (!(getFlags() & tfhdSampleFlag)){return;} + int offset = 8; + if (getFlags() & tfhdBaseOffset){offset += 8;} + if (getFlags() & tfhdSampleDesc){offset += 4;} + if (getFlags() & tfhdSampleDura){offset += 4;} + if (getFlags() & tfhdSampleSize){offset += 4;} + setInt32(newFlags, offset); + } + + long TFHD::getDefaultSampleFlags(){ + if (!(getFlags() & tfhdSampleFlag)){return 0;} + int offset = 8; + if (getFlags() & tfhdBaseOffset){offset += 8;} + if (getFlags() & tfhdSampleDesc){offset += 4;} + if (getFlags() & tfhdSampleDura){offset += 4;} + if (getFlags() & tfhdSampleSize){offset += 4;} + return getInt32(offset); + } + + std::string TFHD::toPrettyString(long indent){ + std::stringstream r; + r << std::string(indent, ' ') << "[tfhd] Track Fragment Header" << std::endl; + r << std::string(indent+1, ' ') << "Version " << getInt8(0) << std::endl; + + long flags = getFlags(); + r << std::string(indent+1, ' ') << "Flags"; + if (flags & tfhdBaseOffset){r << " BaseOffset";} + if (flags & tfhdSampleDesc){r << " SampleDesc";} + if (flags & tfhdSampleDura){r << " SampleDura";} + if (flags & tfhdSampleSize){r << " SampleSize";} + if (flags & tfhdSampleFlag){r << " SampleFlag";} + if (flags & tfhdNoDuration){r << " NoDuration";} + r << std::endl; + + r << std::string(indent+1, ' ') << "TrackID " << getTrackID() << std::endl; + + if (flags & tfhdBaseOffset){r << std::string(indent+1, ' ') << "Base Offset " << getBaseDataOffset() << std::endl;} + if (flags & tfhdSampleDesc){r << std::string(indent+1, ' ') << "Sample Description Index " << getSampleDescriptionIndex() << std::endl;} + if (flags & tfhdSampleDura){r << std::string(indent+1, ' ') << "Default Sample Duration " << getDefaultSampleDuration() << std::endl;} + if (flags & tfhdSampleSize){r << std::string(indent+1, ' ') << "Default Same Size " << getDefaultSampleSize() << std::endl;} + if (flags & tfhdSampleFlag){r << std::string(indent+1, ' ') << "Default Sample Flags " << prettySampleFlags(getDefaultSampleFlags()) << std::endl;} + + return r.str(); + } }; diff --git a/lib/mp4.h b/lib/mp4.h index 29c8fd56..23129af1 100644 --- a/lib/mp4.h +++ b/lib/mp4.h @@ -161,12 +161,12 @@ namespace MP4{ long sampleOffset; }; enum trunflags { - dataOffset = 0x000001, - firstSampleFlags = 0x000004, - sampleDuration = 0x000100, - sampleSize = 0x000200, - sampleFlags = 0x000400, - sampleOffsets = 0x000800 + trundataOffset = 0x000001, + trunfirstSampleFlags = 0x000004, + trunsampleDuration = 0x000100, + trunsampleSize = 0x000200, + trunsampleFlags = 0x000400, + trunsampleOffsets = 0x000800 }; enum sampleflags { noIPicture = 0x1000000, @@ -179,6 +179,7 @@ namespace MP4{ iskeySample = 0x0, MUST_BE_PRESENT = 0x1 }; + std::string prettySampleFlags(long flag); class TRUN : public Box { public: TRUN(); @@ -192,6 +193,34 @@ namespace MP4{ void setSampleInformation(trunSampleInformation newSample, long no); trunSampleInformation getSampleInformation(long no); std::string toPrettyString(long indent = 0); - std::string prettyFlags(long flag); }; + + enum tfhdflags { + tfhdBaseOffset = 0x000001, + tfhdSampleDesc = 0x000002, + tfhdSampleDura = 0x000008, + tfhdSampleSize = 0x000010, + tfhdSampleFlag = 0x000020, + tfhdNoDuration = 0x010000, + }; + class TFHD : public Box { + public: + TFHD(); + void setFlags(long newFlags); + long getFlags(); + void setTrackID(long newID); + long getTrackID(); + void setBaseDataOffset(long long newOffset); + long long getBaseDataOffset(); + void setSampleDescriptionIndex(long newIndex); + long getSampleDescriptionIndex(); + void setDefaultSampleDuration(long newDuration); + long getDefaultSampleDuration(); + void setDefaultSampleSize(long newSize); + long getDefaultSampleSize(); + void setDefaultSampleFlags(long newFlags); + long getDefaultSampleFlags(); + std::string toPrettyString(long indent = 0); + }; + };