From d45a89c5e6bba393a0f112865f8d300b0f3ed360 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Fri, 9 Jun 2017 20:09:12 +0200 Subject: [PATCH 1/4] Added isKeyframe function to H264 library --- lib/h264.cpp | 30 ++++++++++++++++++++++++++++++ lib/h264.h | 1 + 2 files changed, 31 insertions(+) diff --git a/lib/h264.cpp b/lib/h264.cpp index 408a9900..05688266 100644 --- a/lib/h264.cpp +++ b/lib/h264.cpp @@ -9,6 +9,36 @@ #include "defines.h" namespace h264 { + + ///Helper function to determine if a H264 NAL unit is a keyframe or not + bool isKeyframe(const char * data, uint32_t len){ + uint8_t nalType = (data[0] & 0x1F); + if (nalType == 0x05){return true;} + if (nalType != 0x01){return false;} + Utils::bitstream bs; + for (size_t i = 1; i < 10 && i < len; ++i) { + if (i + 2 < len && (memcmp(data + i, "\000\000\003", 3) == 0)) { //Emulation prevention bytes + bs.append(data + i, 2); + i += 2; + } else { + bs.append(data + i, 1); + } + } + bs.getExpGolomb();//Discard first_mb_in_slice + uint64_t sliceType = bs.getUExpGolomb(); + //Slice types: + // 0: P - Predictive slice (at most 1 reference) + // 1: B - Bi-predictive slice (at most 2 references) + // 2: I - Intra slice (no external references) + // 3: SP - Switching predictive slice (at most 1 reference) + // 4: SI - Switching intra slice (no external references) + // 5-9: 0-4, but all in picture of same type + if (sliceType == 2 || sliceType == 4 || sliceType == 7 || sliceType == 9){ + return true; + } + return false; + } + std::deque analysePackets(const char * data, unsigned long len){ std::deque res; diff --git a/lib/h264.h b/lib/h264.h index 0afd0540..7578308f 100644 --- a/lib/h264.h +++ b/lib/h264.h @@ -67,4 +67,5 @@ namespace h264 { unsigned long dataLen; }; + bool isKeyframe(const char * data, uint32_t len); } From c7c94dc3c34cd17c93f8680cb37fd42ffeb6463a Mon Sep 17 00:00:00 2001 From: Thulinma Date: Thu, 1 Jun 2017 20:52:15 +0200 Subject: [PATCH 2/4] Added Util::bootMS() to timing library --- lib/timing.cpp | 6 ++++++ lib/timing.h | 1 + 2 files changed, 7 insertions(+) diff --git a/lib/timing.cpp b/lib/timing.cpp index f2e02c1c..78ff8824 100644 --- a/lib/timing.cpp +++ b/lib/timing.cpp @@ -81,6 +81,12 @@ long long int Util::bootSecs() { return t.tv_sec; } +uint64_t Util::bootMS() { + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + return ((uint64_t)t.tv_sec) * 1000 + t.tv_nsec / 1000000; +} + /// Gets the current time in microseconds. long long unsigned int Util::getMicros() { struct timespec t; diff --git a/lib/timing.h b/lib/timing.h index e7486806..e1d8ebab 100644 --- a/lib/timing.h +++ b/lib/timing.h @@ -9,6 +9,7 @@ namespace Util { void sleep(int ms); ///< Sleeps for roughly the indicated amount of milliseconds. long long int getMS(); ///< Gets the current time in milliseconds. long long int bootSecs(); ///< Gets the current system uptime in seconds. + uint64_t bootMS(); ///< Gets the current system uptime in milliseconds. long long unsigned int getMicros();/// Date: Thu, 1 Jun 2017 20:52:32 +0200 Subject: [PATCH 3/4] Optimized socket library, added generic splitter function --- lib/socket.cpp | 60 ++++++++++++++++++++++++++++++++++++++++---------- lib/socket.h | 3 +++ 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/lib/socket.cpp b/lib/socket.cpp index 41883955..55c378a0 100644 --- a/lib/socket.cpp +++ b/lib/socket.cpp @@ -65,6 +65,10 @@ std::string uint2string(unsigned int i){ return st.str(); } +Socket::Buffer::Buffer(){ + splitter = "\n"; +} + /// Returns the amount of elements in the internal std::deque of std::string objects. /// The back is popped as long as it is empty, first - this way this function is /// guaranteed to return 0 if the buffer is empty. @@ -83,26 +87,58 @@ unsigned int Socket::Buffer::bytes(unsigned int max){ return i; } +/// Returns how many bytes to read until the next splitter, or 0 if none found. +unsigned int Socket::Buffer::bytesToSplit(){ + unsigned int i = 0; + for (std::deque::reverse_iterator it = data.rbegin(); it != data.rend(); ++it){ + i += (*it).size(); + if ((*it).size() >= splitter.size() && (*it).substr((*it).size()-splitter.size()) == splitter){ + return i; + } + } + return 0; +} + /// Appends this string to the internal std::deque of std::string objects. -/// It is automatically split every BUFFER_BLOCKSIZE bytes. +/// It is automatically split every BUFFER_BLOCKSIZE bytes and when the splitter string is encountered. void Socket::Buffer::append(const std::string &newdata){ - append(newdata.c_str(), newdata.size()); + append(newdata.data(), newdata.size()); +} + +///Helper function that does a short-circuiting string compare +inline bool string_compare(const char *a, const char *b, const size_t len){ + for (size_t i = 0; i < len; ++i){ + if (a[i] != b[i]){return false;} + } + return true; } /// Appends this data block to the internal std::deque of std::string objects. -/// It is automatically split every BUFFER_BLOCKSIZE bytes. +/// It is automatically split every BUFFER_BLOCKSIZE bytes and when the splitter string is encountered. void Socket::Buffer::append(const char *newdata, const unsigned int newdatasize){ - unsigned int i = 0, j = 0; + uint32_t i = 0; while (i < newdatasize){ - j = i; - while (j < newdatasize && j - i <= BUFFER_BLOCKSIZE){ - j++; - if (newdata[j - 1] == '\n'){break;} - } - if (i != j){ - data.push_front(std::string(newdata + i, (size_t)(j - i))); - i = j; + uint32_t j = 0; + if (!splitter.size()){ + if (newdatasize - i > BUFFER_BLOCKSIZE){ + j = BUFFER_BLOCKSIZE; + }else{ + j = newdatasize - i; + } }else{ + while (j+i < newdatasize && j < BUFFER_BLOCKSIZE){ + j++; + if (j >= splitter.size()){ + if (string_compare(newdata+i+j-splitter.size(), splitter.data(), splitter.size())){break;} + } + } + } + if (j){ + data.push_front(""); + data.front().assign(newdata + i, (size_t)j); + i += j; + }else{ + FAIL_MSG("Appended an empty string to buffer: aborting!"); break; } } diff --git a/lib/socket.h b/lib/socket.h index 7704143d..0975c283 100644 --- a/lib/socket.h +++ b/lib/socket.h @@ -32,8 +32,11 @@ namespace Socket{ std::deque data; public: + std::string splitter;/// Date: Wed, 7 Jun 2017 14:22:52 +0200 Subject: [PATCH 4/4] Added ability to print backtraces in defines.h --- lib/defines.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/defines.h b/lib/defines.h index e9d5c40e..bc393c91 100644 --- a/lib/defines.h +++ b/lib/defines.h @@ -37,12 +37,30 @@ static const char * DBG_LVL_LIST[] = {"NONE", "FAIL", "ERROR", "WARN", "INFO", " #endif #endif +#include +static inline void show_stackframe() { + void *trace[16]; + char **messages = 0; + int i, trace_size = 0; + trace_size = backtrace(trace, 16); + messages = backtrace_symbols(trace, trace_size); + for (i=1; i