This commit is contained in:
DDVTech 2021-09-10 23:44:31 +02:00 committed by Thulinma
parent 5b79f296d6
commit fccf66fba2
280 changed files with 56975 additions and 71885 deletions

View file

@ -18,10 +18,10 @@ namespace aac {
memcpy(data, _data, len); memcpy(data, _data, len);
} }
bool adts::sameHeader(const adts &rhs) const{ bool adts::sameHeader(const adts &rhs) const{
if (!rhs || !*this){return false;} if (!rhs || !*this){return false;}
return (getAACProfile() == rhs.getAACProfile() && getFrequencyIndex() == rhs.getFrequencyIndex() && getChannelConfig() == rhs.getChannelConfig()); return (getAACProfile() == rhs.getAACProfile() && getFrequencyIndex() == rhs.getFrequencyIndex() &&
getChannelConfig() == rhs.getChannelConfig());
} }
adts::adts(const adts &rhs){ adts::adts(const adts &rhs){
@ -31,9 +31,7 @@ namespace aac {
} }
adts &adts::operator=(const adts &rhs){ adts &adts::operator=(const adts &rhs){
if (data){ if (data){free(data);}
free(data);
}
len = rhs.len; len = rhs.len;
data = (char *)malloc(len); data = (char *)malloc(len);
memcpy(data, rhs.data, len); memcpy(data, rhs.data, len);
@ -41,30 +39,21 @@ namespace aac {
} }
adts::~adts(){ adts::~adts(){
if (data){ if (data){free(data);}
free(data);
}
} }
unsigned long adts::getAACProfile() const{ unsigned long adts::getAACProfile() const{
if (!data || !len){ if (!data || !len){return 0;}
return 0;
}
return ((data[2] >> 6) & 0x03) + 1; return ((data[2] >> 6) & 0x03) + 1;
} }
unsigned long adts::getFrequencyIndex() const{ unsigned long adts::getFrequencyIndex() const{
if (!data || !len){ if (!data || !len){return 0;}
return 0;
}
return ((data[2] >> 2) & 0x0F); return ((data[2] >> 2) & 0x0F);
} }
unsigned long adts::getFrequency() const{ unsigned long adts::getFrequency() const{
if (!data || len < 3){ if (!data || len < 3){return 0;}
return 0;
}
switch (getFrequencyIndex()){ switch (getFrequencyIndex()){
case 0: return 96000; break; case 0: return 96000; break;
case 1: return 88200; break; case 1: return 88200; break;
@ -84,30 +73,22 @@ namespace aac {
} }
unsigned long adts::getChannelConfig() const{ unsigned long adts::getChannelConfig() const{
if (!data || !len){ if (!data || !len){return 0;}
return 0;
}
return ((data[2] & 0x01) << 2) | ((data[3] >> 6) & 0x03); return ((data[2] & 0x01) << 2) | ((data[3] >> 6) & 0x03);
} }
unsigned long adts::getChannelCount() const{ unsigned long adts::getChannelCount() const{
if (!data || !len){ if (!data || !len){return 0;}
return 0;
}
return (getChannelConfig() == 7 ? 8 : getChannelConfig()); return (getChannelConfig() == 7 ? 8 : getChannelConfig());
} }
unsigned long adts::getHeaderSize() const{ unsigned long adts::getHeaderSize() const{
if (!data || !len){ if (!data || !len){return 0;}
return 0;
}
return (data[1] & 0x01 ? 7 : 9); return (data[1] & 0x01 ? 7 : 9);
} }
unsigned long adts::getCompleteSize() const{ unsigned long adts::getCompleteSize() const{
if (!data || len < 6){ if (!data || len < 6){return 0;}
return 0;
}
return (((data[3] & 0x03) << 11) | (data[4] << 3) | ((data[5] >> 5) & 0x07)); return (((data[3] & 0x03) << 11) | (data[4] << 3) | ((data[5] >> 5) & 0x07));
} }
@ -123,16 +104,12 @@ namespace aac {
} }
unsigned long adts::getSampleCount() const{ unsigned long adts::getSampleCount() const{
if (!data || len < 7){ if (!data || len < 7){return 0;}
return 0;
}
return ((data[6] & 0x03) + 1) * 1024; // Number of samples in this frame * 1024 return ((data[6] & 0x03) + 1) * 1024; // Number of samples in this frame * 1024
} }
char *adts::getPayload(){ char *adts::getPayload(){
if (!data || !len){ if (!data || !len){return 0;}
return 0;
}
return data + getHeaderSize(); return data + getHeaderSize();
} }
std::string adts::toPrettyString() const{ std::string adts::toPrettyString() const{
@ -147,12 +124,8 @@ namespace aac {
}else{ }else{
res << " MPEG-4" << std::endl; res << " MPEG-4" << std::endl;
} }
if ((data[1] & 0x6) != 0){ if ((data[1] & 0x6) != 0){res << " Non-zero layer!" << std::endl;}
res << " Non-zero layer!" << std::endl; if ((data[1] & 0x1) == 0x0){res << " CRC present" << std::endl;}
}
if ((data[1] & 0x1) == 0x0){
res << " CRC present" << std::endl;
}
res << " MPEG-4 audio object type: " << getAACProfile() << std::endl; res << " MPEG-4 audio object type: " << getAACProfile() << std::endl;
res << " Frequency: " << getFrequency() << "Hz" << std::endl; res << " Frequency: " << getFrequency() << "Hz" << std::endl;
res << " Channels: " << getChannelCount() << std::endl; res << " Channels: " << getChannelCount() << std::endl;
@ -161,9 +134,10 @@ namespace aac {
return res.str(); return res.str();
} }
adts::operator bool() const{ adts::operator bool() const{
return hasSync() && len && len >= getHeaderSize() && getFrequency() && getChannelCount() && getSampleCount(); return hasSync() && len && len >= getHeaderSize() && getFrequency() && getChannelCount() &&
getSampleCount();
} }
bool adts::hasSync() const{ bool adts::hasSync() const{
return len && (((int)data[0] << 4) | ((data[1] >> 4) & 0x0F)) == 0xfff; return len && (((int)data[0] << 4) | ((data[1] >> 4) & 0x0F)) == 0xfff;
} }
} }// namespace aac

View file

@ -1,6 +1,6 @@
#include "bitstream.h"
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include "bitstream.h"
namespace aac{ namespace aac{
class adts{ class adts{
@ -24,6 +24,7 @@ namespace aac {
char *getPayload(); char *getPayload();
std::string toPrettyString() const; std::string toPrettyString() const;
operator bool() const; operator bool() const;
private: private:
char *data; char *data;
unsigned long len; unsigned long len;
@ -91,6 +92,4 @@ namespace aac {
} }
}; };
}// namespace aac
}

View file

@ -328,8 +328,7 @@ std::string AMF::Object::Pack(){
/// \param i Current parsing position in the raw data. /// \param i Current parsing position in the raw data.
/// \param name Indice name for any new object created. /// \param name Indice name for any new object created.
/// \returns A single AMF::Object, parsed from the raw data. /// \returns A single AMF::Object, parsed from the raw data.
AMF::Object AMF::parseOne(const unsigned char *&data, unsigned int &len, unsigned int &i, AMF::Object AMF::parseOne(const unsigned char *&data, unsigned int &len, unsigned int &i, std::string name){
std::string name){
std::string tmpstr; std::string tmpstr;
unsigned int tmpi = 0; unsigned int tmpi = 0;
unsigned char tmpdbl[8]; unsigned char tmpdbl[8];
@ -375,16 +374,14 @@ AMF::Object AMF::parseOne(const unsigned char *&data, unsigned int &len, unsigne
return AMF::Object(name, (double)tmpi, AMF::AMF0_REFERENCE); return AMF::Object(name, (double)tmpi, AMF::AMF0_REFERENCE);
break; break;
case AMF::AMF0_XMLDOC: case AMF::AMF0_XMLDOC:
tmpi = data[i + 1] * 256 * 256 * 256 + data[i + 2] * 256 * 256 + data[i + 3] * 256 + tmpi = data[i + 1] * 256 * 256 * 256 + data[i + 2] * 256 * 256 + data[i + 3] * 256 + data[i + 4]; // set tmpi to UTF-8-long length
data[i + 4]; // set tmpi to UTF-8-long length
tmpstr.clear(); // clean tmpstr, just to be sure tmpstr.clear(); // clean tmpstr, just to be sure
tmpstr.append((const char *)data + i + 5, (size_t)tmpi); // add the string data tmpstr.append((const char *)data + i + 5, (size_t)tmpi); // add the string data
i += tmpi + 5; // skip length+size+1 forwards i += tmpi + 5; // skip length+size+1 forwards
return AMF::Object(name, tmpstr, AMF::AMF0_XMLDOC); return AMF::Object(name, tmpstr, AMF::AMF0_XMLDOC);
break; break;
case AMF::AMF0_LONGSTRING: case AMF::AMF0_LONGSTRING:
tmpi = data[i + 1] * 256 * 256 * 256 + data[i + 2] * 256 * 256 + data[i + 3] * 256 + tmpi = data[i + 1] * 256 * 256 * 256 + data[i + 2] * 256 * 256 + data[i + 3] * 256 + data[i + 4]; // set tmpi to UTF-8-long length
data[i + 4]; // set tmpi to UTF-8-long length
tmpstr.clear(); // clean tmpstr, just to be sure tmpstr.clear(); // clean tmpstr, just to be sure
tmpstr.append((const char *)data + i + 5, (size_t)tmpi); // add the string data tmpstr.append((const char *)data + i + 5, (size_t)tmpi); // add the string data
i += tmpi + 5; // skip length+size+1 forwards i += tmpi + 5; // skip length+size+1 forwards
@ -411,8 +408,7 @@ AMF::Object AMF::parseOne(const unsigned char *&data, unsigned int &len, unsigne
tmpstr.clear(); // clean tmpstr, just to be sure tmpstr.clear(); // clean tmpstr, just to be sure
tmpstr.append((const char *)data + i + 2, (size_t)tmpi); // add the string data tmpstr.append((const char *)data + i + 2, (size_t)tmpi); // add the string data
i += tmpi + 2; // skip length+size forwards i += tmpi + 2; // skip length+size forwards
ret.addContent(AMF::parseOne( ret.addContent(AMF::parseOne(data, len, i,
data, len, i,
tmpstr)); // add content, recursively parsed, updating i, setting indice to tmpstr tmpstr)); // add content, recursively parsed, updating i, setting indice to tmpstr
} }
i += 3; // skip 0x000009 i += 3; // skip 0x000009
@ -429,8 +425,7 @@ AMF::Object AMF::parseOne(const unsigned char *&data, unsigned int &len, unsigne
tmpstr.clear(); // clean tmpstr, just to be sure tmpstr.clear(); // clean tmpstr, just to be sure
tmpstr.append((const char *)data + i + 2, (size_t)tmpi); // add the string data tmpstr.append((const char *)data + i + 2, (size_t)tmpi); // add the string data
i += tmpi + 2; // skip length+size forwards i += tmpi + 2; // skip length+size forwards
ret.addContent(AMF::parseOne( ret.addContent(AMF::parseOne(data, len, i,
data, len, i,
tmpstr)); // add content, recursively parsed, updating i, setting indice to tmpstr tmpstr)); // add content, recursively parsed, updating i, setting indice to tmpstr
} }
i += 3; // skip 0x000009 i += 3; // skip 0x000009
@ -445,8 +440,7 @@ AMF::Object AMF::parseOne(const unsigned char *&data, unsigned int &len, unsigne
tmpstr.clear(); // clean tmpstr, just to be sure tmpstr.clear(); // clean tmpstr, just to be sure
tmpstr.append((const char *)data + i + 2, (size_t)tmpi); // add the string data tmpstr.append((const char *)data + i + 2, (size_t)tmpi); // add the string data
i += tmpi + 2; // skip length+size forwards i += tmpi + 2; // skip length+size forwards
ret.addContent(AMF::parseOne( ret.addContent(AMF::parseOne(data, len, i,
data, len, i,
tmpstr)); // add content, recursively parsed, updating i, setting indice to tmpstr tmpstr)); // add content, recursively parsed, updating i, setting indice to tmpstr
} }
i += 3; // skip 0x000009 i += 3; // skip 0x000009
@ -454,12 +448,10 @@ AMF::Object AMF::parseOne(const unsigned char *&data, unsigned int &len, unsigne
}break; }break;
case AMF::AMF0_STRICT_ARRAY:{ case AMF::AMF0_STRICT_ARRAY:{
AMF::Object ret(name, AMF::AMF0_STRICT_ARRAY); AMF::Object ret(name, AMF::AMF0_STRICT_ARRAY);
tmpi = data[i + 1] * 256 * 256 * 256 + data[i + 2] * 256 * 256 + data[i + 3] * 256 + tmpi = data[i + 1] * 256 * 256 * 256 + data[i + 2] * 256 * 256 + data[i + 3] * 256 + data[i + 4]; // set tmpi to array length
data[i + 4]; // set tmpi to array length
i += 5; // skip size+1 forwards i += 5; // skip size+1 forwards
while (tmpi > 0){// while not done parsing array while (tmpi > 0){// while not done parsing array
ret.addContent( ret.addContent(AMF::parseOne(data, len, i, "arrVal")); // add content, recursively parsed, updating i
AMF::parseOne(data, len, i, "arrVal")); // add content, recursively parsed, updating i
--tmpi; --tmpi;
} }
return ret; return ret;
@ -712,8 +704,7 @@ std::string AMF::Object3::Pack(){
/// \param i Current parsing position in the raw data. /// \param i Current parsing position in the raw data.
/// \param name Indice name for any new object created. /// \param name Indice name for any new object created.
/// \returns A single AMF::Object3, parsed from the raw data. /// \returns A single AMF::Object3, parsed from the raw data.
AMF::Object3 AMF::parseOne3(const unsigned char *&data, unsigned int &len, unsigned int &i, AMF::Object3 AMF::parseOne3(const unsigned char *&data, unsigned int &len, unsigned int &i, std::string name){
std::string name){
std::string tmpstr; std::string tmpstr;
unsigned int tmpi = 0; unsigned int tmpi = 0;
unsigned int arrsize = 0; unsigned int arrsize = 0;
@ -974,13 +965,11 @@ AMF::Object3 AMF::parseOne3(const unsigned char *&data, unsigned int &len, unsig
if (tmpi > 0){ if (tmpi > 0){
tmpstr.clear(); // clean tmpstr, just to be sure tmpstr.clear(); // clean tmpstr, just to be sure
tmpstr.append((const char *)data + i, (size_t)tmpi); // add the string data tmpstr.append((const char *)data + i, (size_t)tmpi); // add the string data
ret.addContent( ret.addContent(AMF::parseOne3(data, len, i, tmpstr)); // add content, recursively parsed, updating i
AMF::parseOne3(data, len, i, tmpstr)); // add content, recursively parsed, updating i
} }
}while (tmpi > 0); }while (tmpi > 0);
while (arrsize > 0){// while not done parsing array while (arrsize > 0){// while not done parsing array
ret.addContent( ret.addContent(AMF::parseOne3(data, len, i, "arrVal")); // add content, recursively parsed, updating i
AMF::parseOne3(data, len, i, "arrVal")); // add content, recursively parsed, updating i
--arrsize; --arrsize;
} }
return ret; return ret;
@ -1046,8 +1035,7 @@ AMF::Object3 AMF::parseOne3(const unsigned char *&data, unsigned int &len, unsig
if (tmpi > 0){ if (tmpi > 0){
tmpstr.clear(); // clean tmpstr, just to be sure tmpstr.clear(); // clean tmpstr, just to be sure
tmpstr.append((const char *)data + i, (size_t)tmpi); // add the string data tmpstr.append((const char *)data + i, (size_t)tmpi); // add the string data
ret.addContent( ret.addContent(AMF::parseOne3(data, len, i, tmpstr)); // add content, recursively parsed, updating i
AMF::parseOne3(data, len, i, tmpstr)); // add content, recursively parsed, updating i
} }
}while (tmpi > 0); // keep reading dynamic values until empty string }while (tmpi > 0); // keep reading dynamic values until empty string
}// dynamic types }// dynamic types
@ -1081,4 +1069,3 @@ AMF::Object3 AMF::parse3(const unsigned char *data, unsigned int len){
AMF::Object3 AMF::parse3(std::string data){ AMF::Object3 AMF::parse3(std::string data){
return AMF::parse3((const unsigned char *)data.c_str(), data.size()); return AMF::parse3((const unsigned char *)data.c_str(), data.size());
}// parse }// parse

View file

@ -130,8 +130,6 @@ namespace AMF{
/// Parses a std::string to a valid AMF::Object3. /// Parses a std::string to a valid AMF::Object3.
Object3 parse3(std::string data); Object3 parse3(std::string data);
/// Parses a single AMF3 type - used recursively by the AMF::parse3() functions. /// Parses a single AMF3 type - used recursively by the AMF::parse3() functions.
Object3 parseOne3(const unsigned char *&data, unsigned int &len, unsigned int &i, Object3 parseOne3(const unsigned char *&data, unsigned int &len, unsigned int &i, std::string name);
std::string name);
}// namespace AMF }// namespace AMF

View file

@ -1,16 +1,14 @@
#include "auth.h" #include "auth.h"
#include <string.h>
#include <stdio.h>
#include <inttypes.h> #include <inttypes.h>
#include <sstream>
#include <iomanip> #include <iomanip>
#include <sstream>
#include <stdio.h>
#include <string.h>
namespace Secure{ namespace Secure{
/// Calculates a MD5 digest as per rfc1321, returning it as a hexadecimal alphanumeric string. /// Calculates a MD5 digest as per rfc1321, returning it as a hexadecimal alphanumeric string.
std::string md5(std::string input) { std::string md5(std::string input){return md5(input.data(), input.size());}
return md5(input.data(), input.size());
}
/// Calculates a MD5 digest as per rfc1321, returning it as a hexadecimal alphanumeric string. /// Calculates a MD5 digest as per rfc1321, returning it as a hexadecimal alphanumeric string.
std::string md5(const char *input, const unsigned int in_len){ std::string md5(const char *input, const unsigned int in_len){
@ -24,9 +22,7 @@ namespace Secure {
} }
/// Calculates a SHA256 digest as per NSAs SHA-2, returning it as a hexadecimal alphanumeric string. /// Calculates a SHA256 digest as per NSAs SHA-2, returning it as a hexadecimal alphanumeric string.
std::string sha256(std::string input) { std::string sha256(std::string input){return sha256(input.data(), input.size());}
return sha256(input.data(), input.size());
}
/// Calculates a SHA256 digest as per NSAs SHA-2, returning it as a hexadecimal alphanumeric string. /// Calculates a SHA256 digest as per NSAs SHA-2, returning it as a hexadecimal alphanumeric string.
std::string sha256(const char *input, const unsigned int in_len){ std::string sha256(const char *input, const unsigned int in_len){
@ -46,10 +42,24 @@ namespace Secure {
// Inspired by the pseudocode as available on Wikipedia on March 2nd, 2015. // Inspired by the pseudocode as available on Wikipedia on March 2nd, 2015.
uint32_t M[16]; uint32_t M[16];
for (unsigned int i = 0; i < 16; ++i){ for (unsigned int i = 0; i < 16; ++i){
M[i] = data[i << 2] | (data[(i<<2)+1] << 8) | (data[(i<<2)+2] << 16) | (data[(i<<2)+3] << 24); M[i] = data[i << 2] | (data[(i << 2) + 1] << 8) | (data[(i << 2) + 2] << 16) |
(data[(i << 2) + 3] << 24);
} }
static unsigned char shift[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21}; static unsigned char shift[] ={7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
static uint32_t K[] = { 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391}; 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};
static uint32_t K[] ={0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a,
0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340,
0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8,
0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa,
0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,
0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391};
uint32_t A = hash[0]; uint32_t A = hash[0];
uint32_t B = hash[1]; uint32_t B = hash[1];
uint32_t C = hash[2]; uint32_t C = hash[2];
@ -151,7 +161,8 @@ namespace Secure {
// Inspired by the pseudocode as available on Wikipedia on March 3rd, 2015. // Inspired by the pseudocode as available on Wikipedia on March 3rd, 2015.
uint32_t w[64]; uint32_t w[64];
for (unsigned int i = 0; i < 16; ++i){ for (unsigned int i = 0; i < 16; ++i){
w[i] = (uint32_t)data[(i<<2)+3] | ((uint32_t)data[(i<<2)+2] << 8) | ((uint32_t)data[(i<<2)+1] << 16) | ((uint32_t)data[(i<<2)+0] << 24); w[i] = (uint32_t)data[(i << 2) + 3] | ((uint32_t)data[(i << 2) + 2] << 8) |
((uint32_t)data[(i << 2) + 1] << 16) | ((uint32_t)data[(i << 2) + 0] << 24);
} }
for (unsigned int i = 16; i < 64; ++i){ for (unsigned int i = 16; i < 64; ++i){
@ -160,7 +171,17 @@ namespace Secure {
w[i] = w[i - 16] + s0 + w[i - 7] + s1; w[i] = w[i - 16] + s0 + w[i - 7] + s1;
} }
static uint32_t k[] = {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; static uint32_t k[] ={0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
uint32_t a = hash[0]; uint32_t a = hash[0];
uint32_t b = hash[1]; uint32_t b = hash[1];
uint32_t c = hash[2]; uint32_t c = hash[2];
@ -195,7 +216,8 @@ namespace Secure {
/// Assumes output is big enough to contain 16 bytes of data. /// Assumes output is big enough to contain 16 bytes of data.
void sha256bin(const char *input, const unsigned int in_len, char *output){ void sha256bin(const char *input, const unsigned int in_len, char *output){
// Initialize the hash, according to MD5 spec. // Initialize the hash, according to MD5 spec.
uint32_t hash[] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; uint32_t hash[] ={0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
// Add as many whole blocks of 64 bytes as possible from the input, until < 64 are left. // Add as many whole blocks of 64 bytes as possible from the input, until < 64 are left.
unsigned int offset = 0; unsigned int offset = 0;
while (offset + 64 <= in_len){ while (offset + 64 <= in_len){
@ -263,13 +285,12 @@ namespace Secure {
output[28] = (hash[7] >> 24) & 0xff; output[28] = (hash[7] >> 24) & 0xff;
} }
/// Performs HMAC on msg with given key. /// Performs HMAC on msg with given key.
/// Uses given hasher function, requires hashSize to be set accordingly. /// Uses given hasher function, requires hashSize to be set accordingly.
/// Output is returned as hexadecimal alphanumeric string. /// Output is returned as hexadecimal alphanumeric string.
/// The hasher function must be the "bin" version of the hasher to have a compatible function signature. /// The hasher function must be the "bin" version of the hasher to have a compatible function signature.
std::string hmac(std::string msg, std::string key, unsigned int hashSize, void hasher(const char *, const unsigned int, char*), unsigned int blockSize){ std::string hmac(std::string msg, std::string key, unsigned int hashSize,
void hasher(const char *, const unsigned int, char *), unsigned int blockSize){
return hmac(msg.data(), msg.size(), key.data(), key.size(), hashSize, hasher, blockSize); return hmac(msg.data(), msg.size(), key.data(), key.size(), hashSize, hasher, blockSize);
} }
@ -277,7 +298,9 @@ namespace Secure {
/// Uses given hasher function, requires hashSize to be set accordingly. /// Uses given hasher function, requires hashSize to be set accordingly.
/// Output is returned as hexadecimal alphanumeric string. /// Output is returned as hexadecimal alphanumeric string.
/// The hasher function must be the "bin" version of the hasher to have a compatible function signature. /// The hasher function must be the "bin" version of the hasher to have a compatible function signature.
std::string hmac(const char * msg, const unsigned int msg_len, const char * key, const unsigned int key_len, unsigned int hashSize, void hasher(const char *, const unsigned int, char*), unsigned int blockSize){ std::string hmac(const char *msg, const unsigned int msg_len, const char *key,
const unsigned int key_len, unsigned int hashSize,
void hasher(const char *, const unsigned int, char *), unsigned int blockSize){
char output[hashSize]; char output[hashSize];
hmacbin(msg, msg_len, key, key_len, hashSize, hasher, blockSize, output); hmacbin(msg, msg_len, key, key_len, hashSize, hasher, blockSize, output);
std::stringstream outStr; std::stringstream outStr;
@ -291,7 +314,9 @@ namespace Secure {
/// Uses given hasher function, requires hashSize to be set accordingly. /// Uses given hasher function, requires hashSize to be set accordingly.
/// Output is written in binary form to output, and assumes hashSize bytes are available to be written to. /// Output is written in binary form to output, and assumes hashSize bytes are available to be written to.
/// The hasher function must be the "bin" version of the hasher to have a compatible function signature. /// The hasher function must be the "bin" version of the hasher to have a compatible function signature.
void hmacbin(const char * msg, const unsigned int msg_len, const char * key, const unsigned int key_len, unsigned int hashSize, void hasher(const char*, const unsigned int, char*), unsigned int blockSize, char * output){ void hmacbin(const char *msg, const unsigned int msg_len, const char *key, const unsigned int key_len,
unsigned int hashSize, void hasher(const char *, const unsigned int, char *),
unsigned int blockSize, char *output){
char key_data[blockSize]; // holds key as used in HMAC algorithm char key_data[blockSize]; // holds key as used in HMAC algorithm
if (key_len > blockSize){ if (key_len > blockSize){
// If the key given is too big, hash it. // If the key given is too big, hash it.
@ -329,9 +354,9 @@ namespace Secure {
/// Convenience function that sets output to the HMAC-SHA256 of msg and key in binary format. /// Convenience function that sets output to the HMAC-SHA256 of msg and key in binary format.
/// Assumes at least 32 bytes are available for writing in output. /// Assumes at least 32 bytes are available for writing in output.
void hmac_sha256bin(const char * msg, const unsigned int msg_len, const char * key, const unsigned int key_len, char * output){ void hmac_sha256bin(const char *msg, const unsigned int msg_len, const char *key,
const unsigned int key_len, char *output){
return hmacbin(msg, msg_len, key, key_len, 32, sha256bin, 64, output); return hmacbin(msg, msg_len, key, key_len, 32, sha256bin, 64, output);
} }
} }// namespace Secure

View file

@ -13,13 +13,18 @@ namespace Secure {
void sha256bin(const char *input, const unsigned int in_len, char *output); void sha256bin(const char *input, const unsigned int in_len, char *output);
// Generic HMAC functions // Generic HMAC functions
std::string hmac(std::string msg, std::string key, unsigned int hashSize, void hasher(const char *, const unsigned int, char*), unsigned int blockSize); std::string hmac(std::string msg, std::string key, unsigned int hashSize,
std::string hmac(const char * msg, const unsigned int msg_len, const char * key, const unsigned int key_len, unsigned int hashSize, void hasher(const char *, const unsigned int, char*), unsigned int blockSize); void hasher(const char *, const unsigned int, char *), unsigned int blockSize);
void hmacbin(const char * msg, const unsigned int msg_len, const char * key, const unsigned int key_len, unsigned int hashSize, void hasher(const char*, const unsigned int, char*), unsigned int blockSize, char * output); std::string hmac(const char *msg, const unsigned int msg_len, const char *key,
const unsigned int key_len, unsigned int hashSize,
void hasher(const char *, const unsigned int, char *), unsigned int blockSize);
void hmacbin(const char *msg, const unsigned int msg_len, const char *key, const unsigned int key_len,
unsigned int hashSize, void hasher(const char *, const unsigned int, char *),
unsigned int blockSize, char *output);
// Specific HMAC functions // Specific HMAC functions
std::string hmac_sha256(std::string msg, std::string key); std::string hmac_sha256(std::string msg, std::string key);
std::string hmac_sha256(const char *msg, const unsigned int msg_len, const char *key, const unsigned int key_len); std::string hmac_sha256(const char *msg, const unsigned int msg_len, const char *key, const unsigned int key_len);
void hmac_sha256bin(const char * msg, const unsigned int msg_len, const char * key, const unsigned int key_len, char * output); void hmac_sha256bin(const char *msg, const unsigned int msg_len, const char *key,
const unsigned int key_len, char *output);
}
}// namespace Secure

View file

@ -35,8 +35,7 @@ unsigned long long Bit::getMSB(char *pointer, unsigned int offsetBits, unsigned
/// This function assumes Most Significant Bits first. /// This function assumes Most Significant Bits first.
/// WARNING: UNFINISHED. DO NOT USE. /// WARNING: UNFINISHED. DO NOT USE.
/// \todo Finish writing this - untested atm. /// \todo Finish writing this - untested atm.
void Bit::setMSB(char *pointer, unsigned int offsetBits, unsigned int dataBits, void Bit::setMSB(char *pointer, unsigned int offsetBits, unsigned int dataBits, unsigned long long value){
unsigned long long value){
// Set the pointer to the last byte we need to be setting // Set the pointer to the last byte we need to be setting
pointer += (offsetBits + dataBits) >> 3; pointer += (offsetBits + dataBits) >> 3;
// The offset is now guaranteed less than a whole byte. // The offset is now guaranteed less than a whole byte.
@ -73,4 +72,3 @@ bool Util::stringToBool(std::string &str){
return (strncmp(tmp.c_str(), "1", 1) == 0 || strncmp(tmp.c_str(), "yes", 3) == 0 || return (strncmp(tmp.c_str(), "1", 1) == 0 || strncmp(tmp.c_str(), "yes", 3) == 0 ||
strncmp(tmp.c_str(), "true", 4) == 0 || strncmp(tmp.c_str(), "cont", 4) == 0); strncmp(tmp.c_str(), "true", 4) == 0 || strncmp(tmp.c_str(), "cont", 4) == 0);
} }

View file

@ -11,8 +11,7 @@ namespace Bit{
unsigned long long getMSB(char *pointer, unsigned int offsetBits, unsigned int dataBits); unsigned long long getMSB(char *pointer, unsigned int offsetBits, unsigned int dataBits);
unsigned long long getByName(char *pointer); unsigned long long getByName(char *pointer);
// bitfield setters // bitfield setters
void setMSB(char *pointer, unsigned int offsetBits, unsigned int dataBits, void setMSB(char *pointer, unsigned int offsetBits, unsigned int dataBits, unsigned long long value);
unsigned long long value);
void setByName(char *pointer); void setByName(char *pointer);
// Host to binary/binary to host functions - similar to kernel ntoh/hton functions. // Host to binary/binary to host functions - similar to kernel ntoh/hton functions.
@ -143,8 +142,7 @@ namespace Bit{
/// Retrieves a long in network order from the pointer p. /// Retrieves a long in network order from the pointer p.
inline unsigned long btohl_le(const char *p){ inline unsigned long btohl_le(const char *p){
return ((unsigned long)p[3] << 24) | ((unsigned long)p[2] << 16) | ((unsigned long)p[1] << 8) | return ((unsigned long)p[3] << 24) | ((unsigned long)p[2] << 16) | ((unsigned long)p[1] << 8) | p[0];
p[0];
} }
/// Stores a long value of val in little endian to the pointer p. /// Stores a long value of val in little endian to the pointer p.
@ -171,8 +169,7 @@ namespace Bit{
inline unsigned long long btohll_le(const char *p){ inline unsigned long long btohll_le(const char *p){
return ((unsigned long long)p[7] << 56) | ((unsigned long long)p[6] << 48) | return ((unsigned long long)p[7] << 56) | ((unsigned long long)p[6] << 48) |
((unsigned long long)p[5] << 40) | ((unsigned long long)p[4] << 32) | ((unsigned long long)p[5] << 40) | ((unsigned long long)p[4] << 32) |
((unsigned long)p[3] << 24) | ((unsigned long)p[2] << 16) | ((unsigned long)p[1] << 8) | ((unsigned long)p[3] << 24) | ((unsigned long)p[2] << 16) | ((unsigned long)p[1] << 8) | p[0];
p[0];
} }
/// Stores a long value of val in little endian to the pointer p. /// Stores a long value of val in little endian to the pointer p.
@ -188,4 +185,3 @@ namespace Bit{
} }
}// namespace Bit }// namespace Bit

View file

@ -50,8 +50,7 @@ namespace Utils{
// return 0; // return 0;
} }
if (count > size()){ if (count > size()){
DEBUG_MSG(DLVL_ERROR, "Not enough bits left in stream. Left: %d requested: %d", (int)size(), DEBUG_MSG(DLVL_ERROR, "Not enough bits left in stream. Left: %d requested: %d", (int)size(), (int)count);
(int)count);
return 0; return 0;
} }
long long unsigned int retval = 0; long long unsigned int retval = 0;
@ -131,16 +130,14 @@ namespace Utils{
long long int bitstream::getExpGolomb(){ long long int bitstream::getExpGolomb(){
long long unsigned int temp = golombGetter(); long long unsigned int temp = golombGetter();
return (temp >> 1) * return (temp >> 1) * (1 - ((temp & 1) << 1)); // Is actually return (temp / 2) * (1 - (temp & 1) * 2);
(1 - ((temp & 1) << 1)); // Is actually return (temp / 2) * (1 - (temp & 1) * 2);
} }
long long unsigned int bitstream::getUExpGolomb(){return golombGetter() - 1;} long long unsigned int bitstream::getUExpGolomb(){return golombGetter() - 1;}
long long int bitstream::peekExpGolomb(){ long long int bitstream::peekExpGolomb(){
long long unsigned int temp = golombPeeker(); long long unsigned int temp = golombPeeker();
return (temp >> 1) * return (temp >> 1) * (1 - ((temp & 1) << 1)); // Is actually return (temp / 2) * (1 - (temp & 1) * 2);
(1 - ((temp & 1) << 1)); // Is actually return (temp / 2) * (1 - (temp & 1) * 2);
} }
long long unsigned int bitstream::peekUExpGolomb(){return golombPeeker() - 1;} long long unsigned int bitstream::peekUExpGolomb(){return golombPeeker() - 1;}
@ -285,4 +282,3 @@ namespace Utils{
data.erase(0, pos); data.erase(0, pos);
} }
}// namespace Utils }// namespace Utils

View file

@ -93,4 +93,3 @@ namespace Utils{
void fixData(); void fixData();
}; };
}// namespace Utils }// namespace Utils

View file

@ -1,17 +1,13 @@
#include "certificate.h" #include "certificate.h"
#include "defines.h" #include "defines.h"
Certificate::Certificate() Certificate::Certificate() : rsa_ctx(NULL){
:rsa_ctx(NULL)
{
memset((void *)&cert, 0x00, sizeof(cert)); memset((void *)&cert, 0x00, sizeof(cert));
memset((void *)&key, 0x00, sizeof(key)); memset((void *)&key, 0x00, sizeof(key));
} }
int Certificate::init(const std::string &countryName, int Certificate::init(const std::string &countryName, const std::string &organization,
const std::string &organization, const std::string &commonName){
const std::string& commonName)
{
mbedtls_ctr_drbg_context rand_ctx ={}; mbedtls_ctr_drbg_context rand_ctx ={};
mbedtls_entropy_context entropy_ctx ={}; mbedtls_entropy_context entropy_ctx ={};
@ -51,7 +47,8 @@ int Certificate::init(const std::string &countryName,
// initialize random number generator // initialize random number generator
mbedtls_ctr_drbg_init(&rand_ctx); mbedtls_ctr_drbg_init(&rand_ctx);
mbedtls_entropy_init(&entropy_ctx); mbedtls_entropy_init(&entropy_ctx);
r = mbedtls_ctr_drbg_seed(&rand_ctx, mbedtls_entropy_func, &entropy_ctx, (const unsigned char*)personalisation, strlen(personalisation)); r = mbedtls_ctr_drbg_seed(&rand_ctx, mbedtls_entropy_func, &entropy_ctx,
(const unsigned char *)personalisation, strlen(personalisation));
if (0 != r){ if (0 != r){
FAIL_MSG("Failed to initialize and seed the entropy context."); FAIL_MSG("Failed to initialize and seed the entropy context.");
r = -10; r = -10;
@ -86,9 +83,7 @@ int Certificate::init(const std::string &countryName,
time_from = (time_from < 1000000000) ? 1000000000 : time_from; time_from = (time_from < 1000000000) ? 1000000000 : time_from;
time_to = time_from + (60 * 60 * 24 * 365); // valid for a year time_to = time_from + (60 * 60 * 24 * 365); // valid for a year
if (time_to < time_from) { if (time_to < time_from){time_to = INT_MAX;}
time_to = INT_MAX;
}
r = strftime(time_from_str, sizeof(time_from_str), "%Y%m%d%H%M%S", gmtime(&time_from)); r = strftime(time_from_str, sizeof(time_from_str), "%Y%m%d%H%M%S", gmtime(&time_from));
if (0 == r){ if (0 == r){
@ -111,9 +106,7 @@ int Certificate::init(const std::string &countryName,
goto error; goto error;
} }
for (i = 0; i < 8; ++i) { for (i = 0; i < 8; ++i){sprintf(serial_hex + (i * 2), "%02x", serial_ptr[i]);}
sprintf(serial_hex + (i * 2), "%02x", serial_ptr[i]);
}
// start creating the certificate // start creating the certificate
mbedtls_x509write_crt_init(&write_cert); mbedtls_x509write_crt_init(&write_cert);
@ -204,9 +197,7 @@ int Certificate::init(const std::string &countryName,
mbedtls_x509write_crt_free(&write_cert); mbedtls_x509write_crt_free(&write_cert);
mbedtls_mpi_free(&serial_mpi); mbedtls_mpi_free(&serial_mpi);
if (r < 0) { if (r < 0){shutdown();}
shutdown();
}
return r; return r;
} }
@ -235,6 +226,3 @@ std::string Certificate::getFingerprintSha256() {
std::string result = std::string((char *)fingerprint_hex + 1, (32 * 3) - 1); std::string result = std::string((char *)fingerprint_hex + 1, (32 * 3) - 1);
return result; return result;
} }

View file

@ -10,15 +10,15 @@
*/ */
#include <string>
#include <mbedtls/config.h> #include <mbedtls/config.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>
#include <mbedtls/error.h>
#include <mbedtls/md.h>
#include <mbedtls/sha256.h>
#include <mbedtls/x509_crt.h> #include <mbedtls/x509_crt.h>
#include <mbedtls/x509_csr.h> #include <mbedtls/x509_csr.h>
#include <mbedtls/entropy.h> #include <string>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/md.h>
#include <mbedtls/error.h>
#include <mbedtls/sha256.h>
class Certificate{ class Certificate{
public: public:

View file

@ -3,69 +3,42 @@
namespace checksum{ namespace checksum{
inline unsigned int crc32c(unsigned int crc, const char *data, size_t len){ inline unsigned int crc32c(unsigned int crc, const char *data, size_t len){
static const unsigned int table[256] ={ static const unsigned int table[256] ={
0x00000000U, 0x04C11DB7U, 0x09823B6EU, 0x0D4326D9U, 0x00000000U, 0x04C11DB7U, 0x09823B6EU, 0x0D4326D9U, 0x130476DCU, 0x17C56B6BU, 0x1A864DB2U,
0x130476DCU, 0x17C56B6BU, 0x1A864DB2U, 0x1E475005U, 0x1E475005U, 0x2608EDB8U, 0x22C9F00FU, 0x2F8AD6D6U, 0x2B4BCB61U, 0x350C9B64U, 0x31CD86D3U,
0x2608EDB8U, 0x22C9F00FU, 0x2F8AD6D6U, 0x2B4BCB61U, 0x3C8EA00AU, 0x384FBDBDU, 0x4C11DB70U, 0x48D0C6C7U, 0x4593E01EU, 0x4152FDA9U, 0x5F15ADACU,
0x350C9B64U, 0x31CD86D3U, 0x3C8EA00AU, 0x384FBDBDU, 0x5BD4B01BU, 0x569796C2U, 0x52568B75U, 0x6A1936C8U, 0x6ED82B7FU, 0x639B0DA6U, 0x675A1011U,
0x4C11DB70U, 0x48D0C6C7U, 0x4593E01EU, 0x4152FDA9U, 0x791D4014U, 0x7DDC5DA3U, 0x709F7B7AU, 0x745E66CDU, 0x9823B6E0U, 0x9CE2AB57U, 0x91A18D8EU,
0x5F15ADACU, 0x5BD4B01BU, 0x569796C2U, 0x52568B75U, 0x95609039U, 0x8B27C03CU, 0x8FE6DD8BU, 0x82A5FB52U, 0x8664E6E5U, 0xBE2B5B58U, 0xBAEA46EFU,
0x6A1936C8U, 0x6ED82B7FU, 0x639B0DA6U, 0x675A1011U, 0xB7A96036U, 0xB3687D81U, 0xAD2F2D84U, 0xA9EE3033U, 0xA4AD16EAU, 0xA06C0B5DU, 0xD4326D90U,
0x791D4014U, 0x7DDC5DA3U, 0x709F7B7AU, 0x745E66CDU, 0xD0F37027U, 0xDDB056FEU, 0xD9714B49U, 0xC7361B4CU, 0xC3F706FBU, 0xCEB42022U, 0xCA753D95U,
0x9823B6E0U, 0x9CE2AB57U, 0x91A18D8EU, 0x95609039U, 0xF23A8028U, 0xF6FB9D9FU, 0xFBB8BB46U, 0xFF79A6F1U, 0xE13EF6F4U, 0xE5FFEB43U, 0xE8BCCD9AU,
0x8B27C03CU, 0x8FE6DD8BU, 0x82A5FB52U, 0x8664E6E5U, 0xEC7DD02DU, 0x34867077U, 0x30476DC0U, 0x3D044B19U, 0x39C556AEU, 0x278206ABU, 0x23431B1CU,
0xBE2B5B58U, 0xBAEA46EFU, 0xB7A96036U, 0xB3687D81U, 0x2E003DC5U, 0x2AC12072U, 0x128E9DCFU, 0x164F8078U, 0x1B0CA6A1U, 0x1FCDBB16U, 0x018AEB13U,
0xAD2F2D84U, 0xA9EE3033U, 0xA4AD16EAU, 0xA06C0B5DU, 0x054BF6A4U, 0x0808D07DU, 0x0CC9CDCAU, 0x7897AB07U, 0x7C56B6B0U, 0x71159069U, 0x75D48DDEU,
0xD4326D90U, 0xD0F37027U, 0xDDB056FEU, 0xD9714B49U, 0x6B93DDDBU, 0x6F52C06CU, 0x6211E6B5U, 0x66D0FB02U, 0x5E9F46BFU, 0x5A5E5B08U, 0x571D7DD1U,
0xC7361B4CU, 0xC3F706FBU, 0xCEB42022U, 0xCA753D95U, 0x53DC6066U, 0x4D9B3063U, 0x495A2DD4U, 0x44190B0DU, 0x40D816BAU, 0xACA5C697U, 0xA864DB20U,
0xF23A8028U, 0xF6FB9D9FU, 0xFBB8BB46U, 0xFF79A6F1U, 0xA527FDF9U, 0xA1E6E04EU, 0xBFA1B04BU, 0xBB60ADFCU, 0xB6238B25U, 0xB2E29692U, 0x8AAD2B2FU,
0xE13EF6F4U, 0xE5FFEB43U, 0xE8BCCD9AU, 0xEC7DD02DU, 0x8E6C3698U, 0x832F1041U, 0x87EE0DF6U, 0x99A95DF3U, 0x9D684044U, 0x902B669DU, 0x94EA7B2AU,
0x34867077U, 0x30476DC0U, 0x3D044B19U, 0x39C556AEU, 0xE0B41DE7U, 0xE4750050U, 0xE9362689U, 0xEDF73B3EU, 0xF3B06B3BU, 0xF771768CU, 0xFA325055U,
0x278206ABU, 0x23431B1CU, 0x2E003DC5U, 0x2AC12072U, 0xFEF34DE2U, 0xC6BCF05FU, 0xC27DEDE8U, 0xCF3ECB31U, 0xCBFFD686U, 0xD5B88683U, 0xD1799B34U,
0x128E9DCFU, 0x164F8078U, 0x1B0CA6A1U, 0x1FCDBB16U, 0xDC3ABDEDU, 0xD8FBA05AU, 0x690CE0EEU, 0x6DCDFD59U, 0x608EDB80U, 0x644FC637U, 0x7A089632U,
0x018AEB13U, 0x054BF6A4U, 0x0808D07DU, 0x0CC9CDCAU, 0x7EC98B85U, 0x738AAD5CU, 0x774BB0EBU, 0x4F040D56U, 0x4BC510E1U, 0x46863638U, 0x42472B8FU,
0x7897AB07U, 0x7C56B6B0U, 0x71159069U, 0x75D48DDEU, 0x5C007B8AU, 0x58C1663DU, 0x558240E4U, 0x51435D53U, 0x251D3B9EU, 0x21DC2629U, 0x2C9F00F0U,
0x6B93DDDBU, 0x6F52C06CU, 0x6211E6B5U, 0x66D0FB02U, 0x285E1D47U, 0x36194D42U, 0x32D850F5U, 0x3F9B762CU, 0x3B5A6B9BU, 0x0315D626U, 0x07D4CB91U,
0x5E9F46BFU, 0x5A5E5B08U, 0x571D7DD1U, 0x53DC6066U, 0x0A97ED48U, 0x0E56F0FFU, 0x1011A0FAU, 0x14D0BD4DU, 0x19939B94U, 0x1D528623U, 0xF12F560EU,
0x4D9B3063U, 0x495A2DD4U, 0x44190B0DU, 0x40D816BAU, 0xF5EE4BB9U, 0xF8AD6D60U, 0xFC6C70D7U, 0xE22B20D2U, 0xE6EA3D65U, 0xEBA91BBCU, 0xEF68060BU,
0xACA5C697U, 0xA864DB20U, 0xA527FDF9U, 0xA1E6E04EU, 0xD727BBB6U, 0xD3E6A601U, 0xDEA580D8U, 0xDA649D6FU, 0xC423CD6AU, 0xC0E2D0DDU, 0xCDA1F604U,
0xBFA1B04BU, 0xBB60ADFCU, 0xB6238B25U, 0xB2E29692U, 0xC960EBB3U, 0xBD3E8D7EU, 0xB9FF90C9U, 0xB4BCB610U, 0xB07DABA7U, 0xAE3AFBA2U, 0xAAFBE615U,
0x8AAD2B2FU, 0x8E6C3698U, 0x832F1041U, 0x87EE0DF6U, 0xA7B8C0CCU, 0xA379DD7BU, 0x9B3660C6U, 0x9FF77D71U, 0x92B45BA8U, 0x9675461FU, 0x8832161AU,
0x99A95DF3U, 0x9D684044U, 0x902B669DU, 0x94EA7B2AU, 0x8CF30BADU, 0x81B02D74U, 0x857130C3U, 0x5D8A9099U, 0x594B8D2EU, 0x5408ABF7U, 0x50C9B640U,
0xE0B41DE7U, 0xE4750050U, 0xE9362689U, 0xEDF73B3EU, 0x4E8EE645U, 0x4A4FFBF2U, 0x470CDD2BU, 0x43CDC09CU, 0x7B827D21U, 0x7F436096U, 0x7200464FU,
0xF3B06B3BU, 0xF771768CU, 0xFA325055U, 0xFEF34DE2U, 0x76C15BF8U, 0x68860BFDU, 0x6C47164AU, 0x61043093U, 0x65C52D24U, 0x119B4BE9U, 0x155A565EU,
0xC6BCF05FU, 0xC27DEDE8U, 0xCF3ECB31U, 0xCBFFD686U, 0x18197087U, 0x1CD86D30U, 0x029F3D35U, 0x065E2082U, 0x0B1D065BU, 0x0FDC1BECU, 0x3793A651U,
0xD5B88683U, 0xD1799B34U, 0xDC3ABDEDU, 0xD8FBA05AU, 0x3352BBE6U, 0x3E119D3FU, 0x3AD08088U, 0x2497D08DU, 0x2056CD3AU, 0x2D15EBE3U, 0x29D4F654U,
0x690CE0EEU, 0x6DCDFD59U, 0x608EDB80U, 0x644FC637U, 0xC5A92679U, 0xC1683BCEU, 0xCC2B1D17U, 0xC8EA00A0U, 0xD6AD50A5U, 0xD26C4D12U, 0xDF2F6BCBU,
0x7A089632U, 0x7EC98B85U, 0x738AAD5CU, 0x774BB0EBU, 0xDBEE767CU, 0xE3A1CBC1U, 0xE760D676U, 0xEA23F0AFU, 0xEEE2ED18U, 0xF0A5BD1DU, 0xF464A0AAU,
0x4F040D56U, 0x4BC510E1U, 0x46863638U, 0x42472B8FU, 0xF9278673U, 0xFDE69BC4U, 0x89B8FD09U, 0x8D79E0BEU, 0x803AC667U, 0x84FBDBD0U, 0x9ABC8BD5U,
0x5C007B8AU, 0x58C1663DU, 0x558240E4U, 0x51435D53U, 0x9E7D9662U, 0x933EB0BBU, 0x97FFAD0CU, 0xAFB010B1U, 0xAB710D06U, 0xA6322BDFU, 0xA2F33668U,
0x251D3B9EU, 0x21DC2629U, 0x2C9F00F0U, 0x285E1D47U,
0x36194D42U, 0x32D850F5U, 0x3F9B762CU, 0x3B5A6B9BU,
0x0315D626U, 0x07D4CB91U, 0x0A97ED48U, 0x0E56F0FFU,
0x1011A0FAU, 0x14D0BD4DU, 0x19939B94U, 0x1D528623U,
0xF12F560EU, 0xF5EE4BB9U, 0xF8AD6D60U, 0xFC6C70D7U,
0xE22B20D2U, 0xE6EA3D65U, 0xEBA91BBCU, 0xEF68060BU,
0xD727BBB6U, 0xD3E6A601U, 0xDEA580D8U, 0xDA649D6FU,
0xC423CD6AU, 0xC0E2D0DDU, 0xCDA1F604U, 0xC960EBB3U,
0xBD3E8D7EU, 0xB9FF90C9U, 0xB4BCB610U, 0xB07DABA7U,
0xAE3AFBA2U, 0xAAFBE615U, 0xA7B8C0CCU, 0xA379DD7BU,
0x9B3660C6U, 0x9FF77D71U, 0x92B45BA8U, 0x9675461FU,
0x8832161AU, 0x8CF30BADU, 0x81B02D74U, 0x857130C3U,
0x5D8A9099U, 0x594B8D2EU, 0x5408ABF7U, 0x50C9B640U,
0x4E8EE645U, 0x4A4FFBF2U, 0x470CDD2BU, 0x43CDC09CU,
0x7B827D21U, 0x7F436096U, 0x7200464FU, 0x76C15BF8U,
0x68860BFDU, 0x6C47164AU, 0x61043093U, 0x65C52D24U,
0x119B4BE9U, 0x155A565EU, 0x18197087U, 0x1CD86D30U,
0x029F3D35U, 0x065E2082U, 0x0B1D065BU, 0x0FDC1BECU,
0x3793A651U, 0x3352BBE6U, 0x3E119D3FU, 0x3AD08088U,
0x2497D08DU, 0x2056CD3AU, 0x2D15EBE3U, 0x29D4F654U,
0xC5A92679U, 0xC1683BCEU, 0xCC2B1D17U, 0xC8EA00A0U,
0xD6AD50A5U, 0xD26C4D12U, 0xDF2F6BCBU, 0xDBEE767CU,
0xE3A1CBC1U, 0xE760D676U, 0xEA23F0AFU, 0xEEE2ED18U,
0xF0A5BD1DU, 0xF464A0AAU, 0xF9278673U, 0xFDE69BC4U,
0x89B8FD09U, 0x8D79E0BEU, 0x803AC667U, 0x84FBDBD0U,
0x9ABC8BD5U, 0x9E7D9662U, 0x933EB0BBU, 0x97FFAD0CU,
0xAFB010B1U, 0xAB710D06U, 0xA6322BDFU, 0xA2F33668U,
0xBCB4666DU, 0xB8757BDAU, 0xB5365D03U, 0xB1F740B4U, 0xBCB4666DU, 0xB8757BDAU, 0xB5365D03U, 0xB1F740B4U,
}; };
@ -79,71 +52,43 @@ namespace checksum {
inline unsigned int crc32LE(unsigned int crc, const char *data, size_t len){ inline unsigned int crc32LE(unsigned int crc, const char *data, size_t len){
static const unsigned int table[256] ={ static const unsigned int table[256] ={
0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 0x706af48fU, 0xe963a535U,
0x076dc419U, 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU,
0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U, 0xe7b82d07U, 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, 0x1adad47dU,
0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU,
0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, 0x14015c4fU, 0x63066cd9U, 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, 0x35b5a8faU, 0x42b2986cU,
0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU,
0x14015c4fU, 0x63066cd9U, 0xfa0f3d63U, 0x8d080df5U, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, 0xb8bda50fU,
0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0xa2677172U, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU,
0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, 0xb6662d3dU, 0x76dc4190U, 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU,
0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U, 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU,
0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U, 0x8bbeb8eaU,
0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, 0xb8bda50fU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU,
0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, 0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U,
0x76dc4190U, 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x5005713cU, 0x270241aaU, 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U,
0x71b18589U, 0x06b6b51fU, 0x9fbfe4a5U, 0xe8b8d433U, 0xce61e49fU, 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 0x2eb40d81U,
0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU, 0xead54739U,
0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U,
0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U,
0x65b0d9c6U, 0x12b7e950U, 0x8bbeb8eaU, 0xfcb9887cU, 0x10da7a5aU, 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, 0xd6d6a3e8U,
0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU,
0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, 0xcc0c7795U, 0xbb0b4703U,
0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U,
0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U, 0xb5d0cf31U, 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x026d930aU,
0x5005713cU, 0x270241aaU, 0xbe0b1010U, 0xc90c2086U, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U, 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU,
0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU, 0x0cb61b38U, 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x18b74777U, 0x88085ae6U,
0x59b33d17U, 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U,
0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU, 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, 0x4969474dU,
0xead54739U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U,
0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, 0x47b2cf7fU, 0x30b5ffe9U, 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x2a6f2b94U,
0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU};
0xf762575dU, 0x806567cbU, 0x196c3671U, 0x6e6b06e7U,
0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 0x67dd4accU,
0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U,
0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU,
0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U,
0xdf60efc3U, 0xa867df55U, 0x316e8eefU, 0x4669be79U,
0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU,
0xc5ba3bbeU, 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U,
0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, 0x5bdeae1dU,
0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x026d930aU,
0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U,
0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U,
0x86d3d2d4U, 0xf1d4e242U, 0x68ddb3f8U, 0x1fda836eU,
0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x18b74777U,
0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U,
0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U,
0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU,
0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, 0x37d83bf0U,
0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U,
0xbad03605U, 0xcdd70693U, 0x54de5729U, 0x23d967bfU,
0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x2a6f2b94U,
0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU
};
while (len > 0){ while (len > 0){
crc = table[*data ^ ((crc >> 24) & 0xff)] ^ (crc << 8); crc = table[*data ^ ((crc >> 24) & 0xff)] ^ (crc << 8);
@ -155,77 +100,47 @@ namespace checksum {
inline unsigned int crc32(unsigned int crc, const char *data, size_t len){ inline unsigned int crc32(unsigned int crc, const char *data, size_t len){
static const unsigned int table[256] ={ static const unsigned int table[256] ={
0x00000000U, 0xB71DC104U, 0x6E3B8209U, 0xD926430DU, 0x00000000U, 0xB71DC104U, 0x6E3B8209U, 0xD926430DU, 0xDC760413U, 0x6B6BC517U, 0xB24D861AU,
0xDC760413U, 0x6B6BC517U, 0xB24D861AU, 0x0550471EU, 0x0550471EU, 0xB8ED0826U, 0x0FF0C922U, 0xD6D68A2FU, 0x61CB4B2BU, 0x649B0C35U, 0xD386CD31U,
0xB8ED0826U, 0x0FF0C922U, 0xD6D68A2FU, 0x61CB4B2BU, 0x0AA08E3CU, 0xBDBD4F38U, 0x70DB114CU, 0xC7C6D048U, 0x1EE09345U, 0xA9FD5241U, 0xACAD155FU,
0x649B0C35U, 0xD386CD31U, 0x0AA08E3CU, 0xBDBD4F38U, 0x1BB0D45BU, 0xC2969756U, 0x758B5652U, 0xC836196AU, 0x7F2BD86EU, 0xA60D9B63U, 0x11105A67U,
0x70DB114CU, 0xC7C6D048U, 0x1EE09345U, 0xA9FD5241U, 0x14401D79U, 0xA35DDC7DU, 0x7A7B9F70U, 0xCD665E74U, 0xE0B62398U, 0x57ABE29CU, 0x8E8DA191U,
0xACAD155FU, 0x1BB0D45BU, 0xC2969756U, 0x758B5652U, 0x39906095U, 0x3CC0278BU, 0x8BDDE68FU, 0x52FBA582U, 0xE5E66486U, 0x585B2BBEU, 0xEF46EABAU,
0xC836196AU, 0x7F2BD86EU, 0xA60D9B63U, 0x11105A67U, 0x3660A9B7U, 0x817D68B3U, 0x842D2FADU, 0x3330EEA9U, 0xEA16ADA4U, 0x5D0B6CA0U, 0x906D32D4U,
0x14401D79U, 0xA35DDC7DU, 0x7A7B9F70U, 0xCD665E74U, 0x2770F3D0U, 0xFE56B0DDU, 0x494B71D9U, 0x4C1B36C7U, 0xFB06F7C3U, 0x2220B4CEU, 0x953D75CAU,
0xE0B62398U, 0x57ABE29CU, 0x8E8DA191U, 0x39906095U, 0x28803AF2U, 0x9F9DFBF6U, 0x46BBB8FBU, 0xF1A679FFU, 0xF4F63EE1U, 0x43EBFFE5U, 0x9ACDBCE8U,
0x3CC0278BU, 0x8BDDE68FU, 0x52FBA582U, 0xE5E66486U, 0x2DD07DECU, 0x77708634U, 0xC06D4730U, 0x194B043DU, 0xAE56C539U, 0xAB068227U, 0x1C1B4323U,
0x585B2BBEU, 0xEF46EABAU, 0x3660A9B7U, 0x817D68B3U, 0xC53D002EU, 0x7220C12AU, 0xCF9D8E12U, 0x78804F16U, 0xA1A60C1BU, 0x16BBCD1FU, 0x13EB8A01U,
0x842D2FADU, 0x3330EEA9U, 0xEA16ADA4U, 0x5D0B6CA0U, 0xA4F64B05U, 0x7DD00808U, 0xCACDC90CU, 0x07AB9778U, 0xB0B6567CU, 0x69901571U, 0xDE8DD475U,
0x906D32D4U, 0x2770F3D0U, 0xFE56B0DDU, 0x494B71D9U, 0xDBDD936BU, 0x6CC0526FU, 0xB5E61162U, 0x02FBD066U, 0xBF469F5EU, 0x085B5E5AU, 0xD17D1D57U,
0x4C1B36C7U, 0xFB06F7C3U, 0x2220B4CEU, 0x953D75CAU, 0x6660DC53U, 0x63309B4DU, 0xD42D5A49U, 0x0D0B1944U, 0xBA16D840U, 0x97C6A5ACU, 0x20DB64A8U,
0x28803AF2U, 0x9F9DFBF6U, 0x46BBB8FBU, 0xF1A679FFU, 0xF9FD27A5U, 0x4EE0E6A1U, 0x4BB0A1BFU, 0xFCAD60BBU, 0x258B23B6U, 0x9296E2B2U, 0x2F2BAD8AU,
0xF4F63EE1U, 0x43EBFFE5U, 0x9ACDBCE8U, 0x2DD07DECU, 0x98366C8EU, 0x41102F83U, 0xF60DEE87U, 0xF35DA999U, 0x4440689DU, 0x9D662B90U, 0x2A7BEA94U,
0x77708634U, 0xC06D4730U, 0x194B043DU, 0xAE56C539U, 0xE71DB4E0U, 0x500075E4U, 0x892636E9U, 0x3E3BF7EDU, 0x3B6BB0F3U, 0x8C7671F7U, 0x555032FAU,
0xAB068227U, 0x1C1B4323U, 0xC53D002EU, 0x7220C12AU, 0xE24DF3FEU, 0x5FF0BCC6U, 0xE8ED7DC2U, 0x31CB3ECFU, 0x86D6FFCBU, 0x8386B8D5U, 0x349B79D1U,
0xCF9D8E12U, 0x78804F16U, 0xA1A60C1BU, 0x16BBCD1FU, 0xEDBD3ADCU, 0x5AA0FBD8U, 0xEEE00C69U, 0x59FDCD6DU, 0x80DB8E60U, 0x37C64F64U, 0x3296087AU,
0x13EB8A01U, 0xA4F64B05U, 0x7DD00808U, 0xCACDC90CU, 0x858BC97EU, 0x5CAD8A73U, 0xEBB04B77U, 0x560D044FU, 0xE110C54BU, 0x38368646U, 0x8F2B4742U,
0x07AB9778U, 0xB0B6567CU, 0x69901571U, 0xDE8DD475U, 0x8A7B005CU, 0x3D66C158U, 0xE4408255U, 0x535D4351U, 0x9E3B1D25U, 0x2926DC21U, 0xF0009F2CU,
0xDBDD936BU, 0x6CC0526FU, 0xB5E61162U, 0x02FBD066U, 0x471D5E28U, 0x424D1936U, 0xF550D832U, 0x2C769B3FU, 0x9B6B5A3BU, 0x26D61503U, 0x91CBD407U,
0xBF469F5EU, 0x085B5E5AU, 0xD17D1D57U, 0x6660DC53U, 0x48ED970AU, 0xFFF0560EU, 0xFAA01110U, 0x4DBDD014U, 0x949B9319U, 0x2386521DU, 0x0E562FF1U,
0x63309B4DU, 0xD42D5A49U, 0x0D0B1944U, 0xBA16D840U, 0xB94BEEF5U, 0x606DADF8U, 0xD7706CFCU, 0xD2202BE2U, 0x653DEAE6U, 0xBC1BA9EBU, 0x0B0668EFU,
0x97C6A5ACU, 0x20DB64A8U, 0xF9FD27A5U, 0x4EE0E6A1U, 0xB6BB27D7U, 0x01A6E6D3U, 0xD880A5DEU, 0x6F9D64DAU, 0x6ACD23C4U, 0xDDD0E2C0U, 0x04F6A1CDU,
0x4BB0A1BFU, 0xFCAD60BBU, 0x258B23B6U, 0x9296E2B2U, 0xB3EB60C9U, 0x7E8D3EBDU, 0xC990FFB9U, 0x10B6BCB4U, 0xA7AB7DB0U, 0xA2FB3AAEU, 0x15E6FBAAU,
0x2F2BAD8AU, 0x98366C8EU, 0x41102F83U, 0xF60DEE87U, 0xCCC0B8A7U, 0x7BDD79A3U, 0xC660369BU, 0x717DF79FU, 0xA85BB492U, 0x1F467596U, 0x1A163288U,
0xF35DA999U, 0x4440689DU, 0x9D662B90U, 0x2A7BEA94U, 0xAD0BF38CU, 0x742DB081U, 0xC3307185U, 0x99908A5DU, 0x2E8D4B59U, 0xF7AB0854U, 0x40B6C950U,
0xE71DB4E0U, 0x500075E4U, 0x892636E9U, 0x3E3BF7EDU, 0x45E68E4EU, 0xF2FB4F4AU, 0x2BDD0C47U, 0x9CC0CD43U, 0x217D827BU, 0x9660437FU, 0x4F460072U,
0x3B6BB0F3U, 0x8C7671F7U, 0x555032FAU, 0xE24DF3FEU, 0xF85BC176U, 0xFD0B8668U, 0x4A16476CU, 0x93300461U, 0x242DC565U, 0xE94B9B11U, 0x5E565A15U,
0x5FF0BCC6U, 0xE8ED7DC2U, 0x31CB3ECFU, 0x86D6FFCBU, 0x87701918U, 0x306DD81CU, 0x353D9F02U, 0x82205E06U, 0x5B061D0BU, 0xEC1BDC0FU, 0x51A69337U,
0x8386B8D5U, 0x349B79D1U, 0xEDBD3ADCU, 0x5AA0FBD8U, 0xE6BB5233U, 0x3F9D113EU, 0x8880D03AU, 0x8DD09724U, 0x3ACD5620U, 0xE3EB152DU, 0x54F6D429U,
0xEEE00C69U, 0x59FDCD6DU, 0x80DB8E60U, 0x37C64F64U, 0x7926A9C5U, 0xCE3B68C1U, 0x171D2BCCU, 0xA000EAC8U, 0xA550ADD6U, 0x124D6CD2U, 0xCB6B2FDFU,
0x3296087AU, 0x858BC97EU, 0x5CAD8A73U, 0xEBB04B77U, 0x7C76EEDBU, 0xC1CBA1E3U, 0x76D660E7U, 0xAFF023EAU, 0x18EDE2EEU, 0x1DBDA5F0U, 0xAAA064F4U,
0x560D044FU, 0xE110C54BU, 0x38368646U, 0x8F2B4742U, 0x738627F9U, 0xC49BE6FDU, 0x09FDB889U, 0xBEE0798DU, 0x67C63A80U, 0xD0DBFB84U, 0xD58BBC9AU,
0x8A7B005CU, 0x3D66C158U, 0xE4408255U, 0x535D4351U, 0x62967D9EU, 0xBBB03E93U, 0x0CADFF97U, 0xB110B0AFU, 0x060D71ABU, 0xDF2B32A6U, 0x6836F3A2U,
0x9E3B1D25U, 0x2926DC21U, 0xF0009F2CU, 0x471D5E28U, 0x6D66B4BCU, 0xDA7B75B8U, 0x035D36B5U, 0xB440F7B1U};
0x424D1936U, 0xF550D832U, 0x2C769B3FU, 0x9B6B5A3BU,
0x26D61503U, 0x91CBD407U, 0x48ED970AU, 0xFFF0560EU,
0xFAA01110U, 0x4DBDD014U, 0x949B9319U, 0x2386521DU,
0x0E562FF1U, 0xB94BEEF5U, 0x606DADF8U, 0xD7706CFCU,
0xD2202BE2U, 0x653DEAE6U, 0xBC1BA9EBU, 0x0B0668EFU,
0xB6BB27D7U, 0x01A6E6D3U, 0xD880A5DEU, 0x6F9D64DAU,
0x6ACD23C4U, 0xDDD0E2C0U, 0x04F6A1CDU, 0xB3EB60C9U,
0x7E8D3EBDU, 0xC990FFB9U, 0x10B6BCB4U, 0xA7AB7DB0U,
0xA2FB3AAEU, 0x15E6FBAAU, 0xCCC0B8A7U, 0x7BDD79A3U,
0xC660369BU, 0x717DF79FU, 0xA85BB492U, 0x1F467596U,
0x1A163288U, 0xAD0BF38CU, 0x742DB081U, 0xC3307185U,
0x99908A5DU, 0x2E8D4B59U, 0xF7AB0854U, 0x40B6C950U,
0x45E68E4EU, 0xF2FB4F4AU, 0x2BDD0C47U, 0x9CC0CD43U,
0x217D827BU, 0x9660437FU, 0x4F460072U, 0xF85BC176U,
0xFD0B8668U, 0x4A16476CU, 0x93300461U, 0x242DC565U,
0xE94B9B11U, 0x5E565A15U, 0x87701918U, 0x306DD81CU,
0x353D9F02U, 0x82205E06U, 0x5B061D0BU, 0xEC1BDC0FU,
0x51A69337U, 0xE6BB5233U, 0x3F9D113EU, 0x8880D03AU,
0x8DD09724U, 0x3ACD5620U, 0xE3EB152DU, 0x54F6D429U,
0x7926A9C5U, 0xCE3B68C1U, 0x171D2BCCU, 0xA000EAC8U,
0xA550ADD6U, 0x124D6CD2U, 0xCB6B2FDFU, 0x7C76EEDBU,
0xC1CBA1E3U, 0x76D660E7U, 0xAFF023EAU, 0x18EDE2EEU,
0x1DBDA5F0U, 0xAAA064F4U, 0x738627F9U, 0xC49BE6FDU,
0x09FDB889U, 0xBEE0798DU, 0x67C63A80U, 0xD0DBFB84U,
0xD58BBC9AU, 0x62967D9EU, 0xBBB03E93U, 0x0CADFF97U,
0xB110B0AFU, 0x060D71ABU, 0xDF2B32A6U, 0x6836F3A2U,
0x6D66B4BCU, 0xDA7B75B8U, 0x035D36B5U, 0xB440F7B1U
};
const char *tmpData = data; const char *tmpData = data;
const char *end = tmpData + len; const char *end = tmpData + len;
while(tmpData < end){ while (tmpData < end){crc = table[((unsigned char)crc) ^ *tmpData++] ^ (crc >> 8);}
crc = table[((unsigned char) crc) ^ *tmpData++] ^ (crc >> 8);
}
return crc; return crc;
} }
} }// namespace checksum

View file

@ -132,8 +132,7 @@ void Util::Config::printHelp(std::ostream &output){
} }
while (f.size() < longest){f.append(" ");} while (f.size() < longest){f.append(" ");}
if (it->isMember("arg")){ if (it->isMember("arg")){
output << f << "(" << (*it)["arg"].asString() << ") " << (*it)["help"].asString() output << f << "(" << (*it)["arg"].asString() << ") " << (*it)["help"].asString() << std::endl;
<< std::endl;
}else{ }else{
output << f << (*it)["help"].asString() << std::endl; output << f << (*it)["help"].asString() << std::endl;
} }
@ -141,8 +140,7 @@ void Util::Config::printHelp(std::ostream &output){
if (it->isMember("arg_num")){ if (it->isMember("arg_num")){
f = it.key(); f = it.key();
while (f.size() < longest){f.append(" ");} while (f.size() < longest){f.append(" ");}
output << f << "(" << (*it)["arg"].asString() << ") " << (*it)["help"].asString() output << f << "(" << (*it)["arg"].asString() << ") " << (*it)["help"].asString() << std::endl;
<< std::endl;
} }
} }
} }
@ -188,8 +186,8 @@ bool Util::Config::parseArgs(int &argc, char **&argv){
<< std::endl; << std::endl;
#endif #endif
#ifdef WITH_THREADNAMES #ifdef WITH_THREADNAMES
std::cout std::cout << "- Flag: With threadnames. Debuggers will show sensible human-readable thread "
<< "- Flag: With threadnames. Debuggers will show sensible human-readable thread names." "names."
<< std::endl; << std::endl;
#endif #endif
/*LTS-START*/ /*LTS-START*/
@ -210,9 +208,8 @@ bool Util::Config::parseArgs(int &argc, char **&argv){
#endif #endif
#ifdef STATS_DELAY #ifdef STATS_DELAY
if (STATS_DELAY != 15){ if (STATS_DELAY != 15){
std::cout << "- Setting: Stats delay " << STATS_DELAY std::cout << "- Setting: Stats delay " << STATS_DELAY << ". Statistics of viewer counts are delayed by "
<< ". Statistics of viewer counts are delayed by " << STATS_DELAY << STATS_DELAY << " seconds as opposed to the default of 15 seconds. ";
<< " seconds as opposed to the default of 15 seconds. ";
if (STATS_DELAY > 15){ if (STATS_DELAY > 15){
std::cout << "This makes them more accurate." << std::endl; std::cout << "This makes them more accurate." << std::endl;
}else{ }else{
@ -263,8 +260,7 @@ bool Util::Config::hasOption(const std::string &optname){
/// If the option does not exist, this exits the application with a return code of 37. /// If the option does not exist, this exits the application with a return code of 37.
JSON::Value &Util::Config::getOption(std::string optname, bool asArray){ JSON::Value &Util::Config::getOption(std::string optname, bool asArray){
if (!vals.isMember(optname)){ if (!vals.isMember(optname)){
std::cout << "Fatal error: a non-existent option '" << optname << "' was accessed." std::cout << "Fatal error: a non-existent option '" << optname << "' was accessed." << std::endl;
<< std::endl;
exit(37); exit(37);
} }
if (!vals[optname].isMember("value") || !vals[optname]["value"].isArray()){ if (!vals[optname].isMember("value") || !vals[optname]["value"].isArray()){
@ -313,8 +309,7 @@ static void callThreadCallback(void *cDataArg){
INSANE_MSG("Thread for %p ended", cDataArg); INSANE_MSG("Thread for %p ended", cDataArg);
} }
int Util::Config::threadServer(Socket::Server &server_socket, int Util::Config::threadServer(Socket::Server &server_socket, int (*callback)(Socket::Connection &)){
int (*callback)(Socket::Connection &)){
Util::Procs::socketList.insert(server_socket.getSocket()); Util::Procs::socketList.insert(server_socket.getSocket());
while (is_active && server_socket.connected()){ while (is_active && server_socket.connected()){
Socket::Connection S = server_socket.accept(); Socket::Connection S = server_socket.accept();
@ -354,9 +349,7 @@ int Util::Config::forkServer(Socket::Server &server_socket, int (*callback)(Sock
} }
} }
Util::Procs::socketList.erase(server_socket.getSocket()); Util::Procs::socketList.erase(server_socket.getSocket());
if (!is_restarting){ if (!is_restarting){server_socket.close();}
server_socket.close();
}
return 0; return 0;
} }
@ -463,8 +456,7 @@ void Util::Config::signal_handler(int signum, siginfo_t *sigInfo, void *ignore){
case SI_TIMER: case SI_TIMER:
case SI_ASYNCIO: case SI_ASYNCIO:
case SI_MESGQ: case SI_MESGQ:
INFO_MSG("Received signal %s (%d) from process %d", strsignal(signum), signum, INFO_MSG("Received signal %s (%d) from process %d", strsignal(signum), signum, sigInfo->si_pid);
sigInfo->si_pid);
break; break;
default: INFO_MSG("Received signal %s (%d)", strsignal(signum), signum); break; default: INFO_MSG("Received signal %s (%d)", strsignal(signum), signum); break;
} }
@ -653,4 +645,3 @@ void Util::setUser(std::string username){
} }
} }
} }

View file

@ -64,4 +64,3 @@ namespace Util{
void setUser(std::string user); void setUser(std::string user);
}// namespace Util }// namespace Util

View file

@ -15,18 +15,20 @@
#define DLVL_INSANE 9 // Everything is reported in insane detail. #define DLVL_INSANE 9 // Everything is reported in insane detail.
#define DLVL_DONTEVEN 10 // All messages enabled, even pointless ones. #define DLVL_DONTEVEN 10 // All messages enabled, even pointless ones.
#define PRETTY_PRINT_TIME "%ud%uh%um%us" #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_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_PRINT_MSTIME "%ud%.2uh%.2um%.2us.%.3u"
#define PRETTY_ARG_MSTIME(t) PRETTY_ARG_TIME(t / 1000), (int)(t % 1000) #define PRETTY_ARG_MSTIME(t) PRETTY_ARG_TIME(t / 1000), (int)(t % 1000)
#if DEBUG > -1 #if DEBUG > -1
#define __STDC_FORMAT_MACROS 1 #define __STDC_FORMAT_MACROS 1
#include <stdio.h> #include "config.h"
#include <unistd.h>
#include <inttypes.h> #include <inttypes.h>
#include <stdint.h> #include <stdint.h>
#include "config.h" #include <stdio.h>
static const char * DBG_LVL_LIST[] = {"NONE", "FAIL", "ERROR", "WARN", "INFO", "MEDIUM", "HIGH", "VERYHIGH", "EXTREME", "INSANE", "DONTEVEN"}; #include <unistd.h>
static const char *DBG_LVL_LIST[] ={"NONE", "FAIL", "ERROR", "WARN", "INFO", "MEDIUM",
"HIGH", "VERYHIGH", "EXTREME", "INSANE", "DONTEVEN"};
#if !defined(PRIu64) #if !defined(PRIu64)
#define PRIu64 "llu" #define PRIu64 "llu"
@ -40,15 +42,31 @@ static const char * DBG_LVL_LIST[] = {"NONE", "FAIL", "ERROR", "WARN", "INFO", "
#include <errno.h> #include <errno.h>
#if DEBUG >= DLVL_DEVEL #if DEBUG >= DLVL_DEVEL
#define DEBUG_MSG(lvl, msg, ...) if (Util::Config::printDebugLevel >= lvl){fprintf(stderr, "%s|%s|%d|%s:%d|%s|" msg "\n", DBG_LVL_LIST[lvl], program_invocation_short_name, getpid(), __FILE__, __LINE__, Util::Config::streamName.c_str(), ##__VA_ARGS__);} #define DEBUG_MSG(lvl, msg, ...) \
if (Util::Config::printDebugLevel >= lvl){\
fprintf(stderr, "%s|%s|%d|%s:%d|%s|" msg "\n", DBG_LVL_LIST[lvl], program_invocation_short_name, \
getpid(), __FILE__, __LINE__, Util::Config::streamName.c_str(), ##__VA_ARGS__); \
}
#else #else
#define DEBUG_MSG(lvl, msg, ...) if (Util::Config::printDebugLevel >= lvl){fprintf(stderr, "%s|%s|%d||%s|" msg "\n", DBG_LVL_LIST[lvl], program_invocation_short_name, getpid(), Util::Config::streamName.c_str(), ##__VA_ARGS__);} #define DEBUG_MSG(lvl, msg, ...) \
if (Util::Config::printDebugLevel >= lvl){\
fprintf(stderr, "%s|%s|%d||%s|" msg "\n", DBG_LVL_LIST[lvl], program_invocation_short_name, \
getpid(), Util::Config::streamName.c_str(), ##__VA_ARGS__); \
}
#endif #endif
#else #else
#if DEBUG >= DLVL_DEVEL #if DEBUG >= DLVL_DEVEL
#define DEBUG_MSG(lvl, msg, ...) if (Util::Config::printDebugLevel >= lvl){fprintf(stderr, "%s|MistProcess|%d|%s:%d|%s|" msg "\n", DBG_LVL_LIST[lvl], getpid(), __FILE__, __LINE__, Util::Config::streamName.c_str(), ##__VA_ARGS__);} #define DEBUG_MSG(lvl, msg, ...) \
if (Util::Config::printDebugLevel >= lvl){\
fprintf(stderr, "%s|MistProcess|%d|%s:%d|%s|" msg "\n", DBG_LVL_LIST[lvl], getpid(), __FILE__, \
__LINE__, Util::Config::streamName.c_str(), ##__VA_ARGS__); \
}
#else #else
#define DEBUG_MSG(lvl, msg, ...) if (Util::Config::printDebugLevel >= lvl){fprintf(stderr, "%s|MistProcess|%d||%s|" msg "\n", DBG_LVL_LIST[lvl], getpid(), Util::Config::streamName.c_str(), ##__VA_ARGS__);} #define DEBUG_MSG(lvl, msg, ...) \
if (Util::Config::printDebugLevel >= lvl){\
fprintf(stderr, "%s|MistProcess|%d||%s|" msg "\n", DBG_LVL_LIST[lvl], getpid(), \
Util::Config::streamName.c_str(), ##__VA_ARGS__); \
}
#endif #endif
#endif #endif
@ -64,9 +82,7 @@ static inline void show_stackframe() {
messages = backtrace_symbols(trace, trace_size); messages = backtrace_symbols(trace, trace_size);
for (i = 1; i < trace_size; ++i){ for (i = 1; i < trace_size; ++i){
size_t p = 0; size_t p = 0;
while(messages[i][p] != '(' && messages[i][p] != ' ' && messages[i][p] != 0){ while (messages[i][p] != '(' && messages[i][p] != ' ' && messages[i][p] != 0){++p;}
++p;
}
DEBUG_MSG(0, "Backtrace[%d]: %s", i, messages[i] + p); DEBUG_MSG(0, "Backtrace[%d]: %s", i, messages[i] + p);
} }
} }
@ -94,12 +110,12 @@ static inline void show_stackframe(){}
#endif #endif
#ifndef SHM_DATASIZE #ifndef SHM_DATASIZE
#define SHM_DATASIZE 20 #define SHM_DATASIZE 20
#endif #endif
#define AUDIO_KEY_INTERVAL 2000 ///< This define controls the keyframe interval for non-video tracks, such as audio and metadata tracks. #define AUDIO_KEY_INTERVAL \
2000 ///< This define controls the keyframe interval for non-video tracks, such as audio and metadata tracks.
#ifndef STATS_DELAY #ifndef STATS_DELAY
#define STATS_DELAY 15 #define STATS_DELAY 15
@ -166,7 +182,6 @@ static inline void show_stackframe(){}
#define SIMUL_TRACKS 20 #define SIMUL_TRACKS 20
#ifndef UDP_API_HOST #ifndef UDP_API_HOST
#define UDP_API_HOST "localhost" #define UDP_API_HOST "localhost"
#endif #endif
@ -180,4 +195,3 @@ static inline void show_stackframe(){}
// The amount of milliseconds a simulated live stream is allowed to be "behind". // The amount of milliseconds a simulated live stream is allowed to be "behind".
// Setting this value to lower than 2 seconds **WILL** cause stuttering in playback due to buffer negotiation. // Setting this value to lower than 2 seconds **WILL** cause stuttering in playback due to buffer negotiation.
#define SIMULATED_LIVE_BUFFER 7000 #define SIMULATED_LIVE_BUFFER 7000

View file

@ -1,5 +1,5 @@
#include "downloader.h"
#include "defines.h" #include "defines.h"
#include "downloader.h"
#include "encode.h" #include "encode.h"
#include "timing.h" #include "timing.h"
@ -136,7 +136,8 @@ namespace HTTP{
} }
/// Sends a request for the given URL, does no waiting. /// Sends a request for the given URL, does no waiting.
void Downloader::doRequest(const HTTP::URL &link, const std::string &method, const void * body, const size_t bodyLen){ void Downloader::doRequest(const HTTP::URL &link, const std::string &method, const void *body,
const size_t bodyLen){
prepareRequest(link, method); prepareRequest(link, method);
H.sendRequest(getSocket(), body, bodyLen, false); H.sendRequest(getSocket(), body, bodyLen, false);
H.Clean(); H.Clean();
@ -147,7 +148,6 @@ namespace HTTP{
doRequest(link, method, body.data(), body.size()); doRequest(link, method, body.data(), body.size());
} }
/// Do a HEAD request to download the HTTP headers only, returns true on success /// Do a HEAD request to download the HTTP headers only, returns true on success
bool Downloader::head(const HTTP::URL &link, uint8_t maxRecursiveDepth){ bool Downloader::head(const HTTP::URL &link, uint8_t maxRecursiveDepth){
if (!canRequest(link)){return false;} if (!canRequest(link)){return false;}
@ -190,9 +190,7 @@ namespace HTTP{
} }
} }
if(H.protocol == "HTTP/1.0"){ if (H.protocol == "HTTP/1.0"){getSocket().close();}
getSocket().close();
}
H.headerOnly = false; H.headerOnly = false;
return true; // Success! return true; // Success!
@ -218,9 +216,11 @@ namespace HTTP{
getSocket().close(); getSocket().close();
}else{ }else{
if (retryCount - loop + 1 > 2){ if (retryCount - loop + 1 > 2){
INFO_MSG("Lost connection while retrieving %s (%zu/%" PRIu32 ")", link.getUrl().c_str(), retryCount - loop + 1, retryCount); INFO_MSG("Lost connection while retrieving %s (%zu/%" PRIu32 ")", link.getUrl().c_str(),
retryCount - loop + 1, retryCount);
}else{ }else{
MEDIUM_MSG("Lost connection while retrieving %s (%zu/%" PRIu32 ")", link.getUrl().c_str(), retryCount - loop + 1, retryCount); MEDIUM_MSG("Lost connection while retrieving %s (%zu/%" PRIu32 ")", link.getUrl().c_str(),
retryCount - loop + 1, retryCount);
} }
H.Clean(); H.Clean();
} }
@ -230,7 +230,8 @@ namespace HTTP{
return false; return false;
} }
bool Downloader::getRangeNonBlocking(const HTTP::URL &link, size_t byteStart, size_t byteEnd, Util::DataCallback &cb){ bool Downloader::getRangeNonBlocking(const HTTP::URL &link, size_t byteStart, size_t byteEnd,
Util::DataCallback &cb){
char tmp[32]; char tmp[32];
if (byteEnd <= 0){// get range from byteStart til eof if (byteEnd <= 0){// get range from byteStart til eof
sprintf(tmp, "bytes=%zu-", byteStart); sprintf(tmp, "bytes=%zu-", byteStart);
@ -277,9 +278,7 @@ namespace HTTP{
return true; return true;
} }
const HTTP::URL & Downloader::lastURL(){ const HTTP::URL &Downloader::lastURL(){return nbLink;}
return nbLink;
}
// continue handling a request, originally set up by the getNonBlocking() function // continue handling a request, originally set up by the getNonBlocking() function
// returns true if the request is complete // returns true if the request is complete
@ -375,7 +374,8 @@ namespace HTTP{
return post(link, payload.data(), payload.size(), sync, maxRecursiveDepth); return post(link, payload.data(), payload.size(), sync, maxRecursiveDepth);
} }
bool Downloader::post(const HTTP::URL &link, const void * payload, const size_t payloadLen, bool sync, uint8_t maxRecursiveDepth){ bool Downloader::post(const HTTP::URL &link, const void *payload, const size_t payloadLen,
bool sync, uint8_t maxRecursiveDepth){
if (!canRequest(link)){return false;} if (!canRequest(link)){return false;}
size_t loop = retryCount; // max 5 attempts size_t loop = retryCount; // max 5 attempts
while (--loop){// loop while we are unsuccessful while (--loop){// loop while we are unsuccessful
@ -499,4 +499,3 @@ namespace HTTP{
} }
}// namespace HTTP }// namespace HTTP

View file

@ -1,6 +1,6 @@
#include "http_parser.h" #include "http_parser.h"
#include "url.h"
#include "socket.h" #include "socket.h"
#include "url.h"
#include "util.h" #include "util.h"
namespace HTTP{ namespace HTTP{
@ -11,7 +11,8 @@ namespace HTTP{
std::string &data(); std::string &data();
const std::string &const_data() const; const std::string &const_data() const;
void prepareRequest(const HTTP::URL &link, const std::string &method = ""); void prepareRequest(const HTTP::URL &link, const std::string &method = "");
void doRequest(const HTTP::URL &link, const std::string &method = "", const void * body = 0, const size_t bodyLen = 0); void doRequest(const HTTP::URL &link, const std::string &method = "", const void *body = 0,
const size_t bodyLen = 0);
void doRequest(const HTTP::URL &link, const std::string &method, const std::string &body); void doRequest(const HTTP::URL &link, const std::string &method, const std::string &body);
bool get(const std::string &link, Util::DataCallback &cb = Util::defaultDataCallback); bool get(const std::string &link, Util::DataCallback &cb = Util::defaultDataCallback);
bool get(const HTTP::URL &link, uint8_t maxRecursiveDepth = 6, Util::DataCallback &cb = Util::defaultDataCallback); bool get(const HTTP::URL &link, uint8_t maxRecursiveDepth = 6, Util::DataCallback &cb = Util::defaultDataCallback);
@ -20,7 +21,8 @@ namespace HTTP{
Util::DataCallback &cb = Util::defaultDataCallback); Util::DataCallback &cb = Util::defaultDataCallback);
bool getRangeNonBlocking(const HTTP::URL &link, size_t byteStart, size_t byteEnd, bool getRangeNonBlocking(const HTTP::URL &link, size_t byteStart, size_t byteEnd,
Util::DataCallback &cb = Util::defaultDataCallback); Util::DataCallback &cb = Util::defaultDataCallback);
bool post(const HTTP::URL &link, const void * payload, const size_t payloadLen, bool sync = true, uint8_t maxRecursiveDepth = 6); bool post(const HTTP::URL &link, const void *payload, const size_t payloadLen, bool sync = true,
uint8_t maxRecursiveDepth = 6);
bool post(const HTTP::URL &link, const std::string &payload, bool sync = true, bool post(const HTTP::URL &link, const std::string &payload, bool sync = true,
uint8_t maxRecursiveDepth = 6); uint8_t maxRecursiveDepth = 6);
@ -65,8 +67,4 @@ namespace HTTP{
uint64_t nbReqTime; uint64_t nbReqTime;
}; };
}// namespace HTTP }// namespace HTTP

View file

@ -1,6 +1,6 @@
#include <algorithm>
#include "defines.h" #include "defines.h"
#include "dtls_srtp_handshake.h" #include "dtls_srtp_handshake.h"
#include <algorithm>
/* Write mbedtls into a log file. */ /* Write mbedtls into a log file. */
#define LOG_TO_FILE 0 #define LOG_TO_FILE 0
@ -12,17 +12,15 @@
static void print_mbedtls_error(int r); static void print_mbedtls_error(int r);
static void print_mbedtls_debug_message(void *ctx, int level, const char *file, int line, const char *str); static void print_mbedtls_debug_message(void *ctx, int level, const char *file, int line, const char *str);
static int on_mbedtls_wants_to_read(void* user, unsigned char* buf, size_t len); /* Called when mbedtls wants to read data from e.g. a socket. */ static int on_mbedtls_wants_to_read(void *user, unsigned char *buf,
static int on_mbedtls_wants_to_write(void* user, const unsigned char* buf, size_t len); /* Called when mbedtls wants to write data to e.g. a socket. */ size_t len); /* Called when mbedtls wants to read data from e.g. a socket. */
static int on_mbedtls_wants_to_write(void *user, const unsigned char *buf,
size_t len); /* Called when mbedtls wants to write data to e.g. a socket. */
static std::string mbedtls_err_to_string(int r); static std::string mbedtls_err_to_string(int r);
/* ----------------------------------------- */ /* ----------------------------------------- */
DTLSSRTPHandshake::DTLSSRTPHandshake() DTLSSRTPHandshake::DTLSSRTPHandshake() : write_callback(NULL), cert(NULL), key(NULL){
:write_callback(NULL)
,cert(NULL)
,key(NULL)
{
memset((void *)&entropy_ctx, 0x00, sizeof(entropy_ctx)); memset((void *)&entropy_ctx, 0x00, sizeof(entropy_ctx));
memset((void *)&rand_ctx, 0x00, sizeof(rand_ctx)); memset((void *)&rand_ctx, 0x00, sizeof(rand_ctx));
memset((void *)&ssl_ctx, 0x00, sizeof(ssl_ctx)); memset((void *)&ssl_ctx, 0x00, sizeof(ssl_ctx));
@ -31,17 +29,12 @@ DTLSSRTPHandshake::DTLSSRTPHandshake()
memset((void *)&timer_ctx, 0x00, sizeof(timer_ctx)); memset((void *)&timer_ctx, 0x00, sizeof(timer_ctx));
} }
int DTLSSRTPHandshake::init(mbedtls_x509_crt* certificate, int DTLSSRTPHandshake::init(mbedtls_x509_crt *certificate, mbedtls_pk_context *privateKey,
mbedtls_pk_context* privateKey, int (*writeCallback)(const uint8_t *data, int *nbytes)){
int(*writeCallback)(const uint8_t* data, int* nbytes)
)
{
int r = 0; int r = 0;
mbedtls_ssl_srtp_profile srtp_profiles[] = { mbedtls_ssl_srtp_profile srtp_profiles[] ={MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_80,
MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_80, MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_32};
MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_32
};
if (!writeCallback){ if (!writeCallback){
FAIL_MSG("No writeCallack function given."); FAIL_MSG("No writeCallack function given.");
@ -72,7 +65,8 @@ int DTLSSRTPHandshake::init(mbedtls_x509_crt* certificate,
mbedtls_ssl_cookie_init(&cookie_ctx); mbedtls_ssl_cookie_init(&cookie_ctx);
/* seed and setup the random number generator */ /* seed and setup the random number generator */
r = mbedtls_ctr_drbg_seed(&rand_ctx, mbedtls_entropy_func, &entropy_ctx, (const unsigned char*)"mist-srtp", 9); r = mbedtls_ctr_drbg_seed(&rand_ctx, mbedtls_entropy_func, &entropy_ctx,
(const unsigned char *)"mist-srtp", 9);
if (0 != r){ if (0 != r){
print_mbedtls_error(r); print_mbedtls_error(r);
r = -20; r = -20;
@ -80,7 +74,8 @@ int DTLSSRTPHandshake::init(mbedtls_x509_crt* certificate,
} }
/* load defaults into our ssl_conf */ /* load defaults into our ssl_conf */
r = mbedtls_ssl_config_defaults(&ssl_conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT); r = mbedtls_ssl_config_defaults(&ssl_conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_DATAGRAM,
MBEDTLS_SSL_PRESET_DEFAULT);
if (0 != r){ if (0 != r){
print_mbedtls_error(r); print_mbedtls_error(r);
r = -30; r = -30;
@ -95,7 +90,8 @@ int DTLSSRTPHandshake::init(mbedtls_x509_crt* certificate,
mbedtls_debug_set_threshold(10); mbedtls_debug_set_threshold(10);
/* enable SRTP */ /* enable SRTP */
r = mbedtls_ssl_conf_dtls_srtp_protection_profiles(&ssl_conf, srtp_profiles, sizeof(srtp_profiles) / sizeof(srtp_profiles[0])); r = mbedtls_ssl_conf_dtls_srtp_protection_profiles(&ssl_conf, srtp_profiles,
sizeof(srtp_profiles) / sizeof(srtp_profiles[0]));
if (0 != r){ if (0 != r){
print_mbedtls_error(r); print_mbedtls_error(r);
r = -40; r = -40;
@ -135,7 +131,8 @@ int DTLSSRTPHandshake::init(mbedtls_x509_crt* certificate,
/* set temp id, just adds some exta randomness */ /* set temp id, just adds some exta randomness */
{ {
std::string remote_id = "mist"; std::string remote_id = "mist";
r = mbedtls_ssl_set_client_transport_id(&ssl_ctx, (const unsigned char*)remote_id.c_str(), remote_id.size()); r = mbedtls_ssl_set_client_transport_id(&ssl_ctx, (const unsigned char *)remote_id.c_str(),
remote_id.size());
if (0 != r){ if (0 != r){
print_mbedtls_error(r); print_mbedtls_error(r);
r = -80; r = -80;
@ -150,9 +147,7 @@ int DTLSSRTPHandshake::init(mbedtls_x509_crt* certificate,
error: error:
if (r < 0) { if (r < 0){shutdown();}
shutdown();
}
return r; return r;
} }
@ -218,13 +213,15 @@ int DTLSSRTPHandshake::parse(const uint8_t* data, size_t nbytes) {
/* see the dtls server example; this is used to prevent certain attacks (ddos) */ /* see the dtls server example; this is used to prevent certain attacks (ddos) */
case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:{ case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:{
if (0 != resetSession()){ if (0 != resetSession()){
ERROR_MSG("Failed to reset the session which is necessary when we need to verify the HELLO."); ERROR_MSG(
"Failed to reset the session which is necessary when we need to verify the HELLO.");
return -3; return -3;
} }
break; break;
} }
case MBEDTLS_ERR_SSL_WANT_READ:{ case MBEDTLS_ERR_SSL_WANT_READ:{
DONTEVEN_MSG("mbedtls wants a bit more data before it can continue parsing the DTLS handshake."); DONTEVEN_MSG(
"mbedtls wants a bit more data before it can continue parsing the DTLS handshake.");
break; break;
} }
default:{ default:{
@ -233,8 +230,7 @@ int DTLSSRTPHandshake::parse(const uint8_t* data, size_t nbytes) {
return -2; return -2;
} }
} }
} }while (MBEDTLS_ERR_SSL_WANT_WRITE == r);
while (MBEDTLS_ERR_SSL_WANT_WRITE == r);
return 0; return 0;
} }
@ -252,7 +248,8 @@ int DTLSSRTPHandshake::resetSession() {
return -1; return -1;
} }
r = mbedtls_ssl_set_client_transport_id(&ssl_ctx, (const unsigned char*)remote_id.c_str(), remote_id.size()); r = mbedtls_ssl_set_client_transport_id(&ssl_ctx, (const unsigned char *)remote_id.c_str(),
remote_id.size());
if (0 != r){ if (0 != r){
print_mbedtls_error(r); print_mbedtls_error(r);
return -2; return -2;
@ -336,14 +333,10 @@ static int on_mbedtls_wants_to_read(void* user, unsigned char* buf, size_t len)
} }
/* figure out how much we can read. */ /* figure out how much we can read. */
if (hs->buffer.size() == 0) { if (hs->buffer.size() == 0){return MBEDTLS_ERR_SSL_WANT_READ;}
return MBEDTLS_ERR_SSL_WANT_READ;
}
size_t nbytes = hs->buffer.size(); size_t nbytes = hs->buffer.size();
if (nbytes > len) { if (nbytes > len){nbytes = len;}
nbytes = len;
}
/* "read" into the given buffer. */ /* "read" into the given buffer. */
memcpy(buf, &hs->buffer[0], nbytes); memcpy(buf, &hs->buffer[0], nbytes);
@ -392,22 +385,21 @@ static void print_mbedtls_debug_message(void *ctx, int level, const char *file,
#if LOG_TO_FILE #if LOG_TO_FILE
static std::ofstream ofs; static std::ofstream ofs;
if (!ofs.is_open()) { if (!ofs.is_open()){ofs.open("mbedtls.log", std::ios::out);}
ofs.open("mbedtls.log", std::ios::out); if (!ofs.is_open()){return;}
}
if (!ofs.is_open()) {
return;
}
ofs << str; ofs << str;
ofs.flush(); ofs.flush();
#endif #endif
} }
static std::string mbedtls_err_to_string(int r){ static std::string mbedtls_err_to_string(int r){
switch (r){ switch (r){
case MBEDTLS_ERR_SSL_WANT_READ: { return "MBEDTLS_ERR_SSL_WANT_READ"; } case MBEDTLS_ERR_SSL_WANT_READ:{
case MBEDTLS_ERR_SSL_WANT_WRITE: { return "MBEDTLS_ERR_SSL_WANT_WRITE"; } return "MBEDTLS_ERR_SSL_WANT_READ";
}
case MBEDTLS_ERR_SSL_WANT_WRITE:{
return "MBEDTLS_ERR_SSL_WANT_WRITE";
}
default:{ default:{
print_mbedtls_error(r); print_mbedtls_error(r);
return "UNKNOWN"; return "UNKNOWN";
@ -416,5 +408,3 @@ static std::string mbedtls_err_to_string(int r) {
} }
/* ---------------------------------------- */ /* ---------------------------------------- */

View file

@ -1,24 +1,25 @@
#pragma once #pragma once
#include <stdint.h>
#include <deque> #include <deque>
#include <mbedtls/config.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/certs.h> #include <mbedtls/certs.h>
#include <mbedtls/x509.h> #include <mbedtls/config.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/debug.h>
#include <mbedtls/entropy.h>
#include <mbedtls/error.h>
#include <mbedtls/ssl.h> #include <mbedtls/ssl.h>
#include <mbedtls/ssl_cookie.h> #include <mbedtls/ssl_cookie.h>
#include <mbedtls/error.h>
#include <mbedtls/debug.h>
#include <mbedtls/timing.h> #include <mbedtls/timing.h>
#include <mbedtls/x509.h>
#include <stdint.h>
/* ----------------------------------------- */ /* ----------------------------------------- */
class DTLSSRTPHandshake{ class DTLSSRTPHandshake{
public: public:
DTLSSRTPHandshake(); DTLSSRTPHandshake();
int init(mbedtls_x509_crt* certificate, mbedtls_pk_context* privateKey, int(*writeCallback)(const uint8_t* data, int* nbytes)); // writeCallback should return 0 on succes < 0 on error. nbytes holds the number of bytes to be sent and needs to be set to the number of bytes actually sent. int init(mbedtls_x509_crt *certificate,
mbedtls_pk_context *privateKey, int (*writeCallback)(const uint8_t *data, int *nbytes)); // writeCallback should return 0 on succes < 0 on error. nbytes holds the number of bytes to be sent and needs to be set to the number of bytes actually sent.
int shutdown(); int shutdown();
int parse(const uint8_t *data, size_t nbytes); int parse(const uint8_t *data, size_t nbytes);
bool hasKeyingMaterial(); bool hasKeyingMaterial();
@ -50,10 +51,8 @@ public:
/* ----------------------------------------- */ /* ----------------------------------------- */
inline bool DTLSSRTPHandshake::hasKeyingMaterial(){ inline bool DTLSSRTPHandshake::hasKeyingMaterial(){
return (0 != remote_key.size() return (0 != remote_key.size() && 0 != remote_salt.size() && 0 != local_key.size() &&
&& 0 != remote_salt.size() 0 != local_salt.size());
&& 0 != local_key.size()
&& 0 != local_salt.size());
} }
/* ----------------------------------------- */ /* ----------------------------------------- */

View file

@ -1,11 +1,11 @@
/// \file dtsc.cpp /// \file dtsc.cpp
/// Holds all code for DDVTECH Stream Container parsing/generation. /// Holds all code for DDVTECH Stream Container parsing/generation.
#include "dtsc.h"
#include "defines.h" #include "defines.h"
#include "dtsc.h"
#include <arpa/inet.h> //for htonl/ntohl
#include <stdlib.h> #include <stdlib.h>
#include <string.h> //for memcmp #include <string.h> //for memcmp
#include <arpa/inet.h> //for htonl/ntohl
char DTSC::Magic_Header[] = "DTSC"; char DTSC::Magic_Header[] = "DTSC";
char DTSC::Magic_Packet[] = "DTPD"; char DTSC::Magic_Packet[] = "DTPD";
char DTSC::Magic_Packet2[] = "DTP2"; char DTSC::Magic_Packet2[] = "DTP2";
@ -30,9 +30,7 @@ DTSC::File & DTSC::File::operator =(const File & rhs) {
F = 0; F = 0;
} }
endPos = rhs.endPos; endPos = rhs.endPos;
if (rhs.myPack) { if (rhs.myPack){myPack = rhs.myPack;}
myPack = rhs.myPack;
}
metadata = rhs.metadata; metadata = rhs.metadata;
currtime = rhs.currtime; currtime = rhs.currtime;
lastreadpos = rhs.lastreadpos; lastreadpos = rhs.lastreadpos;
@ -83,7 +81,8 @@ DTSC::File::File(std::string filename, bool create) {
return; return;
} }
if (memcmp(buffer, DTSC::Magic_Header, 4) != 0){ if (memcmp(buffer, DTSC::Magic_Header, 4) != 0){
if (memcmp(buffer, DTSC::Magic_Packet2, 4) != 0 && memcmp(buffer, DTSC::Magic_Packet, 4) != 0 && memcmp(buffer, DTSC::Magic_Command, 4) != 0) { if (memcmp(buffer, DTSC::Magic_Packet2, 4) != 0 &&
memcmp(buffer, DTSC::Magic_Packet, 4) != 0 && memcmp(buffer, DTSC::Magic_Command, 4) != 0){
DEBUG_MSG(DLVL_ERROR, "%s is not a valid DTSC file", filename.c_str()); DEBUG_MSG(DLVL_ERROR, "%s is not a valid DTSC file", filename.c_str());
fclose(F); fclose(F);
F = 0; F = 0;
@ -112,20 +111,16 @@ DTSC::File::File(std::string filename, bool create) {
}else{ }else{
fseek(F, 0, SEEK_SET); fseek(F, 0, SEEK_SET);
File Fhead(filename + ".dtsh"); File Fhead(filename + ".dtsh");
if (Fhead) { if (Fhead){metadata = Fhead.metadata;}
metadata = Fhead.metadata;
}
} }
currframe = 0; currframe = 0;
} }
/// Returns the header metadata for this file as JSON::Value. /// Returns the header metadata for this file as JSON::Value.
DTSC::Meta &DTSC::File::getMeta(){ DTSC::Meta &DTSC::File::getMeta(){
return metadata; return metadata;
} }
/// (Re)writes the given string to the header area if the size is the same as the existing header. /// (Re)writes the given string to the header area if the size is the same as the existing header.
/// Forces a write if force is set to true. /// Forces a write if force is set to true.
bool DTSC::File::writeHeader(std::string &header, bool force){ bool DTSC::File::writeHeader(std::string &header, bool force){
@ -137,9 +132,7 @@ bool DTSC::File::writeHeader(std::string & header, bool force) {
int pSize = htonl(header.size()); int pSize = htonl(header.size());
fseek(F, 4, SEEK_SET); fseek(F, 4, SEEK_SET);
int tmpret = fwrite((void *)(&pSize), 4, 1, F); int tmpret = fwrite((void *)(&pSize), 4, 1, F);
if (tmpret != 1) { if (tmpret != 1){return false;}
return false;
}
fseek(F, 8, SEEK_SET); fseek(F, 8, SEEK_SET);
int ret = fwrite(header.c_str(), headerSize, 1, F); int ret = fwrite(header.c_str(), headerSize, 1, F);
fseek(F, 8 + headerSize, SEEK_SET); fseek(F, 8 + headerSize, SEEK_SET);
@ -153,17 +146,11 @@ long long int DTSC::File::addHeader(std::string & header) {
long long int writePos = ftell(F); long long int writePos = ftell(F);
int hSize = htonl(header.size()); int hSize = htonl(header.size());
int ret = fwrite(DTSC::Magic_Header, 4, 1, F); // write header int ret = fwrite(DTSC::Magic_Header, 4, 1, F); // write header
if (ret != 1) { if (ret != 1){return 0;}
return 0;
}
ret = fwrite((void *)(&hSize), 4, 1, F); // write size ret = fwrite((void *)(&hSize), 4, 1, F); // write size
if (ret != 1) { if (ret != 1){return 0;}
return 0;
}
ret = fwrite(header.c_str(), header.size(), 1, F); // write contents ret = fwrite(header.c_str(), header.size(), 1, F); // write contents
if (ret != 1) { if (ret != 1){return 0;}
return 0;
}
fseek(F, 0, SEEK_END); fseek(F, 0, SEEK_END);
endPos = ftell(F); endPos = ftell(F);
return writePos; // return position written at return writePos; // return position written at
@ -212,9 +199,7 @@ void DTSC::File::readHeader(int pos) {
return; return;
} }
} }
if (!metadata.live){ if (!metadata.live){metadata.vod = true;}
metadata.vod = true;
}
} }
long int DTSC::File::getBytePosEOF(){ long int DTSC::File::getBytePosEOF(){
@ -261,14 +246,11 @@ void DTSC::File::seekNext() {
return seekNext(); return seekNext();
} }
long long unsigned int version = 0; long long unsigned int version = 0;
if (memcmp(buffer, DTSC::Magic_Packet, 4) == 0) { if (memcmp(buffer, DTSC::Magic_Packet, 4) == 0){version = 1;}
version = 1; if (memcmp(buffer, DTSC::Magic_Packet2, 4) == 0){version = 2;}
}
if (memcmp(buffer, DTSC::Magic_Packet2, 4) == 0) {
version = 2;
}
if (version == 0){ if (version == 0){
DEBUG_MSG(DLVL_ERROR, "Invalid packet header @ %#x - %.4s != %.4s @ %d", (unsigned int)lastreadpos, (char *)buffer, DTSC::Magic_Packet2, (int)lastreadpos); DEBUG_MSG(DLVL_ERROR, "Invalid packet header @ %#x - %.4s != %.4s @ %d",
(unsigned int)lastreadpos, (char *)buffer, DTSC::Magic_Packet2, (int)lastreadpos);
myPack.null(); myPack.null();
return; return;
} }
@ -320,7 +302,8 @@ void DTSC::File::seekNext() {
} }
} }
if (currentPositions.size()){ if (currentPositions.size()){
for (std::set<seekPos>::iterator curPosIter = currentPositions.begin(); curPosIter != currentPositions.end(); curPosIter++) { for (std::set<seekPos>::iterator curPosIter = currentPositions.begin();
curPosIter != currentPositions.end(); curPosIter++){
if ((*curPosIter).trackID == tmpPos.trackID && (*curPosIter).seekTime >= tmpPos.seekTime){ if ((*curPosIter).trackID == tmpPos.trackID && (*curPosIter).seekTime >= tmpPos.seekTime){
insert = false; insert = false;
break; break;
@ -330,9 +313,7 @@ void DTSC::File::seekNext() {
} }
} }
if (insert){ if (insert){
if (tmpPos.seekTime > 0xffffffffffffff00ll){ if (tmpPos.seekTime > 0xffffffffffffff00ll){tmpPos.seekTime = 0;}
tmpPos.seekTime = 0;
}
currentPositions.insert(tmpPos); currentPositions.insert(tmpPos);
}else{ }else{
seek_time(myPack.getTime(), myPack.getTrackId(), true); seek_time(myPack.getTime(), myPack.getTrackId(), true);
@ -357,12 +338,11 @@ void DTSC::File::parseNext(){
return; return;
} }
long long unsigned int version = 0; long long unsigned int version = 0;
if (memcmp(header_buffer, DTSC::Magic_Packet, 4) == 0 || memcmp(header_buffer, DTSC::Magic_Command, 4) == 0 || memcmp(header_buffer, DTSC::Magic_Header, 4) == 0) { if (memcmp(header_buffer, DTSC::Magic_Packet, 4) == 0 || memcmp(header_buffer, DTSC::Magic_Command, 4) == 0 ||
memcmp(header_buffer, DTSC::Magic_Header, 4) == 0){
version = 1; version = 1;
} }
if (memcmp(header_buffer, DTSC::Magic_Packet2, 4) == 0) { if (memcmp(header_buffer, DTSC::Magic_Packet2, 4) == 0){version = 2;}
version = 2;
}
if (version == 0){ if (version == 0){
DEBUG_MSG(DLVL_ERROR, "Invalid packet header @ %#x: %.4s", (unsigned int)lastreadpos, (char *)buffer); DEBUG_MSG(DLVL_ERROR, "Invalid packet header @ %#x: %.4s", (unsigned int)lastreadpos, (char *)buffer);
myPack.null(); myPack.null();
@ -421,9 +401,7 @@ bool DTSC::File::seek_time(unsigned int ms, unsigned int trackNo, bool forceSeek
DTSC::Track &trackRef = metadata.tracks[trackNo]; DTSC::Track &trackRef = metadata.tracks[trackNo];
for (unsigned int i = 0; i < trackRef.keys.size(); i++){ for (unsigned int i = 0; i < trackRef.keys.size(); i++){
long keyTime = trackRef.keys[i].getTime(); long keyTime = trackRef.keys[i].getTime();
if (keyTime > ms) { if (keyTime > ms){break;}
break;
}
if ((long long unsigned int)keyTime > tmpPos.seekTime){ if ((long long unsigned int)keyTime > tmpPos.seekTime){
tmpPos.seekTime = keyTime; tmpPos.seekTime = keyTime;
tmpPos.bytePos = trackRef.keys[i].getBpos(); tmpPos.bytePos = trackRef.keys[i].getBpos();
@ -449,7 +427,8 @@ bool DTSC::File::seek_time(unsigned int ms, unsigned int trackNo, bool forceSeek
unsigned int packID = ntohl(((int *)header)[2]); unsigned int packID = ntohl(((int *)header)[2]);
if (memcmp(header, Magic_Packet2, 4) != 0 || packID != trackNo){ if (memcmp(header, Magic_Packet2, 4) != 0 || packID != trackNo){
if (memcmp(header, "DT", 2) != 0){ if (memcmp(header, "DT", 2) != 0){
DEBUG_MSG(DLVL_WARN, "Invalid header during seek to %u in track %d @ %lld - resetting bytePos from %lld to zero", ms, trackNo, lastreadpos, tmpPos.bytePos); DEBUG_MSG(DLVL_WARN, "Invalid header during seek to %u in track %d @ %lld - resetting bytePos from %lld to zero",
ms, trackNo, lastreadpos, tmpPos.bytePos);
tmpPos.bytePos = 0; tmpPos.bytePos = 0;
continue; continue;
} }
@ -468,9 +447,7 @@ bool DTSC::File::seek_time(unsigned int ms, unsigned int trackNo, bool forceSeek
} }
} }
// DEBUG_MSG(DLVL_HIGH, "Seek to %u:%d resulted in %lli", trackNo, ms, tmpPos.seekTime); // DEBUG_MSG(DLVL_HIGH, "Seek to %u:%d resulted in %lli", trackNo, ms, tmpPos.seekTime);
if (tmpPos.seekTime > 0xffffffffffffff00ll){ if (tmpPos.seekTime > 0xffffffffffffff00ll){tmpPos.seekTime = 0;}
tmpPos.seekTime = 0;
}
currentPositions.insert(tmpPos); currentPositions.insert(tmpPos);
return true; return true;
} }
@ -488,9 +465,7 @@ bool DTSC::File::seek_time(unsigned int ms) {
} }
bool DTSC::File::seek_bpos(int bpos){ bool DTSC::File::seek_bpos(int bpos){
if (fseek(F, bpos, SEEK_SET) == 0) { if (fseek(F, bpos, SEEK_SET) == 0){return true;}
return true;
}
return false; return false;
} }
@ -498,9 +473,7 @@ void DTSC::File::rewritePacket(std::string & newPacket, int bytePos) {
fseek(F, bytePos, SEEK_SET); fseek(F, bytePos, SEEK_SET);
fwrite(newPacket.c_str(), newPacket.size(), 1, F); fwrite(newPacket.c_str(), newPacket.size(), 1, F);
fseek(F, 0, SEEK_END); fseek(F, 0, SEEK_END);
if (ftell(F) > endPos) { if (ftell(F) > endPos){endPos = ftell(F);}
endPos = ftell(F);
}
} }
void DTSC::File::writePacket(std::string &newPacket){ void DTSC::File::writePacket(std::string &newPacket){
@ -515,15 +488,11 @@ void DTSC::File::writePacket(JSON::Value & newPacket) {
} }
bool DTSC::File::atKeyframe(){ bool DTSC::File::atKeyframe(){
if (myPack.getFlag("keyframe")) { if (myPack.getFlag("keyframe")){return true;}
return true;
}
long long int bTime = myPack.getTime(); long long int bTime = myPack.getTime();
DTSC::Track &trackRef = metadata.tracks[myPack.getTrackId()]; DTSC::Track &trackRef = metadata.tracks[myPack.getTrackId()];
for (unsigned int i = 0; i < trackRef.keys.size(); i++){ for (unsigned int i = 0; i < trackRef.keys.size(); i++){
if (trackRef.keys[i].getTime() >= bTime) { if (trackRef.keys[i].getTime() >= bTime){return (trackRef.keys[i].getTime() == bTime);}
return (trackRef.keys[i].getTime() == bTime);
}
} }
return false; return false;
} }

View file

@ -2,16 +2,16 @@
/// Holds all headers for DDVTECH Stream Container parsing/generation. /// Holds all headers for DDVTECH Stream Container parsing/generation.
#pragma once #pragma once
#include <vector>
#include <iostream>
#include <stdint.h> //for uint64_t
#include <string>
#include <deque>
#include <set>
#include <stdio.h> //for FILE
#include "json.h" #include "json.h"
#include "socket.h" #include "socket.h"
#include "timing.h" #include "timing.h"
#include <deque>
#include <iostream>
#include <set>
#include <stdint.h> //for uint64_t
#include <stdio.h> //for FILE
#include <string>
#include <vector>
#define DTSC_INT 0x01 #define DTSC_INT 0x01
#define DTSC_STR 0x02 #define DTSC_STR 0x02
@ -53,9 +53,7 @@ namespace DTSC {
return true; return true;
}else{ }else{
if (seekTime == rhs.seekTime){ if (seekTime == rhs.seekTime){
if (trackID < rhs.trackID) { if (trackID < rhs.trackID){return true;}
return true;
}
} }
} }
return false; return false;
@ -65,13 +63,7 @@ namespace DTSC {
unsigned int trackID; ///< Stores the track the DTSC packet referenced by this structure is associated with. unsigned int trackID; ///< Stores the track the DTSC packet referenced by this structure is associated with.
}; };
enum packType { enum packType{DTSC_INVALID, DTSC_HEAD, DTSC_V1, DTSC_V2, DTCM};
DTSC_INVALID,
DTSC_HEAD,
DTSC_V1,
DTSC_V2,
DTCM
};
/// This class allows scanning through raw binary format DTSC data. /// This class allows scanning through raw binary format DTSC data.
/// It can be used as an iterator or as a direct accessor. /// It can be used as an iterator or as a direct accessor.
@ -98,6 +90,7 @@ namespace DTSC {
std::string asString() const; std::string asString() const;
void getString(char *&result, size_t &len) const; void getString(char *&result, size_t &len) const;
JSON::Value asJSON() const; JSON::Value asJSON() const;
private: private:
char *p; char *p;
size_t len; size_t len;
@ -106,8 +99,8 @@ namespace DTSC {
/// DTSC::Packets can currently be three types: /// DTSC::Packets can currently be three types:
/// DTSC_HEAD packets are the "DTSC" header string, followed by 4 bytes len and packed content. /// DTSC_HEAD packets are the "DTSC" header string, followed by 4 bytes len and packed content.
/// DTSC_V1 packets are "DTPD", followed by 4 bytes len and packed content. /// DTSC_V1 packets are "DTPD", followed by 4 bytes len and packed content.
/// DTSC_V2 packets are "DTP2", followed by 4 bytes len, 4 bytes trackID, 8 bytes time, and packed content. /// DTSC_V2 packets are "DTP2", followed by 4 bytes len, 4 bytes trackID, 8 bytes time, and packed
/// The len is always without the first 8 bytes counted. /// content. The len is always without the first 8 bytes counted.
class Packet{ class Packet{
public: public:
Packet(); Packet();
@ -120,7 +113,9 @@ namespace DTSC {
packType getVersion() const; packType getVersion() const;
void reInit(Socket::Connection &src); void reInit(Socket::Connection &src);
void reInit(const char *data_, unsigned int len, bool noCopy = false); 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, uint64_t packBytePos, bool isKeyframe, int64_t bootMsOffset = 0); void genericFill(long long packTime, long long packOffset, long long packTrack,
const char *packData, long long packDataSize, uint64_t packBytePos,
bool isKeyframe, int64_t bootMsOffset = 0);
void appendData(const char *appendData, uint32_t appendLen); void appendData(const char *appendData, uint32_t appendLen);
void getString(const char *identifier, char *&result, size_t &len) const; void getString(const char *identifier, char *&result, size_t &len) const;
void getString(const char *identifier, std::string &result) const; void getString(const char *identifier, std::string &result) const;
@ -145,6 +140,7 @@ namespace DTSC {
std::string toSummary() const; std::string toSummary() const;
Scan getScan() const; Scan getScan() const;
Scan getScan(); Scan getScan();
protected: protected:
bool master; bool master;
packType version; packType version;
@ -159,16 +155,14 @@ namespace DTSC {
/// A child class of DTSC::Packet, which allows overriding the packet time efficiently. /// A child class of DTSC::Packet, which allows overriding the packet time efficiently.
class RetimedPacket : public Packet{ class RetimedPacket : public Packet{
public: public:
RetimedPacket(uint64_t reTime){ RetimedPacket(uint64_t reTime){timeOverride = reTime;}
timeOverride = reTime; RetimedPacket(uint64_t reTime, const Packet &rhs) : Packet(rhs){timeOverride = reTime;}
} RetimedPacket(uint64_t reTime, const char *data_, unsigned int len, bool noCopy = false)
RetimedPacket(uint64_t reTime, const Packet & rhs) : Packet(rhs){ : Packet(data_, len, noCopy){
timeOverride = reTime;
}
RetimedPacket(uint64_t reTime, const char * data_, unsigned int len, bool noCopy = false) : Packet(data_, len, noCopy){
timeOverride = reTime; timeOverride = reTime;
} }
virtual uint64_t getTime() const{return timeOverride;} virtual uint64_t getTime() const{return timeOverride;}
protected: protected:
uint64_t timeOverride; uint64_t timeOverride;
}; };
@ -197,9 +191,7 @@ namespace DTSC {
if (seekTime < rhs.seekTime){ if (seekTime < rhs.seekTime){
return true; return true;
}else{ }else{
if (seekTime > rhs.seekTime) { if (seekTime > rhs.seekTime){return false;}
return false;
}
} }
return (trackID < rhs.trackID); return (trackID < rhs.trackID);
} }
@ -220,6 +212,7 @@ namespace DTSC {
void setIvec(const char *iVec, int len); void setIvec(const char *iVec, int len);
long long int asInt(); long long int asInt();
char *getData(); char *getData();
private: private:
///\brief Data storage for this initialization vector. ///\brief Data storage for this initialization vector.
/// ///
@ -239,6 +232,7 @@ namespace DTSC {
void setOffset(uint32_t newOffset); void setOffset(uint32_t newOffset);
char *getData(); char *getData();
void toPrettyString(std::ostream &str, int indent = 0); void toPrettyString(std::ostream &str, int indent = 0);
private: private:
#define PACKED_PART_SIZE 9 #define PACKED_PART_SIZE 9
///\brief Data storage for this Part. ///\brief Data storage for this Part.
@ -266,6 +260,7 @@ namespace DTSC {
void setTime(unsigned long long newTime); void setTime(unsigned long long newTime);
char *getData(); char *getData();
void toPrettyString(std::ostream &str, int indent = 0); void toPrettyString(std::ostream &str, int indent = 0);
private: private:
#define PACKED_KEY_SIZE 25 #define PACKED_KEY_SIZE 25
///\brief Data storage for this Key. ///\brief Data storage for this Key.
@ -291,6 +286,7 @@ namespace DTSC {
void setSize(unsigned long newSize); void setSize(unsigned long newSize);
char *getData(); char *getData();
void toPrettyString(std::ostream &str, int indent = 0); void toPrettyString(std::ostream &str, int indent = 0);
private: private:
#define PACKED_FRAGMENT_SIZE 13 #define PACKED_FRAGMENT_SIZE 13
///\brief Data storage for this Fragment. ///\brief Data storage for this Fragment.
@ -314,9 +310,12 @@ namespace DTSC {
return (parts.size() && keySizes.size() && (keySizes.size() == keys.size())); return (parts.size() && keySizes.size() && (keySizes.size() == keys.size()));
} }
/* /*
void update(long long packTime, long long packOffset, long long packDataSize, uint64_t packBytePos, bool isKeyframe, long long packSendSize, unsigned long segment_size = 1900); void update(long long packTime, long long packOffset, long long packDataSize, uint64_t
packBytePos, bool isKeyframe, long long packSendSize, unsigned long segment_size = 1900);
*/ */
void update(long long packTime, long long packOffset, long long packDataSize, uint64_t packBytePos, bool isKeyframe, long long packSendSize, unsigned long segment_size = 1900, 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 = 1900, const char *iVec = 0);
int getSendLen(bool skipDynamic = false); int getSendLen(bool skipDynamic = false);
void send(Socket::Connection &conn, bool skipDynamic = false); void send(Socket::Connection &conn, bool skipDynamic = false);
void writeTo(char *&p); void writeTo(char *&p);
@ -358,6 +357,7 @@ namespace DTSC {
int fpks; int fpks;
void removeFirstKey(); void removeFirstKey();
uint32_t secsSinceFirstFragmentInsert(); uint32_t secsSinceFirstFragmentInsert();
private: private:
std::string cachedIdent; std::string cachedIdent;
std::deque<uint32_t> fragInsertTime; std::deque<uint32_t> fragInsertTime;
@ -380,11 +380,16 @@ namespace DTSC {
void updatePosOverride(DTSC::Packet &pack, uint64_t bpos); void updatePosOverride(DTSC::Packet &pack, uint64_t bpos);
void update(JSON::Value &pack, unsigned long segment_size = 1900); void update(JSON::Value &pack, unsigned long segment_size = 1900);
/*LTS /*LTS
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 = 1900); void update(long long packTime, long long packOffset, long long packTrack, long long
LTS*/ packDataSize, uint64_t packBytePos, bool isKeyframe, long long packSendSize = 0, unsigned long
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 = 1900, const char * iVec = 0); segment_size = 1900); LTS*/
unsigned int getSendLen(bool skipDynamic = false, std::set<unsigned long> selectedTracks = std::set<unsigned long>()); void update(long long packTime, long long packOffset, long long packTrack,
void send(Socket::Connection & conn, bool skipDynamic = false, std::set<unsigned long> selectedTracks = std::set<unsigned long>()); long long packDataSize, uint64_t packBytePos, bool isKeyframe,
long long packSendSize = 0, unsigned long segment_size = 1900, const char *iVec = 0);
unsigned int getSendLen(bool skipDynamic = false,
std::set<unsigned long> selectedTracks = std::set<unsigned long>());
void send(Socket::Connection &conn, bool skipDynamic = false,
std::set<unsigned long> selectedTracks = std::set<unsigned long>());
void writeTo(char *p); void writeTo(char *p);
JSON::Value toJSON(); JSON::Value toJSON();
void reset(); void reset();
@ -448,6 +453,7 @@ namespace DTSC {
void writePacket(JSON::Value &newPacket); void writePacket(JSON::Value &newPacket);
bool atKeyframe(); bool atKeyframe();
void selectTracks(std::set<unsigned long> &tracks); void selectTracks(std::set<unsigned long> &tracks);
private: private:
long int endPos; long int endPos;
void readHeader(int pos); void readHeader(int pos);
@ -466,5 +472,4 @@ namespace DTSC {
}; };
// FileWriter // FileWriter
} }// namespace DTSC

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
#include "ebml.h"
#include "bitfields.h" #include "bitfields.h"
#include "defines.h" #include "defines.h"
#include "ebml.h"
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
@ -380,8 +380,7 @@ namespace EBML{
switch (getType()){ switch (getType()){
case ELEM_MASTER:{ case ELEM_MASTER:{
const uint64_t payLen = getPayloadLen(); const uint64_t payLen = getPayloadLen();
ret << std::string(indent, ' ') << "Element [" << getIDString(getID()) << "] (" ret << std::string(indent, ' ') << "Element [" << getIDString(getID()) << "] (" << getOuterLen() << "b, ";
<< getOuterLen() << "b, ";
if (payLen == 0xFFFFFFFFFFFFFFFFull){ if (payLen == 0xFFFFFFFFFFFFFFFFull){
ret << "infinite"; ret << "infinite";
}else{ }else{
@ -639,9 +638,8 @@ namespace EBML{
std::string Block::toPrettyString(const uint8_t indent, const uint8_t detail) const{ std::string Block::toPrettyString(const uint8_t indent, const uint8_t detail) const{
std::stringstream ret; std::stringstream ret;
ret << std::string(indent, ' ') << getIDString(getID()) << " with " ret << std::string(indent, ' ') << getIDString(getID()) << " with " << (unsigned int)getFrameCount()
<< (unsigned int)getFrameCount() << " frame(s) for track " << getTrackNum() << " @ " << " frame(s) for track " << getTrackNum() << " @ " << getTimecode();
<< getTimecode();
if (isKeyframe()){ret << " [KeyOnly]";} if (isKeyframe()){ret << " [KeyOnly]";}
if (isInvisible()){ret << " [Invisible]";} if (isInvisible()){ret << " [Invisible]";}
if (isDiscardable()){ret << " [Discardable]";} if (isDiscardable()){ret << " [Discardable]";}
@ -656,8 +654,7 @@ namespace EBML{
for (uint32_t frameNo = 0; frameNo < getFrameCount(); ++frameNo){ for (uint32_t frameNo = 0; frameNo < getFrameCount(); ++frameNo){
const char *payDat = getFrameData(frameNo); const char *payDat = getFrameData(frameNo);
const uint64_t payLen = getFrameSize(frameNo); const uint64_t payLen = getFrameSize(frameNo);
ret << std::dec << std::string(indent + 4, ' ') << "Frame " << (frameNo + 1) << " (" ret << std::dec << std::string(indent + 4, ' ') << "Frame " << (frameNo + 1) << " (" << payLen << "b):";
<< payLen << "b):";
if (!payDat || !payLen || detail < 6){ if (!payDat || !payLen || detail < 6){
ret << std::endl; ret << std::endl;
continue; continue;
@ -683,4 +680,3 @@ namespace EBML{
return ret.str(); return ret.str();
} }
}// namespace EBML }// namespace EBML

View file

@ -121,4 +121,3 @@ namespace EBML{
virtual std::string toPrettyString(const uint8_t indent = 0, const uint8_t detail = 3) const; virtual std::string toPrettyString(const uint8_t indent = 0, const uint8_t detail = 3) const;
}; };
}// namespace EBML }// namespace EBML

View file

@ -118,8 +118,7 @@ namespace EBML{
void sendElemInfo(Socket::Connection &C, const std::string &appName, double duration){ void sendElemInfo(Socket::Connection &C, const std::string &appName, double duration){
sendElemHead(C, EID_INFO, sendElemHead(C, EID_INFO,
13 + 2 * appName.size() + 13 + 2 * appName.size() + (duration > 0 ? sizeElemDbl(EID_DURATION, duration) : 0));
(duration > 0 ? sizeElemDbl(EID_DURATION, duration) : 0));
sendElemUInt(C, EID_TIMECODESCALE, 1000000); sendElemUInt(C, EID_TIMECODESCALE, 1000000);
if (duration > 0){sendElemDbl(C, EID_DURATION, duration);} if (duration > 0){sendElemDbl(C, EID_DURATION, duration);}
sendElemStr(C, EID_MUXINGAPP, appName); sendElemStr(C, EID_MUXINGAPP, appName);
@ -136,8 +135,7 @@ namespace EBML{
(duration > 0 ? sizeElemDbl(EID_DURATION, duration) : 0)); (duration > 0 ? sizeElemDbl(EID_DURATION, duration) : 0));
} }
void sendSimpleBlock(Socket::Connection &C, DTSC::Packet &pkt, uint64_t clusterTime, void sendSimpleBlock(Socket::Connection &C, DTSC::Packet &pkt, uint64_t clusterTime, bool forceKeyframe){
bool forceKeyframe){
size_t dataLen = 0; size_t dataLen = 0;
char *dataPointer = 0; char *dataPointer = 0;
pkt.getString("data", dataPointer, dataLen); pkt.getString("data", dataPointer, dataLen);
@ -170,8 +168,7 @@ namespace EBML{
return sizeElemHead(EID_SEEK, elems) + elems; return sizeElemHead(EID_SEEK, elems) + elems;
} }
void sendElemCuePoint(Socket::Connection &C, uint64_t time, uint64_t track, uint64_t clusterPos, void sendElemCuePoint(Socket::Connection &C, uint64_t time, uint64_t track, uint64_t clusterPos, uint64_t relaPos){
uint64_t relaPos){
uint32_t elemsA = 0, elemsB = 0; uint32_t elemsA = 0, elemsB = 0;
elemsA += sizeElemUInt(EID_CUETRACK, track); elemsA += sizeElemUInt(EID_CUETRACK, track);
elemsA += sizeElemUInt(EID_CUECLUSTERPOSITION, clusterPos); elemsA += sizeElemUInt(EID_CUECLUSTERPOSITION, clusterPos);
@ -196,4 +193,3 @@ namespace EBML{
} }
}// namespace EBML }// namespace EBML

View file

@ -17,8 +17,7 @@ namespace EBML{
void sendElemSeek(Socket::Connection &C, uint32_t ID, uint64_t bytePos); void sendElemSeek(Socket::Connection &C, uint32_t ID, uint64_t bytePos);
uint32_t sizeElemSeek(uint32_t ID, uint64_t bytePos); uint32_t sizeElemSeek(uint32_t ID, uint64_t bytePos);
void sendElemCuePoint(Socket::Connection &C, uint64_t time, uint64_t track, uint64_t clusterPos, void sendElemCuePoint(Socket::Connection &C, uint64_t time, uint64_t track, uint64_t clusterPos, uint64_t relaPos);
uint64_t relaPos);
uint32_t sizeElemCuePoint(uint64_t time, uint64_t track, uint64_t clusterPos, uint64_t relaPos); uint32_t sizeElemCuePoint(uint64_t time, uint64_t track, uint64_t clusterPos, uint64_t relaPos);
uint8_t sizeUInt(const uint64_t val); uint8_t sizeUInt(const uint64_t val);
@ -28,8 +27,6 @@ namespace EBML{
uint32_t sizeElemDbl(uint32_t ID, const double val); uint32_t sizeElemDbl(uint32_t ID, const double val);
uint32_t sizeElemStr(uint32_t ID, const std::string &val); uint32_t sizeElemStr(uint32_t ID, const std::string &val);
void sendSimpleBlock(Socket::Connection &C, DTSC::Packet &pkt, uint64_t clusterTime, void sendSimpleBlock(Socket::Connection &C, DTSC::Packet &pkt, uint64_t clusterTime, bool forceKeyframe = false);
bool forceKeyframe = false);
uint32_t sizeSimpleBlock(uint64_t trackId, uint32_t dataSize); uint32_t sizeSimpleBlock(uint64_t trackId, uint32_t dataSize);
}// namespace EBML }// namespace EBML

View file

@ -101,11 +101,9 @@ namespace Encodings{
std::string escaped = ""; std::string escaped = "";
int max = c.length(); int max = c.length();
for (int i = 0; i < max; i++){ for (int i = 0; i < max; i++){
if (('0' <= c[i] && c[i] <= '9') || ('a' <= c[i] && c[i] <= 'z') || if (('0' <= c[i] && c[i] <= '9') || ('a' <= c[i] && c[i] <= 'z') || ('A' <= c[i] && c[i] <= 'Z') ||
('A' <= c[i] && c[i] <= 'Z') ||
(c[i] == '$' || c[i] == '-' || c[i] == '_' || c[i] == '.' || c[i] == ',' || c[i] == '!' || (c[i] == '$' || c[i] == '-' || c[i] == '_' || c[i] == '.' || c[i] == ',' || c[i] == '!' ||
c[i] == '~' || c[i] == ';' || c[i] == '*' || c[i] == '(' || c[i] == ')' || c[i] == '~' || c[i] == ';' || c[i] == '*' || c[i] == '(' || c[i] == ')' || c[i] == '\'') ||
c[i] == '\'') ||
(ign.size() && ign.find(c[i]) != std::string::npos)){ (ign.size() && ign.find(c[i]) != std::string::npos)){
escaped.append(&c[i], 1); escaped.append(&c[i], 1);
}else{ }else{
@ -143,4 +141,3 @@ namespace Encodings{
} }
}// namespace Encodings }// namespace Encodings

View file

@ -40,4 +40,3 @@ namespace Encodings{
}; };
}// namespace Encodings }// namespace Encodings

View file

@ -1,16 +1,16 @@
#include "encryption.h"
#include "auth.h" #include "auth.h"
#include "bitfields.h"
#include "defines.h"
#include "encode.h"
#include "encryption.h"
#include "http_parser.h"
#include "nal.h" /*LTS*/
#include "rijndael.h"
#include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <iomanip> #include <iomanip>
#include <cstdio>
#include <iostream> #include <iostream>
#include "rijndael.h"
#include "defines.h"
#include "bitfields.h"
#include "http_parser.h"
#include "encode.h"
#include "nal.h"/*LTS*/
#include <sstream> #include <sstream>
namespace Encryption{ namespace Encryption{
@ -19,14 +19,11 @@ namespace Encryption {
std::stringstream res; std::stringstream res;
for (int i = 0; i < dataLen; i++){ for (int i = 0; i < dataLen; i++){
res << std::hex << std::setw(2) << std::setfill('0') << (int)data[i]; res << std::hex << std::setw(2) << std::setfill('0') << (int)data[i];
if (i % 4 == 3){ if (i % 4 == 3){res << " ";}
res << " ";
}
} }
return res.str(); return res.str();
} }
std::string AES_Crypt(const std::string &data, const std::string &key, std::string &ivec){ std::string AES_Crypt(const std::string &data, const std::string &key, std::string &ivec){
return AES_Crypt(data.data(), data.size(), key.data(), ivec.data()); return AES_Crypt(data.data(), data.size(), key.data(), ivec.data());
} }
@ -43,7 +40,8 @@ namespace Encryption {
/// This function encrypts data in-place. /// This function encrypts data in-place.
/// It alters all parameters except dataLen. /// It alters all parameters except dataLen.
/// Do not use it unless you know what you are doing. /// Do not use it unless you know what you are doing.
void AESPartialCrypt(char * data, int dataLen, char * expandedKey, char * eCount, char * iVec, unsigned int & num, bool & initialize) { void AESPartialCrypt(char *data, int dataLen, char *expandedKey, char *eCount, char *iVec,
unsigned int &num, bool &initialize){
if (initialize){ if (initialize){
num = 0; num = 0;
memset(eCount, 0, 16); memset(eCount, 0, 16);
@ -100,7 +98,6 @@ namespace Encryption {
return std::string(result, 8); return std::string(result, 8);
} }
/// This function encrypts data in-place. /// This function encrypts data in-place.
void AESFullCrypt(char *data, int dataLen, const char *key, const char *ivec){ void AESFullCrypt(char *data, int dataLen, const char *key, const char *ivec){
unsigned int num = 0; unsigned int num = 0;
@ -137,9 +134,7 @@ namespace Encryption {
pos += *it; pos += *it;
} }
} }
if (codec == "AAC") { if (codec == "AAC"){Encryption::AESFullCrypt(data, dataLen, key, iVec);}
Encryption::AESFullCrypt(data, dataLen, key, iVec);
}
} }
/// Converts a hexidecimal string format key to binary string format. /// Converts a hexidecimal string format key to binary string format.
@ -153,7 +148,6 @@ namespace Encryption {
return std::string(newkey, 16); return std::string(newkey, 16);
} }
/// Helper function for urlescape. /// Helper function for urlescape.
/// Encodes a character as two hex digits. /// Encodes a character as two hex digits.
std::string hex(char dec){ std::string hex(char dec){
@ -171,9 +165,7 @@ namespace Encryption {
std::string hex(const std::string &input){ std::string hex(const std::string &input){
std::string res; std::string res;
res.reserve(input.size() * 2); res.reserve(input.size() * 2);
for (unsigned int i = 0; i < input.size(); i++) { for (unsigned int i = 0; i < input.size(); i++){res += hex(input[i]);}
res += hex(input[i]);
}
return res; return res;
} }
@ -181,7 +173,8 @@ namespace Encryption {
int hostPos = vmData.url.find("://") + 3; int hostPos = vmData.url.find("://") + 3;
int portPos = vmData.url.find(":", hostPos); int portPos = vmData.url.find(":", hostPos);
std::string hostName = vmData.url.substr(hostPos, (portPos == std::string::npos ? portPos : portPos - hostPos)); std::string hostName =
vmData.url.substr(hostPos, (portPos == std::string::npos ? portPos : portPos - hostPos));
int port = (portPos == std::string::npos ? 80 : atoi(vmData.url.data() + portPos + 1)); int port = (portPos == std::string::npos ? 80 : atoi(vmData.url.data() + portPos + 1));
Socket::Connection veriConn(hostName, port, true); Socket::Connection veriConn(hostName, port, true);
@ -229,5 +222,4 @@ namespace Encryption {
offset += laurl.size() + 1; //+1 for the concluding 0-byte offset += laurl.size() + 1; //+1 for the concluding 0-byte
memcpy(shmPage + offset, lauurl.c_str(), lauurl.size() + 1); memcpy(shmPage + offset, lauurl.c_str(), lauurl.size() + 1);
} }
} }// namespace Encryption

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <string>
#include "dtsc.h" #include "dtsc.h"
#include <string>
namespace Encryption{ namespace Encryption{
class verimatrixData{ class verimatrixData{
@ -23,7 +23,8 @@ namespace Encryption {
// These functions are dangerous for your data // These functions are dangerous for your data
void AESFullCrypt(char *data, int dataLen, const char *key, const char *ivec); void AESFullCrypt(char *data, int dataLen, const char *key, const char *ivec);
void AESPartialCrypt(char * data, int dataLen, char * expandedKey, char * eCount, char * iVec, unsigned int & num, bool & initialize); void AESPartialCrypt(char *data, int dataLen, char *expandedKey, char *eCount, char *iVec,
unsigned int &num, bool &initialize);
std::string PR_GenerateContentKey(std::string &keyseed, std::string &keyid); std::string PR_GenerateContentKey(std::string &keyseed, std::string &keyid);
std::string PR_GuidToByteArray(std::string &guid); std::string PR_GuidToByteArray(std::string &guid);
@ -31,4 +32,4 @@ namespace Encryption {
void encryptPlayReady(DTSC::Packet &pack, std::string &codec, const char *iVec, const char *key); void encryptPlayReady(DTSC::Packet &pack, std::string &codec, const char *iVec, const char *key);
void fillVerimatrix(verimatrixData &vmData); void fillVerimatrix(verimatrixData &vmData);
} }// namespace Encryption

View file

@ -1,12 +1,12 @@
/// \file flv_tag.cpp /// \file flv_tag.cpp
/// Holds all code for the FLV namespace. /// Holds all code for the FLV namespace.
#include "flv_tag.h" #include "adts.h"
#include "defines.h" #include "defines.h"
#include "flv_tag.h"
#include "rtmpchunks.h" #include "rtmpchunks.h"
#include "timing.h" #include "timing.h"
#include "util.h" #include "util.h"
#include "adts.h"
#include <fcntl.h> //for Tag::FileLoader #include <fcntl.h> //for Tag::FileLoader
#include <sstream> #include <sstream>
#include <stdio.h> //for Tag::FileLoader #include <stdio.h> //for Tag::FileLoader
@ -20,8 +20,7 @@
/// Defaults to a audio+video header on FLV version 0x01 if no header received yet. /// Defaults to a audio+video header on FLV version 0x01 if no header received yet.
char FLV::Header[13] ={'F', 'L', 'V', 0x01, 0x05, 0, 0, 0, 0x09, 0, 0, 0, 0}; char FLV::Header[13] ={'F', 'L', 'V', 0x01, 0x05, 0, 0, 0, 0x09, 0, 0, 0, 0};
bool FLV::Parse_Error = bool FLV::Parse_Error = false; ///< This variable is set to true if a problem is encountered while parsing the FLV.
false; ///< This variable is set to true if a problem is encountered while parsing the FLV.
std::string FLV::Error_Str = ""; std::string FLV::Error_Str = "";
/// Checks a FLV Header for validness. Returns true if the header is valid, false /// Checks a FLV Header for validness. Returns true if the header is valid, false
@ -504,51 +503,41 @@ bool FLV::Tag::DTSCMetaInit(DTSC::Meta &M, std::set<long unsigned int> &selTrack
if (M.tracks[*it].type == "video"){ if (M.tracks[*it].type == "video"){
trinfo.addContent(AMF::Object("", AMF::AMF0_OBJECT)); trinfo.addContent(AMF::Object("", AMF::AMF0_OBJECT));
trinfo.getContentP(i)->addContent(AMF::Object( trinfo.getContentP(i)->addContent(AMF::Object(
"length", ((double)M.tracks[*it].lastms / 1000) * ((double)M.tracks[*it].fpks / 1000.0), "length", ((double)M.tracks[*it].lastms / 1000) * ((double)M.tracks[*it].fpks / 1000.0), AMF::AMF0_NUMBER));
AMF::AMF0_NUMBER));
trinfo.getContentP(i)->addContent( trinfo.getContentP(i)->addContent(
AMF::Object("timescale", ((double)M.tracks[*it].fpks / 1000.0), AMF::AMF0_NUMBER)); AMF::Object("timescale", ((double)M.tracks[*it].fpks / 1000.0), AMF::AMF0_NUMBER));
trinfo.getContentP(i)->addContent(AMF::Object("sampledescription", AMF::AMF0_STRICT_ARRAY)); trinfo.getContentP(i)->addContent(AMF::Object("sampledescription", AMF::AMF0_STRICT_ARRAY));
amfdata.getContentP(1)->addContent(AMF::Object("hasVideo", 1, AMF::AMF0_BOOL)); amfdata.getContentP(1)->addContent(AMF::Object("hasVideo", 1, AMF::AMF0_BOOL));
if (M.tracks[*it].codec == "H264"){ if (M.tracks[*it].codec == "H264"){
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 7, AMF::AMF0_NUMBER)); amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 7, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->getContentP(2)->addContent( trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "avc1"));
AMF::Object("sampletype", (std::string) "avc1"));
} }
if (M.tracks[*it].codec == "ScreenVideo2"){ if (M.tracks[*it].codec == "ScreenVideo2"){
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 6, AMF::AMF0_NUMBER)); amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 6, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->getContentP(2)->addContent( trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "sv2"));
AMF::Object("sampletype", (std::string) "sv2"));
} }
if (M.tracks[*it].codec == "VP6Alpha"){ if (M.tracks[*it].codec == "VP6Alpha"){
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 5, AMF::AMF0_NUMBER)); amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 5, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->getContentP(2)->addContent( trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "vp6a"));
AMF::Object("sampletype", (std::string) "vp6a"));
} }
if (M.tracks[*it].codec == "VP6"){ if (M.tracks[*it].codec == "VP6"){
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 4, AMF::AMF0_NUMBER)); amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 4, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->getContentP(2)->addContent( trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "vp6"));
AMF::Object("sampletype", (std::string) "vp6"));
} }
if (M.tracks[*it].codec == "ScreenVideo1"){ if (M.tracks[*it].codec == "ScreenVideo1"){
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 3, AMF::AMF0_NUMBER)); amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 3, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->getContentP(2)->addContent( trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "sv1"));
AMF::Object("sampletype", (std::string) "sv1"));
} }
if (M.tracks[*it].codec == "H263"){ if (M.tracks[*it].codec == "H263"){
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 2, AMF::AMF0_NUMBER)); amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 2, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->getContentP(2)->addContent( trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "h263"));
AMF::Object("sampletype", (std::string) "h263"));
} }
if (M.tracks[*it].codec == "JPEG"){ if (M.tracks[*it].codec == "JPEG"){
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 1, AMF::AMF0_NUMBER)); amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 1, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->getContentP(2)->addContent( trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "jpeg"));
AMF::Object("sampletype", (std::string) "jpeg"));
} }
amfdata.getContentP(1)->addContent( amfdata.getContentP(1)->addContent(AMF::Object("width", M.tracks[*it].width, AMF::AMF0_NUMBER));
AMF::Object("width", M.tracks[*it].width, AMF::AMF0_NUMBER)); amfdata.getContentP(1)->addContent(AMF::Object("height", M.tracks[*it].height, AMF::AMF0_NUMBER));
amfdata.getContentP(1)->addContent(
AMF::Object("height", M.tracks[*it].height, AMF::AMF0_NUMBER));
amfdata.getContentP(1)->addContent( amfdata.getContentP(1)->addContent(
AMF::Object("videoframerate", (double)M.tracks[*it].fpks / 1000.0, AMF::AMF0_NUMBER)); AMF::Object("videoframerate", (double)M.tracks[*it].fpks / 1000.0, AMF::AMF0_NUMBER));
amfdata.getContentP(1)->addContent( amfdata.getContentP(1)->addContent(
@ -557,30 +546,23 @@ bool FLV::Tag::DTSCMetaInit(DTSC::Meta &M, std::set<long unsigned int> &selTrack
} }
if (M.tracks[*it].type == "audio"){ if (M.tracks[*it].type == "audio"){
trinfo.addContent(AMF::Object("", AMF::AMF0_OBJECT)); trinfo.addContent(AMF::Object("", AMF::AMF0_OBJECT));
trinfo.getContentP(i)->addContent( trinfo.getContentP(i)->addContent(AMF::Object(
AMF::Object("length", ((double)M.tracks[*it].lastms) * ((double)M.tracks[*it].rate), "length", ((double)M.tracks[*it].lastms) * ((double)M.tracks[*it].rate), AMF::AMF0_NUMBER));
AMF::AMF0_NUMBER)); trinfo.getContentP(i)->addContent(AMF::Object("timescale", M.tracks[*it].rate, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->addContent(
AMF::Object("timescale", M.tracks[*it].rate, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->addContent(AMF::Object("sampledescription", AMF::AMF0_STRICT_ARRAY)); trinfo.getContentP(i)->addContent(AMF::Object("sampledescription", AMF::AMF0_STRICT_ARRAY));
amfdata.getContentP(1)->addContent(AMF::Object("hasAudio", 1, AMF::AMF0_BOOL)); amfdata.getContentP(1)->addContent(AMF::Object("hasAudio", 1, AMF::AMF0_BOOL));
amfdata.getContentP(1)->addContent(AMF::Object("audiodelay", 0.0, AMF::AMF0_NUMBER)); amfdata.getContentP(1)->addContent(AMF::Object("audiodelay", 0.0, AMF::AMF0_NUMBER));
if (M.tracks[*it].codec == "AAC"){ if (M.tracks[*it].codec == "AAC"){
amfdata.getContentP(1)->addContent(AMF::Object("audiocodecid", (std::string) "mp4a")); amfdata.getContentP(1)->addContent(AMF::Object("audiocodecid", (std::string) "mp4a"));
trinfo.getContentP(i)->getContentP(2)->addContent( trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "mp4a"));
AMF::Object("sampletype", (std::string) "mp4a"));
} }
if (M.tracks[*it].codec == "MP3"){ if (M.tracks[*it].codec == "MP3"){
amfdata.getContentP(1)->addContent(AMF::Object("audiocodecid", (std::string) "mp3")); amfdata.getContentP(1)->addContent(AMF::Object("audiocodecid", (std::string) "mp3"));
trinfo.getContentP(i)->getContentP(2)->addContent( trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "mp3"));
AMF::Object("sampletype", (std::string) "mp3"));
} }
amfdata.getContentP(1)->addContent( amfdata.getContentP(1)->addContent(AMF::Object("audiochannels", M.tracks[*it].channels, AMF::AMF0_NUMBER));
AMF::Object("audiochannels", M.tracks[*it].channels, AMF::AMF0_NUMBER)); amfdata.getContentP(1)->addContent(AMF::Object("audiosamplerate", M.tracks[*it].rate, AMF::AMF0_NUMBER));
amfdata.getContentP(1)->addContent( amfdata.getContentP(1)->addContent(AMF::Object("audiosamplesize", M.tracks[*it].size, AMF::AMF0_NUMBER));
AMF::Object("audiosamplerate", M.tracks[*it].rate, AMF::AMF0_NUMBER));
amfdata.getContentP(1)->addContent(
AMF::Object("audiosamplesize", M.tracks[*it].size, AMF::AMF0_NUMBER));
amfdata.getContentP(1)->addContent( amfdata.getContentP(1)->addContent(
AMF::Object("audiodatarate", (double)M.tracks[*it].bps / 128.0, AMF::AMF0_NUMBER)); AMF::Object("audiodatarate", (double)M.tracks[*it].bps / 128.0, AMF::AMF0_NUMBER));
++i; ++i;
@ -836,20 +818,17 @@ void FLV::Tag::toMeta(DTSC::Meta &metadata, AMF::Object &amf_storage, unsigned i
if (data[0] == 0x12){ if (data[0] == 0x12){
AMF::Object meta_in = AMF::parse((unsigned char *)data + 11, len - 15); AMF::Object meta_in = AMF::parse((unsigned char *)data + 11, len - 15);
AMF::Object *tmp = 0; AMF::Object *tmp = 0;
if (meta_in.getContentP(1) && meta_in.getContentP(0) && if (meta_in.getContentP(1) && meta_in.getContentP(0) && (meta_in.getContentP(0)->StrValue() == "onMetaData")){
(meta_in.getContentP(0)->StrValue() == "onMetaData")){
tmp = meta_in.getContentP(1); tmp = meta_in.getContentP(1);
}else{ }else{
if (meta_in.getContentP(2) && meta_in.getContentP(1) && if (meta_in.getContentP(2) && meta_in.getContentP(1) && (meta_in.getContentP(1)->StrValue() == "onMetaData")){
(meta_in.getContentP(1)->StrValue() == "onMetaData")){
tmp = meta_in.getContentP(2); tmp = meta_in.getContentP(2);
} }
} }
if (tmp){amf_storage = *tmp;} if (tmp){amf_storage = *tmp;}
return; return;
} }
if (data[0] == 0x08 && if (data[0] == 0x08 && (metadata.tracks[reTrack].codec == "" || metadata.tracks[reTrack].codec != getAudioCodec() ||
(metadata.tracks[reTrack].codec == "" || metadata.tracks[reTrack].codec != getAudioCodec() ||
(needsInitData() && isInitData()))){ (needsInitData() && isInitData()))){
char audiodata = data[11]; char audiodata = data[11];
metadata.tracks[reTrack].trackID = reTrack; metadata.tracks[reTrack].trackID = reTrack;
@ -863,16 +842,14 @@ void FLV::Tag::toMeta(DTSC::Meta &metadata, AMF::Object &amf_storage, unsigned i
case 0xC: metadata.tracks[reTrack].rate = 44100; break; case 0xC: metadata.tracks[reTrack].rate = 44100; break;
} }
if (amf_storage.getContentP("audiosamplerate")){ if (amf_storage.getContentP("audiosamplerate")){
metadata.tracks[reTrack].rate = metadata.tracks[reTrack].rate = (long long int)amf_storage.getContentP("audiosamplerate")->NumValue();
(long long int)amf_storage.getContentP("audiosamplerate")->NumValue();
} }
switch (audiodata & 0x02){ switch (audiodata & 0x02){
case 0x0: metadata.tracks[reTrack].size = 8; break; case 0x0: metadata.tracks[reTrack].size = 8; break;
case 0x2: metadata.tracks[reTrack].size = 16; break; case 0x2: metadata.tracks[reTrack].size = 16; break;
} }
if (amf_storage.getContentP("audiosamplesize")){ if (amf_storage.getContentP("audiosamplesize")){
metadata.tracks[reTrack].size = metadata.tracks[reTrack].size = (long long int)amf_storage.getContentP("audiosamplesize")->NumValue();
(long long int)amf_storage.getContentP("audiosamplesize")->NumValue();
} }
switch (audiodata & 0x01){ switch (audiodata & 0x01){
case 0x0: metadata.tracks[reTrack].channels = 1; break; case 0x0: metadata.tracks[reTrack].channels = 1; break;
@ -898,8 +875,7 @@ void FLV::Tag::toMeta(DTSC::Meta &metadata, AMF::Object &amf_storage, unsigned i
} }
} }
if (data[0] == 0x09 && if (data[0] == 0x09 && ((needsInitData() && isInitData()) || !metadata.tracks[reTrack].codec.size())){
((needsInitData() && isInitData()) || !metadata.tracks[reTrack].codec.size())){
char videodata = data[11]; char videodata = data[11];
metadata.tracks[reTrack].codec = getVideoCodec(); metadata.tracks[reTrack].codec = getVideoCodec();
metadata.tracks[reTrack].type = "video"; metadata.tracks[reTrack].type = "video";
@ -908,8 +884,7 @@ void FLV::Tag::toMeta(DTSC::Meta &metadata, AMF::Object &amf_storage, unsigned i
metadata.tracks[reTrack].width = (long long int)amf_storage.getContentP("width")->NumValue(); metadata.tracks[reTrack].width = (long long int)amf_storage.getContentP("width")->NumValue();
} }
if (amf_storage.getContentP("height")){ if (amf_storage.getContentP("height")){
metadata.tracks[reTrack].height = metadata.tracks[reTrack].height = (long long int)amf_storage.getContentP("height")->NumValue();
(long long int)amf_storage.getContentP("height")->NumValue();
} }
if (!metadata.tracks[reTrack].fpks && amf_storage.getContentP("videoframerate")){ if (!metadata.tracks[reTrack].fpks && amf_storage.getContentP("videoframerate")){
if (amf_storage.getContentP("videoframerate")->NumValue()){ if (amf_storage.getContentP("videoframerate")->NumValue()){
@ -960,4 +935,3 @@ bool FLV::Tag::checkBufferSize(){
} }
return true; return true;
} }

View file

@ -18,8 +18,7 @@ namespace FLV{
extern char Header[13]; ///< Holds the last FLV header parsed. extern char Header[13]; ///< Holds the last FLV header parsed.
extern bool Parse_Error; ///< This variable is set to true if a problem is encountered while extern bool Parse_Error; ///< This variable is set to true if a problem is encountered while
///< parsing the FLV. ///< parsing the FLV.
extern std::string extern std::string Error_Str; ///< This variable is set if a problem is encountered while parsing the FLV.
Error_Str; ///< This variable is set if a problem is encountered while parsing the FLV.
// functions // functions
bool check_header(char *header); ///< Checks a FLV Header for validness. bool check_header(char *header); ///< Checks a FLV Header for validness.
@ -45,8 +44,7 @@ namespace FLV{
void offset(int64_t o); void offset(int64_t o);
Tag(); ///< Constructor for a new, empty, tag. Tag(); ///< Constructor for a new, empty, tag.
Tag(const Tag &O); ///< Copy constructor, copies the contents of an existing tag. Tag(const Tag &O); ///< Copy constructor, copies the contents of an existing tag.
Tag & Tag &operator=(const Tag &O); ///< Assignment operator - works exactly like the copy constructor.
operator=(const Tag &O); ///< Assignment operator - works exactly like the copy constructor.
Tag(const RTMPStream::Chunk &O); ///< Copy constructor from a RTMP chunk. Tag(const RTMPStream::Chunk &O); ///< Copy constructor from a RTMP chunk.
~Tag(); ///< Generic destructor. ~Tag(); ///< Generic destructor.
// loader functions // loader functions
@ -76,4 +74,3 @@ namespace FLV{
// Tag // Tag
}// namespace FLV }// namespace FLV

View file

@ -1,10 +1,10 @@
#ifndef _GNU_SOURCE #ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif #endif
#include "h264.h"
#include "bitfields.h" #include "bitfields.h"
#include "bitstream.h" #include "bitstream.h"
#include "defines.h" #include "defines.h"
#include "h264.h"
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>
#include <iomanip> #include <iomanip>
@ -93,8 +93,7 @@ namespace h264{
// Fill the bitstream // Fill the bitstream
Utils::bitstream bs; Utils::bitstream bs;
for (size_t i = 1; i < dataLen; i++){ for (size_t i = 1; i < dataLen; i++){
if (i + 2 < dataLen && if (i + 2 < dataLen && (memcmp(data + i, "\000\000\003", 3) == 0)){// Emulation prevention bytes
(memcmp(data + i, "\000\000\003", 3) == 0)){// Emulation prevention bytes
// Yes, we increase i here // Yes, we increase i here
bs.append(data + i, 2); bs.append(data + i, 2);
i += 2; i += 2;
@ -111,8 +110,7 @@ namespace h264{
result.level = bs.get(8); result.level = bs.get(8);
bs.getUExpGolomb(); bs.getUExpGolomb();
if (profileIdc == 100 || profileIdc == 110 || profileIdc == 122 || profileIdc == 244 || if (profileIdc == 100 || profileIdc == 110 || profileIdc == 122 || profileIdc == 244 ||
profileIdc == 44 || profileIdc == 83 || profileIdc == 86 || profileIdc == 118 || profileIdc == 44 || profileIdc == 83 || profileIdc == 86 || profileIdc == 118 || profileIdc == 128){
profileIdc == 128){
// chroma format idc // chroma format idc
char chromaFormatIdc = bs.getUExpGolomb(); char chromaFormatIdc = bs.getUExpGolomb();
if (chromaFormatIdc == 3){result.sep_col_plane = (bs.get(1) == 1);} if (chromaFormatIdc == 3){result.sep_col_plane = (bs.get(1) == 1);}
@ -260,7 +258,6 @@ namespace h264{
result.width = ((result.width * sar_width) / sar_height); result.width = ((result.width * sar_width) / sar_height);
}else{ }else{
result.height = ((result.height * sar_height) / sar_width); result.height = ((result.height * sar_height) / sar_width);
} }
} }
return result; return result;
@ -351,8 +348,7 @@ namespace h264{
bitDepthChromaMinus8 = bs.getUExpGolomb(); bitDepthChromaMinus8 = bs.getUExpGolomb();
derived_bitDepth_C = 8 + bitDepthChromaMinus8; derived_bitDepth_C = 8 + bitDepthChromaMinus8;
derived_qpBdOffset_C = 6 * bitDepthChromaMinus8; derived_qpBdOffset_C = 6 * bitDepthChromaMinus8;
derived_rawMbBits = derived_rawMbBits = 256 * derived_bitDepth_Y + 2 * derived_mbWidthC * derived_mbHeightC * derived_bitDepth_C;
256 * derived_bitDepth_Y + 2 * derived_mbWidthC * derived_mbHeightC * derived_bitDepth_C;
qpprimeYZeroTransformBypassFlag = bs.get(1); qpprimeYZeroTransformBypassFlag = bs.get(1);
seqScalingMatrixPresentFlag = bs.get(1); seqScalingMatrixPresentFlag = bs.get(1);
if (seqScalingMatrixPresentFlag){ if (seqScalingMatrixPresentFlag){
@ -361,8 +357,7 @@ namespace h264{
derived_scalingList4x4Amount = 6; derived_scalingList4x4Amount = 6;
scalingList4x4 = (uint64_t **)malloc(derived_scalingList4x4Amount * sizeof(uint64_t *)); scalingList4x4 = (uint64_t **)malloc(derived_scalingList4x4Amount * sizeof(uint64_t *));
useDefaultScalingMatrix4x4Flag = useDefaultScalingMatrix4x4Flag = (bool *)malloc(derived_scalingList4x4Amount * sizeof(bool));
(bool *)malloc(derived_scalingList4x4Amount * sizeof(bool));
for (int i = 0; i < derived_scalingList4x4Amount; i++){ for (int i = 0; i < derived_scalingList4x4Amount; i++){
scalingList4x4[i] = NULL; scalingList4x4[i] = NULL;
useDefaultScalingMatrix4x4Flag[i] = false; useDefaultScalingMatrix4x4Flag[i] = false;
@ -370,8 +365,7 @@ namespace h264{
derived_scalingList8x8Amount = derived_scalingListSize - 6; derived_scalingList8x8Amount = derived_scalingListSize - 6;
scalingList8x8 = (uint64_t **)malloc(derived_scalingList8x8Amount * sizeof(uint64_t *)); scalingList8x8 = (uint64_t **)malloc(derived_scalingList8x8Amount * sizeof(uint64_t *));
useDefaultScalingMatrix8x8Flag = useDefaultScalingMatrix8x8Flag = (bool *)malloc(derived_scalingList8x8Amount * sizeof(bool));
(bool *)malloc(derived_scalingList8x8Amount * sizeof(bool));
for (int i = 0; i < derived_scalingList8x8Amount; i++){ for (int i = 0; i < derived_scalingList8x8Amount; i++){
scalingList8x8[i] = NULL; scalingList8x8[i] = NULL;
useDefaultScalingMatrix8x8Flag[i] = false; useDefaultScalingMatrix8x8Flag[i] = false;
@ -472,8 +466,7 @@ namespace h264{
out << " -> RawMbBits: " << derived_rawMbBits << std::endl; out << " -> RawMbBits: " << derived_rawMbBits << std::endl;
out << " qpprime_y_zero-transform_bypass_flag: " << (qpprimeYZeroTransformBypassFlag ? 1 : 0) out << " qpprime_y_zero-transform_bypass_flag: " << (qpprimeYZeroTransformBypassFlag ? 1 : 0)
<< std::endl; << std::endl;
out << " seq_scaling_matrix_present_flag: " << (seqScalingMatrixPresentFlag ? 1 : 0) out << " seq_scaling_matrix_present_flag: " << (seqScalingMatrixPresentFlag ? 1 : 0) << std::endl;
<< std::endl;
if (seqScalingMatrixPresentFlag){ if (seqScalingMatrixPresentFlag){
for (int i = 0; i < derived_scalingListSize; i++){ for (int i = 0; i < derived_scalingListSize; i++){
out << " seq_scaling_list_present_flag[" << i out << " seq_scaling_list_present_flag[" << i
@ -503,16 +496,14 @@ namespace h264{
out << " log2_max_frame_num_minus4: " << log2MaxFrameNumMinus4 out << " log2_max_frame_num_minus4: " << log2MaxFrameNumMinus4
<< (log2MaxFrameNumMinus4 >= 13 ? " INVALID" : "") << std::endl; << (log2MaxFrameNumMinus4 >= 13 ? " INVALID" : "") << std::endl;
out << " -> MaxFrameNum: " << derived_maxFrameNum << std::endl; out << " -> MaxFrameNum: " << derived_maxFrameNum << std::endl;
out << " pic_order_cnt_type: " << picOrderCntType << (picOrderCntType >= 3 ? " INVALID" : "") out << " pic_order_cnt_type: " << picOrderCntType << (picOrderCntType >= 3 ? " INVALID" : "") << std::endl;
<< std::endl;
if (!picOrderCntType){ if (!picOrderCntType){
out << " log2_max_pic_order_cnt_lsb_minus4: " << log2MaxPicOrderCntLsbMinus4 out << " log2_max_pic_order_cnt_lsb_minus4: " << log2MaxPicOrderCntLsbMinus4
<< (log2MaxPicOrderCntLsbMinus4 >= 13 ? " INVALID" : "") << std::endl; << (log2MaxPicOrderCntLsbMinus4 >= 13 ? " INVALID" : "") << std::endl;
out << " -> MaxPicOrderCntLsb: " << derived_maxPicOrderCntLsb << std::endl; out << " -> MaxPicOrderCntLsb: " << derived_maxPicOrderCntLsb << std::endl;
} }
out << " max_num_ref_frames: " << maxNumRefFrames << std::endl; out << " max_num_ref_frames: " << maxNumRefFrames << std::endl;
out << " gaps_in_frame_num_value_allowed_flag: " << (gapsInFrameNumValueAllowedFlag ? 1 : 0) out << " gaps_in_frame_num_value_allowed_flag: " << (gapsInFrameNumValueAllowedFlag ? 1 : 0) << std::endl;
<< std::endl;
out << " pic_width_in_mbs_minus_1: " << picWidthInMbsMinus1 << std::endl; out << " pic_width_in_mbs_minus_1: " << picWidthInMbsMinus1 << std::endl;
out << " -> PicWidthInMbs: " << derived_picWidthInMbs << std::endl; out << " -> PicWidthInMbs: " << derived_picWidthInMbs << std::endl;
out << " -> PicWidthInSamples_L: " << derived_picWidthInSamples_L << std::endl; out << " -> PicWidthInSamples_L: " << derived_picWidthInSamples_L << std::endl;
@ -725,17 +716,14 @@ namespace h264{
<< (bottomFieldPicOrderInFramePresentFlag ? 1 : 0) << std::endl; << (bottomFieldPicOrderInFramePresentFlag ? 1 : 0) << std::endl;
out << " num_slice_groups_minus1: " << numSliceGroupsMinus1 << std::endl; out << " num_slice_groups_minus1: " << numSliceGroupsMinus1 << std::endl;
if (numSliceGroupsMinus1 > 0){return;} if (numSliceGroupsMinus1 > 0){return;}
out << " num_ref_idx_10_default_active_minus1: " << numrefIdx10DefaultActiveMinus1 out << " num_ref_idx_10_default_active_minus1: " << numrefIdx10DefaultActiveMinus1 << std::endl;
<< std::endl; out << " num_ref_idx_11_default_active_minus1: " << numrefIdx11DefaultActiveMinus1 << std::endl;
out << " num_ref_idx_11_default_active_minus1: " << numrefIdx11DefaultActiveMinus1
<< std::endl;
out << " weighted_pred_flag: " << (weightedPredFlag ? 1 : 0) << std::endl; out << " weighted_pred_flag: " << (weightedPredFlag ? 1 : 0) << std::endl;
out << " weighted_bipred_idc: " << (uint32_t)weightedBipredIdc << std::endl; out << " weighted_bipred_idc: " << (uint32_t)weightedBipredIdc << std::endl;
out << " pic_init_qp_minus26: " << picInitQpMinus26 << std::endl; out << " pic_init_qp_minus26: " << picInitQpMinus26 << std::endl;
out << " pic_init_qs_minus26: " << picInitQsMinus26 << std::endl; out << " pic_init_qs_minus26: " << picInitQsMinus26 << std::endl;
out << " chroma_qp_index_offset: " << chromaQpIndexOffset << std::endl; out << " chroma_qp_index_offset: " << chromaQpIndexOffset << std::endl;
out << " deblocking_filter_control_present_flag: " << deblockingFilterControlPresentFlag out << " deblocking_filter_control_present_flag: " << deblockingFilterControlPresentFlag << std::endl;
<< std::endl;
out << " constrained_intra_pred_flag: " << constrainedIntraPredFlag << std::endl; out << " constrained_intra_pred_flag: " << constrainedIntraPredFlag << std::endl;
out << " redundant_pic_cnt_present_flag: " << redundantPicCntPresentFlag << std::endl; out << " redundant_pic_cnt_present_flag: " << redundantPicCntPresentFlag << std::endl;
if (status_moreRBSP){ if (status_moreRBSP){
@ -848,8 +836,7 @@ namespace h264{
payload[1 + byteOffset] |= (0x08 >> bitOffset); payload[1 + byteOffset] |= (0x08 >> bitOffset);
payload[2 + byteOffset] &= secondBitmask; payload[2 + byteOffset] &= secondBitmask;
payload[2 + byteOffset] |= (0x08 << (8 - bitOffset)); payload[2 + byteOffset] |= (0x08 << (8 - bitOffset));
INFO_MSG("Translated %.2X to %.2X %.2X", toCopy, payload[1 + byteOffset], INFO_MSG("Translated %.2X to %.2X %.2X", toCopy, payload[1 + byteOffset], payload[2 + byteOffset]);
payload[2 + byteOffset]);
} }
void codedSliceUnit::toPrettyString(std::ostream &out){ void codedSliceUnit::toPrettyString(std::ostream &out){
@ -922,12 +909,10 @@ namespace h264{
uuid.str("x264 encoder configuration"); uuid.str("x264 encoder configuration");
} }
out << " UUID: " << uuid.str() << std::endl; out << " UUID: " << uuid.str() << std::endl;
out << " Payload: " << std::string(payload.data() + payloadOffset + 16, payloadSize - 17) out << " Payload: " << std::string(payload.data() + payloadOffset + 16, payloadSize - 17) << std::endl;
<< std::endl;
}break; }break;
default: default:
out << " Message of type " << payloadType << ", " << payloadSize << " bytes long" out << " Message of type " << payloadType << ", " << payloadSize << " bytes long" << std::endl;
<< std::endl;
} }
} }
@ -1149,8 +1134,7 @@ namespace h264{
out << std::string(indent + 2, ' ') out << std::string(indent + 2, ' ')
<< "aspect_ratio_info_present_flag: " << aspectRatioInfoPresentFlag << std::endl; << "aspect_ratio_info_present_flag: " << aspectRatioInfoPresentFlag << std::endl;
if (aspectRatioInfoPresentFlag){ if (aspectRatioInfoPresentFlag){
out << std::string(indent + 2, ' ') << "aspect_ratio_idc: " << (int32_t)aspectRatioIdc out << std::string(indent + 2, ' ') << "aspect_ratio_idc: " << (int32_t)aspectRatioIdc << std::endl;
<< std::endl;
if (aspectRatioIdc == 255){ if (aspectRatioIdc == 255){
out << std::string(indent + 2, ' ') << "sar_width: " << sarWidth << std::endl; out << std::string(indent + 2, ' ') << "sar_width: " << sarWidth << std::endl;
out << std::string(indent + 2, ' ') << "sar_height: " << sarHeight << std::endl; out << std::string(indent + 2, ' ') << "sar_height: " << sarHeight << std::endl;
@ -1166,16 +1150,14 @@ namespace h264{
<< "video_signal_type_present_flag: " << videoSignalTypePresentFlag << std::endl; << "video_signal_type_present_flag: " << videoSignalTypePresentFlag << std::endl;
if (videoSignalTypePresentFlag){ if (videoSignalTypePresentFlag){
out << std::string(indent + 2, ' ') << "video_format" << videoFormat << std::endl; out << std::string(indent + 2, ' ') << "video_format" << videoFormat << std::endl;
out << std::string(indent + 2, ' ') << "video_full_range_flag" << videoFullRangeFlag out << std::string(indent + 2, ' ') << "video_full_range_flag" << videoFullRangeFlag << std::endl;
<< std::endl;
out << std::string(indent + 2, ' ') << "colour_description_present_flag" out << std::string(indent + 2, ' ') << "colour_description_present_flag"
<< colourDescriptionPresentFlag << std::endl; << colourDescriptionPresentFlag << std::endl;
if (colourDescriptionPresentFlag){ if (colourDescriptionPresentFlag){
out << std::string(indent + 2, ' ') << "colour_primaries" << colourPrimaries << std::endl; out << std::string(indent + 2, ' ') << "colour_primaries" << colourPrimaries << std::endl;
out << std::string(indent + 2, ' ') << "transfer_characteristics" << transferCharacteristics out << std::string(indent + 2, ' ') << "transfer_characteristics" << transferCharacteristics
<< std::endl; << std::endl;
out << std::string(indent + 2, ' ') << "matrix_coefficients" << matrixCoefficients out << std::string(indent + 2, ' ') << "matrix_coefficients" << matrixCoefficients << std::endl;
<< std::endl;
} }
} }
out << std::string(indent + 2, ' ') out << std::string(indent + 2, ' ')
@ -1186,13 +1168,11 @@ namespace h264{
out << std::string(indent + 2, ' ') << "chroma_sample_loc_type_bottom_field" out << std::string(indent + 2, ' ') << "chroma_sample_loc_type_bottom_field"
<< chromaSampleLocTypeBottomField << std::endl; << chromaSampleLocTypeBottomField << std::endl;
} }
out << std::string(indent + 2, ' ') << "timing_info_present_flag: " << timingInfoPresentFlag out << std::string(indent + 2, ' ') << "timing_info_present_flag: " << timingInfoPresentFlag << std::endl;
<< std::endl;
if (timingInfoPresentFlag){ if (timingInfoPresentFlag){
out << std::string(indent + 2, ' ') << "num_units_in_tick: " << numUnitsInTick << std::endl; out << std::string(indent + 2, ' ') << "num_units_in_tick: " << numUnitsInTick << std::endl;
out << std::string(indent + 2, ' ') << "time_scale: " << timeScale << std::endl; out << std::string(indent + 2, ' ') << "time_scale: " << timeScale << std::endl;
out << std::string(indent + 2, ' ') << "fixed_frame_rate_flag: " << fixedFrameRateFlag out << std::string(indent + 2, ' ') << "fixed_frame_rate_flag: " << fixedFrameRateFlag << std::endl;
<< std::endl;
} }
out << std::string(indent + 2, ' ') out << std::string(indent + 2, ' ')
<< "nal_hrd_parameters_present_flag: " << nalHrdParametersPresentFlag << std::endl; << "nal_hrd_parameters_present_flag: " << nalHrdParametersPresentFlag << std::endl;
@ -1202,27 +1182,20 @@ namespace h264{
if (nalHrdParametersPresentFlag || vclHrdParametersPresentFlag){ if (nalHrdParametersPresentFlag || vclHrdParametersPresentFlag){
out << std::string(indent + 2, ' ') << "low_delay_hrd_flag: " << lowDelayHrdFlag << std::endl; out << std::string(indent + 2, ' ') << "low_delay_hrd_flag: " << lowDelayHrdFlag << std::endl;
} }
out << std::string(indent + 2, ' ') << "pic_struct_present_flag: " << picStructPresentFlag out << std::string(indent + 2, ' ') << "pic_struct_present_flag: " << picStructPresentFlag << std::endl;
<< std::endl;
out << std::string(indent + 2, ' ') << "bitstream_restiction_flag: " << bitstreamRestrictionFlag out << std::string(indent + 2, ' ') << "bitstream_restiction_flag: " << bitstreamRestrictionFlag
<< std::endl; << std::endl;
if (bitstreamRestrictionFlag){ if (bitstreamRestrictionFlag){
out << std::string(indent + 2, ' ') out << std::string(indent + 2, ' ')
<< "motion_vectors_over_pic_boundaries_flag: " << motionVectorsOverPicBoundariesFlag << "motion_vectors_over_pic_boundaries_flag: " << motionVectorsOverPicBoundariesFlag << std::endl;
<< std::endl; out << std::string(indent + 2, ' ') << "max_bytes_per_pic_denom: " << maxBytesPerPicDenom << std::endl;
out << std::string(indent + 2, ' ') << "max_bytes_per_pic_denom: " << maxBytesPerPicDenom out << std::string(indent + 2, ' ') << "max_bits_per_mb_denom: " << maxBitsPerMbDenom << std::endl;
<< std::endl;
out << std::string(indent + 2, ' ') << "max_bits_per_mb_denom: " << maxBitsPerMbDenom
<< std::endl;
out << std::string(indent + 2, ' ') out << std::string(indent + 2, ' ')
<< "log2_max_mv_length_horizontal: " << log2MaxMvLengthHorizontal << std::endl; << "log2_max_mv_length_horizontal: " << log2MaxMvLengthHorizontal << std::endl;
out << std::string(indent + 2, ' ') out << std::string(indent + 2, ' ')
<< "log2_max_mv_length_vertical: " << log2MaxMvLengthVertical << std::endl; << "log2_max_mv_length_vertical: " << log2MaxMvLengthVertical << std::endl;
out << std::string(indent + 2, ' ') << "num_reorder_frames: " << numReorderFrames out << std::string(indent + 2, ' ') << "num_reorder_frames: " << numReorderFrames << std::endl;
<< std::endl; out << std::string(indent + 2, ' ') << "max_dec_frame_buffering: " << maxDecFrameBuffering << std::endl;
out << std::string(indent + 2, ' ') << "max_dec_frame_buffering: " << maxDecFrameBuffering
<< std::endl;
} }
} }
}// namespace h264 }// namespace h264

View file

@ -303,4 +303,3 @@ namespace h264{
nalUnit *nalFactory(FILE *in, bool annexb = true); nalUnit *nalFactory(FILE *in, bool annexb = true);
nalUnit *nalFactory(const char *data, size_t len, size_t &offset, bool annexb = true); nalUnit *nalFactory(const char *data, size_t len, size_t &offset, bool annexb = true);
}// namespace h264 }// namespace h264

View file

@ -1,6 +1,6 @@
#include "h265.h"
#include "bitfields.h" #include "bitfields.h"
#include "defines.h" #include "defines.h"
#include "h265.h"
namespace h265{ namespace h265{
const char *typeToStr(uint8_t type){ const char *typeToStr(uint8_t type){
@ -64,8 +64,7 @@ namespace h265{
hvccBox.setPayload(hvccData); hvccBox.setPayload(hvccData);
std::deque<MP4::HVCCArrayEntry> arrays = hvccBox.getArrays(); std::deque<MP4::HVCCArrayEntry> arrays = hvccBox.getArrays();
for (std::deque<MP4::HVCCArrayEntry>::iterator it = arrays.begin(); it != arrays.end(); it++){ for (std::deque<MP4::HVCCArrayEntry>::iterator it = arrays.begin(); it != arrays.end(); it++){
for (std::deque<std::string>::iterator nalIt = it->nalUnits.begin(); for (std::deque<std::string>::iterator nalIt = it->nalUnits.begin(); nalIt != it->nalUnits.end(); nalIt++){
nalIt != it->nalUnits.end(); nalIt++){
nalUnits[it->nalUnitType].insert(*nalIt); nalUnits[it->nalUnitType].insert(*nalIt);
} }
} }
@ -156,8 +155,7 @@ namespace h265{
metaInfo initData::getMeta(){ metaInfo initData::getMeta(){
metaInfo res; metaInfo res;
if (!nalUnits.count(33)){ if (!nalUnits.count(33)){return res;}
return res;}
spsUnit sps(*nalUnits[33].begin()); spsUnit sps(*nalUnits[33].begin());
sps.getMeta(res); sps.getMeta(res);
return res; return res;
@ -195,8 +193,7 @@ namespace h265{
} }
} }
std::string printProfileTierLevel(Utils::bitstream &bs, unsigned int maxSubLayersMinus1, std::string printProfileTierLevel(Utils::bitstream &bs, unsigned int maxSubLayersMinus1, size_t indent){
size_t indent){
std::stringstream r; std::stringstream r;
r << std::string(indent, ' ') << "general_profile_space: " << bs.get(2) << std::endl; r << std::string(indent, ' ') << "general_profile_space: " << bs.get(2) << std::endl;
r << std::string(indent, ' ') << "general_tier_flag: " << bs.get(1) << std::endl; r << std::string(indent, ' ') << "general_tier_flag: " << bs.get(1) << std::endl;
@ -205,10 +202,8 @@ namespace h265{
<< bs.get(32) << std::dec << std::endl; << bs.get(32) << std::dec << std::endl;
r << std::string(indent, ' ') << "general_progressive_source_flag: " << bs.get(1) << std::endl; r << std::string(indent, ' ') << "general_progressive_source_flag: " << bs.get(1) << std::endl;
r << std::string(indent, ' ') << "general_interlaced_source_flag: " << bs.get(1) << std::endl; r << std::string(indent, ' ') << "general_interlaced_source_flag: " << bs.get(1) << std::endl;
r << std::string(indent, ' ') << "general_non_packed_constraint_flag: " << bs.get(1) r << std::string(indent, ' ') << "general_non_packed_constraint_flag: " << bs.get(1) << std::endl;
<< std::endl; r << std::string(indent, ' ') << "general_frame_only_constraint_flag: " << bs.get(1) << std::endl;
r << std::string(indent, ' ') << "general_frame_only_constraint_flag: " << bs.get(1)
<< std::endl;
r << std::string(indent, ' ') << "general_reserved_zero_44bits: " << bs.get(44) << std::endl; r << std::string(indent, ' ') << "general_reserved_zero_44bits: " << bs.get(44) << std::endl;
r << std::string(indent, ' ') << "general_level_idc: " << bs.get(8) << std::endl; r << std::string(indent, ' ') << "general_level_idc: " << bs.get(8) << std::endl;
std::deque<bool> profilePresent; std::deque<bool> profilePresent;
@ -226,8 +221,7 @@ namespace h265{
if (maxSubLayersMinus1){ if (maxSubLayersMinus1){
for (int i = maxSubLayersMinus1; i < 8; i++){ for (int i = maxSubLayersMinus1; i < 8; i++){
r << std::string(indent + 1, ' ') << "reserved_zero_2_bits[" << i << "]: " << bs.get(2) r << std::string(indent + 1, ' ') << "reserved_zero_2_bits[" << i << "]: " << bs.get(2) << std::endl;
<< std::endl;
} }
} }
for (int i = 0; i < maxSubLayersMinus1; i++){ for (int i = 0; i < maxSubLayersMinus1; i++){
@ -238,16 +232,11 @@ namespace h265{
r << std::string(indent + 2, ' ') << "sub_layer_profile_idc: " << bs.get(5) << std::endl; r << std::string(indent + 2, ' ') << "sub_layer_profile_idc: " << bs.get(5) << std::endl;
r << std::string(indent + 2, ' ') << "sub_layer_profile_compatibility_flags: " << std::hex r << std::string(indent + 2, ' ') << "sub_layer_profile_compatibility_flags: " << std::hex
<< bs.get(32) << std::dec << std::endl; << bs.get(32) << std::dec << std::endl;
r << std::string(indent + 2, ' ') << "sub_layer_progressive_source_flag: " << bs.get(1) r << std::string(indent + 2, ' ') << "sub_layer_progressive_source_flag: " << bs.get(1) << std::endl;
<< std::endl; r << std::string(indent + 2, ' ') << "sub_layer_interlaced_source_flag: " << bs.get(1) << std::endl;
r << std::string(indent + 2, ' ') << "sub_layer_interlaced_source_flag: " << bs.get(1) r << std::string(indent + 2, ' ') << "sub_layer_non_packed_constraint_flag: " << bs.get(1) << std::endl;
<< std::endl; r << std::string(indent + 2, ' ') << "sub_layer_frame_only_constraint_flag: " << bs.get(1) << std::endl;
r << std::string(indent + 2, ' ') << "sub_layer_non_packed_constraint_flag: " << bs.get(1) r << std::string(indent + 2, ' ') << "sub_layer_reserved_zero_44bits: " << bs.get(44) << std::endl;
<< std::endl;
r << std::string(indent + 2, ' ') << "sub_layer_frame_only_constraint_flag: " << bs.get(1)
<< std::endl;
r << std::string(indent + 2, ' ') << "sub_layer_reserved_zero_44bits: " << bs.get(44)
<< std::endl;
} }
if (levelPresent[i]){ if (levelPresent[i]){
r << std::string(indent + 2, ' ') << "sub_layer_level_idc: " << bs.get(8) << std::endl; r << std::string(indent + 2, ' ') << "sub_layer_level_idc: " << bs.get(8) << std::endl;
@ -256,17 +245,13 @@ namespace h265{
return r.str(); return r.str();
} }
void updateProfileTierLevel(Utils::bitstream &bs, MP4::HVCC &hvccBox, void updateProfileTierLevel(Utils::bitstream &bs, MP4::HVCC &hvccBox, unsigned int maxSubLayersMinus1){
unsigned int maxSubLayersMinus1){
hvccBox.setGeneralProfileSpace(bs.get(2)); hvccBox.setGeneralProfileSpace(bs.get(2));
unsigned int tierFlag = bs.get(1); unsigned int tierFlag = bs.get(1);
hvccBox.setGeneralProfileIdc( hvccBox.setGeneralProfileIdc(std::max((unsigned long long)hvccBox.getGeneralProfileIdc(), bs.get(5)));
std::max((unsigned long long)hvccBox.getGeneralProfileIdc(), bs.get(5))); hvccBox.setGeneralProfileCompatibilityFlags(hvccBox.getGeneralProfileCompatibilityFlags() & bs.get(32));
hvccBox.setGeneralProfileCompatibilityFlags(hvccBox.getGeneralProfileCompatibilityFlags() & hvccBox.setGeneralConstraintIndicatorFlags(hvccBox.getGeneralConstraintIndicatorFlags() & bs.get(48));
bs.get(32));
hvccBox.setGeneralConstraintIndicatorFlags(hvccBox.getGeneralConstraintIndicatorFlags() &
bs.get(48));
unsigned int levelIdc = bs.get(8); unsigned int levelIdc = bs.get(8);
if (tierFlag && !hvccBox.getGeneralTierFlag()){ if (tierFlag && !hvccBox.getGeneralTierFlag()){
@ -309,8 +294,7 @@ namespace h265{
unsigned int maxSubLayers = bs.get(3) + 1; unsigned int maxSubLayers = bs.get(3) + 1;
hvccBox.setNumberOfTemporalLayers( hvccBox.setNumberOfTemporalLayers(std::max((unsigned int)hvccBox.getNumberOfTemporalLayers(), maxSubLayers));
std::max((unsigned int)hvccBox.getNumberOfTemporalLayers(), maxSubLayers));
bs.skip(17); bs.skip(17);
@ -326,8 +310,7 @@ namespace h265{
r << std::string(indent, ' ') << "vps_reserved_three_2bits: " << bs.get(2) << std::endl; r << std::string(indent, ' ') << "vps_reserved_three_2bits: " << bs.get(2) << std::endl;
r << std::string(indent, ' ') << "vps_max_layers_minus1: " << bs.get(6) << std::endl; r << std::string(indent, ' ') << "vps_max_layers_minus1: " << bs.get(6) << std::endl;
unsigned int maxSubLayersMinus1 = bs.get(3); unsigned int maxSubLayersMinus1 = bs.get(3);
r << std::string(indent, ' ') << "vps_max_sub_layers_minus1: " << maxSubLayersMinus1 r << std::string(indent, ' ') << "vps_max_sub_layers_minus1: " << maxSubLayersMinus1 << std::endl;
<< std::endl;
r << std::string(indent, ' ') << "vps_temporal_id_nesting_flag: " << bs.get(1) << std::endl; r << std::string(indent, ' ') << "vps_temporal_id_nesting_flag: " << bs.get(1) << std::endl;
r << std::string(indent, ' ') << "vps_reserved_0xffff_16bits: " << std::hex << bs.get(16) r << std::string(indent, ' ') << "vps_reserved_0xffff_16bits: " << std::hex << bs.get(16)
<< std::dec << std::endl; << std::dec << std::endl;
@ -347,8 +330,7 @@ namespace h265{
unsigned int vps_max_layer_id = bs.get(6); unsigned int vps_max_layer_id = bs.get(6);
uint64_t vps_num_layer_sets_minus1 = bs.getUExpGolomb(); uint64_t vps_num_layer_sets_minus1 = bs.getUExpGolomb();
r << std::string(indent, ' ') << "vps_max_layer_id: " << vps_max_layer_id << std::endl; r << std::string(indent, ' ') << "vps_max_layer_id: " << vps_max_layer_id << std::endl;
r << std::string(indent, ' ') << "vps_num_layer_sets_minus1: " << vps_num_layer_sets_minus1 r << std::string(indent, ' ') << "vps_num_layer_sets_minus1: " << vps_num_layer_sets_minus1 << std::endl;
<< std::endl;
for (int i = 1; i <= vps_num_layer_sets_minus1; i++){ for (int i = 1; i <= vps_num_layer_sets_minus1; i++){
for (int j = 0; j < vps_max_layer_id; j++){ for (int j = 0; j < vps_max_layer_id; j++){
r << std::string(indent, ' ') << "layer_id_included_flag[" << i << "][" << j r << std::string(indent, ' ') << "layer_id_included_flag[" << i << "][" << j
@ -356,8 +338,7 @@ namespace h265{
} }
} }
bool vps_timing_info = bs.get(1); bool vps_timing_info = bs.get(1);
r << std::string(indent, ' ') << "vps_timing_info_present_flag: " << (vps_timing_info ? 1 : 0) r << std::string(indent, ' ') << "vps_timing_info_present_flag: " << (vps_timing_info ? 1 : 0) << std::endl;
<< std::endl;
return r.str(); return r.str();
} }
@ -420,15 +401,14 @@ namespace h265{
deltaIdxMinus1 = bs.getUExpGolomb(); deltaIdxMinus1 = bs.getUExpGolomb();
r << std::string(indent, ' ') << "delta_idx_minus_1: " << deltaIdxMinus1 << std::endl; r << std::string(indent, ' ') << "delta_idx_minus_1: " << deltaIdxMinus1 << std::endl;
} }
r << std::string(indent, ' ') r << std::string(indent, ' ') << "delta_rps_sign: " << (int)bs.get(1) << std::endl;
<< "delta_rps_sign: " << (int)bs.get(1) << std::endl; r << std::string(indent, ' ') << "abs_delta_rps_minus1: " << bs.getUExpGolomb() << std::endl;
r << std::string(indent, ' ')
<< "abs_delta_rps_minus1: " << bs.getUExpGolomb() << std::endl;
uint64_t refRpsIdx = idx - deltaIdxMinus1 - 1; uint64_t refRpsIdx = idx - deltaIdxMinus1 - 1;
uint64_t deltaPocs = negativePics[refRpsIdx] + positivePics[refRpsIdx]; uint64_t deltaPocs = negativePics[refRpsIdx] + positivePics[refRpsIdx];
for (int j = 0; j < deltaPocs; j++){ for (int j = 0; j < deltaPocs; j++){
bool usedByCurrPicFlag = bs.get(1); bool usedByCurrPicFlag = bs.get(1);
r << std::string(indent + 1, ' ') << "used_by_curr_pic_flag[" << j << "]: " << usedByCurrPicFlag << std::endl; r << std::string(indent + 1, ' ') << "used_by_curr_pic_flag[" << j
<< "]: " << usedByCurrPicFlag << std::endl;
if (!usedByCurrPicFlag){ if (!usedByCurrPicFlag){
r << std::string(indent + 1, ' ') << "used_delta_flag[" << j << "]: " << bs.get(1) << std::endl; r << std::string(indent + 1, ' ') << "used_delta_flag[" << j << "]: " << bs.get(1) << std::endl;
} }
@ -492,8 +472,7 @@ namespace h265{
std::string printVuiParameters(Utils::bitstream &bs, size_t indent){ std::string printVuiParameters(Utils::bitstream &bs, size_t indent){
std::stringstream r; std::stringstream r;
bool aspectRatio = bs.get(1); bool aspectRatio = bs.get(1);
r << std::string(indent, ' ') << "aspect_ratio_info_present_flag: " << (aspectRatio ? 1 : 0) r << std::string(indent, ' ') << "aspect_ratio_info_present_flag: " << (aspectRatio ? 1 : 0) << std::endl;
<< std::endl;
if (aspectRatio){ if (aspectRatio){
uint16_t aspectRatioIdc = bs.get(8); uint16_t aspectRatioIdc = bs.get(8);
r << std::string(indent, ' ') << "aspect_ratio_idc: " << aspectRatioIdc << std::endl; r << std::string(indent, ' ') << "aspect_ratio_idc: " << aspectRatioIdc << std::endl;
@ -595,39 +574,29 @@ namespace h265{
std::stringstream r; std::stringstream r;
r << std::string(indent, ' ') << "sps_video_parameter_set_id: " << bs.get(4) << std::endl; r << std::string(indent, ' ') << "sps_video_parameter_set_id: " << bs.get(4) << std::endl;
unsigned int maxSubLayersMinus1 = bs.get(3); unsigned int maxSubLayersMinus1 = bs.get(3);
r << std::string(indent, ' ') << "sps_max_sub_layers_minus1: " << maxSubLayersMinus1 r << std::string(indent, ' ') << "sps_max_sub_layers_minus1: " << maxSubLayersMinus1 << std::endl;
<< std::endl;
r << std::string(indent, ' ') << "sps_temporal_id_nesting_flag: " << bs.get(1) << std::endl; r << std::string(indent, ' ') << "sps_temporal_id_nesting_flag: " << bs.get(1) << std::endl;
r << std::string(indent, ' ') << "profile_tier_level(): " << std::endl r << std::string(indent, ' ') << "profile_tier_level(): " << std::endl
<< printProfileTierLevel(bs, maxSubLayersMinus1, indent + 1); << printProfileTierLevel(bs, maxSubLayersMinus1, indent + 1);
r << std::string(indent, ' ') << "sps_seq_parameter_set_id: " << bs.getUExpGolomb() r << std::string(indent, ' ') << "sps_seq_parameter_set_id: " << bs.getUExpGolomb() << std::endl;
<< std::endl;
uint64_t chromaFormatIdc = bs.getUExpGolomb(); uint64_t chromaFormatIdc = bs.getUExpGolomb();
r << std::string(indent, ' ') << "chroma_format_idc: " << chromaFormatIdc << std::endl; r << std::string(indent, ' ') << "chroma_format_idc: " << chromaFormatIdc << std::endl;
if (chromaFormatIdc == 3){ if (chromaFormatIdc == 3){
r << std::string(indent, ' ') << "separate_colour_plane_flag: " << bs.get(1) << std::endl; r << std::string(indent, ' ') << "separate_colour_plane_flag: " << bs.get(1) << std::endl;
} }
r << std::string(indent, ' ') << "pic_width_in_luma_samples: " << bs.getUExpGolomb() r << std::string(indent, ' ') << "pic_width_in_luma_samples: " << bs.getUExpGolomb() << std::endl;
<< std::endl; r << std::string(indent, ' ') << "pic_height_in_luma_samples: " << bs.getUExpGolomb() << std::endl;
r << std::string(indent, ' ') << "pic_height_in_luma_samples: " << bs.getUExpGolomb()
<< std::endl;
bool conformance_window_flag = bs.get(1); bool conformance_window_flag = bs.get(1);
r << std::string(indent, ' ') << "conformance_window_flag: " << conformance_window_flag r << std::string(indent, ' ') << "conformance_window_flag: " << conformance_window_flag << std::endl;
<< std::endl;
if (conformance_window_flag){ if (conformance_window_flag){
r << std::string(indent, ' ') << "conf_window_left_offset: " << bs.getUExpGolomb() r << std::string(indent, ' ') << "conf_window_left_offset: " << bs.getUExpGolomb() << std::endl;
<< std::endl; r << std::string(indent, ' ') << "conf_window_right_offset: " << bs.getUExpGolomb() << std::endl;
r << std::string(indent, ' ') << "conf_window_right_offset: " << bs.getUExpGolomb() r << std::string(indent, ' ') << "conf_window_top_offset: " << bs.getUExpGolomb() << std::endl;
<< std::endl; r << std::string(indent, ' ') << "conf_window_bottom_offset: " << bs.getUExpGolomb() << std::endl;
r << std::string(indent, ' ') << "conf_window_top_offset: " << bs.getUExpGolomb()
<< std::endl;
r << std::string(indent, ' ') << "conf_window_bottom_offset: " << bs.getUExpGolomb()
<< std::endl;
} }
r << std::string(indent, ' ') << "bit_depth_luma_minus8: " << bs.getUExpGolomb() << std::endl; r << std::string(indent, ' ') << "bit_depth_luma_minus8: " << bs.getUExpGolomb() << std::endl;
r << std::string(indent, ' ') << "bit_depth_chroma_minus8: " << bs.getUExpGolomb() << std::endl; r << std::string(indent, ' ') << "bit_depth_chroma_minus8: " << bs.getUExpGolomb() << std::endl;
r << std::string(indent, ' ') << "log2_max_pic_order_cnt_lsb_minus4: " << bs.getUExpGolomb() r << std::string(indent, ' ') << "log2_max_pic_order_cnt_lsb_minus4: " << bs.getUExpGolomb() << std::endl;
<< std::endl;
bool subLayerOrdering = bs.get(1); bool subLayerOrdering = bs.get(1);
r << std::string(indent, ' ') r << std::string(indent, ' ')
<< "sps_sub_layer_ordering_info_present_flag: " << subLayerOrdering << std::endl; << "sps_sub_layer_ordering_info_present_flag: " << subLayerOrdering << std::endl;
@ -647,23 +616,18 @@ namespace h265{
<< std::endl; << std::endl;
r << std::string(indent, ' ') r << std::string(indent, ' ')
<< "log2_diff_max_min_transform_block_size: " << bs.getUExpGolomb() << std::endl; << "log2_diff_max_min_transform_block_size: " << bs.getUExpGolomb() << std::endl;
r << std::string(indent, ' ') << "max_transform_hierarchy_depth_inter: " << bs.getUExpGolomb() r << std::string(indent, ' ') << "max_transform_hierarchy_depth_inter: " << bs.getUExpGolomb() << std::endl;
<< std::endl; r << std::string(indent, ' ') << "max_transform_hierarchy_depth_intra: " << bs.getUExpGolomb() << std::endl;
r << std::string(indent, ' ') << "max_transform_hierarchy_depth_intra: " << bs.getUExpGolomb()
<< std::endl;
bool scalingListEnabled = bs.get(1); bool scalingListEnabled = bs.get(1);
r << std::string(indent, ' ') << "scaling_list_enabled_flag: " << scalingListEnabled r << std::string(indent, ' ') << "scaling_list_enabled_flag: " << scalingListEnabled << std::endl;
<< std::endl;
if (scalingListEnabled){WARN_MSG("Not implemented scaling list in HEVC sps");} if (scalingListEnabled){WARN_MSG("Not implemented scaling list in HEVC sps");}
r << std::string(indent, ' ') << "amp_enabled_flag: " << bs.get(1) << std::endl; r << std::string(indent, ' ') << "amp_enabled_flag: " << bs.get(1) << std::endl;
r << std::string(indent, ' ') << "sample_adaptive_offset_enabled_flag: " << bs.get(1) r << std::string(indent, ' ') << "sample_adaptive_offset_enabled_flag: " << bs.get(1) << std::endl;
<< std::endl;
bool pcmEnabled = bs.get(1); bool pcmEnabled = bs.get(1);
r << std::string(indent, ' ') << "pcm_enabled_flag: " << pcmEnabled << std::endl; r << std::string(indent, ' ') << "pcm_enabled_flag: " << pcmEnabled << std::endl;
if (pcmEnabled){WARN_MSG("Not implemented pcm_enabled in HEVC sps");} if (pcmEnabled){WARN_MSG("Not implemented pcm_enabled in HEVC sps");}
uint64_t shortTermPicSets = bs.getUExpGolomb(); uint64_t shortTermPicSets = bs.getUExpGolomb();
r << std::string(indent, ' ') << "num_short_term_ref_pic_sets: " << shortTermPicSets r << std::string(indent, ' ') << "num_short_term_ref_pic_sets: " << shortTermPicSets << std::endl;
<< std::endl;
for (int i = 0; i < shortTermPicSets; i++){ for (int i = 0; i < shortTermPicSets; i++){
r << std::string(indent, ' ') << "short_term_ref_pic_set(" << i << "):" << std::endl r << std::string(indent, ' ') << "short_term_ref_pic_set(" << i << "):" << std::endl
<< printShortTermRefPicSet(bs, i, shortTermPicSets, indent + 1); << printShortTermRefPicSet(bs, i, shortTermPicSets, indent + 1);
@ -673,12 +637,10 @@ namespace h265{
<< "long_term_ref_pics_present_flag: " << (longTermRefPics ? 1 : 0) << std::endl; << "long_term_ref_pics_present_flag: " << (longTermRefPics ? 1 : 0) << std::endl;
if (longTermRefPics){WARN_MSG("Implement longTermRefPics");} if (longTermRefPics){WARN_MSG("Implement longTermRefPics");}
r << std::string(indent, ' ') << "sps_temporal_mvp_enabled_flag: " << bs.get(1) << std::endl; r << std::string(indent, ' ') << "sps_temporal_mvp_enabled_flag: " << bs.get(1) << std::endl;
r << std::string(indent, ' ') << "strong_intra_smoothing_enabled_flag: " << bs.get(1) r << std::string(indent, ' ') << "strong_intra_smoothing_enabled_flag: " << bs.get(1) << std::endl;
<< std::endl;
bool vuiParams = bs.get(1); bool vuiParams = bs.get(1);
r << std::string(indent, ' ') << "vui_parameters_present_flag: " << (vuiParams ? 1 : 0) r << std::string(indent, ' ') << "vui_parameters_present_flag: " << (vuiParams ? 1 : 0) << std::endl;
<< std::endl;
if (vuiParams){ if (vuiParams){
r << std::string(indent, ' ') << "vui_parameters:" << std::endl r << std::string(indent, ' ') << "vui_parameters:" << std::endl
<< printVuiParameters(bs, indent + 1); << printVuiParameters(bs, indent + 1);
@ -694,8 +656,7 @@ namespace h265{
unsigned int maxSubLayers = bs.get(3) + 1; unsigned int maxSubLayers = bs.get(3) + 1;
hvccBox.setNumberOfTemporalLayers( hvccBox.setNumberOfTemporalLayers(std::max((unsigned int)hvccBox.getNumberOfTemporalLayers(), maxSubLayers));
std::max((unsigned int)hvccBox.getNumberOfTemporalLayers(), maxSubLayers));
hvccBox.setTemporalIdNested(bs.get(1)); hvccBox.setTemporalIdNested(bs.get(1));
updateProfileTierLevel(bs, hvccBox, maxSubLayers - 1); updateProfileTierLevel(bs, hvccBox, maxSubLayers - 1);
@ -858,8 +819,7 @@ namespace h265{
if (bs.get(1)){ if (bs.get(1)){
bs.skip(3); bs.skip(3);
int spatialSegmentIdc = bs.getUExpGolomb(); int spatialSegmentIdc = bs.getUExpGolomb();
hvccBox.setMinSpatialSegmentationIdc( hvccBox.setMinSpatialSegmentationIdc(std::min((int)hvccBox.getMinSpatialSegmentationIdc(), spatialSegmentIdc));
std::min((int)hvccBox.getMinSpatialSegmentationIdc(), spatialSegmentIdc));
bs.getUExpGolomb(); bs.getUExpGolomb();
bs.getUExpGolomb(); bs.getUExpGolomb();
bs.getUExpGolomb(); bs.getUExpGolomb();
@ -868,4 +828,3 @@ namespace h265{
} }
} }
}// namespace h265 }// namespace h265

View file

@ -13,10 +13,8 @@ namespace h265{
const char *typeToStr(uint8_t type); const char *typeToStr(uint8_t type);
bool isKeyframe(const char *data, uint32_t len); bool isKeyframe(const char *data, uint32_t len);
void updateProfileTierLevel(Utils::bitstream &bs, MP4::HVCC &hvccBox, void updateProfileTierLevel(Utils::bitstream &bs, MP4::HVCC &hvccBox, unsigned long maxSubLayersMinus1);
unsigned long maxSubLayersMinus1); std::string printProfileTierLevel(Utils::bitstream &bs, unsigned long maxSubLayersMinus1, size_t indent);
std::string printProfileTierLevel(Utils::bitstream &bs, unsigned long maxSubLayersMinus1,
size_t indent);
struct metaInfo{ struct metaInfo{
uint64_t width; uint64_t width;
@ -71,4 +69,3 @@ namespace h265{
// NOTE: no ppsUnit, as the only information it contains is parallelism mode, which can be set to // NOTE: no ppsUnit, as the only information it contains is parallelism mode, which can be set to
// 0 for 'unknown' // 0 for 'unknown'
}// namespace h265 }// namespace h265

View file

@ -8,8 +8,8 @@
#include "timing.h" #include "timing.h"
#include "url.h" #include "url.h"
#include "util.h" #include "util.h"
#include <strings.h>
#include <iomanip> #include <iomanip>
#include <strings.h>
/// This constructor creates an empty HTTP::Parser, ready for use for either reading or writing. /// This constructor creates an empty HTTP::Parser, ready for use for either reading or writing.
/// All this constructor does is call HTTP::Parser::Clean(). /// All this constructor does is call HTTP::Parser::Clean().
@ -167,7 +167,8 @@ void HTTP::Parser::SendRequest(Socket::Connection &conn, const std::string &reqb
sendRequest(conn, reqbody.data(), reqbody.size(), allAtOnce); sendRequest(conn, reqbody.data(), reqbody.size(), allAtOnce);
} }
void HTTP::Parser::sendRequest(Socket::Connection &conn, const void * reqbody, const size_t reqbodyLen, bool allAtOnce){ void HTTP::Parser::sendRequest(Socket::Connection &conn, const void *reqbody,
const size_t reqbodyLen, bool allAtOnce){
/// \todo Include GET/POST variable parsing? /// \todo Include GET/POST variable parsing?
if (allAtOnce){ if (allAtOnce){
/// \TODO Make this less duplicated / more pretty. /// \TODO Make this less duplicated / more pretty.
@ -421,9 +422,7 @@ const std::string &HTTP::Parser::GetHeader(const std::string &i) const{
if (headers.count(i)){return headers.at(i);} if (headers.count(i)){return headers.at(i);}
for (std::map<std::string, std::string>::const_iterator it = headers.begin(); it != headers.end(); ++it){ for (std::map<std::string, std::string>::const_iterator it = headers.begin(); it != headers.end(); ++it){
if (it->first.length() != i.length()){continue;} if (it->first.length() != i.length()){continue;}
if (strncasecmp(it->first.c_str(), i.c_str(), i.length()) == 0){ if (strncasecmp(it->first.c_str(), i.c_str(), i.length()) == 0){return it->second;}
return it->second;
}
} }
// Return empty string if not found // Return empty string if not found
static const std::string empty; static const std::string empty;
@ -435,9 +434,7 @@ bool HTTP::Parser::hasHeader(const std::string &i) const{
if (headers.count(i)){return true;} if (headers.count(i)){return true;}
for (std::map<std::string, std::string>::const_iterator it = headers.begin(); it != headers.end(); ++it){ for (std::map<std::string, std::string>::const_iterator it = headers.begin(); it != headers.end(); ++it){
if (it->first.length() != i.length()){continue;} if (it->first.length() != i.length()){continue;}
if (strncasecmp(it->first.c_str(), i.c_str(), i.length()) == 0){ if (strncasecmp(it->first.c_str(), i.c_str(), i.length()) == 0){return true;}
return true;
}
} }
return false; return false;
} }
@ -708,9 +705,7 @@ bool HTTP::Parser::parse(std::string &HTTPbuffer, Util::DataCallback &cb){
} }
return false; return false;
}else{ }else{
if (protocol.substr(0, 4) == "RTSP" || method.substr(0,4) == "RTSP"){ if (protocol.substr(0, 4) == "RTSP" || method.substr(0, 4) == "RTSP"){return true;}
return true;
}
unsigned int toappend = HTTPbuffer.size(); unsigned int toappend = HTTPbuffer.size();
bool shouldAppend = true; bool shouldAppend = true;
if (bodyCallback){ if (bodyCallback){

View file

@ -39,7 +39,8 @@ namespace HTTP{
std::string &BuildResponse(); std::string &BuildResponse();
std::string &BuildResponse(std::string code, std::string message); std::string &BuildResponse(std::string code, std::string message);
void SendRequest(Socket::Connection &conn, const std::string &reqbody = "", bool allAtOnce = false); void SendRequest(Socket::Connection &conn, const std::string &reqbody = "", bool allAtOnce = false);
void sendRequest(Socket::Connection &conn, const void * body = 0, const size_t bodyLen = 0, bool allAtOnce = false); void sendRequest(Socket::Connection &conn, const void *body = 0, const size_t bodyLen = 0,
bool allAtOnce = false);
void SendResponse(std::string code, std::string message, Socket::Connection &conn); void SendResponse(std::string code, std::string message, Socket::Connection &conn);
void StartResponse(std::string code, std::string message, Parser &request, void StartResponse(std::string code, std::string message, Parser &request,
Socket::Connection &conn, bool bufferAllChunks = false); Socket::Connection &conn, bool bufferAllChunks = false);

View file

@ -1,8 +1,8 @@
/// \file json.cpp Holds all JSON-related code. /// \file json.cpp Holds all JSON-related code.
#include "json.h"
#include "bitfields.h" #include "bitfields.h"
#include "defines.h" #include "defines.h"
#include "json.h"
#include <arpa/inet.h> //for htonl #include <arpa/inet.h> //for htonl
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
@ -274,8 +274,7 @@ std::string JSON::string_escape(const std::string &val){
if ((c & 0xC0) == 0xC0){ if ((c & 0xC0) == 0xC0){
// possible UTF-8 sequence // possible UTF-8 sequence
// check for 2-byte sequence // check for 2-byte sequence
if (((c & 0xE0) == 0XC0) && (i + 1 < val.size()) && if (((c & 0xE0) == 0XC0) && (i + 1 < val.size()) && ((val.data()[i + 1] & 0xC0) == 0x80)){
((val.data()[i + 1] & 0xC0) == 0x80)){
// valid 2-byte sequence // valid 2-byte sequence
out += UTF16(((c & 0x1F) << 6) | (val.data()[i + 1] & 0x3F)); out += UTF16(((c & 0x1F) << 6) | (val.data()[i + 1] & 0x3F));
i += 1; i += 1;
@ -285,15 +284,13 @@ std::string JSON::string_escape(const std::string &val){
if (((c & 0xF0) == 0XE0) && (i + 2 < val.size()) && if (((c & 0xF0) == 0XE0) && (i + 2 < val.size()) &&
((val.data()[i + 1] & 0xC0) == 0x80) && ((val.data()[i + 2] & 0xC0) == 0x80)){ ((val.data()[i + 1] & 0xC0) == 0x80) && ((val.data()[i + 2] & 0xC0) == 0x80)){
// valid 3-byte sequence // valid 3-byte sequence
out += UTF16(((c & 0x1F) << 12) | ((val.data()[i + 1] & 0x3F) << 6) | out += UTF16(((c & 0x1F) << 12) | ((val.data()[i + 1] & 0x3F) << 6) | (val.data()[i + 2] & 0x3F));
(val.data()[i + 2] & 0x3F));
i += 2; i += 2;
break; break;
} }
// check for 4-byte sequence // check for 4-byte sequence
if (((c & 0xF8) == 0XF0) && (i + 3 < val.size()) && if (((c & 0xF8) == 0XF0) && (i + 3 < val.size()) && ((val.data()[i + 1] & 0xC0) == 0x80) &&
((val.data()[i + 1] & 0xC0) == 0x80) && ((val.data()[i + 2] & 0xC0) == 0x80) && ((val.data()[i + 2] & 0xC0) == 0x80) && ((val.data()[i + 3] & 0xC0) == 0x80)){
((val.data()[i + 3] & 0xC0) == 0x80)){
// valid 4-byte sequence // valid 4-byte sequence
out += UTF16(((c & 0x1F) << 18) | ((val.data()[i + 1] & 0x3F) << 12) | out += UTF16(((c & 0x1F) << 18) | ((val.data()[i + 1] & 0x3F) << 12) |
((val.data()[i + 2] & 0x3F) << 6) | (val.data()[i + 3] & 0x3F)); ((val.data()[i + 2] & 0x3F) << 6) | (val.data()[i + 3] & 0x3F));
@ -919,8 +916,7 @@ void JSON::Value::sendTo(Socket::Connection &socket) const{
unsigned int size = 16; unsigned int size = 16;
if (objVal.size() > 0){ if (objVal.size() > 0){
jsonForEachConst(*this, i){ jsonForEachConst(*this, i){
if (i.key().size() > 0 && i.key() != "trackid" && i.key() != "time" && if (i.key().size() > 0 && i.key() != "trackid" && i.key() != "time" && i.key() != "datatype"){
i.key() != "datatype"){
size += 2 + i.key().size() + i->packedSize(); size += 2 + i.key().size() + i->packedSize();
} }
} }
@ -937,8 +933,7 @@ void JSON::Value::sendTo(Socket::Connection &socket) const{
socket.SendNow("\340", 1); socket.SendNow("\340", 1);
if (objVal.size() > 0){ if (objVal.size() > 0){
jsonForEachConst(*this, i){ jsonForEachConst(*this, i){
if (i.key().size() > 0 && i.key() != "trackid" && i.key() != "time" && if (i.key().size() > 0 && i.key() != "trackid" && i.key() != "time" && i.key() != "datatype"){
i.key() != "datatype"){
char sizebuffer[2] ={0, 0}; char sizebuffer[2] ={0, 0};
sizebuffer[0] = (i.key().size() >> 8) & 0xFF; sizebuffer[0] = (i.key().size() >> 8) & 0xFF;
sizebuffer[1] = i.key().size() & 0xFF; sizebuffer[1] = i.key().size() & 0xFF;
@ -1395,15 +1390,13 @@ void JSON::fromDTMI(const char *data, uint64_t len, uint32_t &i, JSON::Value &re
case 0xFF: // also object case 0xFF: // also object
case 0xE0:{// object case 0xE0:{// object
++i; ++i;
while (data[i] + data[i + 1] != 0 && while (data[i] + data[i + 1] != 0 && i < len){// while not encountering 0x0000 (we assume 0x0000EE)
i < len){// while not encountering 0x0000 (we assume 0x0000EE)
if (i + 2 >= len){return;} if (i + 2 >= len){return;}
uint16_t tmpi = Bit::btohs(data + i); // set tmpi to the UTF-8 length uint16_t tmpi = Bit::btohs(data + i); // set tmpi to the UTF-8 length
std::string tmpstr = std::string(data + i + 2, tmpi); // set the string data std::string tmpstr = std::string(data + i + 2, tmpi); // set the string data
i += tmpi + 2; // skip length+size forwards i += tmpi + 2; // skip length+size forwards
ret[tmpstr].null(); ret[tmpstr].null();
fromDTMI( fromDTMI(data, len, i,
data, len, i,
ret[tmpstr]); // add content, recursively parsed, updating i, setting indice to tmpstr ret[tmpstr]); // add content, recursively parsed, updating i, setting indice to tmpstr
} }
i += 3; // skip 0x0000EE i += 3; // skip 0x0000EE
@ -1412,8 +1405,7 @@ void JSON::fromDTMI(const char *data, uint64_t len, uint32_t &i, JSON::Value &re
} }
case 0x0A:{// array case 0x0A:{// array
++i; ++i;
while (data[i] + data[i + 1] != 0 && while (data[i] + data[i + 1] != 0 && i < len){// while not encountering 0x0000 (we assume 0x0000EE)
i < len){// while not encountering 0x0000 (we assume 0x0000EE)
JSON::Value tval; JSON::Value tval;
fromDTMI(data, len, i, tval); // add content, recursively parsed, updating i fromDTMI(data, len, i, tval); // add content, recursively parsed, updating i
ret.append(tval); ret.append(tval);
@ -1471,4 +1463,3 @@ JSON::Value JSON::fromDTMI2(const char *data, uint64_t len, uint32_t &i){
fromDTMI2(data, len, i, ret); fromDTMI2(data, len, i, ret);
return ret; return ret;
} }

View file

@ -159,4 +159,3 @@ namespace JSON{
#define jsonForEach(val, i) for (JSON::Iter i(val); i; ++i) #define jsonForEach(val, i) for (JSON::Iter i(val); i; ++i)
#define jsonForEachConst(val, i) for (JSON::ConstIter i(val); i; ++i) #define jsonForEachConst(val, i) for (JSON::ConstIter i(val); i; ++i)
}// namespace JSON }// namespace JSON

View file

@ -1221,4 +1221,3 @@ namespace Encodings{
} }
}// namespace Encodings }// namespace Encodings

View file

@ -9,6 +9,4 @@ namespace Encodings {
static std::string encode(const std::string &lang); static std::string encode(const std::string &lang);
}; };
}// namespace Encodings
}

View file

@ -1,16 +1,16 @@
#include <stdlib.h> //for malloc and free #include "json.h"
#include <string.h> //for memcpy
#include <arpa/inet.h> //for htonl and friends
#include "mp4.h" #include "mp4.h"
#include "mp4_adobe.h" #include "mp4_adobe.h"
#include "mp4_ms.h"
#include "mp4_dash.h" #include "mp4_dash.h"
#include "mp4_generic.h"
#include "mp4_encryption.h" // /*LTS*/ #include "mp4_encryption.h" // /*LTS*/
#include "json.h" #include "mp4_generic.h"
#include "mp4_ms.h"
#include <arpa/inet.h> //for htonl and friends
#include <stdlib.h> //for malloc and free
#include <string.h> //for memcpy
#include "defines.h"
#include "bitfields.h" #include "bitfields.h"
#include "defines.h"
/// Contains all MP4 format related code. /// Contains all MP4 format related code.
namespace MP4{ namespace MP4{
@ -59,7 +59,6 @@ namespace MP4 {
return *this; return *this;
} }
/// If managed, this will free the data pointer. /// If managed, this will free the data pointer.
Box::~Box(){ Box::~Box(){
if (managed && data){ if (managed && data){
@ -81,14 +80,10 @@ namespace MP4 {
payloadOffset = rs.payloadOffset; payloadOffset = rs.payloadOffset;
} }
/// Returns the values at byte positions 4 through 7. /// Returns the values at byte positions 4 through 7.
std::string Box::getType() const { std::string Box::getType() const{return std::string(data + 4, 4);}
return std::string(data + 4, 4);
}
/// Returns true if the given 4-byte boxtype is equal to the values at byte positions 4 through 7. /// Returns true if the given 4-byte boxtype is equal to the values at byte positions 4 through 7.
bool Box::isType(const char * boxType) const { bool Box::isType(const char *boxType) const{return !memcmp(boxType, data + 4, 4);}
return !memcmp(boxType, data + 4, 4);
}
/// Reads the first 8 bytes and returns /// Reads the first 8 bytes and returns
std::string readBoxType(FILE *newData){ std::string readBoxType(FILE *newData){
@ -102,9 +97,7 @@ namespace MP4 {
/// Checks box size, offset-aware /// Checks box size, offset-aware
uint64_t calcBoxSize(const char *p){ uint64_t calcBoxSize(const char *p){
uint64_t r = ntohl(((int *)p)[0]); uint64_t r = ntohl(((int *)p)[0]);
if (r == 1){ if (r == 1){return (((uint64_t)ntohl(((int *)p)[2])) << 32) | ntohl(((int *)p)[3]);}
return (((uint64_t)ntohl(((int *)p)[2])) << 32) | ntohl(((int *)p)[3]);
}
return r; return r;
} }
@ -157,12 +150,10 @@ namespace MP4 {
} }
} }
/// Reads out a whole box (if possible) from newData, copying to the internal data storage and removing from the input string. /// Reads out a whole box (if possible) from newData, copying to the internal data storage and
/// \returns True on success, false otherwise. /// removing from the input string. \returns True on success, false otherwise.
bool Box::read(std::string &newData){ bool Box::read(std::string &newData){
if (!managed) { if (!managed){return false;}
return false;
}
if (newData.size() > 4){ if (newData.size() > 4){
payloadOffset = 8; payloadOffset = 8;
uint64_t size = ntohl(((int *)newData.c_str())[0]); uint64_t size = ntohl(((int *)newData.c_str())[0]);
@ -176,9 +167,7 @@ namespace MP4 {
return false; return false;
} }
} }
if (size == 0){ if (size == 0){size = newData.size();}
size = newData.size();
}
if (newData.size() >= size){ if (newData.size() >= size){
data = (char *)realloc(data, size); data = (char *)realloc(data, size);
data_size = size; data_size = size;
@ -200,26 +189,18 @@ namespace MP4 {
/// Retruns the size of the payload of thix box, excluding the header. /// Retruns the size of the payload of thix box, excluding the header.
/// This value is defined as boxedSize() - 8. /// This value is defined as boxedSize() - 8.
uint64_t Box::payloadSize() const { uint64_t Box::payloadSize() const{return boxedSize() - payloadOffset;}
return boxedSize() - payloadOffset;
}
/// Returns a copy of the data pointer. /// Returns a copy of the data pointer.
char * Box::asBox() { char *Box::asBox(){return data;}
return data;
}
char * Box::payload() { char *Box::payload(){return data + payloadOffset;}
return data + payloadOffset;
}
/// Makes this box managed if it wasn't already, resetting the internal storage to 8 bytes (the minimum). /// Makes this box managed if it wasn't already, resetting the internal storage to 8 bytes (the minimum).
/// If this box wasn't managed, the original data is left intact - otherwise it is free'd. /// If this box wasn't managed, the original data is left intact - otherwise it is free'd.
/// If it was somehow impossible to allocate 8 bytes (should never happen), this will cause segfaults later. /// If it was somehow impossible to allocate 8 bytes (should never happen), this will cause segfaults later.
void Box::clear(){ void Box::clear(){
if (data && managed) { if (data && managed){free(data);}
free(data);
}
managed = true; managed = true;
payloadOffset = 8; payloadOffset = 8;
data = (char *)malloc(8); data = (char *)malloc(8);
@ -235,153 +216,59 @@ namespace MP4 {
/// If this failed, it will print out a message saying pretty-printing is not implemented for boxtype. /// If this failed, it will print out a message saying pretty-printing is not implemented for boxtype.
std::string Box::toPrettyString(uint32_t indent) const{ std::string Box::toPrettyString(uint32_t indent) const{
switch (ntohl(*((int *)(data + 4)))){// type is at this address switch (ntohl(*((int *)(data + 4)))){// type is at this address
case 0x6D666864: case 0x6D666864: return ((MFHD *)this)->toPrettyString(indent); break;
return ((MFHD *)this)->toPrettyString(indent); case 0x6D6F6F66: return ((MOOF *)this)->toPrettyString(indent); break;
break; case 0x61627374: return ((ABST *)this)->toPrettyString(indent); break;
case 0x6D6F6F66: case 0x61667274: return ((AFRT *)this)->toPrettyString(indent); break;
return ((MOOF *)this)->toPrettyString(indent); case 0x61667261: return ((AFRA *)this)->toPrettyString(indent); break;
break; case 0x61737274: return ((ASRT *)this)->toPrettyString(indent); break;
case 0x61627374: case 0x7472756E: return ((TRUN *)this)->toPrettyString(indent); break;
return ((ABST *)this)->toPrettyString(indent); case 0x74726166: return ((TRAF *)this)->toPrettyString(indent); break;
break; case 0x74666864: return ((TFHD *)this)->toPrettyString(indent); break;
case 0x61667274: case 0x68766343: return ((HVCC *)this)->toPrettyString(indent); break;
return ((AFRT *)this)->toPrettyString(indent); case 0x61766343: return ((AVCC *)this)->toPrettyString(indent); break;
break; case 0x73647470: return ((SDTP *)this)->toPrettyString(indent); break;
case 0x61667261: case 0x66747970: return ((FTYP *)this)->toPrettyString(indent); break;
return ((AFRA *)this)->toPrettyString(indent); case 0x73747970: return ((STYP *)this)->toPrettyString(indent); break;
break; case 0x6D6F6F76: return ((MOOV *)this)->toPrettyString(indent); break;
case 0x61737274: case 0x6D766578: return ((MVEX *)this)->toPrettyString(indent); break;
return ((ASRT *)this)->toPrettyString(indent); case 0x74726578: return ((TREX *)this)->toPrettyString(indent); break;
break; case 0x6D667261: return ((MFRA *)this)->toPrettyString(indent); break;
case 0x7472756E: case 0x7472616B: return ((TRAK *)this)->toPrettyString(indent); break;
return ((TRUN *)this)->toPrettyString(indent); case 0x6D646961: return ((MDIA *)this)->toPrettyString(indent); break;
break; case 0x6D696E66: return ((MINF *)this)->toPrettyString(indent); break;
case 0x74726166: case 0x64696E66: return ((DINF *)this)->toPrettyString(indent); break;
return ((TRAF *)this)->toPrettyString(indent); case 0x6D66726F: return ((MFRO *)this)->toPrettyString(indent); break;
break; case 0x68646C72: return ((HDLR *)this)->toPrettyString(indent); break;
case 0x74666864: case 0x766D6864: return ((VMHD *)this)->toPrettyString(indent); break;
return ((TFHD *)this)->toPrettyString(indent); case 0x736D6864: return ((SMHD *)this)->toPrettyString(indent); break;
break; case 0x686D6864: return ((HMHD *)this)->toPrettyString(indent); break;
case 0x68766343: case 0x6E6D6864: return ((NMHD *)this)->toPrettyString(indent); break;
return ((HVCC *)this)->toPrettyString(indent); case 0x6D656864: return ((MEHD *)this)->toPrettyString(indent); break;
break; case 0x7374626C: return ((STBL *)this)->toPrettyString(indent); break;
case 0x61766343: case 0x64726566: return ((DREF *)this)->toPrettyString(indent); break;
return ((AVCC *)this)->toPrettyString(indent); case 0x75726C20: return ((URL *)this)->toPrettyString(indent); break;
break; case 0x75726E20: return ((URN *)this)->toPrettyString(indent); break;
case 0x73647470: case 0x6D766864: return ((MVHD *)this)->toPrettyString(indent); break;
return ((SDTP *)this)->toPrettyString(indent); case 0x74667261: return ((TFRA *)this)->toPrettyString(indent); break;
break; case 0x746B6864: return ((TKHD *)this)->toPrettyString(indent); break;
case 0x66747970: case 0x6D646864: return ((MDHD *)this)->toPrettyString(indent); break;
return ((FTYP *)this)->toPrettyString(indent); case 0x73747473: return ((STTS *)this)->toPrettyString(indent); break;
break; case 0x63747473: return ((CTTS *)this)->toPrettyString(indent); break;
case 0x73747970: case 0x73747363: return ((STSC *)this)->toPrettyString(indent); break;
return ((STYP*)this)->toPrettyString(indent); case 0x7374636F: return ((STCO *)this)->toPrettyString(indent); break;
break; case 0x636F3634: return ((CO64 *)this)->toPrettyString(indent); break;
case 0x6D6F6F76: case 0x7374737A: return ((STSZ *)this)->toPrettyString(indent); break;
return ((MOOV *)this)->toPrettyString(indent); case 0x73747364: return ((STSD *)this)->toPrettyString(indent); break;
break;
case 0x6D766578:
return ((MVEX *)this)->toPrettyString(indent);
break;
case 0x74726578:
return ((TREX *)this)->toPrettyString(indent);
break;
case 0x6D667261:
return ((MFRA *)this)->toPrettyString(indent);
break;
case 0x7472616B:
return ((TRAK *)this)->toPrettyString(indent);
break;
case 0x6D646961:
return ((MDIA *)this)->toPrettyString(indent);
break;
case 0x6D696E66:
return ((MINF *)this)->toPrettyString(indent);
break;
case 0x64696E66:
return ((DINF *)this)->toPrettyString(indent);
break;
case 0x6D66726F:
return ((MFRO *)this)->toPrettyString(indent);
break;
case 0x68646C72:
return ((HDLR *)this)->toPrettyString(indent);
break;
case 0x766D6864:
return ((VMHD *)this)->toPrettyString(indent);
break;
case 0x736D6864:
return ((SMHD *)this)->toPrettyString(indent);
break;
case 0x686D6864:
return ((HMHD *)this)->toPrettyString(indent);
break;
case 0x6E6D6864:
return ((NMHD *)this)->toPrettyString(indent);
break;
case 0x6D656864:
return ((MEHD *)this)->toPrettyString(indent);
break;
case 0x7374626C:
return ((STBL *)this)->toPrettyString(indent);
break;
case 0x64726566:
return ((DREF *)this)->toPrettyString(indent);
break;
case 0x75726C20:
return ((URL *)this)->toPrettyString(indent);
break;
case 0x75726E20:
return ((URN *)this)->toPrettyString(indent);
break;
case 0x6D766864:
return ((MVHD *)this)->toPrettyString(indent);
break;
case 0x74667261:
return ((TFRA *)this)->toPrettyString(indent);
break;
case 0x746B6864:
return ((TKHD *)this)->toPrettyString(indent);
break;
case 0x6D646864:
return ((MDHD *)this)->toPrettyString(indent);
break;
case 0x73747473:
return ((STTS *)this)->toPrettyString(indent);
break;
case 0x63747473:
return ((CTTS *)this)->toPrettyString(indent);
break;
case 0x73747363:
return ((STSC *)this)->toPrettyString(indent);
break;
case 0x7374636F:
return ((STCO *)this)->toPrettyString(indent);
break;
case 0x636F3634:
return ((CO64 *)this)->toPrettyString(indent);
break;
case 0x7374737A:
return ((STSZ *)this)->toPrettyString(indent);
break;
case 0x73747364:
return ((STSD *)this)->toPrettyString(indent);
break;
case 0x6D703461: // mp4a case 0x6D703461: // mp4a
case 0x656E6361: // enca case 0x656E6361: // enca
case 0x61632D33: // ac-3 case 0x61632D33: // ac-3
return ((MP4A *)this)->toPrettyString(indent); return ((MP4A *)this)->toPrettyString(indent);
break; break;
case 0x64616333: case 0x64616333: return ((DAC3 *)this)->toPrettyString(indent); break;
return ((DAC3 *)this)->toPrettyString(indent); case 0x61616320: return ((AAC *)this)->toPrettyString(indent); break;
break;
case 0x61616320:
return ((AAC *)this)->toPrettyString(indent);
break;
case 0x68766331: case 0x68766331:
case 0x68657631: case 0x68657631: return ((HEV1 *)this)->toPrettyString(indent); break;
return ((HEV1 *)this)->toPrettyString(indent);
break;
case 0x61766331: case 0x61766331:
case 0x656E6376: // encv case 0x656E6376: // encv
return ((AVC1 *)this)->toPrettyString(indent); return ((AVC1 *)this)->toPrettyString(indent);
@ -389,61 +276,25 @@ namespace MP4 {
case 0x68323634: // h264 case 0x68323634: // h264
return ((H264 *)this)->toPrettyString(indent); return ((H264 *)this)->toPrettyString(indent);
break; break;
case 0x6669656C: case 0x6669656C: return ((FIEL *)this)->toPrettyString(indent); break;
return ((FIEL *)this)->toPrettyString(indent); case 0x74726566: return ((TREF *)this)->toPrettyString(indent); break;
break; case 0x676D6864: return ((GMHD *)this)->toPrettyString(indent); break;
case 0x74726566: case 0x65647473: return ((EDTS *)this)->toPrettyString(indent); break;
return ((TREF *)this)->toPrettyString(indent); case 0x73747373: return ((STSS *)this)->toPrettyString(indent); break;
break; case 0x6D657461: return ((META *)this)->toPrettyString(indent); break;
case 0x676D6864: case 0x656C7374: return ((ELST *)this)->toPrettyString(indent); break;
return ((GMHD *)this)->toPrettyString(indent); case 0x65736473: return ((ESDS *)this)->toPrettyString(indent); break;
break; case 0x75647461: return ((UDTA *)this)->toPrettyString(indent); break;
case 0x65647473: case 0x75756964: return ((UUID *)this)->toPrettyString(indent); break;
return ((EDTS *)this)->toPrettyString(indent); case 0x70617370: return ((PASP *)this)->toPrettyString(indent); break;
break;
case 0x73747373:
return ((STSS *)this)->toPrettyString(indent);
break;
case 0x6D657461:
return ((META *)this)->toPrettyString(indent);
break;
case 0x656C7374:
return ((ELST *)this)->toPrettyString(indent);
break;
case 0x65736473:
return ((ESDS *)this)->toPrettyString(indent);
break;
case 0x75647461:
return ((UDTA *)this)->toPrettyString(indent);
break;
case 0x75756964:
return ((UUID *)this)->toPrettyString(indent);
break;
case 0x70617370:
return ((PASP*)this)->toPrettyString(indent);
break;
/*LTS-START*/ /*LTS-START*/
case 0x73696478: case 0x73696478: return ((SIDX *)this)->toPrettyString(indent); break;
return ((SIDX*)this)->toPrettyString(indent); case 0x74666474: return ((TFDT *)this)->toPrettyString(indent); break;
break; case 0x696F6473: return ((IODS *)this)->toPrettyString(indent); break;
case 0x74666474: case 0x73696E66: return ((SINF *)this)->toPrettyString(indent); break;
return ((TFDT*)this)->toPrettyString(indent); case 0x66726D61: return ((FRMA *)this)->toPrettyString(indent); break;
break; case 0x7363686D: return ((SCHM *)this)->toPrettyString(indent); break;
case 0x696F6473: case 0x73636869: return ((SCHI *)this)->toPrettyString(indent); break;
return ((IODS*)this)->toPrettyString(indent);
break;
case 0x73696E66:
return ((SINF *)this)->toPrettyString(indent);
break;
case 0x66726D61:
return ((FRMA *)this)->toPrettyString(indent);
break;
case 0x7363686D:
return ((SCHM *)this)->toPrettyString(indent);
break;
case 0x73636869:
return ((SCHI *)this)->toPrettyString(indent);
break;
case 0x74783367: case 0x74783367:
INFO_MSG("TX3G box found!"); INFO_MSG("TX3G box found!");
return ((TX3G *)this)->toPrettyString(indent); return ((TX3G *)this)->toPrettyString(indent);
@ -452,28 +303,17 @@ namespace MP4 {
INFO_MSG("FTAB box found!"); INFO_MSG("FTAB box found!");
return ((FontTableBox *)this)->toPrettyString(indent); return ((FontTableBox *)this)->toPrettyString(indent);
break; break;
case 0x70737368: case 0x70737368: return ((PSSH *)this)->toPrettyString(indent); break;
return ((PSSH *)this)->toPrettyString(indent); case 0x73656E63: return ((SENC *)this)->toPrettyString(indent); break;
break; case 0x74656E63: return ((TENC *)this)->toPrettyString(indent); break;
case 0x73656E63: case 0x7361697A: return ((SAIZ *)this)->toPrettyString(indent); break;
return ((SENC *)this)->toPrettyString(indent); case 0x7361696F: return ((SAIO *)this)->toPrettyString(indent); break;
break;
case 0x74656E63:
return ((TENC *)this)->toPrettyString(indent);
break;
case 0x7361697A:
return ((SAIZ *)this)->toPrettyString(indent);
break;
case 0x7361696F:
return ((SAIO *)this)->toPrettyString(indent);
break;
/*LTS-END*/ /*LTS-END*/
default: default: INFO_MSG("no code found: 0x%.8x", Bit::btohl(data + 4)); break;
INFO_MSG("no code found: 0x%.8x",Bit::btohl(data + 4));
break;
} }
std::stringstream retval; std::stringstream retval;
retval << std::string(indent, ' ') << "Unimplemented pretty-printing for box " << std::string(data + 4, 4) << " (" << ntohl(((int*)data)[0]) << ")\n"; retval << std::string(indent, ' ') << "Unimplemented pretty-printing for box "
<< std::string(data + 4, 4) << " (" << ntohl(((int *)data)[0]) << ")\n";
/// \todo Implement hexdump for unimplemented boxes? /// \todo Implement hexdump for unimplemented boxes?
return retval.str(); return retval.str();
} }
@ -484,9 +324,7 @@ namespace MP4 {
void Box::setInt8(char newData, size_t index){ void Box::setInt8(char newData, size_t index){
index += payloadOffset; index += payloadOffset;
if (index >= boxedSize()){ if (index >= boxedSize()){
if (!reserve(index, 0, 1)) { if (!reserve(index, 0, 1)){return;}
return;
}
} }
data[index] = newData; data[index] = newData;
} }
@ -497,9 +335,7 @@ namespace MP4 {
char Box::getInt8(size_t index){ char Box::getInt8(size_t index){
index += payloadOffset; index += payloadOffset;
if (index >= boxedSize()){ if (index >= boxedSize()){
if (!reserve(index, 0, 1)) { if (!reserve(index, 0, 1)){return 0;}
return 0;
}
setInt8(0, index - payloadOffset); setInt8(0, index - payloadOffset);
} }
return data[index]; return data[index];
@ -509,9 +345,7 @@ namespace MP4 {
/// Returns zero if out of bounds. /// Returns zero if out of bounds.
char Box::getInt8(size_t index) const{ char Box::getInt8(size_t index) const{
index += payloadOffset; index += payloadOffset;
if (index >= boxedSize()) { if (index >= boxedSize()){return 0;}
return 0;
}
return data[index]; return data[index];
} }
@ -521,9 +355,7 @@ namespace MP4 {
void Box::setInt16(short newData, size_t index){ void Box::setInt16(short newData, size_t index){
index += payloadOffset; index += payloadOffset;
if (index + 1 >= boxedSize()){ if (index + 1 >= boxedSize()){
if (!reserve(index, 0, 2)) { if (!reserve(index, 0, 2)){return;}
return;
}
} }
Bit::htobs(data + index, newData); Bit::htobs(data + index, newData);
} }
@ -534,9 +366,7 @@ namespace MP4 {
short Box::getInt16(size_t index){ short Box::getInt16(size_t index){
index += payloadOffset; index += payloadOffset;
if (index + 1 >= boxedSize()){ if (index + 1 >= boxedSize()){
if (!reserve(index, 0, 2)) { if (!reserve(index, 0, 2)){return 0;}
return 0;
}
setInt16(0, index - payloadOffset); setInt16(0, index - payloadOffset);
} }
return Bit::btohs(data + index); return Bit::btohs(data + index);
@ -547,9 +377,7 @@ namespace MP4 {
/// Returns zero if resizing failed. /// Returns zero if resizing failed.
short Box::getInt16(size_t index) const{ short Box::getInt16(size_t index) const{
index += payloadOffset; index += payloadOffset;
if (index + 1 >= boxedSize()) { if (index + 1 >= boxedSize()){return 0;}
return 0;
}
return Bit::btohs(data + index); return Bit::btohs(data + index);
} }
@ -559,9 +387,7 @@ namespace MP4 {
void Box::setInt24(uint32_t newData, size_t index){ void Box::setInt24(uint32_t newData, size_t index){
index += payloadOffset; index += payloadOffset;
if (index + 2 >= boxedSize()){ if (index + 2 >= boxedSize()){
if (!reserve(index, 0, 3)) { if (!reserve(index, 0, 3)){return;}
return;
}
} }
Bit::htob24(data + index, newData); Bit::htob24(data + index, newData);
} }
@ -572,9 +398,7 @@ namespace MP4 {
uint32_t Box::getInt24(size_t index){ uint32_t Box::getInt24(size_t index){
index += payloadOffset; index += payloadOffset;
if (index + 2 >= boxedSize()){ if (index + 2 >= boxedSize()){
if (!reserve(index, 0, 3)) { if (!reserve(index, 0, 3)){return 0;}
return 0;
}
setInt24(0, index - payloadOffset); setInt24(0, index - payloadOffset);
} }
return Bit::btoh24(data + index); return Bit::btoh24(data + index);
@ -585,9 +409,7 @@ namespace MP4 {
/// Returns zero if resizing failed. /// Returns zero if resizing failed.
uint32_t Box::getInt24(size_t index) const{ uint32_t Box::getInt24(size_t index) const{
index += payloadOffset; index += payloadOffset;
if (index + 2 >= boxedSize()) { if (index + 2 >= boxedSize()){return 0;}
return 0;
}
return Bit::btoh24(data + index); return Bit::btoh24(data + index);
} }
@ -597,9 +419,7 @@ namespace MP4 {
void Box::setInt32(uint32_t newData, size_t index){ void Box::setInt32(uint32_t newData, size_t index){
index += payloadOffset; index += payloadOffset;
if (index + 3 >= boxedSize()){ if (index + 3 >= boxedSize()){
if (!reserve(index, 0, 4)) { if (!reserve(index, 0, 4)){return;}
return;
}
} }
Bit::htobl(data + index, newData); Bit::htobl(data + index, newData);
} }
@ -610,9 +430,7 @@ namespace MP4 {
uint32_t Box::getInt32(size_t index){ uint32_t Box::getInt32(size_t index){
index += payloadOffset; index += payloadOffset;
if (index + 3 >= boxedSize()){ if (index + 3 >= boxedSize()){
if (!reserve(index, 0, 4)) { if (!reserve(index, 0, 4)){return 0;}
return 0;
}
setInt32(0, index - payloadOffset); setInt32(0, index - payloadOffset);
} }
return Bit::btohl(data + index); return Bit::btohl(data + index);
@ -623,9 +441,7 @@ namespace MP4 {
/// Returns zero if resizing failed. /// Returns zero if resizing failed.
uint32_t Box::getInt32(size_t index) const{ uint32_t Box::getInt32(size_t index) const{
index += payloadOffset; index += payloadOffset;
if (index + 3 >= boxedSize()) { if (index + 3 >= boxedSize()){return 0;}
return 0;
}
return Bit::btohl(data + index); return Bit::btohl(data + index);
} }
@ -635,9 +451,7 @@ namespace MP4 {
void Box::setInt64(uint64_t newData, size_t index){ void Box::setInt64(uint64_t newData, size_t index){
index += payloadOffset; index += payloadOffset;
if (index + 7 >= boxedSize()){ if (index + 7 >= boxedSize()){
if (!reserve(index, 0, 8)) { if (!reserve(index, 0, 8)){return;}
return;
}
} }
Bit::htobll(data + index, newData); Bit::htobll(data + index, newData);
} }
@ -648,9 +462,7 @@ namespace MP4 {
uint64_t Box::getInt64(size_t index){ uint64_t Box::getInt64(size_t index){
index += payloadOffset; index += payloadOffset;
if (index + 7 >= boxedSize()){ if (index + 7 >= boxedSize()){
if (!reserve(index, 0, 8)) { if (!reserve(index, 0, 8)){return 0;}
return 0;
}
setInt64(0, index - payloadOffset); setInt64(0, index - payloadOffset);
} }
return Bit::btohll(data + index); return Bit::btohll(data + index);
@ -661,9 +473,7 @@ namespace MP4 {
/// Returns zero if resizing failed. /// Returns zero if resizing failed.
uint64_t Box::getInt64(size_t index) const{ uint64_t Box::getInt64(size_t index) const{
index += payloadOffset; index += payloadOffset;
if (index + 7 >= boxedSize()) { if (index + 7 >= boxedSize()){return 0;}
return 0;
}
return Bit::btohll(data + index); return Bit::btohll(data + index);
} }
@ -680,15 +490,11 @@ namespace MP4 {
void Box::setString(char *newData, size_t size, size_t index){ void Box::setString(char *newData, size_t size, size_t index){
index += payloadOffset; index += payloadOffset;
if (index >= boxedSize()){ if (index >= boxedSize()){
if (!reserve(index, 0, 1)) { if (!reserve(index, 0, 1)){return;}
return;
}
data[index] = 0; data[index] = 0;
} }
if (getStringLen(index) != size){ if (getStringLen(index) != size){
if (!reserve(index, getStringLen(index) + 1, size + 1)) { if (!reserve(index, getStringLen(index) + 1, size + 1)){return;}
return;
}
} }
memcpy(data + index, newData, size + 1); memcpy(data + index, newData, size + 1);
} }
@ -699,9 +505,7 @@ namespace MP4 {
char *Box::getString(size_t index){ char *Box::getString(size_t index){
index += payloadOffset; index += payloadOffset;
if (index >= boxedSize()){ if (index >= boxedSize()){
if (!reserve(index, 0, 1)) { if (!reserve(index, 0, 1)){return 0;}
return 0;
}
data[index] = 0; data[index] = 0;
} }
return data + index; return data + index;
@ -711,9 +515,7 @@ namespace MP4 {
/// Returns 0 if out of range. /// Returns 0 if out of range.
size_t Box::getStringLen(size_t index) const{ size_t Box::getStringLen(size_t index) const{
index += payloadOffset; index += payloadOffset;
if (index >= boxedSize()) { if (index >= boxedSize()){return 0;}
return 0;
}
return strlen(data + index); return strlen(data + index);
} }
@ -739,9 +541,7 @@ namespace MP4 {
/// Returns undefined values if there is no box at the given position. /// Returns undefined values if there is no box at the given position.
/// Returns 0 if out of range. /// Returns 0 if out of range.
size_t Box::getBoxLen(size_t index) const{ size_t Box::getBoxLen(size_t index) const{
if ((index + payloadOffset + 8) >= boxedSize()) { if ((index + payloadOffset + 8) >= boxedSize()){return 0;}
return 0;
}
return calcBoxSize(data + index + payloadOffset); return calcBoxSize(data + index + payloadOffset);
} }
@ -750,33 +550,23 @@ namespace MP4 {
void Box::setBox(Box &newEntry, size_t index){ void Box::setBox(Box &newEntry, size_t index){
int oldlen = getBoxLen(index); int oldlen = getBoxLen(index);
int newlen = newEntry.boxedSize(); int newlen = newEntry.boxedSize();
if (oldlen != newlen && !reserve(index + payloadOffset, oldlen, newlen)) { if (oldlen != newlen && !reserve(index + payloadOffset, oldlen, newlen)){return;}
return;
}
memcpy(data + index + payloadOffset, newEntry.asBox(), newlen); memcpy(data + index + payloadOffset, newEntry.asBox(), newlen);
} }
/// Attempts to reserve enough space for wanted bytes of data at given position, where current bytes of data is now reserved. /// Attempts to reserve enough space for wanted bytes of data at given position, where current
/// This will move any existing data behind the currently reserved space to the proper location after reserving. /// bytes of data is now reserved. This will move any existing data behind the currently reserved
/// \returns True on success, false otherwise. /// space to the proper location after reserving. \returns True on success, false otherwise.
bool Box::reserve(size_t position, size_t current, size_t wanted){ bool Box::reserve(size_t position, size_t current, size_t wanted){
if (current == wanted) { if (current == wanted){return true;}
return true; if (position > boxedSize()){wanted += position - boxedSize();}
}
if (position > boxedSize()) {
wanted += position - boxedSize();
}
if (current < wanted){ if (current < wanted){
// make bigger // make bigger
if (boxedSize() + (wanted - current) > data_size){ if (boxedSize() + (wanted - current) > data_size){
// realloc if managed, otherwise fail // realloc if managed, otherwise fail
if (!managed) { if (!managed){return false;}
return false;
}
void *ret = realloc(data, boxedSize() + (wanted - current)); void *ret = realloc(data, boxedSize() + (wanted - current));
if (!ret) { if (!ret){return false;}
return false;
}
data = (char *)ret; data = (char *)ret;
memset(data + boxedSize(), 0, wanted - current); // initialize to 0 memset(data + boxedSize(), 0, wanted - current); // initialize to 0
data_size = boxedSize() + (wanted - current); data_size = boxedSize() + (wanted - current);
@ -794,25 +584,15 @@ namespace MP4 {
return true; return true;
} }
fullBox::fullBox() { fullBox::fullBox(){setVersion(0);}
setVersion(0);
}
void fullBox::setVersion(char newVersion) { void fullBox::setVersion(char newVersion){setInt8(newVersion, 0);}
setInt8(newVersion, 0);
}
char fullBox::getVersion() const { char fullBox::getVersion() const{return getInt8(0);}
return getInt8(0);
}
void fullBox::setFlags(uint32_t newFlags) { void fullBox::setFlags(uint32_t newFlags){setInt24(newFlags, 1);}
setInt24(newFlags, 1);
}
uint32_t fullBox::getFlags() const { uint32_t fullBox::getFlags() const{return getInt24(1);}
return getInt24(1);
}
std::string fullBox::toPrettyString(uint32_t indent) const{ std::string fullBox::toPrettyString(uint32_t indent) const{
std::stringstream r; std::stringstream r;
@ -821,9 +601,7 @@ namespace MP4 {
return r.str(); return r.str();
} }
containerBox::containerBox() { containerBox::containerBox(){}
}
uint32_t containerBox::getContentCount(){ uint32_t containerBox::getContentCount(){
int res = 0; int res = 0;
@ -842,9 +620,7 @@ namespace MP4 {
if (i < contentCount){ if (i < contentCount){
tempLoc += getBoxLen(tempLoc); tempLoc += getBoxLen(tempLoc);
}else{ }else{
if (!reserve(tempLoc, 0, (no - contentCount) * 8)) { if (!reserve(tempLoc, 0, (no - contentCount) * 8)){return;};
return;
};
memset(data + tempLoc, 0, (no - contentCount) * 8); memset(data + tempLoc, 0, (no - contentCount) * 8);
tempLoc += (no - contentCount) * 8; tempLoc += (no - contentCount) * 8;
break; break;
@ -855,9 +631,7 @@ namespace MP4 {
Box &containerBox::getContent(uint32_t no, bool unsafe){ Box &containerBox::getContent(uint32_t no, bool unsafe){
static Box ret = Box((char *)"\000\000\000\010erro", false); static Box ret = Box((char *)"\000\000\000\010erro", false);
if (!unsafe && no > getContentCount()) { if (!unsafe && no > getContentCount()){return ret;}
return ret;
}
unsigned int i = 0; unsigned int i = 0;
int tempLoc = 0; int tempLoc = 0;
while (i < no){ while (i < no){
@ -871,9 +645,7 @@ namespace MP4 {
uint32_t count = getContentCount(); uint32_t count = getContentCount();
for (uint32_t i = 0; i < count; i++){ for (uint32_t i = 0; i < count; i++){
Box &thisChild = getContent(i); Box &thisChild = getContent(i);
if (thisChild.isType(boxName)){ if (thisChild.isType(boxName)){return Box(thisChild.asBox(), false);}
return Box(thisChild.asBox(), false);
}
} }
return Box((char *)"\000\000\000\010erro", false); return Box((char *)"\000\000\000\010erro", false);
} }
@ -883,9 +655,7 @@ namespace MP4 {
uint32_t count = getContentCount(); uint32_t count = getContentCount();
for (uint32_t i = 0; i < count; i++){ for (uint32_t i = 0; i < count; i++){
Box &thisChild = getContent(i); Box &thisChild = getContent(i);
if (thisChild.isType(boxName)){ if (thisChild.isType(boxName)){res.push_back(Box(thisChild.asBox(), false));}
res.push_back(Box(thisChild.asBox(), false));
}
} }
return res; return res;
} }
@ -921,9 +691,7 @@ namespace MP4 {
if (i < contentCount){ if (i < contentCount){
tempLoc += getBoxLen(tempLoc); tempLoc += getBoxLen(tempLoc);
}else{ }else{
if (!reserve(tempLoc, 0, (no - contentCount) * 8)) { if (!reserve(tempLoc, 0, (no - contentCount) * 8)){return;};
return;
};
memset(data + tempLoc, 0, (no - contentCount) * 8); memset(data + tempLoc, 0, (no - contentCount) * 8);
tempLoc += (no - contentCount) * 8; tempLoc += (no - contentCount) * 8;
break; break;
@ -934,9 +702,7 @@ namespace MP4 {
Box &containerFullBox::getContent(uint32_t no){ Box &containerFullBox::getContent(uint32_t no){
static Box ret = Box((char *)"\000\000\000\010erro", false); static Box ret = Box((char *)"\000\000\000\010erro", false);
if (no > getContentCount()) { if (no > getContentCount()){return ret;}
return ret;
}
unsigned int i = 0; unsigned int i = 0;
int tempLoc = 4; int tempLoc = 4;
while (i < no){ while (i < no){
@ -961,4 +727,4 @@ namespace MP4 {
return r.str(); return r.str();
} }
} }// namespace MP4

View file

@ -1,17 +1,16 @@
#pragma once #pragma once
#include "dtsc.h"
#include "json.h"
#include <algorithm>
#include <cstdio>
#include <deque>
#include <iomanip>
#include <iostream>
#include <set>
#include <sstream>
#include <stdint.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include <set>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <stdint.h>
#include <sstream>
#include <deque>
#include <algorithm>
#include <vector>
#include "json.h"
#include "dtsc.h"
/// Contains all MP4 format related code. /// Contains all MP4 format related code.
namespace MP4{ namespace MP4{
@ -19,16 +18,13 @@ namespace MP4 {
bool skipBox(FILE *newData); bool skipBox(FILE *newData);
uint64_t calcBoxSize(const char *p); uint64_t calcBoxSize(const char *p);
class Box{ class Box{
public: public:
Box(char *datapointer = 0, bool manage = true); Box(char *datapointer = 0, bool manage = true);
Box(const Box &rs); Box(const Box &rs);
Box &operator=(const Box &rs); Box &operator=(const Box &rs);
~Box(); ~Box();
operator bool() const { operator bool() const{return data && data_size >= 8 && !isType("erro");}
return data && data_size >= 8 && !isType("erro");
}
void copyFrom(const Box &rs); void copyFrom(const Box &rs);
std::string getType() const; std::string getType() const;
@ -42,6 +38,7 @@ namespace MP4 {
char *payload(); char *payload();
void clear(); void clear();
std::string toPrettyString(uint32_t indent = 0) const; std::string toPrettyString(uint32_t indent = 0) const;
protected: protected:
// integer functions // integer functions
void setInt8(char newData, size_t index); void setInt8(char newData, size_t index);
@ -98,15 +95,13 @@ namespace MP4 {
Box &getContent(uint32_t no, bool unsafe = false); Box &getContent(uint32_t no, bool unsafe = false);
std::string toPrettyString(uint32_t indent = 0); std::string toPrettyString(uint32_t indent = 0);
Box getChild(const char *boxName); Box getChild(const char *boxName);
template <typename T> template <typename T> T getChild(){
T getChild(){
T a; T a;
MP4::Box r = getChild(a.getType().c_str()); MP4::Box r = getChild(a.getType().c_str());
return (T &)r; return (T &)r;
} }
std::deque<Box> getChildren(const char *boxName); std::deque<Box> getChildren(const char *boxName);
template <typename T> template <typename T> std::deque<T> getChildren(){
std::deque<T> getChildren(){
T a; T a;
std::deque<Box> tmpRes = getChildren(a.getType().c_str()); std::deque<Box> tmpRes = getChildren(a.getType().c_str());
std::deque<T> res; std::deque<T> res;
@ -124,4 +119,4 @@ namespace MP4 {
Box &getContent(uint32_t no); Box &getContent(uint32_t no);
std::string toPrettyCFBString(uint32_t indent, std::string boxName); std::string toPrettyCFBString(uint32_t indent, std::string boxName);
}; };
} }// namespace MP4

View file

@ -20,89 +20,54 @@ namespace MP4 {
setMetaData(empty); setMetaData(empty);
} }
void ABST::setVersion(char newVersion) { void ABST::setVersion(char newVersion){setInt8(newVersion, 0);}
setInt8(newVersion, 0);
}
char ABST::getVersion() { char ABST::getVersion(){return getInt8(0);}
return getInt8(0);
}
void ABST::setFlags(uint32_t newFlags) { void ABST::setFlags(uint32_t newFlags){setInt24(newFlags, 1);}
setInt24(newFlags, 1);
}
uint32_t ABST::getFlags() { uint32_t ABST::getFlags(){return getInt24(1);}
return getInt24(1);
}
void ABST::setBootstrapinfoVersion(uint32_t newVersion) { void ABST::setBootstrapinfoVersion(uint32_t newVersion){setInt32(newVersion, 4);}
setInt32(newVersion, 4);
}
uint32_t ABST::getBootstrapinfoVersion() { uint32_t ABST::getBootstrapinfoVersion(){return getInt32(4);}
return getInt32(4);
}
void ABST::setProfile(char newProfile){ void ABST::setProfile(char newProfile){
// profile = bit 1 and 2 of byte 8. // profile = bit 1 and 2 of byte 8.
setInt8((getInt8(8) & 0x3F) + ((newProfile & 0x03) << 6), 8); setInt8((getInt8(8) & 0x3F) + ((newProfile & 0x03) << 6), 8);
} }
char ABST::getProfile() { char ABST::getProfile(){return (getInt8(8) & 0xC0);};
return (getInt8(8) & 0xC0);
}
;
void ABST::setLive(bool newLive){ void ABST::setLive(bool newLive){
// live = bit 4 of byte 8. // live = bit 4 of byte 8.
setInt8((getInt8(8) & 0xDF) + (newLive ? 0x10 : 0), 8); setInt8((getInt8(8) & 0xDF) + (newLive ? 0x10 : 0), 8);
} }
bool ABST::getLive() { bool ABST::getLive(){return (getInt8(8) & 0x10);}
return (getInt8(8) & 0x10);
}
void ABST::setUpdate(bool newUpdate){ void ABST::setUpdate(bool newUpdate){
// update = bit 5 of byte 8. // update = bit 5 of byte 8.
setInt8((getInt8(8) & 0xEF) + (newUpdate ? 0x08 : 0), 8); setInt8((getInt8(8) & 0xEF) + (newUpdate ? 0x08 : 0), 8);
} }
bool ABST::getUpdate() { bool ABST::getUpdate(){return (getInt8(8) & 0x08);}
return (getInt8(8) & 0x08);
}
void ABST::setTimeScale(uint32_t newScale) { void ABST::setTimeScale(uint32_t newScale){setInt32(newScale, 9);}
setInt32(newScale, 9);
}
uint32_t ABST::getTimeScale() { uint32_t ABST::getTimeScale(){return getInt32(9);}
return getInt32(9);
}
void ABST::setCurrentMediaTime(uint64_t newTime) { void ABST::setCurrentMediaTime(uint64_t newTime){setInt64(newTime, 13);}
setInt64(newTime, 13);
}
uint64_t ABST::getCurrentMediaTime() { uint64_t ABST::getCurrentMediaTime(){return getInt64(13);}
return getInt64(13);
}
void ABST::setSmpteTimeCodeOffset(uint64_t newTime) { void ABST::setSmpteTimeCodeOffset(uint64_t newTime){setInt64(newTime, 21);}
setInt64(newTime, 21);
}
uint64_t ABST::getSmpteTimeCodeOffset() { uint64_t ABST::getSmpteTimeCodeOffset(){return getInt64(21);}
return getInt64(21);
}
void ABST::setMovieIdentifier(std::string & newIdentifier) { void ABST::setMovieIdentifier(std::string &newIdentifier){setString(newIdentifier, 29);}
setString(newIdentifier, 29);
}
char * ABST::getMovieIdentifier() { char *ABST::getMovieIdentifier(){return getString(29);}
return getString(29);
}
uint32_t ABST::getServerEntryCount(){ uint32_t ABST::getServerEntryCount(){
int countLoc = 29 + getStringLen(29) + 1; int countLoc = 29 + getStringLen(29) + 1;
@ -114,16 +79,12 @@ namespace MP4 {
int tempLoc = countLoc + 1; int tempLoc = countLoc + 1;
// attempt to reach the wanted position // attempt to reach the wanted position
unsigned int i; unsigned int i;
for (i = 0; i < getInt8(countLoc) && i < no; ++i) { for (i = 0; i < getInt8(countLoc) && i < no; ++i){tempLoc += getStringLen(tempLoc) + 1;}
tempLoc += getStringLen(tempLoc) + 1;
}
// we are now either at the end, or at the right position // we are now either at the end, or at the right position
// let's reserve any unreserved space... // let's reserve any unreserved space...
if (no + 1 > getInt8(countLoc)){ if (no + 1 > getInt8(countLoc)){
int amount = no + 1 - getInt8(countLoc); int amount = no + 1 - getInt8(countLoc);
if (!reserve(payloadOffset + tempLoc, 0, amount)) { if (!reserve(payloadOffset + tempLoc, 0, amount)){return;};
return;
};
memset(data + payloadOffset + tempLoc, 0, amount); memset(data + payloadOffset + tempLoc, 0, amount);
setInt8(no + 1, countLoc); // set new qualityEntryCount setInt8(no + 1, countLoc); // set new qualityEntryCount
tempLoc += no - i; tempLoc += no - i;
@ -134,13 +95,9 @@ namespace MP4 {
///\return Empty string if no > serverEntryCount(), serverEntry[no] otherwise. ///\return Empty string if no > serverEntryCount(), serverEntry[no] otherwise.
const char *ABST::getServerEntry(uint32_t no){ const char *ABST::getServerEntry(uint32_t no){
if (no + 1 > getServerEntryCount()) { if (no + 1 > getServerEntryCount()){return "";}
return "";
}
int tempLoc = 29 + getStringLen(29) + 1 + 1; // position of first entry int tempLoc = 29 + getStringLen(29) + 1 + 1; // position of first entry
for (unsigned int i = 0; i < no; i++) { for (unsigned int i = 0; i < no; i++){tempLoc += getStringLen(tempLoc) + 1;}
tempLoc += getStringLen(tempLoc) + 1;
}
return getString(tempLoc); return getString(tempLoc);
} }
@ -160,16 +117,12 @@ namespace MP4 {
int tempLoc = countLoc + 1; int tempLoc = countLoc + 1;
// attempt to reach the wanted position // attempt to reach the wanted position
unsigned int i; unsigned int i;
for (i = 0; i < getInt8(countLoc) && i < no; ++i) { for (i = 0; i < getInt8(countLoc) && i < no; ++i){tempLoc += getStringLen(tempLoc) + 1;}
tempLoc += getStringLen(tempLoc) + 1;
}
// we are now either at the end, or at the right position // we are now either at the end, or at the right position
// let's reserve any unreserved space... // let's reserve any unreserved space...
if (no + 1 > getInt8(countLoc)){ if (no + 1 > getInt8(countLoc)){
int amount = no + 1 - getInt8(countLoc); int amount = no + 1 - getInt8(countLoc);
if (!reserve(payloadOffset + tempLoc, 0, amount)) { if (!reserve(payloadOffset + tempLoc, 0, amount)){return;};
return;
};
memset(data + payloadOffset + tempLoc, 0, amount); memset(data + payloadOffset + tempLoc, 0, amount);
setInt8(no + 1, countLoc); // set new qualityEntryCount setInt8(no + 1, countLoc); // set new qualityEntryCount
tempLoc += no - i; tempLoc += no - i;
@ -179,17 +132,13 @@ namespace MP4 {
} }
const char *ABST::getQualityEntry(uint32_t no){ const char *ABST::getQualityEntry(uint32_t no){
if (no > getQualityEntryCount()) { if (no > getQualityEntryCount()){return "";}
return "";
}
int tempLoc = 29 + getStringLen(29) + 1 + 1; // position of serverentries; int tempLoc = 29 + getStringLen(29) + 1 + 1; // position of serverentries;
for (unsigned int i = 0; i < getServerEntryCount(); i++){ for (unsigned int i = 0; i < getServerEntryCount(); i++){
tempLoc += getStringLen(tempLoc) + 1; tempLoc += getStringLen(tempLoc) + 1;
} }
tempLoc += 1; // first qualityentry tempLoc += 1; // first qualityentry
for (unsigned int i = 0; i < no; i++) { for (unsigned int i = 0; i < no; i++){tempLoc += getStringLen(tempLoc) + 1;}
tempLoc += getStringLen(tempLoc) + 1;
}
return getString(tempLoc); return getString(tempLoc);
} }
@ -272,16 +221,12 @@ namespace MP4 {
tempLoc++; // skip segmentRuntableCount tempLoc++; // skip segmentRuntableCount
// attempt to reach the wanted position // attempt to reach the wanted position
unsigned int i; unsigned int i;
for (i = 0; i < getInt8(countLoc) && i < no; ++i) { for (i = 0; i < getInt8(countLoc) && i < no; ++i){tempLoc += getBoxLen(tempLoc);}
tempLoc += getBoxLen(tempLoc);
}
// we are now either at the end, or at the right position // we are now either at the end, or at the right position
// let's reserve any unreserved space... // let's reserve any unreserved space...
if (no + 1 > getInt8(countLoc)){ if (no + 1 > getInt8(countLoc)){
int amount = no + 1 - getInt8(countLoc); int amount = no + 1 - getInt8(countLoc);
if (!reserve(payloadOffset + tempLoc, 0, amount * 8)) { if (!reserve(payloadOffset + tempLoc, 0, amount * 8)){return;};
return;
};
// set empty erro boxes as contents // set empty erro boxes as contents
for (int j = 0; j < amount; ++j){ for (int j = 0; j < amount; ++j){
memcpy(data + payloadOffset + tempLoc + j * 8, "\000\000\000\010erro", 8); memcpy(data + payloadOffset + tempLoc + j * 8, "\000\000\000\010erro", 8);
@ -310,9 +255,7 @@ namespace MP4 {
tempLoc += getStringLen(tempLoc) + 1; // DrmData tempLoc += getStringLen(tempLoc) + 1; // DrmData
tempLoc += getStringLen(tempLoc) + 1; // MetaData tempLoc += getStringLen(tempLoc) + 1; // MetaData
tempLoc++; // segmentRuntableCount tempLoc++; // segmentRuntableCount
for (unsigned int i = 0; i < no; ++i) { for (unsigned int i = 0; i < no; ++i){tempLoc += getBoxLen(tempLoc);}
tempLoc += getBoxLen(tempLoc);
}
return (ASRT &)getBox(tempLoc); return (ASRT &)getBox(tempLoc);
} }
@ -327,9 +270,7 @@ namespace MP4 {
} }
tempLoc += getStringLen(tempLoc) + 1; // DrmData tempLoc += getStringLen(tempLoc) + 1; // DrmData
tempLoc += getStringLen(tempLoc) + 1; // MetaData tempLoc += getStringLen(tempLoc) + 1; // MetaData
for (unsigned int i = getInt8(tempLoc++); i != 0; --i) { for (unsigned int i = getInt8(tempLoc++); i != 0; --i){tempLoc += getBoxLen(tempLoc);}
tempLoc += getBoxLen(tempLoc);
}
return getInt8(tempLoc); return getInt8(tempLoc);
} }
@ -344,23 +285,17 @@ namespace MP4 {
} }
tempLoc += getStringLen(tempLoc) + 1; // DrmData tempLoc += getStringLen(tempLoc) + 1; // DrmData
tempLoc += getStringLen(tempLoc) + 1; // MetaData tempLoc += getStringLen(tempLoc) + 1; // MetaData
for (unsigned int i = getInt8(tempLoc++); i != 0; --i) { for (unsigned int i = getInt8(tempLoc++); i != 0; --i){tempLoc += getBoxLen(tempLoc);}
tempLoc += getBoxLen(tempLoc);
}
int countLoc = tempLoc; int countLoc = tempLoc;
tempLoc++; tempLoc++;
// attempt to reach the wanted position // attempt to reach the wanted position
unsigned int i; unsigned int i;
for (i = 0; i < getInt8(countLoc) && i < no; ++i) { for (i = 0; i < getInt8(countLoc) && i < no; ++i){tempLoc += getBoxLen(tempLoc);}
tempLoc += getBoxLen(tempLoc);
}
// we are now either at the end, or at the right position // we are now either at the end, or at the right position
// let's reserve any unreserved space... // let's reserve any unreserved space...
if (no + 1 > getInt8(countLoc)){ if (no + 1 > getInt8(countLoc)){
unsigned int amount = no + 1 - getInt8(countLoc); unsigned int amount = no + 1 - getInt8(countLoc);
if (!reserve(payloadOffset + tempLoc, 0, amount * 8)) { if (!reserve(payloadOffset + tempLoc, 0, amount * 8)){return;};
return;
};
// set empty erro boxes as contents // set empty erro boxes as contents
for (unsigned int j = 0; j < amount; ++j){ for (unsigned int j = 0; j < amount; ++j){
memcpy(data + payloadOffset + tempLoc + j * 8, "\000\000\000\010erro", 8); memcpy(data + payloadOffset + tempLoc + j * 8, "\000\000\000\010erro", 8);
@ -388,13 +323,9 @@ namespace MP4 {
} }
tempLoc += getStringLen(tempLoc) + 1; // DrmData tempLoc += getStringLen(tempLoc) + 1; // DrmData
tempLoc += getStringLen(tempLoc) + 1; // MetaData tempLoc += getStringLen(tempLoc) + 1; // MetaData
for (unsigned int i = getInt8(tempLoc++); i != 0; --i) { for (unsigned int i = getInt8(tempLoc++); i != 0; --i){tempLoc += getBoxLen(tempLoc);}
tempLoc += getBoxLen(tempLoc);
}
tempLoc++; tempLoc++;
for (unsigned int i = 0; i < no; i++) { for (unsigned int i = 0; i < no; i++){tempLoc += getBoxLen(tempLoc);}
tempLoc += getBoxLen(tempLoc);
}
return (AFRT &)getBox(tempLoc); return (AFRT &)getBox(tempLoc);
} }
@ -428,11 +359,13 @@ namespace MP4 {
} }
r << std::string(indent + 1, ' ') << "DrmData " << getDrmData() << std::endl; r << std::string(indent + 1, ' ') << "DrmData " << getDrmData() << std::endl;
r << std::string(indent + 1, ' ') << "MetaData " << getMetaData() << std::endl; r << std::string(indent + 1, ' ') << "MetaData " << getMetaData() << std::endl;
r << std::string(indent + 1, ' ') << "SegmentRunTableEntries (" << getSegmentRunTableCount() << ")" << std::endl; r << std::string(indent + 1, ' ') << "SegmentRunTableEntries (" << getSegmentRunTableCount()
<< ")" << std::endl;
for (uint32_t i = 0; i < getSegmentRunTableCount(); i++){ for (uint32_t i = 0; i < getSegmentRunTableCount(); i++){
r << ((Box)getSegmentRunTable(i)).toPrettyString(indent + 2); r << ((Box)getSegmentRunTable(i)).toPrettyString(indent + 2);
} }
r << std::string(indent + 1, ' ') + "FragmentRunTableEntries (" << getFragmentRunTableCount() << ")" << std::endl; r << std::string(indent + 1, ' ') + "FragmentRunTableEntries (" << getFragmentRunTableCount()
<< ")" << std::endl;
for (uint32_t i = 0; i < getFragmentRunTableCount(); i++){ for (uint32_t i = 0; i < getFragmentRunTableCount(); i++){
r << ((Box)getFragmentRunTable(i)).toPrettyString(indent + 2); r << ((Box)getFragmentRunTable(i)).toPrettyString(indent + 2);
} }
@ -446,49 +379,31 @@ namespace MP4 {
setTimeScale(1000); setTimeScale(1000);
} }
void AFRT::setVersion(char newVersion) { void AFRT::setVersion(char newVersion){setInt8(newVersion, 0);}
setInt8(newVersion, 0);
}
uint32_t AFRT::getVersion() { uint32_t AFRT::getVersion(){return getInt8(0);}
return getInt8(0);
}
void AFRT::setUpdate(uint32_t newUpdate) { void AFRT::setUpdate(uint32_t newUpdate){setInt24(newUpdate, 1);}
setInt24(newUpdate, 1);
}
uint32_t AFRT::getUpdate() { uint32_t AFRT::getUpdate(){return getInt24(1);}
return getInt24(1);
}
void AFRT::setTimeScale(uint32_t newScale) { void AFRT::setTimeScale(uint32_t newScale){setInt32(newScale, 4);}
setInt32(newScale, 4);
}
uint32_t AFRT::getTimeScale() { uint32_t AFRT::getTimeScale(){return getInt32(4);}
return getInt32(4);
}
uint32_t AFRT::getQualityEntryCount() { uint32_t AFRT::getQualityEntryCount(){return getInt8(8);}
return getInt8(8);
}
void AFRT::setQualityEntry(std::string &newEntry, uint32_t no){ void AFRT::setQualityEntry(std::string &newEntry, uint32_t no){
int countLoc = 8; int countLoc = 8;
int tempLoc = countLoc + 1; int tempLoc = countLoc + 1;
// attempt to reach the wanted position // attempt to reach the wanted position
unsigned int i; unsigned int i;
for (i = 0; i < getQualityEntryCount() && i < no; ++i) { for (i = 0; i < getQualityEntryCount() && i < no; ++i){tempLoc += getStringLen(tempLoc) + 1;}
tempLoc += getStringLen(tempLoc) + 1;
}
// we are now either at the end, or at the right position // we are now either at the end, or at the right position
// let's reserve any unreserved space... // let's reserve any unreserved space...
if (no + 1 > getQualityEntryCount()){ if (no + 1 > getQualityEntryCount()){
int amount = no + 1 - getQualityEntryCount(); int amount = no + 1 - getQualityEntryCount();
if (!reserve(payloadOffset + tempLoc, 0, amount)) { if (!reserve(payloadOffset + tempLoc, 0, amount)){return;};
return;
};
memset(data + payloadOffset + tempLoc, 0, amount); memset(data + payloadOffset + tempLoc, 0, amount);
setInt8(no + 1, countLoc); // set new qualityEntryCount setInt8(no + 1, countLoc); // set new qualityEntryCount
tempLoc += no - i; tempLoc += no - i;
@ -498,13 +413,9 @@ namespace MP4 {
} }
const char *AFRT::getQualityEntry(uint32_t no){ const char *AFRT::getQualityEntry(uint32_t no){
if (no + 1 > getQualityEntryCount()) { if (no + 1 > getQualityEntryCount()){return "";}
return "";
}
int tempLoc = 9; // position of first quality entry int tempLoc = 9; // position of first quality entry
for (unsigned int i = 0; i < no; i++) { for (unsigned int i = 0; i < no; i++){tempLoc += getStringLen(tempLoc) + 1;}
tempLoc += getStringLen(tempLoc) + 1;
}
return getString(tempLoc); return getString(tempLoc);
} }
@ -539,19 +450,13 @@ namespace MP4 {
setInt32(newRun.firstFragment, tempLoc); setInt32(newRun.firstFragment, tempLoc);
setInt64(newRun.firstTimestamp, tempLoc + 4); setInt64(newRun.firstTimestamp, tempLoc + 4);
setInt32(newRun.duration, tempLoc + 12); setInt32(newRun.duration, tempLoc + 12);
if (newRun.duration == 0) { if (newRun.duration == 0){setInt8(newRun.discontinuity, tempLoc + 16);}
setInt8(newRun.discontinuity, tempLoc + 16); if (count < no + 1){setInt32(no + 1, countLoc);}
}
if (count < no + 1) {
setInt32(no + 1, countLoc);
}
} }
afrt_runtable AFRT::getFragmentRun(uint32_t no){ afrt_runtable AFRT::getFragmentRun(uint32_t no){
afrt_runtable res; afrt_runtable res;
if (no > getFragmentRunCount()) { if (no > getFragmentRunCount()){return res;}
return res;
}
int tempLoc = 9; int tempLoc = 9;
for (unsigned int i = 0; i < getQualityEntryCount(); i++){ for (unsigned int i = 0; i < getQualityEntryCount(); i++){
tempLoc += getStringLen(tempLoc) + 1; tempLoc += getStringLen(tempLoc) + 1;
@ -585,7 +490,8 @@ namespace MP4 {
r << std::string(indent + 1, ' ') << "Replacement or new table" << std::endl; r << std::string(indent + 1, ' ') << "Replacement or new table" << std::endl;
} }
r << std::string(indent + 1, ' ') << "Timescale " << getTimeScale() << std::endl; r << std::string(indent + 1, ' ') << "Timescale " << getTimeScale() << std::endl;
r << std::string(indent + 1, ' ') << "QualitySegmentUrlModifiers (" << getQualityEntryCount() << ")" << std::endl; r << std::string(indent + 1, ' ') << "QualitySegmentUrlModifiers (" << getQualityEntryCount()
<< ")" << std::endl;
for (unsigned int i = 0; i < getQualityEntryCount(); i++){ for (unsigned int i = 0; i < getQualityEntryCount(); i++){
r << std::string(indent + 2, ' ') << i << ": " << getQualityEntry(i) << std::endl; r << std::string(indent + 2, ' ') << i << ": " << getQualityEntry(i) << std::endl;
} }
@ -593,11 +499,13 @@ namespace MP4 {
for (unsigned int i = 0; i < getFragmentRunCount(); i++){ for (unsigned int i = 0; i < getFragmentRunCount(); i++){
afrt_runtable myRun = getFragmentRun(i); afrt_runtable myRun = getFragmentRun(i);
if (myRun.duration){ if (myRun.duration){
r << std::string(indent + 2, ' ') << i << ": " << myRun.firstFragment << " is at " << ((double)myRun.firstTimestamp / (double)getTimeScale()) r << std::string(indent + 2, ' ') << i << ": " << myRun.firstFragment << " is at "
<< "s, " << ((double)myRun.duration / (double)getTimeScale()) << "s per fragment." << std::endl; << ((double)myRun.firstTimestamp / (double)getTimeScale()) << "s, "
<< ((double)myRun.duration / (double)getTimeScale()) << "s per fragment." << std::endl;
}else{ }else{
r << std::string(indent + 2, ' ') << i << ": " << myRun.firstFragment << " is at " << ((double)myRun.firstTimestamp / (double)getTimeScale()) r << std::string(indent + 2, ' ') << i << ": " << myRun.firstFragment << " is at "
<< "s, discontinuity type " << myRun.discontinuity << std::endl; << ((double)myRun.firstTimestamp / (double)getTimeScale()) << "s, discontinuity type "
<< myRun.discontinuity << std::endl;
} }
} }
return r.str(); return r.str();
@ -609,41 +517,27 @@ namespace MP4 {
setUpdate(0); setUpdate(0);
} }
void ASRT::setVersion(char newVersion) { void ASRT::setVersion(char newVersion){setInt8(newVersion, 0);}
setInt8(newVersion, 0);
}
uint32_t ASRT::getVersion() { uint32_t ASRT::getVersion(){return getInt8(0);}
return getInt8(0);
}
void ASRT::setUpdate(uint32_t newUpdate) { void ASRT::setUpdate(uint32_t newUpdate){setInt24(newUpdate, 1);}
setInt24(newUpdate, 1);
}
uint32_t ASRT::getUpdate() { uint32_t ASRT::getUpdate(){return getInt24(1);}
return getInt24(1);
}
uint32_t ASRT::getQualityEntryCount() { uint32_t ASRT::getQualityEntryCount(){return getInt8(4);}
return getInt8(4);
}
void ASRT::setQualityEntry(std::string &newEntry, uint32_t no){ void ASRT::setQualityEntry(std::string &newEntry, uint32_t no){
int countLoc = 4; int countLoc = 4;
int tempLoc = countLoc + 1; int tempLoc = countLoc + 1;
// attempt to reach the wanted position // attempt to reach the wanted position
unsigned int i; unsigned int i;
for (i = 0; i < getQualityEntryCount() && i < no; ++i) { for (i = 0; i < getQualityEntryCount() && i < no; ++i){tempLoc += getStringLen(tempLoc) + 1;}
tempLoc += getStringLen(tempLoc) + 1;
}
// we are now either at the end, or at the right position // we are now either at the end, or at the right position
// let's reserve any unreserved space... // let's reserve any unreserved space...
if (no + 1 > getQualityEntryCount()){ if (no + 1 > getQualityEntryCount()){
int amount = no + 1 - getQualityEntryCount(); int amount = no + 1 - getQualityEntryCount();
if (!reserve(payloadOffset + tempLoc, 0, amount)) { if (!reserve(payloadOffset + tempLoc, 0, amount)){return;};
return;
};
memset(data + payloadOffset + tempLoc, 0, amount); memset(data + payloadOffset + tempLoc, 0, amount);
setInt8(no + 1, countLoc); // set new qualityEntryCount setInt8(no + 1, countLoc); // set new qualityEntryCount
tempLoc += no - i; tempLoc += no - i;
@ -653,13 +547,9 @@ namespace MP4 {
} }
const char *ASRT::getQualityEntry(uint32_t no){ const char *ASRT::getQualityEntry(uint32_t no){
if (no > getQualityEntryCount()) { if (no > getQualityEntryCount()){return "";}
return "";
}
int tempLoc = 5; // position of qualityentry count; int tempLoc = 5; // position of qualityentry count;
for (unsigned int i = 0; i < no; i++) { for (unsigned int i = 0; i < no; i++){tempLoc += getStringLen(tempLoc) + 1;}
tempLoc += getStringLen(tempLoc) + 1;
}
return getString(tempLoc); return getString(tempLoc);
} }
@ -687,9 +577,7 @@ namespace MP4 {
asrt_runtable ASRT::getSegmentRun(uint32_t no){ asrt_runtable ASRT::getSegmentRun(uint32_t no){
asrt_runtable res; asrt_runtable res;
if (no >= getSegmentRunEntryCount()) { if (no >= getSegmentRunEntryCount()){return res;}
return res;
}
int tempLoc = 5; // position of qualityentry count; int tempLoc = 5; // position of qualityentry count;
for (unsigned int i = 0; i < getQualityEntryCount(); ++i){ for (unsigned int i = 0; i < getQualityEntryCount(); ++i){
tempLoc += getStringLen(tempLoc) + 1; tempLoc += getStringLen(tempLoc) + 1;
@ -713,10 +601,11 @@ namespace MP4 {
for (unsigned int i = 0; i < getQualityEntryCount(); i++){ for (unsigned int i = 0; i < getQualityEntryCount(); i++){
r << std::string(indent + 2, ' ') << i << ": " << getQualityEntry(i) << std::endl; r << std::string(indent + 2, ' ') << i << ": " << getQualityEntry(i) << std::endl;
} }
r << std::string(indent + 1, ' ') << "SegmentRunEntryTable (" << getSegmentRunEntryCount() << ")" << std::endl; r << std::string(indent + 1, ' ') << "SegmentRunEntryTable (" << getSegmentRunEntryCount()
<< ")" << std::endl;
for (unsigned int i = 0; i < getSegmentRunEntryCount(); i++){ for (unsigned int i = 0; i < getSegmentRunEntryCount(); i++){
r << std::string(indent + 2, ' ') << i << ": First=" << getSegmentRun(i).firstSegment << ", FragmentsPerSegment=" r << std::string(indent + 2, ' ') << i << ": First=" << getSegmentRun(i).firstSegment
<< getSegmentRun(i).fragmentsPerSegment << std::endl; << ", FragmentsPerSegment=" << getSegmentRun(i).fragmentsPerSegment << std::endl;
} }
return r.str(); return r.str();
} }
@ -726,21 +615,13 @@ namespace MP4 {
setFlags(0); setFlags(0);
} }
void AFRA::setVersion(uint32_t newVersion) { void AFRA::setVersion(uint32_t newVersion){setInt8(newVersion, 0);}
setInt8(newVersion, 0);
}
uint32_t AFRA::getVersion() { uint32_t AFRA::getVersion(){return getInt8(0);}
return getInt8(0);
}
void AFRA::setFlags(uint32_t newFlags) { void AFRA::setFlags(uint32_t newFlags){setInt24(newFlags, 1);}
setInt24(newFlags, 1);
}
uint32_t AFRA::getFlags() { uint32_t AFRA::getFlags(){return getInt24(1);}
return getInt24(1);
}
void AFRA::setLongIDs(bool newVal){ void AFRA::setLongIDs(bool newVal){
if (newVal){ if (newVal){
@ -750,9 +631,7 @@ namespace MP4 {
} }
} }
bool AFRA::getLongIDs() { bool AFRA::getLongIDs(){return getInt8(4) & 0x80;}
return getInt8(4) & 0x80;
}
void AFRA::setLongOffsets(bool newVal){ void AFRA::setLongOffsets(bool newVal){
if (newVal){ if (newVal){
@ -762,9 +641,7 @@ namespace MP4 {
} }
} }
bool AFRA::getLongOffsets() { bool AFRA::getLongOffsets(){return getInt8(4) & 0x40;}
return getInt8(4) & 0x40;
}
void AFRA::setGlobalEntries(bool newVal){ void AFRA::setGlobalEntries(bool newVal){
if (newVal){ if (newVal){
@ -774,44 +651,30 @@ namespace MP4 {
} }
} }
bool AFRA::getGlobalEntries() { bool AFRA::getGlobalEntries(){return getInt8(4) & 0x20;}
return getInt8(4) & 0x20;
}
void AFRA::setTimeScale(uint32_t newVal) { void AFRA::setTimeScale(uint32_t newVal){setInt32(newVal, 5);}
setInt32(newVal, 5);
}
uint32_t AFRA::getTimeScale() { uint32_t AFRA::getTimeScale(){return getInt32(5);}
return getInt32(5);
}
uint32_t AFRA::getEntryCount() { uint32_t AFRA::getEntryCount(){return getInt32(9);}
return getInt32(9);
}
void AFRA::setEntry(afraentry newEntry, uint32_t no){ void AFRA::setEntry(afraentry newEntry, uint32_t no){
int entrysize = 12; int entrysize = 12;
if (getLongOffsets()) { if (getLongOffsets()){entrysize = 16;}
entrysize = 16;
}
setInt64(newEntry.time, 13 + entrysize * no); setInt64(newEntry.time, 13 + entrysize * no);
if (getLongOffsets()){ if (getLongOffsets()){
setInt64(newEntry.offset, 21 + entrysize * no); setInt64(newEntry.offset, 21 + entrysize * no);
}else{ }else{
setInt32(newEntry.offset, 21 + entrysize * no); setInt32(newEntry.offset, 21 + entrysize * no);
} }
if (no + 1 > getEntryCount()) { if (no + 1 > getEntryCount()){setInt32(no + 1, 9);}
setInt32(no + 1, 9);
}
} }
afraentry AFRA::getEntry(uint32_t no){ afraentry AFRA::getEntry(uint32_t no){
afraentry ret; afraentry ret;
int entrysize = 12; int entrysize = 12;
if (getLongOffsets()) { if (getLongOffsets()){entrysize = 16;}
entrysize = 16;
}
ret.time = getInt64(13 + entrysize * no); ret.time = getInt64(13 + entrysize * no);
if (getLongOffsets()){ if (getLongOffsets()){
ret.offset = getInt64(21 + entrysize * no); ret.offset = getInt64(21 + entrysize * no);
@ -822,28 +685,18 @@ namespace MP4 {
} }
uint32_t AFRA::getGlobalEntryCount(){ uint32_t AFRA::getGlobalEntryCount(){
if (!getGlobalEntries()) { if (!getGlobalEntries()){return 0;}
return 0;
}
int entrysize = 12; int entrysize = 12;
if (getLongOffsets()) { if (getLongOffsets()){entrysize = 16;}
entrysize = 16;
}
return getInt32(13 + entrysize * getEntryCount()); return getInt32(13 + entrysize * getEntryCount());
} }
void AFRA::setGlobalEntry(globalafraentry newEntry, uint32_t no){ void AFRA::setGlobalEntry(globalafraentry newEntry, uint32_t no){
int offset = 13 + 12 * getEntryCount() + 4; int offset = 13 + 12 * getEntryCount() + 4;
if (getLongOffsets()) { if (getLongOffsets()){offset = 13 + 16 * getEntryCount() + 4;}
offset = 13 + 16 * getEntryCount() + 4;
}
int entrysize = 20; int entrysize = 20;
if (getLongIDs()) { if (getLongIDs()){entrysize += 4;}
entrysize += 4; if (getLongOffsets()){entrysize += 8;}
}
if (getLongOffsets()) {
entrysize += 8;
}
setInt64(newEntry.time, offset + entrysize * no); setInt64(newEntry.time, offset + entrysize * no);
if (getLongIDs()){ if (getLongIDs()){
@ -861,24 +714,16 @@ namespace MP4 {
setInt32(newEntry.offsetfromafra, offset + entrysize * no + entrysize - 4); setInt32(newEntry.offsetfromafra, offset + entrysize * no + entrysize - 4);
} }
if (getInt32(offset - 4) < no + 1) { if (getInt32(offset - 4) < no + 1){setInt32(no + 1, offset - 4);}
setInt32(no + 1, offset - 4);
}
} }
globalafraentry AFRA::getGlobalEntry(uint32_t no){ globalafraentry AFRA::getGlobalEntry(uint32_t no){
globalafraentry ret; globalafraentry ret;
int offset = 13 + 12 * getEntryCount() + 4; int offset = 13 + 12 * getEntryCount() + 4;
if (getLongOffsets()) { if (getLongOffsets()){offset = 13 + 16 * getEntryCount() + 4;}
offset = 13 + 16 * getEntryCount() + 4;
}
int entrysize = 20; int entrysize = 20;
if (getLongIDs()) { if (getLongIDs()){entrysize += 4;}
entrysize += 4; if (getLongOffsets()){entrysize += 8;}
}
if (getLongOffsets()) {
entrysize += 8;
}
ret.time = getInt64(offset + entrysize * no); ret.time = getInt64(offset + entrysize * no);
if (getLongIDs()){ if (getLongIDs()){
@ -912,7 +757,8 @@ namespace MP4 {
r << std::string(indent + 1, ' ') << "Entries (" << count << ") " << std::endl; r << std::string(indent + 1, ' ') << "Entries (" << count << ") " << std::endl;
for (uint32_t i = 0; i < count; ++i){ for (uint32_t i = 0; i < count; ++i){
afraentry tmpent = getEntry(i); afraentry tmpent = getEntry(i);
r << std::string(indent + 1, ' ') << i << ": Time " << tmpent.time << ", Offset " << tmpent.offset << std::endl; r << std::string(indent + 1, ' ') << i << ": Time " << tmpent.time << ", Offset "
<< tmpent.offset << std::endl;
} }
if (getGlobalEntries()){ if (getGlobalEntries()){
@ -920,10 +766,10 @@ namespace MP4 {
r << std::string(indent + 1, ' ') << "Global Entries (" << count << ") " << std::endl; r << std::string(indent + 1, ' ') << "Global Entries (" << count << ") " << std::endl;
for (uint32_t i = 0; i < count; ++i){ for (uint32_t i = 0; i < count; ++i){
globalafraentry tmpent = getGlobalEntry(i); globalafraentry tmpent = getGlobalEntry(i);
r << std::string(indent + 1, ' ') << i << ": T " << tmpent.time << ", S" << tmpent.segment << "F" << tmpent.fragment << ", " r << std::string(indent + 1, ' ') << i << ": T " << tmpent.time << ", S" << tmpent.segment << "F"
<< tmpent.afraoffset << "/" << tmpent.offsetfromafra << std::endl; << tmpent.fragment << ", " << tmpent.afraoffset << "/" << tmpent.offsetfromafra << std::endl;
} }
} }
return r.str(); return r.str();
} }
} }// namespace MP4

View file

@ -135,5 +135,4 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0); std::string toPrettyString(uint32_t indent = 0);
}; };
} }// namespace MP4

View file

@ -1,5 +1,5 @@
#include "mp4_dash.h"
#include "defines.h" #include "defines.h"
#include "mp4_dash.h"
namespace MP4{ namespace MP4{
SIDX::SIDX(){ SIDX::SIDX(){
@ -8,21 +8,13 @@ namespace MP4 {
setFlags(0); setFlags(0);
} }
void SIDX::setReferenceID(uint32_t newReferenceID) { void SIDX::setReferenceID(uint32_t newReferenceID){setInt32(newReferenceID, 4);}
setInt32(newReferenceID, 4);
}
uint32_t SIDX::getReferenceID() { uint32_t SIDX::getReferenceID(){return getInt32(4);}
return getInt32(4);
}
void SIDX::setTimescale(uint32_t newTimescale) { void SIDX::setTimescale(uint32_t newTimescale){setInt32(newTimescale, 8);}
setInt32(newTimescale, 8);
}
uint32_t SIDX::getTimescale() { uint32_t SIDX::getTimescale(){return getInt32(8);}
return getInt32(8);
}
void SIDX::setEarliestPresentationTime(uint64_t newEarliestPresentationTime){ void SIDX::setEarliestPresentationTime(uint64_t newEarliestPresentationTime){
if (getVersion() == 0){ if (getVersion() == 0){
@ -33,9 +25,7 @@ namespace MP4 {
} }
uint64_t SIDX::getEarliestPresentationTime(){ uint64_t SIDX::getEarliestPresentationTime(){
if (getVersion() == 0) { if (getVersion() == 0){return getInt32(12);}
return getInt32(12);
}
return getInt64(12); return getInt64(12);
} }
@ -48,23 +38,17 @@ namespace MP4 {
} }
uint64_t SIDX::getFirstOffset(){ uint64_t SIDX::getFirstOffset(){
if (getVersion() == 0) { if (getVersion() == 0){return getInt32(16);}
return getInt32(16);
}
return getInt64(20); return getInt64(20);
} }
uint16_t SIDX::getReferenceCount(){ uint16_t SIDX::getReferenceCount(){
if (getVersion() == 0) { if (getVersion() == 0){return getInt16(22);}
return getInt16(22);
}
return getInt16(30); return getInt16(30);
} }
void SIDX::setReference(sidxReference &newRef, size_t index){ void SIDX::setReference(sidxReference &newRef, size_t index){
if (index >= getReferenceCount()) { if (index >= getReferenceCount()){setInt16(index + 1, (getVersion() == 0 ? 22 : 30));}
setInt16(index + 1, (getVersion() == 0 ? 22 : 30));
}
uint32_t offset = 24 + (index * 12) + (getVersion() == 0 ? 0 : 8); uint32_t offset = 24 + (index * 12) + (getVersion() == 0 ? 0 : 8);
uint32_t tmp = (newRef.referenceType ? 0x80000000 : 0) | newRef.referencedSize; uint32_t tmp = (newRef.referenceType ? 0x80000000 : 0) | newRef.referencedSize;
setInt32(tmp, offset); setInt32(tmp, offset);
@ -97,7 +81,8 @@ namespace MP4 {
r << fullBox::toPrettyString(indent); r << fullBox::toPrettyString(indent);
r << std::string(indent + 1, ' ') << "ReferenceID " << getReferenceID() << std::endl; r << std::string(indent + 1, ' ') << "ReferenceID " << getReferenceID() << std::endl;
r << std::string(indent + 1, ' ') << "Timescale " << getTimescale() << std::endl; r << std::string(indent + 1, ' ') << "Timescale " << getTimescale() << std::endl;
r << std::string(indent + 1, ' ') << "EarliestPresentationTime " << getEarliestPresentationTime() << std::endl; r << std::string(indent + 1, ' ') << "EarliestPresentationTime "
<< getEarliestPresentationTime() << std::endl;
r << std::string(indent + 1, ' ') << "FirstOffset " << getFirstOffset() << std::endl; r << std::string(indent + 1, ' ') << "FirstOffset " << getFirstOffset() << std::endl;
r << std::string(indent + 1, ' ') << "References [" << getReferenceCount() << "]" << std::endl; r << std::string(indent + 1, ' ') << "References [" << getReferenceCount() << "]" << std::endl;
for (int i = 0; i < getReferenceCount(); i++){ for (int i = 0; i < getReferenceCount(); i++){
@ -129,15 +114,14 @@ namespace MP4 {
} }
uint64_t TFDT::getBaseMediaDecodeTime(){ uint64_t TFDT::getBaseMediaDecodeTime(){
if (getVersion() == 1) { if (getVersion() == 1){return getInt64(4);}
return getInt64(4);
}
return getInt32(4); return getInt32(4);
} }
std::string TFDT::toPrettyString(uint32_t indent){ std::string TFDT::toPrettyString(uint32_t indent){
std::stringstream r; std::stringstream r;
r << std::string(indent, ' ') << "[tfdt] Track Fragment Base Media Decode Time Box (" << boxedSize() << ")" << std::endl; r << std::string(indent, ' ') << "[tfdt] Track Fragment Base Media Decode Time Box ("
<< boxedSize() << ")" << std::endl;
r << fullBox::toPrettyString(indent); r << fullBox::toPrettyString(indent);
r << std::string(indent + 1, ' ') << "BaseMediaDecodeTime " << getBaseMediaDecodeTime() << std::endl; r << std::string(indent + 1, ' ') << "BaseMediaDecodeTime " << getBaseMediaDecodeTime() << std::endl;
return r.str(); return r.str();
@ -157,85 +141,58 @@ namespace MP4 {
setODGraphicsLevel(0xFF); setODGraphicsLevel(0xFF);
} }
void IODS::setIODTypeTag(char value) { void IODS::setIODTypeTag(char value){setInt8(value, 4);}
setInt8(value, 4);
}
char IODS::getIODTypeTag() { char IODS::getIODTypeTag(){return getInt8(4);}
return getInt8(4);
}
void IODS::setDescriptorTypeLength(char length) { void IODS::setDescriptorTypeLength(char length){setInt8(length, 5);}
setInt8(length, 5);
}
char IODS::getDescriptorTypeLength() { char IODS::getDescriptorTypeLength(){return getInt8(5);}
return getInt8(5);
}
void IODS::setODID(short id) { void IODS::setODID(short id){setInt16(id, 6);}
setInt16(id, 6);
}
short IODS::getODID() { short IODS::getODID(){return getInt16(6);}
return getInt16(6);
}
void IODS::setODProfileLevel(char value) { void IODS::setODProfileLevel(char value){setInt8(value, 8);}
setInt8(value, 8);
}
char IODS::getODProfileLevel() { char IODS::getODProfileLevel(){return getInt8(8);}
return getInt8(8);
}
void IODS::setODSceneLevel(char value) { void IODS::setODSceneLevel(char value){setInt8(value, 9);}
setInt8(value, 9);
}
char IODS::getODSceneLevel() { char IODS::getODSceneLevel(){return getInt8(9);}
return getInt8(9);
}
void IODS::setODAudioLevel(char value) { void IODS::setODAudioLevel(char value){setInt8(value, 10);}
setInt8(value, 10);
}
char IODS::getODAudioLevel() { char IODS::getODAudioLevel(){return getInt8(10);}
return getInt8(10);
}
void IODS::setODVideoLevel(char value) { void IODS::setODVideoLevel(char value){setInt8(value, 11);}
setInt8(value, 11);
}
char IODS::getODVideoLevel() { char IODS::getODVideoLevel(){return getInt8(11);}
return getInt8(11);
}
void IODS::setODGraphicsLevel(char value) { void IODS::setODGraphicsLevel(char value){setInt8(value, 12);}
setInt8(value, 12);
}
char IODS::getODGraphicsLevel() {
return getInt8(12);
}
char IODS::getODGraphicsLevel(){return getInt8(12);}
std::string IODS::toPrettyString(uint32_t indent){ std::string IODS::toPrettyString(uint32_t indent){
std::stringstream r; std::stringstream r;
r << std::string(indent, ' ') << "[iods] IODS Box (" << boxedSize() << ")" << std::endl; r << std::string(indent, ' ') << "[iods] IODS Box (" << boxedSize() << ")" << std::endl;
r << fullBox::toPrettyString(indent); r << fullBox::toPrettyString(indent);
r << std::string(indent + 2, ' ') << "IOD Type Tag: " << std::hex << std::setw(2) << std::setfill('0') << (int)getIODTypeTag() << std::dec << std::endl; r << std::string(indent + 2, ' ') << "IOD Type Tag: " << std::hex << std::setw(2)
r << std::string(indent + 2, ' ') << "DescriptorTypeLength: " << std::hex << std::setw(2) << std::setfill('0') << (int)getDescriptorTypeLength() << std::dec << std::endl; << std::setfill('0') << (int)getIODTypeTag() << std::dec << std::endl;
r << std::string(indent + 2, ' ') << "OD ID: " << std::hex << std::setw(4) << std::setfill('0') << (int)getODID() << std::dec << std::endl; r << std::string(indent + 2, ' ') << "DescriptorTypeLength: " << std::hex << std::setw(2)
r << std::string(indent + 2, ' ') << "OD Profile Level: " << std::hex << std::setw(2) << std::setfill('0') << (int)getODProfileLevel() << std::dec << std::endl; << std::setfill('0') << (int)getDescriptorTypeLength() << std::dec << std::endl;
r << std::string(indent + 2, ' ') << "OD Scene Level: " << std::hex << std::setw(2) << std::setfill('0') << (int)getODSceneLevel() << std::dec << std::endl; r << std::string(indent + 2, ' ') << "OD ID: " << std::hex << std::setw(4) << std::setfill('0')
r << std::string(indent + 2, ' ') << "OD Audio Level: " << std::hex << std::setw(2) << std::setfill('0') << (int)getODAudioLevel() << std::dec << std::endl; << (int)getODID() << std::dec << std::endl;
r << std::string(indent + 2, ' ') << "OD Video Level: " << std::hex << std::setw(2) << std::setfill('0') << (int)getODVideoLevel() << std::dec << std::endl; r << std::string(indent + 2, ' ') << "OD Profile Level: " << std::hex << std::setw(2)
r << std::string(indent + 2, ' ') << "OD Graphics Level: " << std::hex << std::setw(2) << std::setfill('0') << (int)getODGraphicsLevel() << std::dec << std::endl; << std::setfill('0') << (int)getODProfileLevel() << std::dec << std::endl;
r << std::string(indent + 2, ' ') << "OD Scene Level: " << std::hex << std::setw(2)
<< std::setfill('0') << (int)getODSceneLevel() << std::dec << std::endl;
r << std::string(indent + 2, ' ') << "OD Audio Level: " << std::hex << std::setw(2)
<< std::setfill('0') << (int)getODAudioLevel() << std::dec << std::endl;
r << std::string(indent + 2, ' ') << "OD Video Level: " << std::hex << std::setw(2)
<< std::setfill('0') << (int)getODVideoLevel() << std::dec << std::endl;
r << std::string(indent + 2, ' ') << "OD Graphics Level: " << std::hex << std::setw(2)
<< std::setfill('0') << (int)getODGraphicsLevel() << std::dec << std::endl;
return r.str(); return r.str();
} }
} }// namespace MP4

View file

@ -69,5 +69,4 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0); std::string toPrettyString(uint32_t indent = 0);
}; };
} }// namespace MP4

View file

@ -1,15 +1,14 @@
#include "mp4_encryption.h"
#include "defines.h" #include "defines.h"
#include "mp4_encryption.h"
namespace MP4{ namespace MP4{
PSSH::PSSH() { PSSH::PSSH(){memcpy(data + 4, "pssh", 4);}
memcpy(data + 4, "pssh", 4);
}
std::string PSSH::toPrettyString(uint32_t indent){ std::string PSSH::toPrettyString(uint32_t indent){
std::stringstream r; std::stringstream r;
r << std::string(indent, ' ') << "[pssh] Protection System Specific Header Box (" << boxedSize() << ")" << std::endl; r << std::string(indent, ' ') << "[pssh] Protection System Specific Header Box (" << boxedSize()
<< ")" << std::endl;
r << fullBox::toPrettyString(indent); r << fullBox::toPrettyString(indent);
r << std::string(indent + 1, ' ') << "SystemID: " << getSystemIDHex() << std::endl; r << std::string(indent + 1, ' ') << "SystemID: " << getSystemIDHex() << std::endl;
if (getVersion()){ if (getVersion()){
@ -35,13 +34,9 @@ namespace MP4 {
return "0x" + res.str(); return "0x" + res.str();
} }
void PSSH::setSystemIDHex(const std::string & systemID) { void PSSH::setSystemIDHex(const std::string &systemID){setString(systemID, 4);}
setString(systemID, 4);
}
size_t PSSH::getKIDCount(){ size_t PSSH::getKIDCount(){return getVersion() ? getInt32(20) : 0;}
return getVersion() ? getInt32(20) : 0;
}
size_t PSSH::getDataSize(){ size_t PSSH::getDataSize(){
if (getVersion()){ if (getVersion()){
@ -64,9 +59,7 @@ namespace MP4 {
WARN_MSG("Not implemented yet!"); WARN_MSG("Not implemented yet!");
return; return;
} }
for (int i = 0; i < data.size(); i++){ for (int i = 0; i < data.size(); i++){setInt8(data[i], 24 + i);}
setInt8(data[i], 24 + i);
}
setInt32(data.size(), 20); setInt32(data.size(), 20);
} }
@ -90,23 +83,13 @@ namespace MP4 {
setDefaultIsEncrypted(1); setDefaultIsEncrypted(1);
setDefaultIVSize(8); setDefaultIVSize(8);
} }
size_t TENC::getDefaultIsEncrypted(){ size_t TENC::getDefaultIsEncrypted(){return getInt24(4);}
return getInt24(4); void TENC::setDefaultIsEncrypted(size_t isEncrypted){setInt24(isEncrypted, 4);}
} size_t TENC::getDefaultIVSize(){return getInt8(7);}
void TENC::setDefaultIsEncrypted(size_t isEncrypted){ void TENC::setDefaultIVSize(uint8_t ivSize){setInt8(ivSize, 7);}
setInt24(isEncrypted, 4);
}
size_t TENC::getDefaultIVSize(){
return getInt8(7);
}
void TENC::setDefaultIVSize(uint8_t ivSize){
setInt8(ivSize, 7);
}
std::string TENC::getDefaultKID(){ std::string TENC::getDefaultKID(){
std::string result; std::string result;
for (int i = 8; i < 24; i++){ for (int i = 8; i < 24; i++){result += getInt8(i);}
result += getInt8(i);
}
return result; return result;
} }
void TENC::setDefaultKID(const std::string &kid){ void TENC::setDefaultKID(const std::string &kid){
@ -123,9 +106,7 @@ namespace MP4 {
memcpy(data + 4, "senc", 4); memcpy(data + 4, "senc", 4);
setFlags(2); setFlags(2);
} }
uint32_t SENC::getSampleCount() const { uint32_t SENC::getSampleCount() const{return getInt32(4);}
return getInt32(4);
}
#define IV_SIZE 8 #define IV_SIZE 8
void SENC::setSample(UUID_SampleEncryption_Sample newSample, size_t index){ void SENC::setSample(UUID_SampleEncryption_Sample newSample, size_t index){
@ -141,8 +122,8 @@ namespace MP4 {
ERROR_MSG("First fill intermediate entries!"); ERROR_MSG("First fill intermediate entries!");
return; return;
/* /*
//we are now at the end of currently reserved space, reserve more and adapt offset accordingly. //we are now at the end of currently reserved space, reserve more and adapt offset
int reserveSize = ((index - getSampleCount())) * (IV_SIZE + (getFlags() & 0x02)); accordingly. int reserveSize = ((index - getSampleCount())) * (IV_SIZE + (getFlags() & 0x02));
reserveSize += IV_SIZE; reserveSize += IV_SIZE;
if (getFlags() & 0x02){ if (getFlags() & 0x02){
reserveSize += 2 + newSample.Entries.size(); reserveSize += 2 + newSample.Entries.size();
@ -160,22 +141,19 @@ namespace MP4 {
if (getFlags() & 0x02){ if (getFlags() & 0x02){
setInt16(newSample.Entries.size(), myOffset); setInt16(newSample.Entries.size(), myOffset);
myOffset += 2; myOffset += 2;
for (std::vector<UUID_SampleEncryption_Sample_Entry>::iterator it = newSample.Entries.begin(); it != newSample.Entries.end(); it++) { for (std::vector<UUID_SampleEncryption_Sample_Entry>::iterator it = newSample.Entries.begin();
it != newSample.Entries.end(); it++){
setInt16(it->BytesClear, myOffset); setInt16(it->BytesClear, myOffset);
myOffset += 2; myOffset += 2;
setInt32(it->BytesEncrypted, myOffset); setInt32(it->BytesEncrypted, myOffset);
myOffset += 4; myOffset += 4;
} }
} }
if (index >= getSampleCount()) { if (index >= getSampleCount()){setInt32(index + 1, 4);}
setInt32(index + 1, 4);
}
} }
UUID_SampleEncryption_Sample SENC::getSample(size_t index) const{ UUID_SampleEncryption_Sample SENC::getSample(size_t index) const{
if (index >= getSampleCount()) { if (index >= getSampleCount()){return UUID_SampleEncryption_Sample();}
return UUID_SampleEncryption_Sample();
}
int myOffset = 8; int myOffset = 8;
for (unsigned int i = 0; i < index; i++){ for (unsigned int i = 0; i < index; i++){
myOffset += IV_SIZE; myOffset += IV_SIZE;
@ -213,7 +191,8 @@ namespace MP4 {
r << std::string(indent + 1, ' ') << "[" << i << "]" << std::endl; r << std::string(indent + 1, ' ') << "[" << i << "]" << std::endl;
r << std::string(indent + 3, ' ') << "Initialization Vector: 0x"; r << std::string(indent + 3, ' ') << "Initialization Vector: 0x";
for (unsigned int j = 0; j < tmpSample.InitializationVector.size(); j++){ for (unsigned int j = 0; j < tmpSample.InitializationVector.size(); j++){
r << std::hex << std::setw(2) << std::setfill('0') << (int)tmpSample.InitializationVector[j] << std::dec; r << std::hex << std::setw(2) << std::setfill('0') << (int)tmpSample.InitializationVector[j]
<< std::dec;
} }
r << std::endl; r << std::endl;
if (getFlags() & 0x02){ if (getFlags() & 0x02){
@ -221,7 +200,8 @@ namespace MP4 {
for (unsigned int j = 0; j < tmpSample.NumberOfEntries; j++){ for (unsigned int j = 0; j < tmpSample.NumberOfEntries; j++){
r << std::string(indent + 3, ' ') << "[" << j << "]" << std::endl; r << std::string(indent + 3, ' ') << "[" << j << "]" << std::endl;
r << std::string(indent + 5, ' ') << "Bytes clear: " << tmpSample.Entries[j].BytesClear << std::endl; r << std::string(indent + 5, ' ') << "Bytes clear: " << tmpSample.Entries[j].BytesClear << std::endl;
r << std::string(indent + 5, ' ') << "Bytes encrypted: " << tmpSample.Entries[j].BytesEncrypted << std::endl; r << std::string(indent + 5, ' ')
<< "Bytes encrypted: " << tmpSample.Entries[j].BytesEncrypted << std::endl;
} }
} }
} }
@ -239,13 +219,9 @@ namespace MP4 {
} }
} }
size_t SAIZ::getDefaultSampleSize(){ size_t SAIZ::getDefaultSampleSize(){return getInt24(4);}
return getInt24(4);
}
size_t SAIZ::getEntryCount(){ size_t SAIZ::getEntryCount(){return getInt16(7);}
return getInt16(7);
}
size_t SAIZ::getEntrySize(size_t entryNo){ size_t SAIZ::getEntrySize(size_t entryNo){
if (entryNo >= getEntryCount()){return -1;} if (entryNo >= getEntryCount()){return -1;}
@ -254,7 +230,8 @@ namespace MP4 {
std::string SAIZ::toPrettyString(uint32_t indent){ std::string SAIZ::toPrettyString(uint32_t indent){
std::stringstream r; std::stringstream r;
r << std::string(indent, ' ') << "[saiz] Sample Auxiliary Information Size Box (" << boxedSize() << ")" << std::endl; r << std::string(indent, ' ') << "[saiz] Sample Auxiliary Information Size Box (" << boxedSize()
<< ")" << std::endl;
r << fullBox::toPrettyString(indent); r << fullBox::toPrettyString(indent);
r << std::string(indent + 1, ' ') << "Default Sample Size: " << getDefaultSampleSize() << std::endl; r << std::string(indent + 1, ' ') << "Default Sample Size: " << getDefaultSampleSize() << std::endl;
r << std::string(indent + 1, ' ') << "Entry Count: " << getEntryCount() << std::endl; r << std::string(indent + 1, ' ') << "Entry Count: " << getEntryCount() << std::endl;
@ -270,9 +247,7 @@ namespace MP4 {
setInt32(offset, 8); setInt32(offset, 8);
} }
size_t SAIO::getEntryCount(){ size_t SAIO::getEntryCount(){return getInt32(4);}
return getInt32(4);
}
size_t SAIO::getEntrySize(size_t entryNo){ size_t SAIO::getEntrySize(size_t entryNo){
if (entryNo >= getEntryCount()){return -1;} if (entryNo >= getEntryCount()){return -1;}
@ -281,7 +256,8 @@ namespace MP4 {
std::string SAIO::toPrettyString(uint32_t indent){ std::string SAIO::toPrettyString(uint32_t indent){
std::stringstream r; std::stringstream r;
r << std::string(indent, ' ') << "[saio] Sample Auxiliary Information Offset Box (" << boxedSize() << ")" << std::endl; r << std::string(indent, ' ') << "[saio] Sample Auxiliary Information Offset Box ("
<< boxedSize() << ")" << std::endl;
r << fullBox::toPrettyString(indent); r << fullBox::toPrettyString(indent);
r << std::string(indent + 1, ' ') << "Entry Count: " << getEntryCount() << std::endl; r << std::string(indent + 1, ' ') << "Entry Count: " << getEntryCount() << std::endl;
for (size_t i = 0; i < getEntryCount(); ++i){ for (size_t i = 0; i < getEntryCount(); ++i){
@ -299,73 +275,47 @@ namespace MP4 {
setVersion(0); setVersion(0);
setFlags(2); setFlags(2);
size_t sampleCount = senc.getSampleCount(); size_t sampleCount = senc.getSampleCount();
for (size_t i = 0; i < sampleCount; ++i){ for (size_t i = 0; i < sampleCount; ++i){setSample(senc.getSample(i), i);}
setSample(senc.getSample(i), i);
}
} }
void UUID_SampleEncryption::setVersion(uint32_t newVersion) { void UUID_SampleEncryption::setVersion(uint32_t newVersion){setInt8(newVersion, 16);}
setInt8(newVersion, 16);
}
uint32_t UUID_SampleEncryption::getVersion() { uint32_t UUID_SampleEncryption::getVersion(){return getInt8(16);}
return getInt8(16);
}
void UUID_SampleEncryption::setFlags(uint32_t newFlags) { void UUID_SampleEncryption::setFlags(uint32_t newFlags){setInt24(newFlags, 17);}
setInt24(newFlags, 17);
}
uint32_t UUID_SampleEncryption::getFlags() { uint32_t UUID_SampleEncryption::getFlags(){return getInt24(17);}
return getInt24(17);
}
void UUID_SampleEncryption::setAlgorithmID(uint32_t newAlgorithmID){ void UUID_SampleEncryption::setAlgorithmID(uint32_t newAlgorithmID){
if (getFlags() & 0x01) { if (getFlags() & 0x01){setInt24(newAlgorithmID, 20);}
setInt24(newAlgorithmID, 20);
}
} }
uint32_t UUID_SampleEncryption::getAlgorithmID(){ uint32_t UUID_SampleEncryption::getAlgorithmID(){
if (getFlags() & 0x01) { if (getFlags() & 0x01){return getInt24(20);}
return getInt24(20);
}
return -1; return -1;
} }
void UUID_SampleEncryption::setIVSize(uint32_t newIVSize){ void UUID_SampleEncryption::setIVSize(uint32_t newIVSize){
if (getFlags() & 0x01) { if (getFlags() & 0x01){setInt8(newIVSize, 23);}
setInt8(newIVSize, 23);
}
} }
uint32_t UUID_SampleEncryption::getIVSize(){ uint32_t UUID_SampleEncryption::getIVSize(){
if (getFlags() & 0x01) { if (getFlags() & 0x01){return getInt8(23);}
return getInt8(23);
}
return -1; return -1;
} }
void UUID_SampleEncryption::setKID(std::string newKID){ void UUID_SampleEncryption::setKID(std::string newKID){
if (newKID == "") { if (newKID == ""){return;}
return;
}
if (getFlags() & 0x01){ if (getFlags() & 0x01){
while (newKID.size() < 16) { while (newKID.size() < 16){newKID += (char)0x00;}
newKID += (char)0x00; for (int i = 0; i < 16; i++){setInt8(newKID[i], 24 + i);}
}
for (int i = 0; i < 16; i++) {
setInt8(newKID[i], 24 + i);
}
} }
} }
std::string UUID_SampleEncryption::getKID(){ std::string UUID_SampleEncryption::getKID(){
if (getFlags() & 0x01){ if (getFlags() & 0x01){
std::string result; std::string result;
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++){result += (char)getInt8(24 + i);}
result += (char)getInt8(24 + i);
}
return result; return result;
} }
return ""; return "";
@ -373,9 +323,7 @@ namespace MP4 {
uint32_t UUID_SampleEncryption::getSampleCount(){ uint32_t UUID_SampleEncryption::getSampleCount(){
int myOffset = 20; int myOffset = 20;
if (getFlags() & 0x01) { if (getFlags() & 0x01){myOffset += 20;}
myOffset += 20;
}
return getInt32(myOffset); return getInt32(myOffset);
} }
@ -402,22 +350,19 @@ namespace MP4 {
if (getFlags() & 0x02){ if (getFlags() & 0x02){
setInt16(newSample.Entries.size(), myOffset); setInt16(newSample.Entries.size(), myOffset);
myOffset += 2; myOffset += 2;
for (std::vector<UUID_SampleEncryption_Sample_Entry>::iterator it = newSample.Entries.begin(); it != newSample.Entries.end(); it++) { for (std::vector<UUID_SampleEncryption_Sample_Entry>::iterator it = newSample.Entries.begin();
it != newSample.Entries.end(); it++){
setInt16(it->BytesClear, myOffset); setInt16(it->BytesClear, myOffset);
myOffset += 2; myOffset += 2;
setInt32(it->BytesEncrypted, myOffset); setInt32(it->BytesEncrypted, myOffset);
myOffset += 4; myOffset += 4;
} }
} }
if (index >= getSampleCount()) { if (index >= getSampleCount()){setInt32(index + 1, 20 + (20 * (getFlags() & 0x01)));}
setInt32(index + 1, 20 + (20 * (getFlags() & 0x01)));
}
} }
UUID_SampleEncryption_Sample UUID_SampleEncryption::getSample(size_t index){ UUID_SampleEncryption_Sample UUID_SampleEncryption::getSample(size_t index){
if (index >= getSampleCount()) { if (index >= getSampleCount()){return UUID_SampleEncryption_Sample();}
return UUID_SampleEncryption_Sample();
}
int myOffset = 20; int myOffset = 20;
myOffset += 20 * (getFlags() & 0x01); myOffset += 20 * (getFlags() & 0x01);
myOffset += 4; // sampleCount is here myOffset += 4; // sampleCount is here
@ -449,7 +394,8 @@ namespace MP4 {
std::string UUID_SampleEncryption::toPrettyString(uint32_t indent){ std::string UUID_SampleEncryption::toPrettyString(uint32_t indent){
std::stringstream r; std::stringstream r;
r << std::string(indent, ' ') << "[a2394f52-5a9b-4f14-a244-6c427c648df4] Sample Encryption Box (" << boxedSize() << ")" << std::endl; r << std::string(indent, ' ') << "[a2394f52-5a9b-4f14-a244-6c427c648df4] Sample Encryption Box ("
<< boxedSize() << ")" << std::endl;
r << std::string(indent + 1, ' ') << "Version: " << getVersion() << std::endl; r << std::string(indent + 1, ' ') << "Version: " << getVersion() << std::endl;
r << std::string(indent + 1, ' ') << "Flags: " << getFlags() << std::endl; r << std::string(indent + 1, ' ') << "Flags: " << getFlags() << std::endl;
if (getFlags() & 0x01){ if (getFlags() & 0x01){
@ -463,7 +409,8 @@ namespace MP4 {
r << std::string(indent + 1, ' ') << "[" << i << "]" << std::endl; r << std::string(indent + 1, ' ') << "[" << i << "]" << std::endl;
r << std::string(indent + 3, ' ') << "Initialization Vector: 0x"; r << std::string(indent + 3, ' ') << "Initialization Vector: 0x";
for (unsigned int j = 0; j < tmpSample.InitializationVector.size(); j++){ for (unsigned int j = 0; j < tmpSample.InitializationVector.size(); j++){
r << std::hex << std::setw(2) << std::setfill('0') << (int)tmpSample.InitializationVector[j] << std::dec; r << std::hex << std::setw(2) << std::setfill('0') << (int)tmpSample.InitializationVector[j]
<< std::dec;
} }
r << std::endl; r << std::endl;
if (getFlags() & 0x02){ if (getFlags() & 0x02){
@ -471,7 +418,8 @@ namespace MP4 {
for (unsigned int j = 0; j < tmpSample.NumberOfEntries; j++){ for (unsigned int j = 0; j < tmpSample.NumberOfEntries; j++){
r << std::string(indent + 3, ' ') << "[" << j << "]" << std::endl; r << std::string(indent + 3, ' ') << "[" << j << "]" << std::endl;
r << std::string(indent + 5, ' ') << "Bytes clear: " << tmpSample.Entries[j].BytesClear << std::endl; r << std::string(indent + 5, ' ') << "Bytes clear: " << tmpSample.Entries[j].BytesClear << std::endl;
r << std::string(indent + 5, ' ') << "Bytes encrypted: " << tmpSample.Entries[j].BytesEncrypted << std::endl; r << std::string(indent + 5, ' ')
<< "Bytes encrypted: " << tmpSample.Entries[j].BytesEncrypted << std::endl;
} }
} }
} }
@ -482,37 +430,21 @@ namespace MP4 {
setUUID((std::string) "8974dbce-7be7-4c51-84f9-7148f9882554"); setUUID((std::string) "8974dbce-7be7-4c51-84f9-7148f9882554");
} }
void UUID_TrackEncryption::setVersion(uint32_t newVersion) { void UUID_TrackEncryption::setVersion(uint32_t newVersion){setInt8(newVersion, 16);}
setInt8(newVersion, 16);
}
uint32_t UUID_TrackEncryption::getVersion() { uint32_t UUID_TrackEncryption::getVersion(){return getInt8(16);}
return getInt8(16);
}
void UUID_TrackEncryption::setFlags(uint32_t newFlags) { void UUID_TrackEncryption::setFlags(uint32_t newFlags){setInt24(newFlags, 17);}
setInt24(newFlags, 17);
}
uint32_t UUID_TrackEncryption::getFlags() { uint32_t UUID_TrackEncryption::getFlags(){return getInt24(17);}
return getInt24(17);
}
void UUID_TrackEncryption::setDefaultAlgorithmID(uint32_t newID) { void UUID_TrackEncryption::setDefaultAlgorithmID(uint32_t newID){setInt24(newID, 20);}
setInt24(newID, 20);
}
uint32_t UUID_TrackEncryption::getDefaultAlgorithmID() { uint32_t UUID_TrackEncryption::getDefaultAlgorithmID(){return getInt24(20);}
return getInt24(20);
}
void UUID_TrackEncryption::setDefaultIVSize(uint8_t newIVSize) { void UUID_TrackEncryption::setDefaultIVSize(uint8_t newIVSize){setInt8(newIVSize, 23);}
setInt8(newIVSize, 23);
}
uint8_t UUID_TrackEncryption::getDefaultIVSize() { uint8_t UUID_TrackEncryption::getDefaultIVSize(){return getInt8(23);}
return getInt8(23);
}
void UUID_TrackEncryption::setDefaultKID(std::string newKID){ void UUID_TrackEncryption::setDefaultKID(std::string newKID){
for (unsigned int i = 0; i < 16; i++){ for (unsigned int i = 0; i < 16; i++){
@ -526,18 +458,18 @@ namespace MP4 {
std::string UUID_TrackEncryption::getDefaultKID(){ std::string UUID_TrackEncryption::getDefaultKID(){
std::string result; std::string result;
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++){result += getInt8(24 + i);}
result += getInt8(24 + i);
}
return result; return result;
} }
std::string UUID_TrackEncryption::toPrettyString(uint32_t indent){ std::string UUID_TrackEncryption::toPrettyString(uint32_t indent){
std::stringstream r; std::stringstream r;
r << std::string(indent, ' ') << "[8974dbce-7be7-4c51-84f9-7148f9882554] Track Encryption Box (" << boxedSize() << ")" << std::endl; r << std::string(indent, ' ') << "[8974dbce-7be7-4c51-84f9-7148f9882554] Track Encryption Box ("
<< boxedSize() << ")" << std::endl;
r << std::string(indent + 2, ' ') << "Version: " << getVersion() << std::endl; r << std::string(indent + 2, ' ') << "Version: " << getVersion() << std::endl;
r << std::string(indent + 2, ' ') << "Flags: " << getFlags() << std::endl; r << std::string(indent + 2, ' ') << "Flags: " << getFlags() << std::endl;
r << std::string(indent + 2, ' ') << "Default Algorithm ID: " << std::hex << getDefaultAlgorithmID() << std::dec << std::endl; r << std::string(indent + 2, ' ') << "Default Algorithm ID: " << std::hex
<< getDefaultAlgorithmID() << std::dec << std::endl;
r << std::string(indent + 2, ' ') << "Default IV Size: " << (int)getDefaultIVSize() << std::endl; r << std::string(indent + 2, ' ') << "Default IV Size: " << (int)getDefaultIVSize() << std::endl;
r << std::string(indent + 2, ' ') << "Default KID: 16 bytes of binary data." << std::endl; r << std::string(indent + 2, ' ') << "Default KID: 16 bytes of binary data." << std::endl;
return r.str(); return r.str();
@ -551,17 +483,11 @@ namespace MP4 {
setInt8(newVersion, 16); setInt8(newVersion, 16);
} }
uint32_t UUID_ProtectionSystemSpecificHeader::getVersion() { uint32_t UUID_ProtectionSystemSpecificHeader::getVersion(){return getInt8(16);}
return getInt8(16);
}
void UUID_ProtectionSystemSpecificHeader::setFlags(uint32_t newFlags) { void UUID_ProtectionSystemSpecificHeader::setFlags(uint32_t newFlags){setInt24(newFlags, 17);}
setInt24(newFlags, 17);
}
uint32_t UUID_ProtectionSystemSpecificHeader::getFlags() { uint32_t UUID_ProtectionSystemSpecificHeader::getFlags(){return getInt24(17);}
return getInt24(17);
}
void UUID_ProtectionSystemSpecificHeader::setSystemID(std::string newID){ void UUID_ProtectionSystemSpecificHeader::setSystemID(std::string newID){
for (unsigned int i = 0; i < 16; i++){ for (unsigned int i = 0; i < 16; i++){
@ -575,34 +501,27 @@ namespace MP4 {
std::string UUID_ProtectionSystemSpecificHeader::getSystemID(){ std::string UUID_ProtectionSystemSpecificHeader::getSystemID(){
std::string result; std::string result;
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++){result += getInt8(20 + i);}
result += getInt8(20 + i);
}
return result; return result;
} }
uint32_t UUID_ProtectionSystemSpecificHeader::getDataSize() { uint32_t UUID_ProtectionSystemSpecificHeader::getDataSize(){return getInt32(36);}
return getInt32(36);
}
void UUID_ProtectionSystemSpecificHeader::setData(std::string newData){ void UUID_ProtectionSystemSpecificHeader::setData(std::string newData){
setInt32(newData.size(), 36); setInt32(newData.size(), 36);
for (unsigned int i = 0; i < newData.size(); i++) { for (unsigned int i = 0; i < newData.size(); i++){setInt8(newData[i], 40 + i);}
setInt8(newData[i], 40 + i);
}
} }
std::string UUID_ProtectionSystemSpecificHeader::getData(){ std::string UUID_ProtectionSystemSpecificHeader::getData(){
std::string result; std::string result;
for (unsigned int i = 0; i < getDataSize(); i++) { for (unsigned int i = 0; i < getDataSize(); i++){result += getInt8(40 + i);}
result += getInt8(40 + i);
}
return result; return result;
} }
std::string UUID_ProtectionSystemSpecificHeader::toPrettyString(uint32_t indent){ std::string UUID_ProtectionSystemSpecificHeader::toPrettyString(uint32_t indent){
std::stringstream r; std::stringstream r;
r << std::string(indent, ' ') << "[d08a4f18-10f3-4a82-b6c8-32d8aba183d3] Protection System Specific Header Box (" << boxedSize() << ")" << std::endl; r << std::string(indent, ' ') << "[d08a4f18-10f3-4a82-b6c8-32d8aba183d3] Protection System Specific Header Box ("
<< boxedSize() << ")" << std::endl;
r << std::string(indent + 2, ' ') << "Version: " << getVersion() << std::endl; r << std::string(indent + 2, ' ') << "Version: " << getVersion() << std::endl;
r << std::string(indent + 2, ' ') << "Flags: " << getFlags() << std::endl; r << std::string(indent + 2, ' ') << "Flags: " << getFlags() << std::endl;
r << std::string(indent + 2, ' ') << "System ID: " << getSystemID() << std::endl; r << std::string(indent + 2, ' ') << "System ID: " << getSystemID() << std::endl;
@ -611,14 +530,10 @@ namespace MP4 {
return r.str(); return r.str();
} }
SINF::SINF() { SINF::SINF(){memcpy(data + 4, "sinf", 4);}
memcpy(data + 4, "sinf", 4);
}
void SINF::setEntry(Box &newEntry, uint32_t no){ void SINF::setEntry(Box &newEntry, uint32_t no){
if (no > 4) { if (no > 4){return;}
return;
}
int tempLoc = 0; int tempLoc = 0;
for (unsigned int i = 0; i < no; i++){ for (unsigned int i = 0; i < no; i++){
tempLoc += Box(getBox(tempLoc).asBox(), false).boxedSize(); tempLoc += Box(getBox(tempLoc).asBox(), false).boxedSize();
@ -628,13 +543,9 @@ namespace MP4 {
Box &SINF::getEntry(uint32_t no){ Box &SINF::getEntry(uint32_t no){
static Box ret = Box((char *)"\000\000\000\010erro", false); static Box ret = Box((char *)"\000\000\000\010erro", false);
if (no > 4) { if (no > 4){return ret;}
return ret;
}
int tempLoc = 0; int tempLoc = 0;
for (unsigned int i = 0; i < no; i++) { for (unsigned int i = 0; i < no; i++){tempLoc += getBoxLen(tempLoc);}
tempLoc += getBoxLen(tempLoc);
}
return getBox(tempLoc); return getBox(tempLoc);
} }
@ -643,9 +554,7 @@ namespace MP4 {
std::cerr << payloadOffset << std::endl; std::cerr << payloadOffset << std::endl;
r << std::string(indent, ' ') << "[sinf] Protection Scheme Info Box (" << boxedSize() << ")" << std::endl; r << std::string(indent, ' ') << "[sinf] Protection Scheme Info Box (" << boxedSize() << ")" << std::endl;
for (int i = 0; i < 4; i++){ for (int i = 0; i < 4; i++){
if (!getEntry(i).isType("erro")) { if (!getEntry(i).isType("erro")){r << getEntry(i).toPrettyString(indent + 2);}
r << getEntry(i).toPrettyString(indent + 2);
}
} }
r << std::endl; r << std::endl;
return r.str(); return r.str();
@ -666,9 +575,7 @@ namespace MP4 {
} }
} }
std::string FRMA::getOriginalFormat() { std::string FRMA::getOriginalFormat(){return std::string(payload(), 4);}
return std::string(payload(), 4);
}
std::string FRMA::toPrettyString(uint32_t indent){ std::string FRMA::toPrettyString(uint32_t indent){
std::stringstream r; std::stringstream r;
@ -683,21 +590,13 @@ namespace MP4 {
setSchemeVersion(schemeVersion); setSchemeVersion(schemeVersion);
} }
void SCHM::setSchemeType(uint32_t newType) { void SCHM::setSchemeType(uint32_t newType){setInt32(htonl(newType), 4);}
setInt32(htonl(newType), 4);
}
uint32_t SCHM::getSchemeType() { uint32_t SCHM::getSchemeType(){return ntohl(getInt32(4));}
return ntohl(getInt32(4));
}
void SCHM::setSchemeVersion(uint32_t newVersion) { void SCHM::setSchemeVersion(uint32_t newVersion){setInt32(htonl(newVersion), 8);}
setInt32(htonl(newVersion), 8);
}
uint32_t SCHM::getSchemeVersion() { uint32_t SCHM::getSchemeVersion(){return ntohl(getInt32(8));}
return ntohl(getInt32(8));
}
void SCHM::setSchemeURI(std::string newURI){ void SCHM::setSchemeURI(std::string newURI){
setFlags(getFlags() | 0x01); setFlags(getFlags() | 0x01);
@ -705,9 +604,7 @@ namespace MP4 {
} }
std::string SCHM::getSchemeURI(){ std::string SCHM::getSchemeURI(){
if (getFlags() & 0x01) { if (getFlags() & 0x01){return getString(12);}
return getString(12);
}
return ""; return "";
} }
@ -718,24 +615,19 @@ namespace MP4 {
int tmpInt = getSchemeType(); int tmpInt = getSchemeType();
sprintf(tmpStr, "%.4s", (char *)&tmpInt); sprintf(tmpStr, "%.4s", (char *)&tmpInt);
r << std::string(indent + 2, ' ') << "SchemeType: " << std::string(tmpStr, 4) << std::endl; r << std::string(indent + 2, ' ') << "SchemeType: " << std::string(tmpStr, 4) << std::endl;
r << std::string(indent + 2, ' ') << "SchemeVersion: 0x" << std::hex << std::setw(8) << std::setfill('0') << getSchemeVersion() << std::dec << std::endl; r << std::string(indent + 2, ' ') << "SchemeVersion: 0x" << std::hex << std::setw(8)
<< std::setfill('0') << getSchemeVersion() << std::dec << std::endl;
if (getFlags() & 0x01){ if (getFlags() & 0x01){
r << std::string(indent + 2, ' ') << "SchemeURI: " << getSchemeURI() << std::endl; r << std::string(indent + 2, ' ') << "SchemeURI: " << getSchemeURI() << std::endl;
} }
return r.str(); return r.str();
} }
SCHI::SCHI() { SCHI::SCHI(){memcpy(data + 4, "schi", 4);}
memcpy(data + 4, "schi", 4);
}
void SCHI::setContent(Box & newContent) { void SCHI::setContent(Box &newContent){setBox(newContent, 0);}
setBox(newContent, 0);
}
Box & SCHI::getContent() { Box &SCHI::getContent(){return getBox(0);}
return getBox(0);
}
std::string SCHI::toPrettyString(uint32_t indent){ std::string SCHI::toPrettyString(uint32_t indent){
std::stringstream r; std::stringstream r;
@ -744,4 +636,4 @@ namespace MP4 {
return r.str(); return r.str();
} }
} }// namespace MP4

View file

@ -152,4 +152,4 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0); std::string toPrettyString(uint32_t indent = 0);
}; };
} }// namespace MP4

File diff suppressed because it is too large Load diff

View file

@ -102,7 +102,6 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0); std::string toPrettyString(uint32_t indent = 0);
}; };
class AVCC : public Box{ class AVCC : public Box{
public: public:
AVCC(); AVCC();
@ -236,11 +235,8 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0); ///< put it into a pretty string std::string toPrettyString(uint32_t indent = 0); ///< put it into a pretty string
}; };
/// Implements ISO 14496-1 SLConfigDescrTag /// Implements ISO 14496-1 SLConfigDescrTag
class SLCDescriptor: public Descriptor{ class SLCDescriptor : public Descriptor{};
};
class ESDS : public fullBox{ class ESDS : public fullBox{
public: public:
@ -316,7 +312,6 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0); std::string toPrettyString(uint32_t indent = 0);
}; };
class MFRA : public containerBox{ class MFRA : public containerBox{
public: public:
MFRA(); MFRA();
@ -525,6 +520,7 @@ namespace MP4 {
void setHeight(double newHeight); void setHeight(double newHeight);
double getHeight(); double getHeight();
std::string toPrettyString(uint32_t indent = 0); std::string toPrettyString(uint32_t indent = 0);
protected: protected:
void initialize(); void initialize();
}; };
@ -789,21 +785,15 @@ namespace MP4 {
FontTableBox getFontTableBox(); FontTableBox getFontTableBox();
void setFontTableBox(FontTableBox f); void setFontTableBox(FontTableBox f);
std::string toPrettyTextString(uint32_t indent = 0, std::string name = ""); std::string toPrettyTextString(uint32_t indent = 0, std::string name = "");
}; };
class TX3G : public TextSampleEntry{ class TX3G : public TextSampleEntry{
public: public:
TX3G(); TX3G();
std::string toPrettyString(uint32_t indent = 0); std::string toPrettyString(uint32_t indent = 0);
}; };
class MP4A : public AudioSampleEntry{ class MP4A : public AudioSampleEntry{
public: public:
MP4A(); MP4A();
@ -905,5 +895,4 @@ namespace MP4 {
uint16_t getMediaRateFraction(uint32_t cnt); uint16_t getMediaRateFraction(uint32_t cnt);
std::string toPrettyString(uint32_t indent = 0); std::string toPrettyString(uint32_t indent = 0);
}; };
} }// namespace MP4

View file

@ -1,5 +1,5 @@
#include "mp4_ms.h"
#include "mp4_encryption.h" /*LTS*/ #include "mp4_encryption.h" /*LTS*/
#include "mp4_ms.h"
namespace MP4{ namespace MP4{
@ -10,26 +10,15 @@ namespace MP4 {
return 0; return 0;
} }
SDTP::SDTP(){memcpy(data + 4, "sdtp", 4);}
SDTP::SDTP() { void SDTP::setVersion(uint32_t newVersion){setInt8(newVersion, 0);}
memcpy(data + 4, "sdtp", 4);
}
void SDTP::setVersion(uint32_t newVersion) { uint32_t SDTP::getVersion(){return getInt8(0);}
setInt8(newVersion, 0);
}
uint32_t SDTP::getVersion() { void SDTP::setValue(uint32_t newValue, size_t index){setInt8(newValue, index);}
return getInt8(0);
}
void SDTP::setValue(uint32_t newValue, size_t index) { uint32_t SDTP::getValue(size_t index){return getInt8(index);}
setInt8(newValue, index);
}
uint32_t SDTP::getValue(size_t index) {
return getInt8(index);
}
std::string SDTP::toPrettyString(uint32_t indent){ std::string SDTP::toPrettyString(uint32_t indent){
std::stringstream r; std::stringstream r;
@ -39,46 +28,22 @@ namespace MP4 {
uint32_t val = getValue(i + 3); uint32_t val = getValue(i + 3);
r << std::string(indent + 2, ' ') << "[" << i << "] = "; r << std::string(indent + 2, ' ') << "[" << i << "] = ";
switch (val & 3){ switch (val & 3){
case 0: case 0: r << " "; break;
r << " "; case 1: r << "Redundant, "; break;
break; case 2: r << "Not redundant, "; break;
case 1: case 3: r << "Error, "; break;
r << "Redundant, ";
break;
case 2:
r << "Not redundant, ";
break;
case 3:
r << "Error, ";
break;
} }
switch (val & 12){ switch (val & 12){
case 0: case 0: r << " "; break;
r << " "; case 4: r << "Not disposable, "; break;
break; case 8: r << "Disposable, "; break;
case 4: case 12: r << "Error, "; break;
r << "Not disposable, ";
break;
case 8:
r << "Disposable, ";
break;
case 12:
r << "Error, ";
break;
} }
switch (val & 48){ switch (val & 48){
case 0: case 0: r << " "; break;
r << " "; case 16: r << "IFrame, "; break;
break; case 32: r << "Not IFrame, "; break;
case 16: case 48: r << "Error, "; break;
r << "IFrame, ";
break;
case 32:
r << "Not IFrame, ";
break;
case 48:
r << "Error, ";
break;
} }
r << "(" << val << ")" << std::endl; r << "(" << val << ")" << std::endl;
} }
@ -95,9 +60,7 @@ namespace MP4 {
std::stringstream r; std::stringstream r;
r << std::hex; r << std::hex;
for (int i = 0; i < 16; ++i){ for (int i = 0; i < 16; ++i){
if (i == 4 || i == 6 || i == 8 || i == 10) { if (i == 4 || i == 6 || i == 8 || i == 10){r << "-";}
r << "-";
}
r << std::setfill('0') << std::setw(2) << std::right << (int)(data[8 + i]); r << std::setfill('0') << std::setw(2) << std::right << (int)(data[8 + i]);
} }
return r.str(); return r.str();
@ -105,23 +68,17 @@ namespace MP4 {
void UUID::setUUID(const std::string &uuid_string){ void UUID::setUUID(const std::string &uuid_string){
// reset UUID to zero // reset UUID to zero
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i){((uint32_t *)(data + 8))[i] = 0;}
((uint32_t *)(data + 8))[i] = 0;
}
// set the UUID from the string, char by char // set the UUID from the string, char by char
int i = 0; int i = 0;
for (size_t j = 0; j < uuid_string.size(); ++j){ for (size_t j = 0; j < uuid_string.size(); ++j){
if (uuid_string[j] == '-') { if (uuid_string[j] == '-'){continue;}
continue;
}
data[8 + i / 2] |= (c2hex(uuid_string[j]) << ((~i & 1) << 2)); data[8 + i / 2] |= (c2hex(uuid_string[j]) << ((~i & 1) << 2));
++i; ++i;
} }
} }
void UUID::setUUID(const char * raw_uuid) { void UUID::setUUID(const char *raw_uuid){memcpy(data + 8, raw_uuid, 16);}
memcpy(data + 8, raw_uuid, 16);
}
std::string UUID::toPrettyString(uint32_t indent){ std::string UUID::toPrettyString(uint32_t indent){
std::string UUID = getUUID(); std::string UUID = getUUID();
@ -153,29 +110,17 @@ namespace MP4 {
setUUID((std::string) "d4807ef2-ca39-4695-8e54-26cb9e46a79f"); setUUID((std::string) "d4807ef2-ca39-4695-8e54-26cb9e46a79f");
} }
void UUID_TrackFragmentReference::setVersion(uint32_t newVersion) { void UUID_TrackFragmentReference::setVersion(uint32_t newVersion){setInt8(newVersion, 16);}
setInt8(newVersion, 16);
}
uint32_t UUID_TrackFragmentReference::getVersion() { uint32_t UUID_TrackFragmentReference::getVersion(){return getInt8(16);}
return getInt8(16);
}
void UUID_TrackFragmentReference::setFlags(uint32_t newFlags) { void UUID_TrackFragmentReference::setFlags(uint32_t newFlags){setInt24(newFlags, 17);}
setInt24(newFlags, 17);
}
uint32_t UUID_TrackFragmentReference::getFlags() { uint32_t UUID_TrackFragmentReference::getFlags(){return getInt24(17);}
return getInt24(17);
}
void UUID_TrackFragmentReference::setFragmentCount(uint32_t newCount) { void UUID_TrackFragmentReference::setFragmentCount(uint32_t newCount){setInt8(newCount, 20);}
setInt8(newCount, 20);
}
uint32_t UUID_TrackFragmentReference::getFragmentCount() { uint32_t UUID_TrackFragmentReference::getFragmentCount(){return getInt8(20);}
return getInt8(20);
}
void UUID_TrackFragmentReference::setTime(size_t num, uint64_t newTime){ void UUID_TrackFragmentReference::setTime(size_t num, uint64_t newTime){
if (getVersion() == 0){ if (getVersion() == 0){
@ -211,12 +156,14 @@ namespace MP4 {
std::string UUID_TrackFragmentReference::toPrettyString(uint32_t indent){ std::string UUID_TrackFragmentReference::toPrettyString(uint32_t indent){
std::stringstream r; std::stringstream r;
r << std::string(indent, ' ') << "[d4807ef2-ca39-4695-8e54-26cb9e46a79f] Track Fragment Reference (" << boxedSize() << ")" << std::endl; r << std::string(indent, ' ') << "[d4807ef2-ca39-4695-8e54-26cb9e46a79f] Track Fragment Reference ("
<< boxedSize() << ")" << std::endl;
r << std::string(indent + 1, ' ') << "Version: " << getVersion() << std::endl; r << std::string(indent + 1, ' ') << "Version: " << getVersion() << std::endl;
r << std::string(indent + 1, ' ') << "Fragments: " << getFragmentCount() << std::endl; r << std::string(indent + 1, ' ') << "Fragments: " << getFragmentCount() << std::endl;
int j = getFragmentCount(); int j = getFragmentCount();
for (int i = 0; i < j; ++i){ for (int i = 0; i < j; ++i){
r << std::string(indent + 2, ' ') << "[" << i << "] Time = " << getTime(i) << ", Duration = " << getDuration(i) << std::endl; r << std::string(indent + 2, ' ') << "[" << i << "] Time = " << getTime(i)
<< ", Duration = " << getDuration(i) << std::endl;
} }
return r.str(); return r.str();
} }
@ -227,21 +174,13 @@ namespace MP4 {
setFlags(0); setFlags(0);
} }
void UUID_TFXD::setVersion(uint32_t newVersion) { void UUID_TFXD::setVersion(uint32_t newVersion){setInt8(newVersion, 16);}
setInt8(newVersion, 16);
}
uint32_t UUID_TFXD::getVersion() { uint32_t UUID_TFXD::getVersion(){return getInt8(16);}
return getInt8(16);
}
void UUID_TFXD::setFlags(uint32_t newFlags) { void UUID_TFXD::setFlags(uint32_t newFlags){setInt24(newFlags, 17);}
setInt24(newFlags, 17);
}
uint32_t UUID_TFXD::getFlags() { uint32_t UUID_TFXD::getFlags(){return getInt24(17);}
return getInt24(17);
}
void UUID_TFXD::setTime(uint64_t newTime){ void UUID_TFXD::setTime(uint64_t newTime){
if (getVersion() == 0){ if (getVersion() == 0){
@ -278,10 +217,11 @@ namespace MP4 {
std::string UUID_TFXD::toPrettyString(uint32_t indent){ std::string UUID_TFXD::toPrettyString(uint32_t indent){
std::stringstream r; std::stringstream r;
setUUID((std::string) "6d1d9b05-42d5-44e6-80e2-141daff757b2"); setUUID((std::string) "6d1d9b05-42d5-44e6-80e2-141daff757b2");
r << std::string(indent, ' ') << "[6d1d9b05-42d5-44e6-80e2-141daff757b2] TFXD Box (" << boxedSize() << ")" << std::endl; r << std::string(indent, ' ') << "[6d1d9b05-42d5-44e6-80e2-141daff757b2] TFXD Box ("
<< boxedSize() << ")" << std::endl;
r << std::string(indent + 1, ' ') << "Version: " << getVersion() << std::endl; r << std::string(indent + 1, ' ') << "Version: " << getVersion() << std::endl;
r << std::string(indent + 1, ' ') << "Time = " << getTime() << std::endl; r << std::string(indent + 1, ' ') << "Time = " << getTime() << std::endl;
r << std::string(indent + 1, ' ') << "Duration = " << getDuration() << std::endl; r << std::string(indent + 1, ' ') << "Duration = " << getDuration() << std::endl;
return r.str(); return r.str();
} }
} }// namespace MP4

View file

@ -50,4 +50,4 @@ namespace MP4 {
uint64_t getDuration(); uint64_t getDuration();
std::string toPrettyString(uint32_t indent = 0); std::string toPrettyString(uint32_t indent = 0);
}; };
} }// namespace MP4

View file

@ -81,4 +81,3 @@ namespace Mpeg{
return res; return res;
} }
}// namespace Mpeg }// namespace Mpeg

View file

@ -42,4 +42,3 @@ namespace Mpeg{
void parseMPEG2Headers(const char *hdr, uint32_t len, MPEG2Info &mpInfo); void parseMPEG2Headers(const char *hdr, uint32_t len, MPEG2Info &mpInfo);
MPEG2Info parseMPEG2Headers(const char *hdr, uint32_t len); MPEG2Info parseMPEG2Headers(const char *hdr, uint32_t len);
}// namespace Mpeg }// namespace Mpeg

View file

@ -34,8 +34,7 @@ namespace nalu{
size_t dataLen = data.size(); size_t dataLen = data.size();
size_t resPtr = 2; size_t resPtr = 2;
while (dataPtr + 2 < dataLen){ while (dataPtr + 2 < dataLen){
if (!data[dataPtr] && !data[dataPtr + 1] && if (!data[dataPtr] && !data[dataPtr + 1] && data[dataPtr + 2] == 3){// We have found an emulation prevention
data[dataPtr + 2] == 3){// We have found an emulation prevention
result[resPtr++] = data[dataPtr++]; result[resPtr++] = data[dataPtr++];
result[resPtr++] = data[dataPtr++]; result[resPtr++] = data[dataPtr++];
dataPtr++; // Skip the emulation prevention byte dataPtr++; // Skip the emulation prevention byte
@ -129,4 +128,3 @@ namespace nalu{
return newOffset; return newOffset;
} }
}// namespace nalu }// namespace nalu

View file

@ -18,4 +18,3 @@ namespace nalu{
const char *scanAnnexB(const char *data, uint32_t dataSize); const char *scanAnnexB(const char *data, uint32_t dataSize);
const char *nalEndPosition(const char *data, uint32_t dataSize); const char *nalEndPosition(const char *data, uint32_t dataSize);
}// namespace nalu }// namespace nalu

View file

@ -1,11 +1,11 @@
#include "ogg.h" #include "bitstream.h"
#include "defines.h" #include "defines.h"
#include <string.h> #include "ogg.h"
#include <stdlib.h>
#include <sstream>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <iomanip> #include <iomanip>
#include "bitstream.h" #include <sstream>
#include <stdlib.h>
#include <string.h>
namespace OGG{ namespace OGG{
@ -21,13 +21,9 @@ namespace OGG {
res.push_back(0); res.push_back(0);
for (unsigned int i = 0; i < len; i++){ for (unsigned int i = 0; i < len; i++){
*res.rbegin() += data[i]; *res.rbegin() += data[i];
if (data[i] != 0xFF){ if (data[i] != 0xFF){res.push_back(0);}
res.push_back(0);
}
}
if (*res.rbegin() == 0){
res.resize(res.size() - 1);
} }
if (*res.rbegin() == 0){res.resize(res.size() - 1);}
return res; return res;
} }
inline long long unsigned int get_64(char *data){ inline long long unsigned int get_64(char *data){
@ -55,7 +51,6 @@ namespace OGG {
} }
} }
inline void set_32(char *data, long unsigned int val){ inline void set_32(char *data, long unsigned int val){
for (int i = 0; i < 4; ++i){ for (int i = 0; i < 4; ++i){
data[i] = val & 0xFF; data[i] = val & 0xFF;
@ -63,7 +58,6 @@ namespace OGG {
} }
} }
Page::Page(){ Page::Page(){
framesSeen = 0; framesSeen = 0;
lastKeyFrame = 0; lastKeyFrame = 0;
@ -98,9 +92,7 @@ namespace OGG {
unsigned int Page::calcPayloadSize(){ unsigned int Page::calcPayloadSize(){
unsigned int retVal = 0; unsigned int retVal = 0;
for (unsigned int i = 0; i < segments.size(); i++){ for (unsigned int i = 0; i < segments.size(); i++){retVal += segments[i].size();}
retVal += segments[i].size();
}
return retVal; return retVal;
} }
@ -109,9 +101,7 @@ namespace OGG {
int len = newData.size(); int len = newData.size();
int total = 0; int total = 0;
segments.clear(); segments.clear();
if (newData.size() < 27){ if (newData.size() < 27){return false;}
return false;
}
if (newData.substr(0, 4) != "OggS"){ if (newData.substr(0, 4) != "OggS"){
FAIL_MSG("Invalid Ogg page encountered (magic number wrong: %s) - cannot continue", newData.c_str()); FAIL_MSG("Invalid Ogg page encountered (magic number wrong: %s) - cannot continue", newData.c_str());
return false; return false;
@ -129,9 +119,7 @@ namespace OGG {
total += 27; total += 27;
// return false if the segment is not complete // return false if the segment is not complete
total += getPageSegments(); total += getPageSegments();
if(total >= len){ if (total >= len){return false;}
return false;
}
newData.erase(0, getPageSegments() + 27); newData.erase(0, getPageSegments() + 27);
for (std::deque<unsigned int>::iterator it = segSizes.begin(); it != segSizes.end(); it++){ for (std::deque<unsigned int>::iterator it = segSizes.begin(); it != segSizes.end(); it++){
@ -143,7 +131,6 @@ namespace OGG {
return true; return true;
} }
bool Page::read(FILE *inFile){ bool Page::read(FILE *inFile){
segments.clear(); segments.clear();
int oriPos = ftell(inFile); int oriPos = ftell(inFile);
@ -166,11 +153,10 @@ namespace OGG {
for (std::deque<unsigned int>::iterator it = segSizes.begin(); it != segSizes.end(); it++){ for (std::deque<unsigned int>::iterator it = segSizes.begin(); it != segSizes.end(); it++){
if (*it){ if (*it){
char *thisSeg = (char *)malloc(*it * sizeof(char)); char *thisSeg = (char *)malloc(*it * sizeof(char));
if (!thisSeg){ if (!thisSeg){WARN_MSG("malloc failed");}
WARN_MSG("malloc failed");
}
if (!fread(thisSeg, *it, 1, inFile)){ if (!fread(thisSeg, *it, 1, inFile)){
WARN_MSG("Unable to read a segment @ pos %d segment size: %d getPageSegments: %d", oriPos, *it, getPageSegments()); WARN_MSG("Unable to read a segment @ pos %d segment size: %d getPageSegments: %d", oriPos,
*it, getPageSegments());
fseek(inFile, oriPos, SEEK_SET); fseek(inFile, oriPos, SEEK_SET);
return false; return false;
} }
@ -179,7 +165,6 @@ namespace OGG {
}else{ }else{
segments.push_back(std::string("", 0)); segments.push_back(std::string("", 0));
} }
} }
return true; return true;
@ -195,79 +180,47 @@ namespace OGG {
} }
const char *Page::getSegment(unsigned int index){ const char *Page::getSegment(unsigned int index){
if (index >= segments.size()){ if (index >= segments.size()){return 0;}
return 0;
}
return segments[index].data(); return segments[index].data();
} }
unsigned long Page::getSegmentLen(unsigned int index){ unsigned long Page::getSegmentLen(unsigned int index){
if (index >= segments.size()){ if (index >= segments.size()){return 0;}
return 0;
}
return segments[index].size(); return segments[index].size();
} }
void Page::setMagicNumber(){ void Page::setMagicNumber(){memcpy(data, "OggS", 4);}
memcpy(data, "OggS", 4);
}
char Page::getVersion(){ char Page::getVersion(){return data[4];}
return data[4];
}
void Page::setVersion(char newVal){ void Page::setVersion(char newVal){data[4] = newVal;}
data[4] = newVal;
}
char Page::getHeaderType(){ char Page::getHeaderType(){return data[5];}
return data[5];
}
void Page::setHeaderType(char newVal){ void Page::setHeaderType(char newVal){data[5] = newVal;}
data[5] = newVal;
}
long long unsigned int Page::getGranulePosition(){ long long unsigned int Page::getGranulePosition(){return get_64(data + 6);}
return get_64(data + 6);
}
void Page::setGranulePosition(long long unsigned int newVal){ void Page::setGranulePosition(long long unsigned int newVal){set_64(data + 6, newVal);}
set_64(data + 6, newVal);
}
long unsigned int Page::getBitstreamSerialNumber(){ long unsigned int Page::getBitstreamSerialNumber(){
// return ntohl(((long unsigned int*)(data+14))[0]); // return ntohl(((long unsigned int*)(data+14))[0]);
return get_32(data + 14); return get_32(data + 14);
} }
void Page::setBitstreamSerialNumber(long unsigned int newVal){ void Page::setBitstreamSerialNumber(long unsigned int newVal){set_32(data + 14, newVal);}
set_32(data + 14, newVal);
}
long unsigned int Page::getPageSequenceNumber(){ long unsigned int Page::getPageSequenceNumber(){return get_32(data + 18);}
return get_32(data + 18);
}
void Page::setPageSequenceNumber(long unsigned int newVal){ void Page::setPageSequenceNumber(long unsigned int newVal){set_32(data + 18, newVal);}
set_32(data + 18, newVal);
}
long unsigned int Page::getCRCChecksum(){ long unsigned int Page::getCRCChecksum(){return get_32(data + 22);}
return get_32(data + 22);
}
void Page::setCRCChecksum(long unsigned int newVal){ void Page::setCRCChecksum(long unsigned int newVal){set_32(data + 22, newVal);}
set_32(data + 22, newVal);
}
char Page::getPageSegments(){ char Page::getPageSegments(){return data[26];}
return data[26];
}
inline void Page::setPageSegments(char newVal){ inline void Page::setPageSegments(char newVal){data[26] = newVal;}
data[26] = newVal;
}
bool Page::verifyChecksum(){ bool Page::verifyChecksum(){
if (getCRCChecksum() == calcChecksum()){// NOTE: calcChecksum is currently not functional (it will always return 0) if (getCRCChecksum() == calcChecksum()){// NOTE: calcChecksum is currently not functional (it will always return 0)
@ -279,9 +232,7 @@ namespace OGG {
bool Page::possiblyContinued(){ bool Page::possiblyContinued(){
if (getPageSegments() == 255){ if (getPageSegments() == 255){
if (data[281] == 255){ if (data[281] == 255){return true;}
return true;
}
} }
return false; return false;
} }
@ -294,18 +245,13 @@ namespace OGG {
if (!getHeaderType()){ if (!getHeaderType()){
r << " Normal"; r << " Normal";
}else{ }else{
if (getHeaderType() & Continued){ if (getHeaderType() & Continued){r << " Continued";}
r << " Continued"; if (getHeaderType() & BeginOfStream){r << " BeginOfStream";}
} if (getHeaderType() & EndOfStream){r << " EndOfStream";}
if (getHeaderType() & BeginOfStream){
r << " BeginOfStream";
}
if (getHeaderType() & EndOfStream){
r << " EndOfStream";
}
} }
r << " (" << (int)getHeaderType() << ")" << std::endl; r << " (" << (int)getHeaderType() << ")" << std::endl;
r << std::string(indent + 2, ' ') << "Granule position: " << std::hex << std::setw(16) << std::setfill('0') << getGranulePosition() << std::dec << std::endl; r << std::string(indent + 2, ' ') << "Granule position: " << std::hex << std::setw(16)
<< std::setfill('0') << getGranulePosition() << std::dec << std::endl;
r << std::string(indent + 2, ' ') << "Bitstream number: " << getBitstreamSerialNumber() << std::endl; r << std::string(indent + 2, ' ') << "Bitstream number: " << getBitstreamSerialNumber() << std::endl;
r << std::string(indent + 2, ' ') << "Sequence number: " << getPageSequenceNumber() << std::endl; r << std::string(indent + 2, ' ') << "Sequence number: " << getPageSequenceNumber() << std::endl;
r << std::string(indent + 2, ' ') << "Checksum Correct: " << verifyChecksum() << std::endl; r << std::string(indent + 2, ' ') << "Checksum Correct: " << verifyChecksum() << std::endl;
@ -313,78 +259,49 @@ namespace OGG {
r << std::string(indent + 2, ' ') << "Checksum: " << getCRCChecksum() << std::endl; r << std::string(indent + 2, ' ') << "Checksum: " << getCRCChecksum() << std::endl;
r << std::string(indent + 2, ' ') << (int)getPageSegments() << " segments:" << std::endl; r << std::string(indent + 2, ' ') << (int)getPageSegments() << " segments:" << std::endl;
r << std::string(indent + 3, ' '); r << std::string(indent + 3, ' ');
for (unsigned int i = 0; i < segments.size(); i++){ for (unsigned int i = 0; i < segments.size(); i++){r << " " << segments[i].size();}
r << " " << segments[i].size();
}
r << std::endl; r << std::endl;
return r.str(); return r.str();
} }
inline unsigned int crc32(unsigned int crc, const char *data, size_t len){ inline unsigned int crc32(unsigned int crc, const char *data, size_t len){
static const unsigned int table[256] ={ static const unsigned int table[256] ={
0x00000000U, 0x04C11DB7U, 0x09823B6EU, 0x0D4326D9U, 0x00000000U, 0x04C11DB7U, 0x09823B6EU, 0x0D4326D9U, 0x130476DCU, 0x17C56B6BU, 0x1A864DB2U,
0x130476DCU, 0x17C56B6BU, 0x1A864DB2U, 0x1E475005U, 0x1E475005U, 0x2608EDB8U, 0x22C9F00FU, 0x2F8AD6D6U, 0x2B4BCB61U, 0x350C9B64U, 0x31CD86D3U,
0x2608EDB8U, 0x22C9F00FU, 0x2F8AD6D6U, 0x2B4BCB61U, 0x3C8EA00AU, 0x384FBDBDU, 0x4C11DB70U, 0x48D0C6C7U, 0x4593E01EU, 0x4152FDA9U, 0x5F15ADACU,
0x350C9B64U, 0x31CD86D3U, 0x3C8EA00AU, 0x384FBDBDU, 0x5BD4B01BU, 0x569796C2U, 0x52568B75U, 0x6A1936C8U, 0x6ED82B7FU, 0x639B0DA6U, 0x675A1011U,
0x4C11DB70U, 0x48D0C6C7U, 0x4593E01EU, 0x4152FDA9U, 0x791D4014U, 0x7DDC5DA3U, 0x709F7B7AU, 0x745E66CDU, 0x9823B6E0U, 0x9CE2AB57U, 0x91A18D8EU,
0x5F15ADACU, 0x5BD4B01BU, 0x569796C2U, 0x52568B75U, 0x95609039U, 0x8B27C03CU, 0x8FE6DD8BU, 0x82A5FB52U, 0x8664E6E5U, 0xBE2B5B58U, 0xBAEA46EFU,
0x6A1936C8U, 0x6ED82B7FU, 0x639B0DA6U, 0x675A1011U, 0xB7A96036U, 0xB3687D81U, 0xAD2F2D84U, 0xA9EE3033U, 0xA4AD16EAU, 0xA06C0B5DU, 0xD4326D90U,
0x791D4014U, 0x7DDC5DA3U, 0x709F7B7AU, 0x745E66CDU, 0xD0F37027U, 0xDDB056FEU, 0xD9714B49U, 0xC7361B4CU, 0xC3F706FBU, 0xCEB42022U, 0xCA753D95U,
0x9823B6E0U, 0x9CE2AB57U, 0x91A18D8EU, 0x95609039U, 0xF23A8028U, 0xF6FB9D9FU, 0xFBB8BB46U, 0xFF79A6F1U, 0xE13EF6F4U, 0xE5FFEB43U, 0xE8BCCD9AU,
0x8B27C03CU, 0x8FE6DD8BU, 0x82A5FB52U, 0x8664E6E5U, 0xEC7DD02DU, 0x34867077U, 0x30476DC0U, 0x3D044B19U, 0x39C556AEU, 0x278206ABU, 0x23431B1CU,
0xBE2B5B58U, 0xBAEA46EFU, 0xB7A96036U, 0xB3687D81U, 0x2E003DC5U, 0x2AC12072U, 0x128E9DCFU, 0x164F8078U, 0x1B0CA6A1U, 0x1FCDBB16U, 0x018AEB13U,
0xAD2F2D84U, 0xA9EE3033U, 0xA4AD16EAU, 0xA06C0B5DU, 0x054BF6A4U, 0x0808D07DU, 0x0CC9CDCAU, 0x7897AB07U, 0x7C56B6B0U, 0x71159069U, 0x75D48DDEU,
0xD4326D90U, 0xD0F37027U, 0xDDB056FEU, 0xD9714B49U, 0x6B93DDDBU, 0x6F52C06CU, 0x6211E6B5U, 0x66D0FB02U, 0x5E9F46BFU, 0x5A5E5B08U, 0x571D7DD1U,
0xC7361B4CU, 0xC3F706FBU, 0xCEB42022U, 0xCA753D95U, 0x53DC6066U, 0x4D9B3063U, 0x495A2DD4U, 0x44190B0DU, 0x40D816BAU, 0xACA5C697U, 0xA864DB20U,
0xF23A8028U, 0xF6FB9D9FU, 0xFBB8BB46U, 0xFF79A6F1U, 0xA527FDF9U, 0xA1E6E04EU, 0xBFA1B04BU, 0xBB60ADFCU, 0xB6238B25U, 0xB2E29692U, 0x8AAD2B2FU,
0xE13EF6F4U, 0xE5FFEB43U, 0xE8BCCD9AU, 0xEC7DD02DU, 0x8E6C3698U, 0x832F1041U, 0x87EE0DF6U, 0x99A95DF3U, 0x9D684044U, 0x902B669DU, 0x94EA7B2AU,
0x34867077U, 0x30476DC0U, 0x3D044B19U, 0x39C556AEU, 0xE0B41DE7U, 0xE4750050U, 0xE9362689U, 0xEDF73B3EU, 0xF3B06B3BU, 0xF771768CU, 0xFA325055U,
0x278206ABU, 0x23431B1CU, 0x2E003DC5U, 0x2AC12072U, 0xFEF34DE2U, 0xC6BCF05FU, 0xC27DEDE8U, 0xCF3ECB31U, 0xCBFFD686U, 0xD5B88683U, 0xD1799B34U,
0x128E9DCFU, 0x164F8078U, 0x1B0CA6A1U, 0x1FCDBB16U, 0xDC3ABDEDU, 0xD8FBA05AU, 0x690CE0EEU, 0x6DCDFD59U, 0x608EDB80U, 0x644FC637U, 0x7A089632U,
0x018AEB13U, 0x054BF6A4U, 0x0808D07DU, 0x0CC9CDCAU, 0x7EC98B85U, 0x738AAD5CU, 0x774BB0EBU, 0x4F040D56U, 0x4BC510E1U, 0x46863638U, 0x42472B8FU,
0x7897AB07U, 0x7C56B6B0U, 0x71159069U, 0x75D48DDEU, 0x5C007B8AU, 0x58C1663DU, 0x558240E4U, 0x51435D53U, 0x251D3B9EU, 0x21DC2629U, 0x2C9F00F0U,
0x6B93DDDBU, 0x6F52C06CU, 0x6211E6B5U, 0x66D0FB02U, 0x285E1D47U, 0x36194D42U, 0x32D850F5U, 0x3F9B762CU, 0x3B5A6B9BU, 0x0315D626U, 0x07D4CB91U,
0x5E9F46BFU, 0x5A5E5B08U, 0x571D7DD1U, 0x53DC6066U, 0x0A97ED48U, 0x0E56F0FFU, 0x1011A0FAU, 0x14D0BD4DU, 0x19939B94U, 0x1D528623U, 0xF12F560EU,
0x4D9B3063U, 0x495A2DD4U, 0x44190B0DU, 0x40D816BAU, 0xF5EE4BB9U, 0xF8AD6D60U, 0xFC6C70D7U, 0xE22B20D2U, 0xE6EA3D65U, 0xEBA91BBCU, 0xEF68060BU,
0xACA5C697U, 0xA864DB20U, 0xA527FDF9U, 0xA1E6E04EU, 0xD727BBB6U, 0xD3E6A601U, 0xDEA580D8U, 0xDA649D6FU, 0xC423CD6AU, 0xC0E2D0DDU, 0xCDA1F604U,
0xBFA1B04BU, 0xBB60ADFCU, 0xB6238B25U, 0xB2E29692U, 0xC960EBB3U, 0xBD3E8D7EU, 0xB9FF90C9U, 0xB4BCB610U, 0xB07DABA7U, 0xAE3AFBA2U, 0xAAFBE615U,
0x8AAD2B2FU, 0x8E6C3698U, 0x832F1041U, 0x87EE0DF6U, 0xA7B8C0CCU, 0xA379DD7BU, 0x9B3660C6U, 0x9FF77D71U, 0x92B45BA8U, 0x9675461FU, 0x8832161AU,
0x99A95DF3U, 0x9D684044U, 0x902B669DU, 0x94EA7B2AU, 0x8CF30BADU, 0x81B02D74U, 0x857130C3U, 0x5D8A9099U, 0x594B8D2EU, 0x5408ABF7U, 0x50C9B640U,
0xE0B41DE7U, 0xE4750050U, 0xE9362689U, 0xEDF73B3EU, 0x4E8EE645U, 0x4A4FFBF2U, 0x470CDD2BU, 0x43CDC09CU, 0x7B827D21U, 0x7F436096U, 0x7200464FU,
0xF3B06B3BU, 0xF771768CU, 0xFA325055U, 0xFEF34DE2U, 0x76C15BF8U, 0x68860BFDU, 0x6C47164AU, 0x61043093U, 0x65C52D24U, 0x119B4BE9U, 0x155A565EU,
0xC6BCF05FU, 0xC27DEDE8U, 0xCF3ECB31U, 0xCBFFD686U, 0x18197087U, 0x1CD86D30U, 0x029F3D35U, 0x065E2082U, 0x0B1D065BU, 0x0FDC1BECU, 0x3793A651U,
0xD5B88683U, 0xD1799B34U, 0xDC3ABDEDU, 0xD8FBA05AU, 0x3352BBE6U, 0x3E119D3FU, 0x3AD08088U, 0x2497D08DU, 0x2056CD3AU, 0x2D15EBE3U, 0x29D4F654U,
0x690CE0EEU, 0x6DCDFD59U, 0x608EDB80U, 0x644FC637U, 0xC5A92679U, 0xC1683BCEU, 0xCC2B1D17U, 0xC8EA00A0U, 0xD6AD50A5U, 0xD26C4D12U, 0xDF2F6BCBU,
0x7A089632U, 0x7EC98B85U, 0x738AAD5CU, 0x774BB0EBU, 0xDBEE767CU, 0xE3A1CBC1U, 0xE760D676U, 0xEA23F0AFU, 0xEEE2ED18U, 0xF0A5BD1DU, 0xF464A0AAU,
0x4F040D56U, 0x4BC510E1U, 0x46863638U, 0x42472B8FU, 0xF9278673U, 0xFDE69BC4U, 0x89B8FD09U, 0x8D79E0BEU, 0x803AC667U, 0x84FBDBD0U, 0x9ABC8BD5U,
0x5C007B8AU, 0x58C1663DU, 0x558240E4U, 0x51435D53U, 0x9E7D9662U, 0x933EB0BBU, 0x97FFAD0CU, 0xAFB010B1U, 0xAB710D06U, 0xA6322BDFU, 0xA2F33668U,
0x251D3B9EU, 0x21DC2629U, 0x2C9F00F0U, 0x285E1D47U,
0x36194D42U, 0x32D850F5U, 0x3F9B762CU, 0x3B5A6B9BU,
0x0315D626U, 0x07D4CB91U, 0x0A97ED48U, 0x0E56F0FFU,
0x1011A0FAU, 0x14D0BD4DU, 0x19939B94U, 0x1D528623U,
0xF12F560EU, 0xF5EE4BB9U, 0xF8AD6D60U, 0xFC6C70D7U,
0xE22B20D2U, 0xE6EA3D65U, 0xEBA91BBCU, 0xEF68060BU,
0xD727BBB6U, 0xD3E6A601U, 0xDEA580D8U, 0xDA649D6FU,
0xC423CD6AU, 0xC0E2D0DDU, 0xCDA1F604U, 0xC960EBB3U,
0xBD3E8D7EU, 0xB9FF90C9U, 0xB4BCB610U, 0xB07DABA7U,
0xAE3AFBA2U, 0xAAFBE615U, 0xA7B8C0CCU, 0xA379DD7BU,
0x9B3660C6U, 0x9FF77D71U, 0x92B45BA8U, 0x9675461FU,
0x8832161AU, 0x8CF30BADU, 0x81B02D74U, 0x857130C3U,
0x5D8A9099U, 0x594B8D2EU, 0x5408ABF7U, 0x50C9B640U,
0x4E8EE645U, 0x4A4FFBF2U, 0x470CDD2BU, 0x43CDC09CU,
0x7B827D21U, 0x7F436096U, 0x7200464FU, 0x76C15BF8U,
0x68860BFDU, 0x6C47164AU, 0x61043093U, 0x65C52D24U,
0x119B4BE9U, 0x155A565EU, 0x18197087U, 0x1CD86D30U,
0x029F3D35U, 0x065E2082U, 0x0B1D065BU, 0x0FDC1BECU,
0x3793A651U, 0x3352BBE6U, 0x3E119D3FU, 0x3AD08088U,
0x2497D08DU, 0x2056CD3AU, 0x2D15EBE3U, 0x29D4F654U,
0xC5A92679U, 0xC1683BCEU, 0xCC2B1D17U, 0xC8EA00A0U,
0xD6AD50A5U, 0xD26C4D12U, 0xDF2F6BCBU, 0xDBEE767CU,
0xE3A1CBC1U, 0xE760D676U, 0xEA23F0AFU, 0xEEE2ED18U,
0xF0A5BD1DU, 0xF464A0AAU, 0xF9278673U, 0xFDE69BC4U,
0x89B8FD09U, 0x8D79E0BEU, 0x803AC667U, 0x84FBDBD0U,
0x9ABC8BD5U, 0x9E7D9662U, 0x933EB0BBU, 0x97FFAD0CU,
0xAFB010B1U, 0xAB710D06U, 0xA6322BDFU, 0xA2F33668U,
0xBCB4666DU, 0xB8757BDAU, 0xB5365D03U, 0xB1F740B4U, 0xBCB4666DU, 0xB8757BDAU, 0xB5365D03U, 0xB1F740B4U,
}; };
@ -417,15 +334,11 @@ namespace OGG {
int Page::getPayloadSize(){ int Page::getPayloadSize(){
size_t res = 0; size_t res = 0;
for (unsigned int i = 0; i < segments.size(); i++){ for (unsigned int i = 0; i < segments.size(); i++){res += segments[i].size();}
res += segments[i].size();
}
return res; return res;
} }
const std::deque<std::string> & Page::getAllSegments(){ const std::deque<std::string> &Page::getAllSegments(){return segments;}
return segments;
}
void Page::prepareNext(bool continueMe){ void Page::prepareNext(bool continueMe){
clear(0, -1, getBitstreamSerialNumber(), getPageSequenceNumber() + 1); clear(0, -1, getBitstreamSerialNumber(), getPageSequenceNumber() + 1);
@ -444,7 +357,6 @@ namespace OGG {
setPageSequenceNumber(PSN); setPageSequenceNumber(PSN);
} }
unsigned int Page::addSegment(const std::string &payload){// returns added bytes unsigned int Page::addSegment(const std::string &payload){// returns added bytes
segments.push_back(payload); segments.push_back(payload);
return payload.size(); return payload.size();
@ -462,7 +374,8 @@ namespace OGG {
for (unsigned int i = 0; i < segments.size(); i++){ for (unsigned int i = 0; i < segments.size(); i++){
segAmount = (segments[i].size() / 255) + 1; segAmount = (segments[i].size() / 255) + 1;
if (segAmount + curSegNum > 255){ if (segAmount + curSegNum > 255){
retVal += ((segAmount - (255 - curSegNum + 1)) * 255) + (segments[i].size() % 255);//calculate the extra bytes that overflow retVal += ((segAmount - (255 - curSegNum + 1)) * 255) +
(segments[i].size() % 255); // calculate the extra bytes that overflow
curSegNum = 255; // making sure the segment numbers are at maximum curSegNum = 255; // making sure the segment numbers are at maximum
}else{ }else{
curSegNum += segAmount; curSegNum += segAmount;
@ -510,19 +423,12 @@ namespace OGG {
return tempGranule; return tempGranule;
} }
bool Page::shouldSend(){ bool Page::shouldSend(){
unsigned int totalSegmentSize = 0; unsigned int totalSegmentSize = 0;
if (!oggSegments.size()){ if (!oggSegments.size()){return false;}
return false; if (oggSegments.rbegin()->isKeyframe){return true;}
}
if (oggSegments.rbegin()->isKeyframe){
return true;
}
if (codec == OGG::VORBIS){ if (codec == OGG::VORBIS){
if (lastKeyFrame - firstSample >= sampleRate){ if (lastKeyFrame - firstSample >= sampleRate){return true;}
return true;
}
} }
for (unsigned int i = 0; i < oggSegments.size(); i++){ for (unsigned int i = 0; i < oggSegments.size(); i++){
@ -539,9 +445,7 @@ namespace OGG {
HIGH_MSG("!segments.size()"); HIGH_MSG("!segments.size()");
return; return;
} }
if (codec == OGG::VORBIS){ if (codec == OGG::VORBIS){firstSample = lastKeyFrame;}
firstSample = lastKeyFrame;
}
int temp = 0; int temp = 0;
long unsigned int checksum = 0; // reset checksum long unsigned int checksum = 0; // reset checksum
setCRCChecksum(0); setCRCChecksum(0);
@ -585,9 +489,7 @@ namespace OGG {
granules = -1; granules = -1;
}else{ }else{
unsigned int tempIndex = numSegments - 1; unsigned int tempIndex = numSegments - 1;
if (bytesLeft != 0){ if (bytesLeft != 0){tempIndex = numSegments - 2;}
tempIndex = numSegments - 2;
}
granules = calculateGranule(oggSegments[tempIndex]); granules = calculateGranule(oggSegments[tempIndex]);
} }
}else{ }else{
@ -617,7 +519,6 @@ namespace OGG {
destination.SendNow(&tableSize, 1); destination.SendNow(&tableSize, 1);
destination.SendNow(table, tableSize); destination.SendNow(table, tableSize);
for (unsigned int i = 0; i < numSegments; i++){ for (unsigned int i = 0; i < numSegments; i++){
if (bytesLeft != 0 && ((i + 1) == numSegments)){ if (bytesLeft != 0 && ((i + 1) == numSegments)){
destination.SendNow(oggSegments.begin()->dataString.data(), bytesLeft); destination.SendNow(oggSegments.begin()->dataString.data(), bytesLeft);
@ -631,7 +532,6 @@ namespace OGG {
oggSegments.erase(oggSegments.begin()); oggSegments.erase(oggSegments.begin());
setHeaderType(OGG::Plain); // not a continuation setHeaderType(OGG::Plain); // not a continuation
} }
} }
// done sending, assume start of new page. // done sending, assume start of new page.
@ -641,11 +541,5 @@ namespace OGG {
// granule still requires setting! // granule still requires setting!
free(table); free(table);
return; return;
} }
} }// namespace OGG

View file

@ -1,13 +1,13 @@
#pragma once #pragma once
#include <cstdlib>
#include <string>
#include <vector>
#include <deque>
#include <sstream>
#include "dtsc.h" #include "dtsc.h"
#include "socket.h"
#include "theora.h" #include "theora.h"
#include "vorbis.h" #include "vorbis.h"
#include "socket.h" #include <cstdlib>
#include <deque>
#include <sstream>
#include <string>
#include <vector>
namespace OGG{ namespace OGG{
@ -24,18 +24,10 @@ namespace OGG {
enum oggCodec{THEORA, VORBIS, OPUS}; enum oggCodec{THEORA, VORBIS, OPUS};
enum HeaderType { enum HeaderType{Plain = 0, Continued = 1, BeginOfStream = 2, EndOfStream = 4};
Plain = 0,
Continued = 1,
BeginOfStream = 2,
EndOfStream = 4
};
std::deque<unsigned int> decodeXiphSize(char *data, size_t len); std::deque<unsigned int> decodeXiphSize(char *data, size_t len);
class Page{ class Page{
public: public:
Page(); Page();
@ -101,8 +93,6 @@ namespace OGG {
private: private:
char data[282]; // Fulldata char data[282]; // Fulldata
std::deque<std::string> segments; std::deque<std::string> segments;
}; };
class oggTrack{ class oggTrack{
@ -136,6 +126,4 @@ namespace OGG {
std::map<long long unsigned int, unsigned int> DTSCID2seqNum; std::map<long long unsigned int, unsigned int> DTSCID2seqNum;
std::string parsedPages; std::string parsedPages;
}; };
} }// namespace OGG

View file

@ -3,10 +3,7 @@
namespace Opus{ namespace Opus{
uint16_t getPreSkip(const char *initData){return initData[10] + initData[11] * 256;}
uint16_t getPreSkip(const char * initData){
return initData[10] + initData[11]* 256;
}
unsigned int Opus_getDuration(const char *part){ unsigned int Opus_getDuration(const char *part){
const char config = part[0] >> 3; const char config = part[0] >> 3;
@ -107,5 +104,4 @@ namespace Opus{
r << ": " << packets << " packets (VBR = " << VBR << ", padding = " << pad << ")"; r << ": " << packets << " packets (VBR = " << VBR << ", padding = " << pad << ")";
return r.str(); return r.str();
} }
} }// namespace Opus

View file

@ -1,9 +1,8 @@
#include <string>
#include <stdint.h> #include <stdint.h>
#include <string>
namespace Opus{ namespace Opus{
uint16_t getPreSkip(const char *initData); uint16_t getPreSkip(const char *initData);
unsigned int Opus_getDuration(const char *part); unsigned int Opus_getDuration(const char *part);
std::string Opus_prettyPacket(const char *part, int len); std::string Opus_prettyPacket(const char *part, int len);
} }// namespace Opus

View file

@ -1,25 +1,25 @@
/// \file procs.cpp /// \file procs.cpp
/// Contains generic functions for managing processes. /// Contains generic functions for managing processes.
#include "procs.h"
#include "defines.h" #include "defines.h"
#include "procs.h"
#include <signal.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <signal.h>
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__MACH__) #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__MACH__)
#include <sys/wait.h> #include <sys/wait.h>
#else #else
#include <wait.h> #include <wait.h>
#endif #endif
#include <errno.h>
#include <iostream>
#include <sys/types.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdlib.h>
#include <stdio.h>
#include "timing.h" #include "timing.h"
#include <errno.h>
#include <fcntl.h>
#include <iostream>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
std::set<pid_t> Util::Procs::plist; std::set<pid_t> Util::Procs::plist;
std::set<int> Util::Procs::socketList; std::set<int> Util::Procs::socketList;
@ -28,7 +28,6 @@ bool Util::Procs::thread_handler = false;
tthread::mutex Util::Procs::plistMutex; tthread::mutex Util::Procs::plistMutex;
tthread::thread *Util::Procs::reaper_thread = 0; tthread::thread *Util::Procs::reaper_thread = 0;
/// Local-only function. Attempts to reap child and returns current running status. /// Local-only function. Attempts to reap child and returns current running status.
bool Util::Procs::childRunning(pid_t p){ bool Util::Procs::childRunning(pid_t p){
int status; int status;
@ -49,9 +48,7 @@ bool Util::Procs::childRunning(pid_t p) {
} }
return false; return false;
} }
if (ret < 0 && errno == EINTR) { if (ret < 0 && errno == EINTR){return childRunning(p);}
return childRunning(p);
}
return !kill(p, 0); return !kill(p, 0);
} }
@ -79,9 +76,7 @@ void Util::Procs::exit_handler() {
reaper_thread = 0; reaper_thread = 0;
} }
std::set<pid_t>::iterator it; std::set<pid_t>::iterator it;
if (listcopy.empty()) { if (listcopy.empty()){return;}
return;
}
// wait up to 0.5 second for applications to shut down // wait up to 0.5 second for applications to shut down
while (!listcopy.empty() && waiting <= 25){ while (!listcopy.empty() && waiting <= 25){
@ -96,11 +91,10 @@ void Util::Procs::exit_handler() {
} }
} }
} }
if (listcopy.empty()) { if (listcopy.empty()){return;}
return;
}
INFO_MSG("Sending SIGINT and waiting up to 10 seconds for %d children to terminate.", (int)listcopy.size()); INFO_MSG("Sending SIGINT and waiting up to 10 seconds for %d children to terminate.",
(int)listcopy.size());
waiting = 0; waiting = 0;
// wait up to 10 seconds for applications to shut down // wait up to 10 seconds for applications to shut down
while (!listcopy.empty() && waiting <= 500){ while (!listcopy.empty() && waiting <= 500){
@ -123,9 +117,7 @@ void Util::Procs::exit_handler() {
++waiting; ++waiting;
} }
} }
if (listcopy.empty()) { if (listcopy.empty()){return;}
return;
}
ERROR_MSG("Sending SIGKILL to remaining %d children", (int)listcopy.size()); ERROR_MSG("Sending SIGKILL to remaining %d children", (int)listcopy.size());
// send sigkill to all remaining // send sigkill to all remaining
@ -151,9 +143,7 @@ void Util::Procs::exit_handler() {
} }
} }
} }
if (listcopy.empty()) { if (listcopy.empty()){return;}
return;
}
FAIL_MSG("Giving up with %d children left.", (int)listcopy.size()); FAIL_MSG("Giving up with %d children left.", (int)listcopy.size());
} }
@ -210,9 +200,7 @@ void Util::Procs::grim_reaper(void * n){
while (ret != 0){ while (ret != 0){
ret = waitpid(-1, &status, WNOHANG); ret = waitpid(-1, &status, WNOHANG);
if (ret <= 0){// ignore, would block otherwise if (ret <= 0){// ignore, would block otherwise
if (ret == 0 || errno != EINTR) { if (ret == 0 || errno != EINTR){break;}
break;
}
continue; continue;
} }
int exitcode; int exitcode;
@ -241,15 +229,12 @@ void Util::Procs::childsig_handler(int signum) {
return; return;
} }
/// Runs the given command and returns the stdout output as a string. /// Runs the given command and returns the stdout output as a string.
std::string Util::Procs::getOutputOf(char *const *argv){ std::string Util::Procs::getOutputOf(char *const *argv){
std::string ret; std::string ret;
int fin = 0, fout = -1, ferr = 0; int fin = 0, fout = -1, ferr = 0;
pid_t myProc = StartPiped(argv, &fin, &fout, &ferr); pid_t myProc = StartPiped(argv, &fin, &fout, &ferr);
while (childRunning(myProc)) { while (childRunning(myProc)){Util::sleep(100);}
Util::sleep(100);
}
FILE *outFile = fdopen(fout, "r"); FILE *outFile = fdopen(fout, "r");
char *fileBuf = 0; char *fileBuf = 0;
size_t fileBufLen = 0; size_t fileBufLen = 0;
@ -261,13 +246,10 @@ std::string Util::Procs::getOutputOf(char * const * argv) {
return ret; return ret;
} }
/// This function prepares a deque for getOutputOf and automatically inserts a NULL at the end of the char* const* /// This function prepares a deque for getOutputOf and automatically inserts a NULL at the end of the char* const*
char *const *Util::Procs::dequeToArgv(std::deque<std::string> &argDeq){ char *const *Util::Procs::dequeToArgv(std::deque<std::string> &argDeq){
char **ret = (char **)malloc((argDeq.size() + 1) * sizeof(char *)); char **ret = (char **)malloc((argDeq.size() + 1) * sizeof(char *));
for (int i = 0; i<argDeq.size(); i++){ for (int i = 0; i < argDeq.size(); i++){ret[i] = (char *)argDeq[i].c_str();}
ret[i] = (char*)argDeq[i].c_str();
}
ret[argDeq.size()] = NULL; ret[argDeq.size()] = NULL;
return ret; return ret;
} }
@ -289,9 +271,9 @@ pid_t Util::Procs::StartPiped(std::deque<std::string> & argDeq, int * fdin, int
/// Starts a new process with given fds if the name is not already active. /// Starts a new process with given fds if the name is not already active.
/// \return 0 if process was not started, process PID otherwise. /// \return 0 if process was not started, process PID otherwise.
/// \arg argv Command for this process. /// \arg argv Command for this process.
/// \arg fdin Standard input file descriptor. If null, /dev/null is assumed. Otherwise, if arg contains -1, a new fd is automatically allocated and written into this arg. Then the arg will be used as fd. /// \arg fdin Standard input file descriptor. If null, /dev/null is assumed. Otherwise, if arg
/// \arg fdout Same as fdin, but for stdout. /// contains -1, a new fd is automatically allocated and written into this arg. Then the arg will be
/// \arg fdout Same as fdin, but for stderr. /// used as fd. \arg fdout Same as fdin, but for stdout. \arg fdout Same as fdin, but for stderr.
pid_t Util::Procs::StartPiped(const char *const *argv, int *fdin, int *fdout, int *fderr){ pid_t Util::Procs::StartPiped(const char *const *argv, int *fdin, int *fdout, int *fderr){
pid_t pid; pid_t pid;
int pipein[2], pipeout[2], pipeerr[2]; int pipein[2], pipeout[2], pipeerr[2];
@ -344,7 +326,8 @@ pid_t Util::Procs::StartPiped(const char * const * argv, int * fdin, int * fdout
if (pid == 0){// child if (pid == 0){// child
handler_set = false; handler_set = false;
// Close all sockets in the socketList // Close all sockets in the socketList
for (std::set<int>::iterator it = Util::Procs::socketList.begin(); it != Util::Procs::socketList.end(); ++it){ for (std::set<int>::iterator it = Util::Procs::socketList.begin();
it != Util::Procs::socketList.end(); ++it){
close(*it); close(*it);
} }
if (!fdin){ if (!fdin){
@ -374,18 +357,10 @@ pid_t Util::Procs::StartPiped(const char * const * argv, int * fdin, int * fdout
}else if (*fderr != STDERR_FILENO){ }else if (*fderr != STDERR_FILENO){
dup2(*fderr, STDERR_FILENO); dup2(*fderr, STDERR_FILENO);
} }
if (fdin && *fdin != -1 && *fdin != STDIN_FILENO) { if (fdin && *fdin != -1 && *fdin != STDIN_FILENO){close(*fdin);}
close(*fdin); if (fdout && *fdout != -1 && *fdout != STDOUT_FILENO){close(*fdout);}
} if (fderr && *fderr != -1 && *fderr != STDERR_FILENO){close(*fderr);}
if (fdout && *fdout != -1 && *fdout != STDOUT_FILENO) { if (devnull != -1){close(devnull);}
close(*fdout);
}
if (fderr && *fderr != -1 && *fderr != STDERR_FILENO) {
close(*fderr);
}
if (devnull != -1) {
close(devnull);
}
// Because execvp requires a char* const* and we have a const char* const* // Because execvp requires a char* const* and we have a const char* const*
execvp(argv[0], (char *const *)argv); execvp(argv[0], (char *const *)argv);
/*LTS-START*/ /*LTS-START*/
@ -417,9 +392,7 @@ pid_t Util::Procs::StartPiped(const char * const * argv, int * fdin, int * fdout
close(pipeerr[0]); close(pipeerr[0]);
close(pipeerr[1]); close(pipeerr[1]);
} }
if (devnull != -1) { if (devnull != -1){close(devnull);}
close(devnull);
}
return 0; return 0;
}else{// parent }else{// parent
{ {
@ -427,9 +400,7 @@ pid_t Util::Procs::StartPiped(const char * const * argv, int * fdin, int * fdout
plist.insert(pid); plist.insert(pid);
} }
HIGH_MSG("Piped process %s started, PID %d", argv[0], pid); HIGH_MSG("Piped process %s started, PID %d", argv[0], pid);
if (devnull != -1) { if (devnull != -1){close(devnull);}
close(devnull);
}
if (fdin && *fdin == -1){ if (fdin && *fdin == -1){
close(pipein[0]); // close unused end end close(pipein[0]); // close unused end end
*fdin = pipein[1]; *fdin = pipein[1];
@ -466,9 +437,7 @@ void Util::Procs::StopAll() {
listcopy = plist; listcopy = plist;
} }
std::set<pid_t>::iterator it; std::set<pid_t>::iterator it;
for (it = listcopy.begin(); it != listcopy.end(); it++) { for (it = listcopy.begin(); it != listcopy.end(); it++){Stop(*it);}
Stop(*it);
}
} }
/// Returns the number of active child processes. /// Returns the number of active child processes.
@ -494,4 +463,3 @@ void Util::Procs::remember(pid_t pid) {
tthread::lock_guard<tthread::mutex> guard(plistMutex); tthread::lock_guard<tthread::mutex> guard(plistMutex);
plist.insert(pid); plist.insert(pid);
} }

View file

@ -2,12 +2,12 @@
/// Contains generic function headers for managing processes. /// Contains generic function headers for managing processes.
#pragma once #pragma once
#include <unistd.h>
#include <string>
#include <set>
#include <vector>
#include <deque>
#include "tinythread.h" #include "tinythread.h"
#include <deque>
#include <set>
#include <string>
#include <unistd.h>
#include <vector>
/// Contains utility code, not directly related to streaming media /// Contains utility code, not directly related to streaming media
namespace Util{ namespace Util{
@ -22,6 +22,7 @@ namespace Util {
static void exit_handler(); static void exit_handler();
static char *const *dequeToArgv(std::deque<std::string> &argDeq); static char *const *dequeToArgv(std::deque<std::string> &argDeq);
static void grim_reaper(void *n); static void grim_reaper(void *n);
public: public:
static bool childRunning(pid_t p); static bool childRunning(pid_t p);
static tthread::thread *reaper_thread; static tthread::thread *reaper_thread;
@ -43,5 +44,4 @@ namespace Util {
static void remember(pid_t pid); static void remember(pid_t pid);
static std::set<int> socketList; ///< Holds sockets that should be closed before forking static std::set<int> socketList; ///< Holds sockets that should be closed before forking
}; };
} }// namespace Util

View file

@ -5,8 +5,8 @@ namespace RIFF{
Chunk::Chunk(const void *_p, uint32_t len){ Chunk::Chunk(const void *_p, uint32_t len){
p = (const char *)_p; p = (const char *)_p;
if (len && len < getPayloadSize() + 8){ if (len && len < getPayloadSize() + 8){
FAIL_MSG("Chunk %s (%" PRIu32 "b) does not fit in %" PRIu32 " bytes length!", getType().c_str(), FAIL_MSG("Chunk %s (%" PRIu32 "b) does not fit in %" PRIu32 " bytes length!",
getPayloadSize() + 8, len); getType().c_str(), getPayloadSize() + 8, len);
p = 0; p = 0;
} }
} }
@ -109,11 +109,9 @@ namespace RIFF{
return std::string(p + 32, 16); return std::string(p + 32, 16);
} }
void fmt::toPrettyString(std::ostream &o, size_t indent) const{ void fmt::toPrettyString(std::ostream &o, size_t indent) const{
o << std::string(indent, ' ') << "[" << getType() << "] (" << (getPayloadSize() + 8) o << std::string(indent, ' ') << "[" << getType() << "] (" << (getPayloadSize() + 8) << "b):" << std::endl;
<< "b):" << std::endl;
indent += 1; indent += 1;
o << std::string(indent, ' ') << "Codec: " << getCodec() << " (" << getFormat() << ")" o << std::string(indent, ' ') << "Codec: " << getCodec() << " (" << getFormat() << ")" << std::endl;
<< std::endl;
o << std::string(indent, ' ') << "Channels: " << getChannels() << std::endl; o << std::string(indent, ' ') << "Channels: " << getChannels() << std::endl;
o << std::string(indent, ' ') << "Sample rate: " << getHz() << "Hz" << std::endl; o << std::string(indent, ' ') << "Sample rate: " << getHz() << "Hz" << std::endl;
o << std::string(indent, ' ') << "Bytes/s: " << getBPS() << std::endl; o << std::string(indent, ' ') << "Bytes/s: " << getBPS() << std::endl;
@ -132,7 +130,8 @@ namespace RIFF{
} }
} }
} }
std::string fmt::generate(uint16_t format, uint16_t channels, uint32_t hz, uint32_t bps, uint16_t blocksize, uint16_t size){ std::string fmt::generate(uint16_t format, uint16_t channels, uint32_t hz, uint32_t bps,
uint16_t blocksize, uint16_t size){
std::string ret("fmt \022\000\000\000", 8); std::string ret("fmt \022\000\000\000", 8);
ret.append(std::string((size_t)18, '\000')); ret.append(std::string((size_t)18, '\000'));
Bit::htobs_le((char *)ret.data() + 8, format); Bit::htobs_le((char *)ret.data() + 8, format);
@ -150,8 +149,7 @@ namespace RIFF{
return Bit::btohl_le(p + 8); return Bit::btohl_le(p + 8);
} }
void fact::toPrettyString(std::ostream &o, size_t indent) const{ void fact::toPrettyString(std::ostream &o, size_t indent) const{
o << std::string(indent, ' ') << "[" << getType() << "] (" << (getPayloadSize() + 8) o << std::string(indent, ' ') << "[" << getType() << "] (" << (getPayloadSize() + 8) << "b):" << std::endl;
<< "b):" << std::endl;
indent += 1; indent += 1;
o << std::string(indent, ' ') << "Samples per channel: " << getSamplesPerChannel() << std::endl; o << std::string(indent, ' ') << "Samples per channel: " << getSamplesPerChannel() << std::endl;
} }
@ -166,10 +164,8 @@ namespace RIFF{
return std::string(p + 8, getPayloadSize()); return std::string(p + 8, getPayloadSize());
} }
void ISFT::toPrettyString(std::ostream &o, size_t indent) const{ void ISFT::toPrettyString(std::ostream &o, size_t indent) const{
o << std::string(indent, ' ') << "[" << getType() << "] (" << (getPayloadSize() + 8) o << std::string(indent, ' ') << "[" << getType() << "] (" << (getPayloadSize() + 8) << "b):" << std::endl;
<< "b):" << std::endl;
indent += 1; indent += 1;
o << std::string(indent, ' ') << "Software: " << getSoftware() << std::endl; o << std::string(indent, ' ') << "Software: " << getSoftware() << std::endl;
} }
} }// namespace RIFF

View file

@ -41,7 +41,8 @@ namespace RIFF{
/// WAVE "fmt " class. /// WAVE "fmt " class.
class fmt : public Chunk{ class fmt : public Chunk{
public: public:
static std::string generate(uint16_t format, uint16_t channels, uint32_t hz, uint32_t bps, uint16_t blocksize, uint16_t size); static std::string generate(uint16_t format, uint16_t channels, uint32_t hz, uint32_t bps,
uint16_t blocksize, uint16_t size);
fmt(const void *_p = 0, uint32_t len = 0) : Chunk(_p, len){} fmt(const void *_p = 0, uint32_t len = 0) : Chunk(_p, len){}
uint16_t getFormat() const; uint16_t getFormat() const;
std::string getCodec() const; std::string getCodec() const;
@ -74,6 +75,4 @@ namespace RIFF{
virtual void toPrettyString(std::ostream &o, size_t indent = 0) const; virtual void toPrettyString(std::ostream &o, size_t indent = 0) const;
}; };
}// namespace RIFF
}

View file

@ -1,168 +1,349 @@
// This entire file is public domain and comes with no warranties. // This entire file is public domain and comes with no warranties.
// Based on work by Vincent Rijmen, Antoon Bosselaers and Paulo Barreto. // Based on work by Vincent Rijmen, Antoon Bosselaers and Paulo Barreto.
#include "rijndael.h"
#include "bitfields.h" #include "bitfields.h"
#include "defines.h" #include "defines.h"
#include "rijndael.h"
#include <iostream>
#include <iomanip> #include <iomanip>
#include <iostream>
static const unsigned int Te0[256] ={ static const unsigned int Te0[256] ={
0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U,
0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, 0x91c5c554U, 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U,
0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, 0x4dababe6U, 0xec76769aU, 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, 0xeffafa15U,
0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU,
0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, 0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, 0x6834345cU, 0x51a5a5f4U,
0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, 0xd1e5e534U, 0xf9f1f108U, 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, 0x0804040cU,
0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU,
0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, 0xea75759fU, 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U,
0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, 0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, 0x5229297bU,
0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U,
0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, 0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, 0xbbd0d06bU, 0xc5efef2aU,
0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, 0x4faaaae5U, 0xedfbfb16U, 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU,
0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, 0x3f9292adU, 0x219d9dbcU, 0x70383848U,
0xf1f5f504U, 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, 0x20101030U, 0xe5ffff1aU,
0xfdf3f30eU, 0xbfd2d26dU, 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, 0xbe5f5fe1U,
0x359797a2U, 0x884444ccU, 0x2e171739U, 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U,
0xa3dcdc7fU, 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, 0x8c4646caU, 0xc7eeee29U,
0x6bb8b8d3U, 0x2814143cU, 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, 0xdbe0e03bU,
0x64323256U, 0x743a3a4eU, 0x140a0a1eU, 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, 0x399191a8U, 0x319595a4U, 0xd3e4e437U,
0xf279798bU, 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, 0x018d8d8cU, 0xb1d5d564U,
0x9c4e4ed2U, 0x49a9a9e0U, 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, 0xca6565afU,
0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU,
0x3e1f1f21U, 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, 0xe0707090U, 0x7c3e3e42U,
0x71b5b5c4U, 0xcc6666aaU, 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, 0xc26161a3U,
0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U,
0x339494a7U, 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, 0x87cece49U, 0xaa5555ffU,
0x50282878U, 0xa5dfdf7aU, 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, 0x65bfbfdaU,
0xd7e6e631U, 0x844242c6U, 0xd06868b8U, 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
}; };
static const unsigned int Te1[256] ={ static const unsigned int Te1[256] ={
0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU,
0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, 0x5491c5c5U, 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U,
0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, 0xe64dababU, 0x9aec7676U, 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, 0x15effafaU,
0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U,
0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, 0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, 0x5c683434U, 0xf451a5a5U,
0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, 0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, 0x0c080404U,
0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U,
0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, 0x9fea7575U, 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU,
0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, 0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, 0x7b522929U,
0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU,
0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, 0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, 0x6bbbd0d0U, 0x2ac5efefU,
0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, 0xe54faaaaU, 0x16edfbfbU, 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U,
0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, 0xad3f9292U, 0xbc219d9dU, 0x48703838U,
0x04f1f5f5U, 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, 0x30201010U, 0x1ae5ffffU,
0x0efdf3f3U, 0x6dbfd2d2U, 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, 0xe1be5f5fU,
0xa2359797U, 0xcc884444U, 0x392e1717U, 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, 0xa0c06060U, 0x98198181U, 0xd19e4f4fU,
0x7fa3dcdcU, 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, 0xca8c4646U, 0x29c7eeeeU,
0xd36bb8b8U, 0x3c281414U, 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, 0x3bdbe0e0U,
0x56643232U, 0x4e743a3aU, 0x1e140a0aU, 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, 0xa8399191U, 0xa4319595U, 0x37d3e4e4U,
0x8bf27979U, 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, 0x8c018d8dU, 0x64b1d5d5U,
0xd29c4e4eU, 0xe049a9a9U, 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, 0xafca6565U,
0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U,
0x213e1f1fU, 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, 0x90e07070U, 0x427c3e3eU,
0xc471b5b5U, 0xaacc6666U, 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, 0xa3c26161U,
0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU,
0xa7339494U, 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, 0x4987ceceU, 0xffaa5555U,
0x78502828U, 0x7aa5dfdfU, 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, 0xda65bfbfU,
0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
}; };
static const unsigned int Te2[256] ={ static const unsigned int Te2[256] ={
0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU,
0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, 0xc55491c5U, 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U,
0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, 0xabe64dabU, 0x769aec76U, 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, 0xfa15effaU,
0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U,
0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, 0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, 0x345c6834U, 0xa5f451a5U,
0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, 0xe534d1e5U, 0xf108f9f1U, 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, 0x040c0804U,
0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U,
0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, 0x759fea75U, 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU,
0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, 0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, 0x297b5229U,
0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU, 0xbed967beU,
0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, 0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, 0xd06bbbd0U, 0xef2ac5efU,
0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, 0xaae54faaU, 0xfb16edfbU, 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U,
0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, 0x92ad3f92U, 0x9dbc219dU, 0x38487038U,
0xf504f1f5U, 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, 0x10302010U, 0xff1ae5ffU,
0xf30efdf3U, 0xd26dbfd2U, 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, 0x5fe1be5fU,
0x97a23597U, 0x44cc8844U, 0x17392e17U, 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, 0x60a0c060U, 0x81981981U, 0x4fd19e4fU,
0xdc7fa3dcU, 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, 0x46ca8c46U, 0xee29c7eeU,
0xb8d36bb8U, 0x143c2814U, 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, 0xe03bdbe0U,
0x32566432U, 0x3a4e743aU, 0x0a1e140aU, 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, 0x91a83991U, 0x95a43195U, 0xe437d3e4U,
0x798bf279U, 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, 0x8d8c018dU, 0xd564b1d5U,
0x4ed29c4eU, 0xa9e049a9U, 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, 0x65afca65U,
0x7a8ef47aU, 0xaee947aeU, 0x08181008U, 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U,
0x1f213e1fU, 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, 0x7090e070U, 0x3e427c3eU,
0xb5c471b5U, 0x66aacc66U, 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, 0x61a3c261U,
0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU,
0x94a73394U, 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, 0xce4987ceU, 0x55ffaa55U,
0x28785028U, 0xdf7aa5dfU, 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, 0xbfda65bfU,
0xe631d7e6U, 0x42c68442U, 0x68b8d068U, 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
}; };
static const unsigned int Te3[256] ={ static const unsigned int Te3[256] ={
0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU,
0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, 0xc5c55491U, 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U,
0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, 0xababe64dU, 0x76769aecU, 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, 0xfafa15efU,
0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU,
0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, 0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, 0x34345c68U, 0xa5a5f451U,
0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, 0xe5e534d1U, 0xf1f108f9U, 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, 0x04040c08U,
0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU,
0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, 0x75759feaU, 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU,
0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, 0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, 0x29297b52U,
0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U,
0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, 0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, 0xd0d06bbbU, 0xefef2ac5U,
0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, 0xaaaae54fU, 0xfbfb16edU, 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU,
0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U,
0xf5f504f1U, 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, 0x10103020U, 0xffff1ae5U,
0xf3f30efdU, 0xd2d26dbfU, 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, 0x5f5fe1beU,
0x9797a235U, 0x4444cc88U, 0x1717392eU, 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU,
0xdcdc7fa3U, 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, 0x4646ca8cU, 0xeeee29c7U,
0xb8b8d36bU, 0x14143c28U, 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, 0xe0e03bdbU,
0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, 0x9191a839U, 0x9595a431U, 0xe4e437d3U,
0x79798bf2U, 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, 0x8d8d8c01U, 0xd5d564b1U,
0x4e4ed29cU, 0xa9a9e049U, 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, 0x6565afcaU,
0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U,
0x1f1f213eU, 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, 0x707090e0U, 0x3e3e427cU,
0xb5b5c471U, 0x6666aaccU, 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, 0x6161a3c2U,
0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U,
0x9494a733U, 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, 0xcece4987U, 0x5555ffaaU,
0x28287850U, 0xdfdf7aa5U, 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, 0xbfbfda65U,
0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
}; };
static const unsigned int Td0[256] ={ static const unsigned int Td0[256] ={
0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU,
0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, 0x4be30393U, 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U,
0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 0x26354480U, 0xb562a38fU, 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, 0xc32f7502U,
0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, 0x75c2896aU, 0xf48e7978U, 0x99583e6bU,
0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, 0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, 0x63df4a18U, 0xe51a3182U,
0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, 0x97513360U, 0x62537f45U, 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 0x70486858U,
0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, 0x302887f2U, 0x23bfa5b2U, 0x02036abaU,
0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, 0xed16825cU, 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U,
0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, 0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, 0x0b83ec39U,
0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U, 0x894043ccU,
0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, 0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, 0xa17c0a47U, 0x7c420fe9U,
0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, 0xf8841ec9U, 0x00000000U, 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU,
0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, 0x0f853856U, 0x3daed51eU, 0x362d3927U, 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U,
0x1c121a16U, 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, 0x0e090d0bU, 0xf28bc7adU,
0x2db6a8b9U, 0x141ea9c8U, 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, 0xf701269fU,
0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, 0x854a247dU, 0xd2bb3df8U, 0xaef93211U,
0xc729a16dU, 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, 0x2bb3166cU, 0xa970b999U,
0x119448faU, 0x47e96422U, 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, 0x87494ec7U,
0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU,
0x82c3aff5U, 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, 0xc8ac993bU, 0x10187da7U,
0xe89c636eU, 0xdb3bbb7bU, 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, 0xe6956e65U,
0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U,
0x33a7d815U, 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, 0x764dd68dU, 0x43efb04dU,
0xccaa4d54U, 0xe49604dfU, 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, 0x9d5eea04U,
0x018c355dU, 0xfa877473U, 0xfb0b412eU, 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, 0xcea927eeU, 0xb761c935U, 0xe11ce5edU,
0x7a47b13cU, 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, 0x53f7cdeaU, 0x5ffdaa5bU,
0xdf3d6f14U, 0x7844db86U, 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, 0x161dc372U,
0xbce2250cU, 0x283c498bU, 0xff0d9541U, 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
}; };
static const unsigned int Td1[256] ={ static const unsigned int Td1[256] ={
0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U,
0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, 0x934be303U, 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU,
0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, 0x80263544U, 0x8fb562a3U, 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, 0x02c32f75U,
0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, 0x6a75c289U, 0x78f48e79U, 0x6b99583eU,
0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, 0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, 0x1863df4aU, 0x82e51a31U,
0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, 0x60975133U, 0x4562537fU, 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, 0x58704868U,
0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, 0xf2302887U, 0xb223bfa5U, 0xba02036aU,
0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, 0x5ced1682U, 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU,
0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, 0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, 0x390b83ecU,
0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U, 0xcc894043U,
0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, 0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, 0x47a17c0aU, 0xe97c420fU,
0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, 0xc9f8841eU, 0x00000000U, 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU,
0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU,
0x161c121aU, 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, 0x0b0e090dU, 0xadf28bc7U,
0xb92db6a8U, 0xc8141ea9U, 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, 0x9ff70126U,
0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U,
0x6dc729a1U, 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, 0x6c2bb316U, 0x99a970b9U,
0xfa119448U, 0x2247e964U, 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, 0xc787494eU,
0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U,
0xf582c3afU, 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, 0x3bc8ac99U, 0xa710187dU,
0x6ee89c63U, 0x7bdb3bbbU, 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, 0x65e6956eU,
0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U,
0x1533a7d8U, 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, 0x8d764dd6U, 0x4d43efb0U,
0x54ccaa4dU, 0xdfe49604U, 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, 0x049d5eeaU,
0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, 0xeecea927U, 0x35b761c9U, 0xede11ce5U,
0x3c7a47b1U, 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, 0xea53f7cdU, 0x5b5ffdaaU,
0x14df3d6fU, 0x867844dbU, 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, 0x72161dc3U,
0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
}; };
static const unsigned int Td2[256] ={ static const unsigned int Td2[256] ={
0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU,
0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, 0x03934be3U, 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU,
0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, 0x44802635U, 0xa38fb562U, 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, 0x7502c32fU,
0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U,
0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, 0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, 0x4a1863dfU, 0x3182e51aU,
0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, 0x33609751U, 0x7f456253U, 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, 0x68587048U,
0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, 0x87f23028U, 0xa5b223bfU, 0x6aba0203U,
0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, 0x825ced16U, 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U,
0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, 0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, 0xec390b83U,
0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU, 0x43cc8940U,
0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, 0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, 0x0a47a17cU, 0x0fe97c42U,
0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, 0x1ec9f884U, 0x00000000U, 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU,
0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U,
0x1a161c12U, 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, 0x0d0b0e09U, 0xc7adf28bU,
0xa8b92db6U, 0xa9c8141eU, 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, 0x269ff701U,
0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U,
0xa16dc729U, 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, 0x166c2bb3U, 0xb999a970U,
0x48fa1194U, 0x642247e9U, 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, 0x4ec78749U,
0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U,
0xaff582c3U, 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, 0x993bc8acU, 0x7da71018U,
0x636ee89cU, 0xbb7bdb3bU, 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, 0x6e65e695U,
0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U,
0xd81533a7U, 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, 0xd68d764dU, 0xb04d43efU,
0x4d54ccaaU, 0x04dfe496U, 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, 0xea049d5eU,
0x355d018cU, 0x7473fa87U, 0x412efb0bU, 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, 0x27eecea9U, 0xc935b761U, 0xe5ede11cU,
0xb13c7a47U, 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, 0xcdea53f7U, 0xaa5b5ffdU,
0x6f14df3dU, 0xdb867844U, 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, 0xc372161dU,
0x250cbce2U, 0x498b283cU, 0x9541ff0dU, 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
}; };
static const unsigned int Td3[256] ={ static const unsigned int Td3[256] ={
0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU,
0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, 0xe303934bU, 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U,
0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, 0x35448026U, 0x62a38fb5U, 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, 0x2f7502c3U,
0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U,
0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, 0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, 0xdf4a1863U, 0x1a3182e5U,
0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, 0x51336097U, 0x537f4562U, 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, 0x48685870U,
0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, 0x2887f230U, 0xbfa5b223U, 0x036aba02U,
0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, 0x16825cedU, 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U,
0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, 0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, 0x83ec390bU,
0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U, 0x4043cc89U,
0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, 0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, 0x7c0a47a1U, 0x420fe97cU,
0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, 0x841ec9f8U, 0x00000000U, 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU,
0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, 0xc0c54f80U, 0xdc20a261U, 0x774b695aU,
0x121a161cU, 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, 0x090d0b0eU, 0x8bc7adf2U,
0xb6a8b92dU, 0x1ea9c814U, 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, 0x01269ff7U,
0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU,
0x29a16dc7U, 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, 0xb3166c2bU, 0x70b999a9U,
0x9448fa11U, 0xe9642247U, 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, 0x494ec787U,
0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU,
0xc3aff582U, 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, 0xac993bc8U, 0x187da710U,
0x9c636ee8U, 0x3bbb7bdbU, 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, 0x956e65e6U,
0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U,
0xa7d81533U, 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, 0x4dd68d76U, 0xefb04d43U,
0xaa4d54ccU, 0x9604dfe4U, 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, 0x5eea049dU,
0x8c355d01U, 0x877473faU, 0x0b412efbU, 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U,
0x47b13c7aU, 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, 0xf7cdea53U, 0xfdaa5b5fU,
0x3d6f14dfU, 0x44db8678U, 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, 0x1dc37216U,
0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
}; };
static const char Td4[256] ={ static const char Td4[256] ={
0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U,
0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, 0xf3U, 0xd7U, 0xfbU, 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, 0x34U, 0x8eU,
0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U,
0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, 0x3dU, 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, 0x08U, 0x2eU, 0xa1U, 0x66U,
0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, 0x28U, 0xd9U, 0x24U, 0xb2U, 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, 0x72U,
0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U,
0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, 0xb6U, 0x92U, 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, 0x5eU, 0x15U, 0x46U,
0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU,
0x3fU, 0x0fU, 0x02U, 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, 0x3aU, 0x91U,
0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U,
0x73U, 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, 0xe2U, 0xf9U, 0x37U, 0xe8U,
0x1cU, 0x75U, 0xdfU, 0x6eU, 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, 0x6fU,
0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U,
0x79U, 0x20U, 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, 0x1fU, 0xddU, 0xa8U,
0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U,
0xc9U, 0x9cU, 0xefU, 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, 0xc8U, 0xebU,
0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U,
0x26U, 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
}; };
static const unsigned int rcon[] = {0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000}; static const unsigned int rcon[] ={0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000};
// Expand the cipher key into the encryption key schedule. // Expand the cipher key into the encryption key schedule.
void AES_set_encrypt_key(const char *userKey, const int bits, char *key){ void AES_set_encrypt_key(const char *userKey, const int bits, char *key){
@ -177,7 +358,8 @@ void AES_set_encrypt_key(const char * userKey, const int bits, char * key) {
if (bits == 128){ if (bits == 128){
while (1){ while (1){
temp = rk[3]; temp = rk[3];
rk[4] = rk[0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te0[(temp) & 0xff] & 0x0000ff00) ^ (Te1[(temp >> 24)] & 0x000000ff) ^ rcon[i]; rk[4] = rk[0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^
(Te0[(temp)&0xff] & 0x0000ff00) ^ (Te1[(temp >> 24)] & 0x000000ff) ^ rcon[i];
rk[5] = rk[1] ^ rk[4]; rk[5] = rk[1] ^ rk[4];
rk[6] = rk[2] ^ rk[5]; rk[6] = rk[2] ^ rk[5];
rk[7] = rk[3] ^ rk[6]; rk[7] = rk[3] ^ rk[6];
@ -193,7 +375,8 @@ void AES_set_encrypt_key(const char * userKey, const int bits, char * key) {
if (bits == 192){ if (bits == 192){
while (1){ while (1){
temp = rk[5]; temp = rk[5];
rk[ 6] = rk[ 0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te0[(temp) & 0xff] & 0x0000ff00) ^ (Te1[(temp >> 24)] & 0x000000ff) ^ rcon[i]; rk[6] = rk[0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^
(Te0[(temp)&0xff] & 0x0000ff00) ^ (Te1[(temp >> 24)] & 0x000000ff) ^ rcon[i];
rk[7] = rk[1] ^ rk[6]; rk[7] = rk[1] ^ rk[6];
rk[8] = rk[2] ^ rk[7]; rk[8] = rk[2] ^ rk[7];
rk[9] = rk[3] ^ rk[8]; rk[9] = rk[3] ^ rk[8];
@ -211,7 +394,8 @@ void AES_set_encrypt_key(const char * userKey, const int bits, char * key) {
if (bits == 256){ if (bits == 256){
while (1){ while (1){
temp = rk[7]; temp = rk[7];
rk[ 8] = rk[ 0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te0[(temp) & 0xff] & 0x0000ff00) ^ (Te1[(temp >> 24)] & 0x000000ff) ^ rcon[i]; rk[8] = rk[0] ^ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^ (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^
(Te0[(temp)&0xff] & 0x0000ff00) ^ (Te1[(temp >> 24)] & 0x000000ff) ^ rcon[i];
rk[9] = rk[1] ^ rk[8]; rk[9] = rk[1] ^ rk[8];
rk[10] = rk[2] ^ rk[9]; rk[10] = rk[2] ^ rk[9];
rk[11] = rk[3] ^ rk[10]; rk[11] = rk[3] ^ rk[10];
@ -220,7 +404,8 @@ void AES_set_encrypt_key(const char * userKey, const int bits, char * key) {
return; return;
} }
temp = rk[11]; temp = rk[11];
rk[12] = rk[ 4] ^ (Te2[(temp >> 24)] & 0xff000000) ^ (Te3[(temp >> 16) & 0xff] & 0x00ff0000) ^ (Te0[(temp >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(temp) & 0xff] & 0x000000ff); rk[12] = rk[4] ^ (Te2[(temp >> 24)] & 0xff000000) ^ (Te3[(temp >> 16) & 0xff] & 0x00ff0000) ^
(Te0[(temp >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(temp)&0xff] & 0x000000ff);
rk[13] = rk[5] ^ rk[12]; rk[13] = rk[5] ^ rk[12];
rk[14] = rk[6] ^ rk[13]; rk[14] = rk[6] ^ rk[13];
rk[15] = rk[7] ^ rk[14]; rk[15] = rk[7] ^ rk[14];
@ -235,9 +420,7 @@ void AES_set_encrypt_key(const char * userKey, const int bits, char * key) {
void printInverted(const unsigned int *data, unsigned int len){ void printInverted(const unsigned int *data, unsigned int len){
for (int i = 0; i < len; i++){ for (int i = 0; i < len; i++){
std::cout << "0x" << std::hex << std::setw(8) << std::setfill('0') << data[i] << ", "; std::cout << "0x" << std::hex << std::setw(8) << std::setfill('0') << data[i] << ", ";
if (i % 4 == 3){ if (i % 4 == 3){std::cout << std::endl;}
std::cout << std::endl;
}
} }
std::cout << std::endl; std::cout << std::endl;
} }
@ -252,12 +435,8 @@ void AES_set_decrypt_key(const char * userKey, const int bits, char * key) {
AES_set_encrypt_key(userKey, bits, key); AES_set_encrypt_key(userKey, bits, key);
unsigned int rounds = 10; unsigned int rounds = 10;
if (bits > 128) { if (bits > 128){rounds = 12;}
rounds = 12; if (bits > 192){rounds = 14;}
}
if (bits > 192) {
rounds = 14;
}
/* invert the order of the round keys: */ /* invert the order of the round keys: */
for (i = 0, j = 4 * rounds; i < j; i += 4, j -= 4){ for (i = 0, j = 4 * rounds; i < j; i += 4, j -= 4){
@ -277,10 +456,14 @@ void AES_set_decrypt_key(const char * userKey, const int bits, char * key) {
/* apply the inverse MixColumn transform to all round keys but the first and the last: */ /* apply the inverse MixColumn transform to all round keys but the first and the last: */
for (i = 1; i < rounds; i++){ for (i = 1; i < rounds; i++){
rk += 4; rk += 4;
rk[0] = Td0[Te1[(rk[0] >> 24)] & 0xff] ^ Td1[Te1[(rk[0] >> 16) & 0xff] & 0xff] ^ Td2[Te1[(rk[0] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[0]) & 0xff] & 0xff]; rk[0] = Td0[Te1[(rk[0] >> 24)] & 0xff] ^ Td1[Te1[(rk[0] >> 16) & 0xff] & 0xff] ^
rk[1] = Td0[Te1[(rk[1] >> 24)] & 0xff] ^ Td1[Te1[(rk[1] >> 16) & 0xff] & 0xff] ^ Td2[Te1[(rk[1] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[1]) & 0xff] & 0xff]; Td2[Te1[(rk[0] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[0]) & 0xff] & 0xff];
rk[2] = Td0[Te1[(rk[2] >> 24)] & 0xff] ^ Td1[Te1[(rk[2] >> 16) & 0xff] & 0xff] ^ Td2[Te1[(rk[2] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[2]) & 0xff] & 0xff]; rk[1] = Td0[Te1[(rk[1] >> 24)] & 0xff] ^ Td1[Te1[(rk[1] >> 16) & 0xff] & 0xff] ^
rk[3] = Td0[Te1[(rk[3] >> 24)] & 0xff] ^ Td1[Te1[(rk[3] >> 16) & 0xff] & 0xff] ^ Td2[Te1[(rk[3] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[3]) & 0xff] & 0xff]; Td2[Te1[(rk[1] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[1]) & 0xff] & 0xff];
rk[2] = Td0[Te1[(rk[2] >> 24)] & 0xff] ^ Td1[Te1[(rk[2] >> 16) & 0xff] & 0xff] ^
Td2[Te1[(rk[2] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[2]) & 0xff] & 0xff];
rk[3] = Td0[Te1[(rk[3] >> 24)] & 0xff] ^ Td1[Te1[(rk[3] >> 16) & 0xff] & 0xff] ^
Td2[Te1[(rk[3] >> 8) & 0xff] & 0xff] ^ Td3[Te1[(rk[3]) & 0xff] & 0xff];
} }
} }
@ -364,20 +547,20 @@ void AES_encrypt(const char * in, char * out, const int bits, const char * key)
} }
} }
rk += 40; rk += 40;
if (bits > 128) { if (bits > 128){rk += 8;}
rk += 8; if (bits > 192){rk += 8;}
}
if (bits > 192) {
rk += 8;
}
// apply last round and map cipher state to byte array block // apply last round and map cipher state to byte array block
s0 = (Te2[(t0 >> 24)] & 0xff000000) ^ (Te3[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te0[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t3) & 0xff] & 0x000000ff) ^ rk[0]; s0 = (Te2[(t0 >> 24)] & 0xff000000) ^ (Te3[(t1 >> 16) & 0xff] & 0x00ff0000) ^
(Te0[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t3)&0xff] & 0x000000ff) ^ rk[0];
Bit::htobl(out, s0); Bit::htobl(out, s0);
s1 = (Te2[(t1 >> 24)] & 0xff000000) ^ (Te3[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te0[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t0) & 0xff] & 0x000000ff) ^ rk[1]; s1 = (Te2[(t1 >> 24)] & 0xff000000) ^ (Te3[(t2 >> 16) & 0xff] & 0x00ff0000) ^
(Te0[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t0)&0xff] & 0x000000ff) ^ rk[1];
Bit::htobl(out + 4, s1); Bit::htobl(out + 4, s1);
s2 = (Te2[(t2 >> 24)] & 0xff000000) ^ (Te3[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te0[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t1) & 0xff] & 0x000000ff) ^ rk[2]; s2 = (Te2[(t2 >> 24)] & 0xff000000) ^ (Te3[(t3 >> 16) & 0xff] & 0x00ff0000) ^
(Te0[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t1)&0xff] & 0x000000ff) ^ rk[2];
Bit::htobl(out + 8, s2); Bit::htobl(out + 8, s2);
s3 = (Te2[(t3 >> 24)] & 0xff000000) ^ (Te3[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te0[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t2) & 0xff] & 0x000000ff) ^ rk[3]; s3 = (Te2[(t3 >> 24)] & 0xff000000) ^ (Te3[(t0 >> 16) & 0xff] & 0x00ff0000) ^
(Te0[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te1[(t2)&0xff] & 0x000000ff) ^ rk[3];
Bit::htobl(out + 12, s3); Bit::htobl(out + 12, s3);
} }
@ -459,32 +642,30 @@ void AES_decrypt(const char * in, char * out, const char * key, unsigned int bit
} }
} }
rk += 40; rk += 40;
if (bits > 128) { if (bits > 128){rk += 8;}
rk += 8; if (bits > 192){rk += 8;}
} s0 = ((unsigned long)Td4[(t0 >> 24)] << 24) ^ ((unsigned long)Td4[(t3 >> 16) & 0xff] << 16) ^
if (bits > 192) { ((unsigned long)Td4[(t2 >> 8) & 0xff] << 8) ^ ((unsigned long)Td4[(t1)&0xff]) ^ rk[0];
rk += 8;
}
s0 = ((unsigned long)Td4[(t0 >> 24)] << 24) ^ ((unsigned long)Td4[(t3 >> 16) & 0xff] << 16) ^ ((unsigned long)Td4[(t2 >> 8) & 0xff] << 8) ^ ((unsigned long)Td4[(t1) & 0xff]) ^ rk[0];
Bit::htobl(out, s0); Bit::htobl(out, s0);
s1 = ((unsigned long)Td4[(t1 >> 24)] << 24) ^ ((unsigned long)Td4[(t0 >> 16) & 0xff] << 16) ^ ((unsigned long)Td4[(t3 >> 8) & 0xff] << 8) ^ ((unsigned long)Td4[(t2) & 0xff]) ^ rk[1]; s1 = ((unsigned long)Td4[(t1 >> 24)] << 24) ^ ((unsigned long)Td4[(t0 >> 16) & 0xff] << 16) ^
((unsigned long)Td4[(t3 >> 8) & 0xff] << 8) ^ ((unsigned long)Td4[(t2)&0xff]) ^ rk[1];
Bit::htobl(out + 4, s1); Bit::htobl(out + 4, s1);
s2 = ((unsigned long)Td4[(t2 >> 24)] << 24) ^ ((unsigned long)Td4[(t1 >> 16) & 0xff] << 16) ^ ((unsigned long)Td4[(t0 >> 8) & 0xff] << 8) ^ ((unsigned long)Td4[(t3) & 0xff]) ^ rk[2]; s2 = ((unsigned long)Td4[(t2 >> 24)] << 24) ^ ((unsigned long)Td4[(t1 >> 16) & 0xff] << 16) ^
((unsigned long)Td4[(t0 >> 8) & 0xff] << 8) ^ ((unsigned long)Td4[(t3)&0xff]) ^ rk[2];
Bit::htobl(out + 8, s2); Bit::htobl(out + 8, s2);
s3 = ((unsigned long)Td4[(t3 >> 24)] << 24) ^ ((unsigned long)Td4[(t2 >> 16) & 0xff] << 16) ^ ((unsigned long)Td4[(t1 >> 8) & 0xff] << 8) ^ ((unsigned long)Td4[(t0) & 0xff]) ^ rk[3]; s3 = ((unsigned long)Td4[(t3 >> 24)] << 24) ^ ((unsigned long)Td4[(t2 >> 16) & 0xff] << 16) ^
((unsigned long)Td4[(t1 >> 8) & 0xff] << 8) ^ ((unsigned long)Td4[(t0)&0xff]) ^ rk[3];
Bit::htobl(out + 12, s3); Bit::htobl(out + 12, s3);
} }
static void increaseCounter(char *counter){ static void increaseCounter(char *counter){
for (int i = 15; i >= 0; i--){ for (int i = 15; i >= 0; i--){
if (++counter[i]) { if (++counter[i]){return;}
return;
}
} }
} }
void AES_CTR128_crypt(const char * in, char * out, unsigned int len, const char * key, char ivec[16], char ecount_buf[16], unsigned int & num) { void AES_CTR128_crypt(const char *in, char *out, unsigned int len, const char *key, char ivec[16],
char ecount_buf[16], unsigned int &num){
unsigned int l = 0; unsigned int l = 0;
while (l < len){ while (l < len){

View file

@ -5,5 +5,6 @@ void AES_set_decrypt_key(const char * userKey, const int bits, char * key);
void AES_encrypt(const char *in, char *out, const int bits, const char *key); void AES_encrypt(const char *in, char *out, const int bits, const char *key);
void AES_decrypt(const char *in, char *out, const char *key, unsigned int bits); void AES_decrypt(const char *in, char *out, const char *key, unsigned int bits);
static void increaseCounter(char *counter); static void increaseCounter(char *counter);
void AES_CTR128_crypt(const char * in, char * out, unsigned int len, const char * key, char ivec[16], char ecount_buf[16], unsigned int & num); void AES_CTR128_crypt(const char *in, char *out, unsigned int len, const char *key, char ivec[16],
char ecount_buf[16], unsigned int &num);
void printInverted(const unsigned int *data, unsigned int len); void printInverted(const unsigned int *data, unsigned int len);

View file

@ -1,10 +1,10 @@
/// \file rtmpchunks.cpp /// \file rtmpchunks.cpp
/// Holds all code for the RTMPStream namespace. /// Holds all code for the RTMPStream namespace.
#include "rtmpchunks.h"
#include "auth.h" #include "auth.h"
#include "defines.h" #include "defines.h"
#include "flv_tag.h" #include "flv_tag.h"
#include "rtmpchunks.h"
#include "timing.h" #include "timing.h"
std::string RTMPStream::handshake_in; ///< Input for the handshake. std::string RTMPStream::handshake_in; ///< Input for the handshake.
@ -41,8 +41,7 @@ char genuineFMSKey[] ={
0x00, 0xd0, 0xd1, 0x02, 0x9e, 0x7e, 0x57, 0x6e, 0xec, 0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab, 0x00, 0xd0, 0xd1, 0x02, 0x9e, 0x7e, 0x57, 0x6e, 0xec, 0x5d, 0x2d, 0x29, 0x80, 0x6f, 0xab,
0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae}; // 68 0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae}; // 68
char genuineFPKey[] ={ char genuineFPKey[] ={0x47, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x20, 0x41, 0x64, 0x6f, 0x62, 0x65,
0x47, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x20, 0x41, 0x64, 0x6f, 0x62, 0x65,
0x20, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x20, 0x50, 0x6c, 0x61, 0x20, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x20, 0x50, 0x6c, 0x61,
0x79, // Genuine Adobe Flash Player 001 0x79, // Genuine Adobe Flash Player 001
0x65, 0x72, 0x20, 0x30, 0x30, 0x31, 0xf0, 0xee, 0xc2, 0x4a, 0x80, 0x68, 0xbe, 0x65, 0x72, 0x20, 0x30, 0x30, 0x31, 0xf0, 0xee, 0xc2, 0x4a, 0x80, 0x68, 0xbe,
@ -61,8 +60,7 @@ bool ValidateClientScheme(uint8_t *pBuffer, uint8_t scheme){
uint32_t clientDigestOffset = GetDigestOffset(pBuffer, scheme); uint32_t clientDigestOffset = GetDigestOffset(pBuffer, scheme);
uint8_t pTempBuffer[1536 - 32]; uint8_t pTempBuffer[1536 - 32];
memcpy(pTempBuffer, pBuffer, clientDigestOffset); memcpy(pTempBuffer, pBuffer, clientDigestOffset);
memcpy(pTempBuffer + clientDigestOffset, pBuffer + clientDigestOffset + 32, memcpy(pTempBuffer + clientDigestOffset, pBuffer + clientDigestOffset + 32, 1536 - clientDigestOffset - 32);
1536 - clientDigestOffset - 32);
char pTempHash[32]; char pTempHash[32];
Secure::hmac_sha256bin((char *)pTempBuffer, 1536 - 32, genuineFPKey, 30, pTempHash); Secure::hmac_sha256bin((char *)pTempBuffer, 1536 - 32, genuineFPKey, 30, pTempHash);
bool result = (memcmp(pBuffer + clientDigestOffset, pTempHash, 32) == 0); bool result = (memcmp(pBuffer + clientDigestOffset, pTempHash, 32) == 0);
@ -217,8 +215,7 @@ std::string &RTMPStream::SendChunk(unsigned int cs_id, unsigned char msg_type_id
/// \param data Contents of the media data. /// \param data Contents of the media data.
/// \param len Length of the media data, in bytes. /// \param len Length of the media data, in bytes.
/// \param ts Timestamp of the media data, relative to current system time. /// \param ts Timestamp of the media data, relative to current system time.
std::string &RTMPStream::SendMedia(unsigned char msg_type_id, unsigned char *data, int len, std::string &RTMPStream::SendMedia(unsigned char msg_type_id, unsigned char *data, int len, unsigned int ts){
unsigned int ts){
static RTMPStream::Chunk ch; static RTMPStream::Chunk ch;
ch.cs_id = msg_type_id + 42; ch.cs_id = msg_type_id + 42;
ch.timestamp = ts; ch.timestamp = ts;
@ -353,8 +350,7 @@ bool RTMPStream::Chunk::Parse(Socket::Buffer &buffer){
// process the rest of the header, for each chunk type // process the rest of the header, for each chunk type
headertype = chunktype & 0xC0; headertype = chunktype & 0xC0;
DONTEVEN_MSG("Parsing RTMP chunk header (%#.2hhX) at offset %#zx", chunktype, DONTEVEN_MSG("Parsing RTMP chunk header (%#.2hhX) at offset %#zx", chunktype, RTMPStream::rec_cnt);
RTMPStream::rec_cnt);
switch (headertype){ switch (headertype){
case 0x00: case 0x00:
@ -512,8 +508,7 @@ bool RTMPStream::doHandshake(){
// FIRST 1536 bytes for server response // FIRST 1536 bytes for server response
char pTempBuffer[1504]; char pTempBuffer[1504];
memcpy(pTempBuffer, Server, serverDigestOffset); memcpy(pTempBuffer, Server, serverDigestOffset);
memcpy(pTempBuffer + serverDigestOffset, Server + serverDigestOffset + 32, memcpy(pTempBuffer + serverDigestOffset, Server + serverDigestOffset + 32, 1504 - serverDigestOffset);
1504 - serverDigestOffset);
Secure::hmac_sha256bin(pTempBuffer, 1504, genuineFMSKey, 36, (char *)Server + serverDigestOffset); Secure::hmac_sha256bin(pTempBuffer, 1504, genuineFMSKey, 36, (char *)Server + serverDigestOffset);
// SECOND 1536 bytes for server response // SECOND 1536 bytes for server response
@ -523,12 +518,10 @@ bool RTMPStream::doHandshake(){
}else{ }else{
char pTempHash[32]; char pTempHash[32];
Secure::hmac_sha256bin((char *)Client + keyChallengeIndex, 32, genuineFMSKey, 68, pTempHash); Secure::hmac_sha256bin((char *)Client + keyChallengeIndex, 32, genuineFMSKey, 68, pTempHash);
Secure::hmac_sha256bin((char *)Server + 1536, 1536 - 32, pTempHash, 32, Secure::hmac_sha256bin((char *)Server + 1536, 1536 - 32, pTempHash, 32, (char *)Server + 1536 * 2 - 32);
(char *)Server + 1536 * 2 - 32);
} }
Server[-1] = Version; Server[-1] = Version;
RTMPStream::snd_cnt += 3073; RTMPStream::snd_cnt += 3073;
return true; return true;
} }

View file

@ -86,4 +86,3 @@ namespace RTMPStream{
/// Does the handshake. Expects handshake_in to be filled, and fills handshake_out. /// Does the handshake. Expects handshake_in to be filled, and fills handshake_out.
bool doHandshake(); bool doHandshake();
}// namespace RTMPStream }// namespace RTMPStream

View file

@ -1,10 +1,10 @@
#include "rtp.h"
#include "adts.h" #include "adts.h"
#include "bitfields.h" #include "bitfields.h"
#include "defines.h" #include "defines.h"
#include "encode.h" #include "encode.h"
#include "h264.h" #include "h264.h"
#include "mpeg.h" #include "mpeg.h"
#include "rtp.h"
#include "sdp.h" #include "sdp.h"
#include "timing.h" #include "timing.h"
#include <arpa/inet.h> #include <arpa/inet.h>
@ -15,9 +15,7 @@ namespace RTP{
unsigned int Packet::getHsize() const{ unsigned int Packet::getHsize() const{
unsigned int r = 12 + 4 * getContribCount(); unsigned int r = 12 + 4 * getContribCount();
if (getExtension()){ if (getExtension()){r += (1 + Bit::btohs(data + r + 2)) * 4;}
r += (1+Bit::btohs(data+r+2)) * 4;
}
return r; return r;
} }
@ -75,8 +73,7 @@ namespace RTP{
}else{ }else{
data[1] &= 0x7F; // setting the RTP marker bit to 0 data[1] &= 0x7F; // setting the RTP marker bit to 0
unsigned int sent = 0; unsigned int sent = 0;
unsigned int sending = unsigned int sending = maxDataLen - getHsize() - 2; // packages are of size MAX_SEND, except for the final one
maxDataLen - getHsize() - 2; // packages are of size MAX_SEND, except for the final one
char initByte = (payload[0] & 0xE0) | 0x1C; char initByte = (payload[0] & 0xE0) | 0x1C;
char serByte = payload[0] & 0x1F; // ser is now 000 char serByte = payload[0] & 0x1F; // ser is now 000
data[getHsize()] = initByte; data[getHsize()] = initByte;
@ -118,15 +115,10 @@ namespace RTP{
chunkSize = std::min<size_t>(1200, payloadlen); chunkSize = std::min<size_t>(1200, payloadlen);
payloadlen -= chunkSize; payloadlen -= chunkSize;
data[1] = data[1] = (0 != payloadlen) ? (data[1] & 0x7F) : (data[1] | 0x80); // marker bit, 1 for last chunk.
(0 != payloadlen) ? (data[1] & 0x7F) : (data[1] | 0x80); // marker bit, 1 for last chunk.
data[headerSize] = 0x00; // reset data[headerSize] = 0x00; // reset
data[headerSize] |= data[headerSize] |= (isStartOfPartition) ? 0x10 : 0x00; // first chunk is always start of a partition.
(isStartOfPartition) ? 0x10 : 0x00; // first chunk is always start of a partition. data[headerSize] |= (isKeyframe) ? 0x00 : 0x20; // non-reference frame. 0 = frame is needed, 1 = frame can be disgarded.
data[headerSize] |=
(isKeyframe)
? 0x00
: 0x20; // non-reference frame. 0 = frame is needed, 1 = frame can be disgarded.
memcpy(data + headerSize + 1, payload + bytesWritten, chunkSize); memcpy(data + headerSize + 1, payload + bytesWritten, chunkSize);
callBack(socket, data, headerSize + 1 + chunkSize, channel); callBack(socket, data, headerSize + 1 + chunkSize, channel);
@ -154,8 +146,7 @@ namespace RTP{
}else{ }else{
data[1] &= 0x7F; // setting the RTP marker bit to 0 data[1] &= 0x7F; // setting the RTP marker bit to 0
unsigned int sent = 0; unsigned int sent = 0;
unsigned int sending = unsigned int sending = maxDataLen - getHsize() - 3; // packages are of size MAX_SEND, except for the final one
maxDataLen - getHsize() - 3; // packages are of size MAX_SEND, except for the final one
char initByteA = (payload[0] & 0x81) | 0x62; char initByteA = (payload[0] & 0x81) | 0x62;
char initByteB = payload[1]; char initByteB = payload[1];
char serByte = (payload[0] & 0x7E) >> 1; // SE is now 00 char serByte = (payload[0] & 0x7E) >> 1; // SE is now 00
@ -205,8 +196,7 @@ namespace RTP{
}else{ }else{
data[1] &= 0x7F; // setting the RTP marker bit to 0 data[1] &= 0x7F; // setting the RTP marker bit to 0
unsigned int sent = 0; unsigned int sent = 0;
unsigned int sending = unsigned int sending = maxDataLen - getHsize() - 4; // packages are of size MAX_SEND, except for the final one
maxDataLen - getHsize() - 4; // packages are of size MAX_SEND, except for the final one
Mpeg::MPEG2Info mInfo; Mpeg::MPEG2Info mInfo;
MPEGVideoHeader mHead(data + getHsize()); MPEGVideoHeader mHead(data + getHsize());
while (sent < payloadlen){ while (sent < payloadlen){
@ -234,13 +224,13 @@ namespace RTP{
} }
void Packet::sendData(void *socket, void callBack(void *, char *, unsigned int, unsigned int), void Packet::sendData(void *socket, void callBack(void *, char *, unsigned int, unsigned int),
const char *payload, unsigned int payloadlen, unsigned int channel, const char *payload, unsigned int payloadlen, unsigned int channel, std::string codec){
std::string codec){
if (codec == "H264"){ if (codec == "H264"){
unsigned long sent = 0; unsigned long sent = 0;
while (sent < payloadlen){ while (sent < payloadlen){
unsigned long nalSize = ntohl(*((unsigned long *)(payload + sent))); unsigned long nalSize = ntohl(*((unsigned long *)(payload + sent)));
sendH264(socket, callBack, payload + sent + 4, nalSize, channel, (sent + nalSize + 4) >= payloadlen ? true : false); sendH264(socket, callBack, payload + sent + 4, nalSize, channel,
(sent + nalSize + 4) >= payloadlen ? true : false);
sent += nalSize + 4; sent += nalSize + 4;
} }
return; return;
@ -299,8 +289,7 @@ namespace RTP{
increaseSequence(); increaseSequence();
} }
void Packet::sendRTCP_SR(long long &connectedAt, void *socket, unsigned int tid, void Packet::sendRTCP_SR(long long &connectedAt, void *socket, unsigned int tid, DTSC::Meta &metadata,
DTSC::Meta &metadata,
void callBack(void *, char *, unsigned int, unsigned int)){ void callBack(void *, char *, unsigned int, unsigned int)){
char *rtcpData = (char *)malloc(32); char *rtcpData = (char *)malloc(32);
if (!rtcpData){ if (!rtcpData){
@ -322,8 +311,7 @@ namespace RTP{
free(rtcpData); free(rtcpData);
} }
void Packet::sendRTCP_RR(long long &connectedAt, SDP::Track &sTrk, unsigned int tid, void Packet::sendRTCP_RR(long long &connectedAt, SDP::Track &sTrk, unsigned int tid, DTSC::Meta &metadata,
DTSC::Meta &metadata,
void callBack(void *, char *, unsigned int, unsigned int)){ void callBack(void *, char *, unsigned int, unsigned int)){
char *rtcpData = (char *)malloc(32); char *rtcpData = (char *)malloc(32);
if (!rtcpData){ if (!rtcpData){
@ -336,12 +324,9 @@ namespace RTP{
Bit::htobs(rtcpData + 2, 7); // 7 4-byte words follow the header Bit::htobs(rtcpData + 2, 7); // 7 4-byte words follow the header
Bit::htobl(rtcpData + 4, sTrk.mySSRC); // set receiver identifier Bit::htobl(rtcpData + 4, sTrk.mySSRC); // set receiver identifier
Bit::htobl(rtcpData + 8, sTrk.theirSSRC); // set source identifier Bit::htobl(rtcpData + 8, sTrk.theirSSRC); // set source identifier
rtcpData[12] = rtcpData[12] = (sTrk.sorter.lostCurrent * 255) / (sTrk.sorter.lostCurrent + sTrk.sorter.packCurrent); // fraction lost since prev RR
(sTrk.sorter.lostCurrent * 255) /
(sTrk.sorter.lostCurrent + sTrk.sorter.packCurrent); // fraction lost since prev RR
Bit::htob24(rtcpData + 13, sTrk.sorter.lostTotal); // cumulative packets lost since start Bit::htob24(rtcpData + 13, sTrk.sorter.lostTotal); // cumulative packets lost since start
Bit::htobl(rtcpData + 16, sTrk.sorter.rtpSeq | (sTrk.sorter.packTotal & Bit::htobl(rtcpData + 16, sTrk.sorter.rtpSeq | (sTrk.sorter.packTotal & 0xFFFF0000ul)); // highest sequence received
0xFFFF0000ul)); // highest sequence received
Bit::htobl(rtcpData + 20, 0); /// \TODO jitter (diff in timestamp vs packet arrival) Bit::htobl(rtcpData + 20, 0); /// \TODO jitter (diff in timestamp vs packet arrival)
Bit::htobl(rtcpData + 24, 0); /// \TODO last SR (middle 32 bits of last SR or zero) Bit::htobl(rtcpData + 24, 0); /// \TODO last SR (middle 32 bits of last SR or zero)
Bit::htobl(rtcpData + 28, 0); /// \TODO delay since last SR in 2b seconds + 2b fraction Bit::htobl(rtcpData + 28, 0); /// \TODO delay since last SR in 2b seconds + 2b fraction
@ -362,8 +347,7 @@ namespace RTP{
Packet::Packet(unsigned int payloadType, unsigned int sequence, unsigned int timestamp, Packet::Packet(unsigned int payloadType, unsigned int sequence, unsigned int timestamp,
unsigned int ssrc, unsigned int csrcCount){ unsigned int ssrc, unsigned int csrcCount){
managed = true; managed = true;
data = new char[12 + 4 * csrcCount + 2 + data = new char[12 + 4 * csrcCount + 2 + MAX_SEND]; // headerSize, 2 for FU-A, MAX_SEND for maximum sent size
MAX_SEND]; // headerSize, 2 for FU-A, MAX_SEND for maximum sent size
if (data){ if (data){
maxDataLen = 12 + 4 * csrcCount + 2 + MAX_SEND; maxDataLen = 12 + 4 * csrcCount + 2 + MAX_SEND;
data[0] = ((2) << 6) | ((0 & 1) << 5) | ((0 & 1) << 4) | data[0] = ((2) << 6) | ((0 & 1) << 5) | ((0 & 1) << 4) |
@ -397,7 +381,6 @@ namespace RTP{
} }
sentBytes = o.sentBytes; sentBytes = o.sentBytes;
sentPackets = o.sentPackets; sentPackets = o.sentPackets;
} }
void Packet::operator=(const Packet &o){ void Packet::operator=(const Packet &o){
@ -613,7 +596,8 @@ namespace RTP{
int64_t pTime = pkt.getTimeStamp(); int64_t pTime = pkt.getTimeStamp();
if (!firstTime){ if (!firstTime){
firstTime = pTime + 1; firstTime = pTime + 1;
INFO_MSG("RTP timestamp rollover expected in " PRETTY_PRINT_TIME, PRETTY_ARG_TIME((0xFFFFFFFFul - firstTime) / multiplier / 1000)); INFO_MSG("RTP timestamp rollover expected in " PRETTY_PRINT_TIME,
PRETTY_ARG_TIME((0xFFFFFFFFul - firstTime) / multiplier / 1000));
}else{ }else{
if (prevTime > pTime && pTime < 0x40000000lu && prevTime > 0x80000000lu){ if (prevTime > pTime && pTime < 0x40000000lu && prevTime > 0x80000000lu){
++wrapArounds; ++wrapArounds;
@ -657,8 +641,7 @@ namespace RTP{
void toDTSC::handleAAC(uint64_t msTime, char *pl, uint32_t plSize){ void toDTSC::handleAAC(uint64_t msTime, char *pl, uint32_t plSize){
// assume AAC packets are single AU units // assume AAC packets are single AU units
/// \todo Support other input than single AU units /// \todo Support other input than single AU units
unsigned int headLen = unsigned int headLen = (Bit::btohs(pl) >> 3) + 2; // in bits, so /8, plus two for the prepended size
(Bit::btohs(pl) >> 3) + 2; // in bits, so /8, plus two for the prepended size
DTSC::Packet nextPack; DTSC::Packet nextPack;
uint16_t samples = aac::AudSpecConf::samples(init); uint16_t samples = aac::AudSpecConf::samples(init);
uint32_t sampleOffset = 0; uint32_t sampleOffset = 0;
@ -808,8 +791,7 @@ namespace RTP{
isKey ? "key" : "i", frameNo, fps, packCount, (frameNo - packCount), offset); isKey ? "key" : "i", frameNo, fps, packCount, (frameNo - packCount), offset);
}else{ }else{
// For non-steady frame rate, assume no offsets are used and the timestamp is already correct // For non-steady frame rate, assume no offsets are used and the timestamp is already correct
VERYHIGH_MSG("Packing time %llu = %sframe %llu (variable rate)", ts, isKey ? "key" : "i", VERYHIGH_MSG("Packing time %llu = %sframe %llu (variable rate)", ts, isKey ? "key" : "i", packCount);
packCount);
} }
// Fill the new DTSC packet, buffer it. // Fill the new DTSC packet, buffer it.
DTSC::Packet nextPack; DTSC::Packet nextPack;
@ -823,8 +805,7 @@ namespace RTP{
/// for that data. /// for that data.
/// Prints a WARN-level message if packet type is unsupported. /// Prints a WARN-level message if packet type is unsupported.
/// \todo Support other H264 packets types? /// \todo Support other H264 packets types?
void toDTSC::handleH264(uint64_t msTime, char *pl, uint32_t plSize, bool missed, void toDTSC::handleH264(uint64_t msTime, char *pl, uint32_t plSize, bool missed, bool hasPadding){
bool hasPadding){
if (!plSize){ if (!plSize){
WARN_MSG("Empty packet ignored!"); WARN_MSG("Empty packet ignored!");
return; return;
@ -1000,8 +981,7 @@ namespace RTP{
}else{ }else{
// For non-steady frame rate, assume no offsets are used and the timestamp is already // For non-steady frame rate, assume no offsets are used and the timestamp is already
// correct // correct
VERYHIGH_MSG("Packing time %llu = %sframe %llu (variable rate)", ts, isKey ? "key" : "i", VERYHIGH_MSG("Packing time %llu = %sframe %llu (variable rate)", ts, isKey ? "key" : "i", packCount);
packCount);
} }
// Fill the new DTSC packet, buffer it. // Fill the new DTSC packet, buffer it.
DTSC::Packet nextPack; DTSC::Packet nextPack;
@ -1031,8 +1011,7 @@ namespace RTP{
isKey ? "key" : "i", frameNo, fps, packCount, (frameNo - packCount), offset); isKey ? "key" : "i", frameNo, fps, packCount, (frameNo - packCount), offset);
}else{ }else{
// For non-steady frame rate, assume no offsets are used and the timestamp is already correct // For non-steady frame rate, assume no offsets are used and the timestamp is already correct
VERYHIGH_MSG("Packing time %llu = %sframe %llu (variable rate)", ts, isKey ? "key" : "i", VERYHIGH_MSG("Packing time %llu = %sframe %llu (variable rate)", ts, isKey ? "key" : "i", packCount);
packCount);
} }
// Fill the new DTSC packet, buffer it. // Fill the new DTSC packet, buffer it.
DTSC::Packet nextPack; DTSC::Packet nextPack;
@ -1062,8 +1041,7 @@ namespace RTP{
h264::isKeyframe(buffer + lastStart + 4, len - lastStart - 4)); h264::isKeyframe(buffer + lastStart + 4, len - lastStart - 4));
} }
void toDTSC::handleVP8(uint64_t msTime, const char *buffer, const uint32_t len, bool missed, void toDTSC::handleVP8(uint64_t msTime, const char *buffer, const uint32_t len, bool missed, bool hasPadding){
bool hasPadding){
// 1 byte is required but we assume that there some payload // 1 byte is required but we assume that there some payload
// data too :P // data too :P
@ -1139,8 +1117,7 @@ namespace RTP{
// new frame and nothing missed? Send. // new frame and nothing missed? Send.
if (start_of_frame && !missed){ if (start_of_frame && !missed){
DTSC::Packet nextPack; DTSC::Packet nextPack;
nextPack.genericFill(msTime, 0, trackId, vp8FrameBuffer, vp8FrameBuffer.size(), 0, nextPack.genericFill(msTime, 0, trackId, vp8FrameBuffer, vp8FrameBuffer.size(), 0, vp8BufferHasKeyframe);
vp8BufferHasKeyframe);
packCount++; packCount++;
outPacket(nextPack); outPacket(nextPack);
} }
@ -1170,4 +1147,3 @@ namespace RTP{
if (start_of_frame && is_keyframe){vp8BufferHasKeyframe = true;} if (start_of_frame && is_keyframe){vp8BufferHasKeyframe = true;}
} }
}// namespace RTP }// namespace RTP

View file

@ -65,17 +65,14 @@ namespace RTP{
void sendMPEG2(void *socket, void callBack(void *, char *, unsigned int, unsigned int), void sendMPEG2(void *socket, void callBack(void *, char *, unsigned int, unsigned int),
const char *payload, unsigned int payloadlen, unsigned int channel); const char *payload, unsigned int payloadlen, unsigned int channel);
void sendData(void *socket, void callBack(void *, char *, unsigned int, unsigned int), void sendData(void *socket, void callBack(void *, char *, unsigned int, unsigned int),
const char *payload, unsigned int payloadlen, unsigned int channel, const char *payload, unsigned int payloadlen, unsigned int channel, std::string codec);
std::string codec);
void sendRTCP_SR(long long &connectedAt, void *socket, unsigned int tid, DTSC::Meta &metadata, void sendRTCP_SR(long long &connectedAt, void *socket, unsigned int tid, DTSC::Meta &metadata,
void callBack(void *, char *, unsigned int, unsigned int)); void callBack(void *, char *, unsigned int, unsigned int));
void sendRTCP_RR(long long &connectedAt, SDP::Track &sTrk, unsigned int tid, void sendRTCP_RR(long long &connectedAt, SDP::Track &sTrk, unsigned int tid,
DTSC::Meta &metadata, DTSC::Meta &metadata, void callBack(void *, char *, unsigned int, unsigned int));
void callBack(void *, char *, unsigned int, unsigned int));
Packet(); Packet();
Packet(unsigned int pt, unsigned int seq, unsigned int ts, unsigned int ssr, Packet(unsigned int pt, unsigned int seq, unsigned int ts, unsigned int ssr, unsigned int csrcCount = 0);
unsigned int csrcCount = 0);
Packet(const Packet &o); Packet(const Packet &o);
void operator=(const Packet &o); void operator=(const Packet &o);
~Packet(); ~Packet();
@ -173,13 +170,10 @@ namespace RTP{
void handleH264Multi(uint64_t ts, char *buffer, const uint32_t len); void handleH264Multi(uint64_t ts, char *buffer, const uint32_t len);
std::string spsData; ///< SPS for H264 std::string spsData; ///< SPS for H264
std::string ppsData; ///< PPS for H264 std::string ppsData; ///< PPS for H264
void handleVP8(uint64_t msTime, const char *buffer, const uint32_t len, bool missed, void handleVP8(uint64_t msTime, const char *buffer, const uint32_t len, bool missed, bool hasPadding);
bool hasPadding); Util::ResizeablePointer vp8FrameBuffer; ///< Stores successive VP8 payload data. We always start with the first
Util::ResizeablePointer
vp8FrameBuffer; ///< Stores successive VP8 payload data. We always start with the first
///< partition; but we might be missing other partitions when they were ///< partition; but we might be missing other partitions when they were
///< lost. (a partition is basically what's called a slice in H264). ///< lost. (a partition is basically what's called a slice in H264).
bool vp8BufferHasKeyframe; bool vp8BufferHasKeyframe;
}; };
}// namespace RTP }// namespace RTP

View file

@ -1,6 +1,6 @@
#include "defines.h" #include "defines.h"
#include "rtp_fec.h"
#include "rtp.h" #include "rtp.h"
#include "rtp_fec.h"
namespace RTP{ namespace RTP{
/// Based on the `block PT` value, we can either find the /// Based on the `block PT` value, we can either find the
@ -49,8 +49,7 @@ namespace RTP{
/// | mask cont. (present only when L = 1) | /// | mask cont. (present only when L = 1) |
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// ///
PacketFEC::PacketFEC() { PacketFEC::PacketFEC(){}
}
PacketFEC::~PacketFEC(){ PacketFEC::~PacketFEC(){
receivedSeqNums.clear(); receivedSeqNums.clear();
@ -65,7 +64,8 @@ namespace RTP{
} }
if (nbytes < 23){ if (nbytes < 23){
FAIL_MSG("Given fecData is too small. Should be at least: 12 (RTP) + 1 (RED) + 10 (FEC) 23 bytes."); FAIL_MSG("Given fecData is too small. Should be at least: 12 (RTP) + 1 (RED) + 10 (FEC) 23 "
"bytes.");
return false; return false;
} }
@ -84,7 +84,8 @@ namespace RTP{
uint8_t *redHeader = (uint8_t *)(data + rtpPkt.getHsize()); uint8_t *redHeader = (uint8_t *)(data + rtpPkt.getHsize());
uint8_t moreBlocks = redHeader[0] & 0x80; uint8_t moreBlocks = redHeader[0] & 0x80;
if (moreBlocks == 1){ if (moreBlocks == 1){
FAIL_MSG("RED header indicates there are multiple blocks. Haven't seen this before (@todo implement, exiting now)."); FAIL_MSG("RED header indicates there are multiple blocks. Haven't seen this before (@todo "
"implement, exiting now).");
// \todo do not EXIT! // \todo do not EXIT!
return false; return false;
} }
@ -112,7 +113,8 @@ namespace RTP{
uint8_t PacketFEC::getExtensionFlag(){ uint8_t PacketFEC::getExtensionFlag(){
if (fecPacketData.size() == 0){ if (fecPacketData.size() == 0){
FAIL_MSG("Cannot get extension-flag from the FEC header; fecPacketData member is not set. Not initialized?"); FAIL_MSG("Cannot get extension-flag from the FEC header; fecPacketData member is not set. "
"Not initialized?");
return 0; return 0;
} }
@ -122,7 +124,8 @@ namespace RTP{
uint8_t PacketFEC::getLongMaskFlag(){ uint8_t PacketFEC::getLongMaskFlag(){
if (fecPacketData.size() == 0){ if (fecPacketData.size() == 0){
FAIL_MSG("Cannot get the long-mask-flag from the FEC header. fecPacketData member is not set. Not initialized?"); FAIL_MSG("Cannot get the long-mask-flag from the FEC header. fecPacketData member is not "
"set. Not initialized?");
return 0; return 0;
} }
@ -133,13 +136,12 @@ namespace RTP{
uint8_t PacketFEC::getNumBytesUsedForMask(){ uint8_t PacketFEC::getNumBytesUsedForMask(){
if (fecPacketData.size() == 0){ if (fecPacketData.size() == 0){
FAIL_MSG("Cannot get the number of bytes used by the mask. fecPacketData member is not set. Not initialized?"); FAIL_MSG("Cannot get the number of bytes used by the mask. fecPacketData member is not set. "
"Not initialized?");
return 0; return 0;
} }
if (getLongMaskFlag() == 0) { if (getLongMaskFlag() == 0){return 2;}
return 2;
}
return 6; return 6;
} }
@ -147,7 +149,8 @@ namespace RTP{
uint16_t PacketFEC::getSequenceBaseNumber(){ uint16_t PacketFEC::getSequenceBaseNumber(){
if (fecPacketData.size() == 0){ if (fecPacketData.size() == 0){
FAIL_MSG("Cannot get the sequence base number. fecPacketData member is not set. Not initialized?"); FAIL_MSG(
"Cannot get the sequence base number. fecPacketData member is not set. Not initialized?");
return 0; return 0;
} }
@ -189,7 +192,8 @@ namespace RTP{
uint16_t PacketFEC::getLevel0ProtectionLength(){ uint16_t PacketFEC::getLevel0ProtectionLength(){
if (fecPacketData.size() == 0){ if (fecPacketData.size() == 0){
FAIL_MSG("Cannot get the level 0 protection length. fecPacketData member is not set. Not initialized?"); FAIL_MSG("Cannot get the level 0 protection length. fecPacketData member is not set. Not "
"initialized?");
return 0; return 0;
} }
@ -207,7 +211,8 @@ namespace RTP{
char *fecHeader = getFECHeader(); char *fecHeader = getFECHeader();
if (!fecHeader){ if (!fecHeader){
FAIL_MSG("Cannot get the FEC header which we need to get the `length recovery` field. Not initialized?"); FAIL_MSG("Cannot get the FEC header which we need to get the `length recovery` field. Not "
"initialized?");
return 0; return 0;
} }
@ -246,9 +251,7 @@ namespace RTP{
} }
uint16_t seqNumBase = getSequenceBaseNumber(); uint16_t seqNumBase = getSequenceBaseNumber();
if (seqNumBase == 0) { if (seqNumBase == 0){WARN_MSG("Base sequence number is 0; it's possible but unlikely.");}
WARN_MSG("Base sequence number is 0; it's possible but unlikely.");
}
// Skip the `Protection Length` // Skip the `Protection Length`
maskPtr = maskPtr + 2; maskPtr = maskPtr + 2;
@ -292,24 +295,21 @@ namespace RTP{
/// The `receivedMediaPackets` is the history of media packets /// The `receivedMediaPackets` is the history of media packets
/// that you received and keep in a memory. These are used /// that you received and keep in a memory. These are used
/// when XORing when we reconstruct a packet. /// when XORing when we reconstruct a packet.
void PacketFEC::tryToRecoverMissingPacket(std::map<uint16_t, Packet>& receivedMediaPackets, Packet& reconstructedPacket) { void PacketFEC::tryToRecoverMissingPacket(std::map<uint16_t, Packet> &receivedMediaPackets,
Packet &reconstructedPacket){
// Mark all the media packets that we protect and which have // Mark all the media packets that we protect and which have
// been received as "received" in our internal list. // been received as "received" in our internal list.
std::set<uint16_t>::iterator protIt = coveredSeqNums.begin(); std::set<uint16_t>::iterator protIt = coveredSeqNums.begin();
while (protIt != coveredSeqNums.end()){ while (protIt != coveredSeqNums.end()){
if (receivedMediaPackets.count(*protIt) == 1) { if (receivedMediaPackets.count(*protIt) == 1){addReceivedSequenceNumber(*protIt);}
addReceivedSequenceNumber(*protIt);
}
protIt++; protIt++;
} }
// We have received all media packets that we could recover; // We have received all media packets that we could recover;
// so there is no need for this FEC packet. // so there is no need for this FEC packet.
// @todo Jaron shall we reuse allocs/PacketFECs? // @todo Jaron shall we reuse allocs/PacketFECs?
if (receivedSeqNums.size() == coveredSeqNums.size()) { if (receivedSeqNums.size() == coveredSeqNums.size()){return;}
return;
}
if (coveredSeqNums.size() != (receivedSeqNums.size() + 1)){ if (coveredSeqNums.size() != (receivedSeqNums.size() + 1)){
// missing more then 1 packet. we can only recover when // missing more then 1 packet. we can only recover when
@ -402,9 +402,7 @@ namespace RTP{
} }
Packet &mediaPacket = receivedMediaPackets[seqNum]; Packet &mediaPacket = receivedMediaPackets[seqNum];
char *mediaData = mediaPacket.ptr() + mediaPacket.getHsize(); char *mediaData = mediaPacket.ptr() + mediaPacket.getHsize();
for (size_t i = 0; i < recoverPayloadSize; ++i) { for (size_t i = 0; i < recoverPayloadSize; ++i){recoverData[12 + i] ^= mediaData[i];}
recoverData[12 + i] ^= mediaData[i];
}
++protIt; ++protIt;
} }
@ -414,7 +412,6 @@ namespace RTP{
// @todo check what other header fields we need to fix. // @todo check what other header fields we need to fix.
} }
void FECSorter::addPacket(const Packet &pack){ void FECSorter::addPacket(const Packet &pack){
if (tmpVideoLossPrevention & SDP_LOSS_PREVENTION_ULPFEC){ if (tmpVideoLossPrevention & SDP_LOSS_PREVENTION_ULPFEC){
packetHistory[pack.getSequence()] = pack; packetHistory[pack.getSequence()] = pack;
@ -447,12 +444,8 @@ namespace RTP{
/// |F| block PT | timestamp offset | block length | /// |F| block PT | timestamp offset | block length |
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/// ///
void FECSorter::addREDPacket(char* dat, void FECSorter::addREDPacket(char *dat, unsigned int len, uint8_t codecPayloadType,
unsigned int len, uint8_t REDPayloadType, uint8_t ULPFECPayloadType){
uint8_t codecPayloadType,
uint8_t REDPayloadType,
uint8_t ULPFECPayloadType)
{
RTP::Packet pkt(dat, len); RTP::Packet pkt(dat, len);
if (pkt.getPayloadType() != REDPayloadType){ if (pkt.getPayloadType() != REDPayloadType){
@ -510,7 +503,8 @@ namespace RTP{
fec->tryToRecoverMissingPacket(packetHistory, recreatedPacket); fec->tryToRecoverMissingPacket(packetHistory, recreatedPacket);
if (recreatedPacket.ptr() != NULL){ if (recreatedPacket.ptr() != NULL){
char *pl = recreatedPacket.getPayload(); char *pl = recreatedPacket.getPayload();
WARN_MSG(" => reconstructed %u, %02X %02X %02X %02X | %02X %02X %02X %02X", recreatedPacket.getSequence(), pl[0], pl[1], pl[2], pl[3], pl[4], pl[5], pl[6], pl[7]); WARN_MSG(" => reconstructed %u, %02X %02X %02X %02X | %02X %02X %02X %02X",
recreatedPacket.getSequence(), pl[0], pl[1], pl[2], pl[3], pl[4], pl[5], pl[6], pl[7]);
addPacket(recreatedPacket); addPacket(recreatedPacket);
} }
return; return;
@ -531,14 +525,13 @@ namespace RTP{
size_t nfecs = fecPackets.size(); size_t nfecs = fecPackets.size();
for (size_t i = 0; i < nfecs; ++i){ for (size_t i = 0; i < nfecs; ++i){
PacketFEC *fec = fecPackets[i]; PacketFEC *fec = fecPackets[i];
if (fec->coversSequenceNumber(sn)) { if (fec->coversSequenceNumber(sn)){return fec;}
return fec;
}
} }
return NULL; return NULL;
} }
void FECPacket::sendRTCP_RR(RTP::FECSorter &sorter, uint32_t mySSRC, uint32_t theirSSRC, void* userData, void callBack(void* userData, const char* payload, uint32_t nbytes)) { void FECPacket::sendRTCP_RR(RTP::FECSorter &sorter, uint32_t mySSRC, uint32_t theirSSRC, void *userData,
void callBack(void *userData, const char *payload, uint32_t nbytes)){
char *rtcpData = (char *)malloc(32); char *rtcpData = (char *)malloc(32);
if (!rtcpData){ if (!rtcpData){
FAIL_MSG("Could not allocate 32 bytes. Something is seriously messed up."); FAIL_MSG("Could not allocate 32 bytes. Something is seriously messed up.");
@ -550,12 +543,9 @@ namespace RTP{
Bit::htobs(rtcpData + 2, 7); // 7 4-byte words follow the header Bit::htobs(rtcpData + 2, 7); // 7 4-byte words follow the header
Bit::htobl(rtcpData + 4, mySSRC); // set receiver identifier Bit::htobl(rtcpData + 4, mySSRC); // set receiver identifier
Bit::htobl(rtcpData + 8, theirSSRC); // set source identifier Bit::htobl(rtcpData + 8, theirSSRC); // set source identifier
rtcpData[12] = rtcpData[12] = (sorter.lostCurrent * 255) / (sorter.lostCurrent + sorter.packCurrent); // fraction lost since prev RR
(sorter.lostCurrent * 255) /
(sorter.lostCurrent + sorter.packCurrent); // fraction lost since prev RR
Bit::htob24(rtcpData + 13, sorter.lostTotal); // cumulative packets lost since start Bit::htob24(rtcpData + 13, sorter.lostTotal); // cumulative packets lost since start
Bit::htobl(rtcpData + 16, sorter.rtpSeq | (sorter.packTotal & Bit::htobl(rtcpData + 16, sorter.rtpSeq | (sorter.packTotal & 0xFFFF0000ul)); // highest sequence received
0xFFFF0000ul)); // highest sequence received
Bit::htobl(rtcpData + 20, 0); /// \TODO jitter (diff in timestamp vs packet arrival) Bit::htobl(rtcpData + 20, 0); /// \TODO jitter (diff in timestamp vs packet arrival)
Bit::htobl(rtcpData + 24, 0); /// \TODO last SR (middle 32 bits of last SR or zero) Bit::htobl(rtcpData + 24, 0); /// \TODO last SR (middle 32 bits of last SR or zero)
Bit::htobl(rtcpData + 28, 0); /// \TODO delay since last SR in 2b seconds + 2b fraction Bit::htobl(rtcpData + 28, 0); /// \TODO delay since last SR in 2b seconds + 2b fraction
@ -565,5 +555,4 @@ namespace RTP{
free(rtcpData); free(rtcpData);
} }
} }// namespace RTP

View file

@ -21,14 +21,12 @@ namespace RTP{
public: public:
PacketFEC(); PacketFEC();
~PacketFEC(); ~PacketFEC();
bool initWithREDPacket( bool initWithREDPacket(const char *data,
const char *data,
size_t nbytes); /// Initialize using the given data. `data` must point to the first byte of size_t nbytes); /// Initialize using the given data. `data` must point to the first byte of
/// the RTP packet which contains the RED and FEC headers and data. /// the RTP packet which contains the RED and FEC headers and data.
uint8_t getExtensionFlag(); ///< From fec header: should be 0, see uint8_t getExtensionFlag(); ///< From fec header: should be 0, see
///< https://tools.ietf.org/html/rfc5109#section-7.3. ///< https://tools.ietf.org/html/rfc5109#section-7.3.
uint8_t uint8_t getLongMaskFlag(); ///< From fec header: returns 0 when the short mask version is used (16
getLongMaskFlag(); ///< From fec header: returns 0 when the short mask version is used (16
///< bits), otherwise 1 (48 bits). The mask is used to calculate what ///< bits), otherwise 1 (48 bits). The mask is used to calculate what
///< sequence numbers are protected, starting at the base sequence number. ///< sequence numbers are protected, starting at the base sequence number.
uint16_t getSequenceBaseNumber(); ///< From fec header: get the base sequence number. The base uint16_t getSequenceBaseNumber(); ///< From fec header: get the base sequence number. The base
@ -44,13 +42,11 @@ namespace RTP{
/// and paylaod. /// and paylaod.
char *getFECHeader(); ///< Get a pointer to the first byte of the FEC header. char *getFECHeader(); ///< Get a pointer to the first byte of the FEC header.
uint16_t getLevel0ProtectionLength(); ///< Get the length of the `getLevel0Payload()`. uint16_t getLevel0ProtectionLength(); ///< Get the length of the `getLevel0Payload()`.
uint16_t uint16_t getLengthRecovery(); ///< Get the `length recovery` value (Little Endian). This value is used
getLengthRecovery(); ///< Get the `length recovery` value (Little Endian). This value is used
///< while XORing to recover the length of the missing media packet. ///< while XORing to recover the length of the missing media packet.
bool coversSequenceNumber(uint16_t sn); ///< Returns true when this `PacketFEC` instance is used bool coversSequenceNumber(uint16_t sn); ///< Returns true when this `PacketFEC` instance is used
///< to protect the given sequence number. ///< to protect the given sequence number.
void void addReceivedSequenceNumber(uint16_t sn); ///< Whenever you receive a media packet (complete) call
addReceivedSequenceNumber(uint16_t sn); ///< Whenever you receive a media packet (complete) call
///< this as we need to know if enough media packets ///< this as we need to know if enough media packets
///< exist that are needed to recover another one. ///< exist that are needed to recover another one.
void tryToRecoverMissingPacket( void tryToRecoverMissingPacket(
@ -61,17 +57,14 @@ namespace RTP{
///< will fill the packet passed by reference. ///< will fill the packet passed by reference.
private: private:
bool bool extractCoveringSequenceNumbers(); ///< Used internally to fill the `coveredSeqNums` member which
extractCoveringSequenceNumbers(); ///< Used internally to fill the `coveredSeqNums` member which
///< tell us what media packets this FEC packet rotects. ///< tell us what media packets this FEC packet rotects.
public: public:
Util::ResizeablePointer fecPacketData; Util::ResizeablePointer fecPacketData;
Util::ResizeablePointer recoverData; Util::ResizeablePointer recoverData;
std::set<uint16_t> std::set<uint16_t> coveredSeqNums; ///< The sequence numbers of the packets that this FEC protects.
coveredSeqNums; ///< The sequence numbers of the packets that this FEC protects. std::set<uint16_t> receivedSeqNums; ///< We keep track of sequence numbers that were received (at some higher
std::set<uint16_t>
receivedSeqNums; ///< We keep track of sequence numbers that were received (at some higher
///< level). We can only recover 1 media packet and this is used to check ///< level). We can only recover 1 media packet and this is used to check
///< if this `PacketFEC` instance is capable of recovering anything. ///< if this `PacketFEC` instance is capable of recovering anything.
}; };
@ -97,4 +90,3 @@ namespace RTP{
}; };
}// namespace RTP }// namespace RTP

View file

@ -1,12 +1,12 @@
#include "sdp.h"
#include "adts.h" #include "adts.h"
#include "defines.h" #include "defines.h"
#include "encode.h" #include "encode.h"
#include "h264.h" #include "h264.h"
#include "h265.h" #include "h265.h"
#include "http_parser.h" #include "http_parser.h"
#include "util.h" #include "sdp.h"
#include "url.h" #include "url.h"
#include "util.h"
namespace SDP{ namespace SDP{
@ -15,7 +15,6 @@ namespace SDP{
snglState->updateInit(track, initData); snglState->updateInit(track, initData);
} }
Track::Track(){ Track::Track(){
rtcpSent = 0; rtcpSent = 0;
channel = -1; channel = -1;
@ -67,15 +66,13 @@ namespace SDP{
size_t count = avccbox.getSPSCount(); size_t count = avccbox.getSPSCount();
for (size_t i = 0; i < count; ++i){ for (size_t i = 0; i < count; ++i){
mediaDesc << (i ? "," : "") mediaDesc << (i ? "," : "")
<< Encodings::Base64::encode( << Encodings::Base64::encode(std::string(avccbox.getSPS(i), avccbox.getSPSLen(i)));
std::string(avccbox.getSPS(i), avccbox.getSPSLen(i)));
} }
mediaDesc << ","; mediaDesc << ",";
count = avccbox.getPPSCount(); count = avccbox.getPPSCount();
for (size_t i = 0; i < count; ++i){ for (size_t i = 0; i < count; ++i){
mediaDesc << (i ? "," : "") mediaDesc << (i ? "," : "")
<< Encodings::Base64::encode( << Encodings::Base64::encode(std::string(avccbox.getPPS(i), avccbox.getPPSLen(i)));
std::string(avccbox.getPPS(i), avccbox.getPPSLen(i)));
} }
mediaDesc << "\r\n" mediaDesc << "\r\n"
<< "a=framerate:" << ((double)trk.fpks) / 1000.0 << "a=framerate:" << ((double)trk.fpks) / 1000.0
@ -188,8 +185,7 @@ namespace SDP{
}else{ }else{
mediaDesc << "m=audio 0 RTP/AVP 103" mediaDesc << "m=audio 0 RTP/AVP 103"
<< "\r\n"; << "\r\n";
mediaDesc << "a=rtpmap:103 L" << trk.size << "/" << trk.rate << "/" << trk.channels mediaDesc << "a=rtpmap:103 L" << trk.size << "/" << trk.rate << "/" << trk.channels << "\r\n";
<< "\r\n";
} }
mediaDesc << "a=control:track" << trk.trackID << "\r\n"; mediaDesc << "a=control:track" << trk.trackID << "\r\n";
}else if (trk.codec == "opus"){ }else if (trk.codec == "opus"){
@ -212,8 +208,7 @@ namespace SDP{
// We simply request interleaved delivery over a trackNo-based identifier. // We simply request interleaved delivery over a trackNo-based identifier.
// No need to set any internal state, parseTransport will handle it all. // No need to set any internal state, parseTransport will handle it all.
std::stringstream tStr; std::stringstream tStr;
tStr << "RTP/AVP/TCP;unicast;interleaved=" << ((trackNo - 1) * 2) << "-" tStr << "RTP/AVP/TCP;unicast;interleaved=" << ((trackNo - 1) * 2) << "-" << ((trackNo - 1) * 2 + 1);
<< ((trackNo - 1) * 2 + 1);
return tStr.str(); return tStr.str();
}else{ }else{
// A little more tricky: we need to find free ports and remember them. // A little more tricky: we need to find free ports and remember them.
@ -277,8 +272,7 @@ namespace SDP{
return false; return false;
} }
if (transport.find("TCP") != std::string::npos){ if (transport.find("TCP") != std::string::npos){
std::string chanE = std::string chanE = transport.substr(transport.find("interleaved=") + 12,
transport.substr(transport.find("interleaved=") + 12,
(transport.size() - transport.rfind('-') - 1)); // extract channel ID (transport.size() - transport.rfind('-') - 1)); // extract channel ID
channel = atol(chanE.c_str()); channel = atol(chanE.c_str());
rtcpSent = 0; rtcpSent = 0;
@ -289,8 +283,7 @@ namespace SDP{
cPortA = cPortB = 0; cPortA = cPortB = 0;
size_t sPort_loc = transport.rfind("server_port=") + 12; size_t sPort_loc = transport.rfind("server_port=") + 12;
if (sPort_loc != std::string::npos){ if (sPort_loc != std::string::npos){
sPortA = sPortA = atol(transport.substr(sPort_loc, transport.find('-', sPort_loc) - sPort_loc).c_str());
atol(transport.substr(sPort_loc, transport.find('-', sPort_loc) - sPort_loc).c_str());
sPortB = atol(transport.substr(transport.find('-', sPort_loc) + 1).c_str()); sPortB = atol(transport.substr(transport.find('-', sPort_loc) + 1).c_str());
} }
size_t port_loc = transport.rfind("client_port=") + 12; size_t port_loc = transport.rfind("client_port=") + 12;
@ -311,8 +304,7 @@ namespace SDP{
std::stringstream tStr; std::stringstream tStr;
tStr << "RTP/AVP/UDP;unicast;client_port=" << cPortA << '-' << cPortB << ";"; tStr << "RTP/AVP/UDP;unicast;client_port=" << cPortA << '-' << cPortB << ";";
if (source.size()){tStr << "source=" << source << ";";} if (source.size()){tStr << "source=" << source << ";";}
tStr << "server_port=" << portA << "-" << portB << ";ssrc=" << std::hex << mySSRC tStr << "server_port=" << portA << "-" << portB << ";ssrc=" << std::hex << mySSRC << std::dec;
<< std::dec;
transportString = tStr.str(); transportString = tStr.str();
}else{ }else{
// Client mode - check ports and/or obey given ports if possible // Client mode - check ports and/or obey given ports if possible
@ -342,11 +334,9 @@ namespace SDP{
} }
/// Gets the rtpInfo for a given DTSC::Track, source identifier and timestamp (in millis). /// Gets the rtpInfo for a given DTSC::Track, source identifier and timestamp (in millis).
std::string Track::rtpInfo(const DTSC::Track &trk, const std::string &source, std::string Track::rtpInfo(const DTSC::Track &trk, const std::string &source, uint64_t currentTime){
uint64_t currentTime){
std::stringstream rInfo; std::stringstream rInfo;
rInfo << "url=" << source << "/track" << trk.trackID rInfo << "url=" << source << "/track" << trk.trackID << ";"; // get the current url, not localhost
<< ";"; // get the current url, not localhost
rInfo << "sequence=" << pack.getSequence() << ";rtptime=" << currentTime * getMultiplier(trk); rInfo << "sequence=" << pack.getSequence() << ";rtptime=" << currentTime * getMultiplier(trk);
return rInfo.str(); return rInfo.str();
} }
@ -541,8 +531,7 @@ namespace SDP{
// a=fmtp:97 // a=fmtp:97
// profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3; // profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;
// config=120856E500 // config=120856E500
FAIL_MSG("AAC transport mode not supported: %s", FAIL_MSG("AAC transport mode not supported: %s", tracks[trackNo].getParamString("mode").c_str());
tracks[trackNo].getParamString("mode").c_str());
nope = true; nope = true;
myMeta->tracks.erase(trackNo); myMeta->tracks.erase(trackNo);
tracks.erase(trackNo); tracks.erase(trackNo);
@ -562,12 +551,9 @@ namespace SDP{
updateH264Init(trackNo); updateH264Init(trackNo);
} }
if (thisTrack->codec == "HEVC"){ if (thisTrack->codec == "HEVC"){
tracks[trackNo].hevcInfo.addUnit( tracks[trackNo].hevcInfo.addUnit(Encodings::Base64::decode(tracks[trackNo].getParamString("sprop-vps")));
Encodings::Base64::decode(tracks[trackNo].getParamString("sprop-vps"))); tracks[trackNo].hevcInfo.addUnit(Encodings::Base64::decode(tracks[trackNo].getParamString("sprop-sps")));
tracks[trackNo].hevcInfo.addUnit( tracks[trackNo].hevcInfo.addUnit(Encodings::Base64::decode(tracks[trackNo].getParamString("sprop-pps")));
Encodings::Base64::decode(tracks[trackNo].getParamString("sprop-sps")));
tracks[trackNo].hevcInfo.addUnit(
Encodings::Base64::decode(tracks[trackNo].getParamString("sprop-pps")));
updateH265Init(trackNo); updateH265Init(trackNo);
} }
continue; continue;
@ -639,8 +625,7 @@ namespace SDP{
if (H.url == "200"){ if (H.url == "200"){
++trackCounter; ++trackCounter;
if (!tracks.count(trackCounter)){return 0;} if (!tracks.count(trackCounter)){return 0;}
if (!tracks[trackCounter].parseTransport(H.GetHeader("Transport"), cH, src, if (!tracks[trackCounter].parseTransport(H.GetHeader("Transport"), cH, src, myMeta->tracks[trackCounter])){
myMeta->tracks[trackCounter])){
return 0; return 0;
} }
return trackCounter; return trackCounter;
@ -660,13 +645,11 @@ namespace SDP{
} }
if ((urlString.size() >= it->second.control.size() && if ((urlString.size() >= it->second.control.size() &&
urlString.substr(urlString.size() - it->second.control.size()) == urlString.substr(urlString.size() - it->second.control.size()) == it->second.control) ||
it->second.control) ||
(pw.size() >= it->second.control.size() && (pw.size() >= it->second.control.size() &&
pw.substr(pw.size() - it->second.control.size()) == it->second.control)){ pw.substr(pw.size() - it->second.control.size()) == it->second.control)){
INFO_MSG("Parsing SETUP against track %lu", it->first); INFO_MSG("Parsing SETUP against track %lu", it->first);
if (!it->second.parseTransport(H.GetHeader("Transport"), cH, src, if (!it->second.parseTransport(H.GetHeader("Transport"), cH, src, myMeta->tracks[it->first])){
myMeta->tracks[it->first])){
return 0; return 0;
} }
return it->first; return it->first;
@ -677,8 +660,7 @@ namespace SDP{
uint32_t trackNo = atoi(H.url.c_str() + H.url.find("/track") + 6); uint32_t trackNo = atoi(H.url.c_str() + H.url.find("/track") + 6);
if (trackNo){ if (trackNo){
INFO_MSG("Parsing SETUP against track %lu", trackNo); INFO_MSG("Parsing SETUP against track %lu", trackNo);
if (!tracks[trackNo].parseTransport(H.GetHeader("Transport"), cH, src, if (!tracks[trackNo].parseTransport(H.GetHeader("Transport"), cH, src, myMeta->tracks[trackNo])){
myMeta->tracks[trackNo])){
return 0; return 0;
} }
return trackNo; return trackNo;
@ -701,9 +683,7 @@ namespace SDP{
} }
void State::updateInit(const uint64_t trackNo, const std::string &initData){ void State::updateInit(const uint64_t trackNo, const std::string &initData){
if (myMeta->tracks.count(trackNo)){ if (myMeta->tracks.count(trackNo)){myMeta->tracks[trackNo].init = initData;}
myMeta->tracks[trackNo].init = initData;
}
} }
/// Handles RTP packets generically, for both TCP and UDP-based connections. /// Handles RTP packets generically, for both TCP and UDP-based connections.
@ -714,4 +694,3 @@ namespace SDP{
} }
}// namespace SDP }// namespace SDP

View file

@ -13,8 +13,7 @@ namespace SDP{
class Track{ class Track{
public: public:
Track(); Track();
std::string generateTransport(uint32_t trackNo, const std::string &dest = "", std::string generateTransport(uint32_t trackNo, const std::string &dest = "", bool TCPmode = true);
bool TCPmode = true);
std::string getParamString(const std::string &param) const; std::string getParamString(const std::string &param) const;
uint64_t getParamInt(const std::string &param) const; uint64_t getParamInt(const std::string &param) const;
bool parseTransport(const std::string &transport, const std::string &host, bool parseTransport(const std::string &transport, const std::string &host,
@ -54,6 +53,7 @@ namespace SDP{
uint32_t getTrackNoForChannel(uint8_t chan); uint32_t getTrackNoForChannel(uint8_t chan);
uint32_t parseSetup(HTTP::Parser &H, const std::string &host, const std::string &source); uint32_t parseSetup(HTTP::Parser &H, const std::string &host, const std::string &source);
void handleIncomingRTP(const uint64_t track, const RTP::Packet &pkt); void handleIncomingRTP(const uint64_t track, const RTP::Packet &pkt);
public: public:
DTSC::Meta *myMeta; DTSC::Meta *myMeta;
std::map<uint32_t, RTP::toDTSC> tConv; ///< Converters to DTSC std::map<uint32_t, RTP::toDTSC> tConv; ///< Converters to DTSC
@ -62,4 +62,3 @@ namespace SDP{
std::string mediaDescription(const DTSC::Track &trk); std::string mediaDescription(const DTSC::Track &trk);
}// namespace SDP }// namespace SDP

View file

@ -75,24 +75,20 @@ namespace SDP{
return ""; return "";
} }
static std::vector<std::string> sdp_split( static std::vector<std::string>
const std::string &str, const std::string &delim, sdp_split(const std::string &str, const std::string &delim,
bool keepEmpty); // Split a string on the given delimeter and return a vector with the parts. bool keepEmpty); // Split a string on the given delimeter and return a vector with the parts.
static bool static bool sdp_extract_payload_type(const std::string &str,
sdp_extract_payload_type(const std::string &str,
uint64_t &result); // Extract the payload number from a SDP line that uint64_t &result); // Extract the payload number from a SDP line that
// starts like: `a=something:[payloadtype]`. // starts like: `a=something:[payloadtype]`.
static bool sdp_get_name_value_from_varval( static bool sdp_get_name_value_from_varval(const std::string &str, std::string &var,
const std::string &str, std::string &var,
std::string &value); // Extracts the `name` and `value` from a string like `<name>=<value>`. std::string &value); // Extracts the `name` and `value` from a string like `<name>=<value>`.
// The `name` will always be converted to lowercase!. // The `name` will always be converted to lowercase!.
static void sdp_get_all_name_values_from_string( static void
const std::string &str, std::map<std::string, std::string> sdp_get_all_name_values_from_string(const std::string &str, std::map<std::string, std::string> &result); // Extracts all the name/value pairs from a string like:
&result); // Extracts all the name/value pairs from a string like:
// `<name>=<value>;<name>=<value>`. The `name` part will // `<name>=<value>;<name>=<value>`. The `name` part will
// always be converted to lowercase. // always be converted to lowercase.
static bool static bool sdp_get_attribute_value(const std::string &str,
sdp_get_attribute_value(const std::string &str,
std::string &result); // Extract an "attribute" value, which is formatted std::string &result); // Extract an "attribute" value, which is formatted
// like: `a=something:<attribute-value>` // like: `a=something:<attribute-value>`
static std::string string_to_upper(const std::string &str); static std::string string_to_upper(const std::string &str);
@ -352,8 +348,7 @@ namespace SDP{
bool Media::parseFrameRateLine(const std::string &line){ bool Media::parseFrameRateLine(const std::string &line){
if (line.substr(0, 12) != "a=framerate:"){ if (line.substr(0, 12) != "a=framerate:"){
ERROR_MSG("Cannot parse the `a=framerate:` line because it's incorrectly formatted: `%s`.", ERROR_MSG("Cannot parse the `a=framerate:` line because it's incorrectly formatted: `%s`.", line.c_str());
line.c_str());
return false; return false;
} }
@ -533,14 +528,10 @@ namespace SDP{
MediaFormat *Media::getRetransMissionFormatForPayloadType(uint64_t pt){ MediaFormat *Media::getRetransMissionFormatForPayloadType(uint64_t pt){
std::vector<SDP::MediaFormat *> rtxFormats = getFormatsForEncodingName("RTX"); std::vector<SDP::MediaFormat *> rtxFormats = getFormatsForEncodingName("RTX");
if (rtxFormats.size() == 0) { if (rtxFormats.size() == 0){return NULL;}
return NULL;
}
for (size_t i = 0; i < rtxFormats.size(); ++i){ for (size_t i = 0; i < rtxFormats.size(); ++i){
if (rtxFormats[i]->associatedPayloadType == pt) { if (rtxFormats[i]->associatedPayloadType == pt){return rtxFormats[i];}
return rtxFormats[i];
}
} }
return NULL; return NULL;
@ -567,8 +558,7 @@ namespace SDP{
/// ///
/// @param mediaType `video` or `audio` /// @param mediaType `video` or `audio`
/// @param encodingName Encoding name in fullcaps, e.g. `H264`, `OPUS`, etc. /// @param encodingName Encoding name in fullcaps, e.g. `H264`, `OPUS`, etc.
MediaFormat *Session::getMediaFormatByEncodingName(const std::string &mediaType, MediaFormat *Session::getMediaFormatByEncodingName(const std::string &mediaType, const std::string &encodingName){
const std::string &encodingName){
SDP::Media *media = getMediaForType(mediaType); SDP::Media *media = getMediaForType(mediaType);
if (!media){ if (!media){
WARN_MSG("No SDP::Media found for media type %s.", mediaType.c_str()); WARN_MSG("No SDP::Media found for media type %s.", mediaType.c_str());
@ -666,8 +656,7 @@ namespace SDP{
return true; return true;
} }
static std::vector<std::string> sdp_split(const std::string &str, const std::string &delim, static std::vector<std::string> sdp_split(const std::string &str, const std::string &delim, bool keepEmpty){
bool keepEmpty){
std::vector<std::string> strings; std::vector<std::string> strings;
std::ostringstream word; std::ostringstream word;
for (size_t n = 0; n < str.size(); ++n){ for (size_t n = 0; n < str.size(); ++n){
@ -686,8 +675,7 @@ namespace SDP{
// extract payload type. // extract payload type.
size_t start_pos = str.find_first_of(':'); size_t start_pos = str.find_first_of(':');
size_t end_pos = str.find_first_of(' ', start_pos); size_t end_pos = str.find_first_of(' ', start_pos);
if (start_pos == std::string::npos || end_pos == std::string::npos || if (start_pos == std::string::npos || end_pos == std::string::npos || (start_pos + 1) >= end_pos){
(start_pos + 1) >= end_pos){
FAIL_MSG("Invalid `a=rtpmap` line. Has not payload type."); FAIL_MSG("Invalid `a=rtpmap` line. Has not payload type.");
return false; return false;
} }
@ -704,8 +692,7 @@ namespace SDP{
// when parsing the `a=fmtp:<fmt>` line. // when parsing the `a=fmtp:<fmt>` line.
// //
// Note that we will always convert the `var` to lowercase. // Note that we will always convert the `var` to lowercase.
static bool sdp_get_name_value_from_varval(const std::string &str, std::string &var, static bool sdp_get_name_value_from_varval(const std::string &str, std::string &var, std::string &value){
std::string &value){
if (str.empty()){ if (str.empty()){
ERROR_MSG("Cannot get `name` and `value` from string because the given string is empty. " ERROR_MSG("Cannot get `name` and `value` from string because the given string is empty. "
@ -764,8 +751,7 @@ namespace SDP{
size_t start = str.find(":"); size_t start = str.find(":");
if (start == std::string::npos){ if (start == std::string::npos){
ERROR_MSG("Cannot get attribute value because we did not find the : character in %s.", ERROR_MSG("Cannot get attribute value because we did not find the : character in %s.", str.c_str());
str.c_str());
return false; return false;
} }
@ -773,12 +759,9 @@ namespace SDP{
return true; return true;
} }
Answer::Answer() : Answer::Answer()
isVideoEnabled(false), : isVideoEnabled(false), isAudioEnabled(false), candidatePort(0),
isAudioEnabled(false), videoLossPrevention(SDP_LOSS_PREVENTION_NONE){}
candidatePort(0),
videoLossPrevention(SDP_LOSS_PREVENTION_NONE)
{}
bool Answer::parseOffer(const std::string &sdp){ bool Answer::parseOffer(const std::string &sdp){
@ -964,10 +947,7 @@ namespace SDP{
// them payload types into a string that is used with the // them payload types into a string that is used with the
// `m=` line to indicate we have support for these. // `m=` line to indicate we have support for these.
supportedPayloadTypes.push_back((uint8_t)fmtMedia->payloadType); supportedPayloadTypes.push_back((uint8_t)fmtMedia->payloadType);
if ((videoLossPrevention & SDP_LOSS_PREVENTION_ULPFEC) if ((videoLossPrevention & SDP_LOSS_PREVENTION_ULPFEC) && fmtRED && fmtULPFEC){
&& fmtRED
&& fmtULPFEC)
{
supportedPayloadTypes.push_back(fmtRED->payloadType); supportedPayloadTypes.push_back(fmtRED->payloadType);
supportedPayloadTypes.push_back(fmtULPFEC->payloadType); supportedPayloadTypes.push_back(fmtULPFEC->payloadType);
} }
@ -976,9 +956,7 @@ namespace SDP{
size_t nels = supportedPayloadTypes.size(); size_t nels = supportedPayloadTypes.size();
for (size_t k = 0; k < nels; ++k){ for (size_t k = 0; k < nels; ++k){
ss << (int)supportedPayloadTypes[k]; ss << (int)supportedPayloadTypes[k];
if ((k + 1) < nels) { if ((k + 1) < nels){ss << " ";}
ss << " ";
}
} }
std::string payloadTypes = ss.str(); std::string payloadTypes = ss.str();
@ -1008,10 +986,7 @@ namespace SDP{
addLine("a=%s", fmtMedia->rtpmap.c_str()); addLine("a=%s", fmtMedia->rtpmap.c_str());
// BEGIN FEC/RTX: testing with just FEC or RTX // BEGIN FEC/RTX: testing with just FEC or RTX
if ((videoLossPrevention & SDP_LOSS_PREVENTION_ULPFEC) if ((videoLossPrevention & SDP_LOSS_PREVENTION_ULPFEC) && fmtRED && fmtULPFEC){
&& fmtRED
&& fmtULPFEC)
{
addLine("a=rtpmap:%u ulpfec/90000", fmtULPFEC->payloadType); addLine("a=rtpmap:%u ulpfec/90000", fmtULPFEC->payloadType);
addLine("a=rtpmap:%u red/90000", fmtRED->payloadType); addLine("a=rtpmap:%u red/90000", fmtRED->payloadType);
} }
@ -1026,7 +1001,8 @@ namespace SDP{
if (fmtMedia->encodingName == "H264"){ if (fmtMedia->encodingName == "H264"){
std::string usedProfile = fmtMedia->getFormatParameterForName("profile-level-id"); std::string usedProfile = fmtMedia->getFormatParameterForName("profile-level-id");
if (usedProfile != "42e01f"){ if (usedProfile != "42e01f"){
WARN_MSG("The selected profile-level-id was not 42e01f. We rewrite it into this because that's what we support atm."); WARN_MSG("The selected profile-level-id was not 42e01f. We rewrite it into this because "
"that's what we support atm.");
usedProfile = "42e01f"; usedProfile = "42e01f";
} }
@ -1074,8 +1050,7 @@ namespace SDP{
SDP::Media &outMedia, SDP::MediaFormat &outFormat){ SDP::Media &outMedia, SDP::MediaFormat &outFormat){
Media *media = sdpOffer.getMediaForType(type); Media *media = sdpOffer.getMediaForType(type);
if (!media){ if (!media){
INFO_MSG("Cannot enable %s codec; offer doesn't have %s media.", codecList.c_str(), INFO_MSG("Cannot enable %s codec; offer doesn't have %s media.", codecList.c_str(), type.c_str());
type.c_str());
return false; return false;
} }
@ -1103,7 +1078,8 @@ namespace SDP{
continue; continue;
} }
if (formats[j]->getProfileLevelIdForH264() != "42e01f"){ if (formats[j]->getProfileLevelIdForH264() != "42e01f"){
MEDIUM_MSG("Skipping this H264 format because it uses an unsupported profile-level-id."); MEDIUM_MSG(
"Skipping this H264 format because it uses an unsupported profile-level-id.");
format = NULL; format = NULL;
continue; continue;
} }
@ -1179,6 +1155,4 @@ namespace SDP{
return result; return result;
} }
}// namespace SDP
}

View file

@ -1,14 +1,16 @@
#pragma once #pragma once
#include <string> #include "dtsc.h"
#include <map> #include <map>
#include <set> #include <set>
#include <string>
#include <vector> #include <vector>
#include "dtsc.h"
#define SDP_PAYLOAD_TYPE_NONE 9999 /// Define that is used to indicate a payload type is not set. #define SDP_PAYLOAD_TYPE_NONE 9999 /// Define that is used to indicate a payload type is not set.
#define SDP_LOSS_PREVENTION_NONE 0 #define SDP_LOSS_PREVENTION_NONE 0
#define SDP_LOSS_PREVENTION_NACK (1 << 1) /// Use simple NACK based loss prevention. (e.g. send a NACK to pusher of video stream when a packet is lost) #define SDP_LOSS_PREVENTION_NACK \
#define SDP_LOSS_PREVENTION_ULPFEC (1 << 2) /// Use FEC (See rtp.cpp, PacketRED). When used we try to add the correct `a=rtpmap` for RED and ULPFEC to the SDP when supported by the offer. (1 << 1) /// Use simple NACK based loss prevention. (e.g. send a NACK to pusher of video stream when a packet is lost)
#define SDP_LOSS_PREVENTION_ULPFEC \
(1 << 2) /// Use FEC (See rtp.cpp, PacketRED). When used we try to add the correct `a=rtpmap` for RED and ULPFEC to the SDP when supported by the offer.
namespace SDP{ namespace SDP{
@ -30,28 +32,23 @@ namespace SDP{
class MediaFormat{ class MediaFormat{
public: public:
MediaFormat(); MediaFormat();
std::string getFormatParameterForName( std::string getFormatParameterForName(const std::string &name) const; ///< Get a parameter which was part of the `a=fmtp:` line.
const std::string &name) const; ///< Get a parameter which was part of the `a=fmtp:` line. uint32_t getAudioSampleRate() const; ///< Returns the audio sample rate. When `audioSampleRate` has been set this will be
uint32_t getAudioSampleRate()
const; ///< Returns the audio sample rate. When `audioSampleRate` has been set this will be
///< returned, otherwise we use the `payloadType` to determine the samplerate or ///< returned, otherwise we use the `payloadType` to determine the samplerate or
///< return 0 when we fail to determine to samplerate. ///< return 0 when we fail to determine to samplerate.
uint32_t getAudioNumChannels() uint32_t
const; ///< Returns the number of audio channels. When `audioNumChannels` has been set this getAudioNumChannels() const; ///< Returns the number of audio channels. When `audioNumChannels` has been set this
///< will be returned, otherwise we use the `payloadType` when it's set to determine ///< will be returned, otherwise we use the `payloadType` when it's set to determine
///< the samplerate or we return 0 when we can't determine the number of channels. ///< the samplerate or we return 0 when we can't determine the number of channels.
uint32_t getAudioBitSize() uint32_t getAudioBitSize() const; ///< Returns the audio bitsize. When `audioBitSize` has been set this will be
const; ///< Returns the audio bitsize. When `audioBitSize` has been set this will be
///< returned, othwerise we use the `encodingName` to determine the right ///< returned, othwerise we use the `encodingName` to determine the right
///< `audioBitSize` or 0 when we can't determine the `audioBitSize` ///< `audioBitSize` or 0 when we can't determine the `audioBitSize`
uint32_t uint32_t getVideoRate() const; ///< Returns the video time base. When `videoRate` has been set this will
getVideoRate() const; ///< Returns the video time base. When `videoRate` has been set this will
///< be returned, otherwise we use the `encodingName` to determine the ///< be returned, otherwise we use the `encodingName` to determine the
///< right value or 0 when we can't determine the video rate. ///< right value or 0 when we can't determine the video rate.
uint32_t getVideoOrAudioRate() const; ///< Returns whichever rate has been set. uint32_t getVideoOrAudioRate() const; ///< Returns whichever rate has been set.
uint64_t getPayloadType() const; ///< Returns the `payloadType` member. uint64_t getPayloadType() const; ///< Returns the `payloadType` member.
int32_t int32_t getPacketizationModeForH264(); ///< When this represents a h264 format this will return the
getPacketizationModeForH264(); ///< When this represents a h264 format this will return the
///< packetization mode when it was provided in the SDP ///< packetization mode when it was provided in the SDP
std::string getProfileLevelIdForH264(); ///< When this represents a H264 format, this will return the profile-level-id from the format parameters. std::string getProfileLevelIdForH264(); ///< When this represents a H264 format, this will return the profile-level-id from the format parameters.
@ -72,12 +69,10 @@ namespace SDP{
std::string iceUFrag; ///< From `a=ice-ufrag:<ufrag>, used with WebRTC / STUN. std::string iceUFrag; ///< From `a=ice-ufrag:<ufrag>, used with WebRTC / STUN.
std::string icePwd; ///< From `a=ice-pwd:<pwd>`, used with WebRTC / STUN std::string icePwd; ///< From `a=ice-pwd:<pwd>`, used with WebRTC / STUN
std::string rtpmap; ///< The `a=<rtpmap:...> value; value between brackets. std::string rtpmap; ///< The `a=<rtpmap:...> value; value between brackets.
std::map<std::string, std::string> std::map<std::string, std::string> formatParameters; ///< Stores the var-val pairs from `a=fmtp:<fmt>` entry e.g. =
formatParameters; ///< Stores the var-val pairs from `a=fmtp:<fmt>` entry e.g. =
///< `packetization-mode=1;profile-level-id=4d0029;sprop-parameter-sets=Z00AKeKQCADDYC3AQEBpB4kRUA==,aO48gA==` ///< `packetization-mode=1;profile-level-id=4d0029;sprop-parameter-sets=Z00AKeKQCADDYC3AQEBpB4kRUA==,aO48gA==`
///< */ ///< */
std::set<std::string> std::set<std::string> rtcpFormats; ///< Stores the `fb-val` from the line with `a=rtcp-fb:<fmt> <fb-val>`.
rtcpFormats; ///< Stores the `fb-val` from the line with `a=rtcp-fb:<fmt> <fb-val>`.
}; };
class Media{ class Media{
@ -85,40 +80,32 @@ namespace SDP{
Media(); Media();
bool parseMediaLine(const std::string &sdpLine); ///< Parses `m=` line. Creates a `MediaFormat` bool parseMediaLine(const std::string &sdpLine); ///< Parses `m=` line. Creates a `MediaFormat`
///< entry for each of the found <fmt> values. ///< entry for each of the found <fmt> values.
bool parseRtpMapLine( bool parseRtpMapLine(const std::string &sdpLine); ///< Parses `a=rtpmap:` line which contains the some codec
const std::string &sdpLine); ///< Parses `a=rtpmap:` line which contains the some codec
///< specific info. When this line contains the samplerate and ///< specific info. When this line contains the samplerate and
///< number of audio channels they will be extracted. ///< number of audio channels they will be extracted.
bool parseRtspControlLine(const std::string &sdpLine); ///< Parses `a=control:` bool parseRtspControlLine(const std::string &sdpLine); ///< Parses `a=control:`
bool parseFrameRateLine(const std::string &sdpLine); ///< Parses `a=framerate:` bool parseFrameRateLine(const std::string &sdpLine); ///< Parses `a=framerate:`
bool parseFormatParametersLine(const std::string &sdpLine); ///< Parses `a=fmtp:<payload-type>`. bool parseFormatParametersLine(const std::string &sdpLine); ///< Parses `a=fmtp:<payload-type>`.
bool parseRtcpFeedbackLine( bool parseRtcpFeedbackLine(const std::string &sdpLine); ///< Parses `a=rtcp-fb:<payload-type>`. See RFC4584
const std::string &sdpLine); ///< Parses `a=rtcp-fb:<payload-type>`. See RFC4584 bool parseFingerprintLine(const std::string &sdpLine); ///< Parses `a=fingerprint:<hash-func> <value>`. See
bool parseFingerprintLine(
const std::string
&sdpLine); ///< Parses `a=fingerprint:<hash-func> <value>`. See
///< https://tools.ietf.org/html/rfc8122#section-5, used with WebRTC ///< https://tools.ietf.org/html/rfc8122#section-5, used with WebRTC
bool parseSSRCLine(const std::string &sdpLine); ///< Parses `a=ssrc:<ssrc>`. bool parseSSRCLine(const std::string &sdpLine); ///< Parses `a=ssrc:<ssrc>`.
MediaFormat *getFormatForSdpLine( MediaFormat *getFormatForSdpLine(const std::string &sdpLine); ///< Returns the track to which this SDP line applies. This means that the
const std::string
&sdpLine); ///< Returns the track to which this SDP line applies. This means that the
///< SDP line should be formatteed like: `a=something:[payloadtype]`. ///< SDP line should be formatteed like: `a=something:[payloadtype]`.
MediaFormat *getFormatForPayloadType( MediaFormat *
uint64_t &payloadType); ///< Finds the `MediaFormat` in `formats`. Returns NULL when no getFormatForPayloadType(uint64_t &payloadType); ///< Finds the `MediaFormat` in `formats`. Returns NULL when no
///< format was found for the given payload type. . ///< format was found for the given payload type. .
MediaFormat *getFormatForEncodingName( MediaFormat *getFormatForEncodingName(const std::string &encName); ///< Finds the `MediaFormats in `formats`. Returns NULL when no format was
const std::string
&encName); ///< Finds the `MediaFormats in `formats`. Returns NULL when no format was
///< found for the given encoding name. E.g. `VP8`, `VP9`, `H264` ///< found for the given encoding name. E.g. `VP8`, `VP9`, `H264`
std::vector<SDP::MediaFormat *> getFormatsForEncodingName(const std::string &encName); std::vector<SDP::MediaFormat *> getFormatsForEncodingName(const std::string &encName);
std::string getIcePwdForFormat( std::string getIcePwdForFormat(const MediaFormat &fmt); ///< The `a=ice-pwd` can be session global or media specific. This function will
const MediaFormat
&fmt); ///< The `a=ice-pwd` can be session global or media specific. This function will
///< check if the `SDP::MediaFormat` has a ice-pwd that we should use. ///< check if the `SDP::MediaFormat` has a ice-pwd that we should use.
uint32_t uint32_t getSSRC() const; ///< Returns the first SSRC `a=ssrc:<value>` value found for the media.
getSSRC() const; ///< Returns the first SSRC `a=ssrc:<value>` value found for the media.
operator bool() const; operator bool() const;
MediaFormat* getRetransMissionFormatForPayloadType(uint64_t pt); ///< When available, it resurns the RTX format that is directly associated with the media (not encapsulated with a RED header). RTX can be combined with FEC in which case it's supposed to be stored in RED packets. The `encName` should be something like H264,VP8; e.g. the format for which you want to get the RTX format. MediaFormat *getRetransMissionFormatForPayloadType(
uint64_t pt); ///< When available, it resurns the RTX format that is directly associated with
///< the media (not encapsulated with a RED header). RTX can be combined with
///< FEC in which case it's supposed to be stored in RED packets. The `encName` should be something like H264,VP8; e.g. the format for which you want to get the RTX format.
public: public:
std::string type; ///< The `media` field of the media line: `m=<media> <port> <proto> <fmt>`, std::string type; ///< The `media` field of the media line: `m=<media> <port> <proto> <fmt>`,
@ -132,8 +119,7 @@ namespace SDP{
std::string setupMethod; ///< From `a=setup:<passive, active, actpass>, used with WebRTC / STUN std::string setupMethod; ///< From `a=setup:<passive, active, actpass>, used with WebRTC / STUN
std::string fingerprintHash; ///< From `a=fingerprint:<hash> <value>`, e.g. sha-256, used with std::string fingerprintHash; ///< From `a=fingerprint:<hash> <value>`, e.g. sha-256, used with
///< WebRTC / STUN ///< WebRTC / STUN
std::string std::string fingerprintValue; ///< From `a=fingerprint:<hash> <value>`, the actual fingerprint, used
fingerprintValue; ///< From `a=fingerprint:<hash> <value>`, the actual fingerprint, used
///< with WebRTC / STUN, see https://tools.ietf.org/html/rfc8122#section-5 ///< with WebRTC / STUN, see https://tools.ietf.org/html/rfc8122#section-5
std::string mediaID; ///< From `a=mid:<value>`. When generating an WebRTC answer this value must std::string mediaID; ///< From `a=mid:<value>`. When generating an WebRTC answer this value must
///< be the same as in the offer. ///< be the same as in the offer.
@ -144,21 +130,17 @@ namespace SDP{
bool supportsRTCPMux; ///< From `a=rtcp-mux`, indicates if it can mux RTP and RTCP on one bool supportsRTCPMux; ///< From `a=rtcp-mux`, indicates if it can mux RTP and RTCP on one
///< transport channel. ///< transport channel.
bool supportsRTCPReducedSize; ///< From `a=rtcp-rsize`, reduced size RTCP packets. bool supportsRTCPReducedSize; ///< From `a=rtcp-rsize`, reduced size RTCP packets.
std::string std::string payloadTypes; ///< From `m=` line, all the payload types as string, separated by space.
payloadTypes; ///< From `m=` line, all the payload types as string, separated by space. std::map<uint64_t, MediaFormat> formats; ///< Formats indexed by payload type. Payload type is the number in the <fmt>
std::map<uint64_t, MediaFormat>
formats; ///< Formats indexed by payload type. Payload type is the number in the <fmt>
///< field(s) from the `m=` line. ///< field(s) from the `m=` line.
}; };
class Session{ class Session{
public: public:
bool parseSDP(const std::string &sdp); bool parseSDP(const std::string &sdp);
Media *getMediaForType( Media *getMediaForType(const std::string &type); ///< Get a `SDP::Media*` for the given type, e.g. `video` or
const std::string &type); ///< Get a `SDP::Media*` for the given type, e.g. `video` or
///< `audio`. Returns NULL when the type was not found. ///< `audio`. Returns NULL when the type was not found.
MediaFormat *getMediaFormatByEncodingName(const std::string &mediaType, MediaFormat *getMediaFormatByEncodingName(const std::string &mediaType, const std::string &encodingName);
const std::string &encodingName);
bool hasReceiveOnlyMedia(); ///< Returns true when one of the media sections has a `a=recvonly` bool hasReceiveOnlyMedia(); ///< Returns true when one of the media sections has a `a=recvonly`
///< attribute. This is used to determine if the other peer only ///< attribute. This is used to determine if the other peer only
///< wants to receive or also sent data. */ ///< wants to receive or also sent data. */
@ -168,8 +150,7 @@ namespace SDP{
///< stream specific infomration is stored in a `MediaFormat` ///< stream specific infomration is stored in a `MediaFormat`
std::string icePwd; ///< From `a=ice-pwd`, this property can be session-wide or media specific. std::string icePwd; ///< From `a=ice-pwd`, this property can be session-wide or media specific.
///< Used with WebRTC and STUN when calculating the message-integrity. ///< Used with WebRTC and STUN when calculating the message-integrity.
std::string std::string iceUFrag; ///< From `a=ice-ufag`, this property can be session-wide or media specific. Used
iceUFrag; ///< From `a=ice-ufag`, this property can be session-wide or media specific. Used
///< with WebRTC and STUN when calculating the message-integrity. ///< with WebRTC and STUN when calculating the message-integrity.
}; };
@ -216,5 +197,4 @@ namespace SDP{
uint8_t videoLossPrevention; ///< See the SDP_LOSS_PREVENTION_* values at the top of this header. uint8_t videoLossPrevention; ///< See the SDP_LOSS_PREVENTION_* values at the top of this header.
}; };
} }// namespace SDP

View file

@ -1,28 +1,27 @@
#include <fcntl.h> #include "auth.h"
#include <sys/stat.h> #include "bitfields.h"
#include <sys/mman.h>
#include <sys/sem.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#include <iostream>
#include "defines.h" #include "defines.h"
#include "procs.h"
#include "shared_memory.h" #include "shared_memory.h"
#include "stream.h" #include "stream.h"
#include "procs.h"
#include "bitfields.h"
#include "timing.h" #include "timing.h"
#include "auth.h" #include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fcntl.h>
#include <iostream>
#include <sys/mman.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <unistd.h>
#if defined(__CYGWIN__) || defined(_WIN32) #if defined(__CYGWIN__) || defined(_WIN32)
#include <windows.h>
#include <aclapi.h>
#include <accctrl.h> #include <accctrl.h>
#include <aclapi.h>
#include <windows.h>
#endif #endif
/// Forces a disconnect to all users. /// Forces a disconnect to all users.
static void killStatistics(char *data, size_t len, unsigned int id){ static void killStatistics(char *data, size_t len, unsigned int id){
(*(data - 1)) = 60 | ((*(data - 1)) & 0x80); // Send disconnect message; (*(data - 1)) = 60 | ((*(data - 1)) & 0x80); // Send disconnect message;
@ -32,12 +31,8 @@ namespace IPC {
#if defined(__CYGWIN__) || defined(_WIN32) #if defined(__CYGWIN__) || defined(_WIN32)
static std::map<std::string, sharedPage> preservedPages; static std::map<std::string, sharedPage> preservedPages;
void preservePage(std::string p) { void preservePage(std::string p){preservedPages[p].init(p, 0, false, false);}
preservedPages[p].init(p, 0, false, false); void releasePage(std::string p){preservedPages.erase(p);}
}
void releasePage(std::string p) {
preservedPages.erase(p);
}
#endif #endif
///\brief Empty semaphore constructor, clears all values ///\brief Empty semaphore constructor, clears all values
@ -66,10 +61,7 @@ namespace IPC {
} }
///\brief The deconstructor ///\brief The deconstructor
semaphore::~semaphore() { semaphore::~semaphore(){close();}
close();
}
///\brief Returns whether we have a valid semaphore ///\brief Returns whether we have a valid semaphore
semaphore::operator bool() const{ semaphore::operator bool() const{
@ -106,9 +98,7 @@ namespace IPC {
} }
SECURITY_ATTRIBUTES security = getSecurityAttributes(); SECURITY_ATTRIBUTES security = getSecurityAttributes();
mySem = CreateMutex(&security, true, semaName.c_str()); mySem = CreateMutex(&security, true, semaName.c_str());
if (value){ if (value){ReleaseMutex(mySem);}
ReleaseMutex(mySem);
}
}else{ }else{
mySem = OpenMutex(SYNCHRONIZE, false, semaName.c_str()); mySem = OpenMutex(SYNCHRONIZE, false, semaName.c_str());
} }
@ -142,9 +132,7 @@ namespace IPC {
} }
#endif #endif
} }
if (*this) { if (*this){myName = (char *)name;}
myName = (char *)name;
}
} }
///\brief Returns the current value of the semaphore ///\brief Returns the current value of the semaphore
@ -189,9 +177,7 @@ namespace IPC {
WaitForSingleObject(mySem, INFINITE); WaitForSingleObject(mySem, INFINITE);
#else #else
int tmp; int tmp;
do { do{tmp = sem_wait(mySem);}while (tmp == -1 && errno == EINTR);
tmp = sem_wait(mySem);
} while (tmp == -1 && errno == EINTR);
#endif #endif
lockTime = Util::getMicros(); lockTime = Util::getMicros();
++isLocked; ++isLocked;
@ -209,9 +195,7 @@ namespace IPC {
result = 0; result = 0;
} }
#else #else
do { do{result = sem_trywait(mySem);}while (result == -1 && errno == EINTR);
result = sem_trywait(mySem);
} while (result == -1 && errno == EINTR);
#endif #endif
isLocked += (result == 0 ? 1 : 0); isLocked += (result == 0 ? 1 : 0);
if (isLocked == 1){lockTime = Util::getMicros();} if (isLocked == 1){lockTime = Util::getMicros();}
@ -306,9 +290,7 @@ namespace IPC {
static SECURITY_ATTRIBUTES result; static SECURITY_ATTRIBUTES result;
static bool resultValid = false; static bool resultValid = false;
static SECURITY_DESCRIPTOR securityDescriptor; static SECURITY_DESCRIPTOR securityDescriptor;
if (resultValid) { if (resultValid){return result;}
return result;
}
InitializeSecurityDescriptor(&securityDescriptor, SECURITY_DESCRIPTOR_REVISION); InitializeSecurityDescriptor(&securityDescriptor, SECURITY_DESCRIPTOR_REVISION);
if (!SetSecurityDescriptorDacl(&securityDescriptor, TRUE, NULL, FALSE)){ if (!SetSecurityDescriptorDacl(&securityDescriptor, TRUE, NULL, FALSE)){
@ -349,9 +331,7 @@ namespace IPC {
} }
///\brief Default destructor ///\brief Default destructor
sharedPage::~sharedPage() { sharedPage::~sharedPage(){close();}
close();
}
#ifdef SHM_ENABLED #ifdef SHM_ENABLED
@ -394,18 +374,14 @@ namespace IPC {
CloseHandle(handle); CloseHandle(handle);
#else #else
::close(handle); ::close(handle);
if (master && name != "") { if (master && name != ""){shm_unlink(name.c_str());}
shm_unlink(name.c_str());
}
#endif #endif
handle = 0; handle = 0;
} }
} }
///\brief Returns whether the shared page is valid or not ///\brief Returns whether the shared page is valid or not
sharedPage::operator bool() const { sharedPage::operator bool() const{return mapped != 0;}
return mapped != 0;
}
///\brief Assignment operator ///\brief Assignment operator
void sharedPage::operator=(sharedPage &rhs){ void sharedPage::operator=(sharedPage &rhs){
@ -414,7 +390,6 @@ namespace IPC {
rhs.master = false; // Make sure the memory does not get unlinked rhs.master = false; // Make sure the memory does not get unlinked
} }
///\brief Initialize a page, de-initialize before if needed ///\brief Initialize a page, de-initialize before if needed
///\param name_ The name of the page to be created ///\param name_ The name of the page to be created
///\param len_ The size to make the page ///\param len_ The size to make the page
@ -427,7 +402,8 @@ namespace IPC {
master = master_; master = master_;
mapped = 0; mapped = 0;
if (name.size()){ if (name.size()){
INSANE_MSG("Opening page %s in %s mode %s auto-backoff", name.c_str(), master ? "master" : "client", autoBackoff ? "with" : "without"); INSANE_MSG("Opening page %s in %s mode %s auto-backoff", name.c_str(),
master ? "master" : "client", autoBackoff ? "with" : "without");
#if defined(__CYGWIN__) || defined(_WIN32) #if defined(__CYGWIN__) || defined(_WIN32)
if (master){ if (master){
// Under cygwin, all pages are 4 bytes longer than claimed. // Under cygwin, all pages are 4 bytes longer than claimed.
@ -435,15 +411,14 @@ namespace IPC {
}else{ }else{
int i = 0; int i = 0;
do{ do{
if (i != 0) { if (i != 0){Util::wait(1000);}
Util::wait(1000);
}
handle = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, name.c_str()); handle = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, name.c_str());
i++; i++;
}while (i < 10 && !handle && autoBackoff); }while (i < 10 && !handle && autoBackoff);
} }
if (!handle){ if (!handle){
MEDIUM_MSG("%s for page %s failed with error code %u", (master ? "CreateFileMapping" : "OpenFileMapping"), name.c_str(), GetLastError()); MEDIUM_MSG("%s for page %s failed with error code %u",
(master ? "CreateFileMapping" : "OpenFileMapping"), name.c_str(), GetLastError());
return; return;
} }
mapped = (char *)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0); mapped = (char *)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
@ -488,9 +463,7 @@ namespace IPC {
}else{ }else{
struct stat buffStats; struct stat buffStats;
int xRes = fstat(handle, &buffStats); int xRes = fstat(handle, &buffStats);
if (xRes < 0) { if (xRes < 0){return;}
return;
}
len = buffStats.st_size; len = buffStats.st_size;
if (!len){ if (!len){
mapped = 0; mapped = 0;
@ -514,7 +487,8 @@ namespace IPC {
///\param len_ The size to make the file ///\param len_ The size to make the file
///\param master_ Whether to create or merely open the file ///\param master_ Whether to create or merely open the file
///\param autoBackoff When only opening the file, wait for it to appear or fail ///\param autoBackoff When only opening the file, wait for it to appear or fail
sharedFile::sharedFile(const std::string & name_, uint64_t len_, bool master_, bool autoBackoff) : handle(0), name(name_), len(len_), master(master_), mapped(NULL) { sharedFile::sharedFile(const std::string &name_, uint64_t len_, bool master_, bool autoBackoff)
: handle(0), name(name_), len(len_), master(master_), mapped(NULL){
handle = 0; handle = 0;
name = name_; name = name_;
len = len_; len = len_;
@ -523,7 +497,6 @@ namespace IPC {
init(name_, len_, master_, autoBackoff); init(name_, len_, master_, autoBackoff);
} }
///\brief Creates a copy of a shared page ///\brief Creates a copy of a shared page
///\param rhs The page to copy ///\param rhs The page to copy
sharedFile::sharedFile(const sharedFile &rhs){ sharedFile::sharedFile(const sharedFile &rhs){
@ -536,9 +509,7 @@ namespace IPC {
} }
///\brief Returns whether the shared file is valid or not ///\brief Returns whether the shared file is valid or not
sharedFile::operator bool() const { sharedFile::operator bool() const{return mapped != 0;}
return mapped != 0;
}
///\brief Assignment operator ///\brief Assignment operator
void sharedFile::operator=(sharedFile &rhs){ void sharedFile::operator=(sharedFile &rhs){
@ -560,9 +531,7 @@ namespace IPC {
unmap(); unmap();
if (handle > 0){ if (handle > 0){
::close(handle); ::close(handle);
if (master && name != "") { if (master && name != ""){unlink(name.c_str());}
unlink(name.c_str());
}
handle = 0; handle = 0;
} }
} }
@ -587,11 +556,13 @@ namespace IPC {
mapped = 0; mapped = 0;
if (name.size()){ if (name.size()){
/// \todo Use ACCESSPERMS instead of 0600? /// \todo Use ACCESSPERMS instead of 0600?
handle = open(std::string(Util::getTmpFolder() + name).c_str(), (master ? O_CREAT | O_TRUNC | O_EXCL : 0) | O_RDWR, (mode_t)0600); handle = open(std::string(Util::getTmpFolder() + name).c_str(),
(master ? O_CREAT | O_TRUNC | O_EXCL : 0) | O_RDWR, (mode_t)0600);
if (handle == -1){ if (handle == -1){
if (master){ if (master){
HIGH_MSG("Overwriting old file for %s", name.c_str()); HIGH_MSG("Overwriting old file for %s", name.c_str());
handle = open(std::string(Util::getTmpFolder() + name).c_str(), O_CREAT | O_TRUNC | O_RDWR, (mode_t)0600); handle = open(std::string(Util::getTmpFolder() + name).c_str(),
O_CREAT | O_TRUNC | O_RDWR, (mode_t)0600);
}else{ }else{
int i = 0; int i = 0;
while (i < 10 && handle == -1 && autoBackoff){ while (i < 10 && handle == -1 && autoBackoff){
@ -613,9 +584,7 @@ namespace IPC {
}else{ }else{
struct stat buffStats; struct stat buffStats;
int xRes = fstat(handle, &buffStats); int xRes = fstat(handle, &buffStats);
if (xRes < 0) { if (xRes < 0){return;}
return;
}
len = buffStats.st_size; len = buffStats.st_size;
} }
mapped = (char *)mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, handle, 0); mapped = (char *)mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, handle, 0);
@ -627,18 +596,13 @@ namespace IPC {
} }
///\brief Default destructor ///\brief Default destructor
sharedFile::~sharedFile() { sharedFile::~sharedFile(){close();}
close();
}
///\brief StatExchange constructor, sets the datapointer to the given value ///\brief StatExchange constructor, sets the datapointer to the given value
statExchange::statExchange(char *_data) : data(_data){} statExchange::statExchange(char *_data) : data(_data){}
///\brief Sets timestamp of the current stats ///\brief Sets timestamp of the current stats
void statExchange::now(long long int time) { void statExchange::now(long long int time){Bit::htobll(data, time);}
Bit::htobll(data, time);
}
///\brief Gets timestamp of the current stats ///\brief Gets timestamp of the current stats
long long int statExchange::now(){ long long int statExchange::now(){
@ -647,81 +611,53 @@ namespace IPC {
} }
///\brief Sets time currently connected ///\brief Sets time currently connected
void statExchange::time(long time) { void statExchange::time(long time){Bit::htobl(data + 8, time);}
Bit::htobl(data + 8, time);
}
/// Calculates session ID from CRC, stream name, connector and host. /// Calculates session ID from CRC, stream name, connector and host.
std::string statExchange::getSessId(){ std::string statExchange::getSessId(){return Secure::md5(data + 32, 140);}
return Secure::md5(data+32, 140);
}
///\brief Gets time currently connected ///\brief Gets time currently connected
long statExchange::time() { long statExchange::time(){return Bit::btohl(data + 8);}
return Bit::btohl(data + 8);
}
///\brief Sets the last viewing second of this user ///\brief Sets the last viewing second of this user
void statExchange::lastSecond(long time) { void statExchange::lastSecond(long time){Bit::htobl(data + 12, time);}
Bit::htobl(data + 12, time);
}
///\brief Gets the last viewing second of this user ///\brief Gets the last viewing second of this user
long statExchange::lastSecond() { long statExchange::lastSecond(){return Bit::btohl(data + 12);}
return Bit::btohl(data + 12);
}
///\brief Sets the amount of bytes received ///\brief Sets the amount of bytes received
void statExchange::down(long long int bytes) { void statExchange::down(long long int bytes){Bit::htobll(data + 16, bytes);}
Bit::htobll(data + 16, bytes);
}
///\brief Gets the amount of bytes received ///\brief Gets the amount of bytes received
long long int statExchange::down() { long long int statExchange::down(){return Bit::btohll(data + 16);}
return Bit::btohll(data + 16);
}
///\brief Sets the amount of bytes sent ///\brief Sets the amount of bytes sent
void statExchange::up(long long int bytes) { void statExchange::up(long long int bytes){Bit::htobll(data + 24, bytes);}
Bit::htobll(data + 24, bytes);
}
///\brief Gets the amount of bytes sent ///\brief Gets the amount of bytes sent
long long int statExchange::up() { long long int statExchange::up(){return Bit::btohll(data + 24);}
return Bit::btohll(data + 24);
}
///\brief Sets the host of this connection ///\brief Sets the host of this connection
void statExchange::host(std::string name){ void statExchange::host(std::string name){
if (name.size() < 16) { if (name.size() < 16){memset(data + 32, 0, 16);}
memset(data + 32, 0, 16);
}
memcpy(data + 32, name.c_str(), std::min((int)name.size(), 16)); memcpy(data + 32, name.c_str(), std::min((int)name.size(), 16));
} }
///\brief Gets the host of this connection ///\brief Gets the host of this connection
std::string statExchange::host() { std::string statExchange::host(){return std::string(data + 32, 16);}
return std::string(data + 32, 16);
}
///\brief Sets the name of the stream this user is viewing ///\brief Sets the name of the stream this user is viewing
void statExchange::streamName(std::string name){ void statExchange::streamName(std::string name){
size_t splitChar = name.find_first_of("+ "); size_t splitChar = name.find_first_of("+ ");
if (splitChar != std::string::npos) { if (splitChar != std::string::npos){name[splitChar] = '+';}
name[splitChar] = '+';
}
snprintf(data + 48, 100, "%s", name.c_str()); snprintf(data + 48, 100, "%s", name.c_str());
} }
///\brief Gets the name of the stream this user is viewing ///\brief Gets the name of the stream this user is viewing
std::string statExchange::streamName() { std::string statExchange::streamName(){return std::string(data + 48, strnlen(data + 48, 100));}
return std::string(data + 48, strnlen(data + 48, 100));
}
///\brief Sets the name of the connector through which this user is viewing ///\brief Sets the name of the connector through which this user is viewing
void statExchange::connector(std::string name) { void statExchange::connector(std::string name){snprintf(data + 148, 20, "%s", name.c_str());}
snprintf(data+148, 20, "%s", name.c_str());
}
///\brief Gets the name of the connector through which this user is viewing ///\brief Gets the name of the connector through which this user is viewing
std::string statExchange::connector(){ std::string statExchange::connector(){
@ -729,39 +665,25 @@ namespace IPC {
} }
///\brief Sets checksum field ///\brief Sets checksum field
void statExchange::crc(unsigned int sum) { void statExchange::crc(unsigned int sum){Bit::htobl(data + 168, sum);}
Bit::htobl(data + 168, sum);
}
///\brief Gets checksum field ///\brief Gets checksum field
unsigned int statExchange::crc() { unsigned int statExchange::crc(){return Bit::btohl(data + 168);}
return Bit::btohl(data + 168);
}
///\brief Sets checksum field ///\brief Sets checksum field
void statExchange::setSync(char s) { void statExchange::setSync(char s){data[172] = s;}
data[172] = s;
}
///\brief Gets checksum field ///\brief Gets checksum field
char statExchange::getSync() { char statExchange::getSync(){return data[172];}
return data[172];
}
///\brief Gets PID field ///\brief Gets PID field
uint32_t statExchange::getPID() { uint32_t statExchange::getPID(){return *(uint32_t *)(data + 173);}
return *(uint32_t*)(data+173);
}
///\brief Creates a semaphore guard, locks the semaphore on call ///\brief Creates a semaphore guard, locks the semaphore on call
semGuard::semGuard(semaphore * thisSemaphore) : mySemaphore(thisSemaphore) { semGuard::semGuard(semaphore *thisSemaphore) : mySemaphore(thisSemaphore){mySemaphore->wait();}
mySemaphore->wait();
}
///\brief Destructs a semaphore guard, unlocks the semaphore on call ///\brief Destructs a semaphore guard, unlocks the semaphore on call
semGuard::~semGuard() { semGuard::~semGuard(){mySemaphore->post();}
mySemaphore->post();
}
///\brief Default constructor, erases all the values ///\brief Default constructor, erases all the values
sharedServer::sharedServer(){ sharedServer::sharedServer(){
@ -784,12 +706,8 @@ namespace IPC {
///\param len The lenght of the payload ///\param len The lenght of the payload
///\param withCounter Whether the content should have a counter ///\param withCounter Whether the content should have a counter
void sharedServer::init(std::string name, int len, bool withCounter){ void sharedServer::init(std::string name, int len, bool withCounter){
if (mySemaphore) { if (mySemaphore){mySemaphore.close();}
mySemaphore.close(); if (baseName != ""){mySemaphore.unlink();}
}
if (baseName != "") {
mySemaphore.unlink();
}
myPages.clear(); myPages.clear();
baseName = "/" + name; baseName = "/" + name;
payLen = len; payLen = len;
@ -806,17 +724,13 @@ namespace IPC {
} }
///\brief The deconstructor ///\brief The deconstructor
sharedServer::~sharedServer() { sharedServer::~sharedServer(){mySemaphore.unlink();}
mySemaphore.unlink();
}
///\brief Determines whether a sharedServer is valid ///\brief Determines whether a sharedServer is valid
sharedServer::operator bool() const { sharedServer::operator bool() const{return myPages.size();}
return myPages.size();
}
///Sets all currently loaded memory pages to non-master, so they are not cleaned up on destruction, but left behind. /// Sets all currently loaded memory pages to non-master, so they are not cleaned up on
///Useful for doing rolling updates and such. /// destruction, but left behind. Useful for doing rolling updates and such.
void sharedServer::abandon(){ void sharedServer::abandon(){
if (!myPages.size()){return;} if (!myPages.size()){return;}
VERYHIGH_MSG("Abandoning %llu memory pages, leaving them behind on purpose", myPages.size()); VERYHIGH_MSG("Abandoning %llu memory pages, leaving them behind on purpose", myPages.size());
@ -827,9 +741,11 @@ namespace IPC {
///\brief Creates the next page with the correct size ///\brief Creates the next page with the correct size
void sharedServer::newPage(){ void sharedServer::newPage(){
sharedPage tmp(std::string(baseName.substr(1) + (char)(myPages.size() + (int)'A')), std::min(((8192 * 2) << myPages.size()), (32 * 1024 * 1024)), false, false); sharedPage tmp(std::string(baseName.substr(1) + (char)(myPages.size() + (int)'A')),
std::min(((8192 * 2) << myPages.size()), (32 * 1024 * 1024)), false, false);
if (!tmp.mapped){ if (!tmp.mapped){
tmp.init(std::string(baseName.substr(1) + (char)(myPages.size() + (int)'A')), std::min(((8192 * 2) << myPages.size()), (32 * 1024 * 1024)), true); tmp.init(std::string(baseName.substr(1) + (char)(myPages.size() + (int)'A')),
std::min(((8192 * 2) << myPages.size()), (32 * 1024 * 1024)), true);
tmp.master = false; tmp.master = false;
} }
myPages.push_back(tmp); myPages.push_back(tmp);
@ -852,9 +768,7 @@ namespace IPC {
unsigned int i = 0; unsigned int i = 0;
for (std::deque<sharedPage>::iterator it = myPages.begin(); it != myPages.end(); it++){ for (std::deque<sharedPage>::iterator it = myPages.begin(); it != myPages.end(); it++){
// return if we reached the end // return if we reached the end
if (!it->mapped || !it->len) { if (!it->mapped || !it->len){return false;}
return false;
}
// not on this page? skip to next. // not on this page? skip to next.
if (it->len < (id - i) * payLen){ if (it->len < (id - i) * payLen){
i += it->len / payLen; i += it->len / payLen;
@ -866,9 +780,7 @@ namespace IPC {
}else{ }else{
// no counter - check the entire size for being all zeroes. // no counter - check the entire size for being all zeroes.
for (unsigned int j = 0; j < payLen; ++j){ for (unsigned int j = 0; j < payLen; ++j){
if (it->mapped[(id - i)*payLen + j]) { if (it->mapped[(id - i) * payLen + j]){return true;}
return true;
}
} }
return false; return false;
} }
@ -879,9 +791,7 @@ namespace IPC {
/// Disconnect all connected users, waits at most 2.5 seconds until completed /// Disconnect all connected users, waits at most 2.5 seconds until completed
void sharedServer::finishEach(){ void sharedServer::finishEach(){
if (!hasCounter){ if (!hasCounter){return;}
return;
}
unsigned int c = 0; // to prevent eternal loops unsigned int c = 0; // to prevent eternal loops
do{ do{
parseEach(killStatistics); parseEach(killStatistics);
@ -928,7 +838,8 @@ namespace IPC {
} }
///\brief Parse each of the possible payload pieces, and runs a callback on it if in use. ///\brief Parse each of the possible payload pieces, and runs a callback on it if in use.
void sharedServer::parseEach(void (*activeCallback)(char * data, size_t len, unsigned int id), void (*disconCallback)(char * data, size_t len, unsigned int id)) { void sharedServer::parseEach(void (*activeCallback)(char *data, size_t len, unsigned int id),
void (*disconCallback)(char *data, size_t len, unsigned int id)){
char *empty = 0; char *empty = 0;
if (!hasCounter){ if (!hasCounter){
empty = (char *)malloc(payLen * sizeof(char)); empty = (char *)malloc(payLen * sizeof(char));
@ -952,9 +863,7 @@ namespace IPC {
char *counter = it->mapped + offset; char *counter = it->mapped + offset;
// increase the count if needed // increase the count if needed
++userCount; ++userCount;
if (*counter & 0x80){ if (*counter & 0x80){connectedUsers++;}
connectedUsers++;
}
char countNum = (*counter) & 0x7F; char countNum = (*counter) & 0x7F;
lastFilled = id; lastFilled = id;
if (id >= amount){ if (id >= amount){
@ -962,26 +871,21 @@ namespace IPC {
VERYHIGH_MSG("Shared memory %s is now at count %u", baseName.c_str(), amount); VERYHIGH_MSG("Shared memory %s is now at count %u", baseName.c_str(), amount);
} }
uint32_t tmpPID = *((uint32_t *)(it->mapped + 1 + offset + payLen - 4)); uint32_t tmpPID = *((uint32_t *)(it->mapped + 1 + offset + payLen - 4));
if (tmpPID > 1 && it->master && !Util::Procs::isRunning(tmpPID) && !(countNum == 126 || countNum == 127)){ if (tmpPID > 1 && it->master && !Util::Procs::isRunning(tmpPID) &&
!(countNum == 126 || countNum == 127)){
WARN_MSG("process disappeared, timing out. (pid %lu)", tmpPID); WARN_MSG("process disappeared, timing out. (pid %lu)", tmpPID);
*counter = 125 | (0x80 & (*counter)); // if process is already dead, instant timeout. *counter = 125 | (0x80 & (*counter)); // if process is already dead, instant timeout.
} }
activeCallback(it->mapped + offset + 1, payLen, id); activeCallback(it->mapped + offset + 1, payLen, id);
switch (countNum){ switch (countNum){
case 127: case 127: HIGH_MSG("Client %u requested disconnect", id); break;
HIGH_MSG("Client %u requested disconnect", id); case 126: HIGH_MSG("Client %u timed out", id); break;
break;
case 126:
HIGH_MSG("Client %u timed out", id);
break;
default: default:
#ifndef NOCRASHCHECK #ifndef NOCRASHCHECK
if (tmpPID > 1 && it->master){ if (tmpPID > 1 && it->master){
if (countNum > 10 && countNum < 60){ if (countNum > 10 && countNum < 60){
if (countNum < 30){ if (countNum < 30){
if (countNum > 15) { if (countNum > 15){WARN_MSG("Process %d is unresponsive", tmpPID);}
WARN_MSG("Process %d is unresponsive", tmpPID);
}
Util::Procs::Stop(tmpPID); // soft kill Util::Procs::Stop(tmpPID); // soft kill
}else{ }else{
ERROR_MSG("Killing unresponsive process %d", tmpPID); ERROR_MSG("Killing unresponsive process %d", tmpPID);
@ -990,9 +894,7 @@ namespace IPC {
} }
if (countNum > 70){ if (countNum > 70){
if (countNum < 90){ if (countNum < 90){
if (countNum > 75) { if (countNum > 75){WARN_MSG("Stopping process %d is unresponsive", tmpPID);}
WARN_MSG("Stopping process %d is unresponsive", tmpPID);
}
Util::Procs::Stop(tmpPID); // soft kill Util::Procs::Stop(tmpPID); // soft kill
}else{ }else{
ERROR_MSG("Killing unresponsive stopping process %d", tmpPID); ERROR_MSG("Killing unresponsive stopping process %d", tmpPID);
@ -1005,9 +907,7 @@ namespace IPC {
} }
if (countNum == 127 || countNum == 126){ if (countNum == 127 || countNum == 126){
semGuard tmpGuard(&mySemaphore); semGuard tmpGuard(&mySemaphore);
if (disconCallback){ if (disconCallback){disconCallback(counter + 1, payLen, id);}
disconCallback(counter + 1, payLen, id);
}
memset(counter + 1, 0, payLen); memset(counter + 1, 0, payLen);
*counter = 0; *counter = 0;
}else{ }else{
@ -1047,9 +947,7 @@ namespace IPC {
} }
if (id >= amount + 100){ if (id >= amount + 100){
// stop, we're guaranteed no more pages are full at this point // stop, we're guaranteed no more pages are full at this point
if (empty) { if (empty){free(empty);}
free(empty);
}
break; break;
} }
} }
@ -1067,9 +965,7 @@ namespace IPC {
bool unsetMaster = !(it->master); bool unsetMaster = !(it->master);
semGuard tmpGuard(&mySemaphore); semGuard tmpGuard(&mySemaphore);
newPage(); newPage();
if (unsetMaster){ if (unsetMaster){(myPages.end() - 1)->master = false;}
(myPages.end()-1)->master = false;
}
it = myPages.end() - 2; it = myPages.end() - 2;
} }
} }
@ -1080,9 +976,7 @@ namespace IPC {
deletePage(); deletePage();
} }
if (empty) { if (empty){free(empty);}
free(empty);
}
} }
///\brief Creates an empty shared client ///\brief Creates an empty shared client
@ -1093,7 +987,6 @@ namespace IPC {
countAsViewer = true; countAsViewer = true;
} }
///\brief Copy constructor for sharedClients ///\brief Copy constructor for sharedClients
///\param rhs The client ro copy ///\param rhs The client ro copy
sharedClient::sharedClient(const sharedClient &rhs){ sharedClient::sharedClient(const sharedClient &rhs){
@ -1139,7 +1032,8 @@ namespace IPC {
///\param name The basename of the server to connect to ///\param name The basename of the server to connect to
///\param len The size of the payload to allocate ///\param len The size of the payload to allocate
///\param withCounter Whether or not this payload has a counter ///\param withCounter Whether or not this payload has a counter
sharedClient::sharedClient(std::string name, int len, bool withCounter) : baseName("/" + name), payLen(len), offsetOnPage(-1), hasCounter(withCounter) { sharedClient::sharedClient(std::string name, int len, bool withCounter)
: baseName("/" + name), payLen(len), offsetOnPage(-1), hasCounter(withCounter){
countAsViewer = true; countAsViewer = true;
#ifdef __APPLE__ #ifdef __APPLE__
// note: O_CREAT is only needed for mac, probably // note: O_CREAT is only needed for mac, probably
@ -1165,14 +1059,14 @@ namespace IPC {
while (offsetOnPage == -1 && (++attempts) < 20){ while (offsetOnPage == -1 && (++attempts) < 20){
for (char i = 'A'; i <= 'Z'; i++){ for (char i = 'A'; i <= 'Z'; i++){
myPage.init(baseName.substr(1) + i, (4096 << (i - 'A')), false, false); myPage.init(baseName.substr(1) + i, (4096 << (i - 'A')), false, false);
if (!myPage.mapped) { if (!myPage.mapped){break;}
break;
}
int offset = 0; int offset = 0;
while (offset + payLen + (hasCounter ? 1 : 0) <= myPage.len){ while (offset + payLen + (hasCounter ? 1 : 0) <= myPage.len){
if ((hasCounter && myPage.mapped[offset] == 0) || (!hasCounter && !memcmp(myPage.mapped + offset, empty, payLen))) { if ((hasCounter && myPage.mapped[offset] == 0) ||
(!hasCounter && !memcmp(myPage.mapped + offset, empty, payLen))){
semGuard tmpGuard(&mySemaphore); semGuard tmpGuard(&mySemaphore);
if ((hasCounter && myPage.mapped[offset] == 0) || (!hasCounter && !memcmp(myPage.mapped + offset, empty, payLen))) { if ((hasCounter && myPage.mapped[offset] == 0) ||
(!hasCounter && !memcmp(myPage.mapped + offset, empty, payLen))){
offsetOnPage = offset; offsetOnPage = offset;
if (hasCounter){ if (hasCounter){
myPage.mapped[offset] = 1; myPage.mapped[offset] = 1;
@ -1184,41 +1078,29 @@ namespace IPC {
} }
offset += payLen + (hasCounter ? 1 : 0); offset += payLen + (hasCounter ? 1 : 0);
} }
if (offsetOnPage != -1) { if (offsetOnPage != -1){break;}
break;
}
}
if (offsetOnPage == -1) {
Util::wait(500);
} }
if (offsetOnPage == -1){Util::wait(500);}
} }
if (offsetOnPage == -1){ if (offsetOnPage == -1){
FAIL_MSG("Could not register on page for %s", baseName.c_str()); FAIL_MSG("Could not register on page for %s", baseName.c_str());
myPage.close(); myPage.close();
} }
if (empty) { if (empty){free(empty);}
free(empty);
}
} }
///\brief The deconstructor ///\brief The deconstructor
sharedClient::~sharedClient() { sharedClient::~sharedClient(){mySemaphore.close();}
mySemaphore.close();
}
///\brief Writes data to the shared data ///\brief Writes data to the shared data
void sharedClient::write(char *data, int len){ void sharedClient::write(char *data, int len){
if (hasCounter) { if (hasCounter){keepAlive();}
keepAlive();
}
memcpy(myPage.mapped + offsetOnPage + (hasCounter ? 1 : 0), data, std::min(len, payLen)); memcpy(myPage.mapped + offsetOnPage + (hasCounter ? 1 : 0), data, std::min(len, payLen));
} }
///\brief Indicate that the process is done using this piece of memory, set the counter to finished ///\brief Indicate that the process is done using this piece of memory, set the counter to finished
void sharedClient::finish(){ void sharedClient::finish(){
if (!myPage.mapped) { if (!myPage.mapped){return;}
return;
}
if (!hasCounter){ if (!hasCounter){
DEBUG_MSG(DLVL_WARN, "Trying to time-out an element without counters"); DEBUG_MSG(DLVL_WARN, "Trying to time-out an element without counters");
myPage.close(); myPage.close();
@ -1236,44 +1118,30 @@ namespace IPC {
DEBUG_MSG(DLVL_WARN, "Trying to keep-alive an element without counters"); DEBUG_MSG(DLVL_WARN, "Trying to keep-alive an element without counters");
return; return;
} }
if (isAlive()){ if (isAlive()){myPage.mapped[offsetOnPage] = (countAsViewer ? 0x81 : 0x01);}
myPage.mapped[offsetOnPage] = (countAsViewer ? 0x81 : 0x01);
}
} }
bool sharedClient::isAlive(){ bool sharedClient::isAlive(){
if (!hasCounter) { if (!hasCounter){return (myPage.mapped != 0);}
return (myPage.mapped != 0); if (myPage.mapped && offsetOnPage >= 0){return (myPage.mapped[offsetOnPage] & 0x7F) < 60;}
}
if (myPage.mapped && offsetOnPage >= 0){
return (myPage.mapped[offsetOnPage] & 0x7F) < 60;
}
return false; return false;
} }
///\brief Get a pointer to the data of this client ///\brief Get a pointer to the data of this client
char *sharedClient::getData(){ char *sharedClient::getData(){
if (!myPage.mapped) { if (!myPage.mapped){return 0;}
return 0;
}
return (myPage.mapped + offsetOnPage + (hasCounter ? 1 : 0)); return (myPage.mapped + offsetOnPage + (hasCounter ? 1 : 0));
} }
int sharedClient::getCounter(){ int sharedClient::getCounter(){
if (!hasCounter){ if (!hasCounter){return -1;}
return -1; if (!myPage.mapped){return 0;}
}
if (!myPage.mapped) {
return 0;
}
return *(myPage.mapped + offsetOnPage); return *(myPage.mapped + offsetOnPage);
} }
userConnection::userConnection(char *_data){ userConnection::userConnection(char *_data){
data = _data; data = _data;
if (!data){ if (!data){WARN_MSG("userConnection created with null pointer!");}
WARN_MSG("userConnection created with null pointer!");
}
} }
unsigned long userConnection::getTrackId(size_t offset) const{ unsigned long userConnection::getTrackId(size_t offset) const{
@ -1290,7 +1158,6 @@ namespace IPC {
return; return;
} }
Bit::htobl(data + (offset * 6), trackId); Bit::htobl(data + (offset * 6), trackId);
} }
unsigned long userConnection::getKeynum(size_t offset) const{ unsigned long userConnection::getKeynum(size_t offset) const{
@ -1307,7 +1174,5 @@ namespace IPC {
return; return;
} }
Bit::htobs(data + (offset * 6) + 4, keynum); Bit::htobs(data + (offset * 6) + 4, keynum);
} }
} }// namespace IPC

View file

@ -1,9 +1,9 @@
#pragma once #pragma once
#include <string>
#include <set> #include <set>
#include <string>
#include "timing.h"
#include "defines.h" #include "defines.h"
#include "timing.h"
#if defined(__CYGWIN__) || defined(_WIN32) #if defined(__CYGWIN__) || defined(_WIN32)
#include <windows.h> #include <windows.h>
@ -46,6 +46,7 @@ namespace IPC {
unsigned int crc(); unsigned int crc();
uint32_t getPID(); uint32_t getPID();
std::string getSessId(); std::string getSessId();
private: private:
///\brief The payload for the stat exchange ///\brief The payload for the stat exchange
/// - 8 byte - now (timestamp of last statistics) /// - 8 byte - now (timestamp of last statistics)
@ -78,6 +79,7 @@ namespace IPC {
void close(); void close();
void abandon(); void abandon();
void unlink(); void unlink();
private: private:
#if defined(__CYGWIN__) || defined(_WIN32) #if defined(__CYGWIN__) || defined(_WIN32)
///\todo Maybe sometime implement anything else than 777 ///\todo Maybe sometime implement anything else than 777
@ -96,6 +98,7 @@ namespace IPC {
public: public:
semGuard(semaphore *thisSemaphore); semGuard(semaphore *thisSemaphore);
~semGuard(); ~semGuard();
private: private:
///\brief The semaphore to guard. ///\brief The semaphore to guard.
semaphore *mySemaphore; semaphore *mySemaphore;
@ -110,9 +113,7 @@ namespace IPC {
operator bool() const; operator bool() const;
void init(const std::string &name_, uint64_t len_, bool master_ = false, bool autoBackoff = true); void init(const std::string &name_, uint64_t len_, bool master_ = false, bool autoBackoff = true);
void operator=(sharedFile &rhs); void operator=(sharedFile &rhs);
bool operator < (const sharedFile & rhs) const { bool operator<(const sharedFile &rhs) const{return name < rhs.name;}
return name < rhs.name;
}
void close(); void close();
void unmap(); void unmap();
bool exists(); bool exists();
@ -143,9 +144,7 @@ namespace IPC {
operator bool() const; operator bool() const;
void init(const std::string &name_, uint64_t len_, bool master_ = false, bool autoBackoff = true); void init(const std::string &name_, uint64_t len_, bool master_ = false, bool autoBackoff = true);
void operator=(sharedPage &rhs); void operator=(sharedPage &rhs);
bool operator < (const sharedPage & rhs) const { bool operator<(const sharedPage &rhs) const{return name < rhs.name;}
return name < rhs.name;
}
void unmap(); void unmap();
void close(); void close();
bool exists(); bool exists();
@ -191,7 +190,8 @@ namespace IPC {
sharedServer(std::string name, int len, bool withCounter = false); sharedServer(std::string name, int len, bool withCounter = false);
void init(std::string name, int len, bool withCounter = false); void init(std::string name, int len, bool withCounter = false);
~sharedServer(); ~sharedServer();
void parseEach(void (*activeCallback)(char * data, size_t len, unsigned int id), void (*disconCallback)(char * data, size_t len, unsigned int id) = 0); void parseEach(void (*activeCallback)(char *data, size_t len, unsigned int id),
void (*disconCallback)(char *data, size_t len, unsigned int id) = 0);
char *getIndex(unsigned int id); char *getIndex(unsigned int id);
operator bool() const; operator bool() const;
///\brief The amount of connected clients ///\brief The amount of connected clients
@ -199,6 +199,7 @@ namespace IPC {
unsigned int connectedUsers; unsigned int connectedUsers;
void finishEach(); void finishEach();
void abandon(); void abandon();
private: private:
bool isInUse(unsigned int id); bool isInUse(unsigned int id);
void newPage(); void newPage();
@ -238,6 +239,7 @@ namespace IPC {
char *getData(); char *getData();
int getCounter(); int getCounter();
bool countAsViewer; bool countAsViewer;
private: private:
///\brief The basename of the shared pages. ///\brief The basename of the shared pages.
std::string baseName; std::string baseName;
@ -260,7 +262,8 @@ namespace IPC {
void setTrackId(size_t offset, unsigned long trackId) const; void setTrackId(size_t offset, unsigned long trackId) const;
unsigned long getKeynum(size_t offset) const; unsigned long getKeynum(size_t offset) const;
void setKeynum(size_t offset, unsigned long keynum); void setKeynum(size_t offset, unsigned long keynum);
private: private:
char *data; char *data;
}; };
} }// namespace IPC

View file

@ -275,9 +275,7 @@ std::string Socket::resolveHostToBestExternalAddrGuess(const std::string &host,
bool Socket::getSocketName(int fd, std::string &host, uint32_t &port){ bool Socket::getSocketName(int fd, std::string &host, uint32_t &port){
struct sockaddr_in6 tmpaddr; struct sockaddr_in6 tmpaddr;
socklen_t len = sizeof(tmpaddr); socklen_t len = sizeof(tmpaddr);
if (getsockname(fd, (sockaddr *)&tmpaddr, &len)){ if (getsockname(fd, (sockaddr *)&tmpaddr, &len)){return false;}
return false;
}
static char addrconv[INET6_ADDRSTRLEN]; static char addrconv[INET6_ADDRSTRLEN];
if (tmpaddr.sin6_family == AF_INET6){ if (tmpaddr.sin6_family == AF_INET6){
host = inet_ntop(AF_INET6, &(tmpaddr.sin6_addr), addrconv, INET6_ADDRSTRLEN); host = inet_ntop(AF_INET6, &(tmpaddr.sin6_addr), addrconv, INET6_ADDRSTRLEN);
@ -1184,9 +1182,7 @@ void Socket::Connection::setHost(std::string host){
hints.ai_next = NULL; hints.ai_next = NULL;
int s = getaddrinfo(host.c_str(), 0, &hints, &result); int s = getaddrinfo(host.c_str(), 0, &hints, &result);
if (s != 0){return;} if (s != 0){return;}
if (result){ if (result){memcpy(&remoteaddr, result->ai_addr, result->ai_addrlen);}
memcpy(&remoteaddr, result->ai_addr, result->ai_addrlen);
}
freeaddrinfo(result); freeaddrinfo(result);
} }

View file

@ -91,6 +91,7 @@ namespace Socket{
bool iread(Buffer &buffer, int flags = 0); ///< Incremental write call that is compatible with Socket::Buffer. 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. bool iwrite(std::string &buffer); ///< Write call that is compatible with std::string.
void setBoundAddr(); void setBoundAddr();
protected: protected:
std::string lastErr; ///< Stores last error, if any. std::string lastErr; ///< Stores last error, if any.
#ifdef SSL #ifdef SSL

View file

@ -1,6 +1,6 @@
#include <algorithm>
#include "defines.h" #include "defines.h"
#include "srtp.h" #include "srtp.h"
#include <algorithm>
/* --------------------------------------- */ /* --------------------------------------- */
@ -59,11 +59,9 @@ int SRTPReader::init(const std::string& cipher, const std::string& key, const st
/* select the right profile from exchanged cipher */ /* select the right profile from exchanged cipher */
if ("SRTP_AES128_CM_SHA1_80" == cipher){ if ("SRTP_AES128_CM_SHA1_80" == cipher){
profile = srtp_profile_aes128_cm_sha1_80; profile = srtp_profile_aes128_cm_sha1_80;
} }else if ("SRTP_AES128_CM_SHA1_32" == cipher){
else if ("SRTP_AES128_CM_SHA1_32" == cipher) {
profile = srtp_profile_aes128_cm_sha1_32; profile = srtp_profile_aes128_cm_sha1_32;
} }else{
else {
ERROR_MSG("Unsupported SRTP cipher used: %s.", cipher.c_str()); ERROR_MSG("Unsupported SRTP cipher used: %s.", cipher.c_str());
r = -2; r = -2;
goto error; goto error;
@ -103,9 +101,7 @@ int SRTPReader::init(const std::string& cipher, const std::string& key, const st
} }
error: error:
if (r < 0) { if (r < 0){shutdown();}
shutdown();
}
return r; return r;
} }
@ -116,7 +112,8 @@ int SRTPReader::shutdown() {
srtp_err_status_t status = srtp_dealloc(session); srtp_err_status_t status = srtp_dealloc(session);
if (srtp_err_status_ok != status){ if (srtp_err_status_ok != status){
ERROR_MSG("Failed to cleanly shutdown the SRTP session. Status: %s", srtp_status_to_string(status).c_str()); ERROR_MSG("Failed to cleanly shutdown the SRTP session. Status: %s",
srtp_status_to_string(status).c_str());
r -= 5; r -= 5;
} }
@ -245,11 +242,9 @@ int SRTPWriter::init(const std::string& cipher, const std::string& key, const st
/* select the exchanged cipher */ /* select the exchanged cipher */
if ("SRTP_AES128_CM_SHA1_80" == cipher){ if ("SRTP_AES128_CM_SHA1_80" == cipher){
profile = srtp_profile_aes128_cm_sha1_80; profile = srtp_profile_aes128_cm_sha1_80;
} }else if ("SRTP_AES128_CM_SHA1_32" == cipher){
else if ("SRTP_AES128_CM_SHA1_32" == cipher) {
profile = srtp_profile_aes128_cm_sha1_32; profile = srtp_profile_aes128_cm_sha1_32;
} }else{
else {
ERROR_MSG("Unsupported SRTP cipher used: %s.", cipher.c_str()); ERROR_MSG("Unsupported SRTP cipher used: %s.", cipher.c_str());
r = -2; r = -2;
goto error; goto error;
@ -289,9 +284,7 @@ int SRTPWriter::init(const std::string& cipher, const std::string& key, const st
} }
error: error:
if (r < 0) { if (r < 0){shutdown();}
shutdown();
}
return r; return r;
} }
@ -302,7 +295,8 @@ int SRTPWriter::shutdown() {
srtp_err_status_t status = srtp_dealloc(session); srtp_err_status_t status = srtp_dealloc(session);
if (srtp_err_status_ok != status){ if (srtp_err_status_ok != status){
ERROR_MSG("Failed to cleanly shutdown the SRTP session. Status: %s", srtp_status_to_string(status).c_str()); ERROR_MSG("Failed to cleanly shutdown the SRTP session. Status: %s",
srtp_status_to_string(status).c_str());
r -= 5; r -= 5;
} }
@ -381,41 +375,98 @@ int SRTPWriter::protectRtcp(uint8_t* data, int* nbytes) {
return 0; return 0;
} }
/* --------------------------------------- */ /* --------------------------------------- */
static std::string srtp_status_to_string(uint32_t status){ static std::string srtp_status_to_string(uint32_t status){
switch (status){ switch (status){
case srtp_err_status_ok: { return "srtp_err_status_ok"; } case srtp_err_status_ok:{
case srtp_err_status_fail: { return "srtp_err_status_fail"; } return "srtp_err_status_ok";
case srtp_err_status_bad_param: { return "srtp_err_status_bad_param"; } }
case srtp_err_status_alloc_fail: { return "srtp_err_status_alloc_fail"; } case srtp_err_status_fail:{
case srtp_err_status_dealloc_fail: { return "srtp_err_status_dealloc_fail"; } return "srtp_err_status_fail";
case srtp_err_status_init_fail: { return "srtp_err_status_init_fail"; } }
case srtp_err_status_terminus: { return "srtp_err_status_terminus"; } case srtp_err_status_bad_param:{
case srtp_err_status_auth_fail: { return "srtp_err_status_auth_fail"; } return "srtp_err_status_bad_param";
case srtp_err_status_cipher_fail: { return "srtp_err_status_cipher_fail"; } }
case srtp_err_status_replay_fail: { return "srtp_err_status_replay_fail"; } case srtp_err_status_alloc_fail:{
case srtp_err_status_replay_old: { return "srtp_err_status_replay_old"; } return "srtp_err_status_alloc_fail";
case srtp_err_status_algo_fail: { return "srtp_err_status_algo_fail"; } }
case srtp_err_status_no_such_op: { return "srtp_err_status_no_such_op"; } case srtp_err_status_dealloc_fail:{
case srtp_err_status_no_ctx: { return "srtp_err_status_no_ctx"; } return "srtp_err_status_dealloc_fail";
case srtp_err_status_cant_check: { return "srtp_err_status_cant_check"; } }
case srtp_err_status_key_expired: { return "srtp_err_status_key_expired"; } case srtp_err_status_init_fail:{
case srtp_err_status_socket_err: { return "srtp_err_status_socket_err"; } return "srtp_err_status_init_fail";
case srtp_err_status_signal_err: { return "srtp_err_status_signal_err"; } }
case srtp_err_status_nonce_bad: { return "srtp_err_status_nonce_bad"; } case srtp_err_status_terminus:{
case srtp_err_status_read_fail: { return "srtp_err_status_read_fail"; } return "srtp_err_status_terminus";
case srtp_err_status_write_fail: { return "srtp_err_status_write_fail"; } }
case srtp_err_status_parse_err: { return "srtp_err_status_parse_err"; } case srtp_err_status_auth_fail:{
case srtp_err_status_encode_err: { return "srtp_err_status_encode_err"; } return "srtp_err_status_auth_fail";
case srtp_err_status_semaphore_err: { return "srtp_err_status_semaphore_err"; } }
case srtp_err_status_pfkey_err: { return "srtp_err_status_pfkey_err"; } case srtp_err_status_cipher_fail:{
case srtp_err_status_bad_mki: { return "srtp_err_status_bad_mki"; } return "srtp_err_status_cipher_fail";
case srtp_err_status_pkt_idx_old: { return "srtp_err_status_pkt_idx_old"; } }
case srtp_err_status_pkt_idx_adv: { return "srtp_err_status_pkt_idx_adv"; } case srtp_err_status_replay_fail:{
default: { return "UNKNOWN"; } return "srtp_err_status_replay_fail";
}
case srtp_err_status_replay_old:{
return "srtp_err_status_replay_old";
}
case srtp_err_status_algo_fail:{
return "srtp_err_status_algo_fail";
}
case srtp_err_status_no_such_op:{
return "srtp_err_status_no_such_op";
}
case srtp_err_status_no_ctx:{
return "srtp_err_status_no_ctx";
}
case srtp_err_status_cant_check:{
return "srtp_err_status_cant_check";
}
case srtp_err_status_key_expired:{
return "srtp_err_status_key_expired";
}
case srtp_err_status_socket_err:{
return "srtp_err_status_socket_err";
}
case srtp_err_status_signal_err:{
return "srtp_err_status_signal_err";
}
case srtp_err_status_nonce_bad:{
return "srtp_err_status_nonce_bad";
}
case srtp_err_status_read_fail:{
return "srtp_err_status_read_fail";
}
case srtp_err_status_write_fail:{
return "srtp_err_status_write_fail";
}
case srtp_err_status_parse_err:{
return "srtp_err_status_parse_err";
}
case srtp_err_status_encode_err:{
return "srtp_err_status_encode_err";
}
case srtp_err_status_semaphore_err:{
return "srtp_err_status_semaphore_err";
}
case srtp_err_status_pfkey_err:{
return "srtp_err_status_pfkey_err";
}
case srtp_err_status_bad_mki:{
return "srtp_err_status_bad_mki";
}
case srtp_err_status_pkt_idx_old:{
return "srtp_err_status_pkt_idx_old";
}
case srtp_err_status_pkt_idx_adv:{
return "srtp_err_status_pkt_idx_adv";
}
default:{
return "UNKNOWN";
}
} }
} }

View file

@ -1,8 +1,8 @@
#pragma once #pragma once
#include <srtp2/srtp.h>
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <srtp2/srtp.h>
#define SRTP_PARSER_MASTER_KEY_LEN 16 #define SRTP_PARSER_MASTER_KEY_LEN 16
#define SRTP_PARSER_MASTER_SALT_LEN 14 #define SRTP_PARSER_MASTER_SALT_LEN 14

View file

@ -1,19 +1,19 @@
/// \file stream.cpp /// \file stream.cpp
/// Utilities for handling streams. /// Utilities for handling streams.
#include "stream.h"
#include "config.h" #include "config.h"
#include "defines.h" #include "defines.h"
#include "dtsc.h" #include "dtsc.h"
#include "h265.h"
#include "http_parser.h"
#include "json.h" #include "json.h"
#include "langcodes.h"
#include "mp4_generic.h"
#include "procs.h" #include "procs.h"
#include "shared_memory.h" #include "shared_memory.h"
#include "socket.h" #include "socket.h"
#include "stream.h"
#include "triggers.h" //LTS #include "triggers.h" //LTS
#include "h265.h"
#include "mp4_generic.h"
#include "langcodes.h"
#include "http_parser.h"
#include <semaphore.h> #include <semaphore.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -98,7 +98,11 @@ std::string Util::codecString(const std::string & codec, const std::string & ini
if (mInfo.general_profile_compatflags & 0x40000000ul){mappedFlags += 0x00000002ul;} if (mInfo.general_profile_compatflags & 0x40000000ul){mappedFlags += 0x00000002ul;}
if (mInfo.general_profile_compatflags & 0x80000000ul){mappedFlags += 0x00000001ul;} if (mInfo.general_profile_compatflags & 0x80000000ul){mappedFlags += 0x00000001ul;}
r << std::hex << (unsigned long)mappedFlags << std::dec << '.'; r << std::hex << (unsigned long)mappedFlags << std::dec << '.';
if (mInfo.general_tier_flag){r << 'H';}else{r << 'L';} if (mInfo.general_tier_flag){
r << 'H';
}else{
r << 'L';
}
r << (unsigned long)mInfo.general_level_idc; r << (unsigned long)mInfo.general_level_idc;
if (mInfo.constraint_flags[0]){ if (mInfo.constraint_flags[0]){
r << '.' << std::hex << (unsigned long)mInfo.constraint_flags[0] << std::dec; r << '.' << std::hex << (unsigned long)mInfo.constraint_flags[0] << std::dec;
@ -112,8 +116,7 @@ std::string Util::codecString(const std::string & codec, const std::string & ini
} }
/// Replaces all stream-related variables in the given 'str' with their values. /// Replaces all stream-related variables in the given 'str' with their values.
void Util::streamVariables(std::string &str, const std::string &streamname, void Util::streamVariables(std::string &str, const std::string &streamname, const std::string &source){
const std::string &source){
replace(str, "$source", source); replace(str, "$source", source);
replace(str, "$datetime", "$year.$month.$day.$hour.$minute.$second"); replace(str, "$datetime", "$year.$month.$day.$hour.$minute.$second");
replace(str, "$day", strftime_now("%d")); replace(str, "$day", strftime_now("%d"));
@ -213,7 +216,9 @@ JSON::Value Util::getStreamConfig(const std::string &streamname){
if (!Util::getGlobalConfig("defaultStream")){ if (!Util::getGlobalConfig("defaultStream")){
WARN_MSG("Could not get stream '%s' config!", smp.c_str()); WARN_MSG("Could not get stream '%s' config!", smp.c_str());
}else{ }else{
INFO_MSG("Could not get stream '%s' config, not emitting WARN message because fallback is configured", smp.c_str()); INFO_MSG("Could not get stream '%s' config, not emitting WARN message because fallback is "
"configured",
smp.c_str());
} }
return result; return result;
} }
@ -447,7 +452,8 @@ bool Util::startInput(std::string streamname, std::string filename, bool forkFir
} }
if (pid == 0){ if (pid == 0){
for (std::set<int>::iterator it = Util::Procs::socketList.begin(); it != Util::Procs::socketList.end(); ++it){ for (std::set<int>::iterator it = Util::Procs::socketList.begin();
it != Util::Procs::socketList.end(); ++it){
close(*it); close(*it);
} }
Socket::Connection io(0, 1); Socket::Connection io(0, 1);
@ -511,8 +517,7 @@ JSON::Value Util::getInputBySource(const std::string &filename, bool isProvider)
MEDIUM_MSG("Checking input %s: %s (%s)", inputs.getIndiceName(i).c_str(), MEDIUM_MSG("Checking input %s: %s (%s)", inputs.getIndiceName(i).c_str(),
tmp_input.getMember("name").asString().c_str(), source.c_str()); tmp_input.getMember("name").asString().c_str(), source.c_str());
if (tmpFn.substr(0, front.size()) == front && if (tmpFn.substr(0, front.size()) == front && tmpFn.substr(tmpFn.size() - back.size()) == back){
tmpFn.substr(tmpFn.size() - back.size()) == back){
if (tmp_input.getMember("non-provider") && !isProvider){ if (tmp_input.getMember("non-provider") && !isProvider){
noProviderNoPick = true; noProviderNoPick = true;
continue; continue;
@ -643,12 +648,24 @@ bool Util::checkException(const JSON::Value & ex, const std::string & useragent)
if (!e->isArray() || !e->size()){continue;} if (!e->isArray() || !e->size()){continue;}
bool setTo = false; bool setTo = false;
bool except = false; bool except = false;
//whitelist makes the return value true if any value is contained in the UA, blacklist makes it false. // whitelist makes the return value true if any value is contained in the UA, blacklist makes it
//the '_except' variants do so only if none of the values are contained in the UA. // false. the '_except' variants do so only if none of the values are contained in the UA.
if ((*e)[0u].asStringRef() == "whitelist"){setTo = true; except = false;} if ((*e)[0u].asStringRef() == "whitelist"){
if ((*e)[0u].asStringRef() == "whitelist_except"){setTo = true; except = true;} setTo = true;
if ((*e)[0u].asStringRef() == "blacklist"){setTo = false; except = false;} except = false;
if ((*e)[0u].asStringRef() == "blacklist_except"){setTo = false; except = true;} }
if ((*e)[0u].asStringRef() == "whitelist_except"){
setTo = true;
except = true;
}
if ((*e)[0u].asStringRef() == "blacklist"){
setTo = false;
except = false;
}
if ((*e)[0u].asStringRef() == "blacklist_except"){
setTo = false;
except = true;
}
if (e->size() == 1){ if (e->size() == 1){
ret = setTo; ret = setTo;
continue; continue;
@ -679,9 +696,12 @@ DTSC::Scan Util::DTSCShmReader::getScan(){
return DTSC::Scan(rAcc.getPointer("dtsc_data"), rAcc.getSize("dtsc_data")); return DTSC::Scan(rAcc.getPointer("dtsc_data"), rAcc.getSize("dtsc_data"));
} }
std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa, const std::string &trackType, const std::string &trackVal, const std::string &UA){ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa, const std::string &trackType,
const std::string &trackVal, const std::string &UA){
std::set<size_t> result; std::set<size_t> result;
if (!trackVal.size() || trackVal == "0" || trackVal == "-1" || trackVal == "none"){return result;}//don't select anything in particular if (!trackVal.size() || trackVal == "0" || trackVal == "-1" || trackVal == "none"){
return result;
}// don't select anything in particular
if (trackVal.find(',') != std::string::npos){ if (trackVal.find(',') != std::string::npos){
// Comma-separated list, recurse. // Comma-separated list, recurse.
std::stringstream ss(trackVal); std::stringstream ss(trackVal);
@ -702,10 +722,12 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
} }
const DTSC::Track &Trk = M.tracks.at(trackNo); const DTSC::Track &Trk = M.tracks.at(trackNo);
if (Trk.type != trackType && Trk.codec != trackType){ if (Trk.type != trackType && Trk.codec != trackType){
INFO_MSG("Track %zd is not %s (%s/%s), cannot select", trackNo, trackType.c_str(), Trk.type.c_str(), Trk.codec.c_str()); INFO_MSG("Track %zd is not %s (%s/%s), cannot select", trackNo, trackType.c_str(),
Trk.type.c_str(), Trk.codec.c_str());
return result; return result;
} }
INFO_MSG("Selecting %s track %zd (%s/%s)", trackType.c_str(), trackNo, Trk.type.c_str(), Trk.codec.c_str()); INFO_MSG("Selecting %s track %zd (%s/%s)", trackType.c_str(), trackNo, Trk.type.c_str(),
Trk.codec.c_str());
result.insert(trackNo); result.insert(trackNo);
return result; return result;
} }
@ -717,7 +739,9 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
std::set<size_t> validTracks = getSupportedTracks(M, capa); std::set<size_t> validTracks = getSupportedTracks(M, capa);
for (std::set<size_t>::iterator it = validTracks.begin(); it != validTracks.end(); it++){ for (std::set<size_t>::iterator it = validTracks.begin(); it != validTracks.end(); it++){
const DTSC::Track &Trk = M.tracks.at(*it); const DTSC::Track &Trk = M.tracks.at(*it);
if (!trackType.size() || Trk.type == trackType || Trk.codec == trackType){result.insert(*it);} if (!trackType.size() || Trk.type == trackType || Trk.codec == trackType){
result.insert(*it);
}
} }
return result; return result;
} }
@ -759,12 +783,24 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
if (trackLow[0] == '<' || trackLow[0] == '>'){ if (trackLow[0] == '<' || trackLow[0] == '>'){
unsigned int bpsVal; unsigned int bpsVal;
uint64_t targetBps = 0; uint64_t targetBps = 0;
if (trackLow.find("bps") != std::string::npos && sscanf(trackLow.c_str(), "<%ubps", &bpsVal) == 1){targetBps = bpsVal;} if (trackLow.find("bps") != std::string::npos && sscanf(trackLow.c_str(), "<%ubps", &bpsVal) == 1){
if (trackLow.find("kbps") != std::string::npos && sscanf(trackLow.c_str(), "<%ukbps", &bpsVal) == 1){targetBps = bpsVal*1024;} targetBps = bpsVal;
if (trackLow.find("mbps") != std::string::npos && sscanf(trackLow.c_str(), "<%umbps", &bpsVal) == 1){targetBps = bpsVal*1024*1024;} }
if (trackLow.find("bps") != std::string::npos && sscanf(trackLow.c_str(), ">%ubps", &bpsVal) == 1){targetBps = bpsVal;} if (trackLow.find("kbps") != std::string::npos && sscanf(trackLow.c_str(), "<%ukbps", &bpsVal) == 1){
if (trackLow.find("kbps") != std::string::npos && sscanf(trackLow.c_str(), ">%ukbps", &bpsVal) == 1){targetBps = bpsVal*1024;} targetBps = bpsVal * 1024;
if (trackLow.find("mbps") != std::string::npos && sscanf(trackLow.c_str(), ">%umbps", &bpsVal) == 1){targetBps = bpsVal*1024*1024;} }
if (trackLow.find("mbps") != std::string::npos && sscanf(trackLow.c_str(), "<%umbps", &bpsVal) == 1){
targetBps = bpsVal * 1024 * 1024;
}
if (trackLow.find("bps") != std::string::npos && sscanf(trackLow.c_str(), ">%ubps", &bpsVal) == 1){
targetBps = bpsVal;
}
if (trackLow.find("kbps") != std::string::npos && sscanf(trackLow.c_str(), ">%ukbps", &bpsVal) == 1){
targetBps = bpsVal * 1024;
}
if (trackLow.find("mbps") != std::string::npos && sscanf(trackLow.c_str(), ">%umbps", &bpsVal) == 1){
targetBps = bpsVal * 1024 * 1024;
}
if (targetBps){ if (targetBps){
targetBps >>= 3; targetBps >>= 3;
// select all tracks of this type that match the requirements // select all tracks of this type that match the requirements
@ -799,9 +835,15 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
{ {
unsigned int bpsVal; unsigned int bpsVal;
uint64_t targetBps = 0; uint64_t targetBps = 0;
if (trackLow.find("bps") != std::string::npos && sscanf(trackLow.c_str(), "%ubps", &bpsVal) == 1){targetBps = bpsVal;} if (trackLow.find("bps") != std::string::npos && sscanf(trackLow.c_str(), "%ubps", &bpsVal) == 1){
if (trackLow.find("kbps") != std::string::npos && sscanf(trackLow.c_str(), "%ukbps", &bpsVal) == 1){targetBps = bpsVal*1024;} targetBps = bpsVal;
if (trackLow.find("mbps") != std::string::npos && sscanf(trackLow.c_str(), "%umbps", &bpsVal) == 1){targetBps = bpsVal*1024*1024;} }
if (trackLow.find("kbps") != std::string::npos && sscanf(trackLow.c_str(), "%ukbps", &bpsVal) == 1){
targetBps = bpsVal * 1024;
}
if (trackLow.find("mbps") != std::string::npos && sscanf(trackLow.c_str(), "%umbps", &bpsVal) == 1){
targetBps = bpsVal * 1024 * 1024;
}
if (targetBps){ if (targetBps){
targetBps >>= 3; targetBps >>= 3;
// select nearest bit rate track of this type // select nearest bit rate track of this type
@ -811,7 +853,8 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
for (std::set<size_t>::iterator it = validTracks.begin(); it != validTracks.end(); it++){ for (std::set<size_t>::iterator it = validTracks.begin(); it != validTracks.end(); it++){
const DTSC::Track &Trk = M.tracks.at(*it); const DTSC::Track &Trk = M.tracks.at(*it);
if (!trackType.size() || Trk.type == trackType || Trk.codec == trackType){ if (!trackType.size() || Trk.type == trackType || Trk.codec == trackType){
if (currVal == INVALID_TRACK_ID || (Trk.bps >= targetBps && currDist > (Trk.bps-targetBps)) || (Trk.bps < targetBps && currDist > (targetBps-Trk.bps))){ if (currVal == INVALID_TRACK_ID || (Trk.bps >= targetBps && currDist > (Trk.bps - targetBps)) ||
(Trk.bps < targetBps && currDist > (targetBps - Trk.bps))){
currVal = *it; currVal = *it;
currDist = (Trk.bps >= targetBps) ? (Trk.bps - targetBps) : (targetBps - Trk.bps); currDist = (Trk.bps >= targetBps) ? (Trk.bps - targetBps) : (targetBps - Trk.bps);
} }
@ -838,7 +881,9 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
if (trackLow == "mono"){targetChannel = 1;} if (trackLow == "mono"){targetChannel = 1;}
if (trackLow == "stereo"){targetChannel = 2;} if (trackLow == "stereo"){targetChannel = 2;}
if (trackLow == "stereo"){targetChannel = 2;} if (trackLow == "stereo"){targetChannel = 2;}
if (trackLow.find("ch") != std::string::npos && sscanf(trackLow.c_str(), "%uch", &channelVal) == 1){targetChannel = channelVal;} if (trackLow.find("ch") != std::string::npos && sscanf(trackLow.c_str(), "%uch", &channelVal) == 1){
targetChannel = channelVal;
}
if (targetChannel){ if (targetChannel){
std::set<size_t> validTracks = getSupportedTracks(M, capa); std::set<size_t> validTracks = getSupportedTracks(M, capa);
for (std::set<size_t>::iterator it = validTracks.begin(); it != validTracks.end(); it++){ for (std::set<size_t>::iterator it = validTracks.begin(); it != validTracks.end(); it++){
@ -900,7 +945,8 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
const DTSC::Track &Trk = M.tracks.at(*it); const DTSC::Track &Trk = M.tracks.at(*it);
if (!trackType.size() || Trk.type == trackType || Trk.codec == trackType){ if (!trackType.size() || Trk.type == trackType || Trk.codec == trackType){
uint64_t trackArea = Trk.width * Trk.height; uint64_t trackArea = Trk.width * Trk.height;
if (currVal == INVALID_TRACK_ID || (trackArea >= targetArea && currDist > (trackArea-targetArea)) || (trackArea < targetArea && currDist > (targetArea-trackArea))){ if (currVal == INVALID_TRACK_ID || (trackArea >= targetArea && currDist > (trackArea - targetArea)) ||
(trackArea < targetArea && currDist > (targetArea - trackArea))){
currVal = *it; currVal = *it;
currDist = (trackArea >= targetArea) ? (trackArea - targetArea) : (targetArea - trackArea); currDist = (trackArea >= targetArea) ? (trackArea - targetArea) : (targetArea - trackArea);
} }
@ -953,9 +999,7 @@ std::set<size_t> Util::getSupportedTracks(const DTSC::Meta &M, const JSON::Value
std::set<size_t> validTracks; std::set<size_t> validTracks;
for (std::map<unsigned int, DTSC::Track>::const_iterator it = M.tracks.begin(); it != M.tracks.end(); it++){ for (std::map<unsigned int, DTSC::Track>::const_iterator it = M.tracks.begin(); it != M.tracks.end(); it++){
const DTSC::Track &Trk = it->second; const DTSC::Track &Trk = it->second;
if (type != "" && type != Trk.type){ if (type != "" && type != Trk.type){continue;}
continue;
}
// Remove tracks for which we don't have codec support // Remove tracks for which we don't have codec support
if (capa.isMember("codecs")){ if (capa.isMember("codecs")){
std::string codec = Trk.codec; std::string codec = Trk.codec;
@ -1071,8 +1115,7 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri
for (std::set<size_t>::iterator trit = validTracks.begin(); trit != validTracks.end(); trit++){ for (std::set<size_t>::iterator trit = validTracks.begin(); trit != validTracks.end(); trit++){
const DTSC::Track &Trk = M.tracks.at(*trit); const DTSC::Track &Trk = M.tracks.at(*trit);
bool problems = false; bool problems = false;
if (capa.isMember("exceptions") && capa["exceptions"].isObject() && if (capa.isMember("exceptions") && capa["exceptions"].isObject() && capa["exceptions"].size()){
capa["exceptions"].size()){
jsonForEachConst(capa["exceptions"], ex){ jsonForEachConst(capa["exceptions"], ex){
if (ex.key() == "codec:" + Trk.codec){ if (ex.key() == "codec:" + Trk.codec){
problems = !Util::checkException(*ex, UA); problems = !Util::checkException(*ex, UA);
@ -1091,7 +1134,6 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri
} }
/*LTS-END*/ /*LTS-END*/
jsonForEachConst(capa["codecs"], it){ jsonForEachConst(capa["codecs"], it){
unsigned int selCounter = 0; unsigned int selCounter = 0;
if ((*it).size() > 0){ if ((*it).size() > 0){
@ -1222,10 +1264,7 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri
/*LTS-START*/ /*LTS-START*/
if (noSelAudio && Trk.type == "audio"){continue;} if (noSelAudio && Trk.type == "audio"){continue;}
if (noSelVideo && Trk.type == "video"){continue;} if (noSelVideo && Trk.type == "video"){continue;}
if (noSelSub && if (noSelSub && (Trk.type == "subtitle" || Trk.codec == "subtitle")){continue;}
(Trk.type == "subtitle" || Trk.codec == "subtitle")){
continue;
}
/*LTS-END*/ /*LTS-END*/
result.insert(*trit); result.insert(*trit);
found = true; found = true;
@ -1253,10 +1292,7 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri
/*LTS-START*/ /*LTS-START*/
if (noSelAudio && Trk.type == "audio"){continue;} if (noSelAudio && Trk.type == "audio"){continue;}
if (noSelVideo && Trk.type == "video"){continue;} if (noSelVideo && Trk.type == "video"){continue;}
if (noSelSub && if (noSelSub && (Trk.type == "subtitle" || Trk.type == "subtitle")){continue;}
(Trk.type == "subtitle" || Trk.type == "subtitle")){
continue;
}
/*LTS-END*/ /*LTS-END*/
result.insert(*trit); result.insert(*trit);
found = true; found = true;

View file

@ -2,12 +2,12 @@
/// Utilities for handling streams. /// Utilities for handling streams.
#pragma once #pragma once
#include <string>
#include "socket.h"
#include "json.h"
#include "dtsc.h" #include "dtsc.h"
#include "json.h"
#include "shared_memory.h" #include "shared_memory.h"
#include "socket.h"
#include "util.h" #include "util.h"
#include <string>
const JSON::Value empty; const JSON::Value empty;
@ -16,7 +16,10 @@ namespace Util {
std::string getTmpFolder(); std::string getTmpFolder();
void sanitizeName(std::string &streamname); void sanitizeName(std::string &streamname);
bool streamAlive(std::string &streamname); bool streamAlive(std::string &streamname);
bool startInput(std::string streamname, std::string filename = "", bool forkFirst = true, bool isProvider = false, const std::map<std::string, std::string> & overrides = std::map<std::string, std::string>(), pid_t * spawn_pid = NULL); bool startInput(std::string streamname, std::string filename = "", bool forkFirst = true,
bool isProvider = false,
const std::map<std::string, std::string> &overrides = std::map<std::string, std::string>(),
pid_t *spawn_pid = NULL);
int startPush(const std::string &streamname, std::string &target); int startPush(const std::string &streamname, std::string &target);
JSON::Value getStreamConfig(const std::string &streamname); JSON::Value getStreamConfig(const std::string &streamname);
JSON::Value getGlobalConfig(const std::string &optionName); JSON::Value getGlobalConfig(const std::string &optionName);
@ -26,20 +29,25 @@ namespace Util {
bool checkException(const JSON::Value &ex, const std::string &useragent); bool checkException(const JSON::Value &ex, const std::string &useragent);
std::string codecString(const std::string &codec, const std::string &initData = ""); std::string codecString(const std::string &codec, const std::string &initData = "");
std::set<size_t> getSupportedTracks(const DTSC::Meta &M, const JSON::Value &capa = empty, const std::string &type = "", const std::string &UA = ""); std::set<size_t> getSupportedTracks(const DTSC::Meta &M, const JSON::Value &capa = empty,
std::set<size_t> findTracks(const DTSC::Meta &M, const JSON::Value &capa, const std::string &trackType, const std::string &trackVal, const std::string &UA = ""); const std::string &type = "", const std::string &UA = "");
std::set<size_t> wouldSelect(const DTSC::Meta &M, const std::string &trackSelector = "", const JSON::Value &capa = empty, const std::string &UA = ""); std::set<size_t> findTracks(const DTSC::Meta &M, const JSON::Value &capa, const std::string &trackType,
std::set<size_t> wouldSelect(const DTSC::Meta &M, const std::map<std::string, std::string> &targetParams, const JSON::Value &capa = empty, const std::string &UA = "", uint64_t seekTarget = 0); const std::string &trackVal, const std::string &UA = "");
std::set<size_t> wouldSelect(const DTSC::Meta &M, const std::string &trackSelector = "",
const JSON::Value &capa = empty, const std::string &UA = "");
std::set<size_t> wouldSelect(const DTSC::Meta &M, const std::map<std::string, std::string> &targetParams,
const JSON::Value &capa = empty, const std::string &UA = "",
uint64_t seekTarget = 0);
class DTSCShmReader{ class DTSCShmReader{
public: public:
DTSCShmReader(const std::string &pageName); DTSCShmReader(const std::string &pageName);
DTSC::Scan getMember(const std::string &indice); DTSC::Scan getMember(const std::string &indice);
DTSC::Scan getScan(); DTSC::Scan getScan();
private: private:
IPC::sharedPage rPage; IPC::sharedPage rPage;
Util::RelAccX rAcc; Util::RelAccX rAcc;
}; };
} }// namespace Util

View file

@ -1,62 +1,144 @@
#include "checksum.h" // for crc32
#include "defines.h" #include "defines.h"
#include "stun.h" #include "stun.h"
#include "checksum.h" // for crc32
/* --------------------------------------- */ /* --------------------------------------- */
std::string stun_family_type_to_string(uint8_t type){ std::string stun_family_type_to_string(uint8_t type){
switch (type){ switch (type){
case STUN_IP4: { return "STUN_IP4"; } case STUN_IP4:{
case STUN_IP6: { return "STUN_IP6"; } return "STUN_IP4";
default: { return "UNKNOWN"; } }
case STUN_IP6:{
return "STUN_IP6";
}
default:{
return "UNKNOWN";
}
} }
} }
std::string stun_message_type_to_string(uint16_t type){ std::string stun_message_type_to_string(uint16_t type){
switch (type){ switch (type){
case STUN_MSG_TYPE_NONE: { return "STUN_MSG_TYPE_NONE"; } case STUN_MSG_TYPE_NONE:{
case STUN_MSG_TYPE_BINDING_REQUEST: { return "STUN_MSG_TYPE_BINDING_REQUEST"; } return "STUN_MSG_TYPE_NONE";
case STUN_MSG_TYPE_BINDING_RESPONSE_SUCCESS: { return "STUN_MSG_TYPE_BINDING_RESPONSE_SUCCESS"; } }
case STUN_MSG_TYPE_BINDING_RESPONSE_ERROR: { return "STUN_MSG_TYPE_BINDING_RESPONSE_ERROR"; } case STUN_MSG_TYPE_BINDING_REQUEST:{
case STUN_MSG_TYPE_BINDING_INDICATION: { return "STUN_MSG_TYPE_BINDING_INDICATION"; } return "STUN_MSG_TYPE_BINDING_REQUEST";
default: { return "UNKNOWN"; } }
case STUN_MSG_TYPE_BINDING_RESPONSE_SUCCESS:{
return "STUN_MSG_TYPE_BINDING_RESPONSE_SUCCESS";
}
case STUN_MSG_TYPE_BINDING_RESPONSE_ERROR:{
return "STUN_MSG_TYPE_BINDING_RESPONSE_ERROR";
}
case STUN_MSG_TYPE_BINDING_INDICATION:{
return "STUN_MSG_TYPE_BINDING_INDICATION";
}
default:{
return "UNKNOWN";
}
} }
} }
std::string stun_attribute_type_to_string(uint16_t type){ std::string stun_attribute_type_to_string(uint16_t type){
switch (type){ switch (type){
case STUN_ATTR_TYPE_NONE: { return "STUN_ATTR_TYPE_NONE"; } case STUN_ATTR_TYPE_NONE:{
case STUN_ATTR_TYPE_MAPPED_ADDR: { return "STUN_ATTR_TYPE_MAPPED_ADDR"; } return "STUN_ATTR_TYPE_NONE";
case STUN_ATTR_TYPE_CHANGE_REQ: { return "STUN_ATTR_TYPE_CHANGE_REQ"; } }
case STUN_ATTR_TYPE_USERNAME: { return "STUN_ATTR_TYPE_USERNAME"; } case STUN_ATTR_TYPE_MAPPED_ADDR:{
case STUN_ATTR_TYPE_MESSAGE_INTEGRITY: { return "STUN_ATTR_TYPE_MESSAGE_INTEGRITY"; } return "STUN_ATTR_TYPE_MAPPED_ADDR";
case STUN_ATTR_TYPE_ERR_CODE: { return "STUN_ATTR_TYPE_ERR_CODE"; } }
case STUN_ATTR_TYPE_UNKNOWN_ATTRIBUTES: { return "STUN_ATTR_TYPE_UNKNOWN_ATTRIBUTES"; } case STUN_ATTR_TYPE_CHANGE_REQ:{
case STUN_ATTR_TYPE_CHANNEL_NUMBER: { return "STUN_ATTR_TYPE_CHANNEL_NUMBER"; } return "STUN_ATTR_TYPE_CHANGE_REQ";
case STUN_ATTR_TYPE_LIFETIME: { return "STUN_ATTR_TYPE_LIFETIME"; } }
case STUN_ATTR_TYPE_XOR_PEER_ADDR: { return "STUN_ATTR_TYPE_XOR_PEER_ADDR"; } case STUN_ATTR_TYPE_USERNAME:{
case STUN_ATTR_TYPE_DATA: { return "STUN_ATTR_TYPE_DATA"; } return "STUN_ATTR_TYPE_USERNAME";
case STUN_ATTR_TYPE_REALM: { return "STUN_ATTR_TYPE_REALM"; } }
case STUN_ATTR_TYPE_NONCE: { return "STUN_ATTR_TYPE_NONCE"; } case STUN_ATTR_TYPE_MESSAGE_INTEGRITY:{
case STUN_ATTR_TYPE_XOR_RELAY_ADDRESS: { return "STUN_ATTR_TYPE_XOR_RELAY_ADDRESS"; } return "STUN_ATTR_TYPE_MESSAGE_INTEGRITY";
case STUN_ATTR_TYPE_REQ_ADDRESS_FAMILY: { return "STUN_ATTR_TYPE_REQ_ADDRESS_FAMILY"; } }
case STUN_ATTR_TYPE_EVEN_PORT: { return "STUN_ATTR_TYPE_EVEN_PORT"; } case STUN_ATTR_TYPE_ERR_CODE:{
case STUN_ATTR_TYPE_REQUESTED_TRANSPORT: { return "STUN_ATTR_TYPE_REQUESTED_TRANSPORT"; } return "STUN_ATTR_TYPE_ERR_CODE";
case STUN_ATTR_TYPE_DONT_FRAGMENT: { return "STUN_ATTR_TYPE_DONT_FRAGMENT"; } }
case STUN_ATTR_TYPE_XOR_MAPPED_ADDRESS: { return "STUN_ATTR_TYPE_XOR_MAPPED_ADDRESS"; } case STUN_ATTR_TYPE_UNKNOWN_ATTRIBUTES:{
case STUN_ATTR_TYPE_RESERVATION_TOKEN: { return "STUN_ATTR_TYPE_RESERVATION_TOKEN"; } return "STUN_ATTR_TYPE_UNKNOWN_ATTRIBUTES";
case STUN_ATTR_TYPE_PRIORITY: { return "STUN_ATTR_TYPE_PRIORITY"; } }
case STUN_ATTR_TYPE_USE_CANDIDATE: { return "STUN_ATTR_TYPE_USE_CANDIDATE"; } case STUN_ATTR_TYPE_CHANNEL_NUMBER:{
case STUN_ATTR_TYPE_PADDING: { return "STUN_ATTR_TYPE_PADDING"; } return "STUN_ATTR_TYPE_CHANNEL_NUMBER";
case STUN_ATTR_TYPE_RESPONSE_PORT: { return "STUN_ATTR_TYPE_RESPONSE_PORT"; } }
case STUN_ATTR_TYPE_SOFTWARE: { return "STUN_ATTR_TYPE_SOFTWARE"; } case STUN_ATTR_TYPE_LIFETIME:{
case STUN_ATTR_TYPE_ALTERNATE_SERVER: { return "STUN_ATTR_TYPE_ALTERNATE_SERVER"; } return "STUN_ATTR_TYPE_LIFETIME";
case STUN_ATTR_TYPE_FINGERPRINT: { return "STUN_ATTR_TYPE_FINGERPRINT"; } }
case STUN_ATTR_TYPE_ICE_CONTROLLED: { return "STUN_ATTR_TYPE_ICE_CONTROLLED"; } case STUN_ATTR_TYPE_XOR_PEER_ADDR:{
case STUN_ATTR_TYPE_ICE_CONTROLLING: { return "STUN_ATTR_TYPE_ICE_CONTROLLING"; } return "STUN_ATTR_TYPE_XOR_PEER_ADDR";
case STUN_ATTR_TYPE_RESPONSE_ORIGIN: { return "STUN_ATTR_TYPE_RESPONSE_ORIGIN"; } }
case STUN_ATTR_TYPE_OTHER_ADDRESS: { return "STUN_ATTR_TYPE_OTHER_ADDRESS"; } case STUN_ATTR_TYPE_DATA:{
default: { return "UNKNOWN"; } return "STUN_ATTR_TYPE_DATA";
}
case STUN_ATTR_TYPE_REALM:{
return "STUN_ATTR_TYPE_REALM";
}
case STUN_ATTR_TYPE_NONCE:{
return "STUN_ATTR_TYPE_NONCE";
}
case STUN_ATTR_TYPE_XOR_RELAY_ADDRESS:{
return "STUN_ATTR_TYPE_XOR_RELAY_ADDRESS";
}
case STUN_ATTR_TYPE_REQ_ADDRESS_FAMILY:{
return "STUN_ATTR_TYPE_REQ_ADDRESS_FAMILY";
}
case STUN_ATTR_TYPE_EVEN_PORT:{
return "STUN_ATTR_TYPE_EVEN_PORT";
}
case STUN_ATTR_TYPE_REQUESTED_TRANSPORT:{
return "STUN_ATTR_TYPE_REQUESTED_TRANSPORT";
}
case STUN_ATTR_TYPE_DONT_FRAGMENT:{
return "STUN_ATTR_TYPE_DONT_FRAGMENT";
}
case STUN_ATTR_TYPE_XOR_MAPPED_ADDRESS:{
return "STUN_ATTR_TYPE_XOR_MAPPED_ADDRESS";
}
case STUN_ATTR_TYPE_RESERVATION_TOKEN:{
return "STUN_ATTR_TYPE_RESERVATION_TOKEN";
}
case STUN_ATTR_TYPE_PRIORITY:{
return "STUN_ATTR_TYPE_PRIORITY";
}
case STUN_ATTR_TYPE_USE_CANDIDATE:{
return "STUN_ATTR_TYPE_USE_CANDIDATE";
}
case STUN_ATTR_TYPE_PADDING:{
return "STUN_ATTR_TYPE_PADDING";
}
case STUN_ATTR_TYPE_RESPONSE_PORT:{
return "STUN_ATTR_TYPE_RESPONSE_PORT";
}
case STUN_ATTR_TYPE_SOFTWARE:{
return "STUN_ATTR_TYPE_SOFTWARE";
}
case STUN_ATTR_TYPE_ALTERNATE_SERVER:{
return "STUN_ATTR_TYPE_ALTERNATE_SERVER";
}
case STUN_ATTR_TYPE_FINGERPRINT:{
return "STUN_ATTR_TYPE_FINGERPRINT";
}
case STUN_ATTR_TYPE_ICE_CONTROLLED:{
return "STUN_ATTR_TYPE_ICE_CONTROLLED";
}
case STUN_ATTR_TYPE_ICE_CONTROLLING:{
return "STUN_ATTR_TYPE_ICE_CONTROLLING";
}
case STUN_ATTR_TYPE_RESPONSE_ORIGIN:{
return "STUN_ATTR_TYPE_RESPONSE_ORIGIN";
}
case STUN_ATTR_TYPE_OTHER_ADDRESS:{
return "STUN_ATTR_TYPE_OTHER_ADDRESS";
}
default:{
return "UNKNOWN";
}
} }
} }
@ -99,15 +181,12 @@ static uint32_t poly_crc32(uint32_t inCrc, const uint8_t* data, size_t nbytes)
0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
};
uint32_t crc32 = inCrc ^ 0xFFFFFFFF; uint32_t crc32 = inCrc ^ 0xFFFFFFFF;
size_t i; size_t i;
for (i = 0; i < nbytes; i++) { for (i = 0; i < nbytes; i++){crc32 = (crc32 >> 8) ^ crc_table[(crc32 ^ data[i]) & 0xFF];}
crc32 = (crc32 >> 8) ^ crc_table[ (crc32 ^ data[i]) & 0xFF ];
}
return (crc32 ^ 0xFFFFFFFF); return (crc32 ^ 0xFFFFFFFF);
} }
@ -154,7 +233,8 @@ int stun_compute_hmac_sha1(uint8_t* message, uint32_t nbytes, std::string key, u
goto error; goto error;
} }
DONTEVEN_MSG("Calculating hmac-sha1 with key `%s` with size %zu over %zu bytes of data.", key.c_str(), key.size(), nbytes); DONTEVEN_MSG("Calculating hmac-sha1 with key `%s` with size %zu over %zu bytes of data.",
key.c_str(), key.size(), nbytes);
r = mbedtls_md_hmac_starts(&md_ctx, (const unsigned char *)key.c_str(), key.size()); r = mbedtls_md_hmac_starts(&md_ctx, (const unsigned char *)key.c_str(), key.size());
if (r != 0){ if (r != 0){
@ -243,13 +323,9 @@ int stun_compute_message_integrity(std::vector<uint8_t>& buffer, std::string key
dx += len; dx += len;
/* skip padding. */ /* skip padding. */
while ( (dx & 0x03) != 0 && dx < buffer.size()) { while ((dx & 0x03) != 0 && dx < buffer.size()){dx++;}
dx++;
}
if (type == STUN_ATTR_TYPE_MESSAGE_INTEGRITY) { if (type == STUN_ATTR_TYPE_MESSAGE_INTEGRITY){break;}
break;
}
type = 0; type = 0;
len = 0; len = 0;
@ -310,13 +386,9 @@ int stun_compute_fingerprint(std::vector<uint8_t>& buffer, uint32_t& result) {
dx += len; dx += len;
/* skip padding. */ /* skip padding. */
while ( (dx & 0x03) != 0 && dx < buffer.size()) { while ((dx & 0x03) != 0 && dx < buffer.size()){dx++;}
dx++;
}
if (type == STUN_ATTR_TYPE_FINGERPRINT) { if (type == STUN_ATTR_TYPE_FINGERPRINT){break;}
break;
}
type = 0; type = 0;
len = 0; len = 0;
@ -327,7 +399,6 @@ int stun_compute_fingerprint(std::vector<uint8_t>& buffer, uint32_t& result) {
buffer[2] = (offset >> 8) & 0xFF; buffer[2] = (offset >> 8) & 0xFF;
buffer[3] = offset & 0xFF; buffer[3] = offset & 0xFF;
// result = (checksum::crc32LE(0 ^ 0xFFFFFFFF, (const char*)&buffer[0], offset + 12) ^ 0xFFFFFFFF) ^ 0x5354554e; // result = (checksum::crc32LE(0 ^ 0xFFFFFFFF, (const char*)&buffer[0], offset + 12) ^ 0xFFFFFFFF) ^ 0x5354554e;
result = poly_crc32(0L, &buffer[0], offset + 12) ^ 0x5354554e; result = poly_crc32(0L, &buffer[0], offset + 12) ^ 0x5354554e;
@ -340,11 +411,7 @@ int stun_compute_fingerprint(std::vector<uint8_t>& buffer, uint32_t& result) {
/* --------------------------------------- */ /* --------------------------------------- */
StunAttribute::StunAttribute() StunAttribute::StunAttribute() : type(STUN_ATTR_TYPE_NONE), length(0){}
:type(STUN_ATTR_TYPE_NONE)
,length(0)
{
}
void StunAttribute::print(){ void StunAttribute::print(){
@ -354,7 +421,8 @@ void StunAttribute::print() {
switch (type){ switch (type){
case STUN_ATTR_TYPE_XOR_MAPPED_ADDRESS:{ case STUN_ATTR_TYPE_XOR_MAPPED_ADDRESS:{
DONTEVEN_MSG("StunAttribute.xor_address.family: %s", stun_family_type_to_string(xor_address.family).c_str()); DONTEVEN_MSG("StunAttribute.xor_address.family: %s",
stun_family_type_to_string(xor_address.family).c_str());
DONTEVEN_MSG("StunAttribute.xor_address.port: %u", xor_address.port); DONTEVEN_MSG("StunAttribute.xor_address.port: %u", xor_address.port);
DONTEVEN_MSG("StunAttribute.xor_address.ip: %s", (char *)xor_address.ip); DONTEVEN_MSG("StunAttribute.xor_address.ip: %s", (char *)xor_address.ip);
break; break;
@ -372,7 +440,8 @@ void StunAttribute::print() {
case STUN_ATTR_TYPE_ICE_CONTROLLING:{ case STUN_ATTR_TYPE_ICE_CONTROLLING:{
uint8_t *p = (uint8_t *)&ice_controlling.tie_breaker; uint8_t *p = (uint8_t *)&ice_controlling.tie_breaker;
DONTEVEN_MSG("StunAttribute.ice_controlling.tie_breaker: 0x%04x%04x", *(uint32_t*)(p + 4), *(uint32_t*)(p)); DONTEVEN_MSG("StunAttribute.ice_controlling.tie_breaker: 0x%04x%04x", *(uint32_t *)(p + 4),
*(uint32_t *)(p));
break; break;
} }
@ -383,9 +452,7 @@ void StunAttribute::print() {
case STUN_ATTR_TYPE_MESSAGE_INTEGRITY:{ case STUN_ATTR_TYPE_MESSAGE_INTEGRITY:{
std::stringstream ss; std::stringstream ss;
for(int i = 0; i < 20; ++i) { for (int i = 0; i < 20; ++i){ss << std::hex << (int)message_integrity.sha1[i];}
ss << std::hex << (int) message_integrity.sha1[i];
}
std::string str = ss.str(); std::string str = ss.str();
DONTEVEN_MSG("StunAttribute.message_integrity.sha1: %s", str.c_str()); DONTEVEN_MSG("StunAttribute.message_integrity.sha1: %s", str.c_str());
break; break;
@ -400,11 +467,7 @@ void StunAttribute::print() {
/* --------------------------------------- */ /* --------------------------------------- */
StunMessage::StunMessage() StunMessage::StunMessage() : type(STUN_MSG_TYPE_NONE), length(0), cookie(0x2112a442){
:type(STUN_MSG_TYPE_NONE)
,length(0)
,cookie(0x2112a442)
{
transaction_id[0] = 0; transaction_id[0] = 0;
transaction_id[1] = 0; transaction_id[1] = 0;
transaction_id[2] = 0; transaction_id[2] = 0;
@ -432,25 +495,19 @@ void StunMessage::print() {
DONTEVEN_MSG("StunMessage.type: %s", stun_message_type_to_string(type).c_str()); DONTEVEN_MSG("StunMessage.type: %s", stun_message_type_to_string(type).c_str());
DONTEVEN_MSG("StunMessage.length: %u", length); DONTEVEN_MSG("StunMessage.length: %u", length);
DONTEVEN_MSG("StunMessage.cookie: 0x%08X", cookie); DONTEVEN_MSG("StunMessage.cookie: 0x%08X", cookie);
DONTEVEN_MSG("StunMessage.transaction_id: 0x%08X, 0x%08X, 0x%08X", transaction_id[0], transaction_id[1], transaction_id[2]); DONTEVEN_MSG("StunMessage.transaction_id: 0x%08X, 0x%08X, 0x%08X", transaction_id[0],
transaction_id[1], transaction_id[2]);
} }
StunAttribute *StunMessage::getAttributeByType(uint16_t type){ StunAttribute *StunMessage::getAttributeByType(uint16_t type){
size_t nattribs = attributes.size(); size_t nattribs = attributes.size();
for (size_t i = 0; i < nattribs; ++i){ for (size_t i = 0; i < nattribs; ++i){
if (attributes[i].type == type) { if (attributes[i].type == type){return &attributes[i];}
return &attributes[i];
}
} }
return NULL; return NULL;
} }
/* --------------------------------------- */ /* --------------------------------------- */
StunReader::StunReader() StunReader::StunReader() : buffer_data(NULL), buffer_size(0), read_dx(0){}
:buffer_data(NULL)
,buffer_size(0)
,read_dx(0)
{
}
int StunReader::parse(uint8_t *data, size_t nbytes, size_t &nparsed, StunMessage &msg){ int StunReader::parse(uint8_t *data, size_t nbytes, size_t &nparsed, StunMessage &msg){
@ -551,16 +608,15 @@ int StunReader::parse(uint8_t* data, size_t nbytes, size_t& nparsed, StunMessage
} }
default:{ default:{
DONTEVEN_MSG("Unhandled stun attribute: 0x%04X, %s", attr.type, stun_attribute_type_to_string(attr.type).c_str()); DONTEVEN_MSG("Unhandled stun attribute: 0x%04X, %s", attr.type,
stun_attribute_type_to_string(attr.type).c_str());
break; break;
} }
} }
/* Move the read_dx so it's positioned after the currently parsed attribute */ /* Move the read_dx so it's positioned after the currently parsed attribute */
read_dx = attr_offset + attr.length; read_dx = attr_offset + attr.length;
while ( (read_dx & 0x03) != 0 && (read_dx < buffer_size)) { while ((read_dx & 0x03) != 0 && (read_dx < buffer_size)){read_dx++;}
read_dx++;
}
msg.attributes.push_back(attr); msg.attributes.push_back(attr);
@ -681,12 +737,7 @@ int StunReader::parseXorMappedAddress(StunAttribute& attr) {
ip_ptr[2] = ip_ptr[2] ^ cookie[2]; ip_ptr[2] = ip_ptr[2] ^ cookie[2];
ip_ptr[3] = ip_ptr[3] ^ cookie[3]; ip_ptr[3] = ip_ptr[3] ^ cookie[3];
sprintf((char*)attr.xor_address.ip, sprintf((char *)attr.xor_address.ip, "%u.%u.%u.%u", ip_ptr[3], ip_ptr[2], ip_ptr[1], ip_ptr[0]);
"%u.%u.%u.%u",
ip_ptr[3],
ip_ptr[2],
ip_ptr[1],
ip_ptr[0]);
return 0; return 0;
} }
@ -767,10 +818,7 @@ uint64_t StunReader::readU64() {
/* --------------------------------------- */ /* --------------------------------------- */
StunWriter::StunWriter() StunWriter::StunWriter() : padding_byte(0){}
:padding_byte(0)
{
}
int StunWriter::begin(StunMessage &msg, uint8_t paddingByte){ int StunWriter::begin(StunMessage &msg, uint8_t paddingByte){
@ -819,7 +867,8 @@ int StunWriter::writeXorMappedAddress(uint8_t family, uint16_t port, const std::
uint32_t ip_int = 0; uint32_t ip_int = 0;
if (0 != convertIp4StringToInt(ip, ip_int)){ if (0 != convertIp4StringToInt(ip, ip_int)){
FAIL_MSG("Cannot write xor-mapped-address, because we failed to convert the given IP4 string into a uint32_t."); FAIL_MSG("Cannot write xor-mapped-address, because we failed to convert the given IP4 string "
"into a uint32_t.");
return -1; return -1;
} }
@ -870,7 +919,8 @@ int StunWriter::writeXorMappedAddress(uint8_t family, uint16_t port, uint32_t ip
int StunWriter::writeUsername(const std::string &username){ int StunWriter::writeUsername(const std::string &username){
if (buffer.size() < 20){ if (buffer.size() < 20){
FAIL_MSG("Cannot write username because you didn't call `begin()` and the STUN header hasn't been written yet.."); FAIL_MSG("Cannot write username because you didn't call `begin()` and the STUN header hasn't "
"been written yet..");
return -1; return -1;
} }
@ -885,7 +935,8 @@ int StunWriter::writeUsername(const std::string& username) {
int StunWriter::writeSoftware(const std::string &software){ int StunWriter::writeSoftware(const std::string &software){
if (buffer.size() < 20){ if (buffer.size() < 20){
FAIL_MSG("Cannot write software because it seems that you didn't call `begin()` which writes the stun header."); FAIL_MSG("Cannot write software because it seems that you didn't call `begin()` which writes "
"the stun header.");
return -1; return -1;
} }
@ -905,7 +956,8 @@ int StunWriter::writeSoftware(const std::string& software) {
int StunWriter::writeMessageIntegrity(const std::string &password){ int StunWriter::writeMessageIntegrity(const std::string &password){
if (buffer.size() < 20){ if (buffer.size() < 20){
FAIL_MSG("Cannot write the message integrity because it seems that you didn't call `begin()` which writes the stun header."); FAIL_MSG("Cannot write the message integrity because it seems that you didn't call `begin()` "
"which writes the stun header.");
return -1; return -1;
} }
@ -936,7 +988,8 @@ int StunWriter::writeMessageIntegrity(const std::string& password) {
int StunWriter::writeFingerprint(){ int StunWriter::writeFingerprint(){
if (buffer.size() < 20){ if (buffer.size() < 20){
FAIL_MSG("Cannot write the fingerprint because it seems that you didn't write the header, call `begin()` first."); FAIL_MSG("Cannot write the fingerprint because it seems that you didn't write the header, call "
"`begin()` first.");
return -1; return -1;
} }
@ -1026,7 +1079,8 @@ void StunWriter::rewriteU16(size_t dx, uint16_t v) {
void StunWriter::rewriteU32(size_t dx, uint32_t v){ void StunWriter::rewriteU32(size_t dx, uint32_t v){
if ((dx + 4) > buffer.size()){ if ((dx + 4) > buffer.size()){
FAIL_MSG("Trying to rewrite U32 in Stun::StunWriter::rewriteU32() but index is out of bounds.\n"); FAIL_MSG(
"Trying to rewrite U32 in Stun::StunWriter::rewriteU32() but index is out of bounds.\n");
return; return;
} }
@ -1043,9 +1097,7 @@ void StunWriter::writeString(const std::string& str) {
void StunWriter::writePadding(){ void StunWriter::writePadding(){
while ((buffer.size() & 0x03) != 0) { while ((buffer.size() & 0x03) != 0){buffer.push_back(padding_byte);}
buffer.push_back(padding_byte);
}
} }
/* --------------------------------------- */ /* --------------------------------------- */

View file

@ -1,8 +1,8 @@
#pragma once #pragma once
#include <stdint.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <vector> #include <stdint.h>
#include <string> #include <string>
#include <vector>
/* --------------------------------------- */ /* --------------------------------------- */
@ -200,7 +200,10 @@ public:
StunWriter(); StunWriter();
/* write header and finalize. call for each stun message */ /* write header and finalize. call for each stun message */
int begin(StunMessage& msg, uint8_t paddingByte = 0x00); /* I've added the padding byte here so that we can use the examples that can be found here https://tools.ietf.org/html/rfc5769#section-2.2 as they use 0x20 or 0x00 as the padding byte which is correct as you are free to use w/e padding byte you want. */ int begin(StunMessage &msg,
uint8_t paddingByte = 0x00); /* I've added the padding byte here so that we can use the
examples that can be found here https://tools.ietf.org/html/rfc5769#section-2.2
as they use 0x20 or 0x00 as the padding byte which is correct as you are free to use w/e padding byte you want. */
int end(); int end();
/* write attributes */ /* write attributes */
@ -236,9 +239,7 @@ private:
inline uint8_t *StunWriter::getBufferPtr(){ inline uint8_t *StunWriter::getBufferPtr(){
if (0 == buffer.size()) { if (0 == buffer.size()){return NULL;}
return NULL;
}
return &buffer[0]; return &buffer[0];
} }

View file

@ -1,5 +1,5 @@
#include "subtitles.h"
#include "bitfields.h" #include "bitfields.h"
#include "subtitles.h"
#include "defines.h" #include "defines.h"
namespace Subtitle{ namespace Subtitle{
@ -21,7 +21,6 @@ namespace Subtitle {
}else{ }else{
// get parts from meta // get parts from meta
// calculate duration // calculate duration
} }
packet.getString("data", output.subtitle); packet.getString("data", output.subtitle);
@ -33,6 +32,4 @@ namespace Subtitle {
return output; return output;
} }
}// namespace Subtitle
}

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <string>
#include "dtsc.h" #include "dtsc.h"
#include <string>
namespace Subtitle{ namespace Subtitle{
@ -11,5 +11,4 @@ namespace Subtitle {
Packet getSubtitle(DTSC::Packet packet, DTSC::Meta meta); Packet getSubtitle(DTSC::Packet packet, DTSC::Meta meta);
} }// namespace Subtitle

View file

@ -1,9 +1,9 @@
#include "defines.h"
#include "theora.h" #include "theora.h"
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sstream> #include <sstream>
#include "defines.h" #include <stdlib.h>
#include <string.h>
namespace theora{ namespace theora{
bool header::checkDataSize(unsigned int size){ bool header::checkDataSize(unsigned int size){
@ -36,9 +36,7 @@ namespace theora {
} }
uint16_t header::getInt16(size_t index){ uint16_t header::getInt16(size_t index){
if (datasize >= (index + 1)){ if (datasize >= (index + 1)){return 0 + (data[index] << 8) + data[index + 1];}
return 0 + (data[index] << 8) + data[index + 1];
}
return 0; return 0;
} }
@ -54,197 +52,138 @@ namespace theora {
datasize = length; datasize = length;
} }
header::~header(){ header::~header(){}
}
bool isHeader(const char *newData, unsigned int length){ bool isHeader(const char *newData, unsigned int length){
if (length < 7){ if (length < 7){return false;}
return false;
}
if (!(newData[0] & 0x80)){ if (!(newData[0] & 0x80)){
FAIL_MSG("newdata != 0x80: %.2X", newData[0]); FAIL_MSG("newdata != 0x80: %.2X", newData[0]);
return false; return false;
} }
if (memcmp(newData + 1, "theora", 6) != 0){ if (memcmp(newData + 1, "theora", 6) != 0){return false;}
return false;
}
return true; return true;
} }
int header::getHeaderType(){ int header::getHeaderType(){return (data[0] & 0x7F);}
return (data[0] & 0x7F);
}
char header::getVMAJ(){ char header::getVMAJ(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return data[7];}
return data[7];
}
return 0; return 0;
} }
char header::getVMIN(){ char header::getVMIN(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return data[8];}
return data[8];
}
return 0; return 0;
} }
char header::getVREV(){ char header::getVREV(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return data[9];}
return data[9];
}
return 0; return 0;
} }
short header::getFMBW(){ short header::getFMBW(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return getInt16(10);}
return getInt16(10);
}
return 0; return 0;
} }
short header::getFMBH(){ short header::getFMBH(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return getInt16(12);}
return getInt16(12);
}
return 0; return 0;
} }
char header::getPICX(){ char header::getPICX(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return data[20];}
return data[20];
}
return 0; return 0;
} }
char header::getPICY(){ char header::getPICY(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return data[21];}
return data[21];
}
return 0; return 0;
} }
char header::getKFGShift(){ char header::getKFGShift(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return (getInt16(40) >> 5) & 0x1F;}
return (getInt16(40) >> 5) & 0x1F;
}
return 0; return 0;
} }
long unsigned int header::getFRN(){ long unsigned int header::getFRN(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return getInt32(22);}
return getInt32(22);
}
return 0; return 0;
} }
long unsigned int header::getPICH(){ long unsigned int header::getPICH(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return getInt24(17);}
return getInt24(17);
}
return 0; return 0;
} }
long unsigned int header::getPICW(){ long unsigned int header::getPICW(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return getInt24(14);}
return getInt24(14);
}
return 0; return 0;
} }
long unsigned int header::getFRD(){ long unsigned int header::getFRD(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return getInt32(26);}
return getInt32(26);
}
return 0; return 0;
} }
long unsigned int header::getPARN(){ long unsigned int header::getPARN(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return getInt24(30);}
return getInt24(30);
}
return 0; return 0;
} }
long unsigned int header::getPARD(){ long unsigned int header::getPARD(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return getInt24(33);}
return getInt24(33);
}
return 0; return 0;
} }
char header::getCS(){ char header::getCS(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return data[36];}
return data[36];
}
return 0; return 0;
} }
long unsigned int header::getNOMBR(){ long unsigned int header::getNOMBR(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return getInt24(37);}
return getInt24(37);
}
return 0; return 0;
} }
char header::getQUAL(){ char header::getQUAL(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return (data[40] >> 3) & 0x1F;}
return (data[40] >> 3) & 0x1F;
}
return 0; return 0;
} }
char header::getPF(){ char header::getPF(){
if (getHeaderType() == 0){ if (getHeaderType() == 0){return (data[41] >> 3) & 0x03;}
return (data[41] >> 3) & 0x03;
}
return 0; return 0;
} }
std::string header::getVendor(){ std::string header::getVendor(){
if (getHeaderType() != 1){ if (getHeaderType() != 1){return "";}
return "";
}
return std::string(data + 11, commentLen(7)); return std::string(data + 11, commentLen(7));
} }
long unsigned int header::getNComments(){ long unsigned int header::getNComments(){
if (getHeaderType() != 1){ if (getHeaderType() != 1){return 0;}
return 0;
}
int offset = 11 + commentLen(7); int offset = 11 + commentLen(7);
return commentLen(offset); return commentLen(offset);
} }
char header::getLFLIMS(size_t index){ char header::getLFLIMS(size_t index){
if (getHeaderType() != 2){ if (getHeaderType() != 2){return 0;}
return 0; if (index >= 64){return 0;}
}
if (index >= 64){
return 0;
}
char NBITS = (data[0] >> 5) & 0x07; char NBITS = (data[0] >> 5) & 0x07;
return NBITS; return NBITS;
} }
std::string header::getUserComment(size_t index){ std::string header::getUserComment(size_t index){
if (index >= getNComments()){ if (index >= getNComments()){return "";}
return "";
}
int offset = 11 + commentLen(7) + 4; int offset = 11 + commentLen(7) + 4;
for (size_t i = 0; i < index; i++){ for (size_t i = 0; i < index; i++){offset += 4 + commentLen(offset);}
offset += 4 + commentLen(offset);
}
return std::string(data + offset + 4, commentLen(offset)); return std::string(data + offset + 4, commentLen(offset));
} }
char header::getFTYPE(){ char header::getFTYPE(){return (data[0] >> 6) & 0x01;}
return (data[0] >> 6) & 0x01;
}
bool header::isHeader(){ bool header::isHeader(){return ::theora::isHeader(data, datasize);}
return ::theora::isHeader(data, datasize);
}
std::string header::toPrettyString(size_t indent){ std::string header::toPrettyString(size_t indent){
std::stringstream result; std::stringstream result;
@ -282,8 +221,7 @@ namespace theora {
result << std::string(indent + 4, ' ') << "[" << i << "] " << getUserComment(i) << std::endl; result << std::string(indent + 4, ' ') << "[" << i << "] " << getUserComment(i) << std::endl;
} }
break; break;
case 2: case 2: result << std::string(indent + 2, ' ') << "NBITS: " << (int)getLFLIMS(0) << std::endl;
result << std::string(indent + 2, ' ') << "NBITS: " << (int)getLFLIMS(0) << std::endl;
} }
return result.str(); return result.str();
} }
@ -357,9 +295,4 @@ namespace theora {
result << std::string(indent + 2, ' ') << "FType: " << (int)getFTYPE() << std::endl; result << std::string(indent + 2, ' ') << "FType: " << (int)getFTYPE() << std::endl;
return result.str(); return result.str();
}*/ }*/
} }// namespace theora

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include<sys/types.h>
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <sys/types.h>
namespace theora{ namespace theora{
@ -45,6 +45,7 @@ namespace theora {
uint32_t getInt24(size_t index); uint32_t getInt24(size_t index);
uint16_t getInt16(size_t index); uint16_t getInt16(size_t index);
uint32_t commentLen(size_t index); uint32_t commentLen(size_t index);
private: private:
char *data; char *data;
bool checkDataSize(unsigned int size); bool checkDataSize(unsigned int size);
@ -64,5 +65,4 @@ namespace theora {
unsigned int datasize; unsigned int datasize;
bool checkDataSize(unsigned int size); bool checkDataSize(unsigned int size);
};*/ };*/
} }// namespace theora

View file

@ -2,10 +2,10 @@
/// Utilities for handling time and timestamps. /// Utilities for handling time and timestamps.
#include "timing.h" #include "timing.h"
#include <cstdio>
#include <cstring>
#include <sys/time.h> //for gettimeofday #include <sys/time.h> //for gettimeofday
#include <time.h> //for time and nanosleep #include <time.h> //for time and nanosleep
#include <cstring>
#include <cstdio>
// emulate clock_gettime() for OSX compatibility // emulate clock_gettime() for OSX compatibility
#if defined(__APPLE__) || defined(__MACH__) #if defined(__APPLE__) || defined(__MACH__)
@ -30,12 +30,8 @@ void clock_gettime(int ign, struct timespec * ts) {
/// If interrupted by signal, resumes sleep until at least ms milliseconds have passed. /// If interrupted by signal, resumes sleep until at least ms milliseconds have passed.
/// Can be slightly off (in positive direction only) depending on OS accuracy. /// Can be slightly off (in positive direction only) depending on OS accuracy.
void Util::wait(int64_t ms){ void Util::wait(int64_t ms){
if (ms < 0) { if (ms < 0){return;}
return; if (ms > 600000){ms = 600000;}
}
if (ms > 600000) {
ms = 600000;
}
uint64_t start = getMS(); uint64_t start = getMS();
uint64_t now = start; uint64_t now = start;
while (now < start + ms){ while (now < start + ms){
@ -50,12 +46,8 @@ void Util::wait(int64_t ms){
/// Can be interrupted early by a signal, no guarantee of minimum sleep time. /// Can be interrupted early by a signal, no guarantee of minimum sleep time.
/// Can be slightly off depending on OS accuracy. /// Can be slightly off depending on OS accuracy.
void Util::sleep(int64_t ms){ void Util::sleep(int64_t ms){
if (ms < 0) { if (ms < 0){return;}
return; if (ms > 100000){ms = 100000;}
}
if (ms > 100000) {
ms = 100000;
}
struct timespec T; struct timespec T;
T.tv_sec = ms / 1000; T.tv_sec = ms / 1000;
T.tv_nsec = 1000000 * (ms % 1000); T.tv_nsec = 1000000 * (ms % 1000);
@ -118,6 +110,7 @@ std::string Util::getUTCString(uint64_t epoch){
struct tm *ptm; struct tm *ptm;
ptm = gmtime(&rawtime); ptm = gmtime(&rawtime);
char result[20]; char result[20];
snprintf(result, 20, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d", ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec); snprintf(result, 20, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d", ptm->tm_year + 1900, ptm->tm_mon + 1,
ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
return std::string(result); return std::string(result);
} }

View file

@ -4,7 +4,6 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <stdint.h>
namespace Util{ namespace Util{
void wait(int64_t ms); ///< Sleeps for the indicated amount of milliseconds or longer. void wait(int64_t ms); ///< Sleeps for the indicated amount of milliseconds or longer.
@ -18,4 +17,4 @@ namespace Util {
uint64_t getNTP(); uint64_t getNTP();
uint64_t epoch(); ///< Gets the amount of seconds since 01/01/1970. uint64_t epoch(); ///< Gets the amount of seconds since 01/01/1970.
std::string getUTCString(uint64_t epoch = 0); std::string getUTCString(uint64_t epoch = 0);
} }// namespace Util

View file

@ -21,17 +21,16 @@ freely, subject to the following restrictions:
distribution. distribution.
*/ */
#include <exception>
#include "tinythread.h" #include "tinythread.h"
#include <exception>
#if defined(_TTHREAD_POSIX_) #if defined(_TTHREAD_POSIX_)
#include <unistd.h>
#include <map> #include <map>
#include <unistd.h>
#elif defined(_TTHREAD_WIN32_) #elif defined(_TTHREAD_WIN32_)
#include <process.h> #include <process.h>
#endif #endif
namespace tthread{ namespace tthread{
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -78,13 +77,11 @@ namespace tthread {
// Check if we are the last waiter // Check if we are the last waiter
EnterCriticalSection(&mWaitersCountLock); EnterCriticalSection(&mWaitersCountLock);
--mWaitersCount; --mWaitersCount;
bool lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) && bool lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) && (mWaitersCount == 0);
(mWaitersCount == 0);
LeaveCriticalSection(&mWaitersCountLock); LeaveCriticalSection(&mWaitersCountLock);
// If we are the last waiter to be notified to stop waiting, reset the event // If we are the last waiter to be notified to stop waiting, reset the event
if (lastWaiter) if (lastWaiter) ResetEvent(mEvents[_CONDITION_EVENT_ALL]);
ResetEvent(mEvents[_CONDITION_EVENT_ALL]);
} }
#endif #endif
@ -96,8 +93,7 @@ namespace tthread {
LeaveCriticalSection(&mWaitersCountLock); LeaveCriticalSection(&mWaitersCountLock);
// If we have any waiting threads, send them a signal // If we have any waiting threads, send them a signal
if (haveWaiters) if (haveWaiters) SetEvent(mEvents[_CONDITION_EVENT_ONE]);
SetEvent(mEvents[_CONDITION_EVENT_ONE]);
} }
#endif #endif
@ -109,12 +105,10 @@ namespace tthread {
LeaveCriticalSection(&mWaitersCountLock); LeaveCriticalSection(&mWaitersCountLock);
// If we have any waiting threads, send them a signal // If we have any waiting threads, send them a signal
if (haveWaiters) if (haveWaiters) SetEvent(mEvents[_CONDITION_EVENT_ALL]);
SetEvent(mEvents[_CONDITION_EVENT_ALL]);
} }
#endif #endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// POSIX pthread_t to unique thread::id mapping logic. // POSIX pthread_t to unique thread::id mapping logic.
// Note: Here we use a global thread safe std::map to convert instances of // Note: Here we use a global thread safe std::map to convert instances of
@ -129,13 +123,11 @@ namespace tthread {
static unsigned long int idCount(1); static unsigned long int idCount(1);
lock_guard<mutex> guard(idMapLock); lock_guard<mutex> guard(idMapLock);
if (idMap.find(aHandle) == idMap.end()) if (idMap.find(aHandle) == idMap.end()) idMap[aHandle] = idCount++;
idMap[aHandle] = idCount ++;
return thread::id(idMap[aHandle]); return thread::id(idMap[aHandle]);
} }
#endif // _TTHREAD_POSIX_ #endif // _TTHREAD_POSIX_
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// thread // thread
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -200,8 +192,7 @@ namespace tthread {
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
mHandle = (HANDLE)_beginthreadex(0, 0, wrapper_function, (void *)ti, 0, &mWin32ThreadID); mHandle = (HANDLE)_beginthreadex(0, 0, wrapper_function, (void *)ti, 0, &mWin32ThreadID);
#elif defined(_TTHREAD_POSIX_) #elif defined(_TTHREAD_POSIX_)
if (pthread_create(&mHandle, NULL, wrapper_function, (void *) ti) != 0) if (pthread_create(&mHandle, NULL, wrapper_function, (void *)ti) != 0) mHandle = 0;
mHandle = 0;
#endif #endif
// Did we fail to create the thread? // Did we fail to create the thread?
@ -213,11 +204,8 @@ namespace tthread {
} }
thread::~thread(){ thread::~thread(){
if (ti_copy) { if (ti_copy){((_thread_start_info *)ti_copy)->mThread = 0;}
((_thread_start_info *)ti_copy)->mThread = 0; if (joinable()) std::terminate();
}
if (joinable())
std::terminate();
} }
void thread::join(){ void thread::join(){
@ -252,8 +240,7 @@ namespace tthread {
} }
thread::id thread::get_id() const{ thread::id thread::get_id() const{
if (!joinable()) if (!joinable()) return id();
return id();
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
return id((unsigned long int)mWin32ThreadID); return id((unsigned long int)mWin32ThreadID);
#elif defined(_TTHREAD_POSIX_) #elif defined(_TTHREAD_POSIX_)
@ -277,7 +264,6 @@ namespace tthread {
#endif #endif
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// this_thread // this_thread
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -290,4 +276,4 @@ namespace tthread {
#endif #endif
} }
} }// namespace tthread

View file

@ -78,8 +78,8 @@ freely, subject to the following restrictions:
#endif #endif
#else #else
#include <pthread.h> #include <pthread.h>
#include <signal.h>
#include <sched.h> #include <sched.h>
#include <signal.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
@ -143,7 +143,6 @@ freely, subject to the following restrictions:
#endif #endif
#endif #endif
/// Main name space for TinyThread++. /// Main name space for TinyThread++.
/// This namespace is more or less equivalent to the @c std namespace for the /// This namespace is more or less equivalent to the @c std namespace for the
/// C++11 thread classes. For instance, the tthread::mutex class corresponds to /// C++11 thread classes. For instance, the tthread::mutex class corresponds to
@ -329,8 +328,7 @@ namespace tthread {
///} ///}
/// @endcode /// @endcode
template <class T> template <class T> class lock_guard{
class lock_guard {
public: public:
typedef T mutex_type; typedef T mutex_type;
@ -344,8 +342,7 @@ namespace tthread {
/// The destructor unlocks the mutex. /// The destructor unlocks the mutex.
~lock_guard(){ ~lock_guard(){
if (mMutex) if (mMutex) mMutex->unlock();
mMutex->unlock();
} }
private: private:
@ -383,18 +380,14 @@ namespace tthread {
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
condition_variable(); condition_variable();
#else #else
condition_variable() { condition_variable(){pthread_cond_init(&mHandle, NULL);}
pthread_cond_init(&mHandle, NULL);
}
#endif #endif
/// Destructor. /// Destructor.
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
~condition_variable(); ~condition_variable();
#else #else
~condition_variable() { ~condition_variable(){pthread_cond_destroy(&mHandle);}
pthread_cond_destroy(&mHandle);
}
#endif #endif
/// Wait for the condition. /// Wait for the condition.
@ -402,8 +395,7 @@ namespace tthread {
/// is woken by @c notify_one(), @c notify_all() or a spurious wake up. /// is woken by @c notify_one(), @c notify_all() or a spurious wake up.
/// @param[in] aMutex A mutex that will be unlocked when the wait operation /// @param[in] aMutex A mutex that will be unlocked when the wait operation
/// starts, an locked again as soon as the wait operation is finished. /// starts, an locked again as soon as the wait operation is finished.
template <class _mutexT> template <class _mutexT> inline void wait(_mutexT &aMutex){
inline void wait(_mutexT & aMutex) {
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
// Increment number of waiters // Increment number of waiters
EnterCriticalSection(&mWaitersCountLock); EnterCriticalSection(&mWaitersCountLock);
@ -428,9 +420,7 @@ namespace tthread {
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
void notify_one(); void notify_one();
#else #else
inline void notify_one() { inline void notify_one(){pthread_cond_signal(&mHandle);}
pthread_cond_signal(&mHandle);
}
#endif #endif
/// Notify all threads that are waiting for the condition. /// Notify all threads that are waiting for the condition.
@ -441,9 +431,7 @@ namespace tthread {
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
void notify_all(); void notify_all();
#else #else
inline void notify_all() { inline void notify_all(){pthread_cond_broadcast(&mHandle);}
pthread_cond_broadcast(&mHandle);
}
#endif #endif
_TTHREAD_DISABLE_ASSIGNMENT(condition_variable) _TTHREAD_DISABLE_ASSIGNMENT(condition_variable)
@ -459,7 +447,6 @@ namespace tthread {
#endif #endif
}; };
/// Thread class. /// Thread class.
class thread{ class thread{
public: public:
@ -474,11 +461,14 @@ namespace tthread {
/// Default constructor. /// Default constructor.
/// Construct a @c thread object without an associated thread of execution /// Construct a @c thread object without an associated thread of execution
/// (i.e. non-joinable). /// (i.e. non-joinable).
thread() : mHandle(0), mNotAThread(true) thread()
: mHandle(0), mNotAThread(true)
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
, mWin32ThreadID(0) ,
mWin32ThreadID(0)
#endif #endif
{} {
}
/// Thread starting constructor. /// Thread starting constructor.
/// Construct a @c thread object with a new thread of execution. /// Construct a @c thread object with a new thread of execution.
@ -519,9 +509,7 @@ namespace tthread {
/// Get the native handle for this thread. /// Get the native handle for this thread.
/// @note Under Windows, this is a @c HANDLE, and under POSIX systems, this /// @note Under Windows, this is a @c HANDLE, and under POSIX systems, this
/// is a @c pthread_t. /// is a @c pthread_t.
inline native_handle_type native_handle() { inline native_handle_type native_handle(){return mHandle;}
return mHandle;
}
/// Determine the number of threads which can possibly execute concurrently. /// Determine the number of threads which can possibly execute concurrently.
/// This function is useful for determining the optimal number of threads to /// This function is useful for determining the optimal number of threads to
@ -568,29 +556,17 @@ namespace tthread {
return *this; return *this;
} }
inline friend bool operator==(const id & aId1, const id & aId2) { inline friend bool operator==(const id &aId1, const id &aId2){return (aId1.mId == aId2.mId);}
return (aId1.mId == aId2.mId);
}
inline friend bool operator!=(const id & aId1, const id & aId2) { inline friend bool operator!=(const id &aId1, const id &aId2){return (aId1.mId != aId2.mId);}
return (aId1.mId != aId2.mId);
}
inline friend bool operator<=(const id & aId1, const id & aId2) { inline friend bool operator<=(const id &aId1, const id &aId2){return (aId1.mId <= aId2.mId);}
return (aId1.mId <= aId2.mId);
}
inline friend bool operator<(const id & aId1, const id & aId2) { inline friend bool operator<(const id &aId1, const id &aId2){return (aId1.mId < aId2.mId);}
return (aId1.mId < aId2.mId);
}
inline friend bool operator>=(const id & aId1, const id & aId2) { inline friend bool operator>=(const id &aId1, const id &aId2){return (aId1.mId >= aId2.mId);}
return (aId1.mId >= aId2.mId);
}
inline friend bool operator>(const id & aId1, const id & aId2) { inline friend bool operator>(const id &aId1, const id &aId2){return (aId1.mId > aId2.mId);}
return (aId1.mId > aId2.mId);
}
inline friend std::ostream &operator<<(std::ostream &os, const id &obj){ inline friend std::ostream &operator<<(std::ostream &os, const id &obj){
os << obj.mId; os << obj.mId;
@ -601,7 +577,6 @@ namespace tthread {
unsigned long int mId; unsigned long int mId;
}; };
// Related to <ratio> - minimal to be able to support chrono. // Related to <ratio> - minimal to be able to support chrono.
typedef long long __intmax_t; typedef long long __intmax_t;
@ -609,9 +584,7 @@ namespace tthread {
/// functionality to implement some basic @c chrono classes. /// functionality to implement some basic @c chrono classes.
template <__intmax_t N, __intmax_t D = 1> class ratio{ template <__intmax_t N, __intmax_t D = 1> class ratio{
public: public:
static double _as_double() { static double _as_double(){return double(N) / double(D);}
return double(N) / double(D);
}
}; };
/// Minimal implementation of the @c chrono namespace. /// Minimal implementation of the @c chrono namespace.
@ -622,18 +595,16 @@ namespace tthread {
template <class _Rep, class _Period = ratio<1> > class duration{ template <class _Rep, class _Period = ratio<1> > class duration{
private: private:
_Rep rep_; _Rep rep_;
public: public:
typedef _Rep rep; typedef _Rep rep;
typedef _Period period; typedef _Period period;
/// Construct a duration object with the given duration. /// Construct a duration object with the given duration.
template <class _Rep2> template <class _Rep2> explicit duration(const _Rep2 &r) : rep_(r){};
explicit duration(const _Rep2 & r) : rep_(r) {};
/// Return the value of the duration object. /// Return the value of the duration object.
rep count() const { rep count() const{return rep_;}
return rep_;
}
}; };
// Standard duration types. // Standard duration types.
@ -643,7 +614,7 @@ namespace tthread {
typedef duration<__intmax_t> seconds; ///< Duration with the unit seconds. typedef duration<__intmax_t> seconds; ///< Duration with the unit seconds.
typedef duration<__intmax_t, ratio<60> > minutes; ///< Duration with the unit minutes. typedef duration<__intmax_t, ratio<60> > minutes; ///< Duration with the unit minutes.
typedef duration<__intmax_t, ratio<3600> > hours; ///< Duration with the unit hours. typedef duration<__intmax_t, ratio<3600> > hours; ///< Duration with the unit hours.
} }// namespace chrono
/// The namespace @c this_thread provides methods for dealing with the /// The namespace @c this_thread provides methods for dealing with the
/// calling thread. /// calling thread.
@ -671,16 +642,17 @@ namespace tthread {
/// @endcode /// @endcode
/// @note Supported duration types are: nanoseconds, microseconds, /// @note Supported duration types are: nanoseconds, microseconds,
/// milliseconds, seconds, minutes and hours. /// milliseconds, seconds, minutes and hours.
template <class _Rep, class _Period> void sleep_for(const chrono::duration<_Rep, _Period> & aTime) { template <class _Rep, class _Period>
void sleep_for(const chrono::duration<_Rep, _Period> &aTime){
#if defined(_TTHREAD_WIN32_) #if defined(_TTHREAD_WIN32_)
Sleep(int(double(aTime.count()) * (1000.0 * _Period::_as_double()) + 0.5)); Sleep(int(double(aTime.count()) * (1000.0 * _Period::_as_double()) + 0.5));
#else #else
usleep(int(double(aTime.count()) * (1000000.0 * _Period::_as_double()) + 0.5)); usleep(int(double(aTime.count()) * (1000000.0 * _Period::_as_double()) + 0.5));
#endif #endif
} }
} }// namespace this_thread
} }// namespace tthread
// Define/macro cleanup // Define/macro cleanup
#undef _TTHREAD_DISABLE_ASSIGNMENT #undef _TTHREAD_DISABLE_ASSIGNMENT

View file

@ -1,31 +1,33 @@
/// \page triggers Triggers /// \page triggers Triggers
/// \brief Listing of all available triggers and their payloads. /// \brief Listing of all available triggers and their payloads.
/// MistServer reports certain occurances as configurable triggers to a URL or executable. This page describes the triggers system in full. /// MistServer reports certain occurances as configurable triggers to a URL or executable. This page
/// describes the triggers system in full.
/// ///
/// Triggers are the preferred way of responding to server events. Each trigger has a name and a payload, and may be stream-specific or global. /// Triggers are the preferred way of responding to server events. Each trigger has a name and a
/// payload, and may be stream-specific or global.
/// ///
/// Triggers may be handled by a URL or an executable. If the handler contains ://, a HTTP URL is assumed. Otherwise, an executable is assumed. /// Triggers may be handled by a URL or an executable. If the handler contains ://, a HTTP URL is
/// If handled by an URL, a POST request is sent to the URL with an extra X-Trigger header containing the trigger name and the payload as the /// assumed. Otherwise, an executable is assumed. If handled by an URL, a POST request is sent to
/// POST body. /// the URL with an extra X-Trigger header containing the trigger name and the payload as the POST
/// If handled by an executable, it's started with the trigger name as its only argument, and the payload is piped into the executable over /// body. If handled by an executable, it's started with the trigger name as its only argument, and
/// standard input. /// the payload is piped into the executable over standard input.
/// ///
/// Currently, all triggers are handled asynchronously and responses (if any) are completely ignored. In the future this may change. /// Currently, all triggers are handled asynchronously and responses (if any) are completely
/// ignored. In the future this may change.
/// ///
#include "triggers.h"
#include "bitfields.h" //for strToBool #include "bitfields.h" //for strToBool
#include "defines.h" //for FAIL_MSG and INFO_MSG #include "defines.h" //for FAIL_MSG and INFO_MSG
#include "downloader.h" //for sending http request #include "downloader.h" //for sending http request
#include "procs.h" //for StartPiped #include "procs.h" //for StartPiped
#include "shared_memory.h" #include "shared_memory.h"
#include "util.h"
#include "timing.h" #include "timing.h"
#include "triggers.h"
#include "util.h"
#include <string.h> //for strncmp #include <string.h> //for strncmp
namespace Triggers{ namespace Triggers{
static void submitTriggerStat(const std::string trigger, uint64_t millis, bool ok){ static void submitTriggerStat(const std::string trigger, uint64_t millis, bool ok){
JSON::Value j; JSON::Value j;
j["trigger_stat"]["name"] = trigger; j["trigger_stat"]["name"] = trigger;
@ -42,7 +44,8 @@ namespace Triggers{
///\param payload This data will be sent to the destionation URL/program ///\param payload This data will be sent to the destionation URL/program
///\param sync If true, handler is executed blocking and uses the response data. ///\param sync If true, handler is executed blocking and uses the response data.
///\returns String, false if further processing should be aborted. ///\returns String, false if further processing should be aborted.
std::string handleTrigger(const std::string &trigger, const std::string &value, const std::string &payload, int sync, const std::string &defaultResponse){ std::string handleTrigger(const std::string &trigger, const std::string &value,
const std::string &payload, int sync, const std::string &defaultResponse){
uint64_t tStartMs = Util::bootMS(); uint64_t tStartMs = Util::bootMS();
if (!value.size()){ if (!value.size()){
WARN_MSG("Trigger requested with empty destination"); WARN_MSG("Trigger requested with empty destination");
@ -58,7 +61,8 @@ namespace Triggers{
submitTriggerStat(trigger, tStartMs, true); submitTriggerStat(trigger, tStartMs, true);
return DL.data(); return DL.data();
} }
FAIL_MSG("Trigger failed to execute (%s), using default response: %s", DL.getStatusText().c_str(), defaultResponse.c_str()); FAIL_MSG("Trigger failed to execute (%s), using default response: %s",
DL.getStatusText().c_str(), defaultResponse.c_str());
submitTriggerStat(trigger, tStartMs, false); submitTriggerStat(trigger, tStartMs, false);
return defaultResponse; return defaultResponse;
}else{// send payload to stdin of newly forked process }else{// send payload to stdin of newly forked process
@ -90,9 +94,7 @@ namespace Triggers{
Util::sleep(100); Util::sleep(100);
++counter; ++counter;
if (counter >= 150){ if (counter >= 150){
if (counter == 150){ if (counter == 150){FAIL_MSG("Trigger taking too long - killing process");}
FAIL_MSG("Trigger taking too long - killing process");
}
if (counter >= 250){ if (counter >= 250){
Util::Procs::Stop(myProc); Util::Procs::Stop(myProc);
}else{ }else{
@ -104,7 +106,9 @@ namespace Triggers{
FILE *outFile = fdopen(fdOut, "r"); FILE *outFile = fdopen(fdOut, "r");
char *fileBuf = 0; char *fileBuf = 0;
size_t fileBufLen = 0; size_t fileBufLen = 0;
while (!(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)){ret += fileBuf;} while (!(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)){
ret += fileBuf;
}
fclose(outFile); fclose(outFile);
free(fileBuf); free(fileBuf);
close(fdOut); close(fdOut);
@ -124,14 +128,14 @@ namespace Triggers{
static std::string usually_empty; static std::string usually_empty;
///\brief returns true if a trigger of the specified type should be handled for a specified stream (, or entire server) ///\brief returns true if a trigger of the specified type should be handled for a specified stream
///\param type Trigger event type. ///(, or entire server) \param type Trigger event type. \param streamName the stream to be handled
///\param streamName the stream to be handled
///\return returns true if so ///\return returns true if so
/// calls doTrigger with dryRun set to true /// calls doTrigger with dryRun set to true
/// returns true if a trigger of the specified type should be /// returns true if a trigger of the specified type should be
/// handled for a specified stream (, or entire server) /// handled for a specified stream (, or entire server)
bool shouldTrigger(const std::string & type, const std::string & streamName, bool paramsCB(const char *, const void *), const void * extraParam){ bool shouldTrigger(const std::string &type, const std::string &streamName,
bool paramsCB(const char *, const void *), const void *extraParam){
usually_empty.clear(); usually_empty.clear();
return doTrigger(type, empty, streamName, true, usually_empty, paramsCB, extraParam); return doTrigger(type, empty, streamName, true, usually_empty, paramsCB, extraParam);
} }
@ -162,7 +166,9 @@ namespace Triggers{
/// this can be used to make sure a payload is only generated if at least one trigger should be handled. /// this can be used to make sure a payload is only generated if at least one trigger should be handled.
///-if this function is called with dryRun==false (for example, from one of the overloaded doTrigger functions), handleTrigger is called for ///-if this function is called with dryRun==false (for example, from one of the overloaded doTrigger functions), handleTrigger is called for
/// all configured triggers. In that case, the return value does not matter, it will probably be false in all cases. /// all configured triggers. In that case, the return value does not matter, it will probably be false in all cases.
bool doTrigger(const std::string & type, const std::string &payload, const std::string &streamName, bool dryRun, std::string &response, bool paramsCB(const char *, const void *), const void * extraParam){ bool doTrigger(const std::string &type, const std::string &payload, const std::string &streamName,
bool dryRun, std::string &response, bool paramsCB(const char *, const void *),
const void *extraParam){
// open SHM page for this type: // open SHM page for this type:
char thisPageName[NAME_BUFFER_SIZE]; char thisPageName[NAME_BUFFER_SIZE];
snprintf(thisPageName, NAME_BUFFER_SIZE, SHM_TRIGGER, type.c_str()); snprintf(thisPageName, NAME_BUFFER_SIZE, SHM_TRIGGER, type.c_str());
@ -192,15 +198,14 @@ namespace Triggers{
while (bPos + 4 < pLen){ while (bPos + 4 < pLen){
uint32_t stringLen = ((unsigned int *)(strPtr + bPos))[0]; uint32_t stringLen = ((unsigned int *)(strPtr + bPos))[0];
if (bPos + 4 + stringLen > pLen || !stringLen){break;} if (bPos + 4 + stringLen > pLen || !stringLen){break;}
if ((streamName.size() == stringLen || splitter == stringLen) && strncmp(strPtr+bPos+4, streamName.data(), stringLen) == 0){ if ((streamName.size() == stringLen || splitter == stringLen) &&
strncmp(strPtr + bPos + 4, streamName.data(), stringLen) == 0){
isHandled = true; isHandled = true;
} }
bPos += stringLen + 4; bPos += stringLen + 4;
} }
// no streams explicitly defined for this trigger, return true for all streams. // no streams explicitly defined for this trigger, return true for all streams.
if (bPos <= 4){ if (bPos <= 4){isHandled = true;}
isHandled = true;
}
if (isHandled && paramsCB){ if (isHandled && paramsCB){
isHandled = paramsCB(trigs.getPointer("params", i), extraParam); isHandled = paramsCB(trigs.getPointer("params", i), extraParam);
@ -227,5 +232,4 @@ namespace Triggers{
return retVal; return retVal;
} }
} }
} }// namespace Triggers

View file

@ -5,11 +5,15 @@ namespace Triggers{
static const std::string empty; static const std::string empty;
bool doTrigger(const std::string & triggerType, const std::string &payload, const std::string &streamName, bool dryRun, std::string &response, bool paramsCB(const char *, const void *) = 0, const void * extraParam = 0); bool doTrigger(const std::string &triggerType, const std::string &payload,
std::string handleTrigger(const std::string &triggerType, const std::string &value, const std::string &payload, int sync, const std::string &defaultResponse); const std::string &streamName, bool dryRun, std::string &response,
bool paramsCB(const char *, const void *) = 0, const void *extraParam = 0);
std::string handleTrigger(const std::string &triggerType, const std::string &value,
const std::string &payload, int sync, const std::string &defaultResponse);
// All of the below are just shorthands for specific usage of the doTrigger function above: // All of the below are just shorthands for specific usage of the doTrigger function above:
bool shouldTrigger(const std::string & triggerType, const std::string &streamName = empty, bool paramsCB(const char *, const void *) = 0, const void * extraParam = 0); bool shouldTrigger(const std::string &triggerType, const std::string &streamName = empty,
bool doTrigger(const std::string & triggerType, const std::string & payload = empty, const std::string & streamName = empty); bool paramsCB(const char *, const void *) = 0, const void *extraParam = 0);
} bool doTrigger(const std::string &triggerType, const std::string &payload = empty,
const std::string &streamName = empty);
}// namespace Triggers

View file

@ -1,24 +1,35 @@
/// \file ts_packet.cpp /// \file ts_packet.cpp
/// Holds all code for the TS namespace. /// Holds all code for the TS namespace.
#include "util.h"
#include <sstream>
#include <iomanip>
#include <string.h>
#include <set>
#include <map>
#include "ts_packet.h"
#include "defines.h"
#include "bitfields.h" #include "bitfields.h"
#include "defines.h"
#include "ts_packet.h"
#include "util.h"
#include <iomanip>
#include <map>
#include <set>
#include <sstream>
#include <string.h>
#ifndef FILLER_DATA #ifndef FILLER_DATA
#define FILLER_DATA "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent commodo vulputate urna eu commodo. Cras tempor velit nec nulla placerat volutpat. Proin eleifend blandit quam sit amet suscipit. Pellentesque vitae tristique lorem. Maecenas facilisis consequat neque, vitae iaculis eros vulputate ut. Suspendisse ut arcu non eros vestibulum pulvinar id sed erat. Nam dictum tellus vel tellus rhoncus ut mollis tellus fermentum. Fusce volutpat consectetur ante, in mollis nisi euismod vulputate. Curabitur vitae facilisis ligula. Sed sed gravida dolor. Integer eu eros a dolor lobortis ullamcorper. Mauris interdum elit non neque interdum dictum. Suspendisse imperdiet eros sed sapien cursus pulvinar. Vestibulum ut dolor lectus, id commodo elit. Cras convallis varius leo eu porta. Duis luctus sapien nec dui adipiscing quis interdum nunc congue. Morbi pharetra aliquet mauris vitae tristique. Etiam feugiat sapien quis augue elementum id ultricies magna vulputate. Phasellus luctus, leo id egestas consequat, eros tortor commodo neque, vitae hendrerit nunc sem ut odio." #define FILLER_DATA \
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent commodo vulputate urna eu " \
"commodo. Cras tempor velit nec nulla placerat volutpat. Proin eleifend blandit quam sit amet " \
"suscipit. Pellentesque vitae tristique lorem. Maecenas facilisis consequat neque, vitae " \
"iaculis eros vulputate ut. Suspendisse ut arcu non eros vestibulum pulvinar id sed erat. Nam " \
"dictum tellus vel tellus rhoncus ut mollis tellus fermentum. Fusce volutpat consectetur ante, " \
"in mollis nisi euismod vulputate. Curabitur vitae facilisis ligula. Sed sed gravida dolor. " \
"Integer eu eros a dolor lobortis ullamcorper. Mauris interdum elit non neque interdum dictum. " \
"Suspendisse imperdiet eros sed sapien cursus pulvinar. Vestibulum ut dolor lectus, id commodo " \
"elit. Cras convallis varius leo eu porta. Duis luctus sapien nec dui adipiscing quis interdum " \
"nunc congue. Morbi pharetra aliquet mauris vitae tristique. Etiam feugiat sapien quis augue " \
"elementum id ultricies magna vulputate. Phasellus luctus, leo id egestas consequat, eros " \
"tortor commodo neque, vitae hendrerit nunc sem ut odio."
#endif #endif
std::set<unsigned int> pmt_pids; std::set<unsigned int> pmt_pids;
std::map<unsigned int, std::string> stream_pids; std::map<unsigned int, std::string> stream_pids;
namespace TS{ namespace TS{
/// This constructor creates an empty Packet, ready for use for either reading or writing. /// This constructor creates an empty Packet, ready for use for either reading or writing.
/// All this constructor does is call Packet::clear(). /// All this constructor does is call Packet::clear().
@ -41,9 +52,7 @@ namespace TS {
uint16_t retries = 0; uint16_t retries = 0;
while (retries < 256){ while (retries < 256){
if (!fread((void *)strBuf, 188, 1, data)){ if (!fread((void *)strBuf, 188, 1, data)){
if (!feof(data)){ if (!feof(data)){FAIL_MSG("Could not read 188 bytes from file! %s", strerror(errno));}
FAIL_MSG("Could not read 188 bytes from file! %s", strerror(errno));
}
return false; return false;
} }
if (strBuf[0] == 0x47){ if (strBuf[0] == 0x47){
@ -54,9 +63,7 @@ namespace TS {
if (strBuf[i] == 0x47){ if (strBuf[i] == 0x47){
INFO_MSG("Shifting %u bytes", i); INFO_MSG("Shifting %u bytes", i);
memmove((void *)strBuf, (void *)(strBuf + i), 188 - i); memmove((void *)strBuf, (void *)(strBuf + i), 188 - i);
if (!fread((void *)strBuf, i, 1, data)) { if (!fread((void *)strBuf, i, 1, data)){return false;}
return false;
}
pos = 188; pos = 188;
return true; return true;
} }
@ -67,19 +74,14 @@ namespace TS {
return false; return false;
} }
bool Packet::FromStream(std::istream & data) bool Packet::FromStream(std::istream &data){
{
long long int bPos = data.tellg(); long long int bPos = data.tellg();
if(!data.read (strBuf,188)) if (!data.read(strBuf, 188)){
{ if (!data.eof()){HIGH_MSG("failed to read 188 bytes: %s", strerror(errno));}
if (!data.eof()){
HIGH_MSG("failed to read 188 bytes: %s", strerror(errno));
}
return false; return false;
} }
if(strBuf[0] != 0x47) if (strBuf[0] != 0x47){
{
HIGH_MSG("Failed to read a good packet on pos %lld", bPos); HIGH_MSG("Failed to read a good packet on pos %lld", bPos);
return false; return false;
} }
@ -88,7 +90,6 @@ namespace TS {
return true; return true;
} }
/// This funtion fills a Packet from /// This funtion fills a Packet from
/// a char array. It fills the content with /// a char array. It fills the content with
/// the first 188 characters of a char array /// the first 188 characters of a char array
@ -101,14 +102,11 @@ namespace TS {
} }
/// The deconstructor deletes all space that may be occupied by a Packet. /// The deconstructor deletes all space that may be occupied by a Packet.
Packet::~Packet() { Packet::~Packet(){}
}
/// update position in character array (pos), /// update position in character array (pos),
void Packet::updPos(unsigned int newPos){ void Packet::updPos(unsigned int newPos){
if(pos < newPos){ if (pos < newPos){pos = newPos;}
pos=newPos;
}
} }
/// Sets the PID of a single Packet. /// Sets the PID of a single Packet.
@ -134,9 +132,7 @@ namespace TS {
/// Gets the Continuity Counter of a single Packet. /// Gets the Continuity Counter of a single Packet.
/// \return The value of the Continuity Counter. /// \return The value of the Continuity Counter.
int Packet::getContinuityCounter() const{ int Packet::getContinuityCounter() const{return (strBuf[3] & 0x0F);}
return (strBuf[3] & 0x0F);
}
/// Gets the amount of bytes that are not written yet in a Packet. /// Gets the amount of bytes that are not written yet in a Packet.
/// \return The amount of bytes that can still be written to this packet. /// \return The amount of bytes that can still be written to this packet.
@ -176,9 +172,7 @@ namespace TS {
/// \return The existence of an adaptationfield. /// \return The existence of an adaptationfield.
/// - 0: No adaptationfield present. /// - 0: No adaptationfield present.
/// - 1: Adaptationfield is present. /// - 1: Adaptationfield is present.
int Packet::getAdaptationField() const{ int Packet::getAdaptationField() const{return ((strBuf[3] & 0x30) >> 4);}
return ((strBuf[3] & 0x30) >> 4);
}
/// Sets the PCR (Program Clock Reference) of a Packet. /// Sets the PCR (Program Clock Reference) of a Packet.
/// \param NewVal The new PCR Value. /// \param NewVal The new PCR Value.
@ -200,13 +194,10 @@ namespace TS {
/// Gets the PCR (Program Clock Reference) of a Packet. /// Gets the PCR (Program Clock Reference) of a Packet.
/// \return The value of the PCR. /// \return The value of the PCR.
int64_t Packet::getPCR() const{ int64_t Packet::getPCR() const{
if (!getAdaptationField()) { if (!getAdaptationField()){return -1;}
return -1; if (!(strBuf[5] & 0x10)){return -1;}
} int64_t Result = (((strBuf[6] << 24) | (strBuf[7] << 16) | (strBuf[8] << 8) | strBuf[9]) << 1) |
if (!(strBuf[5] & 0x10)) { (strBuf[10] >> 7);
return -1;
}
int64_t Result = (((strBuf[6] << 24) | (strBuf[7] << 16) | (strBuf[8] << 8) | strBuf[9]) << 1) | (strBuf[10] >> 7);
Result *= 300; Result *= 300;
Result |= (((strBuf[10] & 0x01) << 8) + strBuf[11]); Result |= (((strBuf[10] & 0x01) << 8) + strBuf[11]);
return Result; return Result;
@ -215,14 +206,11 @@ namespace TS {
/// Gets the OPCR (Original Program Clock Reference) of a Packet. /// Gets the OPCR (Original Program Clock Reference) of a Packet.
/// \return The value of the OPCR. /// \return The value of the OPCR.
int64_t Packet::getOPCR() const{ int64_t Packet::getOPCR() const{
if (!getAdaptationField()) { if (!getAdaptationField()){return -1;}
return -1; if (!(strBuf[5 + 6] & 0x10)){return -1;}
}
if (!(strBuf[5 + 6] & 0x10)) {
return -1;
}
int64_t Result = 0; int64_t Result = 0;
Result = (((strBuf[6 + 6] << 24) + (strBuf[7 + 6] << 16) + (strBuf[8 + 6] << 8) + strBuf[9 + 6]) << 1) + (strBuf[10 + 6] & 0x80 >> 7); Result = (((strBuf[6 + 6] << 24) + (strBuf[7 + 6] << 16) + (strBuf[8 + 6] << 8) + strBuf[9 + 6]) << 1) +
(strBuf[10 + 6] & 0x80 >> 7);
Result = Result * 300; Result = Result * 300;
Result += (((strBuf[10 + 6] & 0x01) << 8) + strBuf[11 + 6]); Result += (((strBuf[10 + 6] & 0x01) << 8) + strBuf[11 + 6]);
return Result; return Result;
@ -230,21 +218,15 @@ namespace TS {
/// Gets the transport error inficator of a Packet /// Gets the transport error inficator of a Packet
/// \return The transport error inficator of a Packet /// \return The transport error inficator of a Packet
bool Packet::hasTransportError() const{ bool Packet::hasTransportError() const{return strBuf[1] & 0x80;}
return strBuf[1] & 0x80;
}
/// Gets the payload unit start inficator of a Packet /// Gets the payload unit start inficator of a Packet
/// \return The payload unit start inficator of a Packet /// \return The payload unit start inficator of a Packet
bool Packet::getUnitStart() const{ bool Packet::getUnitStart() const{return strBuf[1] & 0x40;}
return strBuf[1] & 0x40;
}
/// Gets the transport priority of a Packet /// Gets the transport priority of a Packet
/// \return The transport priority of a Packet /// \return The transport priority of a Packet
bool Packet::hasPriority() const{ bool Packet::hasPriority() const{return strBuf[1] & 0x20;}
return strBuf[1] & 0x20;
}
/// Gets the transport scrambling control of a Packet /// Gets the transport scrambling control of a Packet
/// \return The transport scrambling control of a Packet /// \return The transport scrambling control of a Packet
@ -255,24 +237,19 @@ namespace TS {
/// Gets the current length of the adaptationfield. /// Gets the current length of the adaptationfield.
/// \return The length of the adaptationfield. /// \return The length of the adaptationfield.
int Packet::getAdaptationFieldLen() const{ int Packet::getAdaptationFieldLen() const{
if (!getAdaptationField()) { if (!getAdaptationField()){return -1;}
return -1;
}
return (int)strBuf[4]; return (int)strBuf[4];
} }
Packet::operator bool() const{ Packet::operator bool() const{return pos && strBuf[0] == 0x47;}
return pos && strBuf[0] == 0x47;
}
/// Prints a packet to stdout, for analyser purposes. /// Prints a packet to stdout, for analyser purposes.
/// If detail level contains bitmask 64, prints raw bytes after packet. /// If detail level contains bitmask 64, prints raw bytes after packet.
std::string Packet::toPrettyString(size_t indent, int detailLevel) const{ std::string Packet::toPrettyString(size_t indent, int detailLevel) const{
if (!(*this)){ if (!(*this)){return "[Invalid packet - no sync byte]";}
return "[Invalid packet - no sync byte]";
}
std::stringstream output; std::stringstream output;
output << std::string(indent, ' ') << "[PID " << getPID() << "|" << std::hex << getContinuityCounter() << std::dec << ": " << getDataSize() << "b "; output << std::string(indent, ' ') << "[PID " << getPID() << "|" << std::hex
<< getContinuityCounter() << std::dec << ": " << getDataSize() << "b ";
switch (getPID()){ switch (getPID()){
case 0: output << "PAT"; break; case 0: output << "PAT"; break;
case 1: output << "CAT"; break; case 1: output << "CAT"; break;
@ -292,25 +269,13 @@ namespace TS {
break; break;
} }
output << "]"; output << "]";
if (getUnitStart()){ if (getUnitStart()){output << " [Start]";}
output << " [Start]";
}
if (getAdaptationField() > 1 && getAdaptationFieldLen()){ if (getAdaptationField() > 1 && getAdaptationFieldLen()){
if (hasDiscontinuity()){ if (hasDiscontinuity()){output << " [Discontinuity]";}
output << " [Discontinuity]"; if (getRandomAccess()){output << " [RandomXS]";}
} if (getESPriority()){output << " [ESPriority]";}
if (getRandomAccess()){ if (hasPCR()){output << " [PCR " << (double)getPCR() / 27000000 << "s]";}
output << " [RandomXS]"; if (hasOPCR()){output << " [OPCR: " << (double)getOPCR() / 27000000 << "s]";}
}
if (getESPriority()){
output << " [ESPriority]";
}
if (hasPCR()) {
output << " [PCR " << (double)getPCR() / 27000000 << "s]";
}
if (hasOPCR()) {
output<< " [OPCR: " << (double)getOPCR() / 27000000 << "s]";
}
} }
output << std::endl; output << std::endl;
if (!getPID()){ if (!getPID()){
@ -336,13 +301,10 @@ namespace TS {
unsigned int size = getDataSize(); unsigned int size = getDataSize();
for (unsigned int i = 0; i < size; ++i){ for (unsigned int i = 0; i < size; ++i){
if (!(i % 32)){ if (!(i % 32)){output << std::endl << std::string(indent + 4, ' ');}
output << std::endl << std::string(indent + 4, ' '); output << std::hex << std::setw(2) << std::setfill('0')
} << (unsigned int)(strBuf + 188 - size)[i] << " ";
output << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)(strBuf+188-size)[i] << " "; if ((i % 4) == 3){output << " ";}
if ((i % 4) == 3){
output << " ";
}
} }
output << std::endl; output << std::endl;
} }
@ -356,15 +318,11 @@ namespace TS {
/// Returns true if this PID contains a PMT. /// Returns true if this PID contains a PMT.
/// Important caveat: only works if the corresponding PAT has been pretty-printed or had parsePIDs() called on it! /// Important caveat: only works if the corresponding PAT has been pretty-printed or had parsePIDs() called on it!
bool Packet::isPMT() const{ bool Packet::isPMT() const{return pmt_pids.count(getPID());}
return pmt_pids.count(getPID());
}
/// Returns true if this PID contains a stream known from a PMT. /// Returns true if this PID contains a stream known from a PMT.
/// Important caveat: only works if the corresponding PMT was pretty-printed or had parseStreams() called on it! /// Important caveat: only works if the corresponding PMT was pretty-printed or had parseStreams() called on it!
bool Packet::isStream() const{ bool Packet::isStream() const{return stream_pids.count(getPID());}
return stream_pids.count(getPID());
}
/// Sets the start of a new unit in this Packet. /// Sets the start of a new unit in this Packet.
/// \param NewVal The new value for the start of a unit. /// \param NewVal The new value for the start of a unit.
@ -376,16 +334,12 @@ namespace TS {
} }
} }
bool Packet::hasDiscontinuity() const{ bool Packet::hasDiscontinuity() const{return strBuf[5] & 0x80;}
return strBuf[5] & 0x80;
}
void Packet::setDiscontinuity(bool newVal){ void Packet::setDiscontinuity(bool newVal){
updPos(6); updPos(6);
if (getAdaptationField() == 3){ if (getAdaptationField() == 3){
if (!strBuf[4]) { if (!strBuf[4]){strBuf[4] = 1;}
strBuf[4] = 1;
}
if (newVal){ if (newVal){
strBuf[5] |= 0x80; strBuf[5] |= 0x80;
}else{ }else{
@ -405,47 +359,35 @@ namespace TS {
/// Gets whether this Packet can be accessed at random (indicates keyframe). /// Gets whether this Packet can be accessed at random (indicates keyframe).
/// \return Whether or not this Packet contains a keyframe. /// \return Whether or not this Packet contains a keyframe.
bool Packet::getRandomAccess() const{ bool Packet::getRandomAccess() const{
if (getAdaptationField() < 2) { if (getAdaptationField() < 2){return false;}
return false;
}
return strBuf[5] & 0x40; return strBuf[5] & 0x40;
} }
/// Gets whether this Packet has the priority bit set /// Gets whether this Packet has the priority bit set
/// \return Whether or not this Packet has the priority bit set /// \return Whether or not this Packet has the priority bit set
bool Packet::getESPriority() const{ bool Packet::getESPriority() const{
if (getAdaptationField() < 2) { if (getAdaptationField() < 2){return false;}
return false;
}
return strBuf[5] & 0x20; return strBuf[5] & 0x20;
} }
/// Gets the value of the PCR flag /// Gets the value of the PCR flag
///\return true if there is a PCR, false otherwise ///\return true if there is a PCR, false otherwise
bool Packet::hasPCR() const{ bool Packet::hasPCR() const{return strBuf[5] & 0x10;}
return strBuf[5] & 0x10;
}
/// Gets the value of the OPCR flag /// Gets the value of the OPCR flag
///\return true if there is an OPCR, false otherwise ///\return true if there is an OPCR, false otherwise
bool Packet::hasOPCR() const{ bool Packet::hasOPCR() const{return strBuf[5] & 0x08;}
return strBuf[5] & 0x08;
}
/// Gets the value of the splicing point flag /// Gets the value of the splicing point flag
///\return the value of the splicing point flag ///\return the value of the splicing point flag
bool Packet::hasSplicingPoint() const{ bool Packet::hasSplicingPoint() const{return strBuf[5] & 0x04;}
return strBuf[5] & 0x04;
}
/// Gets the value of the transport private data point flag /// Gets the value of the transport private data point flag
///\return the value of the transport private data point flag ///\return the value of the transport private data point flag
void Packet::setRandomAccess(bool NewVal){ void Packet::setRandomAccess(bool NewVal){
updPos(6); updPos(6);
if (getAdaptationField() == 3){ if (getAdaptationField() == 3){
if (!strBuf[4]) { if (!strBuf[4]){strBuf[4] = 1;}
strBuf[4] = 1;
}
if (NewVal){ if (NewVal){
strBuf[5] |= 0x40; strBuf[5] |= 0x40;
}else{ }else{
@ -467,9 +409,7 @@ namespace TS {
void Packet::setESPriority(bool NewVal){ void Packet::setESPriority(bool NewVal){
updPos(6); updPos(6);
if (getAdaptationField() == 3){ if (getAdaptationField() == 3){
if (!strBuf[4]) { if (!strBuf[4]){strBuf[4] = 1;}
strBuf[4] = 1;
}
if (NewVal){ if (NewVal){
strBuf[5] |= 0x20; strBuf[5] |= 0x20;
}else{ }else{
@ -495,16 +435,13 @@ namespace TS {
MyCntr %= 0x10; MyCntr %= 0x10;
} }
/// Checks the size of the internal packet buffer (prints error if size !=188), then returns a pointer to the data. /// Checks the size of the internal packet buffer (prints error if size !=188), then returns a
/// \return A character pointer to the internal packet buffer data /// pointer to the data. \return A character pointer to the internal packet buffer data
const char *Packet::checkAndGetBuffer() const{ const char *Packet::checkAndGetBuffer() const{
if (pos != 188) { if (pos != 188){HIGH_MSG("Size invalid (%d) - invalid data from this point on", pos);}
HIGH_MSG("Size invalid (%d) - invalid data from this point on", pos);
}
return strBuf; return strBuf;
} }
// BEGIN PES FUNCTIONS // BEGIN PES FUNCTIONS
// pes functons do not use the internal strBuf character buffer // pes functons do not use the internal strBuf character buffer
///\brief Appends the PES-encoded timestamp to a string. ///\brief Appends the PES-encoded timestamp to a string.
@ -528,14 +465,11 @@ namespace TS {
/// Prepends the lead-in to variable toSend, assumes toSend's length is all other data. /// Prepends the lead-in to variable toSend, assumes toSend's length is all other data.
/// \param len The length of this frame. /// \param len The length of this frame.
/// \param PTS The timestamp of the frame. /// \param PTS The timestamp of the frame.
std::string & Packet::getPESVideoLeadIn(unsigned int len, unsigned long long PTS, unsigned long long offset, bool isAligned, uint64_t bps) { std::string &Packet::getPESVideoLeadIn(unsigned int len, unsigned long long PTS,
if (len){ unsigned long long offset, bool isAligned, uint64_t bps){
len += (offset ? 13 : 8); if (len){len += (offset ? 13 : 8);}
}
if (bps >= 50){ if (bps >= 50){
if (len){ if (len){len += 3;}
len += 3;
}
}else{ }else{
bps = 0; bps = 0;
} }
@ -553,9 +487,7 @@ namespace TS {
tmpStr += (char)((offset ? 0xC0 : 0x80) | (bps ? 0x10 : 0)); // PTS/DTS + Flags tmpStr += (char)((offset ? 0xC0 : 0x80) | (bps ? 0x10 : 0)); // PTS/DTS + Flags
tmpStr += (char)((offset ? 10 : 5) + (bps ? 3 : 0)); // PESHeaderDataLength tmpStr += (char)((offset ? 10 : 5) + (bps ? 3 : 0)); // PESHeaderDataLength
encodePESTimestamp(tmpStr, (offset ? 0x30 : 0x20), PTS + offset); encodePESTimestamp(tmpStr, (offset ? 0x30 : 0x20), PTS + offset);
if (offset){ if (offset){encodePESTimestamp(tmpStr, 0x10, PTS);}
encodePESTimestamp(tmpStr, 0x10, PTS);
}
if (bps){ if (bps){
char rate_buf[3]; char rate_buf[3];
Bit::htob24(rate_buf, (bps / 50) | 0x800001); Bit::htob24(rate_buf, (bps / 50) | 0x800001);
@ -611,12 +543,11 @@ namespace TS {
/// \return The amount of content bytes that can be send. /// \return The amount of content bytes that can be send.
void Packet::addStuffing(){ void Packet::addStuffing(){
unsigned int numBytes = getBytesFree(); unsigned int numBytes = getBytesFree();
if (!numBytes) { if (!numBytes){return;}
return;
}
if (getAdaptationField() == 2){ if (getAdaptationField() == 2){
FAIL_MSG("Can not handle adaptation field 2 - should stuff the entire packet, no data will follow after the adaptation field"); ///\todo more stuffing required FAIL_MSG("Can not handle adaptation field 2 - should stuff the entire packet, no data will "
"follow after the adaptation field"); ///\todo more stuffing required
return; return;
} }
@ -640,7 +571,8 @@ namespace TS {
memset((void *)(strBuf + 5), '$', numBytes); memset((void *)(strBuf + 5), '$', numBytes);
pos += numBytes; pos += numBytes;
}else{ }else{
memmove((void*)(strBuf+5+strBuf[4]+numBytes), (void*)(strBuf+5+strBuf[4]) , 188-5-strBuf[4]-numBytes); memmove((void *)(strBuf + 5 + strBuf[4] + numBytes), (void *)(strBuf + 5 + strBuf[4]),
188 - 5 - strBuf[4] - numBytes);
memset((void *)(strBuf + 5 + strBuf[4]), '$', numBytes); memset((void *)(strBuf + 5 + strBuf[4]), '$', numBytes);
pos += numBytes; pos += numBytes;
} }
@ -676,7 +608,6 @@ namespace TS {
return 184 - ((getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0)); return 184 - ((getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0));
} }
ProgramAssociationTable &ProgramAssociationTable::operator=(const Packet &rhs){ ProgramAssociationTable &ProgramAssociationTable::operator=(const Packet &rhs){
memcpy(strBuf, rhs.checkAndGetBuffer(), 188); memcpy(strBuf, rhs.checkAndGetBuffer(), 188);
pos = 188; pos = 188;
@ -737,30 +668,26 @@ namespace TS {
} }
short ProgramAssociationTable::getProgramNumber(short index) const{ short ProgramAssociationTable::getProgramNumber(short index) const{
if (index > getProgramCount()) { if (index > getProgramCount()){return 0;}
return 0;
}
unsigned int loc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset() + 9; unsigned int loc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset() + 9;
return ((short)(strBuf[loc + (index * 4)]) << 8) | strBuf[loc + (index * 4) + 1]; return ((short)(strBuf[loc + (index * 4)]) << 8) | strBuf[loc + (index * 4) + 1];
} }
short ProgramAssociationTable::getProgramPID(short index) const{ short ProgramAssociationTable::getProgramPID(short index) const{
if (index > getProgramCount()) { if (index > getProgramCount()){return 0;}
return 0;
}
unsigned int loc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset() + 9; unsigned int loc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset() + 9;
return (((short)(strBuf[loc + (index * 4) + 2]) << 8) | strBuf[loc + (index * 4) + 3]) & 0x1FFF; return (((short)(strBuf[loc + (index * 4) + 2]) << 8) | strBuf[loc + (index * 4) + 3]) & 0x1FFF;
} }
int ProgramAssociationTable::getCRC() const{ int ProgramAssociationTable::getCRC() const{
unsigned int loc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset() + 9 + (getProgramCount() * 4); unsigned int loc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) +
return ((int)(strBuf[loc]) << 24) | ((int)(strBuf[loc + 1]) << 16) | ((int)(strBuf[loc + 2]) << 8) | strBuf[loc + 3]; getOffset() + 9 + (getProgramCount() * 4);
return ((int)(strBuf[loc]) << 24) | ((int)(strBuf[loc + 1]) << 16) |
((int)(strBuf[loc + 2]) << 8) | strBuf[loc + 3];
} }
void ProgramAssociationTable::parsePIDs(){ void ProgramAssociationTable::parsePIDs(){
for (int i = 0; i < getProgramCount(); i++) { for (int i = 0; i < getProgramCount(); i++){pmt_pids.insert(getProgramPID(i));}
pmt_pids.insert(getProgramPID(i));
}
} }
/// This function prints a program association table, /// This function prints a program association table,
@ -775,9 +702,11 @@ namespace TS {
output << std::string(indent + 2, ' ') << "Sectionlen: " << getSectionLength() << std::endl; output << std::string(indent + 2, ' ') << "Sectionlen: " << getSectionLength() << std::endl;
output << std::string(indent + 2, ' ') << "Transport Stream ID: " << getTransportStreamId() << std::endl; output << std::string(indent + 2, ' ') << "Transport Stream ID: " << getTransportStreamId() << std::endl;
output << std::string(indent + 2, ' ') << "Version Number: " << (int)getVersionNumber() << std::endl; output << std::string(indent + 2, ' ') << "Version Number: " << (int)getVersionNumber() << std::endl;
output << std::string(indent + 2, ' ') << "Current/Next Indicator: " << (int)getCurrentNextIndicator() << std::endl; output << std::string(indent + 2, ' ')
<< "Current/Next Indicator: " << (int)getCurrentNextIndicator() << std::endl;
output << std::string(indent + 2, ' ') << "Section number: " << (int)getSectionNumber() << std::endl; output << std::string(indent + 2, ' ') << "Section number: " << (int)getSectionNumber() << std::endl;
output << std::string(indent + 2, ' ') << "Last Section number: " << (int)getLastSectionNumber() << std::endl; output << std::string(indent + 2, ' ') << "Last Section number: " << (int)getLastSectionNumber()
<< std::endl;
output << std::string(indent + 2, ' ') << "Programs [" << (int)getProgramCount() << "]" << std::endl; output << std::string(indent + 2, ' ') << "Programs [" << (int)getProgramCount() << "]" << std::endl;
for (int i = 0; i < getProgramCount(); i++){ for (int i = 0; i < getProgramCount(); i++){
output << std::string(indent + 4, ' ') << "[" << i + 1 << "] "; output << std::string(indent + 4, ' ') << "[" << i + 1 << "] ";
@ -785,9 +714,9 @@ namespace TS {
output << (getProgramNumber(i) == 0 ? "Network" : "Program Map") << " PID: " << getProgramPID(i); output << (getProgramNumber(i) == 0 ? "Network" : "Program Map") << " PID: " << getProgramPID(i);
output << std::endl; output << std::endl;
} }
output << std::string(indent + 2, ' ') << "CRC32: " << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << getCRC() << std::dec << std::endl; output << std::string(indent + 2, ' ') << "CRC32: " << std::hex << std::setw(8)
<< std::setfill('0') << std::uppercase << getCRC() << std::dec << std::endl;
return output.str(); return output.str();
} }
ProgramMappingEntry::ProgramMappingEntry(char *begin, char *end){ ProgramMappingEntry::ProgramMappingEntry(char *begin, char *end){
@ -795,17 +724,11 @@ namespace TS {
boundary = end; boundary = end;
} }
ProgramMappingEntry::operator bool() const { ProgramMappingEntry::operator bool() const{return data && (data < boundary);}
return data && (data < boundary);
}
int ProgramMappingEntry::getStreamType() const{ int ProgramMappingEntry::getStreamType() const{return data[0];}
return data[0];
}
void ProgramMappingEntry::setStreamType(int newType){ void ProgramMappingEntry::setStreamType(int newType){data[0] = newType;}
data[0] = newType;
}
std::string ProgramMappingEntry::getCodec() const{ std::string ProgramMappingEntry::getCodec() const{
switch (getStreamType()){ switch (getStreamType()){
@ -855,22 +778,16 @@ namespace TS {
} }
} }
int ProgramMappingEntry::getElementaryPid() const{ int ProgramMappingEntry::getElementaryPid() const{return ((data[1] << 8) | data[2]) & 0x1FFF;}
return ((data[1] << 8) | data[2]) & 0x1FFF;
}
void ProgramMappingEntry::setElementaryPid(int newElementaryPid){ void ProgramMappingEntry::setElementaryPid(int newElementaryPid){
data[1] = (newElementaryPid >> 8 & 0x1F) | 0xE0; // 0xE0 = three reserved bits data[1] = (newElementaryPid >> 8 & 0x1F) | 0xE0; // 0xE0 = three reserved bits
data[2] = newElementaryPid & 0xFF; data[2] = newElementaryPid & 0xFF;
} }
int ProgramMappingEntry::getESInfoLength() const{ int ProgramMappingEntry::getESInfoLength() const{return ((data[3] << 8) | data[4]) & 0x0FFF;}
return ((data[3] << 8) | data[4]) & 0x0FFF;
}
const char * ProgramMappingEntry::getESInfo() const{ const char *ProgramMappingEntry::getESInfo() const{return data + 5;}
return data + 5;
}
void ProgramMappingEntry::setESInfo(const std::string &newInfo){ void ProgramMappingEntry::setESInfo(const std::string &newInfo){
data[3] = ((newInfo.size() >> 8) & 0x0F) | 0xF0; // 0xF0 = four reserved bits data[3] = ((newInfo.size() >> 8) & 0x0F) | 0xF0; // 0xF0 = four reserved bits
@ -879,9 +796,7 @@ namespace TS {
} }
void ProgramMappingEntry::advance(){ void ProgramMappingEntry::advance(){
if (!(*this)) { if (!(*this)){return;}
return;
}
data += 5 + getESInfoLength(); data += 5 + getESInfoLength();
} }
@ -1020,22 +935,25 @@ namespace TS {
ProgramMappingEntry ProgramMappingTable::getEntry(int index) const{ ProgramMappingEntry ProgramMappingTable::getEntry(int index) const{
int dataOffset = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset(); int dataOffset = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset();
ProgramMappingEntry res((char*)(strBuf + dataOffset + 13 + getProgramInfoLength()), (char*)(strBuf + dataOffset + getSectionLength()) ); ProgramMappingEntry res((char *)(strBuf + dataOffset + 13 + getProgramInfoLength()),
for (int i = 0; i < index; i++){ (char *)(strBuf + dataOffset + getSectionLength()));
res.advance(); for (int i = 0; i < index; i++){res.advance();}
}
return res; return res;
} }
int ProgramMappingTable::getCRC() const{ int ProgramMappingTable::getCRC() const{
unsigned int loc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset() + getSectionLength(); unsigned int loc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) +
return ((int)(strBuf[loc]) << 24) | ((int)(strBuf[loc + 1]) << 16) | ((int)(strBuf[loc + 2]) << 8) | strBuf[loc + 3]; getOffset() + getSectionLength();
return ((int)(strBuf[loc]) << 24) | ((int)(strBuf[loc + 1]) << 16) |
((int)(strBuf[loc + 2]) << 8) | strBuf[loc + 3];
} }
void ProgramMappingTable::calcCRC(){ void ProgramMappingTable::calcCRC(){
unsigned int loc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset() + getSectionLength(); unsigned int loc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) +
getOffset() + getSectionLength();
unsigned int newVal; // this will hold the CRC32 value; unsigned int newVal; // this will hold the CRC32 value;
unsigned int pidLoc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset() + 1;//location of PCRPID unsigned int pidLoc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) +
getOffset() + 1; // location of PCRPID
newVal = checksum::crc32(-1, strBuf + pidLoc, loc - pidLoc); // calculating checksum over all the fields from table ID to the last stream element newVal = checksum::crc32(-1, strBuf + pidLoc, loc - pidLoc); // calculating checksum over all the fields from table ID to the last stream element
updPos(188); updPos(188);
strBuf[loc + 3] = (newVal >> 24) & 0xFF; strBuf[loc + 3] = (newVal >> 24) & 0xFF;
@ -1049,7 +967,8 @@ namespace TS {
void ProgramMappingTable::parseStreams(){ void ProgramMappingTable::parseStreams(){
ProgramMappingEntry entry = getEntry(0); ProgramMappingEntry entry = getEntry(0);
while (entry){ while (entry){
stream_pids[entry.getElementaryPid()] = entry.getCodec() + std::string(" ") + entry.getStreamTypeString(); stream_pids[entry.getElementaryPid()] =
entry.getCodec() + std::string(" ") + entry.getStreamTypeString();
entry.advance(); entry.advance();
} }
} }
@ -1065,25 +984,30 @@ namespace TS {
output << std::string(indent + 2, ' ') << "Section Length: " << getSectionLength() << std::endl; output << std::string(indent + 2, ' ') << "Section Length: " << getSectionLength() << std::endl;
output << std::string(indent + 2, ' ') << "Program number: " << getProgramNumber() << std::endl; output << std::string(indent + 2, ' ') << "Program number: " << getProgramNumber() << std::endl;
output << std::string(indent + 2, ' ') << "Version number: " << (int)getVersionNumber() << std::endl; output << std::string(indent + 2, ' ') << "Version number: " << (int)getVersionNumber() << std::endl;
output << std::string(indent + 2, ' ') << "Current next indicator: " << (int)getCurrentNextIndicator() << std::endl; output << std::string(indent + 2, ' ')
<< "Current next indicator: " << (int)getCurrentNextIndicator() << std::endl;
output << std::string(indent + 2, ' ') << "Section number: " << (int)getSectionNumber() << std::endl; output << std::string(indent + 2, ' ') << "Section number: " << (int)getSectionNumber() << std::endl;
output << std::string(indent + 2, ' ') << "Last Section number: " << (int)getLastSectionNumber() << std::endl; output << std::string(indent + 2, ' ') << "Last Section number: " << (int)getLastSectionNumber()
<< std::endl;
output << std::string(indent + 2, ' ') << "PCR PID: " << getPCRPID() << std::endl; output << std::string(indent + 2, ' ') << "PCR PID: " << getPCRPID() << std::endl;
output << std::string(indent + 2, ' ') << "Program Info Length: " << getProgramInfoLength() << std::endl; output << std::string(indent + 2, ' ') << "Program Info Length: " << getProgramInfoLength() << std::endl;
ProgramMappingEntry entry = getEntry(0); ProgramMappingEntry entry = getEntry(0);
while (entry){ while (entry){
output << std::string(indent + 4, ' '); output << std::string(indent + 4, ' ');
stream_pids[entry.getElementaryPid()] = entry.getCodec() + std::string(" ") + entry.getStreamTypeString(); stream_pids[entry.getElementaryPid()] =
output << "Stream " << entry.getElementaryPid() << ": " << stream_pids[entry.getElementaryPid()] << " (" << entry.getStreamType() << ")" << std::endl; entry.getCodec() + std::string(" ") + entry.getStreamTypeString();
output << "Stream " << entry.getElementaryPid() << ": " << stream_pids[entry.getElementaryPid()]
<< " (" << entry.getStreamType() << ")" << std::endl;
output << ProgramDescriptors(entry.getESInfo(), entry.getESInfoLength()).toPrettyString(indent + 6); output << ProgramDescriptors(entry.getESInfo(), entry.getESInfoLength()).toPrettyString(indent + 6);
entry.advance(); entry.advance();
} }
output << std::string(indent + 2, ' ') << "CRC32: " << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << getCRC() << std::dec << std::endl; output << std::string(indent + 2, ' ') << "CRC32: " << std::hex << std::setw(8)
<< std::setfill('0') << std::uppercase << getCRC() << std::dec << std::endl;
return output.str(); return output.str();
} }
ProgramDescriptors::ProgramDescriptors(const char * data, const uint32_t len) : p_data(data), p_len(len){ ProgramDescriptors::ProgramDescriptors(const char *data, const uint32_t len)
} : p_data(data), p_len(len){}
/// Returns the ISO-629 language code, or "und" if unknown. /// Returns the ISO-629 language code, or "und" if unknown.
std::string ProgramDescriptors::getLanguage() const{ std::string ProgramDescriptors::getLanguage() const{
@ -1145,16 +1069,20 @@ namespace TS {
case 0x61: output << "AAC-HEv2, level 3"; break; case 0x61: output << "AAC-HEv2, level 3"; break;
case 0x62: output << "AAC-HEv2, level 4"; break; case 0x62: output << "AAC-HEv2, level 4"; break;
case 0x63: output << "AAC-HEv2, level 5"; break; case 0x63: output << "AAC-HEv2, level 5"; break;
default: output << std::hex << std::setw(2) << std::setfill('0') << std::uppercase << (int)p_data[p+2] << std::dec; default:
output << std::hex << std::setw(2) << std::setfill('0') << std::uppercase
<< (int)p_data[p + 2] << std::dec;
} }
if (p_data[p + 3] & 0x80){ if (p_data[p + 3] & 0x80){
output << ", type: " << std::hex << std::setw(2) << std::setfill('0') << std::uppercase << (int)p_data[p+3] << std::dec; output << ", type: " << std::hex << std::setw(2) << std::setfill('0') << std::uppercase
<< (int)p_data[p + 3] << std::dec;
} }
output << std::endl; output << std::endl;
if (p_data[p + 1] > 2){ if (p_data[p + 1] > 2){
output << std::string(indent + 2, ' ') << "Extra data: "; output << std::string(indent + 2, ' ') << "Extra data: ";
for (uint32_t offset = 2; p + 2 + offset < p_data[p + 1]; ++offset){ for (uint32_t offset = 2; p + 2 + offset < p_data[p + 1]; ++offset){
output << std::hex << std::setw(2) << std::setfill('0') << std::uppercase << (int)p_data[p+2+offset] << std::dec; output << std::hex << std::setw(2) << std::setfill('0') << std::uppercase
<< (int)p_data[p + 2 + offset] << std::dec;
} }
} }
}break; }break;
@ -1164,7 +1092,8 @@ namespace TS {
default:{ default:{
output << std::string(indent, ' ') << "Undecoded descriptor: "; output << std::string(indent, ' ') << "Undecoded descriptor: ";
for (uint32_t i = 0; i < p_data[p + 1] + 2; ++i){ for (uint32_t i = 0; i < p_data[p + 1] + 2; ++i){
output << std::hex << std::setw(2) << std::setfill('0') << std::uppercase << (int)p_data[p+i] << std::dec; output << std::hex << std::setw(2) << std::setfill('0') << std::uppercase
<< (int)p_data[p + i] << std::dec;
} }
output << std::endl; output << std::endl;
} }
@ -1187,9 +1116,7 @@ namespace TS {
int sectionLen = 0; int sectionLen = 0;
for (std::set<long unsigned int>::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){ for (std::set<long unsigned int>::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){
sectionLen += 5; sectionLen += 5;
if (myMeta.tracks[*it].codec == "ID3"){ if (myMeta.tracks[*it].codec == "ID3"){sectionLen += myMeta.tracks[*it].init.size();}
sectionLen += myMeta.tracks[*it].init.size();
}
if (myMeta.tracks[*it].codec == "AAC"){ if (myMeta.tracks[*it].codec == "AAC"){
sectionLen += 4; // aac descriptor sectionLen += 4; // aac descriptor
if (myMeta.tracks[*it].lang.size() == 3 && myMeta.tracks[*it].lang != "und"){ if (myMeta.tracks[*it].lang.size() == 3 && myMeta.tracks[*it].lang != "und"){
@ -1211,9 +1138,7 @@ namespace TS {
break; break;
} }
} }
if (vidTrack == -1){ if (vidTrack == -1){vidTrack = *(selectedTracks.begin());}
vidTrack = *(selectedTracks.begin());
}
PMT.setPCRPID(255 + vidTrack); PMT.setPCRPID(255 + vidTrack);
PMT.setProgramInfoLength(0); PMT.setProgramInfoLength(0);
short id = 0; short id = 0;
@ -1251,51 +1176,32 @@ namespace TS {
return PMT.checkAndGetBuffer(); return PMT.checkAndGetBuffer();
} }
ServiceDescriptionEntry::ServiceDescriptionEntry(char *begin, char *end){ ServiceDescriptionEntry::ServiceDescriptionEntry(char *begin, char *end){
data = begin; data = begin;
boundary = end; boundary = end;
} }
ServiceDescriptionEntry::operator bool() const { ServiceDescriptionEntry::operator bool() const{return data && (data < boundary);}
return data && (data < boundary);
}
uint16_t ServiceDescriptionEntry::getServiceID() const{ uint16_t ServiceDescriptionEntry::getServiceID() const{return Bit::btohs(data);}
return Bit::btohs(data);
}
void ServiceDescriptionEntry::setServiceID(uint16_t val){ void ServiceDescriptionEntry::setServiceID(uint16_t val){Bit::htobs(data, val);}
Bit::htobs(data, val);
}
bool ServiceDescriptionEntry::getEITSchedule() const{ bool ServiceDescriptionEntry::getEITSchedule() const{return data[2] & 2;}
return data[2] & 2;
}
void ServiceDescriptionEntry::setEITSchedule(bool val){ void ServiceDescriptionEntry::setEITSchedule(bool val){data[2] |= 2;}
data[2] |= 2;
}
bool ServiceDescriptionEntry::getEITPresentFollowing() const{ bool ServiceDescriptionEntry::getEITPresentFollowing() const{return data[2] & 1;}
return data[2] & 1;
}
void ServiceDescriptionEntry::setEITPresentFollowing(bool val){ void ServiceDescriptionEntry::setEITPresentFollowing(bool val){data[2] |= 1;}
data[2] |= 1;
}
uint8_t ServiceDescriptionEntry::getRunningStatus() const{ uint8_t ServiceDescriptionEntry::getRunningStatus() const{return (data[3] & 0xE0) >> 5;}
return (data[3] & 0xE0) >> 5;
}
void ServiceDescriptionEntry::setRunningStatus(uint8_t val){ void ServiceDescriptionEntry::setRunningStatus(uint8_t val){
data[3] = (data[3] & 0x1F) | (val << 5); data[3] = (data[3] & 0x1F) | (val << 5);
} }
bool ServiceDescriptionEntry::getFreeCAM() const{ bool ServiceDescriptionEntry::getFreeCAM() const{return data[3] & 0x10;}
return data[3] & 0x10;
}
void ServiceDescriptionEntry::setFreeCAM(bool val){ void ServiceDescriptionEntry::setFreeCAM(bool val){
data[3] = (data[3] & 0xEF) | (val ? 0x10 : 0); data[3] = (data[3] & 0xEF) | (val ? 0x10 : 0);
@ -1305,9 +1211,7 @@ namespace TS {
return ((data[3] << 8) | data[4]) & 0x0FFF; return ((data[3] << 8) | data[4]) & 0x0FFF;
} }
const char * ServiceDescriptionEntry::getESInfo() const{ const char *ServiceDescriptionEntry::getESInfo() const{return data + 5;}
return data + 5;
}
void ServiceDescriptionEntry::setESInfo(const std::string &newInfo){ void ServiceDescriptionEntry::setESInfo(const std::string &newInfo){
data[3] = ((newInfo.size() >> 8) & 0x0F) | (data[3] & 0xF0); data[3] = ((newInfo.size() >> 8) & 0x0F) | (data[3] & 0xF0);
@ -1316,9 +1220,7 @@ namespace TS {
} }
void ServiceDescriptionEntry::advance(){ void ServiceDescriptionEntry::advance(){
if (!(*this)) { if (!(*this)){return;}
return;
}
data += 5 + getESInfoLength(); data += 5 + getESInfoLength();
} }
@ -1445,20 +1347,22 @@ namespace TS {
ServiceDescriptionEntry ServiceDescriptionTable::getEntry(int index) const{ ServiceDescriptionEntry ServiceDescriptionTable::getEntry(int index) const{
int dataOffset = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset(); int dataOffset = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset();
ServiceDescriptionEntry res((char*)(strBuf + dataOffset + 12), (char*)(strBuf + dataOffset + getSectionLength()) ); ServiceDescriptionEntry res((char *)(strBuf + dataOffset + 12),
for (int i = 0; i < index; i++){ (char *)(strBuf + dataOffset + getSectionLength()));
res.advance(); for (int i = 0; i < index; i++){res.advance();}
}
return res; return res;
} }
int ServiceDescriptionTable::getCRC() const{ int ServiceDescriptionTable::getCRC() const{
unsigned int loc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset() + getSectionLength(); unsigned int loc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) +
return ((int)(strBuf[loc]) << 24) | ((int)(strBuf[loc + 1]) << 16) | ((int)(strBuf[loc + 2]) << 8) | strBuf[loc + 3]; getOffset() + getSectionLength();
return ((int)(strBuf[loc]) << 24) | ((int)(strBuf[loc + 1]) << 16) |
((int)(strBuf[loc + 2]) << 8) | strBuf[loc + 3];
} }
void ServiceDescriptionTable::calcCRC(){ void ServiceDescriptionTable::calcCRC(){
unsigned int loc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset() + getSectionLength(); unsigned int loc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) +
getOffset() + getSectionLength();
unsigned int newVal; // this will hold the CRC32 value; unsigned int newVal; // this will hold the CRC32 value;
unsigned int pidLoc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset() + 1; unsigned int pidLoc = 4 + (getAdaptationField() > 1 ? getAdaptationFieldLen() + 1 : 0) + getOffset() + 1;
newVal = checksum::crc32(-1, strBuf + pidLoc, loc - pidLoc); // calculating checksum over all the fields from table ID to the last stream element newVal = checksum::crc32(-1, strBuf + pidLoc, loc - pidLoc); // calculating checksum over all the fields from table ID to the last stream element
@ -1481,9 +1385,11 @@ namespace TS {
output << std::string(indent + 2, ' ') << "Section Length: " << getSectionLength() << std::endl; output << std::string(indent + 2, ' ') << "Section Length: " << getSectionLength() << std::endl;
output << std::string(indent + 2, ' ') << "TS Stream ID: " << getTSStreamID() << std::endl; output << std::string(indent + 2, ' ') << "TS Stream ID: " << getTSStreamID() << std::endl;
output << std::string(indent + 2, ' ') << "Version number: " << (int)getVersionNumber() << std::endl; output << std::string(indent + 2, ' ') << "Version number: " << (int)getVersionNumber() << std::endl;
output << std::string(indent + 2, ' ') << "Current next indicator: " << (int)getCurrentNextIndicator() << std::endl; output << std::string(indent + 2, ' ')
<< "Current next indicator: " << (int)getCurrentNextIndicator() << std::endl;
output << std::string(indent + 2, ' ') << "Section number: " << (int)getSectionNumber() << std::endl; output << std::string(indent + 2, ' ') << "Section number: " << (int)getSectionNumber() << std::endl;
output << std::string(indent + 2, ' ') << "Last Section number: " << (int)getLastSectionNumber() << std::endl; output << std::string(indent + 2, ' ') << "Last Section number: " << (int)getLastSectionNumber()
<< std::endl;
output << std::string(indent + 2, ' ') << "Original Network ID: " << getOrigID() << std::endl; output << std::string(indent + 2, ' ') << "Original Network ID: " << getOrigID() << std::endl;
ServiceDescriptionEntry entry = getEntry(0); ServiceDescriptionEntry entry = getEntry(0);
while (entry){ while (entry){
@ -1506,7 +1412,8 @@ namespace TS {
output << ProgramDescriptors(entry.getESInfo(), entry.getESInfoLength()).toPrettyString(indent + 6); output << ProgramDescriptors(entry.getESInfo(), entry.getESInfoLength()).toPrettyString(indent + 6);
entry.advance(); entry.advance();
} }
output << std::string(indent + 2, ' ') << "CRC32: " << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << getCRC() << std::dec << std::endl; output << std::string(indent + 2, ' ') << "CRC32: " << std::hex << std::setw(8)
<< std::setfill('0') << std::uppercase << getCRC() << std::dec << std::endl;
return output.str(); return output.str();
} }
@ -1542,7 +1449,4 @@ namespace TS {
return SDT.checkAndGetBuffer(); return SDT.checkAndGetBuffer();
} }
} }// namespace TS

Some files were not shown because too many files have changed in this diff Show more