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

@ -6,66 +6,55 @@
#include "defines.h"
namespace aac {
namespace aac{
adts::adts(){
data = NULL;
len = 0;
}
adts::adts(const char * _data, unsigned long _len){
adts::adts(const char *_data, unsigned long _len){
len = _len;
data = (char*)malloc(len);
data = (char *)malloc(len);
memcpy(data, _data, len);
}
bool adts::sameHeader(const adts & rhs) const {
bool adts::sameHeader(const adts &rhs) const{
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){
data = NULL;
len = 0;
*this = rhs;
}
adts& adts::operator = (const adts & rhs){
if (data){
free(data);
}
adts &adts::operator=(const adts &rhs){
if (data){free(data);}
len = rhs.len;
data = (char*)malloc(len);
data = (char *)malloc(len);
memcpy(data, rhs.data, len);
return * this;
return *this;
}
adts::~adts(){
if (data){
free(data);
}
if (data){free(data);}
}
unsigned long adts::getAACProfile() const{
if (!data || !len){
return 0;
}
if (!data || !len){return 0;}
return ((data[2] >> 6) & 0x03) + 1;
}
unsigned long adts::getFrequencyIndex() const{
if (!data || !len){
return 0;
}
if (!data || !len){return 0;}
return ((data[2] >> 2) & 0x0F);
}
unsigned long adts::getFrequency() const{
if (!data || len < 3){
return 0;
}
switch(getFrequencyIndex()){
if (!data || len < 3){return 0;}
switch (getFrequencyIndex()){
case 0: return 96000; break;
case 1: return 88200; break;
case 2: return 64000; break;
@ -84,55 +73,43 @@ namespace aac {
}
unsigned long adts::getChannelConfig() const{
if (!data || !len){
return 0;
}
if (!data || !len){return 0;}
return ((data[2] & 0x01) << 2) | ((data[3] >> 6) & 0x03);
}
unsigned long adts::getChannelCount() const{
if (!data || !len){
return 0;
}
if (!data || !len){return 0;}
return (getChannelConfig() == 7 ? 8 : getChannelConfig());
}
unsigned long adts::getHeaderSize() const{
if (!data || !len){
return 0;
}
if (!data || !len){return 0;}
return (data[1] & 0x01 ? 7 : 9);
}
unsigned long adts::getCompleteSize() const{
if (!data || len < 6){
return 0;
}
if (!data || len < 6){return 0;}
return (((data[3] & 0x03) << 11) | (data[4] << 3) | ((data[5] >> 5) & 0x07));
}
unsigned long adts::getPayloadSize() const{
unsigned long ret = getCompleteSize();
if (!ret){return ret;}//catch zero length
if (!ret){return ret;}// catch zero length
if (ret >= getHeaderSize()){
ret -= getHeaderSize();
}else{
return 0;//catch size less than header size (corrupt data)
return 0; // catch size less than header size (corrupt data)
}
return ret;
}
unsigned long adts::getSampleCount() const{
if (!data || len < 7){
return 0;
}
return ((data[6] & 0x03) + 1) * 1024;//Number of samples in this frame * 1024
if (!data || len < 7){return 0;}
return ((data[6] & 0x03) + 1) * 1024; // Number of samples in this frame * 1024
}
char * adts::getPayload() {
if (!data || !len){
return 0;
}
char *adts::getPayload(){
if (!data || !len){return 0;}
return data + getHeaderSize();
}
std::string adts::toPrettyString() const{
@ -147,12 +124,8 @@ namespace aac {
}else{
res << " MPEG-4" << std::endl;
}
if ((data[1] & 0x6) != 0){
res << " Non-zero layer!" << std::endl;
}
if ((data[1] & 0x1) == 0x0){
res << " CRC present" << std::endl;
}
if ((data[1] & 0x6) != 0){res << " Non-zero layer!" << std::endl;}
if ((data[1] & 0x1) == 0x0){res << " CRC present" << std::endl;}
res << " MPEG-4 audio object type: " << getAACProfile() << std::endl;
res << " Frequency: " << getFrequency() << "Hz" << std::endl;
res << " Channels: " << getChannelCount() << std::endl;
@ -161,9 +134,10 @@ namespace aac {
return res.str();
}
adts::operator bool() const{
return hasSync() && len && len >= getHeaderSize() && getFrequency() && getChannelCount() && getSampleCount();
return hasSync() && len && len >= getHeaderSize() && getFrequency() && getChannelCount() &&
getSampleCount();
}
bool adts::hasSync() const{
return len && (((int)data[0] << 4) | ((data[1] >> 4) & 0x0F)) == 0xfff;
}
}
}// namespace aac

View file

@ -1,16 +1,16 @@
#include "bitstream.h"
#include <stdint.h>
#include <string>
#include "bitstream.h"
namespace aac {
class adts {
namespace aac{
class adts{
public:
adts();
adts(const char * _data, unsigned long _len);
adts(const adts & rhs);
adts(const char *_data, unsigned long _len);
adts(const adts &rhs);
~adts();
adts& operator = (const adts & rhs);
bool sameHeader(const adts & rhs) const;
adts &operator=(const adts &rhs);
bool sameHeader(const adts &rhs) const;
unsigned long getAACProfile() const;
unsigned long getFrequencyIndex() const;
unsigned long getFrequency() const;
@ -21,21 +21,22 @@ namespace aac {
unsigned long getCompleteSize() const;
unsigned long getSampleCount() const;
bool hasSync() const;
char * getPayload();
char *getPayload();
std::string toPrettyString() const;
operator bool() const;
private:
char * data;
char *data;
unsigned long len;
};
class AudSpecConf{
public:
static inline uint32_t rate(const std::string & conf){
static inline uint32_t rate(const std::string &conf){
Utils::bitstream bs;
bs.append(conf.data(), conf.size());
if (bs.get(5) == 31){bs.skip(6);}//skip object type
switch (bs.get(4)){//frequency index
if (bs.get(5) == 31){bs.skip(6);}// skip object type
switch (bs.get(4)){// frequency index
case 0: return 96000;
case 1: return 88200;
case 2: return 64000;
@ -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 name Indice name for any new object created.
/// \returns A single AMF::Object, parsed from the raw data.
AMF::Object AMF::parseOne(const unsigned char *&data, unsigned int &len, unsigned int &i,
std::string name){
AMF::Object AMF::parseOne(const unsigned char *&data, unsigned int &len, unsigned int &i, std::string name){
std::string tmpstr;
unsigned int tmpi = 0;
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);
break;
case AMF::AMF0_XMLDOC:
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
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
tmpstr.clear(); // clean tmpstr, just to be sure
tmpstr.append((const char *)data + i + 5, (size_t)tmpi); // add the string data
i += tmpi + 5; // skip length+size+1 forwards
return AMF::Object(name, tmpstr, AMF::AMF0_XMLDOC);
break;
case AMF::AMF0_LONGSTRING:
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
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
tmpstr.clear(); // clean tmpstr, just to be sure
tmpstr.append((const char *)data + i + 5, (size_t)tmpi); // add the string data
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.append((const char *)data + i + 2, (size_t)tmpi); // add the string data
i += tmpi + 2; // skip length+size forwards
ret.addContent(AMF::parseOne(
data, len, i,
ret.addContent(AMF::parseOne(data, len, i,
tmpstr)); // add content, recursively parsed, updating i, setting indice to tmpstr
}
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.append((const char *)data + i + 2, (size_t)tmpi); // add the string data
i += tmpi + 2; // skip length+size forwards
ret.addContent(AMF::parseOne(
data, len, i,
ret.addContent(AMF::parseOne(data, len, i,
tmpstr)); // add content, recursively parsed, updating i, setting indice to tmpstr
}
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.append((const char *)data + i + 2, (size_t)tmpi); // add the string data
i += tmpi + 2; // skip length+size forwards
ret.addContent(AMF::parseOne(
data, len, i,
ret.addContent(AMF::parseOne(data, len, i,
tmpstr)); // add content, recursively parsed, updating i, setting indice to tmpstr
}
i += 3; // skip 0x000009
@ -454,12 +448,10 @@ AMF::Object AMF::parseOne(const unsigned char *&data, unsigned int &len, unsigne
}break;
case 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 +
data[i + 4]; // set tmpi to array length
tmpi = data[i + 1] * 256 * 256 * 256 + data[i + 2] * 256 * 256 + data[i + 3] * 256 + data[i + 4]; // set tmpi to array length
i += 5; // skip size+1 forwards
while (tmpi > 0){// while not done parsing array
ret.addContent(
AMF::parseOne(data, len, i, "arrVal")); // add content, recursively parsed, updating i
ret.addContent(AMF::parseOne(data, len, i, "arrVal")); // add content, recursively parsed, updating i
--tmpi;
}
return ret;
@ -712,8 +704,7 @@ std::string AMF::Object3::Pack(){
/// \param i Current parsing position in the raw data.
/// \param name Indice name for any new object created.
/// \returns A single AMF::Object3, parsed from the raw data.
AMF::Object3 AMF::parseOne3(const unsigned char *&data, unsigned int &len, unsigned int &i,
std::string name){
AMF::Object3 AMF::parseOne3(const unsigned char *&data, unsigned int &len, unsigned int &i, std::string name){
std::string tmpstr;
unsigned int tmpi = 0;
unsigned int arrsize = 0;
@ -974,13 +965,11 @@ AMF::Object3 AMF::parseOne3(const unsigned char *&data, unsigned int &len, unsig
if (tmpi > 0){
tmpstr.clear(); // clean tmpstr, just to be sure
tmpstr.append((const char *)data + i, (size_t)tmpi); // add the string data
ret.addContent(
AMF::parseOne3(data, len, i, tmpstr)); // add content, recursively parsed, updating i
ret.addContent(AMF::parseOne3(data, len, i, tmpstr)); // add content, recursively parsed, updating i
}
}while (tmpi > 0);
while (arrsize > 0){// while not done parsing array
ret.addContent(
AMF::parseOne3(data, len, i, "arrVal")); // add content, recursively parsed, updating i
ret.addContent(AMF::parseOne3(data, len, i, "arrVal")); // add content, recursively parsed, updating i
--arrsize;
}
return ret;
@ -1046,8 +1035,7 @@ AMF::Object3 AMF::parseOne3(const unsigned char *&data, unsigned int &len, unsig
if (tmpi > 0){
tmpstr.clear(); // clean tmpstr, just to be sure
tmpstr.append((const char *)data + i, (size_t)tmpi); // add the string data
ret.addContent(
AMF::parseOne3(data, len, i, tmpstr)); // add content, recursively parsed, updating i
ret.addContent(AMF::parseOne3(data, len, i, tmpstr)); // add content, recursively parsed, updating i
}
}while (tmpi > 0); // keep reading dynamic values until empty string
}// dynamic types
@ -1081,4 +1069,3 @@ AMF::Object3 AMF::parse3(const unsigned char *data, unsigned int len){
AMF::Object3 AMF::parse3(std::string data){
return AMF::parse3((const unsigned char *)data.c_str(), data.size());
}// parse

View file

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

View file

@ -1,19 +1,17 @@
#include "auth.h"
#include <string.h>
#include <stdio.h>
#include <inttypes.h>
#include <sstream>
#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.
std::string md5(std::string input) {
return md5(input.data(), input.size());
}
std::string md5(std::string input){return md5(input.data(), input.size());}
/// 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){
char output[16];
md5bin(input, in_len, output);
std::stringstream outStr;
@ -24,12 +22,10 @@ namespace Secure {
}
/// Calculates a SHA256 digest as per NSAs SHA-2, returning it as a hexadecimal alphanumeric string.
std::string sha256(std::string input) {
return sha256(input.data(), input.size());
}
std::string sha256(std::string input){return sha256(input.data(), input.size());}
/// 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){
char output[32];
sha256bin(input, in_len, output);
std::stringstream outStr;
@ -42,14 +38,28 @@ namespace Secure {
/// Adds 64 bytes of data to the current MD5 hash.
/// hash is the current hash, represented by 4 unsigned longs.
/// data is the 64 bytes of data that need to be added.
static inline void md5_add64(uint32_t * hash, const char * data){
//Inspired by the pseudocode as available on Wikipedia on March 2nd, 2015.
static inline void md5_add64(uint32_t *hash, const char *data){
// Inspired by the pseudocode as available on Wikipedia on March 2nd, 2015.
uint32_t M[16];
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 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};
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 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 B = hash[1];
uint32_t C = hash[2];
@ -61,19 +71,19 @@ namespace Secure {
g = i;
}else if (i < 32){
F = (D & B) | ((~D) & C);
g = (5*i + 1) % 16;
g = (5 * i + 1) % 16;
}else if (i < 48){
F = B ^ C ^ D;
g = (3*i + 5) % 16;
g = (3 * i + 5) % 16;
}else{
F = C ^ (B | (~D));
g = (7*i) % 16;
g = (7 * i) % 16;
}
uint32_t dTemp = D;
D = C;
C = B;
uint32_t x = A + F + K[i] + M[g];
B += (x << shift[i] | (x >> (32-shift[i])));
B += (x << shift[i] | (x >> (32 - shift[i])));
A = dTemp;
}
hash[0] += A;
@ -84,31 +94,31 @@ namespace Secure {
/// Calculates a MD5 digest as per rfc1321, returning it as binary.
/// Assumes output is big enough to contain 16 bytes of data.
void md5bin(const char * input, const unsigned int in_len, char * output){
//Initialize the hash, according to MD5 spec.
uint32_t hash[] = {0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476};
//Add as many whole blocks of 64 bytes as possible from the input, until < 64 are left.
void md5bin(const char *input, const unsigned int in_len, char *output){
// Initialize the hash, according to MD5 spec.
uint32_t hash[] ={0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476};
// Add as many whole blocks of 64 bytes as possible from the input, until < 64 are left.
unsigned int offset = 0;
while (offset+64 <= in_len){
md5_add64(hash, input+offset);
while (offset + 64 <= in_len){
md5_add64(hash, input + offset);
offset += 64;
}
//now, copy the remainder to a 64 byte buffer.
// now, copy the remainder to a 64 byte buffer.
char buffer[64];
memcpy(buffer, input+offset, in_len-offset);
//Calculate how much we've filled in that buffer
memcpy(buffer, input + offset, in_len - offset);
// Calculate how much we've filled in that buffer
offset = in_len - offset;
//We know at least 1 byte must be empty, so we can safely do this
buffer[offset] = 0x80;//append 0x80
//fill to the end of the buffer with zeroes
memset(buffer+offset+1, 0, 64-offset-1);
// We know at least 1 byte must be empty, so we can safely do this
buffer[offset] = 0x80; // append 0x80
// fill to the end of the buffer with zeroes
memset(buffer + offset + 1, 0, 64 - offset - 1);
if (offset > 55){
//There's no space for the length, add what we have and zero it
// There's no space for the length, add what we have and zero it
md5_add64(hash, buffer);
memset(buffer, 0, 64);
}
unsigned long long bit_len = in_len << 3;
//Write the length into the last 8 bytes
// Write the length into the last 8 bytes
buffer[56] = (bit_len >> 0) & 0xff;
buffer[57] = (bit_len >> 8) & 0xff;
buffer[58] = (bit_len >> 16) & 0xff;
@ -117,24 +127,24 @@ namespace Secure {
buffer[61] = (bit_len >> 40) & 0xff;
buffer[62] = (bit_len >> 48) & 0xff;
buffer[63] = (bit_len >> 54) & 0xff;
//Add the last bit of buffer
// Add the last bit of buffer
md5_add64(hash, buffer);
//Write to output
//convert hash to hexadecimal string
output[0 ] = (hash[0] >> 0 ) & 0xff;
output[1 ] = (hash[0] >> 8 ) & 0xff;
output[2 ] = (hash[0] >> 16) & 0xff;
output[3 ] = (hash[0] >> 24) & 0xff;
output[4 ] = (hash[1] >> 0 ) & 0xff;
output[5 ] = (hash[1] >> 8 ) & 0xff;
output[6 ] = (hash[1] >> 16) & 0xff;
output[7 ] = (hash[1] >> 24) & 0xff;
output[8 ] = (hash[2] >> 0 ) & 0xff;
output[9 ] = (hash[2] >> 8 ) & 0xff;
// Write to output
// convert hash to hexadecimal string
output[0] = (hash[0] >> 0) & 0xff;
output[1] = (hash[0] >> 8) & 0xff;
output[2] = (hash[0] >> 16) & 0xff;
output[3] = (hash[0] >> 24) & 0xff;
output[4] = (hash[1] >> 0) & 0xff;
output[5] = (hash[1] >> 8) & 0xff;
output[6] = (hash[1] >> 16) & 0xff;
output[7] = (hash[1] >> 24) & 0xff;
output[8] = (hash[2] >> 0) & 0xff;
output[9] = (hash[2] >> 8) & 0xff;
output[10] = (hash[2] >> 16) & 0xff;
output[11] = (hash[2] >> 24) & 0xff;
output[12] = (hash[3] >> 0 ) & 0xff;
output[13] = (hash[3] >> 8 ) & 0xff;
output[12] = (hash[3] >> 0) & 0xff;
output[13] = (hash[3] >> 8) & 0xff;
output[14] = (hash[3] >> 16) & 0xff;
output[15] = (hash[3] >> 24) & 0xff;
}
@ -147,20 +157,31 @@ namespace Secure {
/// Adds 64 bytes of data to the current SHA256 hash.
/// hash is the current hash, represented by 8 unsigned longs.
/// data is the 64 bytes of data that need to be added.
static inline void sha256_add64(uint32_t * hash, const char * data){
//Inspired by the pseudocode as available on Wikipedia on March 3rd, 2015.
static inline void sha256_add64(uint32_t *hash, const char *data){
// Inspired by the pseudocode as available on Wikipedia on March 3rd, 2015.
uint32_t w[64];
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){
uint32_t s0 = rr(w[i-15], 7) ^ rr(w[i-15], 18) ^ ((w[i-15] & 0xFFFFFFFF ) >> 3);
uint32_t s1 = rr(w[i-2], 17) ^ rr(w[i-2], 19) ^ ((w[i-2] & 0xFFFFFFFF) >> 10);
w[i] = w[i-16] + s0 + w[i-7] + s1;
uint32_t s0 = rr(w[i - 15], 7) ^ rr(w[i - 15], 18) ^ ((w[i - 15] & 0xFFFFFFFF) >> 3);
uint32_t s1 = rr(w[i - 2], 17) ^ rr(w[i - 2], 19) ^ ((w[i - 2] & 0xFFFFFFFF) >> 10);
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 b = hash[1];
uint32_t c = hash[2];
@ -170,8 +191,8 @@ namespace Secure {
uint32_t g = hash[6];
uint32_t h = hash[7];
for (unsigned int i = 0; i < 64; ++i){
uint32_t temp1 = h + (rr(e, 6) ^ rr(e, 11) ^ rr(e, 25)) + (g^(e&(f^g))) + k[i] + w[i];
uint32_t temp2 = (rr(a, 2) ^ rr(a, 13) ^ rr(a, 22)) + ((a&b)|(c&(a|b)));
uint32_t temp1 = h + (rr(e, 6) ^ rr(e, 11) ^ rr(e, 25)) + (g ^ (e & (f ^ g))) + k[i] + w[i];
uint32_t temp2 = (rr(a, 2) ^ rr(a, 13) ^ rr(a, 22)) + ((a & b) | (c & (a | b)));
h = g;
g = f;
f = e;
@ -193,31 +214,32 @@ namespace Secure {
/// Calculates a SHA256 digest as per NSAs SHA-2, returning it as binary.
/// Assumes output is big enough to contain 16 bytes of data.
void sha256bin(const char * input, const unsigned int in_len, char * output){
//Initialize the hash, according to MD5 spec.
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.
void sha256bin(const char *input, const unsigned int in_len, char *output){
// Initialize the hash, according to MD5 spec.
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.
unsigned int offset = 0;
while (offset+64 <= in_len){
sha256_add64(hash, input+offset);
while (offset + 64 <= in_len){
sha256_add64(hash, input + offset);
offset += 64;
}
//now, copy the remainder to a 64 byte buffer.
// now, copy the remainder to a 64 byte buffer.
char buffer[64];
memcpy(buffer, input+offset, in_len-offset);
//Calculate how much we've filled in that buffer
memcpy(buffer, input + offset, in_len - offset);
// Calculate how much we've filled in that buffer
offset = in_len - offset;
//We know at least 1 byte must be empty, so we can safely do this
buffer[offset] = 0x80;//append 0x80
//fill to the end of the buffer with zeroes
memset(buffer+offset+1, 0, 64-offset-1);
// We know at least 1 byte must be empty, so we can safely do this
buffer[offset] = 0x80; // append 0x80
// fill to the end of the buffer with zeroes
memset(buffer + offset + 1, 0, 64 - offset - 1);
if (offset > 55){
//There's no space for the length, add what we have and zero it
// There's no space for the length, add what we have and zero it
sha256_add64(hash, buffer);
memset(buffer, 0, 64);
}
unsigned long long bit_len = in_len << 3;
//Write the length into the last 8 bytes
// Write the length into the last 8 bytes
buffer[56] = (bit_len >> 54) & 0xff;
buffer[57] = (bit_len >> 48) & 0xff;
buffer[58] = (bit_len >> 40) & 0xff;
@ -226,9 +248,9 @@ namespace Secure {
buffer[61] = (bit_len >> 16) & 0xff;
buffer[62] = (bit_len >> 8) & 0xff;
buffer[63] = (bit_len >> 0) & 0xff;
//Add the last bit of buffer
// Add the last bit of buffer
sha256_add64(hash, buffer);
//Write result to output
// Write result to output
output[3] = hash[0] & 0xff;
output[2] = (hash[0] >> 8) & 0xff;
output[1] = (hash[0] >> 16) & 0xff;
@ -263,13 +285,12 @@ namespace Secure {
output[28] = (hash[7] >> 24) & 0xff;
}
/// Performs HMAC on msg with given key.
/// Uses given hasher function, requires hashSize to be set accordingly.
/// Output is returned as hexadecimal alphanumeric string.
/// 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);
}
@ -277,7 +298,9 @@ namespace Secure {
/// Uses given hasher function, requires hashSize to be set accordingly.
/// Output is returned as hexadecimal alphanumeric string.
/// 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];
hmacbin(msg, msg_len, key, key_len, hashSize, hasher, blockSize, output);
std::stringstream outStr;
@ -291,30 +314,32 @@ namespace Secure {
/// 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.
/// 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){
char key_data[blockSize];//holds key as used in HMAC algorithm
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
if (key_len > blockSize){
//If the key given is too big, hash it.
// If the key given is too big, hash it.
hasher(key, key_len, key_data);
memset(key_data+hashSize, 0, blockSize-hashSize);
memset(key_data + hashSize, 0, blockSize - hashSize);
}else{
//Otherwise, use as-is, zero-padded if too small.
// Otherwise, use as-is, zero-padded if too small.
memcpy(key_data, key, key_len);
memset(key_data+key_len, 0, blockSize-key_len);
memset(key_data + key_len, 0, blockSize - key_len);
}
//key_data now contains hashSize bytes of key data, treated as per spec.
char inner[blockSize+msg_len];//holds data for inner hash
char outer[blockSize+hashSize];//holds data for outer hash
// key_data now contains hashSize bytes of key data, treated as per spec.
char inner[blockSize + msg_len]; // holds data for inner hash
char outer[blockSize + hashSize]; // holds data for outer hash
for (unsigned int i = 0; i < blockSize; ++i){
inner[i] = key_data[i] ^ 0x36;
outer[i] = key_data[i] ^ 0x5c;
}
//Copy the message to the inner hash data buffer
memcpy(inner+blockSize, msg, msg_len);
//Calculate the inner hash
hasher(inner, blockSize+msg_len, outer+blockSize);
//Calculate the outer hash
hasher(outer, blockSize+hashSize, output);
// Copy the message to the inner hash data buffer
memcpy(inner + blockSize, msg, msg_len);
// Calculate the inner hash
hasher(inner, blockSize + msg_len, outer + blockSize);
// Calculate the outer hash
hasher(outer, blockSize + hashSize, output);
}
/// Convenience function that returns the hexadecimal alphanumeric HMAC-SHA256 of msg and key
@ -323,15 +348,15 @@ namespace Secure {
}
/// Convenience function that returns the hexadecimal alphanumeric HMAC-SHA256 of msg and 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){
return hmac(msg, msg_len, key, key_len, 32, sha256bin, 64);
}
/// 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.
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);
}
}
}// namespace Secure

View file

@ -1,25 +1,30 @@
#pragma once
#include <string>
namespace Secure {
//MD5 hashing functions
namespace Secure{
// MD5 hashing functions
std::string md5(std::string input);
std::string md5(const char * input, const unsigned int in_len);
void md5bin(const char * input, const unsigned int in_len, char * output);
std::string md5(const char *input, const unsigned int in_len);
void md5bin(const char *input, const unsigned int in_len, char *output);
//SHA256 hashing functions
// SHA256 hashing functions
std::string sha256(std::string input);
std::string sha256(const char * input, const unsigned int in_len);
void sha256bin(const char * input, const unsigned int in_len, char * output);
std::string sha256(const char *input, const unsigned int in_len);
void sha256bin(const char *input, const unsigned int in_len, char *output);
//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(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
// 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(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
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);
void hmac_sha256bin(const char * msg, const unsigned int msg_len, const char * key, const unsigned int key_len, char * output);
}
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);
}// 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.
/// WARNING: UNFINISHED. DO NOT USE.
/// \todo Finish writing this - untested atm.
void Bit::setMSB(char *pointer, unsigned int offsetBits, unsigned int dataBits,
unsigned long long value){
void Bit::setMSB(char *pointer, unsigned int offsetBits, unsigned int dataBits, unsigned long long value){
// Set the pointer to the last byte we need to be setting
pointer += (offsetBits + dataBits) >> 3;
// 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 ||
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 getByName(char *pointer);
// bitfield setters
void setMSB(char *pointer, unsigned int offsetBits, unsigned int dataBits,
unsigned long long value);
void setMSB(char *pointer, unsigned int offsetBits, unsigned int dataBits, unsigned long long value);
void setByName(char *pointer);
// 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.
inline unsigned long btohl_le(const char *p){
return ((unsigned long)p[3] << 24) | ((unsigned long)p[2] << 16) | ((unsigned long)p[1] << 8) |
p[0];
return ((unsigned long)p[3] << 24) | ((unsigned long)p[2] << 16) | ((unsigned long)p[1] << 8) | p[0];
}
/// 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){
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)p[3] << 24) | ((unsigned long)p[2] << 16) | ((unsigned long)p[1] << 8) |
p[0];
((unsigned long)p[3] << 24) | ((unsigned long)p[2] << 16) | ((unsigned long)p[1] << 8) | p[0];
}
/// Stores a long value of val in little endian to the pointer p.
@ -188,4 +185,3 @@ namespace Bit{
}
}// namespace Bit

View file

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

View file

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

View file

@ -1,48 +1,44 @@
#include "certificate.h"
#include "defines.h"
Certificate::Certificate()
:rsa_ctx(NULL)
{
memset((void*)&cert, 0x00, sizeof(cert));
memset((void*)&key, 0x00, sizeof(key));
Certificate::Certificate() : rsa_ctx(NULL){
memset((void *)&cert, 0x00, sizeof(cert));
memset((void *)&key, 0x00, sizeof(key));
}
int Certificate::init(const std::string &countryName,
const std::string &organization,
const std::string& commonName)
{
int Certificate::init(const std::string &countryName, const std::string &organization,
const std::string &commonName){
mbedtls_ctr_drbg_context rand_ctx = {};
mbedtls_entropy_context entropy_ctx = {};
mbedtls_x509write_cert write_cert = {};
mbedtls_ctr_drbg_context rand_ctx ={};
mbedtls_entropy_context entropy_ctx ={};
mbedtls_x509write_cert write_cert ={};
const char* personalisation = "mbedtls-self-signed-key";
std::string subject_name = "C=" +countryName +",O=" +organization +",CN=" +commonName;
time_t time_from = { 0 };
time_t time_to = { 0 };
char time_from_str[20] = { 0 };
char time_to_str[20] = { 0 };
mbedtls_mpi serial_mpi = { 0 };
char serial_hex[17] = { 0 };
const char *personalisation = "mbedtls-self-signed-key";
std::string subject_name = "C=" + countryName + ",O=" + organization + ",CN=" + commonName;
time_t time_from ={0};
time_t time_to ={0};
char time_from_str[20] ={0};
char time_to_str[20] ={0};
mbedtls_mpi serial_mpi ={0};
char serial_hex[17] ={0};
uint64_t serial_num = 0;
uint8_t* serial_ptr = (uint8_t*)&serial_num;
uint8_t *serial_ptr = (uint8_t *)&serial_num;
int r = 0;
int i = 0;
uint8_t buf[4096] = { 0 };
uint8_t buf[4096] ={0};
// validate
if (countryName.empty()) {
if (countryName.empty()){
FAIL_MSG("Given `countryName`, C=<countryName>, is empty.");
r = -1;
goto error;
}
if (organization.empty()) {
if (organization.empty()){
FAIL_MSG("Given `organization`, O=<organization>, is empty.");
r = -2;
goto error;
}
if (commonName.empty()) {
if (commonName.empty()){
FAIL_MSG("Given `commonName`, CN=<commonName>, is empty.");
r = -3;
goto error;
@ -51,8 +47,9 @@ int Certificate::init(const std::string &countryName,
// initialize random number generator
mbedtls_ctr_drbg_init(&rand_ctx);
mbedtls_entropy_init(&entropy_ctx);
r = mbedtls_ctr_drbg_seed(&rand_ctx, mbedtls_entropy_func, &entropy_ctx, (const unsigned char*)personalisation, strlen(personalisation));
if (0 != r) {
r = mbedtls_ctr_drbg_seed(&rand_ctx, mbedtls_entropy_func, &entropy_ctx,
(const unsigned char *)personalisation, strlen(personalisation));
if (0 != r){
FAIL_MSG("Failed to initialize and seed the entropy context.");
r = -10;
goto error;
@ -61,21 +58,21 @@ int Certificate::init(const std::string &countryName,
// initialize the public key context
mbedtls_pk_init(&key);
r = mbedtls_pk_setup(&key, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
if (0 != r) {
if (0 != r){
FAIL_MSG("Faild to initialize the PK context.");
r = -20;
goto error;
}
rsa_ctx = mbedtls_pk_rsa(key);
if (NULL == rsa_ctx) {
if (NULL == rsa_ctx){
FAIL_MSG("Failed to get the RSA context from from the public key context (key).");
r = -30;
goto error;
}
r = mbedtls_rsa_gen_key(rsa_ctx, mbedtls_ctr_drbg_random, &rand_ctx, 2048, 65537);
if (0 != r) {
if (0 != r){
FAIL_MSG("Failed to generate a private key.");
r = -40;
goto error;
@ -86,34 +83,30 @@ int Certificate::init(const std::string &countryName,
time_from = (time_from < 1000000000) ? 1000000000 : time_from;
time_to = time_from + (60 * 60 * 24 * 365); // valid for a year
if (time_to < time_from) {
time_to = INT_MAX;
}
if (time_to < time_from){time_to = INT_MAX;}
r = strftime(time_from_str, sizeof(time_from_str), "%Y%m%d%H%M%S", gmtime(&time_from));
if (0 == r) {
if (0 == r){
FAIL_MSG("Failed to generate the valid-from time string.");
r = -50;
goto error;
}
r = strftime(time_to_str, sizeof(time_to_str), "%Y%m%d%H%M%S", gmtime(&time_to));
if (0 == r) {
if (0 == r){
FAIL_MSG("Failed to generate the valid-to time string.");
r = -60;
goto error;
}
r = mbedtls_ctr_drbg_random((void*)&rand_ctx, (uint8_t*)&serial_num, sizeof(serial_num));
if (0 != r) {
r = mbedtls_ctr_drbg_random((void *)&rand_ctx, (uint8_t *)&serial_num, sizeof(serial_num));
if (0 != r){
FAIL_MSG("Failed to generate a random u64.");
r = -70;
goto error;
}
for (i = 0; i < 8; ++i) {
sprintf(serial_hex + (i * 2), "%02x", serial_ptr[i]);
}
for (i = 0; i < 8; ++i){sprintf(serial_hex + (i * 2), "%02x", serial_ptr[i]);}
// start creating the certificate
mbedtls_x509write_crt_init(&write_cert);
@ -122,42 +115,42 @@ int Certificate::init(const std::string &countryName,
mbedtls_x509write_crt_set_subject_key(&write_cert, &key);
r = mbedtls_x509write_crt_set_subject_name(&write_cert, subject_name.c_str());
if (0 != r) {
if (0 != r){
FAIL_MSG("Failed to set the subject name.");
r = -80;
goto error;
}
r = mbedtls_x509write_crt_set_issuer_name(&write_cert, subject_name.c_str());
if (0 != r) {
if (0 != r){
FAIL_MSG("Failed to set the issuer name.");
r = -90;
goto error;
}
r = mbedtls_x509write_crt_set_validity(&write_cert, time_from_str, time_to_str);
if (0 != r) {
if (0 != r){
FAIL_MSG("Failed to set the x509 validity string.");
r = -100;
goto error;
}
r = mbedtls_x509write_crt_set_basic_constraints(&write_cert, 0, -1);
if (0 != r) {
if (0 != r){
FAIL_MSG("Failed ot set the basic constraints for the certificate.");
r = -110;
goto error;
}
r = mbedtls_x509write_crt_set_subject_key_identifier(&write_cert);
if (0 != r) {
if (0 != r){
FAIL_MSG("Failed to set the subjectKeyIdentifier.");
r = -120;
goto error;
}
r = mbedtls_x509write_crt_set_authority_key_identifier(&write_cert);
if (0 != r) {
if (0 != r){
FAIL_MSG("Failed to set the authorityKeyIdentifier.");
r = -130;
goto error;
@ -167,7 +160,7 @@ int Certificate::init(const std::string &countryName,
mbedtls_mpi_init(&serial_mpi);
mbedtls_mpi_read_string(&serial_mpi, 16, serial_hex);
r = mbedtls_x509write_crt_set_serial(&write_cert, &serial_mpi);
if (0 != r) {
if (0 != r){
FAIL_MSG("Failed to set the certificate serial.");
r = -140;
goto error;
@ -175,7 +168,7 @@ int Certificate::init(const std::string &countryName,
// write the certificate into a PEM structure
r = mbedtls_x509write_crt_pem(&write_cert, buf, sizeof(buf), mbedtls_ctr_drbg_random, &rand_ctx);
if (0 != r) {
if (0 != r){
FAIL_MSG("Failed to create the PEM data from the x509 write structure.");
r = -150;
goto error;
@ -188,15 +181,15 @@ int Certificate::init(const std::string &countryName,
// function.
mbedtls_x509_crt_init(&cert);
r = mbedtls_x509_crt_parse(&cert, (const unsigned char*)buf, strlen((char*)buf) + 1);
if (0 != r) {
mbedtls_strerror(r, (char*)buf, sizeof(buf));
r = mbedtls_x509_crt_parse(&cert, (const unsigned char *)buf, strlen((char *)buf) + 1);
if (0 != r){
mbedtls_strerror(r, (char *)buf, sizeof(buf));
FAIL_MSG("Failed to convert the mbedtls_x509write_crt into a mbedtls_x509_crt: %s", buf);
r = -160;
goto error;
}
error:
error:
// cleanup
mbedtls_ctr_drbg_free(&rand_ctx);
@ -204,37 +197,32 @@ int Certificate::init(const std::string &countryName,
mbedtls_x509write_crt_free(&write_cert);
mbedtls_mpi_free(&serial_mpi);
if (r < 0) {
shutdown();
}
if (r < 0){shutdown();}
return r;
}
int Certificate::shutdown() {
int Certificate::shutdown(){
rsa_ctx = NULL;
mbedtls_pk_free(&key);
mbedtls_x509_crt_free(&cert);
return 0;
}
std::string Certificate::getFingerprintSha256() {
std::string Certificate::getFingerprintSha256(){
uint8_t fingerprint_raw[32] = {};
uint8_t fingerprint_hex[128] = {};
uint8_t fingerprint_raw[32] ={};
uint8_t fingerprint_hex[128] ={};
mbedtls_md_type_t hash_type = MBEDTLS_MD_SHA256;
mbedtls_sha256(cert.raw.p, cert.raw.len, fingerprint_raw, 0);
for (int i = 0; i < 32; ++i) {
sprintf((char*)(fingerprint_hex + (i * 3)), ":%02X", (int)fingerprint_raw[i]);
for (int i = 0; i < 32; ++i){
sprintf((char *)(fingerprint_hex + (i * 3)), ":%02X", (int)fingerprint_raw[i]);
}
fingerprint_hex[32 * 3] = '\0';
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;
}

View file

@ -10,25 +10,25 @@
*/
#include <string>
#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_csr.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/md.h>
#include <mbedtls/error.h>
#include <mbedtls/sha256.h>
#include <string>
class Certificate {
class Certificate{
public:
Certificate();
int init(const std::string &countryName, const std::string &organization, const std::string& commonName);
int init(const std::string &countryName, const std::string &organization, const std::string &commonName);
int shutdown();
std::string getFingerprintSha256();
public:
mbedtls_x509_crt cert;
mbedtls_pk_context key; /* key context, stores private and public key. */
mbedtls_rsa_context* rsa_ctx; /* rsa context, stored in key_ctx */
mbedtls_rsa_context *rsa_ctx; /* rsa context, stored in key_ctx */
};

View file

@ -1,75 +1,48 @@
#include <stddef.h>
namespace checksum {
inline unsigned int crc32c(unsigned int crc, const char * data, size_t len) {
static const unsigned int table[256] = {
0x00000000U, 0x04C11DB7U, 0x09823B6EU, 0x0D4326D9U,
0x130476DCU, 0x17C56B6BU, 0x1A864DB2U, 0x1E475005U,
0x2608EDB8U, 0x22C9F00FU, 0x2F8AD6D6U, 0x2B4BCB61U,
0x350C9B64U, 0x31CD86D3U, 0x3C8EA00AU, 0x384FBDBDU,
0x4C11DB70U, 0x48D0C6C7U, 0x4593E01EU, 0x4152FDA9U,
0x5F15ADACU, 0x5BD4B01BU, 0x569796C2U, 0x52568B75U,
0x6A1936C8U, 0x6ED82B7FU, 0x639B0DA6U, 0x675A1011U,
0x791D4014U, 0x7DDC5DA3U, 0x709F7B7AU, 0x745E66CDU,
0x9823B6E0U, 0x9CE2AB57U, 0x91A18D8EU, 0x95609039U,
0x8B27C03CU, 0x8FE6DD8BU, 0x82A5FB52U, 0x8664E6E5U,
0xBE2B5B58U, 0xBAEA46EFU, 0xB7A96036U, 0xB3687D81U,
0xAD2F2D84U, 0xA9EE3033U, 0xA4AD16EAU, 0xA06C0B5DU,
0xD4326D90U, 0xD0F37027U, 0xDDB056FEU, 0xD9714B49U,
0xC7361B4CU, 0xC3F706FBU, 0xCEB42022U, 0xCA753D95U,
0xF23A8028U, 0xF6FB9D9FU, 0xFBB8BB46U, 0xFF79A6F1U,
0xE13EF6F4U, 0xE5FFEB43U, 0xE8BCCD9AU, 0xEC7DD02DU,
0x34867077U, 0x30476DC0U, 0x3D044B19U, 0x39C556AEU,
0x278206ABU, 0x23431B1CU, 0x2E003DC5U, 0x2AC12072U,
0x128E9DCFU, 0x164F8078U, 0x1B0CA6A1U, 0x1FCDBB16U,
0x018AEB13U, 0x054BF6A4U, 0x0808D07DU, 0x0CC9CDCAU,
0x7897AB07U, 0x7C56B6B0U, 0x71159069U, 0x75D48DDEU,
0x6B93DDDBU, 0x6F52C06CU, 0x6211E6B5U, 0x66D0FB02U,
0x5E9F46BFU, 0x5A5E5B08U, 0x571D7DD1U, 0x53DC6066U,
0x4D9B3063U, 0x495A2DD4U, 0x44190B0DU, 0x40D816BAU,
0xACA5C697U, 0xA864DB20U, 0xA527FDF9U, 0xA1E6E04EU,
0xBFA1B04BU, 0xBB60ADFCU, 0xB6238B25U, 0xB2E29692U,
0x8AAD2B2FU, 0x8E6C3698U, 0x832F1041U, 0x87EE0DF6U,
0x99A95DF3U, 0x9D684044U, 0x902B669DU, 0x94EA7B2AU,
0xE0B41DE7U, 0xE4750050U, 0xE9362689U, 0xEDF73B3EU,
0xF3B06B3BU, 0xF771768CU, 0xFA325055U, 0xFEF34DE2U,
0xC6BCF05FU, 0xC27DEDE8U, 0xCF3ECB31U, 0xCBFFD686U,
0xD5B88683U, 0xD1799B34U, 0xDC3ABDEDU, 0xD8FBA05AU,
0x690CE0EEU, 0x6DCDFD59U, 0x608EDB80U, 0x644FC637U,
0x7A089632U, 0x7EC98B85U, 0x738AAD5CU, 0x774BB0EBU,
0x4F040D56U, 0x4BC510E1U, 0x46863638U, 0x42472B8FU,
0x5C007B8AU, 0x58C1663DU, 0x558240E4U, 0x51435D53U,
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,
namespace checksum{
inline unsigned int crc32c(unsigned int crc, const char *data, size_t len){
static const unsigned int table[256] ={
0x00000000U, 0x04C11DB7U, 0x09823B6EU, 0x0D4326D9U, 0x130476DCU, 0x17C56B6BU, 0x1A864DB2U,
0x1E475005U, 0x2608EDB8U, 0x22C9F00FU, 0x2F8AD6D6U, 0x2B4BCB61U, 0x350C9B64U, 0x31CD86D3U,
0x3C8EA00AU, 0x384FBDBDU, 0x4C11DB70U, 0x48D0C6C7U, 0x4593E01EU, 0x4152FDA9U, 0x5F15ADACU,
0x5BD4B01BU, 0x569796C2U, 0x52568B75U, 0x6A1936C8U, 0x6ED82B7FU, 0x639B0DA6U, 0x675A1011U,
0x791D4014U, 0x7DDC5DA3U, 0x709F7B7AU, 0x745E66CDU, 0x9823B6E0U, 0x9CE2AB57U, 0x91A18D8EU,
0x95609039U, 0x8B27C03CU, 0x8FE6DD8BU, 0x82A5FB52U, 0x8664E6E5U, 0xBE2B5B58U, 0xBAEA46EFU,
0xB7A96036U, 0xB3687D81U, 0xAD2F2D84U, 0xA9EE3033U, 0xA4AD16EAU, 0xA06C0B5DU, 0xD4326D90U,
0xD0F37027U, 0xDDB056FEU, 0xD9714B49U, 0xC7361B4CU, 0xC3F706FBU, 0xCEB42022U, 0xCA753D95U,
0xF23A8028U, 0xF6FB9D9FU, 0xFBB8BB46U, 0xFF79A6F1U, 0xE13EF6F4U, 0xE5FFEB43U, 0xE8BCCD9AU,
0xEC7DD02DU, 0x34867077U, 0x30476DC0U, 0x3D044B19U, 0x39C556AEU, 0x278206ABU, 0x23431B1CU,
0x2E003DC5U, 0x2AC12072U, 0x128E9DCFU, 0x164F8078U, 0x1B0CA6A1U, 0x1FCDBB16U, 0x018AEB13U,
0x054BF6A4U, 0x0808D07DU, 0x0CC9CDCAU, 0x7897AB07U, 0x7C56B6B0U, 0x71159069U, 0x75D48DDEU,
0x6B93DDDBU, 0x6F52C06CU, 0x6211E6B5U, 0x66D0FB02U, 0x5E9F46BFU, 0x5A5E5B08U, 0x571D7DD1U,
0x53DC6066U, 0x4D9B3063U, 0x495A2DD4U, 0x44190B0DU, 0x40D816BAU, 0xACA5C697U, 0xA864DB20U,
0xA527FDF9U, 0xA1E6E04EU, 0xBFA1B04BU, 0xBB60ADFCU, 0xB6238B25U, 0xB2E29692U, 0x8AAD2B2FU,
0x8E6C3698U, 0x832F1041U, 0x87EE0DF6U, 0x99A95DF3U, 0x9D684044U, 0x902B669DU, 0x94EA7B2AU,
0xE0B41DE7U, 0xE4750050U, 0xE9362689U, 0xEDF73B3EU, 0xF3B06B3BU, 0xF771768CU, 0xFA325055U,
0xFEF34DE2U, 0xC6BCF05FU, 0xC27DEDE8U, 0xCF3ECB31U, 0xCBFFD686U, 0xD5B88683U, 0xD1799B34U,
0xDC3ABDEDU, 0xD8FBA05AU, 0x690CE0EEU, 0x6DCDFD59U, 0x608EDB80U, 0x644FC637U, 0x7A089632U,
0x7EC98B85U, 0x738AAD5CU, 0x774BB0EBU, 0x4F040D56U, 0x4BC510E1U, 0x46863638U, 0x42472B8FU,
0x5C007B8AU, 0x58C1663DU, 0x558240E4U, 0x51435D53U, 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,
};
while (len > 0) {
while (len > 0){
crc = table[*data ^ ((crc >> 24) & 0xff)] ^ (crc << 8);
data++;
len--;
@ -77,75 +50,47 @@ namespace checksum {
return crc;
}
inline unsigned int crc32LE(unsigned int crc, const char * data, size_t len) {
static const unsigned int table[256] = {
0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU,
0x076dc419U, 0x706af48fU, 0xe963a535U, 0x9e6495a3U,
0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U,
0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U,
0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U,
0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU,
0x14015c4fU, 0x63066cd9U, 0xfa0f3d63U, 0x8d080df5U,
0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0xa2677172U,
0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U,
0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U,
0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U,
0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, 0xb8bda50fU,
0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU,
0x76dc4190U, 0x01db7106U, 0x98d220bcU, 0xefd5102aU,
0x71b18589U, 0x06b6b51fU, 0x9fbfe4a5U, 0xe8b8d433U,
0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U,
0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU,
0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U,
0x65b0d9c6U, 0x12b7e950U, 0x8bbeb8eaU, 0xfcb9887cU,
0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U,
0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU,
0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0xda60b8d0U,
0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U,
0x5005713cU, 0x270241aaU, 0xbe0b1010U, 0xc90c2086U,
0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U,
0x59b33d17U, 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU,
0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU,
0xead54739U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U,
0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U,
0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU,
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
};
inline unsigned int crc32LE(unsigned int crc, const char *data, size_t len){
static const unsigned int table[256] ={
0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 0x706af48fU, 0xe963a535U,
0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU,
0xe7b82d07U, 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, 0x1adad47dU,
0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU,
0x14015c4fU, 0x63066cd9U, 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, 0x35b5a8faU, 0x42b2986cU,
0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU,
0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, 0xb8bda50fU,
0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU,
0xb6662d3dU, 0x76dc4190U, 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU,
0x086d3d2dU, 0x91646c97U, 0xe6635c01U, 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU,
0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U, 0x8bbeb8eaU,
0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU,
0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U,
0x5005713cU, 0x270241aaU, 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U,
0xce61e49fU, 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 0x2eb40d81U,
0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU, 0xead54739U,
0x9dd277afU, 0x04db2615U, 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U,
0x6906c2feU, 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);
data++;
len--;
@ -153,79 +98,49 @@ namespace checksum {
return crc;
}
inline unsigned int crc32(unsigned int crc, const char * data, size_t len) {
static const unsigned int table[256] = {
0x00000000U, 0xB71DC104U, 0x6E3B8209U, 0xD926430DU,
0xDC760413U, 0x6B6BC517U, 0xB24D861AU, 0x0550471EU,
0xB8ED0826U, 0x0FF0C922U, 0xD6D68A2FU, 0x61CB4B2BU,
0x649B0C35U, 0xD386CD31U, 0x0AA08E3CU, 0xBDBD4F38U,
0x70DB114CU, 0xC7C6D048U, 0x1EE09345U, 0xA9FD5241U,
0xACAD155FU, 0x1BB0D45BU, 0xC2969756U, 0x758B5652U,
0xC836196AU, 0x7F2BD86EU, 0xA60D9B63U, 0x11105A67U,
0x14401D79U, 0xA35DDC7DU, 0x7A7B9F70U, 0xCD665E74U,
0xE0B62398U, 0x57ABE29CU, 0x8E8DA191U, 0x39906095U,
0x3CC0278BU, 0x8BDDE68FU, 0x52FBA582U, 0xE5E66486U,
0x585B2BBEU, 0xEF46EABAU, 0x3660A9B7U, 0x817D68B3U,
0x842D2FADU, 0x3330EEA9U, 0xEA16ADA4U, 0x5D0B6CA0U,
0x906D32D4U, 0x2770F3D0U, 0xFE56B0DDU, 0x494B71D9U,
0x4C1B36C7U, 0xFB06F7C3U, 0x2220B4CEU, 0x953D75CAU,
0x28803AF2U, 0x9F9DFBF6U, 0x46BBB8FBU, 0xF1A679FFU,
0xF4F63EE1U, 0x43EBFFE5U, 0x9ACDBCE8U, 0x2DD07DECU,
0x77708634U, 0xC06D4730U, 0x194B043DU, 0xAE56C539U,
0xAB068227U, 0x1C1B4323U, 0xC53D002EU, 0x7220C12AU,
0xCF9D8E12U, 0x78804F16U, 0xA1A60C1BU, 0x16BBCD1FU,
0x13EB8A01U, 0xA4F64B05U, 0x7DD00808U, 0xCACDC90CU,
0x07AB9778U, 0xB0B6567CU, 0x69901571U, 0xDE8DD475U,
0xDBDD936BU, 0x6CC0526FU, 0xB5E61162U, 0x02FBD066U,
0xBF469F5EU, 0x085B5E5AU, 0xD17D1D57U, 0x6660DC53U,
0x63309B4DU, 0xD42D5A49U, 0x0D0B1944U, 0xBA16D840U,
0x97C6A5ACU, 0x20DB64A8U, 0xF9FD27A5U, 0x4EE0E6A1U,
0x4BB0A1BFU, 0xFCAD60BBU, 0x258B23B6U, 0x9296E2B2U,
0x2F2BAD8AU, 0x98366C8EU, 0x41102F83U, 0xF60DEE87U,
0xF35DA999U, 0x4440689DU, 0x9D662B90U, 0x2A7BEA94U,
0xE71DB4E0U, 0x500075E4U, 0x892636E9U, 0x3E3BF7EDU,
0x3B6BB0F3U, 0x8C7671F7U, 0x555032FAU, 0xE24DF3FEU,
0x5FF0BCC6U, 0xE8ED7DC2U, 0x31CB3ECFU, 0x86D6FFCBU,
0x8386B8D5U, 0x349B79D1U, 0xEDBD3ADCU, 0x5AA0FBD8U,
0xEEE00C69U, 0x59FDCD6DU, 0x80DB8E60U, 0x37C64F64U,
0x3296087AU, 0x858BC97EU, 0x5CAD8A73U, 0xEBB04B77U,
0x560D044FU, 0xE110C54BU, 0x38368646U, 0x8F2B4742U,
0x8A7B005CU, 0x3D66C158U, 0xE4408255U, 0x535D4351U,
0x9E3B1D25U, 0x2926DC21U, 0xF0009F2CU, 0x471D5E28U,
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
};
inline unsigned int crc32(unsigned int crc, const char *data, size_t len){
static const unsigned int table[256] ={
0x00000000U, 0xB71DC104U, 0x6E3B8209U, 0xD926430DU, 0xDC760413U, 0x6B6BC517U, 0xB24D861AU,
0x0550471EU, 0xB8ED0826U, 0x0FF0C922U, 0xD6D68A2FU, 0x61CB4B2BU, 0x649B0C35U, 0xD386CD31U,
0x0AA08E3CU, 0xBDBD4F38U, 0x70DB114CU, 0xC7C6D048U, 0x1EE09345U, 0xA9FD5241U, 0xACAD155FU,
0x1BB0D45BU, 0xC2969756U, 0x758B5652U, 0xC836196AU, 0x7F2BD86EU, 0xA60D9B63U, 0x11105A67U,
0x14401D79U, 0xA35DDC7DU, 0x7A7B9F70U, 0xCD665E74U, 0xE0B62398U, 0x57ABE29CU, 0x8E8DA191U,
0x39906095U, 0x3CC0278BU, 0x8BDDE68FU, 0x52FBA582U, 0xE5E66486U, 0x585B2BBEU, 0xEF46EABAU,
0x3660A9B7U, 0x817D68B3U, 0x842D2FADU, 0x3330EEA9U, 0xEA16ADA4U, 0x5D0B6CA0U, 0x906D32D4U,
0x2770F3D0U, 0xFE56B0DDU, 0x494B71D9U, 0x4C1B36C7U, 0xFB06F7C3U, 0x2220B4CEU, 0x953D75CAU,
0x28803AF2U, 0x9F9DFBF6U, 0x46BBB8FBU, 0xF1A679FFU, 0xF4F63EE1U, 0x43EBFFE5U, 0x9ACDBCE8U,
0x2DD07DECU, 0x77708634U, 0xC06D4730U, 0x194B043DU, 0xAE56C539U, 0xAB068227U, 0x1C1B4323U,
0xC53D002EU, 0x7220C12AU, 0xCF9D8E12U, 0x78804F16U, 0xA1A60C1BU, 0x16BBCD1FU, 0x13EB8A01U,
0xA4F64B05U, 0x7DD00808U, 0xCACDC90CU, 0x07AB9778U, 0xB0B6567CU, 0x69901571U, 0xDE8DD475U,
0xDBDD936BU, 0x6CC0526FU, 0xB5E61162U, 0x02FBD066U, 0xBF469F5EU, 0x085B5E5AU, 0xD17D1D57U,
0x6660DC53U, 0x63309B4DU, 0xD42D5A49U, 0x0D0B1944U, 0xBA16D840U, 0x97C6A5ACU, 0x20DB64A8U,
0xF9FD27A5U, 0x4EE0E6A1U, 0x4BB0A1BFU, 0xFCAD60BBU, 0x258B23B6U, 0x9296E2B2U, 0x2F2BAD8AU,
0x98366C8EU, 0x41102F83U, 0xF60DEE87U, 0xF35DA999U, 0x4440689DU, 0x9D662B90U, 0x2A7BEA94U,
0xE71DB4E0U, 0x500075E4U, 0x892636E9U, 0x3E3BF7EDU, 0x3B6BB0F3U, 0x8C7671F7U, 0x555032FAU,
0xE24DF3FEU, 0x5FF0BCC6U, 0xE8ED7DC2U, 0x31CB3ECFU, 0x86D6FFCBU, 0x8386B8D5U, 0x349B79D1U,
0xEDBD3ADCU, 0x5AA0FBD8U, 0xEEE00C69U, 0x59FDCD6DU, 0x80DB8E60U, 0x37C64F64U, 0x3296087AU,
0x858BC97EU, 0x5CAD8A73U, 0xEBB04B77U, 0x560D044FU, 0xE110C54BU, 0x38368646U, 0x8F2B4742U,
0x8A7B005CU, 0x3D66C158U, 0xE4408255U, 0x535D4351U, 0x9E3B1D25U, 0x2926DC21U, 0xF0009F2CU,
0x471D5E28U, 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 * end = tmpData + len;
while(tmpData < end){
crc = table[((unsigned char) crc) ^ *tmpData++] ^ (crc >> 8);
}
const char *tmpData = data;
const char *end = tmpData + len;
while (tmpData < end){crc = table[((unsigned char)crc) ^ *tmpData++] ^ (crc >> 8);}
return crc;
}
}
}// namespace checksum

View file

@ -132,8 +132,7 @@ void Util::Config::printHelp(std::ostream &output){
}
while (f.size() < longest){f.append(" ");}
if (it->isMember("arg")){
output << f << "(" << (*it)["arg"].asString() << ") " << (*it)["help"].asString()
<< std::endl;
output << f << "(" << (*it)["arg"].asString() << ") " << (*it)["help"].asString() << std::endl;
}else{
output << f << (*it)["help"].asString() << std::endl;
}
@ -141,8 +140,7 @@ void Util::Config::printHelp(std::ostream &output){
if (it->isMember("arg_num")){
f = it.key();
while (f.size() < longest){f.append(" ");}
output << f << "(" << (*it)["arg"].asString() << ") " << (*it)["help"].asString()
<< std::endl;
output << f << "(" << (*it)["arg"].asString() << ") " << (*it)["help"].asString() << std::endl;
}
}
}
@ -188,8 +186,8 @@ bool Util::Config::parseArgs(int &argc, char **&argv){
<< std::endl;
#endif
#ifdef WITH_THREADNAMES
std::cout
<< "- Flag: With threadnames. Debuggers will show sensible human-readable thread names."
std::cout << "- Flag: With threadnames. Debuggers will show sensible human-readable thread "
"names."
<< std::endl;
#endif
/*LTS-START*/
@ -210,9 +208,8 @@ bool Util::Config::parseArgs(int &argc, char **&argv){
#endif
#ifdef STATS_DELAY
if (STATS_DELAY != 15){
std::cout << "- Setting: Stats delay " << STATS_DELAY
<< ". Statistics of viewer counts are delayed by " << STATS_DELAY
<< " seconds as opposed to the default of 15 seconds. ";
std::cout << "- Setting: Stats delay " << STATS_DELAY << ". Statistics of viewer counts are delayed by "
<< STATS_DELAY << " seconds as opposed to the default of 15 seconds. ";
if (STATS_DELAY > 15){
std::cout << "This makes them more accurate." << std::endl;
}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.
JSON::Value &Util::Config::getOption(std::string optname, bool asArray){
if (!vals.isMember(optname)){
std::cout << "Fatal error: a non-existent option '" << optname << "' was accessed."
<< std::endl;
std::cout << "Fatal error: a non-existent option '" << optname << "' was accessed." << std::endl;
exit(37);
}
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);
}
int Util::Config::threadServer(Socket::Server &server_socket,
int (*callback)(Socket::Connection &)){
int Util::Config::threadServer(Socket::Server &server_socket, int (*callback)(Socket::Connection &)){
Util::Procs::socketList.insert(server_socket.getSocket());
while (is_active && server_socket.connected()){
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());
if (!is_restarting){
server_socket.close();
}
if (!is_restarting){server_socket.close();}
return 0;
}
@ -366,7 +359,7 @@ int Util::Config::serveThreadedSocket(int (*callback)(Socket::Connection &)){
server_socket = Socket::Server(0);
}else if (vals.isMember("socket")){
server_socket = Socket::Server(Util::getTmpFolder() + getString("socket"));
} else if (vals.isMember("port") && vals.isMember("interface")){
}else if (vals.isMember("port") && vals.isMember("interface")){
server_socket = Socket::Server(getInteger("port"), getString("interface"), false);
}
if (!server_socket.connected()){
@ -394,7 +387,7 @@ int Util::Config::serveForkedSocket(int (*callback)(Socket::Connection &S)){
server_socket = Socket::Server(0);
}else if (vals.isMember("socket")){
server_socket = Socket::Server(Util::getTmpFolder() + getString("socket"));
} else if (vals.isMember("port") && vals.isMember("interface")){
}else if (vals.isMember("port") && vals.isMember("interface")){
server_socket = Socket::Server(getInteger("port"), getString("interface"), false);
}
if (!server_socket.connected()){
@ -463,8 +456,7 @@ void Util::Config::signal_handler(int signum, siginfo_t *sigInfo, void *ignore){
case SI_TIMER:
case SI_ASYNCIO:
case SI_MESGQ:
INFO_MSG("Received signal %s (%d) from process %d", strsignal(signum), signum,
sigInfo->si_pid);
INFO_MSG("Received signal %s (%d) from process %d", strsignal(signum), signum, sigInfo->si_pid);
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);
}// namespace Util

View file

@ -15,18 +15,20 @@
#define DLVL_INSANE 9 // Everything is reported in insane detail.
#define DLVL_DONTEVEN 10 // All messages enabled, even pointless ones.
#define PRETTY_PRINT_TIME "%ud%uh%um%us"
#define PRETTY_ARG_TIME(t) (int)(t)/86400, ((int)(t)%86400)/3600, ((int)(t)%3600)/60, (int)(t)%60
#define PRETTY_ARG_TIME(t) \
(int)(t) / 86400, ((int)(t) % 86400) / 3600, ((int)(t) % 3600) / 60, (int)(t) % 60
#define PRETTY_PRINT_MSTIME "%ud%.2uh%.2um%.2us.%.3u"
#define PRETTY_ARG_MSTIME(t) PRETTY_ARG_TIME(t/1000), (int)(t%1000)
#define PRETTY_ARG_MSTIME(t) PRETTY_ARG_TIME(t / 1000), (int)(t % 1000)
#if DEBUG > -1
#define __STDC_FORMAT_MACROS 1
#include <stdio.h>
#include <unistd.h>
#include "config.h"
#include <inttypes.h>
#include <stdint.h>
#include "config.h"
static const char * DBG_LVL_LIST[] = {"NONE", "FAIL", "ERROR", "WARN", "INFO", "MEDIUM", "HIGH", "VERYHIGH", "EXTREME", "INSANE", "DONTEVEN"};
#include <stdio.h>
#include <unistd.h>
static const char *DBG_LVL_LIST[] ={"NONE", "FAIL", "ERROR", "WARN", "INFO", "MEDIUM",
"HIGH", "VERYHIGH", "EXTREME", "INSANE", "DONTEVEN"};
#if !defined(PRIu64)
#define PRIu64 "llu"
@ -40,15 +42,31 @@ static const char * DBG_LVL_LIST[] = {"NONE", "FAIL", "ERROR", "WARN", "INFO", "
#include <errno.h>
#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
#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
#else
#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
#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
@ -56,18 +74,16 @@ static const char * DBG_LVL_LIST[] = {"NONE", "FAIL", "ERROR", "WARN", "INFO", "
static inline void show_stackframe(){}
#else
#include <execinfo.h>
static inline void show_stackframe() {
static inline void show_stackframe(){
void *trace[16];
char **messages = 0;
int i, trace_size = 0;
trace_size = backtrace(trace, 16);
messages = backtrace_symbols(trace, trace_size);
for (i=1; i<trace_size; ++i){
for (i = 1; i < trace_size; ++i){
size_t p = 0;
while(messages[i][p] != '(' && messages[i][p] != ' ' && messages[i][p] != 0){
++p;
}
DEBUG_MSG(0, "Backtrace[%d]: %s", i, messages[i]+p);
while (messages[i][p] != '(' && messages[i][p] != ' ' && messages[i][p] != 0){++p;}
DEBUG_MSG(0, "Backtrace[%d]: %s", i, messages[i] + p);
}
}
#endif
@ -94,12 +110,12 @@ static inline void show_stackframe(){}
#endif
#ifndef SHM_DATASIZE
#define SHM_DATASIZE 20
#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
#define STATS_DELAY 15
@ -107,7 +123,7 @@ static inline void show_stackframe(){}
#define STATS_INPUT_DELAY 2
#ifndef INPUT_TIMEOUT
#define INPUT_TIMEOUT STATS_DELAY*2
#define INPUT_TIMEOUT STATS_DELAY * 2
#endif
/// The size used for stream headers for live streams
@ -157,16 +173,15 @@ static inline void show_stackframe(){}
#define SHM_STATE_LOGS "MstStateLogs"
#define SHM_STATE_ACCS "MstStateAccs"
#define SHM_STATE_STREAMS "MstStateStreams"
#define NAME_BUFFER_SIZE 200 //char buffer size for snprintf'ing shm filenames
#define NAME_BUFFER_SIZE 200 // char buffer size for snprintf'ing shm filenames
#define SHM_SESSIONS "/MstSess"
#define SHM_SESSIONS_ITEM 165 //4 byte crc, 100b streamname, 20b connector, 40b host, 1b sync
#define SHM_SESSIONS_SIZE 5248000 //5MiB = almost 32k sessions
#define SHM_SESSIONS_ITEM 165 // 4 byte crc, 100b streamname, 20b connector, 40b host, 1b sync
#define SHM_SESSIONS_SIZE 5248000 // 5MiB = almost 32k sessions
#define SHM_STREAM_ENCRYPT "MstCRYP%s" //%s stream name
#define SIMUL_TRACKS 20
#ifndef UDP_API_HOST
#define UDP_API_HOST "localhost"
#endif
@ -177,7 +192,6 @@ static inline void show_stackframe(){}
#define INVALID_TRACK_ID 0
//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.
// 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.
#define SIMULATED_LIVE_BUFFER 7000

View file

@ -1,5 +1,5 @@
#include "downloader.h"
#include "defines.h"
#include "downloader.h"
#include "encode.h"
#include "timing.h"
@ -136,7 +136,8 @@ namespace HTTP{
}
/// 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);
H.sendRequest(getSocket(), body, bodyLen, false);
H.Clean();
@ -147,7 +148,6 @@ namespace HTTP{
doRequest(link, method, body.data(), body.size());
}
/// Do a HEAD request to download the HTTP headers only, returns true on success
bool Downloader::head(const HTTP::URL &link, uint8_t maxRecursiveDepth){
if (!canRequest(link)){return false;}
@ -190,9 +190,7 @@ namespace HTTP{
}
}
if(H.protocol == "HTTP/1.0"){
getSocket().close();
}
if (H.protocol == "HTTP/1.0"){getSocket().close();}
H.headerOnly = false;
return true; // Success!
@ -218,9 +216,11 @@ namespace HTTP{
getSocket().close();
}else{
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{
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();
}
@ -230,7 +230,8 @@ namespace HTTP{
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];
if (byteEnd <= 0){// get range from byteStart til eof
sprintf(tmp, "bytes=%zu-", byteStart);
@ -277,9 +278,7 @@ namespace HTTP{
return true;
}
const HTTP::URL & Downloader::lastURL(){
return nbLink;
}
const HTTP::URL &Downloader::lastURL(){return nbLink;}
// continue handling a request, originally set up by the getNonBlocking() function
// returns true if the request is complete
@ -368,14 +367,15 @@ namespace HTTP{
}
}
WARN_MSG("Invalid connection state for HTTP request");
return false; //we should never get here
return false; // we should never get here
}
bool Downloader::post(const HTTP::URL &link, const std::string &payload, bool sync, uint8_t 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;}
size_t loop = retryCount; // max 5 attempts
while (--loop){// loop while we are unsuccessful
@ -499,4 +499,3 @@ namespace HTTP{
}
}// namespace HTTP

View file

@ -1,6 +1,6 @@
#include "http_parser.h"
#include "url.h"
#include "socket.h"
#include "url.h"
#include "util.h"
namespace HTTP{
@ -11,7 +11,8 @@ namespace HTTP{
std::string &data();
const std::string &const_data() const;
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);
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);
@ -20,7 +21,8 @@ namespace HTTP{
Util::DataCallback &cb = Util::defaultDataCallback);
bool getRangeNonBlocking(const HTTP::URL &link, size_t byteStart, size_t byteEnd,
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,
uint8_t maxRecursiveDepth = 6);
@ -45,7 +47,7 @@ namespace HTTP{
const Socket::Connection &getSocket() const;
uint32_t retryCount, dataTimeout;
bool isProxied() const;
const HTTP::URL & lastURL();
const HTTP::URL &lastURL();
private:
bool isComplete;
@ -65,8 +67,4 @@ namespace HTTP{
uint64_t nbReqTime;
};
}// namespace HTTP

View file

@ -1,61 +1,54 @@
#include <algorithm>
#include "defines.h"
#include "dtls_srtp_handshake.h"
#include <algorithm>
/* Write mbedtls into a log file. */
#define LOG_TO_FILE 0
#if LOG_TO_FILE
# include <fstream>
#include <fstream>
#endif
/* ----------------------------------------- */
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 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_write(void* user, const unsigned char* buf, size_t len); /* Called when mbedtls wants to write data to e.g. a socket. */
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_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);
/* ----------------------------------------- */
DTLSSRTPHandshake::DTLSSRTPHandshake()
:write_callback(NULL)
,cert(NULL)
,key(NULL)
{
memset((void*)&entropy_ctx, 0x00, sizeof(entropy_ctx));
memset((void*)&rand_ctx, 0x00, sizeof(rand_ctx));
memset((void*)&ssl_ctx, 0x00, sizeof(ssl_ctx));
memset((void*)&ssl_conf, 0x00, sizeof(ssl_conf));
memset((void*)&cookie_ctx, 0x00, sizeof(cookie_ctx));
memset((void*)&timer_ctx, 0x00, sizeof(timer_ctx));
DTLSSRTPHandshake::DTLSSRTPHandshake() : write_callback(NULL), cert(NULL), key(NULL){
memset((void *)&entropy_ctx, 0x00, sizeof(entropy_ctx));
memset((void *)&rand_ctx, 0x00, sizeof(rand_ctx));
memset((void *)&ssl_ctx, 0x00, sizeof(ssl_ctx));
memset((void *)&ssl_conf, 0x00, sizeof(ssl_conf));
memset((void *)&cookie_ctx, 0x00, sizeof(cookie_ctx));
memset((void *)&timer_ctx, 0x00, sizeof(timer_ctx));
}
int DTLSSRTPHandshake::init(mbedtls_x509_crt* certificate,
mbedtls_pk_context* privateKey,
int(*writeCallback)(const uint8_t* data, int* nbytes)
)
{
int DTLSSRTPHandshake::init(mbedtls_x509_crt *certificate, mbedtls_pk_context *privateKey,
int (*writeCallback)(const uint8_t *data, int *nbytes)){
int r = 0;
mbedtls_ssl_srtp_profile srtp_profiles[] = {
MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_80,
MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_32
};
mbedtls_ssl_srtp_profile srtp_profiles[] ={MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_80,
MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_32};
if (!writeCallback) {
if (!writeCallback){
FAIL_MSG("No writeCallack function given.");
r = -3;
goto error;
}
if (!certificate) {
if (!certificate){
FAIL_MSG("Given certificate is null.");
r = -5;
goto error;
}
if (!privateKey) {
if (!privateKey){
FAIL_MSG("Given key is null.");
r = -10;
goto error;
@ -72,16 +65,18 @@ int DTLSSRTPHandshake::init(mbedtls_x509_crt* certificate,
mbedtls_ssl_cookie_init(&cookie_ctx);
/* 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);
if (0 != r) {
r = mbedtls_ctr_drbg_seed(&rand_ctx, mbedtls_entropy_func, &entropy_ctx,
(const unsigned char *)"mist-srtp", 9);
if (0 != r){
print_mbedtls_error(r);
r = -20;
goto error;
}
/* 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);
if (0 != r) {
r = mbedtls_ssl_config_defaults(&ssl_conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_DATAGRAM,
MBEDTLS_SSL_PRESET_DEFAULT);
if (0 != r){
print_mbedtls_error(r);
r = -30;
goto error;
@ -95,8 +90,9 @@ int DTLSSRTPHandshake::init(mbedtls_x509_crt* certificate,
mbedtls_debug_set_threshold(10);
/* enable SRTP */
r = mbedtls_ssl_conf_dtls_srtp_protection_profiles(&ssl_conf, srtp_profiles, sizeof(srtp_profiles) / sizeof(srtp_profiles[0]));
if (0 != r) {
r = mbedtls_ssl_conf_dtls_srtp_protection_profiles(&ssl_conf, srtp_profiles,
sizeof(srtp_profiles) / sizeof(srtp_profiles[0]));
if (0 != r){
print_mbedtls_error(r);
r = -40;
goto error;
@ -104,7 +100,7 @@ int DTLSSRTPHandshake::init(mbedtls_x509_crt* certificate,
/* cert certificate chain + key, so we can verify the client-hello signed data */
r = mbedtls_ssl_conf_own_cert(&ssl_conf, cert, key);
if (0 != r) {
if (0 != r){
print_mbedtls_error(r);
r = -50;
goto error;
@ -112,7 +108,7 @@ int DTLSSRTPHandshake::init(mbedtls_x509_crt* certificate,
/* cookie setup (e.g. to prevent ddos). */
r = mbedtls_ssl_cookie_setup(&cookie_ctx, mbedtls_ctr_drbg_random, &rand_ctx);
if (0 != r) {
if (0 != r){
print_mbedtls_error(r);
r = -60;
goto error;
@ -123,20 +119,21 @@ int DTLSSRTPHandshake::init(mbedtls_x509_crt* certificate,
/* setup the ssl context for use. note that ssl_conf will be referenced internall by the context and therefore should be kept around. */
r = mbedtls_ssl_setup(&ssl_ctx, &ssl_conf);
if (0 != r) {
if (0 != r){
print_mbedtls_error(r);
r = -70;
goto error;
}
/* set bio handlers */
mbedtls_ssl_set_bio(&ssl_ctx, (void*)this, on_mbedtls_wants_to_write, on_mbedtls_wants_to_read, NULL);
mbedtls_ssl_set_bio(&ssl_ctx, (void *)this, on_mbedtls_wants_to_write, on_mbedtls_wants_to_read, NULL);
/* set temp id, just adds some exta randomness */
{
std::string remote_id = "mist";
r = mbedtls_ssl_set_client_transport_id(&ssl_ctx, (const unsigned char*)remote_id.c_str(), remote_id.size());
if (0 != r) {
r = mbedtls_ssl_set_client_transport_id(&ssl_ctx, (const unsigned char *)remote_id.c_str(),
remote_id.size());
if (0 != r){
print_mbedtls_error(r);
r = -80;
goto error;
@ -148,16 +145,14 @@ int DTLSSRTPHandshake::init(mbedtls_x509_crt* certificate,
write_callback = writeCallback;
error:
error:
if (r < 0) {
shutdown();
}
if (r < 0){shutdown();}
return r;
}
int DTLSSRTPHandshake::shutdown() {
int DTLSSRTPHandshake::shutdown(){
/* cleanup the refs from the settings. */
cert = NULL;
@ -181,19 +176,19 @@ int DTLSSRTPHandshake::shutdown() {
/* ----------------------------------------- */
int DTLSSRTPHandshake::parse(const uint8_t* data, size_t nbytes) {
int DTLSSRTPHandshake::parse(const uint8_t *data, size_t nbytes){
if (NULL == data) {
if (NULL == data){
ERROR_MSG("Given `data` is NULL.");
return -1;
}
if (0 == nbytes) {
if (0 == nbytes){
ERROR_MSG("Given nbytes is 0.");
return -2;
}
if (MBEDTLS_SSL_HANDSHAKE_OVER == ssl_ctx.state) {
if (MBEDTLS_SSL_HANDSHAKE_OVER == ssl_ctx.state){
ERROR_MSG("Already finished the handshake.");
return -3;
}
@ -202,58 +197,60 @@ int DTLSSRTPHandshake::parse(const uint8_t* data, size_t nbytes) {
int r = 0;
std::copy(data, data + nbytes, std::back_inserter(buffer));
do {
do{
r = mbedtls_ssl_handshake(&ssl_ctx);
switch (r) {
switch (r){
/* 0 = handshake done. */
case 0: {
if (0 != extractKeyingMaterial()) {
case 0:{
if (0 != extractKeyingMaterial()){
ERROR_MSG("Failed to extract keying material after handshake was done.");
return -2;
}
return 0;
}
/* see the dtls server example; this is used to prevent certain attacks (ddos) */
case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED: {
if (0 != resetSession()) {
ERROR_MSG("Failed to reset the session which is necessary when we need to verify the HELLO.");
case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:{
if (0 != resetSession()){
ERROR_MSG(
"Failed to reset the session which is necessary when we need to verify the HELLO.");
return -3;
}
break;
}
case MBEDTLS_ERR_SSL_WANT_READ: {
DONTEVEN_MSG("mbedtls wants a bit more data before it can continue parsing the DTLS handshake.");
case MBEDTLS_ERR_SSL_WANT_READ:{
DONTEVEN_MSG(
"mbedtls wants a bit more data before it can continue parsing the DTLS handshake.");
break;
}
default: {
default:{
ERROR_MSG("A serious mbedtls error occured.");
print_mbedtls_error(r);
return -2;
}
}
}
while (MBEDTLS_ERR_SSL_WANT_WRITE == r);
}while (MBEDTLS_ERR_SSL_WANT_WRITE == r);
return 0;
}
/* ----------------------------------------- */
int DTLSSRTPHandshake::resetSession() {
int DTLSSRTPHandshake::resetSession(){
std::string remote_id = "mist"; /* @todo for now we hardcoded this... */
int r = 0;
r = mbedtls_ssl_session_reset(&ssl_ctx);
if (0 != r) {
if (0 != r){
print_mbedtls_error(r);
return -1;
}
r = mbedtls_ssl_set_client_transport_id(&ssl_ctx, (const unsigned char*)remote_id.c_str(), remote_id.size());
if (0 != r) {
r = mbedtls_ssl_set_client_transport_id(&ssl_ctx, (const unsigned char *)remote_id.c_str(),
remote_id.size());
if (0 != r){
print_mbedtls_error(r);
return -2;
}
@ -267,39 +264,39 @@ int DTLSSRTPHandshake::resetSession() {
master key is 128 bits => 16 bytes.
master salt is 112 bits => 14 bytes
*/
int DTLSSRTPHandshake::extractKeyingMaterial() {
int DTLSSRTPHandshake::extractKeyingMaterial(){
int r = 0;
uint8_t keying_material[MBEDTLS_DTLS_SRTP_MAX_KEY_MATERIAL_LENGTH] = {};
uint8_t keying_material[MBEDTLS_DTLS_SRTP_MAX_KEY_MATERIAL_LENGTH] ={};
size_t keying_material_len = sizeof(keying_material);
r = mbedtls_ssl_get_dtls_srtp_key_material(&ssl_ctx, keying_material, &keying_material_len);
if (0 != r) {
if (0 != r){
print_mbedtls_error(r);
return -1;
}
/* @todo following code is for server mode only */
mbedtls_ssl_srtp_profile srtp_profile = mbedtls_ssl_get_dtls_srtp_protection_profile(&ssl_ctx);
switch (srtp_profile) {
case MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_80: {
switch (srtp_profile){
case MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_80:{
cipher = "SRTP_AES128_CM_SHA1_80";
break;
}
case MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_32: {
case MBEDTLS_SRTP_AES128_CM_HMAC_SHA1_32:{
cipher = "SRTP_AES128_CM_SHA1_32";
break;
}
default: {
default:{
ERROR_MSG("Unhandled SRTP profile, cannot extract keying material.");
return -6;
}
}
remote_key.assign((char*)(&keying_material[0]) + 0, 16);
local_key.assign((char*)(&keying_material[0]) + 16, 16);
remote_salt.assign((char*)(&keying_material[0]) + 32, 14);
local_salt.assign((char*)(&keying_material[0]) + 46, 14);
remote_key.assign((char *)(&keying_material[0]) + 0, 16);
local_key.assign((char *)(&keying_material[0]) + 16, 16);
remote_salt.assign((char *)(&keying_material[0]) + 32, 14);
local_salt.assign((char *)(&keying_material[0]) + 46, 14);
DONTEVEN_MSG("Extracted the DTLS SRTP keying material with cipher %s.", cipher.c_str());
DONTEVEN_MSG("Remote DTLS SRTP key size is %zu.", remote_key.size());
@ -327,23 +324,19 @@ int DTLSSRTPHandshake::extractKeyingMaterial() {
- when there is data in our temporary buffer, we read from that
*/
static int on_mbedtls_wants_to_read(void* user, unsigned char* buf, size_t len) {
static int on_mbedtls_wants_to_read(void *user, unsigned char *buf, size_t len){
DTLSSRTPHandshake* hs = static_cast<DTLSSRTPHandshake*>(user);
if (NULL == hs) {
DTLSSRTPHandshake *hs = static_cast<DTLSSRTPHandshake *>(user);
if (NULL == hs){
ERROR_MSG("Failed to cast the user pointer into a DTLSSRTPHandshake.");
return -1;
}
/* figure out how much we can read. */
if (hs->buffer.size() == 0) {
return MBEDTLS_ERR_SSL_WANT_READ;
}
if (hs->buffer.size() == 0){return MBEDTLS_ERR_SSL_WANT_READ;}
size_t nbytes = hs->buffer.size();
if (nbytes > len) {
nbytes = len;
}
if (nbytes > len){nbytes = len;}
/* "read" into the given buffer. */
memcpy(buf, &hs->buffer[0], nbytes);
@ -352,26 +345,26 @@ static int on_mbedtls_wants_to_read(void* user, unsigned char* buf, size_t len)
return (int)nbytes;
}
static int on_mbedtls_wants_to_write(void* user, const unsigned char* buf, size_t len) {
static int on_mbedtls_wants_to_write(void *user, const unsigned char *buf, size_t len){
DTLSSRTPHandshake* hs = static_cast<DTLSSRTPHandshake*>(user);
if (!hs) {
DTLSSRTPHandshake *hs = static_cast<DTLSSRTPHandshake *>(user);
if (!hs){
FAIL_MSG("Failed to cast the user pointer into a DTLSSRTPHandshake.");
return -1;
}
if (!hs->write_callback) {
if (!hs->write_callback){
FAIL_MSG("The `write_callback` member is NULL.");
return -2;
}
int nwritten = (int)len;
if (0 != hs->write_callback(buf, &nwritten)) {
if (0 != hs->write_callback(buf, &nwritten)){
FAIL_MSG("Failed to write some DTLS handshake data.");
return -3;
}
if (nwritten != (int)len) {
if (nwritten != (int)len){
FAIL_MSG("The DTLS-SRTP handshake listener MUST write all the data.");
return -4;
}
@ -381,34 +374,33 @@ static int on_mbedtls_wants_to_write(void* user, const unsigned char* buf, size_
/* ----------------------------------------- */
static void print_mbedtls_error(int r) {
char buf[1024] = {};
static void print_mbedtls_error(int r){
char buf[1024] ={};
mbedtls_strerror(r, buf, sizeof(buf));
ERROR_MSG("mbedtls error: %s", buf);
}
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){
DONTEVEN_MSG("%s:%04d: %.*s", file, line, strlen(str) - 1, str);
#if LOG_TO_FILE
static std::ofstream ofs;
if (!ofs.is_open()) {
ofs.open("mbedtls.log", std::ios::out);
}
if (!ofs.is_open()) {
return;
}
if (!ofs.is_open()){ofs.open("mbedtls.log", std::ios::out);}
if (!ofs.is_open()){return;}
ofs << str;
ofs.flush();
#endif
}
static std::string mbedtls_err_to_string(int r) {
switch (r) {
case MBEDTLS_ERR_SSL_WANT_READ: { return "MBEDTLS_ERR_SSL_WANT_READ"; }
case MBEDTLS_ERR_SSL_WANT_WRITE: { return "MBEDTLS_ERR_SSL_WANT_WRITE"; }
default: {
static std::string mbedtls_err_to_string(int r){
switch (r){
case MBEDTLS_ERR_SSL_WANT_READ:{
return "MBEDTLS_ERR_SSL_WANT_READ";
}
case MBEDTLS_ERR_SSL_WANT_WRITE:{
return "MBEDTLS_ERR_SSL_WANT_WRITE";
}
default:{
print_mbedtls_error(r);
return "UNKNOWN";
}
@ -416,5 +408,3 @@ static std::string mbedtls_err_to_string(int r) {
}
/* ---------------------------------------- */

View file

@ -1,26 +1,27 @@
#pragma once
#include <stdint.h>
#include <deque>
#include <mbedtls/config.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.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_cookie.h>
#include <mbedtls/error.h>
#include <mbedtls/debug.h>
#include <mbedtls/timing.h>
#include <mbedtls/x509.h>
#include <stdint.h>
/* ----------------------------------------- */
class DTLSSRTPHandshake {
class DTLSSRTPHandshake{
public:
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 parse(const uint8_t* data, size_t nbytes);
int parse(const uint8_t *data, size_t nbytes);
bool hasKeyingMaterial();
private:
@ -28,8 +29,8 @@ private:
int resetSession();
private:
mbedtls_x509_crt* cert; /* Certificate, we do not own the key. Make sure it's kept alive during the livetime of this class instance. */
mbedtls_pk_context* key; /* Private key, we do not own the key. Make sure it's kept alive during the livetime of this class instance. */
mbedtls_x509_crt *cert; /* Certificate, we do not own the key. Make sure it's kept alive during the livetime of this class instance. */
mbedtls_pk_context *key; /* Private key, we do not own the key. Make sure it's kept alive during the livetime of this class instance. */
mbedtls_entropy_context entropy_ctx;
mbedtls_ctr_drbg_context rand_ctx;
mbedtls_ssl_context ssl_ctx;
@ -38,7 +39,7 @@ private:
mbedtls_timing_delay_context timer_ctx;
public:
int (*write_callback)(const uint8_t* data, int* nbytes);
int (*write_callback)(const uint8_t *data, int *nbytes);
std::deque<uint8_t> buffer; /* Accessed from BIO callbback. We copy the bytes you pass into `parse()` into this temporary buffer which is read by a trigger to `mbedlts_ssl_handshake()`. */
std::string cipher; /* selected SRTP cipher. */
std::string remote_key;
@ -49,11 +50,9 @@ public:
/* ----------------------------------------- */
inline bool DTLSSRTPHandshake::hasKeyingMaterial() {
return (0 != remote_key.size()
&& 0 != remote_salt.size()
&& 0 != local_key.size()
&& 0 != local_salt.size());
inline bool DTLSSRTPHandshake::hasKeyingMaterial(){
return (0 != remote_key.size() && 0 != remote_salt.size() && 0 != local_key.size() &&
0 != local_salt.size());
}
/* ----------------------------------------- */

View file

@ -1,38 +1,36 @@
/// \file dtsc.cpp
/// Holds all code for DDVTECH Stream Container parsing/generation.
#include "dtsc.h"
#include "defines.h"
#include "dtsc.h"
#include <arpa/inet.h> //for htonl/ntohl
#include <stdlib.h>
#include <string.h> //for memcmp
#include <arpa/inet.h> //for htonl/ntohl
char DTSC::Magic_Header[] = "DTSC";
char DTSC::Magic_Packet[] = "DTPD";
char DTSC::Magic_Packet2[] = "DTP2";
char DTSC::Magic_Command[] = "DTCM";
DTSC::File::File() {
DTSC::File::File(){
F = 0;
buffer = malloc(4);
endPos = 0;
}
DTSC::File::File(const File & rhs) {
DTSC::File::File(const File &rhs){
buffer = malloc(4);
*this = rhs;
}
DTSC::File & DTSC::File::operator =(const File & rhs) {
DTSC::File &DTSC::File::operator=(const File &rhs){
created = rhs.created;
if (rhs.F) {
if (rhs.F){
F = fdopen(dup(fileno(rhs.F)), (created ? "w+b" : "r+b"));
} else {
}else{
F = 0;
}
endPos = rhs.endPos;
if (rhs.myPack) {
myPack = rhs.myPack;
}
if (rhs.myPack){myPack = rhs.myPack;}
metadata = rhs.metadata;
currtime = rhs.currtime;
lastreadpos = rhs.lastreadpos;
@ -42,31 +40,31 @@ DTSC::File & DTSC::File::operator =(const File & rhs) {
return *this;
}
DTSC::File::operator bool() const {
DTSC::File::operator bool() const{
return F;
}
/// Open a filename for DTSC reading/writing.
/// If create is true and file does not exist, attempt to create.
DTSC::File::File(std::string filename, bool create) {
DTSC::File::File(std::string filename, bool create){
buffer = malloc(8);
if (create) {
if (create){
F = fopen(filename.c_str(), "w+b");
if (!F) {
if (!F){
DEBUG_MSG(DLVL_ERROR, "Could not create file %s: %s", filename.c_str(), strerror(errno));
return;
}
//write an empty header
// write an empty header
fseek(F, 0, SEEK_SET);
fwrite(DTSC::Magic_Header, 4, 1, F);
memset(buffer, 0, 4);
fwrite(buffer, 4, 1, F); //write 4 zero-bytes
fwrite(buffer, 4, 1, F); // write 4 zero-bytes
headerSize = 0;
} else {
}else{
F = fopen(filename.c_str(), "r+b");
}
created = create;
if (!F) {
if (!F){
HIGH_MSG("Could not open file %s", filename.c_str());
return;
}
@ -74,62 +72,59 @@ DTSC::File::File(std::string filename, bool create) {
endPos = ftell(F);
bool sepHeader = false;
if (!create) {
if (!create){
fseek(F, 0, SEEK_SET);
if (fread(buffer, 4, 1, F) != 1) {
if (fread(buffer, 4, 1, F) != 1){
DEBUG_MSG(DLVL_ERROR, "Can't read file contents of %s", filename.c_str());
fclose(F);
F = 0;
return;
}
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_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){
DEBUG_MSG(DLVL_ERROR, "%s is not a valid DTSC file", filename.c_str());
fclose(F);
F = 0;
return;
} else {
}else{
metadata.moreheader = -1;
}
}
}
//we now know the first 4 bytes are DTSC::Magic_Header and we have a valid file
// we now know the first 4 bytes are DTSC::Magic_Header and we have a valid file
fseek(F, 4, SEEK_SET);
if (fread(buffer, 4, 1, F) != 1) {
if (fread(buffer, 4, 1, F) != 1){
fseek(F, 4, SEEK_SET);
memset(buffer, 0, 4);
fwrite(buffer, 4, 1, F); //write 4 zero-bytes
} else {
fwrite(buffer, 4, 1, F); // write 4 zero-bytes
}else{
headerSize = ntohl(((uint32_t *)buffer)[0]);
}
if (metadata.moreheader != -1) {
if (!sepHeader) {
if (metadata.moreheader != -1){
if (!sepHeader){
readHeader(0);
fseek(F, 8 + headerSize, SEEK_SET);
} else {
}else{
fseek(F, 0, SEEK_SET);
}
} else {
}else{
fseek(F, 0, SEEK_SET);
File Fhead(filename + ".dtsh");
if (Fhead) {
metadata = Fhead.metadata;
}
if (Fhead){metadata = Fhead.metadata;}
}
currframe = 0;
}
/// Returns the header metadata for this file as JSON::Value.
DTSC::Meta & DTSC::File::getMeta() {
DTSC::Meta &DTSC::File::getMeta(){
return metadata;
}
/// (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.
bool DTSC::File::writeHeader(std::string & header, bool force) {
if (headerSize != header.size() && !force) {
bool DTSC::File::writeHeader(std::string &header, bool force){
if (headerSize != header.size() && !force){
DEBUG_MSG(DLVL_ERROR, "Could not overwrite header - not equal size");
return false;
}
@ -137,9 +132,7 @@ bool DTSC::File::writeHeader(std::string & header, bool force) {
int pSize = htonl(header.size());
fseek(F, 4, SEEK_SET);
int tmpret = fwrite((void *)(&pSize), 4, 1, F);
if (tmpret != 1) {
return false;
}
if (tmpret != 1){return false;}
fseek(F, 8, SEEK_SET);
int ret = fwrite(header.c_str(), headerSize, 1, F);
fseek(F, 8 + headerSize, SEEK_SET);
@ -148,47 +141,41 @@ bool DTSC::File::writeHeader(std::string & header, bool force) {
/// Adds the given string as a new header to the end of the file.
/// \returns The positon the header was written at, or 0 on failure.
long long int DTSC::File::addHeader(std::string & header) {
long long int DTSC::File::addHeader(std::string &header){
fseek(F, 0, SEEK_END);
long long int writePos = ftell(F);
int hSize = htonl(header.size());
int ret = fwrite(DTSC::Magic_Header, 4, 1, F); //write header
if (ret != 1) {
return 0;
}
ret = fwrite((void *)(&hSize), 4, 1, F); //write size
if (ret != 1) {
return 0;
}
ret = fwrite(header.c_str(), header.size(), 1, F); //write contents
if (ret != 1) {
return 0;
}
int ret = fwrite(DTSC::Magic_Header, 4, 1, F); // write header
if (ret != 1){return 0;}
ret = fwrite((void *)(&hSize), 4, 1, F); // write size
if (ret != 1){return 0;}
ret = fwrite(header.c_str(), header.size(), 1, F); // write contents
if (ret != 1){return 0;}
fseek(F, 0, SEEK_END);
endPos = ftell(F);
return writePos; //return position written at
return writePos; // return position written at
}
/// Reads the header at the given file position.
/// If the packet could not be read for any reason, the reason is printed.
/// Reading the header means the file position is moved to after the header.
void DTSC::File::readHeader(int pos) {
void DTSC::File::readHeader(int pos){
fseek(F, pos, SEEK_SET);
if (fread(buffer, 4, 1, F) != 1) {
if (feof(F)) {
if (fread(buffer, 4, 1, F) != 1){
if (feof(F)){
DEBUG_MSG(DLVL_DEVEL, "End of file reached while reading header @ %d", pos);
} else {
}else{
DEBUG_MSG(DLVL_ERROR, "Could not read header @ %d", pos);
}
metadata = Meta();
return;
}
if (memcmp(buffer, DTSC::Magic_Header, 4) != 0) {
if (memcmp(buffer, DTSC::Magic_Header, 4) != 0){
DEBUG_MSG(DLVL_ERROR, "Invalid header - %.4s != %.4s @ %i", (char *)buffer, DTSC::Magic_Header, pos);
metadata = Meta();
return;
}
if (fread(buffer, 4, 1, F) != 1) {
if (fread(buffer, 4, 1, F) != 1){
DEBUG_MSG(DLVL_ERROR, "Could not read header size @ %i", pos);
metadata = Meta();
return;
@ -196,96 +183,91 @@ void DTSC::File::readHeader(int pos) {
long packSize = ntohl(((unsigned long *)buffer)[0]) + 8;
std::string strBuffer;
strBuffer.resize(packSize);
if (packSize) {
if (packSize){
fseek(F, pos, SEEK_SET);
if (fread((void *)strBuffer.c_str(), packSize, 1, F) != 1) {
if (fread((void *)strBuffer.c_str(), packSize, 1, F) != 1){
DEBUG_MSG(DLVL_ERROR, "Could not read header packet @ %i", pos);
metadata = Meta();
return;
}
metadata = Meta(DTSC::Packet(strBuffer.data(), strBuffer.size(),true));
metadata = Meta(DTSC::Packet(strBuffer.data(), strBuffer.size(), true));
}
//if there is another header, read it and replace metadata with that one.
if (metadata.moreheader) {
if (metadata.moreheader < getBytePosEOF()) {
// if there is another header, read it and replace metadata with that one.
if (metadata.moreheader){
if (metadata.moreheader < getBytePosEOF()){
readHeader(metadata.moreheader);
return;
}
}
if (!metadata.live){
metadata.vod = true;
}
if (!metadata.live){metadata.vod = true;}
}
long int DTSC::File::getBytePosEOF() {
long int DTSC::File::getBytePosEOF(){
return endPos;
}
long int DTSC::File::getBytePos() {
long int DTSC::File::getBytePos(){
return ftell(F);
}
bool DTSC::File::reachedEOF() {
bool DTSC::File::reachedEOF(){
return feof(F);
}
/// Reads the packet available at the current file position.
/// If the packet could not be read for any reason, the reason is printed.
/// Reading the packet means the file position is increased to the next packet.
void DTSC::File::seekNext() {
if (!currentPositions.size()) {
void DTSC::File::seekNext(){
if (!currentPositions.size()){
DEBUG_MSG(DLVL_WARN, "No seek positions set - returning empty packet.");
myPack.null();
return;
}
seekPos thisPos = *currentPositions.begin();
fseek(F, thisPos.bytePos, SEEK_SET);
if (reachedEOF()) {
if (reachedEOF()){
myPack.null();
return;
}
clearerr(F);
currentPositions.erase(currentPositions.begin());
lastreadpos = ftell(F);
if (fread(buffer, 4, 1, F) != 1) {
if (feof(F)) {
if (fread(buffer, 4, 1, F) != 1){
if (feof(F)){
DEBUG_MSG(DLVL_DEVEL, "End of file reached while seeking @ %i", (int)lastreadpos);
} else {
}else{
DEBUG_MSG(DLVL_ERROR, "Could not seek to next @ %i", (int)lastreadpos);
}
myPack.null();
return;
}
if (memcmp(buffer, DTSC::Magic_Header, 4) == 0) {
if (memcmp(buffer, DTSC::Magic_Header, 4) == 0){
seek_time(myPack.getTime(), myPack.getTrackId(), true);
return seekNext();
}
long long unsigned int version = 0;
if (memcmp(buffer, DTSC::Magic_Packet, 4) == 0) {
version = 1;
}
if (memcmp(buffer, DTSC::Magic_Packet2, 4) == 0) {
version = 2;
}
if (version == 0) {
DEBUG_MSG(DLVL_ERROR, "Invalid packet header @ %#x - %.4s != %.4s @ %d", (unsigned int)lastreadpos, (char *)buffer, DTSC::Magic_Packet2, (int)lastreadpos);
if (memcmp(buffer, DTSC::Magic_Packet, 4) == 0){version = 1;}
if (memcmp(buffer, DTSC::Magic_Packet2, 4) == 0){version = 2;}
if (version == 0){
DEBUG_MSG(DLVL_ERROR, "Invalid packet header @ %#x - %.4s != %.4s @ %d",
(unsigned int)lastreadpos, (char *)buffer, DTSC::Magic_Packet2, (int)lastreadpos);
myPack.null();
return;
}
if (fread(buffer, 4, 1, F) != 1) {
if (fread(buffer, 4, 1, F) != 1){
DEBUG_MSG(DLVL_ERROR, "Could not read packet size @ %d", (int)lastreadpos);
myPack.null();
return;
}
long packSize = ntohl(((unsigned long *)buffer)[0]);
char * packBuffer = (char *)malloc(packSize + 8);
if (version == 1) {
char *packBuffer = (char *)malloc(packSize + 8);
if (version == 1){
memcpy(packBuffer, "DTPD", 4);
} else {
}else{
memcpy(packBuffer, "DTP2", 4);
}
memcpy(packBuffer + 4, buffer, 4);
if (fread((void *)(packBuffer + 8), packSize, 1, F) != 1) {
if (fread((void *)(packBuffer + 8), packSize, 1, F) != 1){
DEBUG_MSG(DLVL_ERROR, "Could not read packet @ %d", (int)lastreadpos);
myPack.null();
free(packBuffer);
@ -293,24 +275,24 @@ void DTSC::File::seekNext() {
}
myPack.reInit(packBuffer, packSize + 8);
free(packBuffer);
if (metadata.merged) {
if (metadata.merged){
int tempLoc = getBytePos();
char newHeader[20];
bool insert = false;
seekPos tmpPos;
if (fread((void *)newHeader, 20, 1, F) == 1) {
if (memcmp(newHeader, DTSC::Magic_Packet2, 4) == 0) {
if (fread((void *)newHeader, 20, 1, F) == 1){
if (memcmp(newHeader, DTSC::Magic_Packet2, 4) == 0){
tmpPos.bytePos = tempLoc;
tmpPos.trackID = ntohl(((int *)newHeader)[2]);
tmpPos.seekTime = 0;
if (selectedTracks.find(tmpPos.trackID) != selectedTracks.end()) {
if (selectedTracks.find(tmpPos.trackID) != selectedTracks.end()){
tmpPos.seekTime = ((long long unsigned int)ntohl(((int *)newHeader)[3])) << 32;
tmpPos.seekTime += ntohl(((int *)newHeader)[4]);
insert = true;
} else {
}else{
long tid = myPack.getTrackId();
for (unsigned int i = 0; i != metadata.tracks[tid].keys.size(); i++) {
if ((unsigned long long)metadata.tracks[tid].keys[i].getTime() > myPack.getTime()) {
for (unsigned int i = 0; i != metadata.tracks[tid].keys.size(); i++){
if ((unsigned long long)metadata.tracks[tid].keys[i].getTime() > myPack.getTime()){
tmpPos.seekTime = metadata.tracks[tid].keys[i].getTime();
tmpPos.bytePos = metadata.tracks[tid].keys[i].getBpos();
tmpPos.trackID = tid;
@ -319,9 +301,10 @@ void DTSC::File::seekNext() {
}
}
}
if (currentPositions.size()) {
for (std::set<seekPos>::iterator curPosIter = currentPositions.begin(); curPosIter != currentPositions.end(); curPosIter++) {
if ((*curPosIter).trackID == tmpPos.trackID && (*curPosIter).seekTime >= tmpPos.seekTime) {
if (currentPositions.size()){
for (std::set<seekPos>::iterator curPosIter = currentPositions.begin();
curPosIter != currentPositions.end(); curPosIter++){
if ((*curPosIter).trackID == tmpPos.trackID && (*curPosIter).seekTime >= tmpPos.seekTime){
insert = false;
break;
}
@ -330,11 +313,9 @@ void DTSC::File::seekNext() {
}
}
if (insert){
if (tmpPos.seekTime > 0xffffffffffffff00ll){
tmpPos.seekTime = 0;
}
if (tmpPos.seekTime > 0xffffffffffffff00ll){tmpPos.seekTime = 0;}
currentPositions.insert(tmpPos);
} else {
}else{
seek_time(myPack.getTime(), myPack.getTrackId(), true);
}
seek_bpos(tempLoc);
@ -345,39 +326,38 @@ void DTSC::File::seekNext() {
}
void DTSC::File::parseNext(){
char header_buffer[4] = {0, 0, 0, 0};
char header_buffer[4] ={0, 0, 0, 0};
lastreadpos = ftell(F);
if (fread(header_buffer, 4, 1, F) != 1) {
if (feof(F)) {
if (fread(header_buffer, 4, 1, F) != 1){
if (feof(F)){
DEBUG_MSG(DLVL_DEVEL, "End of file reached @ %d", (int)lastreadpos);
} else {
}else{
DEBUG_MSG(DLVL_ERROR, "Could not read header @ %d", (int)lastreadpos);
}
myPack.null();
return;
}
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;
}
if (memcmp(header_buffer, DTSC::Magic_Packet2, 4) == 0) {
version = 2;
}
if (version == 0) {
if (memcmp(header_buffer, DTSC::Magic_Packet2, 4) == 0){version = 2;}
if (version == 0){
DEBUG_MSG(DLVL_ERROR, "Invalid packet header @ %#x: %.4s", (unsigned int)lastreadpos, (char *)buffer);
myPack.null();
return;
}
if (fread(buffer, 4, 1, F) != 1) {
if (fread(buffer, 4, 1, F) != 1){
DEBUG_MSG(DLVL_ERROR, "Could not read packet size @ %#x", (unsigned int)lastreadpos);
myPack.null();
return;
}
long packSize = ntohl(((unsigned long *)buffer)[0]);
char * packBuffer = (char *)malloc(packSize + 8);
char *packBuffer = (char *)malloc(packSize + 8);
memcpy(packBuffer, header_buffer, 4);
memcpy(packBuffer + 4, buffer, 4);
if (fread((void *)(packBuffer + 8), packSize, 1, F) != 1) {
if (fread((void *)(packBuffer + 8), packSize, 1, F) != 1){
DEBUG_MSG(DLVL_ERROR, "Could not read packet @ %d", (int)lastreadpos);
myPack.null();
free(packBuffer);
@ -388,19 +368,19 @@ void DTSC::File::parseNext(){
}
/// Returns the byte positon of the start of the last packet that was read.
long long int DTSC::File::getLastReadPos() {
long long int DTSC::File::getLastReadPos(){
return lastreadpos;
}
/// Returns the internal buffer of the last read packet in raw binary format.
DTSC::Packet & DTSC::File::getPacket() {
DTSC::Packet &DTSC::File::getPacket(){
return myPack;
}
bool DTSC::File::seek_time(unsigned int ms, unsigned int trackNo, bool forceSeek) {
bool DTSC::File::seek_time(unsigned int ms, unsigned int trackNo, bool forceSeek){
seekPos tmpPos;
tmpPos.trackID = trackNo;
if (!forceSeek && myPack && ms >= myPack.getTime() && trackNo >= myPack.getTrackId()) {
if (!forceSeek && myPack && ms >= myPack.getTime() && trackNo >= myPack.getTrackId()){
tmpPos.seekTime = myPack.getTime();
tmpPos.bytePos = getBytePos();
/*
@ -408,135 +388,124 @@ bool DTSC::File::seek_time(unsigned int ms, unsigned int trackNo, bool forceSeek
tmpPos.bytePos += myPack.getDataLen();
}
*/
} else {
}else{
tmpPos.seekTime = 0;
tmpPos.bytePos = 0;
}
if (reachedEOF()) {
if (reachedEOF()){
clearerr(F);
seek_bpos(0);
tmpPos.bytePos = 0;
tmpPos.seekTime = 0;
}
DTSC::Track & trackRef = metadata.tracks[trackNo];
for (unsigned int i = 0; i < trackRef.keys.size(); i++) {
DTSC::Track &trackRef = metadata.tracks[trackNo];
for (unsigned int i = 0; i < trackRef.keys.size(); i++){
long keyTime = trackRef.keys[i].getTime();
if (keyTime > ms) {
break;
}
if ((long long unsigned int)keyTime > tmpPos.seekTime) {
if (keyTime > ms){break;}
if ((long long unsigned int)keyTime > tmpPos.seekTime){
tmpPos.seekTime = keyTime;
tmpPos.bytePos = trackRef.keys[i].getBpos();
}
}
bool foundPacket = false;
while (!foundPacket) {
while (!foundPacket){
lastreadpos = ftell(F);
if (reachedEOF()) {
if (reachedEOF()){
DEBUG_MSG(DLVL_WARN, "Reached EOF during seek to %u in track %d - aborting @ %lld", ms, trackNo, lastreadpos);
return false;
}
//Seek to first packet after ms.
// Seek to first packet after ms.
seek_bpos(tmpPos.bytePos);
//read the header
// read the header
char header[20];
if (fread((void *)header, 20, 1, F) != 1){
DEBUG_MSG(DLVL_WARN, "Could not read header from file. Much sadface.");
return false;
}
//check if packetID matches, if not, skip size + 8 bytes.
// check if packetID matches, if not, skip size + 8 bytes.
int packSize = ntohl(((int *)header)[1]);
unsigned int packID = ntohl(((int *)header)[2]);
if (memcmp(header, Magic_Packet2, 4) != 0 || packID != trackNo) {
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);
if (memcmp(header, Magic_Packet2, 4) != 0 || packID != trackNo){
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);
tmpPos.bytePos = 0;
continue;
}
tmpPos.bytePos += 8 + packSize;
continue;
}
//get timestamp of packet, if too large, break, if not, skip size bytes.
// get timestamp of packet, if too large, break, if not, skip size bytes.
long long unsigned int myTime = ((long long unsigned int)ntohl(((int *)header)[3]) << 32);
myTime += ntohl(((int *)header)[4]);
tmpPos.seekTime = myTime;
if (myTime >= ms) {
if (myTime >= ms){
foundPacket = true;
} else {
}else{
tmpPos.bytePos += 8 + packSize;
continue;
}
}
//DEBUG_MSG(DLVL_HIGH, "Seek to %u:%d resulted in %lli", trackNo, ms, tmpPos.seekTime);
if (tmpPos.seekTime > 0xffffffffffffff00ll){
tmpPos.seekTime = 0;
}
// DEBUG_MSG(DLVL_HIGH, "Seek to %u:%d resulted in %lli", trackNo, ms, tmpPos.seekTime);
if (tmpPos.seekTime > 0xffffffffffffff00ll){tmpPos.seekTime = 0;}
currentPositions.insert(tmpPos);
return true;
}
/// Attempts to seek to the given time in ms within the file.
/// Returns true if successful, false otherwise.
bool DTSC::File::seek_time(unsigned int ms) {
bool DTSC::File::seek_time(unsigned int ms){
currentPositions.clear();
if (selectedTracks.size()) {
for (std::set<unsigned long>::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++) {
if (selectedTracks.size()){
for (std::set<unsigned long>::iterator it = selectedTracks.begin(); it != selectedTracks.end(); it++){
seek_time(ms, (*it), true);
}
}
return true;
}
bool DTSC::File::seek_bpos(int bpos) {
if (fseek(F, bpos, SEEK_SET) == 0) {
return true;
}
bool DTSC::File::seek_bpos(int bpos){
if (fseek(F, bpos, SEEK_SET) == 0){return true;}
return false;
}
void DTSC::File::rewritePacket(std::string & newPacket, int bytePos) {
void DTSC::File::rewritePacket(std::string &newPacket, int bytePos){
fseek(F, bytePos, SEEK_SET);
fwrite(newPacket.c_str(), newPacket.size(), 1, F);
fseek(F, 0, SEEK_END);
if (ftell(F) > endPos) {
endPos = ftell(F);
}
if (ftell(F) > endPos){endPos = ftell(F);}
}
void DTSC::File::writePacket(std::string & newPacket) {
void DTSC::File::writePacket(std::string &newPacket){
fseek(F, 0, SEEK_END);
fwrite(newPacket.c_str(), newPacket.size(), 1, F); //write contents
fwrite(newPacket.c_str(), newPacket.size(), 1, F); // write contents
fseek(F, 0, SEEK_END);
endPos = ftell(F);
}
void DTSC::File::writePacket(JSON::Value & newPacket) {
void DTSC::File::writePacket(JSON::Value &newPacket){
writePacket(newPacket.toNetPacked());
}
bool DTSC::File::atKeyframe() {
if (myPack.getFlag("keyframe")) {
return true;
}
bool DTSC::File::atKeyframe(){
if (myPack.getFlag("keyframe")){return true;}
long long int bTime = myPack.getTime();
DTSC::Track & trackRef = metadata.tracks[myPack.getTrackId()];
for (unsigned int i = 0; i < trackRef.keys.size(); i++) {
if (trackRef.keys[i].getTime() >= bTime) {
return (trackRef.keys[i].getTime() == bTime);
}
DTSC::Track &trackRef = metadata.tracks[myPack.getTrackId()];
for (unsigned int i = 0; i < trackRef.keys.size(); i++){
if (trackRef.keys[i].getTime() >= bTime){return (trackRef.keys[i].getTime() == bTime);}
}
return false;
}
void DTSC::File::selectTracks(std::set<unsigned long> & tracks) {
void DTSC::File::selectTracks(std::set<unsigned long> &tracks){
selectedTracks = tracks;
currentPositions.clear();
seek_time(0);
}
/// Close the file if open
DTSC::File::~File() {
if (F) {
DTSC::File::~File(){
if (F){
fclose(F);
F = 0;
}

View file

@ -2,16 +2,16 @@
/// Holds all headers for DDVTECH Stream Container parsing/generation.
#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 "socket.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_STR 0x02
@ -19,17 +19,17 @@
#define DTSC_ARR 0x0A
#define DTSC_CON 0xFF
//Increase this value every time the DTSH file format changes in an incompatible way
//Changelog:
// Increase this value every time the DTSH file format changes in an incompatible way
// Changelog:
// Version 0-2: Undocumented changes
// Version 3: switched to bigMeta-style by default, Parts layout switched from 3/2/4 to 3/3/3 bytes
// Version 4: renamed bps to maxbps (peak bit rate) and added new value bps (average bit rate)
#define DTSH_VERSION 4
namespace DTSC {
namespace DTSC{
///\brief This enum holds all possible datatypes for DTSC packets.
enum datatype {
enum datatype{
AUDIO, ///< Stream Audio data
VIDEO, ///< Stream Video data
META, ///< Stream Metadata
@ -44,50 +44,42 @@ namespace DTSC {
extern char Magic_Command[]; ///< The magic bytes for a DTCM packet
///\brief A simple structure used for ordering byte seek positions.
struct seekPos {
struct seekPos{
///\brief Less-than comparison for seekPos structures.
///\param rhs The seekPos to compare with.
///\return Whether this object is smaller than rhs.
bool operator < (const seekPos & rhs) const {
if (seekTime < rhs.seekTime) {
bool operator<(const seekPos &rhs) const{
if (seekTime < rhs.seekTime){
return true;
} else {
if (seekTime == rhs.seekTime) {
if (trackID < rhs.trackID) {
return true;
}
}else{
if (seekTime == rhs.seekTime){
if (trackID < rhs.trackID){return true;}
}
}
return false;
}
long long unsigned int seekTime;///< Stores the timestamp of the DTSC packet referenced by this structure.
long long unsigned int bytePos;///< Stores the byteposition of the DTSC packet referenced by this structure.
unsigned int trackID;///< Stores the track the DTSC packet referenced by this structure is associated with.
long long unsigned int seekTime; ///< Stores the timestamp of the DTSC packet referenced by this structure.
long long unsigned int bytePos; ///< Stores the byteposition of the DTSC packet referenced by this structure.
unsigned int trackID; ///< Stores the track the DTSC packet referenced by this structure is associated with.
};
enum packType {
DTSC_INVALID,
DTSC_HEAD,
DTSC_V1,
DTSC_V2,
DTCM
};
enum packType{DTSC_INVALID, DTSC_HEAD, DTSC_V1, DTSC_V2, DTCM};
/// This class allows scanning through raw binary format DTSC data.
/// It can be used as an iterator or as a direct accessor.
class Scan {
class Scan{
public:
Scan();
Scan(char * pointer, size_t len);
Scan(char *pointer, size_t len);
operator bool() const;
std::string toPrettyString(size_t indent = 0) const;
bool hasMember(const std::string & indice) const;
bool hasMember(const char * indice, size_t ind_len) const;
Scan getMember(const std::string & indice) const;
Scan getMember(const char * indice) const;
Scan getMember(const char * indice, size_t ind_len) const;
void nullMember(const std::string & indice);
void nullMember(const char * indice, size_t ind_len);
bool hasMember(const std::string &indice) const;
bool hasMember(const char *indice, size_t ind_len) const;
Scan getMember(const std::string &indice) const;
Scan getMember(const char *indice) const;
Scan getMember(const char *indice, size_t ind_len) const;
void nullMember(const std::string &indice);
void nullMember(const char *indice, size_t ind_len);
Scan getIndice(size_t num) const;
std::string getIndiceName(size_t num) const;
size_t getSize() const;
@ -96,47 +88,50 @@ namespace DTSC {
bool asBool() const;
int64_t asInt() 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;
private:
char * p;
char *p;
size_t len;
};
/// DTSC::Packets can currently be three types:
/// 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_V2 packets are "DTP2", followed by 4 bytes len, 4 bytes trackID, 8 bytes time, and packed content.
/// The len is always without the first 8 bytes counted.
class Packet {
/// DTSC_V2 packets are "DTP2", followed by 4 bytes len, 4 bytes trackID, 8 bytes time, and packed
/// content. The len is always without the first 8 bytes counted.
class Packet{
public:
Packet();
Packet(const Packet & rhs);
Packet(const char * data_, unsigned int len, bool noCopy = false);
Packet(const Packet &rhs);
Packet(const char *data_, unsigned int len, bool noCopy = false);
virtual ~Packet();
void null();
void operator = (const Packet & rhs);
void operator=(const Packet &rhs);
operator bool() const;
packType getVersion() const;
void reInit(Socket::Connection & src);
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 appendData(const char * appendData, uint32_t appendLen);
void getString(const char * identifier, char *& result, size_t & len) const;
void getString(const char * identifier, std::string & result) const;
void getInt(const char * identifier, uint64_t & result) const;
uint64_t getInt(const char * identifier) const;
void getFlag(const char * identifier, bool & result) const;
bool getFlag(const char * identifier) const;
bool hasMember(const char * identifier) const;
void appendNal(const char * appendData, uint32_t appendLen);
void upgradeNal(const char * appendData, uint32_t appendLen);
void reInit(Socket::Connection &src);
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 appendData(const char *appendData, uint32_t appendLen);
void getString(const char *identifier, char *&result, size_t &len) const;
void getString(const char *identifier, std::string &result) const;
void getInt(const char *identifier, uint64_t &result) const;
uint64_t getInt(const char *identifier) const;
void getFlag(const char *identifier, bool &result) const;
bool getFlag(const char *identifier) const;
bool hasMember(const char *identifier) const;
void appendNal(const char *appendData, uint32_t appendLen);
void upgradeNal(const char *appendData, uint32_t appendLen);
void setKeyFrame(bool kf);
virtual uint64_t getTime() const;
void setTime(uint64_t _time);
void nullMember(const std::string & memb);
void nullMember(const std::string &memb);
size_t getTrackId() const;
char * getData() const;
char *getData() const;
size_t getDataLen() const;
size_t getPayloadLen() const;
size_t getDataStringLen();
@ -145,11 +140,12 @@ namespace DTSC {
std::string toSummary() const;
Scan getScan() const;
Scan getScan();
protected:
bool master;
packType version;
void resize(size_t size);
char * data;
char *data;
size_t bufferLen;
size_t dataLen;
@ -157,49 +153,45 @@ namespace DTSC {
};
/// A child class of DTSC::Packet, which allows overriding the packet time efficiently.
class RetimedPacket : public Packet {
class RetimedPacket : public Packet{
public:
RetimedPacket(uint64_t 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) : Packet(data_, len, noCopy){
RetimedPacket(uint64_t 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)
: Packet(data_, len, noCopy){
timeOverride = reTime;
}
virtual uint64_t getTime() const{return timeOverride;}
protected:
uint64_t timeOverride;
};
/// A simple structure used for ordering byte seek positions.
struct livePos {
livePos() {
struct livePos{
livePos(){
seekTime = 0;
trackID = 0;
}
livePos(const livePos & rhs) {
livePos(const livePos &rhs){
seekTime = rhs.seekTime;
trackID = rhs.trackID;
}
void operator = (const livePos & rhs) {
void operator=(const livePos &rhs){
seekTime = rhs.seekTime;
trackID = rhs.trackID;
}
bool operator == (const livePos & rhs) {
bool operator==(const livePos &rhs){
return seekTime == rhs.seekTime && trackID == rhs.trackID;
}
bool operator != (const livePos & rhs) {
bool operator!=(const livePos &rhs){
return seekTime != rhs.seekTime || trackID != rhs.trackID;
}
bool operator < (const livePos & rhs) const {
if (seekTime < rhs.seekTime) {
bool operator<(const livePos &rhs) const{
if (seekTime < rhs.seekTime){
return true;
} else {
if (seekTime > rhs.seekTime) {
return false;
}
}else{
if (seekTime > rhs.seekTime){return false;}
}
return (trackID < rhs.trackID);
}
@ -210,16 +202,17 @@ namespace DTSC {
/*LTS-START*/
///\brief Basic class supporting initialization Vectors.
///
///These are used for encryption of data.
class Ivec {
/// These are used for encryption of data.
class Ivec{
public:
Ivec();
Ivec(long long int iVec);
void setIvec(long long int iVec);
void setIvec(std::string iVec);
void setIvec(const char * iVec, int len);
void setIvec(const char *iVec, int len);
long long int asInt();
char * getData();
char *getData();
private:
///\brief Data storage for this initialization vector.
///
@ -229,7 +222,7 @@ namespace DTSC {
/*LTS-END*/
///\brief Basic class for storage of data associated with single DTSC packets, a.k.a. parts.
class Part {
class Part{
public:
uint32_t getSize();
void setSize(uint32_t newSize);
@ -237,8 +230,9 @@ namespace DTSC {
void setDuration(uint32_t newDuration);
uint32_t getOffset();
void setOffset(uint32_t newOffset);
char * getData();
void toPrettyString(std::ostream & str, int indent = 0);
char *getData();
void toPrettyString(std::ostream &str, int indent = 0);
private:
#define PACKED_PART_SIZE 9
///\brief Data storage for this Part.
@ -252,7 +246,7 @@ namespace DTSC {
///\brief Basic class for storage of data associated with keyframes.
///
/// When deleting this object, make sure to remove all DTSC::Part associated with it, if any. If you fail doing this, it *will* cause data corruption.
class Key {
class Key{
public:
unsigned long long getBpos();
void setBpos(unsigned long long newBpos);
@ -264,8 +258,9 @@ namespace DTSC {
void setParts(unsigned short newParts);
unsigned long long getTime();
void setTime(unsigned long long newTime);
char * getData();
void toPrettyString(std::ostream & str, int indent = 0);
char *getData();
void toPrettyString(std::ostream &str, int indent = 0);
private:
#define PACKED_KEY_SIZE 25
///\brief Data storage for this Key.
@ -279,7 +274,7 @@ namespace DTSC {
};
///\brief Basic class for storage of data associated with fragments.
class Fragment {
class Fragment{
public:
unsigned long getDuration();
void setDuration(unsigned long newDuration);
@ -289,8 +284,9 @@ namespace DTSC {
void setNumber(unsigned long newNumber);
unsigned long getSize();
void setSize(unsigned long newSize);
char * getData();
void toPrettyString(std::ostream & str, int indent = 0);
char *getData();
void toPrettyString(std::ostream &str, int indent = 0);
private:
#define PACKED_FRAGMENT_SIZE 13
///\brief Data storage for this Fragment.
@ -303,35 +299,38 @@ namespace DTSC {
};
///\brief Class for storage of track data
class Track {
class Track{
public:
Track();
Track(JSON::Value & trackRef);
Track(Scan & trackRef);
Track(JSON::Value &trackRef);
Track(Scan &trackRef);
void clearParts();
inline operator bool() const {
inline operator bool() const{
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);
void send(Socket::Connection & conn, bool skipDynamic = false);
void writeTo(char *& p);
void send(Socket::Connection &conn, bool skipDynamic = false);
void writeTo(char *&p);
JSON::Value toJSON(bool skipDynamic = false);
std::deque<Fragment> fragments;
std::deque<Key> keys;
std::deque<unsigned long> keySizes;
std::deque<Part> parts;
std::deque<Ivec> ivecs; /*LTS*/
Key & getKey(unsigned int keyNum);
Fragment & getFrag(unsigned int fragNum);
Key &getKey(unsigned int keyNum);
Fragment &getFrag(unsigned int fragNum);
unsigned int timeToKeynum(unsigned int timestamp);
uint32_t timeToFragnum(uint64_t timestamp);
void reset();
void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0);
void toPrettyString(std::ostream &str, int indent = 0, int verbosity = 0);
void finalize();
uint32_t biggestFragment();
@ -346,18 +345,19 @@ namespace DTSC {
std::string init;
std::string codec;
std::string type;
std::string lang;///< ISO 639-2 Language of track, empty or und if unknown.
uint32_t minKeepAway;///<Time in MS to never seek closer than live point to
//audio only
std::string lang; ///< ISO 639-2 Language of track, empty or und if unknown.
uint32_t minKeepAway; ///< Time in MS to never seek closer than live point to
// audio only
int rate;
int size;
int channels;
//video only
// video only
int width;
int height;
int fpks;
void removeFirstKey();
uint32_t secsSinceFirstFragmentInsert();
private:
std::string cachedIdent;
std::deque<uint32_t> fragInsertTime;
@ -368,31 +368,36 @@ namespace DTSC {
/// \todo Make toJSON().toNetpacked() shorter
public:
Meta();
Meta(const DTSC::Packet & source);
Meta(JSON::Value & meta);
Meta(const DTSC::Packet &source);
Meta(JSON::Value &meta);
bool nextIsKey;
inline operator bool() const { //returns if the object contains valid meta data BY LOOKING AT vod/live FLAGS
inline operator bool() const{// returns if the object contains valid meta data BY LOOKING AT vod/live FLAGS
return vod || live;
}
void reinit(const DTSC::Packet & source);
void update(const DTSC::Packet & pack, unsigned long segment_size = 1900);
void updatePosOverride(DTSC::Packet & pack, uint64_t bpos);
void update(JSON::Value & pack, unsigned long segment_size = 1900);
void reinit(const DTSC::Packet &source);
void update(const DTSC::Packet &pack, unsigned long segment_size = 1900);
void updatePosOverride(DTSC::Packet &pack, uint64_t bpos);
void update(JSON::Value &pack, unsigned long segment_size = 1900);
/*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);
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, 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 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); 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, 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);
JSON::Value toJSON();
void reset();
bool toFile(const std::string & fileName);
void toPrettyString(std::ostream & str, int indent = 0, int verbosity = 0);
//members:
bool toFile(const std::string &fileName);
void toPrettyString(std::ostream &str, int indent = 0, int verbosity = 0);
// members:
std::map<unsigned int, Track> tracks;
Track & mainTrack();
Track &mainTrack();
uint32_t biggestFragment();
bool vod;
bool live;
@ -400,54 +405,55 @@ namespace DTSC {
uint16_t version;
int64_t moreheader;
int64_t bufferWindow;
int64_t bootMsOffset;///< Millis to add to packet timestamps to get millis since system boot.
int64_t bootMsOffset; ///< Millis to add to packet timestamps to get millis since system boot.
std::string sourceURI;
JSON::Value inputLocalVars;
};
/// An iterator helper for easily iterating over the parts in a Fragment.
class PartIter {
class PartIter{
public:
PartIter(Track & Trk, Fragment & frag);
Part & operator*() const;///< Dereferences into a Value reference.
Part* operator->() const;///< Dereferences into a Value reference.
operator bool() const;///< True if not done iterating.
PartIter & operator++();///<Go to next iteration.
PartIter(Track &Trk, Fragment &frag);
Part &operator*() const; ///< Dereferences into a Value reference.
Part *operator->() const; ///< Dereferences into a Value reference.
operator bool() const; ///< True if not done iterating.
PartIter &operator++(); ///< Go to next iteration.
private:
uint32_t lastKey;
uint32_t currInKey;
Track * tRef;
Track *tRef;
std::deque<Part>::iterator pIt;
std::deque<Key>::iterator kIt;
};
/// A simple wrapper class that will open a file and allow easy reading/writing of DTSC data from/to it.
class File {
class File{
public:
File();
File(const File & rhs);
File(const File &rhs);
File(std::string filename, bool create = false);
File & operator = (const File & rhs);
File &operator=(const File &rhs);
operator bool() const;
~File();
Meta & getMeta();
Meta &getMeta();
long long int getLastReadPos();
bool writeHeader(std::string & header, bool force = false);
long long int addHeader(std::string & header);
bool writeHeader(std::string &header, bool force = false);
long long int addHeader(std::string &header);
long int getBytePosEOF();
long int getBytePos();
bool reachedEOF();
void seekNext();
void parseNext();
DTSC::Packet & getPacket();
DTSC::Packet &getPacket();
bool seek_time(unsigned int ms);
bool seek_time(unsigned int ms, unsigned int trackNo, bool forceSeek = false);
bool seek_bpos(int bpos);
void rewritePacket(std::string & newPacket, int bytePos);
void writePacket(std::string & newPacket);
void writePacket(JSON::Value & newPacket);
void rewritePacket(std::string &newPacket, int bytePos);
void writePacket(std::string &newPacket);
void writePacket(JSON::Value &newPacket);
bool atKeyframe();
void selectTracks(std::set<unsigned long> & tracks);
void selectTracks(std::set<unsigned long> &tracks);
private:
long int endPos;
void readHeader(int pos);
@ -457,14 +463,13 @@ namespace DTSC {
long long int currtime;
long long int lastreadpos;
int currframe;
FILE * F;
FILE *F;
unsigned long headerSize;
void * buffer;
void *buffer;
bool created;
std::set<seekPos> currentPositions;
std::set<unsigned long> selectedTracks;
};
//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 "defines.h"
#include "ebml.h"
#include <iomanip>
#include <sstream>
@ -380,8 +380,7 @@ namespace EBML{
switch (getType()){
case ELEM_MASTER:{
const uint64_t payLen = getPayloadLen();
ret << std::string(indent, ' ') << "Element [" << getIDString(getID()) << "] ("
<< getOuterLen() << "b, ";
ret << std::string(indent, ' ') << "Element [" << getIDString(getID()) << "] (" << getOuterLen() << "b, ";
if (payLen == 0xFFFFFFFFFFFFFFFFull){
ret << "infinite";
}else{
@ -639,9 +638,8 @@ namespace EBML{
std::string Block::toPrettyString(const uint8_t indent, const uint8_t detail) const{
std::stringstream ret;
ret << std::string(indent, ' ') << getIDString(getID()) << " with "
<< (unsigned int)getFrameCount() << " frame(s) for track " << getTrackNum() << " @ "
<< getTimecode();
ret << std::string(indent, ' ') << getIDString(getID()) << " with " << (unsigned int)getFrameCount()
<< " frame(s) for track " << getTrackNum() << " @ " << getTimecode();
if (isKeyframe()){ret << " [KeyOnly]";}
if (isInvisible()){ret << " [Invisible]";}
if (isDiscardable()){ret << " [Discardable]";}
@ -656,8 +654,7 @@ namespace EBML{
for (uint32_t frameNo = 0; frameNo < getFrameCount(); ++frameNo){
const char *payDat = getFrameData(frameNo);
const uint64_t payLen = getFrameSize(frameNo);
ret << std::dec << std::string(indent + 4, ' ') << "Frame " << (frameNo + 1) << " ("
<< payLen << "b):";
ret << std::dec << std::string(indent + 4, ' ') << "Frame " << (frameNo + 1) << " (" << payLen << "b):";
if (!payDat || !payLen || detail < 6){
ret << std::endl;
continue;
@ -683,4 +680,3 @@ namespace EBML{
return ret.str();
}
}// 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;
};
}// namespace EBML

View file

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

View file

@ -17,8 +17,7 @@ namespace EBML{
void sendElemSeek(Socket::Connection &C, 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,
uint64_t relaPos);
void sendElemCuePoint(Socket::Connection &C, 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);
@ -28,8 +27,6 @@ namespace EBML{
uint32_t sizeElemDbl(uint32_t ID, const double val);
uint32_t sizeElemStr(uint32_t ID, const std::string &val);
void sendSimpleBlock(Socket::Connection &C, DTSC::Packet &pkt, uint64_t clusterTime,
bool forceKeyframe = false);
void sendSimpleBlock(Socket::Connection &C, DTSC::Packet &pkt, uint64_t clusterTime, bool forceKeyframe = false);
uint32_t sizeSimpleBlock(uint64_t trackId, uint32_t dataSize);
}// namespace EBML

View file

@ -101,11 +101,9 @@ namespace Encodings{
std::string escaped = "";
int max = c.length();
for (int i = 0; i < max; i++){
if (('0' <= c[i] && c[i] <= '9') || ('a' <= c[i] && c[i] <= 'z') ||
('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') ||
(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)){
escaped.append(&c[i], 1);
}else{
@ -143,4 +141,3 @@ namespace Encodings{
}
}// namespace Encodings

View file

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

View file

@ -1,38 +1,35 @@
#include "encryption.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 <cstring>
#include <iomanip>
#include <cstdio>
#include <iostream>
#include "rijndael.h"
#include "defines.h"
#include "bitfields.h"
#include "http_parser.h"
#include "encode.h"
#include "nal.h"/*LTS*/
#include <sstream>
namespace Encryption {
///helper function for printing binary values
std::string hexString(const char * data, unsigned long dataLen){
namespace Encryption{
/// helper function for printing binary values
std::string hexString(const char *data, unsigned long dataLen){
std::stringstream res;
for (int i = 0; i < dataLen; i++){
res << std::hex << std::setw(2) << std::setfill('0') << (int)data[i];
if (i % 4 == 3){
res << " ";
}
if (i % 4 == 3){res << " ";}
}
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());
}
std::string AES_Crypt(const char * data, int dataLen, const char * key, const char * ivec) {
char * outData = (char *)malloc(dataLen * sizeof(char));
std::string AES_Crypt(const char *data, int dataLen, const char *key, const char *ivec){
char *outData = (char *)malloc(dataLen * sizeof(char));
memcpy(outData, data, dataLen);
AESFullCrypt(outData, dataLen, key, ivec);
std::string result = std::string(outData, dataLen);
@ -40,29 +37,30 @@ namespace Encryption {
return result;
}
///This function encrypts data in-place.
///It alters all parameters except dataLen.
///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) {
if (initialize) {
/// This function encrypts data in-place.
/// It alters all parameters except dataLen.
/// 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){
if (initialize){
num = 0;
memset(eCount, 0, 16);
///Before use, make sure the iVec is in the UPPER 8 bytes
/// Before use, make sure the iVec is in the UPPER 8 bytes
memset(iVec + 8, 0, 8);
///Before use, make sure this is not the only copy of the key you had. It is lost upon initialization
/// Before use, make sure this is not the only copy of the key you had. It is lost upon initialization
char cryptKey[224];
AES_set_encrypt_key(expandedKey, 128, cryptKey);
memcpy(expandedKey, cryptKey, 224);
initialize = false;
}
char * outData = (char *)malloc(dataLen * sizeof(char));
char *outData = (char *)malloc(dataLen * sizeof(char));
AES_CTR128_crypt(data, outData, dataLen, expandedKey, iVec, eCount, num);
memcpy(data, outData, dataLen);
free(outData);
}
//Generates the contentkey from a keyseed and a keyid
std::string PR_GenerateContentKey(std::string & keyseed, std::string & keyid) {
// Generates the contentkey from a keyseed and a keyid
std::string PR_GenerateContentKey(std::string &keyseed, std::string &keyid){
char contentKey[16];
char dataBlob[92];
char keyA[32], keyB[32], keyC[32];
@ -71,20 +69,20 @@ namespace Encryption {
memcpy(dataBlob + 30, keyidBytes.data(), 16);
memcpy(dataBlob + 46, keyseed.data(), 30);
memcpy(dataBlob + 76, keyidBytes.data(), 16);
//KeyA is generated from keyseed/keyid
// KeyA is generated from keyseed/keyid
Secure::sha256bin(dataBlob, 46, keyA);
//KeyB is generated from keyseed/keyid/keyseed
// KeyB is generated from keyseed/keyid/keyseed
Secure::sha256bin(dataBlob, 76, keyB);
//KeyC is generated from keyseed/keyid/keyseed/keyid
// KeyC is generated from keyseed/keyid/keyseed/keyid
Secure::sha256bin(dataBlob, 92, keyC);
for (int i = 0; i < 16; i++) {
for (int i = 0; i < 16; i++){
contentKey[i] = keyA[i] ^ keyA[i + 16] ^ keyB[i] ^ keyB[i + 16] ^ keyC[i] ^ keyC[i + 16];
}
return std::string(contentKey, 16);
}
//Transforms a guid to the MS byte array representation
std::string PR_GuidToByteArray(std::string & guid) {
// Transforms a guid to the MS byte array representation
std::string PR_GuidToByteArray(std::string &guid){
char result[16];
result[0] = guid[3];
result[1] = guid[2];
@ -100,9 +98,8 @@ namespace Encryption {
return std::string(result, 8);
}
///This function encrypts data in-place.
void AESFullCrypt(char * data, int dataLen, const char * key, const char * ivec) {
/// This function encrypts data in-place.
void AESFullCrypt(char *data, int dataLen, const char *key, const char *ivec){
unsigned int num = 0;
char expandedKey[224];
memcpy(expandedKey, key, 16);
@ -113,12 +110,12 @@ namespace Encryption {
AESPartialCrypt(data, dataLen, expandedKey, eCount, iVec, num, initialize);
}
void encryptPlayReady(DTSC::Packet & thisPack, std::string & codec, const char * iVec, const char * key) {
char * data;
void encryptPlayReady(DTSC::Packet &thisPack, std::string &codec, const char *iVec, const char *key){
char *data;
size_t dataLen;
thisPack.getString("data", data, dataLen);
if (codec == "H264") {
if (codec == "H264"){
unsigned int num = 0;
char expandedKey[224];
memcpy(expandedKey, key, 16);
@ -130,33 +127,30 @@ namespace Encryption {
int pos = 0;
std::deque<int> nalSizes = nalu::parseNalSizes(thisPack);
for (std::deque<int>::iterator it = nalSizes.begin(); it != nalSizes.end(); it++) {
int encrypted = (*it - 5) & ~0xF;//Bitmask to a multiple of 16
for (std::deque<int>::iterator it = nalSizes.begin(); it != nalSizes.end(); it++){
int encrypted = (*it - 5) & ~0xF; // Bitmask to a multiple of 16
int clear = *it - encrypted;
Encryption::AESPartialCrypt(data + pos + clear, encrypted, expandedKey, eCount, initVec, num, initialize);
pos += *it;
}
}
if (codec == "AAC") {
Encryption::AESFullCrypt(data, dataLen, key, iVec);
}
if (codec == "AAC"){Encryption::AESFullCrypt(data, dataLen, key, iVec);}
}
/// Converts a hexidecimal string format key to binary string format.
std::string binKey(std::string hexkey) {
std::string binKey(std::string hexkey){
char newkey[16];
memset(newkey, 0, 16);
for (size_t i = 0; i < hexkey.size(); ++i) {
for (size_t i = 0; i < hexkey.size(); ++i){
char c = hexkey[i];
newkey[i >> 1] |= ((c & 15) + (((c & 64) >> 6) | ((c & 64) >> 3))) << ((~i & 1) << 2);
}
return std::string(newkey, 16);
}
/// Helper function for urlescape.
/// Encodes a character as two hex digits.
std::string hex(char dec) {
std::string hex(char dec){
char dig1 = (dec & 0xF0) >> 4;
char dig2 = (dec & 0x0F);
if (dig1 <= 9) dig1 += 48;
@ -168,20 +162,19 @@ namespace Encryption {
r.append(&dig2, 1);
return r;
}
std::string hex(const std::string & input) {
std::string hex(const std::string &input){
std::string res;
res.reserve(input.size() * 2);
for (unsigned int i = 0; i < input.size(); i++) {
res += hex(input[i]);
}
for (unsigned int i = 0; i < input.size(); i++){res += hex(input[i]);}
return res;
}
void fillVerimatrix(verimatrixData & vmData) {
void fillVerimatrix(verimatrixData &vmData){
int hostPos = vmData.url.find("://") + 3;
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));
Socket::Connection veriConn(hostName, port, true);
@ -190,44 +183,43 @@ namespace Encryption {
H.SetHeader("Host", vmData.url.substr(hostPos));
H.SendRequest(veriConn);
H.Clean();
while (veriConn && (!veriConn.spool() || !H.Read(veriConn))) {}
while (veriConn && (!veriConn.spool() || !H.Read(veriConn))){}
vmData.key = binKey(H.GetHeader("Key"));
vmData.keyid = H.GetHeader("KeyId");
vmData.laurl = H.GetHeader("LAURL");
vmData.lauurl = H.GetHeader("LAUURL");
}
void verimatrixData::read(const char * shmPage) {
void verimatrixData::read(const char *shmPage){
int offset = 0;
url = std::string(shmPage + offset);
offset += url.size() + 1;//+1 for the concluding 0-byte
offset += url.size() + 1; //+1 for the concluding 0-byte
name = std::string(shmPage + offset);
offset += name.size() + 1;//+1 for the concluding 0-byte
offset += name.size() + 1; //+1 for the concluding 0-byte
key = std::string(shmPage + offset);
offset += key.size() + 1;//+1 for the concluding 0-byte
offset += key.size() + 1; //+1 for the concluding 0-byte
keyid = std::string(shmPage + offset);
offset += keyid.size() + 1;//+1 for the concluding 0-byte
offset += keyid.size() + 1; //+1 for the concluding 0-byte
laurl = std::string(shmPage + offset);
offset += laurl.size() + 1;//+1 for the concluding 0-byte
offset += laurl.size() + 1; //+1 for the concluding 0-byte
lauurl = std::string(shmPage + offset);
key = binKey(key);
}
void verimatrixData::write(char * shmPage) {
void verimatrixData::write(char *shmPage){
int offset = 0;
memcpy(shmPage + offset, url.c_str(), url.size() + 1);
offset += url.size() + 1;//+1 for the concluding 0-byte
offset += url.size() + 1; //+1 for the concluding 0-byte
memcpy(shmPage + offset, name.c_str(), name.size() + 1);
offset += name.size() + 1;//+1 for the concluding 0-byte
offset += name.size() + 1; //+1 for the concluding 0-byte
std::string tmpKey = hex(key);
memcpy(shmPage + offset, tmpKey.c_str(), tmpKey.size() + 1);
offset += tmpKey.size() + 1;//+1 for the concluding 0-byte
offset += tmpKey.size() + 1; //+1 for the concluding 0-byte
memcpy(shmPage + offset, keyid.c_str(), keyid.size() + 1);
offset += keyid.size() + 1;//+1 for the concluding 0-byte
offset += keyid.size() + 1; //+1 for the concluding 0-byte
memcpy(shmPage + offset, laurl.c_str(), laurl.size() + 1);
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);
}
}
}// namespace Encryption

View file

@ -1,12 +1,12 @@
#pragma once
#include <string>
#include "dtsc.h"
#include <string>
namespace Encryption {
class verimatrixData {
namespace Encryption{
class verimatrixData{
public:
void read(const char * shmPage);
void write(char * shmPage);
void read(const char *shmPage);
void write(char *shmPage);
std::string url;
std::string name;
std::string key;
@ -16,19 +16,20 @@ namespace Encryption {
std::string lauurl;
};
std::string hexString(const char * data, unsigned long dataLen);
std::string hexString(const char *data, unsigned long dataLen);
std::string AES_Crypt(const std::string & data, const std::string & key, std::string & ivec);
std::string AES_Crypt(const char * data, int dataLen, const char * key, const char * ivec);
std::string AES_Crypt(const std::string &data, const std::string &key, std::string &ivec);
std::string AES_Crypt(const char *data, int dataLen, const char *key, const char *ivec);
//These functions are dangerous for your data
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);
// These functions are dangerous for your data
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);
std::string PR_GenerateContentKey(std::string & keyseed, std::string & keyid);
std::string PR_GuidToByteArray(std::string & guid);
std::string PR_GenerateContentKey(std::string &keyseed, std::string &keyid);
std::string PR_GuidToByteArray(std::string &guid);
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
/// Holds all code for the FLV namespace.
#include "flv_tag.h"
#include "adts.h"
#include "defines.h"
#include "flv_tag.h"
#include "rtmpchunks.h"
#include "timing.h"
#include "util.h"
#include "adts.h"
#include <fcntl.h> //for Tag::FileLoader
#include <sstream>
#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.
char FLV::Header[13] ={'F', 'L', 'V', 0x01, 0x05, 0, 0, 0, 0x09, 0, 0, 0, 0};
bool FLV::Parse_Error =
false; ///< This variable is set to true if a problem is encountered while parsing the FLV.
bool FLV::Parse_Error = false; ///< This variable is set to true if a problem is encountered while parsing the FLV.
std::string FLV::Error_Str = "";
/// Checks a FLV Header for validness. Returns true if the header is valid, false
@ -307,8 +306,8 @@ FLV::Tag::~Tag(){
/// Assignment operator - works exactly like the copy constructor.
/// This operator checks for self-assignment.
FLV::Tag &FLV::Tag::operator=(const FLV::Tag & O){
if (this != &O){ //no self-assignment
FLV::Tag &FLV::Tag::operator=(const FLV::Tag &O){
if (this != &O){// no self-assignment
done = true;
sofar = 0;
len = O.len;
@ -504,51 +503,41 @@ bool FLV::Tag::DTSCMetaInit(DTSC::Meta &M, std::set<long unsigned int> &selTrack
if (M.tracks[*it].type == "video"){
trinfo.addContent(AMF::Object("", AMF::AMF0_OBJECT));
trinfo.getContentP(i)->addContent(AMF::Object(
"length", ((double)M.tracks[*it].lastms / 1000) * ((double)M.tracks[*it].fpks / 1000.0),
AMF::AMF0_NUMBER));
"length", ((double)M.tracks[*it].lastms / 1000) * ((double)M.tracks[*it].fpks / 1000.0), AMF::AMF0_NUMBER));
trinfo.getContentP(i)->addContent(
AMF::Object("timescale", ((double)M.tracks[*it].fpks / 1000.0), AMF::AMF0_NUMBER));
trinfo.getContentP(i)->addContent(AMF::Object("sampledescription", AMF::AMF0_STRICT_ARRAY));
amfdata.getContentP(1)->addContent(AMF::Object("hasVideo", 1, AMF::AMF0_BOOL));
if (M.tracks[*it].codec == "H264"){
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 7, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->getContentP(2)->addContent(
AMF::Object("sampletype", (std::string) "avc1"));
trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "avc1"));
}
if (M.tracks[*it].codec == "ScreenVideo2"){
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 6, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->getContentP(2)->addContent(
AMF::Object("sampletype", (std::string) "sv2"));
trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "sv2"));
}
if (M.tracks[*it].codec == "VP6Alpha"){
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 5, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->getContentP(2)->addContent(
AMF::Object("sampletype", (std::string) "vp6a"));
trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "vp6a"));
}
if (M.tracks[*it].codec == "VP6"){
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 4, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->getContentP(2)->addContent(
AMF::Object("sampletype", (std::string) "vp6"));
trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "vp6"));
}
if (M.tracks[*it].codec == "ScreenVideo1"){
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 3, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->getContentP(2)->addContent(
AMF::Object("sampletype", (std::string) "sv1"));
trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "sv1"));
}
if (M.tracks[*it].codec == "H263"){
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 2, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->getContentP(2)->addContent(
AMF::Object("sampletype", (std::string) "h263"));
trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "h263"));
}
if (M.tracks[*it].codec == "JPEG"){
amfdata.getContentP(1)->addContent(AMF::Object("videocodecid", 1, AMF::AMF0_NUMBER));
trinfo.getContentP(i)->getContentP(2)->addContent(
AMF::Object("sampletype", (std::string) "jpeg"));
trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "jpeg"));
}
amfdata.getContentP(1)->addContent(
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("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("videoframerate", (double)M.tracks[*it].fpks / 1000.0, AMF::AMF0_NUMBER));
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"){
trinfo.addContent(AMF::Object("", AMF::AMF0_OBJECT));
trinfo.getContentP(i)->addContent(
AMF::Object("length", ((double)M.tracks[*it].lastms) * ((double)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(
"length", ((double)M.tracks[*it].lastms) * ((double)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));
amfdata.getContentP(1)->addContent(AMF::Object("hasAudio", 1, AMF::AMF0_BOOL));
amfdata.getContentP(1)->addContent(AMF::Object("audiodelay", 0.0, AMF::AMF0_NUMBER));
if (M.tracks[*it].codec == "AAC"){
amfdata.getContentP(1)->addContent(AMF::Object("audiocodecid", (std::string) "mp4a"));
trinfo.getContentP(i)->getContentP(2)->addContent(
AMF::Object("sampletype", (std::string) "mp4a"));
trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "mp4a"));
}
if (M.tracks[*it].codec == "MP3"){
amfdata.getContentP(1)->addContent(AMF::Object("audiocodecid", (std::string) "mp3"));
trinfo.getContentP(i)->getContentP(2)->addContent(
AMF::Object("sampletype", (std::string) "mp3"));
trinfo.getContentP(i)->getContentP(2)->addContent(AMF::Object("sampletype", (std::string) "mp3"));
}
amfdata.getContentP(1)->addContent(
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(
AMF::Object("audiosamplesize", M.tracks[*it].size, AMF::AMF0_NUMBER));
amfdata.getContentP(1)->addContent(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(AMF::Object("audiosamplesize", M.tracks[*it].size, AMF::AMF0_NUMBER));
amfdata.getContentP(1)->addContent(
AMF::Object("audiodatarate", (double)M.tracks[*it].bps / 128.0, AMF::AMF0_NUMBER));
++i;
@ -836,20 +818,17 @@ void FLV::Tag::toMeta(DTSC::Meta &metadata, AMF::Object &amf_storage, unsigned i
if (data[0] == 0x12){
AMF::Object meta_in = AMF::parse((unsigned char *)data + 11, len - 15);
AMF::Object *tmp = 0;
if (meta_in.getContentP(1) && meta_in.getContentP(0) &&
(meta_in.getContentP(0)->StrValue() == "onMetaData")){
if (meta_in.getContentP(1) && meta_in.getContentP(0) && (meta_in.getContentP(0)->StrValue() == "onMetaData")){
tmp = meta_in.getContentP(1);
}else{
if (meta_in.getContentP(2) && meta_in.getContentP(1) &&
(meta_in.getContentP(1)->StrValue() == "onMetaData")){
if (meta_in.getContentP(2) && meta_in.getContentP(1) && (meta_in.getContentP(1)->StrValue() == "onMetaData")){
tmp = meta_in.getContentP(2);
}
}
if (tmp){amf_storage = *tmp;}
return;
}
if (data[0] == 0x08 &&
(metadata.tracks[reTrack].codec == "" || metadata.tracks[reTrack].codec != getAudioCodec() ||
if (data[0] == 0x08 && (metadata.tracks[reTrack].codec == "" || metadata.tracks[reTrack].codec != getAudioCodec() ||
(needsInitData() && isInitData()))){
char audiodata = data[11];
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;
}
if (amf_storage.getContentP("audiosamplerate")){
metadata.tracks[reTrack].rate =
(long long int)amf_storage.getContentP("audiosamplerate")->NumValue();
metadata.tracks[reTrack].rate = (long long int)amf_storage.getContentP("audiosamplerate")->NumValue();
}
switch (audiodata & 0x02){
case 0x0: metadata.tracks[reTrack].size = 8; break;
case 0x2: metadata.tracks[reTrack].size = 16; break;
}
if (amf_storage.getContentP("audiosamplesize")){
metadata.tracks[reTrack].size =
(long long int)amf_storage.getContentP("audiosamplesize")->NumValue();
metadata.tracks[reTrack].size = (long long int)amf_storage.getContentP("audiosamplesize")->NumValue();
}
switch (audiodata & 0x01){
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 &&
((needsInitData() && isInitData()) || !metadata.tracks[reTrack].codec.size())){
if (data[0] == 0x09 && ((needsInitData() && isInitData()) || !metadata.tracks[reTrack].codec.size())){
char videodata = data[11];
metadata.tracks[reTrack].codec = getVideoCodec();
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();
}
if (amf_storage.getContentP("height")){
metadata.tracks[reTrack].height =
(long long int)amf_storage.getContentP("height")->NumValue();
metadata.tracks[reTrack].height = (long long int)amf_storage.getContentP("height")->NumValue();
}
if (!metadata.tracks[reTrack].fpks && amf_storage.getContentP("videoframerate")){
if (amf_storage.getContentP("videoframerate")->NumValue()){
@ -960,4 +935,3 @@ bool FLV::Tag::checkBufferSize(){
}
return true;
}

View file

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

View file

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

View file

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

View file

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

View file

@ -13,10 +13,8 @@ namespace h265{
const char *typeToStr(uint8_t type);
bool isKeyframe(const char *data, uint32_t len);
void updateProfileTierLevel(Utils::bitstream &bs, MP4::HVCC &hvccBox,
unsigned long maxSubLayersMinus1);
std::string printProfileTierLevel(Utils::bitstream &bs, unsigned long maxSubLayersMinus1,
size_t indent);
void updateProfileTierLevel(Utils::bitstream &bs, MP4::HVCC &hvccBox, unsigned long maxSubLayersMinus1);
std::string printProfileTierLevel(Utils::bitstream &bs, unsigned long maxSubLayersMinus1, size_t indent);
struct metaInfo{
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
// 0 for 'unknown'
}// namespace h265

View file

@ -8,8 +8,8 @@
#include "timing.h"
#include "url.h"
#include "util.h"
#include <strings.h>
#include <iomanip>
#include <strings.h>
/// This constructor creates an empty HTTP::Parser, ready for use for either reading or writing.
/// 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);
}
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?
if (allAtOnce){
/// \TODO Make this less duplicated / more pretty.
@ -183,7 +184,7 @@ void HTTP::Parser::sendRequest(Socket::Connection &conn, const void * reqbody, c
}
builder += "\r\n";
if (reqbodyLen){
builder += std::string((char*)reqbody, reqbodyLen);
builder += std::string((char *)reqbody, reqbodyLen);
}else{
builder += body;
}
@ -203,7 +204,7 @@ void HTTP::Parser::sendRequest(Socket::Connection &conn, const void * reqbody, c
}
conn.SendNow("\r\n", 2);
if (reqbodyLen){
conn.SendNow((char*)reqbody, reqbodyLen);
conn.SendNow((char *)reqbody, reqbodyLen);
}else{
conn.SendNow(body);
}
@ -421,11 +422,9 @@ const std::string &HTTP::Parser::GetHeader(const std::string &i) const{
if (headers.count(i)){return headers.at(i);}
for (std::map<std::string, std::string>::const_iterator it = headers.begin(); it != headers.end(); ++it){
if (it->first.length() != i.length()){continue;}
if (strncasecmp(it->first.c_str(), i.c_str(), i.length()) == 0){
return it->second;
if (strncasecmp(it->first.c_str(), i.c_str(), i.length()) == 0){return it->second;}
}
}
//Return empty string if not found
// Return empty string if not found
static const std::string empty;
return empty;
}
@ -435,9 +434,7 @@ bool HTTP::Parser::hasHeader(const std::string &i) const{
if (headers.count(i)){return true;}
for (std::map<std::string, std::string>::const_iterator it = headers.begin(); it != headers.end(); ++it){
if (it->first.length() != i.length()){continue;}
if (strncasecmp(it->first.c_str(), i.c_str(), i.length()) == 0){
return true;
}
if (strncasecmp(it->first.c_str(), i.c_str(), i.length()) == 0){return true;}
}
return false;
}
@ -499,7 +496,7 @@ void HTTP::Parser::SetVar(std::string i, std::string v){
/// returned. If not, as much as can be interpreted is removed and false returned. \param conn The
/// socket to read from. \return True if a whole request or response was read, false otherwise.
bool HTTP::Parser::Read(Socket::Connection &conn, Util::DataCallback &cb){
//In this case, we might have a broken connection and need to check if we're done
// In this case, we might have a broken connection and need to check if we're done
if (!conn.Received().size()){
return (parse(conn.Received().get(), cb) && (!possiblyComplete || !conn || !JSON::Value(url).asInt()));
}
@ -708,9 +705,7 @@ bool HTTP::Parser::parse(std::string &HTTPbuffer, Util::DataCallback &cb){
}
return false;
}else{
if (protocol.substr(0, 4) == "RTSP" || method.substr(0,4) == "RTSP"){
return true;
}
if (protocol.substr(0, 4) == "RTSP" || method.substr(0, 4) == "RTSP"){return true;}
unsigned int toappend = HTTPbuffer.size();
bool shouldAppend = true;
if (bodyCallback){

View file

@ -39,7 +39,8 @@ namespace HTTP{
std::string &BuildResponse();
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 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 StartResponse(std::string code, std::string message, Parser &request,
Socket::Connection &conn, bool bufferAllChunks = false);

View file

@ -1,8 +1,8 @@
/// \file json.cpp Holds all JSON-related code.
#include "json.h"
#include "bitfields.h"
#include "defines.h"
#include "json.h"
#include <arpa/inet.h> //for htonl
#include <fstream>
#include <sstream>
@ -274,8 +274,7 @@ std::string JSON::string_escape(const std::string &val){
if ((c & 0xC0) == 0xC0){
// possible UTF-8 sequence
// check for 2-byte sequence
if (((c & 0xE0) == 0XC0) && (i + 1 < val.size()) &&
((val.data()[i + 1] & 0xC0) == 0x80)){
if (((c & 0xE0) == 0XC0) && (i + 1 < val.size()) && ((val.data()[i + 1] & 0xC0) == 0x80)){
// valid 2-byte sequence
out += UTF16(((c & 0x1F) << 6) | (val.data()[i + 1] & 0x3F));
i += 1;
@ -285,15 +284,13 @@ std::string JSON::string_escape(const std::string &val){
if (((c & 0xF0) == 0XE0) && (i + 2 < val.size()) &&
((val.data()[i + 1] & 0xC0) == 0x80) && ((val.data()[i + 2] & 0xC0) == 0x80)){
// valid 3-byte sequence
out += UTF16(((c & 0x1F) << 12) | ((val.data()[i + 1] & 0x3F) << 6) |
(val.data()[i + 2] & 0x3F));
out += UTF16(((c & 0x1F) << 12) | ((val.data()[i + 1] & 0x3F) << 6) | (val.data()[i + 2] & 0x3F));
i += 2;
break;
}
// check for 4-byte sequence
if (((c & 0xF8) == 0XF0) && (i + 3 < val.size()) &&
((val.data()[i + 1] & 0xC0) == 0x80) && ((val.data()[i + 2] & 0xC0) == 0x80) &&
((val.data()[i + 3] & 0xC0) == 0x80)){
if (((c & 0xF8) == 0XF0) && (i + 3 < val.size()) && ((val.data()[i + 1] & 0xC0) == 0x80) &&
((val.data()[i + 2] & 0xC0) == 0x80) && ((val.data()[i + 3] & 0xC0) == 0x80)){
// valid 4-byte sequence
out += UTF16(((c & 0x1F) << 18) | ((val.data()[i + 1] & 0x3F) << 12) |
((val.data()[i + 2] & 0x3F) << 6) | (val.data()[i + 3] & 0x3F));
@ -614,9 +611,9 @@ JSON::Value &JSON::Value::assignFrom(const Value &rhs, const std::set<std::strin
/// Extends this JSON::Value object with the given JSON::Value object, skipping given member(s) recursively.
JSON::Value &JSON::Value::extend(const Value &rhs, const std::set<std::string> &skip){
//Null values turn into objects automatically for sanity reasons
// Null values turn into objects automatically for sanity reasons
if (myType == EMPTY){myType = OBJECT;}
//Abort if either value is not an object
// Abort if either value is not an object
if (myType != rhs.myType || myType != OBJECT){return *this;}
jsonForEachConst(rhs, i){
if (!skip.count(i.key())){
@ -919,8 +916,7 @@ void JSON::Value::sendTo(Socket::Connection &socket) const{
unsigned int size = 16;
if (objVal.size() > 0){
jsonForEachConst(*this, i){
if (i.key().size() > 0 && i.key() != "trackid" && i.key() != "time" &&
i.key() != "datatype"){
if (i.key().size() > 0 && i.key() != "trackid" && i.key() != "time" && i.key() != "datatype"){
size += 2 + i.key().size() + i->packedSize();
}
}
@ -937,8 +933,7 @@ void JSON::Value::sendTo(Socket::Connection &socket) const{
socket.SendNow("\340", 1);
if (objVal.size() > 0){
jsonForEachConst(*this, i){
if (i.key().size() > 0 && i.key() != "trackid" && i.key() != "time" &&
i.key() != "datatype"){
if (i.key().size() > 0 && i.key() != "trackid" && i.key() != "time" && i.key() != "datatype"){
char sizebuffer[2] ={0, 0};
sizebuffer[0] = (i.key().size() >> 8) & 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 0xE0:{// object
++i;
while (data[i] + data[i + 1] != 0 &&
i < len){// while not encountering 0x0000 (we assume 0x0000EE)
while (data[i] + data[i + 1] != 0 && i < len){// while not encountering 0x0000 (we assume 0x0000EE)
if (i + 2 >= len){return;}
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
i += tmpi + 2; // skip length+size forwards
ret[tmpstr].null();
fromDTMI(
data, len, i,
fromDTMI(data, len, i,
ret[tmpstr]); // add content, recursively parsed, updating i, setting indice to tmpstr
}
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
++i;
while (data[i] + data[i + 1] != 0 &&
i < len){// while not encountering 0x0000 (we assume 0x0000EE)
while (data[i] + data[i + 1] != 0 && i < len){// while not encountering 0x0000 (we assume 0x0000EE)
JSON::Value tval;
fromDTMI(data, len, i, tval); // add content, recursively parsed, updating i
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);
return ret;
}

View file

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

View file

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

View file

@ -1,14 +1,12 @@
#include <string>
namespace Encodings {
namespace Encodings{
class ISO639{
public:
static std::string decode(const std::string & lang);
static std::string twoToThree(const std::string & lang);
static std::string encode(const std::string & lang);
static std::string decode(const std::string &lang);
static std::string twoToThree(const std::string &lang);
static std::string encode(const std::string &lang);
};
}
}// namespace Encodings

File diff suppressed because it is too large Load diff

113
lib/mp4.h
View file

@ -1,49 +1,46 @@
#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 <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.
namespace MP4 {
std::string readBoxType(FILE * newData);
bool skipBox(FILE * newData);
uint64_t calcBoxSize(const char * p);
namespace MP4{
std::string readBoxType(FILE *newData);
bool skipBox(FILE *newData);
uint64_t calcBoxSize(const char *p);
class Box {
class Box{
public:
Box(char * datapointer = 0, bool manage = true);
Box(const Box & rs);
Box & operator = (const Box & rs);
Box(char *datapointer = 0, bool manage = true);
Box(const Box &rs);
Box &operator=(const Box &rs);
~Box();
operator bool() const {
return data && data_size >= 8 && !isType("erro");
}
void copyFrom(const Box & rs);
operator bool() const{return data && data_size >= 8 && !isType("erro");}
void copyFrom(const Box &rs);
std::string getType() const;
bool isType(const char * boxType) const;
bool read(FILE * newData);
bool read(std::string & newData);
bool isType(const char *boxType) const;
bool read(FILE *newData);
bool read(std::string &newData);
uint64_t boxedSize() const;
uint64_t payloadSize() const;
char * asBox();
char * payload();
char *asBox();
char *payload();
void clear();
std::string toPrettyString(uint32_t indent = 0) const;
protected:
//integer functions
// integer functions
void setInt8(char newData, size_t index);
char getInt8(size_t index);
char getInt8(size_t index) const;
@ -59,69 +56,67 @@ namespace MP4 {
void setInt64(uint64_t newData, size_t index);
uint64_t getInt64(size_t index);
uint64_t getInt64(size_t index) const;
//string functions
// string functions
void setString(std::string newData, size_t index);
void setString(char * newData, size_t size, size_t index);
char * getString(size_t index);
void setString(char *newData, size_t size, size_t index);
char *getString(size_t index);
size_t getStringLen(size_t index) const;
//box functions
Box & getBox(size_t index);
// box functions
Box &getBox(size_t index);
size_t getBoxLen(size_t index) const;
void setBox(Box & newEntry, size_t index);
//data functions
void setBox(Box &newEntry, size_t index);
// data functions
bool reserve(size_t position, size_t current, size_t wanted);
bool reserve(size_t position, size_t current, size_t wanted) const {return false;}
bool reserve(size_t position, size_t current, size_t wanted) const{return false;}
//internal variables
char * data; ///< Holds the data of this box
// internal variables
char *data; ///< Holds the data of this box
unsigned int data_size; ///< Currently reserved size
bool managed; ///< If false, will not attempt to resize/free the data pointer.
unsigned int payloadOffset; ///<The offset of the payload with regards to the data
unsigned int payloadOffset; ///< The offset of the payload with regards to the data
};
//Box Class
// Box Class
class fullBox: public Box {
class fullBox : public Box{
public:
fullBox();
void setVersion(char newVersion);
char getVersion() const;
void setFlags(uint32_t newFlags);
uint32_t getFlags() const;
std::string toPrettyString(uint32_t indent = 0) const ;
std::string toPrettyString(uint32_t indent = 0) const;
};
class containerBox: public Box {
class containerBox : public Box{
public:
containerBox();
uint32_t getContentCount();
void setContent(Box & newContent, uint32_t no);
Box & getContent(uint32_t no, bool unsafe = false);
void setContent(Box &newContent, uint32_t no);
Box &getContent(uint32_t no, bool unsafe = false);
std::string toPrettyString(uint32_t indent = 0);
Box getChild(const char * boxName);
template <typename T>
T getChild(){
Box getChild(const char *boxName);
template <typename T> T getChild(){
T a;
MP4::Box r = getChild(a.getType().c_str());
return (T&)r;
return (T &)r;
}
std::deque<Box> getChildren(const char * boxName);
template <typename T>
std::deque<T> getChildren(){
std::deque<Box> getChildren(const char *boxName);
template <typename T> std::deque<T> getChildren(){
T a;
std::deque<Box> tmpRes = getChildren(a.getType().c_str());
std::deque<T> res;
for (std::deque<Box>::iterator it = tmpRes.begin(); it != tmpRes.end(); it++){
res.push_back((T&)*it);
res.push_back((T &)*it);
}
return res;
}
};
class containerFullBox: public fullBox {
class containerFullBox : public fullBox{
public:
uint32_t getContentCount();
void setContent(Box & newContent, uint32_t no);
Box & getContent(uint32_t no);
void setContent(Box &newContent, uint32_t no);
Box &getContent(uint32_t no);
std::string toPrettyCFBString(uint32_t indent, std::string boxName);
};
}
}// namespace MP4

File diff suppressed because it is too large Load diff

View file

@ -2,19 +2,19 @@
#include "mp4.h"
#include <stdint.h>
namespace MP4 {
//class Box;
namespace MP4{
// class Box;
struct afrt_runtable {
struct afrt_runtable{
uint32_t firstFragment;
uint64_t firstTimestamp;
uint32_t duration;
uint32_t discontinuity;
};
//fragmentRun
// fragmentRun
/// AFRT Box class
class AFRT: public Box {
class AFRT : public Box{
public:
AFRT();
void setVersion(char newVersion);
@ -24,22 +24,22 @@ namespace MP4 {
void setTimeScale(uint32_t newScale);
uint32_t getTimeScale();
uint32_t getQualityEntryCount();
void setQualityEntry(std::string & newQuality, uint32_t no);
const char * getQualityEntry(uint32_t no);
void setQualityEntry(std::string &newQuality, uint32_t no);
const char *getQualityEntry(uint32_t no);
uint32_t getFragmentRunCount();
void setFragmentRun(afrt_runtable newRun, uint32_t no);
afrt_runtable getFragmentRun(uint32_t no);
std::string toPrettyString(uint32_t indent = 0);
};
//AFRT Box
// AFRT Box
struct asrt_runtable {
struct asrt_runtable{
uint32_t firstSegment;
uint32_t fragmentsPerSegment;
};
/// ASRT Box class
class ASRT: public Box {
class ASRT : public Box{
public:
ASRT();
void setVersion(char newVersion);
@ -47,17 +47,17 @@ namespace MP4 {
void setUpdate(uint32_t newUpdate);
uint32_t getUpdate();
uint32_t getQualityEntryCount();
void setQualityEntry(std::string & newQuality, uint32_t no);
const char * getQualityEntry(uint32_t no);
void setQualityEntry(std::string &newQuality, uint32_t no);
const char *getQualityEntry(uint32_t no);
uint32_t getSegmentRunEntryCount();
void setSegmentRun(uint32_t firstSegment, uint32_t fragmentsPerSegment, uint32_t no);
asrt_runtable getSegmentRun(uint32_t no);
std::string toPrettyString(uint32_t indent = 0);
};
//ASRT Box
// ASRT Box
/// ABST Box class
class ABST: public Box {
class ABST : public Box{
public:
ABST();
void setVersion(char newVersion);
@ -78,40 +78,40 @@ namespace MP4 {
uint64_t getCurrentMediaTime();
void setSmpteTimeCodeOffset(uint64_t newTime);
uint64_t getSmpteTimeCodeOffset();
void setMovieIdentifier(std::string & newIdentifier);
char * getMovieIdentifier();
void setMovieIdentifier(std::string &newIdentifier);
char *getMovieIdentifier();
uint32_t getServerEntryCount();
void setServerEntry(std::string & entry, uint32_t no);
const char * getServerEntry(uint32_t no);
void setServerEntry(std::string &entry, uint32_t no);
const char *getServerEntry(uint32_t no);
uint32_t getQualityEntryCount();
void setQualityEntry(std::string & entry, uint32_t no);
const char * getQualityEntry(uint32_t no);
void setQualityEntry(std::string &entry, uint32_t no);
const char *getQualityEntry(uint32_t no);
void setDrmData(std::string newDrm);
char * getDrmData();
char *getDrmData();
void setMetaData(std::string newMetaData);
char * getMetaData();
char *getMetaData();
uint32_t getSegmentRunTableCount();
void setSegmentRunTable(ASRT & table, uint32_t no);
ASRT & getSegmentRunTable(uint32_t no);
void setSegmentRunTable(ASRT &table, uint32_t no);
ASRT &getSegmentRunTable(uint32_t no);
uint32_t getFragmentRunTableCount();
void setFragmentRunTable(AFRT & table, uint32_t no);
AFRT & getFragmentRunTable(uint32_t no);
void setFragmentRunTable(AFRT &table, uint32_t no);
AFRT &getFragmentRunTable(uint32_t no);
std::string toPrettyString(uint32_t indent = 0);
};
//ABST Box
// ABST Box
struct afraentry {
struct afraentry{
uint64_t time;
uint64_t offset;
};
struct globalafraentry {
struct globalafraentry{
uint64_t time;
uint32_t segment;
uint32_t fragment;
uint64_t afraoffset;
uint64_t offsetfromafra;
};
class AFRA: public Box {
class AFRA : public Box{
public:
AFRA();
void setVersion(uint32_t newVersion);
@ -135,5 +135,4 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
}
}// namespace MP4

View file

@ -1,70 +1,54 @@
#include "mp4_dash.h"
#include "defines.h"
#include "mp4_dash.h"
namespace MP4 {
SIDX::SIDX() {
namespace MP4{
SIDX::SIDX(){
memcpy(data + 4, "sidx", 4);
setVersion(0);
setFlags(0);
}
void SIDX::setReferenceID(uint32_t newReferenceID) {
setInt32(newReferenceID, 4);
}
void SIDX::setReferenceID(uint32_t newReferenceID){setInt32(newReferenceID, 4);}
uint32_t SIDX::getReferenceID() {
return getInt32(4);
}
uint32_t SIDX::getReferenceID(){return getInt32(4);}
void SIDX::setTimescale(uint32_t newTimescale) {
setInt32(newTimescale, 8);
}
void SIDX::setTimescale(uint32_t newTimescale){setInt32(newTimescale, 8);}
uint32_t SIDX::getTimescale() {
return getInt32(8);
}
uint32_t SIDX::getTimescale(){return getInt32(8);}
void SIDX::setEarliestPresentationTime(uint64_t newEarliestPresentationTime) {
if (getVersion() == 0) {
void SIDX::setEarliestPresentationTime(uint64_t newEarliestPresentationTime){
if (getVersion() == 0){
setInt32(newEarliestPresentationTime, 12);
} else {
}else{
setInt64(newEarliestPresentationTime, 12);
}
}
uint64_t SIDX::getEarliestPresentationTime() {
if (getVersion() == 0) {
return getInt32(12);
}
uint64_t SIDX::getEarliestPresentationTime(){
if (getVersion() == 0){return getInt32(12);}
return getInt64(12);
}
void SIDX::setFirstOffset(uint64_t newFirstOffset) {
if (getVersion() == 0) {
void SIDX::setFirstOffset(uint64_t newFirstOffset){
if (getVersion() == 0){
setInt32(newFirstOffset, 16);
} else {
}else{
setInt64(newFirstOffset, 20);
}
}
uint64_t SIDX::getFirstOffset() {
if (getVersion() == 0) {
return getInt32(16);
}
uint64_t SIDX::getFirstOffset(){
if (getVersion() == 0){return getInt32(16);}
return getInt64(20);
}
uint16_t SIDX::getReferenceCount() {
if (getVersion() == 0) {
return getInt16(22);
}
uint16_t SIDX::getReferenceCount(){
if (getVersion() == 0){return getInt16(22);}
return getInt16(30);
}
void SIDX::setReference(sidxReference & newRef, size_t index) {
if (index >= getReferenceCount()) {
setInt16(index + 1, (getVersion() == 0 ? 22 : 30));
}
void SIDX::setReference(sidxReference &newRef, size_t index){
if (index >= getReferenceCount()){setInt16(index + 1, (getVersion() == 0 ? 22 : 30));}
uint32_t offset = 24 + (index * 12) + (getVersion() == 0 ? 0 : 8);
uint32_t tmp = (newRef.referenceType ? 0x80000000 : 0) | newRef.referencedSize;
setInt32(tmp, offset);
@ -73,9 +57,9 @@ namespace MP4 {
setInt32(tmp, offset + 8);
}
sidxReference SIDX::getReference(size_t index) {
sidxReference SIDX::getReference(size_t index){
sidxReference result;
if (index >= getReferenceCount()) {
if (index >= getReferenceCount()){
DEVEL_MSG("Warning, attempt to obtain reference out of bounds");
return result;
}
@ -91,16 +75,17 @@ namespace MP4 {
return result;
}
std::string SIDX::toPrettyString(uint32_t indent) {
std::string SIDX::toPrettyString(uint32_t indent){
std::stringstream r;
r << std::string(indent, ' ') << "[sidx] Segment Index Box (" << boxedSize() << ")" << std::endl;
r << fullBox::toPrettyString(indent);
r << std::string(indent + 1, ' ') << "ReferenceID " << getReferenceID() << 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, ' ') << "References [" << getReferenceCount() << "]" << std::endl;
for (int i = 0; i < getReferenceCount(); i++) {
for (int i = 0; i < getReferenceCount(); i++){
sidxReference tmp = getReference(i);
r << std::string(indent + 2, ' ') << "[" << i << "]" << std::endl;
r << std::string(indent + 3, ' ') << "ReferenceType " << (int)tmp.referenceType << std::endl;
@ -113,37 +98,36 @@ namespace MP4 {
return r.str();
}
TFDT::TFDT() {
TFDT::TFDT(){
memcpy(data + 4, "tfdt", 4);
setVersion(1);
setFlags(0);
setBaseMediaDecodeTime(0);
}
void TFDT::setBaseMediaDecodeTime(uint64_t newBaseMediaDecodeTime) {
if (getVersion() == 1) {
void TFDT::setBaseMediaDecodeTime(uint64_t newBaseMediaDecodeTime){
if (getVersion() == 1){
setInt64(newBaseMediaDecodeTime, 4);
} else {
}else{
setInt32(newBaseMediaDecodeTime, 4);
}
}
uint64_t TFDT::getBaseMediaDecodeTime() {
if (getVersion() == 1) {
return getInt64(4);
}
uint64_t TFDT::getBaseMediaDecodeTime(){
if (getVersion() == 1){return getInt64(4);}
return getInt32(4);
}
std::string TFDT::toPrettyString(uint32_t indent) {
std::string TFDT::toPrettyString(uint32_t indent){
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 << std::string(indent + 1, ' ') << "BaseMediaDecodeTime " << getBaseMediaDecodeTime() << std::endl;
return r.str();
}
IODS::IODS() {
IODS::IODS(){
memcpy(data + 4, "iods", 4);
setVersion(0);
setFlags(0);
@ -157,85 +141,58 @@ namespace MP4 {
setODGraphicsLevel(0xFF);
}
void IODS::setIODTypeTag(char value) {
setInt8(value, 4);
}
void IODS::setIODTypeTag(char value){setInt8(value, 4);}
char IODS::getIODTypeTag() {
return getInt8(4);
}
char IODS::getIODTypeTag(){return getInt8(4);}
void IODS::setDescriptorTypeLength(char length) {
setInt8(length, 5);
}
void IODS::setDescriptorTypeLength(char length){setInt8(length, 5);}
char IODS::getDescriptorTypeLength() {
return getInt8(5);
}
char IODS::getDescriptorTypeLength(){return getInt8(5);}
void IODS::setODID(short id) {
setInt16(id, 6);
}
void IODS::setODID(short id){setInt16(id, 6);}
short IODS::getODID() {
return getInt16(6);
}
short IODS::getODID(){return getInt16(6);}
void IODS::setODProfileLevel(char value) {
setInt8(value, 8);
}
void IODS::setODProfileLevel(char value){setInt8(value, 8);}
char IODS::getODProfileLevel() {
return getInt8(8);
}
char IODS::getODProfileLevel(){return getInt8(8);}
void IODS::setODSceneLevel(char value) {
setInt8(value, 9);
}
void IODS::setODSceneLevel(char value){setInt8(value, 9);}
char IODS::getODSceneLevel() {
return getInt8(9);
}
char IODS::getODSceneLevel(){return getInt8(9);}
void IODS::setODAudioLevel(char value) {
setInt8(value, 10);
}
void IODS::setODAudioLevel(char value){setInt8(value, 10);}
char IODS::getODAudioLevel() {
return getInt8(10);
}
char IODS::getODAudioLevel(){return getInt8(10);}
void IODS::setODVideoLevel(char value) {
setInt8(value, 11);
}
void IODS::setODVideoLevel(char value){setInt8(value, 11);}
char IODS::getODVideoLevel() {
return getInt8(11);
}
char IODS::getODVideoLevel(){return getInt8(11);}
void IODS::setODGraphicsLevel(char value) {
setInt8(value, 12);
}
void IODS::setODGraphicsLevel(char value){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;
r << std::string(indent, ' ') << "[iods] IODS Box (" << boxedSize() << ")" << std::endl;
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, ' ') << "DescriptorTypeLength: " << std::hex << std::setw(2) << std::setfill('0') << (int)getDescriptorTypeLength() << 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, ' ') << "OD Profile Level: " << std::hex << std::setw(2) << 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;
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, ' ') << "DescriptorTypeLength: " << std::hex << std::setw(2)
<< std::setfill('0') << (int)getDescriptorTypeLength() << 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, ' ') << "OD Profile Level: " << std::hex << std::setw(2)
<< 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();
}
}
}// namespace MP4

View file

@ -1,8 +1,8 @@
#pragma once
#include "mp4.h"
namespace MP4 {
struct sidxReference {
namespace MP4{
struct sidxReference{
bool referenceType;
uint32_t referencedSize;
uint32_t subSegmentDuration;
@ -11,7 +11,7 @@ namespace MP4 {
uint32_t sapDeltaTime;
};
class SIDX: public fullBox {
class SIDX : public fullBox{
public:
SIDX();
void setReferenceID(uint32_t newReferenceID);
@ -25,13 +25,13 @@ namespace MP4 {
uint64_t getFirstOffset();
uint16_t getReferenceCount();
void setReference(sidxReference & newRef, size_t index);
void setReference(sidxReference &newRef, size_t index);
sidxReference getReference(size_t index);
std::string toPrettyString(uint32_t indent = 0);
};
class TFDT: public fullBox {
class TFDT : public fullBox{
public:
TFDT();
void setBaseMediaDecodeTime(uint64_t newBaseMediaDecodeTime);
@ -40,7 +40,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class IODS: public fullBox {
class IODS : public fullBox{
public:
IODS();
void setIODTypeTag(char value);
@ -69,5 +69,4 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
}
}// namespace MP4

View file

@ -1,15 +1,14 @@
#include "mp4_encryption.h"
#include "defines.h"
#include "mp4_encryption.h"
namespace MP4 {
namespace MP4{
PSSH::PSSH() {
memcpy(data + 4, "pssh", 4);
}
PSSH::PSSH(){memcpy(data + 4, "pssh", 4);}
std::string PSSH::toPrettyString(uint32_t indent) {
std::string PSSH::toPrettyString(uint32_t indent){
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 << std::string(indent + 1, ' ') << "SystemID: " << getSystemIDHex() << std::endl;
if (getVersion()){
@ -18,7 +17,7 @@ namespace MP4 {
r << std::string(indent + 1, ' ') << "DataSize: " << getDataSize() << std::endl;
r << std::string(indent + 1, ' ') << "Data: ";
size_t dataSize = getDataSize();
char * data = getData();
char *data = getData();
for (size_t i = 0; i < dataSize; ++i){
r << std::hex << std::setw(2) << std::setfill('0') << (int)data[i] << std::dec << "";
}
@ -26,8 +25,8 @@ namespace MP4 {
return r.str();
}
std::string PSSH::getSystemIDHex() {
char * systemID = getString(4);
std::string PSSH::getSystemIDHex(){
char *systemID = getString(4);
std::stringstream res;
for (size_t i = 0; i < 16; ++i){
res << std::hex << std::setw(2) << std::setfill('0') << (int)systemID[i] << std::dec;
@ -35,13 +34,9 @@ namespace MP4 {
return "0x" + res.str();
}
void PSSH::setSystemIDHex(const std::string & systemID) {
setString(systemID, 4);
}
void PSSH::setSystemIDHex(const std::string &systemID){setString(systemID, 4);}
size_t PSSH::getKIDCount(){
return getVersion() ? getInt32(20) : 0;
}
size_t PSSH::getKIDCount(){return getVersion() ? getInt32(20) : 0;}
size_t PSSH::getDataSize(){
if (getVersion()){
@ -51,7 +46,7 @@ namespace MP4 {
return getInt32(20);
}
char * PSSH::getData(){
char *PSSH::getData(){
if (getVersion()){
size_t kidCount = getInt32(20);
return getString(24 + (kidCount * 16) + 4);
@ -59,18 +54,16 @@ namespace MP4 {
return getString(24);
}
void PSSH::setData(const std::string & data){
void PSSH::setData(const std::string &data){
if (getVersion()){
WARN_MSG("Not implemented yet!");
return;
}
for (int i = 0; i < data.size(); i++){
setInt8(data[i], 24 + i);
}
for (int i = 0; i < data.size(); i++){setInt8(data[i], 24 + i);}
setInt32(data.size(), 20);
}
std::string TENC::toPrettyString(uint32_t indent) {
std::string TENC::toPrettyString(uint32_t indent){
std::stringstream r;
r << std::string(indent, ' ') << "[tenc] Track Encryption Box (" << boxedSize() << ")" << std::endl;
r << fullBox::toPrettyString(indent);
@ -85,31 +78,21 @@ namespace MP4 {
return r.str();
}
TENC::TENC() {
TENC::TENC(){
memcpy(data + 4, "tenc", 4);
setDefaultIsEncrypted(1);
setDefaultIVSize(8);
}
size_t TENC::getDefaultIsEncrypted(){
return getInt24(4);
}
void TENC::setDefaultIsEncrypted(size_t isEncrypted){
setInt24(isEncrypted, 4);
}
size_t TENC::getDefaultIVSize(){
return getInt8(7);
}
void TENC::setDefaultIVSize(uint8_t ivSize){
setInt8(ivSize, 7);
}
size_t TENC::getDefaultIsEncrypted(){return getInt24(4);}
void TENC::setDefaultIsEncrypted(size_t isEncrypted){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 result;
for (int i = 8; i < 24; i++){
result += getInt8(i);
}
for (int i = 8; i < 24; i++){result += getInt8(i);}
return result;
}
void TENC::setDefaultKID(const std::string & kid){
void TENC::setDefaultKID(const std::string &kid){
for (int i = 0; i < 16; i++){
if (i < kid.size()){
setInt8(kid[i], i + 8);
@ -119,80 +102,75 @@ namespace MP4 {
}
}
SENC::SENC() {
SENC::SENC(){
memcpy(data + 4, "senc", 4);
setFlags(2);
}
uint32_t SENC::getSampleCount() const {
return getInt32(4);
}
uint32_t SENC::getSampleCount() const{return getInt32(4);}
#define IV_SIZE 8
void SENC::setSample(UUID_SampleEncryption_Sample newSample, size_t index) {
void SENC::setSample(UUID_SampleEncryption_Sample newSample, size_t index){
int myOffset = 8;
for (unsigned int i = 0; i < std::min(index, (size_t)getSampleCount()); i++) {
for (unsigned int i = 0; i < std::min(index, (size_t)getSampleCount()); i++){
myOffset += IV_SIZE;
if (getFlags() & 0x02) {
if (getFlags() & 0x02){
int entryCount = getInt16(myOffset);
myOffset += 2 + (entryCount * 6);
}
}
if (index > getSampleCount()) {
if (index > getSampleCount()){
ERROR_MSG("First fill intermediate entries!");
return;
/*
//we are now at the end of currently reserved space, reserve more and adapt offset accordingly.
int reserveSize = ((index - getSampleCount())) * (IV_SIZE + (getFlags() & 0x02));
//we are now at the end of currently reserved space, reserve more and adapt offset
accordingly. int reserveSize = ((index - getSampleCount())) * (IV_SIZE + (getFlags() & 0x02));
reserveSize += IV_SIZE;
if (getFlags() & 0x02) {
if (getFlags() & 0x02){
reserveSize += 2 + newSample.Entries.size();
}
if (!reserve(myOffset, 0, reserveSize)) {
if (!reserve(myOffset, 0, reserveSize)){
return;//Memory errors...
}
myOffset += (index - getSampleCount()) * (IV_SIZE + (getFlags() & 0x02));
*/
}
//write box.
for (int i = 0; i < IV_SIZE; i++) {
setInt8(newSample.InitializationVector[i], myOffset ++);//set and skip
// write box.
for (int i = 0; i < IV_SIZE; i++){
setInt8(newSample.InitializationVector[i], myOffset++); // set and skip
}
if (getFlags() & 0x02) {
if (getFlags() & 0x02){
setInt16(newSample.Entries.size(), myOffset);
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);
myOffset += 2;
setInt32(it->BytesEncrypted, myOffset);
myOffset += 4;
}
}
if (index >= getSampleCount()) {
setInt32(index + 1, 4);
}
if (index >= getSampleCount()){setInt32(index + 1, 4);}
}
UUID_SampleEncryption_Sample SENC::getSample(size_t index) const {
if (index >= getSampleCount()) {
return UUID_SampleEncryption_Sample();
}
UUID_SampleEncryption_Sample SENC::getSample(size_t index) const{
if (index >= getSampleCount()){return UUID_SampleEncryption_Sample();}
int myOffset = 8;
for (unsigned int i = 0; i < index; i++) {
for (unsigned int i = 0; i < index; i++){
myOffset += IV_SIZE;
if (getFlags() & 0x02) {
if (getFlags() & 0x02){
int entryCount = getInt16(myOffset);
myOffset += 2;//skip over entrycount
myOffset += entryCount * 6;//skip entryCount sample entries
myOffset += 2; // skip over entrycount
myOffset += entryCount * 6; // skip entryCount sample entries
}
}
UUID_SampleEncryption_Sample result;
for (int i = 0; i < IV_SIZE; i++) {
result.InitializationVector += (char)getInt8(myOffset++);//read and skip
for (int i = 0; i < IV_SIZE; i++){
result.InitializationVector += (char)getInt8(myOffset++); // read and skip
}
if (getFlags() & 0x02) {
if (getFlags() & 0x02){
result.NumberOfEntries = getInt16(myOffset);
myOffset += 2;
for (unsigned int i = 0; i < result.NumberOfEntries; i++) {
for (unsigned int i = 0; i < result.NumberOfEntries; i++){
result.Entries.push_back(UUID_SampleEncryption_Sample_Entry());
result.Entries[i].BytesClear = getInt16(myOffset);
myOffset += 2;
@ -203,25 +181,27 @@ namespace MP4 {
return result;
}
std::string SENC::toPrettyString(uint32_t indent) const {
std::string SENC::toPrettyString(uint32_t indent) const{
std::stringstream r;
r << std::string(indent, ' ') << "[senc] Sample Encryption Box (" << boxedSize() << ")" << std::endl;
r << fullBox::toPrettyString(indent);
r << std::string(indent + 1, ' ') << "Sample Count: " << getSampleCount() << std::endl;
for (unsigned int i = 0; i < getSampleCount(); i++) {
for (unsigned int i = 0; i < getSampleCount(); i++){
UUID_SampleEncryption_Sample tmpSample = getSample(i);
r << std::string(indent + 1, ' ') << "[" << i << "]" << std::endl;
r << std::string(indent + 3, ' ') << "Initialization Vector: 0x";
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;
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::endl;
if (getFlags() & 0x02) {
if (getFlags() & 0x02){
r << std::string(indent + 3, ' ') << "Number of entries: " << tmpSample.NumberOfEntries << std::endl;
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 + 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;
}
}
}
@ -232,29 +212,26 @@ namespace MP4 {
memcpy(data + 4, "saiz", 4);
setFlags(0);
setVersion(0);
setInt24(0, 4); //Default sample size
setInt16(entryCount, 7);//EntryCount Samples
setInt24(0, 4); // Default sample size
setInt16(entryCount, 7); // EntryCount Samples
for (int i = 0; i < entryCount; i++){
setInt8(16, i+9);//16 bytes IV's
setInt8(16, i + 9); // 16 bytes IV's
}
}
size_t SAIZ::getDefaultSampleSize(){
return getInt24(4);
}
size_t SAIZ::getDefaultSampleSize(){return getInt24(4);}
size_t SAIZ::getEntryCount(){
return getInt16(7);
}
size_t SAIZ::getEntryCount(){return getInt16(7);}
size_t SAIZ::getEntrySize(size_t entryNo){
if (entryNo >= getEntryCount()){return -1;}
return getInt8(9 + entryNo);
}
std::string SAIZ::toPrettyString(uint32_t indent) {
std::string SAIZ::toPrettyString(uint32_t indent){
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 << std::string(indent + 1, ' ') << "Default Sample Size: " << getDefaultSampleSize() << std::endl;
r << std::string(indent + 1, ' ') << "Entry Count: " << getEntryCount() << std::endl;
@ -270,18 +247,17 @@ namespace MP4 {
setInt32(offset, 8);
}
size_t SAIO::getEntryCount(){
return getInt32(4);
}
size_t SAIO::getEntryCount(){return getInt32(4);}
size_t SAIO::getEntrySize(size_t entryNo){
if (entryNo >= getEntryCount()){return -1;}
return getInt32(8 + (entryNo * 4));
}
std::string SAIO::toPrettyString(uint32_t indent) {
std::string SAIO::toPrettyString(uint32_t indent){
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 << std::string(indent + 1, ' ') << "Entry Count: " << getEntryCount() << std::endl;
for (size_t i = 0; i < getEntryCount(); ++i){
@ -290,153 +266,122 @@ namespace MP4 {
return r.str();
}
UUID_SampleEncryption::UUID_SampleEncryption() {
setUUID((std::string)"a2394f52-5a9b-4f14-a244-6c427c648df4");
UUID_SampleEncryption::UUID_SampleEncryption(){
setUUID((std::string) "a2394f52-5a9b-4f14-a244-6c427c648df4");
}
UUID_SampleEncryption::UUID_SampleEncryption(const SENC & senc){
setUUID((std::string)"a2394f52-5a9b-4f14-a244-6c427c648df4");
UUID_SampleEncryption::UUID_SampleEncryption(const SENC &senc){
setUUID((std::string) "a2394f52-5a9b-4f14-a244-6c427c648df4");
setVersion(0);
setFlags(2);
size_t sampleCount = senc.getSampleCount();
for (size_t i = 0; i < sampleCount; ++i){
setSample(senc.getSample(i), i);
}
for (size_t i = 0; i < sampleCount; ++i){setSample(senc.getSample(i), i);}
}
void UUID_SampleEncryption::setVersion(uint32_t newVersion) {
setInt8(newVersion, 16);
void UUID_SampleEncryption::setVersion(uint32_t newVersion){setInt8(newVersion, 16);}
uint32_t UUID_SampleEncryption::getVersion(){return getInt8(16);}
void UUID_SampleEncryption::setFlags(uint32_t newFlags){setInt24(newFlags, 17);}
uint32_t UUID_SampleEncryption::getFlags(){return getInt24(17);}
void UUID_SampleEncryption::setAlgorithmID(uint32_t newAlgorithmID){
if (getFlags() & 0x01){setInt24(newAlgorithmID, 20);}
}
uint32_t UUID_SampleEncryption::getVersion() {
return getInt8(16);
}
void UUID_SampleEncryption::setFlags(uint32_t newFlags) {
setInt24(newFlags, 17);
}
uint32_t UUID_SampleEncryption::getFlags() {
return getInt24(17);
}
void UUID_SampleEncryption::setAlgorithmID(uint32_t newAlgorithmID) {
if (getFlags() & 0x01) {
setInt24(newAlgorithmID, 20);
}
}
uint32_t UUID_SampleEncryption::getAlgorithmID() {
if (getFlags() & 0x01) {
return getInt24(20);
}
uint32_t UUID_SampleEncryption::getAlgorithmID(){
if (getFlags() & 0x01){return getInt24(20);}
return -1;
}
void UUID_SampleEncryption::setIVSize(uint32_t newIVSize) {
if (getFlags() & 0x01) {
setInt8(newIVSize, 23);
}
void UUID_SampleEncryption::setIVSize(uint32_t newIVSize){
if (getFlags() & 0x01){setInt8(newIVSize, 23);}
}
uint32_t UUID_SampleEncryption::getIVSize() {
if (getFlags() & 0x01) {
return getInt8(23);
}
uint32_t UUID_SampleEncryption::getIVSize(){
if (getFlags() & 0x01){return getInt8(23);}
return -1;
}
void UUID_SampleEncryption::setKID(std::string newKID) {
if (newKID == "") {
return;
}
if (getFlags() & 0x01) {
while (newKID.size() < 16) {
newKID += (char)0x00;
}
for (int i = 0; i < 16; i++) {
setInt8(newKID[i], 24 + i);
}
void UUID_SampleEncryption::setKID(std::string newKID){
if (newKID == ""){return;}
if (getFlags() & 0x01){
while (newKID.size() < 16){newKID += (char)0x00;}
for (int i = 0; i < 16; i++){setInt8(newKID[i], 24 + i);}
}
}
std::string UUID_SampleEncryption::getKID() {
if (getFlags() & 0x01) {
std::string UUID_SampleEncryption::getKID(){
if (getFlags() & 0x01){
std::string result;
for (int i = 0; i < 16; i++) {
result += (char)getInt8(24 + i);
}
for (int i = 0; i < 16; i++){result += (char)getInt8(24 + i);}
return result;
}
return "";
}
uint32_t UUID_SampleEncryption::getSampleCount() {
uint32_t UUID_SampleEncryption::getSampleCount(){
int myOffset = 20;
if (getFlags() & 0x01) {
myOffset += 20;
}
if (getFlags() & 0x01){myOffset += 20;}
return getInt32(myOffset);
}
#define IV_SIZE 8
void UUID_SampleEncryption::setSample(UUID_SampleEncryption_Sample newSample, size_t index) {
void UUID_SampleEncryption::setSample(UUID_SampleEncryption_Sample newSample, size_t index){
int myOffset = 20;
myOffset += 20 * (getFlags() & 0x01);
myOffset += 4;//sampleCount is here;
for (unsigned int i = 0; i < std::min(index, (size_t)getSampleCount()); i++) {
myOffset += 4; // sampleCount is here;
for (unsigned int i = 0; i < std::min(index, (size_t)getSampleCount()); i++){
myOffset += IV_SIZE;
if (getFlags() & 0x02) {
if (getFlags() & 0x02){
int entryCount = getInt16(myOffset);
myOffset += 2 + (entryCount * 6);
}
}
if (index > getSampleCount()) {
if (index > getSampleCount()){
ERROR_MSG("First fill intermediate entries!");
return;
}
//write box.
for (int i = 0; i < IV_SIZE; i++) {
setInt8(newSample.InitializationVector[i], myOffset ++);//set and skip
// write box.
for (int i = 0; i < IV_SIZE; i++){
setInt8(newSample.InitializationVector[i], myOffset++); // set and skip
}
if (getFlags() & 0x02) {
if (getFlags() & 0x02){
setInt16(newSample.Entries.size(), myOffset);
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);
myOffset += 2;
setInt32(it->BytesEncrypted, myOffset);
myOffset += 4;
}
}
if (index >= getSampleCount()) {
setInt32(index + 1, 20 + (20 * (getFlags() & 0x01)));
}
if (index >= getSampleCount()){setInt32(index + 1, 20 + (20 * (getFlags() & 0x01)));}
}
UUID_SampleEncryption_Sample UUID_SampleEncryption::getSample(size_t index) {
if (index >= getSampleCount()) {
return UUID_SampleEncryption_Sample();
}
UUID_SampleEncryption_Sample UUID_SampleEncryption::getSample(size_t index){
if (index >= getSampleCount()){return UUID_SampleEncryption_Sample();}
int myOffset = 20;
myOffset += 20 * (getFlags() & 0x01);
myOffset += 4;//sampleCount is here
for (unsigned int i = 0; i < index; i++) {
myOffset += 4; // sampleCount is here
for (unsigned int i = 0; i < index; i++){
myOffset += IV_SIZE;
if (getFlags() & 0x02) {
if (getFlags() & 0x02){
int entryCount = getInt16(myOffset);
myOffset += 2;//skip over entrycount
myOffset += entryCount * 6;//skip entryCount sample entries
myOffset += 2; // skip over entrycount
myOffset += entryCount * 6; // skip entryCount sample entries
}
}
UUID_SampleEncryption_Sample result;
for (int i = 0; i < IV_SIZE; i++) {
result.InitializationVector += getInt8(myOffset++);//read and skip
for (int i = 0; i < IV_SIZE; i++){
result.InitializationVector += getInt8(myOffset++); // read and skip
}
if (getFlags() & 0x02) {
if (getFlags() & 0x02){
result.NumberOfEntries = getInt16(myOffset);
myOffset += 2;
for (unsigned int i = 0; i < result.NumberOfEntries; i++) {
for (unsigned int i = 0; i < result.NumberOfEntries; i++){
result.Entries.push_back(UUID_SampleEncryption_Sample_Entry());
result.Entries[i].BytesClear = getInt16(myOffset);
myOffset += 2;
@ -447,162 +392,136 @@ namespace MP4 {
return result;
}
std::string UUID_SampleEncryption::toPrettyString(uint32_t indent) {
std::string UUID_SampleEncryption::toPrettyString(uint32_t indent){
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, ' ') << "Flags: " << getFlags() << std::endl;
if (getFlags() & 0x01) {
if (getFlags() & 0x01){
r << std::string(indent + 1, ' ') << "Algorithm ID: " << getAlgorithmID() << std::endl;
r << std::string(indent + 1, ' ') << "IV Size: " << getIVSize() << std::endl;
r << std::string(indent + 1, ' ') << "Key ID: " << getKID() << std::endl;
}
r << std::string(indent + 1, ' ') << "Sample Count: " << getSampleCount() << std::endl;
for (unsigned int i = 0; i < getSampleCount(); i++) {
for (unsigned int i = 0; i < getSampleCount(); i++){
UUID_SampleEncryption_Sample tmpSample = getSample(i);
r << std::string(indent + 1, ' ') << "[" << i << "]" << std::endl;
r << std::string(indent + 3, ' ') << "Initialization Vector: 0x";
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;
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::endl;
if (getFlags() & 0x02) {
if (getFlags() & 0x02){
r << std::string(indent + 3, ' ') << "Number of entries: " << tmpSample.NumberOfEntries << std::endl;
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 + 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;
}
}
}
return r.str();
}
UUID_TrackEncryption::UUID_TrackEncryption() {
setUUID((std::string)"8974dbce-7be7-4c51-84f9-7148f9882554");
UUID_TrackEncryption::UUID_TrackEncryption(){
setUUID((std::string) "8974dbce-7be7-4c51-84f9-7148f9882554");
}
void UUID_TrackEncryption::setVersion(uint32_t newVersion) {
setInt8(newVersion, 16);
}
void UUID_TrackEncryption::setVersion(uint32_t newVersion){setInt8(newVersion, 16);}
uint32_t UUID_TrackEncryption::getVersion() {
return getInt8(16);
}
uint32_t UUID_TrackEncryption::getVersion(){return getInt8(16);}
void UUID_TrackEncryption::setFlags(uint32_t newFlags) {
setInt24(newFlags, 17);
}
void UUID_TrackEncryption::setFlags(uint32_t newFlags){setInt24(newFlags, 17);}
uint32_t UUID_TrackEncryption::getFlags() {
return getInt24(17);
}
uint32_t UUID_TrackEncryption::getFlags(){return getInt24(17);}
void UUID_TrackEncryption::setDefaultAlgorithmID(uint32_t newID) {
setInt24(newID, 20);
}
void UUID_TrackEncryption::setDefaultAlgorithmID(uint32_t newID){setInt24(newID, 20);}
uint32_t UUID_TrackEncryption::getDefaultAlgorithmID() {
return getInt24(20);
}
uint32_t UUID_TrackEncryption::getDefaultAlgorithmID(){return getInt24(20);}
void UUID_TrackEncryption::setDefaultIVSize(uint8_t newIVSize) {
setInt8(newIVSize, 23);
}
void UUID_TrackEncryption::setDefaultIVSize(uint8_t newIVSize){setInt8(newIVSize, 23);}
uint8_t UUID_TrackEncryption::getDefaultIVSize() {
return getInt8(23);
}
uint8_t UUID_TrackEncryption::getDefaultIVSize(){return getInt8(23);}
void UUID_TrackEncryption::setDefaultKID(std::string newKID) {
for (unsigned int i = 0; i < 16; i++) {
if (i < newKID.size()) {
void UUID_TrackEncryption::setDefaultKID(std::string newKID){
for (unsigned int i = 0; i < 16; i++){
if (i < newKID.size()){
setInt8(newKID[i], 24 + i);
} else {
}else{
setInt8(0x00, 24 + i);
}
}
}
std::string UUID_TrackEncryption::getDefaultKID() {
std::string UUID_TrackEncryption::getDefaultKID(){
std::string result;
for (int i = 0; i < 16; i++) {
result += getInt8(24 + i);
}
for (int i = 0; i < 16; i++){result += getInt8(24 + i);}
return result;
}
std::string UUID_TrackEncryption::toPrettyString(uint32_t indent) {
std::string UUID_TrackEncryption::toPrettyString(uint32_t indent){
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, ' ') << "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 KID: 16 bytes of binary data." << std::endl;
return r.str();
}
UUID_ProtectionSystemSpecificHeader::UUID_ProtectionSystemSpecificHeader() {
setUUID((std::string)"d08a4f18-10f3-4a82-b6c8-32d8aba183d3");
UUID_ProtectionSystemSpecificHeader::UUID_ProtectionSystemSpecificHeader(){
setUUID((std::string) "d08a4f18-10f3-4a82-b6c8-32d8aba183d3");
}
void UUID_ProtectionSystemSpecificHeader::setVersion(uint32_t newVersion) {
void UUID_ProtectionSystemSpecificHeader::setVersion(uint32_t newVersion){
setInt8(newVersion, 16);
}
uint32_t UUID_ProtectionSystemSpecificHeader::getVersion() {
return getInt8(16);
}
uint32_t UUID_ProtectionSystemSpecificHeader::getVersion(){return getInt8(16);}
void UUID_ProtectionSystemSpecificHeader::setFlags(uint32_t newFlags) {
setInt24(newFlags, 17);
}
void UUID_ProtectionSystemSpecificHeader::setFlags(uint32_t newFlags){setInt24(newFlags, 17);}
uint32_t UUID_ProtectionSystemSpecificHeader::getFlags() {
return getInt24(17);
}
uint32_t UUID_ProtectionSystemSpecificHeader::getFlags(){return getInt24(17);}
void UUID_ProtectionSystemSpecificHeader::setSystemID(std::string newID) {
for (unsigned int i = 0; i < 16; i++) {
if (i < newID.size()) {
void UUID_ProtectionSystemSpecificHeader::setSystemID(std::string newID){
for (unsigned int i = 0; i < 16; i++){
if (i < newID.size()){
setInt8(newID[i], 20 + i);
} else {
}else{
setInt8(0x00, 20 + i);
}
}
}
std::string UUID_ProtectionSystemSpecificHeader::getSystemID() {
std::string UUID_ProtectionSystemSpecificHeader::getSystemID(){
std::string result;
for (int i = 0; i < 16; i++) {
result += getInt8(20 + i);
}
for (int i = 0; i < 16; i++){result += getInt8(20 + i);}
return result;
}
uint32_t UUID_ProtectionSystemSpecificHeader::getDataSize() {
return getInt32(36);
}
uint32_t UUID_ProtectionSystemSpecificHeader::getDataSize(){return getInt32(36);}
void UUID_ProtectionSystemSpecificHeader::setData(std::string newData) {
void UUID_ProtectionSystemSpecificHeader::setData(std::string newData){
setInt32(newData.size(), 36);
for (unsigned int i = 0; i < newData.size(); i++) {
setInt8(newData[i], 40 + i);
}
for (unsigned int i = 0; i < newData.size(); i++){setInt8(newData[i], 40 + i);}
}
std::string UUID_ProtectionSystemSpecificHeader::getData() {
std::string UUID_ProtectionSystemSpecificHeader::getData(){
std::string result;
for (unsigned int i = 0; i < getDataSize(); i++) {
result += getInt8(40 + i);
}
for (unsigned int i = 0; i < getDataSize(); i++){result += getInt8(40 + i);}
return result;
}
std::string UUID_ProtectionSystemSpecificHeader::toPrettyString(uint32_t indent) {
std::string UUID_ProtectionSystemSpecificHeader::toPrettyString(uint32_t indent){
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, ' ') << "Flags: " << getFlags() << std::endl;
r << std::string(indent + 2, ' ') << "System ID: " << getSystemID() << std::endl;
@ -611,66 +530,54 @@ namespace MP4 {
return r.str();
}
SINF::SINF() {
memcpy(data + 4, "sinf", 4);
}
SINF::SINF(){memcpy(data + 4, "sinf", 4);}
void SINF::setEntry(Box & newEntry, uint32_t no) {
if (no > 4) {
return;
}
void SINF::setEntry(Box &newEntry, uint32_t no){
if (no > 4){return;}
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();
}
setBox(newEntry, tempLoc);
}
Box & SINF::getEntry(uint32_t no) {
Box &SINF::getEntry(uint32_t no){
static Box ret = Box((char *)"\000\000\000\010erro", false);
if (no > 4) {
return ret;
}
if (no > 4){return ret;}
int tempLoc = 0;
for (unsigned int i = 0; i < no; i++) {
tempLoc += getBoxLen(tempLoc);
}
for (unsigned int i = 0; i < no; i++){tempLoc += getBoxLen(tempLoc);}
return getBox(tempLoc);
}
std::string SINF::toPrettyString(uint32_t indent) {
std::string SINF::toPrettyString(uint32_t indent){
std::stringstream r;
std::cerr << payloadOffset << std::endl;
r << std::string(indent, ' ') << "[sinf] Protection Scheme Info Box (" << boxedSize() << ")" << std::endl;
for (int i = 0; i < 4; i++) {
if (!getEntry(i).isType("erro")) {
r << getEntry(i).toPrettyString(indent + 2);
}
for (int i = 0; i < 4; i++){
if (!getEntry(i).isType("erro")){r << getEntry(i).toPrettyString(indent + 2);}
}
r << std::endl;
return r.str();
}
FRMA::FRMA(const std::string & originalFormat) {
FRMA::FRMA(const std::string &originalFormat){
memcpy(data + 4, "frma", 4);
setOriginalFormat(originalFormat);
}
void FRMA::setOriginalFormat(const std::string & newFormat) {
for (unsigned int i = 0; i < 4; i++) {
if (i < newFormat.size()) {
void FRMA::setOriginalFormat(const std::string &newFormat){
for (unsigned int i = 0; i < 4; i++){
if (i < newFormat.size()){
setInt8(newFormat[i], i);
} else {
}else{
setInt8(0x00, i);
}
}
}
std::string FRMA::getOriginalFormat() {
return std::string(payload(), 4);
}
std::string FRMA::getOriginalFormat(){return std::string(payload(), 4);}
std::string FRMA::toPrettyString(uint32_t indent) {
std::string FRMA::toPrettyString(uint32_t indent){
std::stringstream r;
r << std::string(indent, ' ') << "[frma] Original Format Box (" << boxedSize() << ")" << std::endl;
r << std::string(indent + 2, ' ') << "Original Format: " << getOriginalFormat() << std::endl;
@ -683,65 +590,50 @@ namespace MP4 {
setSchemeVersion(schemeVersion);
}
void SCHM::setSchemeType(uint32_t newType) {
setInt32(htonl(newType), 4);
}
void SCHM::setSchemeType(uint32_t newType){setInt32(htonl(newType), 4);}
uint32_t SCHM::getSchemeType() {
return ntohl(getInt32(4));
}
uint32_t SCHM::getSchemeType(){return ntohl(getInt32(4));}
void SCHM::setSchemeVersion(uint32_t newVersion) {
setInt32(htonl(newVersion), 8);
}
void SCHM::setSchemeVersion(uint32_t newVersion){setInt32(htonl(newVersion), 8);}
uint32_t SCHM::getSchemeVersion() {
return ntohl(getInt32(8));
}
uint32_t SCHM::getSchemeVersion(){return ntohl(getInt32(8));}
void SCHM::setSchemeURI(std::string newURI) {
void SCHM::setSchemeURI(std::string newURI){
setFlags(getFlags() | 0x01);
setString(newURI, 12);
}
std::string SCHM::getSchemeURI() {
if (getFlags() & 0x01) {
return getString(12);
}
std::string SCHM::getSchemeURI(){
if (getFlags() & 0x01){return getString(12);}
return "";
}
std::string SCHM::toPrettyString(uint32_t indent) {
std::string SCHM::toPrettyString(uint32_t indent){
std::stringstream r;
r << std::string(indent, ' ') << "[schm] Scheme Type Box (" << boxedSize() << ")" << std::endl;
char tmpStr[10];
int tmpInt = getSchemeType();
sprintf(tmpStr, "%.4s", (char *)&tmpInt);
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;
if (getFlags() & 0x01) {
r << std::string(indent + 2, ' ') << "SchemeVersion: 0x" << std::hex << std::setw(8)
<< std::setfill('0') << getSchemeVersion() << std::dec << std::endl;
if (getFlags() & 0x01){
r << std::string(indent + 2, ' ') << "SchemeURI: " << getSchemeURI() << std::endl;
}
return r.str();
}
SCHI::SCHI() {
memcpy(data + 4, "schi", 4);
}
SCHI::SCHI(){memcpy(data + 4, "schi", 4);}
void SCHI::setContent(Box & newContent) {
setBox(newContent, 0);
}
void SCHI::setContent(Box &newContent){setBox(newContent, 0);}
Box & SCHI::getContent() {
return getBox(0);
}
Box &SCHI::getContent(){return getBox(0);}
std::string SCHI::toPrettyString(uint32_t indent) {
std::string SCHI::toPrettyString(uint32_t indent){
std::stringstream r;
r << std::string(indent, ' ') << "[schi] Scheme Information Box (" << boxedSize() << ")" << std::endl;
r << getContent().toPrettyString(indent + 2);
return r.str();
}
}
}// namespace MP4

View file

@ -1,32 +1,32 @@
#include "mp4.h"
#include "mp4_ms.h"
namespace MP4 {
namespace MP4{
struct UUID_SampleEncryption_Sample_Entry {
struct UUID_SampleEncryption_Sample_Entry{
uint32_t BytesClear;
uint32_t BytesEncrypted;
};
struct UUID_SampleEncryption_Sample {
struct UUID_SampleEncryption_Sample{
std::string InitializationVector;
uint32_t NumberOfEntries;
std::vector<UUID_SampleEncryption_Sample_Entry> Entries;
};
class PSSH: public fullBox {
class PSSH : public fullBox{
public:
PSSH();
std::string getSystemIDHex();
void setSystemIDHex(const std::string & systemID);
void setSystemIDHex(const std::string &systemID);
std::string toPrettyString(uint32_t indent = 0);
size_t getKIDCount();
size_t getDataSize();
char * getData();
void setData(const std::string & data);
char *getData();
void setData(const std::string &data);
};
class TENC: public fullBox {
class TENC : public fullBox{
public:
TENC();
std::string toPrettyString(uint32_t indent = 0);
@ -35,10 +35,10 @@ namespace MP4 {
size_t getDefaultIVSize();
void setDefaultIVSize(uint8_t ivSize);
std::string getDefaultKID();
void setDefaultKID(const std::string & kid);
void setDefaultKID(const std::string &kid);
};
class SENC: public fullBox {
class SENC : public fullBox{
public:
SENC();
uint32_t getSampleCount() const;
@ -47,7 +47,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0) const;
};
class SAIZ : public fullBox {
class SAIZ : public fullBox{
public:
SAIZ(size_t entryCount = 0);
size_t getDefaultSampleSize();
@ -56,7 +56,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class SAIO : public fullBox {
class SAIO : public fullBox{
public:
SAIO(size_t offset = 0);
size_t getEntryCount();
@ -64,10 +64,10 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class UUID_SampleEncryption: public UUID {
class UUID_SampleEncryption : public UUID{
public:
UUID_SampleEncryption();
UUID_SampleEncryption(const SENC & senc);
UUID_SampleEncryption(const SENC &senc);
void setVersion(uint32_t newVersion);
uint32_t getVersion();
void setFlags(uint32_t newFlags);
@ -84,7 +84,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class UUID_TrackEncryption: public UUID {
class UUID_TrackEncryption : public UUID{
public:
UUID_TrackEncryption();
void setVersion(uint32_t newVersion);
@ -100,7 +100,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class UUID_ProtectionSystemSpecificHeader: public UUID {
class UUID_ProtectionSystemSpecificHeader : public UUID{
public:
UUID_ProtectionSystemSpecificHeader();
void setVersion(uint32_t newVersion);
@ -116,25 +116,25 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class SINF: public Box {
class SINF : public Box{
public:
SINF();
void setEntry(Box & newEntry, uint32_t no);
Box & getEntry(uint32_t no);
void setEntry(Box &newEntry, uint32_t no);
Box &getEntry(uint32_t no);
std::string toPrettyString(uint32_t indent = 0);
};
class FRMA: public Box {
class FRMA : public Box{
public:
FRMA(const std::string & originalFormat = "");
void setOriginalFormat(const std::string & newFormat);
FRMA(const std::string &originalFormat = "");
void setOriginalFormat(const std::string &newFormat);
std::string getOriginalFormat();
std::string toPrettyString(uint32_t indent = 0);
};
class SCHM: public fullBox {
class SCHM : public fullBox{
public:
SCHM(uint32_t schemeType = 0x636E6563, uint32_t schemeVersion = 0x00000100);//CENC defaults
SCHM(uint32_t schemeType = 0x636E6563, uint32_t schemeVersion = 0x00000100); // CENC defaults
void setSchemeType(uint32_t newType);
uint32_t getSchemeType();
void setSchemeVersion(uint32_t newVersion);
@ -144,12 +144,12 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class SCHI: public Box {
class SCHI : public Box{
public:
SCHI();
void setContent(Box & newContent);
Box & getContent();
void setContent(Box &newContent);
Box &getContent();
std::string toPrettyString(uint32_t indent = 0);
};
}
}// namespace MP4

File diff suppressed because it is too large Load diff

View file

@ -1,43 +1,43 @@
#pragma once
#include "mp4.h"
namespace h265 {
namespace h265{
struct metaInfo;
}
namespace MP4 {
class MFHD: public Box {
namespace MP4{
class MFHD : public Box{
public:
MFHD();
void setSequenceNumber(uint32_t newSequenceNumber);
uint32_t getSequenceNumber();
std::string toPrettyString(uint32_t indent = 0);
};
//MFHD Box
// MFHD Box
class MOOF: public containerBox {
class MOOF : public containerBox{
public:
MOOF();
};
//MOOF Box
// MOOF Box
class TRAF: public Box {
class TRAF : public Box{
public:
TRAF();
uint32_t getContentCount();
void setContent(Box & newContent, uint32_t no);
Box & getContent(uint32_t no, bool unsafe = false);
void setContent(Box &newContent, uint32_t no);
Box &getContent(uint32_t no, bool unsafe = false);
std::string toPrettyString(uint32_t indent = 0);
};
//TRAF Box
// TRAF Box
struct trunSampleInformation {
struct trunSampleInformation{
uint32_t sampleDuration;
uint32_t sampleSize;
uint32_t sampleFlags;
uint32_t sampleOffset;
};
enum trunflags {
enum trunflags{
trundataOffset = 0x00000001,
trunfirstSampleFlags = 0x00000004,
trunsampleDuration = 0x00000100,
@ -45,7 +45,7 @@ namespace MP4 {
trunsampleFlags = 0x00000400,
trunsampleOffsets = 0x00000800
};
enum sampleflags {
enum sampleflags{
noIPicture = 0x01000000,
isIPicture = 0x02000000,
noDisposable = 0x00400000,
@ -57,7 +57,7 @@ namespace MP4 {
MUST_BE_PRESENT = 0x1
};
std::string prettySampleFlags(uint32_t flag);
class TRUN: public Box {
class TRUN : public Box{
public:
TRUN();
void setFlags(uint32_t newFlags);
@ -72,7 +72,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
enum tfhdflags {
enum tfhdflags{
tfhdBaseOffset = 0x000001,
tfhdSampleDesc = 0x000002,
tfhdSampleDura = 0x000008,
@ -81,7 +81,7 @@ namespace MP4 {
tfhdNoDuration = 0x010000,
tfhdBaseIsMoof = 0x020000,
};
class TFHD: public Box {
class TFHD : public Box{
public:
TFHD();
void setFlags(uint32_t newFlags);
@ -102,8 +102,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class AVCC: public Box {
class AVCC : public Box{
public:
AVCC();
void setVersion(uint32_t newVersion);
@ -118,36 +117,36 @@ namespace MP4 {
void setSPSCount(uint32_t _count);
uint32_t getSPSCount();
void setSPS(std::string newSPS, size_t index = 0);
void setSPS(const char * data, size_t len, size_t index = 0);
void setSPS(const char *data, size_t len, size_t index = 0);
uint32_t getSPSLen(size_t index = 0);
char * getSPS(size_t index = 0);
char *getSPS(size_t index = 0);
std::string hexSPS(size_t index = 0);
size_t PPSCountOffset();
void setPPSCount(uint32_t _count);
uint32_t getPPSCount();
void setPPS(std::string newPPS, size_t index = 0);
void setPPS(const char * data, size_t len, size_t index = 0);
void setPPS(const char *data, size_t len, size_t index = 0);
uint32_t getPPSLen(size_t index = 0);
char * getPPS(size_t index = 0);
char *getPPS(size_t index = 0);
void multiplyPPS(size_t newAmount);
std::string hexPPS(size_t index = 0);
std::string asAnnexB();
void setPayload(std::string newPayload);
void setPayload(const char * data, size_t len);
void setPayload(const char *data, size_t len);
bool sanitize();
std::string toPrettyString(uint32_t indent = 0);
};
struct HVCCArrayEntry {
struct HVCCArrayEntry{
char arrayCompleteness;
char nalUnitType;
std::deque<std::string> nalUnits;
};
class HVCC: public Box {
class HVCC : public Box{
public:
HVCC();
void setConfigurationVersion(char newVersion);
@ -185,7 +184,7 @@ namespace MP4 {
void setLengthSizeMinus1(char newLengthSizeMinus1);
char getLengthSizeMinus1();
///\todo Add setter for the array entries
void setArrays(std::deque<HVCCArrayEntry> & arrays);
void setArrays(std::deque<HVCCArrayEntry> &arrays);
std::deque<HVCCArrayEntry> getArrays();
std::string asAnnexB();
void setPayload(std::string newPayload);
@ -196,53 +195,50 @@ namespace MP4 {
class Descriptor{
public:
Descriptor();
Descriptor(const char* pointer, const unsigned long length, const bool master = false);
char getTag();///< Get type of descriptor
void setTag(char t);///< Set type of descriptor
unsigned long getDataSize();///< Get internal size of descriptor
unsigned long getFullSize();///< Get external size of descriptor
void resize(unsigned long t);///< Resize descriptor
char* getData();///< Returns pointer to start of internal data
std::string toPrettyString(uint32_t indent = 0);///< put it into a pretty string
Descriptor(const char *pointer, const unsigned long length, const bool master = false);
char getTag(); ///< Get type of descriptor
void setTag(char t); ///< Set type of descriptor
unsigned long getDataSize(); ///< Get internal size of descriptor
unsigned long getFullSize(); ///< Get external size of descriptor
void resize(unsigned long t); ///< Resize descriptor
char *getData(); ///< Returns pointer to start of internal data
std::string toPrettyString(uint32_t indent = 0); ///< put it into a pretty string
protected:
unsigned long size;///< Length of data
char* data;///< Pointer to data in memory
unsigned long size; ///< Length of data
char *data; ///< Pointer to data in memory
bool master;
};
/// Implements ISO 14496-1 DecSpecificInfoTag
class DSDescriptor: public Descriptor{
class DSDescriptor : public Descriptor{
public:
DSDescriptor (const char* pointer, const unsigned long length, const bool master = false);
std::string toPrettyString(uint32_t indent = 0);///< put it into a pretty string
DSDescriptor(const char *pointer, const unsigned long length, const bool master = false);
std::string toPrettyString(uint32_t indent = 0); ///< put it into a pretty string
std::string toString(); ///< Return decoder specific info as standard string in binary format.
};
/// Implements ISO 14496-1 DecoderConfigDescrTag
class DCDescriptor: public Descriptor{
class DCDescriptor : public Descriptor{
public:
DCDescriptor (const char* pointer, const unsigned long length, const bool master = false);
DCDescriptor(const char *pointer, const unsigned long length, const bool master = false);
bool isAAC(); ///< Returns true if this track is AAC.
std::string getCodec();
DSDescriptor getSpecific();
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 ES_DescrTag
class ESDescriptor: public Descriptor{
class ESDescriptor : public Descriptor{
public:
ESDescriptor (const char* pointer, const unsigned long length, const bool master = false);
ESDescriptor(const char *pointer, const unsigned long length, const bool master = false);
DCDescriptor getDecoderConfig();
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
class SLCDescriptor: public Descriptor{
};
class SLCDescriptor : public Descriptor{};
class ESDS: public fullBox {
class ESDS : public fullBox{
public:
ESDS();
ESDS(std::string init);
@ -253,54 +249,54 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class DAC3: public Box {
class DAC3 : public Box{
public:
DAC3(unsigned int rate, unsigned int channels);
char getSampleRateCode();//2bits
void setSampleRateCode(char newVal);//2bits
char getBitStreamIdentification();//5bits
void setBitStreamIdentification(char newVal);//5bits
char getBitStreamMode();//3 bits
void setBitStreamMode(char newVal);//3 bits
char getAudioConfigMode();//3 bits
void setAudioConfigMode(char newVal);//3 bits
bool getLowFrequencyEffectsChannelOn();//1bit
void setLowFrequencyEffectsChannelOn(bool newVal);//1bit
char getFrameSizeCode();//6bits
void setFrameSizeCode(char newVal);//6bits
char getSampleRateCode(); // 2bits
void setSampleRateCode(char newVal); // 2bits
char getBitStreamIdentification(); // 5bits
void setBitStreamIdentification(char newVal); // 5bits
char getBitStreamMode(); // 3 bits
void setBitStreamMode(char newVal); // 3 bits
char getAudioConfigMode(); // 3 bits
void setAudioConfigMode(char newVal); // 3 bits
bool getLowFrequencyEffectsChannelOn(); // 1bit
void setLowFrequencyEffectsChannelOn(bool newVal); // 1bit
char getFrameSizeCode(); // 6bits
void setFrameSizeCode(char newVal); // 6bits
std::string toPrettyString(uint32_t indent = 0);
};
class FTYP: public Box {
class FTYP : public Box{
public:
FTYP(bool fillDefaults = true);
void setMajorBrand(const char * newMajorBrand);
void setMajorBrand(const char *newMajorBrand);
std::string getMajorBrand();
void setMinorVersion(const char * newMinorVersion);
void setMinorVersion(const char *newMinorVersion);
std::string getMinorVersion();
size_t getCompatibleBrandsCount();
void setCompatibleBrands(const char * newCompatibleBrand, size_t index);
void setCompatibleBrands(const char *newCompatibleBrand, size_t index);
std::string getCompatibleBrands(size_t index);
std::string toPrettyString(uint32_t indent = 0);
};
class STYP: public FTYP {
class STYP : public FTYP{
public:
STYP(bool fillDefaults = true);
std::string toPrettyString(uint32_t indent = 0);
};
class MOOV: public containerBox {
class MOOV : public containerBox{
public:
MOOV();
};
class MVEX: public containerBox {
class MVEX : public containerBox{
public:
MVEX();
};
class TREX: public fullBox {
class TREX : public fullBox{
public:
TREX(unsigned int trackId = 0);
void setTrackID(uint32_t newTrackID);
@ -316,33 +312,32 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class MFRA: public containerBox {
class MFRA : public containerBox{
public:
MFRA();
};
class TRAK: public containerBox {
class TRAK : public containerBox{
public:
TRAK();
};
class MDIA: public containerBox {
class MDIA : public containerBox{
public:
MDIA();
};
class MINF: public containerBox {
class MINF : public containerBox{
public:
MINF();
};
class DINF: public containerBox {
class DINF : public containerBox{
public:
DINF();
};
class MFRO: public Box {
class MFRO : public Box{
public:
MFRO();
void setSize(uint32_t newSize);
@ -350,17 +345,17 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class HDLR: public Box {
class HDLR : public Box{
public:
HDLR(const std::string & type = "", const std::string & name = "");
void setHandlerType(const char * newHandlerType);
HDLR(const std::string &type = "", const std::string &name = "");
void setHandlerType(const char *newHandlerType);
std::string getHandlerType();
void setName(std::string newName);
std::string getName();
std::string toPrettyString(uint32_t indent = 0);
};
class VMHD: public fullBox {
class VMHD : public fullBox{
public:
VMHD();
void setGraphicsMode(uint16_t newGraphicsMode);
@ -371,7 +366,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class SMHD: public fullBox {
class SMHD : public fullBox{
public:
SMHD();
void setBalance(int16_t newBalance);
@ -379,13 +374,13 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class STHD: public fullBox {
class STHD : public fullBox{
public:
STHD();
std::string toPrettyString(uint32_t indent = 0);
};
class HMHD: public fullBox {
class HMHD : public fullBox{
public:
HMHD();
void setMaxPDUSize(uint16_t newMaxPDUSize);
@ -399,13 +394,13 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class NMHD: public fullBox {
class NMHD : public fullBox{
public:
NMHD();
std::string toPrettyString(uint32_t indent = 0);
};
class MEHD: public fullBox {
class MEHD : public fullBox{
public:
MEHD();
void setFragmentDuration(uint64_t newFragmentDuration);
@ -413,12 +408,12 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class STBL: public containerBox {
class STBL : public containerBox{
public:
STBL();
};
class URL: public fullBox {
class URL : public fullBox{
public:
URL();
void setLocation(std::string newLocation);
@ -426,7 +421,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class URN: public fullBox {
class URN : public fullBox{
public:
URN();
void setName(std::string newName);
@ -436,16 +431,16 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class DREF: public fullBox {
class DREF : public fullBox{
public:
DREF();
uint32_t getEntryCount();
void setDataEntry(fullBox & newDataEntry, size_t index);
Box & getDataEntry(size_t index);
void setDataEntry(fullBox &newDataEntry, size_t index);
Box &getDataEntry(size_t index);
std::string toPrettyString(uint32_t indent = 0);
};
class MVHD: public fullBox {
class MVHD : public fullBox{
public:
MVHD(long long unsigned int duration);
void setCreationTime(uint64_t newCreationTime);
@ -468,7 +463,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
struct TFRAEntry {
struct TFRAEntry{
uint64_t time;
uint64_t moofOffset;
uint32_t trafNumber;
@ -476,7 +471,7 @@ namespace MP4 {
uint32_t sampleNumber;
};
class TFRA: public fullBox {
class TFRA : public fullBox{
public:
TFRA();
void setTrackID(uint32_t newTrackID);
@ -490,15 +485,15 @@ namespace MP4 {
void setNumberOfEntry(uint32_t newNumberOfEntry);
uint32_t getNumberOfEntry();
void setTFRAEntry(TFRAEntry newTFRAEntry, uint32_t no);
TFRAEntry & getTFRAEntry(uint32_t no);
TFRAEntry &getTFRAEntry(uint32_t no);
uint32_t getTFRAEntrySize();
std::string toPrettyString(uint32_t indent = 0);
};
class TKHD: public fullBox {
class TKHD : public fullBox{
public:
TKHD(uint32_t trackId = 0, uint64_t duration = 0, uint32_t width = 0, uint32_t height = 0);
TKHD(DTSC::Track & track, bool fragmented);
TKHD(DTSC::Track &track, bool fragmented);
void setCreationTime(uint64_t newCreationTime);
uint64_t getCreationTime();
@ -525,11 +520,12 @@ namespace MP4 {
void setHeight(double newHeight);
double getHeight();
std::string toPrettyString(uint32_t indent = 0);
protected:
void initialize();
};
class MDHD: public fullBox {
class MDHD : public fullBox{
public:
MDHD(uint64_t duration = 0);
void setCreationTime(uint64_t newCreationTime);
@ -542,17 +538,17 @@ namespace MP4 {
uint64_t getDuration();
void setLanguage(uint16_t newLanguage);
uint16_t getLanguageInt();
void setLanguage(const std::string & newLanguage);
void setLanguage(const std::string &newLanguage);
std::string getLanguage();
std::string toPrettyString(uint32_t indent = 0);
};
struct STTSEntry {
struct STTSEntry{
uint32_t sampleCount;
uint32_t sampleDelta;
};
class STTS: public fullBox {
class STTS : public fullBox{
public:
STTS(char v = 1, uint32_t f = 0);
void setEntryCount(uint32_t newEntryCount);
@ -562,12 +558,12 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
struct CTTSEntry {
struct CTTSEntry{
uint32_t sampleCount;
int32_t sampleOffset;
};
class CTTS: public fullBox {
class CTTS : public fullBox{
public:
CTTS();
void setEntryCount(uint32_t newEntryCount);
@ -577,7 +573,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class STSCEntry {
class STSCEntry{
public:
STSCEntry(unsigned int _first = 0, unsigned int _count = 0, unsigned int _index = 0);
uint32_t firstChunk;
@ -585,7 +581,7 @@ namespace MP4 {
uint32_t sampleDescriptionIndex;
};
class STSC: public fullBox {
class STSC : public fullBox{
public:
STSC(char v = 1, uint32_t f = 0);
void setEntryCount(uint32_t newEntryCount);
@ -595,7 +591,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class STCO: public fullBox {
class STCO : public fullBox{
public:
STCO(char v = 1, uint32_t f = 0);
void setEntryCount(uint32_t newEntryCount);
@ -605,7 +601,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class CO64: public fullBox {
class CO64 : public fullBox{
public:
CO64(char v = 1, uint32_t f = 0);
void setEntryCount(uint32_t newEntryCount);
@ -615,7 +611,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class STSZ: public fullBox {
class STSZ : public fullBox{
public:
STSZ(char v = 1, uint32_t f = 0);
void setSampleSize(uint32_t newSampleSize);
@ -627,7 +623,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class SampleEntry: public Box {
class SampleEntry : public Box{
public:
SampleEntry();
void setDataReferenceIndex(uint16_t newDataReferenceIndex);
@ -635,7 +631,7 @@ namespace MP4 {
std::string toPrettySampleString(uint32_t index);
};
class CLAP: public Box { //CleanApertureBox
class CLAP : public Box{// CleanApertureBox
public:
CLAP();
void setCleanApertureWidthN(uint32_t newVal);
@ -657,7 +653,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class PASP: public Box { //PixelAspectRatioBox
class PASP : public Box{// PixelAspectRatioBox
public:
PASP(uint32_t hSpacing = 1, uint32_t vSpacing = 1);
void setHSpacing(uint32_t newVal);
@ -667,13 +663,13 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class VisualSampleEntry: public SampleEntry {
class VisualSampleEntry : public SampleEntry{
///\todo set default values
public:
VisualSampleEntry();
VisualSampleEntry(DTSC::Track & track);
VisualSampleEntry(DTSC::Track &track);
void initialize();
void setCodec(const char * newCodec);
void setCodec(const char *newCodec);
void setWidth(uint16_t newWidth);
uint16_t getWidth();
void setHeight(uint16_t newHeight);
@ -688,25 +684,25 @@ namespace MP4 {
std::string getCompressorName();
void setDepth(uint16_t newDepth);
uint16_t getDepth();
Box & getCLAP();
void setCLAP(Box & clap);
Box & getPASP();
void setPASP(Box & pasp);
Box &getCLAP();
void setCLAP(Box &clap);
Box &getPASP();
void setPASP(Box &pasp);
size_t getBoxEntryCount();
Box & getBoxEntry(size_t index);
void setBoxEntry(size_t index, Box & box);
Box &getBoxEntry(size_t index);
void setBoxEntry(size_t index, Box &box);
std::string toPrettyVisualString(uint32_t index = 0, std::string = "");
};
class AudioSampleEntry: public SampleEntry {
class AudioSampleEntry : public SampleEntry{
public:
///\todo set default values
AudioSampleEntry();
AudioSampleEntry(DTSC::Track & track);
AudioSampleEntry(DTSC::Track &track);
void initialize();
void setCodec(const char * newCodec);
void setCodec(const char *newCodec);
void setChannelCount(uint16_t newChannelCount);
uint16_t getChannelCount();
void setSampleSize(uint16_t newSampleSize);
@ -716,20 +712,20 @@ namespace MP4 {
void setSampleRate(uint32_t newSampleRate);
uint16_t toAACInit();
uint32_t getSampleRate();
void setCodecBox(Box & newBox);
Box & getCodecBox();
Box & getSINFBox(); /*LTS*/
void setCodecBox(Box &newBox);
Box &getCodecBox();
Box &getSINFBox(); /*LTS*/
std::string toPrettyAudioString(uint32_t indent = 0, std::string name = "");
};
struct BoxRecord {
struct BoxRecord{
int16_t top;
int16_t left;
int16_t bottom;
int16_t right;
};
struct StyleRecord {
struct StyleRecord{
uint16_t startChar;
uint16_t endChar;
uint16_t font_id;
@ -738,19 +734,19 @@ namespace MP4 {
uint8_t text_color_rgba[4];
};
class FontRecord {
class FontRecord{
public:
FontRecord();
~FontRecord();
uint16_t font_id;
uint8_t font_name_length;
char* font;
//uint8_t font[font_name_length];
char *font;
// uint8_t font[font_name_length];
void setFont(const char* f);
void setFont(const char *f);
};
class FontTableBox: public Box {
class FontTableBox : public Box{
public:
FontTableBox();
void setEntryCount(uint16_t);
@ -759,13 +755,13 @@ namespace MP4 {
void setFontRecord(FontRecord f);
FontRecord font_entry[1];
void setFontId(uint16_t id);
//FontRecord font_entry[entry_count];
// FontRecord font_entry[entry_count];
};
class TextSampleEntry: public SampleEntry {
class TextSampleEntry : public SampleEntry{
public:
TextSampleEntry();
TextSampleEntry(DTSC::Track & track);
TextSampleEntry(DTSC::Track &track);
void initialize();
void setHzJustification(int8_t n);
void setVtJustification(int8_t n);
@ -776,9 +772,9 @@ namespace MP4 {
uint8_t getBackGroundColorRGBA(uint8_t n = 0);
void setBackGroundColorRGBA(uint8_t pos, uint8_t value);
void setCodec(const char * newCodec);
void setCodecBox(Box & newBox);
Box & getCodecBox();
void setCodec(const char *newCodec);
void setCodecBox(Box &newBox);
Box &getCodecBox();
BoxRecord getBoxRecord();
void setBoxRecord(BoxRecord b);
@ -789,52 +785,46 @@ namespace MP4 {
FontTableBox getFontTableBox();
void setFontTableBox(FontTableBox f);
std::string toPrettyTextString(uint32_t indent = 0, std::string name = "");
};
class TX3G: public TextSampleEntry {
class TX3G : public TextSampleEntry{
public:
TX3G();
std::string toPrettyString(uint32_t indent = 0);
};
class MP4A: public AudioSampleEntry {
class MP4A : public AudioSampleEntry{
public:
MP4A();
std::string toPrettyString(uint32_t indent = 0);
};
class AAC: public AudioSampleEntry {
class AAC : public AudioSampleEntry{
public:
AAC();
std::string toPrettyString(uint32_t indent = 0);
};
class HEV1: public VisualSampleEntry {
class HEV1 : public VisualSampleEntry{
public:
HEV1();
std::string toPrettyString(uint32_t indent = 0);
};
class AVC1: public VisualSampleEntry {
class AVC1 : public VisualSampleEntry{
public:
AVC1();
std::string toPrettyString(uint32_t indent = 0);
};
class H264: public VisualSampleEntry {
class H264 : public VisualSampleEntry{
public:
H264();
std::string toPrettyString(uint32_t indent = 0);
};
class FIEL: public Box {
class FIEL : public Box{
public:
FIEL();
void setTotal(char newTotal);
@ -844,37 +834,37 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class STSD: public fullBox {
class STSD : public fullBox{
public:
STSD(char v = 1, uint32_t f = 0);
void setEntryCount(uint32_t newEntryCount);
uint32_t getEntryCount();
void setEntry(Box & newContent, uint32_t no);
Box & getEntry(uint32_t no);
void setEntry(Box &newContent, uint32_t no);
Box &getEntry(uint32_t no);
std::string toPrettyString(uint32_t indent = 0);
};
class GMHD: public containerBox {
class GMHD : public containerBox{
public:
GMHD();
};
class TREF: public containerBox {
class TREF : public containerBox{
public:
TREF();
};
class EDTS: public containerBox {
class EDTS : public containerBox{
public:
EDTS();
};
class UDTA: public containerBox {
class UDTA : public containerBox{
public:
UDTA();
};
class STSS: public fullBox {
class STSS : public fullBox{
public:
STSS(char v = 1, uint32_t f = 0);
void setEntryCount(uint32_t newVal);
@ -884,13 +874,13 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class META: public containerFullBox {
class META : public containerFullBox{
public:
META();
std::string toPrettyString(uint32_t indent = 0);
};
class ELST: public fullBox {
class ELST : public fullBox{
public:
ELST();
void setCount(uint32_t newVal);
@ -905,5 +895,4 @@ namespace MP4 {
uint16_t getMediaRateFraction(uint32_t cnt);
std::string toPrettyString(uint32_t indent = 0);
};
}
}// namespace MP4

View file

@ -1,144 +1,101 @@
#include "mp4_ms.h"
#include "mp4_encryption.h" /*LTS*/
#include "mp4_ms.h"
namespace MP4 {
namespace MP4{
static char c2hex(int c) {
static char c2hex(int c){
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
return 0;
}
SDTP::SDTP(){memcpy(data + 4, "sdtp", 4);}
SDTP::SDTP() {
memcpy(data + 4, "sdtp", 4);
}
void SDTP::setVersion(uint32_t newVersion){setInt8(newVersion, 0);}
void SDTP::setVersion(uint32_t newVersion) {
setInt8(newVersion, 0);
}
uint32_t SDTP::getVersion(){return getInt8(0);}
uint32_t SDTP::getVersion() {
return getInt8(0);
}
void SDTP::setValue(uint32_t newValue, size_t index){setInt8(newValue, index);}
void SDTP::setValue(uint32_t newValue, size_t index) {
setInt8(newValue, index);
}
uint32_t SDTP::getValue(size_t index){return getInt8(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;
r << std::string(indent, ' ') << "[sdtp] Sample Dependancy Type (" << boxedSize() << ")" << std::endl;
r << std::string(indent + 1, ' ') << "Samples: " << (boxedSize() - 12) << std::endl;
for (size_t i = 1; i <= boxedSize() - 12; ++i) {
for (size_t i = 1; i <= boxedSize() - 12; ++i){
uint32_t val = getValue(i + 3);
r << std::string(indent + 2, ' ') << "[" << i << "] = ";
switch (val & 3) {
case 0:
r << " ";
break;
case 1:
r << "Redundant, ";
break;
case 2:
r << "Not redundant, ";
break;
case 3:
r << "Error, ";
break;
switch (val & 3){
case 0: r << " "; break;
case 1: r << "Redundant, "; break;
case 2: r << "Not redundant, "; break;
case 3: r << "Error, "; break;
}
switch (val & 12) {
case 0:
r << " ";
break;
case 4:
r << "Not disposable, ";
break;
case 8:
r << "Disposable, ";
break;
case 12:
r << "Error, ";
break;
switch (val & 12){
case 0: r << " "; break;
case 4: r << "Not disposable, "; break;
case 8: r << "Disposable, "; break;
case 12: r << "Error, "; break;
}
switch (val & 48) {
case 0:
r << " ";
break;
case 16:
r << "IFrame, ";
break;
case 32:
r << "Not IFrame, ";
break;
case 48:
r << "Error, ";
break;
switch (val & 48){
case 0: r << " "; break;
case 16: r << "IFrame, "; break;
case 32: r << "Not IFrame, "; break;
case 48: r << "Error, "; break;
}
r << "(" << val << ")" << std::endl;
}
return r.str();
}
UUID::UUID() {
UUID::UUID(){
memcpy(data + 4, "uuid", 4);
setInt64(0, 0);
setInt64(0, 8);
}
std::string UUID::getUUID() {
std::string UUID::getUUID(){
std::stringstream r;
r << std::hex;
for (int i = 0; i < 16; ++i) {
if (i == 4 || i == 6 || i == 8 || i == 10) {
r << "-";
}
for (int i = 0; i < 16; ++i){
if (i == 4 || i == 6 || i == 8 || i == 10){r << "-";}
r << std::setfill('0') << std::setw(2) << std::right << (int)(data[8 + i]);
}
return r.str();
}
void UUID::setUUID(const std::string & uuid_string) {
//reset UUID to zero
for (int i = 0; i < 4; ++i) {
((uint32_t *)(data + 8))[i] = 0;
}
//set the UUID from the string, char by char
void UUID::setUUID(const std::string &uuid_string){
// reset UUID to zero
for (int i = 0; i < 4; ++i){((uint32_t *)(data + 8))[i] = 0;}
// set the UUID from the string, char by char
int i = 0;
for (size_t j = 0; j < uuid_string.size(); ++j) {
if (uuid_string[j] == '-') {
continue;
}
for (size_t j = 0; j < uuid_string.size(); ++j){
if (uuid_string[j] == '-'){continue;}
data[8 + i / 2] |= (c2hex(uuid_string[j]) << ((~i & 1) << 2));
++i;
}
}
void UUID::setUUID(const char * raw_uuid) {
memcpy(data + 8, raw_uuid, 16);
}
void UUID::setUUID(const char *raw_uuid){memcpy(data + 8, raw_uuid, 16);}
std::string UUID::toPrettyString(uint32_t indent) {
std::string UUID::toPrettyString(uint32_t indent){
std::string UUID = getUUID();
if (UUID == "d4807ef2-ca39-4695-8e54-26cb9e46a79f") {
if (UUID == "d4807ef2-ca39-4695-8e54-26cb9e46a79f"){
return ((UUID_TrackFragmentReference *)this)->toPrettyString(indent);
}
/*LTS-START*/
if (UUID == "a2394f52-5a9b-4f14-a244-6c427c648df4") {
if (UUID == "a2394f52-5a9b-4f14-a244-6c427c648df4"){
return ((UUID_SampleEncryption *)this)->toPrettyString(indent);
}
if (UUID == "8974dbce-7be7-4c51-84f9-7148f9882554") {
if (UUID == "8974dbce-7be7-4c51-84f9-7148f9882554"){
return ((UUID_TrackEncryption *)this)->toPrettyString(indent);
}
if (UUID == "d08a4f18-10f3-4a82-b6c8-32d8aba183d3") {
if (UUID == "d08a4f18-10f3-4a82-b6c8-32d8aba183d3"){
return ((UUID_ProtectionSystemSpecificHeader *)this)->toPrettyString(indent);
}
if (UUID == "6d1d9b05-42d5-44e6-80e2-141daff757b2") {
if (UUID == "6d1d9b05-42d5-44e6-80e2-141daff757b2"){
return ((UUID_TFXD *)this)->toPrettyString(indent);
}
/*LTS-END*/
@ -149,139 +106,122 @@ namespace MP4 {
return r.str();
}
UUID_TrackFragmentReference::UUID_TrackFragmentReference() {
setUUID((std::string)"d4807ef2-ca39-4695-8e54-26cb9e46a79f");
UUID_TrackFragmentReference::UUID_TrackFragmentReference(){
setUUID((std::string) "d4807ef2-ca39-4695-8e54-26cb9e46a79f");
}
void UUID_TrackFragmentReference::setVersion(uint32_t newVersion) {
setInt8(newVersion, 16);
}
void UUID_TrackFragmentReference::setVersion(uint32_t newVersion){setInt8(newVersion, 16);}
uint32_t UUID_TrackFragmentReference::getVersion() {
return getInt8(16);
}
uint32_t UUID_TrackFragmentReference::getVersion(){return getInt8(16);}
void UUID_TrackFragmentReference::setFlags(uint32_t newFlags) {
setInt24(newFlags, 17);
}
void UUID_TrackFragmentReference::setFlags(uint32_t newFlags){setInt24(newFlags, 17);}
uint32_t UUID_TrackFragmentReference::getFlags() {
return getInt24(17);
}
uint32_t UUID_TrackFragmentReference::getFlags(){return getInt24(17);}
void UUID_TrackFragmentReference::setFragmentCount(uint32_t newCount) {
setInt8(newCount, 20);
}
void UUID_TrackFragmentReference::setFragmentCount(uint32_t newCount){setInt8(newCount, 20);}
uint32_t UUID_TrackFragmentReference::getFragmentCount() {
return getInt8(20);
}
uint32_t UUID_TrackFragmentReference::getFragmentCount(){return getInt8(20);}
void UUID_TrackFragmentReference::setTime(size_t num, uint64_t newTime) {
if (getVersion() == 0) {
void UUID_TrackFragmentReference::setTime(size_t num, uint64_t newTime){
if (getVersion() == 0){
setInt32(newTime, 21 + (num * 8));
} else {
}else{
setInt64(newTime, 21 + (num * 16));
}
}
uint64_t UUID_TrackFragmentReference::getTime(size_t num) {
if (getVersion() == 0) {
uint64_t UUID_TrackFragmentReference::getTime(size_t num){
if (getVersion() == 0){
return getInt32(21 + (num * 8));
} else {
}else{
return getInt64(21 + (num * 16));
}
}
void UUID_TrackFragmentReference::setDuration(size_t num, uint64_t newDuration) {
if (getVersion() == 0) {
void UUID_TrackFragmentReference::setDuration(size_t num, uint64_t newDuration){
if (getVersion() == 0){
setInt32(newDuration, 21 + (num * 8) + 4);
} else {
}else{
setInt64(newDuration, 21 + (num * 16) + 8);
}
}
uint64_t UUID_TrackFragmentReference::getDuration(size_t num) {
if (getVersion() == 0) {
uint64_t UUID_TrackFragmentReference::getDuration(size_t num){
if (getVersion() == 0){
return getInt32(21 + (num * 8) + 4);
} else {
}else{
return getInt64(21 + (num * 16) + 8);
}
}
std::string UUID_TrackFragmentReference::toPrettyString(uint32_t indent) {
std::string UUID_TrackFragmentReference::toPrettyString(uint32_t indent){
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, ' ') << "Fragments: " << getFragmentCount() << std::endl;
int j = getFragmentCount();
for (int i = 0; i < j; ++i) {
r << std::string(indent + 2, ' ') << "[" << i << "] Time = " << getTime(i) << ", Duration = " << getDuration(i) << std::endl;
for (int i = 0; i < j; ++i){
r << std::string(indent + 2, ' ') << "[" << i << "] Time = " << getTime(i)
<< ", Duration = " << getDuration(i) << std::endl;
}
return r.str();
}
UUID_TFXD::UUID_TFXD() {
setUUID((std::string)"6d1d9b05-42d5-44e6-80e2-141daff757b2");
UUID_TFXD::UUID_TFXD(){
setUUID((std::string) "6d1d9b05-42d5-44e6-80e2-141daff757b2");
setVersion(0);
setFlags(0);
}
void UUID_TFXD::setVersion(uint32_t newVersion) {
setInt8(newVersion, 16);
}
void UUID_TFXD::setVersion(uint32_t newVersion){setInt8(newVersion, 16);}
uint32_t UUID_TFXD::getVersion() {
return getInt8(16);
}
uint32_t UUID_TFXD::getVersion(){return getInt8(16);}
void UUID_TFXD::setFlags(uint32_t newFlags) {
setInt24(newFlags, 17);
}
void UUID_TFXD::setFlags(uint32_t newFlags){setInt24(newFlags, 17);}
uint32_t UUID_TFXD::getFlags() {
return getInt24(17);
}
uint32_t UUID_TFXD::getFlags(){return getInt24(17);}
void UUID_TFXD::setTime(uint64_t newTime) {
if (getVersion() == 0) {
void UUID_TFXD::setTime(uint64_t newTime){
if (getVersion() == 0){
setInt32(newTime, 20);
} else {
}else{
setInt64(newTime, 20);
}
}
uint64_t UUID_TFXD::getTime() {
if (getVersion() == 0) {
uint64_t UUID_TFXD::getTime(){
if (getVersion() == 0){
return getInt32(20);
} else {
}else{
return getInt64(20);
}
}
void UUID_TFXD::setDuration(uint64_t newDuration) {
if (getVersion() == 0) {
void UUID_TFXD::setDuration(uint64_t newDuration){
if (getVersion() == 0){
setInt32(newDuration, 24);
} else {
}else{
setInt64(newDuration, 28);
}
}
uint64_t UUID_TFXD::getDuration() {
if (getVersion() == 0) {
uint64_t UUID_TFXD::getDuration(){
if (getVersion() == 0){
return getInt32(24);
} else {
}else{
return getInt64(28);
}
}
std::string UUID_TFXD::toPrettyString(uint32_t indent) {
std::string UUID_TFXD::toPrettyString(uint32_t indent){
std::stringstream r;
setUUID((std::string)"6d1d9b05-42d5-44e6-80e2-141daff757b2");
r << std::string(indent, ' ') << "[6d1d9b05-42d5-44e6-80e2-141daff757b2] TFXD Box (" << boxedSize() << ")" << std::endl;
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 + 1, ' ') << "Version: " << getVersion() << std::endl;
r << std::string(indent + 1, ' ') << "Time = " << getTime() << std::endl;
r << std::string(indent + 1, ' ') << "Duration = " << getDuration() << std::endl;
return r.str();
}
}
}// namespace MP4

View file

@ -1,8 +1,8 @@
#pragma once
#include "mp4.h"
namespace MP4 {
class SDTP: public Box {
namespace MP4{
class SDTP : public Box{
public:
SDTP();
void setVersion(uint32_t newVersion);
@ -12,16 +12,16 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class UUID: public Box {
class UUID : public Box{
public:
UUID();
std::string getUUID();
void setUUID(const std::string & uuid_string);
void setUUID(const char * raw_uuid);
void setUUID(const std::string &uuid_string);
void setUUID(const char *raw_uuid);
std::string toPrettyString(uint32_t indent = 0);
};
class UUID_TrackFragmentReference: public UUID {
class UUID_TrackFragmentReference : public UUID{
public:
UUID_TrackFragmentReference();
void setVersion(uint32_t newVersion);
@ -37,7 +37,7 @@ namespace MP4 {
std::string toPrettyString(uint32_t indent = 0);
};
class UUID_TFXD: public UUID {
class UUID_TFXD : public UUID{
public:
UUID_TFXD();
void setVersion(uint32_t newVersion);
@ -50,4 +50,4 @@ namespace MP4 {
uint64_t getDuration();
std::string toPrettyString(uint32_t indent = 0);
};
}
}// namespace MP4

View file

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

View file

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

View file

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

View file

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

View file

@ -1,13 +1,13 @@
#include "ogg.h"
#include "bitstream.h"
#include "defines.h"
#include <string.h>
#include <stdlib.h>
#include <sstream>
#include "ogg.h"
#include <arpa/inet.h>
#include <iomanip>
#include "bitstream.h"
#include <sstream>
#include <stdlib.h>
#include <string.h>
namespace OGG {
namespace OGG{
oggSegment::oggSegment(){
isKeyframe = 0;
@ -16,21 +16,17 @@ namespace OGG {
framesSinceKeyFrame = 0;
}
std::deque<unsigned int> decodeXiphSize(char * data, size_t len){
std::deque<unsigned int> decodeXiphSize(char *data, size_t len){
std::deque<unsigned int> res;
res.push_back(0);
for (unsigned int i = 0; i < len; i++){
*res.rbegin() += data[i];
if (data[i] != 0xFF){
res.push_back(0);
}
}
if (*res.rbegin() == 0){
res.resize(res.size() - 1);
if (data[i] != 0xFF){res.push_back(0);}
}
if (*res.rbegin() == 0){res.resize(res.size() - 1);}
return res;
}
inline long long unsigned int get_64(char * data){
inline long long unsigned int get_64(char *data){
long long unsigned int temp = 0;
for (int i = 7; i >= 0; --i){
temp <<= 8;
@ -39,7 +35,7 @@ namespace OGG {
return temp;
}
inline long unsigned int get_32(char * data){
inline long unsigned int get_32(char *data){
long unsigned int temp = 0;
for (int i = 3; i >= 0; --i){
temp <<= 8;
@ -48,22 +44,20 @@ namespace OGG {
return temp;
}
inline void set_64(char * data, long unsigned int val){
inline void set_64(char *data, long unsigned int val){
for (int i = 0; i < 8; ++i){
data[i] = val & 0xFF;
val >>= 8;
}
}
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){
data[i] = val & 0xFF;
val >>= 8;
}
}
Page::Page(){
framesSeen = 0;
lastKeyFrame = 0;
@ -74,66 +68,60 @@ namespace OGG {
memset(data, 0, 282);
}
Page::Page(const Page & rhs){
framesSeen=rhs.framesSeen;
Page::Page(const Page &rhs){
framesSeen = rhs.framesSeen;
pageSequenceNumber = rhs.pageSequenceNumber;
lastKeyFrame = rhs.lastKeyFrame;
sampleRate = rhs.sampleRate;
firstSample = rhs.firstSample;
totalFrames= rhs.totalFrames;
totalFrames = rhs.totalFrames;
memcpy(data, rhs.data, 282);
segments = rhs.segments;
}
void Page::operator = (const Page & rhs){
framesSeen=rhs.framesSeen;
void Page::operator=(const Page &rhs){
framesSeen = rhs.framesSeen;
pageSequenceNumber = rhs.pageSequenceNumber;
lastKeyFrame = rhs.lastKeyFrame;
firstSample = rhs.firstSample;
sampleRate = rhs.sampleRate;
totalFrames= rhs.totalFrames;
totalFrames = rhs.totalFrames;
memcpy(data, rhs.data, 282);
segments = rhs.segments;
}
unsigned int Page::calcPayloadSize(){
unsigned int retVal = 0;
for (unsigned int i = 0; i < segments.size(); i++){
retVal += segments[i].size();
}
for (unsigned int i = 0; i < segments.size(); i++){retVal += segments[i].size();}
return retVal;
}
/// Reads an OGG Page from the source and if valid, removes it from source.
bool Page::read(std::string & newData){
bool Page::read(std::string &newData){
int len = newData.size();
int total = 0;
segments.clear();
if (newData.size() < 27){
return false;
}
if (newData.size() < 27){return false;}
if (newData.substr(0, 4) != "OggS"){
FAIL_MSG("Invalid Ogg page encountered (magic number wrong: %s) - cannot continue", newData.c_str());
return false;
}
memcpy(data, newData.c_str(), 27);//copying the header, always 27 bytes
if (newData.size() < 27u + getPageSegments()){ //check input size
memcpy(data, newData.c_str(), 27); // copying the header, always 27 bytes
if (newData.size() < 27u + getPageSegments()){// check input size
return false;
}
memcpy(data + 27, newData.data()+27, getPageSegments());
memcpy(data + 27, newData.data() + 27, getPageSegments());
std::deque<unsigned int> segSizes = decodeXiphSize(data + 27, getPageSegments());
for (std::deque<unsigned int>::iterator it = segSizes.begin(); it != segSizes.end(); it++){
total += *it;
}
total += 27;
//return false if the segment is not complete
// return false if the segment is not complete
total += getPageSegments();
if(total >= len){
return false;
}
if (total >= len){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++){
segments.push_back(std::string(newData.data(), *it));
newData.erase(0, *it);
@ -143,11 +131,10 @@ namespace OGG {
return true;
}
bool Page::read(FILE * inFile){
bool Page::read(FILE *inFile){
segments.clear();
int oriPos = ftell(inFile);
//INFO_MSG("pos: %d", oriPos);
// INFO_MSG("pos: %d", oriPos);
if (!fread(data, 27, 1, inFile)){
fseek(inFile, oriPos, SEEK_SET);
FAIL_MSG("failed to fread(data, 27, 1, inFile) @ pos %d", oriPos);
@ -165,12 +152,11 @@ namespace OGG {
std::deque<unsigned int> segSizes = decodeXiphSize(data + 27, getPageSegments());
for (std::deque<unsigned int>::iterator it = segSizes.begin(); it != segSizes.end(); it++){
if (*it){
char * thisSeg = (char *)malloc(*it * sizeof(char));
if (!thisSeg){
WARN_MSG("malloc failed");
}
char *thisSeg = (char *)malloc(*it * sizeof(char));
if (!thisSeg){WARN_MSG("malloc failed");}
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);
return false;
}
@ -179,13 +165,12 @@ namespace OGG {
}else{
segments.push_back(std::string("", 0));
}
}
return true;
}
bool Page::getSegment(unsigned int index, std::string & ret){
bool Page::getSegment(unsigned int index, std::string &ret){
if (index >= segments.size()){
ret.clear();
return false;
@ -194,94 +179,60 @@ namespace OGG {
return true;
}
const char * Page::getSegment(unsigned int index){
if (index >= segments.size()){
return 0;
}
const char *Page::getSegment(unsigned int index){
if (index >= segments.size()){return 0;}
return segments[index].data();
}
unsigned long Page::getSegmentLen(unsigned int index){
if (index >= segments.size()){
return 0;
}
if (index >= segments.size()){return 0;}
return segments[index].size();
}
void Page::setMagicNumber(){
memcpy(data, "OggS", 4);
}
void Page::setMagicNumber(){memcpy(data, "OggS", 4);}
char Page::getVersion(){
return data[4];
}
char Page::getVersion(){return data[4];}
void Page::setVersion(char newVal){
data[4] = newVal;
}
void Page::setVersion(char newVal){data[4] = newVal;}
char Page::getHeaderType(){
return data[5];
}
char Page::getHeaderType(){return data[5];}
void Page::setHeaderType(char newVal){
data[5] = newVal;
}
void Page::setHeaderType(char newVal){data[5] = newVal;}
long long unsigned int Page::getGranulePosition(){
return get_64(data + 6);
}
long long unsigned int Page::getGranulePosition(){return get_64(data + 6);}
void Page::setGranulePosition(long long unsigned int newVal){
set_64(data + 6, newVal);
}
void Page::setGranulePosition(long long unsigned int newVal){set_64(data + 6, newVal);}
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);
}
void Page::setBitstreamSerialNumber(long unsigned int newVal){
set_32(data + 14, newVal);
}
void Page::setBitstreamSerialNumber(long unsigned int newVal){set_32(data + 14, newVal);}
long unsigned int Page::getPageSequenceNumber(){
return get_32(data + 18);
}
long unsigned int Page::getPageSequenceNumber(){return get_32(data + 18);}
void Page::setPageSequenceNumber(long unsigned int newVal){
set_32(data + 18, newVal);
}
void Page::setPageSequenceNumber(long unsigned int newVal){set_32(data + 18, newVal);}
long unsigned int Page::getCRCChecksum(){
return get_32(data + 22);
}
long unsigned int Page::getCRCChecksum(){return get_32(data + 22);}
void Page::setCRCChecksum(long unsigned int newVal){
set_32(data + 22, newVal);
}
void Page::setCRCChecksum(long unsigned int newVal){set_32(data + 22, newVal);}
char Page::getPageSegments(){
return data[26];
}
char Page::getPageSegments(){return data[26];}
inline void Page::setPageSegments(char newVal){
data[26] = newVal;
}
inline void Page::setPageSegments(char newVal){data[26] = newVal;}
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)
return true;
} else {
}else{
return false;
}
}
bool Page::possiblyContinued(){
if (getPageSegments() == 255){
if (data[281] == 255){
return true;
}
if (data[281] == 255){return true;}
}
return false;
}
@ -293,98 +244,64 @@ namespace OGG {
r << std::string(indent + 2, ' ') << "Header type:";
if (!getHeaderType()){
r << " Normal";
} else {
if (getHeaderType() & Continued){
r << " Continued";
}
if (getHeaderType() & BeginOfStream){
r << " BeginOfStream";
}
if (getHeaderType() & EndOfStream){
r << " EndOfStream";
}
}else{
if (getHeaderType() & Continued){r << " Continued";}
if (getHeaderType() & BeginOfStream){r << " BeginOfStream";}
if (getHeaderType() & EndOfStream){r << " EndOfStream";}
}
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, ' ') << "Sequence number: " << getPageSequenceNumber() << std::endl;
r << std::string(indent + 2, ' ') << "Checksum Correct: " << verifyChecksum() << std::endl;
//r << " Calced Checksum: " << std::hex << calcChecksum() << std::dec << std::endl;
// r << " Calced Checksum: " << std::hex << calcChecksum() << std::dec << 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 + 3, ' ');
for (unsigned int i = 0; i < segments.size(); i++){
r << " " << segments[i].size();
}
for (unsigned int i = 0; i < segments.size(); i++){r << " " << segments[i].size();}
r << std::endl;
return r.str();
}
inline unsigned int crc32(unsigned int crc, const char * data, size_t len){
static const unsigned int table[256] = {
0x00000000U, 0x04C11DB7U, 0x09823B6EU, 0x0D4326D9U,
0x130476DCU, 0x17C56B6BU, 0x1A864DB2U, 0x1E475005U,
0x2608EDB8U, 0x22C9F00FU, 0x2F8AD6D6U, 0x2B4BCB61U,
0x350C9B64U, 0x31CD86D3U, 0x3C8EA00AU, 0x384FBDBDU,
0x4C11DB70U, 0x48D0C6C7U, 0x4593E01EU, 0x4152FDA9U,
0x5F15ADACU, 0x5BD4B01BU, 0x569796C2U, 0x52568B75U,
0x6A1936C8U, 0x6ED82B7FU, 0x639B0DA6U, 0x675A1011U,
0x791D4014U, 0x7DDC5DA3U, 0x709F7B7AU, 0x745E66CDU,
0x9823B6E0U, 0x9CE2AB57U, 0x91A18D8EU, 0x95609039U,
0x8B27C03CU, 0x8FE6DD8BU, 0x82A5FB52U, 0x8664E6E5U,
0xBE2B5B58U, 0xBAEA46EFU, 0xB7A96036U, 0xB3687D81U,
0xAD2F2D84U, 0xA9EE3033U, 0xA4AD16EAU, 0xA06C0B5DU,
0xD4326D90U, 0xD0F37027U, 0xDDB056FEU, 0xD9714B49U,
0xC7361B4CU, 0xC3F706FBU, 0xCEB42022U, 0xCA753D95U,
0xF23A8028U, 0xF6FB9D9FU, 0xFBB8BB46U, 0xFF79A6F1U,
0xE13EF6F4U, 0xE5FFEB43U, 0xE8BCCD9AU, 0xEC7DD02DU,
0x34867077U, 0x30476DC0U, 0x3D044B19U, 0x39C556AEU,
0x278206ABU, 0x23431B1CU, 0x2E003DC5U, 0x2AC12072U,
0x128E9DCFU, 0x164F8078U, 0x1B0CA6A1U, 0x1FCDBB16U,
0x018AEB13U, 0x054BF6A4U, 0x0808D07DU, 0x0CC9CDCAU,
0x7897AB07U, 0x7C56B6B0U, 0x71159069U, 0x75D48DDEU,
0x6B93DDDBU, 0x6F52C06CU, 0x6211E6B5U, 0x66D0FB02U,
0x5E9F46BFU, 0x5A5E5B08U, 0x571D7DD1U, 0x53DC6066U,
0x4D9B3063U, 0x495A2DD4U, 0x44190B0DU, 0x40D816BAU,
0xACA5C697U, 0xA864DB20U, 0xA527FDF9U, 0xA1E6E04EU,
0xBFA1B04BU, 0xBB60ADFCU, 0xB6238B25U, 0xB2E29692U,
0x8AAD2B2FU, 0x8E6C3698U, 0x832F1041U, 0x87EE0DF6U,
0x99A95DF3U, 0x9D684044U, 0x902B669DU, 0x94EA7B2AU,
0xE0B41DE7U, 0xE4750050U, 0xE9362689U, 0xEDF73B3EU,
0xF3B06B3BU, 0xF771768CU, 0xFA325055U, 0xFEF34DE2U,
0xC6BCF05FU, 0xC27DEDE8U, 0xCF3ECB31U, 0xCBFFD686U,
0xD5B88683U, 0xD1799B34U, 0xDC3ABDEDU, 0xD8FBA05AU,
0x690CE0EEU, 0x6DCDFD59U, 0x608EDB80U, 0x644FC637U,
0x7A089632U, 0x7EC98B85U, 0x738AAD5CU, 0x774BB0EBU,
0x4F040D56U, 0x4BC510E1U, 0x46863638U, 0x42472B8FU,
0x5C007B8AU, 0x58C1663DU, 0x558240E4U, 0x51435D53U,
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,
inline unsigned int crc32(unsigned int crc, const char *data, size_t len){
static const unsigned int table[256] ={
0x00000000U, 0x04C11DB7U, 0x09823B6EU, 0x0D4326D9U, 0x130476DCU, 0x17C56B6BU, 0x1A864DB2U,
0x1E475005U, 0x2608EDB8U, 0x22C9F00FU, 0x2F8AD6D6U, 0x2B4BCB61U, 0x350C9B64U, 0x31CD86D3U,
0x3C8EA00AU, 0x384FBDBDU, 0x4C11DB70U, 0x48D0C6C7U, 0x4593E01EU, 0x4152FDA9U, 0x5F15ADACU,
0x5BD4B01BU, 0x569796C2U, 0x52568B75U, 0x6A1936C8U, 0x6ED82B7FU, 0x639B0DA6U, 0x675A1011U,
0x791D4014U, 0x7DDC5DA3U, 0x709F7B7AU, 0x745E66CDU, 0x9823B6E0U, 0x9CE2AB57U, 0x91A18D8EU,
0x95609039U, 0x8B27C03CU, 0x8FE6DD8BU, 0x82A5FB52U, 0x8664E6E5U, 0xBE2B5B58U, 0xBAEA46EFU,
0xB7A96036U, 0xB3687D81U, 0xAD2F2D84U, 0xA9EE3033U, 0xA4AD16EAU, 0xA06C0B5DU, 0xD4326D90U,
0xD0F37027U, 0xDDB056FEU, 0xD9714B49U, 0xC7361B4CU, 0xC3F706FBU, 0xCEB42022U, 0xCA753D95U,
0xF23A8028U, 0xF6FB9D9FU, 0xFBB8BB46U, 0xFF79A6F1U, 0xE13EF6F4U, 0xE5FFEB43U, 0xE8BCCD9AU,
0xEC7DD02DU, 0x34867077U, 0x30476DC0U, 0x3D044B19U, 0x39C556AEU, 0x278206ABU, 0x23431B1CU,
0x2E003DC5U, 0x2AC12072U, 0x128E9DCFU, 0x164F8078U, 0x1B0CA6A1U, 0x1FCDBB16U, 0x018AEB13U,
0x054BF6A4U, 0x0808D07DU, 0x0CC9CDCAU, 0x7897AB07U, 0x7C56B6B0U, 0x71159069U, 0x75D48DDEU,
0x6B93DDDBU, 0x6F52C06CU, 0x6211E6B5U, 0x66D0FB02U, 0x5E9F46BFU, 0x5A5E5B08U, 0x571D7DD1U,
0x53DC6066U, 0x4D9B3063U, 0x495A2DD4U, 0x44190B0DU, 0x40D816BAU, 0xACA5C697U, 0xA864DB20U,
0xA527FDF9U, 0xA1E6E04EU, 0xBFA1B04BU, 0xBB60ADFCU, 0xB6238B25U, 0xB2E29692U, 0x8AAD2B2FU,
0x8E6C3698U, 0x832F1041U, 0x87EE0DF6U, 0x99A95DF3U, 0x9D684044U, 0x902B669DU, 0x94EA7B2AU,
0xE0B41DE7U, 0xE4750050U, 0xE9362689U, 0xEDF73B3EU, 0xF3B06B3BU, 0xF771768CU, 0xFA325055U,
0xFEF34DE2U, 0xC6BCF05FU, 0xC27DEDE8U, 0xCF3ECB31U, 0xCBFFD686U, 0xD5B88683U, 0xD1799B34U,
0xDC3ABDEDU, 0xD8FBA05AU, 0x690CE0EEU, 0x6DCDFD59U, 0x608EDB80U, 0x644FC637U, 0x7A089632U,
0x7EC98B85U, 0x738AAD5CU, 0x774BB0EBU, 0x4F040D56U, 0x4BC510E1U, 0x46863638U, 0x42472B8FU,
0x5C007B8AU, 0x58C1663DU, 0x558240E4U, 0x51435D53U, 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,
};
@ -396,7 +313,7 @@ namespace OGG {
return crc;
}
long unsigned int Page::calcChecksum(){ //implement in sending out page, probably delete this -- probably don't delete this because this function appears to be in use
long unsigned int Page::calcChecksum(){// implement in sending out page, probably delete this -- probably don't delete this because this function appears to be in use
long unsigned int retVal = 0;
/*
long unsigned int oldChecksum = getCRCChecksum();
@ -417,19 +334,15 @@ namespace OGG {
int Page::getPayloadSize(){
size_t res = 0;
for (unsigned int i = 0; i < segments.size(); i++){
res += segments[i].size();
}
for (unsigned int i = 0; i < segments.size(); i++){res += segments[i].size();}
return res;
}
const std::deque<std::string> & Page::getAllSegments(){
return segments;
}
const std::deque<std::string> &Page::getAllSegments(){return segments;}
void Page::prepareNext(bool continueMe){
clear(0, -1, getBitstreamSerialNumber(), getPageSequenceNumber() + 1);
if (continueMe){ //noting that the page will be continued
if (continueMe){// noting that the page will be continued
setHeaderType(OGG::Continued);
}
}
@ -444,27 +357,27 @@ namespace OGG {
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);
return payload.size();
}
unsigned int Page::addSegment(const char * content, unsigned int length){
unsigned int Page::addSegment(const char *content, unsigned int length){
segments.push_back(std::string(content, length));
return length;
}
unsigned int Page::overFlow(){ //returns the amount of bytes that don't fit in this page from the segments;
unsigned int Page::overFlow(){// returns the amount of bytes that don't fit in this page from the segments;
unsigned int retVal = 0;
unsigned int curSegNum = 0;//the current segment number we are looking at
unsigned int curSegNum = 0; // the current segment number we are looking at
unsigned int segAmount = 0;
for (unsigned int i = 0; i < segments.size(); i++){
segAmount = (segments[i].size() / 255) + 1;
if (segAmount + curSegNum > 255){
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
} else {
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
}else{
curSegNum += segAmount;
}
}
@ -473,7 +386,7 @@ namespace OGG {
void Page::vorbisStuff(){
Utils::bitstreamLSBF packet;
packet.append(oggSegments.rbegin()->dataString);//this is a heavy operation, it needs to be optimised //todo?
packet.append(oggSegments.rbegin()->dataString); // this is a heavy operation, it needs to be optimised //todo?
int curPCMSamples = 0;
long long unsigned int packetType = packet.get(1);
if (packetType == 0){
@ -484,45 +397,38 @@ namespace OGG {
if (prevBlockFlag != -1){
if (curBlockFlag == prevBlockFlag){
curPCMSamples /= 2;
} else {
}else{
curPCMSamples -= (1 << blockSize[0]) / 4 + (1 << blockSize[1]) / 4;
}
}
prevBlockFlag = curBlockFlag;
} else {
ERROR_MSG("Error, Vorbis packet type !=0 actual type: %llu",packetType );
}else{
ERROR_MSG("Error, Vorbis packet type !=0 actual type: %llu", packetType);
}
//add to granule position
// add to granule position
lastKeyFrame += curPCMSamples;
oggSegments.rbegin()->lastKeyFrameSeen = lastKeyFrame;
}
///this calculates the granule position for a DTSC packet
long long unsigned int Page::calculateGranule(oggSegment & currentSegment){
/// this calculates the granule position for a DTSC packet
long long unsigned int Page::calculateGranule(oggSegment &currentSegment){
long long unsigned int tempGranule = 0;
if (codec == OGG::THEORA){
tempGranule = (currentSegment.lastKeyFrameSeen << split) | currentSegment.framesSinceKeyFrame;
} else if (codec == OGG::VORBIS){
}else if (codec == OGG::VORBIS){
tempGranule = currentSegment.lastKeyFrameSeen;
} else if (codec == OGG::OPUS){
tempGranule = currentSegment.timeStamp*48;
}else if (codec == OGG::OPUS){
tempGranule = currentSegment.timeStamp * 48;
}
return tempGranule;
}
bool Page::shouldSend(){
unsigned int totalSegmentSize = 0;
if (!oggSegments.size()){
return false;
}
if (oggSegments.rbegin()->isKeyframe){
return true;
}
if (!oggSegments.size()){return false;}
if (oggSegments.rbegin()->isKeyframe){return true;}
if (codec == OGG::VORBIS){
if (lastKeyFrame - firstSample >= sampleRate){
return true;
}
if (lastKeyFrame - firstSample >= sampleRate){return true;}
}
for (unsigned int i = 0; i < oggSegments.size(); i++){
@ -534,79 +440,75 @@ namespace OGG {
}
///\todo Rewrite this
void Page::sendTo(Socket::Connection & destination, int calcGranule){ //combines all data and sends it to socket
void Page::sendTo(Socket::Connection &destination, int calcGranule){// combines all data and sends it to socket
if (!oggSegments.size()){
HIGH_MSG("!segments.size()");
return;
}
if (codec == OGG::VORBIS){
firstSample = lastKeyFrame;
}
if (codec == OGG::VORBIS){firstSample = lastKeyFrame;}
int temp = 0;
long unsigned int checksum = 0; //reset checksum
long unsigned int checksum = 0; // reset checksum
setCRCChecksum(0);
unsigned int numSegments = oggSegments.size();
int tableIndex = 0;
char tableSize = 0;
//char table[255];
char * table = (char *)malloc(255);
// char table[255];
char *table = (char *)malloc(255);
unsigned int bytesLeft = 0;
for (unsigned int i = 0; i < numSegments; i++){
//calculate amount of 255 bytes needed to store size (remainder not counted)
// calculate amount of 255 bytes needed to store size (remainder not counted)
temp = (oggSegments[i].dataString.size() / 255);
//if everything still fits in the table
// if everything still fits in the table
if ((temp + tableIndex + 1) <= 255){
//set the 255 bytes
// set the 255 bytes
memset(table + tableIndex, 255, temp);
//increment tableIndex with 255 byte count
// increment tableIndex with 255 byte count
tableIndex += temp;
//set the last table entry to the remainder, and increase tableIndex with one
// set the last table entry to the remainder, and increase tableIndex with one
table[tableIndex++] = (oggSegments[i].dataString.size() % 255);
//update tableSize to be equal to tableIndex
// update tableSize to be equal to tableIndex
tableSize = tableIndex;
bytesLeft = 0;
} else {
//stuff doesn't fit
//set the rest of the table to 255s
}else{
// stuff doesn't fit
// set the rest of the table to 255s
memset(table + tableIndex, 255, (255 - tableIndex));
//table size is full table in use
// table size is full table in use
tableSize = 255;
//space left on current page, for this segment: (255-tableIndex)*255
// space left on current page, for this segment: (255-tableIndex)*255
bytesLeft = (255 - tableIndex) * 255;
if (oggSegments[i].dataString.size() == bytesLeft){
bytesLeft = 0; //segment barely fits.
bytesLeft = 0; // segment barely fits.
}
break;
}
}
if (calcGranule < -1){
if (numSegments == 1 && bytesLeft){ //no segment ends on this page.
if (numSegments == 1 && bytesLeft){// no segment ends on this page.
granules = -1;
} else {
}else{
unsigned int tempIndex = numSegments - 1;
if (bytesLeft != 0){
tempIndex = numSegments - 2;
}
if (bytesLeft != 0){tempIndex = numSegments - 2;}
granules = calculateGranule(oggSegments[tempIndex]);
}
} else {
granules = calcGranule; //force granule
}else{
granules = calcGranule; // force granule
}
setGranulePosition(granules);
checksum = crc32(checksum, data, 22);//calculating the checksum over the first part of the page
checksum = crc32(checksum, &tableSize, 1); //calculating the checksum over the segment Table Size
checksum = crc32(checksum, table, tableSize);//calculating the checksum over the segment Table
checksum = crc32(checksum, data, 22); // calculating the checksum over the first part of the page
checksum = crc32(checksum, &tableSize, 1); // calculating the checksum over the segment Table Size
checksum = crc32(checksum, table, tableSize); // calculating the checksum over the segment Table
DONTEVEN_MSG("numSegments: %d", numSegments);
for (unsigned int i = 0; i < numSegments; i++){
//INFO_MSG("checksum, i: %d", i);
// INFO_MSG("checksum, i: %d", i);
if (bytesLeft != 0 && ((i + 1) == numSegments)){
checksum = crc32(checksum, oggSegments[i].dataString.data(), bytesLeft);
//take only part of this segment
} else { //take the entire segment
// take only part of this segment
}else{// take the entire segment
checksum = crc32(checksum, oggSegments[i].dataString.data(), oggSegments[i].dataString.size());
}
}
@ -617,35 +519,27 @@ namespace OGG {
destination.SendNow(&tableSize, 1);
destination.SendNow(table, tableSize);
for (unsigned int i = 0; i < numSegments; i++){
if (bytesLeft != 0 && ((i + 1) == numSegments)){
destination.SendNow(oggSegments.begin()->dataString.data(), bytesLeft);
oggSegments.begin()->dataString.erase(0, bytesLeft);
setHeaderType(OGG::Continued);//set continuation flag
setHeaderType(OGG::Continued); // set continuation flag
break;
//for loop WILL exit after this.
} else {
// for loop WILL exit after this.
}else{
destination.SendNow(oggSegments.begin()->dataString.data(), oggSegments.begin()->dataString.size());
//this segment WILL be deleted
// this segment WILL be deleted
oggSegments.erase(oggSegments.begin());
setHeaderType(OGG::Plain);//not a continuation
setHeaderType(OGG::Plain); // not a continuation
}
}
}
//done sending, assume start of new page.
//inc. page num, write to header
// done sending, assume start of new page.
// inc. page num, write to header
pageSequenceNumber++;
setPageSequenceNumber(pageSequenceNumber);
//granule still requires setting!
// granule still requires setting!
free(table);
return;
}
}
}// namespace OGG

108
lib/ogg.h
View file

@ -1,17 +1,17 @@
#pragma once
#include <cstdlib>
#include <string>
#include <vector>
#include <deque>
#include <sstream>
#include "dtsc.h"
#include "socket.h"
#include "theora.h"
#include "vorbis.h"
#include "socket.h"
#include <cstdlib>
#include <deque>
#include <sstream>
#include <string>
#include <vector>
namespace OGG {
namespace OGG{
class oggSegment {
class oggSegment{
public:
oggSegment();
std::string dataString;
@ -22,29 +22,21 @@ namespace OGG {
long long unsigned int timeStamp;
};
enum oggCodec {THEORA, VORBIS, OPUS};
enum oggCodec{THEORA, VORBIS, OPUS};
enum HeaderType {
Plain = 0,
Continued = 1,
BeginOfStream = 2,
EndOfStream = 4
};
enum HeaderType{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:
Page();
Page(const Page & rhs);
void operator = (const Page & rhs);
bool read(std::string & newData);
bool read(FILE * inFile);
bool getSegment(unsigned int index, std::string & ret);
const char * getSegment(unsigned int index);
Page(const Page &rhs);
void operator=(const Page &rhs);
bool read(std::string &newData);
bool read(FILE *inFile);
bool getSegment(unsigned int index, std::string &ret);
const char *getSegment(unsigned int index);
unsigned long getSegmentLen(unsigned int index);
void setMagicNumber();
char getVersion();
@ -59,10 +51,10 @@ namespace OGG {
void setCRCChecksum(long unsigned int newVal);
long unsigned int getPageSequenceNumber();
void setPageSequenceNumber(long unsigned int newVal);
char getPageSegments();//get the amount of page segments
inline void setPageSegments(char newVal);//set the amount of page segments
char getPageSegments(); // get the amount of page segments
inline void setPageSegments(char newVal); // set the amount of page segments
int getPayloadSize();
const std::deque<std::string> & getAllSegments();
const std::deque<std::string> &getAllSegments();
bool possiblyContinued();
@ -71,46 +63,44 @@ namespace OGG {
long unsigned int calcChecksum();
bool verifyChecksum();
unsigned int calcPayloadSize();
//void clear();
// void clear();
void clear(char HeaderType, long long unsigned int GranPos, long unsigned int BSN, long unsigned int PSN);
void prepareNext(bool continueMe = false);//prepare the page to become the next page
bool setPayload(char * newData, unsigned int length); //probably obsolete
unsigned int addSegment(const std::string & content); //add a segment to the page, returns added bytes
unsigned int addSegment(const char * content, unsigned int length); //add a segment to the page, returns added bytes
void sendTo(Socket::Connection & destination, int calcGranule = -2); //combines all data and sends it to socket
unsigned int setNextSegmentTableEntry(unsigned int entrySize);//returns the size that could not be added to the table
unsigned int overFlow();//returns the amount of bytes that don't fit in this page from the segments;
void prepareNext(bool continueMe = false); // prepare the page to become the next page
bool setPayload(char *newData, unsigned int length); // probably obsolete
unsigned int addSegment(const std::string &content); // add a segment to the page, returns added bytes
unsigned int addSegment(const char *content, unsigned int length); // add a segment to the page, returns added bytes
void sendTo(Socket::Connection &destination, int calcGranule = -2); // combines all data and sends it to socket
unsigned int setNextSegmentTableEntry(unsigned int entrySize); // returns the size that could not be added to the table
unsigned int overFlow(); // returns the amount of bytes that don't fit in this page from the segments;
long long unsigned int calculateGranule(oggSegment & currentSegment);
long long unsigned int calculateGranule(oggSegment &currentSegment);
bool shouldSend();
void vorbisStuff();//process most recent segment
void vorbisStuff(); // process most recent segment
long long unsigned int totalFrames;
int granules;
OGG::oggCodec codec;
std::deque<oggSegment> oggSegments; //used for ogg output
std::deque<oggSegment> oggSegments; // used for ogg output
unsigned int pageSequenceNumber;
unsigned int framesSeen;
unsigned int lastKeyFrame;
unsigned int firstSample;//for vorbis, to handle "when to send the page"
unsigned int sampleRate;//for vorbis, to handle the sampleRate
unsigned int firstSample; // for vorbis, to handle "when to send the page"
unsigned int sampleRate; // for vorbis, to handle the sampleRate
int prevBlockFlag;
char blockSize[2];
std::deque<vorbis::mode> vorbisModes;//modes for vorbis
unsigned int split; //KFGShift for theora
std::deque<vorbis::mode> vorbisModes; // modes for vorbis
unsigned int split; // KFGShift for theora
private:
char data[282];//Fulldata
char data[282]; // Fulldata
std::deque<std::string> segments;
};
class oggTrack {
class oggTrack{
public:
oggTrack() : KFGShift(0), lastTime(0), parsedHeaders(false), lastPageOffset(0), nxtSegment(0){ }
oggTrack() : KFGShift(0), lastTime(0), parsedHeaders(false), lastPageOffset(0), nxtSegment(0){}
oggCodec codec;
std::string name;
std::string contBuffer;//buffer for continuing pages
std::string contBuffer; // buffer for continuing pages
long long unsigned int dtscID;
char KFGShift;
double lastTime;
@ -120,22 +110,20 @@ namespace OGG {
unsigned int nxtSegment;
double msPerFrame;
Page myPage;
//Codec specific elements
//theora
// Codec specific elements
// theora
// theora::header idHeader;//needed to determine keyframe //bullshit?
//vorbis
// vorbis
std::deque<vorbis::mode> vModes;
char channels;
long long unsigned int blockSize[2];
//unsigned long getBlockSize(unsigned int vModeIndex);
// unsigned long getBlockSize(unsigned int vModeIndex);
};
class headerPages {
class headerPages{
public:
std::map <long long unsigned int, unsigned int> DTSCID2OGGSerial;
std::map <long long unsigned int, unsigned int> DTSCID2seqNum;
std::map<long long unsigned int, unsigned int> DTSCID2OGGSerial;
std::map<long long unsigned int, unsigned int> DTSCID2seqNum;
std::string parsedPages;
};
}
}// namespace OGG

View file

@ -3,10 +3,7 @@
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){
const char config = part[0] >> 3;
@ -19,13 +16,13 @@ namespace Opus{
case 2: dur = 40; break;
case 3: dur = 60; break;
}
} else if (config < 16){
}else if (config < 16){
if (config % 2 == 0){
dur = 10;
}else{
dur = 20;
}
} else {
}else{
switch (config % 4){
case 0: dur = 2.5; break;
case 1: dur = 5; break;
@ -34,8 +31,8 @@ namespace Opus{
}
}
if (code == 0){return (unsigned int)dur;}
if (code < 3){return (unsigned int)(dur*2);}
return (unsigned int)(dur*(part[1] & 63));
if (code < 3){return (unsigned int)(dur * 2);}
return (unsigned int)(dur * (part[1] & 63));
}
std::string Opus_prettyPacket(const char *part, int len){
@ -107,5 +104,4 @@ namespace Opus{
r << ": " << packets << " packets (VBR = " << VBR << ", padding = " << pad << ")";
return r.str();
}
}
}// namespace Opus

View file

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

View file

@ -1,57 +1,54 @@
/// \file procs.cpp
/// Contains generic functions for managing processes.
#include "procs.h"
#include "defines.h"
#include "procs.h"
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__MACH__)
#include <sys/wait.h>
#else
#include <wait.h>
#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 <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<int> Util::Procs::socketList;
bool Util::Procs::handler_set = false;
bool Util::Procs::thread_handler = false;
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.
bool Util::Procs::childRunning(pid_t p) {
bool Util::Procs::childRunning(pid_t p){
int status;
pid_t ret = waitpid(p, &status, WNOHANG);
if (ret == p) {
if (ret == p){
tthread::lock_guard<tthread::mutex> guard(plistMutex);
int exitcode = -1;
if (WIFEXITED(status)) {
if (WIFEXITED(status)){
exitcode = WEXITSTATUS(status);
} else if (WIFSIGNALED(status)) {
}else if (WIFSIGNALED(status)){
exitcode = -WTERMSIG(status);
}
if (plist.count(ret)) {
if (plist.count(ret)){
HIGH_MSG("Process %d fully terminated with code %d", ret, exitcode);
plist.erase(ret);
} else {
}else{
HIGH_MSG("Child process %d exited with code %d", ret, exitcode);
}
return false;
}
if (ret < 0 && errno == EINTR) {
return childRunning(p);
}
if (ret < 0 && errno == EINTR){return childRunning(p);}
return !kill(p, 0);
}
@ -64,7 +61,7 @@ bool Util::Procs::isRunning(pid_t pid){
/// Waits up to 1 second, then sends SIGINT signal to all managed processes.
/// After that waits up to 5 seconds for children to exit, then sends SIGKILL to
/// all remaining children. Waits one more second for cleanup to finish, then exits.
void Util::Procs::exit_handler() {
void Util::Procs::exit_handler(){
if (!handler_set){return;}
int waiting = 0;
std::set<pid_t> listcopy;
@ -79,42 +76,39 @@ void Util::Procs::exit_handler() {
reaper_thread = 0;
}
std::set<pid_t>::iterator it;
if (listcopy.empty()) {
return;
}
if (listcopy.empty()){return;}
//wait up to 0.5 second for applications to shut down
while (!listcopy.empty() && waiting <= 25) {
for (it = listcopy.begin(); it != listcopy.end(); it++) {
if (!childRunning(*it)) {
// wait up to 0.5 second for applications to shut down
while (!listcopy.empty() && waiting <= 25){
for (it = listcopy.begin(); it != listcopy.end(); it++){
if (!childRunning(*it)){
listcopy.erase(it);
break;
}
if (!listcopy.empty()) {
if (!listcopy.empty()){
Util::wait(20);
++waiting;
}
}
}
if (listcopy.empty()) {
return;
}
if (listcopy.empty()){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;
//wait up to 10 seconds for applications to shut down
while (!listcopy.empty() && waiting <= 500) {
// wait up to 10 seconds for applications to shut down
while (!listcopy.empty() && waiting <= 500){
bool doWait = true;
for (it = listcopy.begin(); it != listcopy.end(); it++) {
if (!childRunning(*it)) {
for (it = listcopy.begin(); it != listcopy.end(); it++){
if (!childRunning(*it)){
listcopy.erase(it);
doWait = false;
break;
}
}
if (doWait && !listcopy.empty()) {
if (doWait && !listcopy.empty()){
if ((waiting % 50) == 0){
for (it = listcopy.begin(); it != listcopy.end(); it++) {
for (it = listcopy.begin(); it != listcopy.end(); it++){
INFO_MSG("SIGINT %d", *it);
kill(*it, SIGINT);
}
@ -123,14 +117,12 @@ void Util::Procs::exit_handler() {
++waiting;
}
}
if (listcopy.empty()) {
return;
}
if (listcopy.empty()){return;}
ERROR_MSG("Sending SIGKILL to remaining %d children", (int)listcopy.size());
//send sigkill to all remaining
if (!listcopy.empty()) {
for (it = listcopy.begin(); it != listcopy.end(); it++) {
// send sigkill to all remaining
if (!listcopy.empty()){
for (it = listcopy.begin(); it != listcopy.end(); it++){
INFO_MSG("SIGKILL %d", *it);
kill(*it, SIGKILL);
}
@ -138,22 +130,20 @@ void Util::Procs::exit_handler() {
INFO_MSG("Waiting up to a second for %d children to terminate.", (int)listcopy.size());
waiting = 0;
//wait up to 1 second for applications to shut down
while (!listcopy.empty() && waiting <= 50) {
for (it = listcopy.begin(); it != listcopy.end(); it++) {
if (!childRunning(*it)) {
// wait up to 1 second for applications to shut down
while (!listcopy.empty() && waiting <= 50){
for (it = listcopy.begin(); it != listcopy.end(); it++){
if (!childRunning(*it)){
listcopy.erase(it);
break;
}
if (!listcopy.empty()) {
if (!listcopy.empty()){
Util::wait(20);
++waiting;
}
}
}
if (listcopy.empty()) {
return;
}
if (listcopy.empty()){return;}
FAIL_MSG("Giving up with %d children left.", (int)listcopy.size());
}
@ -182,9 +172,9 @@ void Util::Procs::fork_complete(){
/// Sets up exit and childsig handlers.
/// Spawns grim_reaper. exit handler despawns grim_reaper
/// Called by every Start* function.
void Util::Procs::setHandler() {
void Util::Procs::setHandler(){
tthread::lock_guard<tthread::mutex> guard(plistMutex);
if (!handler_set) {
if (!handler_set){
thread_handler = true;
reaper_thread = new tthread::thread(grim_reaper, 0);
struct sigaction new_action;
@ -197,36 +187,34 @@ void Util::Procs::setHandler() {
}
}
///Thread that loops until thread_handler is false.
///Reaps available children and then sleeps for a second.
///Not done in signal handler so we can use a mutex to prevent race conditions.
void Util::Procs::grim_reaper(void * n){
/// Thread that loops until thread_handler is false.
/// Reaps available children and then sleeps for a second.
/// Not done in signal handler so we can use a mutex to prevent race conditions.
void Util::Procs::grim_reaper(void *n){
VERYHIGH_MSG("Grim reaper start");
while (thread_handler){
{
tthread::lock_guard<tthread::mutex> guard(plistMutex);
int status;
pid_t ret = -1;
while (ret != 0) {
while (ret != 0){
ret = waitpid(-1, &status, WNOHANG);
if (ret <= 0) { //ignore, would block otherwise
if (ret == 0 || errno != EINTR) {
break;
}
if (ret <= 0){// ignore, would block otherwise
if (ret == 0 || errno != EINTR){break;}
continue;
}
int exitcode;
if (WIFEXITED(status)) {
if (WIFEXITED(status)){
exitcode = WEXITSTATUS(status);
} else if (WIFSIGNALED(status)) {
}else if (WIFSIGNALED(status)){
exitcode = -WTERMSIG(status);
} else { // not possible
}else{// not possible
break;
}
if (plist.count(ret)) {
if (plist.count(ret)){
HIGH_MSG("Process %d fully terminated with code %d", ret, exitcode);
plist.erase(ret);
} else {
}else{
HIGH_MSG("Child process %d exited with code %d", ret, exitcode);
}
}
@ -237,23 +225,20 @@ void Util::Procs::grim_reaper(void * n){
}
/// Ignores everything. Separate thread handles waiting for children.
void Util::Procs::childsig_handler(int signum) {
void Util::Procs::childsig_handler(int signum){
return;
}
/// 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;
int fin = 0, fout = -1, ferr = 0;
pid_t myProc = StartPiped(argv, &fin, &fout, &ferr);
while (childRunning(myProc)) {
Util::sleep(100);
}
FILE * outFile = fdopen(fout, "r");
char * fileBuf = 0;
while (childRunning(myProc)){Util::sleep(100);}
FILE *outFile = fdopen(fout, "r");
char *fileBuf = 0;
size_t fileBufLen = 0;
while (!(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)) {
while (!(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)){
ret += fileBuf;
}
fclose(outFile);
@ -261,27 +246,24 @@ std::string Util::Procs::getOutputOf(char * const * argv) {
return ret;
}
///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** ret = (char**)malloc((argDeq.size()+1)*sizeof(char*));
for (int i = 0; i<argDeq.size(); i++){
ret[i] = (char*)argDeq[i].c_str();
}
/// 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 **ret = (char **)malloc((argDeq.size() + 1) * sizeof(char *));
for (int i = 0; i < argDeq.size(); i++){ret[i] = (char *)argDeq[i].c_str();}
ret[argDeq.size()] = NULL;
return ret;
}
std::string Util::Procs::getOutputOf(std::deque<std::string> & argDeq){
std::string Util::Procs::getOutputOf(std::deque<std::string> &argDeq){
std::string ret;
char* const* argv = dequeToArgv(argDeq);//Note: Do not edit deque before executing command
char *const *argv = dequeToArgv(argDeq); // Note: Do not edit deque before executing command
ret = getOutputOf(argv);
return ret;
}
pid_t Util::Procs::StartPiped(std::deque<std::string> & argDeq, int * fdin, int * fdout, int * fderr) {
pid_t Util::Procs::StartPiped(std::deque<std::string> &argDeq, int *fdin, int *fdout, int *fderr){
pid_t ret;
char* const* argv = dequeToArgv(argDeq);//Note: Do not edit deque before executing command
char *const *argv = dequeToArgv(argDeq); // Note: Do not edit deque before executing command
ret = Util::Procs::StartPiped(argv, fdin, fdout, fderr);
return ret;
}
@ -289,51 +271,51 @@ 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.
/// \return 0 if process was not started, process PID otherwise.
/// \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 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) {
/// \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 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 pid;
int pipein[2], pipeout[2], pipeerr[2];
setHandler();
if (fdin && *fdin == -1 && pipe(pipein) < 0) {
if (fdin && *fdin == -1 && pipe(pipein) < 0){
ERROR_MSG("stdin pipe creation failed for process %s, reason: %s", argv[0], strerror(errno));
return 0;
}
if (fdout && *fdout == -1 && pipe(pipeout) < 0) {
if (fdout && *fdout == -1 && pipe(pipeout) < 0){
ERROR_MSG("stdout pipe creation failed for process %s, reason: %s", argv[0], strerror(errno));
if (*fdin == -1) {
if (*fdin == -1){
close(pipein[0]);
close(pipein[1]);
}
return 0;
}
if (fderr && *fderr == -1 && pipe(pipeerr) < 0) {
if (fderr && *fderr == -1 && pipe(pipeerr) < 0){
ERROR_MSG("stderr pipe creation failed for process %s, reason: %s", argv[0], strerror(errno));
if (*fdin == -1) {
if (*fdin == -1){
close(pipein[0]);
close(pipein[1]);
}
if (*fdout == -1) {
if (*fdout == -1){
close(pipeout[0]);
close(pipeout[1]);
}
return 0;
}
int devnull = -1;
if (!fdin || !fdout || !fderr) {
if (!fdin || !fdout || !fderr){
devnull = open("/dev/null", O_RDWR);
if (devnull == -1) {
if (devnull == -1){
ERROR_MSG("Could not open /dev/null for process %s, reason: %s", argv[0], strerror(errno));
if (*fdin == -1) {
if (*fdin == -1){
close(pipein[0]);
close(pipein[1]);
}
if (*fdout == -1) {
if (*fdout == -1){
close(pipeout[0]);
close(pipeout[1]);
}
if (*fderr == -1) {
if (*fderr == -1){
close(pipeerr[0]);
close(pipeerr[1]);
}
@ -341,55 +323,48 @@ pid_t Util::Procs::StartPiped(const char * const * argv, int * fdin, int * fdout
}
}
pid = fork();
if (pid == 0) { //child
if (pid == 0){// child
handler_set = false;
//Close all sockets in the socketList
for (std::set<int>::iterator it = Util::Procs::socketList.begin(); it != Util::Procs::socketList.end(); ++it){
// Close all sockets in the socketList
for (std::set<int>::iterator it = Util::Procs::socketList.begin();
it != Util::Procs::socketList.end(); ++it){
close(*it);
}
if (!fdin) {
if (!fdin){
dup2(devnull, STDIN_FILENO);
} else if (*fdin == -1) {
}else if (*fdin == -1){
close(pipein[1]); // close unused write end
dup2(pipein[0], STDIN_FILENO);
close(pipein[0]);
} else if (*fdin != STDIN_FILENO) {
}else if (*fdin != STDIN_FILENO){
dup2(*fdin, STDIN_FILENO);
}
if (!fdout) {
if (!fdout){
dup2(devnull, STDOUT_FILENO);
} else if (*fdout == -1) {
}else if (*fdout == -1){
close(pipeout[0]); // close unused read end
dup2(pipeout[1], STDOUT_FILENO);
close(pipeout[1]);
} else if (*fdout != STDOUT_FILENO) {
}else if (*fdout != STDOUT_FILENO){
dup2(*fdout, STDOUT_FILENO);
}
if (!fderr) {
if (!fderr){
dup2(devnull, STDERR_FILENO);
} else if (*fderr == -1) {
}else if (*fderr == -1){
close(pipeerr[0]); // close unused read end
dup2(pipeerr[1], STDERR_FILENO);
close(pipeerr[1]);
} else if (*fderr != STDERR_FILENO) {
}else if (*fderr != STDERR_FILENO){
dup2(*fderr, STDERR_FILENO);
}
if (fdin && *fdin != -1 && *fdin != STDIN_FILENO) {
close(*fdin);
}
if (fdout && *fdout != -1 && *fdout != STDOUT_FILENO) {
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*
execvp(argv[0], (char* const*)argv);
if (fdin && *fdin != -1 && *fdin != STDIN_FILENO){close(*fdin);}
if (fdout && *fdout != -1 && *fdout != STDOUT_FILENO){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*
execvp(argv[0], (char *const *)argv);
/*LTS-START*/
char * trggr = getenv("MIST_TRIGGER");
char *trggr = getenv("MIST_TRIGGER");
if (trggr && strlen(trggr)){
ERROR_MSG("%s trigger failed to execute %s: %s", trggr, argv[0], strerror(errno));
JSON::Value j;
@ -403,42 +378,38 @@ pid_t Util::Procs::StartPiped(const char * const * argv, int * fdin, int * fdout
/*LTS-END*/
ERROR_MSG("execvp failed for process %s, reason: %s", argv[0], strerror(errno));
exit(42);
} else if (pid == -1) {
}else if (pid == -1){
ERROR_MSG("fork failed for process %s, reason: %s", argv[0], strerror(errno));
if (fdin && *fdin == -1) {
if (fdin && *fdin == -1){
close(pipein[0]);
close(pipein[1]);
}
if (fdout && *fdout == -1) {
if (fdout && *fdout == -1){
close(pipeout[0]);
close(pipeout[1]);
}
if (fderr && *fderr == -1) {
if (fderr && *fderr == -1){
close(pipeerr[0]);
close(pipeerr[1]);
}
if (devnull != -1) {
close(devnull);
}
if (devnull != -1){close(devnull);}
return 0;
} else { //parent
}else{// parent
{
tthread::lock_guard<tthread::mutex> guard(plistMutex);
plist.insert(pid);
}
HIGH_MSG("Piped process %s started, PID %d", argv[0], pid);
if (devnull != -1) {
close(devnull);
}
if (fdin && *fdin == -1) {
if (devnull != -1){close(devnull);}
if (fdin && *fdin == -1){
close(pipein[0]); // close unused end end
*fdin = pipein[1];
}
if (fdout && *fdout == -1) {
if (fdout && *fdout == -1){
close(pipeout[1]); // close unused write end
*fdout = pipeout[0];
}
if (fderr && *fderr == -1) {
if (fderr && *fderr == -1){
close(pipeerr[1]); // close unused write end
*fderr = pipeerr[0];
}
@ -448,50 +419,47 @@ pid_t Util::Procs::StartPiped(const char * const * argv, int * fdin, int * fdout
/// Stops the process with this pid, if running.
/// \arg name The PID of the process to stop.
void Util::Procs::Stop(pid_t name) {
void Util::Procs::Stop(pid_t name){
kill(name, SIGTERM);
}
/// Stops the process with this pid, if running.
/// \arg name The PID of the process to murder.
void Util::Procs::Murder(pid_t name) {
void Util::Procs::Murder(pid_t name){
kill(name, SIGKILL);
}
/// (Attempts to) stop all running child processes.
void Util::Procs::StopAll() {
void Util::Procs::StopAll(){
std::set<pid_t> listcopy;
{
tthread::lock_guard<tthread::mutex> guard(plistMutex);
listcopy = plist;
}
std::set<pid_t>::iterator it;
for (it = listcopy.begin(); it != listcopy.end(); it++) {
Stop(*it);
}
for (it = listcopy.begin(); it != listcopy.end(); it++){Stop(*it);}
}
/// Returns the number of active child processes.
int Util::Procs::Count() {
int Util::Procs::Count(){
tthread::lock_guard<tthread::mutex> guard(plistMutex);
return plist.size();
}
/// Returns true if a process with this PID is currently active.
bool Util::Procs::isActive(pid_t name) {
bool Util::Procs::isActive(pid_t name){
tthread::lock_guard<tthread::mutex> guard(plistMutex);
return (kill(name, 0) == 0);
}
/// Forget about the given PID, keeping it running on shutdown.
void Util::Procs::forget(pid_t pid) {
void Util::Procs::forget(pid_t pid){
tthread::lock_guard<tthread::mutex> guard(plistMutex);
plist.erase(pid);
}
/// Remember the given PID, killing it on shutdown.
void Util::Procs::remember(pid_t pid) {
void Util::Procs::remember(pid_t pid){
tthread::lock_guard<tthread::mutex> guard(plistMutex);
plist.insert(pid);
}

View file

@ -2,37 +2,38 @@
/// Contains generic function headers for managing processes.
#pragma once
#include <unistd.h>
#include <string>
#include <set>
#include <vector>
#include <deque>
#include "tinythread.h"
#include <deque>
#include <set>
#include <string>
#include <unistd.h>
#include <vector>
/// Contains utility code, not directly related to streaming media
namespace Util {
namespace Util{
/// Deals with spawning, monitoring and stopping child processes
class Procs {
class Procs{
private:
static tthread::mutex plistMutex;
static std::set<pid_t> plist; ///< Holds active process list.
static bool thread_handler;///< True while thread handler should be running.
static bool thread_handler; ///< True while thread handler should be running.
static void childsig_handler(int signum);
static void exit_handler();
static char* const* dequeToArgv(std::deque<std::string> & argDeq);
static void grim_reaper(void * n);
static char *const *dequeToArgv(std::deque<std::string> &argDeq);
static void grim_reaper(void *n);
public:
static bool childRunning(pid_t p);
static tthread::thread * reaper_thread;
static tthread::thread *reaper_thread;
static bool handler_set; ///< If true, the sigchld handler has been setup.
static void fork_prepare();
static void fork_complete();
static void setHandler();
static std::string getOutputOf(char * const * argv);
static std::string getOutputOf(std::deque<std::string> & argDeq);
static pid_t StartPiped(const char * const * argv, int * fdin, int * fdout, int * fderr);
static pid_t StartPiped(std::deque<std::string> & argDeq, int * fdin, int * fdout, int * fderr);
static std::string getOutputOf(char *const *argv);
static std::string getOutputOf(std::deque<std::string> &argDeq);
static pid_t StartPiped(const char *const *argv, int *fdin, int *fdout, int *fderr);
static pid_t StartPiped(std::deque<std::string> &argDeq, int *fdin, int *fdout, int *fderr);
static void Stop(pid_t name);
static void Murder(pid_t name);
static void StopAll();
@ -43,5 +44,4 @@ namespace Util {
static void remember(pid_t pid);
static std::set<int> socketList; ///< Holds sockets that should be closed before forking
};
}
}// namespace Util

View file

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

View file

@ -10,7 +10,7 @@ namespace RIFF{
class Chunk{
public:
Chunk(const void *_p = 0, uint32_t len = 0);
Chunk(void *_p, const char * t, uint32_t len);
Chunk(void *_p, const char *t, uint32_t len);
inline operator bool() const{return p;}
inline std::string getType() const{
if (!p){return "";}
@ -41,7 +41,8 @@ namespace RIFF{
/// WAVE "fmt " class.
class fmt : public Chunk{
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){}
uint16_t getFormat() const;
std::string getCodec() const;
@ -58,7 +59,7 @@ namespace RIFF{
};
/// WAVE fact class.
class fact : public Chunk {
class fact : public Chunk{
public:
static std::string generate(uint32_t samples);
fact(const void *_p = 0, uint32_t len = 0) : Chunk(_p, len){}
@ -67,13 +68,11 @@ namespace RIFF{
};
/// ISFT class. Contains software name.
class ISFT : public Chunk {
class ISFT : public Chunk{
public:
ISFT(const void *_p = 0, uint32_t len = 0) : Chunk(_p, len){}
std::string getSoftware() const;
virtual void toPrettyString(std::ostream &o, size_t indent = 0) const;
};
}
}// namespace RIFF

View file

@ -1,172 +1,353 @@
// This entire file is public domain and comes with no warranties.
// Based on work by Vincent Rijmen, Antoon Bosselaers and Paulo Barreto.
#include "rijndael.h"
#include "bitfields.h"
#include "defines.h"
#include "rijndael.h"
#include <iostream>
#include <iomanip>
#include <iostream>
static const unsigned int Te0[256] = {
0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU, 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 Te0[256] ={
0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U,
0x91c5c554U, 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U,
0x4dababe6U, 0xec76769aU, 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, 0xeffafa15U,
0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU,
0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, 0x6834345cU, 0x51a5a5f4U,
0xd1e5e534U, 0xf9f1f108U, 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, 0x0804040cU,
0x95c7c752U, 0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU,
0xea75759fU, 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U,
0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, 0x5229297bU,
0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U,
0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, 0xbbd0d06bU, 0xc5efef2aU,
0x4faaaae5U, 0xedfbfb16U, 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU,
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] = {
0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U, 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 Te1[256] ={
0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU,
0x5491c5c5U, 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U,
0xe64dababU, 0x9aec7676U, 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, 0x15effafaU,
0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U,
0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, 0x5c683434U, 0xf451a5a5U,
0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, 0x0c080404U,
0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U,
0x9fea7575U, 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU,
0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, 0x7b522929U,
0x3edde3e3U, 0x715e2f2fU, 0x97138484U, 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU,
0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, 0x6bbbd0d0U, 0x2ac5efefU,
0xe54faaaaU, 0x16edfbfbU, 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U,
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] = {
0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U, 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 Te2[256] ={
0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU,
0xc55491c5U, 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U,
0xabe64dabU, 0x769aec76U, 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, 0xfa15effaU,
0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U,
0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, 0x345c6834U, 0xa5f451a5U,
0xe534d1e5U, 0xf108f9f1U, 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, 0x040c0804U,
0xc75295c7U, 0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U,
0x759fea75U, 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU,
0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, 0x297b5229U,
0xe33edde3U, 0x2f715e2fU, 0x84971384U, 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU, 0xbed967beU,
0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, 0xd06bbbd0U, 0xef2ac5efU,
0xaae54faaU, 0xfb16edfbU, 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U,
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] = {
0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU, 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 Te3[256] ={
0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU,
0xc5c55491U, 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U,
0xababe64dU, 0x76769aecU, 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, 0xfafa15efU,
0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU,
0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, 0x34345c68U, 0xa5a5f451U,
0xe5e534d1U, 0xf1f108f9U, 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, 0x04040c08U,
0xc7c75295U, 0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU,
0x75759feaU, 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU,
0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, 0x29297b52U,
0xe3e33eddU, 0x2f2f715eU, 0x84849713U, 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U,
0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, 0xd0d06bbbU, 0xefef2ac5U,
0xaaaae54fU, 0xfbfb16edU, 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU,
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] = {
0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU, 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 Td0[256] ={
0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU,
0x4be30393U, 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U,
0x26354480U, 0xb562a38fU, 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, 0xc32f7502U,
0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, 0x75c2896aU, 0xf48e7978U, 0x99583e6bU,
0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, 0x63df4a18U, 0xe51a3182U,
0x97513360U, 0x62537f45U, 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 0x70486858U,
0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, 0x302887f2U, 0x23bfa5b2U, 0x02036abaU,
0xed16825cU, 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U,
0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, 0x0b83ec39U,
0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U, 0x894043ccU,
0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, 0xa17c0a47U, 0x7c420fe9U,
0xf8841ec9U, 0x00000000U, 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU,
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] = {
0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU, 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 Td1[256] ={
0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U,
0x934be303U, 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU,
0x80263544U, 0x8fb562a3U, 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, 0x02c32f75U,
0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, 0x6a75c289U, 0x78f48e79U, 0x6b99583eU,
0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, 0x1863df4aU, 0x82e51a31U,
0x60975133U, 0x4562537fU, 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, 0x58704868U,
0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, 0xf2302887U, 0xb223bfa5U, 0xba02036aU,
0x5ced1682U, 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU,
0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, 0x390b83ecU,
0xaa4060efU, 0x065e719fU, 0x51bd6e10U, 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U, 0xcc894043U,
0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, 0x47a17c0aU, 0xe97c420fU,
0xc9f8841eU, 0x00000000U, 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU,
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] = {
0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU, 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 Td2[256] ={
0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU,
0x03934be3U, 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU,
0x44802635U, 0xa38fb562U, 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, 0x7502c32fU,
0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U,
0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, 0x4a1863dfU, 0x3182e51aU,
0x33609751U, 0x7f456253U, 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, 0x68587048U,
0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, 0x87f23028U, 0xa5b223bfU, 0x6aba0203U,
0x825ced16U, 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U,
0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, 0xec390b83U,
0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU, 0x43cc8940U,
0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, 0x0a47a17cU, 0x0fe97c42U,
0x1ec9f884U, 0x00000000U, 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU,
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] = {
0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU, 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 unsigned int Td3[256] ={
0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU,
0xe303934bU, 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U,
0x35448026U, 0x62a38fb5U, 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, 0x2f7502c3U,
0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U,
0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, 0xdf4a1863U, 0x1a3182e5U,
0x51336097U, 0x537f4562U, 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, 0x48685870U,
0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, 0x2887f230U, 0xbfa5b223U, 0x036aba02U,
0x16825cedU, 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U,
0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, 0x83ec390bU,
0x60efaa40U, 0x719f065eU, 0x6e1051bdU, 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U, 0x4043cc89U,
0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, 0x7c0a47a1U, 0x420fe97cU,
0x841ec9f8U, 0x00000000U, 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU,
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] = {
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,
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,
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,
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 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, 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, 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, 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.
void AES_set_encrypt_key(const char * userKey, const int bits, char * key) {
unsigned int * rk = (unsigned int *)key;
// Expand the cipher key into the encryption key schedule.
void AES_set_encrypt_key(const char *userKey, const int bits, char *key){
unsigned int *rk = (unsigned int *)key;
int i = 0;
unsigned int temp;
@ -174,56 +355,60 @@ void AES_set_encrypt_key(const char * userKey, const int bits, char * key) {
rk[1] = Bit::btohl(userKey + 4);
rk[2] = Bit::btohl(userKey + 8);
rk[3] = Bit::btohl(userKey + 12);
if (bits == 128) {
while (1) {
if (bits == 128){
while (1){
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[6] = rk[2] ^ rk[5];
rk[7] = rk[3] ^ rk[6];
if (++i == 10) {
if (++i == 10){
rk += 8;
break;
}
rk += 4;
}
}else{
rk[4] = (*((uint32_t*)(userKey + 16)));
rk[5] = (*((uint32_t*)(userKey + 20)));
if (bits == 192) {
while (1) {
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[ 7] = rk[ 1] ^ rk[ 6];
rk[ 8] = rk[ 2] ^ rk[ 7];
rk[ 9] = rk[ 3] ^ rk[ 8];
if (++i == 8) {
rk+= 10;
rk[4] = (*((uint32_t *)(userKey + 16)));
rk[5] = (*((uint32_t *)(userKey + 20)));
if (bits == 192){
while (1){
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[7] = rk[1] ^ rk[6];
rk[8] = rk[2] ^ rk[7];
rk[9] = rk[3] ^ rk[8];
if (++i == 8){
rk += 10;
break;
}
rk[10] = rk[ 4] ^ rk[ 9];
rk[11] = rk[ 5] ^ rk[10];
rk[10] = rk[4] ^ rk[9];
rk[11] = rk[5] ^ rk[10];
rk += 6;
}
}else{
rk[6] = (*((uint32_t*)(userKey + 24)));
rk[7] = (*((uint32_t*)(userKey + 28)));
if (bits == 256) {
while (1) {
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[ 9] = rk[ 1] ^ rk[ 8];
rk[10] = rk[ 2] ^ rk[ 9];
rk[11] = rk[ 3] ^ rk[10];
if (++i == 7) {
rk[6] = (*((uint32_t *)(userKey + 24)));
rk[7] = (*((uint32_t *)(userKey + 28)));
if (bits == 256){
while (1){
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[9] = rk[1] ^ rk[8];
rk[10] = rk[2] ^ rk[9];
rk[11] = rk[3] ^ rk[10];
if (++i == 7){
rk += 12;
return;
}
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[13] = rk[ 5] ^ rk[12];
rk[14] = rk[ 6] ^ rk[13];
rk[15] = rk[ 7] ^ rk[14];
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[14] = rk[6] ^ rk[13];
rk[15] = rk[7] ^ rk[14];
rk += 8;
}
@ -232,19 +417,17 @@ 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++){
std::cout << "0x" << std::hex << std::setw(8) << std::setfill('0') << data[i] << ", ";
if (i % 4 == 3){
std::cout << std::endl;
}
if (i % 4 == 3){std::cout << std::endl;}
}
std::cout << std::endl;
}
// Expand the cipher key into the decryption key schedule.
void AES_set_decrypt_key(const char * userKey, const int bits, char * key) {
unsigned long * rk = (unsigned long *)key;
void AES_set_decrypt_key(const char *userKey, const int bits, char *key){
unsigned long *rk = (unsigned long *)key;
int i, j;
unsigned long temp;
@ -252,18 +435,14 @@ void AES_set_decrypt_key(const char * userKey, const int bits, char * key) {
AES_set_encrypt_key(userKey, bits, key);
unsigned int rounds = 10;
if (bits > 128) {
rounds = 12;
}
if (bits > 192) {
rounds = 14;
}
if (bits > 128){rounds = 12;}
if (bits > 192){rounds = 14;}
/* invert the order of the round keys: */
for (i = 0, j = 4 * rounds; i < j; i += 4, j -= 4) {
temp = rk[i ];
rk[i ] = rk[j ];
rk[j ] = temp;
for (i = 0, j = 4 * rounds; i < j; i += 4, j -= 4){
temp = rk[i];
rk[i] = rk[j];
rk[j] = temp;
temp = rk[i + 1];
rk[i + 1] = rk[j + 1];
rk[j + 1] = temp;
@ -275,33 +454,37 @@ void AES_set_decrypt_key(const char * userKey, const int bits, char * key) {
rk[j + 3] = temp;
}
/* 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[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[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];
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];
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[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];
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];
}
}
//Encrypt a single block in and out can overlap
void AES_encrypt(const char * in, char * out, const int bits, const char * key) {
const unsigned int * rk = (const unsigned int *)key;
// Encrypt a single block in and out can overlap
void AES_encrypt(const char *in, char *out, const int bits, const char *key){
const unsigned int *rk = (const unsigned int *)key;
unsigned int s0, s1, s2, s3, t0, t1, t2, t3;
//map byte array block to cipher state and add initial round key
// map byte array block to cipher state and add initial round key
s0 = Bit::btohl(in) ^ rk[0];
s1 = Bit::btohl(in + 4) ^ rk[1];
s2 = Bit::btohl(in + 8) ^ rk[2];
s3 = Bit::btohl(in + 12) ^ rk[3];
/* round 1:*/
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[4];
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[5];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[6];
t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[7];
/* round 2:*/
s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[8];
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[9];
s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
/* round 3:*/
@ -339,7 +522,7 @@ void AES_encrypt(const char * in, char * out, const int bits, const char * key)
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
if (bits > 128) {
if (bits > 128){
/* round 10:*/
s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
@ -350,7 +533,7 @@ void AES_encrypt(const char * in, char * out, const int bits, const char * key)
t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
if (bits > 192) {
if (bits > 192){
/* round 12:*/
s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
@ -364,94 +547,94 @@ void AES_encrypt(const char * in, char * out, const int bits, const char * key)
}
}
rk += 40;
if (bits > 128) {
rk += 8;
}
if (bits > 192) {
rk += 8;
}
//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];
if (bits > 128){rk += 8;}
if (bits > 192){rk += 8;}
// 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];
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);
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);
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);
}
void AES_decrypt(const char * in, char * out, const char * key, unsigned int bits) {
const unsigned long * rk = (const unsigned long *)key;
void AES_decrypt(const char *in, char *out, const char *key, unsigned int bits){
const unsigned long *rk = (const unsigned long *)key;
unsigned long s0, s1, s2, s3, t0, t1, t2, t3;
//map byte array block to cipher state and add initial round key:
// map byte array block to cipher state and add initial round key:
s0 = htonl(Bit::btohl(in)) ^ rk[0];
s1 = htonl(Bit::btohl(in + 4)) ^ rk[1];
s2 = htonl(Bit::btohl(in + 8)) ^ rk[2];
s3 = htonl(Bit::btohl(in + 12)) ^ rk[3];
//round 1
t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
//round 2
s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
// round 1
t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[4];
t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[5];
t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[6];
t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[7];
// round 2
s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[8];
s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[9];
s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
//round 3
// round 3
t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
//round 4
// round 4
s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
//round 5
// round 5
t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
//round 6
// round 6
s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
//round 7
// round 7
t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
//round 8
// round 8
s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
//round 9
// round 9
t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
if (bits > 128) {
//round 10
if (bits > 128){
// round 10
s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
//round 11
// round 11
t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
if (bits > 192) {
//round 12
if (bits > 192){
// round 12
s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
//round 13
// round 13
t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
@ -459,36 +642,34 @@ void AES_decrypt(const char * in, char * out, const char * key, unsigned int bit
}
}
rk += 40;
if (bits > 128) {
rk += 8;
}
if (bits > 192) {
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];
if (bits > 128){rk += 8;}
if (bits > 192){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);
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);
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);
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);
}
static void increaseCounter(char * counter) {
for (int i = 15; i >= 0; i--) {
if (++counter[i]) {
return;
}
static void increaseCounter(char *counter){
for (int i = 15; i >= 0; i--){
if (++counter[i]){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;
while (l < len) {
if ((num % 16) == 0) {
while (l < len){
if ((num % 16) == 0){
num = 0;
AES_encrypt(ivec, ecount_buf, 128, key);
increaseCounter(ivec);

View file

@ -1,9 +1,10 @@
#pragma once
void AES_set_encrypt_key(const char * userKey, const int bits, char * key);
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_decrypt(const char * in, char * out, const char * key, unsigned int bits);
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 printInverted(const unsigned int * data, unsigned int len);
void AES_set_encrypt_key(const char *userKey, const int bits, char *key);
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_decrypt(const char *in, char *out, const char *key, unsigned int bits);
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 printInverted(const unsigned int *data, unsigned int len);

View file

@ -1,10 +1,10 @@
/// \file rtmpchunks.cpp
/// Holds all code for the RTMPStream namespace.
#include "rtmpchunks.h"
#include "auth.h"
#include "defines.h"
#include "flv_tag.h"
#include "rtmpchunks.h"
#include "timing.h"
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,
0x93, 0xb8, 0xe6, 0x36, 0xcf, 0xeb, 0x31, 0xae}; // 68
char genuineFPKey[] ={
0x47, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x20, 0x41, 0x64, 0x6f, 0x62, 0x65,
char genuineFPKey[] ={0x47, 0x65, 0x6e, 0x75, 0x69, 0x6e, 0x65, 0x20, 0x41, 0x64, 0x6f, 0x62, 0x65,
0x20, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x20, 0x50, 0x6c, 0x61,
0x79, // Genuine Adobe Flash Player 001
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);
uint8_t pTempBuffer[1536 - 32];
memcpy(pTempBuffer, pBuffer, clientDigestOffset);
memcpy(pTempBuffer + clientDigestOffset, pBuffer + clientDigestOffset + 32,
1536 - clientDigestOffset - 32);
memcpy(pTempBuffer + clientDigestOffset, pBuffer + clientDigestOffset + 32, 1536 - clientDigestOffset - 32);
char pTempHash[32];
Secure::hmac_sha256bin((char *)pTempBuffer, 1536 - 32, genuineFPKey, 30, pTempHash);
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 len Length of the media data, in bytes.
/// \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,
unsigned int ts){
std::string &RTMPStream::SendMedia(unsigned char msg_type_id, unsigned char *data, int len, unsigned int ts){
static RTMPStream::Chunk ch;
ch.cs_id = msg_type_id + 42;
ch.timestamp = ts;
@ -353,8 +350,7 @@ bool RTMPStream::Chunk::Parse(Socket::Buffer &buffer){
// process the rest of the header, for each chunk type
headertype = chunktype & 0xC0;
DONTEVEN_MSG("Parsing RTMP chunk header (%#.2hhX) at offset %#zx", chunktype,
RTMPStream::rec_cnt);
DONTEVEN_MSG("Parsing RTMP chunk header (%#.2hhX) at offset %#zx", chunktype, RTMPStream::rec_cnt);
switch (headertype){
case 0x00:
@ -512,8 +508,7 @@ bool RTMPStream::doHandshake(){
// FIRST 1536 bytes for server response
char pTempBuffer[1504];
memcpy(pTempBuffer, Server, serverDigestOffset);
memcpy(pTempBuffer + serverDigestOffset, Server + serverDigestOffset + 32,
1504 - serverDigestOffset);
memcpy(pTempBuffer + serverDigestOffset, Server + serverDigestOffset + 32, 1504 - serverDigestOffset);
Secure::hmac_sha256bin(pTempBuffer, 1504, genuineFMSKey, 36, (char *)Server + serverDigestOffset);
// SECOND 1536 bytes for server response
@ -523,12 +518,10 @@ bool RTMPStream::doHandshake(){
}else{
char pTempHash[32];
Secure::hmac_sha256bin((char *)Client + keyChallengeIndex, 32, genuineFMSKey, 68, pTempHash);
Secure::hmac_sha256bin((char *)Server + 1536, 1536 - 32, pTempHash, 32,
(char *)Server + 1536 * 2 - 32);
Secure::hmac_sha256bin((char *)Server + 1536, 1536 - 32, pTempHash, 32, (char *)Server + 1536 * 2 - 32);
}
Server[-1] = Version;
RTMPStream::snd_cnt += 3073;
return true;
}

View file

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

View file

@ -1,10 +1,10 @@
#include "rtp.h"
#include "adts.h"
#include "bitfields.h"
#include "defines.h"
#include "encode.h"
#include "h264.h"
#include "mpeg.h"
#include "rtp.h"
#include "sdp.h"
#include "timing.h"
#include <arpa/inet.h>
@ -15,14 +15,12 @@ namespace RTP{
unsigned int Packet::getHsize() const{
unsigned int r = 12 + 4 * getContribCount();
if (getExtension()){
r += (1+Bit::btohs(data+r+2)) * 4;
}
if (getExtension()){r += (1 + Bit::btohs(data + r + 2)) * 4;}
return r;
}
unsigned int Packet::getPayloadSize() const{
return maxDataLen - getHsize() - (getPadding() ? data[maxDataLen-1] : 0);
return maxDataLen - getHsize() - (getPadding() ? data[maxDataLen - 1] : 0);
}
char *Packet::getPayload() const{return data + getHsize();}
@ -47,7 +45,7 @@ namespace RTP{
char *Packet::getData(){return data + 8 + 4 * getContribCount() + getExtension();}
void Packet::setTimestamp(uint32_t t){Bit::htobl(data+4, t);}
void Packet::setTimestamp(uint32_t t){Bit::htobl(data + 4, t);}
void Packet::setSequence(unsigned int seq){*((short *)(data + 2)) = htons(seq);}
@ -75,8 +73,7 @@ namespace RTP{
}else{
data[1] &= 0x7F; // setting the RTP marker bit to 0
unsigned int sent = 0;
unsigned int sending =
maxDataLen - getHsize() - 2; // packages are of size MAX_SEND, except for the final one
unsigned int sending = maxDataLen - getHsize() - 2; // packages are of size MAX_SEND, except for the final one
char initByte = (payload[0] & 0xE0) | 0x1C;
char serByte = payload[0] & 0x1F; // ser is now 000
data[getHsize()] = initByte;
@ -118,15 +115,10 @@ namespace RTP{
chunkSize = std::min<size_t>(1200, payloadlen);
payloadlen -= chunkSize;
data[1] =
(0 != payloadlen) ? (data[1] & 0x7F) : (data[1] | 0x80); // marker bit, 1 for last chunk.
data[1] = (0 != payloadlen) ? (data[1] & 0x7F) : (data[1] | 0x80); // marker bit, 1 for last chunk.
data[headerSize] = 0x00; // reset
data[headerSize] |=
(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] |= (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.
memcpy(data + headerSize + 1, payload + bytesWritten, chunkSize);
callBack(socket, data, headerSize + 1 + chunkSize, channel);
@ -154,8 +146,7 @@ namespace RTP{
}else{
data[1] &= 0x7F; // setting the RTP marker bit to 0
unsigned int sent = 0;
unsigned int sending =
maxDataLen - getHsize() - 3; // packages are of size MAX_SEND, except for the final one
unsigned int sending = maxDataLen - getHsize() - 3; // packages are of size MAX_SEND, except for the final one
char initByteA = (payload[0] & 0x81) | 0x62;
char initByteB = payload[1];
char serByte = (payload[0] & 0x7E) >> 1; // SE is now 00
@ -205,8 +196,7 @@ namespace RTP{
}else{
data[1] &= 0x7F; // setting the RTP marker bit to 0
unsigned int sent = 0;
unsigned int sending =
maxDataLen - getHsize() - 4; // packages are of size MAX_SEND, except for the final one
unsigned int sending = maxDataLen - getHsize() - 4; // packages are of size MAX_SEND, except for the final one
Mpeg::MPEG2Info mInfo;
MPEGVideoHeader mHead(data + getHsize());
while (sent < payloadlen){
@ -234,13 +224,13 @@ namespace RTP{
}
void Packet::sendData(void *socket, void callBack(void *, char *, unsigned int, unsigned int),
const char *payload, unsigned int payloadlen, unsigned int channel,
std::string codec){
const char *payload, unsigned int payloadlen, unsigned int channel, std::string codec){
if (codec == "H264"){
unsigned long sent = 0;
while (sent < payloadlen){
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;
}
return;
@ -299,8 +289,7 @@ namespace RTP{
increaseSequence();
}
void Packet::sendRTCP_SR(long long &connectedAt, void *socket, unsigned int tid,
DTSC::Meta &metadata,
void Packet::sendRTCP_SR(long long &connectedAt, void *socket, unsigned int tid, DTSC::Meta &metadata,
void callBack(void *, char *, unsigned int, unsigned int)){
char *rtcpData = (char *)malloc(32);
if (!rtcpData){
@ -322,8 +311,7 @@ namespace RTP{
free(rtcpData);
}
void Packet::sendRTCP_RR(long long &connectedAt, SDP::Track &sTrk, unsigned int tid,
DTSC::Meta &metadata,
void Packet::sendRTCP_RR(long long &connectedAt, SDP::Track &sTrk, unsigned int tid, DTSC::Meta &metadata,
void callBack(void *, char *, unsigned int, unsigned int)){
char *rtcpData = (char *)malloc(32);
if (!rtcpData){
@ -336,12 +324,9 @@ namespace RTP{
Bit::htobs(rtcpData + 2, 7); // 7 4-byte words follow the header
Bit::htobl(rtcpData + 4, sTrk.mySSRC); // set receiver identifier
Bit::htobl(rtcpData + 8, sTrk.theirSSRC); // set source identifier
rtcpData[12] =
(sTrk.sorter.lostCurrent * 255) /
(sTrk.sorter.lostCurrent + sTrk.sorter.packCurrent); // fraction lost since prev RR
rtcpData[12] = (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::htobl(rtcpData + 16, sTrk.sorter.rtpSeq | (sTrk.sorter.packTotal &
0xFFFF0000ul)); // highest sequence received
Bit::htobl(rtcpData + 16, sTrk.sorter.rtpSeq | (sTrk.sorter.packTotal & 0xFFFF0000ul)); // highest sequence received
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 + 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,
unsigned int ssrc, unsigned int csrcCount){
managed = true;
data = new char[12 + 4 * csrcCount + 2 +
MAX_SEND]; // headerSize, 2 for FU-A, MAX_SEND for maximum sent size
data = new char[12 + 4 * csrcCount + 2 + MAX_SEND]; // headerSize, 2 for FU-A, MAX_SEND for maximum sent size
if (data){
maxDataLen = 12 + 4 * csrcCount + 2 + MAX_SEND;
data[0] = ((2) << 6) | ((0 & 1) << 5) | ((0 & 1) << 4) |
@ -397,7 +381,6 @@ namespace RTP{
}
sentBytes = o.sentBytes;
sentPackets = o.sentPackets;
}
void Packet::operator=(const Packet &o){
@ -613,7 +596,8 @@ namespace RTP{
int64_t pTime = pkt.getTimeStamp();
if (!firstTime){
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{
if (prevTime > pTime && pTime < 0x40000000lu && prevTime > 0x80000000lu){
++wrapArounds;
@ -625,7 +609,7 @@ namespace RTP{
}
}
prevTime = pkt.getTimeStamp();
uint64_t msTime = ((uint64_t)pTime - firstTime + 1 + 0xFFFFFFFFull*wrapArounds) / multiplier;
uint64_t msTime = ((uint64_t)pTime - firstTime + 1 + 0xFFFFFFFFull * wrapArounds) / multiplier;
char *pl = pkt.getPayload();
uint32_t plSize = pkt.getPayloadSize();
bool missed = lastSeq != (pkt.getSequence() - 1);
@ -657,8 +641,7 @@ namespace RTP{
void toDTSC::handleAAC(uint64_t msTime, char *pl, uint32_t plSize){
// assume AAC packets are single AU units
/// \todo Support other input than single AU units
unsigned int headLen =
(Bit::btohs(pl) >> 3) + 2; // in bits, so /8, plus two for the prepended size
unsigned int headLen = (Bit::btohs(pl) >> 3) + 2; // in bits, so /8, plus two for the prepended size
DTSC::Packet nextPack;
uint16_t samples = aac::AudSpecConf::samples(init);
uint32_t sampleOffset = 0;
@ -706,7 +689,7 @@ namespace RTP{
unsigned int pos = 2;
while (pos + 2 < plSize){
unsigned int pLen = Bit::btohs(pl + pos);
VERYHIGH_MSG("AP Packet of %ub and type %s", pLen, h265::typeToStr((pl[pos+2]&0x7E) >> 1));
VERYHIGH_MSG("AP Packet of %ub and type %s", pLen, h265::typeToStr((pl[pos + 2] & 0x7E) >> 1));
if (packBuffer.allocate(4 + pLen)){
Bit::htobl(packBuffer, pLen); // size-prepend
memcpy(packBuffer + 4, pl + pos + 2, pLen);
@ -808,8 +791,7 @@ namespace RTP{
isKey ? "key" : "i", frameNo, fps, packCount, (frameNo - packCount), offset);
}else{
// 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",
packCount);
VERYHIGH_MSG("Packing time %llu = %sframe %llu (variable rate)", ts, isKey ? "key" : "i", packCount);
}
// Fill the new DTSC packet, buffer it.
DTSC::Packet nextPack;
@ -823,8 +805,7 @@ namespace RTP{
/// for that data.
/// Prints a WARN-level message if packet type is unsupported.
/// \todo Support other H264 packets types?
void toDTSC::handleH264(uint64_t msTime, char *pl, uint32_t plSize, bool missed,
bool hasPadding){
void toDTSC::handleH264(uint64_t msTime, char *pl, uint32_t plSize, bool missed, bool hasPadding){
if (!plSize){
WARN_MSG("Empty packet ignored!");
return;
@ -1000,8 +981,7 @@ namespace RTP{
}else{
// 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",
packCount);
VERYHIGH_MSG("Packing time %llu = %sframe %llu (variable rate)", ts, isKey ? "key" : "i", packCount);
}
// Fill the new DTSC packet, buffer it.
DTSC::Packet nextPack;
@ -1031,8 +1011,7 @@ namespace RTP{
isKey ? "key" : "i", frameNo, fps, packCount, (frameNo - packCount), offset);
}else{
// 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",
packCount);
VERYHIGH_MSG("Packing time %llu = %sframe %llu (variable rate)", ts, isKey ? "key" : "i", packCount);
}
// Fill the new DTSC packet, buffer it.
DTSC::Packet nextPack;
@ -1062,8 +1041,7 @@ namespace RTP{
h264::isKeyframe(buffer + lastStart + 4, len - lastStart - 4));
}
void toDTSC::handleVP8(uint64_t msTime, const char *buffer, const uint32_t len, bool missed,
bool hasPadding){
void toDTSC::handleVP8(uint64_t msTime, const char *buffer, const uint32_t len, bool missed, bool hasPadding){
// 1 byte is required but we assume that there some payload
// data too :P
@ -1136,15 +1114,14 @@ namespace RTP{
// (e.g. only received the first partition of a frame) we will
// flush a new DTSC packet.
if (vp8FrameBuffer.size()){
//new frame and nothing missed? Send.
// new frame and nothing missed? Send.
if (start_of_frame && !missed){
DTSC::Packet nextPack;
nextPack.genericFill(msTime, 0, trackId, vp8FrameBuffer, vp8FrameBuffer.size(), 0,
vp8BufferHasKeyframe);
nextPack.genericFill(msTime, 0, trackId, vp8FrameBuffer, vp8FrameBuffer.size(), 0, vp8BufferHasKeyframe);
packCount++;
outPacket(nextPack);
}
//Wipe the buffer clean if missed packets or we just sent data out.
// Wipe the buffer clean if missed packets or we just sent data out.
if (start_of_frame || missed){
vp8FrameBuffer.assign(0, 0);
vp8BufferHasKeyframe = false;
@ -1170,4 +1147,3 @@ namespace RTP{
if (start_of_frame && is_keyframe){vp8BufferHasKeyframe = true;}
}
}// namespace RTP

View file

@ -65,23 +65,20 @@ namespace RTP{
void sendMPEG2(void *socket, void callBack(void *, char *, unsigned int, unsigned int),
const char *payload, unsigned int payloadlen, unsigned int channel);
void sendData(void *socket, void callBack(void *, char *, unsigned int, unsigned int),
const char *payload, unsigned int payloadlen, unsigned int channel,
std::string codec);
const char *payload, unsigned int payloadlen, unsigned int channel, std::string codec);
void sendRTCP_SR(long long &connectedAt, void *socket, unsigned int tid, DTSC::Meta &metadata,
void callBack(void *, char *, unsigned int, unsigned int));
void sendRTCP_RR(long long &connectedAt, SDP::Track &sTrk, unsigned int tid,
DTSC::Meta &metadata,
void callBack(void *, char *, unsigned int, unsigned int));
DTSC::Meta &metadata, void callBack(void *, char *, unsigned int, unsigned int));
Packet();
Packet(unsigned int pt, unsigned int seq, unsigned int ts, unsigned int ssr,
unsigned int csrcCount = 0);
Packet(unsigned int pt, unsigned int seq, unsigned int ts, unsigned int ssr, unsigned int csrcCount = 0);
Packet(const Packet &o);
void operator=(const Packet &o);
~Packet();
Packet(const char *dat, unsigned int len);
char *getData();
char *ptr() const { return data; }
char *ptr() const{return data;}
};
/// Sorts RTP packets, outputting them through a callback in correct order.
@ -173,13 +170,10 @@ namespace RTP{
void handleH264Multi(uint64_t ts, char *buffer, const uint32_t len);
std::string spsData; ///< SPS for H264
std::string ppsData; ///< PPS for H264
void handleVP8(uint64_t msTime, const char *buffer, const uint32_t len, bool missed,
bool hasPadding);
Util::ResizeablePointer
vp8FrameBuffer; ///< Stores successive VP8 payload data. We always start with the first
void handleVP8(uint64_t msTime, const char *buffer, const uint32_t len, bool missed, bool hasPadding);
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
///< lost. (a partition is basically what's called a slice in H264).
bool vp8BufferHasKeyframe;
};
}// namespace RTP

View file

@ -1,6 +1,6 @@
#include "defines.h"
#include "rtp_fec.h"
#include "rtp.h"
#include "rtp_fec.h"
namespace RTP{
/// Based on the `block PT` value, we can either find the
@ -49,49 +49,50 @@ namespace RTP{
/// | mask cont. (present only when L = 1) |
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
///
PacketFEC::PacketFEC() {
}
PacketFEC::PacketFEC(){}
PacketFEC::~PacketFEC() {
PacketFEC::~PacketFEC(){
receivedSeqNums.clear();
coveredSeqNums.clear();
}
bool PacketFEC::initWithREDPacket(const char* data, size_t nbytes) {
bool PacketFEC::initWithREDPacket(const char *data, size_t nbytes){
if (!data) {
if (!data){
FAIL_MSG("Given fecData pointer is NULL.");
return false;
}
if (nbytes < 23) {
FAIL_MSG("Given fecData is too small. Should be at least: 12 (RTP) + 1 (RED) + 10 (FEC) 23 bytes.");
if (nbytes < 23){
FAIL_MSG("Given fecData is too small. Should be at least: 12 (RTP) + 1 (RED) + 10 (FEC) 23 "
"bytes.");
return false;
}
if (coveredSeqNums.size() != 0) {
if (coveredSeqNums.size() != 0){
FAIL_MSG("It seems we're already initialized; coveredSeqNums already set.");
return false;
}
if (receivedSeqNums.size() != 0) {
if (receivedSeqNums.size() != 0){
FAIL_MSG("It seems we're already initialized; receivedSeqNums is not empty.");
return false;
}
// Decode RED header.
RTP::Packet rtpPkt(data, nbytes);
uint8_t* redHeader = (uint8_t*)(data + rtpPkt.getHsize());
uint8_t *redHeader = (uint8_t *)(data + rtpPkt.getHsize());
uint8_t moreBlocks = redHeader[0] & 0x80;
if (moreBlocks == 1) {
FAIL_MSG("RED header indicates there are multiple blocks. Haven't seen this before (@todo implement, exiting now).");
if (moreBlocks == 1){
FAIL_MSG("RED header indicates there are multiple blocks. Haven't seen this before (@todo "
"implement, exiting now).");
// \todo do not EXIT!
return false;
}
// Copy the data, starting at the FEC header (skip RTP + RED header)
size_t numHeaderBytes = rtpPkt.getHsize() + 1;
if (numHeaderBytes > nbytes) {
if (numHeaderBytes > nbytes){
FAIL_MSG("Invalid FEC packet; too small to contain FEC data.");
return false;
}
@ -100,7 +101,7 @@ namespace RTP{
fecPacketData.append(data + numHeaderBytes, nbytes - numHeaderBytes);
// Extract the sequence numbers this packet protects.
if (!extractCoveringSequenceNumbers()) {
if (!extractCoveringSequenceNumbers()){
FAIL_MSG("Failed to extract the protected sequence numbers for this FEC.");
// @todo we probably want to reset our set.
return false;
@ -109,20 +110,22 @@ namespace RTP{
return true;
}
uint8_t PacketFEC::getExtensionFlag() {
uint8_t PacketFEC::getExtensionFlag(){
if (fecPacketData.size() == 0) {
FAIL_MSG("Cannot get extension-flag from the FEC header; fecPacketData member is not set. Not initialized?");
if (fecPacketData.size() == 0){
FAIL_MSG("Cannot get extension-flag from the FEC header; fecPacketData member is not set. "
"Not initialized?");
return 0;
}
return ((fecPacketData[0] & 0x80) >> 7);
}
uint8_t PacketFEC::getLongMaskFlag() {
uint8_t PacketFEC::getLongMaskFlag(){
if (fecPacketData.size() == 0) {
FAIL_MSG("Cannot get the long-mask-flag from the FEC header. fecPacketData member is not set. Not initialized?");
if (fecPacketData.size() == 0){
FAIL_MSG("Cannot get the long-mask-flag from the FEC header. fecPacketData member is not "
"set. Not initialized?");
return 0;
}
@ -130,52 +133,52 @@ namespace RTP{
}
// Returns 0 (error), 2 or 6, wich are the valid sizes of the mask.
uint8_t PacketFEC::getNumBytesUsedForMask() {
uint8_t PacketFEC::getNumBytesUsedForMask(){
if (fecPacketData.size() == 0) {
FAIL_MSG("Cannot get the number of bytes used by the mask. fecPacketData member is not set. Not initialized?");
if (fecPacketData.size() == 0){
FAIL_MSG("Cannot get the number of bytes used by the mask. fecPacketData member is not set. "
"Not initialized?");
return 0;
}
if (getLongMaskFlag() == 0) {
return 2;
}
if (getLongMaskFlag() == 0){return 2;}
return 6;
}
uint16_t PacketFEC::getSequenceBaseNumber() {
uint16_t PacketFEC::getSequenceBaseNumber(){
if (fecPacketData.size() == 0) {
FAIL_MSG("Cannot get the sequence base number. fecPacketData member is not set. Not initialized?");
if (fecPacketData.size() == 0){
FAIL_MSG(
"Cannot get the sequence base number. fecPacketData member is not set. Not initialized?");
return 0;
}
return (uint16_t) (fecPacketData[2] << 8) | fecPacketData[3];
return (uint16_t)(fecPacketData[2] << 8) | fecPacketData[3];
}
char* PacketFEC::getFECHeader() {
char *PacketFEC::getFECHeader(){
if (fecPacketData.size() == 0) {
if (fecPacketData.size() == 0){
FAIL_MSG("Cannot get fec header. fecPacketData member is not set. Not initialized?");
}
return fecPacketData;
}
char* PacketFEC::getLevel0Header() {
char *PacketFEC::getLevel0Header(){
if (fecPacketData.size() == 0) {
if (fecPacketData.size() == 0){
FAIL_MSG("Cannot get the level 0 header. fecPacketData member is not set. Not initialized?");
return NULL;
}
return (char*)(fecPacketData + 10);
return (char *)(fecPacketData + 10);
}
char* PacketFEC::getLevel0Payload() {
char *PacketFEC::getLevel0Payload(){
if (fecPacketData.size() == 0) {
if (fecPacketData.size() == 0){
FAIL_MSG("Cannot get the level 0 payload. fecPacketData member is not set. Not initialized?");
return NULL;
}
@ -183,18 +186,19 @@ namespace RTP{
// 10 bytes for FEC header
// 2 bytes for `Protection Length`
// 2 or 6 bytes for `mask`.
return (char*)(fecPacketData + 10 + 2 + getNumBytesUsedForMask());
return (char *)(fecPacketData + 10 + 2 + getNumBytesUsedForMask());
}
uint16_t PacketFEC::getLevel0ProtectionLength() {
uint16_t PacketFEC::getLevel0ProtectionLength(){
if (fecPacketData.size() == 0) {
FAIL_MSG("Cannot get the level 0 protection length. fecPacketData member is not set. Not initialized?");
if (fecPacketData.size() == 0){
FAIL_MSG("Cannot get the level 0 protection length. fecPacketData member is not set. Not "
"initialized?");
return 0;
}
char* level0Header = getLevel0Header();
if (!level0Header) {
char *level0Header = getLevel0Header();
if (!level0Header){
FAIL_MSG("Failed to get the level 0 header, cannot get protection length.");
return 0;
}
@ -203,11 +207,12 @@ namespace RTP{
return protectionLength;
}
uint16_t PacketFEC::getLengthRecovery() {
uint16_t PacketFEC::getLengthRecovery(){
char* fecHeader = getFECHeader();
if (!fecHeader) {
FAIL_MSG("Cannot get the FEC header which we need to get the `length recovery` field. Not initialized?");
char *fecHeader = getFECHeader();
if (!fecHeader){
FAIL_MSG("Cannot get the FEC header which we need to get the `length recovery` field. Not "
"initialized?");
return 0;
}
@ -226,37 +231,35 @@ namespace RTP{
// packet protects the media packet with sequence number
// 230. We have to start counting the bit numbers from the
// most-significant-bit (e.g. 1 << 7).
bool PacketFEC::extractCoveringSequenceNumbers() {
bool PacketFEC::extractCoveringSequenceNumbers(){
if (coveredSeqNums.size() != 0) {
if (coveredSeqNums.size() != 0){
FAIL_MSG("Cannot extract protected sequence numbers; looks like we already did that.");
return false;
}
size_t maskNumBytes = getNumBytesUsedForMask();
if (maskNumBytes != 2 && maskNumBytes != 6) {
if (maskNumBytes != 2 && maskNumBytes != 6){
FAIL_MSG("Invalid mask size (%u) cannot extract sequence numbers.", maskNumBytes);
return false;
}
char* maskPtr = getLevel0Header();
if (!maskPtr) {
char *maskPtr = getLevel0Header();
if (!maskPtr){
FAIL_MSG("Failed to get the level-0 header ptr. Cannot extract protected sequence numbers.");
return false;
}
uint16_t seqNumBase = getSequenceBaseNumber();
if (seqNumBase == 0) {
WARN_MSG("Base sequence number is 0; it's possible but unlikely.");
}
if (seqNumBase == 0){WARN_MSG("Base sequence number is 0; it's possible but unlikely.");}
// Skip the `Protection Length`
maskPtr = maskPtr + 2;
for (uint16_t byteDX = 0; byteDX < maskNumBytes; ++byteDX) {
for (uint16_t byteDX = 0; byteDX < maskNumBytes; ++byteDX){
uint8_t maskByte = maskPtr[byteDX];
for (uint16_t bitDX = 0; bitDX < 8; ++bitDX) {
if (maskByte & (1 << 7 - bitDX)) {
for (uint16_t bitDX = 0; bitDX < 8; ++bitDX){
if (maskByte & (1 << 7 - bitDX)){
uint16_t seqNum = seqNumBase + (byteDX << 3) + bitDX;
coveredSeqNums.insert(seqNum);
}
@ -267,12 +270,12 @@ namespace RTP{
}
// \todo rename coversSequenceNumber
bool PacketFEC::coversSequenceNumber(uint16_t sn) {
bool PacketFEC::coversSequenceNumber(uint16_t sn){
return (coveredSeqNums.count(sn) == 0) ? false : true;
}
void PacketFEC::addReceivedSequenceNumber(uint16_t sn) {
if (false == coversSequenceNumber(sn)) {
void PacketFEC::addReceivedSequenceNumber(uint16_t sn){
if (false == coversSequenceNumber(sn)){
FAIL_MSG("Trying to add a received sequence number this instance is not handling (%u).", sn);
return;
}
@ -292,26 +295,23 @@ namespace RTP{
/// The `receivedMediaPackets` is the history of media packets
/// that you received and keep in a memory. These are used
/// 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
// been received as "received" in our internal list.
std::set<uint16_t>::iterator protIt = coveredSeqNums.begin();
while (protIt != coveredSeqNums.end()) {
if (receivedMediaPackets.count(*protIt) == 1) {
addReceivedSequenceNumber(*protIt);
}
while (protIt != coveredSeqNums.end()){
if (receivedMediaPackets.count(*protIt) == 1){addReceivedSequenceNumber(*protIt);}
protIt++;
}
// We have received all media packets that we could recover;
// so there is no need for this FEC packet.
// @todo Jaron shall we reuse allocs/PacketFECs?
if (receivedSeqNums.size() == coveredSeqNums.size()) {
return;
}
if (receivedSeqNums.size() == coveredSeqNums.size()){return;}
if (coveredSeqNums.size() != (receivedSeqNums.size() + 1)) {
if (coveredSeqNums.size() != (receivedSeqNums.size() + 1)){
// missing more then 1 packet. we can only recover when
// one packet is lost.
return;
@ -320,21 +320,21 @@ namespace RTP{
// Find missing sequence number.
uint16_t missingSeqNum = 0;
protIt = coveredSeqNums.begin();
while (protIt != coveredSeqNums.end()) {
if (receivedSeqNums.count(*protIt) == 0) {
while (protIt != coveredSeqNums.end()){
if (receivedSeqNums.count(*protIt) == 0){
missingSeqNum = *protIt;
break;
}
++protIt;
}
if (!coversSequenceNumber(missingSeqNum)) {
if (!coversSequenceNumber(missingSeqNum)){
WARN_MSG("We cannot recover %u.", missingSeqNum);
return;
}
// Copy FEC into new RTP-header
char* fecHeader = getFECHeader();
if (!fecHeader) {
char *fecHeader = getFECHeader();
if (!fecHeader){
FAIL_MSG("Failed to get the fec header. Cannot recover.");
return;
}
@ -342,34 +342,34 @@ namespace RTP{
recoverData.append(fecHeader, 12);
// Copy FEC into new RTP-payload
char* level0Payload = getLevel0Payload();
if (!level0Payload) {
char *level0Payload = getLevel0Payload();
if (!level0Payload){
FAIL_MSG("Failed to get the level-0 payload data (XOR'd media data from FEC packet).");
return;
}
uint16_t level0ProtLen = getLevel0ProtectionLength();
if (level0ProtLen == 0) {
if (level0ProtLen == 0){
FAIL_MSG("Failed to get the level-0 protection length.");
return;
}
recoverData.append(level0Payload, level0ProtLen);
uint8_t recoverLength[2] = { fecHeader[8], fecHeader[9] };
uint8_t recoverLength[2] ={fecHeader[8], fecHeader[9]};
// XOR headers
protIt = coveredSeqNums.begin();
while (protIt != coveredSeqNums.end()) {
while (protIt != coveredSeqNums.end()){
uint16_t seqNum = *protIt;
if (seqNum == missingSeqNum) {
if (seqNum == missingSeqNum){
++protIt;
continue;
}
Packet& mediaPacket = receivedMediaPackets[seqNum];
char* mediaData = mediaPacket.ptr();
Packet &mediaPacket = receivedMediaPackets[seqNum];
char *mediaData = mediaPacket.ptr();
uint16_t mediaSize = mediaPacket.getPayloadSize();
uint8_t* mediaSizePtr = (uint8_t*)&mediaSize;
uint8_t *mediaSizePtr = (uint8_t *)&mediaSize;
WARN_MSG(" => XOR header with %u, size: %u.", seqNum, mediaSize);
@ -390,21 +390,19 @@ namespace RTP{
++protIt;
}
uint16_t recoverPayloadSize = ntohs(*(uint16_t*)recoverLength);
uint16_t recoverPayloadSize = ntohs(*(uint16_t *)recoverLength);
// XOR payloads
protIt = coveredSeqNums.begin();
while (protIt != coveredSeqNums.end()) {
while (protIt != coveredSeqNums.end()){
uint16_t seqNum = *protIt;
if (seqNum == missingSeqNum) {
if (seqNum == missingSeqNum){
++protIt;
continue;
}
Packet& mediaPacket = receivedMediaPackets[seqNum];
char* mediaData = mediaPacket.ptr() + mediaPacket.getHsize();
for (size_t i = 0; i < recoverPayloadSize; ++i) {
recoverData[12 + i] ^= mediaData[i];
}
Packet &mediaPacket = receivedMediaPackets[seqNum];
char *mediaData = mediaPacket.ptr() + mediaPacket.getHsize();
for (size_t i = 0; i < recoverPayloadSize; ++i){recoverData[12 + i] ^= mediaData[i];}
++protIt;
}
@ -414,9 +412,8 @@ namespace RTP{
// @todo check what other header fields we need to fix.
}
void FECSorter::addPacket(const Packet &pack){
if (tmpVideoLossPrevention & SDP_LOSS_PREVENTION_ULPFEC) {
if (tmpVideoLossPrevention & SDP_LOSS_PREVENTION_ULPFEC){
packetHistory[pack.getSequence()] = pack;
while (packetHistory.begin()->first < pack.getSequence() - 500){
packetHistory.erase(packetHistory.begin());
@ -447,24 +444,20 @@ namespace RTP{
/// |F| block PT | timestamp offset | block length |
/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
///
void FECSorter::addREDPacket(char* dat,
unsigned int len,
uint8_t codecPayloadType,
uint8_t REDPayloadType,
uint8_t ULPFECPayloadType)
{
void FECSorter::addREDPacket(char *dat, unsigned int len, uint8_t codecPayloadType,
uint8_t REDPayloadType, uint8_t ULPFECPayloadType){
RTP::Packet pkt(dat, len);
if (pkt.getPayloadType() != REDPayloadType) {
if (pkt.getPayloadType() != REDPayloadType){
FAIL_MSG("Requested to add a RED packet, but it has an invalid payload type.");
return;
}
// Check if the `F` flag is set. Chromium will always set
// this to 0 (at time of writing, check: https://goo.gl/y1eJ6k
uint8_t* REDHeader = (uint8_t*)(dat + pkt.getHsize());
uint8_t *REDHeader = (uint8_t *)(dat + pkt.getHsize());
uint8_t moreBlocksAvailable = REDHeader[0] & 0x80;
if (moreBlocksAvailable == 1) {
if (moreBlocksAvailable == 1){
FAIL_MSG("Not yet received a RED packet that had it's F bit set; @todo implement.");
exit(EXIT_FAILURE);
return;
@ -474,11 +467,11 @@ namespace RTP{
// fec-pt. When it's just media that follows, we move all
// data one byte up and reconstruct a normal media packet.
uint8_t blockPayloadType = REDHeader[0] & 0x7F;
if (blockPayloadType == codecPayloadType) {
if (blockPayloadType == codecPayloadType){
memmove(dat + pkt.getHsize(), dat + pkt.getHsize() + 1, len - pkt.getHsize() - 1);
dat[1] &= 0x80;
dat[1] |= codecPayloadType;
RTP::Packet mediaPacket((const char*)dat, len -1);
RTP::Packet mediaPacket((const char *)dat, len - 1);
addPacket(mediaPacket);
return;
}
@ -496,10 +489,10 @@ namespace RTP{
// is going to deal with FEC.
//
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (blockPayloadType == ULPFECPayloadType) {
if (blockPayloadType == ULPFECPayloadType){
WARN_MSG(" => got fec packet: %u", pkt.getSequence());
PacketFEC* fec = new PacketFEC();
if (!fec->initWithREDPacket(dat, len)) {
PacketFEC *fec = new PacketFEC();
if (!fec->initWithREDPacket(dat, len)){
delete fec;
fec = NULL;
FAIL_MSG("Failed to initialize a `PacketFEC`");
@ -508,9 +501,10 @@ namespace RTP{
Packet recreatedPacket;
fec->tryToRecoverMissingPacket(packetHistory, recreatedPacket);
if (recreatedPacket.ptr() != NULL) {
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]);
if (recreatedPacket.ptr() != NULL){
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]);
addPacket(recreatedPacket);
}
return;
@ -527,18 +521,17 @@ namespace RTP{
/// have been received except the one that we want to
/// recover. This function returns the FEC packet might be able
/// to recover the given sequence number.
PacketFEC* FECSorter::getFECPacketWhichCoversSequenceNumber(uint16_t sn) {
PacketFEC *FECSorter::getFECPacketWhichCoversSequenceNumber(uint16_t sn){
size_t nfecs = fecPackets.size();
for (size_t i = 0; i < nfecs; ++i) {
PacketFEC* fec = fecPackets[i];
if (fec->coversSequenceNumber(sn)) {
return fec;
}
for (size_t i = 0; i < nfecs; ++i){
PacketFEC *fec = fecPackets[i];
if (fec->coversSequenceNumber(sn)){return fec;}
}
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);
if (!rtcpData){
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::htobl(rtcpData + 4, mySSRC); // set receiver identifier
Bit::htobl(rtcpData + 8, theirSSRC); // set source identifier
rtcpData[12] =
(sorter.lostCurrent * 255) /
(sorter.lostCurrent + sorter.packCurrent); // fraction lost since prev RR
rtcpData[12] = (sorter.lostCurrent * 255) / (sorter.lostCurrent + sorter.packCurrent); // fraction lost since prev RR
Bit::htob24(rtcpData + 13, sorter.lostTotal); // cumulative packets lost since start
Bit::htobl(rtcpData + 16, sorter.rtpSeq | (sorter.packTotal &
0xFFFF0000ul)); // highest sequence received
Bit::htobl(rtcpData + 16, sorter.rtpSeq | (sorter.packTotal & 0xFFFF0000ul)); // highest sequence received
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 + 28, 0); /// \TODO delay since last SR in 2b seconds + 2b fraction
@ -565,5 +555,4 @@ namespace RTP{
free(rtcpData);
}
}
}// namespace RTP

View file

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

View file

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

View file

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

View file

@ -38,7 +38,7 @@ namespace SDP{
}else if (codec == "RED"){
return "";
}
ERROR_MSG( "%s support not implemented", codec.c_str());
ERROR_MSG("%s support not implemented", codec.c_str());
return "";
}
@ -70,29 +70,25 @@ namespace SDP{
}else if (codec == "RED"){
return "";
}
ERROR_MSG( "%s support not implemented", codec.c_str());
ERROR_MSG("%s support not implemented", codec.c_str());
BACKTRACE;
return "";
}
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); // Split a string on the given delimeter and return a vector with the parts.
static bool
sdp_extract_payload_type(const std::string &str,
static bool sdp_extract_payload_type(const std::string &str,
uint64_t &result); // Extract the payload number from a SDP line that
// starts like: `a=something:[payloadtype]`.
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); // Extracts the `name` and `value` from a string like `<name>=<value>`.
// The `name` will always be converted to lowercase!.
static void 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:
static void
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:
// `<name>=<value>;<name>=<value>`. The `name` part will
// always be converted to lowercase.
static bool
sdp_get_attribute_value(const std::string &str,
static bool sdp_get_attribute_value(const std::string &str,
std::string &result); // Extract an "attribute" value, which is formatted
// like: `a=something:<attribute-value>`
static std::string string_to_upper(const std::string &str);
@ -234,9 +230,9 @@ namespace SDP{
return pm;
}
std::string MediaFormat::getProfileLevelIdForH264() {
std::string MediaFormat::getProfileLevelIdForH264(){
if (encodingName != "H264") {
if (encodingName != "H264"){
ERROR_MSG("Encoding is not H264, cannot get profile-level-id.");
return "";
}
@ -352,8 +348,7 @@ namespace SDP{
bool Media::parseFrameRateLine(const std::string &line){
if (line.substr(0, 12) != "a=framerate:"){
ERROR_MSG("Cannot parse the `a=framerate:` line because it's incorrectly formatted: `%s`.",
line.c_str());
ERROR_MSG("Cannot parse the `a=framerate:` line because it's incorrectly formatted: `%s`.", line.c_str());
return false;
}
@ -389,7 +384,7 @@ namespace SDP{
// When this format is associated with another format
// which is the case for RTX, we store the associated
// payload type too. `apt` means "Associated Payload Type".
if (format->formatParameters.count("apt") != 0) {
if (format->formatParameters.count("apt") != 0){
std::stringstream ss(format->formatParameters["apt"]);
ss >> format->associatedPayloadType;
}
@ -530,17 +525,13 @@ namespace SDP{
return result;
}
MediaFormat* Media::getRetransMissionFormatForPayloadType(uint64_t pt) {
MediaFormat *Media::getRetransMissionFormatForPayloadType(uint64_t pt){
std::vector<SDP::MediaFormat*> rtxFormats = getFormatsForEncodingName("RTX");
if (rtxFormats.size() == 0) {
return NULL;
}
std::vector<SDP::MediaFormat *> rtxFormats = getFormatsForEncodingName("RTX");
if (rtxFormats.size() == 0){return NULL;}
for (size_t i = 0; i < rtxFormats.size(); ++i) {
if (rtxFormats[i]->associatedPayloadType == pt) {
return rtxFormats[i];
}
for (size_t i = 0; i < rtxFormats.size(); ++i){
if (rtxFormats[i]->associatedPayloadType == pt){return rtxFormats[i];}
}
return NULL;
@ -567,8 +558,7 @@ namespace SDP{
///
/// @param mediaType `video` or `audio`
/// @param encodingName Encoding name in fullcaps, e.g. `H264`, `OPUS`, etc.
MediaFormat *Session::getMediaFormatByEncodingName(const std::string &mediaType,
const std::string &encodingName){
MediaFormat *Session::getMediaFormatByEncodingName(const std::string &mediaType, const std::string &encodingName){
SDP::Media *media = getMediaForType(mediaType);
if (!media){
WARN_MSG("No SDP::Media found for media type %s.", mediaType.c_str());
@ -666,8 +656,7 @@ namespace SDP{
return true;
}
static std::vector<std::string> sdp_split(const std::string &str, const std::string &delim,
bool keepEmpty){
static std::vector<std::string> sdp_split(const std::string &str, const std::string &delim, bool keepEmpty){
std::vector<std::string> strings;
std::ostringstream word;
for (size_t n = 0; n < str.size(); ++n){
@ -686,8 +675,7 @@ namespace SDP{
// extract payload type.
size_t start_pos = str.find_first_of(':');
size_t end_pos = str.find_first_of(' ', start_pos);
if (start_pos == std::string::npos || end_pos == std::string::npos ||
(start_pos + 1) >= end_pos){
if (start_pos == std::string::npos || end_pos == std::string::npos || (start_pos + 1) >= end_pos){
FAIL_MSG("Invalid `a=rtpmap` line. Has not payload type.");
return false;
}
@ -704,8 +692,7 @@ namespace SDP{
// when parsing the `a=fmtp:<fmt>` line.
//
// 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,
std::string &value){
static bool sdp_get_name_value_from_varval(const std::string &str, std::string &var, std::string &value){
if (str.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(":");
if (start == std::string::npos){
ERROR_MSG("Cannot get attribute value because we did not find the : character in %s.",
str.c_str());
ERROR_MSG("Cannot get attribute value because we did not find the : character in %s.", str.c_str());
return false;
}
@ -773,12 +759,9 @@ namespace SDP{
return true;
}
Answer::Answer() :
isVideoEnabled(false),
isAudioEnabled(false),
candidatePort(0),
videoLossPrevention(SDP_LOSS_PREVENTION_NONE)
{}
Answer::Answer()
: isVideoEnabled(false), isAudioEnabled(false), candidatePort(0),
videoLossPrevention(SDP_LOSS_PREVENTION_NONE){}
bool Answer::parseOffer(const std::string &sdp){
@ -931,8 +914,8 @@ namespace SDP{
std::string type = mediaOffer.type;
SDP::Media *media = NULL;
SDP::MediaFormat *fmtMedia = NULL;
SDP::MediaFormat* fmtRED = NULL;
SDP::MediaFormat* fmtULPFEC = NULL;
SDP::MediaFormat *fmtRED = NULL;
SDP::MediaFormat *fmtULPFEC = NULL;
bool isEnabled = false;
std::vector<uint8_t> supportedPayloadTypes;
@ -951,11 +934,11 @@ namespace SDP{
fmtULPFEC = media->getFormatForEncodingName("ULPFEC");
}
if (!media) {
if (!media){
WARN_MSG("No media found.");
continue;
}
if (!fmtMedia) {
if (!fmtMedia){
WARN_MSG("No format found.");
continue;
}
@ -964,21 +947,16 @@ namespace SDP{
// them payload types into a string that is used with the
// `m=` line to indicate we have support for these.
supportedPayloadTypes.push_back((uint8_t)fmtMedia->payloadType);
if ((videoLossPrevention & SDP_LOSS_PREVENTION_ULPFEC)
&& fmtRED
&& fmtULPFEC)
{
if ((videoLossPrevention & SDP_LOSS_PREVENTION_ULPFEC) && fmtRED && fmtULPFEC){
supportedPayloadTypes.push_back(fmtRED->payloadType);
supportedPayloadTypes.push_back(fmtULPFEC->payloadType);
}
std::stringstream ss;
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];
if ((k + 1) < nels) {
ss << " ";
}
if ((k + 1) < nels){ss << " ";}
}
std::string payloadTypes = ss.str();
@ -1008,14 +986,11 @@ namespace SDP{
addLine("a=%s", fmtMedia->rtpmap.c_str());
// BEGIN FEC/RTX: testing with just FEC or RTX
if ((videoLossPrevention & SDP_LOSS_PREVENTION_ULPFEC)
&& fmtRED
&& fmtULPFEC)
{
if ((videoLossPrevention & SDP_LOSS_PREVENTION_ULPFEC) && fmtRED && fmtULPFEC){
addLine("a=rtpmap:%u ulpfec/90000", fmtULPFEC->payloadType);
addLine("a=rtpmap:%u red/90000", fmtRED->payloadType);
}
if (videoLossPrevention & SDP_LOSS_PREVENTION_NACK) {
if (videoLossPrevention & SDP_LOSS_PREVENTION_NACK){
addLine("a=rtcp-fb:%u nack", fmtMedia->payloadType);
}
// END FEC/RTX
@ -1026,7 +1001,8 @@ namespace SDP{
if (fmtMedia->encodingName == "H264"){
std::string usedProfile = fmtMedia->getFormatParameterForName("profile-level-id");
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";
}
@ -1074,8 +1050,7 @@ namespace SDP{
SDP::Media &outMedia, SDP::MediaFormat &outFormat){
Media *media = sdpOffer.getMediaForType(type);
if (!media){
INFO_MSG("Cannot enable %s codec; offer doesn't have %s media.", codecList.c_str(),
type.c_str());
INFO_MSG("Cannot enable %s codec; offer doesn't have %s media.", codecList.c_str(), type.c_str());
return false;
}
@ -1102,8 +1077,9 @@ namespace SDP{
format = NULL;
continue;
}
if (formats[j]->getProfileLevelIdForH264() != "42e01f") {
MEDIUM_MSG("Skipping this H264 format because it uses an unsupported profile-level-id.");
if (formats[j]->getProfileLevelIdForH264() != "42e01f"){
MEDIUM_MSG(
"Skipping this H264 format because it uses an unsupported profile-level-id.");
format = NULL;
continue;
}
@ -1179,6 +1155,4 @@ namespace SDP{
return result;
}
}
}// namespace SDP

View file

@ -1,14 +1,16 @@
#pragma once
#include <string>
#include "dtsc.h"
#include <map>
#include <set>
#include <string>
#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_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_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.
#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_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{
@ -30,28 +32,23 @@ namespace SDP{
class MediaFormat{
public:
MediaFormat();
std::string getFormatParameterForName(
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
std::string getFormatParameterForName(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
///< returned, otherwise we use the `payloadType` to determine the samplerate or
///< return 0 when we fail to determine to samplerate.
uint32_t getAudioNumChannels()
const; ///< Returns the number of audio channels. When `audioNumChannels` has been set this
uint32_t
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
///< the samplerate or we return 0 when we can't determine the number of channels.
uint32_t getAudioBitSize()
const; ///< Returns the audio bitsize. When `audioBitSize` has been set this will be
uint32_t getAudioBitSize() const; ///< Returns the audio bitsize. When `audioBitSize` has been set this will be
///< returned, othwerise we use the `encodingName` to determine the right
///< `audioBitSize` or 0 when we can't determine the `audioBitSize`
uint32_t
getVideoRate() const; ///< Returns the video time base. When `videoRate` has been set this will
uint32_t getVideoRate() const; ///< Returns the video time base. When `videoRate` has been set this will
///< be returned, otherwise we use the `encodingName` to determine the
///< right value or 0 when we can't determine the video rate.
uint32_t getVideoOrAudioRate() const; ///< Returns whichever rate has been set.
uint64_t getPayloadType() const; ///< Returns the `payloadType` member.
int32_t
getPacketizationModeForH264(); ///< When this represents a h264 format this will return the
int32_t getPacketizationModeForH264(); ///< When this represents a h264 format this will return the
///< 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.
@ -72,12 +69,10 @@ namespace SDP{
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 rtpmap; ///< The `a=<rtpmap:...> value; value between brackets.
std::map<std::string, std::string>
formatParameters; ///< Stores the var-val pairs from `a=fmtp:<fmt>` entry e.g. =
std::map<std::string, std::string> 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==`
///< */
std::set<std::string>
rtcpFormats; ///< Stores the `fb-val` from the line with `a=rtcp-fb:<fmt> <fb-val>`.
std::set<std::string> rtcpFormats; ///< Stores the `fb-val` from the line with `a=rtcp-fb:<fmt> <fb-val>`.
};
class Media{
@ -85,40 +80,32 @@ namespace SDP{
Media();
bool parseMediaLine(const std::string &sdpLine); ///< Parses `m=` line. Creates a `MediaFormat`
///< entry for each of the found <fmt> values.
bool parseRtpMapLine(
const std::string &sdpLine); ///< Parses `a=rtpmap:` line which contains the some codec
bool parseRtpMapLine(const std::string &sdpLine); ///< Parses `a=rtpmap:` line which contains the some codec
///< specific info. When this line contains the samplerate and
///< number of audio channels they will be extracted.
bool parseRtspControlLine(const std::string &sdpLine); ///< Parses `a=control:`
bool parseFrameRateLine(const std::string &sdpLine); ///< Parses `a=framerate:`
bool parseFormatParametersLine(const std::string &sdpLine); ///< Parses `a=fmtp:<payload-type>`.
bool parseRtcpFeedbackLine(
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 parseRtcpFeedbackLine(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
///< https://tools.ietf.org/html/rfc8122#section-5, used with WebRTC
bool parseSSRCLine(const std::string &sdpLine); ///< Parses `a=ssrc:<ssrc>`.
MediaFormat *getFormatForSdpLine(
const std::string
&sdpLine); ///< Returns the track to which this SDP line applies. This means that the
MediaFormat *getFormatForSdpLine(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]`.
MediaFormat *getFormatForPayloadType(
uint64_t &payloadType); ///< Finds the `MediaFormat` in `formats`. Returns NULL when no
MediaFormat *
getFormatForPayloadType(uint64_t &payloadType); ///< Finds the `MediaFormat` in `formats`. Returns NULL when no
///< format was found for the given payload type. .
MediaFormat *getFormatForEncodingName(
const std::string
&encName); ///< Finds the `MediaFormats in `formats`. Returns NULL when no format was
MediaFormat *getFormatForEncodingName(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`
std::vector<SDP::MediaFormat *> getFormatsForEncodingName(const std::string &encName);
std::string getIcePwdForFormat(
const MediaFormat
&fmt); ///< The `a=ice-pwd` can be session global or media specific. This function will
std::string getIcePwdForFormat(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.
uint32_t
getSSRC() const; ///< Returns the first SSRC `a=ssrc:<value>` value found for the media.
uint32_t getSSRC() const; ///< Returns the first SSRC `a=ssrc:<value>` value found for the media.
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:
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 fingerprintHash; ///< From `a=fingerprint:<hash> <value>`, e.g. sha-256, used with
///< WebRTC / STUN
std::string
fingerprintValue; ///< From `a=fingerprint:<hash> <value>`, the actual fingerprint, used
std::string fingerprintValue; ///< From `a=fingerprint:<hash> <value>`, the actual fingerprint, used
///< 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
///< 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
///< transport channel.
bool supportsRTCPReducedSize; ///< From `a=rtcp-rsize`, reduced size RTCP packets.
std::string
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::string 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>
///< field(s) from the `m=` line.
};
class Session{
public:
bool parseSDP(const std::string &sdp);
Media *getMediaForType(
const std::string &type); ///< Get a `SDP::Media*` for the given type, e.g. `video` or
Media *getMediaForType(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.
MediaFormat *getMediaFormatByEncodingName(const std::string &mediaType,
const std::string &encodingName);
MediaFormat *getMediaFormatByEncodingName(const std::string &mediaType, const std::string &encodingName);
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
///< wants to receive or also sent data. */
@ -168,8 +150,7 @@ namespace SDP{
///< stream specific infomration is stored in a `MediaFormat`
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.
std::string
iceUFrag; ///< From `a=ice-ufag`, this property can be session-wide or media specific. Used
std::string iceUFrag; ///< From `a=ice-ufag`, this property can be session-wide or media specific. Used
///< 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.
};
}
}// namespace SDP

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,9 @@
#pragma once
#include <string>
#include <set>
#include <string>
#include "timing.h"
#include "defines.h"
#include "timing.h"
#if defined(__CYGWIN__) || defined(_WIN32)
#include <windows.h>
@ -12,18 +12,18 @@
#endif
#ifndef ACCESSPERMS
#define ACCESSPERMS (S_IRWXU|S_IRWXG|S_IRWXO)
#define ACCESSPERMS (S_IRWXU | S_IRWXG | S_IRWXO)
#endif
#define STAT_EX_SIZE 177
#define PLAY_EX_SIZE 2+6*SIMUL_TRACKS
#define PLAY_EX_SIZE 2 + 6 * SIMUL_TRACKS
namespace IPC {
namespace IPC{
///\brief A class used for the exchange of statistics over shared memory.
class statExchange {
class statExchange{
public:
statExchange(char * _data);
statExchange(char *_data);
void now(long long int time);
long long int now();
void time(long time);
@ -46,6 +46,7 @@ namespace IPC {
unsigned int crc();
uint32_t getPID();
std::string getSessId();
private:
///\brief The payload for the stat exchange
/// - 8 byte - now (timestamp of last statistics)
@ -59,17 +60,17 @@ namespace IPC {
/// - 4 byte - CRC32 of user agent (or zero if none)
/// - 1 byte sync (was seen by controller yes/no)
/// - (implicit 4 bytes: PID)
char * data;
char *data;
};
///\brief A class used for the abstraction of semaphores
class semaphore {
class semaphore{
public:
semaphore();
semaphore(const char * name, int oflag, mode_t mode = 0, unsigned int value = 0, bool noWait = false);
semaphore(const char *name, int oflag, mode_t mode = 0, unsigned int value = 0, bool noWait = false);
~semaphore();
operator bool() const;
void open(const char * name, int oflag, mode_t mode = 0, unsigned int value = 0, bool noWait = false);
void open(const char *name, int oflag, mode_t mode = 0, unsigned int value = 0, bool noWait = false);
int getVal() const;
void post();
void wait();
@ -78,13 +79,14 @@ namespace IPC {
void close();
void abandon();
void unlink();
private:
#if defined(__CYGWIN__) || defined(_WIN32)
///\todo Maybe sometime implement anything else than 777
static SECURITY_ATTRIBUTES getSecurityAttributes();
HANDLE mySem;
#else
sem_t * mySem;
sem_t *mySem;
#endif
unsigned int isLocked;
uint64_t lockTime;
@ -92,27 +94,26 @@ namespace IPC {
};
///\brief A class used as a semaphore guard
class semGuard {
class semGuard{
public:
semGuard(semaphore * thisSemaphore);
semGuard(semaphore *thisSemaphore);
~semGuard();
private:
///\brief The semaphore to guard.
semaphore * mySemaphore;
semaphore *mySemaphore;
};
///\brief A class for managing shared files.
class sharedFile {
class sharedFile{
public:
sharedFile(const std::string & name_ = "", uint64_t len_ = 0, bool master_ = false, bool autoBackoff = true);
sharedFile(const sharedFile & rhs);
sharedFile(const std::string &name_ = "", uint64_t len_ = 0, bool master_ = false, bool autoBackoff = true);
sharedFile(const sharedFile &rhs);
~sharedFile();
operator bool() const;
void init(const std::string & name_, uint64_t len_, bool master_ = false, bool autoBackoff = true);
void operator =(sharedFile & rhs);
bool operator < (const sharedFile & rhs) const {
return name < rhs.name;
}
void init(const std::string &name_, uint64_t len_, bool master_ = false, bool autoBackoff = true);
void operator=(sharedFile &rhs);
bool operator<(const sharedFile &rhs) const{return name < rhs.name;}
void close();
void unmap();
bool exists();
@ -125,7 +126,7 @@ namespace IPC {
///\brief Whether this class should unlink the shared file upon deletion or not
bool master;
///\brief A pointer to the payload of the file file
char * mapped;
char *mapped;
};
#if defined(__CYGWIN__) || defined(_WIN32)
@ -135,27 +136,25 @@ namespace IPC {
#ifdef SHM_ENABLED
///\brief A class for managing shared memory pages.
class sharedPage {
class sharedPage{
public:
sharedPage(const std::string & name_ = "", uint64_t len_ = 0, bool master_ = false, bool autoBackoff = true);
sharedPage(const sharedPage & rhs);
sharedPage(const std::string &name_ = "", uint64_t len_ = 0, bool master_ = false, bool autoBackoff = true);
sharedPage(const sharedPage &rhs);
~sharedPage();
operator bool() const;
void init(const std::string & name_, uint64_t len_, bool master_ = false, bool autoBackoff = true);
void operator =(sharedPage & rhs);
bool operator < (const sharedPage & rhs) const {
return name < rhs.name;
}
void init(const std::string &name_, uint64_t len_, bool master_ = false, bool autoBackoff = true);
void operator=(sharedPage &rhs);
bool operator<(const sharedPage &rhs) const{return name < rhs.name;}
void unmap();
void close();
bool exists();
#if defined(__CYGWIN__) || defined(_WIN32)
#if defined(__CYGWIN__) || defined(_WIN32)
///\brief The handle of the opened shared memory page
HANDLE handle;
#else
#else
///\brief The fd handle of the opened shared memory page
int handle;
#endif
#endif
///\brief The name of the opened shared memory page
std::string name;
///\brief The size in bytes of the opened shared memory page
@ -163,42 +162,44 @@ namespace IPC {
///\brief Whether this class should unlink the shared memory upon deletion or not
bool master;
///\brief A pointer to the payload of the page
char * mapped;
char *mapped;
};
#else
///\brief A class for handling shared memory pages.
///Uses shared files at its backbone, defined for portability
class sharedPage: public sharedFile {
/// Uses shared files at its backbone, defined for portability
class sharedPage : public sharedFile{
public:
sharedPage(const std::string & name_ = "", uint64_t len_ = 0, bool master_ = false, bool autoBackoff = true);
sharedPage(const sharedPage & rhs);
sharedPage(const std::string &name_ = "", uint64_t len_ = 0, bool master_ = false, bool autoBackoff = true);
sharedPage(const sharedPage &rhs);
~sharedPage();
};
#endif
///\brief The server part of a server/client model for shared memory.
///
///The server manages the shared memory pages, and allocates new pages when needed.
/// The server manages the shared memory pages, and allocates new pages when needed.
///
///Pages are created with a basename + index, where index is in the range of 'A' - 'Z'
///Each time a page is nearly full, the next page is created with a size double to the previous one.
/// Pages are created with a basename + index, where index is in the range of 'A' - 'Z'
/// Each time a page is nearly full, the next page is created with a size double to the previous one.
///
///Clients should allocate payLen bytes at a time, possibly with the addition of a counter.
///If no such length can be allocated, the next page should be tried, and so on.
class sharedServer {
/// Clients should allocate payLen bytes at a time, possibly with the addition of a counter.
/// If no such length can be allocated, the next page should be tried, and so on.
class sharedServer{
public:
sharedServer();
sharedServer(std::string name, int len, bool withCounter = false);
void init(std::string name, int len, bool withCounter = false);
~sharedServer();
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);
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);
operator bool() const;
///\brief The amount of connected clients
unsigned int amount;
unsigned int connectedUsers;
void finishEach();
void abandon();
private:
bool isInUse(unsigned int id);
void newPage();
@ -217,27 +218,28 @@ namespace IPC {
///\brief The client part of a server/client model for shared memory.
///
///The server manages the shared memory pages, and allocates new pages when needed.
/// The server manages the shared memory pages, and allocates new pages when needed.
///
///Pages are created with a basename + index, where index is in the range of 'A' - 'Z'
///Each time a page is nearly full, the next page is created with a size double to the previous one.
/// Pages are created with a basename + index, where index is in the range of 'A' - 'Z'
/// Each time a page is nearly full, the next page is created with a size double to the previous one.
///
///Clients should allocate payLen bytes at a time, possibly with the addition of a counter.
///If no such length can be allocated, the next page should be tried, and so on.
class sharedClient {
/// Clients should allocate payLen bytes at a time, possibly with the addition of a counter.
/// If no such length can be allocated, the next page should be tried, and so on.
class sharedClient{
public:
sharedClient();
sharedClient(const sharedClient & rhs);
sharedClient(const sharedClient &rhs);
sharedClient(std::string name, int len, bool withCounter = false);
void operator = (const sharedClient & rhs);
void operator=(const sharedClient &rhs);
~sharedClient();
void write(char * data, int len);
void write(char *data, int len);
void finish();
void keepAlive();
bool isAlive();
char * getData();
char *getData();
int getCounter();
bool countAsViewer;
private:
///\brief The basename of the shared pages.
std::string baseName;
@ -253,14 +255,15 @@ namespace IPC {
bool hasCounter;
};
class userConnection {
class userConnection{
public:
userConnection(char * _data);
userConnection(char *_data);
unsigned long getTrackId(size_t offset) const;
void setTrackId(size_t offset, unsigned long trackId) const;
unsigned long getKeynum(size_t offset) const;
void setKeynum(size_t offset, unsigned long keynum);
private:
char * data;
char *data;
};
}
}// namespace IPC

View file

@ -34,7 +34,7 @@ static const char *addrFam(int f){
}
/// Calls gai_strerror with the given argument, calling regular strerror on the global errno as needed
static const char * gai_strmagic(int errcode){
static const char *gai_strmagic(int errcode){
if (errcode == EAI_SYSTEM){
return strerror(errno);
}else{
@ -272,12 +272,10 @@ std::string Socket::resolveHostToBestExternalAddrGuess(const std::string &host,
/// Gets bound host and port for a socket and returns them by reference.
/// Returns true on success and false on failure.
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;
socklen_t len = sizeof(tmpaddr);
if (getsockname(fd, (sockaddr *)&tmpaddr, &len)){
return false;
}
if (getsockname(fd, (sockaddr *)&tmpaddr, &len)){return false;}
static char addrconv[INET6_ADDRSTRLEN];
if (tmpaddr.sin6_family == AF_INET6){
host = inet_ntop(AF_INET6, &(tmpaddr.sin6_addr), addrconv, INET6_ADDRSTRLEN);
@ -480,18 +478,18 @@ void Socket::Buffer::clear(){
}
void Socket::Connection::setBoundAddr(){
//If a bound address was set through environment (e.g. HTTPS output), restore it from there.
char * envbound = getenv("MIST_BOUND_ADDR");
// If a bound address was set through environment (e.g. HTTPS output), restore it from there.
char *envbound = getenv("MIST_BOUND_ADDR");
if (envbound){
boundaddr = envbound;
return;
}
//If we can't read the address, don't try
// If we can't read the address, don't try
if (!isTrueSocket){
boundaddr = "";
return;
}
//Otherwise, read from socket pointer. Works for both SSL and non-SSL sockets, and real sockets passed as fd's, but not for non-sockets (duh)
// Otherwise, read from socket pointer. Works for both SSL and non-SSL sockets, and real sockets passed as fd's, but not for non-sockets (duh)
uint32_t boundport = 0;
getSocketName(getSocket(), boundaddr, boundport);
}
@ -1184,9 +1182,7 @@ void Socket::Connection::setHost(std::string host){
hints.ai_next = NULL;
int s = getaddrinfo(host.c_str(), 0, &hints, &result);
if (s != 0){return;}
if (result){
memcpy(&remoteaddr, result->ai_addr, result->ai_addrlen);
}
if (result){memcpy(&remoteaddr, result->ai_addr, result->ai_addrlen);}
freeaddrinfo(result);
}

View file

@ -44,7 +44,7 @@ namespace Socket{
bool checkTrueSocket(int sock);
std::string resolveHostToBestExternalAddrGuess(const std::string &host, int family = AF_UNSPEC,
const std::string &hint = "");
bool getSocketName(int fd, std::string & host, uint32_t & port);
bool getSocketName(int fd, std::string &host, uint32_t &port);
/// A buffer made out of std::string objects that can be efficiently read from and written to.
class Buffer{
@ -91,6 +91,7 @@ namespace Socket{
bool iread(Buffer &buffer, int flags = 0); ///< Incremental write call that is compatible with Socket::Buffer.
bool iwrite(std::string &buffer); ///< Write call that is compatible with std::string.
void setBoundAddr();
protected:
std::string lastErr; ///< Stores last error, if any.
#ifdef SSL

View file

@ -1,6 +1,6 @@
#include <algorithm>
#include "defines.h"
#include "srtp.h"
#include <algorithm>
/* --------------------------------------- */
@ -8,34 +8,34 @@ static std::string srtp_status_to_string(uint32_t status);
/* --------------------------------------- */
SRTPReader::SRTPReader() {
memset((void*)&session, 0x00, sizeof(session));
memset((void*)&policy, 0x00, sizeof(policy));
SRTPReader::SRTPReader(){
memset((void *)&session, 0x00, sizeof(session));
memset((void *)&policy, 0x00, sizeof(policy));
}
/*
Before initializing the srtp library we shut it down first
because initializing the library twice results in an error.
*/
int SRTPReader::init(const std::string& cipher, const std::string& key, const std::string& salt) {
int SRTPReader::init(const std::string &cipher, const std::string &key, const std::string &salt){
int r = 0;
srtp_err_status_t status = srtp_err_status_ok;
srtp_profile_t profile;
memset((void*) &profile, 0x00, sizeof(profile));
memset((void *)&profile, 0x00, sizeof(profile));
/* validate input */
if (cipher.empty()) {
if (cipher.empty()){
FAIL_MSG("Given `cipher` is empty.");
r = -1;
goto error;
}
if (key.empty()) {
if (key.empty()){
FAIL_MSG("Given `key` is empty.");
r = -2;
goto error;
}
if (salt.empty()) {
if (salt.empty()){
FAIL_MSG("Given `salt` is empty.");
r = -3;
goto error;
@ -43,27 +43,25 @@ int SRTPReader::init(const std::string& cipher, const std::string& key, const st
/* re-initialize the srtp library. */
status = srtp_shutdown();
if (srtp_err_status_ok != status) {
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to shutdown the srtp lib %s", srtp_status_to_string(status).c_str());
r = -1;
goto error;
}
status = srtp_init();
if (srtp_err_status_ok != status) {
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to initialize the SRTP library. %s", srtp_status_to_string(status).c_str());
r = -2;
goto error;
}
/* 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;
}
else if ("SRTP_AES128_CM_SHA1_32" == cipher) {
}else if ("SRTP_AES128_CM_SHA1_32" == cipher){
profile = srtp_profile_aes128_cm_sha1_32;
}
else {
}else{
ERROR_MSG("Unsupported SRTP cipher used: %s.", cipher.c_str());
r = -2;
goto error;
@ -71,14 +69,14 @@ int SRTPReader::init(const std::string& cipher, const std::string& key, const st
/* set the crypto policy using the profile. */
status = srtp_crypto_policy_set_from_profile_for_rtp(&policy.rtp, profile);
if (srtp_err_status_ok != status) {
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to set the crypto policy for RTP for cipher %s.", cipher.c_str());
r = -3;
goto error;
}
status = srtp_crypto_policy_set_from_profile_for_rtcp(&policy.rtcp, profile);
if (srtp_err_status_ok != status) {
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to set the crypto policy for RTCP for cipher %s.", cipher.c_str());
r = -4;
goto error;
@ -87,7 +85,7 @@ int SRTPReader::init(const std::string& cipher, const std::string& key, const st
/* set the keying material. */
std::copy(key.begin(), key.end(), std::back_inserter(key_salt));
std::copy(salt.begin(), salt.end(), std::back_inserter(key_salt));
policy.key = (unsigned char*)&key_salt[0];
policy.key = (unsigned char *)&key_salt[0];
/* only unprotecting data for now, so using inbound; and some other settings. */
policy.ssrc.type = ssrc_any_inbound;
@ -96,62 +94,61 @@ int SRTPReader::init(const std::string& cipher, const std::string& key, const st
/* create the srtp session. */
status = srtp_create(&session, &policy);
if (srtp_err_status_ok != status) {
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to initialize our SRTP session. Status: %s. ", srtp_status_to_string(status).c_str());
r = -3;
goto error;
}
error:
if (r < 0) {
shutdown();
}
error:
if (r < 0){shutdown();}
return r;
}
int SRTPReader::shutdown() {
int SRTPReader::shutdown(){
int r = 0;
srtp_err_status_t status = srtp_dealloc(session);
if (srtp_err_status_ok != status) {
ERROR_MSG("Failed to cleanly shutdown the SRTP session. Status: %s", srtp_status_to_string(status).c_str());
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to cleanly shutdown the SRTP session. Status: %s",
srtp_status_to_string(status).c_str());
r -= 5;
}
memset((void*)&policy, 0x00, sizeof(policy));
memset((char*)&session, 0x00, sizeof(session));
memset((void *)&policy, 0x00, sizeof(policy));
memset((char *)&session, 0x00, sizeof(session));
return r;
}
/* --------------------------------------- */
int SRTPReader::unprotectRtp(uint8_t* data, int* nbytes) {
int SRTPReader::unprotectRtp(uint8_t *data, int *nbytes){
if (NULL == data) {
if (NULL == data){
ERROR_MSG("Cannot unprotect the given SRTP, because data is NULL.");
return -1;
}
if (NULL == nbytes) {
if (NULL == nbytes){
ERROR_MSG("Cannot unprotect the given SRTP, becuase nbytes is NULL.");
return -2;
}
if (0 == (*nbytes)) {
if (0 == (*nbytes)){
ERROR_MSG("Cannot unprotect the given SRTP, because nbytes is 0.");
return -3;
}
if (NULL == policy.key) {
if (NULL == policy.key){
ERROR_MSG("Cannot unprotect the SRTP packet, it seems we're not initialized.");
return -4;
}
srtp_err_status_t status = srtp_unprotect(session, data, nbytes);
if (srtp_err_status_ok != status) {
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to unprotect the given SRTP. %s.", srtp_status_to_string(status).c_str());
return -5;
}
@ -161,30 +158,30 @@ int SRTPReader::unprotectRtp(uint8_t* data, int* nbytes) {
return 0;
}
int SRTPReader::unprotectRtcp(uint8_t* data, int* nbytes) {
int SRTPReader::unprotectRtcp(uint8_t *data, int *nbytes){
if (NULL == data) {
if (NULL == data){
ERROR_MSG("Cannot unprotect the given SRTCP, because data is NULL.");
return -1;
}
if (NULL == nbytes) {
if (NULL == nbytes){
ERROR_MSG("Cannot unprotect the given SRTCP, becuase nbytes is NULL.");
return -2;
}
if (0 == (*nbytes)) {
if (0 == (*nbytes)){
ERROR_MSG("Cannot unprotect the given SRTCP, because nbytes is 0.");
return -3;
}
if (NULL == policy.key) {
if (NULL == policy.key){
ERROR_MSG("Cannot unprotect the SRTCP packet, it seems we're not initialized.");
return -4;
}
srtp_err_status_t status = srtp_unprotect_rtcp(session, data, nbytes);
if (srtp_err_status_ok != status) {
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to unprotect the given SRTCP. %s.", srtp_status_to_string(status).c_str());
return -5;
}
@ -194,34 +191,34 @@ int SRTPReader::unprotectRtcp(uint8_t* data, int* nbytes) {
/* --------------------------------------- */
SRTPWriter::SRTPWriter() {
memset((void*)&session, 0x00, sizeof(session));
memset((void*)&policy, 0x00, sizeof(policy));
SRTPWriter::SRTPWriter(){
memset((void *)&session, 0x00, sizeof(session));
memset((void *)&policy, 0x00, sizeof(policy));
}
/*
Before initializing the srtp library we shut it down first
because initializing the library twice results in an error.
*/
int SRTPWriter::init(const std::string& cipher, const std::string& key, const std::string& salt) {
int SRTPWriter::init(const std::string &cipher, const std::string &key, const std::string &salt){
int r = 0;
srtp_err_status_t status = srtp_err_status_ok;
srtp_profile_t profile;
memset((void*)&profile, 0x00, sizeof(profile));
memset((void *)&profile, 0x00, sizeof(profile));
/* validate input */
if (cipher.empty()) {
if (cipher.empty()){
FAIL_MSG("Given `cipher` is empty.");
r = -1;
goto error;
}
if (key.empty()) {
if (key.empty()){
FAIL_MSG("Given `key` is empty.");
r = -2;
goto error;
}
if (salt.empty()) {
if (salt.empty()){
FAIL_MSG("Given `salt` is empty.");
r = -3;
goto error;
@ -229,27 +226,25 @@ int SRTPWriter::init(const std::string& cipher, const std::string& key, const st
/* re-initialize the srtp library. */
status = srtp_shutdown();
if (srtp_err_status_ok != status) {
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to shutdown the srtp lib %s", srtp_status_to_string(status).c_str());
r = -1;
goto error;
}
status = srtp_init();
if (srtp_err_status_ok != status) {
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to initialize the SRTP library. %s", srtp_status_to_string(status).c_str());
r = -2;
goto error;
}
/* 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;
}
else if ("SRTP_AES128_CM_SHA1_32" == cipher) {
}else if ("SRTP_AES128_CM_SHA1_32" == cipher){
profile = srtp_profile_aes128_cm_sha1_32;
}
else {
}else{
ERROR_MSG("Unsupported SRTP cipher used: %s.", cipher.c_str());
r = -2;
goto error;
@ -257,14 +252,14 @@ int SRTPWriter::init(const std::string& cipher, const std::string& key, const st
/* set the crypto policy using the profile. */
status = srtp_crypto_policy_set_from_profile_for_rtp(&policy.rtp, profile);
if (srtp_err_status_ok != status) {
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to set the crypto policy for RTP for cipher %s.", cipher.c_str());
r = -3;
goto error;
}
status = srtp_crypto_policy_set_from_profile_for_rtcp(&policy.rtcp, profile);
if (srtp_err_status_ok != status) {
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to set the crypto policy for RTCP for cipher %s.", cipher.c_str());
r = -4;
goto error;
@ -273,7 +268,7 @@ int SRTPWriter::init(const std::string& cipher, const std::string& key, const st
/* set the keying material. */
std::copy(key.begin(), key.end(), std::back_inserter(key_salt));
std::copy(salt.begin(), salt.end(), std::back_inserter(key_salt));
policy.key = (unsigned char*)&key_salt[0];
policy.key = (unsigned char *)&key_salt[0];
/* only unprotecting data for now, so using inbound; and some other settings. */
policy.ssrc.type = ssrc_any_outbound;
@ -282,62 +277,61 @@ int SRTPWriter::init(const std::string& cipher, const std::string& key, const st
/* create the srtp session. */
status = srtp_create(&session, &policy);
if (srtp_err_status_ok != status) {
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to initialize our SRTP session. Status: %s. ", srtp_status_to_string(status).c_str());
r = -3;
goto error;
}
error:
if (r < 0) {
shutdown();
}
error:
if (r < 0){shutdown();}
return r;
}
int SRTPWriter::shutdown() {
int SRTPWriter::shutdown(){
int r = 0;
srtp_err_status_t status = srtp_dealloc(session);
if (srtp_err_status_ok != status) {
ERROR_MSG("Failed to cleanly shutdown the SRTP session. Status: %s", srtp_status_to_string(status).c_str());
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to cleanly shutdown the SRTP session. Status: %s",
srtp_status_to_string(status).c_str());
r -= 5;
}
memset((char*)&policy, 0x00, sizeof(policy));
memset((char*)&session, 0x00, sizeof(session));
memset((char *)&policy, 0x00, sizeof(policy));
memset((char *)&session, 0x00, sizeof(session));
return r;
}
/* --------------------------------------- */
int SRTPWriter::protectRtp(uint8_t* data, int* nbytes) {
int SRTPWriter::protectRtp(uint8_t *data, int *nbytes){
if (NULL == data) {
if (NULL == data){
ERROR_MSG("Cannot protect the RTP packet because given data is NULL.");
return -1;
}
if (NULL == nbytes) {
if (NULL == nbytes){
ERROR_MSG("Cannot protect the RTP packet because the given nbytes is NULL.");
return -2;
}
if ((*nbytes) <= 0) {
if ((*nbytes) <= 0){
ERROR_MSG("Cannot protect the RTP packet because the given nbytes has a value <= 0.");
return -3;
}
if (NULL == policy.key) {
if (NULL == policy.key){
ERROR_MSG("Cannot protect the RTP packet because we're not initialized.");
return -4;
}
srtp_err_status_t status = srtp_protect(session, (void*)data, nbytes);
if (srtp_err_status_ok != status) {
srtp_err_status_t status = srtp_protect(session, (void *)data, nbytes);
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to protect the RTP packet. %s.", srtp_status_to_string(status).c_str());
return -5;
}
@ -350,30 +344,30 @@ int SRTPWriter::protectRtp(uint8_t* data, int* nbytes) {
of bytes at the into which libsrtp can write the
authentication tag
*/
int SRTPWriter::protectRtcp(uint8_t* data, int* nbytes) {
int SRTPWriter::protectRtcp(uint8_t *data, int *nbytes){
if (NULL == data) {
if (NULL == data){
ERROR_MSG("Cannot protect the RTCP packet because given data is NULL.");
return -1;
}
if (NULL == nbytes) {
if (NULL == nbytes){
ERROR_MSG("Cannot protect the RTCP packet because nbytes is NULL.");
return -2;
}
if ((*nbytes) <= 0) {
if ((*nbytes) <= 0){
ERROR_MSG("Cannot protect the RTCP packet because *nbytes is <= 0.");
return -3;
}
if (NULL == policy.key) {
if (NULL == policy.key){
ERROR_MSG("Not initialized cannot protect the RTCP packet.");
return -4;
}
srtp_err_status_t status = srtp_protect_rtcp(session, (void*)data, nbytes);
if (srtp_err_status_ok != status) {
srtp_err_status_t status = srtp_protect_rtcp(session, (void *)data, nbytes);
if (srtp_err_status_ok != status){
ERROR_MSG("Failed to protect the RTCP packet. %s.", srtp_status_to_string(status).c_str());
return -3;
}
@ -381,41 +375,98 @@ int SRTPWriter::protectRtcp(uint8_t* data, int* nbytes) {
return 0;
}
/* --------------------------------------- */
static std::string srtp_status_to_string(uint32_t status) {
static std::string srtp_status_to_string(uint32_t status){
switch (status) {
case srtp_err_status_ok: { return "srtp_err_status_ok"; }
case srtp_err_status_fail: { return "srtp_err_status_fail"; }
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_dealloc_fail: { return "srtp_err_status_dealloc_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_auth_fail: { return "srtp_err_status_auth_fail"; }
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_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"; }
switch (status){
case srtp_err_status_ok:{
return "srtp_err_status_ok";
}
case srtp_err_status_fail:{
return "srtp_err_status_fail";
}
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_dealloc_fail:{
return "srtp_err_status_dealloc_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_auth_fail:{
return "srtp_err_status_auth_fail";
}
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_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
#include <srtp2/srtp.h>
#include <stdint.h>
#include <string>
#include <srtp2/srtp.h>
#define SRTP_PARSER_MASTER_KEY_LEN 16
#define SRTP_PARSER_MASTER_SALT_LEN 14
@ -10,13 +10,13 @@
/* --------------------------------------- */
class SRTPReader {
class SRTPReader{
public:
SRTPReader();
int init(const std::string& cipher, const std::string& key, const std::string& salt);
int init(const std::string &cipher, const std::string &key, const std::string &salt);
int shutdown();
int unprotectRtp(uint8_t* data, int* nbytes); /* `nbytes` should contain the number of bytes in `data`. On success `nbytes` will hold the number of bytes of the decoded RTP packet. */
int unprotectRtcp(uint8_t* data, int* nbytes); /* `nbytes` should contains the number of bytes in `data`. On success `nbytes` will hold the number of bytes the decoded RTCP packet. */
int unprotectRtp(uint8_t *data, int *nbytes); /* `nbytes` should contain the number of bytes in `data`. On success `nbytes` will hold the number of bytes of the decoded RTP packet. */
int unprotectRtcp(uint8_t *data, int *nbytes); /* `nbytes` should contains the number of bytes in `data`. On success `nbytes` will hold the number of bytes the decoded RTCP packet. */
private:
srtp_t session;
@ -26,13 +26,13 @@ private:
/* --------------------------------------- */
class SRTPWriter {
class SRTPWriter{
public:
SRTPWriter();
int init(const std::string& cipher, const std::string& key, const std::string& salt);
int init(const std::string &cipher, const std::string &key, const std::string &salt);
int shutdown();
int protectRtp(uint8_t* data, int* nbytes);
int protectRtcp(uint8_t* data, int* nbytes);
int protectRtp(uint8_t *data, int *nbytes);
int protectRtcp(uint8_t *data, int *nbytes);
private:
srtp_t session;

View file

@ -1,19 +1,19 @@
/// \file stream.cpp
/// Utilities for handling streams.
#include "stream.h"
#include "config.h"
#include "defines.h"
#include "dtsc.h"
#include "h265.h"
#include "http_parser.h"
#include "json.h"
#include "langcodes.h"
#include "mp4_generic.h"
#include "procs.h"
#include "shared_memory.h"
#include "socket.h"
#include "stream.h"
#include "triggers.h" //LTS
#include "h265.h"
#include "mp4_generic.h"
#include "langcodes.h"
#include "http_parser.h"
#include <semaphore.h>
#include <stdlib.h>
#include <sys/stat.h>
@ -41,7 +41,7 @@ static void replace(std::string &str, const std::string &from, const std::string
}
}
std::string Util::codecString(const std::string & codec, const std::string & initData){
std::string Util::codecString(const std::string &codec, const std::string &initData){
if (codec == "H264"){
std::stringstream r;
MP4::AVCC avccBox;
@ -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 & 0x80000000ul){mappedFlags += 0x00000001ul;}
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;
if (mInfo.constraint_flags[0]){
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.
void Util::streamVariables(std::string &str, const std::string &streamname,
const std::string &source){
void Util::streamVariables(std::string &str, const std::string &streamname, const std::string &source){
replace(str, "$source", source);
replace(str, "$datetime", "$year.$month.$day.$hour.$minute.$second");
replace(str, "$day", strftime_now("%d"));
@ -122,9 +125,9 @@ void Util::streamVariables(std::string &str, const std::string &streamname,
replace(str, "$hour", strftime_now("%H"));
replace(str, "$minute", strftime_now("%M"));
replace(str, "$second", strftime_now("%S"));
replace(str, "$wday", strftime_now("%u"));//weekday, 1-7, monday=1
replace(str, "$yday", strftime_now("%j"));//yearday, 001-366
replace(str, "$week", strftime_now("%V"));//week number, 01-53
replace(str, "$wday", strftime_now("%u")); // weekday, 1-7, monday=1
replace(str, "$yday", strftime_now("%j")); // yearday, 001-366
replace(str, "$week", strftime_now("%V")); // week number, 01-53
replace(str, "$stream", streamname);
if (streamname.find('+') != std::string::npos){
std::string strbase = streamname.substr(0, streamname.find('+'));
@ -213,7 +216,9 @@ JSON::Value Util::getStreamConfig(const std::string &streamname){
if (!Util::getGlobalConfig("defaultStream")){
WARN_MSG("Could not get stream '%s' config!", smp.c_str());
}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;
}
@ -235,14 +240,14 @@ JSON::Value Util::getGlobalConfig(const std::string &optionName){
switch (dataField.type & 0xF0){
case RAX_INT:
case RAX_UINT:
//Integer types, return JSON::Value integer
// Integer types, return JSON::Value integer
return JSON::Value(cfgData.getInt(dataField));
case RAX_RAW:
case RAX_STRING:
//String types, return JSON::Value string
// String types, return JSON::Value string
return JSON::Value(std::string(cfgData.getPointer(dataField), cfgData.getSize(optionName)));
default:
//Unimplemented types
// Unimplemented types
FAIL_MSG("Global configuration setting for '%s' is not an implemented datatype!", optionName.c_str());
return JSON::Value();
}
@ -447,7 +452,8 @@ bool Util::startInput(std::string streamname, std::string filename, bool forkFir
}
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);
}
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(),
tmp_input.getMember("name").asString().c_str(), source.c_str());
if (tmpFn.substr(0, front.size()) == front &&
tmpFn.substr(tmpFn.size() - back.size()) == back){
if (tmpFn.substr(0, front.size()) == front && tmpFn.substr(tmpFn.size() - back.size()) == back){
if (tmp_input.getMember("non-provider") && !isProvider){
noProviderNoPick = true;
continue;
@ -569,7 +574,7 @@ pid_t Util::startPush(const std::string &streamname, std::string &target){
return 0;
}
//Set original target string in environment
// Set original target string in environment
setenv("MST_ORIG_TARGET", target.c_str(), 1);
// The target can hold variables like current time etc
@ -617,11 +622,11 @@ pid_t Util::startPush(const std::string &streamname, std::string &target){
(char *)target.c_str(), (char *)NULL};
int stdErr = 2;
//Cache return value so we can do some cleaning before we return
// Cache return value so we can do some cleaning before we return
pid_t ret = Util::Procs::StartPiped(argv, 0, 0, &stdErr);
//Clean up environment
// Clean up environment
unsetenv("MST_ORIG_TARGET");
//Actually return the resulting PID
// Actually return the resulting PID
return ret;
}
@ -634,8 +639,8 @@ uint8_t Util::getStreamStatus(const std::string &streamname){
}
/// Checks if a given user agent is allowed according to the given exception.
bool Util::checkException(const JSON::Value & ex, const std::string & useragent){
//No user agent? Always allow everything.
bool Util::checkException(const JSON::Value &ex, const std::string &useragent){
// No user agent? Always allow everything.
if (!useragent.size()){return true;}
if (!ex.isArray() || !ex.size()){return true;}
bool ret = true;
@ -643,12 +648,24 @@ bool Util::checkException(const JSON::Value & ex, const std::string & useragent)
if (!e->isArray() || !e->size()){continue;}
bool setTo = false;
bool except = false;
//whitelist makes the return value true if any value is contained in the UA, blacklist makes it 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_except"){setTo = true; except = true;}
if ((*e)[0u].asStringRef() == "blacklist"){setTo = false; except = false;}
if ((*e)[0u].asStringRef() == "blacklist_except"){setTo = false; except = true;}
// whitelist makes the return value true if any value is contained in the UA, blacklist makes it
// 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_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){
ret = setTo;
continue;
@ -658,7 +675,7 @@ bool Util::checkException(const JSON::Value & ex, const std::string & useragent)
jsonForEachConst((*e)[1u], i){
if (useragent.find(i->asStringRef()) != std::string::npos){match = true;}
}
//set the (temp) return value if this was either a match in regular mode, or a non-match in except-mode.
// set the (temp) return value if this was either a match in regular mode, or a non-match in except-mode.
if (except != match){ret = setTo;}
}
return ret;
@ -679,9 +696,12 @@ DTSC::Scan Util::DTSCShmReader::getScan(){
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;
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){
// Comma-separated list, recurse.
std::stringstream ss(trackVal);
@ -695,17 +715,19 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
{
size_t trackNo = JSON::Value(trackVal).asInt();
if (trackVal == JSON::Value((uint64_t)trackNo).asString()){
//It's an integer number
// It's an integer number
if (!M.tracks.count(trackNo)){
INFO_MSG("Track %zd does not exist in stream, cannot select", trackNo);
return result;
}
const DTSC::Track & Trk = M.tracks.at(trackNo);
const DTSC::Track &Trk = M.tracks.at(trackNo);
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;
}
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);
return result;
}
@ -716,8 +738,10 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
// select all tracks of this type
std::set<size_t> validTracks = getSupportedTracks(M, capa);
for (std::set<size_t>::iterator it = validTracks.begin(); it != validTracks.end(); it++){
const DTSC::Track & Trk = M.tracks.at(*it);
if (!trackType.size() || Trk.type == trackType || Trk.codec == trackType){result.insert(*it);}
const DTSC::Track &Trk = M.tracks.at(*it);
if (!trackType.size() || Trk.type == trackType || Trk.codec == trackType){
result.insert(*it);
}
}
return result;
}
@ -727,7 +751,7 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
uint32_t currRate = 0;
std::set<size_t> validTracks = getSupportedTracks(M, capa);
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 (currRate < Trk.bps){
currVal = *it;
@ -744,7 +768,7 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
uint32_t currRate = 0xFFFFFFFFul;
std::set<size_t> validTracks = getSupportedTracks(M, capa);
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 (currRate > Trk.bps){
currVal = *it;
@ -755,22 +779,34 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
if (currVal != INVALID_TRACK_ID){result.insert(currVal);}
return result;
}
//less-than or greater-than track matching on bit rate or resolution
// less-than or greater-than track matching on bit rate or resolution
if (trackLow[0] == '<' || trackLow[0] == '>'){
unsigned int bpsVal;
uint64_t targetBps = 0;
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 (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 (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 (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){
targetBps >>= 3;
// select all tracks of this type that match the requirements
std::set<size_t> validTracks = getSupportedTracks(M, capa);
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 (trackLow[0] == '>' && Trk.bps > targetBps){result.insert(*it);}
if (trackLow[0] == '<' && Trk.bps < targetBps){result.insert(*it);}
@ -780,14 +816,14 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
}
unsigned int resX, resY;
uint64_t targetArea = 0;
if (sscanf(trackLow.c_str(), "<%ux%u", &resX, &resY) == 2){targetArea = resX*resY;}
if (sscanf(trackLow.c_str(), ">%ux%u", &resX, &resY) == 2){targetArea = resX*resY;}
if (sscanf(trackLow.c_str(), "<%ux%u", &resX, &resY) == 2){targetArea = resX * resY;}
if (sscanf(trackLow.c_str(), ">%ux%u", &resX, &resY) == 2){targetArea = resX * resY;}
if (targetArea){
std::set<size_t> validTracks = getSupportedTracks(M, capa);
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){
uint64_t trackArea = Trk.width*Trk.height;
uint64_t trackArea = Trk.width * Trk.height;
if (trackLow[0] == '>' && trackArea > targetArea){result.insert(*it);}
if (trackLow[0] == '<' && trackArea < targetArea){result.insert(*it);}
}
@ -795,13 +831,19 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
return result;
}
}
//approx bitrate matching
// approx bitrate matching
{
unsigned int bpsVal;
uint64_t targetBps = 0;
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 (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){
targetBps >>= 3;
// select nearest bit rate track of this type
@ -809,11 +851,12 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
uint32_t currDist = 0;
std::set<size_t> validTracks = getSupportedTracks(M, capa);
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 (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;
currDist = (Trk.bps >= targetBps)?(Trk.bps-targetBps):(targetBps-Trk.bps);
currDist = (Trk.bps >= targetBps) ? (Trk.bps - targetBps) : (targetBps - Trk.bps);
}
}
}
@ -821,12 +864,12 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
return result;
}
}
//audio channel matching
// audio channel matching
if (!trackType.size() || trackType == "audio"){
if (trackLow == "surround"){
std::set<size_t> validTracks = getSupportedTracks(M, capa);
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 (Trk.channels > 2){result.insert(*it);}
}
@ -838,11 +881,13 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
if (trackLow == "mono"){targetChannel = 1;}
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){
std::set<size_t> validTracks = getSupportedTracks(M, capa);
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 (Trk.channels == targetChannel){result.insert(*it);}
}
@ -850,7 +895,7 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
return result;
}
}
//approx resolution matching
// approx resolution matching
if (!trackType.size() || trackType == "video"){
if (trackLow == "highres" || trackLow == "bestres" || trackLow == "maxres"){
// select highest resolution track of this type
@ -858,9 +903,9 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
uint64_t currRes = 0;
std::set<size_t> validTracks = getSupportedTracks(M, capa);
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){
uint64_t trackRes = Trk.width*Trk.height;
uint64_t trackRes = Trk.width * Trk.height;
if (currRes < trackRes){
currVal = *it;
currRes = trackRes;
@ -876,9 +921,9 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
uint64_t currRes = 0xFFFFFFFFFFFFFFFFull;
std::set<size_t> validTracks = getSupportedTracks(M, capa);
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){
uint64_t trackRes = Trk.width*Trk.height;
uint64_t trackRes = Trk.width * Trk.height;
if (currRes > trackRes){
currVal = *it;
currRes = trackRes;
@ -894,15 +939,16 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
// select nearest resolution track of this type
size_t currVal = INVALID_TRACK_ID;
uint64_t currDist = 0;
uint64_t targetArea = resX*resY;
uint64_t targetArea = resX * resY;
std::set<size_t> validTracks = getSupportedTracks(M, capa);
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){
uint64_t trackArea = Trk.width*Trk.height;
if (currVal == INVALID_TRACK_ID || (trackArea >= targetArea && currDist > (trackArea-targetArea)) || (trackArea < targetArea && currDist > (targetArea-trackArea))){
uint64_t trackArea = Trk.width * Trk.height;
if (currVal == INVALID_TRACK_ID || (trackArea >= targetArea && currDist > (trackArea - targetArea)) ||
(trackArea < targetArea && currDist > (targetArea - trackArea))){
currVal = *it;
currDist = (trackArea >= targetArea)?(trackArea-targetArea):(targetArea-trackArea);
currDist = (trackArea >= targetArea) ? (trackArea - targetArea) : (targetArea - trackArea);
}
}
}
@ -910,13 +956,13 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
return result;
}
}
}//video track specific
}// video track specific
// attempt to do language/codec matching
// convert 2-character language codes into 3-character language codes
if (trackLow.size() == 2){trackLow = Encodings::ISO639::twoToThree(trackLow);}
std::set<size_t> validTracks = getSupportedTracks(M, capa);
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){
std::string codecLow = Trk.codec;
Util::stringToLower(codecLow);
@ -930,7 +976,7 @@ std::set<size_t> Util::findTracks(const DTSC::Meta &M, const JSON::Value &capa,
if (trackLow == "4k" && Trk.width == 3840 && Trk.height == 2160){result.insert(*it);}
if (trackLow == "5k" && Trk.width == 5120 && Trk.height == 2880){result.insert(*it);}
if (trackLow == "8k" && Trk.width == 7680 && Trk.height == 4320){result.insert(*it);}
//match "XxY" format
// match "XxY" format
if (sscanf(trackLow.c_str(), "%ux%u", &resX, &resY) == 2){
if (Trk.width == resX && Trk.height == resY){result.insert(*it);}
}
@ -952,10 +998,8 @@ std::set<size_t> Util::getSupportedTracks(const DTSC::Meta &M, const JSON::Value
const std::string &type, const std::string &UA){
std::set<size_t> validTracks;
for (std::map<unsigned int, DTSC::Track>::const_iterator it = M.tracks.begin(); it != M.tracks.end(); it++){
const DTSC::Track & Trk = it->second;
if (type != "" && type != Trk.type){
continue;
}
const DTSC::Track &Trk = it->second;
if (type != "" && type != Trk.type){continue;}
// Remove tracks for which we don't have codec support
if (capa.isMember("codecs")){
std::string codec = Trk.codec;
@ -1042,7 +1086,7 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri
toRemove.insert(*it);
continue;
}
//autoSeeking and target not in bounds? Drop it too.
// autoSeeking and target not in bounds? Drop it too.
if (seekTarget && M.tracks.at(*it).lastms < std::max(seekTarget, (uint64_t)6000lu) - 6000){
toRemove.insert(*it);
}
@ -1069,10 +1113,9 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri
/*LTS-START*/
if (!capa.isMember("codecs")){
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;
if (capa.isMember("exceptions") && capa["exceptions"].isObject() &&
capa["exceptions"].size()){
if (capa.isMember("exceptions") && capa["exceptions"].isObject() && capa["exceptions"].size()){
jsonForEachConst(capa["exceptions"], ex){
if (ex.key() == "codec:" + Trk.codec){
problems = !Util::checkException(*ex, UA);
@ -1080,7 +1123,7 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri
}
}
}
//if (!allowBFrames && M.hasBFrames(*trit)){problems = true;}
// if (!allowBFrames && M.hasBFrames(*trit)){problems = true;}
if (problems){continue;}
if (noSelAudio && Trk.type == "audio"){continue;}
if (noSelVideo && Trk.type == "video"){continue;}
@ -1091,7 +1134,6 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri
}
/*LTS-END*/
jsonForEachConst(capa["codecs"], it){
unsigned int selCounter = 0;
if ((*it).size() > 0){
@ -1111,7 +1153,7 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri
++shift;
}
for (std::set<size_t>::iterator itd = result.begin(); itd != result.end(); itd++){
const DTSC::Track & Trk = M.tracks.at(*itd);
const DTSC::Track &Trk = M.tracks.at(*itd);
if ((!byType && Trk.codec == strRef.substr(shift)) ||
(byType && Trk.type == strRef.substr(shift)) || strRef.substr(shift) == "*"){
// user-agent-check
@ -1166,7 +1208,7 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri
++shift;
}
for (std::set<size_t>::iterator itd = result.begin(); itd != result.end(); itd++){
const DTSC::Track & Trk = M.tracks.at(*itd);
const DTSC::Track &Trk = M.tracks.at(*itd);
if ((!byType && Trk.codec == strRef.substr(shift)) ||
(byType && Trk.type == strRef.substr(shift)) || strRef.substr(shift) == "*"){
// user-agent-check
@ -1203,7 +1245,7 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri
if (M.live){
for (std::set<size_t>::reverse_iterator trit = validTracks.rbegin();
trit != validTracks.rend(); trit++){
const DTSC::Track & Trk = M.tracks.at(*trit);
const DTSC::Track &Trk = M.tracks.at(*trit);
if ((!byType && Trk.codec == strRef.substr(shift)) ||
(byType && Trk.type == strRef.substr(shift)) || strRef.substr(shift) == "*"){
// user-agent-check
@ -1217,15 +1259,12 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri
}
}
}
//if (!allowBFrames && M.hasBFrames(*trit)){problems = true;}
// if (!allowBFrames && M.hasBFrames(*trit)){problems = true;}
if (problems){break;}
/*LTS-START*/
if (noSelAudio && Trk.type == "audio"){continue;}
if (noSelVideo && Trk.type == "video"){continue;}
if (noSelSub &&
(Trk.type == "subtitle" || Trk.codec == "subtitle")){
continue;
}
if (noSelSub && (Trk.type == "subtitle" || Trk.codec == "subtitle")){continue;}
/*LTS-END*/
result.insert(*trit);
found = true;
@ -1234,7 +1273,7 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri
}
}else{
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);
if ((!byType && Trk.codec == strRef.substr(shift)) ||
(byType && Trk.type == strRef.substr(shift)) || strRef.substr(shift) == "*"){
// user-agent-check
@ -1248,15 +1287,12 @@ std::set<size_t> Util::wouldSelect(const DTSC::Meta &M, const std::map<std::stri
}
}
}
//if (!allowBFrames && M.hasBFrames(*trit)){problems = true;}
// if (!allowBFrames && M.hasBFrames(*trit)){problems = true;}
if (problems){break;}
/*LTS-START*/
if (noSelAudio && Trk.type == "audio"){continue;}
if (noSelVideo && Trk.type == "video"){continue;}
if (noSelSub &&
(Trk.type == "subtitle" || Trk.type == "subtitle")){
continue;
}
if (noSelSub && (Trk.type == "subtitle" || Trk.type == "subtitle")){continue;}
/*LTS-END*/
result.insert(*trit);
found = true;

View file

@ -2,44 +2,52 @@
/// Utilities for handling streams.
#pragma once
#include <string>
#include "socket.h"
#include "json.h"
#include "dtsc.h"
#include "json.h"
#include "shared_memory.h"
#include "socket.h"
#include "util.h"
#include <string>
const JSON::Value empty;
namespace Util {
void streamVariables(std::string &str, const std::string & streamname, const std::string & source = "");
namespace Util{
void streamVariables(std::string &str, const std::string &streamname, const std::string &source = "");
std::string getTmpFolder();
void sanitizeName(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);
int startPush(const std::string & streamname, std::string & target);
JSON::Value getStreamConfig(const std::string & streamname);
JSON::Value getGlobalConfig(const std::string & optionName);
JSON::Value getInputBySource(const std::string & filename, bool isProvider = false);
DTSC::Meta getStreamMeta(const std::string & streamname);
uint8_t getStreamStatus(const std::string & streamname);
bool checkException(const JSON::Value & ex, const std::string & useragent);
std::string codecString(const std::string & codec, const std::string & initData = "");
void sanitizeName(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);
int startPush(const std::string &streamname, std::string &target);
JSON::Value getStreamConfig(const std::string &streamname);
JSON::Value getGlobalConfig(const std::string &optionName);
JSON::Value getInputBySource(const std::string &filename, bool isProvider = false);
DTSC::Meta getStreamMeta(const std::string &streamname);
uint8_t getStreamStatus(const std::string &streamname);
bool checkException(const JSON::Value &ex, const std::string &useragent);
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> 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> 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);
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> 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> 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{
public:
DTSCShmReader(const std::string &pageName);
DTSC::Scan getMember(const std::string &indice);
DTSC::Scan getScan();
private:
IPC::sharedPage rPage;
Util::RelAccX rAcc;
};
}
}// namespace Util

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
#pragma once
#include <stdint.h>
#include <netinet/in.h>
#include <vector>
#include <stdint.h>
#include <string>
#include <vector>
/* --------------------------------------- */
@ -60,7 +60,7 @@ std::string stun_family_type_to_string(uint8_t type);
std::string key: key to use for hmac
uint8_t* output: we write the sha1 into this buffer.
*/
int stun_compute_hmac_sha1(uint8_t* message, uint32_t nbytes, std::string key, uint8_t* output);
int stun_compute_hmac_sha1(uint8_t *message, uint32_t nbytes, std::string key, uint8_t *output);
/*
Compute the Message-Integrity of a stun message.
@ -70,7 +70,7 @@ int stun_compute_hmac_sha1(uint8_t* message, uint32_t nbytes, std::string key, u
std::string key: key to use for hmac
uint8_t* output: will be filled with the correct hmac-sha1 of that represents the integrity message value.
*/
int stun_compute_message_integrity(std::vector<uint8_t>& buffer, std::string key, uint8_t* output);
int stun_compute_message_integrity(std::vector<uint8_t> &buffer, std::string key, uint8_t *output);
/*
Compute the fingerprint value for the stun message.
@ -78,47 +78,47 @@ int stun_compute_message_integrity(std::vector<uint8_t>& buffer, std::string key
std::vector<uint8_t>& buffer: the buffer that contains a valid stun message.
uint32_t& result: will be set to the calculated crc value.
*/
int stun_compute_fingerprint(std::vector<uint8_t>& buffer, uint32_t& result);
int stun_compute_fingerprint(std::vector<uint8_t> &buffer, uint32_t &result);
/* --------------------------------------- */
/* https://tools.ietf.org/html/rfc5389#section-15.10 */
class StunAttribSoftware {
class StunAttribSoftware{
public:
char* value;
char *value;
};
class StunAttribFingerprint {
class StunAttribFingerprint{
public:
uint32_t value;
};
/* https://tools.ietf.org/html/rfc5389#section-15.4 */
class StunAttribMessageIntegrity {
class StunAttribMessageIntegrity{
public:
uint8_t* sha1;
uint8_t *sha1;
};
/* https://tools.ietf.org/html/rfc5245#section-19.1 */
class StunAttribPriority {
class StunAttribPriority{
public:
uint32_t value;
};
/* https://tools.ietf.org/html/rfc5245#section-19.1 */
class StunAttribIceControllling {
class StunAttribIceControllling{
public:
uint64_t tie_breaker;
};
/* https://tools.ietf.org/html/rfc3489#section-11.2.6 */
class StunAttribUsername {
class StunAttribUsername{
public:
char* value; /* Must use `length` member of attribute that indicates the number of valid bytes in the username. */
char *value; /* Must use `length` member of attribute that indicates the number of valid bytes in the username. */
};
/* https://tools.ietf.org/html/rfc5389#section-15.2 */
class StunAttribXorMappedAddress {
class StunAttribXorMappedAddress{
public:
uint8_t family;
uint16_t port;
@ -127,7 +127,7 @@ public:
/* --------------------------------------- */
class StunAttribute {
class StunAttribute{
public:
StunAttribute();
void print();
@ -135,7 +135,7 @@ public:
public:
uint16_t type;
uint16_t length;
union {
union{
StunAttribXorMappedAddress xor_address;
StunAttribUsername username;
StunAttribIceControllling ice_controlling;
@ -148,15 +148,15 @@ public:
/* --------------------------------------- */
class StunMessage {
class StunMessage{
public:
StunMessage();
void setType(uint16_t type);
void setTransactionId(uint32_t a, uint32_t b, uint32_t c);
void print();
void addAttribute(StunAttribute& attr);
void addAttribute(StunAttribute &attr);
void removeAttributes();
StunAttribute* getAttributeByType(uint16_t type);
StunAttribute *getAttributeByType(uint16_t type);
public:
uint16_t type;
@ -168,19 +168,19 @@ public:
/* --------------------------------------- */
class StunReader {
class StunReader{
public:
StunReader();
int parse(uint8_t* data, size_t nbytes, size_t& nparsed, StunMessage& msg); /* `nparsed` and `msg` are filled. */
int parse(uint8_t *data, size_t nbytes, size_t &nparsed, StunMessage &msg); /* `nparsed` and `msg` are filled. */
private:
int parseXorMappedAddress(StunAttribute& attr);
int parseUsername(StunAttribute& attr);
int parseIceControlling(StunAttribute& attr);
int parsePriority(StunAttribute& attr);
int parseSoftware(StunAttribute& attr);
int parseMessageIntegrity(StunAttribute& attr);
int parseFingerprint(StunAttribute& attr);
int parseXorMappedAddress(StunAttribute &attr);
int parseUsername(StunAttribute &attr);
int parseIceControlling(StunAttribute &attr);
int parsePriority(StunAttribute &attr);
int parseSoftware(StunAttribute &attr);
int parseMessageIntegrity(StunAttribute &attr);
int parseFingerprint(StunAttribute &attr);
uint8_t readU8();
uint16_t readU16();
@ -188,32 +188,35 @@ private:
uint64_t readU64();
private:
uint8_t* buffer_data;
uint8_t *buffer_data;
size_t buffer_size;
size_t read_dx;
};
/* --------------------------------------- */
class StunWriter {
class StunWriter{
public:
StunWriter();
/* 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();
/* write attributes */
int writeXorMappedAddress(sockaddr_in addr);
int writeXorMappedAddress(uint8_t family, uint16_t port, uint32_t ip);
int writeXorMappedAddress(uint8_t family, uint16_t port, const std::string& ip);
int writeUsername(const std::string& username);
int writeSoftware(const std::string& software);
int writeMessageIntegrity(const std::string& password); /* When using WebRtc this is the ice-upwd of the other agent. */
int writeXorMappedAddress(uint8_t family, uint16_t port, const std::string &ip);
int writeUsername(const std::string &username);
int writeSoftware(const std::string &software);
int writeMessageIntegrity(const std::string &password); /* When using WebRtc this is the ice-upwd of the other agent. */
int writeFingerprint(); /* Must be the last attribute in the message. When adding a fingerprint, make sure that it is added after the message-integrity (when you also use a message-integrity). */
/* get buffer */
uint8_t* getBufferPtr();
uint8_t *getBufferPtr();
size_t getBufferSize();
private:
@ -223,9 +226,9 @@ private:
void writeU64(uint64_t v);
void rewriteU16(size_t dx, uint16_t v);
void rewriteU32(size_t dx, uint32_t v);
void writeString(const std::string& str);
void writeString(const std::string &str);
void writePadding();
int convertIp4StringToInt(const std::string& ip, uint32_t& result);
int convertIp4StringToInt(const std::string &ip, uint32_t &result);
private:
std::vector<uint8_t> buffer;
@ -234,16 +237,14 @@ private:
/* --------------------------------------- */
inline uint8_t* StunWriter::getBufferPtr() {
inline uint8_t *StunWriter::getBufferPtr(){
if (0 == buffer.size()) {
return NULL;
}
if (0 == buffer.size()){return NULL;}
return &buffer[0];
}
inline size_t StunWriter::getBufferSize() {
inline size_t StunWriter::getBufferSize(){
return buffer.size();
}

View file

@ -1,38 +1,35 @@
#include "subtitles.h"
#include "bitfields.h"
#include "subtitles.h"
#include "defines.h"
namespace Subtitle {
namespace Subtitle{
Packet getSubtitle(DTSC::Packet packet, DTSC::Meta meta) {
char * tmp = 0;
Packet getSubtitle(DTSC::Packet packet, DTSC::Meta meta){
char *tmp = 0;
uint16_t length = 0;
unsigned int len;
Packet output;
long int trackId= packet.getTrackId();
if(meta.tracks[trackId].codec != "TTXT" && meta.tracks[trackId].codec != "SRT") {
//no subtitle track
long int trackId = packet.getTrackId();
if (meta.tracks[trackId].codec != "TTXT" && meta.tracks[trackId].codec != "SRT"){
// no subtitle track
return output;
}
if(packet.hasMember("duration")) {
if (packet.hasMember("duration")){
output.duration = packet.getInt("duration");
} else {
//get parts from meta
//calculate duration
}else{
// get parts from meta
// calculate duration
}
packet.getString("data", output.subtitle);
if(meta.tracks[trackId].codec == "TTXT") {
if (meta.tracks[trackId].codec == "TTXT"){
unsigned short size = Bit::btohs(output.subtitle.c_str());
output.subtitle = output.subtitle.substr(2,size);
output.subtitle = output.subtitle.substr(2, size);
}
return output;
}
}
}// namespace Subtitle

View file

@ -1,15 +1,14 @@
#pragma once
#include <string>
#include "dtsc.h"
#include <string>
namespace Subtitle {
namespace Subtitle{
struct Packet {
struct Packet{
std::string subtitle;
uint64_t duration;
};
Packet getSubtitle(DTSC::Packet packet, DTSC::Meta meta);
}
}// namespace Subtitle

View file

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

View file

@ -1,27 +1,27 @@
#pragma once
#include<sys/types.h>
#include<stdint.h>
#include<string>
#include <stdint.h>
#include <string>
#include <sys/types.h>
namespace theora {
namespace theora{
bool isHeader(const char * newData, unsigned int length);
class header {
bool isHeader(const char *newData, unsigned int length);
class header{
public:
~header();
header(char * newData, unsigned int length); // if managed is true, this class manages the data pointer
header(char *newData, unsigned int length); // if managed is true, this class manages the data pointer
int getHeaderType();
char getVMAJ();
char getVMIN();
char getVREV();
short getFMBW();
short getFMBH();
long unsigned int getPICW();//movie width
long unsigned int getPICH();//movie height
long unsigned int getPICW(); // movie width
long unsigned int getPICH(); // movie height
char getPICX();
char getPICY();
long unsigned int getFRN();//frame rate numerator
long unsigned int getFRD();//frame rate denominator
long unsigned int getFRN(); // frame rate numerator
long unsigned int getFRD(); // frame rate denominator
long unsigned int getPARN();
long unsigned int getPARD();
char getCS();
@ -33,24 +33,25 @@ namespace theora {
long unsigned int getNComments();
std::string getUserComment(size_t index);
char getLFLIMS(size_t index);
std::string toPrettyString(size_t indent = 0); //update this, it should check (header) type and output relevant stuff only.
//long long unsigned int parseGranuleUpper(long long unsigned int granPos);
//long long unsigned int parseGranuleLower(long long unsigned int granPos);
std::string toPrettyString(size_t indent = 0); // update this, it should check (header) type and output relevant stuff only.
// long long unsigned int parseGranuleUpper(long long unsigned int granPos);
// long long unsigned int parseGranuleLower(long long unsigned int granPos);
///\todo put this back in pravate
unsigned int datasize;
bool isHeader();
char getFTYPE();//for frames
char getFTYPE(); // for frames
protected:
uint32_t getInt32(size_t index);
uint32_t getInt24(size_t index);
uint16_t getInt16(size_t index);
uint32_t commentLen(size_t index);
private:
char * data;
char *data;
bool checkDataSize(unsigned int size);
};
/*
class frame{ // we don't need this. I hope.
class frame{// we don't need this. I hope.
public:
frame();
~frame();
@ -64,5 +65,4 @@ namespace theora {
unsigned int datasize;
bool checkDataSize(unsigned int size);
};*/
}
}// namespace theora

View file

@ -2,18 +2,18 @@
/// Utilities for handling time and timestamps.
#include "timing.h"
#include <sys/time.h>//for gettimeofday
#include <time.h>//for time and nanosleep
#include <cstring>
#include <cstdio>
#include <cstring>
#include <sys/time.h> //for gettimeofday
#include <time.h> //for time and nanosleep
//emulate clock_gettime() for OSX compatibility
// emulate clock_gettime() for OSX compatibility
#if defined(__APPLE__) || defined(__MACH__)
#include <mach/clock.h>
#include <mach/mach.h>
#define CLOCK_REALTIME CALENDAR_CLOCK
#define CLOCK_MONOTONIC SYSTEM_CLOCK
void clock_gettime(int ign, struct timespec * ts) {
void clock_gettime(int ign, struct timespec *ts){
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), ign, &cclock);
@ -30,16 +30,12 @@ void clock_gettime(int ign, struct timespec * ts) {
/// 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.
void Util::wait(int64_t ms){
if (ms < 0) {
return;
}
if (ms > 600000) {
ms = 600000;
}
if (ms < 0){return;}
if (ms > 600000){ms = 600000;}
uint64_t start = getMS();
uint64_t now = start;
while (now < start+ms){
sleep(start+ms-now);
while (now < start + ms){
sleep(start + ms - now);
now = getMS();
}
}
@ -49,39 +45,35 @@ void Util::wait(int64_t ms){
/// Will not sleep for longer than 100 seconds (100000ms).
/// Can be interrupted early by a signal, no guarantee of minimum sleep time.
/// Can be slightly off depending on OS accuracy.
void Util::sleep(int64_t ms) {
if (ms < 0) {
return;
}
if (ms > 100000) {
ms = 100000;
}
void Util::sleep(int64_t ms){
if (ms < 0){return;}
if (ms > 100000){ms = 100000;}
struct timespec T;
T.tv_sec = ms / 1000;
T.tv_nsec = 1000000 * (ms % 1000);
nanosleep(&T, 0);
}
uint64_t Util::getNTP() {
uint64_t Util::getNTP(){
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
return ((uint64_t)(t.tv_sec + 2208988800ull) << 32) + (t.tv_nsec * 4.2949);
}
/// Gets the current time in milliseconds.
uint64_t Util::getMS() {
uint64_t Util::getMS(){
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
return (uint64_t)t.tv_sec * 1000 + t.tv_nsec / 1000000;
}
uint64_t Util::bootSecs() {
uint64_t Util::bootSecs(){
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
return t.tv_sec;
}
uint64_t Util::bootMS() {
uint64_t Util::bootMS(){
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
return ((uint64_t)t.tv_sec) * 1000 + t.tv_nsec / 1000000;
@ -94,30 +86,31 @@ uint64_t Util::unixMS(){
}
/// Gets the current time in microseconds.
uint64_t Util::getMicros() {
uint64_t Util::getMicros(){
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
return (uint64_t)t.tv_sec * 1000000 + t.tv_nsec / 1000;
}
/// Gets the time difference in microseconds.
uint64_t Util::getMicros(uint64_t previous) {
uint64_t Util::getMicros(uint64_t previous){
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
return (uint64_t)t.tv_sec * 1000000 + t.tv_nsec / 1000 - previous;
}
/// Gets the amount of seconds since 01/01/1970.
uint64_t Util::epoch() {
uint64_t Util::epoch(){
return time(0);
}
std::string Util::getUTCString(uint64_t epoch){
if (!epoch){epoch = time(0);}
time_t rawtime = epoch;
struct tm * ptm;
struct tm *ptm;
ptm = gmtime(&rawtime);
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);
}

View file

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

View file

@ -21,32 +21,31 @@ freely, subject to the following restrictions:
distribution.
*/
#include <exception>
#include "tinythread.h"
#include <exception>
#if defined(_TTHREAD_POSIX_)
#include <unistd.h>
#include <map>
#include <unistd.h>
#elif defined(_TTHREAD_WIN32_)
#include <process.h>
#endif
namespace tthread{
namespace tthread {
//------------------------------------------------------------------------------
// condition_variable
//------------------------------------------------------------------------------
// NOTE 1: The Win32 implementation of the condition_variable class is based on
// the corresponding implementation in GLFW, which in turn is based on a
// description by Douglas C. Schmidt and Irfan Pyarali:
// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
//
// NOTE 2: Windows Vista actually has native support for condition variables
// (InitializeConditionVariable, WakeConditionVariable, etc), but we want to
// be portable with pre-Vista Windows versions, so TinyThread++ does not use
// Vista condition variables.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// condition_variable
//------------------------------------------------------------------------------
// NOTE 1: The Win32 implementation of the condition_variable class is based on
// the corresponding implementation in GLFW, which in turn is based on a
// description by Douglas C. Schmidt and Irfan Pyarali:
// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
//
// NOTE 2: Windows Vista actually has native support for condition variables
// (InitializeConditionVariable, WakeConditionVariable, etc), but we want to
// be portable with pre-Vista Windows versions, so TinyThread++ does not use
// Vista condition variables.
//------------------------------------------------------------------------------
#if defined(_TTHREAD_WIN32_)
#define _CONDITION_EVENT_ONE 0
@ -54,7 +53,7 @@ namespace tthread {
#endif
#if defined(_TTHREAD_WIN32_)
condition_variable::condition_variable() : mWaitersCount(0) {
condition_variable::condition_variable() : mWaitersCount(0){
mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL);
mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL);
InitializeCriticalSection(&mWaitersCountLock);
@ -62,7 +61,7 @@ namespace tthread {
#endif
#if defined(_TTHREAD_WIN32_)
condition_variable::~condition_variable() {
condition_variable::~condition_variable(){
CloseHandle(mEvents[_CONDITION_EVENT_ONE]);
CloseHandle(mEvents[_CONDITION_EVENT_ALL]);
DeleteCriticalSection(&mWaitersCountLock);
@ -70,104 +69,97 @@ namespace tthread {
#endif
#if defined(_TTHREAD_WIN32_)
void condition_variable::_wait() {
void condition_variable::_wait(){
// Wait for either event to become signaled due to notify_one() or
// notify_all() being called
int result = WaitForMultipleObjects(2, mEvents, FALSE, INFINITE);
// Check if we are the last waiter
EnterCriticalSection(&mWaitersCountLock);
-- mWaitersCount;
bool lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) &&
(mWaitersCount == 0);
--mWaitersCount;
bool lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) && (mWaitersCount == 0);
LeaveCriticalSection(&mWaitersCountLock);
// If we are the last waiter to be notified to stop waiting, reset the event
if (lastWaiter)
ResetEvent(mEvents[_CONDITION_EVENT_ALL]);
if (lastWaiter) ResetEvent(mEvents[_CONDITION_EVENT_ALL]);
}
#endif
#if defined(_TTHREAD_WIN32_)
void condition_variable::notify_one() {
void condition_variable::notify_one(){
// Are there any waiters?
EnterCriticalSection(&mWaitersCountLock);
bool haveWaiters = (mWaitersCount > 0);
LeaveCriticalSection(&mWaitersCountLock);
// If we have any waiting threads, send them a signal
if (haveWaiters)
SetEvent(mEvents[_CONDITION_EVENT_ONE]);
if (haveWaiters) SetEvent(mEvents[_CONDITION_EVENT_ONE]);
}
#endif
#if defined(_TTHREAD_WIN32_)
void condition_variable::notify_all() {
void condition_variable::notify_all(){
// Are there any waiters?
EnterCriticalSection(&mWaitersCountLock);
bool haveWaiters = (mWaitersCount > 0);
LeaveCriticalSection(&mWaitersCountLock);
// If we have any waiting threads, send them a signal
if (haveWaiters)
SetEvent(mEvents[_CONDITION_EVENT_ALL]);
if (haveWaiters) SetEvent(mEvents[_CONDITION_EVENT_ALL]);
}
#endif
//------------------------------------------------------------------------------
// POSIX pthread_t to unique thread::id mapping logic.
// Note: Here we use a global thread safe std::map to convert instances of
// pthread_t to small thread identifier numbers (unique within one process).
// This method should be portable across different POSIX implementations.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// POSIX pthread_t to unique thread::id mapping logic.
// Note: Here we use a global thread safe std::map to convert instances of
// pthread_t to small thread identifier numbers (unique within one process).
// This method should be portable across different POSIX implementations.
//------------------------------------------------------------------------------
#if defined(_TTHREAD_POSIX_)
static thread::id _pthread_t_to_ID(const pthread_t & aHandle) {
static thread::id _pthread_t_to_ID(const pthread_t &aHandle){
static mutex idMapLock;
static std::map<pthread_t, unsigned long int> idMap;
static unsigned long int idCount(1);
lock_guard<mutex> guard(idMapLock);
if (idMap.find(aHandle) == idMap.end())
idMap[aHandle] = idCount ++;
if (idMap.find(aHandle) == idMap.end()) idMap[aHandle] = idCount++;
return thread::id(idMap[aHandle]);
}
#endif // _TTHREAD_POSIX_
//------------------------------------------------------------------------------
// thread
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// thread
//------------------------------------------------------------------------------
/// Information to pass to the new thread (what to run).
struct _thread_start_info {
/// Information to pass to the new thread (what to run).
struct _thread_start_info{
void (*mFunction)(void *); ///< Pointer to the function to be executed.
void * mArg; ///< Function argument for the thread function.
thread * mThread; ///< Pointer to the thread object.
void *mArg; ///< Function argument for the thread function.
thread *mThread; ///< Pointer to the thread object.
};
// Thread wrapper function.
#if defined(_TTHREAD_WIN32_)
unsigned WINAPI thread::wrapper_function(void * aArg)
unsigned WINAPI thread::wrapper_function(void *aArg)
#elif defined(_TTHREAD_POSIX_)
void * thread::wrapper_function(void * aArg)
void *thread::wrapper_function(void *aArg)
#endif
{
// Get thread startup information
_thread_start_info * ti = (_thread_start_info *) aArg;
_thread_start_info *ti = (_thread_start_info *)aArg;
//try {
// try{
// Call the actual client thread function
ti->mFunction(ti->mArg);
//} catch (...) {
//}catch (...){
// Uncaught exceptions will terminate the application (default behavior
// according to C++11)
//std::terminate();
// std::terminate();
//}
// The thread is no longer executing
if (ti->mThread) {
if (ti->mThread){
lock_guard<mutex> guard(ti->mThread->mDataMutex);
if (ti->mThread){
ti->mThread->mNotAThread = true;
@ -181,13 +173,13 @@ namespace tthread {
return 0;
}
thread::thread(void (*aFunction)(void *), void * aArg) {
thread::thread(void (*aFunction)(void *), void *aArg){
// Serialize access to this thread structure
lock_guard<mutex> guard(mDataMutex);
// Fill out the thread startup information (passed to the thread wrapper,
// which will eventually free it)
_thread_start_info * ti = new _thread_start_info;
_thread_start_info *ti = new _thread_start_info;
ti_copy = ti;
ti->mFunction = aFunction;
ti->mArg = aArg;
@ -198,30 +190,26 @@ namespace tthread {
// Create the thread
#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_)
if (pthread_create(&mHandle, NULL, wrapper_function, (void *) ti) != 0)
mHandle = 0;
if (pthread_create(&mHandle, NULL, wrapper_function, (void *)ti) != 0) mHandle = 0;
#endif
// Did we fail to create the thread?
if (!mHandle) {
if (!mHandle){
mNotAThread = true;
ti_copy = 0;
delete ti;
}
}
thread::~thread() {
if (ti_copy) {
((_thread_start_info *)ti_copy)->mThread = 0;
}
if (joinable())
std::terminate();
thread::~thread(){
if (ti_copy){((_thread_start_info *)ti_copy)->mThread = 0;}
if (joinable()) std::terminate();
}
void thread::join() {
if (joinable()) {
void thread::join(){
if (joinable()){
#if defined(_TTHREAD_WIN32_)
WaitForSingleObject(mHandle, INFINITE);
CloseHandle(mHandle);
@ -231,16 +219,16 @@ namespace tthread {
}
}
bool thread::joinable() const {
bool thread::joinable() const{
mDataMutex.lock();
bool result = !mNotAThread;
mDataMutex.unlock();
return result;
}
void thread::detach() {
void thread::detach(){
mDataMutex.lock();
if (!mNotAThread) {
if (!mNotAThread){
#if defined(_TTHREAD_WIN32_)
CloseHandle(mHandle);
#elif defined(_TTHREAD_POSIX_)
@ -251,25 +239,24 @@ namespace tthread {
mDataMutex.unlock();
}
thread::id thread::get_id() const {
if (!joinable())
return id();
thread::id thread::get_id() const{
if (!joinable()) return id();
#if defined(_TTHREAD_WIN32_)
return id((unsigned long int) mWin32ThreadID);
return id((unsigned long int)mWin32ThreadID);
#elif defined(_TTHREAD_POSIX_)
return _pthread_t_to_ID(mHandle);
#endif
}
unsigned thread::hardware_concurrency() {
unsigned thread::hardware_concurrency(){
#if defined(_TTHREAD_WIN32_)
SYSTEM_INFO si;
GetSystemInfo(&si);
return (int) si.dwNumberOfProcessors;
return (int)si.dwNumberOfProcessors;
#elif defined(_SC_NPROCESSORS_ONLN)
return (int) sysconf(_SC_NPROCESSORS_ONLN);
return (int)sysconf(_SC_NPROCESSORS_ONLN);
#elif defined(_SC_NPROC_ONLN)
return (int) sysconf(_SC_NPROC_ONLN);
return (int)sysconf(_SC_NPROC_ONLN);
#else
// The standard requires this function to return zero if the number of
// hardware cores could not be determined.
@ -277,17 +264,16 @@ namespace tthread {
#endif
}
//------------------------------------------------------------------------------
// this_thread
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// this_thread
//------------------------------------------------------------------------------
thread::id this_thread::get_id() {
thread::id this_thread::get_id(){
#if defined(_TTHREAD_WIN32_)
return thread::id((unsigned long int) GetCurrentThreadId());
return thread::id((unsigned long int)GetCurrentThreadId());
#elif defined(_TTHREAD_POSIX_)
return _pthread_t_to_ID(pthread_self());
#endif
}
}
}// namespace tthread

View file

@ -78,8 +78,8 @@ freely, subject to the following restrictions:
#endif
#else
#include <pthread.h>
#include <signal.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>
#endif
@ -106,12 +106,12 @@ freely, subject to the following restrictions:
// Macro for disabling assignments of objects.
#ifdef _TTHREAD_CPP11_PARTIAL_
#define _TTHREAD_DISABLE_ASSIGNMENT(name) \
name(const name&) = delete; \
name& operator=(const name&) = delete;
name(const name &) = delete; \
name &operator=(const name &) = delete;
#else
#define _TTHREAD_DISABLE_ASSIGNMENT(name) \
name(const name&); \
name& operator=(const name&);
name(const name &); \
name &operator=(const name &);
#endif
/// @def thread_local
@ -143,20 +143,19 @@ freely, subject to the following restrictions:
#endif
#endif
/// Main name space for TinyThread++.
/// 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
/// the std::mutex class.
namespace tthread {
namespace tthread{
/// Mutex class.
/// This is a mutual exclusion object for synchronizing access to shared
/// memory areas for several threads. The mutex is non-recursive (i.e. a
/// program may deadlock if the thread that owns a mutex object calls lock()
/// on that object).
/// @see recursive_mutex
class mutex {
/// Mutex class.
/// This is a mutual exclusion object for synchronizing access to shared
/// memory areas for several threads. The mutex is non-recursive (i.e. a
/// program may deadlock if the thread that owns a mutex object calls lock()
/// on that object).
/// @see recursive_mutex
class mutex{
public:
/// Constructor.
mutex()
@ -172,7 +171,7 @@ namespace tthread {
}
/// Destructor.
~mutex() {
~mutex(){
#if defined(_TTHREAD_WIN32_)
DeleteCriticalSection(&mHandle);
#else
@ -184,7 +183,7 @@ namespace tthread {
/// The method will block the calling thread until a lock on the mutex can
/// be obtained. The mutex remains locked until @c unlock() is called.
/// @see lock_guard
inline void lock() {
inline void lock(){
#if defined(_TTHREAD_WIN32_)
EnterCriticalSection(&mHandle);
while (mAlreadyLocked) Sleep(1000); // Simulate deadlock...
@ -199,10 +198,10 @@ namespace tthread {
/// return immediately (non-blocking).
/// @return @c true if the lock was acquired, or @c false if the lock could
/// not be acquired.
inline bool try_lock() {
inline bool try_lock(){
#if defined(_TTHREAD_WIN32_)
bool ret = (TryEnterCriticalSection(&mHandle) ? true : false);
if (ret && mAlreadyLocked) {
if (ret && mAlreadyLocked){
LeaveCriticalSection(&mHandle);
ret = false;
}
@ -215,7 +214,7 @@ namespace tthread {
/// Unlock the mutex.
/// If any threads are waiting for the lock on this mutex, one of them will
/// be unblocked.
inline void unlock() {
inline void unlock(){
#if defined(_TTHREAD_WIN32_)
mAlreadyLocked = false;
LeaveCriticalSection(&mHandle);
@ -237,16 +236,16 @@ namespace tthread {
friend class condition_variable;
};
/// Recursive mutex class.
/// This is a mutual exclusion object for synchronizing access to shared
/// memory areas for several threads. The mutex is recursive (i.e. a thread
/// may lock the mutex several times, as long as it unlocks the mutex the same
/// number of times).
/// @see mutex
class recursive_mutex {
/// Recursive mutex class.
/// This is a mutual exclusion object for synchronizing access to shared
/// memory areas for several threads. The mutex is recursive (i.e. a thread
/// may lock the mutex several times, as long as it unlocks the mutex the same
/// number of times).
/// @see mutex
class recursive_mutex{
public:
/// Constructor.
recursive_mutex() {
recursive_mutex(){
#if defined(_TTHREAD_WIN32_)
InitializeCriticalSection(&mHandle);
#else
@ -258,7 +257,7 @@ namespace tthread {
}
/// Destructor.
~recursive_mutex() {
~recursive_mutex(){
#if defined(_TTHREAD_WIN32_)
DeleteCriticalSection(&mHandle);
#else
@ -270,7 +269,7 @@ namespace tthread {
/// The method will block the calling thread until a lock on the mutex can
/// be obtained. The mutex remains locked until @c unlock() is called.
/// @see lock_guard
inline void lock() {
inline void lock(){
#if defined(_TTHREAD_WIN32_)
EnterCriticalSection(&mHandle);
#else
@ -283,7 +282,7 @@ namespace tthread {
/// return immediately (non-blocking).
/// @return @c true if the lock was acquired, or @c false if the lock could
/// not be acquired.
inline bool try_lock() {
inline bool try_lock(){
#if defined(_TTHREAD_WIN32_)
return TryEnterCriticalSection(&mHandle) ? true : false;
#else
@ -294,7 +293,7 @@ namespace tthread {
/// Unlock the mutex.
/// If any threads are waiting for the lock on this mutex, one of them will
/// be unblocked.
inline void unlock() {
inline void unlock(){
#if defined(_TTHREAD_WIN32_)
LeaveCriticalSection(&mHandle);
#else
@ -314,87 +313,81 @@ namespace tthread {
friend class condition_variable;
};
/// Lock guard class.
/// The constructor locks the mutex, and the destructor unlocks the mutex, so
/// the mutex will automatically be unlocked when the lock guard goes out of
/// scope. Example usage:
/// @code
/// mutex m;
/// int counter;
///
/// void increment()
/// {
/// lock_guard<mutex> guard(m);
/// ++ counter;
/// }
/// @endcode
/// Lock guard class.
/// The constructor locks the mutex, and the destructor unlocks the mutex, so
/// the mutex will automatically be unlocked when the lock guard goes out of
/// scope. Example usage:
/// @code
/// mutex m;
/// int counter;
///
/// void increment()
///{
/// lock_guard<mutex> guard(m);
/// ++ counter;
///}
/// @endcode
template <class T>
class lock_guard {
template <class T> class lock_guard{
public:
typedef T mutex_type;
lock_guard() : mMutex(0) {}
lock_guard() : mMutex(0){}
/// The constructor locks the mutex.
explicit lock_guard(mutex_type & aMutex) {
explicit lock_guard(mutex_type &aMutex){
mMutex = &aMutex;
mMutex->lock();
}
/// The destructor unlocks the mutex.
~lock_guard() {
if (mMutex)
mMutex->unlock();
~lock_guard(){
if (mMutex) mMutex->unlock();
}
private:
mutex_type * mMutex;
mutex_type *mMutex;
};
/// Condition variable class.
/// This is a signalling object for synchronizing the execution flow for
/// several threads. Example usage:
/// @code
/// // Shared data and associated mutex and condition variable objects
/// int count;
/// mutex m;
/// condition_variable cond;
///
/// // Wait for the counter to reach a certain number
/// void wait_counter(int targetCount)
/// {
/// lock_guard<mutex> guard(m);
/// while(count < targetCount)
/// cond.wait(m);
/// }
///
/// // Increment the counter, and notify waiting threads
/// void increment()
/// {
/// lock_guard<mutex> guard(m);
/// ++ count;
/// cond.notify_all();
/// }
/// @endcode
class condition_variable {
/// Condition variable class.
/// This is a signalling object for synchronizing the execution flow for
/// several threads. Example usage:
/// @code
/// // Shared data and associated mutex and condition variable objects
/// int count;
/// mutex m;
/// condition_variable cond;
///
/// // Wait for the counter to reach a certain number
/// void wait_counter(int targetCount)
///{
/// lock_guard<mutex> guard(m);
/// while(count < targetCount)
/// cond.wait(m);
///}
///
/// // Increment the counter, and notify waiting threads
/// void increment()
///{
/// lock_guard<mutex> guard(m);
/// ++ count;
/// cond.notify_all();
///}
/// @endcode
class condition_variable{
public:
/// Constructor.
#if defined(_TTHREAD_WIN32_)
condition_variable();
#else
condition_variable() {
pthread_cond_init(&mHandle, NULL);
}
condition_variable(){pthread_cond_init(&mHandle, NULL);}
#endif
/// Destructor.
#if defined(_TTHREAD_WIN32_)
~condition_variable();
#else
~condition_variable() {
pthread_cond_destroy(&mHandle);
}
~condition_variable(){pthread_cond_destroy(&mHandle);}
#endif
/// Wait for the condition.
@ -402,12 +395,11 @@ namespace tthread {
/// 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
/// starts, an locked again as soon as the wait operation is finished.
template <class _mutexT>
inline void wait(_mutexT & aMutex) {
template <class _mutexT> inline void wait(_mutexT &aMutex){
#if defined(_TTHREAD_WIN32_)
// Increment number of waiters
EnterCriticalSection(&mWaitersCountLock);
++ mWaitersCount;
++mWaitersCount;
LeaveCriticalSection(&mWaitersCountLock);
// Release the mutex while waiting for the condition (will decrease
@ -428,9 +420,7 @@ namespace tthread {
#if defined(_TTHREAD_WIN32_)
void notify_one();
#else
inline void notify_one() {
pthread_cond_signal(&mHandle);
}
inline void notify_one(){pthread_cond_signal(&mHandle);}
#endif
/// Notify all threads that are waiting for the condition.
@ -441,9 +431,7 @@ namespace tthread {
#if defined(_TTHREAD_WIN32_)
void notify_all();
#else
inline void notify_all() {
pthread_cond_broadcast(&mHandle);
}
inline void notify_all(){pthread_cond_broadcast(&mHandle);}
#endif
_TTHREAD_DISABLE_ASSIGNMENT(condition_variable)
@ -459,9 +447,8 @@ namespace tthread {
#endif
};
/// Thread class.
class thread {
/// Thread class.
class thread{
public:
#if defined(_TTHREAD_WIN32_)
typedef HANDLE native_handle_type;
@ -474,11 +461,14 @@ namespace tthread {
/// Default constructor.
/// Construct a @c thread object without an associated thread of execution
/// (i.e. non-joinable).
thread() : mHandle(0), mNotAThread(true)
thread()
: mHandle(0), mNotAThread(true)
#if defined(_TTHREAD_WIN32_)
, mWin32ThreadID(0)
,
mWin32ThreadID(0)
#endif
{}
{
}
/// Thread starting constructor.
/// Construct a @c thread object with a new thread of execution.
@ -488,7 +478,7 @@ namespace tthread {
/// @note This constructor is not fully compatible with the standard C++
/// thread class. It is more similar to the pthread_create() (POSIX) and
/// CreateThread() (Windows) functions.
thread(void (*aFunction)(void *), void * aArg);
thread(void (*aFunction)(void *), void *aArg);
/// Destructor.
/// @note If the thread is joinable upon destruction, @c std::terminate()
@ -519,9 +509,7 @@ namespace tthread {
/// Get the native handle for this thread.
/// @note Under Windows, this is a @c HANDLE, and under POSIX systems, this
/// is a @c pthread_t.
inline native_handle_type native_handle() {
return mHandle;
}
inline native_handle_type native_handle(){return mHandle;}
/// Determine the number of threads which can possibly execute concurrently.
/// This function is useful for determining the optimal number of threads to
@ -536,63 +524,51 @@ namespace tthread {
native_handle_type mHandle; ///< Thread handle.
mutable mutex mDataMutex; ///< Serializer for access to the thread private data.
bool mNotAThread; ///< True if this object is not a thread of execution.
void * ti_copy;
void *ti_copy;
#if defined(_TTHREAD_WIN32_)
unsigned int mWin32ThreadID; ///< Unique thread ID (filled out by _beginthreadex).
#endif
// This is the internal thread wrapper function.
#if defined(_TTHREAD_WIN32_)
static unsigned WINAPI wrapper_function(void * aArg);
static unsigned WINAPI wrapper_function(void *aArg);
#else
static void * wrapper_function(void * aArg);
static void *wrapper_function(void *aArg);
#endif
};
/// Thread ID.
/// The thread ID is a unique identifier for each thread.
/// @see thread::get_id()
class thread::id {
/// Thread ID.
/// The thread ID is a unique identifier for each thread.
/// @see thread::get_id()
class thread::id{
public:
/// Default constructor.
/// The default constructed ID is that of thread without a thread of
/// execution.
id() : mId(0) {};
id() : mId(0){};
id(unsigned long int aId) : mId(aId) {};
id(unsigned long int aId) : mId(aId){};
id(const id & aId) : mId(aId.mId) {};
id(const id &aId) : mId(aId.mId){};
inline id & operator=(const id & aId) {
inline id &operator=(const id &aId){
mId = aId.mId;
return *this;
}
inline friend bool operator==(const id & aId1, const id & aId2) {
return (aId1.mId == aId2.mId);
}
inline friend bool operator==(const id &aId1, const id &aId2){return (aId1.mId == aId2.mId);}
inline friend bool operator!=(const id & aId1, const id & aId2) {
return (aId1.mId != aId2.mId);
}
inline friend bool operator!=(const id &aId1, const id &aId2){return (aId1.mId != aId2.mId);}
inline friend bool operator<=(const id & aId1, const id & aId2) {
return (aId1.mId <= aId2.mId);
}
inline friend bool operator<=(const id &aId1, const id &aId2){return (aId1.mId <= aId2.mId);}
inline friend bool operator<(const id & aId1, const id & aId2) {
return (aId1.mId < aId2.mId);
}
inline friend bool operator<(const id &aId1, const id &aId2){return (aId1.mId < aId2.mId);}
inline friend bool operator>=(const id & aId1, const id & aId2) {
return (aId1.mId >= aId2.mId);
}
inline friend bool operator>=(const id &aId1, const id &aId2){return (aId1.mId >= aId2.mId);}
inline friend bool operator>(const id & aId1, const id & aId2) {
return (aId1.mId > aId2.mId);
}
inline friend bool operator>(const id &aId1, const id &aId2){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;
return os;
}
@ -601,39 +577,34 @@ namespace tthread {
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;
/// Minimal implementation of the @c ratio class. This class provides enough
/// functionality to implement some basic @c chrono classes.
template <__intmax_t N, __intmax_t D = 1> class ratio {
/// Minimal implementation of the @c ratio class. This class provides enough
/// functionality to implement some basic @c chrono classes.
template <__intmax_t N, __intmax_t D = 1> class ratio{
public:
static double _as_double() {
return double(N) / double(D);
}
static double _as_double(){return double(N) / double(D);}
};
/// Minimal implementation of the @c chrono namespace.
/// The @c chrono namespace provides types for specifying time intervals.
namespace chrono {
/// Minimal implementation of the @c chrono namespace.
/// The @c chrono namespace provides types for specifying time intervals.
namespace chrono{
/// Duration template class. This class provides enough functionality to
/// implement @c this_thread::sleep_for().
template <class _Rep, class _Period = ratio<1> > class duration {
template <class _Rep, class _Period = ratio<1> > class duration{
private:
_Rep rep_;
public:
typedef _Rep rep;
typedef _Period period;
/// Construct a duration object with the given duration.
template <class _Rep2>
explicit duration(const _Rep2 & r) : rep_(r) {};
template <class _Rep2> explicit duration(const _Rep2 &r) : rep_(r){};
/// Return the value of the duration object.
rep count() const {
return rep_;
}
rep count() const{return rep_;}
};
// Standard duration types.
@ -643,18 +614,18 @@ namespace tthread {
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<3600> > hours; ///< Duration with the unit hours.
}
}// namespace chrono
/// The namespace @c this_thread provides methods for dealing with the
/// calling thread.
namespace this_thread {
/// The namespace @c this_thread provides methods for dealing with the
/// calling thread.
namespace this_thread{
/// Return the thread ID of the calling thread.
thread::id get_id();
/// Yield execution to another thread.
/// Offers the operating system the opportunity to schedule another thread
/// that is ready to run on the current processor.
inline void yield() {
inline void yield(){
#if defined(_TTHREAD_WIN32_)
Sleep(0);
#else
@ -671,16 +642,17 @@ namespace tthread {
/// @endcode
/// @note Supported duration types are: nanoseconds, microseconds,
/// 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_)
Sleep(int(double(aTime.count()) * (1000.0 * _Period::_as_double()) + 0.5));
#else
usleep(int(double(aTime.count()) * (1000000.0 * _Period::_as_double()) + 0.5));
#endif
}
}
}// namespace this_thread
}
}// namespace tthread
// Define/macro cleanup
#undef _TTHREAD_DISABLE_ASSIGNMENT

View file

@ -1,35 +1,37 @@
/// \page triggers Triggers
/// \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.
/// 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
/// POST body.
/// 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
/// standard input.
/// Triggers may be handled by a URL or an executable. If the handler contains ://, a HTTP URL is
/// assumed. Otherwise, an executable is assumed. 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 POST
/// body. 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 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 "defines.h" //for FAIL_MSG and INFO_MSG
#include "downloader.h" //for sending http request
#include "procs.h" //for StartPiped
#include "shared_memory.h"
#include "util.h"
#include "timing.h"
#include "triggers.h"
#include "util.h"
#include <string.h> //for strncmp
namespace Triggers{
static void submitTriggerStat(const std::string trigger, uint64_t millis, bool ok){
JSON::Value j;
j["trigger_stat"]["name"] = trigger;
j["trigger_stat"]["ms"] = Util::bootMS()-millis;
j["trigger_stat"]["ms"] = Util::bootMS() - millis;
j["trigger_stat"]["ok"] = ok;
Socket::UDPConnection uSock;
uSock.SetDestination(UDP_API_HOST, UDP_API_PORT);
@ -42,7 +44,8 @@ namespace Triggers{
///\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.
///\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();
if (!value.size()){
WARN_MSG("Trigger requested with empty destination");
@ -58,7 +61,8 @@ namespace Triggers{
submitTriggerStat(trigger, tStartMs, true);
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);
return defaultResponse;
}else{// send payload to stdin of newly forked process
@ -90,9 +94,7 @@ namespace Triggers{
Util::sleep(100);
++counter;
if (counter >= 150){
if (counter == 150){
FAIL_MSG("Trigger taking too long - killing process");
}
if (counter == 150){FAIL_MSG("Trigger taking too long - killing process");}
if (counter >= 250){
Util::Procs::Stop(myProc);
}else{
@ -104,7 +106,9 @@ namespace Triggers{
FILE *outFile = fdopen(fdOut, "r");
char *fileBuf = 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);
free(fileBuf);
close(fdOut);
@ -124,14 +128,14 @@ namespace Triggers{
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)
///\param type Trigger event type.
///\param streamName the stream to be handled
///\brief returns true if a trigger of the specified type should be handled for a specified stream
///(, or entire server) \param type Trigger event type. \param streamName the stream to be handled
///\return returns true if so
/// calls doTrigger with dryRun set to true
/// returns true if a trigger of the specified type should be
/// 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();
return doTrigger(type, empty, streamName, true, usually_empty, paramsCB, extraParam);
}
@ -142,7 +146,7 @@ namespace Triggers{
///\param streamName The name of a stream.
///\returns Boolean, false if further processing should be aborted.
/// calls doTrigger with dryRun set to false
bool doTrigger(const std::string & type, const std::string &payload, const std::string &streamName){
bool doTrigger(const std::string &type, const std::string &payload, const std::string &streamName){
usually_empty.clear();
return doTrigger(type, payload, streamName, false, usually_empty);
}
@ -158,11 +162,13 @@ namespace Triggers{
/// defined for that trigger event type.
/// The function can be used for two separate purposes, determined by the value of dryRun
///-if this function is called with dryRun==true (for example, from a handleTrigger function), the return value will be true, if at least one
///trigger should be handled for the requested type/stream.
/// trigger should be handled for the requested type/stream.
/// 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
///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){
/// 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){
// open SHM page for this type:
char thisPageName[NAME_BUFFER_SIZE];
snprintf(thisPageName, NAME_BUFFER_SIZE, SHM_TRIGGER, type.c_str());
@ -184,23 +190,22 @@ namespace Triggers{
std::string uri = std::string(trigs.getPointer("url", i));
uint8_t sync = trigs.getInt("sync", i);
char * strPtr = trigs.getPointer("streams", i);
char *strPtr = trigs.getPointer("streams", i);
uint32_t pLen = trigs.getSize("streams");
uint32_t bPos = 0;
bool isHandled = !streamName.size();
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 ((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;
}
bPos += stringLen + 4;
}
// no streams explicitly defined for this trigger, return true for all streams.
if (bPos <= 4){
isHandled = true;
}
if (bPos <= 4){isHandled = true;}
if (isHandled && paramsCB){
isHandled = paramsCB(trigs.getPointer("params", i), extraParam);
@ -227,5 +232,4 @@ namespace Triggers{
return retVal;
}
}
}
}// namespace Triggers

View file

@ -5,11 +5,15 @@ namespace Triggers{
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);
std::string handleTrigger(const std::string &triggerType, const std::string &value, const std::string &payload, int sync, const std::string &defaultResponse);
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);
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:
bool shouldTrigger(const std::string & triggerType, 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);
}
bool shouldTrigger(const std::string &triggerType, 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

File diff suppressed because it is too large Load diff

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