New Meta commit
This commit is contained in:
parent
fccf66fba2
commit
2b99f2f5ea
183 changed files with 13333 additions and 14421 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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> ¤tPos){
|
||||
// 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> ¤tPos){
|
|||
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> ¤tPos){
|
|||
// 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> ¤tPos){
|
|||
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> ¤tPos){
|
|||
// 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> ¤tPos){
|
|||
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> ¤tPos, 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;}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -9,5 +9,5 @@ public:
|
|||
|
||||
private:
|
||||
FLV::Tag flvData;
|
||||
long long filter;
|
||||
int64_t filter;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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] << " ";
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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> ¤tPos){
|
||||
// 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> ¤tPos, 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;
|
||||
}
|
78
src/analysers/h264_translate.cpp
Normal file
78
src/analysers/h264_translate.cpp
Normal 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);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue