141 lines
5.5 KiB
C++
141 lines
5.5 KiB
C++
/// \file dtscmerge.cpp
|
|
/// Contains the code that will attempt to merge multiple files into a single DTSC file.
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <mist/config.h>
|
|
#include <mist/dtsc.h>
|
|
|
|
namespace Converters {
|
|
int getNextFree( std::map<std::string,std::map<int,int> > mapping ){
|
|
int result = 1;
|
|
std::map<std::string,std::map<int,int> >::iterator mapIt;
|
|
std::map<int,int>::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<std::string,std::map<int, int> > trackMapping;
|
|
|
|
bool fullSort = true;
|
|
std::map<std::string, DTSC::File> 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<std::string,DTSC::File>(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<int,int>(trackIt->second["trackid"].asInt(),getNextFree(trackMapping)));
|
|
newMeta["tracks"][trackIt->first]["trackid"] = trackMapping[argv[1]][trackIt->second["trackid"].asInt()];
|
|
}
|
|
}
|
|
}
|
|
|
|
std::multimap<int,keyframeInfo> allSorted;
|
|
|
|
for (std::map<std::string,DTSC::File>::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<int,int>(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<int,keyframeInfo>((*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<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].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);
|
|
}
|