From a0a6e957a52883333dcec9d800b3ed5e4d209483 Mon Sep 17 00:00:00 2001 From: Oswald Auguste de Bruin Date: Tue, 16 Jul 2013 16:22:26 +0200 Subject: [PATCH] Ogg 2 DTSC nearly working --- src/analysers/ogg_analyser.cpp | 3 + src/converters/ogg2dtsc.cpp | 148 ++++++++++++++++++++++----------- 2 files changed, 102 insertions(+), 49 deletions(-) diff --git a/src/analysers/ogg_analyser.cpp b/src/analysers/ogg_analyser.cpp index e035566d..ac519232 100644 --- a/src/analysers/ogg_analyser.cpp +++ b/src/analysers/ogg_analyser.cpp @@ -27,6 +27,9 @@ namespace Analysers{ if (memcmp("theora",oggPage.getFullPayload() + 1,6) == 0){ sn2Codec[oggPage.getBitstreamSerialNumber()] = "theora"; } + if (memcmp("vorbis",oggPage.getFullPayload() + 1,6) == 0){ + sn2Codec[oggPage.getBitstreamSerialNumber()] = "vorbis"; + } } oggPage.setInternalCodec(sn2Codec[oggPage.getBitstreamSerialNumber()]); std::cout << oggPage.toPrettyString() << std::endl; diff --git a/src/converters/ogg2dtsc.cpp b/src/converters/ogg2dtsc.cpp index 64cc3f8a..b942b61f 100644 --- a/src/converters/ogg2dtsc.cpp +++ b/src/converters/ogg2dtsc.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -15,13 +16,14 @@ namespace Converters{ class oggTrack{ public: - oggTrack() : lastTime() { } + oggTrack() : lastTime(), parsedHeaders(false) { } codecType codec; std::string name; long long unsigned int dtscID; long long unsigned int lastTime; + bool parsedHeaders; //Codec specific elements - theora::header idHeader; + theora::header idHeader;//needed to determine keyframe }; int OGG2DTSC(){ @@ -30,13 +32,16 @@ namespace Converters{ //netpacked //Read all of std::cin to oggBuffer - //while stream busy JSON::Value DTSCOut; JSON::Value DTSCHeader; DTSCHeader.null(); DTSCHeader["moreheader"] = 0ll; std::map trackData; long long int lastTrackID = 1; + int headerSeen = 0; + bool headerWritten = false;//important bool, used for outputting the simple DTSC header. + bool allStreamsSeen = false; //other important bool used for error checking the EOS. + //while stream busy while (std::cin.good()){ for (unsigned int i = 0; (i < 1024) && (std::cin.good()); i++){//buffering oggBuffer += std::cin.get(); @@ -47,9 +52,13 @@ namespace Converters{ if (oggPage.typeBOS()){//defines a new track std::cerr << "Begin "<< sNum << std::endl; if (memcmp(oggPage.getFullPayload()+1, "theora", 6) == 0){ + headerSeen += 1; + headerWritten = false; trackData[sNum].codec = THEORA; std::cerr << "Snr " << sNum << "=theora" << std::endl; }else if(memcmp(oggPage.getFullPayload()+1, "vorbis", 6) == 0){ + headerSeen += 1; + headerWritten = false; std::cerr << "Snr " << sNum << "=vorbis" << std::endl; trackData[sNum].codec = VORBIS; }else{ @@ -63,60 +72,101 @@ namespace Converters{ } //if Serial number is available in mapping if(trackData.find(sNum)!=trackData.end()){ - //switch on codec - switch(trackData[sNum].codec){ - case THEORA:{ - int offset = 0; - theora::header tHead; - fprintf(stderr, "Parsing %d elements\n", oggPage.getSegmentTableDeque().size()); - for (std::deque::iterator it = oggPage.getSegmentTableDeque().begin(); it != oggPage.getSegmentTableDeque().end(); it++){ - fprintf(stderr, "Parsing Snr %u: element of length %d\n", sNum, (*it)); - if(tHead.read(oggPage.getFullPayload()+offset, (*it))){//if the current segment is a header part - std::cerr << "Theora Header Segment " << tHead.getHeaderType() << std::endl; - //fillDTSC header - switch(tHead.getHeaderType()){ - case 0:{ //identification header - trackData[sNum].idHeader = tHead; - break; - } - case 1: //comment header - break; - case 2:{ //setup header, also the point to start writing the header - std::cout << DTSCHeader.toNetPacked(); - break; - } - } - }else{//if the current segment is a movie part - //output DTSC packet - DTSCOut.null();//clearing DTSC buffer - DTSCOut["trackid"] = (long long)trackData[sNum].dtscID; - long long unsigned int temp = oggPage.getGranulePosition(); - DTSCOut["time"] = (long long)trackData[sNum].lastTime ++; - DTSCOut["data"] = std::string(oggPage.getFullPayload()+offset, (*it)); //segment content put in JSON - if (trackData[sNum].idHeader.parseGranuleLower(temp) == 0){ //granule mask equals zero when on keyframe - DTSCOut["keyframe"] = 1; - }else{ - DTSCOut["interframe"] = 1; - } - fprintf(stderr,"Outputting a packet of %d bytes\n", (*it)); - std::cout << DTSCOut.toNetPacked(); + int offset = 0; + for (std::deque::iterator it = oggPage.getSegmentTableDeque().begin(); it != oggPage.getSegmentTableDeque().end(); it++){ + if (trackData[sNum].parsedHeaders){ + //todo output segment + //output DTSC packet + DTSCOut.null();//clearing DTSC buffer + DTSCOut["trackid"] = (long long)trackData[sNum].dtscID; + long long unsigned int temp = oggPage.getGranulePosition(); + DTSCOut["time"] = (long long)trackData[sNum].lastTime ++; + DTSCOut["data"] = std::string(oggPage.getFullPayload()+offset, (*it)); //segment content put in JSON + if (trackData[sNum].codec == THEORA){ + if (trackData[sNum].idHeader.parseGranuleLower(temp) == 0){ //granule mask equals zero when on keyframe + DTSCOut["keyframe"] = 1; + }else{ + DTSCOut["interframe"] = 1; } - offset += (*it); } - if (trackData[sNum].lastTime != (trackData[sNum].idHeader.parseGranuleUpper(oggPage.getGranulePosition()) + trackData[sNum].idHeader.parseGranuleLower(oggPage.getGranulePosition()))){ - + std::cout << DTSCOut.toNetPacked(); + }else{ + //switch on codec + switch(trackData[sNum].codec){ + case THEORA:{ + theora::header tHead; + if(tHead.read(oggPage.getFullPayload()+offset, (*it))){//if the current segment is a Theora header part + std::cerr << "Theora Header Segment " << tHead.getHeaderType() << std::endl; + //fillDTSC header + switch(tHead.getHeaderType()){ + case 0:{ //identification header + std::cerr << "Theora ID header found" << std::endl; + trackData[sNum].idHeader = tHead; + DTSCHeader["tracks"][trackData[sNum].name]["height"] = (long long)tHead.getPICH(); + DTSCHeader["tracks"][trackData[sNum].name]["width"] = (long long)tHead.getPICW(); + DTSCHeader["tracks"][trackData[sNum].name]["theoraID"] = std::string(oggPage.getFullPayload()+offset, (*it)); + break; + } + case 1: //comment header + std::cerr << "Theora comment header found" << std::endl; + break; + case 2:{ //setup header, also the point to start writing the header + DTSCHeader["tracks"][trackData[sNum].name]["codec"] = "theora"; + DTSCHeader["tracks"][trackData[sNum].name]["trackid"] = (long long)trackData[sNum].dtscID; + DTSCHeader["tracks"][trackData[sNum].name]["type"] = "video"; + DTSCHeader["tracks"][trackData[sNum].name]["init"] = std::string(oggPage.getFullPayload()+offset, (*it)); + headerSeen --; + trackData[sNum].parsedHeaders = true; + break; + } + } + }else{//if the current segment is a movie part + } + break; + } + case VORBIS:{ + vorbis::header vHead; + if(vHead.read(oggPage.getFullPayload()+offset, (*it))){//if the current segment is a Theora header part + switch(vHead.getHeaderType()){ + case 1:{ + std::cerr << "Vorbis ID header" << std::endl; + DTSCHeader["tracks"][trackData[sNum].name]["channels"] = (long long)vHead.getAudioChannels(); + break; + } + case 5:{ + std::cerr << "Vorbis init header" << std::endl; + DTSCHeader["tracks"][trackData[sNum].name]["codec"] = "vorbis"; + DTSCHeader["tracks"][trackData[sNum].name]["trackid"] = (long long)trackData[sNum].dtscID; + DTSCHeader["tracks"][trackData[sNum].name]["type"] = "audio"; + DTSCHeader["tracks"][trackData[sNum].name]["init"] = std::string(oggPage.getFullPayload()+offset, (*it)); + headerSeen --; + trackData[sNum].parsedHeaders = true; + break; + } + } + }else{ + //buffer vorbis + } + break; + } + default: + std::cerr << "Can not handle this codec" << std::endl; + break; } - break; } - case VORBIS: - break; - default: - std::cerr << "Can not handle this codec" << std::endl; - break; + offset += (*it); } + }else{ std::cerr <<"Error! Unknown bitstream number " << oggPage.getBitstreamSerialNumber() << std::endl; } + //write header here + if (headerSeen == 0 && headerWritten == false){ + std::cout << DTSCHeader.toNetPacked(); + headerWritten = true; + } + //write section buffer + //write section if (oggPage.typeEOS()){//ending page std::cerr << oggPage.getBitstreamSerialNumber() << " ending" << std::endl; trackData.erase(sNum);