New Meta commit

This commit is contained in:
Phencys 2021-04-21 18:10:03 +02:00 committed by Thulinma
parent fccf66fba2
commit 2b99f2f5ea
183 changed files with 13333 additions and 14421 deletions

View file

@ -67,10 +67,10 @@ int Analyser::run(Util::Config &conf){
if (validate && ((finTime - upTime + 10) * 1000 < mediaTime)){
uint32_t sleepMs = mediaTime - (Util::bootSecs() - upTime + 10) * 1000;
if ((finTime - upTime + sleepMs / 1000) >= timeOut){
WARN_MSG("Reached timeout of %llu seconds, stopping", timeOut);
WARN_MSG("Reached timeout of %" PRIu64 " seconds, stopping", timeOut);
return 3;
}
INFO_MSG("Sleeping for %lums", sleepMs);
INFO_MSG("Sleeping for %" PRIu32 "ms", sleepMs);
Util::sleep(sleepMs);
finTime = Util::bootSecs();
}
@ -80,7 +80,7 @@ int Analyser::run(Util::Config &conf){
return 4;
}
if ((finTime - upTime) >= timeOut){
WARN_MSG("Reached timeout of %llu seconds, stopping", timeOut);
WARN_MSG("Reached timeout of %" PRIu64 " seconds, stopping", timeOut);
return 3;
}
}

View file

@ -30,17 +30,14 @@ bool getDelimBlock(std::string &data, std::string name, size_t &blockStart, size
offset--;
blockStart = data.find(delim, offset);
// DEBUG_MSG(DLVL_INFO, "offset: %i blockStart: %i ", offset, blockStart);
offset = blockStart + 1; // skip single character!
blockEnd = data.find(delim, offset);
// DEBUG_MSG(DLVL_INFO, "offset: %i blockEnd: %i ", offset, blockEnd);
if (blockStart == std::string::npos || blockEnd == std::string::npos){
return false; // no start/end quotes found
}
blockEnd++; // include delim
// DEBUG_MSG(DLVL_INFO, "getDelimPos: data.size() %i start %i end %i num %i", data.size(), blockStart,blockEnd,(blockEnd-blockStart) );
return true;
}
@ -50,15 +47,12 @@ bool getValueBlock(std::string &data, std::string name, size_t &blockStart, size
return false; // name string not found.
}
blockStart = data.find(delim, offset);
// DEBUG_MSG(DLVL_INFO, "offset: %i blockStart: %i ", offset, blockStart);
blockStart++; // clip off quote characters
offset = blockStart; // skip single character!
blockEnd = data.find(delim, offset);
// DEBUG_MSG(DLVL_INFO, "offset: %i blockEnd: %i ", offset, blockEnd);
if (blockStart == std::string::npos || blockEnd == std::string::npos){
return false; // no start/end quotes found
}
// DEBUG_MSG(DLVL_INFO, "getValueBlock: data.size() %i start %i end %i num %i", data.size(), blockStart,blockEnd,(blockEnd-blockStart) );
return true;
}
@ -67,23 +61,17 @@ bool getString(std::string &data, std::string name, std::string &output){
size_t blockEnd = 0;
if (!getValueBlock(data, name, blockStart, blockEnd, "\"")){
// DEBUG_MSG(DLVL_FAIL, "could not find \"%s\" in data block", name.c_str());
return false; // could not find value in this data block.
}
// DEBUG_MSG(DLVL_INFO, "data.size() %i start %i end %i num %i", data.size(), blockStart,blockEnd,(blockEnd-blockStart) )
output = data.substr(blockStart, (blockEnd - blockStart));
// looks like this function is working as expected
// DEBUG_MSG(DLVL_INFO, "data in getstring %s", (data.substr(blockStart,(blockEnd-blockStart))).c_str());
return true;
}
bool getLong(std::string &data, std::string name, long &output){
size_t blockStart, blockEnd;
if (!getValueBlock(data, name, blockStart, blockEnd, "\"")){
// DEBUG_MSG(DLVL_FAIL, "could not find \"%s\" in data block", name.c_str());
return false; // could not find value in this data block.
}
// DEBUG_MSG(DLVL_INFO, "name: %s data in atol %s",name.c_str(), (data.substr(blockStart,(blockEnd-blockStart))).c_str());
output = atol((data.substr(blockStart, (blockEnd - blockStart))).c_str());
return true;
}
@ -96,7 +84,7 @@ bool getBlock(std::string &data, std::string name, int offset, size_t &blockStar
}
if (blockStart == std::string::npos){
DEBUG_MSG(DLVL_INFO, "no block start found for name: %s at offset: %i", name.c_str(), offset);
INFO_MSG("no block start found for name: %s at offset: %i", name.c_str(), offset);
return false;
}
@ -104,75 +92,71 @@ bool getBlock(std::string &data, std::string name, int offset, size_t &blockStar
if (blockEnd == std::string::npos){
blockEnd = data.find("/>", blockStart);
if (blockEnd == std::string::npos){
DEBUG_MSG(DLVL_INFO, "no block end found.");
INFO_MSG("no block end found.");
return false;
}
size_t temp = data.find("<", blockStart + 1, (blockEnd - blockStart - 1)); // the +1 is to avoid re-interpreting the starting < //TODO!!
size_t temp = data.find("<", blockStart + 1,
(blockEnd - blockStart - 1)); // the +1 is to avoid re-interpreting the starting < //TODO!!
if (temp != std::string::npos){// all info is epxected between <name ... />
DEBUG_MSG(DLVL_FAIL, "block start found before block end. offset: %lu block: %s", temp, data.c_str());
FAIL_MSG("block start found before block end. offset: %lu block: %s", temp, data.c_str());
return false;
}
// DEBUG_MSG(DLVL_FAIL, "special block end found");
blockEnd += 2; // position after />
}else{
blockEnd += name.size() + 2; // position after /name>
}
// DEBUG_MSG(DLVL_INFO, "getBlock: start: %i end: %i",blockStart,blockEnd);
return true;
}
bool parseAdaptationSet(std::string &data, std::set<seekPos> &currentPos){
// DEBUG_MSG(DLVL_INFO, "Parsing adaptationSet: %s", data.c_str());
size_t offset = 0;
size_t blockStart, blockEnd;
tempSD.trackType = OTHER;
// get value: mimetype //todo: handle this!
std::string mimeType;
if (!getString(
data, "mimeType",
mimeType)){// get first occurence of mimeType. --> this will break if multiple mimetypes
// should be read from this block because no offset is provided. solution:
// use this on a substring containing the desired information.
DEBUG_MSG(DLVL_FAIL, "mimeType not found");
if (!getString(data, "mimeType",
mimeType)){// get first occurence of mimeType. --> this will break if multiple mimetypes
// should be read from this block because no offset is provided. solution:
// use this on a substring containing the desired information.
FAIL_MSG("mimeType not found");
return false;
}
DEBUG_MSG(DLVL_INFO, "mimeType: %s", mimeType.c_str()); // checked, OK
INFO_MSG("mimeType: %s", mimeType.c_str()); // checked, OK
if (mimeType.find("video") != std::string::npos){tempSD.trackType = VIDEO;}
if (mimeType.find("audio") != std::string::npos){tempSD.trackType = AUDIO;}
if (tempSD.trackType == OTHER){
DEBUG_MSG(DLVL_FAIL, "no audio or video type found. giving up.");
FAIL_MSG("no audio or video type found. giving up.");
return false;
}
// find an ID within this adaptationSet block.
if (!getBlock(data, (std::string) "Representation", offset, blockStart, blockEnd)){
DEBUG_MSG(DLVL_FAIL, "Representation not found");
FAIL_MSG("Representation not found");
return false;
}
// representation string
std::string block = data.substr(blockStart, (blockEnd - blockStart));
DEBUG_MSG(DLVL_INFO, "Representation block: %s", block.c_str());
// check if block is not junk?
INFO_MSG("Representation block: %s", block.c_str());
///\todo check if block is not junk?
if (!getLong(block, "id", tempSD.trackID)){
DEBUG_MSG(DLVL_FAIL, "Representation id not found in block %s", block.c_str());
FAIL_MSG("Representation id not found in block %s", block.c_str());
return false;
}
DEBUG_MSG(DLVL_INFO, "Representation/id: %li", tempSD.trackID); // checked, OK
INFO_MSG("Representation/id: %li", tempSD.trackID); // checked, OK
offset = 0;
// get values from SegmentTemplate
if (!getBlock(data, (std::string) "SegmentTemplate", offset, blockStart, blockEnd)){
DEBUG_MSG(DLVL_FAIL, "SegmentTemplate not found");
FAIL_MSG("SegmentTemplate not found");
return false;
}
block = data.substr(blockStart, (blockEnd - blockStart));
// DEBUG_MSG(DLVL_INFO, "SegmentTemplate block: %s",block.c_str()); //OK
getLong(block, "timescale", tempSD.timeScale);
getString(block, "media", tempSD.media);
@ -181,20 +165,19 @@ bool parseAdaptationSet(std::string &data, std::set<seekPos> &currentPos){
size_t tmpBlockStart = 0;
size_t tmpBlockEnd = 0;
if (!getDelimBlock(tempSD.media, "RepresentationID", tmpBlockStart, tmpBlockEnd, "$")){
DEBUG_MSG(DLVL_FAIL, "Failed to find and replace $RepresentationID$ in %s", tempSD.media.c_str());
FAIL_MSG("Failed to find and replace $RepresentationID$ in %s", tempSD.media.c_str());
return false;
}
tempSD.media.replace(tmpBlockStart, (tmpBlockEnd - tmpBlockStart), "%d");
if (!getDelimBlock(tempSD.media, "Time", tmpBlockStart, tmpBlockEnd, "$")){
DEBUG_MSG(DLVL_FAIL, "Failed to find and replace $Time$ in %s", tempSD.media.c_str());
FAIL_MSG("Failed to find and replace $Time$ in %s", tempSD.media.c_str());
return false;
}
tempSD.media.replace(tmpBlockStart, (tmpBlockEnd - tmpBlockStart), "%d");
if (!getDelimBlock(tempSD.initialization, "RepresentationID", tmpBlockStart, tmpBlockEnd, "$")){
DEBUG_MSG(DLVL_FAIL, "Failed to find and replace $RepresentationID$ in %s",
tempSD.initialization.c_str());
FAIL_MSG("Failed to find and replace $RepresentationID$ in %s", tempSD.initialization.c_str());
return false;
}
tempSD.initialization.replace(tmpBlockStart, (tmpBlockEnd - tmpBlockStart), "%d");
@ -202,12 +185,12 @@ bool parseAdaptationSet(std::string &data, std::set<seekPos> &currentPos){
// get segment timeline block from within segment template:
size_t blockOffset = 0; // offset should be 0 because this is a new block
if (!getBlock(block, "SegmentTimeline", blockOffset, blockStart, blockEnd)){
DEBUG_MSG(DLVL_FAIL, "SegmentTimeline block not found");
FAIL_MSG("SegmentTimeline block not found");
return false;
}
std::string block2 = block.substr(blockStart, (blockEnd - blockStart)); // overwrites previous block (takes just the segmentTimeline part
// DEBUG_MSG(DLVL_INFO, "SegmentTimeline block: %s",block2.c_str()); //OK
std::string block2 = block.substr(blockStart,
(blockEnd - blockStart)); // overwrites previous block (takes just the segmentTimeline part
int numS = 0;
offset = 0;
@ -216,10 +199,10 @@ bool parseAdaptationSet(std::string &data, std::set<seekPos> &currentPos){
while (1){
if (!getBlock(block2, "S", offset, blockStart, blockEnd)){
if (numS == 0){
DEBUG_MSG(DLVL_FAIL, "no S found within SegmentTimeline");
FAIL_MSG("no S found within SegmentTimeline");
return false;
}else{
DEBUG_MSG(DLVL_INFO, "all S found within SegmentTimeline %i", numS);
INFO_MSG("all S found within SegmentTimeline %i", numS);
return true; // break; //escape from while loop (to return true)
}
}
@ -227,16 +210,14 @@ bool parseAdaptationSet(std::string &data, std::set<seekPos> &currentPos){
// stuff S data into: currentPos
// searching for t(start position)
std::string sBlock = block2.substr(blockStart, (blockEnd - blockStart));
// DEBUG_MSG(DLVL_INFO, "S found. offset: %i blockStart: %i blockend: %i block: %s",offset,blockStart, blockEnd, sBlock.c_str()); //OK!
if (getLong(sBlock, "t", timeValue)){
totalDuration = timeValue; // reset totalDuration to value of t
}
if (!getLong(sBlock, "d", timeValue)){// expected duration in every S.
DEBUG_MSG(DLVL_FAIL, "no d found within S");
FAIL_MSG("no d found within S");
return false;
}
// stuff data with old value (start of block)
// DEBUG_MSG(DLVL_INFO, "stuffing info from S into set");
seekPos thisPos;
thisPos.trackType = tempSD.trackType;
thisPos.trackID = tempSD.trackID;
@ -249,7 +230,6 @@ bool parseAdaptationSet(std::string &data, std::set<seekPos> &currentPos){
static char charBuf[512];
snprintf(charBuf, 512, tempSD.media.c_str(), tempSD.trackID, totalDuration);
thisPos.url.assign(charBuf);
// DEBUG_MSG(DLVL_INFO, "media url (from rep.ID %d, startTime %d): %s", tempSD.trackID, totalDuration,thisPos.url.c_str());
currentPos.insert(thisPos); // assumes insert copies all data in seekPos struct.
totalDuration += timeValue; // update totalDuration
@ -265,30 +245,30 @@ bool parseXML(std::string &body, std::set<seekPos> &currentPos, std::vector<Stre
size_t currentOffset = 0;
size_t adaptationSetStart;
size_t adaptationSetEnd;
// DEBUG_MSG(DLVL_INFO, "body received: %s", body.c_str());
while (getBlock(body, "AdaptationSet", currentOffset, adaptationSetStart, adaptationSetEnd)){
tempSD.adaptationSet = numAdaptationSet;
numAdaptationSet++;
DEBUG_MSG(DLVL_INFO, "adaptationSet found. start: %lu end: %lu num: %lu ", adaptationSetStart,
adaptationSetEnd, (adaptationSetEnd - adaptationSetStart));
INFO_MSG("adaptationSet found. start: %lu end: %lu num: %lu ", adaptationSetStart,
adaptationSetEnd, (adaptationSetEnd - adaptationSetStart));
// get substring: from <adaptationSet... to /adaptationSet>
std::string adaptationSet = body.substr(adaptationSetStart, (adaptationSetEnd - adaptationSetStart));
// function was verified: output as expected.
if (!parseAdaptationSet(adaptationSet, currentPos)){
DEBUG_MSG(DLVL_FAIL, "parseAdaptationSet returned false."); // this also happens in the case of OTHER mimetype. in that case it might be
// desirable to continue searching for valid data instead of quitting.
FAIL_MSG("parseAdaptationSet returned false."); // this also happens in the case of OTHER mimetype.
// in that case it might be desirable to continue
// searching for valid data instead of quitting.
return false;
}
streamData.push_back(tempSD); // put temp values into adaptation set vector
currentOffset = adaptationSetEnd; // the getblock function should make sure End is at the correct offset.
}
if (numAdaptationSet == 0){
DEBUG_MSG(DLVL_FAIL, "no adaptationSet found.");
FAIL_MSG("no adaptationSet found.");
return false;
}
DEBUG_MSG(DLVL_INFO, "all adaptation sets found. total: %i", numAdaptationSet);
INFO_MSG("all adaptation sets found. total: %i", numAdaptationSet);
return true;
}
@ -297,7 +277,7 @@ dashAnalyser::dashAnalyser(Util::Config conf) : analysers(conf){
url = conf.getString("url");
if (url.substr(0, 7) != "http://"){
DEBUG_MSG(DLVL_FAIL, "The URL must start with http://");
FAIL_MSG("The URL must start with http://");
// return -1;
exit(1);
}
@ -329,9 +309,9 @@ dashAnalyser::dashAnalyser(Util::Config conf) : analysers(conf){
}
// url:
DEBUG_MSG(DLVL_INFO, "url %s server: %s port: %d", url.c_str(), server.c_str(), port);
INFO_MSG("url %s server: %s port: %d", url.c_str(), server.c_str(), port);
urlPrependStuff = url.substr(0, url.rfind("/") + 1);
DEBUG_MSG(DLVL_INFO, "prepend stuff: %s", urlPrependStuff.c_str());
INFO_MSG("prepend stuff: %s", urlPrependStuff.c_str());
if (!conn){conn.open(server, port, false);}
pos = 0;
@ -346,13 +326,8 @@ dashAnalyser::dashAnalyser(Util::Config conf) : analysers(conf){
currentPos;
streamData;
// DEBUG_MSG(DLVL_INFO, "body received: %s", H.body.c_str()); //keeps giving empty stuff :(
// DEBUG_MSG(DLVL_INFO, "url %s ", url.c_str());
// std::ifstream in(url.c_str());
// std::string s((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
if (!parseXML(H.body, currentPos, streamData)){
DEBUG_MSG(DLVL_FAIL, "Manifest parsing failed. body: \n %s", H.body.c_str());
FAIL_MSG("Manifest parsing failed. body: \n %s", H.body.c_str());
if (conf.getString("mode") == "validate"){
long long int endTime = Util::bootSecs();
std::cout << startTime << ", " << endTime << ", " << (endTime - startTime) << ", " << pos << std::endl;
@ -362,30 +337,30 @@ dashAnalyser::dashAnalyser(Util::Config conf) : analysers(conf){
}
H.Clean();
DEBUG_MSG(DLVL_INFO, "*********");
DEBUG_MSG(DLVL_INFO, "*SUMMARY*");
DEBUG_MSG(DLVL_INFO, "*********");
INFO_MSG("*********");
INFO_MSG("*SUMMARY*");
INFO_MSG("*********");
DEBUG_MSG(DLVL_INFO, "num streams: %lu", streamData.size());
INFO_MSG("num streams: %lu", streamData.size());
for (unsigned int i = 0; i < streamData.size(); i++){
DEBUG_MSG(DLVL_INFO, "");
DEBUG_MSG(DLVL_INFO, "ID in vector %d", i);
DEBUG_MSG(DLVL_INFO, "trackID %ld", streamData[i].trackID);
DEBUG_MSG(DLVL_INFO, "adaptationSet %d", streamData[i].adaptationSet);
DEBUG_MSG(DLVL_INFO, "trackType (audio 0x02, video 0x01) %d", streamData[i].trackType);
DEBUG_MSG(DLVL_INFO, "TimeScale %ld", streamData[i].timeScale);
DEBUG_MSG(DLVL_INFO, "Media string %s", streamData[i].media.c_str());
DEBUG_MSG(DLVL_INFO, "Init string %s", streamData[i].initialization.c_str());
INFO_MSG("");
INFO_MSG("ID in vector %d", i);
INFO_MSG("trackID %ld", streamData[i].trackID);
INFO_MSG("adaptationSet %d", streamData[i].adaptationSet);
INFO_MSG("trackType (audio 0x02, video 0x01) %d", streamData[i].trackType);
INFO_MSG("TimeScale %ld", streamData[i].timeScale);
INFO_MSG("Media string %s", streamData[i].media.c_str());
INFO_MSG("Init string %s", streamData[i].initialization.c_str());
}
DEBUG_MSG(DLVL_INFO, "");
INFO_MSG("");
for (unsigned int i = 0; i < streamData.size(); i++){// get init url
static char charBuf[512];
snprintf(charBuf, 512, streamData[i].initialization.c_str(), streamData[i].trackID);
streamData[i].initURL.assign(charBuf);
DEBUG_MSG(DLVL_INFO, "init url for adaptationSet %d trackID %ld: %s ",
streamData[i].adaptationSet, streamData[i].trackID, streamData[i].initURL.c_str());
INFO_MSG("init url for adaptationSet %d trackID %ld: %s ", streamData[i].adaptationSet,
streamData[i].trackID, streamData[i].initURL.c_str());
}
}
@ -403,8 +378,7 @@ dashAnalyser::~dashAnalyser(){
int dashAnalyser::doAnalyse(){
// DEBUG_MSG(DLVL_INFO, "next url: %s", currentPos.begin()->url.c_str());
// match adaptation set and track id?
///\todo match adaptation set and track id?
int tempID = 0;
for (unsigned int i = 0; i < streamData.size(); i++){
if (streamData[i].trackID == currentPos.begin()->trackID &&
@ -415,20 +389,16 @@ int dashAnalyser::doAnalyse(){
HTTP::Parser H;
H.url = urlPrependStuff;
H.url.append(currentPos.begin()->url);
DEBUG_MSG(DLVL_INFO, "Retrieving segment: %s (%llu-%llu)", H.url.c_str(),
currentPos.begin()->seekTime, currentPos.begin()->seekTime + currentPos.begin()->duration);
INFO_MSG("Retrieving segment: %s (%llu-%llu)", H.url.c_str(), currentPos.begin()->seekTime,
currentPos.begin()->seekTime + currentPos.begin()->duration);
H.SetHeader("Host", server + ":" + JSON::Value((long long)port).toString()); // wut?
H.SendRequest(conn);
// TODO: get response?
H.Clean();
while (conn && (!conn.spool() || !H.Read(conn))){}// ehm...
// std::cout << "leh vomi: "<<H.body <<std::endl;
// DEBUG_MSG(DLVL_INFO, "zut: %s", H.body.c_str());
// strBuf[tempID].append(H.body);
if (!H.body.size()){
DEBUG_MSG(DLVL_FAIL, "No data downloaded from %s", H.url.c_str());
// break;
FAIL_MSG("No data downloaded from %s", H.url.c_str());
return 0;
}
@ -440,17 +410,14 @@ int dashAnalyser::doAnalyse(){
}
if (!mdatSeen){
DEBUG_MSG(DLVL_FAIL, "No mdat present. Sadface. :-(");
// break;
FAIL_MSG("No mdat present. Sadface. :-(");
return 0;
}
if (H.body.size()){
DEBUG_MSG(DLVL_FAIL, "%lu bytes left in body. Assuming horrible things...", H.body.size()); //,H.body.c_str());
FAIL_MSG("%lu bytes left in body. Assuming horrible things...",
H.body.size()); //,H.body.c_str());
std::cerr << H.body << std::endl;
if (beforeParse == H.body.size()){
// break;
return 0;
}
if (beforeParse == H.body.size()){return 0;}
}
H.Clean();
@ -516,7 +483,7 @@ int main2(int argc, char **argv){
std::string url = conf.getString("url");
if (url.substr(0, 7) != "http://"){
DEBUG_MSG(DLVL_FAIL, "The URL must start with http://");
FAIL_MSG("The URL must start with http://");
return -1;
}
url = url.substr(7); // found problem if url is to short!! it gives out of range when entering http://meh.meh
@ -535,9 +502,9 @@ int main2(int argc, char **argv){
Socket::Connection conn(server, port, false);
// url:
DEBUG_MSG(DLVL_INFO, "url %s server: %s port: %d", url.c_str(), server.c_str(), port);
INFO_MSG("url %s server: %s port: %d", url.c_str(), server.c_str(), port);
std::string urlPrependStuff = url.substr(0, url.rfind("/") + 1);
DEBUG_MSG(DLVL_INFO, "prepend stuff: %s", urlPrependStuff.c_str());
INFO_MSG("prepend stuff: %s", urlPrependStuff.c_str());
if (!conn){conn.open(server, port, false);}
unsigned int pos = 0;
HTTP::Parser H;
@ -551,13 +518,8 @@ int main2(int argc, char **argv){
std::set<seekPos> currentPos;
std::vector<StreamData> streamData;
// DEBUG_MSG(DLVL_INFO, "body received: %s", H.body.c_str()); //keeps giving empty stuff :(
// DEBUG_MSG(DLVL_INFO, "url %s ", url.c_str());
// std::ifstream in(url.c_str());
// std::string s((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
if (!parseXML(H.body, currentPos, streamData)){
DEBUG_MSG(DLVL_FAIL, "Manifest parsing failed. body: \n %s", H.body.c_str());
FAIL_MSG("Manifest parsing failed. body: \n %s", H.body.c_str());
if (conf.getString("mode") == "validate"){
long long int endTime = Util::bootSecs();
std::cout << startTime << ", " << endTime << ", " << (endTime - startTime) << ", " << pos << std::endl;
@ -566,37 +528,36 @@ int main2(int argc, char **argv){
}
H.Clean();
DEBUG_MSG(DLVL_INFO, "*********");
DEBUG_MSG(DLVL_INFO, "*SUMMARY*");
DEBUG_MSG(DLVL_INFO, "*********");
INFO_MSG("*********");
INFO_MSG("*SUMMARY*");
INFO_MSG("*********");
DEBUG_MSG(DLVL_INFO, "num streams: %lu", streamData.size());
INFO_MSG("num streams: %lu", streamData.size());
for (unsigned int i = 0; i < streamData.size(); i++){
DEBUG_MSG(DLVL_INFO, "");
DEBUG_MSG(DLVL_INFO, "ID in vector %d", i);
DEBUG_MSG(DLVL_INFO, "trackID %ld", streamData[i].trackID);
DEBUG_MSG(DLVL_INFO, "adaptationSet %d", streamData[i].adaptationSet);
DEBUG_MSG(DLVL_INFO, "trackType (audio 0x02, video 0x01) %d", streamData[i].trackType);
DEBUG_MSG(DLVL_INFO, "TimeScale %ld", streamData[i].timeScale);
DEBUG_MSG(DLVL_INFO, "Media string %s", streamData[i].media.c_str());
DEBUG_MSG(DLVL_INFO, "Init string %s", streamData[i].initialization.c_str());
INFO_MSG("");
INFO_MSG("ID in vector %d", i);
INFO_MSG("trackID %ld", streamData[i].trackID);
INFO_MSG("adaptationSet %d", streamData[i].adaptationSet);
INFO_MSG("trackType (audio 0x02, video 0x01) %d", streamData[i].trackType);
INFO_MSG("TimeScale %ld", streamData[i].timeScale);
INFO_MSG("Media string %s", streamData[i].media.c_str());
INFO_MSG("Init string %s", streamData[i].initialization.c_str());
}
DEBUG_MSG(DLVL_INFO, "");
INFO_MSG("");
for (unsigned int i = 0; i < streamData.size(); i++){// get init url
static char charBuf[512];
snprintf(charBuf, 512, streamData[i].initialization.c_str(), streamData[i].trackID);
streamData[i].initURL.assign(charBuf);
DEBUG_MSG(DLVL_INFO, "init url for adaptationSet %d trackID %ld: %s ",
streamData[i].adaptationSet, streamData[i].trackID, streamData[i].initURL.c_str());
INFO_MSG("init url for adaptationSet %d trackID %ld: %s ", streamData[i].adaptationSet,
streamData[i].trackID, streamData[i].initURL.c_str());
}
while (currentPos.size() && (abortTime <= 0 || Util::bootSecs() < startTime + abortTime)){
// DEBUG_MSG(DLVL_INFO, "next url: %s", currentPos.begin()->url.c_str());
std::cout << "blaa" << std::endl;
// match adaptation set and track id?
///\todo match adaptation set and track id?
int tempID = 0;
for (unsigned int i = 0; i < streamData.size(); i++){
if (streamData[i].trackID == currentPos.begin()->trackID &&
@ -607,18 +568,15 @@ int main2(int argc, char **argv){
HTTP::Parser H;
H.url = urlPrependStuff;
H.url.append(currentPos.begin()->url);
DEBUG_MSG(DLVL_INFO, "Retrieving segment: %s (%llu-%llu)", H.url.c_str(),
currentPos.begin()->seekTime, currentPos.begin()->seekTime + currentPos.begin()->duration);
INFO_MSG("Retrieving segment: %s (%llu-%llu)", H.url.c_str(), currentPos.begin()->seekTime,
currentPos.begin()->seekTime + currentPos.begin()->duration);
H.SetHeader("Host", server + ":" + JSON::Value((long long)port).toString()); // wut?
H.SendRequest(conn);
// TODO: get response?
H.Clean();
while (conn && (!conn.spool() || !H.Read(conn))){}// ehm...
// std::cout << "leh vomi: "<<H.body <<std::endl;
// DEBUG_MSG(DLVL_INFO, "zut: %s", H.body.c_str());
// strBuf[tempID].append(H.body);
if (!H.body.size()){
DEBUG_MSG(DLVL_FAIL, "No data downloaded from %s", H.url.c_str());
FAIL_MSG("No data downloaded from %s", H.url.c_str());
break;
}
size_t beforeParse = H.body.size();
@ -628,11 +586,12 @@ int main2(int argc, char **argv){
if (mp4Data.isType("mdat")){mdatSeen = true;}
}
if (!mdatSeen){
DEBUG_MSG(DLVL_FAIL, "No mdat present. Sadface. :-(");
FAIL_MSG("No mdat present. Sadface. :-(");
break;
}
if (H.body.size()){
DEBUG_MSG(DLVL_FAIL, "%lu bytes left in body. Assuming horrible things...", H.body.size()); //,H.body.c_str());
FAIL_MSG("%lu bytes left in body. Assuming horrible things...",
H.body.size()); //,H.body.c_str());
std::cerr << H.body << std::endl;
if (beforeParse == H.body.size()){break;}
}

View file

@ -35,7 +35,7 @@ bool AnalyserDTSC::parsePacket(){
}
P.reInit(conn);
if (conn && !P){
FAIL_MSG("Invalid DTSC packet @ byte %llu", totalBytes)
FAIL_MSG("Invalid DTSC packet @ byte %" PRIu64, totalBytes)
return false;
}
if (!conn && !P){
@ -70,8 +70,7 @@ bool AnalyserDTSC::parsePacket(){
case DTSC::DTSC_HEAD:{
if (detail >= 3){
std::cout << "DTSC header: ";
DTSC::Meta(P).toPrettyString(
std::cout, 0, (detail == 3 ? 0 : (detail == 4 ? 0x01 : (detail == 5 ? 0x03 : 0x07))));
std::cout << DTSC::Meta("", P.getScan()).toPrettyString();
}
if (detail == 2){std::cout << "DTSC header: " << P.getScan().toPrettyString() << std::endl;}
if (detail == 1){
@ -79,30 +78,34 @@ bool AnalyserDTSC::parsePacket(){
bool hasAAC = false;
JSON::Value result;
std::stringstream issues;
DTSC::Meta M(P);
for (std::map<unsigned int, DTSC::Track>::iterator it = M.tracks.begin(); it != M.tracks.end(); it++){
DTSC::Meta M("", P.getScan());
std::set<size_t> validTracks = M.getValidTracks();
for (std::set<size_t>::iterator it = validTracks.begin(); it != validTracks.end(); it++){
std::string codec = M.getCodec(*it);
JSON::Value track;
track["kbits"] = (uint64_t)((double)it->second.bps * 8 / 1024);
track["codec"] = it->second.codec;
track["kbits"] = M.getBps(*it) * 8 / 1024;
track["codec"] = codec;
uint32_t shrtest_key = 0xFFFFFFFFul;
uint32_t longest_key = 0;
uint32_t shrtest_prt = 0xFFFFFFFFul;
uint32_t longest_prt = 0;
uint32_t shrtest_cnt = 0xFFFFFFFFul;
uint32_t longest_cnt = 0;
for (std::deque<DTSC::Key>::iterator k = it->second.keys.begin(); k != it->second.keys.end(); k++){
if (!k->getLength()){continue;}
if (k->getLength() > longest_key){longest_key = k->getLength();}
if (k->getLength() < shrtest_key){shrtest_key = k->getLength();}
if (k->getParts() > longest_cnt){longest_cnt = k->getParts();}
if (k->getParts() < shrtest_cnt){shrtest_cnt = k->getParts();}
if (k->getParts()){
if ((k->getLength() / k->getParts()) > longest_prt){
longest_prt = (k->getLength() / k->getParts());
}
if ((k->getLength() / k->getParts()) < shrtest_prt){
shrtest_prt = (k->getLength() / k->getParts());
}
DTSC::Keys keys(M.keys(*it));
uint32_t firstKey = keys.getFirstValid();
uint32_t endKey = keys.getEndValid();
for (int i = firstKey; i < endKey; i++){
uint64_t keyDuration = keys.getDuration(i);
uint64_t keyParts = keys.getParts(i);
if (!keyDuration){continue;}
if (keyDuration > longest_key){longest_key = keyDuration;}
if (keyDuration < shrtest_key){shrtest_key = keyDuration;}
if (keyParts > longest_cnt){longest_cnt = keyParts;}
if (keyParts < shrtest_cnt){shrtest_cnt = keyParts;}
if (keyParts){
if ((keyDuration / keyParts) > longest_prt){longest_prt = (keyDuration / keyParts);}
if ((keyDuration / keyParts) < shrtest_prt){shrtest_prt = (keyDuration / keyParts);}
}
}
track["keys"]["ms_min"] = shrtest_key;
@ -112,28 +115,28 @@ bool AnalyserDTSC::parsePacket(){
track["keys"]["frames_min"] = shrtest_cnt;
track["keys"]["frames_max"] = longest_cnt;
if (longest_prt > 500){
issues << "unstable connection (" << longest_prt << "ms " << it->second.codec << " frame)! ";
issues << "unstable connection (" << longest_prt << "ms " << codec << " frame)! ";
}
if (shrtest_cnt < 6){
issues << "unstable connection (" << shrtest_cnt << " " << it->second.codec << " frames in key)! ";
issues << "unstable connection (" << shrtest_cnt << " " << codec << " frames in key)! ";
}
if (it->second.codec == "AAC"){hasAAC = true;}
if (it->second.codec == "H264"){hasH264 = true;}
if (it->second.type == "video"){
track["width"] = it->second.width;
track["height"] = it->second.height;
track["fpks"] = it->second.fpks;
if (it->second.codec == "H264"){
if (codec == "AAC"){hasAAC = true;}
if (codec == "H264"){hasH264 = true;}
if (M.getType(*it) == "video"){
track["width"] = M.getWidth(*it);
track["height"] = M.getHeight(*it);
track["fpks"] = M.getFpks(*it);
if (codec == "H264"){
h264::sequenceParameterSet sps;
sps.fromDTSCInit(it->second.init);
sps.fromDTSCInit(M.getInit(*it));
h264::SPSMeta spsData = sps.getCharacteristics();
track["h264"]["profile"] = spsData.profile;
track["h264"]["level"] = spsData.level;
}
}
result[it->second.getWritableIdentifier()] = track;
result[M.getTrackIdentifier(*it)] = track;
}
if ((hasAAC || hasH264) && M.tracks.size() > 1){
if (hasAAC || hasH264){
if (!hasAAC){issues << "HLS no audio!";}
if (!hasH264){issues << "HLS no video!";}
}
@ -147,7 +150,7 @@ bool AnalyserDTSC::parsePacket(){
if (detail >= 2){std::cout << "DTCM command: " << P.getScan().toPrettyString() << std::endl;}
break;
}
default: FAIL_MSG("Invalid DTSC packet @ byte %llu", totalBytes); break;
default: FAIL_MSG("Invalid DTSC packet @ byte %" PRIu64, totalBytes); break;
}
totalBytes += P.getDataLen();

View file

@ -35,7 +35,7 @@ bool AnalyserEBML::parsePacket(){
if (dataBuffer.size() < neededBytes()){return false;}
EBML::Element E(dataBuffer.data(), true);
HIGH_MSG("Read an element at position %d", prePos);
HIGH_MSG("Read an element at position %zu", prePos);
if (detail >= 2){std::cout << E.toPrettyString(depthStash.size() * 2, detail);}
switch (E.getID()){
case EBML::EID_SEGMENT:

View file

@ -11,7 +11,7 @@ private:
uint64_t neededBytes();
std::string dataBuffer;
uint64_t curPos;
uint64_t prePos;
size_t prePos;
uint64_t segmentOffset;
uint32_t lastSeekId;
uint64_t lastSeekPos;

View file

@ -32,7 +32,8 @@ bool AnalyserFLV::parsePacket(){
// If we arrive here, we've loaded a FLV packet
if (!filter || filter == flvData.data[0]){
DETAIL_MED("[%llu+%llu] %s", flvData.tagTime(), flvData.offset(), flvData.tagType().c_str());
DETAIL_MED("[%" PRIu64 "+%" PRId64 "] %s", flvData.tagTime(), flvData.offset(),
flvData.tagType().c_str());
}
mediaTime = flvData.tagTime();
return true;

View file

@ -9,5 +9,5 @@ public:
private:
FLV::Tag flvData;
long long filter;
int64_t filter;
};

View file

@ -39,7 +39,7 @@ bool AnalyserH264::parsePacket(){
size = 0;
nalPtr = h264::nalFactory(dataBuffer.data(), dataBuffer.size(), size, !sizePrepended);
if (nalPtr){
HIGH_MSG("Read a %lu-byte NAL unit at position %llu", size, prePos);
HIGH_MSG("Read a %lu-byte NAL unit at position %" PRIu64, size, prePos);
if (detail >= 2){nalPtr->toPrettyString(std::cout);}
dataBuffer.erase(0, size); // erase the NAL unit we just read
prePos += size;
@ -47,7 +47,7 @@ bool AnalyserH264::parsePacket(){
///\TODO update mediaTime with current timestamp
}while (nalPtr);
if (!nalPtr){
FAIL_MSG("Could not read a NAL unit at position %llu", prePos);
FAIL_MSG("Could not read a NAL unit at position %" PRIu64, prePos);
return false;
}
return true;

View file

@ -40,7 +40,7 @@ void AnalyserHLS::getParts(const std::string &body){
}
if (!parsedPart || no > parsedPart){
HTTP::URL newURL = root.link(line);
INFO_MSG("Discovered #%llu: %s", no, newURL.getUrl().c_str());
INFO_MSG("Discovered #%" PRIu64 ": %s", no, newURL.getUrl().c_str());
parts.push_back(HLSPart(newURL, no, durat));
}
++no;
@ -111,7 +111,7 @@ bool AnalyserHLS::parsePacket(){
}
}
if (DL.data().size() % 188){
FAIL_MSG("Expected a multiple of 188 bytes, received %d bytes", DL.data().size());
FAIL_MSG("Expected a multiple of 188 bytes, received %zu bytes", DL.data().size());
return false;
}
parsedPart = part.no;
@ -124,8 +124,8 @@ bool AnalyserHLS::parsePacket(){
// Hm. I guess we had no parts to get.
if (refreshAt && refreshAt > Util::bootSecs()){
// We're getting a live stream. Let's wait and check again.
uint32_t sleepSecs = (refreshAt - Util::bootSecs());
INFO_MSG("Sleeping for %lu seconds", sleepSecs);
uint64_t sleepSecs = (refreshAt - Util::bootSecs());
INFO_MSG("Sleeping for %" PRIu64 " seconds", sleepSecs);
Util::sleep(sleepSecs * 1000);
}
// The non-live case is already handled in isOpen()

View file

@ -1,4 +1,5 @@
#include "analyser_mp4.h"
#include <mist/bitfields.h>
void AnalyserMP4::init(Util::Config &conf){
Analyser::init(conf);
@ -22,23 +23,21 @@ bool AnalyserMP4::parsePacket(){
}
if (mp4Data.read(mp4Buffer)){
INFO_MSG("Read a box at position %d", prePos);
INFO_MSG("Read a box at position %" PRIu64, prePos);
if (detail >= 2){std::cout << mp4Data.toPrettyString(0) << std::endl;}
///\TODO update mediaTime with the current timestamp
return true;
}
FAIL_MSG("Could not read box at position %llu", prePos);
FAIL_MSG("Could not read box at position %" PRIu64, prePos);
return false;
}
/// Calculates how many bytes we need to read a whole box.
uint64_t AnalyserMP4::neededBytes(){
if (mp4Buffer.size() < 4){return 4;}
uint64_t size = ntohl(((int *)mp4Buffer.data())[0]);
uint64_t size = Bit::btohl(mp4Buffer.data());
if (size != 1){return size;}
if (mp4Buffer.size() < 16){return 16;}
size = 0 + ntohl(((int *)mp4Buffer.data())[2]);
size <<= 32;
size += ntohl(((int *)mp4Buffer.data())[3]);
size = Bit::btohll(mp4Buffer.data() + 8);
return size;
}

View file

@ -28,18 +28,18 @@ bool AnalyserOGG::parsePacket(){
sn2Codec[oggPage.getBitstreamSerialNumber()] = "Opus";
}
if (sn2Codec[oggPage.getBitstreamSerialNumber()] != ""){
INFO_MSG("Bitstream %llu recognized as %s", oggPage.getBitstreamSerialNumber(),
INFO_MSG("Bitstream %" PRIu64 " recognized as %s", oggPage.getBitstreamSerialNumber(),
sn2Codec[oggPage.getBitstreamSerialNumber()].c_str());
}else{
WARN_MSG("Bitstream %llu not recognized!", oggPage.getBitstreamSerialNumber());
WARN_MSG("Bitstream %" PRIu64 " not recognized!", oggPage.getBitstreamSerialNumber());
}
}
if (sn2Codec[oggPage.getBitstreamSerialNumber()] == "Theora"){
if (detail >= 2){std::cout << " Theora data" << std::endl;}
static unsigned int numParts = 0;
static unsigned int keyCount = 0;
for (unsigned int i = 0; i < oggPage.getAllSegments().size(); i++){
static size_t numParts = 0;
static size_t keyCount = 0;
for (size_t i = 0; i < oggPage.getAllSegments().size(); i++){
theora::header tmpHeader((char *)oggPage.getSegment(i), oggPage.getAllSegments()[i].size());
if (tmpHeader.isHeader()){
if (tmpHeader.getHeaderType() == 0){kfgshift = tmpHeader.getKFGShift();}

View file

@ -8,8 +8,8 @@ public:
static void init(Util::Config &conf);
private:
std::map<int, std::string> sn2Codec;
std::map<uint64_t, std::string> sn2Codec;
std::string oggBuffer;
OGG::Page oggPage;
int kfgshift;
uint16_t kfgshift;
};

View file

@ -26,7 +26,7 @@ bool AnalyserRIFF::parsePacket(){
if (dataBuffer.size() < 8){return false;}
RIFF::Chunk C(dataBuffer.data(), dataBuffer.size());
INFO_MSG("Read a chunk at position %d", prePos);
INFO_MSG("Read a chunk at position %" PRIu64, prePos);
if (detail >= 2){C.toPrettyString(std::cout);}
///\TODO update mediaTime with the current timestamp
if (C){

View file

@ -2,6 +2,7 @@
/// Debugging tool for RTMP data.
#include "analyser_rtmp.h"
#include <mist/bitfields.h>
void AnalyserRTMP::init(Util::Config &conf){
Analyser::init(conf);
@ -42,23 +43,19 @@ bool AnalyserRTMP::parsePacket(){
// While we can't parse a packet,
while (!next.Parse(strbuf)){
// fill our internal buffer "strbuf" in (up to) 1024 byte chunks
if (std::cin.good()){
unsigned int charCount = 0;
std::string tmpbuffer;
tmpbuffer.reserve(1024);
while (std::cin.good() && charCount < 1024){
char newchar = std::cin.get();
if (std::cin.good()){
tmpbuffer += newchar;
++read_in;
++charCount;
}
if (!std::cin.good()){return false;}
size_t charCount = 0;
std::string tmpbuffer;
tmpbuffer.reserve(1024);
while (std::cin.good() && charCount < 1024){
char newchar = std::cin.get();
if (std::cin.good()){
tmpbuffer += newchar;
++read_in;
++charCount;
}
strbuf.append(tmpbuffer);
}else{
// if we can't fill the buffer, and have no parsable packet(s), return false
return false;
}
strbuf.append(tmpbuffer);
}
// We now know for sure that we've parsed a packet
@ -72,71 +69,66 @@ bool AnalyserRTMP::parsePacket(){
break; // happens when connection breaks unexpectedly
case 1: // set chunk size
RTMPStream::chunk_rec_max = ntohl(*(int *)next.data.c_str());
DETAIL_MED("CTRL: Set chunk size: %i", RTMPStream::chunk_rec_max);
DETAIL_MED("CTRL: Set chunk size: %" PRIu64, RTMPStream::chunk_rec_max);
break;
case 2: // abort message - we ignore this one
DETAIL_MED("CTRL: Abort message: %i", ntohl(*(int *)next.data.c_str()));
DETAIL_MED("CTRL: Abort message: %" PRIu32, Bit::btohl(next.data.data()));
// 4 bytes of stream id to drop
break;
case 3: // ack
RTMPStream::snd_window_at = ntohl(*(int *)next.data.c_str());
DETAIL_MED("CTRL: Acknowledgement: %i", RTMPStream::snd_window_at);
RTMPStream::snd_window_at = Bit::btohl(next.data.data());
DETAIL_MED("CTRL: Acknowledgement: %" PRIu64, RTMPStream::snd_window_at);
break;
case 4:{
short int ucmtype = ntohs(*(short int *)next.data.c_str());
int16_t ucmtype = Bit::btohs(next.data.data());
switch (ucmtype){
case 0:
DETAIL_MED("CTRL: User control message: stream begin %u",
ntohl(*(unsigned int *)(next.data.c_str() + 2)));
DETAIL_MED("CTRL: User control message: stream begin %" PRIu32, Bit::btohl(next.data.data() + 2));
break;
case 1:
DETAIL_MED("CTRL: User control message: stream EOF %u", ntohl(*(unsigned int *)(next.data.c_str() + 2)));
DETAIL_MED("CTRL: User control message: stream EOF %" PRIu32, Bit::btohl(next.data.data() + 2));
break;
case 2:
DETAIL_MED("CTRL: User control message: stream dry %u", ntohl(*(unsigned int *)(next.data.c_str() + 2)));
DETAIL_MED("CTRL: User control message: stream dry %" PRIu32, Bit::btohl(next.data.data() + 2));
break;
case 3:
DETAIL_MED("CTRL: User control message: setbufferlen %u",
ntohl(*(unsigned int *)(next.data.c_str() + 2)));
DETAIL_MED("CTRL: User control message: setbufferlen %" PRIu32, Bit::btohl(next.data.data() + 2));
break;
case 4:
DETAIL_MED("CTRL: User control message: streamisrecorded %u",
ntohl(*(unsigned int *)(next.data.c_str() + 2)));
DETAIL_MED("CTRL: User control message: streamisrecorded %" PRIu32, Bit::btohl(next.data.data() + 2));
break;
case 6:
DETAIL_MED("CTRL: User control message: pingrequest %u",
ntohl(*(unsigned int *)(next.data.c_str() + 2)));
DETAIL_MED("CTRL: User control message: pingrequest %" PRIu32, Bit::btohl(next.data.data() + 2));
break;
case 7:
DETAIL_MED("CTRL: User control message: pingresponse %u",
ntohl(*(unsigned int *)(next.data.c_str() + 2)));
DETAIL_MED("CTRL: User control message: pingresponse %" PRIu32, Bit::btohl(next.data.data() + 2));
break;
case 31:
case 32:
// don't know, but not interesting anyway
// don't know, but not interes ting anyway
break;
default:
DETAIL_LOW("CTRL: User control message: UNKNOWN %hu - %u", ucmtype,
ntohl(*(unsigned int *)(next.data.c_str() + 2)));
DETAIL_LOW("CTRL: User control message: UNKNOWN %" PRId16 " - %" PRIu32, ucmtype,
Bit::btohl(next.data.data() + 2));
break;
}
}break;
case 5: // window size of other end
RTMPStream::rec_window_size = ntohl(*(int *)next.data.c_str());
RTMPStream::rec_window_size = Bit::btohl(next.data.data());
RTMPStream::rec_window_at = RTMPStream::rec_cnt;
DETAIL_MED("CTRL: Window size: %i", RTMPStream::rec_window_size);
DETAIL_MED("CTRL: Window size: %" PRIu64, RTMPStream::rec_window_size);
break;
case 6:
RTMPStream::snd_window_size = ntohl(*(int *)next.data.c_str());
RTMPStream::snd_window_size = Bit::btohl(next.data.data());
// 4 bytes window size, 1 byte limit type (ignored)
DETAIL_MED("CTRL: Set peer bandwidth: %i", RTMPStream::snd_window_size);
DETAIL_MED("CTRL: Set peer bandwidth: %" PRIu64, RTMPStream::snd_window_size);
break;
case 8:
case 9:
if (detail >= 4 || reconstruct.good() || validate){
F.ChunkLoader(next);
mediaTime = F.tagTime();
DETAIL_VHI("[%llu+%llu] %s", F.tagTime(), F.offset(), F.tagType().c_str());
DETAIL_VHI("[%" PRIu64 "+%" PRId64 "] %s", F.tagTime(), F.offset(), F.tagType().c_str());
if (reconstruct.good()){reconstruct.write(F.data, F.len);}
}
break;

View file

@ -7,7 +7,7 @@ class AnalyserRTMP : public Analyser{
private:
RTMPStream::Chunk next; ///< Holds the most recently parsed RTMP chunk
FLV::Tag F; ///< Holds the most recently created FLV packet
unsigned int read_in; ///< Amounts of bytes read to fill 'strbuf' so far
size_t read_in; ///< Amounts of bytes read to fill 'strbuf' so far
Socket::Buffer strbuf; ///< Internal buffer from where 'next' is filled
AMF::Object amfdata; ///< Last read AMF object
AMF::Object3 amf3data; ///< Last read AMF3 object

View file

@ -14,9 +14,9 @@ void AnalyserRTSP::incoming(const DTSC::Packet &pkt){
char *dataPtr;
size_t dataSize;
pkt.getString("data", dataPtr, dataSize);
DETAIL_MED("Received %ub %sfor track %lu (%s) @ %llums", dataSize,
DETAIL_MED("Received %zub %sfor track %zu (%s) @ %" PRIu64 "ms", dataSize,
pkt.getFlag("keyframe") ? "keyframe " : "", pkt.getTrackId(),
myMeta.tracks[pkt.getTrackId()].getIdentifier().c_str(), pkt.getTime());
myMeta.getTrackIdentifier(pkt.getTrackId()).c_str(), pkt.getTime());
if (detail >= 8){
for (uint32_t i = 0; i < dataSize; ++i){
std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)dataPtr[i] << " ";
@ -58,9 +58,9 @@ bool AnalyserRTSP::parsePacket(){
return true;
}
if (HTTP.hasHeader("Transport")){
uint32_t trackNo = sdpState.parseSetup(HTTP, "", "");
size_t trackNo = sdpState.parseSetup(HTTP, "", "");
if (trackNo){
DETAIL_MED("Parsed transport for track: %lu", trackNo);
DETAIL_MED("Parsed transport for track: %zu", trackNo);
}else{
DETAIL_MED("Could not parse transport string!");
}
@ -95,15 +95,15 @@ bool AnalyserRTSP::parsePacket(){
RTP::Packet pkt(tcpPacket.data() + 4, len);
uint8_t chan = tcpHead.data()[1];
uint32_t trackNo = sdpState.getTrackNoForChannel(chan);
DETAIL_HI("Received %ub RTP packet #%u on channel %u, time %llu", len,
(unsigned int)pkt.getSequence(), chan, pkt.getTimeStamp());
DETAIL_HI("Received %ub RTP packet #%u on channel %u, time %" PRIu32, len, pkt.getSequence(),
chan, pkt.getTimeStamp());
if (!trackNo && (chan % 2) != 1){
DETAIL_MED("Received packet for unknown track number on channel %u", chan);
}
if (trackNo){sdpState.tracks[trackNo].sorter.rtpSeq = pkt.getSequence();}
if (detail >= 10){
char *pl = pkt.getPayload();
const char *pl = pkt.getPayload();
uint32_t payLen = pkt.getPayloadSize();
for (uint32_t i = 0; i < payLen; ++i){
std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)pl[i] << " ";

View file

@ -46,7 +46,7 @@ bool AnalyserTS::parsePacket(){
static char packetPtr[188];
std::cin.read(packetPtr, 188);
if (std::cin.gcount() != 188){return false;}
DONTEVEN_MSG("Reading from position %llu", bytes);
DONTEVEN_MSG("Reading from position %" PRIu64, bytes);
bytes += 188;
if (!packet.FromPointer(packetPtr)){return false;}
if (detail){
@ -74,15 +74,15 @@ bool AnalyserTS::parsePacket(){
}
AnalyserTS::~AnalyserTS(){
for (std::map<unsigned long long, std::string>::iterator it = payloads.begin(); it != payloads.end(); it++){
for (std::map<size_t, std::string>::iterator it = payloads.begin(); it != payloads.end(); it++){
if ((detail & 1) && (!pidOnly || it->first == pidOnly)){
std::cout << printPES(it->second, it->first);
}
}
}
std::string AnalyserTS::printPES(const std::string &d, unsigned long PID){
unsigned int headSize = 0;
std::string AnalyserTS::printPES(const std::string &d, size_t PID){
size_t headSize = 0;
std::stringstream res;
bool known = false;
res << "[PES " << PID << "]";
@ -98,7 +98,7 @@ std::string AnalyserTS::printPES(const std::string &d, unsigned long PID){
if (d[0] != 0 || d[1] != 0 || d[2] != 1){
res << " [!!! INVALID START CODE: " << (int)d[0] << " " << (int)d[1] << " " << (int)d[2] << " ]";
}
unsigned int padding = 0;
size_t padding = 0;
if (known){
if ((d[6] & 0xC0) != 0x80){res << " [!INVALID FIRST BITS!]";}
if (d[6] & 0x30){res << " [SCRAMBLED]";}
@ -144,19 +144,19 @@ std::string AnalyserTS::printPES(const std::string &d, unsigned long PID){
res << " [Padding: " << padding << "b]";
}
if (timeFlags & 0x02){
long long unsigned int time = (((unsigned int)d[9] & 0xE) >> 1);
uint64_t time = ((d[9] & 0xE) >> 1);
time <<= 15;
time |= ((unsigned int)d[10] << 7) | (((unsigned int)d[11] >> 1) & 0x7F);
time |= ((uint32_t)d[10] << 7) | ((d[11] >> 1) & 0x7F);
time <<= 15;
time |= ((unsigned int)d[12] << 7) | (((unsigned int)d[13] >> 1) & 0x7F);
time |= ((uint32_t)d[12] << 7) | ((d[13] >> 1) & 0x7F);
res << " [PTS " << ((double)time / 90000) << "s]";
}
if (timeFlags & 0x01){
long long unsigned int time = ((d[14] >> 1) & 0x07);
uint64_t time = ((d[14] >> 1) & 0x07);
time <<= 15;
time |= ((int)d[15] << 7) | (d[16] >> 1);
time |= ((uint32_t)d[15] << 7) | (d[16] >> 1);
time <<= 15;
time |= ((int)d[17] << 7) | (d[18] >> 1);
time |= ((uint32_t)d[17] << 7) | (d[18] >> 1);
res << " [DTS " << ((double)time / 90000) << "s]";
}
}
@ -169,12 +169,18 @@ std::string AnalyserTS::printPES(const std::string &d, unsigned long PID){
res << std::endl;
if (detail & 32){
unsigned int counter = 0;
for (unsigned int i = 9 + headSize + padding; i < d.size(); ++i){
size_t counter = 0;
for (size_t i = 9 + headSize + padding; i < d.size(); ++i){
if ((i < d.size() - 4) && d[i] == 0 && d[i + 1] == 0 && d[i + 2] == 0 && d[i + 3] == 1){
res << std::endl;
counter = 0;
}
if ((i < d.size() - 3) && d[i] == 0 && d[i + 1] == 0 && d[i + 2] == 1){
if (counter > 1){
res << std::endl << " ";
counter = 0;
}
}
res << std::hex << std::setw(2) << std::setfill('0') << (int)(d[i] & 0xff) << " ";
if ((counter) % 32 == 31){res << std::endl;}
counter++;

View file

@ -8,11 +8,11 @@ public:
~AnalyserTS();
bool parsePacket();
static void init(Util::Config &conf);
std::string printPES(const std::string &d, unsigned long PID);
std::string printPES(const std::string &d, size_t PID);
private:
std::map<unsigned long long, std::string> payloads;
uint32_t pidOnly;
std::map<size_t, std::string> payloads;
size_t pidOnly;
TS::Packet packet;
uint64_t bytes;
};

View file

@ -1,485 +0,0 @@
/// \file dash_analyzer.cpp
/// Contains the code for the DASH Analysing tool.
/// Currently, only mp4 is supported, and the xml parser assumes a representation id tag exists
#include <fstream>
#include <iostream>
#include <mist/config.h>
#include <mist/defines.h>
#include <mist/http_parser.h>
#include <mist/mp4.h>
#include <mist/mp4_generic.h>
#include <mist/timing.h>
#include <set>
#define OTHER 0x00
#define VIDEO 0x01
#define AUDIO 0x02
///\brief simple struct for storage of stream-specific data
struct StreamData{
long timeScale;
std::string media;
std::string initialization;
std::string initURL;
long trackID;
unsigned int adaptationSet;
unsigned char trackType;
};
StreamData tempSD; // temp global
///\brief another simple structure used for ordering byte seek positions.
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.timeScale) < (rhs.seekTime * timeScale)){
return true;
}else{
if ((seekTime * rhs.timeScale) == (rhs.seekTime * timeScale)){
if (adaptationSet < rhs.adaptationSet){
return true;
}else if (adaptationSet == rhs.adaptationSet){
if (trackID < rhs.trackID){return true;}
}
}
}
return false;
}
long timeScale;
long long unsigned int bytePos; /// ?
long long unsigned int seekTime; /// start
long long unsigned int duration; /// duration
unsigned int trackID; /// stores representation ID
unsigned int adaptationSet; /// stores type
unsigned char trackType; /// stores type
std::string url;
};
bool getDelimBlock(std::string &data, std::string name, size_t &blockStart, size_t &blockEnd, std::string delim){
size_t offset = data.find(name);
if (offset == std::string::npos){
return false; // name string not found.
}
// expected: delim character BEFORE blockstart.
offset--;
blockStart = data.find(delim, offset);
// DEBUG_MSG(DLVL_INFO, "offset: %i blockStart: %i ", offset, blockStart);
offset = blockStart + 1; // skip single character!
blockEnd = data.find(delim, offset);
// DEBUG_MSG(DLVL_INFO, "offset: %i blockEnd: %i ", offset, blockEnd);
if (blockStart == std::string::npos || blockEnd == std::string::npos){
return false; // no start/end quotes found
}
blockEnd++; // include delim
// DEBUG_MSG(DLVL_INFO, "getDelimPos: data.size() %i start %i end %i num %i", data.size(), blockStart,blockEnd,(blockEnd-blockStart) );
return true;
}
bool getValueBlock(std::string &data, std::string name, size_t &blockStart, size_t &blockEnd, std::string delim){
size_t offset = data.find(name);
if (offset == std::string::npos){
return false; // name string not found.
}
blockStart = data.find(delim, offset);
// DEBUG_MSG(DLVL_INFO, "offset: %i blockStart: %i ", offset, blockStart);
blockStart++; // clip off quote characters
offset = blockStart; // skip single character!
blockEnd = data.find(delim, offset);
// DEBUG_MSG(DLVL_INFO, "offset: %i blockEnd: %i ", offset, blockEnd);
if (blockStart == std::string::npos || blockEnd == std::string::npos){
return false; // no start/end quotes found
}
// DEBUG_MSG(DLVL_INFO, "getValueBlock: data.size() %i start %i end %i num %i", data.size(), blockStart,blockEnd,(blockEnd-blockStart) );
return true;
}
bool getString(std::string &data, std::string name, std::string &output){
size_t blockStart = 0;
size_t blockEnd = 0;
if (!getValueBlock(data, name, blockStart, blockEnd, "\"")){
// DEBUG_MSG(DLVL_FAIL, "could not find \"%s\" in data block", name.c_str());
return false; // could not find value in this data block.
}
// DEBUG_MSG(DLVL_INFO, "data.size() %i start %i end %i num %i", data.size(), blockStart,blockEnd,(blockEnd-blockStart) )
output = data.substr(blockStart, (blockEnd - blockStart));
// looks like this function is working as expected
// DEBUG_MSG(DLVL_INFO, "data in getstring %s", (data.substr(blockStart,(blockEnd-blockStart))).c_str());
return true;
}
bool getLong(std::string &data, std::string name, long &output){
size_t blockStart, blockEnd;
if (!getValueBlock(data, name, blockStart, blockEnd, "\"")){
// DEBUG_MSG(DLVL_FAIL, "could not find \"%s\" in data block", name.c_str());
return false; // could not find value in this data block.
}
// DEBUG_MSG(DLVL_INFO, "name: %s data in atol %s",name.c_str(), (data.substr(blockStart,(blockEnd-blockStart))).c_str());
output = atol((data.substr(blockStart, (blockEnd - blockStart))).c_str());
return true;
}
// block expecting separate name and /name occurence, or name and /> before another occurence of <.
bool getBlock(std::string &data, std::string name, int offset, size_t &blockStart, size_t &blockEnd){
blockStart = data.find("<" + name + ">", offset);
if (blockStart == std::string::npos){
blockStart = data.find("<" + name + " ", offset); // this considers both valid situations <name> and <name bla="bla"/>
}
if (blockStart == std::string::npos){
DEBUG_MSG(DLVL_INFO, "no block start found for name: %s at offset: %i", name.c_str(), offset);
return false;
}
blockEnd = data.find("/" + name + ">", blockStart);
if (blockEnd == std::string::npos){
blockEnd = data.find("/>", blockStart);
if (blockEnd == std::string::npos){
DEBUG_MSG(DLVL_INFO, "no block end found.");
return false;
}
size_t temp = data.find("<", blockStart + 1, (blockEnd - blockStart - 1)); // the +1 is to avoid re-interpreting the starting < //TODO!!
if (temp != std::string::npos){// all info is epxected between <name ... />
DEBUG_MSG(DLVL_FAIL, "block start found before block end. offset: %lu block: %s", temp, data.c_str());
return false;
}
// DEBUG_MSG(DLVL_FAIL, "special block end found");
blockEnd += 2; // position after />
}else{
blockEnd += name.size() + 2; // position after /name>
}
// DEBUG_MSG(DLVL_INFO, "getBlock: start: %i end: %i",blockStart,blockEnd);
return true;
}
bool parseAdaptationSet(std::string &data, std::set<seekPos> &currentPos){
// DEBUG_MSG(DLVL_INFO, "Parsing adaptationSet: %s", data.c_str());
size_t offset = 0;
size_t blockStart, blockEnd;
tempSD.trackType = OTHER;
// get value: mimetype //todo: handle this!
std::string mimeType;
if (!getString(data, "mimeType", mimeType)){// get first occurence of mimeType. --> this will break
// if multiple mimetypes should be read from this block
// because no offset is provided. solution: use this on a substring containing the desired information.
DEBUG_MSG(DLVL_FAIL, "mimeType not found");
return false;
}
DEBUG_MSG(DLVL_INFO, "mimeType: %s", mimeType.c_str()); // checked, OK
if (mimeType.find("video") != std::string::npos){tempSD.trackType = VIDEO;}
if (mimeType.find("audio") != std::string::npos){tempSD.trackType = AUDIO;}
if (tempSD.trackType == OTHER){
DEBUG_MSG(DLVL_FAIL, "no audio or video type found. giving up.");
return false;
}
// find an ID within this adaptationSet block.
if (!getBlock(data, (std::string) "Representation", offset, blockStart, blockEnd)){
DEBUG_MSG(DLVL_FAIL, "Representation not found");
return false;
}
// representation string
std::string block = data.substr(blockStart, (blockEnd - blockStart));
DEBUG_MSG(DLVL_INFO, "Representation block: %s", block.c_str());
// check if block is not junk?
if (!getLong(block, "id", tempSD.trackID)){
DEBUG_MSG(DLVL_FAIL, "Representation id not found in block %s", block.c_str());
return false;
}
DEBUG_MSG(DLVL_INFO, "Representation/id: %li", tempSD.trackID); // checked, OK
offset = 0;
// get values from SegmentTemplate
if (!getBlock(data, (std::string) "SegmentTemplate", offset, blockStart, blockEnd)){
DEBUG_MSG(DLVL_FAIL, "SegmentTemplate not found");
return false;
}
block = data.substr(blockStart, (blockEnd - blockStart));
// DEBUG_MSG(DLVL_INFO, "SegmentTemplate block: %s",block.c_str()); //OK
getLong(block, "timescale", tempSD.timeScale);
getString(block, "media", tempSD.media);
getString(block, "initialization", tempSD.initialization);
size_t tmpBlockStart = 0;
size_t tmpBlockEnd = 0;
if (!getDelimBlock(tempSD.media, "RepresentationID", tmpBlockStart, tmpBlockEnd, "$")){
DEBUG_MSG(DLVL_FAIL, "Failed to find and replace $RepresentationID$ in %s", tempSD.media.c_str());
return false;
}
tempSD.media.replace(tmpBlockStart, (tmpBlockEnd - tmpBlockStart), "%d");
if (!getDelimBlock(tempSD.media, "Time", tmpBlockStart, tmpBlockEnd, "$")){
DEBUG_MSG(DLVL_FAIL, "Failed to find and replace $Time$ in %s", tempSD.media.c_str());
return false;
}
tempSD.media.replace(tmpBlockStart, (tmpBlockEnd - tmpBlockStart), "%d");
if (!getDelimBlock(tempSD.initialization, "RepresentationID", tmpBlockStart, tmpBlockEnd, "$")){
DEBUG_MSG(DLVL_FAIL, "Failed to find and replace $RepresentationID$ in %s",
tempSD.initialization.c_str());
return false;
}
tempSD.initialization.replace(tmpBlockStart, (tmpBlockEnd - tmpBlockStart), "%d");
// get segment timeline block from within segment template:
size_t blockOffset = 0; // offset should be 0 because this is a new block
if (!getBlock(block, "SegmentTimeline", blockOffset, blockStart, blockEnd)){
DEBUG_MSG(DLVL_FAIL, "SegmentTimeline block not found");
return false;
}
std::string block2 = block.substr(blockStart, (blockEnd - blockStart)); // overwrites previous block (takes just the segmentTimeline part
// DEBUG_MSG(DLVL_INFO, "SegmentTimeline block: %s",block2.c_str()); //OK
int numS = 0;
offset = 0;
long long unsigned int totalDuration = 0;
long timeValue;
while (1){
if (!getBlock(block2, "S", offset, blockStart, blockEnd)){
if (numS == 0){
DEBUG_MSG(DLVL_FAIL, "no S found within SegmentTimeline");
return false;
}else{
DEBUG_MSG(DLVL_INFO, "all S found within SegmentTimeline %i", numS);
return true; // break; //escape from while loop (to return true)
}
}
numS++;
// stuff S data into: currentPos
// searching for t(start position)
std::string sBlock = block2.substr(blockStart, (blockEnd - blockStart));
// DEBUG_MSG(DLVL_INFO, "S found. offset: %i blockStart: %i blockend: %i block: %s",offset,blockStart, blockEnd, sBlock.c_str()); //OK!
if (getLong(sBlock, "t", timeValue)){
totalDuration = timeValue; // reset totalDuration to value of t
}
if (!getLong(sBlock, "d", timeValue)){// expected duration in every S.
DEBUG_MSG(DLVL_FAIL, "no d found within S");
return false;
}
// stuff data with old value (start of block)
// DEBUG_MSG(DLVL_INFO, "stuffing info from S into set");
seekPos thisPos;
thisPos.trackType = tempSD.trackType;
thisPos.trackID = tempSD.trackID;
thisPos.adaptationSet = tempSD.adaptationSet;
// thisPos.trackID=id;
thisPos.seekTime = totalDuration; // previous total duration is start time of this S.
thisPos.duration = timeValue;
thisPos.timeScale = tempSD.timeScale;
static char charBuf[512];
snprintf(charBuf, 512, tempSD.media.c_str(), tempSD.trackID, totalDuration);
thisPos.url.assign(charBuf);
// DEBUG_MSG(DLVL_INFO, "media url (from rep.ID %d, startTime %d): %s", tempSD.trackID, totalDuration,thisPos.url.c_str());
currentPos.insert(thisPos); // assumes insert copies all data in seekPos struct.
totalDuration += timeValue; // update totalDuration
offset = blockEnd; // blockEnd and blockStart are absolute values within string, offset is not relevant.
}
return true;
}
bool parseXML(std::string &body, std::set<seekPos> &currentPos, std::vector<StreamData> &streamData){
// for all adaptation sets
// representation ID
int numAdaptationSet = 0;
size_t currentOffset = 0;
size_t adaptationSetStart;
size_t adaptationSetEnd;
// DEBUG_MSG(DLVL_INFO, "body received: %s", body.c_str());
while (getBlock(body, "AdaptationSet", currentOffset, adaptationSetStart, adaptationSetEnd)){
tempSD.adaptationSet = numAdaptationSet;
numAdaptationSet++;
DEBUG_MSG(DLVL_INFO, "adaptationSet found. start: %lu end: %lu num: %lu ", adaptationSetStart,
adaptationSetEnd, (adaptationSetEnd - adaptationSetStart));
// get substring: from <adaptationSet... to /adaptationSet>
std::string adaptationSet = body.substr(adaptationSetStart, (adaptationSetEnd - adaptationSetStart));
// function was verified: output as expected.
if (!parseAdaptationSet(adaptationSet, currentPos)){
DEBUG_MSG(DLVL_FAIL, "parseAdaptationSet returned false."); // this also happens in the case
// of OTHER mimetype. in that case it might be desirable to continue searching for valid data instead of quitting.
return false;
}
streamData.push_back(tempSD); // put temp values into adaptation set vector
currentOffset = adaptationSetEnd; // the getblock function should make sure End is at the correct offset.
}
if (numAdaptationSet == 0){
DEBUG_MSG(DLVL_FAIL, "no adaptationSet found.");
return false;
}
DEBUG_MSG(DLVL_INFO, "all adaptation sets found. total: %i", numAdaptationSet);
return true;
}
int main(int argc, char **argv){
Util::Config conf = Util::Config(argv[0]);
conf.addOption("mode",
JSON::fromString("{\"long\":\"mode\", \"arg\":\"string\", \"short\":\"m\", "
"\"default\":\"analyse\", \"help\":\"What to do with the stream. "
"Valid modes are 'analyse', 'validate', 'output'.\"}"));
conf.addOption("url", JSON::fromString("{\"arg_num\":1, \"arg\":\"string\", \"help\":\"URL to "
"HLS stream index file to retrieve.\"}"));
conf.addOption("abort", JSON::fromString("{\"long\":\"abort\", \"short\":\"a\", "
"\"arg\":\"integer\", \"default\":-1, \"help\":\"Abort "
"after this many seconds of downloading. Negative "
"values mean unlimited, which is the default.\"}"));
conf.parseArgs(argc, argv);
conf.activate();
unsigned int port = 80;
std::string url = conf.getString("url");
if (url.substr(0, 7) != "http://"){
DEBUG_MSG(DLVL_FAIL, "The URL must start with http://");
return -1;
}
url = url.substr(7); // found problem if url is to short!! it gives out of range when entering http://meh.meh
std::string server = url.substr(0, url.find('/'));
url = url.substr(url.find('/'));
if (server.find(':') != std::string::npos){
port = atoi(server.substr(server.find(':') + 1).c_str());
server = server.substr(0, server.find(':'));
}
long long int startTime = Util::bootSecs();
long long int abortTime = conf.getInteger("abort");
Socket::Connection conn(server, port, false);
// url:
DEBUG_MSG(DLVL_INFO, "url %s server: %s port: %d", url.c_str(), server.c_str(), port);
std::string urlPrependStuff = url.substr(0, url.rfind("/") + 1);
DEBUG_MSG(DLVL_INFO, "prepend stuff: %s", urlPrependStuff.c_str());
if (!conn){conn.open(server, port, false);}
unsigned int pos = 0;
HTTP::Parser H;
H.url = url;
H.SetHeader("Host", server + ":" + JSON::Value((long long)port).toString());
H.SendRequest(conn);
H.Clean();
while (conn && (!conn.spool() || !H.Read(conn))){}
H.BuildResponse();
std::set<seekPos> currentPos;
std::vector<StreamData> streamData;
// DEBUG_MSG(DLVL_INFO, "body received: %s", H.body.c_str()); //keeps giving empty stuff :(
// DEBUG_MSG(DLVL_INFO, "url %s ", url.c_str());
// std::ifstream in(url.c_str());
// std::string s((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
if (!parseXML(H.body, currentPos, streamData)){
DEBUG_MSG(DLVL_FAIL, "Manifest parsing failed. body: \n %s", H.body.c_str());
if (conf.getString("mode") == "validate"){
long long int endTime = Util::bootSecs();
std::cout << startTime << ", " << endTime << ", " << (endTime - startTime) << ", " << pos << std::endl;
}
return -1;
}
H.Clean();
DEBUG_MSG(DLVL_INFO, "*********");
DEBUG_MSG(DLVL_INFO, "*SUMMARY*");
DEBUG_MSG(DLVL_INFO, "*********");
DEBUG_MSG(DLVL_INFO, "num streams: %lu", streamData.size());
for (unsigned int i = 0; i < streamData.size(); i++){
DEBUG_MSG(DLVL_INFO, "");
DEBUG_MSG(DLVL_INFO, "ID in vector %d", i);
DEBUG_MSG(DLVL_INFO, "trackID %ld", streamData[i].trackID);
DEBUG_MSG(DLVL_INFO, "adaptationSet %d", streamData[i].adaptationSet);
DEBUG_MSG(DLVL_INFO, "trackType (audio 0x02, video 0x01) %d", streamData[i].trackType);
DEBUG_MSG(DLVL_INFO, "TimeScale %ld", streamData[i].timeScale);
DEBUG_MSG(DLVL_INFO, "Media string %s", streamData[i].media.c_str());
DEBUG_MSG(DLVL_INFO, "Init string %s", streamData[i].initialization.c_str());
}
DEBUG_MSG(DLVL_INFO, "");
for (unsigned int i = 0; i < streamData.size(); i++){// get init url
static char charBuf[512];
snprintf(charBuf, 512, streamData[i].initialization.c_str(), streamData[i].trackID);
streamData[i].initURL.assign(charBuf);
DEBUG_MSG(DLVL_INFO, "init url for adaptationSet %d trackID %ld: %s ",
streamData[i].adaptationSet, streamData[i].trackID, streamData[i].initURL.c_str());
}
while (currentPos.size() && (abortTime <= 0 || Util::bootSecs() < startTime + abortTime)){
// DEBUG_MSG(DLVL_INFO, "next url: %s", currentPos.begin()->url.c_str());
// match adaptation set and track id?
int tempID = 0;
for (unsigned int i = 0; i < streamData.size(); i++){
if (streamData[i].trackID == currentPos.begin()->trackID &&
streamData[i].adaptationSet == currentPos.begin()->adaptationSet)
tempID = i;
}
if (!conn){conn.open(server, port, false);}
HTTP::Parser H;
H.url = urlPrependStuff;
H.url.append(currentPos.begin()->url);
DEBUG_MSG(DLVL_INFO, "Retrieving segment: %s (%llu-%llu)", H.url.c_str(),
currentPos.begin()->seekTime, currentPos.begin()->seekTime + currentPos.begin()->duration);
H.SetHeader("Host", server + ":" + JSON::Value((long long)port).toString()); // wut?
H.SendRequest(conn);
// TODO: get response?
H.Clean();
while (conn && (!conn.spool() || !H.Read(conn))){}// ehm...
// std::cout << "leh vomi: "<<H.body <<std::endl;
// DEBUG_MSG(DLVL_INFO, "zut: %s", H.body.c_str());
// strBuf[tempID].append(H.body);
if (!H.body.size()){
DEBUG_MSG(DLVL_FAIL, "No data downloaded from %s", H.url.c_str());
break;
}
size_t beforeParse = H.body.size();
MP4::Box mp4Data;
bool mdatSeen = false;
while (mp4Data.read(H.body)){
if (mp4Data.isType("mdat")){mdatSeen = true;}
}
if (!mdatSeen){
DEBUG_MSG(DLVL_FAIL, "No mdat present. Sadface. :-(");
break;
}
if (H.body.size()){
DEBUG_MSG(DLVL_FAIL, "%lu bytes left in body. Assuming horrible things...", H.body.size()); //,H.body.c_str());
std::cerr << H.body << std::endl;
if (beforeParse == H.body.size()){break;}
}
H.Clean();
pos = 1000 * (currentPos.begin()->seekTime + currentPos.begin()->duration) / streamData[tempID].timeScale;
if (conf.getString("mode") == "validate" && (Util::bootSecs() - startTime + 5) * 1000 < pos){
Util::wait(pos - (Util::bootSecs() - startTime + 5) * 1000);
}
currentPos.erase(currentPos.begin());
}
if (conf.getString("mode") == "validate"){
long long int endTime = Util::bootSecs();
std::cout << startTime << ", " << endTime << ", " << (endTime - startTime) << ", " << pos << std::endl;
}
return 0;
}

View file

@ -0,0 +1,78 @@
#include <cstdio>
#include <iostream>
#include <string>
#include <mist/bitfields.h>
#include <mist/config.h>
#include <mist/defines.h>
#include <mist/h264.h>
///\brief Holds everything unique to the analysers.
namespace Analysers{
int analyseH264(Util::Config conf){
FILE *F = fopen(conf.getString("filename").c_str(), "r+b");
if (!F){FAIL_MSG("No such file");}
h264::nalUnit *nalPtr = h264::nalFactory(F);
while (nalPtr){
if (nalPtr->getType() == 0x07){
Utils::bitstream br;
br << nalPtr->payload;
Utils::bitWriter bw;
bw.append(br.get(8), 8); // nalType
bw.append(br.get(8), 8); // profile_idc
bw.append(br.get(8), 8); // constraint flags
bw.append(br.get(8), 8); // level_idc
br.getUExpGolomb();
bw.appendUExpGolomb(0); // seq_parameter_set_id
while (br.size() >= 64){bw.append(br.get(64), 64);}
size_t remainder = br.size();
if (remainder){bw.append(br.get(remainder), remainder);}
nalPtr->payload = bw.str();
}else if (nalPtr->getType() == 0x08){
Utils::bitstream br;
br << nalPtr->payload;
Utils::bitWriter bw;
bw.append(br.get(8), 8); // nalType
br.getUExpGolomb();
bw.appendUExpGolomb(0); // pic_parameter_set_id
br.getUExpGolomb();
bw.appendUExpGolomb(0); // seq_parameter_set_id
while (br.size() >= 64){bw.append(br.get(64), 64);}
size_t remainder = br.size();
if (remainder){bw.append(br.get(remainder), remainder);}
nalPtr->payload = bw.str();
}else if (nalPtr->getType() == 0x01 || nalPtr->getType() == 0x05 || nalPtr->getType() == 0x19){
Utils::bitstream br;
br << nalPtr->payload;
Utils::bitWriter bw;
bw.append(br.get(8), 8); // nalType
bw.appendUExpGolomb(br.getUExpGolomb()); // first_mb_in_slice
bw.appendUExpGolomb(br.getUExpGolomb()); // slice_type
br.getUExpGolomb();
bw.appendUExpGolomb(0); // pic_parameter_set_id
while (br.size() >= 64){bw.append(br.get(64), 64);}
size_t remainder = br.size();
if (remainder){bw.append(br.get(remainder), remainder);}
nalPtr->payload = bw.str();
}
nalPtr->write(std::cout);
delete nalPtr;
nalPtr = h264::nalFactory(F);
}
return 0;
}
}// namespace Analysers
int main(int argc, char **argv){
Util::Config conf = Util::Config(argv[0]);
conf.addOption("filename", JSON::fromString("{\"arg_num\":1, \"arg\":\"string\", \"help\":\"Full "
"path of the file to analyse.\"}"));
conf.parseArgs(argc, argv);
return Analysers::analyseH264(conf);
}