Пример #1
0
/// Entry point for DTSCFix, simply calls Converters::DTSCFix().
int main(int argc, char ** argv){
  Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION);
  conf.addOption("filename", JSON::fromString("{\"arg_num\":1, \"arg\":\"string\", \"help\":\"Filename of the file to attempt to fix.\"}"));
  conf.addOption("force", JSON::fromString("{\"short\":\"f\", \"long\":\"force\", \"default\":0, \"help\":\"Force fixing.\"}"));
  conf.parseArgs(argc, argv);
  return Converters::DTSCFix(conf);
} //main
Пример #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;
  }
Пример #3
0
int main(int argc, char ** argv){
  Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION);
  conf.addOption("detail",
      JSON::fromString(
          "{\"arg_num\":1, \"arg\":\"integer\", \"default\":0, \"help\":\"Bitmask, 1 = Reconstruct, 2 = Explicit media info, 4 = Verbose chunks\"}"));
  conf.parseArgs(argc, argv);

  return Analysers::analyseRTMP(conf);
} //main
Пример #4
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
Пример #5
0
/// Reads an DTSC file and prints all readable data about it
int main(int argc, char ** argv){
  Util::Config conf = Util::Config(argv[0]);
  conf.addOption("filename", JSON::fromString("{\"arg_num\":1, \"arg\":\"string\", \"help\":\"Filename of the DTSC file to analyse.\"}"));
  conf.parseArgs(argc, argv);
  return Analysers::analyseDTSC(conf);
} //main
Пример #6
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;
}
Пример #7
0
int main(int argc, char ** argv){
  Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION);
  conf.addOption("filename", JSON::fromString("{\"arg_num\":1, \"arg\":\"string\", \"help\":\"Filename of the DTSC file to analyse.\"}"));
  conf.parseArgs(argc, argv);
  return Converters::DTSC2OGG(conf);
}
Пример #8
0
/// Debugging tool for RTMP data.
/// Expects RTMP data of one side of the conversion through stdin, outputs human-readable information to stderr.
/// Will output FLV file to stdout, if available
/// Automatically skips 3073 bytes of handshake data.
int main(int argc, char ** argv){
  Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION);
  conf.addOption("detail",
      JSON::fromString(
          "{\"arg_num\":1, \"arg\":\"integer\", \"default\":0, \"help\":\"Bitmask, 1 = Reconstruct, 2 = Explicit media info, 4 = Verbose chunks\"}"));
  conf.parseArgs(argc, argv);

  Detail = conf.getInteger("detail");
  if (Detail > 0){
    fprintf(stderr, "Detail level set:\n");
    if ((Detail & DETAIL_RECONSTRUCT) == DETAIL_RECONSTRUCT){
      fprintf(stderr, " - Will reconstuct FLV file to stdout\n");
      std::cout.write(FLV::Header, 13);
    }
    if ((Detail & DETAIL_EXPLICIT) == DETAIL_EXPLICIT){
      fprintf(stderr, " - Will list explicit video/audio data information\n");
    }
    if ((Detail & DETAIL_VERBOSE) == DETAIL_VERBOSE){
      fprintf(stderr, " - Will list verbose chunk information\n");
    }
  }

  std::string inbuffer;
  while (std::cin.good()){
    inbuffer += std::cin.get();
  } //read all of std::cin to temp
  inbuffer.erase(0, 3073); //strip the handshake part
  RTMPStream::Chunk next;
  FLV::Tag F; //FLV holder
  AMF::Object amfdata("empty", AMF::AMF0_DDV_CONTAINER);
  AMF::Object3 amf3data("empty", AMF::AMF3_DDV_CONTAINER);

  while (next.Parse(inbuffer)){
    if ((Detail & DETAIL_VERBOSE) == DETAIL_VERBOSE){
      fprintf(stderr, "Chunk info: [%#2X] CS ID %u, timestamp %u, len %u, type ID %u, Stream ID %u\n", next.headertype, next.cs_id, next.timestamp,
          next.len, next.msg_type_id, next.msg_stream_id);
    }
    switch (next.msg_type_id){
      case 0: //does not exist
        fprintf(stderr, "Error chunk - %i, %i, %i, %i, %i\n", next.cs_id, next.timestamp, next.real_len, next.len_left, next.msg_stream_id);
        //return 0;
        break; //happens when connection breaks unexpectedly
      case 1: //set chunk size
        RTMPStream::chunk_rec_max = ntohl(*(int*)next.data.c_str());
        fprintf(stderr, "CTRL: Set chunk size: %i\n", RTMPStream::chunk_rec_max);
        break;
      case 2: //abort message - we ignore this one
        fprintf(stderr, "CTRL: Abort message: %i\n", ntohl(*(int*)next.data.c_str()));
        //4 bytes of stream id to drop
        break;
      case 3: //ack
        RTMPStream::snd_window_at = ntohl(*(int*)next.data.c_str());
        fprintf(stderr, "CTRL: Acknowledgement: %i\n", RTMPStream::snd_window_at);
        break;
      case 4: {
        short int ucmtype = ntohs(*(short int*)next.data.c_str());
        switch (ucmtype){
          case 0:
            fprintf(stderr, "CTRL: User control message: stream begin %u\n", ntohl(*(unsigned int*)(next.data.c_str()+2)));
            break;
          case 1:
            fprintf(stderr, "CTRL: User control message: stream EOF %u\n", ntohl(*(unsigned int*)(next.data.c_str()+2)));
            break;
          case 2:
            fprintf(stderr, "CTRL: User control message: stream dry %u\n", ntohl(*(unsigned int*)(next.data.c_str()+2)));
            break;
          case 3:
            fprintf(stderr, "CTRL: User control message: setbufferlen %u\n", ntohl(*(unsigned int*)(next.data.c_str()+2)));
            break;
          case 4:
            fprintf(stderr, "CTRL: User control message: streamisrecorded %u\n", ntohl(*(unsigned int*)(next.data.c_str()+2)));
            break;
          case 6:
            fprintf(stderr, "CTRL: User control message: pingrequest %u\n", ntohl(*(unsigned int*)(next.data.c_str()+2)));
            break;
          case 7:
            fprintf(stderr, "CTRL: User control message: pingresponse %u\n", ntohl(*(unsigned int*)(next.data.c_str()+2)));
            break;
          default:
            fprintf(stderr, "CTRL: User control message: UNKNOWN %hu - %u\n", ucmtype, ntohl(*(unsigned int*)(next.data.c_str()+2)));
            break;
        }
      }
        break;
      case 5: //window size of other end
        RTMPStream::rec_window_size = ntohl(*(int*)next.data.c_str());
        RTMPStream::rec_window_at = RTMPStream::rec_cnt;
        fprintf(stderr, "CTRL: Window size: %i\n", RTMPStream::rec_window_size);
        break;
      case 6:
        RTMPStream::snd_window_size = ntohl(*(int*)next.data.c_str());
        //4 bytes window size, 1 byte limit type (ignored)
        fprintf(stderr, "CTRL: Set peer bandwidth: %i\n", RTMPStream::snd_window_size);
        break;
      case 8:
        if (Detail & (DETAIL_EXPLICIT | DETAIL_RECONSTRUCT)){
          F.ChunkLoader(next);
          if ((Detail & DETAIL_EXPLICIT) == DETAIL_EXPLICIT){
            fprintf(stderr, "Received %i bytes audio data\n", next.len);
            std::cerr << "Got a " << F.len << " bytes " << F.tagType() << " FLV tag of time " << F.tagTime() << "." << std::endl;
          }
          if ((Detail & DETAIL_RECONSTRUCT) == DETAIL_RECONSTRUCT){
            std::cout.write(F.data, F.len);
          }
        }
        break;
      case 9:
        if (Detail & (DETAIL_EXPLICIT | DETAIL_RECONSTRUCT)){
          F.ChunkLoader(next);
          if ((Detail & DETAIL_EXPLICIT) == DETAIL_EXPLICIT){
            fprintf(stderr, "Received %i bytes video data\n", next.len);
            std::cerr << "Got a " << F.len << " bytes " << F.tagType() << " FLV tag of time " << F.tagTime() << "." << std::endl;
          }
          if ((Detail & DETAIL_RECONSTRUCT) == DETAIL_RECONSTRUCT){
            std::cout.write(F.data, F.len);
          }
        }
        break;
      case 15:
        fprintf(stderr, "Received AFM3 data message\n");
        break;
      case 16:
        fprintf(stderr, "Received AFM3 shared object\n");
        break;
      case 17: {
        fprintf(stderr, "Received AFM3 command message:\n");
        char soort = next.data[0];
        next.data = next.data.substr(1);
        if (soort == 0){
          amfdata = AMF::parse(next.data);
          std::cerr << amfdata.Print() << std::endl;
        }else{
          amf3data = AMF::parse3(next.data);
          amf3data.Print();
        }
      }
        break;
      case 18: {
        fprintf(stderr, "Received AFM0 data message (metadata):\n");
        amfdata = AMF::parse(next.data);
        amfdata.Print();
        if ((Detail & DETAIL_RECONSTRUCT) == DETAIL_RECONSTRUCT){
          F.ChunkLoader(next);
          std::cout.write(F.data, F.len);
        }
      }
        break;
      case 19:
        fprintf(stderr, "Received AFM0 shared object\n");
        break;
      case 20: { //AMF0 command message
        fprintf(stderr, "Received AFM0 command message:\n");
        amfdata = AMF::parse(next.data);
        std::cerr << amfdata.Print() << std::endl;
      }
        break;
      case 22:
        fprintf(stderr, "Received aggregate message\n");
        break;
      default:
        fprintf(stderr, "Unknown chunk received! Probably protocol corruption, stopping parsing of incoming data.\n");
        return 1;
        break;
    } //switch for type of chunk
  } //while chunk parsed
  fprintf(stderr, "No more readable data\n");
  return 0;
} //main
Пример #9
0
  int DTSCMerge(int argc, char ** argv){
    Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION);
    conf.addOption("output", JSON::fromString("{\"arg_num\":1, \"arg\":\"string\", \"help\":\"Filename of the output file.\"}"));
    conf.addOption("input", JSON::fromString("{\"arg_num\":2, \"arg\":\"string\", \"help\":\"Filename of the first input file.\"}"));
    conf.addOption("[additional_inputs ...]", JSON::fromString("{\"arg_num\":3, \"default\":\"\", \"arg\":\"string\", \"help\":\"Filenames of any number of aditional inputs.\"}"));
    conf.parseArgs(argc, argv);

    DTSC::File outFile;
    JSON::Value meta;
    DTSC::Meta newMeta;
    std::map<std::string,std::map<int, int> > trackMapping;

    bool fullSort = true;
    std::map<std::string, DTSC::File> inFiles;
    std::map<std::string, DTSC::Meta> metaData;
    std::string outFileName = argv[1];
    std::string tmpFileName;
    for (int i = 2; i < argc; i++){
      tmpFileName = argv[i];
      if (tmpFileName == outFileName){
        fullSort = false;
      }else{
        DTSC::File F(tmpFileName);
        if (!F.getMeta().isFixed()){
          std::cerr << tmpFileName << " has not been run through DTSCFix yet." << std::endl;
          return 1;
        }
        inFiles[tmpFileName] = F;
      }
    }

    if (fullSort){
      outFile = DTSC::File(outFileName, true);
    }else{
      outFile = DTSC::File(outFileName);
      if ( !outFile.getMeta().isFixed()){
        std::cerr << outFileName << " has not been run through DTSCFix yet." << std::endl;
        return 1;
      }
      meta = outFile.getMeta().toJSON();
      newMeta = DTSC::Meta(meta);
      if (meta.isMember("tracks") && meta["tracks"].size() > 0){
        for (JSON::ObjIter trackIt = meta["tracks"].ObjBegin(); trackIt != meta["tracks"].ObjEnd(); trackIt++){
          int nxtMap = getNextFree(trackMapping);
          trackMapping[argv[1]].insert(std::pair<int,int>(trackIt->second["trackid"].asInt(),nxtMap));
          newMeta.tracks[nxtMap].trackID = nxtMap;
        }
      }
    }

    std::multimap<int,keyframeInfo> allSorted;

    for (std::map<std::string,DTSC::File>::iterator it = inFiles.begin(); it != inFiles.end(); it++){
      DTSC::Meta tmpMeta(it->second.getMeta());
      for (std::map<int,DTSC::Track>::iterator trackIt = tmpMeta.tracks.begin(); trackIt != tmpMeta.tracks.end(); trackIt++){
        long long int oldID = trackIt->first;
        long long int mappedID = getNextFree(trackMapping);
        trackMapping[it->first].insert(std::pair<int,int>(oldID,mappedID));
        for (std::deque<DTSC::Key>::iterator keyIt = trackIt->second.keys.begin(); keyIt != trackIt->second.keys.end(); keyIt++){
          keyframeInfo tmpInfo;
          tmpInfo.fileName = it->first;
          tmpInfo.trackID = oldID;
          tmpInfo.keyTime = keyIt->getTime();
          tmpInfo.keyBPos = keyIt->getBpos();
          tmpInfo.keyNum = keyIt->getNumber();
          tmpInfo.keyLen = keyIt->getLength();
          if ((keyIt + 1) != trackIt->second.keys.end()){
            tmpInfo.endBPos = (keyIt + 1)->getBpos();
          }else{
            tmpInfo.endBPos = it->second.getBytePosEOF();
          }
          allSorted.insert(std::pair<int,keyframeInfo>(keyIt->getTime(),tmpInfo));
        }
        newMeta.tracks[mappedID] = trackIt->second;
        newMeta.tracks[mappedID].trackID = mappedID;
        newMeta.tracks[mappedID].reset();
      }
    }

    if (fullSort){
      meta.null();
      meta["moreheader"] = 0ll;
      std::string tmpWrite = meta.toPacked();
      outFile.writeHeader(tmpWrite,true);
    }

    std::set<int> trackSelector;
    for (std::multimap<int,keyframeInfo>::iterator sortIt = allSorted.begin(); sortIt != allSorted.end(); sortIt++){
      trackSelector.clear();
      trackSelector.insert(sortIt->second.trackID);
      inFiles[sortIt->second.fileName].selectTracks(trackSelector);
      inFiles[sortIt->second.fileName].seek_time(sortIt->second.keyTime);
      inFiles[sortIt->second.fileName].seekNext();
      while (inFiles[sortIt->second.fileName].getPacket() && inFiles[sortIt->second.fileName].getBytePos() <= sortIt->second.endBPos && !inFiles[sortIt->second.fileName].reachedEOF()){
        if (inFiles[sortIt->second.fileName].getPacket().getTrackId() == sortIt->second.trackID){
          JSON::Value tmp = inFiles[sortIt->second.fileName].getPacket().toJSON();
          tmp["trackid"] = trackMapping[sortIt->second.fileName][sortIt->second.trackID];
          outFile.writePacket(tmp);
        }
        inFiles[sortIt->second.fileName].seekNext();
      }
    }

    if (fullSort || (meta.isMember("merged") && meta["merged"])){
      newMeta.merged = 1;
    }else{
      newMeta.merged = 0;
    }
    std::string writeMeta = newMeta.toJSON().toPacked();
    meta["moreheader"] = outFile.addHeader(writeMeta);
    writeMeta = meta.toPacked();
    outFile.writeHeader(writeMeta);

    return 0;
  }