diff --git a/Connector_HTTP/main.cpp b/Connector_HTTP/main.cpp index d2b97e1b..8d0bd18f 100644 --- a/Connector_HTTP/main.cpp +++ b/Connector_HTTP/main.cpp @@ -103,7 +103,6 @@ std::string BuildManifest( std::string MetaData, std::string MovieId, int Curren Result += "streaming\n"; Result += ""; Result += base64_encode(temp->GenerateLiveBootstrap(1)); -// Result += "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"; Result += "\n"; Result += " Flash_FragBuffer; FLV_Pack * tag = 0; + char * Video_Init_Data = 0; + int Video_Init_Len = 0; + char * Audio_Init_Data = 0; + int Audio_Init_Len = 0; HTTPReader HTTP_R, HTTP_S;//HTTP Receiver en HTTP Sender. int retval; @@ -151,73 +154,62 @@ int mainHandler(int CONN_fd){ while (!socketError && !All_Hell_Broke_Loose){ //only parse input if available or not yet init'ed - retval = epoll_wait(poller, events, 1, 1); - if ((retval > 0) || !ready4data){ - if (HTTP_R.ReadSocket(CONN_fd)){ - handler = HANDLER_PROGRESSIVE; - if ((HTTP_R.url.find("Seg") != std::string::npos) && (HTTP_R.url.find("Frag") != std::string::npos)){handler = HANDLER_FLASH;} - if (HTTP_R.url.find("f4m") != std::string::npos){handler = HANDLER_FLASH;} - if (HTTP_R.url == "/crossdomain.xml"){ - handler = HANDLER_NONE; - HTTP_S.Clean(); - HTTP_S.SetHeader("Content-Type", "text/xml"); - HTTP_S.SetBody(""); - HTTP_S.SendResponse(CONN_fd, "200", "OK");//geen SetBody = unknown length! Dat willen we hier. - #if DEBUG >= 3 - printf("Sending crossdomain.xml file\n"); - #endif - } - if(handler == HANDLER_FLASH){ - if (HTTP_R.url.find("f4m") == std::string::npos){ - Movie = HTTP_R.url.substr(1); - Movie = Movie.substr(0,Movie.find("/")); - Quality = HTTP_R.url.substr( HTTP_R.url.find("/",1)+1 ); - Quality = Quality.substr(0, Quality.find("Seg")); - temp = HTTP_R.url.find("Seg") + 3; - Segment = atoi( HTTP_R.url.substr(temp,HTTP_R.url.find("-",temp)-temp).c_str()); - temp = HTTP_R.url.find("Frag") + 4; - ReqFragment = atoi( HTTP_R.url.substr(temp).c_str() ); - #if DEBUG >= 4 - /* strftime example */ - time_t rawtime; - struct tm * timeinfo; - char timebuffer [80]; - time ( &rawtime ); - timeinfo = localtime ( &rawtime ); - strftime (timebuffer,80,"%H:%M.%S.",timeinfo); - fprintf(stderr, "< %s >\t", timebuffer ); - printf( "URL: %s\n", HTTP_R.url.c_str()); - printf( "Movie: %s, Quality: %s, Seg %d Frag %d\n", Movie.c_str(), Quality.c_str(), Segment, ReqFragment); - #endif - Flash_RequestPending++; - }else{ - Movie = HTTP_R.url.substr(1); - Movie = Movie.substr(0,Movie.find("/")); - } - streamname = "/tmp/shared_socket_"; - for (std::string::iterator i=Movie.end()-1; i>=Movie.begin(); --i){ - if (!isalpha(*i) && !isdigit(*i)){ - Movie.erase(i); - }else{ - *i=tolower(*i); - }//strip nonalphanumeric - } - streamname += Movie; - ready4data = true; - }//FLASH handler - if (handler == HANDLER_PROGRESSIVE){ - //in het geval progressive nemen we aan dat de URL de streamname is, met .flv erachter - streamname = HTTP_R.url.substr(0, HTTP_R.url.size()-4);//strip de .flv - for (std::string::iterator i=streamname.end()-1; i>=streamname.begin(); --i){ - if (!isalpha(*i) && !isdigit(*i)){streamname.erase(i);}else{*i=tolower(*i);}//strip nonalphanumeric - } - streamname = "/tmp/shared_socket_" + streamname;//dit is dan onze shared_socket - //normaal zouden we ook een position uitlezen uit de URL, maar bij LIVE streams is dat zinloos - printf("Streamname: %s\n", streamname.c_str()); - ready4data = true; - }//PROGRESSIVE handler - HTTP_R.Clean(); //maak schoon na verwerken voor eventuele volgende requests... + if (HTTP_R.ReadSocket(CONN_fd)){ + handler = HANDLER_PROGRESSIVE; + if ((HTTP_R.url.find("Seg") != std::string::npos) && (HTTP_R.url.find("Frag") != std::string::npos)){handler = HANDLER_FLASH;} + if (HTTP_R.url.find("f4m") != std::string::npos){handler = HANDLER_FLASH;} + if (HTTP_R.url == "/crossdomain.xml"){ + handler = HANDLER_NONE; + HTTP_S.Clean(); + HTTP_S.SetHeader("Content-Type", "text/xml"); + HTTP_S.SetBody(""); + HTTP_S.SendResponse(CONN_fd, "200", "OK");//geen SetBody = unknown length! Dat willen we hier. + #if DEBUG >= 3 + printf("Sending crossdomain.xml file\n"); + #endif } + if(handler == HANDLER_FLASH){ + if (HTTP_R.url.find("f4m") == std::string::npos){ + Movie = HTTP_R.url.substr(1); + Movie = Movie.substr(0,Movie.find("/")); + Quality = HTTP_R.url.substr( HTTP_R.url.find("/",1)+1 ); + Quality = Quality.substr(0, Quality.find("Seg")); + temp = HTTP_R.url.find("Seg") + 3; + Segment = atoi( HTTP_R.url.substr(temp,HTTP_R.url.find("-",temp)-temp).c_str()); + temp = HTTP_R.url.find("Frag") + 4; + ReqFragment = atoi( HTTP_R.url.substr(temp).c_str() ); + #if DEBUG >= 4 + printf( "URL: %s\n", HTTP_R.url.c_str()); + printf( "Movie: %s, Quality: %s, Seg %d Frag %d\n", Movie.c_str(), Quality.c_str(), Segment, ReqFragment); + #endif + Flash_RequestPending++; + }else{ + Movie = HTTP_R.url.substr(1); + Movie = Movie.substr(0,Movie.find("/")); + } + streamname = "/tmp/shared_socket_"; + for (std::string::iterator i=Movie.end()-1; i>=Movie.begin(); --i){ + if (!isalpha(*i) && !isdigit(*i)){ + Movie.erase(i); + }else{ + *i=tolower(*i); + }//strip nonalphanumeric + } + streamname += Movie; + ready4data = true; + }//FLASH handler + if (handler == HANDLER_PROGRESSIVE){ + //in het geval progressive nemen we aan dat de URL de streamname is, met .flv erachter + streamname = HTTP_R.url.substr(0, HTTP_R.url.size()-4);//strip de .flv + for (std::string::iterator i=streamname.end()-1; i>=streamname.begin(); --i){ + if (!isalpha(*i) && !isdigit(*i)){streamname.erase(i);}else{*i=tolower(*i);}//strip nonalphanumeric + } + streamname = "/tmp/shared_socket_" + streamname;//dit is dan onze shared_socket + //normaal zouden we ook een position uitlezen uit de URL, maar bij LIVE streams is dat zinloos + printf("Streamname: %s\n", streamname.c_str()); + ready4data = true; + }//PROGRESSIVE handler + HTTP_R.CleanForNext(); //maak schoon na verwerken voor eventuele volgende requests... } if (ready4data){ if (!inited){ @@ -246,14 +238,6 @@ int mainHandler(int CONN_fd){ HTTP_S.SendResponse(CONN_fd, "200", "OK");//schrijf de HTTP response header Flash_RequestPending--; #if DEBUG >= 3 - /* strftime example */ - time_t rawtime; - struct tm * timeinfo; - char timebuffer [80]; - time ( &rawtime ); - timeinfo = localtime ( &rawtime ); - strftime (timebuffer,80,"%H:%M.%S.",timeinfo); - fprintf(stderr, "< %s >\t", timebuffer ); fprintf(stderr, "Sending a video fragment. %i left in buffer, %i requested\n", (int)Flash_FragBuffer.size(), Flash_RequestPending); #endif } @@ -267,25 +251,40 @@ int mainHandler(int CONN_fd){ break; case -1: break;//not ready yet default: - if (FLV_GetPacket(tag, ss)){//able to read a full packet? + if (FLV_GetPacket(tag, ss)){//able to read a full packet?f if (handler == HANDLER_FLASH){ if(tag->data[0] != 0x12 ) { - if (tag->isKeyframe){ - if (FlashBuf != ""){ - Flash_FragBuffer.push(FlashBuf); + if ((tag->isKeyframe) && (Video_Init_Data == 0)){ + if (((tag->data[11] & 0x0f) == 7) && (tag->data[12] == 0)){ + tag->data[4] = 0;//timestamp to zero + tag->data[5] = 0;//timestamp to zero + tag->data[6] = 0;//timestamp to zero + Video_Init_Data = (char*)malloc(tag->len); + Video_Init_Len = tag->len; + memcpy(Video_Init_Data, tag->data, tag->len); + } + } + if ((tag->data[0] == 0x08) && (Audio_Init_Data == 0)){ + if (((tag->data[11] & 0xf0) >> 4) == 10){//aac packet + tag->data[4] = 0;//timestamp to zero + tag->data[5] = 0;//timestamp to zero + tag->data[6] = 0;//timestamp to zero + Audio_Init_Data = (char*)malloc(tag->len); + Audio_Init_Len = tag->len; + memcpy(Audio_Init_Data, tag->data, tag->len); + } + } + if (tag->isKeyframe){ + if (FlashBuf != ""){ + Flash_FragBuffer.push(FlashBuf); #if DEBUG >= 4 - time_t rawtime; - struct tm * timeinfo; - char timebuffer [80]; - time ( &rawtime ); - timeinfo = localtime ( &rawtime ); - strftime (timebuffer,80,"%H:%M.%S.",timeinfo); - fprintf(stderr, "< %s >\t", timebuffer ); - fprintf(stderr, "Received a fragment. Now %i in buffer.\n", (int)Flash_FragBuffer.size()); + fprintf(stderr, "Received a fragment. Now %i in buffer.\n", (int)Flash_FragBuffer.size()); #endif - } - FlashBuf = ""; - } + } + FlashBuf.clear(); + if (Video_Init_Len > 0) FlashBuf.append(Video_Init_Data, Video_Init_Len); + if (Audio_Init_Len > 0) FlashBuf.append(Audio_Init_Data, Audio_Init_Len); + } FlashBuf.append(tag->data,tag->len); } else { FlashMeta = ""; @@ -319,6 +318,8 @@ int mainHandler(int CONN_fd){ } } close(CONN_fd); + if (Video_Init_Data){free(Video_Init_Data);} + if (Audio_Init_Data){free(Audio_Init_Data);} if (inited) close(ss); #if DEBUG >= 1 if (All_Hell_Broke_Loose){fprintf(stderr, "All Hell Broke Loose\n");} diff --git a/HTTP_Box_Parser/Makefile b/HTTP_Box_Parser/Makefile new file mode 100644 index 00000000..6dd89381 --- /dev/null +++ b/HTTP_Box_Parser/Makefile @@ -0,0 +1,19 @@ +SRC = main.cpp +OBJ = $(SRC:.cpp=.o) +OUT = Box_Parser +INCLUDES = +CCFLAGS = -Wall -Wextra -funsigned-char -g +CC = $(CROSS)g++ +LD = $(CROSS)ld +AR = $(CROSS)ar +LIBS = -lssl -lcrypto +.SUFFIXES: .cpp +.PHONY: clean default +default: $(OUT) +.cpp.o: + $(CC) $(INCLUDES) $(CCFLAGS) -c $< -o $@ +$(OUT): $(OBJ) + $(CC) $(LIBS) -o $(OUT) $(OBJ) +clean: + rm -rf $(OBJ) $(OUT) Makefile.bak *~ + diff --git a/HTTP_Box_Parser/main.cpp b/HTTP_Box_Parser/main.cpp new file mode 100644 index 00000000..1d06741e --- /dev/null +++ b/HTTP_Box_Parser/main.cpp @@ -0,0 +1,46 @@ +#include +#include +#include +#include "../util/http_parser.cpp" +#include "../util/MP4/box_includes.h" +#include "../util/flv_data.cpp" + +std::string tagType(FLV_Pack * F){ + switch (F->data[0]){ + case 0x09: + if (F->isKeyframe){ + return "video keyframe"; + }else{ + return "video"; + } + break; + case 0x08: return "audio"; break; + case 0x12: return "data"; break; + } + return "unknown"; +} + +int main( ) { + std::string temp; + + HTTPReader H; + FLV_Pack * F = 0; + unsigned int P = 0; + + while (H.ReadSocket(stdin) || H.CleanForNext()){ + if (H.body.size() > 10000){ + Box * TestBox = new Box((uint8_t*)H.body.c_str(), H.body.size()); + TestBox->Parse(); + P = 0; + while (TestBox->PayloadSize > P){ + if (FLV_GetPacket(F, (char*)TestBox->Payload, TestBox->PayloadSize, P)){ + std::cout << "Got a " << F->len << " bytes " << tagType(F) << " FLV tag." << std::endl; + } + } + delete TestBox; + }else{ + std::cout << "Skipped too small fragment" << std::endl; + } + } + +} diff --git a/util/MP4/box.cpp b/util/MP4/box.cpp index be18b31e..46412680 100644 --- a/util/MP4/box.cpp +++ b/util/MP4/box.cpp @@ -46,7 +46,6 @@ class Box { uint8_t * Payload; BoxHeader header; uint32_t PayloadSize; - private: };//Box Class Box::Box() { @@ -176,3 +175,225 @@ void Box::ResetPayload( ) { 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"; + } +} + diff --git a/util/MP4/interface.cpp b/util/MP4/interface.cpp index 8437913b..56b63040 100644 --- a/util/MP4/interface.cpp +++ b/util/MP4/interface.cpp @@ -547,13 +547,13 @@ std::string Interface::GenerateLiveBootstrap( uint32_t CurMediaTime ) { afrt->SetUpdate(false); afrt->SetTimeScale( 1000 ); afrt->AddQualityEntry( "" ); - afrt->AddFragmentRunEntry( 1, 1 , 4000 ); + afrt->AddFragmentRunEntry( 1, 1 , 4000 ); //FirstFragment, FirstFragmentTimestamp,Fragment Duration in milliseconds afrt->WriteContent( ); //SetUpASRT asrt->SetUpdate(false); asrt->AddQualityEntry( "" ); - asrt->AddSegmentRunEntry( 1, 199 ); + asrt->AddSegmentRunEntry( 1, 199 );//1 Segment, 199 Fragments asrt->WriteContent( ); //SetUpABST @@ -562,9 +562,9 @@ std::string Interface::GenerateLiveBootstrap( uint32_t CurMediaTime ) { abst->SetLive( true ); abst->SetUpdate( false ); abst->SetTimeScale( 1000 ); - abst->SetMediaTime( 596458 ); + abst->SetMediaTime( CurMediaTime ); abst->SetSMPTE( 0 ); - abst->SetMovieIdentifier( "" ); + abst->SetMovieIdentifier( "fifa" ); abst->SetDRM( "" ); abst->SetMetaData( "" ); abst->AddServerEntry( "" ); diff --git a/util/ddv_socket.cpp b/util/ddv_socket.cpp index 0f26d36c..b1bd03e0 100644 --- a/util/ddv_socket.cpp +++ b/util/ddv_socket.cpp @@ -1,3 +1,4 @@ +#pragma once #include #include #include diff --git a/util/flv_data.cpp b/util/flv_data.cpp new file mode 100644 index 00000000..28a18da4 --- /dev/null +++ b/util/flv_data.cpp @@ -0,0 +1,90 @@ +#include //for read() +#include + +struct FLV_Pack { + int len; + int buf; + bool isKeyframe; + char * data; +};//FLV_Pack + +char FLVHeader[13]; +bool All_Hell_Broke_Loose = false; + +//checks FLV Header for correctness +//returns true if everything is alright, false otherwise +bool FLV_Checkheader(char * header){ + if (header[0] != 'F') return false; + if (header[1] != 'L') return false; + if (header[2] != 'V') return false; + if (header[8] != 0x09) return false; + if (header[9] != 0) return false; + if (header[10] != 0) return false; + if (header[11] != 0) return false; + if (header[12] != 0) return false; + return true; +}//FLV_Checkheader + +//returns true if header is an FLV header +bool FLV_Isheader(char * header){ + if (header[0] != 'F') return false; + if (header[1] != 'L') return false; + if (header[2] != 'V') return false; + return true; +}//FLV_Isheader + +bool ReadUntil(char * buffer, unsigned int count, unsigned int & sofar, char * D, unsigned int S, unsigned int & P){ + if (sofar >= count){return true;} + int r = 0; + if (P+(count-sofar) > S){r = S-P;}else{r = count-sofar;} + memcpy(buffer+sofar, D+P, r); + P += r; + sofar += r; + if (sofar >= count){return true;} + return false; +} + +//gets a packet, storing in given FLV_Pack pointer. +//will assign pointer if null +//resizes FLV_Pack data field bigger if data doesn't fit +// (does not auto-shrink for speed!) +bool FLV_GetPacket(FLV_Pack *& p, char * D, unsigned int S, unsigned int & P){ + static bool done = true; + static unsigned int sofar = 0; + if (!p){p = (FLV_Pack*)calloc(1, sizeof(FLV_Pack));} + if (p->buf < 15){p->data = (char*)realloc(p->data, 15000000); p->buf = 15000000;} + + if (done){ + //read a header + if (ReadUntil(p->data, 11, sofar, D, S, P)){ + //if its a correct FLV header, throw away and read tag header + if (FLV_Isheader(p->data)){ + if (ReadUntil(p->data, 13, sofar, D, S, P)){ + if (FLV_Checkheader(p->data)){ + sofar = 0; + memcpy(FLVHeader, p->data, 13); + }else{All_Hell_Broke_Loose = true;} + } + }else{ + //if a tag header, calculate length and read tag body + p->len = p->data[3] + 15; + p->len += (p->data[2] << 8); + p->len += (p->data[1] << 16); + //if (p->buf < p->len){p->data = (char*)realloc(p->data, p->len);p->buf = p->len;} + done = false; + } + } + }else{ + //read tag body + if (ReadUntil(p->data, p->len, sofar, D, S, P)){ + //calculate keyframeness, next time read header again, return true + p->isKeyframe = false; + if ((p->data[0] == 0x09) && (((p->data[11] & 0xf0) >> 4) == 1)){p->isKeyframe = true;} + done = true; + sofar = 0; + return true; + } + } + return false; +}//FLV_GetPacket + diff --git a/util/http_parser.cpp b/util/http_parser.cpp index 6f7d619f..36557fbd 100644 --- a/util/http_parser.cpp +++ b/util/http_parser.cpp @@ -1,10 +1,14 @@ +#pragma once +#include "ddv_socket.cpp" #include #include +#include class HTTPReader{ public: HTTPReader(); bool ReadSocket(int CONN_fd); + bool ReadSocket(FILE * F); std::string GetHeader(std::string i); std::string GetVar(std::string i); void SetHeader(std::string i, std::string v); @@ -18,6 +22,8 @@ class HTTPReader{ void SendBodyPart(int conn, char * buffer, int len); void SendBodyPart(int conn, std::string bodypart); void Clean(); + bool CleanForNext(); + std::string body; std::string method; std::string url; std::string protocol; @@ -39,12 +45,26 @@ void HTTPReader::Clean(){ method = "GET"; url = "/"; protocol = "HTTP/1.1"; + body = ""; length = 0; HTTPbuffer = ""; headers.erase(headers.begin(), headers.end()); vars.erase(vars.begin(), vars.end()); } +bool HTTPReader::CleanForNext(){ + seenHeaders = false; + seenReq = false; + method = "GET"; + url = "/"; + protocol = "HTTP/1.1"; + body = ""; + length = 0; + headers.erase(headers.begin(), headers.end()); + vars.erase(vars.begin(), vars.end()); + return parse(); +} + std::string HTTPReader::BuildRequest(){ std::map::iterator it; std::string tmp = method+" "+url+" "+protocol+"\n"; @@ -129,6 +149,16 @@ bool HTTPReader::ReadSocket(int CONN_fd){ return false; }//HTTPReader::ReadSocket +bool HTTPReader::ReadSocket(FILE * F){ + //returned true als hele http packet gelezen is + int b = 1; + char buffer[500]; + while (b > 0){ + b = fread(buffer, 1, 500, F); + HTTPbuffer.append(buffer, b); + } + return false; +}//HTTPReader::ReadSocket bool HTTPReader::parse(){ size_t f; @@ -148,7 +178,7 @@ bool HTTPReader::parse(){ if (f != std::string::npos){url = tmpA.substr(0, f); tmpA.erase(0, f+1);} f = tmpA.find(' '); if (f != std::string::npos){protocol = tmpA.substr(0, f); tmpA.erase(0, f+1);} - //TODO: GET variable parsing + //TODO: GET variable parsing? }else{ if (tmpA.size() == 0){ seenHeaders = true; @@ -164,8 +194,14 @@ bool HTTPReader::parse(){ } if (seenHeaders){ if (length > 0){ - //TODO: POST variable parsing - return (HTTPbuffer.length() >= length); + //TODO: POST variable parsing? + if (HTTPbuffer.length() >= length){ + body = HTTPbuffer.substr(0, length); + HTTPbuffer.erase(0, length); + return true; + }else{ + return false; + } }else{ return true; }