diff --git a/lib/dtsc.cpp b/lib/dtsc.cpp index b6437520..e73a26fe 100644 --- a/lib/dtsc.cpp +++ b/lib/dtsc.cpp @@ -79,7 +79,7 @@ bool DTSC::Stream::parsePacket(std::string & buffer){ newPack = JSON::fromDTMI((unsigned char*)buffer.c_str() + 8, len, i); } if (version == 2){ - newPack = JSON::fromDTMI2(buffer.substr(8)); + newPack = JSON::fromDTMI2((unsigned char*)buffer.c_str() + 8, len, i); } addPacket(newPack); syncing = false; @@ -124,17 +124,17 @@ bool DTSC::Stream::parsePacket(Socket::Buffer & buffer){ std::string wholepacket = buffer.remove(len + 8); metadata = JSON::fromDTMI((unsigned char*)wholepacket.c_str() + 8, len, i); metadata.removeMember("moreheader"); - metadata.netPrepare(); - trackMapping.clear(); + if (buffercount > 1){ + metadata.netPrepare(); + } if (metadata.isMember("tracks")){ + trackMapping.clear(); for (JSON::ObjIter it = metadata["tracks"].ObjBegin(); it != metadata["tracks"].ObjEnd(); it++){ trackMapping.insert(std::pair(it->second["trackid"].asInt(),it->first)); } } - if ( !buffer.available(8)){ - return false; - } - header_bytes = buffer.copy(8); + //recursively calls itself until failure or data packet instead of header + return parsePacket(buffer); } int version = 0; if (memcmp(header_bytes.c_str(), DTSC::Magic_Packet, 4) == 0){ @@ -155,7 +155,7 @@ bool DTSC::Stream::parsePacket(Socket::Buffer & buffer){ newPack = JSON::fromDTMI((unsigned char*)wholepacket.c_str() + 8, len, i); } if (version == 2){ - newPack = JSON::fromDTMI2(wholepacket.substr(8)); + newPack = JSON::fromDTMI2((unsigned char*)wholepacket.c_str() + 8, len, i); } addPacket(newPack); syncing = false; @@ -229,11 +229,17 @@ void DTSC::Stream::addPacket(JSON::Value & newPack){ //increase buffer size if no keyframes available or too little time available timeBuffered = buffers.rbegin()->second["time"].asInt() - buffers.begin()->second["time"].asInt(); } - if (buffercount > 1 && (keyframes.size() < 2 || timeBuffered < buffertime)){ + if (buffercount > 1 && timeBuffered < buffertime){ buffercount++; } while (buffers.size() > buffercount){ if (keyframes[buffers.begin()->first.trackID].count(buffers.begin()->first)){ + //if there are < 3 keyframes, throwing one away would mean less than 2 left. + if (keyframes[buffers.begin()->first.trackID].size() < 3){ + //so, we don't throw it away but instead increase the buffer size + buffercount++; + break; + } std::string track = trackMapping[buffers.begin()->first.trackID]; keyframes[buffers.begin()->first.trackID].erase(buffers.begin()->first); int keySize = metadata["tracks"][track]["keys"].size(); diff --git a/lib/json.cpp b/lib/json.cpp index 59bf8b13..84b76de1 100644 --- a/lib/json.cpp +++ b/lib/json.cpp @@ -816,8 +816,14 @@ JSON::Value JSON::fromDTMI(const unsigned char * data, unsigned int len, unsigne #if DEBUG >= 10 fprintf(stderr, "Note: AMF type %hhx found. %i bytes left\n", data[i], len-i); #endif + if (i >= len){ + return JSON::Value(); + } switch (data[i]){ case 0x01: { //integer + if (i+8 >= len){ + return JSON::Value(); + } unsigned char tmpdbl[8]; tmpdbl[7] = data[i + 1]; tmpdbl[6] = data[i + 2]; @@ -833,8 +839,14 @@ JSON::Value JSON::fromDTMI(const unsigned char * data, unsigned int len, unsigne } break; case 0x02: { //string + if (i+4 >= len){ + return JSON::Value(); + } unsigned int tmpi = data[i + 1] * 256 * 256 * 256 + data[i + 2] * 256 * 256 + data[i + 3] * 256 + data[i + 4]; //set tmpi to UTF-8-long length std::string tmpstr = std::string((const char *)data + i + 5, (size_t)tmpi); //set the string data + if (i+4+tmpi >= len){ + return JSON::Value(); + } i += tmpi + 5; //skip length+size+1 forwards return JSON::Value(tmpstr); } @@ -843,7 +855,10 @@ JSON::Value JSON::fromDTMI(const unsigned char * data, unsigned int len, unsigne case 0xE0: { //object ++i; JSON::Value ret; - while (data[i] + data[i + 1] != 0){ //while not encountering 0x0000 (we assume 0x0000EE) + while (data[i] + data[i + 1] != 0 && i < len){ //while not encountering 0x0000 (we assume 0x0000EE) + if (i+2 >= len){ + return JSON::Value(); + } unsigned int tmpi = data[i] * 256 + data[i + 1]; //set tmpi to the UTF-8 length std::string tmpstr = std::string((const char *)data + i + 2, (size_t)tmpi); //set the string data i += tmpi + 2; //skip length+size forwards @@ -856,7 +871,7 @@ JSON::Value JSON::fromDTMI(const unsigned char * data, unsigned int len, unsigne case 0x0A: { //array JSON::Value ret; ++i; - while (data[i] + data[i + 1] != 0){ //while not encountering 0x0000 (we assume 0x0000EE) + while (data[i] + data[i + 1] != 0 && i < len){ //while not encountering 0x0000 (we assume 0x0000EE) ret.append(fromDTMI(data, len, i)); //add content, recursively parsed, updating i } i += 3; //skip 0x0000EE @@ -865,8 +880,9 @@ JSON::Value JSON::fromDTMI(const unsigned char * data, unsigned int len, unsigne break; } #if DEBUG >= 2 - fprintf(stderr, "Error: Unimplemented DTMI type %hhx - returning.\n", data[i]); + fprintf(stderr, "Error: Unimplemented DTMI type %hhx, @ %i / %i - returning.\n", data[i], i, len); #endif + i += 1; return JSON::Value(); } //fromOneDTMI @@ -887,3 +903,17 @@ JSON::Value JSON::fromDTMI2(std::string data){ tmp["trackid"] = tmpTrackID; return tmp; } + +JSON::Value JSON::fromDTMI2(const unsigned char * data, unsigned int len, unsigned int &i){ + JSON::Value tmp; + if (len < 13){return tmp;} + long long int tmpTrackID = ntohl(((int*)data)[0]); + long long int tmpTime = ntohl(((int*)data)[1]); + tmpTime << 32; + tmpTime += ntohl(((int*)data)[2]); + i += 12; + tmp = fromDTMI(data, len, i); + tmp["time"] = tmpTime; + tmp["trackid"] = tmpTrackID; + return tmp; +} diff --git a/lib/json.h b/lib/json.h index f54e7384..65aca525 100644 --- a/lib/json.h +++ b/lib/json.h @@ -94,6 +94,7 @@ namespace JSON { }; Value fromDTMI2(std::string data); + Value fromDTMI2(const unsigned char * data, unsigned int len, unsigned int &i); Value fromDTMI(std::string data); Value fromDTMI(const unsigned char * data, unsigned int len, unsigned int &i); Value fromString(std::string json);