diff --git a/lib/defines.h b/lib/defines.h index cbdf9659..5da8a135 100644 --- a/lib/defines.h +++ b/lib/defines.h @@ -16,6 +16,8 @@ #define DLVL_DONTEVEN 10 // All messages enabled, even pointless ones. #define PRETTY_PRINT_TIME "%ud%uh%um%us" #define PRETTY_ARG_TIME(t) (int)(t)/86400, ((int)(t)%86400)/3600, ((int)(t)%3600)/60, (int)(t)%60 +#define PRETTY_PRINT_MSTIME "%ud%.2uh%.2um%.2us.%.3u" +#define PRETTY_ARG_MSTIME(t) PRETTY_ARG_TIME(t/1000), (int)(t%1000) #if DEBUG > -1 #define __STDC_FORMAT_MACROS 1 diff --git a/lib/socket.cpp b/lib/socket.cpp index b591fa58..1a62cf85 100644 --- a/lib/socket.cpp +++ b/lib/socket.cpp @@ -372,6 +372,29 @@ void Socket::Buffer::clear(){ data.clear(); } +void Socket::Connection::setBoundAddr(){ + if (!isTrueSocket){ + boundaddr = ""; + return; + } + struct sockaddr_in6 tmpaddr; + socklen_t len = sizeof(tmpaddr); + if (!getsockname(sSend, (sockaddr*)&tmpaddr, &len)){ + static char addrconv[INET6_ADDRSTRLEN]; + if (tmpaddr.sin6_family == AF_INET6){ + boundaddr = inet_ntop(AF_INET6, &(tmpaddr.sin6_addr), addrconv, INET6_ADDRSTRLEN); + if (boundaddr.substr(0, 7) == "::ffff:"){ + boundaddr = boundaddr.substr(7); + } + HIGH_MSG("Local IPv6 addr [%s]", boundaddr.c_str()); + } + if (tmpaddr.sin6_family == AF_INET){ + boundaddr = inet_ntop(AF_INET, &(((sockaddr_in *)&tmpaddr)->sin_addr), addrconv, INET6_ADDRSTRLEN); + HIGH_MSG("Local IPv4 addr [%s]", boundaddr.c_str()); + } + } +} + /// Create a new base socket. This is a basic constructor for converting any valid socket to a /// Socket::Connection. \param sockNo Integer representing the socket to convert. Socket::Connection::Connection(int sockNo){ @@ -380,6 +403,7 @@ Socket::Connection::Connection(int sockNo){ isTrueSocket = false; struct stat sBuf; if (sSend != -1 && !fstat(sSend, &sBuf)){isTrueSocket = S_ISSOCK(sBuf.st_mode);} + setBoundAddr(); up = 0; down = 0; conntime = Util::epoch(); @@ -401,6 +425,7 @@ Socket::Connection::Connection(int write, int read){ isTrueSocket = false; struct stat sBuf; if (sSend != -1 && !fstat(sSend, &sBuf)){isTrueSocket = S_ISSOCK(sBuf.st_mode);} + setBoundAddr(); up = 0; down = 0; conntime = Util::epoch(); @@ -600,6 +625,7 @@ Socket::Connection::Connection(std::string host, int port, bool nonblock){ int optval = 1; int optlen = sizeof(optval); setsockopt(sSend, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen); + setBoundAddr(); } }// Socket::Connection TCP Constructor @@ -796,6 +822,11 @@ std::string Socket::Connection::getHost() const{ return remotehost; } +/// Gets locally bound host for connection, if available. +std::string Socket::Connection::getBoundAddress() const{ + return boundaddr; +} + /// Gets binary IPv6 address for connection, if available. /// Guaranteed to be either empty or 16 bytes long. std::string Socket::Connection::getBinHost(){ diff --git a/lib/socket.h b/lib/socket.h index cdc8b1b3..e378530c 100644 --- a/lib/socket.h +++ b/lib/socket.h @@ -74,6 +74,7 @@ namespace Socket{ int sSend; ///< Write end of socket. int sRecv; ///< Read end of socket. std::string remotehost; ///< Stores remote host address. + std::string boundaddr; ///< Stores bound interface address. struct sockaddr_in6 remoteaddr;///< Stores remote host address. uint64_t up; uint64_t down; @@ -83,6 +84,7 @@ namespace Socket{ virtual unsigned int iwrite(const void *buffer, int len); ///< Incremental write call. bool iread(Buffer &buffer, int flags = 0); ///< Incremental write call that is compatible with Socket::Buffer. bool iwrite(std::string &buffer); ///< Write call that is compatible with std::string. + void setBoundAddr(); public: // friends friend class ::Buffer::user; @@ -100,6 +102,7 @@ namespace Socket{ std::string getHost() const; ///< Gets hostname for connection, if available. std::string getBinHost(); void setHost(std::string host); ///< Sets hostname for connection manually. + std::string getBoundAddress() const; int getSocket(); ///< Returns internal socket number. int getPureSocket(); ///< Returns non-piped internal socket number. std::string getError(); ///< Returns a string describing the last error that occured. diff --git a/src/input/input_ebml.h b/src/input/input_ebml.h index 4d4af639..55079f2d 100644 --- a/src/input/input_ebml.h +++ b/src/input/input_ebml.h @@ -52,7 +52,7 @@ namespace Mist{ if (finished){ return (ctr - rem > 0); }else{ - return (ctr - rem > 12); + return frameOffsetKnown ? (ctr - rem > 1) : (ctr - rem > 12); } } /// Clears all internal values, for reuse as-new. @@ -76,6 +76,11 @@ namespace Mist{ }else{ if (rem && !p.key){ p.offset = p.time + maxEBMLFrameOffset - (lastTime + smallestFrame); + if (p.offset > (maxEBMLFrameOffset + frameOffset + smallestFrame)){ + uint64_t diff = p.offset - (maxEBMLFrameOffset + frameOffset + smallestFrame); + p.offset -= diff; + lastTime += diff; + } //If we calculate an offset less than a frame away, //we assume it's just time stamp drift due to lack of precision. p.time = (lastTime + smallestFrame); @@ -96,15 +101,16 @@ namespace Mist{ } if (isVideo && ctr && ctr >= rem){ int32_t currOffset = packTime - pkts[(ctr-1)%PKT_COUNT].time; + if (!frameOffsetKnown && currOffset < 0 && -currOffset < 8 * smallestFrame && + -currOffset * 2 > maxEBMLFrameOffset && ctr < PKT_COUNT / 2){ + maxEBMLFrameOffset = -currOffset * 2; + INFO_MSG("Max frame offset is now %u", maxEBMLFrameOffset); + } if (currOffset < 0){currOffset *= -1;} if (!smallestFrame || currOffset < smallestFrame){ smallestFrame = currOffset; HIGH_MSG("Smallest frame is now %u", smallestFrame); } - if (!frameOffsetKnown && currOffset < 8*smallestFrame && currOffset*2 > maxEBMLFrameOffset && ctr < PKT_COUNT/2){ - maxEBMLFrameOffset = currOffset*2; - INFO_MSG("Max frame offset is now %u", maxEBMLFrameOffset); - } } DONTEVEN_MSG("Ingesting %llu (%llu -> %llu)", packTime, ctr, ctr % PKT_COUNT); pkts[ctr % PKT_COUNT].set(packTime, packOffset, packTrack, packDataSize, packBytePos, isKeyframe, dataPtr); diff --git a/src/output/output_ebml.cpp b/src/output/output_ebml.cpp index 6c6872b1..d078b7f7 100644 --- a/src/output/output_ebml.cpp +++ b/src/output/output_ebml.cpp @@ -108,6 +108,7 @@ namespace Mist{ /// Calculates the size of a Cluster (contents only) and returns it. /// Bases the calculation on the currently selected tracks and the given start/end time for the cluster. uint32_t OutEBML::clusterSize(uint64_t start, uint64_t end){ + if (start == end){++end;} uint32_t sendLen = EBML::sizeElemUInt(EBML::EID_TIMECODE, start); for (std::set::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){