Implement MP4 transformation matrixes with support for basic rotations
This commit is contained in:
parent
1aaaeebb24
commit
e69050224b
2 changed files with 62 additions and 14 deletions
|
@ -1604,9 +1604,10 @@ namespace MP4{
|
||||||
setDuration(duration); // in ms
|
setDuration(duration); // in ms
|
||||||
setRate(0x00010000); // playback rate 1.0X
|
setRate(0x00010000); // playback rate 1.0X
|
||||||
setVolume(0x0100); // volume 1.0X
|
setVolume(0x0100); // volume 1.0X
|
||||||
setMatrix(0x00010000, 0);
|
//Identity Transformation Matrix
|
||||||
setMatrix(0x00010000, 4);
|
setMatrix(1, 0);
|
||||||
setMatrix(0x40000000, 8);
|
setMatrix(1, 4);
|
||||||
|
setMatrix(1, 8);
|
||||||
setTrackID(0xFFFFFFFF); // empty track numbers is unknown
|
setTrackID(0xFFFFFFFF); // empty track numbers is unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1708,24 +1709,45 @@ namespace MP4{
|
||||||
// 10 bytes reserved in between
|
// 10 bytes reserved in between
|
||||||
uint32_t MVHD::getMatrixCount(){return 9;}
|
uint32_t MVHD::getMatrixCount(){return 9;}
|
||||||
|
|
||||||
void MVHD::setMatrix(int32_t newMatrix, size_t index){
|
void MVHD::setMatrix(double newMatrix, size_t index){
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if (getVersion() == 0){
|
if (getVersion() == 0){
|
||||||
offset = 24 + 2 + 10;
|
offset = 24 + 2 + 10;
|
||||||
}else{
|
}else{
|
||||||
offset = 36 + 2 + 10;
|
offset = 36 + 2 + 10;
|
||||||
}
|
}
|
||||||
setInt32(newMatrix, offset + index * 4);
|
//Indexes 2, 6 and 8 are 2.30 fixed point, the rest is 16.16 fixed point.
|
||||||
|
if (index == 2 || index == 5 || index == 8){
|
||||||
|
setInt32((int32_t)(newMatrix * 1073741824.0), offset + index * 4);
|
||||||
|
}else{
|
||||||
|
setInt32((int32_t)(newMatrix * 65536.0), offset + index * 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t MVHD::getMatrix(size_t index){
|
double MVHD::getMatrix(size_t index){
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if (getVersion() == 0){
|
if (getVersion() == 0){
|
||||||
offset = 36;
|
offset = 36;
|
||||||
}else{
|
}else{
|
||||||
offset = 48;
|
offset = 48;
|
||||||
}
|
}
|
||||||
return getInt32(offset + index * 4);
|
//Indexes 2, 6 and 8 are 2.30 fixed point, the rest is 16.16 fixed point.
|
||||||
|
if (index == 2 || index == 5 || index == 8){
|
||||||
|
return (int32_t)getInt32(offset + index * 4) / 1073741824.0;
|
||||||
|
}else{
|
||||||
|
return (int32_t)getInt32(offset + index * 4) / 65536.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t MVHD::getRotation(){
|
||||||
|
//These are oversimplifications that ignore scaling and translation
|
||||||
|
//We also only handle the 90-degree-increment rotations, nothing else
|
||||||
|
//That should cover practically all videos we'll encounter though...
|
||||||
|
if (getMatrix(1) > 0.0 && getMatrix(3) < 0.0){return 90;}
|
||||||
|
if (getMatrix(1) < 0.0 && getMatrix(3) > 0.0){return 270;}
|
||||||
|
if (getMatrix(0) > 0.0 && getMatrix(4) > 0.0){return 0;}
|
||||||
|
if (getMatrix(0) < 0.0 && getMatrix(4) < 0.0){return 180;}
|
||||||
|
return 0; //Unknown rotation, assume none
|
||||||
}
|
}
|
||||||
|
|
||||||
// 24 bytes of pre-defined in between
|
// 24 bytes of pre-defined in between
|
||||||
|
@ -1761,6 +1783,7 @@ namespace MP4{
|
||||||
if (i != getMatrixCount() - 1){r << ", ";}
|
if (i != getMatrixCount() - 1){r << ", ";}
|
||||||
}
|
}
|
||||||
r << std::endl;
|
r << std::endl;
|
||||||
|
r << std::string(indent + 1, ' ') << "Rotation (calculated from Matrix): " << getRotation() << std::endl;
|
||||||
r << std::string(indent + 1, ' ') << "next_track_ID: " << getTrackID() << std::endl;
|
r << std::string(indent + 1, ' ') << "next_track_ID: " << getTrackID() << std::endl;
|
||||||
return r.str();
|
return r.str();
|
||||||
}
|
}
|
||||||
|
@ -1937,9 +1960,10 @@ namespace MP4{
|
||||||
}
|
}
|
||||||
memset(data + payloadOffset, 0, 84); // set all bytes (92 - 8) to zeroes
|
memset(data + payloadOffset, 0, 84); // set all bytes (92 - 8) to zeroes
|
||||||
setFlags(3); // ENABLED | IN_MOVIE
|
setFlags(3); // ENABLED | IN_MOVIE
|
||||||
setMatrix(0x00010000, 0);
|
//Identity transformation Matrix
|
||||||
setMatrix(0x00010000, 4);
|
setMatrix(1, 0);
|
||||||
setMatrix(0x40000000, 8);
|
setMatrix(1, 4);
|
||||||
|
setMatrix(1, 8);
|
||||||
setVolume(0x0100);
|
setVolume(0x0100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2064,7 +2088,12 @@ namespace MP4{
|
||||||
}else{
|
}else{
|
||||||
offset = 52;
|
offset = 52;
|
||||||
}
|
}
|
||||||
setInt32(newMatrix, offset + index * 4);
|
//Indexes 2, 6 and 8 are 2.30 fixed point, the rest is 16.16 fixed point.
|
||||||
|
if (index == 2 || index == 5 || index == 8){
|
||||||
|
setInt32((int32_t)(newMatrix * 1073741824.0), offset + index * 4);
|
||||||
|
}else{
|
||||||
|
setInt32((int32_t)(newMatrix * 65536.0), offset + index * 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t TKHD::getMatrix(size_t index){
|
int32_t TKHD::getMatrix(size_t index){
|
||||||
|
@ -2074,7 +2103,23 @@ namespace MP4{
|
||||||
}else{
|
}else{
|
||||||
offset = 52;
|
offset = 52;
|
||||||
}
|
}
|
||||||
return getInt32(offset + index * 4);
|
//Indexes 2, 6 and 8 are 2.30 fixed point, the rest is 16.16 fixed point.
|
||||||
|
if (index == 2 || index == 5 || index == 8){
|
||||||
|
return (int32_t)getInt32(offset + index * 4) / 1073741824.0;
|
||||||
|
}else{
|
||||||
|
return (int32_t)getInt32(offset + index * 4) / 65536.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t TKHD::getRotation(){
|
||||||
|
//These are oversimplifications that ignore scaling and translation
|
||||||
|
//We also only handle the 90-degree-increment rotations, nothing else
|
||||||
|
//That should cover practically all videos we'll encounter though...
|
||||||
|
if (getMatrix(1) > 0.0 && getMatrix(3) < 0.0){return 90;}
|
||||||
|
if (getMatrix(1) < 0.0 && getMatrix(3) > 0.0){return 270;}
|
||||||
|
if (getMatrix(0) > 0.0 && getMatrix(4) > 0.0){return 0;}
|
||||||
|
if (getMatrix(0) < 0.0 && getMatrix(4) < 0.0){return 180;}
|
||||||
|
return 0; //Unknown rotation, assume none
|
||||||
}
|
}
|
||||||
|
|
||||||
void TKHD::setWidth(double newWidth){
|
void TKHD::setWidth(double newWidth){
|
||||||
|
@ -2126,6 +2171,7 @@ namespace MP4{
|
||||||
if (i != getMatrixCount() - 1){r << ", ";}
|
if (i != getMatrixCount() - 1){r << ", ";}
|
||||||
}
|
}
|
||||||
r << std::endl;
|
r << std::endl;
|
||||||
|
r << std::string(indent + 1, ' ') << "Rotation (calculated from Matrix): " << getRotation() << std::endl;
|
||||||
r << std::string(indent + 1, ' ') << "Width: " << getWidth() << std::endl;
|
r << std::string(indent + 1, ' ') << "Width: " << getWidth() << std::endl;
|
||||||
r << std::string(indent + 1, ' ') << "Height: " << getHeight() << std::endl;
|
r << std::string(indent + 1, ' ') << "Height: " << getHeight() << std::endl;
|
||||||
return r.str();
|
return r.str();
|
||||||
|
|
|
@ -470,8 +470,9 @@ namespace MP4{
|
||||||
void setVolume(uint16_t newVolume);
|
void setVolume(uint16_t newVolume);
|
||||||
uint16_t getVolume();
|
uint16_t getVolume();
|
||||||
uint32_t getMatrixCount();
|
uint32_t getMatrixCount();
|
||||||
void setMatrix(int32_t newMatrix, size_t index);
|
void setMatrix(double newMatrix, size_t index);
|
||||||
int32_t getMatrix(size_t index);
|
double getMatrix(size_t index);
|
||||||
|
uint16_t getRotation();
|
||||||
void setTrackID(uint32_t newTrackID);
|
void setTrackID(uint32_t newTrackID);
|
||||||
uint32_t getTrackID();
|
uint32_t getTrackID();
|
||||||
std::string toPrettyString(uint32_t indent = 0);
|
std::string toPrettyString(uint32_t indent = 0);
|
||||||
|
@ -529,6 +530,7 @@ namespace MP4{
|
||||||
uint32_t getMatrixCount();
|
uint32_t getMatrixCount();
|
||||||
void setMatrix(int32_t newMatrix, size_t index);
|
void setMatrix(int32_t newMatrix, size_t index);
|
||||||
int32_t getMatrix(size_t index);
|
int32_t getMatrix(size_t index);
|
||||||
|
uint16_t getRotation();
|
||||||
|
|
||||||
void setWidth(double newWidth);
|
void setWidth(double newWidth);
|
||||||
double getWidth();
|
double getWidth();
|
||||||
|
|
Loading…
Add table
Reference in a new issue