Implemented TRUN box.
This commit is contained in:
parent
70fe4bbe98
commit
7492e99628
2 changed files with 190 additions and 40 deletions
187
lib/mp4.cpp
187
lib/mp4.cpp
|
@ -887,38 +887,169 @@ namespace MP4{
|
||||||
TRUN::TRUN(){
|
TRUN::TRUN(){
|
||||||
memcpy(data + 4, "trun", 4);
|
memcpy(data + 4, "trun", 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TRUN::setFlags( long newFlags ) {
|
void TRUN::setFlags(long newFlags){
|
||||||
setInt24(newFlags,1);
|
setInt24(newFlags,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TRUN::setDataOffset( long newOffset ) {
|
long TRUN::getFlags(){
|
||||||
dataOffset = newOffset;
|
return getInt24(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TRUN::setFirstSampleFlags( char sampleDependsOn, char sampleIsDependedOn, char sampleHasRedundancy, char sampleIsDifferenceSample ) {
|
void TRUN::setDataOffset(long newOffset){
|
||||||
firstSampleFlags = getSampleFlags( sampleDependsOn, sampleIsDependedOn, sampleHasRedundancy, sampleIsDifferenceSample );
|
if (getFlags() & dataOffset){
|
||||||
|
setInt32(newOffset, 8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TRUN::addSampleInformation( long newDuration, long newSize, char sampleDependsOn, char sampleIsDependedOn, char sampleHasRedundancy,char sampleIsDifferenceSample, long newCompositionTimeOffset ) {
|
long TRUN::getDataOffset(){
|
||||||
trunSampleInformation newSample;
|
if (getFlags() & dataOffset){
|
||||||
newSample.sampleDuration = newDuration;
|
return getInt32(8);
|
||||||
newSample.sampleSize = newSize;
|
}else{
|
||||||
newSample.sampleFlags = getSampleFlags( sampleDependsOn, sampleIsDependedOn, sampleHasRedundancy, sampleIsDifferenceSample );
|
return 0;
|
||||||
newSample.sampleCompositionTimeOffset = newCompositionTimeOffset;
|
}
|
||||||
allSamples.push_back( newSample );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long TRUN::getSampleFlags( char sampleDependsOn, char sampleIsDependedOn, char sampleHasRedundancy, char sampleIsDifferenceSample ) {
|
void TRUN::setFirstSampleFlags(long newSampleFlags){
|
||||||
long sampleFlags = ( sampleDependsOn & 0x03 );
|
if (!(getFlags() & firstSampleFlags)){return;}
|
||||||
sampleFlags <<= 2;
|
if (getFlags() & dataOffset){
|
||||||
sampleFlags += ( sampleIsDependedOn & 0x03 );
|
setInt32(newSampleFlags, 12);
|
||||||
sampleFlags <<= 2;
|
}else{
|
||||||
sampleFlags += ( sampleHasRedundancy & 0x03 );
|
setInt32(newSampleFlags, 8);
|
||||||
sampleFlags <<= 5;
|
}
|
||||||
sampleFlags += ( sampleIsDifferenceSample & 0x01 );
|
|
||||||
sampleFlags <<= 17;
|
|
||||||
sampleFlags += 0x0000FFFF;
|
|
||||||
return sampleFlags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long TRUN::getFirstSampleFlags(){
|
||||||
|
if (!(getFlags() & firstSampleFlags)){return 0;}
|
||||||
|
if (getFlags() & dataOffset){
|
||||||
|
return getInt32(12);
|
||||||
|
}else{
|
||||||
|
return getInt32(8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long TRUN::getSampleInformationCount(){
|
||||||
|
return getInt32(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;}
|
||||||
|
long offset = 8;
|
||||||
|
if (flags & dataOffset){offset += 4;}
|
||||||
|
if (flags & firstSampleFlags){offset += 4;}
|
||||||
|
long innerOffset = 0;
|
||||||
|
if (flags & sampleDuration){
|
||||||
|
setInt32(newSample.sampleDuration, offset + no*sampInfoSize + innerOffset);
|
||||||
|
innerOffset += 4;
|
||||||
|
}
|
||||||
|
if (flags & sampleSize){
|
||||||
|
setInt32(newSample.sampleSize, offset + no*sampInfoSize + innerOffset);
|
||||||
|
innerOffset += 4;
|
||||||
|
}
|
||||||
|
if (flags & sampleFlags){
|
||||||
|
setInt32(newSample.sampleFlags, offset + no*sampInfoSize + innerOffset);
|
||||||
|
innerOffset += 4;
|
||||||
|
}
|
||||||
|
if (flags & sampleOffsets){
|
||||||
|
setInt32(newSample.sampleOffset, offset + no*sampInfoSize + innerOffset);
|
||||||
|
innerOffset += 4;
|
||||||
|
}
|
||||||
|
if (getSampleInformationCount() < no+1){
|
||||||
|
setInt32(no+1,4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trunSampleInformation TRUN::getSampleInformation(long no){
|
||||||
|
trunSampleInformation ret;
|
||||||
|
ret.sampleDuration = 0;
|
||||||
|
ret.sampleSize = 0;
|
||||||
|
ret.sampleFlags = 0;
|
||||||
|
ret.sampleOffset = 0;
|
||||||
|
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;}
|
||||||
|
long offset = 8;
|
||||||
|
if (flags & dataOffset){offset += 4;}
|
||||||
|
if (flags & firstSampleFlags){offset += 4;}
|
||||||
|
long innerOffset = 0;
|
||||||
|
if (flags & sampleDuration){
|
||||||
|
ret.sampleDuration = getInt32(offset + no*sampInfoSize + innerOffset);
|
||||||
|
innerOffset += 4;
|
||||||
|
}
|
||||||
|
if (flags & sampleSize){
|
||||||
|
ret.sampleSize = getInt32(offset + no*sampInfoSize + innerOffset);
|
||||||
|
innerOffset += 4;
|
||||||
|
}
|
||||||
|
if (flags & sampleFlags){
|
||||||
|
ret.sampleFlags = getInt32(offset + no*sampInfoSize + innerOffset);
|
||||||
|
innerOffset += 4;
|
||||||
|
}
|
||||||
|
if (flags & sampleOffsets){
|
||||||
|
ret.sampleOffset = getInt32(offset + no*sampInfoSize + innerOffset);
|
||||||
|
innerOffset += 4;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TRUN::toPrettyString(long indent){
|
||||||
|
std::stringstream r;
|
||||||
|
r << std::string(indent, ' ') << "[trun] Track Fragment Run" << std::endl;
|
||||||
|
r << std::string(indent+1, ' ') << "Version " << getInt8(0) << std::endl;
|
||||||
|
|
||||||
|
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";}
|
||||||
|
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;}
|
||||||
|
|
||||||
|
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){
|
||||||
|
r << std::string(indent+2, ' ') << "Duration " << samp.sampleDuration << std::endl;
|
||||||
|
}
|
||||||
|
if (flags & sampleSize){
|
||||||
|
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 & sampleOffsets){
|
||||||
|
r << std::string(indent+2, ' ') << "Offset " << samp.sampleOffset << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TRUN::prettyFlags(long flag){
|
||||||
|
std::stringstream r;
|
||||||
|
if (flag & noIPicture){r << " noIPicture";}
|
||||||
|
if (flag & isIPicture){r << " isIPicture";}
|
||||||
|
if (flag & noDisposable){r << " noDisposable";}
|
||||||
|
if (flag & isDisposable){r << " isDisposable";}
|
||||||
|
if (flag & isRedundant){r << " isRedundant";}
|
||||||
|
if (flag & noRedundant){r << " noRedundant";}
|
||||||
|
if (flag & noKeySample){r << " noKeySample";}else{r << " isKeySample";}
|
||||||
|
return r.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
43
lib/mp4.h
43
lib/mp4.h
|
@ -158,21 +158,40 @@ namespace MP4{
|
||||||
long sampleDuration;
|
long sampleDuration;
|
||||||
long sampleSize;
|
long sampleSize;
|
||||||
long sampleFlags;
|
long sampleFlags;
|
||||||
long sampleCompositionTimeOffset;
|
long sampleOffset;
|
||||||
|
};
|
||||||
|
enum trunflags {
|
||||||
|
dataOffset = 0x000001,
|
||||||
|
firstSampleFlags = 0x000004,
|
||||||
|
sampleDuration = 0x000100,
|
||||||
|
sampleSize = 0x000200,
|
||||||
|
sampleFlags = 0x000400,
|
||||||
|
sampleOffsets = 0x000800
|
||||||
|
};
|
||||||
|
enum sampleflags {
|
||||||
|
noIPicture = 0x1000000,
|
||||||
|
isIPicture = 0x2000000,
|
||||||
|
noDisposable = 0x400000,
|
||||||
|
isDisposable = 0x800000,
|
||||||
|
isRedundant = 0x100000,
|
||||||
|
noRedundant = 0x200000,
|
||||||
|
noKeySample = 0x10000,
|
||||||
|
iskeySample = 0x0,
|
||||||
|
MUST_BE_PRESENT = 0x1
|
||||||
};
|
};
|
||||||
|
|
||||||
class TRUN : public Box {
|
class TRUN : public Box {
|
||||||
public:
|
public:
|
||||||
TRUN();
|
TRUN();
|
||||||
void setFlags( long newFlags );
|
void setFlags(long newFlags);
|
||||||
void setDataOffset( long newOffset );
|
long getFlags();
|
||||||
void setFirstSampleFlags( char sampleDependsOn, char sampleIsDependedOn, char sampleHasRedundancy, char sampleIsDifferenceSample );
|
void setDataOffset(long newOffset);
|
||||||
void addSampleInformation( long newDuration, long newSize, char sampleDependsOn, char sampleIsDependedOn, char sampleHasRedundancy,char sampleIsDifferenceSample, long newCompositionTimeOffset );
|
long getDataOffset();
|
||||||
void regenerate();
|
void setFirstSampleFlags(long newSampleFlags);
|
||||||
private:
|
long getFirstSampleFlags();
|
||||||
long getSampleFlags( char sampleDependsOn, char sampleIsDependedOn, char sampleHasRedundancy, char sampleIsDifferenceSample );
|
long getSampleInformationCount();
|
||||||
long dataOffset;
|
void setSampleInformation(trunSampleInformation newSample, long no);
|
||||||
long firstSampleFlags;
|
trunSampleInformation getSampleInformation(long no);
|
||||||
std::deque<trunSampleInformation> allSamples;
|
std::string toPrettyString(long indent = 0);
|
||||||
|
std::string prettyFlags(long flag);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue