diff --git a/lib/dtsc.cpp b/lib/dtsc.cpp index bb846123..3d0a64e0 100644 --- a/lib/dtsc.cpp +++ b/lib/dtsc.cpp @@ -7,6 +7,7 @@ #include //for htonl/ntohl char DTSC::Magic_Header[] = "DTSC"; char DTSC::Magic_Packet[] = "DTPD"; +char DTSC::Magic_Packet2[] = "DTP2"; /// Initializes a DTSC::Stream with only one packet buffer. DTSC::Stream::Stream(){ @@ -92,6 +93,49 @@ bool DTSC::Stream::parsePacket(std::string & buffer){ syncing = false; return true; } + if (memcmp(buffer.c_str(), DTSC::Magic_Packet2, 4) == 0){ + len = ntohl(((uint32_t *)buffer.c_str())[1]); + if (buffer.length() < len + 20){ + return false; + } + buffers.push_front(JSON::Value()); + unsigned int i = 0; + long long int tmpTrackID = ntohl(((int*)(buffer.c_str() + 8))[0]); + long long int tmpTime = ntohl(((int*)(buffer.c_str() + 12))[0]); + tmpTime << 32; + tmpTime += ntohl(((int*)(buffer.c_str() + 16))[0]); + buffers.front() = JSON::fromDTMI((unsigned char*)buffer.c_str() + 20, len, i); + buffers.front()["time"] = tmpTime; + buffers.front()["trackid"] = tmpTrackID; + datapointertype = INVALID; + if (buffers.front().isMember("data")){ + datapointer = &(buffers.front()["data"].strVal); + }else{ + datapointer = 0; + } + if (buffers.front().isMember("datatype")){ + std::string tmp = buffers.front()["datatype"].asString(); + if (tmp == "video"){ + datapointertype = VIDEO; + } + if (tmp == "audio"){ + datapointertype = AUDIO; + } + if (tmp == "meta"){ + datapointertype = META; + } + if (tmp == "pause_marker"){ + datapointertype = PAUSEMARK; + } + } + buffer.erase(0, len + 20); + while (buffers.size() > buffercount){ + buffers.pop_back(); + } + advanceRings(); + syncing = false; + return true; + } #if DEBUG >= 2 if (!syncing){ std::cerr << "Error: Invalid DTMI data detected - re-syncing" << std::endl; @@ -99,10 +143,15 @@ bool DTSC::Stream::parsePacket(std::string & buffer){ } #endif size_t magic_search = buffer.find(Magic_Packet); - if (magic_search == std::string::npos){ - buffer.clear(); + size_t magic_search2 = buffer.find(Magic_Packet2); + if (magic_search2 == std::string::npos){ + if (magic_search == std::string::npos){ + buffer.clear(); + }else{ + buffer.erase(0, magic_search); + } }else{ - buffer.erase(0, magic_search); + buffer.erase(0, magic_search2); } } return false; @@ -169,6 +218,49 @@ bool DTSC::Stream::parsePacket(Socket::Buffer & buffer){ syncing = false; return true; } + if (memcmp(header_bytes.c_str(), DTSC::Magic_Packet2, 4) == 0){ + len = ntohl(((uint32_t *)header_bytes.c_str())[1]); + if ( !buffer.available(len + 20)){ + return false; + } + buffers.push_front(JSON::Value()); + unsigned int i = 0; + std::string wholepacket = buffer.remove(len + 20); + long long int tmpTrackID = ntohl(((int*)(wholepacket.c_str() + 8))[0]); + long long int tmpTime = ntohl(((int*)(wholepacket.c_str() + 12))[0]); + tmpTime << 32; + tmpTime += ntohl(((int*)(wholepacket.c_str() + 16))[0]); + buffers.front() = JSON::fromDTMI((unsigned char*)wholepacket.c_str() + 20, len, i); + buffers.front()["time"] = tmpTime; + buffers.front()["trackid"] = tmpTrackID; + datapointertype = INVALID; + if (buffers.front().isMember("data")){ + datapointer = &(buffers.front()["data"].strVal); + }else{ + datapointer = 0; + } + if (buffers.front().isMember("datatype")){ + std::string tmp = buffers.front()["datatype"].asString(); + if (tmp == "video"){ + datapointertype = VIDEO; + } + if (tmp == "audio"){ + datapointertype = AUDIO; + } + if (tmp == "meta"){ + datapointertype = META; + } + if (tmp == "pause_marker"){ + datapointertype = PAUSEMARK; + } + } + while (buffers.size() > buffercount){ + buffers.pop_back(); + } + advanceRings(); + syncing = false; + return true; + } #if DEBUG >= 2 if (!syncing){ std::cerr << "Error: Invalid DTMI data detected - syncing" << std::endl; @@ -648,8 +740,15 @@ void DTSC::File::seekNext(){ jsonbuffer = metadata; return; } - if (memcmp(buffer, DTSC::Magic_Packet, 4) != 0){ - fprintf(stderr, "Invalid header - %.4s != %.4s\n", buffer, DTSC::Magic_Packet); + long long unsigned int version = 0; + if (memcmp(buffer, DTSC::Magic_Packet, 4) == 0){ + version = 1; + } + if (memcmp(buffer, DTSC::Magic_Packet2, 4) == 0){ + version = 2; + } + if (version == 0){ + fprintf(stderr, "Invalid header - %.4s != %.4s\n", buffer, DTSC::Magic_Packet2); strbuffer = ""; jsonbuffer.null(); return; @@ -661,7 +760,7 @@ void DTSC::File::seekNext(){ return; } uint32_t * ubuffer = (uint32_t *)buffer; - long packSize = ntohl(ubuffer[0]); + long packSize = ntohl(ubuffer[0]) + (version == 2 ? 12 : 0); strbuffer.resize(packSize); if (fread((void*)strbuffer.c_str(), packSize, 1, F) != 1){ fprintf(stderr, "Could not read packet\n"); @@ -669,6 +768,9 @@ void DTSC::File::seekNext(){ jsonbuffer.null(); return; } + if (version == 2){ + strbuffer.erase(0,12); + } jsonbuffer = JSON::fromDTMI(strbuffer); if (jsonbuffer.isMember("keyframe")){ if (frames[currframe] != lastreadpos){ diff --git a/lib/dtsc.h b/lib/dtsc.h index cfa8bc08..cb9d392e 100644 --- a/lib/dtsc.h +++ b/lib/dtsc.h @@ -62,6 +62,7 @@ namespace DTSC { extern char Magic_Header[]; ///< The magic bytes for a DTSC header extern char Magic_Packet[]; ///< The magic bytes for a DTSC packet + extern char Magic_Packet2[]; ///< The magic bytes for a DTSC packet version 2 /// A simple wrapper class that will open a file and allow easy reading/writing of DTSC data from/to it. class File{ diff --git a/lib/json.cpp b/lib/json.cpp index dc6b3da2..0b3db6fc 100644 --- a/lib/json.cpp +++ b/lib/json.cpp @@ -475,18 +475,53 @@ void JSON::Value::netPrepare(){ return; } std::string packed = toPacked(); - strVal.resize(packed.size() + 8); //insert proper header for this type of data + int packID = -1; + long long unsigned int time = objVal["time"].asInt(); + std::string dataType = objVal["datatype"].asString(); if (isMember("datatype")){ - memcpy((void*)strVal.c_str(), "DTPD", 4); + if (isMember("trackid")){ + packID = objVal["trackid"].asInt(); + }else{ + if (objVal["datatype"].asString() == "video"){ + packID = 1; + } + if (objVal["datatype"].asString() == "audio"){ + packID = 2; + } + if (objVal["datatype"].asString() == "meta"){ + packID = 3; + } + if (packID == -1){ + packID = 0; + } + } + removeMember("time"); + removeMember("datatype"); + packed = toPacked(); + objVal["time"] = (long long int)time; + objVal["datatype"] = dataType; + strVal.resize(packed.size() + 20); + memcpy((void*)strVal.c_str(), "DTP2", 4); }else{ + strVal.resize(packed.size() + 8); memcpy((void*)strVal.c_str(), "DTSC", 4); } //insert the packet length at bytes 4-7 unsigned int size = htonl(packed.size()); memcpy((void*)(strVal.c_str() + 4), (void*) &size, 4); //copy the rest of the string - memcpy((void*)(strVal.c_str() + 8), packed.c_str(), packed.size()); + if (packID != -1){ + packID = htonl((int)packID); + memcpy((void*)(strVal.c_str() + 8), (void*) &packID, 4); + int tmpHalf = htonl((int)(time >> 32)); + memcpy((void*)(strVal.c_str() + 12), (void*) &tmpHalf, 4); + tmpHalf = htonl((int)(time & 0xFFFFFFFF)); + memcpy((void*)(strVal.c_str() + 16), (void*) &tmpHalf, 4); + memcpy((void*)(strVal.c_str() + 20), packed.c_str(), packed.size()); + }else{ + memcpy((void*)(strVal.c_str() + 8), packed.c_str(), packed.size()); + } } /// Packs any object-type JSON::Value to a std::string for transfer over the network, including proper DTMI header.