From 97357aed9866e0d24bf4b976d2304c8d9f3b9379 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Mon, 21 Mar 2011 18:23:32 +0100 Subject: [PATCH] New FLV_Pack style, hopefully some fixes for HTTP dynamic --- Connector_HTTP/main.cpp | 64 ++++++++++---------- Connector_RTMP/Makefile | 6 +- HTTP_Box_Parser/main.cpp | 23 +------- util/flv.cpp | 8 +-- util/flv_data.cpp | 8 +-- util/flv_pack.cpp | 123 +++++++++++++++++++++++++++++++++++++++ util/flv_sock.cpp | 8 +-- 7 files changed, 163 insertions(+), 77 deletions(-) create mode 100644 util/flv_pack.cpp diff --git a/Connector_HTTP/main.cpp b/Connector_HTTP/main.cpp index 8d0bd18f..a0bf743a 100644 --- a/Connector_HTTP/main.cpp +++ b/Connector_HTTP/main.cpp @@ -46,15 +46,6 @@ std::string base64_encode(std::string const input) { return ret; }//base64_encode -int FlvToFragNum( FLV_Pack * tag ) { - int Timestamp = (tag->data[7] << 24 ) + (tag->data[4] << 16 ) + (tag->data[5] << 8 ) + (tag->data[6] ); - return (Timestamp / 10000) + 1; -} - -int FlvGetTimestamp( FLV_Pack * tag ) { - return ( (tag->data[7] << 24 ) + (tag->data[4] << 16 ) + (tag->data[5] << 8 ) + (tag->data[6] ) ); -} - std::string GetMetaData( ) { AMFType amfreply("container", (unsigned char)AMF0_DDV_CONTAINER); amfreply.addContent(AMFType("onMetaData",(unsigned char)AMF0_STRING)); @@ -128,12 +119,13 @@ int mainHandler(int CONN_fd){ std::string FlashMeta; bool Flash_ManifestSent = false; int Flash_RequestPending = 0; + unsigned int Flash_StartTime; std::queue 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; + FLV_Pack Audio_Init; + FLV_Pack Video_Init; + bool FlashFirstVideo = false; + bool FlashFirstAudio = false; HTTPReader HTTP_R, HTTP_S;//HTTP Receiver en HTTP Sender. int retval; @@ -253,25 +245,23 @@ int mainHandler(int CONN_fd){ default: if (FLV_GetPacket(tag, ss)){//able to read a full packet?f if (handler == HANDLER_FLASH){ - if(tag->data[0] != 0x12 ) { - if ((tag->isKeyframe) && (Video_Init_Data == 0)){ + if (tag->tagTime() > 0){ + if (Flash_StartTime == 0){ + Flash_StartTime = tag->tagTime(); + } + tag->tagTime(tag->tagTime() - Flash_StartTime); + } + if (tag->data[0] != 0x12 ) { + if ((tag->isKeyframe) && (Video_Init.len == 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); + tag->tagTime(0);//timestamp to zero + Video_Init = *tag; } } - if ((tag->data[0] == 0x08) && (Audio_Init_Data == 0)){ + if ((tag->data[0] == 0x08) && (Audio_Init.len == 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); + tag->tagTime(0);//timestamp to zero + Audio_Init = *tag; } } if (tag->isKeyframe){ @@ -282,8 +272,18 @@ int mainHandler(int CONN_fd){ #endif } 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); + FlashFirstVideo = true; + FlashFirstAudio = true; + } + if (FlashFirstVideo && (tag->data[0] == 0x09) && (Video_Init.len > 0)){ + Video_Init.tagTime(tag->tagTime()); + FlashBuf.append(Video_Init.data, Video_Init.len); + FlashFirstVideo = false; + } + if (FlashFirstAudio && (tag->data[0] == 0x08) && (Audio_Init.len > 0)){ + Audio_Init.tagTime(tag->tagTime()); + FlashBuf.append(Audio_Init.data, Audio_Init.len); + FlashFirstAudio = false; } FlashBuf.append(tag->data,tag->len); } else { @@ -293,7 +293,7 @@ int mainHandler(int CONN_fd){ HTTP_S.Clean(); HTTP_S.SetHeader("Content-Type","text/xml"); HTTP_S.SetHeader("Cache-Control","no-cache"); - HTTP_S.SetBody(BuildManifest(FlashMeta, Movie, FlvGetTimestamp(tag))); + HTTP_S.SetBody(BuildManifest(FlashMeta, Movie, tag->tagTime())); HTTP_S.SendResponse(CONN_fd, "200", "OK"); } } @@ -318,8 +318,6 @@ 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/Connector_RTMP/Makefile b/Connector_RTMP/Makefile index c74dc1aa..71f3ffb0 100644 --- a/Connector_RTMP/Makefile +++ b/Connector_RTMP/Makefile @@ -1,7 +1,8 @@ SRC = main.cpp OBJ = $(SRC:.cpp=.o) OUT = Connector_RTMP -INCLUDES = +INCLUDES = +STATIC = CCFLAGS = -Wall -Wextra -funsigned-char -g CC = $(CROSS)g++ LD = $(CROSS)ld @@ -13,7 +14,7 @@ default: $(OUT) .cpp.o: $(CC) $(INCLUDES) $(CCFLAGS) -c $< -o $@ $(OUT): $(OBJ) chunkstream.cpp parsechunks.cpp handshake.cpp crypto.cpp amf.cpp - $(CC) $(LIBS) -o $(OUT) $(OBJ) + $(CC) -o $(OUT) $(OBJ) $(STATIC) $(LIBS) clean: rm -rf $(OBJ) $(OUT) Makefile.bak *~ install: $(OUT) @@ -21,3 +22,4 @@ install: $(OUT) cp -f ./$(OUT) /usr/bin/ cp -f ./RTMP_Conn /etc/init.d/ service RTMP_Conn start + diff --git a/HTTP_Box_Parser/main.cpp b/HTTP_Box_Parser/main.cpp index 1d06741e..1be5951a 100644 --- a/HTTP_Box_Parser/main.cpp +++ b/HTTP_Box_Parser/main.cpp @@ -5,24 +5,7 @@ #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; - +int main(){ HTTPReader H; FLV_Pack * F = 0; unsigned int P = 0; @@ -30,11 +13,10 @@ int main( ) { 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; + std::cout << "Got a " << F->len << " bytes " << F->tagType() << " FLV tag of time " << F->tagTime() << "." << std::endl; } } delete TestBox; @@ -42,5 +24,4 @@ int main( ) { std::cout << "Skipped too small fragment" << std::endl; } } - } diff --git a/util/flv.cpp b/util/flv.cpp index c04d977a..8780077d 100644 --- a/util/flv.cpp +++ b/util/flv.cpp @@ -1,12 +1,6 @@ #include //for read() #include - -struct FLV_Pack { - int len; - int buf; - bool isKeyframe; - char * data; -};//FLV_Pack +#include "flv_pack.cpp" char FLVHeader[13]; bool All_Hell_Broke_Loose = false; diff --git a/util/flv_data.cpp b/util/flv_data.cpp index 28a18da4..ac176ee5 100644 --- a/util/flv_data.cpp +++ b/util/flv_data.cpp @@ -1,12 +1,6 @@ #include //for read() #include - -struct FLV_Pack { - int len; - int buf; - bool isKeyframe; - char * data; -};//FLV_Pack +#include "flv_pack.cpp" char FLVHeader[13]; bool All_Hell_Broke_Loose = false; diff --git a/util/flv_pack.cpp b/util/flv_pack.cpp new file mode 100644 index 00000000..a60bf6a5 --- /dev/null +++ b/util/flv_pack.cpp @@ -0,0 +1,123 @@ +#pragma once + +class FLV_Pack { + public: + int len; + int buf; + bool isKeyframe; + char * data; + std::string tagType(){ + std::string R = ""; + switch (data[0]){ + case 0x09: + switch (data[11] & 0x0F){ + case 1: R += "JPEG"; break; + case 2: R += "H263"; break; + case 3: R += "ScreenVideo1"; break; + case 4: R += "VP6"; break; + case 5: R += "VP6Alpha"; break; + case 6: R += "ScreenVideo2"; break; + case 7: R += "AVC"; break; + default: R += "unknown"; break; + } + R += " video "; + switch (data[11] & 0xF0){ + case 0x10: R += "keyframe"; break; + case 0x20: R += "iframe"; break; + case 0x30: R += "disposableiframe"; break; + case 0x40: R += "generatedkeyframe"; break; + case 0x50: R += "videoinfo"; break; + } + if ((data[11] & 0x0F) == 7){ + switch (data[12]){ + case 0: R += " header"; break; + case 1: R += " NALU"; break; + case 2: R += " endofsequence"; break; + } + } + break; + case 0x08: + switch (data[11] & 0xF0){ + case 0x00: R += "linear PCM PE"; break; + case 0x10: R += "ADPCM"; break; + case 0x20: R += "MP3"; break; + case 0x30: R += "linear PCM LE"; break; + case 0x40: R += "Nelly16kHz"; break; + case 0x50: R += "Nelly8kHz"; break; + case 0x60: R += "Nelly"; break; + case 0x70: R += "G711A-law"; break; + case 0x80: R += "G711mu-law"; break; + case 0x90: R += "reserved"; break; + case 0xA0: R += "AAC"; break; + case 0xB0: R += "Speex"; break; + case 0xE0: R += "MP38kHz"; break; + case 0xF0: R += "DeviceSpecific"; break; + default: R += "unknown"; break; + } + switch (data[11] & 0x0C){ + case 0x0: R += " 5.5kHz"; break; + case 0x4: R += " 11kHz"; break; + case 0x8: R += " 22kHz"; break; + case 0xC: R += " 44kHz"; break; + } + switch (data[11] & 0x02){ + case 0: R += " 8bit"; break; + case 2: R += " 16bit"; break; + } + switch (data[11] & 0x01){ + case 0: R += " mono"; break; + case 1: R += " stereo"; break; + } + R += " audio"; + if ((data[12] == 0) && ((data[11] & 0xF0) == 0xA0)){ + R += " initdata"; + } + break; + case 0x12: + R += "(meta)data"; + break; + default: + R += "unknown"; + break; + } + return R; + };//tagtype + unsigned int tagTime(){ + return (data[4] << 16) + (data[5] << 8) + data[6] + (data[7] << 24); + }//tagTime getter + void tagTime(unsigned int T){ + data[4] = ((T >> 16) & 0xFF); + data[5] = ((T >> 8) & 0xFF); + data[6] = (T & 0xFF); + data[7] = ((T >> 24) & 0xFF); + }//tagTime setter + FLV_Pack(){ + len = 0; buf = 0; data = 0; isKeyframe = false; + }//empty constructor + FLV_Pack(const FLV_Pack& O){ + buf = O.len; + len = buf; + if (len > 0){ + data = (char*)malloc(len); + memcpy(data, O.data, len); + }else{ + data = 0; + } + isKeyframe = O.isKeyframe; + }//copy constructor + FLV_Pack & operator= (const FLV_Pack& O){ + if (this != &O){//no self-assignment + if (data != 0){free(data);} + buf = O.len; + len = buf; + if (len > 0){ + data = (char*)malloc(len); + memcpy(data, O.data, len); + }else{ + data = 0; + } + isKeyframe = O.isKeyframe; + } + return *this; + }//assignment operator +};//FLV_Pack diff --git a/util/flv_sock.cpp b/util/flv_sock.cpp index be752d73..8b74c9aa 100644 --- a/util/flv_sock.cpp +++ b/util/flv_sock.cpp @@ -1,10 +1,4 @@ - -struct FLV_Pack { - int len; - int buf; - bool isKeyframe; - char * data; -};//FLV_Pack +#include "flv_pack.cpp" char FLVHeader[13]; bool All_Hell_Broke_Loose = false;