Ogg 2 DTSC nearly working

This commit is contained in:
Oswald Auguste de Bruin 2013-07-16 16:22:26 +02:00 committed by Thulinma
parent d72b1ebbbf
commit a0a6e957a5
2 changed files with 102 additions and 49 deletions

View file

@ -27,6 +27,9 @@ namespace Analysers{
if (memcmp("theora",oggPage.getFullPayload() + 1,6) == 0){ if (memcmp("theora",oggPage.getFullPayload() + 1,6) == 0){
sn2Codec[oggPage.getBitstreamSerialNumber()] = "theora"; sn2Codec[oggPage.getBitstreamSerialNumber()] = "theora";
} }
if (memcmp("vorbis",oggPage.getFullPayload() + 1,6) == 0){
sn2Codec[oggPage.getBitstreamSerialNumber()] = "vorbis";
}
} }
oggPage.setInternalCodec(sn2Codec[oggPage.getBitstreamSerialNumber()]); oggPage.setInternalCodec(sn2Codec[oggPage.getBitstreamSerialNumber()]);
std::cout << oggPage.toPrettyString() << std::endl; std::cout << oggPage.toPrettyString() << std::endl;

View file

@ -7,6 +7,7 @@
#include <mist/dtsc.h> #include <mist/dtsc.h>
#include <mist/ogg.h> #include <mist/ogg.h>
#include <mist/theora.h> #include <mist/theora.h>
#include <mist/vorbis.h>
#include <mist/config.h> #include <mist/config.h>
#include <mist/json.h> #include <mist/json.h>
@ -15,13 +16,14 @@ namespace Converters{
class oggTrack{ class oggTrack{
public: public:
oggTrack() : lastTime() { } oggTrack() : lastTime(), parsedHeaders(false) { }
codecType codec; codecType codec;
std::string name; std::string name;
long long unsigned int dtscID; long long unsigned int dtscID;
long long unsigned int lastTime; long long unsigned int lastTime;
bool parsedHeaders;
//Codec specific elements //Codec specific elements
theora::header idHeader; theora::header idHeader;//needed to determine keyframe
}; };
int OGG2DTSC(){ int OGG2DTSC(){
@ -30,13 +32,16 @@ namespace Converters{
//netpacked //netpacked
//Read all of std::cin to oggBuffer //Read all of std::cin to oggBuffer
//while stream busy
JSON::Value DTSCOut; JSON::Value DTSCOut;
JSON::Value DTSCHeader; JSON::Value DTSCHeader;
DTSCHeader.null(); DTSCHeader.null();
DTSCHeader["moreheader"] = 0ll; DTSCHeader["moreheader"] = 0ll;
std::map<long unsigned int, oggTrack> trackData; std::map<long unsigned int, oggTrack> trackData;
long long int lastTrackID = 1; 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()){ while (std::cin.good()){
for (unsigned int i = 0; (i < 1024) && (std::cin.good()); i++){//buffering for (unsigned int i = 0; (i < 1024) && (std::cin.good()); i++){//buffering
oggBuffer += std::cin.get(); oggBuffer += std::cin.get();
@ -47,9 +52,13 @@ namespace Converters{
if (oggPage.typeBOS()){//defines a new track if (oggPage.typeBOS()){//defines a new track
std::cerr << "Begin "<< sNum << std::endl; std::cerr << "Begin "<< sNum << std::endl;
if (memcmp(oggPage.getFullPayload()+1, "theora", 6) == 0){ if (memcmp(oggPage.getFullPayload()+1, "theora", 6) == 0){
headerSeen += 1;
headerWritten = false;
trackData[sNum].codec = THEORA; trackData[sNum].codec = THEORA;
std::cerr << "Snr " << sNum << "=theora" << std::endl; std::cerr << "Snr " << sNum << "=theora" << std::endl;
}else if(memcmp(oggPage.getFullPayload()+1, "vorbis", 6) == 0){ }else if(memcmp(oggPage.getFullPayload()+1, "vorbis", 6) == 0){
headerSeen += 1;
headerWritten = false;
std::cerr << "Snr " << sNum << "=vorbis" << std::endl; std::cerr << "Snr " << sNum << "=vorbis" << std::endl;
trackData[sNum].codec = VORBIS; trackData[sNum].codec = VORBIS;
}else{ }else{
@ -63,60 +72,101 @@ namespace Converters{
} }
//if Serial number is available in mapping //if Serial number is available in mapping
if(trackData.find(sNum)!=trackData.end()){ if(trackData.find(sNum)!=trackData.end()){
//switch on codec int offset = 0;
switch(trackData[sNum].codec){ for (std::deque<unsigned int>::iterator it = oggPage.getSegmentTableDeque().begin(); it != oggPage.getSegmentTableDeque().end(); it++){
case THEORA:{ if (trackData[sNum].parsedHeaders){
int offset = 0; //todo output segment
theora::header tHead; //output DTSC packet
fprintf(stderr, "Parsing %d elements\n", oggPage.getSegmentTableDeque().size()); DTSCOut.null();//clearing DTSC buffer
for (std::deque<unsigned int>::iterator it = oggPage.getSegmentTableDeque().begin(); it != oggPage.getSegmentTableDeque().end(); it++){ DTSCOut["trackid"] = (long long)trackData[sNum].dtscID;
fprintf(stderr, "Parsing Snr %u: element of length %d\n", sNum, (*it)); long long unsigned int temp = oggPage.getGranulePosition();
if(tHead.read(oggPage.getFullPayload()+offset, (*it))){//if the current segment is a header part DTSCOut["time"] = (long long)trackData[sNum].lastTime ++;
std::cerr << "Theora Header Segment " << tHead.getHeaderType() << std::endl; DTSCOut["data"] = std::string(oggPage.getFullPayload()+offset, (*it)); //segment content put in JSON
//fillDTSC header if (trackData[sNum].codec == THEORA){
switch(tHead.getHeaderType()){ if (trackData[sNum].idHeader.parseGranuleLower(temp) == 0){ //granule mask equals zero when on keyframe
case 0:{ //identification header DTSCOut["keyframe"] = 1;
trackData[sNum].idHeader = tHead; }else{
break; DTSCOut["interframe"] = 1;
}
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();
} }
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: offset += (*it);
break;
default:
std::cerr << "Can not handle this codec" << std::endl;
break;
} }
}else{ }else{
std::cerr <<"Error! Unknown bitstream number " << oggPage.getBitstreamSerialNumber() << std::endl; 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 if (oggPage.typeEOS()){//ending page
std::cerr << oggPage.getBitstreamSerialNumber() << " ending" << std::endl; std::cerr << oggPage.getBitstreamSerialNumber() << " ending" << std::endl;
trackData.erase(sNum); trackData.erase(sNum);