Metadata upgrades as well as improvements to the buffer in terms of debugging and code maintainability.
This commit is contained in:
parent
bb1971e961
commit
cde42ce36e
25 changed files with 390 additions and 664 deletions
|
@ -33,25 +33,25 @@ namespace Converters {
|
|||
if (Strm.parsePacket(inBuffer)){
|
||||
if ( !doneheader){
|
||||
//find first audio and video tracks
|
||||
for (JSON::ObjIter objIt = Strm.metadata["tracks"].ObjBegin(); objIt != Strm.metadata["tracks"].ObjEnd(); objIt++){
|
||||
if (videoID == -1 && objIt->second["type"].asString() == "video"){
|
||||
videoID = objIt->second["trackid"].asInt();
|
||||
for (std::map<int,DTSC::Track>::iterator it = Strm.metadata.tracks.begin(); it != Strm.metadata.tracks.end(); it++){
|
||||
if (videoID == -1 && it->second.type == "video"){
|
||||
videoID = it->first;
|
||||
}
|
||||
if (audioID == -1 && objIt->second["type"].asString() == "audio"){
|
||||
audioID = objIt->second["trackid"].asInt();
|
||||
if (audioID == -1 && it->second.type == "audio"){
|
||||
audioID = it->first;
|
||||
}
|
||||
}
|
||||
|
||||
doneheader = true;
|
||||
std::cout.write(FLV::Header, 13);
|
||||
FLV_out.DTSCMetaInit(Strm, Strm.getTrackById(videoID), Strm.getTrackById(audioID));
|
||||
FLV_out.DTSCMetaInit(Strm, Strm.metadata.tracks[videoID], Strm.metadata.tracks[audioID]);
|
||||
std::cout.write(FLV_out.data, FLV_out.len);
|
||||
if (videoID && Strm.getTrackById(videoID).isMember("init")){
|
||||
FLV_out.DTSCVideoInit(Strm.getTrackById(videoID));
|
||||
if (videoID != -1){
|
||||
FLV_out.DTSCVideoInit(Strm.metadata.tracks[videoID]);
|
||||
std::cout.write(FLV_out.data, FLV_out.len);
|
||||
}
|
||||
if (audioID && Strm.getTrackById(audioID).isMember("init")){
|
||||
FLV_out.DTSCAudioInit(Strm.getTrackById(audioID));
|
||||
if (audioID != -1){
|
||||
FLV_out.DTSCAudioInit(Strm.metadata.tracks[audioID]);
|
||||
std::cout.write(FLV_out.data, FLV_out.len);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,11 +24,12 @@ namespace Converters {
|
|||
int DTSC2MP4(Util::Config & conf){
|
||||
DTSC::File input(conf.getString("filename"));//DTSC input
|
||||
MP4::DTSC2MP4Converter Conv;//DTSC to MP4 converter class will handle header creation and media parsing
|
||||
std::cout << Conv.DTSCMeta2MP4Header(input.getMeta());//Creating and outputting MP4 header from DTSC file
|
||||
std::cout << Conv.DTSCMeta2MP4Header(input.getMeta().toJSON());//Creating and outputting MP4 header from DTSC file
|
||||
|
||||
//initialising JSON input
|
||||
std::set<int> selector;
|
||||
for (JSON::ObjIter trackIt = input.getMeta()["tracks"].ObjBegin(); trackIt != input.getMeta()["tracks"].ObjEnd(); trackIt++){
|
||||
JSON::Value tmp = input.getMeta().toJSON();
|
||||
for (JSON::ObjIter trackIt = tmp["tracks"].ObjBegin(); trackIt != tmp["tracks"].ObjEnd(); trackIt++){
|
||||
selector.insert(trackIt->second["trackid"].asInt());
|
||||
}
|
||||
input.selectTracks(selector);
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace Converters{
|
|||
char* curNewPayload;
|
||||
OGG::headerPages oggMeta;
|
||||
//Creating ID headers for theora and vorbis
|
||||
oggMeta.readDTSCHeader(DTSCFile.getMeta());
|
||||
oggMeta.readDTSCHeader(DTSCFile.getMeta().toJSON());
|
||||
std::cout << oggMeta.parsedPages;//outputting header pages
|
||||
|
||||
//create DTSC in OGG pages
|
||||
|
|
|
@ -32,10 +32,22 @@ namespace Converters {
|
|||
MP4::AVCC avccbox;
|
||||
bool haveAvcc = false;
|
||||
std::stringstream TSBuf;
|
||||
int videoID = -1;
|
||||
int audioID = -1;
|
||||
|
||||
|
||||
while (std::cin.good()){
|
||||
if (Strm.parsePacket(StrData)){
|
||||
if ((videoID == -1 || audioID == -1) && Strm.metadata){
|
||||
for (std::map<int,DTSC::Track>::iterator it = Strm.metadata.tracks.begin(); it != Strm.metadata.tracks.end(); it++){
|
||||
if (videoID == -1 && it->second.type == "video"){
|
||||
videoID = it->first;
|
||||
}
|
||||
if (audioID == -1 && it->second.type == "audio"){
|
||||
audioID = it->first;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Strm.lastType() == DTSC::PAUSEMARK){
|
||||
TSBuf.flush();
|
||||
if (TSBuf.str().size()){
|
||||
|
@ -46,7 +58,7 @@ namespace Converters {
|
|||
TSBuf.str("");
|
||||
}
|
||||
if ( !haveAvcc){
|
||||
avccbox.setPayload(Strm.metadata["video"]["init"].asString());
|
||||
avccbox.setPayload(Strm.metadata.tracks[videoID].init);
|
||||
haveAvcc = true;
|
||||
}
|
||||
if (Strm.lastType() == DTSC::VIDEO || Strm.lastType() == DTSC::AUDIO){
|
||||
|
@ -83,7 +95,7 @@ namespace Converters {
|
|||
PIDno = 0x100;
|
||||
ContCounter = &VideoCounter;
|
||||
}else if (Strm.lastType() == DTSC::AUDIO){
|
||||
ToPack.append(TS::GetAudioHeader(Strm.lastData().size(), Strm.metadata["audio"]["init"].asString()));
|
||||
ToPack.append(TS::GetAudioHeader(Strm.lastData().size(), Strm.metadata.tracks[audioID].init));
|
||||
ToPack.append(Strm.lastData());
|
||||
ToPack.prepend(TS::Packet::getPESAudioLeadIn(ToPack.bytes(1073741824ul), Strm.getPacket()["time"].asInt() * 90));
|
||||
PIDno = 0x101;
|
||||
|
|
|
@ -8,19 +8,6 @@
|
|||
|
||||
///\brief Holds everything unique to converters.
|
||||
namespace Converters {
|
||||
class HeaderEntryDTSC {
|
||||
public:
|
||||
HeaderEntryDTSC() : totalSize(0), lastKeyTime(-5001), trackID(0), firstms(0x7FFFFFFF), lastms(0), keynum(0) {}
|
||||
long long int totalSize;
|
||||
std::vector<long long int> parts;
|
||||
long long int lastKeyTime;
|
||||
long long int trackID;
|
||||
long long int firstms;
|
||||
long long int lastms;
|
||||
long long int keynum;
|
||||
std::string type;
|
||||
};
|
||||
|
||||
///\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.
|
||||
|
@ -29,232 +16,39 @@ namespace Converters {
|
|||
F.seek_bpos(0);
|
||||
F.parseNext();
|
||||
JSON::Value oriheader = F.getJSON();
|
||||
JSON::Value meta = F.getMeta();
|
||||
JSON::Value pack;
|
||||
DTSC::Meta meta(F.getMeta());
|
||||
|
||||
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")){
|
||||
if (meta.isFixed() && !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");
|
||||
}
|
||||
|
||||
meta.reset();
|
||||
int bPos = F.getBytePos();
|
||||
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.getJSON()["bpos"] = bPos;
|
||||
meta.update(F.getJSON());
|
||||
bPos = F.getBytePos();
|
||||
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;
|
||||
for (std::map<int,DTSC::Track>::iterator it = meta.tracks.begin(); it != meta.tracks.end(); it++){
|
||||
if (it->second.fragments.size()){
|
||||
it->second.fragments.rbegin()->setDuration(it->second.fragments.rbegin()->getDuration() - it->second.lastms);
|
||||
}
|
||||
if (it->second.lastms > lastms){
|
||||
lastms = it->second.lastms;
|
||||
if (it->second.lastms / 1000){
|
||||
it->second.bps /= (it->second.lastms / 1000);
|
||||
}
|
||||
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::string loader = meta.toJSON().toPacked();
|
||||
oriheader["moreheader"] = F.addHeader(loader);
|
||||
if ( !oriheader["moreheader"].asInt()){
|
||||
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;
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace Converters {
|
|||
fullSort = false;
|
||||
}else{
|
||||
DTSC::File F(tmpFileName);
|
||||
if (!DTSC::isFixed(F.getMeta())){
|
||||
if (!F.getMeta().isFixed()){
|
||||
std::cerr << tmpFileName << " has not been run through DTSCFix yet." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
@ -69,11 +69,11 @@ namespace Converters {
|
|||
outFile = DTSC::File(outFileName, true);
|
||||
}else{
|
||||
outFile = DTSC::File(outFileName);
|
||||
if (!DTSC::isFixed(outFile.getMeta())){
|
||||
if ( !outFile.getMeta().isFixed()){
|
||||
std::cerr << outFileName << " has not been run through DTSCFix yet." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
meta = outFile.getMeta();
|
||||
meta = outFile.getMeta().toJSON();
|
||||
newMeta = meta;
|
||||
if (meta.isMember("tracks") && meta["tracks"].size() > 0){
|
||||
for (JSON::ObjIter trackIt = meta["tracks"].ObjBegin(); trackIt != meta["tracks"].ObjEnd(); trackIt++){
|
||||
|
@ -86,7 +86,7 @@ namespace Converters {
|
|||
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();
|
||||
JSON::Value tmpMeta = it->second.getMeta().toJSON();
|
||||
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();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue