Beispiel #1
0
///\brief Entry point for FLV2DTSC, simply calls Converters::FLV2DTSC().
int main(int argc, char ** argv){
  Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION);
  conf.addOption("output",
      JSON::fromString(
          "{\"long\":\"output\", \"value\":[\"stdout\"], \"short\":\"o\", \"arg\":\"string\", \"help\":\"Name of the outputfile or stdout for standard output.\"}"));
  conf.parseArgs(argc, argv);
  if (conf.getString("output") == "stdout"){
    return Converters::FLV2DTSC(std::cout);
  }
  std::ofstream oFile(conf.getString("output").c_str());
  return Converters::FLV2DTSC(oFile);
} //main
Beispiel #2
0
  /// Starts a loop, waiting for connections to send data to.
  int Start(int argc, char ** argv) {
    Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION);
    conf.addOption("stream_name", JSON::fromString("{\"arg_num\":1, \"arg\":\"string\", \"help\":\"Name of the stream this buffer will be providing.\"}"));
    conf.addOption("awaiting_ip", JSON::fromString("{\"arg_num\":2, \"arg\":\"string\", \"default\":\"\", \"help\":\"IP address to expect incoming data from. This will completely disable reading from standard input if used.\"}"));
    conf.addOption("reportstats", JSON::fromString("{\"default\":0, \"help\":\"Report stats to a controller process.\", \"short\":\"s\", \"long\":\"reportstats\"}"));
    conf.parseArgs(argc, argv);

    std::string name = conf.getString("stream_name");

    SS = Util::Stream::makeLive(name);
    if (!SS.connected()) {
      perror("Could not create stream socket");
      return 1;
    }
    conf.activate();
    thisStream = Stream::get();
    thisStream->setName(name);
    Socket::Connection incoming;
    Socket::Connection std_input(fileno(stdin));

    tthread::thread * StatsThread = 0;
    if (conf.getBool("reportstats")){StatsThread = new tthread::thread(handleStats, 0);}
    tthread::thread * StdinThread = 0;
    std::string await_ip = conf.getString("awaiting_ip");
    if (await_ip == ""){
      StdinThread = new tthread::thread(handleStdin, 0);
    }else{
      thisStream->setWaitingIP(await_ip);
      StdinThread = new tthread::thread(handlePushin, 0);
    }

    while (buffer_running && SS.connected() && conf.is_active){
      //check for new connections, accept them if there are any
      //starts a thread for every accepted connection
      incoming = SS.accept(true);
      if (incoming.connected()){
        user * usr_ptr = new user(incoming);
        thisStream->addUser(usr_ptr);
        usr_ptr->Thread = new tthread::thread(handleUser, (void *)usr_ptr);
      }
    }//main loop

    // disconnect listener
    buffer_running = false;
    std::cout << "End of input file - buffer shutting down" << std::endl;
    SS.close();
    if (StatsThread){StatsThread->join();}
    StdinThread->join();
    delete thisStream;
    return 0;
  }
Beispiel #3
0
  ///\brief Debugging tool for DTSC data.
  ///
  /// Expects DTSC data in a file given on the command line, outputs human-readable information to stderr.
  ///\param conf The configuration parsed from the commandline.
  ///\return The return code of the analyser.
  int analyseDTSC(Util::Config conf){
    DTSC::File F(conf.getString("filename"));
    if (!F){
      std::cerr << "Not a valid DTSC file" << std::endl;
      return 1;
    }
    F.getMeta().toPrettyString(std::cout,0, 0x03);

    int bPos = 0;
    F.seek_bpos(0);
    F.parseNext();
    while (F.getPacket()){
      switch (F.getPacket().getVersion()){
        case DTSC::DTSC_V1: {
          std::cout << "DTSCv1 packet: " << F.getPacket().getScan().toPrettyString() << std::endl;
          break;
        }
        case DTSC::DTSC_V2: {
          std::cout << "DTSCv2 packet (Track " << F.getPacket().getTrackId() << ", time " << F.getPacket().getTime() << "): " << F.getPacket().getScan().toPrettyString() << std::endl;
          break;
        }
        case DTSC::DTSC_HEAD: {
          std::cout << "DTSC header: " << F.getPacket().getScan().toPrettyString() << std::endl;
          break;
        }
        default:
          DEBUG_MSG(DLVL_WARN,"Invalid dtsc packet @ bpos %d", bPos);
          break;
      }
      bPos = F.getBytePos();
      F.parseNext();
    }
    return 0;
  }
Beispiel #4
0
 int DTSC2OGG(Util::Config & conf){
   DTSC::File DTSCFile(conf.getString("filename"));
   srand (Util::getMS());//randomising with milliseconds from boot
   std::vector<unsigned int> curSegTable;
   OGG::converter oggMeta;
   //Creating ID headers for theora and vorbis
   DTSC::readOnlyMeta fileMeta = DTSCFile.getMeta();
   DTSC::Meta giveMeta(fileMeta);
   
   oggMeta.readDTSCHeader(giveMeta);
   std::cout << oggMeta.parsedPages;//outputting header pages
  
   //create DTSC in OGG pages
   DTSCFile.parseNext();
   std::map< long long int, std::vector<JSON::Value> > DTSCBuffer;
   OGG::Page curOggPage;
   while(DTSCFile.getJSON()){
     std::string tmpString;
     oggMeta.readDTSCVector(DTSCFile.getJSON(), tmpString);
     std::cout << tmpString;
     DTSCFile.parseNext();
   }
   return 0;   
 }
Beispiel #5
0
///\brief Starts a loop, waiting for connections to send data to.
///\param argc The number of arguments to the program.
///\param argv The arguments to the program.
///\return The return code of the buffer.
int Start(int argc, char ** argv){

	/*std::ofstream myfile  ("/home/sharvanath/mistserver/test.txt",std::ios::app);
	//struct sockaddr add;
	//socklen_t add_length=sizeof(struct sockaddr);
	//getsockname(incoming.sock, &add,&add_length);

	myfile<<"hello1\n";
	//myfile << "the family here is : "<<add.sa_family<<"\n";

	myfile.close();
	*/
	
	Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION);
	conf.addOption("stream_name",
			JSON::fromString("{\"arg_num\":1, \"arg\":\"string\", \"help\":\"Name of the stream this buffer will be providing.\"}"));
	conf.addOption("awaiting_ip",
			JSON::fromString(
					"{\"arg_num\":2, \"arg\":\"string\", \"default\":\"\", \"help\":\"IP address to expect incoming data from. This will completely disable reading from standard input if used.\"}"));
	conf.addOption("reportstats",
			JSON::fromString("{\"default\":0, \"help\":\"Report stats to a controller process.\", \"short\":\"s\", \"long\":\"reportstats\"}"));
	conf.addOption("time",
			JSON::fromString(
					"{\"default\":0, \"arg\": \"integer\", \"help\":\"Buffer a specied amount of time in ms.\", \"short\":\"t\", \"long\":\"time\"}"));
	conf.parseArgs(argc, argv);

	std::string name = conf.getString("stream_name");

	SS = Util::Stream::makeLive(name);
	if ( !SS.connected()){
		perror("Could not create stream socket");
		return 1;
	}
	SS.setBlocking(false);
	conf.activate();
	thisStream = Stream::get();
	thisStream->setName(name);
	thisStream->getStream()->setBufferTime(conf.getInteger("time"));
	Socket::Connection incoming;
	Socket::Connection std_input(fileno(stdin));

	if (conf.getBool("reportstats")){
		tthread::thread StatsThread(handleStats, 0);
		StatsThread.detach();
	}
	std::string await_ip = conf.getString("awaiting_ip");
	if (await_ip == ""){
		tthread::thread StdinThread(handleStdin, 0);
		StdinThread.detach();
	}else{
		thisStream->setWaitingIP(await_ip);
		tthread::thread StdinThread(handlePushin, 0);
		StdinThread.detach();
	}

	while (buffer_running && SS.connected() && conf.is_active){
		//check for new connections, accept them if there are any
		//starts a thread for every accepted connection
		//sharva_mod	
		incoming = SS.accept(true);
		if (incoming.connected()){
			tthread::thread thisUser(handleUser, (void *)new user(incoming));
			thisUser.detach();


		}else{
			Util::sleep(50);//sleep 50ms
		}
	} //main loop

	// disconnect listener
	buffer_running = false;
	std::cout << "Buffer shutting down" << std::endl;
	SS.close();
	if (thisStream->getIPInput().connected()){
		thisStream->getIPInput().close();
	}
	delete thisStream;
	return 0;
}
Beispiel #6
0
  ///\brief Reads a DTSC file and attempts to fix the metadata in it.
  ///\param conf The current configuration of the program.
  ///\return The return code for the fixed program.
  int DTSCFix(Util::Config & conf){
    DTSC::File F(conf.getString("filename"));
    F.seek_bpos(0);
    F.parseNext();
    JSON::Value oriheader = F.getJSON();
    JSON::Value meta = F.getMeta();
    JSON::Value pack;

    if ( !oriheader.isMember("moreheader")){
      std::cerr << "This file is too old to fix - please reconvert." << std::endl;
      return 1;
    }
    if (DTSC::isFixed(meta) && !conf.getBool("force")){
      std::cerr << "This file was already fixed or doesn't need fixing - cancelling." << std::endl;
      return 0;
    }
    meta.removeMember("isFixed");
    meta.removeMember("keytime");
    meta.removeMember("keybpos");
    meta.removeMember("moreheader");

    std::map<std::string,int> trackIDs;
    std::map<std::string,HeaderEntryDTSC> trackData;


    long long int nowpack = 0;
    
    std::string currentID;
    int nextFreeID = 0;

    for (JSON::ObjIter it = meta["tracks"].ObjBegin(); it != meta["tracks"].ObjEnd(); it++){
      trackIDs.insert(std::pair<std::string,int>(it->first,it->second["trackid"].asInt()));
      trackData[it->first].type = it->second["type"].asString();
      trackData[it->first].trackID = it->second["trackid"].asInt();
      trackData[it->first].type = it->second["type"].asString();
      if (it->second["trackid"].asInt() >= nextFreeID){
        nextFreeID = it->second["trackid"].asInt() + 1;
      }
      it->second.removeMember("keylen");
      it->second.removeMember("keybpos");
      it->second.removeMember("frags");
      it->second.removeMember("keytime");
      it->second.removeMember("keynum");
      it->second.removeMember("keydata");
      it->second.removeMember("keyparts");
      it->second.removeMember("keys");
    }

    F.parseNext();
    while ( !F.getJSON().isNull()){
      currentID = "";
      if (F.getJSON()["trackid"].asInt() == 0){
        if (F.getJSON()["datatype"].asString() == "video"){
          currentID = "video0";
          if (trackData[currentID].trackID == 0){
            trackData[currentID].trackID = nextFreeID++;
          }
          if (meta.isMember("video")){
            meta["tracks"][currentID] = meta["video"];
            meta.removeMember("video");
          }
          trackData[currentID].type = F.getJSON()["datatype"].asString();
        }else{
          if (F.getJSON()["datatype"].asString() == "audio"){
            currentID = "audio0";
            if (trackData[currentID].trackID == 0){
              trackData[currentID].trackID = nextFreeID++;
            }
            if (meta.isMember("audio")){
              meta["tracks"][currentID] = meta["audio"];
              meta.removeMember("audio");
            }
            trackData[currentID].type = F.getJSON()["datatype"].asString();
          }else{
            //fprintf(stderr, "Found an unknown package with packetid 0 and datatype %s\n",F.getJSON()["datatype"].asString().c_str());
            F.parseNext();
            continue;
          }
        }
      }else{
        for( std::map<std::string,int>::iterator it = trackIDs.begin(); it != trackIDs.end(); it++ ) {
          if( it->second == F.getJSON()["trackid"].asInt() ) {
            currentID = it->first;
            break;
          }
        }
        if( currentID == "" ) {
          //fprintf(stderr, "Found an unknown v2 packet with id %d\n", F.getJSON()["trackid"].asInt());
          F.parseNext();
          continue;
          //should create new track but this shouldnt be needed...
        }
      }
      if (F.getJSON()["time"].asInt() < trackData[currentID].firstms){
        trackData[currentID].firstms = F.getJSON()["time"].asInt();
      }
      if (F.getJSON()["time"].asInt() >= nowpack){
        nowpack = F.getJSON()["time"].asInt();
      }
      if (trackData[currentID].type == "video"){
        if (F.getJSON().isMember("keyframe")){
          int newNum = meta["tracks"][currentID]["keys"].size();
          meta["tracks"][currentID]["keys"][newNum]["num"] = ++trackData[currentID].keynum;
          meta["tracks"][currentID]["keys"][newNum]["time"] = F.getJSON()["time"];
          meta["tracks"][currentID]["keys"][newNum]["bpos"] = F.getLastReadPos();
          if (meta["tracks"][currentID]["keys"].size() > 1){
            meta["tracks"][currentID]["keys"][newNum - 1]["len"] = F.getJSON()["time"].asInt() - meta["tracks"][currentID]["keys"][newNum - 1]["time"].asInt();
            meta["tracks"][currentID]["keys"][newNum - 1]["size"] = trackData[currentID].totalSize;
            trackData[currentID].totalSize = 0;
            std::string encodeVec = JSON::encodeVector( trackData[currentID].parts.begin(), trackData[currentID].parts.end() );
            meta["tracks"][currentID]["keys"][newNum - 1]["parts"] = encodeVec;
            meta["tracks"][currentID]["keys"][newNum - 1]["partsize"] = (long long int)trackData[currentID].parts.size();
            trackData[currentID].parts.clear();
          }
        }
      }else{
        if ((F.getJSON()["time"].asInt() - trackData[currentID].lastKeyTime) > 1000){
          trackData[currentID].lastKeyTime = F.getJSON()["time"].asInt();
          int newNum = meta["tracks"][currentID]["keys"].size();
          meta["tracks"][currentID]["keys"][newNum]["num"] = ++trackData[currentID].keynum;
          meta["tracks"][currentID]["keys"][newNum]["time"] = F.getJSON()["time"];
          meta["tracks"][currentID]["keys"][newNum]["bpos"] = F.getLastReadPos();
          if (meta["tracks"][currentID]["keys"].size() > 1){
            meta["tracks"][currentID]["keys"][newNum - 1]["len"] = F.getJSON()["time"].asInt() - meta["tracks"][currentID]["keys"][newNum - 1]["time"].asInt();
            meta["tracks"][currentID]["keys"][newNum - 1]["size"] = trackData[currentID].totalSize;
            trackData[currentID].totalSize = 0;
            std::string encodeVec = JSON::encodeVector( trackData[currentID].parts.begin(), trackData[currentID].parts.end() );
            meta["tracks"][currentID]["keys"][newNum - 1]["parts"] = encodeVec;
            meta["tracks"][currentID]["keys"][newNum - 1]["partsize"] = (long long int)trackData[currentID].parts.size();
            trackData[currentID].parts.clear();
          }
        }
      }
      trackData[currentID].totalSize += F.getJSON()["data"].asString().size();
      trackData[currentID].lastms = nowpack;
      trackData[currentID].parts.push_back(F.getJSON()["data"].asString().size());
      F.parseNext();
    }

    long long int firstms = 0x7fffffff;
    long long int lastms = -1;

    for (std::map<std::string,HeaderEntryDTSC>::iterator it = trackData.begin(); it != trackData.end(); it++){
      if (it->second.firstms < firstms){
        firstms = it->second.firstms;
      }
      if (it->second.lastms > lastms){
        lastms = it->second.lastms;
      }
      meta["tracks"][it->first]["firstms"] = it->second.firstms;
      meta["tracks"][it->first]["lastms"] = it->second.lastms;
      meta["tracks"][it->first]["length"] = (it->second.lastms - it->second.firstms) / 1000;
      if ( !meta["tracks"][it->first].isMember("bps")){
        meta["tracks"][it->first]["bps"] = (long long int)(it->second.lastms / ((it->second.lastms - it->second.firstms) / 1000));
      }
      if (it->second.trackID != 0){
        meta["tracks"][it->first]["trackid"] = trackIDs[it->first];
      }else{
        meta["tracks"][it->first]["trackid"] = nextFreeID ++;
      }
      meta["tracks"][it->first]["type"] = it->second.type;
      int tmp = meta["tracks"][it->first]["keys"].size();
      if (tmp > 0){
        if (tmp > 1){
          meta["tracks"][it->first]["keys"][tmp - 1]["len"] = it->second.lastms - meta["tracks"][it->first]["keys"][tmp - 2]["time"].asInt();
        }else{
          meta["tracks"][it->first]["keys"][tmp - 1]["len"] = it->second.lastms;
        }
        meta["tracks"][it->first]["keys"][tmp - 1]["size"] = it->second.totalSize;
        std::string encodeVec = JSON::encodeVector( trackData[it->first].parts.begin(), trackData[it->first].parts.end() );
        meta["tracks"][it->first]["keys"][tmp - 1]["parts"] = encodeVec;
        meta["tracks"][it->first]["keys"][tmp - 1]["partsize"] = (long long int)trackData[it->first].parts.size();
      }else{
        meta["tracks"][it->first]["keys"][tmp]["len"] = it->second.lastms;
        meta["tracks"][it->first]["keys"][tmp]["size"] = it->second.totalSize;
        std::string encodeVec = JSON::encodeVector( trackData[it->first].parts.begin(), trackData[it->first].parts.end() );
        meta["tracks"][it->first]["keys"][tmp]["parts"] = encodeVec;
        meta["tracks"][it->first]["keys"][tmp]["partsize"] = (long long int)trackData[it->first].parts.size();
        meta["tracks"][it->first]["keys"][tmp]["time"] = it->second.firstms;
      }
      //calculate fragments
      meta["tracks"][it->first]["frags"].null();
      long long int currFrag = -1;
      long long int maxBps = 0;
      for (JSON::ArrIter arrIt = meta["tracks"][it->first]["keys"].ArrBegin(); arrIt != meta["tracks"][it->first]["keys"].ArrEnd(); arrIt++) {
        if ((*arrIt)["time"].asInt() / 10000 > currFrag){
          currFrag = (*arrIt)["time"].asInt() / 10000;
          long long int fragLen = 1;
          long long int fragDur = (*arrIt)["len"].asInt();
          long long int fragSize = (*arrIt)["size"].asInt();
          for (JSON::ArrIter it2 = arrIt + 1; it2 != meta["tracks"][it->first]["keys"].ArrEnd(); it2++){
            if ((*it2)["time"].asInt() / 10000 > currFrag || (it2 + 1) == meta["tracks"][it->first]["keys"].ArrEnd()){
              JSON::Value thisFrag;
              thisFrag["num"] = (*arrIt)["num"].asInt();
              thisFrag["time"] = (*arrIt)["time"].asInt();
              thisFrag["len"] = fragLen;
              thisFrag["dur"] = fragDur;
              thisFrag["size"] = fragSize;
              if (fragDur / 1000){
                thisFrag["bps"] = fragSize / (fragDur / 1000);
                if (maxBps < (fragSize / (fragDur / 1000))){
                  maxBps = (fragSize / (fragDur / 999));
                }
              } else {
                thisFrag["bps"] = 1;
              }
              meta["tracks"][it->first]["frags"].append(thisFrag);
              break;
            }
            fragLen ++;
            fragDur += (*it2)["len"].asInt();
            fragSize += (*it2)["size"].asInt();
          }
        }
      }
      meta["tracks"][it->first]["maxbps"] = maxBps;
    }

    meta["firstms"] = firstms;
    meta["lastms"] = lastms;
    meta["length"] = (lastms - firstms) / 1000;

    //append the revised header
    std::string loader = meta.toPacked();
    long long int newHPos = F.addHeader(loader);
    if ( !newHPos){
      std::cerr << "Failure appending new header." << std::endl;
      return -1;
    }
    //re-write the original header with information about the location of the new one
    oriheader["moreheader"] = newHPos;
    loader = oriheader.toPacked();
    if (F.writeHeader(loader)){
      return 0;
    }else{
      std::cerr << "Failure rewriting header." << std::endl;
      return -1;
    }
  } //DTSCFix
  ///\brief Debugging tool for DTSC data.
  ///
  /// Expects DTSC data in a file given on the command line, outputs human-readable information to stderr.
  ///\param conf The configuration parsed from the commandline.
  ///\return The return code of the analyser.
  int analyseDTSC(Util::Config conf){
    DTSC::File F(conf.getString("filename"));
    JSON::Value meta = F.getMeta();
    std::cout << meta.toPrettyString() << std::endl;
    JSON::Value pack;

    long long unsigned int firstpack = 0;
    long long unsigned int nowpack = 0;
    long long unsigned int lastaudio = 0;
    long long unsigned int lastvideo = 0;
    long long unsigned int lastkey = 0;
    long long unsigned int totalvideo = 0;
    long long unsigned int totalaudio = 0;
    long long unsigned int keyframes = 0;
    long long unsigned int key_min = 0xffffffff;
    long long unsigned int key_max = 0;
    long long unsigned int vid_min = 0xffffffff;
    long long unsigned int vid_max = 0;
    long long unsigned int aud_min = 0xffffffff;
    long long unsigned int aud_max = 0;
    long long unsigned int bfrm_min = 0xffffffff;
    long long unsigned int bfrm_max = 0;
    long long unsigned int bps = 0;

    F.seekNext();
    while ( !F.getJSON().isNull()){
      std::cout << F.getJSON().toPrettyString() << std::endl;
      nowpack = F.getJSON()["time"].asInt();
      if (firstpack == 0){
        firstpack = nowpack;
      }
      if (F.getJSON()["datatype"].asString() == "audio"){
        if (lastaudio != 0 && (nowpack - lastaudio) != 0){
          bps = F.getJSON()["data"].asString().size() / (nowpack - lastaudio);
          if (bps < aud_min){
            aud_min = bps;
          }
          if (bps > aud_max){
            aud_max = bps;
          }
        }
        totalaudio += F.getJSON()["data"].asString().size();
        lastaudio = nowpack;
      }
      if (F.getJSON()["datatype"].asString() == "video"){
        if (lastvideo != 0 && (nowpack - lastvideo) != 0){
          bps = F.getJSON()["data"].asString().size() / (nowpack - lastvideo);
          if (bps < vid_min){
            vid_min = bps;
          }
          if (bps > vid_max){
            vid_max = bps;
          }
        }
        if (F.getJSON()["keyframe"].asInt() != 0){
          if (lastkey != 0){
            bps = nowpack - lastkey;
            if (bps < key_min){
              key_min = bps;
            }
            if (bps > key_max){
              key_max = bps;
            }
          }
          keyframes++;
          lastkey = nowpack;
        }
        if (F.getJSON()["offset"].asInt() != 0){
          bps = F.getJSON()["offset"].asInt();
          if (bps < bfrm_min){
            bfrm_min = bps;
          }
          if (bps > bfrm_max){
            bfrm_max = bps;
          }
        }
        totalvideo += F.getJSON()["data"].asString().size();
        lastvideo = nowpack;
      }
      F.seekNext();
    }

    std::cout << std::endl << "Summary:" << std::endl;
    meta["length"] = (long long int)((nowpack - firstpack) / 1000);
    if (meta.isMember("audio")){
      meta["audio"]["bps"] = (long long int)(totalaudio / ((lastaudio - firstpack) / 1000));
      std::cout << "  Audio: " << meta["audio"]["codec"].asString() << std::endl;
      std::cout << "    Bitrate: " << meta["audio"]["bps"].asInt() << std::endl;
    }
    if (meta.isMember("video")){
      meta["video"]["bps"] = (long long int)(totalvideo / ((lastvideo - firstpack) / 1000));
      meta["video"]["keyms"] = (long long int)((lastvideo - firstpack) / keyframes);
      if (meta["video"]["keyms"].asInt() - key_min > key_max - meta["video"]["keyms"].asInt()){
        meta["video"]["keyvar"] = (long long int)(meta["video"]["keyms"].asInt() - key_min);
      }else{
        meta["video"]["keyvar"] = (long long int)(key_max - meta["video"]["keyms"].asInt());
      }
      std::cout << "  Video: " << meta["video"]["codec"].asString() << std::endl;
      std::cout << "    Bitrate: " << meta["video"]["bps"].asInt() << std::endl;
      std::cout << "    Keyframes: " << meta["video"]["keyms"].asInt() << "~" << meta["video"]["keyvar"].asInt() << std::endl;
      std::cout << "    B-frames: " << bfrm_min << " - " << bfrm_max << std::endl;
    }
    return 0;
  }