#pragma once #include #include #include #include #include #include #include #include struct afrt_fragmentrunentry { uint32_t FirstFragment; uint32_t FirstFragmentTimestamp_Upperhalf; //write as uint64_t uint32_t FirstFragmentTimestamp; //write as uint64_t uint32_t FragmentDuration; uint8_t DiscontinuityIndicator;//if FragmentDuration == 0 };//afrt_fragmentrunentry struct BoxHeader { uint32_t TotalSize; uint32_t BoxType; };//BoxHeader struct class Box { public: Box(); Box(uint32_t BoxType); Box(uint8_t * Content, uint32_t length); ~Box(); void SetBoxType(uint32_t BoxType); uint32_t GetBoxType(); void SetPayload(uint32_t Size, uint8_t * Data, uint32_t Index = 0); uint32_t GetPayloadSize(); uint8_t * GetPayload(); uint8_t * GetPayload(uint32_t Index, uint32_t & Size); uint32_t GetBoxedDataSize(); uint8_t * GetBoxedData( ); static uint8_t * uint32_to_uint8( uint32_t data ); static uint8_t * uint16_to_uint8( uint16_t data ); static uint8_t * uint8_to_uint8( uint8_t data ); BoxHeader GetHeader( ); void ResetPayload( ); void Parse( std::string PrintOffset = "" ); uint8_t * Payload; uint32_t PayloadSize; private: BoxHeader header; };//Box Class Box::Box() { Payload = NULL; PayloadSize = 0; } Box::Box(uint32_t BoxType) { header.BoxType = BoxType; Payload = NULL; PayloadSize = 0; } Box::Box(uint8_t * Content, uint32_t length) { header.TotalSize = (Content[0] << 24) + (Content[1] << 16) + (Content[2] << 8) + (Content[3]); if(header.TotalSize != length) { std::cerr << "Warning: length sizes differ\n"; } header.BoxType = (Content[4] << 24) + (Content[5] << 16) + (Content[6] << 8) + (Content[7]); std::cerr << "Created new box with type \"" << (char)(header.BoxType >> 24) << (char)((header.BoxType << 8) >> 24) << (char)((header.BoxType << 16) >> 24) << (char)((header.BoxType << 24) >> 24) << "\"\n"; PayloadSize = length-8; Payload = new uint8_t[PayloadSize]; memcpy( Payload, &Content[8], PayloadSize ); } Box::~Box() { } void Box::SetBoxType(uint32_t BoxType) { header.BoxType = BoxType; } uint32_t Box::GetBoxType() { return header.BoxType; } void Box::SetPayload(uint32_t Size, uint8_t * Data, uint32_t Index) { uint8_t * tempchar = NULL; if ( Index + Size > PayloadSize ) { if ( Payload ) { tempchar = new uint8_t[PayloadSize]; memcpy( tempchar, Payload, PayloadSize ); delete Payload; } PayloadSize = Index + Size; Payload = new uint8_t[PayloadSize]; if( tempchar ) { memcpy( Payload, tempchar, Index ); } else { for(uint32_t i = 0; i < Index; i++) { Payload[i] = 0; } } memcpy( &Payload[Index], Data, Size ); header.TotalSize = PayloadSize + 8; if( tempchar ) { delete tempchar; } } else { memcpy( &Payload[Index], Data, Size ); } } uint32_t Box::GetPayloadSize() { return PayloadSize; } uint8_t * Box::GetPayload() { uint8_t * temp = new uint8_t[PayloadSize]; memcpy( temp, Payload, PayloadSize ); return temp; } uint8_t * Box::GetPayload(uint32_t Index, uint32_t & Size) { if(Index > PayloadSize) { return NULL; } if(Index + Size > PayloadSize) { Size = PayloadSize - Index; } uint8_t * temp = new uint8_t[Size - Index]; memcpy( temp, &Payload[Index], Size - Index ); return temp; } uint32_t Box::GetBoxedDataSize() { return header.TotalSize; } uint8_t * Box::GetBoxedData( ) { uint8_t * temp = new uint8_t[header.TotalSize]; memcpy( temp, uint32_to_uint8(header.TotalSize), 4 ); memcpy( &temp[4], uint32_to_uint8(header.BoxType), 4 ); memcpy( &temp[8], Payload, PayloadSize ); return temp; } uint8_t * Box::uint32_to_uint8( uint32_t data ) { uint8_t * temp = new uint8_t[4]; temp[0] = (data >> 24) & 0x000000FF; temp[1] = (data >> 16 ) & 0x000000FF; temp[2] = (data >> 8 ) & 0x000000FF; temp[3] = (data ) & 0x000000FF; return temp; } uint8_t * Box::uint16_to_uint8( uint16_t data ) { uint8_t * temp = new uint8_t[2]; temp[0] = (data >> 8) & 0x00FF; temp[1] = (data ) & 0x00FF; return temp; } uint8_t * Box::uint8_to_uint8( uint8_t data ) { uint8_t * temp = new uint8_t[1]; temp[0] = data; return temp; } BoxHeader Box::GetHeader( ) { return header; } void Box::ResetPayload( ) { header.TotalSize -= PayloadSize; PayloadSize = 0; if(Payload) { delete Payload; Payload = NULL; } } void Box::Parse( std::string PrintOffset ) { if( header.BoxType == 0x61627374 ) { uint8_t Version = Payload[0]; uint32_t Flags = (Payload[1] << 16) + (Payload[2] << 8) + (Payload[3]); //uint24_t uint32_t BootstrapInfoVersion = (Payload[4] << 24) + (Payload[5] << 16) +(Payload[6] << 8) + (Payload[7]); uint8_t Profile = (Payload[8] >> 6); //uint2_t uint8_t Live = (( Payload[8] >> 5 ) & 0x1); //uint1_t uint8_t Update = (( Payload[8] >> 4 ) & 0x1); //uint1_t uint8_t Reserved = ( Payload[8] & 0x4); //uint4_t uint32_t Timescale = (Payload[9] << 24) + (Payload[10] << 16) +(Payload[11] << 8) + (Payload[12]); uint32_t CurrentMediaTime_Upperhalf = (Payload[13] << 24) + (Payload[14] << 16) +(Payload[15] << 8) + (Payload[16]); uint32_t CurrentMediaTime_Lowerhalf = (Payload[17] << 24) + (Payload[18] << 16) +(Payload[19] << 8) + (Payload[20]); uint32_t SmpteTimeCodeOffset_Upperhalf = (Payload[21] << 24) + (Payload[22] << 16) +(Payload[23] << 8) + (Payload[24]); uint32_t SmpteTimeCodeOffset_Lowerhalf = (Payload[25] << 24) + (Payload[26] << 16) +(Payload[27] << 8) + (Payload[28]); std::string MovieIdentifier; uint8_t ServerEntryCount = -1; std::vector ServerEntryTable; uint8_t QualityEntryCount = -1; std::vector QualityEntryTable; std::string DrmData; std::string MetaData; uint8_t SegmentRunTableCount = -1; std::vector SegmentRunTableEntries; uint8_t FragmentRunTableCount = -1; std::vector FragmentRunTableEntries; uint32_t CurrentOffset = 29; uint32_t TempSize; Box* TempBox; std::string temp; while( Payload[CurrentOffset] != '\0' ) { MovieIdentifier += Payload[CurrentOffset]; CurrentOffset ++; } CurrentOffset ++; ServerEntryCount = Payload[CurrentOffset]; CurrentOffset ++; for( uint8_t i = 0; i < ServerEntryCount; i++ ) { temp = ""; while( Payload[CurrentOffset] != '\0' ) { temp += Payload[CurrentOffset]; CurrentOffset ++; } ServerEntryTable.push_back(temp); CurrentOffset++; } QualityEntryCount = Payload[CurrentOffset]; CurrentOffset ++; for( uint8_t i = 0; i < QualityEntryCount; i++ ) { temp = ""; while( Payload[CurrentOffset] != '\0' ) { temp += Payload[CurrentOffset]; CurrentOffset ++; } QualityEntryTable.push_back(temp); CurrentOffset++; } while( Payload[CurrentOffset] != '\0' ) { DrmData += Payload[CurrentOffset]; CurrentOffset ++; } CurrentOffset ++; while( Payload[CurrentOffset] != '\0' ) { MetaData += Payload[CurrentOffset]; CurrentOffset ++; } CurrentOffset ++; SegmentRunTableCount = Payload[CurrentOffset]; CurrentOffset ++; for( uint8_t i = 0; i < SegmentRunTableCount; i++ ) { TempSize = (Payload[CurrentOffset] << 24) + (Payload[CurrentOffset+1]<< 16) + (Payload[CurrentOffset+2]<< 8) + (Payload[CurrentOffset+3]); TempBox = new Box( &Payload[CurrentOffset], TempSize ); SegmentRunTableEntries.push_back(TempBox); CurrentOffset += TempSize; } FragmentRunTableCount = Payload[CurrentOffset]; CurrentOffset ++; for( uint8_t i = 0; i < FragmentRunTableCount; i++ ) { TempSize = (Payload[CurrentOffset] << 24) + (Payload[CurrentOffset+1]<< 16) + (Payload[CurrentOffset+2]<< 8) + (Payload[CurrentOffset+3]); TempBox = new Box( &Payload[CurrentOffset], TempSize ); FragmentRunTableEntries.push_back(TempBox); CurrentOffset += TempSize; } std::cerr << "Box_ABST:\n"; std::cerr << PrintOffset << " Version: " << (int)Version << "\n"; std::cerr << PrintOffset << " Flags: " << (int)Flags << "\n"; std::cerr << PrintOffset << " BootstrapInfoVersion: " << (int)BootstrapInfoVersion << "\n"; std::cerr << PrintOffset << " Profile: " << (int)Profile << "\n"; std::cerr << PrintOffset << " Live: " << (int)Live << "\n"; std::cerr << PrintOffset << " Update: " << (int)Update << "\n"; std::cerr << PrintOffset << " Reserved: " << (int)Reserved << "\n"; std::cerr << PrintOffset << " Timescale: " << (int)Timescale << "\n"; std::cerr << PrintOffset << " CurrentMediaTime: " << (int)CurrentMediaTime_Upperhalf << " " << CurrentMediaTime_Lowerhalf << "\n"; std::cerr << PrintOffset << " SmpteTimeCodeOffset: " << (int)SmpteTimeCodeOffset_Upperhalf << " " << SmpteTimeCodeOffset_Lowerhalf << "\n"; std::cerr << PrintOffset << " MovieIdentifier: " << MovieIdentifier << "\n"; std::cerr << PrintOffset << " ServerEntryCount: " << (int)ServerEntryCount << "\n"; std::cerr << PrintOffset << " ServerEntryTable:\n"; for( uint32_t i = 0; i < ServerEntryTable.size( ); i++ ) { std::cerr << PrintOffset << " " << i+1 << ": " << ServerEntryTable[i] << "\n"; } std::cerr << PrintOffset << " QualityEntryCount: " << (int)QualityEntryCount << "\n"; std::cerr << PrintOffset << " QualityEntryTable:\n"; for( uint32_t i = 0; i < QualityEntryTable.size( ); i++ ) { std::cerr << PrintOffset << " " << i+1 << ": " << QualityEntryTable[i] << "\n"; } std::cerr << PrintOffset << " DrmData: " << DrmData << "\n"; std::cerr << PrintOffset << " MetaData: " << MetaData << "\n"; std::cerr << PrintOffset << " SegmentRunTableCount: " << (int)SegmentRunTableCount << "\n"; std::cerr << PrintOffset << " SegmentRunTableEntries:\n"; for( uint32_t i = 0; i < SegmentRunTableEntries.size( ); i++ ) { std::cerr << PrintOffset << " " << i+1 << ": "; SegmentRunTableEntries[i]->Parse( PrintOffset+" "); } std::cerr << PrintOffset << " FragmentRunTableCount: " << (int)FragmentRunTableCount << "\n"; std::cerr << PrintOffset << " FragmentRunTableEntries:\n"; for( uint32_t i = 0; i < FragmentRunTableEntries.size( ); i++ ) { std::cerr << PrintOffset << " " << i+1 << ": "; FragmentRunTableEntries[i]->Parse( PrintOffset+" "); } } else if ( header.BoxType == 0x61737274 ) { uint8_t Version = Payload[0]; uint32_t Flags = (Payload[1] << 16) + (Payload[2] << 8) + (Payload[3]); //uint24_t uint8_t QualityEntryCount; std::vector QualitySegmentUrlModifiers; uint32_t SegmentRunEntryCount; std::vector< std::pair > SegmentRunEntryTable; uint32_t CurrentOffset = 4; std::string temp; std::pair TempPair; QualityEntryCount = Payload[CurrentOffset]; CurrentOffset ++; for( uint8_t i = 0; i < QualityEntryCount; i++ ) { temp = ""; while( Payload[CurrentOffset] != '\0' ) { temp += Payload[CurrentOffset]; CurrentOffset ++; } QualitySegmentUrlModifiers.push_back(temp); CurrentOffset++; } SegmentRunEntryCount = (Payload[CurrentOffset] << 24) + (Payload[CurrentOffset+1] << 16) + (Payload[CurrentOffset+2]) + (Payload[CurrentOffset+3]); CurrentOffset +=4; for( uint8_t i = 0; i < SegmentRunEntryCount; i++ ) { TempPair.first = (Payload[CurrentOffset] << 24) + (Payload[CurrentOffset+1] << 16) + (Payload[CurrentOffset+2] << 8) + (Payload[CurrentOffset+3]); CurrentOffset+=4; TempPair.second = (Payload[CurrentOffset] << 24) + (Payload[CurrentOffset+1] << 16) + (Payload[CurrentOffset+2] << 8) + (Payload[CurrentOffset+3]); CurrentOffset+=4; SegmentRunEntryTable.push_back(TempPair); } std::cerr << "Box_ASRT:\n"; std::cerr << PrintOffset << " Version: " << (int)Version << "\n"; std::cerr << PrintOffset << " Flags: " << (int)Flags << "\n"; std::cerr << PrintOffset << " QualityEntryCount: " << (int)QualityEntryCount << "\n"; std::cerr << PrintOffset << " QualitySegmentUrlModifiers:\n"; for( uint32_t i = 0; i < QualitySegmentUrlModifiers.size( ); i++ ) { std::cerr << PrintOffset << " " << i+1 << ": " << QualitySegmentUrlModifiers[i] << "\n"; } std::cerr << PrintOffset << " SegmentRunEntryCount: " << (int)SegmentRunEntryCount << "\n"; std::cerr << PrintOffset << " SegmentRunEntryTable:\n"; for( uint32_t i = 0; i < SegmentRunEntryTable.size( ); i++ ) { std::cerr << PrintOffset << " " << i+1 << ":\n"; std::cerr << PrintOffset << " FirstSegment: " << SegmentRunEntryTable[i].first << "\n"; std::cerr << PrintOffset << " FragmentsPerSegment: " << SegmentRunEntryTable[i].second << "\n"; } } else if ( header.BoxType == 0x61667274 ) { uint8_t Version = Payload[0]; uint32_t Flags = (Payload[1] << 16) + (Payload[2] << 8) + (Payload[3]); //uint24_t uint32_t TimeScale = (Payload[4] << 24) + (Payload[5] << 16) + (Payload[6] << 8) + (Payload[7]); uint8_t QualityEntryCount; std::vector QualitySegmentUrlModifiers; uint32_t FragmentRunEntryCount; std::vector FragmentRunEntryTable; uint32_t CurrentOffset = 8; std::string temp; afrt_fragmentrunentry TempEntry; QualityEntryCount = Payload[CurrentOffset]; CurrentOffset ++; for( uint8_t i = 0; i < QualityEntryCount; i++ ) { temp = ""; while( Payload[CurrentOffset] != '\0' ) { temp += Payload[CurrentOffset]; CurrentOffset ++; } QualitySegmentUrlModifiers.push_back(temp); CurrentOffset++; } FragmentRunEntryCount = (Payload[CurrentOffset] << 24) + (Payload[CurrentOffset+1] << 16) + (Payload[CurrentOffset+2]) + (Payload[CurrentOffset+3]); CurrentOffset +=4; for( uint8_t i = 0; i < FragmentRunEntryCount; i ++ ) { TempEntry.FirstFragment = (Payload[CurrentOffset] << 24) + (Payload[CurrentOffset+1] << 16) + (Payload[CurrentOffset+2]) + (Payload[CurrentOffset+3]); CurrentOffset +=4; TempEntry.FirstFragmentTimestamp_Upperhalf = (Payload[CurrentOffset] << 24) + (Payload[CurrentOffset+1] << 16) + (Payload[CurrentOffset+2]) + (Payload[CurrentOffset+3]); CurrentOffset +=4; TempEntry.FirstFragmentTimestamp = (Payload[CurrentOffset] << 24) + (Payload[CurrentOffset+1] << 16) + (Payload[CurrentOffset+2]) + (Payload[CurrentOffset+3]); CurrentOffset +=4; TempEntry.FragmentDuration = (Payload[CurrentOffset] << 24) + (Payload[CurrentOffset+1] << 16) + (Payload[CurrentOffset+2]) + (Payload[CurrentOffset+3]); CurrentOffset +=4; if( TempEntry.FragmentDuration == 0 ) { TempEntry.DiscontinuityIndicator = Payload[CurrentOffset]; CurrentOffset++; } FragmentRunEntryTable.push_back(TempEntry); } std::cerr << "Box_AFRT:\n"; std::cerr << PrintOffset << " Version: " << (int)Version << "\n"; std::cerr << PrintOffset << " Flags: " << (int)Flags << "\n"; std::cerr << PrintOffset << " Timescale: " << (int)TimeScale << "\n"; std::cerr << PrintOffset << " QualityEntryCount: " << (int)QualityEntryCount << "\n"; std::cerr << PrintOffset << " QualitySegmentUrlModifiers:\n"; for( uint32_t i = 0; i < QualitySegmentUrlModifiers.size( ); i++ ) { std::cerr << PrintOffset << " " << i+1 << ": " << QualitySegmentUrlModifiers[i] << "\n"; } std::cerr << PrintOffset << " FragmentRunEntryCount: " << (int)FragmentRunEntryCount << "\n"; std::cerr << PrintOffset << " FragmentRunEntryTable:\n"; for( uint32_t i = 0; i < FragmentRunEntryTable.size( ); i++ ) { std::cerr << PrintOffset << " " << i+1 << ":\n"; std::cerr << PrintOffset << " FirstFragment: " << FragmentRunEntryTable[i].FirstFragment << "\n"; std::cerr << PrintOffset << " FirstFragmentTimestamp: " << FragmentRunEntryTable[i].FirstFragmentTimestamp_Upperhalf << FragmentRunEntryTable[i].FirstFragmentTimestamp << "\n"; std::cerr << PrintOffset << " FragmentDuration: " << FragmentRunEntryTable[i].FragmentDuration << "\n"; if( FragmentRunEntryTable[i].FragmentDuration == 0 ) { std::cerr << PrintOffset << " DiscontinuityIndicator: " << (int)FragmentRunEntryTable[i].DiscontinuityIndicator << "\n"; } } } else if ( header.BoxType == 0x6D646174 ) { std::cerr << "mdat box containing " << PayloadSize << " bytes of payload" << std::endl; } else { std::cerr << "BoxType '" << (char)(header.BoxType >> 24) << (char)((header.BoxType << 8) >> 24) << (char)((header.BoxType << 16) >> 24) << (char)((header.BoxType << 24) >> 24) << "' not yet implemented!\n"; } }