diff --git a/lib/dtsc.h b/lib/dtsc.h index ae387a7c..02b32f30 100644 --- a/lib/dtsc.h +++ b/lib/dtsc.h @@ -19,6 +19,12 @@ #define DTSC_ARR 0x0A #define DTSC_CON 0xFF +//Increase this value every time the DTSH file format changes in an incompatible way +//Changelog: +// Version 0-2: Undocumented changes +// Version 3: switched to bigMeta-style by default, Parts layout switched from 3/2/4 to 3/3/3 bytes +#define DTSH_VERSION 3 + namespace DTSC { ///\brief This enum holds all possible datatypes for DTSC packets. @@ -125,6 +131,7 @@ namespace DTSC { int getDataLen() const; int getPayloadLen() const; JSON::Value toJSON() const; + std::string toSummary() const; Scan getScan() const; protected: bool master; @@ -173,21 +180,22 @@ namespace DTSC { ///\brief Basic class for storage of data associated with single DTSC packets, a.k.a. parts. class Part { public: - long getSize(); - void setSize(long newSize); - short getDuration(); - void setDuration(short newDuration); - long getOffset(); - void setOffset(long newOffset); + uint32_t getSize(); + void setSize(uint32_t newSize); + uint32_t getDuration(); + void setDuration(uint32_t newDuration); + uint32_t getOffset(); + void setOffset(uint32_t newOffset); char * getData(); void toPrettyString(std::ostream & str, int indent = 0); private: +#define PACKED_PART_SIZE 9 ///\brief Data storage for this Part. /// /// - 3 bytes: MSB storage of the payload size of this packet in bytes. - /// - 2 bytes: MSB storage of the duration of this packet in milliseconds. - /// - 4 bytes: MSB storage of the presentation time offset of this packet in milliseconds. - char data[9]; + /// - 3 bytes: MSB storage of the duration of this packet in milliseconds. + /// - 3 bytes: MSB storage of the presentation time offset of this packet in milliseconds. + char data[PACKED_PART_SIZE]; }; ///\brief Basic class for storage of data associated with keyframes. @@ -208,7 +216,6 @@ namespace DTSC { char * getData(); void toPrettyString(std::ostream & str, int indent = 0); private: -#ifdef BIGMETA #define PACKED_KEY_SIZE 25 ///\brief Data storage for this Key. /// @@ -217,16 +224,6 @@ namespace DTSC { /// - 4 bytes: MSB storage of the number of this keyframe. /// - 2 bytes: MSB storage of the amount of parts in this keyframe. /// - 8 bytes: MSB storage of the timestamp associated with this keyframe's first packet. -#else -#define PACKED_KEY_SIZE 16 - ///\brief Data storage for this Key. - /// - /// - 5 bytes: MSB storage of the position of the first packet of this keyframe within the file. - /// - 3 bytes: MSB storage of the duration of this keyframe. - /// - 2 bytes: MSB storage of the number of this keyframe. - /// - 2 bytes: MSB storage of the amount of parts in this keyframe. - /// - 4 bytes: MSB storage of the timestamp associated with this keyframe's first packet. -#endif char data[PACKED_KEY_SIZE]; }; @@ -244,7 +241,6 @@ namespace DTSC { char * getData(); void toPrettyString(std::ostream & str, int indent = 0); private: -#ifdef BIGMETA #define PACKED_FRAGMENT_SIZE 13 ///\brief Data storage for this Fragment. /// @@ -252,15 +248,6 @@ namespace DTSC { /// - 1 byte: length (amount of keyframes) /// - 4 bytes: number of first keyframe in fragment /// - 4 bytes: size of fragment in bytes -#else -#define PACKED_FRAGMENT_SIZE 11 - ///\brief Data storage for this Fragment. - /// - /// - 4 bytes: duration (in milliseconds) - /// - 1 byte: length (amount of keyframes) - /// - 2 bytes: number of first keyframe in fragment - /// - 4 bytes: size of fragment in bytes -#endif char data[PACKED_FRAGMENT_SIZE]; }; @@ -335,12 +322,14 @@ namespace DTSC { void writeTo(char * p); JSON::Value toJSON(); void reset(); + bool toFile(const std::string & fileName); void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0); //members: std::map tracks; bool vod; bool live; bool merged; + uint16_t version; long long int moreheader; long long int bufferWindow; }; diff --git a/lib/dtscmeta.cpp b/lib/dtscmeta.cpp index 3eb338fc..6a4c5dd1 100644 --- a/lib/dtscmeta.cpp +++ b/lib/dtscmeta.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #define AUDIO_KEY_INTERVAL 5000 ///< This define controls the keyframe interval for non-video tracks, such as audio and metadata tracks. @@ -437,6 +438,18 @@ namespace DTSC { return result; } + std::string Packet::toSummary() const { + std::stringstream out; + char * res = 0; + unsigned int len = 0; + getString("data", res, len); + out << getTrackId() << "@" << getTime() << ": " << len << " bytes"; + if (hasMember("keyframe")){ + out << " (keyframe)"; + } + return out.str(); + } + /// Create an invalid DTSC::Scan object by default. Scan::Scan() { p = 0; @@ -840,33 +853,33 @@ namespace DTSC { ///\brief Returns the payloadsize of a part - long Part::getSize() { + uint32_t Part::getSize() { return Bit::btoh24(data); } ///\brief Sets the payloadsize of a part - void Part::setSize(long newSize) { + void Part::setSize(uint32_t newSize) { Bit::htob24(data, newSize); } - ///\brief Retruns the duration of a part - short Part::getDuration() { - return Bit::btohs(data + 3); + ///\brief Returns the duration of a part + uint32_t Part::getDuration() { + return Bit::btoh24(data + 3); } ///\brief Sets the duration of a part - void Part::setDuration(short newDuration) { - Bit::htobs(data + 3, newDuration); + void Part::setDuration(uint32_t newDuration) { + Bit::htob24(data + 3, newDuration); } ///\brief returns the offset of a part - long Part::getOffset() { - return Bit::btohl(data + 5); + uint32_t Part::getOffset() { + return Bit::btoh24(data + 6); } ///\brief Sets the offset of a part - void Part::setOffset(long newOffset) { - Bit::htobl(data + 5, newOffset); + void Part::setOffset(uint32_t newOffset) { + Bit::htob24(data + 6, newOffset); } ///\brief Returns the data of a part @@ -883,93 +896,49 @@ namespace DTSC { ///\brief Returns the byteposition of a keyframe unsigned long long Key::getBpos() { -#ifdef BIGMETA return Bit::btohll(data); -#else - return (((unsigned long long)data[0] << 32) | (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4]); -#endif } void Key::setBpos(unsigned long long newBpos) { -#ifdef BIGMETA Bit::htobll(data, newBpos); -#else - data[4] = newBpos & 0xFF; - data[3] = (newBpos >> 8) & 0xFF; - data[2] = (newBpos >> 16) & 0xFF; - data[1] = (newBpos >> 24) & 0xFF; - data[0] = (newBpos >> 32) & 0xFF; -#endif } unsigned long Key::getLength() { -#ifdef BIGMETA return Bit::btoh24(data+8); -#else - return Bit::btoh24(data+5); -#endif } void Key::setLength(unsigned long newLength) { -#ifdef BIGMETA Bit::htob24(data+8, newLength); -#else - Bit::htob24(data+5, newLength); -#endif } ///\brief Returns the number of a keyframe unsigned long Key::getNumber() { -#ifdef BIGMETA return Bit::btohl(data + 11); -#else - return Bit::btohs(data + 8); -#endif } ///\brief Sets the number of a keyframe void Key::setNumber(unsigned long newNumber) { -#ifdef BIGMETA Bit::htobl(data + 11, newNumber); -#else - Bit::htobs(data + 8, newNumber); -#endif } ///\brief Returns the number of parts of a keyframe unsigned short Key::getParts() { -#ifdef BIGMETA return Bit::btohs(data + 15); -#else - return Bit::btohs(data + 10); -#endif } ///\brief Sets the number of parts of a keyframe void Key::setParts(unsigned short newParts) { -#ifdef BIGMETA Bit::htobs(data + 15, newParts); -#else - Bit::htobs(data + 10, newParts); -#endif } ///\brief Returns the timestamp of a keyframe unsigned long long Key::getTime() { -#ifdef BIGMETA return Bit::btohll(data + 17); -#else - return Bit::btohl(data + 12); -#endif } ///\brief Sets the timestamp of a keyframe void Key::setTime(unsigned long long newTime) { -#ifdef BIGMETA Bit::htobll(data + 17, newTime); -#else - Bit::htobl(data + 12, newTime); -#endif } ///\brief Returns the data of this keyframe struct @@ -1006,38 +975,22 @@ namespace DTSC { ///\brief Returns the number of the first keyframe in this fragment unsigned long Fragment::getNumber() { -#ifdef BIGMETA return Bit::btohl(data + 5); -#else - return Bit::btohs(data + 5); -#endif } ///\brief Sets the number of the first keyframe in this fragment void Fragment::setNumber(unsigned long newNumber) { -#ifdef BIGMETA Bit::htobl(data + 5, newNumber); -#else - Bit::htobs(data + 5, newNumber); -#endif } ///\brief Returns the size of a fragment unsigned long Fragment::getSize() { -#ifdef BIGMETA return Bit::btohl(data + 9); -#else - return Bit::btohl(data + 7); -#endif } ///\brief Sets the size of a fragement void Fragment::setSize(unsigned long newSize) { -#ifdef BIGMETA Bit::htobl(data + 9, newSize); -#else - Bit::htobl(data + 7, newSize); -#endif } ///\brief Returns thte data of this fragment structure @@ -1294,6 +1247,7 @@ namespace DTSC { Meta::Meta() { vod = false; live = false; + version = DTSH_VERSION; moreheader = 0; merged = false; bufferWindow = 0; @@ -1307,6 +1261,7 @@ namespace DTSC { tracks.clear(); vod = source.getFlag("vod"); live = source.getFlag("live"); + version = source.getInt("version"); merged = source.getFlag("merged"); bufferWindow = source.getInt("buffer_window"); moreheader = source.getInt("moreheader"); @@ -1329,6 +1284,7 @@ namespace DTSC { Meta::Meta(JSON::Value & meta) { vod = meta.isMember("vod") && meta["vod"]; live = meta.isMember("live") && meta["live"]; + version = meta.isMember("version") ? meta["version"].asInt() : 0; merged = meta.isMember("merged") && meta["merged"]; bufferWindow = 0; if (meta.isMember("buffer_window")) { @@ -1713,6 +1669,7 @@ namespace DTSC { dataLen += it->second.getSendLen(skipDynamic); } } + if (version){dataLen += 17;} return dataLen + 8; //add 8 bytes header } @@ -1738,6 +1695,10 @@ namespace DTSC { writePointer(p, "\000\006merged\001", 9); writePointer(p, convertLongLong(1), 8); } + if (version) { + writePointer(p, "\000\006version\001", 9); + writePointer(p, convertLongLong(version), 8); + } if (bufferWindow) { writePointer(p, "\000\015buffer_window\001", 16); writePointer(p, convertLongLong(bufferWindow), 8); @@ -1771,6 +1732,10 @@ namespace DTSC { conn.SendNow("\000\006merged\001", 9); conn.SendNow(convertLongLong(1), 8); } + if (version) { + conn.SendNow("\000\006version\001", 9); + conn.SendNow(convertLongLong(version), 8); + } if (bufferWindow) { conn.SendNow("\000\015buffer_window\001", 16); conn.SendNow(convertLongLong(bufferWindow), 8); @@ -1855,10 +1820,20 @@ namespace DTSC { if (bufferWindow) { result["buffer_window"] = bufferWindow; } + if (version) { + result["version"] = (long long)version; + } result["moreheader"] = moreheader; return result; } + ///\brief Writes metadata to a filename. Wipes existing contents, if any. + bool Meta::toFile(const std::string & fileName){ + std::ofstream oFile(fileName.c_str()); + oFile << toJSON().toNetPacked(); + oFile.close(); + } + ///\brief Converts a meta object to a human readable string ///\param str The stringstream to append to ///\param indent the amount of indentation needed