diff --git a/Source/CLI/Help.cpp b/Source/CLI/Help.cpp index fbdf423..833fcdf 100644 --- a/Source/CLI/Help.cpp +++ b/Source/CLI/Help.cpp @@ -112,6 +112,11 @@ ReturnValue Help_Tech(bool WithExamples) TEXTOUT(" Modify the field handling parameter to VALUE, \"fields,detail\" format"); TEXTOUT(" --field-delete"); TEXTOUT(" Delete the field handling atom"); + TEXTOUT("Options related to video stsd field handling"); + TEXTOUT(" --stsd-video-version VALUE"); + TEXTOUT(" Modify the field version to VALUE for the first video stream, integer value between 0 and 3"); + TEXTOUT(" --temporal-quality VALUE"); + TEXTOUT(" Modify the temporal quality to VALUE, integer value"); TEXTOUT("Options related to the color parameter:"); TEXTOUT(" --color VALUE"); TEXTOUT(" Modify the color parameter to VALUE, \"primaries,transfer,matrix\" format"); diff --git a/Source/Common/mp4/mp4_.h b/Source/Common/mp4/mp4_.h index 129890e..2ba119e 100644 --- a/Source/Common/mp4/mp4_.h +++ b/Source/Common/mp4/mp4_.h @@ -105,6 +105,19 @@ protected: \ void Write_Internal(); \ }; \ +//Chunk with modification/insertion/write +#define CHUNK_M(_Level, _Name) \ +class mp4_##_Name : public mp4_Base \ +{ \ +public: \ + mp4_##_Name(global* Global):mp4_Base(Global, _Level) {Chunk.Header.Name=Elements::_Name;} \ +protected: \ + void Read_Internal(); \ + void Modify_Internal(); \ + size_t Insert_Internal(int32u Chunk_Name_Insert); \ + void Write_Internal(); \ +}; \ + CHUNK_W(1, mdat); CHUNK_W(1, free); CHUNK_I(1, moov); @@ -117,7 +130,7 @@ CHUNK__(3, moov_trak_mdia); CHUNK__(4, moov_trak_mdia_minf); CHUNK__(5, moov_trak_mdia_minf_stbl); CHUNK__(6, moov_trak_mdia_minf_stbl_stsd); -CHUNK_I(7, moov_trak_mdia_minf_stbl_stsd_xxxxVideo); +CHUNK_M(7, moov_trak_mdia_minf_stbl_stsd_xxxxVideo); CHUNK_W(8, moov_trak_mdia_minf_stbl_stsd_xxxx_clap); CHUNK_W(8, moov_trak_mdia_minf_stbl_stsd_xxxx_colr); CHUNK_W(8, moov_trak_mdia_minf_stbl_stsd_xxxx_fiel); diff --git a/Source/Common/mp4/mp4_moov_trak_mdia_mdhd.cpp b/Source/Common/mp4/mp4_moov_trak_mdia_mdhd.cpp index 753ca76..0df4a90 100644 --- a/Source/Common/mp4/mp4_moov_trak_mdia_mdhd.cpp +++ b/Source/Common/mp4/mp4_moov_trak_mdia_mdhd.cpp @@ -17,7 +17,7 @@ //--------------------------------------------------------------------------- void mp4_moov_trak_mdia_mdhd::Read_Internal() { - Chunk.trak_Index=Global->moov_trak.size(); + Chunk.trak_Index=Global->moov_trak.size()-1; Global->moov_trak_mdia_mdhd[Chunk.trak_Index]=new global::block_moov_trak_mdia_mdhd(); Read_Internal_ReadAllInBuffer(); diff --git a/Source/Common/mp4/mp4_moov_trak_mdia_minf_stbl_stsd_xxxxSound.cpp b/Source/Common/mp4/mp4_moov_trak_mdia_minf_stbl_stsd_xxxxSound.cpp index 778c8b6..42b1409 100644 --- a/Source/Common/mp4/mp4_moov_trak_mdia_minf_stbl_stsd_xxxxSound.cpp +++ b/Source/Common/mp4/mp4_moov_trak_mdia_minf_stbl_stsd_xxxxSound.cpp @@ -24,7 +24,7 @@ void mp4_moov_trak_mdia_minf_stbl_stsd_xxxxSound::Read_Internal () Chunk.Content.Size=Chunk.Content.Before_Subs_Content_Size; // Trick to read only node data Read_Internal_ReadAllInBuffer(); Chunk.Content.Size=Content_Size; - Chunk.trak_Index=Global->moov_trak.size(); + Chunk.trak_Index=Global->moov_trak.size()-1; Skip_XX(6); // Reserved; Skip_XX(2); // Data reference index diff --git a/Source/Common/mp4/mp4_moov_trak_mdia_minf_stbl_stsd_xxxxVideo.cpp b/Source/Common/mp4/mp4_moov_trak_mdia_minf_stbl_stsd_xxxxVideo.cpp index 4fbf43d..a82bb87 100644 --- a/Source/Common/mp4/mp4_moov_trak_mdia_minf_stbl_stsd_xxxxVideo.cpp +++ b/Source/Common/mp4/mp4_moov_trak_mdia_minf_stbl_stsd_xxxxVideo.cpp @@ -15,6 +15,12 @@ //--------------------------------------------------------------------------- void mp4_moov_trak_mdia_minf_stbl_stsd_xxxxVideo::Read_Internal () { + Chunk.trak_Index=Global->moov_trak.size()-1; + + if (Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo.count(Chunk.trak_Index)) + throw exception_read_block("2 moov trak mdia minf stbl stsd xxxxVideo blocks"); + + Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]=new global::block_moov_trak_mdia_minf_stbl_stsd_xxxxVideo(); //Reading if (Chunk.Content.Size<78) @@ -24,29 +30,29 @@ void mp4_moov_trak_mdia_minf_stbl_stsd_xxxxVideo::Read_Internal () Chunk.Content.Size=Chunk.Content.Before_Subs_Content_Size; // Trick to read only node data Read_Internal_ReadAllInBuffer(); Chunk.Content.Size=Content_Size; - Chunk.trak_Index=Global->moov_trak.size(); - uint16_t Version, Depth, ColorTableID; - - Skip_XX(6); // Reserved - Skip_XX(2); // Data reference index - Get_B2(Version); - if (Version>3) + Get_B6(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->Reserved); + Get_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->DataReferenceIndex); + Get_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->Version); + if (Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->Version>3) throw exception_read_block("Can not parse moov trak mdia minf stbl stsd xxxxVideo (version not supported)"); - Skip_XX(2); // Revision level - Skip_XX(4); // Vendor - Skip_XX(4); // Temporal quality - Skip_XX(4); // Spatial quality - Skip_XX(2); // Width - Skip_XX(2); // Height - Skip_XX(4); // Horizontal resolution - Skip_XX(4); // Vertical resolution - Skip_XX(4); // Data size - Skip_XX(2); //Frame count - Skip_XX(32); // CompressorName - Get_B2(Depth); - Get_B2(ColorTableID); + Get_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->RevisionLevel); + Get_B4(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->Vendor); + Get_B4(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->TemporalQuality); + Get_B4(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->SpatialQuality); + Get_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->Width); + Get_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->Height); + Get_B4(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->HorizontalResolution); + Get_B4(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->VerticalResolution); + Get_B4(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->DataSize); + Get_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->FrameCount); + + Get_String(32, Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->CompressorName); + Get_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->Depth); + Get_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->ColorTableID); + uint16_t Depth=Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->Depth; + uint16_t ColorTableID=Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->ColorTableID; bool IsGreyscale; if (Depth>0x20 && Depth<0x40) { @@ -130,3 +136,44 @@ size_t mp4_moov_trak_mdia_minf_stbl_stsd_xxxxVideo::Insert_Internal (int32u Chun return Subs.size(); } } + +//--------------------------------------------------------------------------- +void mp4_moov_trak_mdia_minf_stbl_stsd_xxxxVideo::Modify_Internal() +{ + if (Chunk.Content.IsModified) + return; + + if (!Global->moov_trak_mdia_minf_stbl_stsd_xxxx_colr.count(Chunk.trak_Index)) + return; + + if (Chunk.Content.Buffer) + delete[] Chunk.Content.Buffer; + Chunk.Content.Buffer_Offset = 0; + Chunk.Content.Buffer = new int8u[Chunk.Content.Before_Subs_Content_Size]; + + Put_B6(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->Reserved); + Put_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->DataReferenceIndex); + Put_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->Version); + Put_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->RevisionLevel); + Put_B4(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->Vendor); + Put_B4(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->TemporalQuality); + Put_B4(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->SpatialQuality); + Put_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->Width); + Put_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->Height); + Put_B4(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->HorizontalResolution); + Put_B4(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->VerticalResolution); + Put_B4(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->DataSize); + Put_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->FrameCount); + Put_String(32, Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->CompressorName); + Put_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->Depth); + Put_B2(Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunk.trak_Index]->ColorTableID); + + Chunk.Content.IsModified=true; + Chunk.Content.Size_IsModified=true; +} + +//--------------------------------------------------------------------------- +void mp4_moov_trak_mdia_minf_stbl_stsd_xxxxVideo::Write_Internal() +{ + mp4_Base::Write_Internal(Chunk.Content.Buffer, (size_t)Chunk.Content.Size); +} \ No newline at end of file diff --git a/Source/Common/mp4/mp4_moov_trak_mdia_minf_stbl_stsd_xxxx_chan.cpp b/Source/Common/mp4/mp4_moov_trak_mdia_minf_stbl_stsd_xxxx_chan.cpp index ac8a3b0..db1091b 100644 --- a/Source/Common/mp4/mp4_moov_trak_mdia_minf_stbl_stsd_xxxx_chan.cpp +++ b/Source/Common/mp4/mp4_moov_trak_mdia_minf_stbl_stsd_xxxx_chan.cpp @@ -17,7 +17,7 @@ //--------------------------------------------------------------------------- void mp4_moov_trak_mdia_minf_stbl_stsd_xxxx_chan::Read_Internal() { - Chunk.trak_Index=Global->moov_trak.size(); + Chunk.trak_Index=Global->moov_trak.size()-1; Global->moov_trak_mdia_minf_stbl_stsd_xxxx_chan[Chunk.trak_Index]=new global::block_moov_trak_mdia_minf_stbl_stsd_xxxx_chan(); diff --git a/Source/Common/mp4/mp4_moov_trak_tkhd.cpp b/Source/Common/mp4/mp4_moov_trak_tkhd.cpp index 1d5949c..8e0bacf 100644 --- a/Source/Common/mp4/mp4_moov_trak_tkhd.cpp +++ b/Source/Common/mp4/mp4_moov_trak_tkhd.cpp @@ -17,7 +17,7 @@ //--------------------------------------------------------------------------- void mp4_moov_trak_tkhd::Read_Internal() { - Chunk.trak_Index=Global->moov_trak.size(); + Chunk.trak_Index=Global->moov_trak.size()-1; Read_Internal_ReadAllInBuffer(); @@ -33,7 +33,7 @@ void mp4_moov_trak_tkhd::Read_Internal() Get_B4(Width); Get_B4(Height); - if (Chunk.trak_Index==1 && Version<= 1 &&Width && Height) + if (Chunk.trak_Index==0 && Version<= 1 &&Width && Height) { Global->moov_trak_tkhd=new global::block_moov_trak_tkhd(); Global->moov_trak_tkhd->Width_Scale=((double)Width_Scale/(double)(1<<16)); @@ -49,7 +49,7 @@ void mp4_moov_trak_tkhd::Read_Internal() void mp4_moov_trak_tkhd::Modify_Internal() { if (Chunk.Content.IsModified || - Chunk.trak_Index!=1 || + Chunk.trak_Index!=0 || !Chunk.Content.Size || !Global->moov_trak_tkhd || Chunk.Content.Sizemoov_trak_tkhd->Width_Scale_Pos+4) diff --git a/Source/Common/mp4_Base.h b/Source/Common/mp4_Base.h index b778146..ab0c8ce 100644 --- a/Source/Common/mp4_Base.h +++ b/Source/Common/mp4_Base.h @@ -217,6 +217,43 @@ class mp4_Base Height=0; } }; + struct block_moov_trak_mdia_minf_stbl_stsd_xxxxVideo + { + int64u Reserved; + int16u DataReferenceIndex; + int16u Version; + int16u RevisionLevel; + int32u Vendor; + int32u TemporalQuality; + int32u SpatialQuality; + int16u Width; + int16u Height; + int32u HorizontalResolution; + int32u VerticalResolution; + int32u DataSize; + int16u FrameCount; + string CompressorName; + int16u Depth; + int16u ColorTableID; + block_moov_trak_mdia_minf_stbl_stsd_xxxxVideo() + { + Reserved=0; + DataReferenceIndex=0; + Version=0; + RevisionLevel=0; + Vendor=0; + TemporalQuality=0; + SpatialQuality=0; + Width=0; + Height=0; + HorizontalResolution=0; + VerticalResolution=0; + DataSize=0; + FrameCount=0; + Depth=0; + ColorTableID=0; + } + }; struct block_moov_trak_mdia_minf_stbl_stsd_xxxx_fiel { uint8_t Fields; @@ -437,6 +474,8 @@ class mp4_Base bool moov_trak_tapt_prof_Modified; // For FirstVideoIndex map moov_trak_tapt_enof; bool moov_trak_tapt_enof_Modified; // For FirstVideoIndex + map moov_trak_mdia_minf_stbl_stsd_xxxxVideo; + bool moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Modified; // For FirstVideoIndex map moov_trak_mdia_minf_stbl_stsd_xxxx_clap; bool moov_trak_mdia_minf_stbl_stsd_xxxx_clap_Modified; // For FirstVideoIndex map moov_trak_mdia_minf_stbl_stsd_xxxx_colr; @@ -483,6 +522,7 @@ class mp4_Base moov_trak_tapt_clef_Modified=false; moov_trak_tapt_prof_Modified=false; moov_trak_tapt_enof_Modified=false; + moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Modified=false; moov_trak_mdia_minf_stbl_stsd_xxxx_clap_Modified=false; moov_trak_mdia_minf_stbl_stsd_xxxx_colr_Modified=false; moov_trak_mdia_minf_stbl_stsd_xxxx_fiel_Modified=false; @@ -531,6 +571,9 @@ class mp4_Base for (size_t Pos=0; PosGlobal->moov_trak[trak_Index]->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Present) { + if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Modified) + { + Chunks->Subs[Pos]->Subs[Pos2]->Modify(Elements::moov_trak_mdia, Elements::moov_trak_mdia_minf, Elements::moov_trak_mdia_minf_stbl, Elements::moov_trak_mdia_minf_stbl_stsd, Elements::moov_trak_mdia_minf_stbl_stsd_xxxxVideo); + Modified=true; + } if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_clap_Modified) { Chunks->Subs[Pos]->Subs[Pos2]->Modify(Elements::moov_trak_mdia, Elements::moov_trak_mdia_minf, Elements::moov_trak_mdia_minf_stbl, Elements::moov_trak_mdia_minf_stbl_stsd, Elements::moov_trak_mdia_minf_stbl_stsd_xxxxVideo, Elements::moov_trak_mdia_minf_stbl_stsd_xxxx_clap); @@ -837,6 +842,22 @@ string mp4_Handler::Get(const string &Field) << Chunks->Global->moov_trak_tapt_enof[Chunks->Global->moov_trak_FirstVideoIndex]->Height; return ss.str(); } + else if (Field=="stsd_xxxxvideo_version") + { + if (Chunks->Global->moov_trak_FirstVideoIndex==(size_t)-1 || !Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo.count(Chunks->Global->moov_trak_FirstVideoIndex)) + return string(); + + stringstream ss; ss << Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunks->Global->moov_trak_FirstVideoIndex]->Version; + return ss.str(); + } + else if (Field=="temporal_quality") + { + if (Chunks->Global->moov_trak_FirstVideoIndex==(size_t)-1 || !Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo.count(Chunks->Global->moov_trak_FirstVideoIndex)) + return string(); + + stringstream ss; ss << Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunks->Global->moov_trak_FirstVideoIndex]->TemporalQuality; + return ss.str(); + } else if (Field=="fiel") { if (Chunks->Global->moov_trak_FirstVideoIndex==(size_t)-1 || !Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_fiel.count(Chunks->Global->moov_trak_FirstVideoIndex)) @@ -930,7 +951,7 @@ string mp4_Handler::Get(const string &Field) ss << Index << "="; - map::iterator It=Chunks->Global->moov_trak_mdia_mdhd.find(Pos+1); + map::iterator It=Chunks->Global->moov_trak_mdia_mdhd.find(Pos); if (It!=Chunks->Global->moov_trak_mdia_mdhd.end()) ss << It->second->Language; else @@ -954,7 +975,7 @@ string mp4_Handler::Get(const string &Field) ss << Index << "="; - map::iterator It=Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_chan.find(Pos+1); + map::iterator It=Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_chan.find(Pos); if (It!=Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_chan.end()) { if (It->second->Descriptions.empty()) @@ -1128,6 +1149,47 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) } return true; } + + else if (Field=="stsd_xxxxvideo_version") + { + if (Chunks->Global->moov_trak_FirstVideoIndex==(size_t)-1 || !Chunks->Global->moov_trak[Chunks->Global->moov_trak_FirstVideoIndex]->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Present) + return false; + + uint16_t Version=0; + if (sscanf(Value.c_str(), "%hu", &Version)!=1 || Version>0x3) + return false; + + if (!Simulate) + { + if (!Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo.count(Chunks->Global->moov_trak_FirstVideoIndex)) + return false; + + Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunks->Global->moov_trak_FirstVideoIndex]->Version=Version; + Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Modified=true; + } + return true; + } + + else if (Field=="temporal_quality") + { + if (Chunks->Global->moov_trak_FirstVideoIndex==(size_t)-1 || !Chunks->Global->moov_trak[Chunks->Global->moov_trak_FirstVideoIndex]->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Present) + return false; + + uint32_t Quality=0; + if (sscanf(Value.c_str(), "%u", &Quality)!=1) + return false; + + if (!Simulate) + { + if (!Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo.count(Chunks->Global->moov_trak_FirstVideoIndex)) + return false; + + Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo[Chunks->Global->moov_trak_FirstVideoIndex]->TemporalQuality=Quality; + Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Modified=true; + } + return true; + } + else if (Field=="fiel") { if (Chunks->Global->moov_trak_FirstVideoIndex==(size_t)-1 || !Chunks->Global->moov_trak[Chunks->Global->moov_trak_FirstVideoIndex]->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Present) @@ -1611,6 +1673,7 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) size_t Index=0; size_t trak_Index=0; + bool Found=false; for (size_t Pos=0; PosGlobal->moov_trak.size(); Pos++) { if (!Chunks->Global->moov_trak[Pos]->IsSound) @@ -1618,18 +1681,19 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) if (Index++==Track) { - trak_Index=Pos+1; //Track indexes are 1 based + trak_Index=Pos; + Found=true; break; } } - if (!trak_Index) + if (!Found) { Ok=false; continue; } - if (!Chunks->Global->moov_trak[trak_Index-1]->IsSound) + if (!Chunks->Global->moov_trak[trak_Index]->IsSound) { Ok=false; continue; @@ -1689,6 +1753,7 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) size_t Index=0; size_t trak_Index=0; + bool Found=false; for (size_t Pos=0; PosGlobal->moov_trak.size(); Pos++) { if (!Chunks->Global->moov_trak[Pos]->IsSound) @@ -1696,18 +1761,19 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) if (Index++==Track) { - trak_Index=Pos+1; //Track indexes are 1 based + trak_Index=Pos; + Found=true; break; } } - if (!trak_Index) + if (!Found) { Ok=false; continue; } - if (!Chunks->Global->moov_trak[trak_Index-1]->IsSound) + if (!Chunks->Global->moov_trak[trak_Index]->IsSound) { Ok=false; continue; diff --git a/Source/movedit_main.cpp b/Source/movedit_main.cpp index 474a81a..0bd83e9 100644 --- a/Source/movedit_main.cpp +++ b/Source/movedit_main.cpp @@ -38,6 +38,10 @@ int main(int argc, char* argv[]) std::string enof_New=string(); bool enof_Delete=false; bool enof_OK=true; + std::string stsd_xxxxvideo_version_New=string(); + bool stsd_xxxxvideo_version_OK=true; + std::string temporal_quality_New=string(); + bool temporal_quality_OK=true; std::string fiel_New=string(); bool fiel_Delete=false; bool fiel_OK=true; @@ -166,6 +170,34 @@ int main(int argc, char* argv[]) enof_New=string(); enof_Delete=true; } + else if (argp + 1 < argc + && (Ztring(argv[argp]) == __T("--stsd-video-version") + || Ztring(argv[argp]) == __T("-stsd-video-version"))) + { + uint16_t v=0; + if (sscanf(argv[argp + 1], "%hu", &v)!=1 || v>3) + { + cout << "Can not understand version handling value " << argv[argp] << ", it must be an integer between 0 and 3" << endl; + return ReturnValue_ERROR; + } + stsd_xxxxvideo_version_New=argv[argp + 1]; + argp++; + } + + else if (argp + 1 < argc + && (Ztring(argv[argp]) == __T("--temporal-quality") + || Ztring(argv[argp]) == __T("-temporal-quality"))) + { + uint32_t q=0; + if (sscanf(argv[argp + 1], "%u", &q)!=1) + { + cout << "Can not understand temporal quality handling value " << argv[argp] << ", it must be a 32 bits integer value" << endl; + return ReturnValue_ERROR; + } + temporal_quality_New=argv[argp + 1]; + argp++; + } + else if (argp + 1 < argc && (Ztring(argv[argp]) == __T("--field") || Ztring(argv[argp]) == __T("-field"))) @@ -595,6 +627,8 @@ int main(int argc, char* argv[]) !colr_New.empty() || colr_Delete || !clap_New.empty() || clap_Delete || !chan_New.empty() || chan_Delete || + !stsd_xxxxvideo_version_New.empty() || + !temporal_quality_New.empty() || !lang_New.empty() || mdcv_Delete || clli_Delete || @@ -758,7 +792,7 @@ int main(int argc, char* argv[]) cout << " it (empty)" << endl; cout << "M = The field will be modified ('Y') or should be modified but it is not possible" << endl; cout << " due to feature not implemented ('N')" << endl; - cout << FileNameFake << "|OK?|Clean Ap.|M| Prod Ap.|M| Enc. Ap.|M| PAR|M| Display Primaries|M| Luminance|M| Max content light lev.|M| Max frame avg. light lev.|M|w-scale|M| Field|M| Color|M|Gamma|M| Aperture|M| Languages|M| Channels|M|" << endl; + cout << FileNameFake << "|OK?|Clean Ap.|M| Prod Ap.|M| Enc. Ap.|M|vid. version|M|temp. quality|M| PAR|M| Display Primaries|M| Luminance|M| Max content light lev.|M| Max frame avg. light lev.|M|w-scale|M| Field|M| Color|M|Gamma|M| Aperture|M| Languages|M| Channels|M|" << endl; } else cout << FileNameFake << "|OK?| Registry|UniversalAdId value" << endl; @@ -895,6 +929,24 @@ int main(int argc, char* argv[]) else if (enof_Delete) H->Remove("enof"); + if (!stsd_xxxxvideo_version_New.empty()) + { + if(!H->Set("stsd_xxxxvideo_version", stsd_xxxxvideo_version_New)) + { + stsd_xxxxvideo_version_OK=false; + ToReturn=ReturnValue_ERROR; + } + } + + if (!temporal_quality_New.empty()) + { + if(!H->Set("temporal_quality", temporal_quality_New)) + { + temporal_quality_OK=false; + ToReturn=ReturnValue_ERROR; + } + } + if (!pasp_New.empty()) { if(!H->Set("pasp", pasp_New)) @@ -1054,6 +1106,16 @@ int main(int argc, char* argv[]) enof.insert(0, 9 - enof.size(), ' '); cout << enof << "|" << ((!enof_New.empty() || enof_Delete) ? ((OK && enof_OK) ? "Y" : "N") : " ") << "|"; + string stsd_xxxxvideo_version = H->Get("stsd_xxxxvideo_version"); + if (stsd_xxxxvideo_version.size() < 12) + stsd_xxxxvideo_version.insert(0, 12 - stsd_xxxxvideo_version.size(), ' '); + cout << stsd_xxxxvideo_version << "|" << ((!stsd_xxxxvideo_version_New.empty()) ? ((OK && stsd_xxxxvideo_version_OK) ? "Y" : "N") : " ") << "|"; + + string temporal_quality = H->Get("temporal_quality"); + if (temporal_quality.size() < 13) + temporal_quality.insert(0, 13 - temporal_quality.size(), ' '); + cout << temporal_quality << "|" << ((!temporal_quality_New.empty()) ? ((OK && temporal_quality_OK) ? "Y" : "N") : " ") << "|"; + string pasp = H->Get("pasp"); if (pasp.size() < 9) pasp.insert(0, 9 - pasp.size(), ' '); @@ -1175,7 +1237,7 @@ int main(int argc, char* argv[]) for (size_t Pos=0; Pos