Restyle
This commit is contained in:
parent
5b79f296d6
commit
fccf66fba2
280 changed files with 56975 additions and 71885 deletions
88
lib/adts.cpp
88
lib/adts.cpp
|
@ -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
|
||||
|
|
29
lib/adts.h
29
lib/adts.h
|
@ -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
|
||||
|
|
37
lib/amf.cpp
37
lib/amf.cpp
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
225
lib/auth.cpp
225
lib/auth.cpp
|
@ -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
|
||||
|
|
37
lib/auth.h
37
lib/auth.h
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -93,4 +93,3 @@ namespace Utils{
|
|||
void fixData();
|
||||
};
|
||||
}// namespace Utils
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
331
lib/checksum.h
331
lib/checksum.h
|
@ -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
|
||||
|
|
|
@ -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){
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -64,4 +64,3 @@ namespace Util{
|
|||
void setUser(std::string user);
|
||||
|
||||
}// namespace Util
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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) {
|
|||
}
|
||||
|
||||
/* ---------------------------------------- */
|
||||
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
/* ----------------------------------------- */
|
||||
|
|
315
lib/dtsc.cpp
315
lib/dtsc.cpp
|
@ -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;
|
||||
}
|
||||
|
|
307
lib/dtsc.h
307
lib/dtsc.h
|
@ -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
|
||||
|
|
1430
lib/dtscmeta.cpp
1430
lib/dtscmeta.cpp
File diff suppressed because it is too large
Load diff
14
lib/ebml.cpp
14
lib/ebml.cpp
|
@ -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
|
||||
|
||||
|
|
|
@ -121,4 +121,3 @@ namespace EBML{
|
|||
virtual std::string toPrettyString(const uint8_t indent = 0, const uint8_t detail = 3) const;
|
||||
};
|
||||
}// namespace EBML
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -40,4 +40,3 @@ namespace Encodings{
|
|||
};
|
||||
|
||||
}// namespace Encodings
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
79
lib/h264.cpp
79
lib/h264.cpp
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
129
lib/h265.cpp
129
lib/h265.cpp
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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);
|
||||
|
|
33
lib/json.cpp
33
lib/json.cpp
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1221,4 +1221,3 @@ namespace Encodings{
|
|||
}
|
||||
|
||||
}// namespace Encodings
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
746
lib/mp4.cpp
746
lib/mp4.cpp
File diff suppressed because it is too large
Load diff
113
lib/mp4.h
113
lib/mp4.h
|
@ -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
|
@ -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
|
||||
|
|
185
lib/mp4_dash.cpp
185
lib/mp4_dash.cpp
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
2948
lib/mp4_generic.cpp
2948
lib/mp4_generic.cpp
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
242
lib/mp4_ms.cpp
242
lib/mp4_ms.cpp
|
@ -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
|
||||
|
|
16
lib/mp4_ms.h
16
lib/mp4_ms.h
|
@ -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
|
||||
|
|
|
@ -81,4 +81,3 @@ namespace Mpeg{
|
|||
return res;
|
||||
}
|
||||
}// namespace Mpeg
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
436
lib/ogg.cpp
436
lib/ogg.cpp
|
@ -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 ¤tSegment){
|
||||
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
108
lib/ogg.h
|
@ -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 ¤tSegment);
|
||||
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
|
||||
|
|
16
lib/opus.cpp
16
lib/opus.cpp
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
280
lib/procs.cpp
280
lib/procs.cpp
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
34
lib/procs.h
34
lib/procs.h
|
@ -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
|
||||
|
|
46
lib/riff.cpp
46
lib/riff.cpp
|
@ -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
|
||||
|
|
13
lib/riff.h
13
lib/riff.h
|
@ -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
|
||||
|
|
719
lib/rijndael.cpp
719
lib/rijndael.cpp
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -86,4 +86,3 @@ namespace RTMPStream{
|
|||
/// Does the handshake. Expects handshake_in to be filled, and fills handshake_out.
|
||||
bool doHandshake();
|
||||
}// namespace RTMPStream
|
||||
|
||||
|
|
86
lib/rtp.cpp
86
lib/rtp.cpp
|
@ -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
|
||||
|
||||
|
|
18
lib/rtp.h
18
lib/rtp.h
|
@ -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
|
||||
|
||||
|
|
241
lib/rtp_fec.cpp
241
lib/rtp_fec.cpp
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
63
lib/sdp.cpp
63
lib/sdp.cpp
|
@ -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
|
||||
|
||||
|
|
|
@ -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 ¶m) const;
|
||||
uint64_t getParamInt(const std::string ¶m) 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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
281
lib/srtp.cpp
281
lib/srtp.cpp
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
18
lib/srtp.h
18
lib/srtp.h
|
@ -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;
|
||||
|
|
240
lib/stream.cpp
240
lib/stream.cpp
|
@ -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;
|
||||
|
|
52
lib/stream.h
52
lib/stream.h
|
@ -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
|
||||
|
|
636
lib/stun.cpp
636
lib/stun.cpp
File diff suppressed because it is too large
Load diff
89
lib/stun.h
89
lib/stun.h
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
163
lib/theora.cpp
163
lib/theora.cpp
|
@ -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
|
||||
|
|
38
lib/theora.h
38
lib/theora.h
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
290
lib/tinythread.h
290
lib/tinythread.h
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
1108
lib/ts_packet.cpp
1108
lib/ts_packet.cpp
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
Loading…
Add table
Reference in a new issue