From 224e3a3f0d866eb8ada8f2c2de2debe98c5b4c8e Mon Sep 17 00:00:00 2001 From: Thulinma Date: Tue, 11 Oct 2016 16:03:32 +0200 Subject: [PATCH] Some small DTSC and HTTP library fixes --- lib/dtsc.h | 26 +++++++++++--- lib/dtscmeta.cpp | 84 +++++++++++++++++++++++++++++++++++++++------ lib/http_parser.cpp | 2 +- 3 files changed, 95 insertions(+), 17 deletions(-) diff --git a/lib/dtsc.h b/lib/dtsc.h index 7f464545..e94bfa7a 100644 --- a/lib/dtsc.h +++ b/lib/dtsc.h @@ -117,7 +117,7 @@ namespace DTSC { packType getVersion() const; void reInit(Socket::Connection & src); void reInit(const char * data_, unsigned int len, bool noCopy = false); - void genericFill(long long packTime, long long packOffset, long long packTrack, const char * packData, long long packDataSize, long long packBytePos, bool isKeyframe); + void genericFill(long long packTime, long long packOffset, long long packTrack, const char * packData, long long packDataSize, uint64_t packBytePos, bool isKeyframe); 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; @@ -261,7 +261,7 @@ namespace DTSC { inline operator bool() const { return (parts.size() && keySizes.size() && (keySizes.size() == keys.size())); } - void update(long long packTime, long long packOffset, long long packDataSize, long long packBytePos, bool isKeyframe, long long packSendSize, unsigned long segment_size = 5000); + void update(long long packTime, long long packOffset, long long packDataSize, uint64_t packBytePos, bool isKeyframe, long long packSendSize, unsigned long segment_size = 5000); int getSendLen(bool skipDynamic = false); void send(Socket::Connection & conn, bool skipDynamic = false); void writeTo(char *& p); @@ -273,7 +273,7 @@ namespace DTSC { Key & getKey(unsigned int keyNum); Fragment & getFrag(unsigned int fragNum); unsigned int timeToKeynum(unsigned int timestamp); - unsigned int timeToFragnum(unsigned int timestamp); + uint32_t timeToFragnum(uint64_t timestamp); void reset(); void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0); void finalize(); @@ -318,9 +318,9 @@ namespace DTSC { } void reinit(const DTSC::Packet & source); void update(DTSC::Packet & pack, unsigned long segment_size = 5000); - void updatePosOverride(DTSC::Packet & pack, unsigned long bpos); + void updatePosOverride(DTSC::Packet & pack, uint64_t bpos); void update(JSON::Value & pack, unsigned long segment_size = 5000); - void update(long long packTime, long long packOffset, long long packTrack, long long packDataSize, long long packBytePos, bool isKeyframe, long long packSendSize = 0, unsigned long segment_size = 5000); + void update(long long packTime, long long packOffset, long long packTrack, long long packDataSize, uint64_t packBytePos, bool isKeyframe, long long packSendSize = 0, unsigned long segment_size = 5000); unsigned int getSendLen(bool skipDynamic = false, std::set selectedTracks = std::set()); void send(Socket::Connection & conn, bool skipDynamic = false, std::set selectedTracks = std::set()); void writeTo(char * p); @@ -340,6 +340,22 @@ namespace DTSC { long long int bufferWindow; }; + /// An iterator helper for easily iterating over the parts in a Fragment. + class PartIter { + public: + PartIter(Track & Trk, Fragment & frag); + Part & operator*() const;///< Dereferences into a Value reference. + Part* operator->() const;///< Dereferences into a Value reference. + operator bool() const;///< True if not done iterating. + PartIter & operator++();///::iterator pIt; + std::deque::iterator kIt; + }; + /// A simple wrapper class that will open a file and allow easy reading/writing of DTSC data from/to it. class File { public: diff --git a/lib/dtscmeta.cpp b/lib/dtscmeta.cpp index 4071cf9b..68982514 100644 --- a/lib/dtscmeta.cpp +++ b/lib/dtscmeta.cpp @@ -208,7 +208,7 @@ namespace DTSC { /// Re-initializes this Packet to contain a generic DTSC packet with the given data fields. /// When given a NULL pointer, the data is reserved and memset to 0 - void Packet::genericFill(long long packTime, long long packOffset, long long packTrack, const char * packData, long long packDataSize, long long packBytePos, bool isKeyframe){ + void Packet::genericFill(long long packTime, long long packOffset, long long packTrack, const char * packData, long long packDataSize, uint64_t packBytePos, bool isKeyframe){ null(); master = true; //time and trackID are part of the 20-byte header. @@ -1122,7 +1122,7 @@ namespace DTSC { ///\brief Updates a track and its metadata given new packet properties. ///Will also insert keyframes on non-video tracks, and creates fragments - void Track::update(long long packTime, long long packOffset, long long packDataSize, long long packBytePos, bool isKeyframe, long long packSendSize, unsigned long segment_size) { + void Track::update(long long packTime, long long packOffset, long long packDataSize, uint64_t packBytePos, bool isKeyframe, long long packSendSize, unsigned long segment_size) { if ((unsigned long long)packTime < lastms) { static bool warned = false; if (!warned){ @@ -1244,7 +1244,7 @@ namespace DTSC { ///\brief Returns a key given its number, or an empty key if the number is out of bounds Key & Track::getKey(unsigned int keyNum) { static Key empty; - if (keyNum < keys[0].getNumber()) { + if (!keys.size() || keyNum < keys[0].getNumber()) { return empty; } if ((keyNum - keys[0].getNumber()) > keys.size()) { @@ -1266,11 +1266,13 @@ namespace DTSC { } /// Gets indice of the fragment containing timestamp, or last fragment if nowhere. - unsigned int Track::timeToFragnum(unsigned int timestamp){ - for (unsigned int i = 0; i::iterator it = fragments.begin(); it != fragments.end(); ++it){ + if (timestamp < getKey(it->getNumber()).getTime() + it->getDuration()){ return i; } + ++i; } return fragments.size()-1; } @@ -1349,7 +1351,7 @@ namespace DTSC { ///\brief Updates a meta object given a JSON::Value void Meta::update(JSON::Value & pack, unsigned long segment_size) { - update(pack["time"].asInt(), pack.isMember("offset")?pack["offset"].asInt():0, pack["trackid"].asInt(), pack["data"].asStringRef().size(), pack.isMember("bpos")?pack["bpos"].asInt():-1, pack.isMember("keyframe"), pack.packedSize(), segment_size); + update(pack["time"].asInt(), pack.isMember("offset")?pack["offset"].asInt():0, pack["trackid"].asInt(), pack["data"].asStringRef().size(), pack.isMember("bpos")?pack["bpos"].asInt():0, pack.isMember("keyframe"), pack.packedSize(), segment_size); } ///\brief Updates a meta object given a DTSC::Packet @@ -1357,18 +1359,18 @@ namespace DTSC { char * data; unsigned int dataLen; pack.getString("data", data, dataLen); - update(pack.getTime(), pack.hasMember("offset")?pack.getInt("offset"):0, pack.getTrackId(), dataLen, pack.hasMember("bpos")?pack.getInt("bpos"):-1, pack.hasMember("keyframe"), pack.getDataLen(), segment_size); + update(pack.getTime(), pack.hasMember("offset")?pack.getInt("offset"):0, pack.getTrackId(), dataLen, pack.hasMember("bpos")?pack.getInt("bpos"):0, pack.hasMember("keyframe"), pack.getDataLen(), segment_size); } ///\brief Updates a meta object given a DTSC::Packet with byte position override. - void Meta::updatePosOverride(DTSC::Packet & pack, unsigned long bpos) { + void Meta::updatePosOverride(DTSC::Packet & pack, uint64_t bpos) { char * data; unsigned int dataLen; pack.getString("data", data, dataLen); update(pack.getTime(), pack.hasMember("offset")?pack.getInt("offset"):0, pack.getTrackId(), dataLen, bpos, pack.hasMember("keyframe"), pack.getDataLen()); } - void Meta::update(long long packTime, long long packOffset, long long packTrack, long long packDataSize, long long packBytePos, bool isKeyframe, long long packSendSize, unsigned long segment_size){ + void Meta::update(long long packTime, long long packOffset, long long packTrack, long long packDataSize, uint64_t packBytePos, bool isKeyframe, long long packSendSize, unsigned long segment_size){ if (!packSendSize){ //time and trackID are part of the 20-byte header. //the container object adds 4 bytes (plus 2+namelen for each content, see below) @@ -1378,7 +1380,10 @@ namespace DTSC { //data adds packDataSize+5 bytes (string type) and 6 bytes (2+namelen) packSendSize = 24 + (packOffset?17:0) + (packBytePos>=0?15:0) + (isKeyframe?19:0) + packDataSize+11; } - vod = (packBytePos >= 0); + if (vod != (packBytePos > 0)){ + INFO_MSG("Changing stream from %s to %s (bPos=%lld)", vod?"VoD":"live", (packBytePos >= 0)?"Vod":"live", packBytePos); + } + vod = (packBytePos > 0); live = !vod; if (packTrack > 0 && tracks.count(packTrack)){ tracks[packTrack].update(packTime, packOffset, packDataSize, packBytePos, isKeyframe, packSendSize, segment_size); @@ -1929,6 +1934,63 @@ namespace DTSC { it->second.reset(); } } + + + PartIter::PartIter(Track & Trk, Fragment & frag){ + tRef = &Trk; + pIt = tRef->parts.begin(); + kIt = tRef->keys.begin(); + uint32_t fragNum = frag.getNumber(); + while (kIt->getNumber() < fragNum && kIt != tRef->keys.end()){ + uint32_t kParts = kIt->getParts(); + for (uint32_t pCount = 0; pCount < kParts && pIt != tRef->parts.end(); ++pCount){ + ++pIt; + } + ++kIt; + } + if (kIt == tRef->keys.end()){tRef = 0;} + currInKey = 0; + lastKey = fragNum + frag.getLength(); + } + + /// Dereferences into a Value reference. + /// If invalid iterator, returns an empty reference and prints a warning message. + Part & PartIter::operator*() const{ + if (tRef && pIt != tRef->parts.end()){ + return *pIt; + } + static Part error; + WARN_MSG("Dereferenced invalid Part iterator"); + return error; + } + + /// Dereferences into a Value reference. + /// If invalid iterator, returns an empty reference and prints a warning message. + Part* PartIter::operator->() const{ + return &(operator*()); + } + + /// True if not done iterating. + PartIter::operator bool() const{ + return (tRef && pIt != tRef->parts.end()); + } + + PartIter & PartIter::operator++(){ + if (*this){ + ++pIt; + if (++currInKey >= kIt->getParts()){ + currInKey = 0; + //check if we're done iterating - we assume done if past the last key or arrived past the fragment + if (++kIt == tRef->keys.end() || kIt->getNumber() >= lastKey){ + tRef = 0; + } + } + } + return *this; + } + + + } diff --git a/lib/http_parser.cpp b/lib/http_parser.cpp index e1704330..46510b74 100644 --- a/lib/http_parser.cpp +++ b/lib/http_parser.cpp @@ -696,7 +696,7 @@ void HTTP::Parser::Chunkify(const char * data, unsigned int size, Socket::Connec if (sendingChunks) { //prepend the chunk size and \r\n if (!size){ - conn.SendNow("0\r\n\r\n\r\n", 7); + conn.SendNow("0\r\n\r\n", 5); } size_t offset = 8; unsigned int t_size = size;