/* 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" #include "MediaInfo/TimeCode.h" // For bitset8 #include "ZenLib/Conf.h" #include #include #include using namespace ZenLib; using namespace std; //--------------------------------------------------------------------------- //*************************************************************************** // Constants //*************************************************************************** //--------------------------------------------------------------------------- #if defined(MEDIAINFO_AVC_YES) || defined(MEDIAINFO_MPEGPS_YES) || defined(MEDIAINFO_MPEGTS_YES) || defined(MEDIAINFO_MPEG7_YES) //--------------------------------------------------------------------------- namespace MediaInfoLib { //--------------------------------------------------------------------------- static constexpr const char* Avc_profile_idc_Names[]= // Time sorted list { "Baseline", // 2003 "Main", "Extended", "High", // 2005 "High 10", "High 4:2:2", "High 4:4:4", "High 10 Intra", // 2007 "High 4:2:2 Intra", "High 4:4:4 Intra", "CAVLC 4:4:4 Intra", "High 4:4:4 Predictive", "Scalable Baseline", // 2007-11 "Scalable High", "Scalable High Intra", "Constrained Baseline", // 2009 "Multiview High", "Stereo High", // 2010 "Progressive High", // 2011 "Constrained High", // 2012 "Scalable Constrained Baseline", "Scalable Constrained High", "Multiview Depth High", // 2013 "MFC High", // 2014 "Enhanced Multiview Depth High", "MFC Depth High", // 2016 "Progressive High 10", // 2017 }; const char* Avc_profile_idc_Name(size_t Index) { return Avc_profile_idc_Names[Index]; } static constexpr int8u Avc_profile_idc_Mapping[][2]= // profile_idc sorted list { { 44, 10 }, // 44, CAVLC 4:4:4 Intra (2007) { 66, 0 }, // 66, Baseline (2003) { 77, 1 }, // 77, Main (2003) { 83, 12 }, // 83, Scalable Baseline (2007-11) { 86, 13 }, // 86, Scalable High (2007-11) { 88, 2 }, // 88, Extended (2003) { 100, 3 }, // 100, High (2005) { 110, 4 }, // 110, High 10 (2005) { 118, 16 }, // 118, Multiview High (2009) { 122, 5 }, // 122, High 4:2:2 (2005) { 128, 17 }, // 128, Stereo High (2010) { 134, 23 }, // 134, MFC High (2014) { 135, 25 }, // 135, MFC Depth High (2016) { 138, 22 }, // 138, Multiview Depth High (2013) { 139, 24 }, // 139, Enhanced Multiview Depth High (2014) { 144, 16 }, // 144, High 4:4:4 (2005) { 244, 11 }, // 244, High 4:4:4 Predictive (2007) }; static inline constexpr bool Avc_profile_idc_Names_Size_Cmp(const int8u first[2], const int8u second) { return first[0]>4); Level&=0xF; if (Level) { LevelS+='.'; LevelS+='0'+Level; } return LevelS; } string Avc_profile_level_string(int8u profile_idc, int8u level_idc=0, int8u constraint_set_flags=0) { string Profile; bitset8 constraint_setsB(constraint_set_flags); //Profile if (profile_idc) { size_t Profile_Pos=(size_t)-1; if (constraint_setsB[6]) // constraint_set1_flag switch (profile_idc) { case 66 : Profile_Pos= 15; break; // Constrained Baseline (2009) } if (constraint_setsB[4]) // constraint_set3_flag switch (profile_idc) { case 86 : Profile_Pos= 14; break; // Scalable High Intra (2007-11) case 110 : Profile_Pos= 7; break; // High 10 Intra (2007) case 122 : Profile_Pos= 8; break; // High 4:2:2 Intra (2007) case 244 : Profile_Pos= 9; break; // High 4:4:4 Intra (2007) } if (constraint_setsB[3]) // constraint_set4_flag { if (constraint_setsB[2]) // constraint_set5_flag switch (profile_idc) { case 83 : Profile_Pos= 20; break; // Scalable Constrained Baseline (2012) case 86 : Profile_Pos= 21; break; // Scalable Constrained High (2012) case 100 : Profile_Pos= 19; break; // Constrained High (2012) } else switch (profile_idc) { case 100 : Profile_Pos= 18; break; // Progressive High (2011) case 110 : Profile_Pos= 26; break; // Progressive High 10 (2017) } } if (Profile_Pos==(size_t)-1) { auto Pos=lower_bound(begin(Avc_profile_idc_Mapping), end(Avc_profile_idc_Mapping), profile_idc, Avc_profile_idc_Names_Size_Cmp); if (Pos!=end(Avc_profile_idc_Mapping)) Profile_Pos=(*Pos)[1]; } if (Profile_Pos==(size_t)-1) Profile=to_string(profile_idc); else Profile=Avc_profile_idc_Names[Profile_Pos]; } //Level if (level_idc) { auto level_idc_level=level_idc/10; auto level_idc_sub=level_idc%10; if (!Profile.empty()) Profile+='@'; Profile+='L'; bool Is1b=false; switch (level_idc) { case 9: Is1b=true; break; case 11: if (constraint_setsB[4]) // constraint_set3_flag switch (profile_idc) { case 66 : // Baseline case 77 : // Main case 88 : // Extended Is1b=true; break; } break; } if (Is1b) Profile+="1b"; else { if (level_idc_level>=10) { auto level_idc_level_10=level_idc_level/10; auto level_idc_level_01=level_idc_level%10; level_idc_level=level_idc_level_01; Profile+='0'+level_idc_level_10; } Profile+='0'+level_idc_level; if (level_idc_sub && level_idc_sub<10) { Profile+='.'; Profile+='0'+level_idc_sub; } } } return Profile; } size_t Avc_profile_level_Indexes(const string& ProfileLevelS) // Note: 1-based, 0 means not found, 0xPPLL form { auto LevelPos=ProfileLevelS.find('@'); size_t ProfileLevel; string ProfileS; // Level if (LevelPos!=string::npos) { if (ProfileLevelS.size()-LevelPos>2 && ProfileLevelS[LevelPos+1]=='L' && ProfileLevelS[LevelPos+2]>='0' && ProfileLevelS[LevelPos+2]<='9') { int8u Level=ProfileLevelS[LevelPos+2]; if (Level=='1' && ProfileLevelS.size()-LevelPos==3 && ProfileLevelS[LevelPos+3]=='b') Level=9; else { Level-='0'; Level<<=4; if (ProfileLevelS.size()-LevelPos>4 && ProfileLevelS[LevelPos+3]=='.' && ProfileLevelS[LevelPos+4]>='0' && ProfileLevelS[LevelPos+4]<='9') Level+=ProfileLevelS[LevelPos+4]-'0'; } auto Pos=find(begin(Avc_level_idc_Names), end(Avc_level_idc_Names), Level); if (Pos==end(Avc_level_idc_Names)) ProfileLevel=0; else ProfileLevel=distance(begin(Avc_level_idc_Names), Pos)+1; } else { ProfileLevel=0; } ProfileS=ProfileLevelS.substr(0, LevelPos); } else { ProfileLevel=0; ProfileS=ProfileLevelS; } // Profile auto Pos=find(begin(Avc_profile_idc_Names), end(Avc_profile_idc_Names), ProfileS); if (Pos!=end(Avc_profile_idc_Names)) ProfileLevel|=(distance(begin(Avc_profile_idc_Names), Pos)+1)<<8; return ProfileLevel; } //--------------------------------------------------------------------------- } //NameSpace //--------------------------------------------------------------------------- #endif //... //--------------------------------------------------------------------------- //*************************************************************************** // //*************************************************************************** //--------------------------------------------------------------------------- #if defined(MEDIAINFO_AVC_YES) //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include "MediaInfo/Video/File_Avc.h" #if defined(MEDIAINFO_AFDBARDATA_YES) #include "MediaInfo/Video/File_AfdBarData.h" #endif //defined(MEDIAINFO_AFDBARDATA_YES) #if defined(MEDIAINFO_DTVCCTRANSPORT_YES) #include "MediaInfo/Text/File_DtvccTransport.h" #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES) #if MEDIAINFO_ADVANCED2 #include "ThirdParty/base64/base64.h" #endif //MEDIAINFO_ADVANCED2 #include "MediaInfo/MediaInfo_Config_MediaInfo.h" #if MEDIAINFO_EVENTS #include "MediaInfo/MediaInfo_Config_PerPackage.h" #include "MediaInfo/MediaInfo_Events.h" #include "MediaInfo/MediaInfo_Events_Internal.h" #endif //MEDIAINFO_EVENTS #include #include using namespace std; using namespace ZenLib; //--------------------------------------------------------------------------- namespace MediaInfoLib { //*************************************************************************** // Infos //*************************************************************************** //--------------------------------------------------------------------------- const size_t Avc_Errors_MaxCount=32; //--------------------------------------------------------------------------- extern const int8u Avc_PixelAspectRatio_Size=17; extern const float32 Avc_PixelAspectRatio[Avc_PixelAspectRatio_Size]= { (float32)1, //Reserved (float32)1, (float32)12/(float32)11, (float32)10/(float32)11, (float32)16/(float32)11, (float32)40/(float32)33, (float32)24/(float32)11, (float32)20/(float32)11, (float32)32/(float32)11, (float32)80/(float32)33, (float32)18/(float32)11, (float32)15/(float32)11, (float32)64/(float32)33, (float32)160/(float32)99, (float32)4/(float32)3, (float32)3/(float32)2, (float32)2, }; //--------------------------------------------------------------------------- const char* Avc_video_format[]= { "Component", "PAL", "NTSC", "SECAM", "MAC", "", "Reserved", "Reserved", }; //--------------------------------------------------------------------------- const char* Avc_video_full_range[]= { "Limited", "Full", }; //--------------------------------------------------------------------------- static const char* Avc_primary_pic_type[]= { "I", "I, P", "I, P, B", "SI", "SI, SP", "I, SI", "I, SI, P, SP", "I, SI, P, SP, B", }; //--------------------------------------------------------------------------- static const char* Avc_slice_type[]= { "P", "B", "I", "SP", "SI", "P", "B", "I", "SP", "SI", }; //--------------------------------------------------------------------------- const int8u Avc_pic_struct_Size=9; static const char* Avc_pic_struct[]= { "frame", "top field", "bottom field", "top field, bottom field", "bottom field, top field", "top field, bottom field, top field repeated", "bottom field, top field, bottom field repeated", "frame doubling", "frame tripling", }; //--------------------------------------------------------------------------- static const int8u Avc_NumClockTS[]= { 1, 1, 1, 2, 2, 3, 3, 2, 3, }; //--------------------------------------------------------------------------- static const char* Avc_ct_type[]= { "Progressive", "Interlaced", "Unknown", "Reserved", }; //--------------------------------------------------------------------------- static const int8u Avc_SubWidthC[]= { 1, 2, 2, 1, }; //--------------------------------------------------------------------------- static const int8u Avc_SubHeightC[]= { 1, 2, 1, 1, }; //--------------------------------------------------------------------------- const char* Mpegv_colour_primaries(int8u colour_primaries); const char* Mpegv_transfer_characteristics(int8u transfer_characteristics); const char* Mpegv_matrix_coefficients(int8u matrix_coefficients); const char* Mpegv_matrix_coefficients_ColorSpace(int8u matrix_coefficients); //--------------------------------------------------------------------------- static const char* Avc_ChromaSubsampling_format_idc(int8u chroma_format_idc) { switch (chroma_format_idc) { case 1: return "4:2:0"; case 2: return "4:2:2"; case 3: return "4:4:4"; default: return ""; } } //--------------------------------------------------------------------------- static const char* Avc_ChromaSubsampling_format_idc_ColorSpace(int8u chroma_format_idc) { switch (chroma_format_idc) { case 0: return "Y"; case 1: return "YUV"; case 2: return "YUV"; default: return ""; } } //--------------------------------------------------------------------------- const char* Avc_user_data_GA94_cc_type(int8u cc_type) { switch (cc_type) { case 0 : return "CEA-608 line 21 field 1 closed captions"; //closed caption 3 if this is second field case 1 : return "CEA-608 line 21 field 2 closed captions"; //closed caption 4 if this is second field case 2 : return "DTVCC Channel Packet Data"; case 3 : return "DTVCC Channel Packet Start"; default : return ""; } } //--------------------------------------------------------------------------- int32u Avc_MaxDpbMbs(int8u level) { switch (level) { case 10 : return 1485; case 11 : return 3000; case 12 : return 6000; case 13 : case 20 : return 11880; case 21 : return 19800; case 22 : return 20250; case 30 : return 40500; case 31 : return 108000; case 32 : return 216000; case 40 : case 41 : return 245760; case 42 : return 522240; case 50 : return 589824; case 51 : return 983040; default : return 0; } } //--------------------------------------------------------------------------- namespace AVC_Intra_Headers { //720p50 static const size_t __720p50__50_Size = 4 * 0x10 + 0xA; static const int8u __720p50__50[__720p50__50_Size] = { 0x00, 0x00, 0x01, 0x67, 0x6E, 0x10, 0x20, 0xA6, 0xD4, 0x20, 0x32, 0x33, 0x0C, 0x71, 0x18, 0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8C, 0x44, 0x30, 0x21, 0x02, 0x56, 0x4E, 0x6F, 0x37, 0xCD, 0xF9, 0xBF, 0x81, 0x6B, 0xF3, 0x7C, 0xDE, 0x6E, 0x6C, 0xD3, 0x3C, 0x0F, 0x01, 0x6E, 0xFF, 0xC0, 0x00, 0xC0, 0x01, 0x38, 0xC0, 0x40, 0x40, 0x50, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x06, 0x48, 0x40, 0x00, 0x00, 0x01, 0x68, 0xEE, 0x31, 0x12, 0x11 }; static const size_t __720p50_100_Size = 5 * 0x10 + 0x2; static const int8u __720p50_100[__720p50_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x29, 0xB6, 0xD4, 0x20, 0x2A, 0x33, 0x1D, 0xC7, 0x62, 0xA1, 0x08, 0x40, 0x54, 0x66, 0x3B, 0x8E, 0xC5, 0x42, 0x02, 0x10, 0x25, 0x64, 0x2C, 0x89, 0xE8, 0x85, 0xE4, 0x21, 0x4B, 0x90, 0x83, 0x06, 0x95, 0xD1, 0x06, 0x46, 0x97, 0x20, 0xC8, 0xD7, 0x43, 0x08, 0x11, 0xC2, 0x1E, 0x4C, 0x91, 0x0F, 0x01, 0x40, 0x16, 0xEC, 0x07, 0x8C, 0x04, 0x04, 0x05, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x64, 0x84, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x31, 0x12, 0x11 }; //720p60 static const size_t __720p60__50_Size = 4 * 0x10 + 0xB; static const int8u __720p60__50[__720p60__50_Size] = { 0x00, 0x00, 0x01, 0x67, 0x6E, 0x10, 0x20, 0xA6, 0xD4, 0x20, 0x32, 0x33, 0x0C, 0x71, 0x18, 0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8C, 0x44, 0x30, 0x21, 0x02, 0x56, 0x4E, 0x6F, 0x37, 0xCD, 0xF9, 0xBF, 0x81, 0x6B, 0xF3, 0x7C, 0xDE, 0x6E, 0x6C, 0xD3, 0x3C, 0x0F, 0x01, 0x6E, 0xFF, 0xC0, 0x00, 0xC0, 0x01, 0x38, 0xC0, 0x40, 0x40, 0x50, 0x00, 0x00, 0x3E, 0x90, 0x00, 0x1D, 0x4C, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0xEE, 0x31, 0x12, 0x11 }; static const size_t __720p60_100_Size = 5 * 0x10 + 0x1; static const int8u __720p60_100[__720p60_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x29, 0xB6, 0xD4, 0x20, 0x2A, 0x33, 0x1D, 0xC7, 0x62, 0xA1, 0x08, 0x40, 0x54, 0x66, 0x3B, 0x8E, 0xC5, 0x42, 0x02, 0x10, 0x25, 0x64, 0x2C, 0x89, 0xE8, 0x85, 0xE4, 0x21, 0x4B, 0x90, 0x83, 0x06, 0x95, 0xD1, 0x06, 0x46, 0x97, 0x20, 0xC8, 0xD7, 0x43, 0x08, 0x11, 0xC2, 0x1E, 0x4C, 0x91, 0x0F, 0x01, 0x40, 0x16, 0xEC, 0x07, 0x8C, 0x04, 0x04, 0x05, 0x00, 0x00, 0x03, 0x03, 0xE9, 0x00, 0x01, 0xD4, 0xC0, 0x84, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x31, 0x12, 0x11 }; //1080i50 static const size_t _1080i50__50_Size = 5 * 0x10 + 0xE; static const int8u _1080i50__50[_1080i50__50_Size] = { 0x00, 0x00, 0x01, 0x67, 0x6E, 0x10, 0x28, 0xA6, 0xD4, 0x20, 0x32, 0x33, 0x0C, 0x71, 0x18, 0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8C, 0x44, 0x30, 0x21, 0x02, 0x56, 0x4E, 0x6E, 0x61, 0x87, 0x3E, 0x73, 0x4D, 0x98, 0x0C, 0x03, 0x06, 0x9C, 0x0B, 0x73, 0xE6, 0xC0, 0xB5, 0x18, 0x63, 0x0D, 0x39, 0xE0, 0x5B, 0x02, 0xD4, 0xC6, 0x19, 0x1A, 0x79, 0x8C, 0x32, 0x34, 0x24, 0xF0, 0x16, 0x81, 0x13, 0xF7, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x71, 0x80, 0x80, 0x80, 0xA0, 0x00, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x06, 0x50, 0x80, 0x00, 0x00, 0x01, 0x68, 0xEE, 0x31, 0x12, 0x11 }; static const size_t _1080i50_100_Size = 5 * 0x10 + 0xF; static const int8u _1080i50_100[_1080i50_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x29, 0xB6, 0xD4, 0x20, 0x22, 0x33, 0x19, 0xC6, 0x63, 0x23, 0x21, 0x01, 0x11, 0x98, 0xCE, 0x33, 0x19, 0x18, 0x21, 0x03, 0x3A, 0x46, 0x65, 0x6A, 0x65, 0x24, 0xAD, 0xE9, 0x12, 0x32, 0x14, 0x1A, 0x26, 0x34, 0xAD, 0xA4, 0x41, 0x82, 0x23, 0x01, 0x50, 0x2B, 0x1A, 0x24, 0x69, 0x48, 0x30, 0x40, 0x2E, 0x11, 0x12, 0x08, 0xC6, 0x8C, 0x04, 0x41, 0x28, 0x4C, 0x34, 0xF0, 0x1E, 0x01, 0x13, 0xF2, 0xE0, 0x3C, 0x60, 0x20, 0x20, 0x28, 0x00, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x03, 0x01, 0x94, 0x20, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x33, 0x48, 0xD0 }; //1080i60 static const size_t _1080i60__50_Size = 5 * 0x10 + 0xD; static const int8u _1080i60__50[_1080i60__50_Size] = { 0x00, 0x00, 0x01, 0x67, 0x6E, 0x10, 0x28, 0xA6, 0xD4, 0x20, 0x32, 0x33, 0x0C, 0x71, 0x18, 0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8C, 0x44, 0x30, 0x21, 0x02, 0x56, 0x4E, 0x6E, 0x61, 0x87, 0x3E, 0x73, 0x4D, 0x98, 0x0C, 0x03, 0x06, 0x9C, 0x0B, 0x73, 0xE6, 0xC0, 0xB5, 0x18, 0x63, 0x0D, 0x39, 0xE0, 0x5B, 0x02, 0xD4, 0xC6, 0x19, 0x1A, 0x79, 0x8C, 0x32, 0x34, 0x24, 0xF0, 0x16, 0x81, 0x13, 0xF7, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x71, 0x80, 0x80, 0x80, 0xA0, 0x00, 0x00, 0x7D, 0x20, 0x00, 0x1D, 0x4C, 0x10, 0x80, 0x00, 0x00, 0x01, 0x68, 0xEE, 0x31, 0x12, 0x11 }; static const size_t _1080i60_100_Size = 5 * 0x10 + 0xD; static const int8u _1080i60_100[_1080i60_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x29, 0xB6, 0xD4, 0x20, 0x22, 0x33, 0x19, 0xC6, 0x63, 0x23, 0x21, 0x01, 0x11, 0x98, 0xCE, 0x33, 0x19, 0x18, 0x21, 0x03, 0x3A, 0x46, 0x65, 0x6A, 0x65, 0x24, 0xAD, 0xE9, 0x12, 0x32, 0x14, 0x1A, 0x26, 0x34, 0xAD, 0xA4, 0x41, 0x82, 0x23, 0x01, 0x50, 0x2B, 0x1A, 0x24, 0x69, 0x48, 0x30, 0x40, 0x2E, 0x11, 0x12, 0x08, 0xC6, 0x8C, 0x04, 0x41, 0x28, 0x4C, 0x34, 0xF0, 0x1E, 0x01, 0x13, 0xF2, 0xE0, 0x3C, 0x60, 0x20, 0x20, 0x28, 0x00, 0x00, 0x1F, 0x48, 0x00, 0x07, 0x53, 0x04, 0x20, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x33, 0x48, 0xD0 }; //1080p50 static const size_t _1080p50_100_Size = 4 * 0x10 + 0xA; static const int8u _1080p50_100[_1080p50_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x2A, 0xB6, 0xD4, 0x20, 0x22, 0x33, 0x19, 0xC6, 0x63, 0x23, 0x21, 0x01, 0x11, 0x98, 0xCE, 0x33, 0x19, 0x18, 0x21, 0x02, 0x56, 0xB9, 0x3D, 0x7D, 0x7E, 0x4F, 0xE3, 0x3F, 0x11, 0xF1, 0x9E, 0x08, 0xB8, 0x8C, 0x54, 0x43, 0xC0, 0x78, 0x02, 0x27, 0xE2, 0x70, 0x1E, 0x30, 0x10, 0x10, 0x14, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x01, 0x92, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x33, 0x48, 0xD0 }; //1080p60 static const size_t _1080p60_100_Size = 4 * 0x10 + 0x8; static const int8u _1080p60_100[_1080p60_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x2A, 0xB6, 0xD4, 0x20, 0x22, 0x33, 0x19, 0xC6, 0x63, 0x23, 0x21, 0x01, 0x11, 0x98, 0xCE, 0x33, 0x19, 0x18, 0x21, 0x02, 0x56, 0xB9, 0x3D, 0x7D, 0x7E, 0x4F, 0xE3, 0x3F, 0x11, 0xF1, 0x9E, 0x08, 0xB8, 0x8C, 0x54, 0x43, 0xC0, 0x78, 0x02, 0x27, 0xE2, 0x70, 0x1E, 0x30, 0x10, 0x10, 0x14, 0x00, 0x00, 0x0F, 0xA4, 0x00, 0x07, 0x53, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x33, 0x48, 0xD0 }; }; //--------------------------------------------------------------------------- // Some DV Metadata info: http://www.freepatentsonline.com/20050076039.pdf static const char* MDPM(int8u ID) { switch (ID) { case 0x18: return "Date/Time"; // Is "Text header" in doc? case 0x19: return "Date/Time (continue 1)"; // Is "Text" in doc? case 0x70: return "Consumer Camera 1"; case 0x71: return "Consumer Camera 2"; case 0x73: return "Lens"; case 0x7F: return "Camera shutter"; case 0xA1: return "Iris (F)"; case 0xE0: return "Make Model"; case 0xE1: return "Rec Info"; case 0xE4: return "Model Name"; case 0xE5: return "Model Name (continue 1)"; case 0xE6: return "Model Name (continue 1)"; default : return ""; } } //--------------------------------------------------------------------------- static const char* MDPM_MakeName(int16u Value) { switch (Value) { case 0x0103: return "Panasonic"; case 0x0108: return "Sony"; case 0x1011: return "Canon"; case 0x1104: return "JVC"; default : return ""; } } //--------------------------------------------------------------------------- // From DV extern const char* Dv_consumer_camera_1_ae_mode[]; extern const char* Dv_consumer_camera_1_wb_mode[]; extern const char* Dv_consumer_camera_1_white_balance(int8u white_balance); extern const char* Dv_consumer_camera_1_fcm[]; //*************************************************************************** // Constructor/Destructor //*************************************************************************** //--------------------------------------------------------------------------- File_Avc::File_Avc() #if MEDIAINFO_DUPLICATE :File__Duplicate() #endif //MEDIAINFO_DUPLICATE { //Config #if MEDIAINFO_EVENTS ParserIDs[0]=MediaInfo_Parser_Avc; StreamIDs_Width[0]=0; #endif //MEDIAINFO_EVENTS #if MEDIAINFO_TRACE Trace_Layers_Update(8); //Stream #endif //MEDIAINFO_TRACE MustSynchronize=true; PTS_DTS_Needed=true; StreamSource=IsStream; Frame_Count_NotParsedIncluded=0; //In Frame_Count_Valid=0; FrameIsAlwaysComplete=false; MustParse_SPS_PPS=false; SizedBlocks=false; //Temporal references TemporalReferences_DelayedElement=NULL; //Temp preferred_transfer_characteristics=2; //Text #if defined(MEDIAINFO_DTVCCTRANSPORT_YES) GA94_03_Parser=NULL; #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES) } //--------------------------------------------------------------------------- File_Avc::~File_Avc() { Clean_Temp_References(); #if defined(MEDIAINFO_DTVCCTRANSPORT_YES) delete GA94_03_Parser; //GA94_03_Parser=NULL; #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES) Clean_Seq_Parameter(); } //--------------------------------------------------------------------------- void File_Avc::Clean_Temp_References() { for (size_t Pos = 0; Pos::iterator seq_parameter_set_Item=seq_parameter_sets.begin(); seq_parameter_set_Item!=seq_parameter_sets.end(); ++seq_parameter_set_Item) if ((*seq_parameter_set_Item)) Streams_Fill(seq_parameter_set_Item); for (std::vector::iterator subset_seq_parameter_set_Item=subset_seq_parameter_sets.begin(); subset_seq_parameter_set_Item!=subset_seq_parameter_sets.end(); ++subset_seq_parameter_set_Item) if ((*subset_seq_parameter_set_Item)) { if (seq_parameter_sets.empty()) Streams_Fill(subset_seq_parameter_set_Item); else Streams_Fill_subset(subset_seq_parameter_set_Item); Fill(Stream_Video, 0, Video_MultiView_Count, (*subset_seq_parameter_set_Item)->num_views_minus1+1); } #if MEDIAINFO_ADVANCED2 for (size_t Pos = 0; Pos::iterator seq_parameter_set_Item) { if (Count_Get(Stream_Video) && !Retrieve_Const(Stream_Video, 0, Video_Format).empty()) return; if (!Count_Get(Stream_Video)) Stream_Prepare(Stream_Video); Fill(Stream_Video, 0, Video_Format, "AVC"); Fill(Stream_Video, 0, Video_Codec, "AVC"); //Calculating - Pixels int32u Width =((*seq_parameter_set_Item)->pic_width_in_mbs_minus1 +1)*16; int32u Height=((*seq_parameter_set_Item)->pic_height_in_map_units_minus1+1)*16*(2-(*seq_parameter_set_Item)->frame_mbs_only_flag); int8u chromaArrayType = (*seq_parameter_set_Item)->ChromaArrayType(); if (chromaArrayType >= 4) chromaArrayType = 0; int32u CropUnitX=Avc_SubWidthC [chromaArrayType]; int32u CropUnitY=Avc_SubHeightC[chromaArrayType]*(2-(*seq_parameter_set_Item)->frame_mbs_only_flag); Width -=((*seq_parameter_set_Item)->frame_crop_left_offset+(*seq_parameter_set_Item)->frame_crop_right_offset )*CropUnitX; Height-=((*seq_parameter_set_Item)->frame_crop_top_offset +(*seq_parameter_set_Item)->frame_crop_bottom_offset)*CropUnitY; //From vui_parameters float64 PixelAspectRatio=1; float64 FrameRate=0; if ((*seq_parameter_set_Item)->vui_parameters) { if ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_info_present_flag) { if ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_idcvui_parameters->aspect_ratio_idc]; else if ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_idc==0xFF && (*seq_parameter_set_Item)->vui_parameters->sar_height) PixelAspectRatio=((float64)(*seq_parameter_set_Item)->vui_parameters->sar_width)/(*seq_parameter_set_Item)->vui_parameters->sar_height; } if ((*seq_parameter_set_Item)->vui_parameters->timing_info_present_flag) { if (!(*seq_parameter_set_Item)->vui_parameters->fixed_frame_rate_flag) Fill(Stream_Video, StreamPos_Last, Video_FrameRate_Mode, "VFR"); else if ((*seq_parameter_set_Item)->vui_parameters->timing_info_present_flag && (*seq_parameter_set_Item)->vui_parameters->time_scale && (*seq_parameter_set_Item)->vui_parameters->num_units_in_tick) { FrameRate=(float64)(*seq_parameter_set_Item)->vui_parameters->time_scale/(*seq_parameter_set_Item)->vui_parameters->num_units_in_tick/((*seq_parameter_set_Item)->frame_mbs_only_flag?2:(((*seq_parameter_set_Item)->pic_order_cnt_type==2 && Structure_Frame/2>Structure_Field)?1:2))/FrameRate_Divider; Fill(Stream_Video, StreamPos_Last, Video_FrameRate, FrameRate); } } //Colour description if (preferred_transfer_characteristics!=2) Fill(Stream_Video, 0, Video_transfer_characteristics, Mpegv_transfer_characteristics(preferred_transfer_characteristics)); if ((*seq_parameter_set_Item)->vui_parameters->video_signal_type_present_flag) { Fill(Stream_Video, 0, Video_Standard, Avc_video_format[(*seq_parameter_set_Item)->vui_parameters->video_format]); Fill(Stream_Video, 0, Video_colour_range, Avc_video_full_range[(*seq_parameter_set_Item)->vui_parameters->video_full_range_flag]); if ((*seq_parameter_set_Item)->vui_parameters->colour_description_present_flag) { Fill(Stream_Video, 0, Video_colour_description_present, "Yes"); Fill(Stream_Video, 0, Video_colour_primaries, Mpegv_colour_primaries((*seq_parameter_set_Item)->vui_parameters->colour_primaries)); Fill(Stream_Video, 0, Video_transfer_characteristics, Mpegv_transfer_characteristics((*seq_parameter_set_Item)->vui_parameters->transfer_characteristics)); Fill(Stream_Video, 0, Video_matrix_coefficients, Mpegv_matrix_coefficients((*seq_parameter_set_Item)->vui_parameters->matrix_coefficients)); if ((*seq_parameter_set_Item)->vui_parameters->matrix_coefficients!=2) Fill(Stream_Video, 0, Video_ColorSpace, Mpegv_matrix_coefficients_ColorSpace((*seq_parameter_set_Item)->vui_parameters->matrix_coefficients), Unlimited, true, true); } } //hrd_parameter_sets int64u bit_rate_value=(int64u)-1; bool bit_rate_value_IsValid=true; bool cbr_flag=false; bool cbr_flag_IsSet=false; bool cbr_flag_IsValid=true; seq_parameter_set_struct::vui_parameters_struct::xxl* NAL=(*seq_parameter_set_Item)->vui_parameters->NAL; if (NAL) for (size_t Pos=0; PosSchedSel.size(); Pos++) { if (NAL->SchedSel[Pos].cpb_size_value!=(int32u)-1) Fill(Stream_Video, 0, Video_BufferSize, NAL->SchedSel[Pos].cpb_size_value); if (bit_rate_value!=(int64u)-1 && bit_rate_value!=NAL->SchedSel[Pos].bit_rate_value) bit_rate_value_IsValid=false; if (bit_rate_value==(int64u)-1) bit_rate_value=NAL->SchedSel[Pos].bit_rate_value; if (cbr_flag_IsSet==true && cbr_flag!=NAL->SchedSel[Pos].cbr_flag) cbr_flag_IsValid=false; if (cbr_flag_IsSet==0) { cbr_flag=NAL->SchedSel[Pos].cbr_flag; cbr_flag_IsSet=true; } } seq_parameter_set_struct::vui_parameters_struct::xxl* VCL=(*seq_parameter_set_Item)->vui_parameters->VCL; if (VCL) for (size_t Pos=0; PosSchedSel.size(); Pos++) { Fill(Stream_Video, 0, Video_BufferSize, VCL->SchedSel[Pos].cpb_size_value); if (bit_rate_value!=(int64u)-1 && bit_rate_value!=VCL->SchedSel[Pos].bit_rate_value) bit_rate_value_IsValid=false; if (bit_rate_value==(int64u)-1) bit_rate_value=VCL->SchedSel[Pos].bit_rate_value; if (cbr_flag_IsSet==true && cbr_flag!=VCL->SchedSel[Pos].cbr_flag) cbr_flag_IsValid=false; if (cbr_flag_IsSet==0) { cbr_flag=VCL->SchedSel[Pos].cbr_flag; cbr_flag_IsSet=true; } } if (cbr_flag_IsSet && cbr_flag_IsValid) { Fill(Stream_Video, 0, Video_BitRate_Mode, cbr_flag?"CBR":"VBR"); if (bit_rate_value!=(int64u)-1 && bit_rate_value_IsValid) Fill(Stream_Video, 0, cbr_flag?Video_BitRate_Nominal:Video_BitRate_Maximum, bit_rate_value); } } auto Profile=Avc_profile_level_string((*seq_parameter_set_Item)->profile_idc, (*seq_parameter_set_Item)->level_idc, (*seq_parameter_set_Item)->constraint_set_flags); Fill(Stream_Video, 0, Video_Format_Profile, Profile); Fill(Stream_Video, 0, Video_Codec_Profile, Profile); Fill(Stream_Video, StreamPos_Last, Video_Width, Width); Fill(Stream_Video, StreamPos_Last, Video_Height, Height); if ((*seq_parameter_set_Item)->frame_crop_left_offset || (*seq_parameter_set_Item)->frame_crop_right_offset) Fill(Stream_Video, StreamPos_Last, Video_Stored_Width, ((*seq_parameter_set_Item)->pic_width_in_mbs_minus1 +1)*16); if ((*seq_parameter_set_Item)->frame_crop_top_offset || (*seq_parameter_set_Item)->frame_crop_bottom_offset) Fill(Stream_Video, StreamPos_Last, Video_Stored_Height, ((*seq_parameter_set_Item)->pic_height_in_map_units_minus1+1)*16*(2-(*seq_parameter_set_Item)->frame_mbs_only_flag)); Fill(Stream_Video, 0, Video_PixelAspectRatio, PixelAspectRatio, 3, true); if(Height) Fill(Stream_Video, 0, Video_DisplayAspectRatio, Width*PixelAspectRatio/Height, 3, true); //More precise if (FrameRate_Divider==2) { Fill(Stream_Video, StreamPos_Last, Video_Format_Settings_FrameMode, "Frame doubling"); Fill(Stream_Video, StreamPos_Last, Video_Format_Settings, "Frame doubling"); } if (FrameRate_Divider==3) { Fill(Stream_Video, StreamPos_Last, Video_Format_Settings_FrameMode, "Frame tripling"); Fill(Stream_Video, StreamPos_Last, Video_Format_Settings, "Frame tripling"); } //Interlacement if ((*seq_parameter_set_Item)->mb_adaptive_frame_field_flag && Structure_Frame>0) //Interlaced macro-block { Fill(Stream_Video, 0, Video_ScanType, "MBAFF"); Fill(Stream_Video, 0, Video_Interlacement, "MBAFF"); } else if ((*seq_parameter_set_Item)->frame_mbs_only_flag || (Structure_Frame>0 && Structure_Field==0)) //No interlaced frame { switch ((*seq_parameter_set_Item)->pic_struct_FirstDetected) { case 3 : Fill(Stream_Video, 0, Video_ScanType, "Interlaced"); Fill(Stream_Video, 0, Video_Interlacement, "TFF"); Fill(Stream_Video, 0, Video_Format_Settings_PictureStructure, "Frame"); Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "InterleavedFields"); break; case 4 : Fill(Stream_Video, 0, Video_ScanType, "Interlaced"); Fill(Stream_Video, 0, Video_Interlacement, "BFF"); Fill(Stream_Video, 0, Video_Format_Settings_PictureStructure, "Frame"); Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "InterleavedFields"); break; default : Fill(Stream_Video, 0, Video_ScanType, "Progressive"); Fill(Stream_Video, 0, Video_Interlacement, "PPF"); } } else if (Structure_Field>0) { Fill(Stream_Video, 0, Video_ScanType, "Interlaced"); Fill(Stream_Video, 0, Video_Interlacement, "Interlaced"); } std::string ScanOrders, PictureTypes(PictureTypes_PreviousFrames); ScanOrders.reserve(TemporalReferences.size()); for (size_t Pos=0; PosIsTop?'T':'B'; if ((Pos%2)==0) PictureTypes+=Avc_slice_type[TemporalReferences[Pos]->slice_type]; } else if (!PictureTypes.empty()) //Only if stream already started { ScanOrders+=' '; if ((Pos%2)==0) PictureTypes+=' '; } Fill(Stream_Video, 0, Video_ScanOrder, ScanOrder_Detect(ScanOrders)); { //Legacy string Result=ScanOrder_Detect(ScanOrders); if (!Result.empty()) { Fill(Stream_Video, 0, Video_Interlacement, Result, true, true); Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "SeparatedFields", Unlimited, true, true); } else { switch ((*seq_parameter_set_Item)->pic_struct_FirstDetected) { case 1 : Fill(Stream_Video, 0, Video_ScanOrder, (string) "TFF"); Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "SeparatedFields", Unlimited, true, true); break; case 2 : Fill(Stream_Video, 0, Video_ScanOrder, (string) "BFF"); Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "SeparatedFields", Unlimited, true, true); break; case 3 : Fill(Stream_Video, 0, Video_ScanOrder, (string) "TFF"); Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "InterleavedFields", Unlimited, true, true); break; case 4 : Fill(Stream_Video, 0, Video_ScanOrder, (string) "BFF"); Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "InterleavedFields", Unlimited, true, true); break; default : ; } } } Fill(Stream_Video, 0, Video_Format_Settings_GOP, GOP_Detect(PictureTypes)); if (Retrieve_Const(Stream_Video, 0, Video_BitRate).empty() && Retrieve_Const(Stream_Video, 0, Video_Format_Settings_GOP)==__T("N=1") && FrameRate && FrameSizes.size()==1) { Fill(Stream_Video, 0, Video_BitRate, FrameSizes.begin()->first*FrameRate*8, 0); Fill(Stream_Video, 0, Video_BitRate_Mode, "CBR"); } Fill(Stream_General, 0, General_Encoded_Library, Encoded_Library); Fill(Stream_General, 0, General_Encoded_Library_Name, Encoded_Library_Name); Fill(Stream_General, 0, General_Encoded_Library_Version, Encoded_Library_Version); Fill(Stream_General, 0, General_Encoded_Library_Settings, Encoded_Library_Settings); Fill(Stream_Video, 0, Video_Encoded_Library, Encoded_Library); Fill(Stream_Video, 0, Video_Encoded_Library_Name, Encoded_Library_Name); Fill(Stream_Video, 0, Video_Encoded_Library_Version, Encoded_Library_Version); Fill(Stream_Video, 0, Video_Encoded_Library_Settings, Encoded_Library_Settings); if (Retrieve_Const(Stream_Video, 0, Video_BitRate_Nominal).empty()) // SPS has priority over other metadata Fill(Stream_Video, 0, Video_BitRate_Nominal, BitRate_Nominal); Fill(Stream_Video, 0, Video_MuxingMode, MuxingMode); for (std::vector::iterator pic_parameter_set_Item=pic_parameter_sets.begin(); pic_parameter_set_Item!=pic_parameter_sets.end(); ++pic_parameter_set_Item) if (*pic_parameter_set_Item && (*pic_parameter_set_Item)->seq_parameter_set_id==seq_parameter_set_Item-(seq_parameter_sets.empty()?subset_seq_parameter_sets.begin():seq_parameter_sets.begin())) { if ((*pic_parameter_set_Item)->entropy_coding_mode_flag) { Fill(Stream_Video, 0, Video_Format_Settings, "CABAC"); Fill(Stream_Video, 0, Video_Format_Settings_CABAC, "Yes"); Fill(Stream_Video, 0, Video_Codec_Settings, "CABAC"); Fill(Stream_Video, 0, Video_Codec_Settings_CABAC, "Yes"); } else { Fill(Stream_Video, 0, Video_Format_Settings_CABAC, "No"); Fill(Stream_Video, 0, Video_Codec_Settings_CABAC, "No"); } break; //TODO: currently, testing only the first pic_parameter_set } if ((*seq_parameter_set_Item)->max_num_ref_frames>0) { Fill(Stream_Video, 0, Video_Format_Settings, Ztring::ToZtring((*seq_parameter_set_Item)->max_num_ref_frames)+__T(" Ref Frames")); Fill(Stream_Video, 0, Video_Codec_Settings, Ztring::ToZtring((*seq_parameter_set_Item)->max_num_ref_frames)+__T(" Ref Frames")); Fill(Stream_Video, 0, Video_Format_Settings_RefFrames, (*seq_parameter_set_Item)->max_num_ref_frames); Fill(Stream_Video, 0, Video_Codec_Settings_RefFrames, (*seq_parameter_set_Item)->max_num_ref_frames); } if (Retrieve(Stream_Video, 0, Video_ColorSpace).empty()) Fill(Stream_Video, 0, Video_ColorSpace, Avc_ChromaSubsampling_format_idc_ColorSpace((*seq_parameter_set_Item)->chroma_format_idc)); Fill(Stream_Video, 0, Video_ChromaSubsampling, Avc_ChromaSubsampling_format_idc((*seq_parameter_set_Item)->chroma_format_idc)); if ((*seq_parameter_set_Item)->bit_depth_luma_minus8==(*seq_parameter_set_Item)->bit_depth_chroma_minus8) Fill(Stream_Video, 0, Video_BitDepth, (*seq_parameter_set_Item)->bit_depth_luma_minus8+8); if (MaxSlicesCount>1) Fill(Stream_Video, 0, Video_Format_Settings_SliceCount, MaxSlicesCount); hdr::iterator EtsiTs103433 = HDR.find(HdrFormat_EtsiTs103433); if (EtsiTs103433 != HDR.end()) { for (std::map::iterator Item = EtsiTs103433->second.begin(); Item != EtsiTs103433->second.end(); ++Item) { Fill(Stream_Video, 0, Item->first, Item->second); } } hdr::iterator SmpteSt209440 = HDR.find(HdrFormat_SmpteSt209440); if (SmpteSt209440 != HDR.end()) { for (std::map::iterator Item = SmpteSt209440->second.begin(); Item != SmpteSt209440->second.end(); ++Item) { switch (Item->first) { case Video_MasteringDisplay_ColorPrimaries: case Video_MasteringDisplay_Luminance: if (Retrieve_Const(Stream_Video, 0, Item->first) == Item->second) break; // Fallthrough default: Fill(Stream_Video, 0, Item->first, Item->second); } } } hdr::iterator SmpteSt2086 = HDR.find(HdrFormat_SmpteSt2086); if (SmpteSt2086 != HDR.end()) { for (std::map::iterator Item = SmpteSt2086->second.begin(); Item != SmpteSt2086->second.end(); ++Item) { bool Ignore; switch (Item->first) { case Video_HDR_Format: Ignore = !Retrieve_Const(Stream_Video, 0, Item->first).empty(); break; case Video_MasteringDisplay_ColorPrimaries: case Video_MasteringDisplay_Luminance: Ignore = Retrieve_Const(Stream_Video, 0, Item->first) == Item->second; break; default: Ignore = false; } if (!Ignore) Fill(Stream_Video, 0, Item->first, Item->second); } } if (!maximum_content_light_level.empty()) Fill(Stream_Video, 0, Video_MaxCLL, maximum_content_light_level); if (!maximum_frame_average_light_level.empty()) Fill(Stream_Video, 0, Video_MaxFALL, maximum_frame_average_light_level); } //--------------------------------------------------------------------------- void File_Avc::Streams_Fill_subset(const std::vector::iterator seq_parameter_set_Item) { auto Profile=Avc_profile_level_string((*seq_parameter_set_Item)->profile_idc, (*seq_parameter_set_Item)->level_idc, (*seq_parameter_set_Item)->constraint_set_flags); Ztring Profile_Base=Retrieve(Stream_Video, 0, Video_Format_Profile); Fill(Stream_Video, 0, Video_Format_Profile, Profile, true, true); if (!Profile_Base.empty()) Fill(Stream_Video, 0, Video_Format_Profile, Profile_Base); } //--------------------------------------------------------------------------- void File_Avc::Streams_Finish() { if (PTS_End!=(int64u)-1 && (IsSub || File_Offset+Buffer_Offset+Element_Size==File_Size)) { if (PTS_End>PTS_Begin) Fill(Stream_Video, 0, Video_Duration, float64_int64s(((float64)(PTS_End-PTS_Begin))/1000000)); } //GA94 captions #if defined(MEDIAINFO_DTVCCTRANSPORT_YES) if (GA94_03_Parser && GA94_03_Parser->Status[IsAccepted]) { Clear(Stream_Text); Finish(GA94_03_Parser); Merge(*GA94_03_Parser); Ztring LawRating=GA94_03_Parser->Retrieve(Stream_General, 0, General_LawRating); if (!LawRating.empty()) Fill(Stream_General, 0, General_LawRating, LawRating, true); Ztring Title=GA94_03_Parser->Retrieve(Stream_General, 0, General_Title); if (!Title.empty() && Retrieve(Stream_General, 0, General_Title).empty()) Fill(Stream_General, 0, General_Title, Title); for (size_t Pos=0; Posvui_parameters && (*seq_parameter_sets.begin())->vui_parameters->timing_info_present_flag && (*seq_parameter_sets.begin())->vui_parameters->fixed_frame_rate_flag) Ibi_Stream_Finish((*seq_parameter_sets.begin())->vui_parameters->time_scale, (*seq_parameter_sets.begin())->vui_parameters->num_units_in_tick); #endif //MEDIAINFO_IBIUSAGE } //*************************************************************************** // Buffer - File header //*************************************************************************** //--------------------------------------------------------------------------- bool File_Avc::FileHeader_Begin() { if (!File__Analyze::FileHeader_Begin_0x000001()) return false; if (!MustSynchronize) { Synched_Init(); Buffer_TotalBytes_FirstSynched=0; File_Offset_FirstSynched=File_Offset; } //All should be OK return true; } //*************************************************************************** // Buffer - Synchro //*************************************************************************** //--------------------------------------------------------------------------- bool File_Avc::Synchronize() { //Synchronizing size_t Buffer_Offset_Min=Buffer_Offset; while(Buffer_Offset+4<=Buffer_Size && (Buffer[Buffer_Offset ]!=0x00 || Buffer[Buffer_Offset+1]!=0x00 || Buffer[Buffer_Offset+2]!=0x01)) { Buffer_Offset+=2; while(Buffer_Offset=Buffer_Size || Buffer[Buffer_Offset-1]==0x00) Buffer_Offset--; } if (Buffer_Offset>Buffer_Offset_Min && Buffer[Buffer_Offset-1]==0x00) Buffer_Offset--; //Parsing last bytes if needed if (Buffer_Offset+4==Buffer_Size && (Buffer[Buffer_Offset ]!=0x00 || Buffer[Buffer_Offset+1]!=0x00 || Buffer[Buffer_Offset+2]!=0x00 || Buffer[Buffer_Offset+3]!=0x01)) Buffer_Offset++; if (Buffer_Offset+3==Buffer_Size && (Buffer[Buffer_Offset ]!=0x00 || Buffer[Buffer_Offset+1]!=0x00 || Buffer[Buffer_Offset+2]!=0x01)) Buffer_Offset++; if (Buffer_Offset+2==Buffer_Size && (Buffer[Buffer_Offset ]!=0x00 || Buffer[Buffer_Offset+1]!=0x00)) Buffer_Offset++; if (Buffer_Offset+1==Buffer_Size && Buffer[Buffer_Offset ]!=0x00) Buffer_Offset++; if (Buffer_Offset+4>Buffer_Size) return false; //Synched is OK Synched=true; return true; } //--------------------------------------------------------------------------- bool File_Avc::Synched_Test() { //Must have enough buffer for having header if (Buffer_Offset+6>Buffer_Size) return false; //Quick test of synchro if (Buffer[Buffer_Offset ]!=0x00 || Buffer[Buffer_Offset+1]!=0x00 || (Buffer[Buffer_Offset+2]!=0x01 && (Buffer[Buffer_Offset+2]!=0x00 || Buffer[Buffer_Offset+3]!=0x01))) { Synched=false; return true; } //Quick search if (!Header_Parser_QuickSearch()) return false; #if MEDIAINFO_IBIUSAGE bool zero_byte=Buffer[Buffer_Offset+2]==0x00; bool RandomAccess=(Buffer[Buffer_Offset+(zero_byte?4:3)]&0x1F)==0x07 || ((Buffer[Buffer_Offset+(zero_byte?4:3)]&0x1F)==0x09 && ((Buffer[Buffer_Offset+(zero_byte?5:4)]&0xE0)==0x00 || (Buffer[Buffer_Offset+(zero_byte?5:4)]&0xE0)==0xA0)); //seq_parameter_set or access_unit_delimiter with value=0 or 5 (3 bits) if (RandomAccess) Ibi_Add(); #endif //MEDIAINFO_IBIUSAGE //We continue return true; } //*************************************************************************** // Buffer - Demux //*************************************************************************** //--------------------------------------------------------------------------- #if MEDIAINFO_DEMUX void File_Avc::Data_Parse_Iso14496() { if (Demux_Avc_Transcode_Iso14496_15_to_Iso14496_10) { if (Element_Code==0x07) { std::vector::iterator Data_Item=seq_parameter_sets.begin(); if (Data_Item!=seq_parameter_sets.end() && (*Data_Item)) { (*Data_Item)->Init_Iso14496_10(0x67, Buffer+Buffer_Offset, Element_Size); } } if (Element_Code==0x08) { std::vector::iterator Data_Item=pic_parameter_sets.begin(); if (Data_Item!=pic_parameter_sets.end() && (*Data_Item)) { (*Data_Item)->Init_Iso14496_10(0x68, Buffer+Buffer_Offset, Element_Size); } } if (Element_Code==0x0F) { std::vector::iterator Data_Item=subset_seq_parameter_sets.begin(); if (Data_Item!=subset_seq_parameter_sets.end() && (*Data_Item)) { SizeOfNALU_Minus1=0; (*Data_Item)->Init_Iso14496_10(0x6F, Buffer+Buffer_Offset, Element_Size); } } } } //--------------------------------------------------------------------------- bool File_Avc::Demux_UnpacketizeContainer_Test() { const int8u* Buffer_Temp=NULL; size_t Buffer_Temp_Size=0; bool RandomAccess=true; //Default, in case of problem if ((MustParse_SPS_PPS || SizedBlocks) && Demux_Avc_Transcode_Iso14496_15_to_Iso14496_10) { if (MustParse_SPS_PPS) return true; //Wait for SPS and PPS //Random access check RandomAccess=false; //Computing final size size_t TranscodedBuffer_Size=0; size_t Buffer_Offset_Save=Buffer_Offset; while (Buffer_Offset+SizeOfNALU_Minus1+1+1<=Buffer_Size) { size_t Size; if (Buffer_Offset+SizeOfNALU_Minus1>Buffer_Size) { Size=0; Buffer_Offset=Buffer_Size; } else switch (SizeOfNALU_Minus1) { case 0: Size=Buffer[Buffer_Offset]; TranscodedBuffer_Size+=2; break; case 1: Size=BigEndian2int16u(Buffer+Buffer_Offset); TranscodedBuffer_Size++; break; case 2: Size=BigEndian2int24u(Buffer+Buffer_Offset); break; case 3: Size=BigEndian2int32u(Buffer+Buffer_Offset); TranscodedBuffer_Size--; break; default: return true; //Problem } Size+=SizeOfNALU_Minus1+1; //Coherency checking if (Size==0 || Buffer_Offset+Size>Buffer_Size || (Buffer_Offset+Size!=Buffer_Size && Buffer_Offset+Size+SizeOfNALU_Minus1+1>Buffer_Size)) Size=Buffer_Size-Buffer_Offset; //Random access check if (!RandomAccess && Buffer_Offset+SizeOfNALU_Minus1+1Iso14496_10_Buffer_Size; for (seq_parameter_set_structs::iterator Data_Item=subset_seq_parameter_sets.begin(); Data_Item!=subset_seq_parameter_sets.end(); ++Data_Item) TranscodedBuffer_Size+=(*Data_Item)->Iso14496_10_Buffer_Size; for (pic_parameter_set_structs::iterator Data_Item=pic_parameter_sets.begin(); Data_Item!=pic_parameter_sets.end(); ++Data_Item) TranscodedBuffer_Size+=(*Data_Item)->Iso14496_10_Buffer_Size; } //Copying int8u* TranscodedBuffer=new int8u[TranscodedBuffer_Size+100]; size_t TranscodedBuffer_Pos=0; if (RandomAccess) { for (seq_parameter_set_structs::iterator Data_Item=seq_parameter_sets.begin(); Data_Item!=seq_parameter_sets.end(); ++Data_Item) { std::memcpy(TranscodedBuffer+TranscodedBuffer_Pos, (*Data_Item)->Iso14496_10_Buffer, (*Data_Item)->Iso14496_10_Buffer_Size); TranscodedBuffer_Pos+=(*Data_Item)->Iso14496_10_Buffer_Size; } for (seq_parameter_set_structs::iterator Data_Item=subset_seq_parameter_sets.begin(); Data_Item!=subset_seq_parameter_sets.end(); ++Data_Item) { std::memcpy(TranscodedBuffer+TranscodedBuffer_Pos, (*Data_Item)->Iso14496_10_Buffer, (*Data_Item)->Iso14496_10_Buffer_Size); TranscodedBuffer_Pos+=(*Data_Item)->Iso14496_10_Buffer_Size; } for (pic_parameter_set_structs::iterator Data_Item=pic_parameter_sets.begin(); Data_Item!=pic_parameter_sets.end(); ++Data_Item) { std::memcpy(TranscodedBuffer+TranscodedBuffer_Pos, (*Data_Item)->Iso14496_10_Buffer, (*Data_Item)->Iso14496_10_Buffer_Size); TranscodedBuffer_Pos+=(*Data_Item)->Iso14496_10_Buffer_Size; } } while (Buffer_OffsetBuffer_Size || (Buffer_Offset+Size!=Buffer_Size && Buffer_Offset+Size+SizeOfNALU_Minus1+1>Buffer_Size)) Size=Buffer_Size-Buffer_Offset; std::memcpy(TranscodedBuffer+TranscodedBuffer_Pos, Buffer+Buffer_Offset, Size); TranscodedBuffer_Pos+=Size; Buffer_Offset+=Size; } Buffer_Offset=0; Buffer_Temp=Buffer; Buffer=TranscodedBuffer; Buffer_Temp_Size=Buffer_Size; Buffer_Size=TranscodedBuffer_Size; Demux_Offset=Buffer_Size; } else { bool zero_byte=Buffer[Buffer_Offset+2]==0x00; if (!(((Buffer[Buffer_Offset+(zero_byte?4:3)]&0x1B)==0x01 && (Buffer[Buffer_Offset+(zero_byte?5:4)]&0x80)!=0x80) || (Buffer[Buffer_Offset+(zero_byte?4:3)]&0x1F)==0x0C)) { if (Demux_Offset==0) { Demux_Offset=Buffer_Offset; Demux_IntermediateItemFound=false; } while (Demux_Offset+6<=Buffer_Size) { //Synchronizing while(Demux_Offset+6<=Buffer_Size && (Buffer[Demux_Offset ]!=0x00 || Buffer[Demux_Offset+1]!=0x00 || Buffer[Demux_Offset+2]!=0x01)) { Demux_Offset+=2; while(Demux_Offset=Buffer_Size || Buffer[Demux_Offset-1]==0x00) Demux_Offset--; } if (Demux_Offset+6>Buffer_Size) { if (Config->IsFinishing) Demux_Offset=Buffer_Size; break; } zero_byte=Buffer[Demux_Offset+2]==0x00; if (Demux_IntermediateItemFound) { if (!(((Buffer[Demux_Offset+(zero_byte?4:3)]&0x1B)==0x01 && (Buffer[Demux_Offset+(zero_byte?5:4)]&0x80)!=0x80) || (Buffer[Demux_Offset+(zero_byte?4:3)]&0x1F)==0x0C)) break; } else { if ((Buffer[Demux_Offset+(zero_byte?4:3)]&0x1B)==0x01 && (Buffer[Demux_Offset+(zero_byte?5:4)]&0x80)==0x80) Demux_IntermediateItemFound=true; } Demux_Offset++; } if (Demux_Offset+6>Buffer_Size && !FrameIsAlwaysComplete && !Config->IsFinishing) return false; //No complete frame if (Demux_Offset && Buffer[Demux_Offset-1]==0x00) Demux_Offset--; zero_byte=Buffer[Buffer_Offset+2]==0x00; size_t Buffer_Offset_Random=Buffer_Offset; if ((Buffer[Buffer_Offset_Random+(zero_byte?4:3)]&0x1F)==0x09) { Buffer_Offset_Random++; if (zero_byte) Buffer_Offset_Random++; while(Buffer_Offset_Random+6<=Buffer_Size && (Buffer[Buffer_Offset_Random ]!=0x00 || Buffer[Buffer_Offset_Random+1]!=0x00 || Buffer[Buffer_Offset_Random+2]!=0x01)) Buffer_Offset_Random++; zero_byte=Buffer[Buffer_Offset_Random+2]==0x00; } RandomAccess=Buffer_Offset_Random+6<=Buffer_Size && (Buffer[Buffer_Offset_Random+(zero_byte?4:3)]&0x1F)==0x07; //seq_parameter_set } } if (!Status[IsAccepted]) { if (Config->Demux_EventWasSent) return false; File_Avc* MI=new File_Avc; Element_Code=(int64u)-1; Open_Buffer_Init(MI); #ifdef MEDIAINFO_EVENTS MediaInfo_Config_PerPackage* Config_PerPackage_Temp=MI->Config->Config_PerPackage; MI->Config->Config_PerPackage=NULL; #endif //MEDIAINFO_EVENTS Open_Buffer_Continue(MI, Buffer, Buffer_Size); #ifdef MEDIAINFO_EVENTS MI->Config->Config_PerPackage=Config_PerPackage_Temp; #endif //MEDIAINFO_EVENTS bool IsOk=MI->Status[IsAccepted]; delete MI; if (!IsOk) return false; } if (IFrame_Count || RandomAccess) { bool Frame_Count_NotParsedIncluded_PlusOne=false; int64u PTS_Temp=FrameInfo.PTS; if (!IsSub) FrameInfo.PTS=(int64u)-1; if (Frame_Count_NotParsedIncluded!=(int64u)-1 && Interlaced_Top!=Interlaced_Bottom) { Frame_Count_NotParsedIncluded--; Frame_Count_NotParsedIncluded_PlusOne=true; } Demux_UnpacketizeContainer_Demux(RandomAccess); if (!IsSub) FrameInfo.PTS=PTS_Temp; if (Frame_Count_NotParsedIncluded_PlusOne) Frame_Count_NotParsedIncluded++; } else Demux_UnpacketizeContainer_Demux_Clear(); if (Buffer_Temp) { Demux_TotalBytes-=Buffer_Size; Demux_TotalBytes+=Buffer_Temp_Size; delete[] Buffer; Buffer=Buffer_Temp; Buffer_Size=Buffer_Temp_Size; } return true; } #endif //MEDIAINFO_DEMUX //--------------------------------------------------------------------------- void File_Avc::Synched_Init() { if (!Frame_Count_Valid) Frame_Count_Valid=Config->ParseSpeed>=0.3?512:(IsSub?1:2); //FrameInfo PTS_End=0; if (!IsSub) FrameInfo.DTS=0; //No DTS in container DTS_Begin=FrameInfo.DTS; DTS_End=FrameInfo.DTS; //Temporal references TemporalReferences_DelayedElement=NULL; TemporalReferences_Min=0; TemporalReferences_Max=0; TemporalReferences_Reserved=0; TemporalReferences_Offset=0; TemporalReferences_Offset_pic_order_cnt_lsb_Last=0; TemporalReferences_pic_order_cnt_Min=numeric_limits::max(); //Text #if defined(MEDIAINFO_DTVCCTRANSPORT_YES) GA94_03_IsPresent=false; #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES) //File specific SizeOfNALU_Minus1=(int8u)-1; //Status IFrame_Count=0; prevPicOrderCntMsb=0; prevPicOrderCntLsb=(int32u)-1; prevTopFieldOrderCnt=(int32u)-1; prevFrameNum=(int32u)-1; prevFrameNumOffset=(int32u)-1; //Count of a Packets Block_Count=0; Interlaced_Top=0; Interlaced_Bottom=0; Structure_Field=0; Structure_Frame=0; Slices_CountInThisFrame=0; MaxSlicesCount=0; //Temp FrameRate_Divider=1; FirstPFrameInGop_IsParsed=false; Config_IsRepeated=false; tc=0; pic_order_cnt_Displayed=numeric_limits::max(); pic_order_cnt_Delta=0; //Default values Streams.resize(0x100); Streams[0x06].Searching_Payload=true; //sei Streams[0x07].Searching_Payload=true; //seq_parameter_set Streams[0x09].Searching_Payload=true; //access_unit_delimiter Streams[0x0F].Searching_Payload=true; //subset_seq_parameter_set for (int8u Pos=0xFF; Pos>=0xB9; Pos--) Streams[Pos].Searching_Payload=true; //Testing MPEG-PS //Options Option_Manage(); //Specific cases #if MEDIAINFO_EVENTS if (Config->ParseUndecodableFrames_Get()) { Accept(); //In some case, we must accept the stream very quickly and before the sequence header is detected Streams[0x01].Searching_Payload=true; //slice_header Streams[0x05].Searching_Payload=true; //slice_header } #endif //MEDIAINFO_EVENTS #if MEDIAINFO_DEMUX Demux_Avc_Transcode_Iso14496_15_to_Iso14496_10=Config->Demux_Avc_Transcode_Iso14496_15_to_Iso14496_10_Get(); #endif //MEDIAINFO_DEMUX } //*************************************************************************** // Buffer - Global //*************************************************************************** //--------------------------------------------------------------------------- #if MEDIAINFO_ADVANCED2 void File_Avc::Read_Buffer_SegmentChange() { } #endif //MEDIAINFO_ADVANCED2 //--------------------------------------------------------------------------- void File_Avc::Read_Buffer_Unsynched() { //Temporal references Clean_Temp_References(); delete TemporalReferences_DelayedElement; TemporalReferences_DelayedElement=NULL; TemporalReferences_Min=0; TemporalReferences_Max=0; TemporalReferences_Reserved=0; TemporalReferences_Offset=0; TemporalReferences_Offset_pic_order_cnt_lsb_Last=0; TemporalReferences_pic_order_cnt_Min=numeric_limits::max(); pic_order_cnt_Displayed=numeric_limits::max(); pic_order_cnt_Delta=0; Slices_CountInThisFrame=0; //Text #if defined(MEDIAINFO_DTVCCTRANSPORT_YES) if (GA94_03_Parser) GA94_03_Parser->Open_Buffer_Unsynch(); #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES) //parameter_sets if (SizedBlocks || !Config_IsRepeated) //If sized blocks, it is not a broadcasted stream so SPS/PPS are only in container header, we must not disable them. { //Rebuilding immediatly TemporalReferences seq_parameter_set_structs* _seq_parameter_sets=!seq_parameter_sets.empty()?&seq_parameter_sets:&subset_seq_parameter_sets; //Some MVC streams have no seq_parameter_sets. TODO: better management of temporal references for (std::vector::iterator seq_parameter_set_Item=(*_seq_parameter_sets).begin(); seq_parameter_set_Item!=(*_seq_parameter_sets).end(); ++seq_parameter_set_Item) if ((*seq_parameter_set_Item)) { size_t MaxNumber; switch ((*seq_parameter_set_Item)->pic_order_cnt_type) { case 0 : MaxNumber=(*seq_parameter_set_Item)->MaxPicOrderCntLsb; break; case 2 : MaxNumber=(*seq_parameter_set_Item)->MaxFrameNum*2; break; default: Trusted_IsNot("Not supported"); return; } TemporalReferences.resize(4*MaxNumber); TemporalReferences_Reserved=MaxNumber; } } else { Clean_Seq_Parameter(); } //Status Interlaced_Top=0; Interlaced_Bottom=0; prevPicOrderCntMsb=0; prevPicOrderCntLsb=(int32u)-1; prevTopFieldOrderCnt=(int32u)-1; prevFrameNum=(int32u)-1; prevFrameNumOffset=(int32u)-1; //Temp FrameRate_Divider=1; FirstPFrameInGop_IsParsed=false; tc=0; //Impossible to know TimeStamps now PTS_End=0; DTS_End=0; } //*************************************************************************** // Buffer - Per element //*************************************************************************** //--------------------------------------------------------------------------- void File_Avc::Header_Parse() { //Specific case if (MustParse_SPS_PPS) { Header_Fill_Size(Element_Size); Header_Fill_Code((int64u)-1, "Specific"); return; } //Parsing int8u nal_unit_type; if (!SizedBlocks) { if (Buffer[Buffer_Offset+2]==0x00) Skip_B1( "zero_byte"); Skip_B3( "start_code_prefix_one_3bytes"); BS_Begin(); Mark_0 (); Get_S1 ( 2, nal_ref_idc, "nal_ref_idc"); Get_S1 ( 5, nal_unit_type, "nal_unit_type"); BS_End(); if (!Header_Parser_Fill_Size()) { Element_WaitForMoreData(); return; } } else { int64u Size; switch (SizeOfNALU_Minus1) { case 0: { int8u Size_; Get_B1 (Size_, "size"); Size=Size_; } break; case 1: { int16u Size_; Get_B2 (Size_, "size"); Size=Size_; } break; case 2: { int32u Size_; Get_B3 (Size_, "size"); Size=Size_; } break; case 3: { int32u Size_; Get_B4 (Size_, "size"); Size=Size_; } break; default: Trusted_IsNot("No size of NALU defined"); Header_Fill_Size(Buffer_Size-Buffer_Offset); return; } if (Element_Size<(int64u)SizeOfNALU_Minus1+1+1 || Size>Element_Size-Element_Offset) return RanOutOfData("AVC"); Header_Fill_Size(Element_Offset+Size); BS_Begin(); Mark_0 (); Get_S1 ( 2, nal_ref_idc, "nal_ref_idc"); Get_S1 ( 5, nal_unit_type, "nal_unit_type"); BS_End(); } //Filling #if MEDIAINFO_TRACE if (Trace_Activated) Header_Fill_Code(nal_unit_type, Ztring().From_CC1(nal_unit_type)); else #endif //MEDIAINFO_TRACE Header_Fill_Code(nal_unit_type); } //--------------------------------------------------------------------------- bool File_Avc::Header_Parser_Fill_Size() { //Look for next Sync word if (Buffer_Offset_Temp==0) //Buffer_Offset_Temp is not 0 if Header_Parse_Fill_Size() has already parsed first frames Buffer_Offset_Temp=Buffer_Offset+4; while (Buffer_Offset_Temp+5<=Buffer_Size && CC3(Buffer+Buffer_Offset_Temp)!=0x000001) { Buffer_Offset_Temp+=2; while(Buffer_Offset_Temp=Buffer_Size || Buffer[Buffer_Offset_Temp-1]==0x00) Buffer_Offset_Temp--; } //Must wait more data? if (Buffer_Offset_Temp+5>Buffer_Size) { if (FrameIsAlwaysComplete || Config->IsFinishing) Buffer_Offset_Temp=Buffer_Size; //We are sure that the next bytes are a start else return false; } if (!FrameIsAlwaysComplete && Buffer[Buffer_Offset_Temp-1]==0x00) Buffer_Offset_Temp--; //OK, we continue Header_Fill_Size(Buffer_Offset_Temp-Buffer_Offset); Buffer_Offset_Temp=0; return true; } //--------------------------------------------------------------------------- bool File_Avc::Header_Parser_QuickSearch() { while ( Buffer_Offset+6<=Buffer_Size && Buffer[Buffer_Offset ]==0x00 && Buffer[Buffer_Offset+1]==0x00 && (Buffer[Buffer_Offset+2]==0x01 || (Buffer[Buffer_Offset+2]==0x00 && Buffer[Buffer_Offset+3]==0x01))) { //Getting start_code int8u start_code; if (Buffer[Buffer_Offset+2]==0x00) start_code=CC1(Buffer+Buffer_Offset+4)&0x1F; else start_code=CC1(Buffer+Buffer_Offset+3)&0x1F; //Searching start if (Streams[start_code].Searching_Payload || Streams[start_code].ShouldDuplicate) return true; //Synchronizing Buffer_Offset+=4; Synched=false; if (!Synchronize()) { UnSynched_IsNotJunk=true; return false; } if (Buffer_Offset+6>Buffer_Size) { UnSynched_IsNotJunk=true; return false; } } Trusted_IsNot("AVC, Synchronisation lost"); return Synchronize(); } //--------------------------------------------------------------------------- void File_Avc::Data_Parse() { //Specific case if (Element_Code==(int64u)-1) { SPS_PPS(); return; } //Trailing zeroes int64u Element_Size_SaveBeforeZeroes=Element_Size; if (Element_Size) { while (Element_Size && Buffer[Buffer_Offset+(size_t)Element_Size-1]==0) Element_Size--; } //Dump of the SPS/PPS - Init #if MEDIAINFO_ADVANCED2 size_t spspps_Size=0; if (true) //TODO: add an option for activating this extra piece of information in the output { switch (Element_Code) { case 0x07 : //seq_parameter_set(); spspps_Size = seq_parameter_sets.size(); break; case 0x08 : //pic_parameter_set(); spspps_Size = pic_parameter_sets.size(); break; default: ; } } #endif //MEDIAINFO_ADVANCED2 //svc_extension bool svc_extension_flag=false; if (Element_Code==0x0E || Element_Code==0x14) { BS_Begin(); Get_SB (svc_extension_flag, "svc_extension_flag"); if (svc_extension_flag) nal_unit_header_svc_extension(); else nal_unit_header_mvc_extension(); BS_End(); } //Searching emulation_prevention_three_byte int8u* Buffer_3Bytes=NULL; const int8u* Save_Buffer=Buffer; int64u Save_File_Offset=File_Offset; size_t Save_Buffer_Offset=Buffer_Offset; int64u Save_Element_Size=Element_Size; size_t Element_Offset_3Bytes=(size_t)Element_Offset; std::vector ThreeByte_List; while (Element_Offset_3Bytes+3<=Element_Size) { if (CC3(Buffer+Buffer_Offset+(size_t)Element_Offset_3Bytes)==0x000003) ThreeByte_List.push_back(Element_Offset_3Bytes+2); Element_Offset_3Bytes+=2; while(Element_Offset_3Bytes=Element_Size || Buffer[Buffer_Offset+(size_t)Element_Offset_3Bytes-1]==0x00) Element_Offset_3Bytes--; } if (!ThreeByte_List.empty()) { //We must change the buffer for keeping out Element_Size=Save_Element_Size-ThreeByte_List.size(); File_Offset+=Buffer_Offset; Buffer_Offset=0; Buffer_3Bytes=new int8u[(size_t)Element_Size]; for (size_t Pos=0; Pos<=ThreeByte_List.size(); Pos++) { size_t Pos0=(Pos==ThreeByte_List.size())?(size_t)Save_Element_Size:(ThreeByte_List[Pos]); size_t Pos1=(Pos==0)?0:(ThreeByte_List[Pos-1]+1); size_t Buffer_3bytes_Begin=Pos1-Pos; size_t Save_Buffer_Begin =Pos1; size_t Size= Pos0-Pos1; std::memcpy(Buffer_3Bytes+Buffer_3bytes_Begin, Save_Buffer+Save_Buffer_Offset+Save_Buffer_Begin, Size); } Buffer=Buffer_3Bytes; } //Parsing switch (Element_Code) { case 0x00 : Element_Name("unspecified"); Skip_XX(Element_Size-Element_Offset, "Data"); break; case 0x01 : slice_layer_without_partitioning_non_IDR(); break; case 0x02 : Element_Name("slice_data_partition_a_layer"); Skip_XX(Element_Size-Element_Offset, "Data"); break; case 0x03 : Element_Name("slice_data_partition_b_layer"); Skip_XX(Element_Size-Element_Offset, "Data"); break; case 0x04 : Element_Name("slice_data_partition_c_layer"); Skip_XX(Element_Size-Element_Offset, "Data"); break; case 0x05 : slice_layer_without_partitioning_IDR(); break; case 0x06 : sei(); break; case 0x07 : seq_parameter_set(); break; case 0x08 : pic_parameter_set(); break; case 0x09 : access_unit_delimiter(); break; case 0x0A : Element_Name("end_of_seq"); Skip_XX(Element_Size-Element_Offset, "Data"); break; case 0x0B : Element_Name("end_of_stream"); Skip_XX(Element_Size-Element_Offset, "Data"); break; case 0x0C : filler_data(); break; case 0x0D : Element_Name("seq_parameter_set_extension"); Skip_XX(Element_Size-Element_Offset, "Data"); break; case 0x0E : prefix_nal_unit(svc_extension_flag); break; case 0x0F : subset_seq_parameter_set(); break; case 0x13 : Element_Name("slice_layer_without_partitioning"); Skip_XX(Element_Size-Element_Offset, "Data"); break; case 0x14 : slice_layer_extension(svc_extension_flag); break; default : if (Element_Code<0x18) Element_Name("reserved"); else Element_Name("unspecified"); Skip_XX(Element_Size-Element_Offset, "Data"); } if (!ThreeByte_List.empty()) { //We must change the buffer for keeping out Element_Size=Save_Element_Size; File_Offset=Save_File_Offset; Buffer_Offset=Save_Buffer_Offset; delete[] Buffer; Buffer=Save_Buffer; Buffer_3Bytes=NULL; //Same as Buffer... Element_Offset+=ThreeByte_List.size(); } //Duplicate #if MEDIAINFO_DUPLICATE if (!Streams.empty() && Streams[(size_t)Element_Code].ShouldDuplicate) File__Duplicate_Write(Element_Code); #endif //MEDIAINFO_DUPLICATE #if MEDIAINFO_DEMUX Data_Parse_Iso14496(); #endif //MEDIAINFO_DEMUX //Dump of the SPS/PPS - Fill #if MEDIAINFO_ADVANCED2 if (false) //TODO: add an option for activating this extra piece of information in the output { switch (Element_Code) { case 0x07 : //seq_parameter_set(); if (spspps_Size != seq_parameter_sets.size() && !Status[IsFilled]) { std::string Data_Raw((const char*)(Buffer+(size_t)(Buffer_Offset-1)), (size_t)(Element_Size+1)); //Including the last byte in the header Dump_SPS.push_back(Base64::encode(Data_Raw)); } break; case 0x08 : //pic_parameter_set(); if (spspps_Size != pic_parameter_sets.size() && !Status[IsFilled]) { std::string Data_Raw((const char*)(Buffer+(size_t)(Buffer_Offset-1)), (size_t)(Element_Size+1)); //Including the last byte in the header Dump_PPS.push_back(Base64::encode(Data_Raw)); } break; default: ; } } #endif //MEDIAINFO_ADVANCED2 #if MEDIAINFO_DEMUX Data_Parse_Iso14496(); #endif //MEDIAINFO_DEMUX //Trailing zeroes Element_Size=Element_Size_SaveBeforeZeroes; } //*************************************************************************** // Elements //*************************************************************************** //--------------------------------------------------------------------------- // Packet "01" void File_Avc::slice_layer_without_partitioning_non_IDR() { Element_Name("slice_layer_without_partitioning (non-IDR)"); //Parsing BS_Begin(); slice_header(); slice_data(true); BS_End(); } //--------------------------------------------------------------------------- // Packet "05" void File_Avc::slice_layer_without_partitioning_IDR() { Element_Name("slice_layer_without_partitioning (IDR)"); //Parsing BS_Begin(); slice_header(); slice_data(true); BS_End(); FILLING_BEGIN_PRECISE(); //NextCode for (int8u Pos=0x01; Pos<=0x05; Pos++) NextCode_Add(Pos); FILLING_END(); } //--------------------------------------------------------------------------- // void File_Avc::slice_header() { //Encryption management if (CA_system_ID_MustSkipSlices) { //Is not decodable Skip_BS(Data_BS_Remain(), "Data"); Finish("AVC"); return; } Element_Begin1("slice_header"); //Parsing int32u slice_type, pic_order_cnt_lsb=(int32u)-1; int32u first_mb_in_slice, pic_parameter_set_id, frame_num, num_ref_idx_l0_active_minus1, num_ref_idx_l1_active_minus1, disable_deblocking_filter_idc; int32s delta_pic_order_cnt_bottom=0; bool field_pic_flag=false, bottom_field_flag=false; Get_UE (first_mb_in_slice, "first_mb_in_slice"); Get_UE (slice_type, "slice_type"); Param_Info1C((slice_type<10), Avc_slice_type[slice_type]); #if MEDIAINFO_EVENTS if (!first_mb_in_slice) { switch(Element_Code) { case 5 : // This is an IDR frame if (Config->Config_PerPackage) // First slice of an IDR frame { // IDR Config->Config_PerPackage->FrameForAlignment(this, true); Config->Config_PerPackage->IsClosedGOP(this); } break; default : ; // This is not an IDR frame } EVENT_BEGIN (Video, SliceInfo, 0) Event.FieldPosition=Field_Count; Event.SlicePosition=Element_IsOK()?first_mb_in_slice:(int64u)-1; switch (slice_type) { case 0 : case 3 : case 5 : case 8 : Event.SliceType=1; break; case 1 : case 6 : Event.SliceType=2; break; case 2 : case 4 : case 7 : case 9 : Event.SliceType=0; break; default: Event.SliceType=(int8u)-1; } Event.Flags=0; EVENT_END () } #endif //MEDIAINFO_EVENTS if (slice_type>=10) { Skip_BS(Data_BS_Remain(), "Data"); Element_End0(); return; } Get_UE (pic_parameter_set_id, "pic_parameter_set_id"); std::vector::iterator pic_parameter_set_Item; if (pic_parameter_set_id>=pic_parameter_sets.size() || (*(pic_parameter_set_Item=pic_parameter_sets.begin()+pic_parameter_set_id))==NULL) { //Not yet present Skip_BS(Data_BS_Remain(), "Data (pic_parameter_set is missing)"); Element_End0(); return; } std::vector::iterator seq_parameter_set_Item; if ((*pic_parameter_set_Item)->seq_parameter_set_id>=seq_parameter_sets.size() || (*(seq_parameter_set_Item=seq_parameter_sets.begin()+(*pic_parameter_set_Item)->seq_parameter_set_id))==NULL) { if ((*pic_parameter_set_Item)->seq_parameter_set_id>=subset_seq_parameter_sets.size() || (*(seq_parameter_set_Item=subset_seq_parameter_sets.begin()+(*pic_parameter_set_Item)->seq_parameter_set_id))==NULL) { //Not yet present Skip_BS(Data_BS_Remain(), "Data (seq_parameter_set is missing)"); Element_End0(); return; } } if ((*seq_parameter_set_Item)->separate_colour_plane_flag==1) Skip_S1(2, "color_plane_id"); num_ref_idx_l0_active_minus1=(*pic_parameter_set_Item)->num_ref_idx_l0_default_active_minus1; //Default num_ref_idx_l1_active_minus1=(*pic_parameter_set_Item)->num_ref_idx_l1_default_active_minus1; //Default Get_BS ((*seq_parameter_set_Item)->log2_max_frame_num_minus4+4, frame_num, "frame_num"); if (!(*seq_parameter_set_Item)->frame_mbs_only_flag) { TEST_SB_GET(field_pic_flag, "field_pic_flag"); Get_SB (bottom_field_flag, "bottom_field_flag"); TEST_SB_END(); } if (Element_Code==5) //IdrPicFlag Skip_UE( "idr_pic_id"); if ((*seq_parameter_set_Item)->pic_order_cnt_type==0) { Get_BS ((*seq_parameter_set_Item)->log2_max_pic_order_cnt_lsb_minus4+4, pic_order_cnt_lsb, "pic_order_cnt_lsb"); if ((*pic_parameter_set_Item)->bottom_field_pic_order_in_frame_present_flag && !field_pic_flag) Get_SE (delta_pic_order_cnt_bottom, "delta_pic_order_cnt_bottom"); } if ((*seq_parameter_set_Item)->pic_order_cnt_type==1 && !(*seq_parameter_set_Item)->delta_pic_order_always_zero_flag ) { Skip_SE( "delta_pic_order_cnt[0]"); if((*pic_parameter_set_Item)->bottom_field_pic_order_in_frame_present_flag && !field_pic_flag) Skip_SE( "delta_pic_order_cnt[1]"); } if((*pic_parameter_set_Item)->redundant_pic_cnt_present_flag) Skip_UE( "redundant_pic_cnt"); if (slice_type==1 || slice_type==6) //B-Frame Skip_SB( "direct_spatial_mv_pred_flag"); switch (slice_type) { case 0 : //P-Frame case 1 : //B-Frame case 3 : //SP-Frame case 5 : //P-Frame case 6 : //B-Frame case 8 : //SP-Frame TEST_SB_SKIP( "num_ref_idx_active_override_flag"); Get_UE (num_ref_idx_l0_active_minus1, "num_ref_idx_l0_active_minus1"); switch (slice_type) { case 1 : //B-Frame case 6 : //B-Frame Get_UE (num_ref_idx_l1_active_minus1, "num_ref_idx_l1_active_minus1"); break; default: ; } TEST_SB_END(); break; default: ; } ref_pic_list_modification(slice_type, Element_Code==20); //nal_unit_type==20 --> ref_pic_list_mvc_modification() if (((*pic_parameter_set_Item)->weighted_pred_flag && (slice_type==0 || slice_type==3 || slice_type==5 || slice_type==8)) || ((*pic_parameter_set_Item)->weighted_bipred_idc==1 && (slice_type==1 || slice_type==6))) pred_weight_table(slice_type, num_ref_idx_l0_active_minus1, num_ref_idx_l1_active_minus1, (*seq_parameter_set_Item)->ChromaArrayType()); std::vector memory_management_control_operations; if (nal_ref_idc) dec_ref_pic_marking(memory_management_control_operations); if ((*pic_parameter_set_Item)->entropy_coding_mode_flag && (slice_type!=2 && slice_type!=7 && //I-Frames slice_type!=4 && slice_type!=9)) //SI-Frames Skip_UE( "cabac_init_idc"); Skip_SE( "slice_qp_delta"); switch (slice_type) { case 3 : //SP-Frame case 4 : //SI-Frame case 8 : //SP-Frame case 9 : //SI-Frame switch (slice_type) { case 3 : //SP-Frame case 8 : //SP-Frame Skip_SB( "sp_for_switch_flag"); break; default: ; } Skip_SE ( "slice_qs_delta"); break; default: ; } if ((*pic_parameter_set_Item)->deblocking_filter_control_present_flag) { Get_UE(disable_deblocking_filter_idc, "disable_deblocking_filter_idc"); if (disable_deblocking_filter_idc!=1) { Skip_SE( "slice_alpha_c0_offset_div2"); Skip_SE( "slice_beta_offset_div2"); } } Element_End0(); FILLING_BEGIN(); //Count of I-Frames if (first_mb_in_slice==0 && Element_Code!=20 && (slice_type==2 || slice_type==7)) //Not slice_layer_extension, I-Frame IFrame_Count++; if (!first_mb_in_slice && Slices_CountInThisFrame) { if (MaxSlicesCountpic_struct_FirstDetected==(int8u)-1) (*seq_parameter_set_Item)->pic_struct_FirstDetected=bottom_field_flag?2:1; //2=BFF, 1=TFF //Saving some info if ((*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->timing_info_present_flag && (*seq_parameter_set_Item)->vui_parameters->num_units_in_tick) tc=float64_int64s(((float64)1000000000)/((float64)(*seq_parameter_set_Item)->vui_parameters->time_scale/(*seq_parameter_set_Item)->vui_parameters->num_units_in_tick/((*seq_parameter_set_Item)->pic_order_cnt_type==2?1:2)/FrameRate_Divider)/((!(*seq_parameter_set_Item)->frame_mbs_only_flag && field_pic_flag)?2:1)); int32s TemporalReferences_Offset_pic_order_cnt_lsb_Diff=0; if ((*seq_parameter_set_Item)->pic_order_cnt_type!=1 && first_mb_in_slice==0 && (Element_Code!=0x14 || seq_parameter_sets.empty()) && TemporalReferences_Reserved) //Not slice_layer_extension except if MVC only { if (field_pic_flag) { Structure_Field++; if (bottom_field_flag) Interlaced_Bottom++; else Interlaced_Top++; } else Structure_Frame++; //Frame order detection int64s pic_order_cnt=0; switch ((*seq_parameter_set_Item)->pic_order_cnt_type) { case 0 : { if (Element_Code==5) //IDR { prevPicOrderCntMsb=0; prevPicOrderCntLsb=0; TemporalReferences_Offset=TemporalReferences_Max; if (TemporalReferences_Offset%2) TemporalReferences_Offset++; TemporalReferences_pic_order_cnt_Min=0; } else { const bool Has5 = std::find(memory_management_control_operations.begin(), memory_management_control_operations.end(), 5) != memory_management_control_operations.end(); if (Has5) { prevPicOrderCntMsb=0; if (bottom_field_flag) prevPicOrderCntLsb=0; else prevPicOrderCntLsb=prevTopFieldOrderCnt; } } int32s PicOrderCntMsb; if (prevPicOrderCntLsb==(int32u)-1) { PicOrderCntMsb=0; if ((int32u)(2*((*seq_parameter_set_Item)->max_num_ref_frames+3))max_num_ref_frames+3); } else if (pic_order_cnt_lsb=(*seq_parameter_set_Item)->MaxPicOrderCntLsb/2) PicOrderCntMsb=prevPicOrderCntMsb+(*seq_parameter_set_Item)->MaxPicOrderCntLsb; else if (pic_order_cnt_lsb>prevPicOrderCntLsb && pic_order_cnt_lsb-prevPicOrderCntLsb>(*seq_parameter_set_Item)->MaxPicOrderCntLsb/2) PicOrderCntMsb=prevPicOrderCntMsb-(*seq_parameter_set_Item)->MaxPicOrderCntLsb; else PicOrderCntMsb=prevPicOrderCntMsb; int32s TopFieldOrderCnt=PicOrderCntMsb+pic_order_cnt_lsb; int32s BottomFieldOrderCnt; if (field_pic_flag) BottomFieldOrderCnt=TopFieldOrderCnt+delta_pic_order_cnt_bottom; else BottomFieldOrderCnt=PicOrderCntMsb+pic_order_cnt_lsb; prevPicOrderCntMsb=PicOrderCntMsb; prevPicOrderCntLsb=pic_order_cnt_lsb; prevTopFieldOrderCnt=TopFieldOrderCnt; pic_order_cnt=bottom_field_flag?BottomFieldOrderCnt:TopFieldOrderCnt; } break; case 2 : { const bool Has5 = std::find(memory_management_control_operations.begin(), memory_management_control_operations.end(),5) != memory_management_control_operations.end(); if (Has5) prevFrameNumOffset=0; int32u FrameNumOffset; if (Element_Code==5) //IdrPicFlag { TemporalReferences_Offset=TemporalReferences_Max; if (TemporalReferences_Offset%2) TemporalReferences_Offset++; FrameNumOffset=0; } else if (prevFrameNumOffset==(int32u)-1) FrameNumOffset=0; else if (prevFrameNum>frame_num) FrameNumOffset=prevFrameNumOffset+(*seq_parameter_set_Item)->MaxFrameNum; else FrameNumOffset=prevFrameNumOffset; int32u tempPicOrderCnt; if (Element_Code==5) //IdrPicFlag tempPicOrderCnt=0; else { tempPicOrderCnt=2*(FrameNumOffset+frame_num); if (!nal_ref_idc && tempPicOrderCnt) //Note: if nal_ref_idc is 0, tempPicOrderCnt is not expected to be 0 but it may be the case with invalid streams tempPicOrderCnt--; } pic_order_cnt=tempPicOrderCnt; prevFrameNum=frame_num; prevFrameNumOffset=FrameNumOffset; pic_order_cnt_lsb=frame_num; } break; default: ; } if (TemporalReferences_pic_order_cnt_Min==numeric_limits::max()) TemporalReferences_pic_order_cnt_Min=pic_order_cnt; if (pic_order_cnt=4*TemporalReferences_Reserved || Base>=4*TemporalReferences_Reserved || ToInsert+TemporalReferences_Max>=4*TemporalReferences_Reserved || TemporalReferences_Max>=4*TemporalReferences_Reserved || TemporalReferences_Max-Base>=4*TemporalReferences_Reserved) { Trusted_IsNot("Problem in temporal references"); return; } Element_Info1(__T("Offset of ")+Ztring::ToZtring(ToInsert)); TemporalReferences.insert(TemporalReferences.begin()+Base, ToInsert, NULL); TemporalReferences_Offset+=ToInsert; TemporalReferences_Offset_pic_order_cnt_lsb_Last += ToInsert; TemporalReferences_Max+=ToInsert; TemporalReferences_pic_order_cnt_Min=pic_order_cnt; } else if (TemporalReferences_Min>(size_t)(TemporalReferences_Offset+pic_order_cnt)) TemporalReferences_Min=(size_t)(TemporalReferences_Offset+pic_order_cnt); } if (pic_order_cnt<0 && TemporalReferences_Offset<(size_t)(-pic_order_cnt)) //Found in playreadyEncryptedBlowUp.ts without encryption test { Trusted_IsNot("Problem in temporal references"); return; } if ((size_t)(TemporalReferences_Offset+pic_order_cnt)>=3*TemporalReferences_Reserved) { size_t Offset=TemporalReferences_Max-TemporalReferences_Offset; if (Offset%2) Offset++; if (Offset>=TemporalReferences_Reserved && pic_order_cnt>=(int64s)TemporalReferences_Reserved) { TemporalReferences_Offset+=TemporalReferences_Reserved; pic_order_cnt-=TemporalReferences_Reserved; TemporalReferences_pic_order_cnt_Min-=TemporalReferences_Reserved/2; switch ((*seq_parameter_set_Item)->pic_order_cnt_type) { case 0 : prevPicOrderCntMsb-=(int32u)TemporalReferences_Reserved; break; case 2 : prevFrameNumOffset-=(int32u)TemporalReferences_Reserved/2; break; default:; } } while (TemporalReferences_Offset+pic_order_cnt>=3*TemporalReferences_Reserved) { for (size_t Pos=0; Posslice_type]; delete TemporalReferences[Pos]; TemporalReferences[Pos] = NULL; } else if (!PictureTypes_PreviousFrames.empty()) //Only if stream already started { if ((Pos%2)==0) PictureTypes_PreviousFrames+=' '; } } if (PictureTypes_PreviousFrames.size()>=8*TemporalReferences.size()) PictureTypes_PreviousFrames.erase(PictureTypes_PreviousFrames.begin(), PictureTypes_PreviousFrames.begin()+PictureTypes_PreviousFrames.size()-TemporalReferences.size()); TemporalReferences.erase(TemporalReferences.begin(), TemporalReferences.begin()+TemporalReferences_Reserved); TemporalReferences.resize(4*TemporalReferences_Reserved); if (TemporalReferences_Reservedpic_order_cnt_type==2 && TemporalReferences_Offset_pic_order_cnt_lsb_Lastframe_mbs_only_flag?2:1); if (TemporalReferences_Min>TemporalReferences_Offset_pic_order_cnt_lsb_Last) TemporalReferences_Min=TemporalReferences_Offset_pic_order_cnt_lsb_Last; if (TemporalReferences_DelayedElement) { delete TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]; TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]=TemporalReferences_DelayedElement; } if (TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]==NULL) TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]=new temporal_reference(); TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]->frame_num=frame_num; TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]->slice_type=(int8u)slice_type; TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]->IsTop=!bottom_field_flag; TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]->IsField=field_pic_flag; if (TemporalReferences_DelayedElement) { TemporalReferences_DelayedElement=NULL; sei_message_user_data_registered_itu_t_t35_GA94_03_Delayed((*pic_parameter_set_Item)->seq_parameter_set_id); } if (first_mb_in_slice==0) { if (Frame_Count==0) { if (FrameInfo.PTS==(int64u)-1) FrameInfo.PTS=FrameInfo.DTS; PTS_Begin=FrameInfo.PTS; PTS_End=FrameInfo.PTS; } if (IFrame_Count<=1 && TC_Current.IsSet()) { TimeCode TC_Previous(Retrieve_Const(Stream_Video, 0, Video_TimeCode_FirstFrame).To_UTF8(), TC_Current.GetFramesMax()); if (!TC_Previous.IsSet() || TC_Currentpic_order_cnt_type != 1 && (Element_Code != 0x14 || seq_parameter_sets.empty())) //Not slice_layer_extension except if MVC only { if ((!IsSub || Frame_Count_InThisBlock)) { if (!pic_order_cnt_lsb || pic_order_cnt_Displayed==numeric_limits::max()) { pic_order_cnt_Displayed=pic_order_cnt+pic_order_cnt_Delta; pic_order_cnt_Delta=0; FrameInfo.PTS=PTS_End; } int64s Divisor=field_pic_flag?1:(((*seq_parameter_set_Item)->frame_mbs_only_flag?2:(((*seq_parameter_set_Item)->pic_order_cnt_type==2)?1:2))); if (pic_order_cnt_Displayed!=numeric_limits::max()) { int64s MissingFieldCount=pic_order_cnt-pic_order_cnt_Displayed; if (MissingFieldCount<0) { pic_order_cnt_Delta=MissingFieldCount; FrameInfo.PTS=FrameInfo.DTS; pic_order_cnt_Displayed=pic_order_cnt; if (IFrame_Count<=1) { int64s Temp=MissingFieldCount; Temp*=tc; Temp/=Divisor; PTS_Begin-=Temp; } } else { int64s Offset=MissingFieldCount*tc; Offset/=Divisor; FrameInfo.PTS=FrameInfo.DTS+Offset; } } pic_order_cnt_Displayed+=Divisor; } } } } if (first_mb_in_slice==0) { #if MEDIAINFO_ADVANCED2 if (PTS_Begin_Segment==(int64u)-1 && File_Offset>=Config->File_Current_Offset) { PTS_Begin_Segment=FrameInfo.PTS; } #endif //MEDIAINFO_ADVANCED2 if (slice_type==2 || slice_type==7) //IFrame FirstPFrameInGop_IsParsed=false; } else { if (FrameInfo.PTS!=(int64u)-1) FrameInfo.PTS-=tc; if (FrameInfo.DTS!=(int64u)-1) FrameInfo.DTS-=tc; } //Frame pos if (Frame_Count!=(int64u)-1 && Frame_Count && ((!(*seq_parameter_set_Item)->frame_mbs_only_flag && Interlaced_Top==Interlaced_Bottom && field_pic_flag) || first_mb_in_slice!=0 || (Element_Code==0x14 && !seq_parameter_sets.empty()))) { Frame_Count--; if (IFrame_Count && Frame_Count_NotParsedIncluded!=(int64u)-1) Frame_Count_NotParsedIncluded--; Frame_Count_InThisBlock--; } else if (first_mb_in_slice==0) { if (!FirstPFrameInGop_IsParsed && (slice_type==0 || slice_type==5)) //P-Frame { FirstPFrameInGop_IsParsed=true; //Testing if we have enough to test GOP if (Frame_Count<=Frame_Count_Valid) { std::string PictureTypes(PictureTypes_PreviousFrames); PictureTypes.reserve(TemporalReferences.size()); for (size_t Pos=0; Posslice_type]; } else if (!PictureTypes.empty()) //Only if stream already started { if ((Pos%2)==0) PictureTypes+=' '; } #if defined(MEDIAINFO_DTVCCTRANSPORT_YES) if (!GOP_Detect(PictureTypes).empty() && !GA94_03_IsPresent) Frame_Count_Valid=Frame_Count; //We have enough frames #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES) } } } #if MEDIAINFO_TRACE if (Trace_Activated) { Element_Info1(TemporalReferences_Offset_pic_order_cnt_lsb_Last); Element_Info1((((*seq_parameter_set_Item)->frame_mbs_only_flag || !field_pic_flag)?__T("Frame "):(bottom_field_flag?__T("Field (Bottom) "):__T("Field (Top) ")))+Ztring::ToZtring(Frame_Count)); if (slice_type<9) Element_Info1(__T("slice_type ")+Ztring().From_UTF8(Avc_slice_type[slice_type])); Element_Info1(__T("frame_num ")+Ztring::ToZtring(frame_num)); if ((*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->fixed_frame_rate_flag) { if (FrameInfo.PCR!=(int64u)-1) Element_Info1(__T("PCR ")+Ztring().Duration_From_Milliseconds(float64_int64s(((float64)FrameInfo.PCR)/1000000))); if (FrameInfo.DTS!=(int64u)-1) Element_Info1(__T("DTS ")+Ztring().Duration_From_Milliseconds(float64_int64s(((float64)FrameInfo.DTS)/1000000))); if (FrameInfo.PTS!=(int64u)-1) Element_Info1(__T("PTS ")+Ztring().Duration_From_Milliseconds(float64_int64s(((float64)FrameInfo.PTS)/1000000))); } if ((*seq_parameter_set_Item)->pic_order_cnt_type==0) Element_Info1(__T("pic_order_cnt_lsb ")+Ztring::ToZtring(pic_order_cnt_lsb)); if (first_mb_in_slice) Element_Info1(__T("first_mb_in_slice ")+Ztring::ToZtring(first_mb_in_slice)); } #endif //MEDIAINFO_TRACE //Counting if (Frame_Count!=(int64u)-1) { if (File_Offset+Buffer_Offset+Element_Size==File_Size) Frame_Count_Valid=Frame_Count; //Finish frames in case of there are less than Frame_Count_Valid frames Frame_Count++; if (IFrame_Count && Frame_Count_NotParsedIncluded!=(int64u)-1) Frame_Count_NotParsedIncluded++; Frame_Count_InThisBlock++; } if ((*seq_parameter_set_Item)->pic_order_cnt_type==0 && field_pic_flag) { Field_Count++; Field_Count_InThisBlock++; } if (FrameInfo.PTS!=(int64u)-1) FrameInfo.PTS+=tc; if (FrameInfo.DTS!=(int64u)-1) FrameInfo.DTS+=tc; if (FrameInfo.PTS!=(int64u)-1 && (FrameInfo.PTS>PTS_End || (PTS_End>1000000000 && FrameInfo.PTS<=PTS_End-1000000000))) //More than current PTS_End or less than current PTS_End minus 1 second (there is a problem?) PTS_End=FrameInfo.PTS; #if MEDIAINFO_DUPLICATE if (Streams[(size_t)Element_Code].ShouldDuplicate) File__Duplicate_Write(Element_Code, (*seq_parameter_set_Item)->pic_order_cnt_type==0?pic_order_cnt_lsb:frame_num); #endif //MEDIAINFO_DUPLICATE //Filling only if not already done if (Frame_Count==1 && !Status[IsAccepted]) Accept("AVC"); if (!Status[IsFilled]) { #if defined(MEDIAINFO_DTVCCTRANSPORT_YES) if (!GA94_03_IsPresent && IFrame_Count>=8) Frame_Count_Valid=Frame_Count; //We have enough frames #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES) if (Frame_Count>=Frame_Count_Valid) { Fill("AVC"); if (!IsSub && !Streams[(size_t)Element_Code].ShouldDuplicate && Config->ParseSpeed<1.0) Finish("AVC"); } if (FrameIsAlwaysComplete && !first_mb_in_slice && FrameSizes.size()<=1) FrameSizes[Buffer_Size]++; } FILLING_END(); } //--------------------------------------------------------------------------- // void File_Avc::slice_data(bool AllCategories) { Element_Begin1("slice_data"); Skip_BS(Data_BS_Remain(), "(ToDo)"); Element_End0(); } //--------------------------------------------------------------------------- // void File_Avc::ref_pic_list_modification(int32u slice_type, bool mvc) { if ((slice_type%5)!=2 && (slice_type%5)!=4) { TEST_SB_SKIP( "ref_pic_list_modification_flag_l0"); int32u modification_of_pic_nums_idc; do { Get_UE (modification_of_pic_nums_idc, "modification_of_pic_nums_idc"); if (modification_of_pic_nums_idc<2) Skip_UE( "abs_diff_pic_num_minus1"); else if (modification_of_pic_nums_idc==2) Skip_UE( "long_term_pic_num"); else if (mvc && (modification_of_pic_nums_idc==4 || modification_of_pic_nums_idc==5)) //ref_pic_list_mvc_modification only Skip_UE( "abs_diff_view_idx_minus1"); else if (modification_of_pic_nums_idc!=3) { Trusted_IsNot("ref_pic_list_modification_flag_l0"); Skip_BS(Data_BS_Remain(), "(Remaining bits)"); } } while (modification_of_pic_nums_idc!=3 && Data_BS_Remain()); TEST_SB_END(); } if ((slice_type%5)==1) { TEST_SB_SKIP( "ref_pic_list_modification_flag_l1"); int32u modification_of_pic_nums_idc; do { Get_UE (modification_of_pic_nums_idc, "modification_of_pic_nums_idc"); if (modification_of_pic_nums_idc<2) Skip_UE( "abs_diff_pic_num_minus1"); else if (modification_of_pic_nums_idc==2) Skip_UE( "long_term_pic_num"); else if (mvc && (modification_of_pic_nums_idc==4 || modification_of_pic_nums_idc==5)) //ref_pic_list_mvc_modification only Skip_UE( "abs_diff_view_idx_minus1"); else if (modification_of_pic_nums_idc!=3) { Trusted_IsNot("ref_pic_list_modification_flag_l1"); Skip_BS(Data_BS_Remain(), "(Remaining bits)"); } } while (modification_of_pic_nums_idc!=3 && Data_BS_Remain()); TEST_SB_END(); } } //--------------------------------------------------------------------------- // void File_Avc::pred_weight_table(int32u slice_type, int32u num_ref_idx_l0_active_minus1, int32u num_ref_idx_l1_active_minus1, int8u ChromaArrayType) { // 7.3.3.2 Prediction weight table syntax Skip_UE( "luma_log2_weight_denom"); if (ChromaArrayType) Skip_UE( "chroma_log2_weight_denom"); for(int32u i=0; i<=num_ref_idx_l0_active_minus1; i++) { TEST_SB_SKIP( "luma_weight_l0_flag"); Skip_SE( "luma_weight_l0"); Skip_SE( "luma_offset_l0"); TEST_SB_END(); if (ChromaArrayType) { TEST_SB_SKIP( "chroma_weight_l0_flag"); Skip_SE( "chroma_weight_l0"); Skip_SE( "chroma_offset_l0"); Skip_SE( "chroma_weight_l0"); Skip_SE( "chroma_offset_l0"); TEST_SB_END(); } } if (slice_type % 5 == 1) { for (int32u i = 0; i <= num_ref_idx_l1_active_minus1; i++) { TEST_SB_SKIP("luma_weight_l1_flag"); Skip_SE("luma_weight_l1"); Skip_SE("luma_offset_l1"); TEST_SB_END(); if (ChromaArrayType) { TEST_SB_SKIP("chroma_weight_l1_flag"); Skip_SE("chroma_weight_l1"); Skip_SE("chroma_offset_l1"); Skip_SE("chroma_weight_l1"); Skip_SE("chroma_offset_l1"); TEST_SB_END(); } } } } //--------------------------------------------------------------------------- // void File_Avc::dec_ref_pic_marking(std::vector &memory_management_control_operations) { if (Element_Code==5) //IdrPicFlag { Skip_SB( "no_output_of_prior_pics_flag"); Skip_SB( "long_term_reference_flag"); } else { TEST_SB_SKIP( "adaptive_ref_pic_marking_mode_flag"); int32u memory_management_control_operation; do { Get_UE (memory_management_control_operation, "memory_management_control_operation"); switch (memory_management_control_operation) { case 1 : Skip_UE( "difference_of_pic_nums_minus1"); break; case 2 : Skip_UE( "long_term_pic_num"); break; case 3 : Skip_UE( "difference_of_pic_nums_minus1"); //break; 3 --> difference_of_pic_nums_minus1 then long_term_frame_idx case 6 : Skip_UE( "long_term_frame_idx"); break; case 4 : Skip_UE( "max_long_term_frame_idx_plus1"); break; } memory_management_control_operations.push_back((int8u)memory_management_control_operation); } while (Data_BS_Remain() && memory_management_control_operation); TEST_SB_END() } } //--------------------------------------------------------------------------- // Packet "06" void File_Avc::sei() { Element_Name("sei"); //Parsing int32u seq_parameter_set_id=(int32u)-1; while(Element_Offset+1Element_Size) { Trusted_IsNot("Wrong size"); Skip_XX(Element_Size-Element_Offset, "unknown"); return; } int64u Element_Size_Save=Element_Size; Element_Size=Element_Offset_Save; switch (payloadType) { case 0 : sei_message_buffering_period(seq_parameter_set_id); break; case 1 : sei_message_pic_timing(payloadSize, seq_parameter_set_id); break; case 4 : sei_message_user_data_registered_itu_t_t35(); break; case 5 : sei_message_user_data_unregistered(payloadSize); break; case 6 : sei_message_recovery_point(); break; case 32 : sei_message_mainconcept(payloadSize); break; case 147: sei_alternative_transfer_characteristics(); break; case 137: sei_message_mastering_display_colour_volume(); break; case 144: sei_message_light_level(); break; default : Element_Info1("unknown"); Skip_XX(payloadSize, "data"); } Element_Offset=Element_Offset_Save; //Positionning in the right place. Element_Size=Element_Size_Save; //Positionning in the right place. } //--------------------------------------------------------------------------- // SEI - 0 void File_Avc::sei_message_buffering_period(int32u &seq_parameter_set_id) { Element_Info1("buffering_period"); //Parsing if (Element_Offset==Element_Size) return; //Nothing to do BS_Begin(); Get_UE (seq_parameter_set_id, "seq_parameter_set_id"); std::vector::iterator seq_parameter_set_Item; if (seq_parameter_set_id>=seq_parameter_sets.size() || (*(seq_parameter_set_Item=seq_parameter_sets.begin()+seq_parameter_set_id))==NULL) { //Not yet present Skip_BS(Data_BS_Remain(), "Data (seq_parameter_set is missing)"); BS_End(); return; } if ((*seq_parameter_set_Item)->NalHrdBpPresentFlag()) sei_message_buffering_period_xxl((*seq_parameter_set_Item)->vui_parameters->NAL); if ((*seq_parameter_set_Item)->VclHrdBpPresentFlag()) sei_message_buffering_period_xxl((*seq_parameter_set_Item)->vui_parameters->VCL); BS_End(); } void File_Avc::sei_message_buffering_period_xxl(seq_parameter_set_struct::vui_parameters_struct::xxl* xxl) { if (xxl==NULL) return; for (int32u SchedSelIdx=0; SchedSelIdxSchedSel.size(); SchedSelIdx++) { //Get_S4 (xxl->initial_cpb_removal_delay_length_minus1+1, xxl->SchedSel[SchedSelIdx].initial_cpb_removal_delay, "initial_cpb_removal_delay"); Param_Info2(xxl->SchedSel[SchedSelIdx].initial_cpb_removal_delay/90, " ms"); //Get_S4 (xxl->initial_cpb_removal_delay_length_minus1+1, xxl->SchedSel[SchedSelIdx].initial_cpb_removal_delay_offset, "initial_cpb_removal_delay_offset"); Param_Info2(xxl->SchedSel[SchedSelIdx].initial_cpb_removal_delay_offset/90, " ms"); Info_S4 (xxl->initial_cpb_removal_delay_length_minus1+1, initial_cpb_removal_delay, "initial_cpb_removal_delay"); Param_Info2(initial_cpb_removal_delay/90, " ms"); Info_S4 (xxl->initial_cpb_removal_delay_length_minus1+1, initial_cpb_removal_delay_offset, "initial_cpb_removal_delay_offset"); Param_Info2(initial_cpb_removal_delay_offset/90, " ms"); } } //--------------------------------------------------------------------------- // SEI - 1 void File_Avc::sei_message_pic_timing(int32u /*payloadSize*/, int32u seq_parameter_set_id) { Element_Info1("pic_timing"); //Testing if we can parsing it now. TODO: handle case seq_parameter_set_id is unknown (buffering of message, decoding in slice parsing) if (seq_parameter_set_id==(int32u)-1 && seq_parameter_sets.size()==1) seq_parameter_set_id=0; std::vector::iterator seq_parameter_set_Item; if (seq_parameter_set_id>=seq_parameter_sets.size() || (*(seq_parameter_set_Item=seq_parameter_sets.begin()+seq_parameter_set_id))==NULL) { //Not yet present Skip_BS(Data_BS_Remain(), "Data (seq_parameter_set is missing)"); return; } //Parsing int8u pic_struct=(int8u)-1; BS_Begin(); if ((*seq_parameter_set_Item)->CpbDpbDelaysPresentFlag()) { int8u cpb_removal_delay_length_minus1=(*seq_parameter_set_Item)->vui_parameters->NAL?(*seq_parameter_set_Item)->vui_parameters->NAL->cpb_removal_delay_length_minus1:(*seq_parameter_set_Item)->vui_parameters->VCL->cpb_removal_delay_length_minus1; //Spec is not precise, I am not sure int8u dpb_output_delay_length_minus1=(*seq_parameter_set_Item)->vui_parameters->NAL?(*seq_parameter_set_Item)->vui_parameters->NAL->dpb_output_delay_length_minus1:(*seq_parameter_set_Item)->vui_parameters->VCL->dpb_output_delay_length_minus1; //Spec is not precise, I am not sure Skip_S4(cpb_removal_delay_length_minus1+1, "cpb_removal_delay"); Skip_S4(dpb_output_delay_length_minus1+1, "dpb_output_delay"); } if ((*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->pic_struct_present_flag) { Get_S1 (4, pic_struct, "pic_struct"); switch (pic_struct) { case 0 : case 1 : case 2 : case 3 : case 4 : case 5 : case 6 : FrameRate_Divider=1; break; case 7 : FrameRate_Divider=2; break; case 8 : FrameRate_Divider=3; break; default : Param_Info1("Reserved"); return; //NumClockTS is unknown } Param_Info1(Avc_pic_struct[pic_struct]); int8u NumClockTS=Avc_NumClockTS[pic_struct]; int8u seconds_value=0, minutes_value=0, hours_value=0; //Here because theses values can be reused in later ClockTSs. for (int8u i=0; iCpbDpbDelaysPresentFlag()) { int8u time_offset_length=(*seq_parameter_set_Item)->vui_parameters->NAL?(*seq_parameter_set_Item)->vui_parameters->NAL->time_offset_length:(*seq_parameter_set_Item)->vui_parameters->VCL->time_offset_length; //Spec is not precise, I am not sure if (time_offset_length) Get_S4 (time_offset_length, time_offset, "time_offset"); } FILLING_BEGIN(); if (!i && seconds_flag && minutes_flag && hours_flag && IFrame_Count<=1) { int32u FrameMax; if (counting_type>1 && counting_type!=4) { n_frames=0; FrameMax=0; //Unsupported type } else if ((*seq_parameter_set_Item)->vui_parameters->fixed_frame_rate_flag && (*seq_parameter_set_Item)->vui_parameters->timing_info_present_flag && (*seq_parameter_set_Item)->vui_parameters->time_scale && (*seq_parameter_set_Item)->vui_parameters->num_units_in_tick) FrameMax=(int32u)(float64_int64s((float64)(*seq_parameter_set_Item)->vui_parameters->time_scale/(*seq_parameter_set_Item)->vui_parameters->num_units_in_tick/((*seq_parameter_set_Item)->frame_mbs_only_flag?2:(((*seq_parameter_set_Item)->pic_order_cnt_type==2 && Structure_Frame/2>Structure_Field)?1:2))/FrameRate_Divider)-1); else if (n_frames>99) FrameMax=n_frames; else FrameMax=99; TC_Current=TimeCode(hours_value, minutes_value, seconds_value, n_frames, FrameMax, TimeCode::DropFrame(counting_type==4)); Element_Info1(TC_Current.ToString()); } FILLING_END(); TEST_SB_END(); Element_End0(); } } BS_End(); FILLING_BEGIN_PRECISE(); if ((*seq_parameter_set_Item)->pic_struct_FirstDetected==(int8u)-1 && (*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->pic_struct_present_flag) (*seq_parameter_set_Item)->pic_struct_FirstDetected=pic_struct; FILLING_END(); } //--------------------------------------------------------------------------- // SEI - 5 void File_Avc::sei_message_user_data_registered_itu_t_t35() { Element_Info1("user_data_registered_itu_t_t35"); //Parsing int8u itu_t_t35_country_code; Get_B1 (itu_t_t35_country_code, "itu_t_t35_country_code"); if (itu_t_t35_country_code==0xFF) Skip_B1( "itu_t_t35_country_code_extension_byte"); if (itu_t_t35_country_code!=0xB5 || Element_Offset+2>=Element_Size) { if (Element_Size-Element_Offset) Skip_XX(Element_Size-Element_Offset, "Unknown"); return; } //United-States int16u id; Get_B2 (id, "id?"); if (id!=0x0031 || Element_Offset+4>=Element_Size) { if (Element_Size-Element_Offset) Skip_XX(Element_Size-Element_Offset, "Unknown"); return; } int32u Identifier; Peek_B4(Identifier); switch (Identifier) { case 0x44544731 : sei_message_user_data_registered_itu_t_t35_DTG1(); return; case 0x47413934 : sei_message_user_data_registered_itu_t_t35_GA94(); return; default : if (Element_Size-Element_Offset) Skip_XX(Element_Size-Element_Offset, "Unknown"); } } //--------------------------------------------------------------------------- // SEI - 5 - DTG1 void File_Avc::sei_message_user_data_registered_itu_t_t35_DTG1() { Element_Info1("Active Format Description"); //Parsing Skip_C4( "afd_identifier"); if (Element_Offsetvui_parameters && seq_parameter_set_Item->vui_parameters->aspect_ratio_info_present_flag) { //TODO: avoid duplicated code int32u Width =(seq_parameter_set_Item->pic_width_in_mbs_minus1 +1)*16; int32u Height=(seq_parameter_set_Item->pic_height_in_map_units_minus1+1)*16*(2-seq_parameter_set_Item->frame_mbs_only_flag); int8u chromaArrayType = seq_parameter_set_Item->ChromaArrayType(); if (chromaArrayType >= 4) chromaArrayType = 0; int32u CropUnitX=Avc_SubWidthC [chromaArrayType]; int32u CropUnitY=Avc_SubHeightC[chromaArrayType]*(2-seq_parameter_set_Item->frame_mbs_only_flag); Width -=(seq_parameter_set_Item->frame_crop_left_offset+seq_parameter_set_Item->frame_crop_right_offset )*CropUnitX; Height-=(seq_parameter_set_Item->frame_crop_top_offset +seq_parameter_set_Item->frame_crop_bottom_offset)*CropUnitY; if (Height) { float64 PixelAspectRatio = 1; if (seq_parameter_set_Item->vui_parameters->aspect_ratio_idcvui_parameters->aspect_ratio_idc]; else if (seq_parameter_set_Item->vui_parameters->aspect_ratio_idc == 0xFF && seq_parameter_set_Item->vui_parameters->sar_height) PixelAspectRatio = ((float64) seq_parameter_set_Item->vui_parameters->sar_width) / seq_parameter_set_Item->vui_parameters->sar_height; auto DAR=Width*PixelAspectRatio/Height; if (DAR>=4.0/3.0*0.95 && DAR<4.0/3.0*1.05) DTG1_Parser.aspect_ratio_FromContainer=0; //4/3 if (DAR>=16.0/9.0*0.95 && DAR<16.0/9.0*1.05) DTG1_Parser.aspect_ratio_FromContainer=1; //16/9 } break; } } Open_Buffer_Init(&DTG1_Parser); DTG1_Parser.Format=File_AfdBarData::Format_A53_4_DTG1; Open_Buffer_Continue(&DTG1_Parser, Buffer+Buffer_Offset+(size_t)Element_Offset, Element_Size-Element_Offset); Merge(DTG1_Parser, Stream_Video, 0, 0); Element_Offset=Element_Size; } } //--------------------------------------------------------------------------- // SEI - 5 - GA94 void File_Avc::sei_message_user_data_registered_itu_t_t35_GA94() { //Parsing int8u user_data_type_code; Skip_B4( "GA94_identifier"); Get_B1 (user_data_type_code, "user_data_type_code"); switch (user_data_type_code) { case 0x03 : sei_message_user_data_registered_itu_t_t35_GA94_03(); break; case 0x06 : sei_message_user_data_registered_itu_t_t35_GA94_06(); break; default : Skip_XX(Element_Size-Element_Offset, "GA94_reserved_user_data"); } } //--------------------------------------------------------------------------- // SEI - 5 - GA94 - 0x03 void File_Avc::sei_message_user_data_registered_itu_t_t35_GA94_03() { #if defined(MEDIAINFO_DTVCCTRANSPORT_YES) GA94_03_IsPresent=true; MustExtendParsingDuration=true; Buffer_TotalBytes_Fill_Max=(int64u)-1; //Disabling this feature for this format, this is done in the parser Element_Info1("DTVCC Transport"); //Coherency delete TemporalReferences_DelayedElement; TemporalReferences_DelayedElement=new temporal_reference(); TemporalReferences_DelayedElement->GA94_03=new buffer_data(Buffer+Buffer_Offset+(size_t)Element_Offset,(size_t)(Element_Size-Element_Offset)); //Parsing Skip_XX(Element_Size-Element_Offset, "CC data"); #else //defined(MEDIAINFO_DTVCCTRANSPORT_YES) Skip_XX(Element_Size-Element_Offset, "DTVCC Transport data"); #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES) } void File_Avc::sei_message_user_data_registered_itu_t_t35_GA94_03_Delayed(int32u seq_parameter_set_id) { // Skipping missing frames if (TemporalReferences_Max-TemporalReferences_Min>(size_t)(4*(seq_parameter_sets[seq_parameter_set_id]->max_num_ref_frames+3))) // max_num_ref_frames ref frame maximum { size_t TemporalReferences_Min_New=TemporalReferences_Max-4*(seq_parameter_sets[seq_parameter_set_id]->max_num_ref_frames+3); while (TemporalReferences_Min_New>TemporalReferences_Min && TemporalReferences[TemporalReferences_Min_New-1]) TemporalReferences_Min_New--; TemporalReferences_Min=TemporalReferences_Min_New; while (TemporalReferences[TemporalReferences_Min]==NULL) { TemporalReferences_Min++; if (TemporalReferences_Min>=TemporalReferences.size()) return; } } // Parsing captions while (TemporalReferences[TemporalReferences_Min] && TemporalReferences_Min+2*seq_parameter_sets[seq_parameter_set_id]->max_num_ref_framesFormat=File_DtvccTransport::Format_A53_4_GA94_03; } if (((File_DtvccTransport*)GA94_03_Parser)->AspectRatio==0) { float64 PixelAspectRatio=1; std::vector::iterator seq_parameter_set_Item=seq_parameter_sets.begin(); for (; seq_parameter_set_Item!=seq_parameter_sets.end(); ++seq_parameter_set_Item) if ((*seq_parameter_set_Item)) break; if (seq_parameter_set_Item!=seq_parameter_sets.end()) { if (((*seq_parameter_set_Item)->vui_parameters) && ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_info_present_flag)) { if ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_idcvui_parameters->aspect_ratio_idc]; else if ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_idc==0xFF && (*seq_parameter_set_Item)->vui_parameters->sar_height) PixelAspectRatio=((float64)(*seq_parameter_set_Item)->vui_parameters->sar_width)/(*seq_parameter_set_Item)->vui_parameters->sar_height; } const int32u Width =((*seq_parameter_set_Item)->pic_width_in_mbs_minus1 +1)*16; const int32u Height=((*seq_parameter_set_Item)->pic_height_in_map_units_minus1+1)*16*(2-(*seq_parameter_set_Item)->frame_mbs_only_flag); if(Height) ((File_DtvccTransport*)GA94_03_Parser)->AspectRatio=Width*PixelAspectRatio/Height; } } if (GA94_03_Parser->PTS_DTS_Needed) { GA94_03_Parser->FrameInfo.PCR=FrameInfo.PCR; GA94_03_Parser->FrameInfo.PTS=FrameInfo.PTS; GA94_03_Parser->FrameInfo.DTS=FrameInfo.DTS; } #if MEDIAINFO_DEMUX if (TemporalReferences[TemporalReferences_Min]->GA94_03) { int8u Demux_Level_Save=Demux_Level; Demux_Level=8; //Ancillary Demux(TemporalReferences[TemporalReferences_Min]->GA94_03->Data, TemporalReferences[TemporalReferences_Min]->GA94_03->Size, ContentType_MainStream); Demux_Level=Demux_Level_Save; } Element_Code=Element_Code_Old; #endif //MEDIAINFO_DEMUX if (TemporalReferences[TemporalReferences_Min]->GA94_03) { #if defined(MEDIAINFO_EIA608_YES) || defined(MEDIAINFO_EIA708_YES) GA94_03_Parser->ServiceDescriptors=ServiceDescriptors; #endif Open_Buffer_Continue(GA94_03_Parser, TemporalReferences[TemporalReferences_Min]->GA94_03->Data, TemporalReferences[TemporalReferences_Min]->GA94_03->Size); } Element_End0(); #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES) TemporalReferences_Min+=((seq_parameter_sets[seq_parameter_set_id]->frame_mbs_only_flag | !TemporalReferences[TemporalReferences_Min]->IsField)?2:1); } } //--------------------------------------------------------------------------- // SEI - 5 - GA94 - 0x03 void File_Avc::sei_message_user_data_registered_itu_t_t35_GA94_06() { Element_Info1("Bar data"); //Parsing bool top_bar_flag, bottom_bar_flag, left_bar_flag, right_bar_flag; BS_Begin(); Get_SB (top_bar_flag, "top_bar_flag"); Get_SB (bottom_bar_flag, "bottom_bar_flag"); Get_SB (left_bar_flag, "left_bar_flag"); Get_SB (right_bar_flag, "right_bar_flag"); Mark_1_NoTrustError(); Mark_1_NoTrustError(); Mark_1_NoTrustError(); Mark_1_NoTrustError(); BS_End(); if (top_bar_flag) { Mark_1(); Mark_1(); Skip_S2(14, "line_number_end_of_top_bar"); } if (bottom_bar_flag) { Mark_1(); Mark_1(); Skip_S2(14, "line_number_start_of_bottom_bar"); } if (left_bar_flag) { Mark_1(); Mark_1(); Skip_S2(14, "pixel_number_end_of_left_bar"); } if (right_bar_flag) { Mark_1(); Mark_1(); Skip_S2(14, "pixel_number_start_of_right_bar"); } Mark_1(); Mark_1(); Mark_1(); Mark_1(); Mark_1(); Mark_1(); Mark_1(); Mark_1(); BS_End(); if (Element_Size-Element_Offset) Skip_XX(Element_Size-Element_Offset, "additional_bar_data"); } //--------------------------------------------------------------------------- // SEI - 5 void File_Avc::sei_message_user_data_unregistered(int32u payloadSize) { Element_Info1("user_data_unregistered"); //Parsing int128u uuid_iso_iec_11578; Get_UUID(uuid_iso_iec_11578, "uuid_iso_iec_11578"); switch (uuid_iso_iec_11578.hi) { case 0xDC45E9BDE6D948B7LL : Element_Info1("x264"); sei_message_user_data_unregistered_x264(payloadSize-16); break; case 0xFB574A60AC924E68LL : Element_Info1("eavc"); sei_message_user_data_unregistered_x264(payloadSize-16); break; case 0x17EE8C60F84D11D9LL : Element_Info1("Blu-ray"); sei_message_user_data_unregistered_bluray(payloadSize-16); break; default : Element_Info1("unknown"); Skip_XX(payloadSize-16, "data"); } } //--------------------------------------------------------------------------- // SEI - 5 - x264 void File_Avc::sei_message_user_data_unregistered_x264(int32u payloadSize) { //Parsing string Data; Peek_String(payloadSize, Data); if (Data.size()!=payloadSize && Data.size()+1!=payloadSize) { Skip_XX(payloadSize, "Unknown"); return; //This is not a text string } size_t Data_Pos_Before=0; size_t Loop=0; do { size_t Data_Pos=Data.find(" - ", Data_Pos_Before); if (Data_Pos==std::string::npos) Data_Pos=Data.size(); if (Data.find("options: ", Data_Pos_Before)==Data_Pos_Before) { Element_Begin1("options"); size_t Options_Pos_Before=Data_Pos_Before; Encoded_Library_Settings.clear(); do { size_t Options_Pos=Data.find(__T(' '), Options_Pos_Before); if (Options_Pos==std::string::npos) Options_Pos=Data.size(); string option; Get_String (Options_Pos-Options_Pos_Before, option, "option"); Options_Pos_Before=Options_Pos; do { string Separator; Peek_String(1, Separator); if (Separator==" ") { Skip_UTF8(1, "separator"); Options_Pos_Before+=1; } else break; } while (Options_Pos_Before!=Data.size()); //Filling if (option!="options:") { if (!Encoded_Library_Settings.empty()) Encoded_Library_Settings+=__T(" / "); Encoded_Library_Settings+=Ztring().From_UTF8(option.c_str()); if (option.find("bitrate=")==0) BitRate_Nominal.From_UTF8(option.substr(8)+"000"); //After "bitrate=" } } while (Options_Pos_Before!=Data.size()); Element_End0(); } else { string Value; Get_String(Data_Pos-Data_Pos_Before, Value, "data"); //Saving if (Loop==0) { //Cleaning a little the value while (!Value.empty() && Value[0]<0x30) Value.erase(Value.begin()); while (!Value.empty() && Value[Value.size()-1]<0x30) Value.erase(Value.end()-1); Encoded_Library.From_UTF8(Value.c_str()); } if (Loop==1 && Encoded_Library.find(__T("x264"))==0) { Encoded_Library+=__T(" - "); Encoded_Library+=Ztring().From_UTF8(Value.c_str()); } } Data_Pos_Before=Data_Pos; if (Data_Pos_Before+3<=Data.size()) { Skip_UTF8(3, "separator"); Data_Pos_Before+=3; } Loop++; } while (Data_Pos_Before!=Data.size()); //Encoded_Library if (Encoded_Library.find(__T("eavc "))==0) { Encoded_Library_Name=__T("eavc"); Encoded_Library_Version=Encoded_Library.SubString(__T("eavc "), __T("")); } else if (Encoded_Library.find(__T("x264 - "))==0) { Encoded_Library_Name=__T("x264"); Encoded_Library_Version=Encoded_Library.SubString(__T("x264 - "), __T("")); } else if (Encoded_Library.find(__T("SUPER(C) by eRightSoft "))==0) { Encoded_Library_Name=__T("SUPER(C) by eRightSoft"); Encoded_Library_Date=Encoded_Library.SubString(__T("2000-"), __T(" ")); } else Encoded_Library_Name=Encoded_Library; } //--------------------------------------------------------------------------- // SEI - 5 - x264 void File_Avc::sei_message_user_data_unregistered_bluray(int32u payloadSize) { if (payloadSize<4) { Skip_XX(payloadSize, "Unknown"); return; } int32u Identifier; Get_B4 (Identifier, "Identifier"); switch (Identifier) { case 0x47413934 : sei_message_user_data_registered_itu_t_t35_GA94_03(); return; case 0x4D44504D : sei_message_user_data_unregistered_bluray_MDPM(Element_Size-Element_Offset); return; default : Skip_XX(Element_Size-Element_Offset, "Unknown"); } } //--------------------------------------------------------------------------- // SEI - 5 - bluray - MDPM void File_Avc::sei_message_user_data_unregistered_bluray_MDPM(int32u payloadSize) { if (payloadSize<1) { Skip_XX(payloadSize, "Unknown"); return; } Element_Info1("Modified Digital Video Pack Metadata"); Skip_B1( "Count"); payloadSize--; string DateTime0, DateTime1, DateTime2, Model0, Model1, Model2; int16u MakeName=(int16u)-1; Ztring IrisFNumber; while (payloadSize >= 5) { Element_Begin0(); int8u ID; Get_B1(ID, "ID"); Element_Name(MDPM(ID)); switch (ID) { case 0x18: { int16u Year; int8u MM, Zone_Hours; bool Zone_Sign, Zone_Minutes; BS_Begin(); Mark_0(); Skip_SB( "DST flag"); Get_SB (Zone_Sign, "Time zone sign"); Get_S1 (4, Zone_Hours, "Time zone hours"); Get_SB (Zone_Minutes, "Time zone half-hour flag"); BS_End(); Get_B2 (Year, "Year"); Get_B1 (MM, "Month"); DateTime0+='0'+(Year>>12); DateTime0+='0'+((Year&0xF00)>>8); DateTime0+='0'+((Year&0xF0)>>4); DateTime0+='0'+(Year&0xF); DateTime0+='-'; DateTime0+='0'+((MM&0xF0)>>4); DateTime0+='0'+(MM&0xF); DateTime0+='-'; Element_Info1(DateTime0); DateTime2+=Zone_Sign?'-':'+'; DateTime2+='0'+Zone_Hours/10; DateTime2+='0'+Zone_Hours%10; DateTime2+=':'; DateTime2+=Zone_Minutes?'3':'0'; DateTime2+='0'; Element_Info1(DateTime2); } break; case 0x19: { int8u DD, hh, mm, ss; Get_B1 (DD, "Day"); Get_B1 (hh, "Hour"); Get_B1 (mm, "Minute"); Get_B1 (ss, "Second"); DateTime1+='0'+(DD>>4); DateTime1+='0'+(DD&0xF); DateTime1+=' '; DateTime1+='0'+(hh>>4); DateTime1+='0'+(hh&0xF); DateTime1+=':'; DateTime1+='0'+(mm>>4); DateTime1+='0'+(mm&0xF); DateTime1+=':'; DateTime1+='0'+(ss>>4); DateTime1+='0'+(ss&0xF); Element_Info1(DateTime1); } break; case 0x70: consumer_camera_1(); break; case 0x71: consumer_camera_2(); break; case 0xA1: { int16u D, N; Get_B2 (D, "D"); Get_B2 (N, "N"); IrisFNumber.From_Number(((float64)D)/N, 6); Element_Info1(IrisFNumber); } break; case 0xE0: { Get_B2 (MakeName, "Name"); Skip_B2( "Category"); Element_Info1(MDPM_MakeName(MakeName)); } break; case 0xE4: Get_String(4, Model0, "Data"); Element_Info1(Model0); break; case 0xE5: Get_String(4, Model1, "Data"); Element_Info1(Model1); break; case 0xE6: Get_String(4, Model2, "Data"); Model2.erase(Model2.find_last_not_of('\0')+1); Element_Info1(Model2); break; default: Skip_B4("Data"); } Element_End0(); payloadSize -= 5; } if (payloadSize) Skip_XX(payloadSize, "Unknown"); FILLING_BEGIN(); if (!Frame_Count && !seq_parameter_sets.empty() && !pic_parameter_sets.empty()) { if (!DateTime0.empty() && !DateTime1.empty()) Fill(Stream_General, 0, General_Recorded_Date, DateTime0+DateTime1+DateTime2); if (MDPM_MakeName(MakeName)[0] || !Model0.empty()) { string Model; if (MDPM_MakeName(MakeName)[0]) { Model=MDPM_MakeName(MakeName); Fill(Stream_General, 0, General_Encoded_Application_CompanyName, Model); if (!Model0.empty()) Model+=' '; } Fill(Stream_General, 0, General_Encoded_Application, Model+Model0+Model1+Model2); Fill(Stream_General, 0, General_Encoded_Application_Name, Model0+Model1+Model2); } Fill(Stream_Video, 0, "IrisFNumber", IrisFNumber); } FILLING_END(); } //--------------------------------------------------------------------------- void File_Avc::consumer_camera_1() { //Parsing BS_Begin(); int8u ae_mode, wb_mode, white_balance, fcm; Mark_1_NoTrustError(); Mark_1_NoTrustError(); Skip_S1(6, "iris"); Get_S1 (4, ae_mode, "ae mode"); Param_Info1(Dv_consumer_camera_1_ae_mode[ae_mode]); Skip_S1(4, "agc(Automatic Gain Control)"); Get_S1 (3, wb_mode, "wb mode (white balance mode)"); Param_Info1(Dv_consumer_camera_1_wb_mode[wb_mode]); Get_S1 (5, white_balance, "white balance"); Param_Info1(Dv_consumer_camera_1_white_balance(white_balance)); Get_S1 (1, fcm, "fcm (Focus mode)"); Param_Info1(Dv_consumer_camera_1_fcm[fcm]); Skip_S1(7, "focus (focal point)"); BS_End(); /* TODO: need some tweaking FILLING_BEGIN(); if (!Frame_Count) { Ztring Settings; if (ae_mode<0x0F) Settings+=__T("ae mode=")+Ztring(Dv_consumer_camera_1_ae_mode[ae_mode])+__T(", "); if (wb_mode<0x08) Settings+=__T("wb mode=")+Ztring(Dv_consumer_camera_1_wb_mode[wb_mode])+__T(", "); if (wb_mode<0x1F) Settings+=__T("white balance=")+Ztring(Dv_consumer_camera_1_white_balance(white_balance))+__T(", "); Settings+=__T("fcm=")+Ztring(Dv_consumer_camera_1_fcm[fcm]); Fill(Stream_Video, 0, "Camera_Settings", Settings); } FILLING_END(); */ } //--------------------------------------------------------------------------- void File_Avc::consumer_camera_2() { //Parsing BS_Begin(); Mark_1_NoTrustError(); Mark_1_NoTrustError(); Skip_S1(1, "vpd"); Skip_S1(5, "vertical panning speed"); Skip_S1(1, "is"); Skip_S1(1, "hpd"); Skip_S1(6, "horizontal panning speed"); Skip_S1(8, "focal length"); Skip_S1(1, "zen"); Info_S1(3, zoom_U, "units of e-zoom"); Info_S1(4, zoom_D, "1/10 of e-zoom"); /*if (zoom_D!=0xF)*/ Param_Info1(__T("zoom=")+Ztring().From_Number(zoom_U+((float32)zoom_U)/10, 2)); BS_End(); } //--------------------------------------------------------------------------- void File_Avc::sei_message_mastering_display_colour_volume() { Element_Info1("mastering_display_colour_volume"); std::map& SmpteSt2086 = HDR[HdrFormat_SmpteSt2086]; Ztring& HDR_Format = SmpteSt2086[Video_HDR_Format]; if (HDR_Format.empty()) { HDR_Format = __T("SMPTE ST 2086"); SmpteSt2086[Video_HDR_Format_Compatibility] = "HDR10"; } Get_MasteringDisplayColorVolume(SmpteSt2086[Video_MasteringDisplay_ColorPrimaries], SmpteSt2086[Video_MasteringDisplay_Luminance]); } //--------------------------------------------------------------------------- void File_Avc::sei_message_light_level() { Element_Info1("light_level"); //Parsing Get_LightLevel(maximum_content_light_level, maximum_frame_average_light_level); } //--------------------------------------------------------------------------- // SEI - 6 void File_Avc::sei_message_recovery_point() { Element_Info1("recovery_point"); //Parsing BS_Begin(); Skip_UE( "recovery_frame_cnt"); Skip_SB( "exact_match_flag"); Skip_SB( "broken_link_flag"); Skip_S1(2, "changing_slice_group_idc"); BS_End(); } //--------------------------------------------------------------------------- // SEI - 32 void File_Avc::sei_message_mainconcept(int32u payloadSize) { Element_Info1("MainConcept text"); //Parsing string Text; Get_String(payloadSize, Text, "text"); if (Text.find("produced by MainConcept H.264/AVC Codec v")!=std::string::npos) { Encoded_Library=Ztring().From_UTF8(Text).SubString(__T("produced by "), __T(" MainConcept AG")); Encoded_Library_Name=__T("MainConcept H.264/AVC Codec"); Encoded_Library_Version= Ztring().From_UTF8(Text).SubString(__T("produced by MainConcept H.264/AVC Codec v"), __T(" (c) ")); Encoded_Library_Date=MediaInfoLib::Config.Library_Get(InfoLibrary_Format_MainConcept_Avc, Encoded_Library_Version, InfoLibrary_Date); } } //--------------------------------------------------------------------------- void File_Avc::sei_alternative_transfer_characteristics() { Element_Info1("alternative_transfer_characteristics"); //Parsing Get_B1(preferred_transfer_characteristics, "preferred_transfer_characteristics"); Param_Info1(Mpegv_transfer_characteristics(preferred_transfer_characteristics)); } //--------------------------------------------------------------------------- // Packet "07" void File_Avc::seq_parameter_set() { Element_Name("seq_parameter_set"); //parsing int32u seq_parameter_set_id; seq_parameter_set_struct* Data_Item_New=seq_parameter_set_data(seq_parameter_set_id); if (!Data_Item_New) return; Mark_1( ); size_t BS_bits=Data_BS_Remain()%8; while (BS_bits) { Mark_0( ); BS_bits--; } BS_End(); //Hack for 00003.m2ts: There is a trailing 0x89, why? if (Element_Offset+1==Element_Size) { int8u ToTest; Peek_B1(ToTest); if (ToTest==0x98) Skip_B1( "Unknown"); } //Hack for : There is a trailing data, why? if (Element_Offset+4==Element_Size) { int32u ToTest; Peek_B4(ToTest); if (ToTest==0xE30633C0) Skip_B4( "Unknown"); } //NULL bytes while (Element_Offset &Data, const int32u Data_id, seq_parameter_set_struct* Data_Item_New) { //Creating Data if (Data_id>=Data.size()) Data.resize(Data_id+1); else FirstPFrameInGop_IsParsed=true; std::vector::iterator Data_Item=Data.begin()+Data_id; delete *Data_Item; *Data_Item=Data_Item_New; //Computing values (for speed) size_t MaxNumber; switch (Data_Item_New->pic_order_cnt_type) { case 0 : MaxNumber=Data_Item_New->MaxPicOrderCntLsb; break; case 1 : case 2 : MaxNumber=Data_Item_New->MaxFrameNum*2; break; default: MaxNumber = 0; } if (MaxNumber>TemporalReferences_Reserved) { TemporalReferences.resize(4*MaxNumber); TemporalReferences_Reserved=MaxNumber; } } //--------------------------------------------------------------------------- // Packet "08" void File_Avc::pic_parameter_set() { Element_Name("pic_parameter_set"); //Parsing int32u pic_parameter_set_id, seq_parameter_set_id, num_slice_groups_minus1, num_ref_idx_l0_default_active_minus1, num_ref_idx_l1_default_active_minus1, slice_group_map_type=0; int8u weighted_bipred_idc=0; bool entropy_coding_mode_flag,bottom_field_pic_order_in_frame_present_flag, redundant_pic_cnt_present_flag, weighted_pred_flag, deblocking_filter_control_present_flag; BS_Begin(); Get_UE (pic_parameter_set_id, "pic_parameter_set_id"); Get_UE (seq_parameter_set_id, "seq_parameter_set_id"); std::vector::iterator seq_parameter_set_Item; if (seq_parameter_set_id>=seq_parameter_sets.size() || (*(seq_parameter_set_Item=seq_parameter_sets.begin()+seq_parameter_set_id))==NULL) { if (seq_parameter_set_id>=subset_seq_parameter_sets.size() || (*(seq_parameter_set_Item=subset_seq_parameter_sets.begin()+seq_parameter_set_id))==NULL) { //Not yet present Skip_BS(Data_BS_Remain(), "Data (seq_parameter_set is missing)"); return; } } Get_SB (entropy_coding_mode_flag, "entropy_coding_mode_flag"); Get_SB (bottom_field_pic_order_in_frame_present_flag, "bottom_field_pic_order_in_frame_present_flag"); Get_UE (num_slice_groups_minus1, "num_slice_groups_minus1"); if (num_slice_groups_minus1>7) { Trusted_IsNot("num_slice_groups_minus1 too high"); num_slice_groups_minus1=0; } if (num_slice_groups_minus1>0) { Get_UE (slice_group_map_type, "slice_group_map_type"); if (slice_group_map_type==0) { for (int32u Pos=0; Pos<=num_slice_groups_minus1; Pos++) Skip_UE( "run_length_minus1"); } else if (slice_group_map_type==2) { for (int32u Pos=0; Pos((*seq_parameter_set_Item)->pic_width_in_mbs_minus1+1)*((*seq_parameter_set_Item)->pic_height_in_map_units_minus1+1)) { Trusted_IsNot("pic_size_in_map_units_minus1 too high"); return; } #if defined (__mips__) || defined (__mipsel__) int32u slice_group_id_Size=(int32u)(std::ceil(std::log((double)(num_slice_groups_minus1+1))/std::log((double)10))); //std::log is natural logarithm #else int32u slice_group_id_Size=(int32u)(std::ceil(std::log((float32)(num_slice_groups_minus1+1))/std::log((float32)10))); //std::log is natural logarithm #endif for (int32u Pos=0; Pos<=pic_size_in_map_units_minus1; Pos++) Skip_BS(slice_group_id_Size, "slice_group_id"); } } Get_UE (num_ref_idx_l0_default_active_minus1, "num_ref_idx_l0_default_active_minus1"); Get_UE (num_ref_idx_l1_default_active_minus1, "num_ref_idx_l1_default_active_minus1"); Get_SB (weighted_pred_flag, "weighted_pred_flag"); Get_S1 (2, weighted_bipred_idc, "weighted_bipred_idc"); Skip_SE( "pic_init_qp_minus26"); Skip_SE( "pic_init_qs_minus26"); Skip_SE( "chroma_qp_index_offset"); Get_SB (deblocking_filter_control_present_flag, "deblocking_filter_control_present_flag"); Skip_SB( "constrained_intra_pred_flag"); Get_SB (redundant_pic_cnt_present_flag, "redundant_pic_cnt_present_flag"); bool more_rbsp_data=false; if (Element_Size) { int64u Offset=Element_Size-1; while (Offset && Buffer[Buffer_Offset+(size_t)Offset]==0x00) //Searching if there are NULL bytes at the end of the data Offset--; size_t Bit_Pos=7; while (Bit_Pos && !(Buffer[Buffer_Offset+(size_t)Offset]&(1<<(7-Bit_Pos)))) Bit_Pos--; if (Data_BS_Remain()>1+(7-Bit_Pos)+(Element_Size-Offset-1)*8) more_rbsp_data=true; } if (more_rbsp_data) { bool transform_8x8_mode_flag; Get_SB (transform_8x8_mode_flag, "transform_8x8_mode_flag"); TEST_SB_SKIP( "pic_scaling_matrix_present_flag"); for (int8u Pos=0; Pos<6+(transform_8x8_mode_flag?((*seq_parameter_set_Item)->chroma_format_idc!=3?2:6):0); Pos++ ) { TEST_SB_SKIP( "pic_scaling_list_present_flag"); scaling_list(Pos<6?16:64); TEST_SB_END(); } TEST_SB_END(); Skip_SE( "second_chroma_qp_index_offset"); } Mark_1( ); BS_End(); while (Element_Offset=256) { Trusted_IsNot("pic_parameter_set_id not valid"); return; //Problem, not valid } if (seq_parameter_set_id>=32) { Trusted_IsNot("seq_parameter_set_id not valid"); return; //Problem, not valid } //NextCode NextCode_Clear(); NextCode_Add(0x05); NextCode_Add(0x06); if (!subset_seq_parameter_sets.empty()) NextCode_Add(0x14); //slice_layer_extension //Filling if (pic_parameter_set_id>=pic_parameter_sets.size()) pic_parameter_sets.resize(pic_parameter_set_id+1); std::vector::iterator pic_parameter_sets_Item=pic_parameter_sets.begin()+pic_parameter_set_id; delete *pic_parameter_sets_Item; *pic_parameter_sets_Item = new pic_parameter_set_struct( (int8u)seq_parameter_set_id, (int8u)num_ref_idx_l0_default_active_minus1, (int8u)num_ref_idx_l1_default_active_minus1, weighted_bipred_idc, num_slice_groups_minus1, slice_group_map_type, entropy_coding_mode_flag, bottom_field_pic_order_in_frame_present_flag, weighted_pred_flag, redundant_pic_cnt_present_flag, deblocking_filter_control_present_flag ); //Autorisation of other streams if (!seq_parameter_sets.empty()) { for (int8u Pos=0x01; Pos<=0x06; Pos++) { Streams[Pos].Searching_Payload=true; //Coded slice... if (Streams[0x08].ShouldDuplicate) Streams[Pos].ShouldDuplicate=true; } } if (!subset_seq_parameter_sets.empty()) { Streams[0x14].Searching_Payload=true; //slice_layer_extension if (Streams[0x08].ShouldDuplicate) Streams[0x14].ShouldDuplicate=true; //slice_layer_extension } //Setting as OK if (!Status[IsAccepted]) Accept("AVC"); FILLING_END(); } //--------------------------------------------------------------------------- // Packet "09" void File_Avc::access_unit_delimiter() { Element_Name("access_unit_delimiter"); int8u primary_pic_type; BS_Begin(); Get_S1 ( 3, primary_pic_type, "primary_pic_type"); Param_Info1(Avc_primary_pic_type[primary_pic_type]); Mark_1_NoTrustError( ); //Found 1 file without this bit BS_End(); } //--------------------------------------------------------------------------- // Packet "09" void File_Avc::filler_data() { Element_Name("filler_data"); while (Element_Offsetprofile_idc==83 || Data_Item_New->profile_idc==86) { //bool svc_vui_parameters_present_flag; seq_parameter_set_svc_extension(); /* The rest is not yet implemented Get_SB (svc_vui_parameters_present_flag, "svc_vui_parameters_present_flag"); if (svc_vui_parameters_present_flag) svc_vui_parameters_extension(); */ } else if (Data_Item_New->profile_idc==118 || Data_Item_New->profile_idc==128) { //bool mvc_vui_parameters_present_flag, additional_extension2_flag; Mark_1(); seq_parameter_set_mvc_extension(Data_Item_New); /* The rest is not yet implemented Get_SB (mvc_vui_parameters_present_flag, "mvc_vui_parameters_present_flag"); if (mvc_vui_parameters_present_flag) mvc_vui_parameters_extension(); Get_SB (additional_extension2_flag, "additional_extension2_flag"); if (additional_extension2_flag) { //Not handled, should skip all bits except 1 BS_End(); return; } */ } /* The rest is not yet implemented Mark_1( ); */ BS_End(); FILLING_BEGIN(); //NextCode NextCode_Clear(); NextCode_Add(0x08); //Add seq_parameter_set_data_Add(subset_seq_parameter_sets, subset_seq_parameter_set_id, Data_Item_New); //Autorisation of other streams Streams[0x08].Searching_Payload=true; //pic_parameter_set if (Streams[0x0F].ShouldDuplicate) Streams[0x08].ShouldDuplicate=true; //pic_parameter_set Streams[0x0A].Searching_Payload=true; //end_of_seq if (Streams[0x0F].ShouldDuplicate) Streams[0x0A].ShouldDuplicate=true; //end_of_seq Streams[0x0B].Searching_Payload=true; //end_of_stream if (Streams[0x0F].ShouldDuplicate) Streams[0x0B].ShouldDuplicate=true; //end_of_stream FILLING_END(); } //--------------------------------------------------------------------------- // Packet "14" void File_Avc::slice_layer_extension(bool svc_extension_flag) { Element_Name("slice_layer_extension"); //Parsing if (svc_extension_flag) { Skip_XX(Element_Size-Element_Offset, "slice_header_in_scalable_extension + slice_data_in_scalable_extension"); } else { BS_Begin(); slice_header(); slice_data(true); BS_End(); } } //*************************************************************************** // SubElements //*************************************************************************** //--------------------------------------------------------------------------- File_Avc::seq_parameter_set_struct* File_Avc::seq_parameter_set_data(int32u &Data_id) { //Parsing seq_parameter_set_struct::vui_parameters_struct* vui_parameters_Item=NULL; int32u chroma_format_idc=1, bit_depth_luma_minus8=0, bit_depth_chroma_minus8=0, log2_max_frame_num_minus4, pic_order_cnt_type, log2_max_pic_order_cnt_lsb_minus4=(int32u)-1, max_num_ref_frames, pic_width_in_mbs_minus1, pic_height_in_map_units_minus1, frame_crop_left_offset=0, frame_crop_right_offset=0, frame_crop_top_offset=0, frame_crop_bottom_offset=0; int8u profile_idc, constraint_set_flags, level_idc; bool constraint_set1_flag, constraint_set3_flag, separate_colour_plane_flag=false, delta_pic_order_always_zero_flag=false, frame_mbs_only_flag, mb_adaptive_frame_field_flag=false; Get_B1 (profile_idc, "profile_idc"); Get_B1 (constraint_set_flags, "constraint_sett_flags"); Skip_Flags(constraint_set_flags, 7, "constraint_sett0_flag"); Skip_Flags(constraint_set_flags, 6, "constraint_sett1_flag"); Skip_Flags(constraint_set_flags, 5, "constraint_sett2_flag"); Skip_Flags(constraint_set_flags, 4, "constraint_sett3_flag"); Skip_Flags(constraint_set_flags, 3, "constraint_sett4_flag"); Skip_Flags(constraint_set_flags, 2, "constraint_sett5_flag"); Skip_Flags(constraint_set_flags, 1, "constraint_sett6_flag"); Skip_Flags(constraint_set_flags, 0, "constraint_sett7_flag"); Get_B1 (level_idc, "level_idc"); BS_Begin(); Get_UE ( Data_id, "seq_parameter_set_id"); switch (profile_idc) { case 100 : case 110 : case 122 : case 244 : case 44 : case 83 : case 86 : case 118 : case 128 : //High profiles case 138 : Element_Begin1("high profile specific"); Get_UE (chroma_format_idc, "chroma_format_idc"); Param_Info1C((chroma_format_idc<3), Avc_ChromaSubsampling_format_idc(chroma_format_idc)); if (chroma_format_idc==3) Get_SB (separate_colour_plane_flag, "separate_colour_plane_flag"); Get_UE (bit_depth_luma_minus8, "bit_depth_luma_minus8"); Get_UE (bit_depth_chroma_minus8, "bit_depth_chroma_minus8"); Skip_SB( "qpprime_y_zero_transform_bypass_flag"); TEST_SB_SKIP( "seq_scaling_matrix_present_flag"); for (int32u Pos=0; Pos<(int32u)((chroma_format_idc!=3) ? 8 : 12); Pos++) { TEST_SB_SKIP( "seq_scaling_list_present_flag"); scaling_list(Pos<6?16:64); TEST_SB_END(); } TEST_SB_END(); Element_End0(); break; default : ; } Get_UE (log2_max_frame_num_minus4, "log2_max_frame_num_minus4"); Get_UE (pic_order_cnt_type, "pic_order_cnt_type"); if (pic_order_cnt_type==0) Get_UE (log2_max_pic_order_cnt_lsb_minus4, "log2_max_pic_order_cnt_lsb_minus4"); else if (pic_order_cnt_type==1) { int32u num_ref_frames_in_pic_order_cnt_cycle; Get_SB (delta_pic_order_always_zero_flag, "delta_pic_order_always_zero_flag"); Skip_SE( "offset_for_non_ref_pic"); Skip_SE( "offset_for_top_to_bottom_field"); Get_UE (num_ref_frames_in_pic_order_cnt_cycle, "num_ref_frames_in_pic_order_cnt_cycle"); if (num_ref_frames_in_pic_order_cnt_cycle>=256) { Trusted_IsNot("num_ref_frames_in_pic_order_cnt_cycle too high"); return NULL; } for(int32u Pos=0; Pos 2) { Trusted_IsNot("pic_order_cnt_type not supported"); return NULL; } Get_UE (max_num_ref_frames, "max_num_ref_frames"); Skip_SB( "gaps_in_frame_num_value_allowed_flag"); Get_UE (pic_width_in_mbs_minus1, "pic_width_in_mbs_minus1"); Get_UE (pic_height_in_map_units_minus1, "pic_height_in_map_units_minus1"); Get_SB (frame_mbs_only_flag, "frame_mbs_only_flag"); if (!frame_mbs_only_flag) Get_SB (mb_adaptive_frame_field_flag, "mb_adaptive_frame_field_flag"); Skip_SB( "direct_8x8_inference_flag"); TEST_SB_SKIP( "frame_cropping_flag"); Get_UE (frame_crop_left_offset, "frame_crop_left_offset"); Get_UE (frame_crop_right_offset, "frame_crop_right_offset"); Get_UE (frame_crop_top_offset, "frame_crop_top_offset"); Get_UE (frame_crop_bottom_offset, "frame_crop_bottom_offset"); TEST_SB_END(); TEST_SB_SKIP( "vui_parameters_present_flag"); vui_parameters(vui_parameters_Item); TEST_SB_END(); FILLING_BEGIN(); //Integrity if (Data_id>=32) { Trusted_IsNot("seq_parameter_set_id not valid"); delete (seq_parameter_set_struct::vui_parameters_struct*)vui_parameters_Item; return NULL; //Problem, not valid } if (pic_order_cnt_type==0 && log2_max_pic_order_cnt_lsb_minus4>12) { Trusted_IsNot("log2_max_pic_order_cnt_lsb_minus4 not valid"); delete (seq_parameter_set_struct::vui_parameters_struct*)vui_parameters_Item; return NULL; //Problem, not valid } if (log2_max_frame_num_minus4>12) { Trusted_IsNot("log2_max_frame_num_minus4 not valid"); delete (seq_parameter_set_struct::vui_parameters_struct*)vui_parameters_Item; return NULL; //Problem, not valid } //Creating Data return new seq_parameter_set_struct( vui_parameters_Item, pic_width_in_mbs_minus1, pic_height_in_map_units_minus1, frame_crop_left_offset, frame_crop_right_offset, frame_crop_top_offset, frame_crop_bottom_offset, (int8u)chroma_format_idc, profile_idc, level_idc, (int8u)bit_depth_luma_minus8, (int8u)bit_depth_chroma_minus8, (int8u)log2_max_frame_num_minus4, (int8u)pic_order_cnt_type, (int8u)log2_max_pic_order_cnt_lsb_minus4, (int8u)max_num_ref_frames, constraint_set_flags, separate_colour_plane_flag, delta_pic_order_always_zero_flag, frame_mbs_only_flag, mb_adaptive_frame_field_flag ); FILLING_ELSE(); delete vui_parameters_Item; //vui_parameters_Item=NULL; return NULL; FILLING_END(); } //--------------------------------------------------------------------------- void File_Avc::scaling_list(int32u ScalingList_Size) { //From http://mpeg4ip.cvs.sourceforge.net/mpeg4ip/mpeg4ip/util/h264/main.cpp?revision=1.17&view=markup int32u lastScale=8, nextScale=8; for (int32u Pos=0; Pos31) { Trusted_IsNot("cpb_cnt_minus1 too high"); cpb_cnt_minus1=0; } vector SchedSel; SchedSel.reserve(cpb_cnt_minus1+1); for (int8u SchedSelIdx = 0; SchedSelIdx <= cpb_cnt_minus1; ++SchedSelIdx) { Element_Begin1("ShedSel"); int64u bit_rate_value, cpb_size_value; int32u bit_rate_value_minus1, cpb_size_value_minus1; bool cbr_flag; Get_UE (bit_rate_value_minus1, "bit_rate_value_minus1"); bit_rate_value=(int64u)((bit_rate_value_minus1+1)*pow(2.0, 6+bit_rate_scale)); Param_Info2(bit_rate_value, " bps"); Get_UE (cpb_size_value_minus1, "cpb_size_value_minus1"); cpb_size_value=(int64u)((cpb_size_value_minus1+1)*pow(2.0, 4+cpb_size_scale)); Param_Info2(cpb_size_value, " bits"); Get_SB (cbr_flag, "cbr_flag"); Element_End0(); FILLING_BEGIN(); SchedSel.push_back(seq_parameter_set_struct::vui_parameters_struct::xxl::xxl_data( bit_rate_value, cpb_size_value, cbr_flag )); FILLING_END(); } Get_S1 (5, initial_cpb_removal_delay_length_minus1, "initial_cpb_removal_delay_length_minus1"); Get_S1 (5, cpb_removal_delay_length_minus1, "cpb_removal_delay_length_minus1"); Get_S1 (5, dpb_output_delay_length_minus1, "dpb_output_delay_length_minus1"); Get_S1 (5, time_offset_length, "time_offset_length"); //Validity test if (!Element_IsOK() || (SchedSel.size() == 1 && SchedSel[0].bit_rate_value == 64)) { return; //We do not trust this kind of data } //Filling hrd_parameters_Item_=new seq_parameter_set_struct::vui_parameters_struct::xxl( SchedSel, initial_cpb_removal_delay_length_minus1, cpb_removal_delay_length_minus1, dpb_output_delay_length_minus1, time_offset_length ); } //--------------------------------------------------------------------------- void File_Avc::nal_unit_header_svc_extension() { //Parsing Element_Begin1("nal_unit_header_svc_extension"); Skip_SB( "idr_flag"); Skip_S1( 6, "priority_id"); Skip_SB( "no_inter_layer_pred_flag"); Skip_S1( 3, "dependency_id"); Skip_S1( 4, "quality_id"); Skip_S1( 3, "temporal_id"); Skip_SB( "use_ref_base_pic_flag"); Skip_SB( "discardable_flag"); Skip_SB( "output_flag"); Skip_S1( 2, "reserved_three_2bits"); Element_End0(); } //--------------------------------------------------------------------------- void File_Avc::nal_unit_header_mvc_extension() { //Parsing Element_Begin1("nal_unit_header_mvc_extension"); Skip_SB( "non_idr_flag"); Skip_S1( 6, "priority_id"); Skip_S1(10, "view_id"); Skip_S1( 3, "temporal_id"); Skip_SB( "anchor_pic_flag"); Skip_SB( "inter_view_flag"); Skip_SB( "reserved_one_bit"); Element_End0(); } //--------------------------------------------------------------------------- void File_Avc::seq_parameter_set_svc_extension() { //Parsing Element_Begin1("seq_parameter_set_svc_extension"); //Skip_SB( ""); Element_End0(); } //--------------------------------------------------------------------------- void File_Avc::svc_vui_parameters_extension() { //Parsing Element_Begin1("svc_vui_parameters_extension"); //Skip_SB( ""); Element_End0(); } //--------------------------------------------------------------------------- void File_Avc::seq_parameter_set_mvc_extension(seq_parameter_set_struct* Data_Item) { //Parsing Element_Begin1("seq_parameter_set_mvc_extension"); int32u num_views_minus1; Get_UE (num_views_minus1, "num_views_minus1"); //(Not implemented) Element_End0(); FILLING_BEGIN(); Data_Item->num_views_minus1 = (int16u)num_views_minus1; FILLING_END(); } //--------------------------------------------------------------------------- void File_Avc::mvc_vui_parameters_extension() { //Parsing Element_Begin1("mvc_vui_parameters_extension"); Skip_SB( ""); Element_End0(); } //*************************************************************************** // Specific //*************************************************************************** //--------------------------------------------------------------------------- void File_Avc::SPS_PPS() { //Parsing int8u Profile, Level, seq_parameter_set_count, pic_parameter_set_count; if (SizedBlocks) Skip_B1( "configurationVersion"); Get_B1 (Profile, "AVCProfileIndication"); Skip_B1( "profile_compatibility"); Get_B1 (Level, "AVCLevelIndication"); BS_Begin(); Skip_S1(6, "reserved"); Get_S1 (2, SizeOfNALU_Minus1, "lengthSizeMinusOne"); Skip_S1(3, "reserved"); Get_S1 (5, seq_parameter_set_count, "numOfSequenceParameterSets"); BS_End(); for (int8u Pos=0; PosElement_Size-Element_Offset) { Trusted_IsNot("Size is wrong"); break; //There is an error } BS_Begin(); Mark_0 (); Skip_S1( 2, "nal_ref_idc"); Skip_S1( 5, "nal_unit_type"); BS_End(); if (!Trusted_Get()) break; int64u Element_Offset_Save=Element_Offset; int64u Element_Size_Save=Element_Size; Buffer_Offset+=(size_t)Element_Offset_Save; Element_Offset=0; Element_Size=Size-(Size?1:0); Element_Code=0x07; //seq_parameter_set Data_Parse(); Buffer_Offset-=(size_t)Element_Offset_Save; Element_Offset=Element_Offset_Save+Size-1; Element_Size=Element_Size_Save; Element_End0(); } Get_B1 (pic_parameter_set_count, "numOfPictureParameterSets"); for (int8u Pos=0; PosElement_Size-Element_Offset) { Trusted_IsNot("Size is wrong"); break; //There is an error } BS_Begin(); Mark_0 (); Skip_S1( 2, "nal_ref_idc"); Skip_S1( 5, "nal_unit_type"); BS_End(); if (!Trusted_Get()) break; int64u Element_Offset_Save=Element_Offset; int64u Element_Size_Save=Element_Size; Buffer_Offset+=(size_t)Element_Offset_Save; Element_Offset=0; Element_Size=Size-1; Element_Code=0x08; //pic_parameter_set Data_Parse(); Buffer_Offset-=(size_t)Element_Offset_Save; Element_Offset=Element_Offset_Save+Size-1; Element_Size=Element_Size_Save; Element_End0(); } if (Element_OffsetElement_Size_Save-Element_Offset_Save) break; //There is an error Element_Code=0x0F; //subset_seq_parameter_set Data_Parse(); Buffer_Offset-=(size_t)Element_Offset_Save; Element_Offset=Element_Offset_Save+Size-1; Element_Size=Element_Size_Save; Element_End0(); } } default:; } } if (Element_Offsetprofile_idc || Level!=seq_parameter_sets[0]->level_idc)) MuxingMode=Ztring("Container profile=")+Ztring().From_UTF8(Avc_profile_level_string(Profile, Level)); MustParse_SPS_PPS=false; if (!Status[IsAccepted]) Accept("AVC"); FILLING_ELSE(); Frame_Count_NotParsedIncluded--; RanOutOfData("AVC"); Frame_Count_NotParsedIncluded++; FILLING_END(); } //*************************************************************************** // Helpers //*************************************************************************** //--------------------------------------------------------------------------- std::string File_Avc::GOP_Detect (std::string PictureTypes) { //Finding a string without blanks size_t PictureTypes_Limit=PictureTypes.find(' '); if (PictureTypes_Limit!=string::npos) { if (PictureTypes_Limit>PictureTypes.size()/2) PictureTypes.resize(PictureTypes_Limit); else { //Trim size_t TrimPos; TrimPos=PictureTypes.find_first_not_of(' '); if (TrimPos!=string::npos) PictureTypes.erase(0, TrimPos); TrimPos=PictureTypes.find_last_not_of(' '); if (TrimPos!=string::npos) PictureTypes.erase(TrimPos+1); //Finding the longest string ZtringList List; List.Separator_Set(0, __T(" ")); List.Write(Ztring().From_UTF8(PictureTypes)); size_t MaxLength=0; size_t MaxLength_Pos=0; for (size_t Pos=0; PosMaxLength) { MaxLength=List[Pos].size(); MaxLength_Pos=Pos; } PictureTypes=List[MaxLength_Pos].To_UTF8(); } } //Creating all GOP values std::vector GOPs; size_t GOP_Frame_Count=0; size_t GOP_BFrames_Max=0; size_t I_Pos1=PictureTypes.find('I'); while (I_Pos1!=std::string::npos) { size_t I_Pos2=PictureTypes.find('I', I_Pos1+1); if (I_Pos2!=std::string::npos) { std::vector P_Positions; size_t P_Position=I_Pos1; do { P_Position=PictureTypes.find('P', P_Position+1); if (P_Position1 && P_Positions[0]>I_Pos1+1 && P_Positions[P_Positions.size()-1]==I_Pos2-1) P_Positions.resize(P_Positions.size()-1); //Removing last P-Frame for next test, this is often a terminating P-Frame replacing a B-Frame Ztring GOP; bool IsOK=true; if (!P_Positions.empty()) { size_t Delta=P_Positions[0]-I_Pos1; for (size_t Pos=1; PosGOP_BFrames_Max) GOP_BFrames_Max=P_Positions[0]-I_Pos1; } } if (IsOK) { GOP+=__T("N=")+Ztring::ToZtring(I_Pos2-I_Pos1); GOPs.push_back(GOP); } else GOPs.push_back(Ztring()); //There is a problem, blank GOP_Frame_Count+=I_Pos2-I_Pos1; } I_Pos1=I_Pos2; } //Some clean up if (GOP_Frame_Count+GOP_BFrames_Max>Frame_Count && !GOPs.empty()) GOPs.resize(GOPs.size()-1); //Removing the last one, there may have uncomplete B-frame filling if (GOPs.size()>4) GOPs.erase(GOPs.begin()); //Removing the first one, it is sometime different and we have enough to deal with //Filling if (GOPs.size()>=4) { bool IsOK=true; for (size_t Pos=1; PosScanOrders.size()/2) ScanOrders.resize(ScanOrders_Limit); else { //Trim size_t TrimPos; TrimPos=ScanOrders.find_first_not_of(' '); if (TrimPos!=string::npos) ScanOrders.erase(0, TrimPos); TrimPos=ScanOrders.find_last_not_of(' '); if (TrimPos!=string::npos) ScanOrders.erase(TrimPos+1); //Finding the longest string ZtringList List; List.Separator_Set(0, __T(" ")); List.Write(Ztring().From_UTF8(ScanOrders)); size_t MaxLength=0; size_t MaxLength_Pos=0; for (size_t Pos=0; PosMaxLength) { MaxLength=List[Pos].size(); MaxLength_Pos=Pos; } ScanOrders=List[MaxLength_Pos].To_UTF8(); } } //Filling if (ScanOrders.find("TBTBTBTB")==0) return ("TFF"); if (ScanOrders.find("BTBTBTBT")==0) return ("BFF"); return string(); } } //NameSpace #endif //MEDIAINFO_AVC_YES