From e3d86934bdbd469bb13fc77cbb09c1f02ec60ef8 Mon Sep 17 00:00:00 2001 From: Maxime Gervais Date: Sun, 22 Oct 2023 00:42:03 +0200 Subject: [PATCH] Allow first video track at any position Signed-off-by: Maxime Gervais --- .../mp4/mp4_moov_trak_mdia_minf_vmhd.cpp | 2 + Source/Common/mp4_Base.h | 4 +- Source/Common/mp4_Handler.cpp | 136 +++++++++++++----- 3 files changed, 108 insertions(+), 34 deletions(-) diff --git a/Source/Common/mp4/mp4_moov_trak_mdia_minf_vmhd.cpp b/Source/Common/mp4/mp4_moov_trak_mdia_minf_vmhd.cpp index ad7e8f2..6df95da 100644 --- a/Source/Common/mp4/mp4_moov_trak_mdia_minf_vmhd.cpp +++ b/Source/Common/mp4/mp4_moov_trak_mdia_minf_vmhd.cpp @@ -26,4 +26,6 @@ void mp4_moov_trak_mdia_minf_vmhd::Read_Internal () throw exception_read_block("Can not parse moov trak mdia vmhd (version not supported)"); Global->moov_trak.back()->IsVideo=true; + if (Global->moov_trak_FirstVideoIndex==(size_t)-1) + Global->moov_trak_FirstVideoIndex=Global->moov_trak.size()-1; } diff --git a/Source/Common/mp4_Base.h b/Source/Common/mp4_Base.h index 8d83883..9832e0f 100644 --- a/Source/Common/mp4_Base.h +++ b/Source/Common/mp4_Base.h @@ -59,7 +59,7 @@ class exception_valid : public exception } protected: - string text; + string text; }; class exception_read_block : public exception @@ -442,6 +442,7 @@ class mp4_Base size_t moov_meta_keys_AlreadyPresent; vector moov_meta_ilst_NewValues; size_t moov_meta_ilst_AlreadyPresent; + size_t moov_trak_FirstVideoIndex; bool NewChunksAtTheEnd; bool Out_Buffer_File_TryModification; bool Out_Buffer_File_IsModified; @@ -485,6 +486,7 @@ class mp4_Base moov_meta_keys_Modified=false; moov_meta_keys_AlreadyPresent=0; moov_meta_ilst_AlreadyPresent=0; + moov_trak_FirstVideoIndex=(size_t)-1; NewChunksAtTheEnd=false; Out_Buffer_WriteAtEnd=false; Out_Buffer_File_TryModification=true; diff --git a/Source/Common/mp4_Handler.cpp b/Source/Common/mp4_Handler.cpp index 0e07f56..e7f6264 100644 --- a/Source/Common/mp4_Handler.cpp +++ b/Source/Common/mp4_Handler.cpp @@ -368,29 +368,98 @@ bool mp4_Handler::Save() Chunks->Modify(Elements::moov, Elements::moov_meta, Elements::moov_meta_keys); if (Chunks->Global->moov_meta_ilst_Modified) Chunks->Modify(Elements::moov, Elements::moov_meta, Elements::moov_meta_ilst); - if (Chunks->Global->moov_trak_tapt_clef_Modified) - Chunks->Modify(Elements::moov, Elements::moov_trak, Elements::moov_trak_tapt, Elements::moov_trak_tapt_clef); - if (Chunks->Global->moov_trak_tapt_prof_Modified) - Chunks->Modify(Elements::moov, Elements::moov_trak, Elements::moov_trak_tapt, Elements::moov_trak_tapt_prof); - if (Chunks->Global->moov_trak_tapt_enof_Modified) - Chunks->Modify(Elements::moov, Elements::moov_trak, Elements::moov_trak_tapt, Elements::moov_trak_tapt_enof); + + //Modify fist video track + { + size_t trak_Index=0; + for (size_t Pos=0; PosSubs.size(); Pos++) + { + bool Found=false; + if (Chunks->Subs[Pos]->Chunk.Header.Name==Elements::moov) + { + for (size_t Pos2=0; Pos2Subs[Pos]->Subs.size(); Pos2++) + { + if (Chunks->Subs[Pos]->Subs[Pos2]->Chunk.Header.Name==Elements::moov_trak) + { + if (trak_IndexGlobal->moov_trak.size() && Chunks->Global->moov_trak[trak_Index]->IsVideo) + { + bool Modified=false; + if (Chunks->Global->moov_trak_tapt_clef_Modified) + { + Chunks->Subs[Pos]->Subs[Pos2]->Modify(Elements::moov_trak_tapt, Elements::moov_trak_tapt_clef); + Modified=true; + } + if (Chunks->Global->moov_trak_tapt_prof_Modified) + { + Chunks->Subs[Pos]->Subs[Pos2]->Modify(Elements::moov_trak_tapt, Elements::moov_trak_tapt_prof); + Modified=true; + } + if (Chunks->Global->moov_trak_tapt_enof_Modified) + { + Chunks->Subs[Pos]->Subs[Pos2]->Modify(Elements::moov_trak_tapt, Elements::moov_trak_tapt_enof); + Modified=true; + } + if (Chunks->Global->moov_trak[trak_Index]->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Present) + { + 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); + Modified=true; + } + if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_colr_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_colr); + Modified=true; + } + if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_fiel_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_fiel); + Modified=true; + } + if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_gama_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_gama); + Modified=true; + } + if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_pasp_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_pasp); + Modified=true; + } + if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_mdcv_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_mdcv); + Modified=true; + } + if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_clli_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_clli); + Modified=true; + } + } + + if (Modified) + { + Chunks->Chunk.Content.IsModified=true; + Chunks->Chunk.Content.Size_IsModified=true; + Chunks->Subs[Pos]->Chunk.Content.IsModified=true; + Chunks->Subs[Pos]->Chunk.Content.Size_IsModified=true; + Chunks->Subs[Pos]->Subs[Pos2]->Chunk.Content.IsModified=true; + Chunks->Subs[Pos]->Subs[Pos2]->Chunk.Content.Size_IsModified=true; + } + + Found=true; + break; + } + trak_Index++; + } + } + if (Found) + break; + } + } + } if (Chunks->Global->moov_trak_tkhd_Modified) Chunks->Modify(Elements::moov, Elements::moov_trak, Elements::moov_trak_tkhd); - if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_clap_Modified) - Chunks->Modify(Elements::moov, Elements::moov_trak, 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); - if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_colr_Modified) - Chunks->Modify(Elements::moov, Elements::moov_trak, 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_colr); - if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_fiel_Modified) - Chunks->Modify(Elements::moov, Elements::moov_trak, 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_fiel); - if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_gama_Modified) - Chunks->Modify(Elements::moov, Elements::moov_trak, 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_gama); - if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_pasp_Modified) - Chunks->Modify(Elements::moov, Elements::moov_trak, 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_pasp); - if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_mdcv_Modified) - Chunks->Modify(Elements::moov, Elements::moov_trak, 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_mdcv); - if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_clli_Modified) - Chunks->Modify(Elements::moov, Elements::moov_trak, 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_clli); - // Modify chan in all audio tracks if (Chunks->Global->moov_trak_mdia_minf_stbl_stsd_xxxx_chan_Modified) { @@ -786,7 +855,7 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) } else if (Field=="clef" || Field=="prof" || Field=="enof") { - if (Chunks->Global->moov_trak.empty() || !Chunks->Global->moov_trak[0]->IsVideo) + if (Chunks->Global->moov_trak_FirstVideoIndex==(size_t)-1) return false; double Width=0, Height=0; @@ -824,7 +893,7 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) } else if (Field=="fiel") { - if (Chunks->Global->moov_trak.empty() || !Chunks->Global->moov_trak[0]->IsVideo ||!Chunks->Global->moov_trak[0]->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Present) + 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 Fields=0, Detail=0; @@ -844,7 +913,7 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) } else if (Field=="colr") { - if (Chunks->Global->moov_trak.empty() || !Chunks->Global->moov_trak[0]->IsVideo ||!Chunks->Global->moov_trak[0]->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Present) + 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 Primaries=0, Transfer=0, Matrix=0; @@ -866,7 +935,7 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) } else if (Field=="gama") { - if (Chunks->Global->moov_trak.empty() || !Chunks->Global->moov_trak[0]->IsVideo ||!Chunks->Global->moov_trak[0]->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Present) + 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; double Gamma=0; @@ -885,7 +954,7 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) } else if (Field=="pasp") { - if (Chunks->Global->moov_trak.empty() || !Chunks->Global->moov_trak[0]->IsVideo ||!Chunks->Global->moov_trak[0]->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Present) + 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 hSpacing=0, vSpacing=0; @@ -905,7 +974,7 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) } else if (Field=="display_primaries") { - if (Chunks->Global->moov_trak.empty() || !Chunks->Global->moov_trak[0]->IsVideo ||!Chunks->Global->moov_trak[0]->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Present) + 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; double x1=0,y1=0,x2=0,y2=0,x3=0,y3=0, wp_x=0, wp_y=0; @@ -931,7 +1000,7 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) } else if (Field=="luminance") { - if (Chunks->Global->moov_trak.empty() || !Chunks->Global->moov_trak[0]->IsVideo ||!Chunks->Global->moov_trak[0]->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Present) + 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; double max=0,min=0; @@ -959,7 +1028,7 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) } else if (Field=="maximum_content_light_level") { - if (Chunks->Global->moov_trak.empty() || !Chunks->Global->moov_trak[0]->IsVideo ||!Chunks->Global->moov_trak[0]->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Present) + 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; double max=0; @@ -978,7 +1047,7 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) } else if (Field=="maximum_frame_average_light_level") { - if (Chunks->Global->moov_trak.empty() || !Chunks->Global->moov_trak[0]->IsVideo ||!Chunks->Global->moov_trak[0]->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Present) + 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; double max=0; @@ -997,11 +1066,12 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) } else if (Field=="hdr_data_from_xml") { + 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; + string tmp; bool mdcv=false, clli=false; double x1=0, y1=0, x2=0, y2=0, x3=0, y3=0, wp_x=0, wp_y=0, luminance_min=0, luminance_max=0, max_cll=-1, max_fall=-1; - if (Chunks->Global->moov_trak.empty() || !Chunks->Global->moov_trak[0]->IsVideo ||!Chunks->Global->moov_trak[0]->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Present) - return false; tfsxml_string tfsxml_priv, tfsxml_priv_backup, result; tfsxml_init(&tfsxml_priv, (const void*)Value.c_str(), Value.size()); @@ -1188,7 +1258,7 @@ bool mp4_Handler::Set(const string &Field, const string &Value, bool Simulate) } else if (Field=="clap") { - if (Chunks->Global->moov_trak.empty() || !Chunks->Global->moov_trak[0]->IsVideo ||!Chunks->Global->moov_trak[0]->moov_trak_mdia_minf_stbl_stsd_xxxxVideo_Present) + 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 Aperture_Width_Num=(uint32_t)-1, Aperture_Width_Den=1, Aperture_Height_Num=(uint32_t)-1, Aperture_Height_Den=1;