Metadata upgrades as well as improvements to the buffer in terms of debugging and code maintainability.

This commit is contained in:
Thulinma 2013-11-27 15:30:34 +01:00
parent bb1971e961
commit cde42ce36e
25 changed files with 390 additions and 664 deletions

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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();