/* 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 defined(MEDIAINFO_SWF_YES) //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include "MediaInfo/Multiple/File_Swf.h" #include using namespace ZenLib; //--------------------------------------------------------------------------- namespace MediaInfoLib { //*************************************************************************** // Infos //*************************************************************************** //--------------------------------------------------------------------------- static const int8u Swf_SoundType[]= { 1, 2, }; //--------------------------------------------------------------------------- static const int8u Swf_SoundSize[]= { 8, 16, }; //--------------------------------------------------------------------------- static const int16u Swf_SoundRate[]= { 5500, 11025, 22050, 44100, }; //--------------------------------------------------------------------------- static const char* Swf_Format_Audio[]= { "PCM", "ADPCM", "MPEG Audio", "PCM", "Nellymoser", "Nellymoser", "Nellymoser", "", "", "", "", "Speex", "", "", "", "", }; //--------------------------------------------------------------------------- static const char* Swf_Format_Version_Audio[]= { "", "", "Version 1", "", "", "", "", "", "", "", "", "", "", "", "", "", }; //--------------------------------------------------------------------------- static const char* Swf_Format_Profile_Audio[]= { "", "", "Layer 3", "", "", "", "", "", "", "", "", "", "", "", "", "", }; //--------------------------------------------------------------------------- static const char* Swf_SoundFormat[]= { "Uncompressed", "SWF ADPCM", "MPEG-1L3", "Uncompressed Little Endian", "", "", "Nellymoser", "", "", "", "", "", "", "", "", "", }; //--------------------------------------------------------------------------- static const char* Swf_Format_Video[]= { "", "", "H.263", "Screen video", "VP6", "VP6", "Screen video 2", "AVC", "", "", "", "", "", "", "", "", }; //--------------------------------------------------------------------------- static const char* Swf_Format_Profile_Video[]= { "", "", "", "", "", "Alpha channel", "", "", "", "", "", "", "", "", "", "", }; //--------------------------------------------------------------------------- static const char* Swf_Codec_Video[]= { "", "", "Sorenson H263", "Screen video", "On2 VP6", "On2 VP6 with alpha channel", "Screen video 2", "AVC", "", "", "", "", "", "", "", "", }; //*************************************************************************** // Constants //*************************************************************************** namespace Elements { const int16u End = 0; //V1+ const int16u ShowFrame = 1; //V1+ const int16u DefineShape = 2; //V1+ const int16u PlaceObject = 4; //V1+ const int16u RemoveObject = 5; //V1+ const int16u DefineBits = 6; //V1+ const int16u DefineButton = 7; //V1+ const int16u JPEGTables = 8; //V1+ const int16u SetBackgroundColor = 9; //V1+ const int16u DefineFont = 10; //V1+ const int16u DefineText = 11; //V1+ const int16u DoAction = 12; //V3+ const int16u DefineFontInfo = 13; //V1+ const int16u DefineSound = 14; //V1+ const int16u StartSound = 15; //V1+ const int16u DefineButtonSound = 17; //V2+ const int16u SoundStreamHead = 18; //V1+ const int16u SoundStreamBlock = 19; //V1+ const int16u DefineBitsLossless = 20; //V2+ const int16u DefineBitsJPEG2 = 21; //V2+ const int16u DefineShape2 = 22; //V2+ const int16u DefineCxform = 23; //V2+ const int16u Protect = 24; //V2+ const int16u PlaceObject2 = 26; //V3+ const int16u RemoveObject2 = 28; //V3+ const int16u DefineShape3 = 32; //V3+ const int16u DefineText2 = 33; //V3+ const int16u DefineButton2 = 34; //V3+ const int16u DefineBitsJPEG3 = 35; //V3+ const int16u DefineBitsLossless2 = 36; //V3+ const int16u DefineEditText = 37; //V4+ const int16u DefineSprite = 39; //V3+ const int16u FrameLabel = 43; //V3+ const int16u SoundStreamHead2 = 45; //V3+ const int16u DefineMorphShape = 46; //V3+ const int16u DefineFont2 = 48; //V3+ const int16u ExportAssets = 56; //V5+ const int16u ImportAssets = 57; //V5+ const int16u EnableDebugger = 58; //V5 const int16u DoInitAction = 59; //V6+ const int16u DefineVideoStream = 60; //V6+ const int16u DefineVideoFrame = 61; //V6+ const int16u DefineFontInfo2 = 62; //V6+ const int16u EnableDebugger2 = 64; //V6+ const int16u ScriptLimits = 65; //V6+ const int16u SetTabIndex = 66; //V7+ const int16u FileAttributes = 69; //V1+ const int16u PlaceObject3 = 70; //V8+ const int16u ImportAssets2 = 71; //V8+ const int16u DefineFontAlignZones = 73; //V8+ const int16u CSMTextSettings = 74; //V8+ const int16u DefineFont3 = 75; //V8+ const int16u SymbolClass = 76; //V9+ const int16u Metadata = 77; //V1+ const int16u DefineScalingGrid = 78; //V8+ const int16u DoABC = 82; //V9+ const int16u DefineShape4 = 83; //V8+ const int16u DefineMorphShape2 = 84; //V8+ const int16u DefineSceneAndFrameLabelData = 86; //V9+ const int16u DefineBinaryData = 87; //V9+ const int16u DefineFontName = 88; //V9+ const int16u StartSound2 = 89; //V9+ } //*************************************************************************** // Constructor/Destructor //*************************************************************************** //--------------------------------------------------------------------------- File_Swf::File_Swf() :File__Analyze() { //In Frame_Count_Valid=1024; FileLength=0; Version=0; } //*************************************************************************** // Buffer //*************************************************************************** //--------------------------------------------------------------------------- bool File_Swf::FileHeader_Begin() { //Parsing if (Buffer_Size<8) return false; if (CC3(Buffer)!=0x435753) //CWS return true; //Compressed file if (File_Size>16*1024*1024) return true; //The file is too big, we will not parse all, only say this is SWF if (CC4(Buffer+4)<4*16*1024*1024) //FileLength return true; //The file is too big, we will not parse all, only say this is SWF Buffer_MaximumSize=(size_t)File_Size; if (Buffer_Size!=File_Size) return false; return true; } //--------------------------------------------------------------------------- void File_Swf::FileHeader_Parse() { //Parsing if (Buffer_Size<8) { Element_WaitForMoreData(); return; } int32u Signature; if (FileLength==0 && Version==0) { Element_Begin1("SWF header"); Get_C3 (Signature, "Signature"); Get_L1 (Version, "Version"); Get_L4 (FileLength, "FileLength"); Element_End0(); } else { //Was already done by compressed file handling Signature=0x465753; } //Compressed file handling if (Signature==0x435753) //CWS { Decompress(); return; } if (Signature!=0x465753) //FWS { Reject(); return; } //Parsing //Parsing - BitStream float32 FrameRate; int32u Xmin, Xmax, Ymin, Ymax; int16u FrameCount; int8u Nbits; BS_Begin(); Get_S1 (5, Nbits, "Nbits"); Get_BS (Nbits, Xmin, "Xmin"); Get_BS (Nbits, Xmax, "Xmax"); Param_Info2((Xmax-Xmin)/20, " pixels"); Get_BS (Nbits, Ymin, "Ymin"); Get_BS (Nbits, Ymax, "Ymax"); Param_Info2((Ymax-Ymin)/20, " pixels"); BS_End(); if (Version<=7) { int8u FrameRate_8; Skip_L1( "Ignored"); Get_L1 (FrameRate_8, "FrameRate"); FrameRate=FrameRate_8; } else { int16u FrameRate_8_8; Get_L2(FrameRate_8_8, "FrameRate"); FrameRate=((float32)FrameRate_8_8)/0x0100+(((float32)(FrameRate_8_8&0x00FF))/0x0100); //8.8 format Param_Info1(FrameRate); } Get_L2 (FrameCount, "FrameCount"); FILLING_BEGIN(); //Integrity if (Signature!=0x465753 && Signature!=0x435753) //FWS or CWS { Reject("SWF"); return; } //Filling Accept("SWF"); if (!IsSub) Fill(Stream_General, 0, General_Format, "ShockWave"); Stream_Prepare(Stream_Video); Fill(Stream_Video, 0, Video_Width, (Xmax-Xmin)/20); Fill(Stream_Video, 0, Video_Height, (Ymax-Ymin)/20); if (FrameRate) Fill(Stream_Video, 0, Video_FrameRate, FrameRate); if (FrameCount) Fill(Stream_Video, 0, Video_FrameCount, FrameCount); FILLING_END(); } //--------------------------------------------------------------------------- void File_Swf::Header_Parse() { //Parsing int16u TagCodeAndLength; Get_L2 (TagCodeAndLength, "TagCodeAndLength"); //Filling int16u Tag=(TagCodeAndLength&0xFFC0)>>6; Param_Info1(Tag); Header_Fill_Code(Tag, Ztring().From_Number(Tag, 16)); //Size int16u Length=TagCodeAndLength&0x003F; if (Length<0x003F) { Param_Info2(Length, " bytes"); //Filling Header_Fill_Size(Element_Offset+Length); } else { int32u Length2; Get_L4(Length2, "Length"); Param_Info2(Length2, " bytes"); //Filling Header_Fill_Size(Element_Offset+Length2); } } //--------------------------------------------------------------------------- void File_Swf::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; \ //Parsing DATA_BEGIN ATO2(End, "End"); ATO2(ShowFrame, "ShowFrame"); ATO2(DefineShape, "DefineShape"); ATO2(PlaceObject, "PlaceObject"); ATO2(RemoveObject, "RemoveObject"); ATO2(DefineBits, "DefineBits"); ATO2(DefineButton, "DefineButton"); ATO2(JPEGTables, "JPEGTables"); ATO2(SetBackgroundColor, "SetBackgroundColor"); ATO2(DefineFont, "DefineFont"); ATO2(DefineText, "DefineText"); ATO2(DoAction, "DoAction"); ATO2(DefineFontInfo, "DefineFontInfo"); ATO2(DefineSound, "DefineSound"); ATO2(StartSound, "StartSound"); ATO2(DefineButtonSound, "DefineButtonSound"); ATO2(SoundStreamHead, "SoundStreamHead"); ATO2(SoundStreamBlock, "SoundStreamBlock"); ATO2(DefineBitsLossless, "DefineBitsLossless"); ATO2(DefineBitsJPEG2, "DefineBitsJPEG2"); ATO2(DefineShape2, "DefineShape2"); ATO2(DefineCxform, "DefineCxform"); ATO2(Protect, "Protect"); ATO2(PlaceObject2, "PlaceObject2"); ATO2(RemoveObject2, "RemoveObject2"); ATO2(DefineShape3, "DefineShape3"); ATO2(DefineText2, "DefineText2"); ATO2(DefineButton2, "DefineButton2"); ATO2(DefineBitsJPEG3, "DefineBitsJPEG3"); ATO2(DefineBitsLossless2, "DefineBitsLossless2"); ATO2(DefineEditText, "DefineEditText"); LIS2(DefineSprite, "DefineSprite"); ATOM_BEGIN ATO2(ShowFrame, "ShowFrame"); ATO2(PlaceObject, "PlaceObject"); ATO2(RemoveObject, "RemoveObject"); ATO2(StartSound, "StartSound"); ATO2(SoundStreamHead, "SoundStreamHead"); ATO2(SoundStreamBlock, "SoundStreamBlock"); ATO2(PlaceObject2, "PlaceObject2"); ATO2(RemoveObject2, "RemoveObject2"); ATO2(FrameLabel, "FrameLabel"); ATO2(SoundStreamHead2, "SoundStreamHead2"); ATO2(End, "End"); ATOM_END ATO2(FrameLabel, "FrameLabel"); ATO2(DefineMorphShape, "DefineMorphShape"); ATO2(SoundStreamHead2, "SoundStreamHead2"); ATO2(DefineFont2, "DefineFont2"); ATO2(ExportAssets, "ExportAssets"); ATO2(ImportAssets, "ImportAssets"); ATO2(EnableDebugger, "EnableDebugger"); ATO2(DoInitAction, "DoInitAction"); ATO2(DefineVideoStream, "DefineVideoStream"); ATO2(DefineVideoFrame, "DefineVideoFrame"); ATO2(DefineFontInfo2, "DefineFontInfo2"); ATO2(EnableDebugger2, "EnableDebugger2"); ATO2(ScriptLimits, "ScriptLimits"); ATO2(SetTabIndex, "SetTabIndex"); ATO2(FileAttributes, "FileAttributes"); ATO2(PlaceObject3, "PlaceObject3"); ATO2(ImportAssets2, "ImportAssets2"); ATO2(DefineFontAlignZones, "DefineFontAlignZones"); ATO2(CSMTextSettings, "CSMTextSettings"); ATO2(DefineFont3, "DefineFont3"); ATO2(SymbolClass, "SymbolClass"); ATO2(Metadata, "Metadata"); ATO2(DefineScalingGrid, "DefineScalingGrid"); ATO2(DoABC, "DoABC"); ATO2(DefineShape4, "DefineShape4"); ATO2(DefineMorphShape2, "DefineMorphShape2"); ATO2(DefineSceneAndFrameLabelData, "DefineSceneAndFrameLabelData"); ATO2(DefineBinaryData, "DefineBinaryData"); ATO2(DefineFontName, "DefineFontName"); ATO2(StartSound2, "StartSound2"); DATA_END Frame_Count++; if (Frame_Count>=Frame_Count_Valid) Data_Finish("SWF"); } //*************************************************************************** // Elements //*************************************************************************** //--------------------------------------------------------------------------- void File_Swf::DefineSound() { //Parsing int16u SoundId; int8u SoundFormat, SoundRate, SoundSize, SoundType; Get_L2 (SoundId, "SoundId"); BS_Begin(); Get_S1 (4, SoundFormat, "SoundFormat"); Param_Info1(Swf_SoundFormat[SoundFormat]); Get_S1 (2, SoundRate, "SoundRate"); Param_Info2(Swf_SoundRate[SoundRate], " Hz"); Get_S1 (1, SoundSize, "SoundSize"); Param_Info2(Swf_SoundSize[SoundSize], " bits"); Get_S1 (1, SoundType, "SoundType"); Param_Info2(Swf_SoundType[SoundType], " channel(s)"); BS_End(); Skip_L4( "SoundSampleCount"); Skip_XX(Element_Size-Element_Offset, "SoundData"); Stream_Prepare(Stream_Audio); Fill(Stream_Audio, StreamPos_Last, Audio_ID, SoundId); Fill(Stream_Audio, StreamPos_Last, Audio_Format, Swf_Format_Audio[SoundFormat]); Fill(Stream_Audio, StreamPos_Last, Audio_Format_Version, Swf_Format_Version_Audio[SoundFormat]); Fill(Stream_Audio, StreamPos_Last, Audio_Format_Profile, Swf_Format_Profile_Audio[SoundFormat]); Fill(Stream_Audio, StreamPos_Last, Audio_Codec, Swf_SoundFormat[SoundFormat]); Fill(Stream_Audio, StreamPos_Last, Audio_SamplingRate, Swf_SoundRate[SoundRate]); if (SoundFormat!=2) //SoundSize is not valid for MPEG Audio Fill(Stream_Audio, StreamPos_Last, Audio_BitDepth, Swf_SoundSize[SoundSize]); Fill(Stream_Audio, StreamPos_Last, Audio_Channel_s_, Swf_SoundType[SoundType]); } //--------------------------------------------------------------------------- void File_Swf::SoundStreamHead() { //Parsing int16u StreamSoundSampleCount; int8u StreamSoundCompression, StreamSoundRate, StreamSoundType, StreamSoundSize; BS_Begin(); Skip_S1(4, "Reserved"); Info_S1(2, PlaybackSoundRate, "PlaybackSoundRate"); Param_Info2(Swf_SoundRate[PlaybackSoundRate], " Hz"); Info_S1(1, PlaybackSoundSize, "PlaybackSoundSize"); Param_Info2(Swf_SoundSize[PlaybackSoundSize], " bits"); Info_S1(1, PlaybackSoundType, "PlaybackSoundType"); Param_Info2(Swf_SoundType[PlaybackSoundType], " channel(s)"); Get_S1 (4, StreamSoundCompression, "StreamSoundCompression"); Param_Info1(Swf_SoundFormat[StreamSoundCompression]); Get_S1 (2, StreamSoundRate, "StreamSoundRate"); Param_Info2(Swf_SoundRate[StreamSoundRate], " Hz"); Get_S1 (1, StreamSoundSize, "StreamSoundSize"); Param_Info2(Swf_SoundSize[StreamSoundSize], " bits"); Get_S1 (1, StreamSoundType, "StreamSoundType"); Param_Info2(Swf_SoundType[StreamSoundType], " channel(s)"); BS_End(); Get_L2 (StreamSoundSampleCount, "StreamSoundSampleCount"); if (StreamSoundCompression==2) Skip_L2( "LatencySeek"); if (StreamSoundSampleCount>0) { Stream_Prepare(Stream_Audio); Fill(Stream_Audio, StreamPos_Last, Audio_Format, Swf_Format_Audio[StreamSoundCompression]); Fill(Stream_Audio, StreamPos_Last, Audio_Format_Version, Swf_Format_Version_Audio[StreamSoundCompression]); Fill(Stream_Audio, StreamPos_Last, Audio_Format_Profile, Swf_Format_Profile_Audio[StreamSoundCompression]); Fill(Stream_Audio, StreamPos_Last, Audio_Codec, Swf_SoundFormat[StreamSoundCompression]); Fill(Stream_Audio, StreamPos_Last, Audio_SamplingRate, Swf_SoundRate[StreamSoundRate]); if (StreamSoundCompression!=2) //SoundSize is not valid for MPEG Audio Fill(Stream_Audio, StreamPos_Last, Audio_BitDepth, Swf_SoundSize[StreamSoundSize]); Fill(Stream_Audio, StreamPos_Last, Audio_Channel_s_, Swf_SoundType[StreamSoundType]); } } //--------------------------------------------------------------------------- void File_Swf::DefineSprite() { //Parsing Skip_B2( "Character ID of sprite"); Skip_B2( "Number of frames in sprite"); } //--------------------------------------------------------------------------- void File_Swf::DefineVideoStream() { //Parsing int16u CharacterID, NumFrames, Width, Height; int8u CodecID; Get_L2 (CharacterID, "CharacterID"); Get_L2 (NumFrames, "NumFrames"); Get_L2 (Width, "Width"); Get_L2 (Height, "Height"); BS_Begin(); Skip_BS(4, "VideoFlagsReserved"); Skip_BS(3, "VideoFlagsDeblocking"); Skip_BS(1, "VideoFlagsSmoothing"); BS_End(); Get_L1 (CodecID, "CodecID"); Param_Info1C((CodecID<16), Swf_Format_Video[CodecID]); Stream_Prepare(Stream_Video); Fill(Stream_Video, StreamPos_Last, Video_ID, CharacterID); Fill(Stream_Video, StreamPos_Last, Video_Width, Width); Fill(Stream_Video, StreamPos_Last, Video_Height, Height); if (CodecID<16) { Fill(Stream_Video, StreamPos_Last, Video_Format, Swf_Format_Video[CodecID]); Fill(Stream_Video, StreamPos_Last, Video_Format_Profile, Swf_Format_Profile_Video[CodecID]); Fill(Stream_Video, StreamPos_Last, Video_Codec, Swf_Codec_Video[CodecID]); } Fill(Stream_Video, StreamPos_Last, Video_FrameCount, NumFrames); } //*************************************************************************** // Helpers //*************************************************************************** //--------------------------------------------------------------------------- bool File_Swf::Decompress() { if (Buffer_Size!=File_Size) { //We must have the complete file in memory, but this is too big (not handled by FileHeader_Begin()), only saying this is SWF Fill(Stream_General, 0, General_Format, "ShockWave"); Stream_Prepare(Stream_Video); Finish("SWF"); return true; } //Sizes unsigned long Source_Size=(unsigned long)(File_Size-8); unsigned long Dest_Size=(unsigned long)(FileLength-8); //Uncompressing int8u* Dest=new int8u[Dest_Size]; if (uncompress((Bytef*)Dest, &Dest_Size, (const Bytef*)Buffer+Buffer_Offset+8, Source_Size)<0) { delete[] Dest; //Dest=NULL Trusted_IsNot("Error while decompressing"); Reject("SWF"); return false; } Accept("SWF"); Fill(Stream_General, 0, General_Format, "ShockWave"); File_Swf MI; MI.FileLength=FileLength; MI.Version=Version; auto File_Size_Sav=File_Size; File_Size=Dest_Size; Open_Buffer_Init(&MI); MI.Open_Buffer_Continue(Dest, Dest_Size); MI.Open_Buffer_Finalize(); File_Size=File_Size_Sav; Merge(MI, Stream_General, 0, 0); Merge(MI); delete[] Dest; //Dest=NULL; Finish("SWF"); return true; } } //NameSpace #endif //MEDIAINFO_SWF_*