From 3ab582d60bbdd5c2874756c311891fc37178065e Mon Sep 17 00:00:00 2001 From: Balder Date: Tue, 9 Aug 2016 11:03:49 +0200 Subject: [PATCH 1/7] Added bigmeta to cmakelist and ifdef flag to config.cpp --- CMakeLists.txt | 4 +++- lib/config.cpp | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 06961af3..ba98f003 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,7 +68,9 @@ endif() if (NOT DEFINED NOSHM ) add_definitions(-DSHM_ENABLED=1) endif() - +if (DEFINED BIGMETA ) + add_definitions(-DBIGMETA=1) +endif() ######################################## # Build Variables - Thread Names # ######################################## diff --git a/lib/config.cpp b/lib/config.cpp index 7f3990c8..304dc297 100644 --- a/lib/config.cpp +++ b/lib/config.cpp @@ -206,6 +206,9 @@ bool Util::Config::parseArgs(int & argc, char ** & argv) { #ifdef WITH_THREADNAMES std::cout << "- Flag: With threadnames. Debuggers will show sensible human-readable thread names." << std::endl; #endif + #ifdef BIGMETA + std::cout << "- Flag: Big metadata. Enabled longer live stream durations. Breaks compatibility with DTSH files generated by versions without this flag." << std::endl; + #endif std::cout << "Built on " __DATE__ ", " __TIME__ << std::endl; exit(1); break; From 228a03a004fea58c264cdac04d8c3c2d0b33f24f Mon Sep 17 00:00:00 2001 From: Thulinma Date: Fri, 2 Sep 2016 14:31:20 +0200 Subject: [PATCH 2/7] Added Encodings::Hex::decode --- lib/encode.cpp | 10 ++++++++++ lib/encode.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/lib/encode.cpp b/lib/encode.cpp index 32bd8da6..41609a6f 100644 --- a/lib/encode.cpp +++ b/lib/encode.cpp @@ -102,6 +102,16 @@ namespace Encodings { return r; } + /// Decodes a hex-encoded std::string to a raw binary std::string. + std::string Hex::decode(const std::string & in){ + std::string ret(in.size()/2, '\000'); + for (size_t i = 0; i < in.size(); ++i){ + char c = in[i]; + ret[i>>1] |= ((c&15) + (((c&64)>>6) | ((c&64)>>3))) << ((~i&1) << 2); + } + return ret; + } + /// urlencodes std::string data, leaving only the characters A-Za-z0-9~!&()' alone. std::string URL::encode(const std::string & c){ std::string escaped = ""; diff --git a/lib/encode.h b/lib/encode.h index c7fb2eac..a604bb42 100644 --- a/lib/encode.h +++ b/lib/encode.h @@ -33,6 +33,9 @@ namespace Encodings { } /// Encodes a single character as two hex digits in string form. static std::string chr(char dec); + + /// Decodes a hex-encoded std::string to a raw binary std::string. + static std::string decode(const std::string & in); }; } From 4538efb89bddcc5a71f0f7a4597694cc6a9560ea Mon Sep 17 00:00:00 2001 From: Thulinma Date: Fri, 2 Sep 2016 14:31:54 +0200 Subject: [PATCH 3/7] Added/improved start/endTime functions in Output class --- src/output/output.cpp | 27 ++++++++++++++++++++++----- src/output/output.h | 1 + 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/output/output.cpp b/src/output/output.cpp index afe4aded..517a3801 100644 --- a/src/output/output.cpp +++ b/src/output/output.cpp @@ -466,14 +466,31 @@ namespace Mist { return buffer.begin()->time; } - ///Return the end time of the VoD asset, or 0 if unknown. + ///Return the start time of the selected tracks. + uint64_t Output::startTime(){ + uint64_t start = 0xFFFFFFFFFFFFFFFFull; + if (selectedTracks.size()){ + for (std::set::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){ + if (myMeta.tracks.count(*it)){ + if (start < myMeta.tracks[*it].firstms){ + start = myMeta.tracks[*it].firstms; + } + } + } + } + return start; + } + + ///Return the end time of the selected tracks, or 0 if unknown or live. uint64_t Output::endTime(){ if (myMeta.live){return 0;} uint64_t end = 0; - for (std::set::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){ - if (myMeta.tracks.count(*it)){ - if (end < myMeta.tracks[*it].lastms){ - end = myMeta.tracks[*it].lastms; + if (selectedTracks.size()){ + for (std::set::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){ + if (myMeta.tracks.count(*it)){ + if (end < myMeta.tracks[*it].lastms){ + end = myMeta.tracks[*it].lastms; + } } } } diff --git a/src/output/output.h b/src/output/output.h index 718856a7..b19df26d 100644 --- a/src/output/output.h +++ b/src/output/output.h @@ -47,6 +47,7 @@ namespace Mist { bool seek(unsigned int tid, unsigned long long pos, bool getNextKey = false); void stop(); uint64_t currentTime(); + uint64_t startTime(); uint64_t endTime(); void setBlocking(bool blocking); long unsigned int getMainSelectedTrack(); From 50e8c7638a58f4a389b2c06a290c0a81a3be574c Mon Sep 17 00:00:00 2001 From: Thulinma Date: Fri, 2 Sep 2016 14:32:15 +0200 Subject: [PATCH 4/7] Verbosity tweak --- src/io.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io.cpp b/src/io.cpp index 454aa32f..c9ccfa77 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -670,7 +670,7 @@ namespace Mist { break; } - MEDIUM_MSG("Buffer has indicated that incoming track %lu should start writing on track %lu, page %lu", tid, finalTid, firstPage); + MEDIUM_MSG("Buffer says %s:%lu should start writing on track %lu, page %lu", streamName.c_str(), tid, finalTid, firstPage); trackMap[tid] = finalTid; if (myMeta.tracks.count(finalTid) && myMeta.tracks[finalTid].lastms){ myMeta.tracks[finalTid].lastms = 0; From aedc8df4946b4a151ca8b0336db30ec6af180928 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Fri, 2 Sep 2016 14:33:15 +0200 Subject: [PATCH 5/7] Added UDP getDestPort function --- lib/socket.cpp | 35 +++++++++++++++++++++++++++-------- lib/socket.h | 1 + 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/lib/socket.cpp b/lib/socket.cpp index 8458c911..54675a3b 100644 --- a/lib/socket.cpp +++ b/lib/socket.cpp @@ -1023,8 +1023,12 @@ Socket::UDPConnection::UDPConnection(const UDPConnection & o) { destAddr = 0; destAddr_size = 0; } - data = 0; - data_size = 0; + data = (char*)malloc(1024); + if (data){ + data_size = 1024; + }else{ + data_size = 0; + } data_len = 0; } @@ -1103,6 +1107,19 @@ void Socket::UDPConnection::GetDestination(std::string & destIp, uint32_t & port DEBUG_MSG(DLVL_FAIL, "Could not get destination for UDP socket"); }//Socket::UDPConnection GetDestination +/// Returns the port number of the receiving end of this socket. +/// Returns 0 on error. +uint32_t Socket::UDPConnection::getDestPort() const{ + if (!destAddr || !destAddr_size){return 0;} + if (((struct sockaddr_in *)destAddr)->sin_family == AF_INET6) { + return ntohs(((struct sockaddr_in6 *)destAddr)->sin6_port); + } + if (((struct sockaddr_in *)destAddr)->sin_family == AF_INET) { + return ntohs(((struct sockaddr_in *)destAddr)->sin_port); + } + return 0; +} + /// Sets the socket to be blocking if the parameters is true. /// Sets the socket to be non-blocking otherwise. void Socket::UDPConnection::setBlocking(bool blocking) { @@ -1214,20 +1231,22 @@ bool Socket::UDPConnection::Receive() { data_size = SOCKETSIZE; } #endif - int r = recvfrom(sock, data, data_size, MSG_PEEK | MSG_TRUNC, 0, 0); + int r = recvfrom(sock, data, data_size, MSG_PEEK | MSG_TRUNC | MSG_DONTWAIT, 0, 0); if (r == -1) { if (errno != EAGAIN) { - INFO_MSG("Found an error: %d (%s)", errno, strerror(errno)); + INFO_MSG("UDP receive: %d (%s)", errno, strerror(errno)); } data_len = 0; return false; } if (data_size < (unsigned int)r) { - data = (char *)realloc(data, r); - if (data) { + char* tmp = (char*)realloc(data, r); + if (tmp) { + data = tmp; data_size = r; - } else { - data_size = 0; + }else{ + FAIL_MSG("Could not resize socket buffer to %d bytes!", r); + return false; } } socklen_t destsize = destAddr_size; diff --git a/lib/socket.h b/lib/socket.h index 633d6ab5..78cd13cb 100644 --- a/lib/socket.h +++ b/lib/socket.h @@ -141,6 +141,7 @@ namespace Socket { void setBlocking(bool blocking); void SetDestination(std::string hostname, uint32_t port); void GetDestination(std::string & hostname, uint32_t & port); + uint32_t getDestPort() const; bool Receive(); void SendNow(const std::string & data); void SendNow(const char * data); From e8e97adb4980e09d6592eb1e66f9232369e5abb3 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Fri, 2 Sep 2016 14:33:45 +0200 Subject: [PATCH 6/7] Improved HTTP library GetHeader/GetVar functions, added hasHeader function --- lib/http_parser.cpp | 24 ++++++++++++++++++++---- lib/http_parser.h | 5 +++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/lib/http_parser.cpp b/lib/http_parser.cpp index f353c0dd..165d5761 100644 --- a/lib/http_parser.cpp +++ b/lib/http_parser.cpp @@ -305,12 +305,28 @@ std::string HTTP::Parser::getUrl() { } /// Returns header i, if set. -std::string HTTP::Parser::GetHeader(std::string i) { - return headers[i]; +const std::string & HTTP::Parser::GetHeader(const std::string & i) const { + if (headers.count(i)){ + return headers.at(i); + }else{ + static const std::string empty; + return empty; + } } + +/// Returns header i, if set. +bool HTTP::Parser::hasHeader(const std::string & i) const { + return headers.count(i); +} + /// Returns POST variable i, if set. -std::string HTTP::Parser::GetVar(std::string i) { - return vars[i]; +const std::string & HTTP::Parser::GetVar(const std::string & i) const { + if (vars.count(i)){ + return vars.at(i); + }else{ + static const std::string empty; + return empty; + } } std::string HTTP::Parser::allVars(){ diff --git a/lib/http_parser.h b/lib/http_parser.h index 52084ab1..5a716af6 100644 --- a/lib/http_parser.h +++ b/lib/http_parser.h @@ -16,9 +16,10 @@ namespace HTTP { Parser(); bool Read(Socket::Connection & conn); bool Read(std::string & strbuf); - std::string GetHeader(std::string i); + const std::string & GetHeader(const std::string & i) const; + bool hasHeader(const std::string & i) const; void clearHeader(const std::string & i); - std::string GetVar(std::string i); + const std::string & GetVar(const std::string & i) const; std::string getUrl(); std::string allVars(); void SetHeader(std::string i, std::string v); From eb5cdb32b1c7df6504b3339a83fcbd7849983096 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Fri, 2 Sep 2016 14:43:33 +0200 Subject: [PATCH 7/7] Added more H264 SPS decoding --- lib/h264.cpp | 61 ++++++++++++++++++++++++++++++++++++---------------- lib/h264.h | 7 ++++++ 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/lib/h264.cpp b/lib/h264.cpp index 79101e05..97bd6320 100644 --- a/lib/h264.cpp +++ b/lib/h264.cpp @@ -88,15 +88,27 @@ namespace h264 { dataLen = Bit::btohs(dtscInit.data() + 6); } + void skipScalingList(Utils::bitstream & bs, size_t listSize){ + size_t lastScale = 8; + size_t nextScale = 8; + for (size_t i = 0; i < listSize; i++){ + if (nextScale){ + uint64_t deltaScale = bs.getExpGolomb(); + nextScale = (lastScale + deltaScale + 256) % 256; + } + lastScale = (nextScale ? nextScale : lastScale); + } + } + SPSMeta sequenceParameterSet::getCharacteristics() const { SPSMeta result; + result.sep_col_plane = false; //For calculating width unsigned int widthInMbs = 0; unsigned int cropHorizontal = 0; //For calculating height - bool mbsOnlyFlag = 0; unsigned int heightInMapUnits = 0; unsigned int cropVertical = 0; @@ -121,33 +133,44 @@ namespace h264 { bs.getUExpGolomb(); if (profileIdc == 100 || profileIdc == 110 || profileIdc == 122 || profileIdc == 244 || profileIdc == 44 || profileIdc == 83 || profileIdc == 86 || profileIdc == 118 || profileIdc == 128) { //chroma format idc - if (bs.getUExpGolomb() == 3) { - bs.skip(1); + char chromaFormatIdc = bs.getUExpGolomb(); + if (chromaFormatIdc == 3) { + result.sep_col_plane = (bs.get(1) == 1); } - bs.getUExpGolomb(); - bs.getUExpGolomb(); - bs.skip(1); - if (bs.get(1)) { - DEBUG_MSG(DLVL_DEVEL, "Scaling matrix not implemented yet"); + bs.getUExpGolomb();//luma + bs.getUExpGolomb();//chroma + bs.skip(1);//transform bypass + if (bs.get(1)) {//Scaling matrix is present + char listSize = (chromaFormatIdc == 3 ? 12 : 8); + for (size_t i = 0; i < listSize; i++){ + bool thisListPresent = bs.get(1); + if (thisListPresent){ + if (i < 6){ + skipScalingList(bs, 16); + }else{ + skipScalingList(bs, 64); + } + } + } } } - bs.getUExpGolomb(); - unsigned int pic_order_cnt_type = bs.getUExpGolomb(); - if (!pic_order_cnt_type) { - bs.getUExpGolomb(); - } else if (pic_order_cnt_type == 1) { + result.log2_max_frame_num = bs.getUExpGolomb() + 4; + result.cnt_type = bs.getUExpGolomb(); + if (!result.cnt_type) { + result.log2_max_order_cnt = bs.getUExpGolomb() + 4; + } else if (result.cnt_type == 1) { DEBUG_MSG(DLVL_DEVEL, "This part of the implementation is incomplete(2), to be continued. If this message is shown, contact developers immediately."); } - bs.getUExpGolomb(); - bs.skip(1); - //Stop skipping data and start doing usefull stuff + result.max_ref_frames = bs.getUExpGolomb();//max_num_ref_frames + result.gaps = (bs.get(1) == 1);//gaps in frame num allowed + //Stop skipping data and start doing useful stuff widthInMbs = bs.getUExpGolomb() + 1; heightInMapUnits = bs.getUExpGolomb() + 1; - mbsOnlyFlag = bs.get(1);//Gets used in height calculation - if (!mbsOnlyFlag) { + result.mbs_only = (bs.get(1) == 1);//Gets used in height calculation + if (!result.mbs_only) { bs.skip(1); } bs.skip(1); @@ -191,7 +214,7 @@ namespace h264 { } result.width = (widthInMbs * 16) - (cropHorizontal * 2); - result.height = ((mbsOnlyFlag ? 1 : 2) * heightInMapUnits * 16) - (cropVertical * 2); + result.height = ((result.mbs_only ? 1 : 2) * heightInMapUnits * 16) - (cropVertical * 2); return result; } diff --git a/lib/h264.h b/lib/h264.h index 48fcfcc9..0afd0540 100644 --- a/lib/h264.h +++ b/lib/h264.h @@ -14,6 +14,13 @@ namespace h264 { double fps; uint8_t profile; uint8_t level; + bool sep_col_plane; + uint8_t cnt_type; + bool gaps;///< Gaps in frame num allowed flag + bool mbs_only;///