diff --git a/lib/dtsc.h b/lib/dtsc.h index 5eea2682..fdbf984b 100644 --- a/lib/dtsc.h +++ b/lib/dtsc.h @@ -13,6 +13,12 @@ #include "socket.h" #include "timing.h" +#define DTSC_INT 0x01 +#define DTSC_STR 0x02 +#define DTSC_OBJ 0xE0 +#define DTSC_ARR 0x0A +#define DTSC_CON 0xFF + namespace DTSC { bool isFixed(JSON::Value & metadata); @@ -59,6 +65,26 @@ namespace DTSC { DTSC_V2 }; + /// This class allows scanning through raw binary format DTSC data. + /// It can be used as an iterator or as a direct accessor. + class Scan{ + public: + Scan(); + Scan(char * pointer, size_t len); + std::string toPrettyString(unsigned int indent = 0); + Scan getMember(std::string indice); + Scan getIndice(unsigned int num); + + char getType(); + bool asBool(); + long long asInt(); + std::string asString(); + void getString(char *& result, unsigned int & len); + private: + char * p; + size_t len; + }; + /// DTSC::Packets can currently be three types: /// DTSC_HEAD packets are the "DTSC" header string, followed by 4 bytes len and packed content. /// DTSC_V1 packets are "DTPD", followed by 4 bytes len and packed content. @@ -73,30 +99,31 @@ namespace DTSC { void null(); void operator = (const Packet & rhs); operator bool() const; - packType getVersion(); + packType getVersion() const; void reInit(const char * data_, unsigned int len, bool noCopy = false); - void getString(const char * identifier, char *& result, int & len); - void getString(const char * identifier, std::string & result); - void getInt(const char * identifier, int & result); - int getInt(const char * identifier); - void getFlag(const char * identifier, bool & result); - bool getFlag(const char * identifier); - bool hasMember(const char * identifier); - long long unsigned int getTime(); - long int getTrackId(); - char * getData(); - int getDataLen(); - JSON::Value toJSON(); + void getString(const char * identifier, char *& result, unsigned int & len) const; + void getString(const char * identifier, std::string & result) const; + void getInt(const char * identifier, int & result) const; + int getInt(const char * identifier) const; + void getFlag(const char * identifier, bool & result) const; + bool getFlag(const char * identifier) const; + bool hasMember(const char * identifier) const; + long long unsigned int getTime() const; + long int getTrackId() const; + char * getData() const; + int getDataLen() const; + int getPayloadLen() const; + JSON::Value toJSON() const; + Scan getScan() const; protected: bool master; packType version; - char * findIdentifier(const char * identifier); void resize(unsigned int size); char * data; unsigned int bufferLen; unsigned int dataLen; }; - + /// A simple structure used for ordering byte seek positions. struct livePos { livePos() { @@ -255,6 +282,7 @@ namespace DTSC { Track(); Track(const readOnlyTrack & rhs); Track(JSON::Value & trackRef); + Track(Scan & trackRef); inline operator bool() const { return parts.size(); } @@ -298,9 +326,10 @@ namespace DTSC { class Meta : public readOnlyMeta { public: Meta(); + Meta(const DTSC::Packet & source); Meta(const readOnlyMeta & meta); Meta(JSON::Value & meta); - std::map tracks; + void reinit(const DTSC::Packet & source); void update(DTSC::Packet & pack); void update(JSON::Value & pack); unsigned int getSendLen(); @@ -310,6 +339,8 @@ namespace DTSC { void reset(); bool isFixed(); void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0); + //members: + std::map tracks; }; /// A simple wrapper class that will open a file and allow easy reading/writing of DTSC data from/to it. diff --git a/lib/dtscmeta.cpp b/lib/dtscmeta.cpp index 5b5adb41..d6057658 100644 --- a/lib/dtscmeta.cpp +++ b/lib/dtscmeta.cpp @@ -4,7 +4,6 @@ #include #include - /// Retrieves a short in network order from the pointer p. static short btohs(char * p) { return (p[0] << 8) + p[1]; @@ -96,7 +95,7 @@ namespace DTSC { /// Returns the recognized packet type. /// This type is set by reInit and all constructors, and then just referenced from there on. - packType Packet::getVersion(){ + packType Packet::getVersion() const{ return version; } @@ -183,132 +182,78 @@ namespace DTSC { } } - /// Helper function for findIdentifier - static char * findInside(const char * identifier, char *& p, char * max){ + /// Helper function for skipping over whole DTSC parts + static char * skipDTSC(char * p, char * max){ if (p+1 >= max || p[0] == 0x00){ - return (char*)1;//out of packet! 1 == error + return 0;//out of packet! 1 == error } - if (p[0] == 0x01){ + if (p[0] == DTSC_INT){ //int, skip 9 bytes to next value - p+=9; - return 0; + return p+9; } - if (p[0] == 0x02){ + if (p[0] == DTSC_STR){ if (p+4 >= max){ - return (char*)1;//out of packet! 1 == error + return 0;//out of packet! } - //string, read size and skip to next value - unsigned int tmpi = p[1] * 256 * 256 * 256 + p[2] * 256 * 256 + p[3] * 256 + p[4]; - p += tmpi + 5; - return 0; + return p + 5 + p[1] * 256 * 256 * 256 + p[2] * 256 * 256 + p[3] * 256 + p[4]; } - if (p[0] == 0xE0 || p[0] == 0xFF){ + if (p[0] == DTSC_OBJ || p[0] == DTSC_CON){ p++; - unsigned int id_len = strlen(identifier); //object, scan contents while (p[0] + p[1] != 0 && p < max){ //while not encountering 0x0000 (we assume 0x0000EE) if (p+2 >= max){ - return (char*)1;//out of packet! 1 == error + return 0;//out of packet! } - unsigned int tmpi = p[0] * 256 + p[1]; //set tmpi to the UTF-8 length - //compare the name, if match, return contents - if (tmpi == id_len){ - if (memcmp(p+2, identifier, tmpi) == 0){ - return p+2+tmpi; - } - } - p += 2+tmpi;//skip size + p += 2 + (p[0] * 256 + p[1]);//skip size //otherwise, search through the contents, if needed, and continue - char * tmp_ret = findInside(identifier, p, max); - if (tmp_ret){ - return tmp_ret; + p = skipDTSC(p, max); + if (!p){ + return 0; } } - p += 3;//skip end marker - return 0; + return p+3; } - if (p[0] == 0x0A){ + if (p[0] == DTSC_ARR){ p++; //array, scan contents while (p[0] + p[1] != 0 && p < max){ //while not encountering 0x0000 (we assume 0x0000EE) //search through contents... - char * tmp_ret = findInside(identifier, p, max); - if (tmp_ret){ - return tmp_ret; + p = skipDTSC(p, max); + if (!p){ + return 0; } - //no match, continue search } - p += 3; //skip end marker - return 0; + return p + 3; //skip end marker } - DEBUG_MSG(DLVL_FAIL, "Unimplemented DTMI type %hhx, @ %p / %p - returning.", p[0], p, max); - return (char*)1;//out of packet! 1 == error - } - - ///\brief Locates an identifier within the payload - ///\param identifier The identifier to find - ///\return A pointer to the location of the identifier - char * Packet::findIdentifier(const char * identifier){ - char * p = data; - if (version == DTSC_V2){ - p += 20; - }else{ - p += 8; - } - char * ret = findInside(identifier, p, data+dataLen); - return ret; + return 0;//out of packet! 1 == error } ///\brief Retrieves a single parameter as a string ///\param identifier The name of the parameter ///\param result A location on which the string will be returned ///\param len An integer in which the length of the string will be returned - void Packet::getString(const char * identifier, char *& result, int & len) { - char * pos = findIdentifier(identifier); - if (pos < (char*)2) { - result = NULL; - len = 0; - return; - } - if (pos[0] != 0x02) { - result = NULL; - len = 0; - return; - } - result = pos + 5; - len = ntohl(((int *)(pos + 1))[0]); + void Packet::getString(const char * identifier, char *& result, unsigned int & len) const{ + getScan().getMember(identifier).getString(result, len); } ///\brief Retrieves a single parameter as a string ///\param identifier The name of the parameter ///\param result The string in which to store the result - void Packet::getString(const char * identifier, std::string & result) { - char * data = NULL; - int len = 0; - getString(identifier, data, len); - result = std::string(data, len); + void Packet::getString(const char * identifier, std::string & result) const{ + result = getScan().getMember(identifier).asString(); } ///\brief Retrieves a single parameter as an integer ///\param identifier The name of the parameter ///\param result The result is stored in this integer - void Packet::getInt(const char * identifier, int & result) { - char * pos = findIdentifier(identifier); - if (pos < (char*)2) { - result = 0; - return; - } - if (pos[0] != 0x01) { - result = 0; - return; - } - result = ((long long int)pos[1] << 56) | ((long long int)pos[2] << 48) | ((long long int)pos[3] << 40) | ((long long int)pos[4] << 32) | ((long long int)pos[5] << 24) | ((long long int)pos[6] << 16) | ((long long int)pos[7] << 8) | pos[8]; + void Packet::getInt(const char * identifier, int & result) const{ + result = getScan().getMember(identifier).asInt(); } ///\brief Retrieves a single parameter as an integer ///\param identifier The name of the parameter ///\result The requested parameter as an integer - int Packet::getInt(const char * identifier) { + int Packet::getInt(const char * identifier) const{ int result; getInt(identifier, result); return result; @@ -317,7 +262,7 @@ namespace DTSC { ///\brief Retrieves a single parameter as a boolean ///\param identifier The name of the parameter ///\param result The result is stored in this boolean - void Packet::getFlag(const char * identifier, bool & result) { + void Packet::getFlag(const char * identifier, bool & result) const{ int result_; getInt(identifier, result_); result = (bool)result_; @@ -326,7 +271,7 @@ namespace DTSC { ///\brief Retrieves a single parameter as a boolean ///\param identifier The name of the parameter ///\result The requested parameter as a boolean - bool Packet::getFlag(const char * identifier) { + bool Packet::getFlag(const char * identifier) const{ bool result; getFlag(identifier, result); return result; @@ -335,13 +280,13 @@ namespace DTSC { ///\brief Checks whether a parameter exists ///\param identifier The name of the parameter ///\result Whether the parameter exists or not - bool Packet::hasMember(const char * identifier) { - return findIdentifier(identifier) > (char*)2; + bool Packet::hasMember(const char * identifier) const{ + return getScan().getMember(identifier).getType() > 0; } ///\brief Returns the timestamp of the packet. ///\return The timestamp of this packet. - long long unsigned int Packet::getTime() { + long long unsigned int Packet::getTime() const{ if (version != DTSC_V2){ if (!data){return 0;} return getInt("time"); @@ -351,7 +296,7 @@ namespace DTSC { ///\brief Returns the track id of the packet. ///\return The track id of this packet. - long int Packet::getTrackId() { + long int Packet::getTrackId() const{ if (version != DTSC_V2){ return getInt("trackid"); } @@ -360,20 +305,35 @@ namespace DTSC { ///\brief Returns a pointer to the payload of this packet. ///\return A pointer to the payload of this packet. - char * Packet::getData() { + char * Packet::getData() const{ return data; } + ///\brief Returns the size of this packet. + ///\return The size of this packet. + int Packet::getDataLen() const{ + return dataLen; + } + ///\brief Returns the size of the payload of this packet. ///\return The size of the payload of this packet. - int Packet::getDataLen() { - return dataLen; - + int Packet::getPayloadLen() const{ + if (version == DTSC_V2){ + return dataLen-20; + }else{ + return dataLen-8; + } } - + + /// Returns a DTSC::Scan instance to the contents of this packet. + /// May return an invalid instance if this packet is invalid. + Scan Packet::getScan() const{ + return Scan(data+(getDataLen()-getPayloadLen()), getPayloadLen()); + } + ///\brief Converts the packet into a JSON value ///\return A JSON::Value representation of this packet. - JSON::Value Packet::toJSON(){ + JSON::Value Packet::toJSON() const{ JSON::Value result; unsigned int i = 8; if (getVersion() == DTSC_V1){ @@ -384,6 +344,274 @@ namespace DTSC { } return result; } + + /// Create an invalid DTSC::Scan object by default. + Scan::Scan(){ + p = 0; + len = 0; + } + + + /// Create a DTSC::Scan object from memory pointer. + Scan::Scan(char * pointer, size_t length){ + p = pointer; + len = length; + } + + /// Returns an object representing the named indice of this object. + /// Returns an invalid object if this indice doesn't exist or this isn't an object type. + Scan Scan::getMember(std::string indice){ + if (getType() != DTSC_OBJ && getType() != DTSC_CON){ + return Scan(); + } + char * i = p+1; + //object, scan contents + while (i[0] + i[1] != 0 && i < p+len){ //while not encountering 0x0000 (we assume 0x0000EE) + if (i+2 >= p+len){ + return Scan();//out of packet! + } + unsigned int strlen = i[0] * 256 + i[1]; + i += 2; + if (indice.size() == strlen && strncmp(indice.data(), i, strlen) == 0){ + return Scan(i+strlen, len-(i-p)); + }else{ + i = skipDTSC(i+strlen, p+len); + if (!i){ + return Scan(); + } + } + } + return Scan(); + } + + /// Returns an object representing the num-th indice of this array. + /// If not an array but an object, it returns the num-th member, instead. + /// Returns an invalid object if this indice doesn't exist or this isn't an array or object type. + Scan Scan::getIndice(unsigned int num){ + if (getType() == DTSC_ARR){ + char * i = p+1; + unsigned int arr_indice = 0; + //array, scan contents + while (i[0] + i[1] != 0 && i < p+len){ //while not encountering 0x0000 (we assume 0x0000EE) + //search through contents... + if (arr_indice == num){ + return Scan(i, len-(i-p)); + }else{ + arr_indice++; + i = skipDTSC(i, p+len); + if (!i){ + return Scan(); + } + } + } + } + if (getType() == DTSC_OBJ || getType() == DTSC_CON){ + char * i = p+1; + unsigned int arr_indice = 0; + //object, scan contents + while (i[0] + i[1] != 0 && i < p+len){ //while not encountering 0x0000 (we assume 0x0000EE) + if (i+2 >= p+len){ + return Scan();//out of packet! + } + unsigned int strlen = i[0] * 256 + i[1]; + i += 2; + if (arr_indice == num){ + return Scan(i+strlen, len-(i-p)); + }else{ + arr_indice++; + i = skipDTSC(i+strlen, p+len); + if (!i){ + return Scan(); + } + } + } + } + return Scan(); + } + + /// Returns the first byte of this DTSC value, or 0 on error. + char Scan::getType(){ + if (!p){return 0;} + return p[0]; + } + + /// Returns the boolean value of this DTSC value. + /// Numbers are compared to 0. + /// Strings are checked for non-zero length. + /// Objects and arrays are checked for content. + /// Returns false on error or in other cases. + bool Scan::asBool(){ + switch (getType()){ + case DTSC_STR: + return (p[1] | p[2] | p[3] | p[4]); + case DTSC_INT: + return (asInt() != 0); + case DTSC_OBJ: + case DTSC_CON: + case DTSC_ARR: + return (p[1] | p[2]); + default: + return false; + } + } + + /// Returns the long long value of this DTSC number value. + /// Will convert string values to numbers, taking octal and hexadecimal types into account. + /// Illegal or invalid values return 0. + long long Scan::asInt(){ + switch (getType()){ + case DTSC_INT: + return ((long long int)p[1] << 56) | ((long long int)p[2] << 48) | ((long long int)p[3] << 40) | ((long long int)p[4] << 32) | ((long long int)p[5] << 24) | ((long long int)p[6] << 16) | ((long long int)p[7] << 8) | p[8]; + case DTSC_STR: + char * str; + unsigned int strlen; + getString(str, strlen); + if (!strlen){return 0;} + return strtoll(str, 0, 0); + default: + return 0; + } + } + + /// Returns the string value of this DTSC string value. + /// Uses getString internally, does no conversion. + /// Returns an empty string on error. + std::string Scan::asString(){ + char * str; + unsigned int strlen; + getString(str, strlen); + return std::string(str, strlen); + } + + /// Sets result to a pointer to the string, and strlen to the lenght of it. + /// Sets both to zero if this isn't a DTSC string value. + /// Attempts absolutely no conversion. + void Scan::getString(char *& result, unsigned int & strlen){ + switch (getType()){ + case DTSC_STR: + result = p+5; + strlen = p[1] * 256 * 256 * 256 + p[2] * 256 * 256 + p[3] * 256 + p[4]; + return; + default: + result = 0; + strlen = 0; + return; + } + } + + /// \todo Move this function to some generic area. Duplicate from json.cpp + static inline char hex2c(char c){ + if (c < 10){return '0' + c;} + if (c < 16){return 'A' + (c - 10);} + return '0'; + } + + /// \todo Move this function to some generic area. Duplicate from json.cpp + static std::string string_escape(const std::string val){ + std::stringstream out; + out << "\""; + for (unsigned int i = 0; i < val.size(); ++i){ + switch (val.data()[i]){ + case '"': + out << "\\\""; + break; + case '\\': + out << "\\\\"; + break; + case '\n': + out << "\\n"; + break; + case '\b': + out << "\\b"; + break; + case '\f': + out << "\\f"; + break; + case '\r': + out << "\\r"; + break; + case '\t': + out << "\\t"; + break; + default: + if (val.data()[i] < 32 || val.data()[i] > 126){ + out << "\\u00"; + out << hex2c((val.data()[i] >> 4) & 0xf); + out << hex2c(val.data()[i] & 0xf); + }else{ + out << val.data()[i]; + } + break; + } + } + out << "\""; + return out.str(); + } + + std::string Scan::toPrettyString(unsigned int indent){ + switch (getType()){ + case DTSC_STR:{ + unsigned int strlen = p[1] * 256 * 256 * 256 + p[2] * 256 * 256 + p[3] * 256 + p[4]; + if (strlen > 250){ + std::stringstream ret; + ret << "\"" << strlen << " bytes of data\""; + return ret.str(); + } + return string_escape(asString()); + } + case DTSC_INT:{ + std::stringstream ret; + ret << asInt(); + return ret.str(); + } + case DTSC_OBJ: + case DTSC_CON:{ + std::stringstream ret; + ret << "{" << std::endl; + indent += 2; + char * i = p+1; + //object, scan contents + while (i[0] + i[1] != 0 && i < p+len){ //while not encountering 0x0000 (we assume 0x0000EE) + if (i+2 >= p+len){ + indent -= 2; + ret << std::string((size_t)indent, ' ') << "} //walked out of object here"; + return ret.str(); + } + unsigned int strlen = i[0] * 256 + i[1]; + i += 2; + ret << std::string((size_t)indent, ' ') << "\"" << std::string(i, strlen) << "\": " << Scan(i+strlen, len-(i-p)).toPrettyString(indent) << "," << std::endl; + i = skipDTSC(i+strlen, p+len); + if (!i){ + indent -= 2; + ret << std::string((size_t)indent, ' ') << "} //could not locate next object"; + return ret.str(); + } + } + indent -= 2; + ret << std::string((size_t)indent, ' ') << "}"; + return ret.str(); + } + case DTSC_ARR:{ + std::stringstream ret; + ret << "[" << std::endl; + indent += 2; + Scan tmpScan; + unsigned int i = 0; + do { + tmpScan = getIndice(i++); + if (tmpScan.getType()){ + ret << std::string((size_t)indent, ' ') << tmpScan.toPrettyString(indent) << "," << std::endl; + } + }while(tmpScan.getType()); + indent -= 2; + ret << std::string((size_t)indent, ' ') << "]"; + return ret.str(); + } + default: + return "Error"; + } + } + ///\brief Returns the payloadsize of a part @@ -698,6 +926,46 @@ namespace DTSC { commentHeader = trackRef["commentheader"].asStringRef(); } } + + ///\brief Constructs a track from a JSON::Value + Track::Track(Scan & trackRef) { + if (trackRef.getMember("fragments").getType() == DTSC_STR){ + char * tmp = 0; + unsigned int tmplen = 0; + trackRef.getMember("fragments").getString(tmp, tmplen); + fragments = std::deque((Fragment *)tmp, ((Fragment *)tmp) + (tmplen / 11)); + } + if (trackRef.getMember("keys").getType() == DTSC_STR){ + char * tmp = 0; + unsigned int tmplen = 0; + trackRef.getMember("keys").getString(tmp, tmplen); + keys = std::deque((Key *)tmp, ((Key *)tmp) + (tmplen / 16)); + } + if (trackRef.getMember("parts").getType() == DTSC_STR){ + char * tmp = 0; + unsigned int tmplen = 0; + trackRef.getMember("parts").getString(tmp, tmplen); + parts = std::deque((Part *)tmp, ((Part *)tmp) + (tmplen / 9)); + } + trackID = trackRef.getMember("trackid").asInt(); + firstms = trackRef.getMember("firstms").asInt(); + lastms = trackRef.getMember("lastms").asInt(); + bps = trackRef.getMember("bps").asInt(); + missedFrags = trackRef.getMember("missed_frags").asInt(); + codec = trackRef.getMember("codec").asString(); + type = trackRef.getMember("type").asString(); + init = trackRef.getMember("init").asString(); + if (type == "audio") { + rate = trackRef.getMember("rate").asInt(); + size = trackRef.getMember("size").asInt(); + channels = trackRef.getMember("channels").asInt(); + } + if (type == "video") { + width = trackRef.getMember("width").asInt(); + height = trackRef.getMember("height").asInt(); + fpks = trackRef.getMember("fpks").asInt(); + } + } ///\brief Updates a track and its metadata given a DTSC::Packet. /// @@ -709,7 +977,7 @@ namespace DTSC { } Part newPart; char * data; - int dataLen; + unsigned int dataLen; pack.getString("data", data, dataLen); newPart.setSize(dataLen); newPart.setOffset(pack.getInt("offset")); @@ -976,6 +1244,32 @@ namespace DTSC { } moreheader = rhs.moreheader; } + + Meta::Meta(const DTSC::Packet & source){ + reinit(source); + } + + void Meta::reinit(const DTSC::Packet & source){ + tracks.clear(); + vod = source.getFlag("vod"); + live = source.getFlag("live"); + merged = source.getFlag("merged"); + bufferWindow = source.getInt("buffer_window"); + moreheader = source.getInt("moreheader"); + Scan tmpTracks = source.getScan().getMember("tracks"); + unsigned int num = 0; + Scan tmpTrack; + do{ + tmpTrack = tmpTracks.getIndice(num); + if (tmpTrack.asBool()){ + int trackId = tmpTrack.getMember("trackid").asInt(); + if (trackId){ + tracks[trackId] = Track(tmpTrack); + } + num++; + } + }while(tmpTrack.asBool()); + } ///\brief Creates a meta object from a JSON::Value Meta::Meta(JSON::Value & meta) { @@ -1421,12 +1715,12 @@ namespace DTSC { for (std::map::iterator it = tracks.begin(); it != tracks.end(); it++) { dataLen += it->second.getSendLen(); } - return dataLen; + return dataLen+8;//add 8 bytes header length } ///\brief Writes a read-only meta object to a pointer void readOnlyMeta::writeTo(char * p){ - int dataLen = getSendLen(); + int dataLen = getSendLen() - 8;//strip 8 bytes header writePointer(p, DTSC::Magic_Header, 4); writePointer(p, convertInt(dataLen), 4); writePointer(p, "\340\000\006tracks\340", 10); @@ -1457,7 +1751,7 @@ namespace DTSC { ///\brief Writes a read-only meta object to a socket void readOnlyMeta::send(Socket::Connection & conn) { - int dataLen = getSendLen(); + int dataLen = getSendLen()-8;//strip 8 bytes header conn.SendNow(DTSC::Magic_Header, 4); conn.SendNow(convertInt(dataLen), 4); conn.SendNow("\340\000\006tracks\340", 10); @@ -1492,12 +1786,12 @@ namespace DTSC { for (std::map::iterator it = tracks.begin(); it != tracks.end(); it++) { dataLen += it->second.getSendLen(); } - return dataLen; + return dataLen+8;//add 8 bytes header } ///\brief Writes a meta object to a pointer void Meta::writeTo(char * p){ - int dataLen = getSendLen(); + int dataLen = getSendLen()-8;//strip 8 bytes header writePointer(p, DTSC::Magic_Header, 4); writePointer(p, convertInt(dataLen), 4); writePointer(p, "\340\000\006tracks\340", 10); @@ -1528,7 +1822,7 @@ namespace DTSC { ///\brief Writes a meta object to a socket void Meta::send(Socket::Connection & conn) { - int dataLen = getSendLen(); + int dataLen = getSendLen()-8;//strip 8 bytes header conn.SendNow(DTSC::Magic_Header, 4); conn.SendNow(convertInt(dataLen), 4); conn.SendNow("\340\000\006tracks\340", 10); diff --git a/lib/flv_tag.cpp b/lib/flv_tag.cpp index a585660f..2f256d5d 100644 --- a/lib/flv_tag.cpp +++ b/lib/flv_tag.cpp @@ -376,8 +376,9 @@ bool FLV::Tag::DTSCLoader(DTSC::Packet & packData, DTSC::Track & track){ len = 0; if (track.type == "video"){ char * tmpData = 0; - packData.getString("data", tmpData, len); - len += 16; + unsigned int tmpLen = 0; + packData.getString("data", tmpData, tmpLen); + len = tmpLen + 16; if (track.codec == "H264"){ len += 4; } @@ -418,8 +419,9 @@ bool FLV::Tag::DTSCLoader(DTSC::Packet & packData, DTSC::Track & track){ } if (track.type == "audio"){ char * tmpData = 0; - packData.getString("data", tmpData, len); - len += 16; + unsigned int tmpLen = 0; + packData.getString("data", tmpData, tmpLen); + len = tmpLen + 16; if (track.codec == "AAC"){ len ++; }