Ogg optimizes
This commit is contained in:
parent
63913f361a
commit
d8b7a3ea1c
5 changed files with 314 additions and 66 deletions
|
@ -20,6 +20,7 @@
|
|||
#include <mist/config.h>
|
||||
#include <mist/stream.h>
|
||||
#include <mist/timing.h>
|
||||
#include "../converters/oggconv.h"
|
||||
|
||||
///\brief Holds everything unique to HTTP Connectors.
|
||||
namespace Connector_HTTP {
|
||||
|
@ -36,8 +37,9 @@ namespace Connector_HTTP {
|
|||
std::string streamname;//Will contain the name of the stream.
|
||||
|
||||
//OGG specific variables
|
||||
OGG::headerPages oggMeta;
|
||||
OGG::Page curOggPage;
|
||||
//OGG::headerPages oggMeta;
|
||||
//OGG::Page curOggPage;
|
||||
OGG::converter oggConv;
|
||||
std::map <long long unsigned int, std::vector<JSON::Value> > DTSCBuffer;
|
||||
std::set <long long unsigned int> sendReady;
|
||||
//std::map <long long unsigned int, long long unsigned int> prevGran;
|
||||
|
@ -141,7 +143,7 @@ namespace Connector_HTTP {
|
|||
if (audioID != -1){
|
||||
cmd << " " << audioID;
|
||||
}
|
||||
cmd << "\ns " << seek_sec << "\np\n";
|
||||
cmd << "\np\n";
|
||||
ss.SendNow(cmd.str().c_str(), cmd.str().size());
|
||||
inited = true;
|
||||
}
|
||||
|
@ -159,8 +161,8 @@ namespace Connector_HTTP {
|
|||
HTTP_S.protocol = "HTTP/1.0";
|
||||
conn.SendNow(HTTP_S.BuildResponse("200", "OK")); //no SetBody = unknown length - this is intentional, we will stream the entire file
|
||||
//Fill in ogg header here
|
||||
oggMeta.readDTSCHeader(Strm.metadata);
|
||||
conn.SendNow((char*)oggMeta.parsedPages.c_str(), oggMeta.parsedPages.size());
|
||||
oggConv.readDTSCHeader(Strm.metadata);
|
||||
conn.SendNow((char*)oggConv.parsedPages.c_str(), oggConv.parsedPages.size());
|
||||
progressive_has_sent_header = true;
|
||||
//setting sendReady to not ready
|
||||
sendReady.clear();
|
||||
|
@ -168,20 +170,11 @@ namespace Connector_HTTP {
|
|||
//parse DTSC to Ogg here
|
||||
if (Strm.lastType() == DTSC::AUDIO || Strm.lastType() == DTSC::VIDEO){
|
||||
currID = Strm.getPacket()["trackid"].asInt();
|
||||
currGran = Strm.getPacket()["granule"].asInt();
|
||||
if (DTSCBuffer.count(currID) && !DTSCBuffer[currID].empty()){
|
||||
prevGran = DTSCBuffer[currID][0]["granule"].asInt();
|
||||
}else{
|
||||
prevGran = 0;
|
||||
}
|
||||
if ((prevGran != 0 && (prevGran == -1 || currGran != prevGran)) ){
|
||||
curOggPage.readDTSCVector(DTSCBuffer[currID], oggMeta.DTSCID2OGGSerial[currID], oggMeta.DTSCID2seqNum[currID]);
|
||||
conn.SendNow((char*)curOggPage.getPage(), curOggPage.getPageSize());
|
||||
DTSCBuffer[currID].clear();
|
||||
sendReady.insert(currID);
|
||||
oggMeta.DTSCID2seqNum[currID]++;
|
||||
}
|
||||
DTSCBuffer[currID].push_back(Strm.getPacket());
|
||||
std::string tmpString = oggConv.readDTSCVector(DTSCBuffer[currID]);
|
||||
conn.SendNow((char*)tmpString.c_str(), tmpString.size());
|
||||
DTSCBuffer[currID].clear();
|
||||
sendReady.insert(currID);
|
||||
}
|
||||
if (Strm.lastType() == DTSC::PAUSEMARK){
|
||||
conn.close();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include<vector>
|
||||
#include <queue>
|
||||
#include <stdlib.h>
|
||||
#include "oggconv.h"
|
||||
|
||||
#include <mist/timing.h>
|
||||
#include <mist/dtsc.h>
|
||||
|
@ -14,21 +15,14 @@
|
|||
namespace Converters{
|
||||
int DTSC2OGG(Util::Config & conf){
|
||||
DTSC::File DTSCFile(conf.getString("filename"));
|
||||
//JSON::Value meta = DTSCFile.getMeta();
|
||||
srand (Util::getMS());//randomising with milliseconds from boot
|
||||
std::vector<unsigned int> curSegTable;
|
||||
OGG::headerPages oggMeta;
|
||||
char* curNewPayload;
|
||||
OGG::converter oggMeta;
|
||||
//Creating ID headers for theora and vorbis
|
||||
DTSC::readOnlyMeta fileMeta = DTSCFile.getMeta();
|
||||
DTSC::Meta giveMeta;
|
||||
for ( std::map<int,DTSC::readOnlyTrack>::iterator it = fileMeta.tracks.begin(); it != fileMeta.tracks.end(); it ++) {
|
||||
std::cerr << "TrackID: " << it->first << std::endl;
|
||||
giveMeta.tracks[it->first].trackID = fileMeta.tracks[it->first].trackID;
|
||||
giveMeta.tracks[it->first].idHeader = fileMeta.tracks[it->first].idHeader;
|
||||
giveMeta.tracks[it->first].init = fileMeta.tracks[it->first].init;
|
||||
giveMeta.tracks[it->first].commentHeader = fileMeta.tracks[it->first].commentHeader;
|
||||
}
|
||||
|
||||
DTSC::Meta giveMeta(fileMeta);
|
||||
|
||||
oggMeta.readDTSCHeader(giveMeta);
|
||||
std::cout << oggMeta.parsedPages;//outputting header pages
|
||||
|
||||
|
@ -49,28 +43,20 @@ namespace Converters{
|
|||
}else{
|
||||
prevGran = 0;
|
||||
}
|
||||
if (prevGran != 0 && (currGran != prevGran)){
|
||||
curOggPage.readDTSCVector(DTSCBuffer[currID], oggMeta.DTSCID2OGGSerial[currID], oggMeta.DTSCID2seqNum[currID]);
|
||||
std::cout << std::string((char*)curOggPage.getPage(), curOggPage.getPageSize());
|
||||
if (!DTSCBuffer[currID].empty()){
|
||||
std::cout << oggMeta.readDTSCVector(DTSCBuffer[currID]);
|
||||
DTSCBuffer[currID].clear();
|
||||
oggMeta.DTSCID2seqNum[currID]++;
|
||||
}
|
||||
DTSCBuffer[currID].push_back(DTSCFile.getJSON());
|
||||
|
||||
DTSCFile.parseNext();
|
||||
}
|
||||
//outputting end of stream pages
|
||||
for (
|
||||
std::map< long long int, std::vector<JSON::Value> >::iterator it = DTSCBuffer.begin();
|
||||
it != DTSCBuffer.end();
|
||||
it++
|
||||
){
|
||||
for (std::map< long long int, std::vector<JSON::Value> >::iterator it = DTSCBuffer.begin(); it != DTSCBuffer.end(); it++){
|
||||
if (!DTSCBuffer[it->first].empty() && DTSCBuffer[it->first][0]["data"].asString() != ""){
|
||||
curOggPage.readDTSCVector(DTSCBuffer[it->first], oggMeta.DTSCID2OGGSerial[it->first], oggMeta.DTSCID2seqNum[it->first]);
|
||||
std::cout << std::string((char*)curOggPage.getPage(), curOggPage.getPageSize());
|
||||
std::cout << oggMeta.readDTSCVector(DTSCBuffer[it->first]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <mist/vorbis.h>
|
||||
#include <mist/config.h>
|
||||
#include <mist/json.h>
|
||||
#include <mist/bitstream.h>
|
||||
|
||||
namespace Converters{
|
||||
enum codecType {THEORA, VORBIS};
|
||||
|
@ -19,11 +20,18 @@ namespace Converters{
|
|||
oggTrack() : lastTime(0), parsedHeaders(false) { }
|
||||
codecType codec;
|
||||
std::string name;
|
||||
std::string contBuffer;//buffer for continuing pages
|
||||
long long unsigned int dtscID;
|
||||
double lastTime;
|
||||
long long unsigned int lastGran;
|
||||
bool parsedHeaders;
|
||||
//Codec specific elements
|
||||
//theora
|
||||
theora::header idHeader;//needed to determine keyframe
|
||||
//vorbis
|
||||
std::deque<vorbis::mode> vModes;
|
||||
char channels;
|
||||
long long unsigned int blockSize[2];
|
||||
};
|
||||
|
||||
int OGG2DTSC(){
|
||||
|
@ -64,7 +72,7 @@ namespace Converters{
|
|||
trackData[sNum].codec = VORBIS;
|
||||
vorbis::header tempHead;
|
||||
tempHead.read(oggPage.getFullPayload(), oggPage.getPayloadSize());
|
||||
mspfv = ntohl(tempHead.getAudioSampleRate()) / 1000;
|
||||
mspfv = (double)1000 / ntohl(tempHead.getAudioSampleRate());
|
||||
}else{
|
||||
std::cerr << "Unknown Codec, " << std::string(oggPage.getFullPayload()+1, 6)<<" skipping" << std::endl;
|
||||
continue;
|
||||
|
@ -79,34 +87,61 @@ namespace Converters{
|
|||
int offset = 0;
|
||||
for (std::deque<unsigned int>::iterator it = oggPage.getSegmentTableDeque().begin(); it != oggPage.getSegmentTableDeque().end(); it++){
|
||||
if (trackData[sNum].parsedHeaders){
|
||||
//output DTSC packet
|
||||
DTSCOut.null();//clearing DTSC buffer
|
||||
DTSCOut["trackid"] = (long long)trackData[sNum].dtscID;
|
||||
long long unsigned int temp = oggPage.getGranulePosition();
|
||||
DTSCOut["granule"] = (long long)temp;
|
||||
DTSCOut["time"] = (long long)trackData[sNum].lastTime;
|
||||
if (trackData[sNum].codec == THEORA){
|
||||
trackData[sNum].lastTime += (mspft / 4);
|
||||
//if we are dealing with the last segment which is a part of a later continued segment
|
||||
if (it == (oggPage.getSegmentTableDeque().end()-1) && oggPage.getPageSegments() == 255 && oggPage.getSegmentTable()[254] == 255 ){
|
||||
//put in buffer
|
||||
trackData[sNum].contBuffer += std::string(oggPage.getFullPayload()+offset, (*it));
|
||||
}else{
|
||||
trackData[sNum].lastTime += (mspfv / 16);
|
||||
}
|
||||
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;
|
||||
//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;
|
||||
if (trackData[sNum].contBuffer != ""){
|
||||
//if a big segment is ending on this page, output buffer
|
||||
DTSCOut["data"] = trackData[sNum].contBuffer + std::string(oggPage.getFullPayload()+offset, (*it));
|
||||
DTSCOut["comment"] = "Using buffer";
|
||||
trackData[sNum].contBuffer = "";
|
||||
}else{
|
||||
DTSCOut["interframe"] = 1;
|
||||
DTSCOut["data"] = std::string(oggPage.getFullPayload()+offset, (*it)); //segment content put in JSON
|
||||
}
|
||||
DTSCOut["time"] = (long long)trackData[sNum].lastTime;
|
||||
if (trackData[sNum].codec == THEORA){
|
||||
trackData[sNum].lastTime += mspft;
|
||||
}else{
|
||||
//Getting current blockSize
|
||||
unsigned int blockSize = 0;
|
||||
Utils::bitstreamLSBF packet;
|
||||
packet.append(DTSCOut["data"].asString());
|
||||
if (packet.get(1) == 0){
|
||||
blockSize = trackData[sNum].blockSize[trackData[sNum].vModes[packet.get(vorbis::ilog(trackData[sNum].vModes.size()-1))].blockFlag];
|
||||
}else{
|
||||
std::cerr << "Warning! packet type != 0" << std::endl;
|
||||
}
|
||||
trackData[sNum].lastTime += mspfv * (blockSize/trackData[sNum].channels);
|
||||
}
|
||||
if (trackData[sNum].codec == THEORA){//marking keyframes
|
||||
if (it == (oggPage.getSegmentTableDeque().end() - 1)){
|
||||
//if we are in the vicinity of a new keyframe
|
||||
if (trackData[sNum].idHeader.parseGranuleUpper(trackData[sNum].lastGran) != trackData[sNum].idHeader.parseGranuleUpper(temp)){
|
||||
//try to mark right
|
||||
long long unsigned int temper = trackData[sNum].idHeader.parseGranuleUpper(temp) - trackData[sNum].idHeader.parseGranuleUpper(trackData[sNum].lastGran);
|
||||
DTSCOut["keyframe"] = 1;
|
||||
trackData[sNum].lastGran = temp;
|
||||
}else{
|
||||
DTSCOut["interframe"] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Ending packet
|
||||
if (oggPage.typeContinue()){//Continuing page
|
||||
DTSCOut["OggCont"] = 1;
|
||||
}
|
||||
if (oggPage.typeEOS()){//ending page of ogg stream
|
||||
DTSCOut["OggEOS"] = 1;
|
||||
}
|
||||
std::cout << DTSCOut.toNetPacked();
|
||||
}
|
||||
// Ending packet
|
||||
if (oggPage.typeContinue()){//Continuing page
|
||||
DTSCOut["OggCont"] = 1;
|
||||
}
|
||||
if (oggPage.typeEOS()){//ending page
|
||||
DTSCOut["OggEOS"] = 1;
|
||||
}
|
||||
|
||||
std::cout << DTSCOut.toNetPacked();
|
||||
}else{//if we ouput a header:
|
||||
//switch on codec
|
||||
switch(trackData[sNum].codec){
|
||||
|
@ -132,6 +167,7 @@ namespace Converters{
|
|||
DTSCHeader["tracks"][trackData[sNum].name]["init"] = std::string(oggPage.getFullPayload()+offset, (*it));
|
||||
headerSeen --;
|
||||
trackData[sNum].parsedHeaders = true;
|
||||
trackData[sNum].lastGran = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -145,6 +181,9 @@ namespace Converters{
|
|||
case 1:{
|
||||
DTSCHeader["tracks"][trackData[sNum].name]["channels"] = (long long)vHead.getAudioChannels();
|
||||
DTSCHeader["tracks"][trackData[sNum].name]["idheader"] = std::string(oggPage.getFullPayload()+offset, (*it));
|
||||
trackData[sNum].channels = vHead.getAudioChannels();
|
||||
trackData[sNum].blockSize[0] = 1 << vHead.getBlockSize0();
|
||||
trackData[sNum].blockSize[1] = 1 << vHead.getBlockSize1();
|
||||
break;
|
||||
}
|
||||
case 3:{
|
||||
|
@ -156,6 +195,8 @@ namespace Converters{
|
|||
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));
|
||||
//saving modes into deque
|
||||
trackData[sNum].vModes = vHead.readModeDeque(trackData[sNum].channels);
|
||||
headerSeen --;
|
||||
trackData[sNum].parsedHeaders = true;
|
||||
break;
|
||||
|
|
199
src/converters/oggconv.cpp
Normal file
199
src/converters/oggconv.cpp
Normal file
|
@ -0,0 +1,199 @@
|
|||
#include"oggconv.h"
|
||||
#include <stdlib.h>
|
||||
#include <mist/bitstream.h>
|
||||
|
||||
|
||||
namespace OGG{
|
||||
void converter::readDTSCHeader(DTSC::Meta & meta){
|
||||
//pages.clear();
|
||||
parsedPages = "";
|
||||
Page curOggPage;
|
||||
srand (Util::getMS());//randomising with milliseconds from boot
|
||||
std::vector<unsigned int> curSegTable;
|
||||
//trackInf.clear();
|
||||
//Creating ID headers for theora and vorbis
|
||||
for ( std::map<int,DTSC::Track>::iterator it = meta.tracks.begin(); it != meta.tracks.end(); it ++) {
|
||||
curOggPage.clear();
|
||||
curOggPage.setVersion();
|
||||
curOggPage.setHeaderType(2);//headertype 2 = Begin of Stream
|
||||
curOggPage.setGranulePosition(0);
|
||||
trackInf[it->second.trackID].OGGSerial = rand() % 0xFFFFFFFE +1; //initialising on a random not 0 number
|
||||
curOggPage.setBitstreamSerialNumber(trackInf[it->second.trackID].OGGSerial);
|
||||
trackInf[it->second.trackID].seqNum = 0;
|
||||
curOggPage.setPageSequenceNumber(trackInf[it->second.trackID].seqNum++);
|
||||
curSegTable.clear();
|
||||
curSegTable.push_back(it->second.idHeader.size());
|
||||
curOggPage.setSegmentTable(curSegTable);
|
||||
curOggPage.setPayload((char*)it->second.idHeader.c_str(), it->second.idHeader.size());
|
||||
curOggPage.setCRCChecksum(curOggPage.calcChecksum());
|
||||
//pages.push_back(curOggPage);
|
||||
parsedPages += std::string(curOggPage.getPage(), curOggPage.getPageSize());
|
||||
trackInf[it->second.trackID].codec = it->second.codec;
|
||||
if (it->second.codec == "theora"){
|
||||
trackInf[it->second.trackID].lastKeyFrame = 1;
|
||||
trackInf[it->second.trackID].sinceKeyFrame = 0;
|
||||
theora::header tempHead;
|
||||
std::string tempString = it->second.idHeader;
|
||||
tempHead.read((char*)tempString.c_str(),42);
|
||||
trackInf[it->second.trackID].significantValue = tempHead.getKFGShift();
|
||||
}else if (it->second.codec == "vorbis"){
|
||||
trackInf[it->second.trackID].lastKeyFrame = 0;
|
||||
trackInf[it->second.trackID].sinceKeyFrame = 0;
|
||||
trackInf[it->second.trackID].prevBlockFlag = -1;
|
||||
vorbis::header tempHead;
|
||||
std::string tempString = it->second.idHeader;
|
||||
tempHead.read((char*)tempString.c_str(),tempString.size());
|
||||
trackInf[it->second.trackID].significantValue = tempHead.getAudioSampleRate() / tempHead.getAudioChannels();
|
||||
if (tempHead.getBlockSize0() <= tempHead.getBlockSize1()){
|
||||
trackInf[it->second.trackID].blockSize[0] = tempHead.getBlockSize0();
|
||||
trackInf[it->second.trackID].blockSize[1] = tempHead.getBlockSize1();
|
||||
}else{
|
||||
trackInf[it->second.trackID].blockSize[0] = tempHead.getBlockSize1();
|
||||
trackInf[it->second.trackID].blockSize[1] = tempHead.getBlockSize0();
|
||||
}
|
||||
char audioChannels = tempHead.getAudioChannels();
|
||||
//getting modes
|
||||
tempString = it->second.init;
|
||||
tempHead.read((char*)tempString.c_str(),tempString.size());
|
||||
trackInf[it->second.trackID].vorbisModes = tempHead.readModeDeque(audioChannels);
|
||||
trackInf[it->second.trackID].hadFirst = false;
|
||||
}
|
||||
}
|
||||
//Creating remaining headers for theora and vorbis
|
||||
//for tracks in header
|
||||
//create standard page with comment (empty) en setup header(init)
|
||||
for ( std::map<int,DTSC::Track>::iterator it = meta.tracks.begin(); it != meta.tracks.end(); it ++) {
|
||||
curOggPage.clear();
|
||||
curOggPage.setVersion();
|
||||
curOggPage.setHeaderType(0);//headertype 0 = normal
|
||||
curOggPage.setGranulePosition(0);
|
||||
curOggPage.setBitstreamSerialNumber(trackInf[it->second.trackID].OGGSerial);
|
||||
curOggPage.setPageSequenceNumber(trackInf[it->second.trackID].seqNum++);
|
||||
curSegTable.clear();
|
||||
curSegTable.push_back(it->second.commentHeader.size());
|
||||
curSegTable.push_back(it->second.init.size());
|
||||
curOggPage.setSegmentTable(curSegTable);
|
||||
std::string fullHeader = it->second.commentHeader + it->second.init;
|
||||
curOggPage.setPayload((char*)fullHeader.c_str(),fullHeader.size());
|
||||
curOggPage.setCRCChecksum(curOggPage.calcChecksum());
|
||||
parsedPages += std::string(curOggPage.getPage(), curOggPage.getPageSize());
|
||||
}
|
||||
}
|
||||
|
||||
std::string converter::readDTSCVector(std::vector <JSON::Value> DTSCVec){
|
||||
Page retVal;
|
||||
int typeFlag = 0;//flag to remember if the page has a continued segment
|
||||
std::string pageBuffer = "";
|
||||
long long int DTSCID = DTSCVec[0]["trackid"].asInt();
|
||||
std::vector<unsigned int> curSegTable;
|
||||
std::string dataBuffer;
|
||||
long long unsigned int lastGran = 0;
|
||||
|
||||
for (unsigned int i = 0; i < DTSCVec.size(); i++){
|
||||
OGG::Page tempPage;
|
||||
tempPage.setSegmentTable(curSegTable);
|
||||
if (DTSCVec[i]["data"].asString().size() >= (255-tempPage.getPageSegments())*255){//if segment is too big
|
||||
//Put page in Buffer and start next page
|
||||
if (!curSegTable.empty()){
|
||||
//output page
|
||||
retVal.clear();
|
||||
retVal.setVersion();
|
||||
retVal.setHeaderType(typeFlag);//headertype 0 = normal
|
||||
retVal.setGranulePosition(lastGran);
|
||||
retVal.setBitstreamSerialNumber(trackInf[DTSCID].OGGSerial);
|
||||
retVal.setPageSequenceNumber(trackInf[DTSCID].seqNum);
|
||||
retVal.setSegmentTable(curSegTable);
|
||||
retVal.setPayload((char*)dataBuffer.c_str(), dataBuffer.size());
|
||||
retVal.setCRCChecksum(retVal.calcChecksum());
|
||||
trackInf[DTSCID].seqNum++;
|
||||
pageBuffer += std::string((char*)retVal.getPage(), retVal.getPageSize());
|
||||
|
||||
curSegTable.clear();
|
||||
dataBuffer = "";
|
||||
}
|
||||
std::string remainingData = DTSCVec[i]["data"].asString();
|
||||
bool firstLoop;
|
||||
typeFlag = 0;
|
||||
while (remainingData.size() > 255*255){
|
||||
//output part of the segment
|
||||
//granule -1
|
||||
curSegTable.clear();
|
||||
curSegTable.push_back(255*255);///\TODO optimise this
|
||||
retVal.clear();
|
||||
retVal.setVersion();
|
||||
retVal.setHeaderType(typeFlag);//normal Page
|
||||
retVal.setGranulePosition(-1);
|
||||
retVal.setBitstreamSerialNumber(trackInf[DTSCID].OGGSerial);
|
||||
retVal.setPageSequenceNumber(trackInf[DTSCID].seqNum);
|
||||
retVal.setSegmentTable(curSegTable);
|
||||
retVal.setPayload((char*)remainingData.substr(0,255*255).c_str(), 255*255);
|
||||
retVal.setCRCChecksum(retVal.calcChecksum());
|
||||
trackInf[DTSCID].seqNum++;
|
||||
pageBuffer += std::string((char*)retVal.getPage(), retVal.getPageSize());
|
||||
remainingData = remainingData.substr(255*255);
|
||||
typeFlag = 1;//1 = continued page
|
||||
}
|
||||
//output last remaining data
|
||||
curSegTable.clear();
|
||||
curSegTable.push_back(remainingData.size());
|
||||
dataBuffer += remainingData;
|
||||
}else{//build data for page
|
||||
curSegTable.push_back(DTSCVec[i]["data"].asString().size());
|
||||
dataBuffer += DTSCVec[i]["data"].asString();
|
||||
}
|
||||
//lastGran = calcGranule(DTSCID, DTSCVec[i]["keyframe"].asBool());
|
||||
//calculating granule position
|
||||
if (trackInf[DTSCID].codec == "theora"){
|
||||
if (DTSCVec[i]["keyframe"].asBool()){
|
||||
trackInf[DTSCID].lastKeyFrame += trackInf[DTSCID].sinceKeyFrame + 1;
|
||||
trackInf[DTSCID].sinceKeyFrame = 0;
|
||||
}else{
|
||||
trackInf[DTSCID].sinceKeyFrame ++;
|
||||
}
|
||||
lastGran = (trackInf[DTSCID].lastKeyFrame << trackInf[DTSCID].significantValue) + trackInf[DTSCID].sinceKeyFrame;
|
||||
} else if (trackInf[DTSCID].codec == "vorbis"){
|
||||
//decode DTSCVec[i]["data"].asString() for mode index
|
||||
Utils::bitstreamLSBF packet;
|
||||
packet.append(DTSCVec[i]["data"].asString());
|
||||
//calculate amount of samples associated with that block (from ID header)
|
||||
//check mode block in deque for index
|
||||
int curPCMSamples = 0;
|
||||
if (packet.get(1) == 0){
|
||||
int tempModes = vorbis::ilog(trackInf[DTSCID].vorbisModes.size()-1);
|
||||
int tempPacket = packet.get(tempModes);
|
||||
int curBlockFlag = trackInf[DTSCID].vorbisModes[tempPacket].blockFlag;
|
||||
curPCMSamples = (1 << trackInf[DTSCID].blockSize[curBlockFlag]);
|
||||
if (trackInf[DTSCID].prevBlockFlag!= -1){
|
||||
if (curBlockFlag == trackInf[DTSCID].prevBlockFlag){
|
||||
curPCMSamples /= 2;
|
||||
}else{
|
||||
curPCMSamples -= (1 << trackInf[DTSCID].blockSize[0]) / 4 + (1 << trackInf[DTSCID].blockSize[1]) / 4;
|
||||
}
|
||||
}
|
||||
trackInf[DTSCID].sinceKeyFrame = (1 << trackInf[DTSCID].blockSize[curBlockFlag]);
|
||||
trackInf[DTSCID].prevBlockFlag = curBlockFlag;
|
||||
}else{
|
||||
std::cerr << "Error, Vorbis packet type !=0" << std::endl;
|
||||
}
|
||||
//add to granule position
|
||||
trackInf[DTSCID].lastKeyFrame += curPCMSamples;
|
||||
lastGran = trackInf[DTSCID].lastKeyFrame;
|
||||
}
|
||||
}
|
||||
//last parts of page put out
|
||||
if (!curSegTable.empty()){
|
||||
retVal.clear();
|
||||
retVal.setVersion();
|
||||
retVal.setHeaderType(typeFlag);//headertype 0 = normal
|
||||
retVal.setGranulePosition(lastGran);
|
||||
retVal.setBitstreamSerialNumber(trackInf[DTSCID].OGGSerial);
|
||||
retVal.setPageSequenceNumber(trackInf[DTSCID].seqNum);
|
||||
retVal.setSegmentTable(curSegTable);
|
||||
retVal.setPayload((char*)dataBuffer.c_str(), dataBuffer.size());
|
||||
retVal.setCRCChecksum(retVal.calcChecksum());
|
||||
trackInf[DTSCID].seqNum++;
|
||||
pageBuffer += std::string((char*)retVal.getPage(), retVal.getPageSize());
|
||||
}
|
||||
return pageBuffer;
|
||||
}
|
||||
}
|
29
src/converters/oggconv.h
Normal file
29
src/converters/oggconv.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include <mist/ogg.h>
|
||||
|
||||
namespace OGG {
|
||||
struct trackStats{
|
||||
unsigned int OGGSerial;
|
||||
unsigned int seqNum;
|
||||
std::string codec;
|
||||
//theora vars
|
||||
unsigned int lastKeyFrame;
|
||||
unsigned int sinceKeyFrame;
|
||||
unsigned int significantValue;//KFGShift for theora and other video;
|
||||
int prevBlockFlag;
|
||||
//vorbis vars
|
||||
bool hadFirst;
|
||||
std::deque<vorbis::mode> vorbisModes;//modes for vorbis
|
||||
char blockSize[2];
|
||||
};
|
||||
|
||||
class converter{
|
||||
public:
|
||||
void readDTSCHeader(DTSC::Meta & meta);
|
||||
std::string readDTSCVector(std::vector <JSON::Value> DTSCVec);
|
||||
std::string parsedPages;
|
||||
private:
|
||||
std::map <long long unsigned int, trackStats> trackInf;
|
||||
//long long unsigned int calcGranule(long long unsigned int trackID, bool keyFrame);
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue