/// \file dtscmerge.cpp /// Contains the code that will attempt to merge multiple files into a single DTSC file. #include #include #include #include namespace Converters { int getNextFree( std::map > mapping ){ int result = 1; std::map >::iterator mapIt; std::map::iterator subIt; if (mapping.size()){ for (mapIt = mapping.begin(); mapIt != mapping.end(); mapIt++){ if (mapIt->second.size()){ for (subIt = mapIt->second.begin(); subIt != mapIt->second.end(); subIt++){ if (subIt->second >= result){ result = subIt->second + 1; } } } } } return result; } struct keyframeInfo{ std::string fileName; int trackID; int keyTime; int keyBPos; int keyNum; int keyLen; int endBPos; };//keyframeInfo struct 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; JSON::Value newMeta; std::map > trackMapping; bool fullSort = true; std::map inFiles; std::string outFileName = argv[1]; std::string tmpFileName; for (int i = 2; i < argc; i++){ tmpFileName = argv[i]; if (tmpFileName == outFileName){ fullSort = false; }else{ inFiles.insert(std::pair(tmpFileName,DTSC::File(tmpFileName))); } } if (fullSort){ outFile = DTSC::File(outFileName, true); }else{ outFile = DTSC::File(outFileName); meta = outFile.getMeta(); newMeta = meta; if (meta.isMember("tracks") && meta["tracks"].size() > 0){ for (JSON::ObjIter trackIt = meta["tracks"].ObjBegin(); trackIt != meta["tracks"].ObjEnd(); trackIt++){ trackMapping[argv[1]].insert(std::pair(trackIt->second["trackid"].asInt(),getNextFree(trackMapping))); newMeta["tracks"][trackIt->first]["trackid"] = trackMapping[argv[1]][trackIt->second["trackid"].asInt()]; } } } std::multimap allSorted; for (std::map::iterator it = inFiles.begin(); it != inFiles.end(); it++){ JSON::Value tmpMeta = it->second.getMeta(); if (tmpMeta.isMember("tracks") && tmpMeta["tracks"].size() > 0){ for (JSON::ObjIter trackIt = tmpMeta["tracks"].ObjBegin(); trackIt != tmpMeta["tracks"].ObjEnd(); trackIt++){ long long int oldID = trackIt->second["trackid"].asInt(); long long int mappedID = getNextFree(trackMapping); trackMapping[it->first].insert(std::pair(oldID,mappedID)); trackIt->second["trackid"] = mappedID; for (JSON::ArrIter keyIt = trackIt->second["keys"].ArrBegin(); keyIt != trackIt->second["keys"].ArrEnd(); keyIt++){ keyframeInfo tmpInfo; tmpInfo.fileName = it->first; tmpInfo.trackID = oldID; tmpInfo.keyTime = (*keyIt)["time"].asInt(); tmpInfo.keyBPos = (*keyIt)["bpos"].asInt(); tmpInfo.keyNum = (*keyIt)["num"].asInt(); tmpInfo.keyLen = (*keyIt)["len"].asInt(); if ((keyIt + 1) != trackIt->second["keys"].ArrEnd()){ tmpInfo.endBPos = (*(keyIt + 1))["bpos"].asInt(); }else{ tmpInfo.endBPos = it->second.getBytePosEOF(); } allSorted.insert(std::pair((*keyIt)["time"].asInt(),tmpInfo)); } trackIt->second.removeMember("keys"); trackIt->second.removeMember("frags"); newMeta["tracks"][JSON::Value(mappedID).asString()] = trackIt->second; } } } if (fullSort){ meta.null(); meta["moreheader"] = 0ll; std::string tmpWrite = meta.toPacked(); outFile.writeHeader(tmpWrite,true); } std::set trackSelector; for (std::multimap::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].getJSON() && inFiles[sortIt->second.fileName].getBytePos() < sortIt->second.endBPos && !inFiles[sortIt->second.fileName].reachedEOF()){ inFiles[sortIt->second.fileName].getJSON()["trackid"] = trackMapping[sortIt->second.fileName][inFiles[sortIt->second.fileName].getJSON()["trackid"].asInt()]; outFile.writePacket(inFiles[sortIt->second.fileName].getJSON()); inFiles[sortIt->second.fileName].seekNext(); } } std::string writeMeta = newMeta.toPacked(); meta["moreheader"] = outFile.addHeader(writeMeta); writeMeta = meta.toPacked(); outFile.writeHeader(writeMeta); return 0; } } int main(int argc, char ** argv){ return Converters::DTSCMerge(argc, argv); }