Implemented DTSC::Scan for more efficient use of system memory.

This commit is contained in:
Thulinma 2014-05-11 14:38:04 +02:00
parent 180ac5eb9e
commit 9a19cf2e20
3 changed files with 450 additions and 123 deletions

View file

@ -13,6 +13,12 @@
#include "socket.h" #include "socket.h"
#include "timing.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 { namespace DTSC {
bool isFixed(JSON::Value & metadata); bool isFixed(JSON::Value & metadata);
@ -59,6 +65,26 @@ namespace DTSC {
DTSC_V2 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::Packets can currently be three types:
/// DTSC_HEAD packets are the "DTSC" header string, followed by 4 bytes len and packed content. /// 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. /// DTSC_V1 packets are "DTPD", followed by 4 bytes len and packed content.
@ -73,24 +99,25 @@ namespace DTSC {
void null(); void null();
void operator = (const Packet & rhs); void operator = (const Packet & rhs);
operator bool() const; operator bool() const;
packType getVersion(); packType getVersion() const;
void reInit(const char * data_, unsigned int len, bool noCopy = false); 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, char *& result, unsigned int & len) const;
void getString(const char * identifier, std::string & result); void getString(const char * identifier, std::string & result) const;
void getInt(const char * identifier, int & result); void getInt(const char * identifier, int & result) const;
int getInt(const char * identifier); int getInt(const char * identifier) const;
void getFlag(const char * identifier, bool & result); void getFlag(const char * identifier, bool & result) const;
bool getFlag(const char * identifier); bool getFlag(const char * identifier) const;
bool hasMember(const char * identifier); bool hasMember(const char * identifier) const;
long long unsigned int getTime(); long long unsigned int getTime() const;
long int getTrackId(); long int getTrackId() const;
char * getData(); char * getData() const;
int getDataLen(); int getDataLen() const;
JSON::Value toJSON(); int getPayloadLen() const;
JSON::Value toJSON() const;
Scan getScan() const;
protected: protected:
bool master; bool master;
packType version; packType version;
char * findIdentifier(const char * identifier);
void resize(unsigned int size); void resize(unsigned int size);
char * data; char * data;
unsigned int bufferLen; unsigned int bufferLen;
@ -255,6 +282,7 @@ namespace DTSC {
Track(); Track();
Track(const readOnlyTrack & rhs); Track(const readOnlyTrack & rhs);
Track(JSON::Value & trackRef); Track(JSON::Value & trackRef);
Track(Scan & trackRef);
inline operator bool() const { inline operator bool() const {
return parts.size(); return parts.size();
} }
@ -298,9 +326,10 @@ namespace DTSC {
class Meta : public readOnlyMeta { class Meta : public readOnlyMeta {
public: public:
Meta(); Meta();
Meta(const DTSC::Packet & source);
Meta(const readOnlyMeta & meta); Meta(const readOnlyMeta & meta);
Meta(JSON::Value & meta); Meta(JSON::Value & meta);
std::map<int, Track> tracks; void reinit(const DTSC::Packet & source);
void update(DTSC::Packet & pack); void update(DTSC::Packet & pack);
void update(JSON::Value & pack); void update(JSON::Value & pack);
unsigned int getSendLen(); unsigned int getSendLen();
@ -310,6 +339,8 @@ namespace DTSC {
void reset(); void reset();
bool isFixed(); bool isFixed();
void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0); void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0);
//members:
std::map<int, Track> tracks;
}; };
/// A simple wrapper class that will open a file and allow easy reading/writing of DTSC data from/to it. /// A simple wrapper class that will open a file and allow easy reading/writing of DTSC data from/to it.

View file

@ -4,7 +4,6 @@
#include <cstring> #include <cstring>
#include <iomanip> #include <iomanip>
/// Retrieves a short in network order from the pointer p. /// Retrieves a short in network order from the pointer p.
static short btohs(char * p) { static short btohs(char * p) {
return (p[0] << 8) + p[1]; return (p[0] << 8) + p[1];
@ -96,7 +95,7 @@ namespace DTSC {
/// Returns the recognized packet type. /// Returns the recognized packet type.
/// This type is set by reInit and all constructors, and then just referenced from there on. /// 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; return version;
} }
@ -183,132 +182,78 @@ namespace DTSC {
} }
} }
/// Helper function for findIdentifier /// Helper function for skipping over whole DTSC parts
static char * findInside(const char * identifier, char *& p, char * max){ static char * skipDTSC(char * p, char * max){
if (p+1 >= max || p[0] == 0x00){ 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 //int, skip 9 bytes to next value
p+=9; return p+9;
return 0;
} }
if (p[0] == 0x02){ if (p[0] == DTSC_STR){
if (p+4 >= max){ 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 return p + 5 + p[1] * 256 * 256 * 256 + p[2] * 256 * 256 + p[3] * 256 + p[4];
unsigned int tmpi = p[1] * 256 * 256 * 256 + p[2] * 256 * 256 + p[3] * 256 + p[4];
p += tmpi + 5;
return 0;
} }
if (p[0] == 0xE0 || p[0] == 0xFF){ if (p[0] == DTSC_OBJ || p[0] == DTSC_CON){
p++; p++;
unsigned int id_len = strlen(identifier);
//object, scan contents //object, scan contents
while (p[0] + p[1] != 0 && p < max){ //while not encountering 0x0000 (we assume 0x0000EE) while (p[0] + p[1] != 0 && p < max){ //while not encountering 0x0000 (we assume 0x0000EE)
if (p+2 >= max){ 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 p += 2 + (p[0] * 256 + p[1]);//skip size
//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
//otherwise, search through the contents, if needed, and continue //otherwise, search through the contents, if needed, and continue
char * tmp_ret = findInside(identifier, p, max); p = skipDTSC(p, max);
if (tmp_ret){ if (!p){
return tmp_ret;
}
}
p += 3;//skip end marker
return 0; return 0;
} }
if (p[0] == 0x0A){ }
return p+3;
}
if (p[0] == DTSC_ARR){
p++; p++;
//array, scan contents //array, scan contents
while (p[0] + p[1] != 0 && p < max){ //while not encountering 0x0000 (we assume 0x0000EE) while (p[0] + p[1] != 0 && p < max){ //while not encountering 0x0000 (we assume 0x0000EE)
//search through contents... //search through contents...
char * tmp_ret = findInside(identifier, p, max); p = skipDTSC(p, max);
if (tmp_ret){ if (!p){
return tmp_ret;
}
//no match, continue search
}
p += 3; //skip end marker
return 0; return 0;
} }
DEBUG_MSG(DLVL_FAIL, "Unimplemented DTMI type %hhx, @ %p / %p - returning.", p[0], p, max);
return (char*)1;//out of packet! 1 == error
} }
return p + 3; //skip end marker
///\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 0;//out of packet! 1 == error
return ret;
} }
///\brief Retrieves a single parameter as a string ///\brief Retrieves a single parameter as a string
///\param identifier The name of the parameter ///\param identifier The name of the parameter
///\param result A location on which the string will be returned ///\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 ///\param len An integer in which the length of the string will be returned
void Packet::getString(const char * identifier, char *& result, int & len) { void Packet::getString(const char * identifier, char *& result, unsigned int & len) const{
char * pos = findIdentifier(identifier); getScan().getMember(identifier).getString(result, len);
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]);
} }
///\brief Retrieves a single parameter as a string ///\brief Retrieves a single parameter as a string
///\param identifier The name of the parameter ///\param identifier The name of the parameter
///\param result The string in which to store the result ///\param result The string in which to store the result
void Packet::getString(const char * identifier, std::string & result) { void Packet::getString(const char * identifier, std::string & result) const{
char * data = NULL; result = getScan().getMember(identifier).asString();
int len = 0;
getString(identifier, data, len);
result = std::string(data, len);
} }
///\brief Retrieves a single parameter as an integer ///\brief Retrieves a single parameter as an integer
///\param identifier The name of the parameter ///\param identifier The name of the parameter
///\param result The result is stored in this integer ///\param result The result is stored in this integer
void Packet::getInt(const char * identifier, int & result) { void Packet::getInt(const char * identifier, int & result) const{
char * pos = findIdentifier(identifier); result = getScan().getMember(identifier).asInt();
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];
} }
///\brief Retrieves a single parameter as an integer ///\brief Retrieves a single parameter as an integer
///\param identifier The name of the parameter ///\param identifier The name of the parameter
///\result The requested parameter as an integer ///\result The requested parameter as an integer
int Packet::getInt(const char * identifier) { int Packet::getInt(const char * identifier) const{
int result; int result;
getInt(identifier, result); getInt(identifier, result);
return result; return result;
@ -317,7 +262,7 @@ namespace DTSC {
///\brief Retrieves a single parameter as a boolean ///\brief Retrieves a single parameter as a boolean
///\param identifier The name of the parameter ///\param identifier The name of the parameter
///\param result The result is stored in this boolean ///\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_; int result_;
getInt(identifier, result_); getInt(identifier, result_);
result = (bool)result_; result = (bool)result_;
@ -326,7 +271,7 @@ namespace DTSC {
///\brief Retrieves a single parameter as a boolean ///\brief Retrieves a single parameter as a boolean
///\param identifier The name of the parameter ///\param identifier The name of the parameter
///\result The requested parameter as a boolean ///\result The requested parameter as a boolean
bool Packet::getFlag(const char * identifier) { bool Packet::getFlag(const char * identifier) const{
bool result; bool result;
getFlag(identifier, result); getFlag(identifier, result);
return result; return result;
@ -335,13 +280,13 @@ namespace DTSC {
///\brief Checks whether a parameter exists ///\brief Checks whether a parameter exists
///\param identifier The name of the parameter ///\param identifier The name of the parameter
///\result Whether the parameter exists or not ///\result Whether the parameter exists or not
bool Packet::hasMember(const char * identifier) { bool Packet::hasMember(const char * identifier) const{
return findIdentifier(identifier) > (char*)2; return getScan().getMember(identifier).getType() > 0;
} }
///\brief Returns the timestamp of the packet. ///\brief Returns the timestamp of the packet.
///\return The timestamp of this 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 (version != DTSC_V2){
if (!data){return 0;} if (!data){return 0;}
return getInt("time"); return getInt("time");
@ -351,7 +296,7 @@ namespace DTSC {
///\brief Returns the track id of the packet. ///\brief Returns the track id of the packet.
///\return The track id of this packet. ///\return The track id of this packet.
long int Packet::getTrackId() { long int Packet::getTrackId() const{
if (version != DTSC_V2){ if (version != DTSC_V2){
return getInt("trackid"); return getInt("trackid");
} }
@ -360,20 +305,35 @@ namespace DTSC {
///\brief Returns a pointer to the payload of this packet. ///\brief Returns a pointer to the payload of this packet.
///\return 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; 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. ///\brief Returns the size of the payload of this packet.
///\return The size of the payload of this packet. ///\return The size of the payload of this packet.
int Packet::getDataLen() { int Packet::getPayloadLen() const{
return dataLen; 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 ///\brief Converts the packet into a JSON value
///\return A JSON::Value representation of this packet. ///\return A JSON::Value representation of this packet.
JSON::Value Packet::toJSON(){ JSON::Value Packet::toJSON() const{
JSON::Value result; JSON::Value result;
unsigned int i = 8; unsigned int i = 8;
if (getVersion() == DTSC_V1){ if (getVersion() == DTSC_V1){
@ -385,6 +345,274 @@ namespace DTSC {
return result; 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 ///\brief Returns the payloadsize of a part
long Part::getSize() { long Part::getSize() {
@ -699,6 +927,46 @@ namespace DTSC {
} }
} }
///\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>((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>((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>((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. ///\brief Updates a track and its metadata given a DTSC::Packet.
/// ///
///Will also insert keyframes on non-video tracks, and creates fragments ///Will also insert keyframes on non-video tracks, and creates fragments
@ -709,7 +977,7 @@ namespace DTSC {
} }
Part newPart; Part newPart;
char * data; char * data;
int dataLen; unsigned int dataLen;
pack.getString("data", data, dataLen); pack.getString("data", data, dataLen);
newPart.setSize(dataLen); newPart.setSize(dataLen);
newPart.setOffset(pack.getInt("offset")); newPart.setOffset(pack.getInt("offset"));
@ -977,6 +1245,32 @@ namespace DTSC {
moreheader = rhs.moreheader; 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 ///\brief Creates a meta object from a JSON::Value
Meta::Meta(JSON::Value & meta) { Meta::Meta(JSON::Value & meta) {
vod = meta.isMember("vod") && meta["vod"]; vod = meta.isMember("vod") && meta["vod"];
@ -1421,12 +1715,12 @@ namespace DTSC {
for (std::map<int, readOnlyTrack>::iterator it = tracks.begin(); it != tracks.end(); it++) { for (std::map<int, readOnlyTrack>::iterator it = tracks.begin(); it != tracks.end(); it++) {
dataLen += it->second.getSendLen(); dataLen += it->second.getSendLen();
} }
return dataLen; return dataLen+8;//add 8 bytes header length
} }
///\brief Writes a read-only meta object to a pointer ///\brief Writes a read-only meta object to a pointer
void readOnlyMeta::writeTo(char * p){ void readOnlyMeta::writeTo(char * p){
int dataLen = getSendLen(); int dataLen = getSendLen() - 8;//strip 8 bytes header
writePointer(p, DTSC::Magic_Header, 4); writePointer(p, DTSC::Magic_Header, 4);
writePointer(p, convertInt(dataLen), 4); writePointer(p, convertInt(dataLen), 4);
writePointer(p, "\340\000\006tracks\340", 10); writePointer(p, "\340\000\006tracks\340", 10);
@ -1457,7 +1751,7 @@ namespace DTSC {
///\brief Writes a read-only meta object to a socket ///\brief Writes a read-only meta object to a socket
void readOnlyMeta::send(Socket::Connection & conn) { 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(DTSC::Magic_Header, 4);
conn.SendNow(convertInt(dataLen), 4); conn.SendNow(convertInt(dataLen), 4);
conn.SendNow("\340\000\006tracks\340", 10); conn.SendNow("\340\000\006tracks\340", 10);
@ -1492,12 +1786,12 @@ namespace DTSC {
for (std::map<int, Track>::iterator it = tracks.begin(); it != tracks.end(); it++) { for (std::map<int, Track>::iterator it = tracks.begin(); it != tracks.end(); it++) {
dataLen += it->second.getSendLen(); dataLen += it->second.getSendLen();
} }
return dataLen; return dataLen+8;//add 8 bytes header
} }
///\brief Writes a meta object to a pointer ///\brief Writes a meta object to a pointer
void Meta::writeTo(char * p){ void Meta::writeTo(char * p){
int dataLen = getSendLen(); int dataLen = getSendLen()-8;//strip 8 bytes header
writePointer(p, DTSC::Magic_Header, 4); writePointer(p, DTSC::Magic_Header, 4);
writePointer(p, convertInt(dataLen), 4); writePointer(p, convertInt(dataLen), 4);
writePointer(p, "\340\000\006tracks\340", 10); writePointer(p, "\340\000\006tracks\340", 10);
@ -1528,7 +1822,7 @@ namespace DTSC {
///\brief Writes a meta object to a socket ///\brief Writes a meta object to a socket
void Meta::send(Socket::Connection & conn) { 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(DTSC::Magic_Header, 4);
conn.SendNow(convertInt(dataLen), 4); conn.SendNow(convertInt(dataLen), 4);
conn.SendNow("\340\000\006tracks\340", 10); conn.SendNow("\340\000\006tracks\340", 10);

View file

@ -376,8 +376,9 @@ bool FLV::Tag::DTSCLoader(DTSC::Packet & packData, DTSC::Track & track){
len = 0; len = 0;
if (track.type == "video"){ if (track.type == "video"){
char * tmpData = 0; char * tmpData = 0;
packData.getString("data", tmpData, len); unsigned int tmpLen = 0;
len += 16; packData.getString("data", tmpData, tmpLen);
len = tmpLen + 16;
if (track.codec == "H264"){ if (track.codec == "H264"){
len += 4; len += 4;
} }
@ -418,8 +419,9 @@ bool FLV::Tag::DTSCLoader(DTSC::Packet & packData, DTSC::Track & track){
} }
if (track.type == "audio"){ if (track.type == "audio"){
char * tmpData = 0; char * tmpData = 0;
packData.getString("data", tmpData, len); unsigned int tmpLen = 0;
len += 16; packData.getString("data", tmpData, tmpLen);
len = tmpLen + 16;
if (track.codec == "AAC"){ if (track.codec == "AAC"){
len ++; len ++;
} }