LTS Commits
This commit is contained in:
parent
f24d97b510
commit
4bdbd82f66
72 changed files with 8245 additions and 105 deletions
|
@ -96,6 +96,7 @@ namespace Info {
|
|||
fileSpecs["tracks"][trackIt->first].removeMember("keys");
|
||||
fileSpecs["tracks"][trackIt->first].removeMember("keysizes");
|
||||
fileSpecs["tracks"][trackIt->first].removeMember("parts");
|
||||
fileSpecs["tracks"][trackIt->first].removeMember("ivecs");/*LTS*/
|
||||
}
|
||||
}
|
||||
printf( "%s", fileSpecs.toString().c_str() );
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <string.h>
|
||||
#include <mist/mp4.h>
|
||||
#include <mist/config.h>
|
||||
#include <mist/defines.h>
|
||||
|
||||
///\brief Holds everything unique to the analysers.
|
||||
namespace Analysers {
|
||||
|
@ -25,9 +26,15 @@ namespace Analysers {
|
|||
mp4Buffer.erase(mp4Buffer.size() - 1, 1);
|
||||
|
||||
MP4::Box mp4Data;
|
||||
int dataSize = mp4Buffer.size();
|
||||
int curPos = 0;
|
||||
while (mp4Data.read(mp4Buffer)){
|
||||
DEBUG_MSG(DLVL_DEVEL, "Read a box at position %d", curPos);
|
||||
std::cerr << mp4Data.toPrettyString(0) << std::endl;
|
||||
curPos += dataSize - mp4Buffer.size();
|
||||
dataSize = mp4Buffer.size();
|
||||
}
|
||||
DEBUG_MSG(DLVL_DEVEL, "Stopped parsing at position %d", curPos);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
209
src/analysers/rtp_analyser.cpp
Normal file
209
src/analysers/rtp_analyser.cpp
Normal file
|
@ -0,0 +1,209 @@
|
|||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <mist/socket.h>
|
||||
#include <mist/config.h>
|
||||
#include <mist/rtp.h>
|
||||
#include <mist/http_parser.h>
|
||||
|
||||
//rtsp://krabs:1935/vod/gear1.mp4
|
||||
|
||||
namespace Analysers {
|
||||
int analyseRTP(){
|
||||
Socket::Connection conn("localhost", 554, true);
|
||||
//Socket::Connection conn("krabs", 1935, true);
|
||||
HTTP::Parser HTTP_R, HTTP_S;//HTTP Receiver en HTTP Sender.
|
||||
int step = 0;
|
||||
/*1 = sent describe
|
||||
2 = recd describe
|
||||
3 = sent setup
|
||||
4 = received setup
|
||||
5 = sent play"*/
|
||||
std::vector<std::string> tracks;
|
||||
std::vector<Socket::UDPConnection> connections;
|
||||
unsigned int trackIt = 0;
|
||||
while (conn.connected()){
|
||||
// std::cerr << "loopy" << std::endl;
|
||||
if(step == 0){
|
||||
HTTP_S.protocol = "RTSP/1.0";
|
||||
HTTP_S.method = "DESCRIBE";
|
||||
//rtsp://krabs:1935/vod/gear1.mp4
|
||||
//rtsp://localhost/g1
|
||||
HTTP_S.url = "rtsp://localhost/steers";
|
||||
//HTTP_S.url = "rtsp://krabs:1935/vod/steers.mp4";
|
||||
HTTP_S.SetHeader("CSeq",1);
|
||||
HTTP_S.SendRequest(conn);
|
||||
step++;
|
||||
|
||||
}else if(step == 2){
|
||||
std::cerr <<"setup " << tracks[trackIt] << std::endl;
|
||||
HTTP_S.method = "SETUP";
|
||||
HTTP_S.url = "rtsp://localhost/steers/" + tracks[trackIt];
|
||||
//HTTP_S.url = "rtsp://krabs:1935/vod/steers.mp4/" + tracks[trackIt];
|
||||
HTTP_S.SetHeader("CSeq",2+trackIt);
|
||||
std::stringstream ss;
|
||||
ss << "RTP/steersVP;unicast;client_port="<< 20000 + 2*trackIt<<"-"<< 20001 + 2*trackIt;
|
||||
HTTP_S.SetHeader("Transport",ss.str());//make client ports, 4200 + 2*offset
|
||||
trackIt++;
|
||||
step++;
|
||||
HTTP_S.SendRequest(conn);
|
||||
std::cerr << "step " << step << "/\\"<< ss.str()<<std::endl;
|
||||
}else if(step == 4){
|
||||
std::cerr << "Play!!!1" << std::endl;
|
||||
HTTP_S.method = "PLAY";
|
||||
HTTP_S.url = "rtsp://localhost/steers";
|
||||
//HTTP_S.url = "rtsp://krabs:1935/vod/steers.mp4";
|
||||
HTTP_S.SetHeader("Range","npt=0.000-");
|
||||
HTTP_S.SendRequest(conn);
|
||||
step++;
|
||||
std::cerr << "step for play.." << step << std::endl;
|
||||
}
|
||||
|
||||
if (conn.Received().size() || conn.spool()){
|
||||
if (HTTP_R.Read(conn)){
|
||||
if(step == 1){
|
||||
std::cerr << "recvd desc" << std::endl;
|
||||
for(size_t ml = HTTP_R.body.find("a=control:",HTTP_R.body.find("m=")); ml != std::string::npos; ml = HTTP_R.body.find("a=control:",ml+1)){
|
||||
std::cerr << "found trekk" << std::endl;
|
||||
tracks.push_back(HTTP_R.body.substr(ml+10,HTTP_R.body.find_first_of("\r\n",ml)-(ml+10)));
|
||||
connections.push_back(Socket::UDPConnection());
|
||||
}
|
||||
for(unsigned int x = 0; x < connections.size();x++){
|
||||
connections[x].SetDestination("127.0.0.1",666);
|
||||
connections[x].bind(20000+2*x);
|
||||
connections[x].setBlocking(true);
|
||||
}
|
||||
step++;
|
||||
}else if(step == 3){
|
||||
std::cerr << "recvd setup" << std::endl;
|
||||
std::cerr << "trackIt: " << trackIt << " size " << tracks.size() << std::endl;
|
||||
if(trackIt < tracks.size())
|
||||
step--;
|
||||
else
|
||||
step++;
|
||||
std::cerr << HTTP_R.GetHeader("Transport");
|
||||
}
|
||||
HTTP_R.Clean();
|
||||
}
|
||||
}//!
|
||||
if(step == 5){
|
||||
|
||||
for(unsigned int cx = 0; cx < connections.size(); cx++){
|
||||
// std::cerr <<"PLAY MF" << std::endl;
|
||||
if(connections[cx].Receive()){
|
||||
RTP::Packet* pakketje = new RTP::Packet(connections[cx].data, connections[cx].data_len);
|
||||
/*std::cout << "Version = " << pakketje->getVersion() << std::endl;
|
||||
std::cout << "Padding = " << pakketje->getPadding() << std::endl;
|
||||
std::cout << "Extension = " << pakketje->getExtension() << std::endl;
|
||||
std::cout << "Contributing sources = " << pakketje->getContribCount() << std::endl;
|
||||
std::cout << "Marker = " << pakketje->getMarker() << std::endl;
|
||||
std::cout << "Payload Type = " << pakketje->getPayloadType() << std::endl;
|
||||
std::cout << "Sequence = " << pakketje->getSequence() << std::endl;
|
||||
std::cout << "Timestamp = " << pakketje->getTimeStamp() << std::endl;
|
||||
std::cout << "SSRC = " << pakketje->getSSRC() << std::endl;
|
||||
std::cout << "datalen: " << connections[cx].data_len << std::endl;
|
||||
std::cout << "payload:" << std::endl;*/
|
||||
|
||||
if(pakketje->getPayloadType() == 97){
|
||||
int h264type = (int)(connections[cx].data[12] & 0x1f);
|
||||
std::cout << h264type << " - ";
|
||||
if(h264type == 0){
|
||||
std::cout << "unspecified - ";
|
||||
}else if(h264type == 1){
|
||||
std::cout << "Coded slice of a non-IDR picture - ";
|
||||
}else if(h264type == 2){
|
||||
std::cout << "Coded slice data partition A - ";
|
||||
}else if(h264type == 3){
|
||||
std::cout << "Coded slice data partition B - ";
|
||||
}else if(h264type == 4){
|
||||
std::cout << "Coded slice data partition C - ";
|
||||
}else if(h264type == 5){
|
||||
std::cout << "Coded slice of an IDR picture - ";
|
||||
}else if(h264type == 6){
|
||||
std::cout << "Supplemental enhancement information (SEI) - ";
|
||||
}else if(h264type == 7){
|
||||
std::cout << "Sequence parameter set - ";
|
||||
}else if(h264type == 8){
|
||||
std::cout << "Picture parameter set - ";
|
||||
}else if(h264type == 9){
|
||||
std::cout << "Access unit delimiter - ";
|
||||
}else if(h264type == 10){
|
||||
std::cout << "End of sequence - ";
|
||||
}else if(h264type == 11){
|
||||
std::cout << "End of stream - ";
|
||||
}else if(h264type == 12){
|
||||
std::cout << "Filler data - ";
|
||||
}else if(h264type == 13){
|
||||
std::cout << "Sequence parameter set extension - ";
|
||||
}else if(h264type == 14){
|
||||
std::cout << "Prefix NAL unit - ";
|
||||
}else if(h264type == 15){
|
||||
std::cout << "Subset sequence parameter set - ";
|
||||
}else if(h264type == 16){
|
||||
std::cout << "Reserved - ";
|
||||
}else if(h264type == 17){
|
||||
std::cout << "Reserved - ";
|
||||
}else if(h264type == 18){
|
||||
std::cout << "Reserved - ";
|
||||
}else if(h264type == 19){
|
||||
std::cout << "Coded slice of an auxiliary coded picture without partitioning - ";
|
||||
}else if(h264type == 20){
|
||||
std::cout << "Coded slice extension - ";
|
||||
}else if(h264type == 21){
|
||||
std::cout << "Reserved - ";
|
||||
}else if(h264type == 22){
|
||||
std::cout << "Reserved - ";
|
||||
}else if(h264type == 23){
|
||||
std::cout << "Reserved - ";
|
||||
}else if(h264type == 24){
|
||||
std::cout << "stap a - ";
|
||||
}else if(h264type == 25){
|
||||
std::cout << "stap b - ";
|
||||
}else if(h264type == 26){
|
||||
std::cout << "mtap16 - ";
|
||||
}else if(h264type == 27){
|
||||
std::cout << "mtap24 - ";
|
||||
}else if(h264type == 28){
|
||||
std::cout << "fu a - ";
|
||||
}else if(h264type == 29){
|
||||
std::cout << "fu b - ";
|
||||
}else if(h264type == 30){
|
||||
std::cout << "Unspecified - ";
|
||||
}else if(h264type == 31){
|
||||
std::cout << "Unspecified - ";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
for(unsigned int i = 13 ; i < connections[cx].data_len;i++){
|
||||
std::cout << std::hex <<std::setw(2) << std::setfill('0') << (int)connections[cx].data[i]<< std::dec;
|
||||
}
|
||||
std::cout << std::endl<<std::endl;
|
||||
}
|
||||
delete pakketje;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 666;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char ** argv){
|
||||
Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION);
|
||||
conf.parseArgs(argc, argv);
|
||||
return Analysers::analyseRTP();
|
||||
}
|
197
src/analysers/rtsp_rtp_analyser.cpp
Normal file
197
src/analysers/rtsp_rtp_analyser.cpp
Normal file
|
@ -0,0 +1,197 @@
|
|||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
#include <mist/config.h>
|
||||
#include <mist/rtp.h>
|
||||
#include <mist/socket.h>
|
||||
#include <mist/http_parser.h>
|
||||
#include <sstream>
|
||||
|
||||
namespace RtspRtp{
|
||||
|
||||
int analyseRtspRtp(std::string rtspUrl){
|
||||
/*//parse hostname
|
||||
std::string hostname = rtspUrl.substr(7);
|
||||
hostname = hostname.substr(0,hostname.find('/'));
|
||||
std::cout << hostname << std::endl;
|
||||
HTTP::Parser HTTP_R, HTTP_S;//HTTP Receiver en HTTP Sender.
|
||||
Socket::Connection conn(hostname,554,false);//setting rtsp connection
|
||||
|
||||
bool optionsSent = false;
|
||||
bool optionsRecvd = false;
|
||||
bool descSent = false;
|
||||
bool descRecvd = false;
|
||||
bool setupComplete = false;
|
||||
bool playSent = false;
|
||||
int CSeq = 1;
|
||||
while(conn.connected()){
|
||||
if(!optionsSent){
|
||||
HTTP_R.protocol="RTSP/1.0";
|
||||
HTTP_R.method = "OPTIONS";
|
||||
HTTP_R.url = rtspUrl;
|
||||
HTTP_R.SetHeader("CSeq",CSeq);
|
||||
CSeq++;
|
||||
HTTP_R.SetHeader("User-Agent","mistANALyser");
|
||||
HTTP_R.SendRequest(conn);
|
||||
optionsSent = true;
|
||||
}
|
||||
|
||||
if (optionsSent&& !optionsRecvd && (conn.Received().size() || conn.spool() )){
|
||||
if(HTTP_S.Read(conn)){
|
||||
std::cout << "recv opts" << std::endl;
|
||||
|
||||
std::cout << HTTP_S.BuildResponse(HTTP_S.method,HTTP_S.url);
|
||||
optionsRecvd = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(optionsRecvd && !descSent){
|
||||
HTTP_S.Clean();
|
||||
HTTP_R.protocol="RTSP/1.0";
|
||||
HTTP_R.method = "DESCRIBE";
|
||||
HTTP_R.url = rtspUrl;
|
||||
HTTP_R.SetHeader("CSeq",CSeq);
|
||||
CSeq++;
|
||||
HTTP_R.SetHeader("User-Agent","mistANALyser");
|
||||
HTTP_R.SendRequest(conn);
|
||||
descSent = true;
|
||||
|
||||
}
|
||||
|
||||
std::vector<std::string> trackIds;
|
||||
|
||||
if (descSent&&!descRecvd && (conn.Received().size() || conn.spool() )){
|
||||
|
||||
if(HTTP_S.Read(conn)){
|
||||
std::cout << "recv desc2" << std::endl;
|
||||
std::cout << HTTP_S.BuildResponse(HTTP_S.method,HTTP_S.url);
|
||||
size_t pos = HTTP_S.body.find("m=");
|
||||
do{
|
||||
//finding all track IDs
|
||||
pos = HTTP_S.body.find("a=control:",pos);
|
||||
if(pos !=std::string::npos){
|
||||
trackIds.push_back(HTTP_S.body.substr(pos+10,HTTP_S.body.find("\r\n",pos)-pos-10 ) );//setting track IDs;
|
||||
pos++;
|
||||
}
|
||||
}while(pos != std::string::npos);
|
||||
//we have all the tracks
|
||||
|
||||
descRecvd = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned int setupsSent = 0;
|
||||
unsigned int setupsRecvd = 0;
|
||||
Socket::UDPConnection connectors[trackIds.size()];
|
||||
unsigned int setports[trackIds.size()];
|
||||
uint32_t bport = 10000;
|
||||
std::string sessionID = "";
|
||||
|
||||
std::stringstream setup;
|
||||
|
||||
if(descRecvd && !setupComplete){
|
||||
//time to setup.
|
||||
for(std::vector<std::string>::iterator it = trackIds.begin();it!=trackIds.end();it++){
|
||||
std::cout << "setup " << setupsSent<< std::endl;
|
||||
while(!connectors[setupsSent].SetConnection( bport,false) ){
|
||||
bport +=2;//finding an available port
|
||||
}
|
||||
std::cout << "setup" << bport<< std::endl;
|
||||
setports[setupsSent] = bport;
|
||||
bport +=2;
|
||||
if(setupsSent == setupsRecvd){
|
||||
//send only one setup
|
||||
HTTP_S.Clean();
|
||||
HTTP_R.protocol="RTSP/1.0";
|
||||
HTTP_R.method = "SETUP";
|
||||
HTTP_R.url = rtspUrl+ '/' + *(it);
|
||||
setup << "RTP/AVP/UDP;unicast;client_port="<< setports[setupsSent] <<"-" <<setports[setupsSent]+1 ;
|
||||
HTTP_R.SetHeader("Transport",setup.str() );
|
||||
std:: cout << setup.str()<<std::endl;
|
||||
setup.str(std::string());
|
||||
setup.clear();
|
||||
HTTP_R.SetHeader("CSeq",CSeq);
|
||||
CSeq++;
|
||||
if(sessionID != ""){
|
||||
HTTP_R.SetHeader("Session",sessionID);
|
||||
}
|
||||
HTTP_R.SetHeader("User-Agent","mistANALyser");
|
||||
HTTP_R.SendRequest(conn);
|
||||
setupsSent ++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
while(setupsSent == setupsRecvd+1){
|
||||
//lets Assume we assume we always receive a response
|
||||
if ( (conn.Received().size() || conn.spool() )){
|
||||
if(HTTP_S.Read(conn)){
|
||||
std::cout << "recv setup" << std::endl;
|
||||
std::cout << HTTP_S.BuildResponse(HTTP_S.method,HTTP_S.url);
|
||||
optionsRecvd = true;
|
||||
sessionID = HTTP_S.GetHeader("Session");
|
||||
setupsRecvd++;
|
||||
}
|
||||
}
|
||||
}
|
||||
//set up all parameters, and then after the for loop we have to listen to setups and all. sent if both are equal, and recv if one is sent
|
||||
|
||||
}
|
||||
setupComplete = true;
|
||||
}
|
||||
|
||||
if(setupComplete && !playSent){
|
||||
//time to play
|
||||
HTTP_S.Clean();
|
||||
HTTP_R.protocol="RTSP/1.0";
|
||||
HTTP_R.method = "PLAY";
|
||||
HTTP_R.url = rtspUrl;
|
||||
|
||||
HTTP_R.SetHeader("CSeq",CSeq);
|
||||
CSeq++;
|
||||
HTTP_R.SetHeader("User-Agent","mistANALyser");
|
||||
HTTP_R.SetHeader("Session",sessionID);
|
||||
HTTP_R.SendRequest(conn);
|
||||
playSent = true;
|
||||
std::cout << "sent play" << std::endl;
|
||||
char buffer[2000];
|
||||
while(!connectors[0].iread((void*)buffer,2000)) {
|
||||
std::cout << "buffer";
|
||||
}
|
||||
std::cout <<"buffer is not empty" << std::endl;
|
||||
|
||||
}
|
||||
|
||||
//streams set up
|
||||
//time to read some packets
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if(descRecvd){
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
conn.close();*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char ** argv){
|
||||
Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION);
|
||||
conf.addOption("url",JSON::fromString("{\"arg\":\"string\",\"short\":\"u\",\"long\":\"url\",\"help\":\"URL To get.\", \"default\":\"rtsp://localhost/s1k\"}"));
|
||||
conf.parseArgs(argc, argv);
|
||||
return RtspRtp::analyseRtspRtp(conf.getString("url"));
|
||||
}
|
84
src/analysers/stats_analyser.cpp
Normal file
84
src/analysers/stats_analyser.cpp
Normal file
|
@ -0,0 +1,84 @@
|
|||
/// \file stats_analyser.cpp
|
||||
/// Will emulate a given amount of clients in the statistics.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <mist/dtsc.h>
|
||||
#include <mist/json.h>
|
||||
#include <mist/shared_memory.h>
|
||||
#include <mist/config.h>
|
||||
#include <mist/defines.h>
|
||||
|
||||
/// Will emulate a given amount of clients in the statistics.
|
||||
int main(int argc, char ** argv){
|
||||
Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION);
|
||||
conf.addOption("clients", JSON::fromString("{\"arg\":\"num\", \"short\":\"c\", \"long\":\"clients\", \"default\":1000, \"help\":\"Amount of clients to emulate.\"}"));
|
||||
conf.addOption("stream", JSON::fromString("{\"arg\":\"string\", \"short\":\"s\", \"long\":\"stream\", \"default\":\"test\", \"help\":\"Streamname to pretend to request.\"}"));
|
||||
conf.addOption("up", JSON::fromString("{\"arg\":\"string\", \"short\":\"u\", \"long\":\"up\", \"default\":131072, \"help\":\"Bytes per second upstream.\"}"));
|
||||
conf.addOption("down", JSON::fromString("{\"arg\":\"string\", \"short\":\"d\", \"long\":\"down\", \"default\":13000, \"help\":\"Bytes per second downstream.\"}"));
|
||||
conf.addOption("sine", JSON::fromString("{\"arg\":\"string\", \"short\":\"S\", \"long\":\"sine\", \"default\":0, \"help\":\"Bytes per second variance in a sine pattern.\"}"));
|
||||
conf.addOption("userscale", JSON::fromString("{\"arg\":\"string\", \"short\":\"U\", \"long\":\"userscale\", \"default\":0, \"help\":\"If != 0, scales users from 0% to 100% bandwidth.\"}"));
|
||||
conf.parseArgs(argc, argv);
|
||||
|
||||
std::string streamName = conf.getString("stream");
|
||||
long long clientCount = conf.getInteger("clients");
|
||||
long long up = conf.getInteger("up");
|
||||
long long down = conf.getInteger("down");
|
||||
long long sine = conf.getInteger("sine");
|
||||
long long scale = conf.getInteger("userscale");
|
||||
long long currsine = sine;
|
||||
long long goingUp = 0;
|
||||
|
||||
IPC::sharedClient ** clients = (IPC::sharedClient **)malloc(sizeof(IPC::sharedClient *)*clientCount);
|
||||
for (long long i = 0; i < clientCount; i++){
|
||||
clients[i] = new IPC::sharedClient("statistics", STAT_EX_SIZE, true);
|
||||
}
|
||||
|
||||
unsigned long long int counter = 0;
|
||||
conf.activate();
|
||||
|
||||
while (conf.is_active){
|
||||
unsigned long long int now = Util::epoch();
|
||||
counter++;
|
||||
if (sine){
|
||||
currsine += goingUp;
|
||||
if (currsine < -down || currsine < -up){
|
||||
currsine = std::max(-down, -up);
|
||||
}
|
||||
if (currsine > 0){
|
||||
goingUp -= sine/100 + 1;
|
||||
}else{
|
||||
goingUp += sine/100 + 1;
|
||||
}
|
||||
}
|
||||
for (long long i = 0; i < clientCount; i++){
|
||||
if (clients[i]->getData()){
|
||||
IPC::statExchange tmpEx(clients[i]->getData());
|
||||
tmpEx.now(now);
|
||||
tmpEx.host("::42");
|
||||
tmpEx.crc(i);
|
||||
tmpEx.streamName(streamName);
|
||||
tmpEx.connector("TEST");
|
||||
if (scale){
|
||||
tmpEx.up(tmpEx.up() + (up+currsine)*i/clientCount);
|
||||
tmpEx.down(tmpEx.down() + (down+currsine)*i/clientCount);
|
||||
}else{
|
||||
tmpEx.up(tmpEx.up()+up+currsine);
|
||||
tmpEx.down(tmpEx.down()+down+currsine);
|
||||
}
|
||||
tmpEx.time(counter);
|
||||
tmpEx.lastSecond(counter * 1000);
|
||||
clients[i]->keepAlive();
|
||||
}
|
||||
}
|
||||
Util::wait(1000);
|
||||
}
|
||||
|
||||
for (long long i = 0; i < clientCount; i++){
|
||||
clients[i]->finish();
|
||||
delete clients[i];
|
||||
}
|
||||
|
||||
free(clients);
|
||||
return 0;
|
||||
}
|
189
src/analysers/ts_analyser.cpp
Executable file
189
src/analysers/ts_analyser.cpp
Executable file
|
@ -0,0 +1,189 @@
|
|||
#include <fcntl.h>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <string.h>
|
||||
#include <fstream>
|
||||
#include <unistd.h>
|
||||
#include <sstream>
|
||||
#include <signal.h>
|
||||
#include <mist/ts_packet.h>
|
||||
#include <mist/config.h>
|
||||
|
||||
|
||||
namespace Analysers {
|
||||
std::string printPES(const std::string & d, unsigned long PID, int detailLevel){
|
||||
unsigned int headSize = 0;
|
||||
std::stringstream res;
|
||||
bool known = false;
|
||||
res << "[PES " << PID << "]";
|
||||
if ((d[3] & 0xF0) == 0xE0){
|
||||
res << " [Video " << (int)(d[3] & 0xF) << "]";
|
||||
known = true;
|
||||
}
|
||||
if (!known && (d[3] & 0xE0) == 0xC0){
|
||||
res << " [Audio " << (int)(d[3] & 0x1F) << "]";
|
||||
known = true;
|
||||
}
|
||||
if (!known){
|
||||
res << " [Unknown stream ID]";
|
||||
}
|
||||
if (d[0] != 0 || d[1] != 0 || d[2] != 1){
|
||||
res << " [!INVALID START CODE!]";
|
||||
}
|
||||
if (known){
|
||||
if ((d[6] & 0xC0) != 0x80){
|
||||
res << " [!INVALID FIRST BITS!]";
|
||||
}
|
||||
if (d[6] & 0x30){
|
||||
res << " [SCRAMBLED]";
|
||||
}
|
||||
if (d[6] & 0x08){
|
||||
res << " [Priority]";
|
||||
}
|
||||
if (d[6] & 0x04){
|
||||
res << " [Aligned]";
|
||||
}
|
||||
if (d[6] & 0x02){
|
||||
res << " [Copyrighted]";
|
||||
}
|
||||
if (d[6] & 0x01){
|
||||
res << " [Original]";
|
||||
}else{
|
||||
res << " [Copy]";
|
||||
}
|
||||
|
||||
if (d[7] & 0x20){
|
||||
res << " [ESCR present, not decoded!]";
|
||||
headSize += 6;
|
||||
}
|
||||
if (d[7] & 0x10){
|
||||
res << " [ESR present, not decoded!]";
|
||||
headSize += 3;
|
||||
}
|
||||
if (d[7] & 0x08){
|
||||
res << " [Trick mode present, not decoded!]";
|
||||
headSize += 1;
|
||||
}
|
||||
if (d[7] & 0x04){
|
||||
res << " [Add. copy present, not decoded!]";
|
||||
headSize += 1;
|
||||
}
|
||||
if (d[7] & 0x02){
|
||||
res << " [CRC present, not decoded!]";
|
||||
headSize += 2;
|
||||
}
|
||||
if (d[7] & 0x01){
|
||||
res << " [Extension present, not decoded!]";
|
||||
headSize += 0; /// \todo Implement this. Complicated field, bah.
|
||||
}
|
||||
int timeFlags = ((d[7] & 0xC0) >> 6);
|
||||
if (timeFlags == 2){
|
||||
headSize += 5;
|
||||
}
|
||||
if (timeFlags == 3){
|
||||
headSize += 10;
|
||||
}
|
||||
if (d[8] != headSize){
|
||||
res << " [Padding: " << ((int)d[8] - headSize) << "b]";
|
||||
}
|
||||
if (timeFlags & 0x02){
|
||||
long long unsigned int time = (((unsigned int)d[9] & 0xE) >> 1);
|
||||
time <<= 15;
|
||||
time |= ((unsigned int)d[10] << 7) | (((unsigned int)d[11] >> 1) & 0x7F);
|
||||
time <<= 15;
|
||||
time |= ((unsigned int)d[12] << 7) | (((unsigned int)d[13] >> 1) & 0x7F);
|
||||
res << " [PTS " << ((double)time / 90000) << "s]";
|
||||
}
|
||||
if (timeFlags & 0x01){
|
||||
long long unsigned int time = ((d[14] >> 1) & 0x07);
|
||||
time <<= 15;
|
||||
time |= ((int)d[15] << 7) | (d[16] >> 1);
|
||||
time <<= 15;
|
||||
time |= ((int)d[17] << 7) | (d[18] >> 1);
|
||||
res << " [DTS " << ((double)time/90000) << "s]";
|
||||
}
|
||||
}
|
||||
if ((((int)d[4]) << 8 | d[5]) != (d.size() - 6)){
|
||||
res << " [Size " << (((int)d[4]) << 8 | d[5]) << " => " << (d.size() - 6) << "]";
|
||||
}
|
||||
res << std::endl;
|
||||
|
||||
if(detailLevel==1){
|
||||
unsigned int counter = 0;
|
||||
for (unsigned int i = 9+headSize; 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;}
|
||||
res << std::hex << std::setw(2) << std::setfill('0') << (int)(d[i]&0xff) << " ";
|
||||
counter++;
|
||||
if ((counter) % 32 == 31){res << std::endl;}
|
||||
}
|
||||
res << std::endl;
|
||||
}
|
||||
return res.str();
|
||||
}
|
||||
|
||||
/// Debugging tool for TS data.
|
||||
/// Expects TS data through stdin, outputs human-readable information to stderr.
|
||||
/// \return The return code of the analyser.
|
||||
int analyseTS(bool validate, bool analyse, int detailLevel){
|
||||
std::map<unsigned long long, std::string> payloads;
|
||||
TS::Packet packet;
|
||||
long long int upTime = Util::bootSecs();
|
||||
int64_t pcr = 0;
|
||||
unsigned int bytes = 0;
|
||||
char packetPtr[188];
|
||||
while (std::cin.good()){
|
||||
std::cin.read(packetPtr,188);
|
||||
if(std::cin.gcount() != 188){break;}
|
||||
bytes += 188;
|
||||
if(packet.FromPointer(packetPtr)){
|
||||
if(analyse){
|
||||
if (packet.getUnitStart() && payloads[packet.getPID()] != ""){
|
||||
std::cout << printPES(payloads[packet.getPID()], packet.getPID(), detailLevel);
|
||||
payloads.erase(packet.getPID());
|
||||
}
|
||||
if (detailLevel < 2){
|
||||
std::stringstream nul;
|
||||
nul << packet.toPrettyString(0, detailLevel);
|
||||
}else{
|
||||
std::cout << packet.toPrettyString(0, detailLevel);
|
||||
}
|
||||
if (packet.getPID() && !packet.isPMT()){
|
||||
payloads[packet.getPID()].append(packet.getPayload(), packet.getPayloadLength());
|
||||
}
|
||||
}
|
||||
if(packet && packet.getAdaptationField() > 1 && packet.hasPCR()){pcr = packet.getPCR();}
|
||||
}
|
||||
if(bytes > 1024){
|
||||
long long int tTime = Util::bootSecs();
|
||||
if(validate && tTime - upTime > 5 && tTime - upTime > pcr/27000000){
|
||||
std::cerr << "data received too slowly" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
bytes = 0;
|
||||
}
|
||||
}
|
||||
for (std::map<unsigned long long, std::string>::iterator it = payloads.begin(); it != payloads.end(); it++){
|
||||
if (!it->first || it->first == 4096){ continue; }
|
||||
std::cout << printPES(it->second, it->first, detailLevel);
|
||||
}
|
||||
long long int finTime = Util::bootSecs();
|
||||
if(validate){
|
||||
fprintf(stdout,"time since boot,time at completion,real time duration of data receival,video duration\n");
|
||||
fprintf(stdout, "%lli000,%lli000,%lli000,%li \n",upTime,finTime,finTime-upTime,pcr/27000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv){
|
||||
Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION);
|
||||
conf.addOption("analyse", JSON::fromString("{\"long\":\"analyse\", \"short\":\"a\", \"default\":1, \"long_off\":\"notanalyse\", \"short_off\":\"b\", \"help\":\"Analyse a file's contents (-a), or don't (-b) returning false on error. Default is analyse.\"}"));
|
||||
conf.addOption("validate", JSON::fromString("{\"long\":\"validate\", \"short\":\"V\", \"default\":0, \"long_off\":\"notvalidate\", \"short_off\":\"X\", \"help\":\"Validate (-V) the file contents or don't validate (-X) its integrity, returning false on error. Default is don't validate.\"}"));
|
||||
conf.addOption("detail", JSON::fromString("{\"long\":\"detail\", \"short\":\"D\", \"arg\":\"num\", \"default\":3, \"help\":\"Detail level of analysis.\"}"));
|
||||
conf.parseArgs(argc, argv);
|
||||
return Analysers::analyseTS(conf.getBool("validate"),conf.getBool("analyse"),conf.getInteger("detail"));
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue