diff --git a/lib/dtsc.h b/lib/dtsc.h index de2780a6..2a401e1d 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; @@ -282,9 +282,9 @@ namespace DTSC { 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); */ - void update(long long packTime, long long packOffset, long long packDataSize, long long packBytePos, bool isKeyframe, long long packSendSize, unsigned long segment_size = 5000, const char * iVec = 0); + void update(long long packTime, long long packOffset, long long packDataSize, uint64_t packBytePos, bool isKeyframe, long long packSendSize, unsigned long segment_size = 5000, const char * iVec = 0); int getSendLen(bool skipDynamic = false); void send(Socket::Connection & conn, bool skipDynamic = false); void writeTo(char *& p); @@ -297,7 +297,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(); @@ -342,12 +342,12 @@ 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); /*LTS - 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); LTS*/ - 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, const char * iVec = 0); + 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, const char * iVec = 0); 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); @@ -367,6 +367,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 d4956d2e..2cb67fb9 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. @@ -1167,9 +1167,9 @@ namespace DTSC { ///\brief Updates a track and its metadata given new packet properties. ///Will also insert keyframes on non-video tracks, and creates fragments /*LTS - 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) { LTS*/ - void Track::update(long long packTime, long long packOffset, long long packDataSize, long long packBytePos, bool isKeyframe, long long packSendSize, unsigned long segment_size, const char * iVec) { + void Track::update(long long packTime, long long packOffset, long long packDataSize, uint64_t packBytePos, bool isKeyframe, long long packSendSize, unsigned long segment_size, const char * iVec) { if ((unsigned long long)packTime < lastms) { static bool warned = false; if (!warned){ @@ -1298,7 +1298,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()) { @@ -1320,11 +1320,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; } @@ -1404,9 +1406,9 @@ namespace DTSC { ///\brief Updates a meta object given a JSON::Value void Meta::update(JSON::Value & pack, unsigned long segment_size) { /*LTS - 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); LTS*/ - 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, pack.isMember("ivec")?pack["ivec"].asStringRef().data():0); + 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, pack.isMember("ivec")?pack["ivec"].asStringRef().data():0); } ///\brief Updates a meta object given a DTSC::Packet @@ -1418,13 +1420,13 @@ namespace DTSC { unsigned int ivecLen; pack.getString("ivec", ivec, ivecLen); /*LTS - 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); LTS*/ - 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, ivecLen?ivec:0); + 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, ivecLen?ivec:0); } ///\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); @@ -1437,7 +1439,7 @@ namespace DTSC { update(pack.getTime(), pack.hasMember("offset")?pack.getInt("offset"):0, pack.getTrackId(), dataLen, bpos, pack.hasMember("keyframe"), pack.getDataLen(), 5000, ivecLen?ivec:0); } - 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, const char * ivec){ + 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, const char * ivec){ DONTEVEN_MSG("Updating meta with: t=%lld, o=%lld, s=%lld, t=%lld, p=%lld", packTime, packOffset, packDataSize, packTrack, packBytePos); if (!packSendSize){ //time and trackID are part of the 20-byte header. @@ -1448,7 +1450,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, ivec); @@ -2022,6 +2027,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;