Merge branch 'development' into LTS_development

# Conflicts:
#	lib/h264.h
This commit is contained in:
Thulinma 2017-06-09 20:14:23 +02:00
commit 416254304a
7 changed files with 108 additions and 12 deletions

View file

@ -37,12 +37,30 @@ static const char * DBG_LVL_LIST[] = {"NONE", "FAIL", "ERROR", "WARN", "INFO", "
#endif #endif
#endif #endif
#include <execinfo.h>
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<trace_size; ++i){
size_t p = 0;
while(messages[i][p] != '(' && messages[i][p] != ' ' && messages[i][p] != 0){
++p;
}
DEBUG_MSG(0, "Backtrace[%d]: %s", i, messages[i]+p);
}
}
#else #else
#define DEBUG_MSG(lvl, msg, ...) // Debugging disabled. #define DEBUG_MSG(lvl, msg, ...) // Debugging disabled.
static inline void show_stackframe(){}
#endif #endif
#define BACKTRACE show_stackframe();
#define FAIL_MSG(msg, ...) DEBUG_MSG(DLVL_FAIL, msg, ##__VA_ARGS__) #define FAIL_MSG(msg, ...) DEBUG_MSG(DLVL_FAIL, msg, ##__VA_ARGS__)
#define ERROR_MSG(msg, ...) DEBUG_MSG(DLVL_ERROR, msg, ##__VA_ARGS__) #define ERROR_MSG(msg, ...) DEBUG_MSG(DLVL_ERROR, msg, ##__VA_ARGS__)
#define WARN_MSG(msg, ...) DEBUG_MSG(DLVL_WARN, msg, ##__VA_ARGS__) #define WARN_MSG(msg, ...) DEBUG_MSG(DLVL_WARN, msg, ##__VA_ARGS__)

View file

@ -10,6 +10,36 @@
#include "defines.h" #include "defines.h"
namespace h264 { 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<nalu::nalData> analysePackets(const char * data, unsigned long len){ std::deque<nalu::nalData> analysePackets(const char * data, unsigned long len){
std::deque<nalu::nalData> res; std::deque<nalu::nalData> res;

View file

@ -72,6 +72,8 @@ namespace h264 {
size_t dataLen; size_t dataLen;
}; };
bool isKeyframe(const char * data, uint32_t len);
class nalUnit { class nalUnit {
public: public:
nalUnit(const char * data, size_t len) : payload(data, len) {} nalUnit(const char * data, size_t len) : payload(data, len) {}

View file

@ -65,6 +65,10 @@ std::string uint2string(unsigned int i){
return st.str(); return st.str();
} }
Socket::Buffer::Buffer(){
splitter = "\n";
}
/// Returns the amount of elements in the internal std::deque of std::string objects. /// 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 /// 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. /// guaranteed to return 0 if the buffer is empty.
@ -83,26 +87,58 @@ unsigned int Socket::Buffer::bytes(unsigned int max){
return i; 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<std::string>::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. /// 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){ 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. /// 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){ void Socket::Buffer::append(const char *newdata, const unsigned int newdatasize){
unsigned int i = 0, j = 0; uint32_t i = 0;
while (i < newdatasize){ while (i < newdatasize){
j = i; uint32_t j = 0;
while (j < newdatasize && j - i <= BUFFER_BLOCKSIZE){ if (!splitter.size()){
j++; if (newdatasize - i > BUFFER_BLOCKSIZE){
if (newdata[j - 1] == '\n'){break;} j = BUFFER_BLOCKSIZE;
} }else{
if (i != j){ j = newdatasize - i;
data.push_front(std::string(newdata + i, (size_t)(j - i))); }
i = j;
}else{ }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; break;
} }
} }

View file

@ -32,8 +32,11 @@ namespace Socket{
std::deque<std::string> data; std::deque<std::string> data;
public: public:
std::string splitter;///<String to automatically split on if encountered. \n by default
Buffer();
unsigned int size(); unsigned int size();
unsigned int bytes(unsigned int max); unsigned int bytes(unsigned int max);
unsigned int bytesToSplit();
void append(const std::string &newdata); void append(const std::string &newdata);
void append(const char *newdata, const unsigned int newdatasize); void append(const char *newdata, const unsigned int newdatasize);
void prepend(const std::string &newdata); void prepend(const std::string &newdata);

View file

@ -81,6 +81,12 @@ long long int Util::bootSecs() {
return t.tv_sec; 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. /// Gets the current time in microseconds.
long long unsigned int Util::getMicros() { long long unsigned int Util::getMicros() {
struct timespec t; struct timespec t;

View file

@ -9,6 +9,7 @@ namespace Util {
void sleep(int ms); ///< Sleeps for roughly the indicated amount of milliseconds. 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 getMS(); ///< Gets the current time in milliseconds.
long long int bootSecs(); ///< Gets the current system uptime in seconds. 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();///<Gets the current time in microseconds. long long unsigned int getMicros();///<Gets the current time in microseconds.
long long unsigned int getMicros(long long unsigned int previous);///<Gets the time difference in microseconds. long long unsigned int getMicros(long long unsigned int previous);///<Gets the time difference in microseconds.
long long int getNTP(); long long int getNTP();