/* Copyright (c) MediaArea.net SARL. All Rights Reserved. * * Use of this source code is governed by a BSD-style license that can * be found in the License.html file in the root of the source tree. */ //--------------------------------------------------------------------------- // Pre-compilation #include "MediaInfo/PreComp.h" #ifdef __BORLANDC__ #pragma hdrstop #endif //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include "MediaInfo/Setup.h" //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #if MEDIAINFO_IBI //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include "MediaInfo/Multiple/File_Ibi.h" #include "MediaInfo/MediaInfo_Config_MediaInfo.h" #include //--------------------------------------------------------------------------- namespace MediaInfoLib { //*************************************************************************** // Constructor/Destructor //*************************************************************************** //--------------------------------------------------------------------------- File_Ibi::File_Ibi() :File__Analyze() { //Configuration #if MEDIAINFO_DEMUX Demux_Level=2; //Container #endif //MEDIAINFO_DEMUX DataMustAlwaysBeComplete=false; #if MEDIAINFO_IBIUSAGE //In Ibi=NULL; //Temp Ibi_MustDelete=false; #endif //MEDIAINFO_IBIUSAGE } //--------------------------------------------------------------------------- File_Ibi::~File_Ibi() { #if MEDIAINFO_IBIUSAGE if (Ibi_MustDelete) delete Ibi; //Ibi=NULL; #endif //MEDIAINFO_IBIUSAGE } //*************************************************************************** // Get information //*************************************************************************** //--------------------------------------------------------------------------- #if MEDIAINFO_IBIUSAGE const Ztring &File_Ibi::Get (stream_t /*StreamKind*/, size_t /*StreamNumber*/, const Ztring &Parameter, info_t /*KindOfInfo*/, info_t /*KindOfSearch*/) { ibi::streams::iterator IbiStream_Temp=Ibi->Streams.begin(); //TODO: management of multiple streams if (IbiStream_Temp!=Ibi->Streams.end() && !IbiStream_Temp->second->Infos.empty()) { int64u FrameNumber=Parameter.To_int64u(); for (size_t Pos=0; Possecond->Infos.size()-1; Pos++) if (IbiStream_Temp->second->Infos[Pos].FrameNumber==FrameNumber || IbiStream_Temp->second->Infos[Pos+1].FrameNumber>FrameNumber) { Get_Temp=__T("StreamOffset=")+Ztring::ToZtring(IbiStream_Temp->second->Infos[Pos].StreamOffset) + __T(" / FrameNumber=")+Ztring::ToZtring(IbiStream_Temp->second->Infos[Pos].FrameNumber) + __T(" / Dts=")+Ztring::ToZtring(IbiStream_Temp->second->Infos[Pos].Dts); return Get_Temp; } } //Can not be found Get_Temp.clear(); return Get_Temp; } #endif //MEDIAINFO_IBIUSAGE //*************************************************************************** // Streams management //*************************************************************************** //--------------------------------------------------------------------------- void File_Ibi::Streams_Accept() { Fill(Stream_General, 0, General_Format, "Ibi"); #if MEDIAINFO_IBIUSAGE if (Ibi==NULL) { Ibi=new ibi(); Ibi_MustDelete=true; } #endif //MEDIAINFO_IBIUSAGE } //--------------------------------------------------------------------------- #if MEDIAINFO_IBIUSAGE void File_Ibi::Streams_Finish() { Config->File_KeepInfo_Set(true); //In order to let Get() available if (Count_Get(Stream_Video)==0) //If not yet done by Inform part for (ibi::streams::iterator IbiStream_Temp=Ibi->Streams.begin(); IbiStream_Temp!=Ibi->Streams.end(); ++IbiStream_Temp) { Stream_Prepare(Stream_Video); Fill(Stream_Video, StreamPos_Last, General_ID, IbiStream_Temp->first); } } #endif //MEDIAINFO_IBIUSAGE //*************************************************************************** // Buffer //*************************************************************************** //--------------------------------------------------------------------------- void File_Ibi::Header_Parse() { //Test of zero padding int8u Null; Peek_B1(Null); if (Null==0x00) { if (Buffer_Offset_Temp==0) Buffer_Offset_Temp=Buffer_Offset+1; while (Buffer_Offset_Temp=Buffer_Size) { Element_WaitForMoreData(); return; } Header_Fill_Code((int32u)-1); //Should be (int64u)-1 but Borland C++ does not like this Header_Fill_Size(Buffer_Offset_Temp-Buffer_Offset); Buffer_Offset_Temp=0; return; } //Parsing int64u Name, Size; Get_EB (Name, "Name"); Get_EB (Size, "Size"); //Filling Header_Fill_Code(Name, Ztring().From_Number(Name, 16)); Header_Fill_Size(Element_Offset+Size); } //--------------------------------------------------------------------------- namespace Elements { //Common const int64u Zero=(int32u)-1; //Should be (int64u)-1 but Borland C++ does not like this const int64u CRC32=0x3F; const int64u Void=0x6C; //EBML const int64u Ebml=0xA45DFA3; const int64u Ebml_Version=0x286; const int64u Ebml_ReadVersion=0x2F7; const int64u Ebml_MaxIDLength=0x2F2; const int64u Ebml_MaxSizeLength=0x2F3; const int64u Ebml_DocType=0x282; const int64u Ebml_DocTypeVersion=0x287; const int64u Ebml_DocTypeReadVersion=0x285; //Segment const int64u Stream=1; const int64u Stream_Header=1; const int64u Stream_ByteOffset=2; const int64u Stream_FrameNumber=3; const int64u Stream_Dts=4; const int64u CompressedIndex=2; const int64u WritingApplication=3; const int64u WritingApplication_Name=1; const int64u WritingApplication_Version=2; const int64u InformData=4; const int64u SourceInfo=5; const int64u SourceInfo_IndexCreationDate=1; const int64u SourceInfo_SourceModificationDate=2; const int64u SourceInfo_SourceSize=3; } //--------------------------------------------------------------------------- void File_Ibi::Data_Parse() { #define LIS2(_ATOM, _NAME) \ case Elements::_ATOM : \ if (Level==Element_Level) \ { \ Element_Name(_NAME); \ _ATOM(); \ Element_ThisIsAList(); \ } \ #define ATO2(_ATOM, _NAME) \ case Elements::_ATOM : \ if (Level==Element_Level) \ { \ if (Element_IsComplete_Get()) \ { \ Element_Name(_NAME); \ _ATOM(); \ } \ else \ { \ Element_WaitForMoreData(); \ return; \ } \ } \ break; \ #define ATOM_END_MK \ ATOM(Zero) \ ATOM(CRC32) \ ATOM(Void) \ ATOM_END //Parsing DATA_BEGIN LIST(Ebml) ATOM_BEGIN ATOM(Ebml_Version) ATOM(Ebml_ReadVersion) ATOM(Ebml_MaxIDLength) ATOM(Ebml_MaxSizeLength) ATOM(Ebml_DocType) ATOM(Ebml_DocTypeVersion) ATOM(Ebml_DocTypeReadVersion) ATOM_END_MK LIST(Stream) ATOM_BEGIN ATOM(Stream_Header) ATOM(Stream_ByteOffset) ATOM(Stream_FrameNumber) ATOM(Stream_Dts) ATOM_END_MK ATOM(CompressedIndex) LIST(WritingApplication) ATOM_BEGIN ATOM(WritingApplication_Name) ATOM(WritingApplication_Version) ATOM_END_MK LIST(SourceInfo) ATOM_BEGIN ATOM(SourceInfo_IndexCreationDate) ATOM(SourceInfo_SourceModificationDate) ATOM(SourceInfo_SourceSize) ATOM_END_MK ATOM(InformData) DATA_END_DEFAULT } //*************************************************************************** // Elements //*************************************************************************** //--------------------------------------------------------------------------- void File_Ibi::Zero() { Element_Name("ZeroPadding"); } //--------------------------------------------------------------------------- void File_Ibi::CRC32() { Element_Name("CRC32"); //Parsing UInteger_Info(); } //--------------------------------------------------------------------------- void File_Ibi::Void() { Element_Name("Void"); //Parsing UInteger_Info(); } //--------------------------------------------------------------------------- void File_Ibi::Ebml() { Element_Name("Ebml"); } //--------------------------------------------------------------------------- void File_Ibi::Ebml_Version() { Element_Name("Version"); //Parsing UInteger_Info(); } //--------------------------------------------------------------------------- void File_Ibi::Ebml_ReadVersion() { Element_Name("ReadVersion"); //Parsing UInteger_Info(); } //--------------------------------------------------------------------------- void File_Ibi::Ebml_MaxIDLength() { Element_Name("MaxIDLength"); //Parsing UInteger_Info(); } //--------------------------------------------------------------------------- void File_Ibi::Ebml_MaxSizeLength() { Element_Name("MaxSizeLength"); //Parsing UInteger_Info(); } //--------------------------------------------------------------------------- void File_Ibi::Ebml_DocType() { Element_Name("DocType"); //Parsing Ztring Data; Get_UTF8(Element_Size, Data, "Data"); Element_Info1(Data); //Filling FILLING_BEGIN(); if (Data==__T("MediaInfo Index")) Accept("Ibi"); else { Reject("Ibi"); return; } FILLING_END(); } //--------------------------------------------------------------------------- void File_Ibi::Ebml_DocTypeVersion() { Element_Name("DocTypeVersion"); //Parsing UInteger_Info(); } //--------------------------------------------------------------------------- void File_Ibi::Ebml_DocTypeReadVersion() { Element_Name("DocTypeReadVersion"); //Parsing UInteger_Info(); } //--------------------------------------------------------------------------- void File_Ibi::Stream() { Element_Name("Stream"); ID_Current=(int64u)-1; } void File_Ibi::Stream_Header() { Element_Name("Stream Header"); Get_EB (ID_Current, "ID"); FILLING_BEGIN(); #if MEDIAINFO_IBIUSAGE if (Ibi) { //Filling information for ID after data ibi::streams::iterator IbiStream_Temp=Ibi->Streams.find((int64u)-1); if (IbiStream_Temp!=Ibi->Streams.end()) { Ibi->Streams[ID_Current]=IbiStream_Temp->second; Ibi->Streams.erase(IbiStream_Temp); } } #else //MEDIAINFO_IBIUSAGE Stream_Prepare(Stream_Video); Fill(Stream_Video, StreamPos_Last, General_ID, ID_Current); #endif //MEDIAINFO_IBIUSAGE FILLING_END(); } void File_Ibi::Stream_ByteOffset() { Element_Name("Byte Offset"); //Parsing #if MEDIAINFO_IBIUSAGE size_t Pos=0; #endif //MEDIAINFO_IBIUSAGE int64u Offset=0; while (Element_OffsetStreams[ID_Current]==NULL) Ibi->Streams[ID_Current]=new ibi::stream(); if (Pos>=Ibi->Streams[ID_Current]->Infos.size()) { Ibi->Streams[ID_Current]->Infos.push_back(ibi::stream::info()); Ibi->Streams[ID_Current]->Infos[Pos].IsContinuous=true; //default } Ibi->Streams[ID_Current]->Infos[Pos].StreamOffset=Offset; Pos++; } FILLING_END(); #endif //MEDIAINFO_IBIUSAGE } } void File_Ibi::Stream_FrameNumber() { Element_Name("Frame Number"); //Parsing #if MEDIAINFO_IBIUSAGE size_t Pos=0; #endif //MEDIAINFO_IBIUSAGE int64u Offset=0; while (Element_OffsetStreams[ID_Current]==NULL) Ibi->Streams[ID_Current]=new ibi::stream(); if (Pos>=Ibi->Streams[ID_Current]->Infos.size()) { Ibi->Streams[ID_Current]->Infos.push_back(ibi::stream::info()); Ibi->Streams[ID_Current]->Infos[Pos].IsContinuous=true; //default } Ibi->Streams[ID_Current]->Infos[Pos].FrameNumber=Offset; Pos++; } FILLING_END(); #endif //MEDIAINFO_IBIUSAGE } } void File_Ibi::Stream_Dts() { Element_Name("DTS"); //Parsing int64u Item; Get_EB (Item, "DtsFrequencyNumerator"); #if MEDIAINFO_IBIUSAGE FILLING_BEGIN(); if (Ibi) Ibi->Streams[ID_Current]->DtsFrequencyNumerator=Item; FILLING_END(); #endif //MEDIAINFO_IBIUSAGE Get_EB (Item, "DtsFrequencyDenominator"); #if MEDIAINFO_IBIUSAGE FILLING_BEGIN(); if (Ibi) { Ibi->Streams[ID_Current]->DtsFrequencyDenominator=Item; //Handling of previous inverted Numerator/Denominator if (Ibi->Streams[ID_Current]->DtsFrequencyNumeratorStreams[ID_Current]->DtsFrequencyDenominator) std::swap(Ibi->Streams[ID_Current]->DtsFrequencyNumerator, Ibi->Streams[ID_Current]->DtsFrequencyDenominator); } FILLING_END(); #endif //MEDIAINFO_IBIUSAGE #if MEDIAINFO_IBIUSAGE size_t Pos=0; #endif //MEDIAINFO_IBIUSAGE int64u Offset=0; while (Element_OffsetStreams[ID_Current]==NULL) Ibi->Streams[ID_Current]=new ibi::stream(); if (Pos>=Ibi->Streams[ID_Current]->Infos.size()) { Ibi->Streams[ID_Current]->Infos.push_back(ibi::stream::info()); Ibi->Streams[ID_Current]->Infos[Pos].IsContinuous=true; //default } Ibi->Streams[ID_Current]->Infos[Pos].Dts=Offset; Pos++; } FILLING_END(); #endif //MEDIAINFO_IBIUSAGE } } void File_Ibi::CompressedIndex() { if (!Status[IsAccepted]) { Reject("Ibi"); return; } Element_Name("Compressed Index"); int64u UncompressedSize; Get_EB (UncompressedSize, "Uncompressed size"); //Sizes unsigned long Source_Size=(unsigned long)(Element_Size-Element_Offset); unsigned long Dest_Size=(unsigned long)UncompressedSize; if (Dest_Size>=64*1024*1024) { Reject("Ibi"); return; } //Uncompressing int8u* Dest; { Dest=new int8u[Dest_Size]; } if (uncompress((Bytef*)Dest, &Dest_Size, (const Bytef*)Buffer+Buffer_Offset+(size_t)Element_Offset, Source_Size)<0) { Skip_XX(Element_Size-Element_Offset, "Problem during the decompression"); delete[] Dest; //Dest=NULL; return; } //Exiting this element Skip_XX(Element_Size-Element_Offset, "Will be parsed"); //Configuring buffer const int8u* Buffer_Sav=Buffer; size_t Buffer_Size_Sav=Buffer_Size; int8u* Buffer_Temp_Sav=Buffer_Temp; size_t Buffer_Temp_Size_Sav=Buffer_Temp_Size; size_t Buffer_Offset_Sav=Buffer_Offset; size_t Buffer_Offset_Temp_Sav=Buffer_Offset_Temp; Buffer=NULL; Buffer_Size=0; Buffer_Temp=NULL; Buffer_Temp_Size=0; Buffer_Offset=0; Buffer_Offset_Temp=0; //Configuring level std::vector Element_Sizes_Sav; size_t Element_Level_Sav=Element_Level; while(Element_Level) { Element_Sizes_Sav.push_back(Element_TotalSize_Get()); Element_End0(); } //Configuring file size int64u File_Size_Sav=File_Size; if (File_SizeIbi_UseIbiInfoIfAvailable_Get()) { ZtringListList Fields(InformData_FromFile); for (size_t Pos=0; PosFields.size() || Fields[Pos].size()<1) break; //End or problem if (Fields[Pos][0]==__T("General")) ; //Nothing to do else if (Fields[Pos][0]==__T("Video")) Stream_Prepare(Stream_Video); else if (Fields[Pos][0]==__T("Audio")) Stream_Prepare(Stream_Audio); else if (Fields[Pos][0]==__T("Text")) Stream_Prepare(Stream_Text); else if (Fields[Pos][0]==__T("Other")) Stream_Prepare(Stream_Other); else if (Fields[Pos][0]==__T("Image")) Stream_Prepare(Stream_Image); else if (Fields[Pos][0]==__T("Menu")) Stream_Prepare(Stream_Menu); else break; //Problem Pos++; } Fill(StreamKind_Last, StreamPos_Last, Fields[Pos][0].To_UTF8().c_str(), Fields[Pos][1], true); Fill_SetOptions(StreamKind_Last, StreamPos_Last, Fields[Pos][0].To_UTF8().c_str(), Fields[Pos][Info_Options].To_UTF8().c_str()); } } #endif //MEDIAINFO_IBIUSAGE } //*************************************************************************** // Data //*************************************************************************** //--------------------------------------------------------------------------- void File_Ibi::UInteger_Info() { switch (Element_Size) { case 1 : { Info_B1(Data, "Data"); Element_Info1(Data); return; } case 2 : { Info_B2(Data, "Data"); Element_Info1(Data); return; } case 3 : { Info_B3(Data, "Data"); Element_Info1(Data); return; } case 4 : { Info_B4(Data, "Data"); Element_Info1(Data); return; } case 5 : { Info_B5(Data, "Data"); Element_Info1(Data); return; } case 6 : { Info_B6(Data, "Data"); Element_Info1(Data); return; } case 7 : { Info_B7(Data, "Data"); Element_Info1(Data); return; } case 8 : { Info_B8(Data, "Data"); Element_Info1(Data); return; } case 16: { Info_B16(Data, "Data"); Element_Info1(Data); return; } default : Skip_XX(Element_Size, "Data"); } } //--------------------------------------------------------------------------- int64u File_Ibi::UInteger_Get() { switch (Element_Size) { case 1 : { int8u Data; Get_B1 (Data, "Data"); Element_Info1(Data); return Data; } case 2 : { int16u Data; Get_B2 (Data, "Data"); Element_Info1(Data); return Data; } case 3 : { int32u Data; Get_B3 (Data, "Data"); Element_Info1(Data); return Data; } case 4 : { int32u Data; Get_B4 (Data, "Data"); Element_Info1(Data); return Data; } case 5 : { int64u Data; Get_B5 (Data, "Data"); Element_Info1(Data); return Data; } case 6 : { int64u Data; Get_B6 (Data, "Data"); Element_Info1(Data); return Data; } case 7 : { int64u Data; Get_B7 (Data, "Data"); Element_Info1(Data); return Data; } case 8 : { int64u Data; Get_B8 (Data, "Data"); Element_Info1(Data); return Data; } default : Skip_XX(Element_Size, "Data"); return 0; } } //--------------------------------------------------------------------------- int128u File_Ibi::UInteger16_Get() { switch (Element_Size) { case 1 : { int8u Data; Get_B1 (Data, "Data"); Element_Info1(Data); return Data; } case 2 : { int16u Data; Get_B2 (Data, "Data"); Element_Info1(Data); return Data; } case 3 : { int32u Data; Get_B3 (Data, "Data"); Element_Info1(Data); return Data; } case 4 : { int32u Data; Get_B4 (Data, "Data"); Element_Info1(Data); return Data; } case 5 : { int64u Data; Get_B5 (Data, "Data"); Element_Info1(Data); return Data; } case 6 : { int64u Data; Get_B6 (Data, "Data"); Element_Info1(Data); return Data; } case 7 : { int64u Data; Get_B7 (Data, "Data"); Element_Info1(Data); return Data; } case 8 : { int64u Data; Get_B8 (Data, "Data"); Element_Info1(Data); return Data; } case 16: { int128u Data; Get_B16(Data, "Data"); Element_Info1(Data); return Data; } default : Skip_XX(Element_Size, "Data"); return 0; } } } //NameSpace #endif //MEDIAINFO_IBI