From e3861f9fc6b95ba4bcee80a1573e438f1459c0fd Mon Sep 17 00:00:00 2001 From: Oswald de Bruin Date: Thu, 6 Jun 2013 12:06:29 +0200 Subject: [PATCH] Started ogg support in lib --- lib/Makefile.am | 4 +- lib/ogg.cpp | 246 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/ogg.h | 40 ++++++++ 3 files changed, 288 insertions(+), 2 deletions(-) create mode 100644 lib/ogg.cpp create mode 100644 lib/ogg.h diff --git a/lib/Makefile.am b/lib/Makefile.am index 9f68f05d..d0fb29e1 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,5 +1,5 @@ lib_LTLIBRARIES=libmist-1.0.la -libmist_1_0_la_SOURCES=amf.h amf.cpp auth.h auth.cpp base64.h base64.cpp config.h config.cpp dtsc.h dtsc.cpp flv_tag.h flv_tag.cpp http_parser.h http_parser.cpp json.h json.cpp procs.h procs.cpp rtmpchunks.h rtmpchunks.cpp socket.h socket.cpp mp4.h mp4.cpp ftp.h ftp.cpp filesystem.h filesystem.cpp stream.h stream.cpp timing.h timing.cpp ts_packet.cpp ts_packet.h converter.cpp converter.h +libmist_1_0_la_SOURCES=amf.h amf.cpp auth.h auth.cpp base64.h base64.cpp config.h config.cpp dtsc.h dtsc.cpp flv_tag.h flv_tag.cpp http_parser.h http_parser.cpp json.h json.cpp procs.h procs.cpp rtmpchunks.h rtmpchunks.cpp socket.h socket.cpp mp4.h mp4.cpp ftp.h ftp.cpp filesystem.h filesystem.cpp stream.h stream.cpp timing.h timing.cpp ts_packet.cpp ts_packet.h converter.cpp converter.h ogg.h ogg.cpp libmist_1_0_la_LDFLAGS = -version-info 5:1:2 libmist_1_0_la_CPPFLAGS=$(DEPS_CFLAGS) $(global_CFLAGS) libmist_1_0_la_LIBADD=$(DEPS_LIBS) $(CLOCK_LIB) @@ -8,4 +8,4 @@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = mist-1.0.pc library_includedir=$(includedir)/mist-1.0/mist -library_include_HEADERS = amf.h auth.h base64.h config.h dtsc.h flv_tag.h http_parser.h json.h procs.h rtmpchunks.h socket.h mp4.h ftp.h filesystem.h stream.h timing.h nal.h ts_packet.h converter.h +library_include_HEADERS = amf.h auth.h base64.h config.h dtsc.h flv_tag.h http_parser.h json.h procs.h rtmpchunks.h socket.h mp4.h ftp.h filesystem.h stream.h timing.h nal.h ts_packet.h converter.h ogg.h diff --git a/lib/ogg.cpp b/lib/ogg.cpp new file mode 100644 index 00000000..1a04235f --- /dev/null +++ b/lib/ogg.cpp @@ -0,0 +1,246 @@ +#include "ogg.h" +#include +#include +#include +#include + +#define lsb32(offset) data[offset] | data[offset+1] << 8 | data[offset+2] << 16 | data[offset+3] << 24 + +namespace OGG{ + Page::Page(){ + data = NULL; + datasize = 0; + dataSum = 0; + } + + bool Page::read(std::string & newData){ + dataSum = 0; + datasize = 0; + if (newData.size()<27){ + return false; + } + if (!checkDataSize(27)){ + return false; + } + memcpy(data, newData.c_str(), 27);//copying the header, always 27 bytes + if(!checkDataSize(27 + getPageSegments())){ + return false; + } + memcpy(data + 27, newData.c_str() + 27, getPageSegments()); + //copying the first part of the page into data, which tells the size of the page + + for(unsigned int i = 0; i < getPageSegments(); i++){ + dataSum += getSegmentTable()[i]; + } + if(!checkDataSize(27 + getPageSegments()+dataSum)){ + return false; + } + memcpy(data + 27 + getPageSegments(), newData.c_str() + 27 + getPageSegments(), dataSum); + newData.erase(0, datasize); + return true; + } + + long unsigned int Page::getMagicNumber(){ + return ntohl(((long unsigned int*)(data))[0]); + } + + void Page::setMagicNumber(){ + if(checkDataSize(4)){ + memcpy(data, "OggS", 4); + } + } + + char Page::getVersion(){ + return data[4]; + } + + void Page::setVersion(char newVal){ + if(checkDataSize(5)){ + data[4] = newVal; + } + } + + char Page::getHeaderType(){ + return data[5]; + } + + void Page::setHeaderType(char newVal){ + if(checkDataSize(6)){ + data[5] = newVal; + } + } + + long long unsigned int Page::getGranulePosition(){ + if(checkDataSize(14)){ + //switching bit order upon return + return ntohl(((long unsigned*)(data+6))[1]) & ((long long unsigned)(ntohl(((long unsigned*)(data+6))[0]) << 32)); + } + return 0; + } + + void Page::setGranulePosition(long long unsigned int newVal){ + if(checkDataSize(14)){ + ((long unsigned*)(data+6))[1] = htonl(newVal & 0xFFFFFFFF); + ((long unsigned*)(data+6))[0] = htonl((newVal >> 32) & 0xFFFFFFFF); + } + } + + long unsigned int Page::getBitstreamSerialNumber(){ + //return ntohl(((long unsigned int*)(data+14))[0]); + return lsb32(14); + } + + void Page::setBitstreamSerialNumber(long unsigned int newVal){ + if(checkDataSize(18)){ + ((long unsigned *)(data+14))[0] = htonl(newVal); + } + } + + long unsigned int Page::getPageSequenceNumber(){ + return lsb32(18); + } + + void Page::setPageSequenceNumber(long unsigned int newVal){ + if(checkDataSize(22)){ + ((long unsigned *)(data+18))[0] = htonl(newVal); + } + } + + long unsigned int Page::getCRCChecksum(){ + return ntohl(((long unsigned int*)(data+22))[0]); + //return lsb32(22); + } + + void Page::setCRCChecksum(long unsigned int newVal){ + if(checkDataSize(26)){ + ((long unsigned *)(data+22))[0] = htonl(newVal); + } + } + + char Page::getPageSegments(){ + return data[26]; + } + + inline void Page::setPageSegments(char newVal){ + data[26] = newVal; + } + + char* Page::getSegmentTable(){ + return data+27; + } + + std::deque Page::getSegmentTableDeque(){ + std::deque retVal; + unsigned int temp = 0; + char* segmentTable = getSegmentTable(); + for (unsigned int i = 0; i < getPageSegments(); i++){ + temp += segmentTable[i]; + if (segmentTable[i] < 255){ + retVal.push_back(temp); + temp = 0; + } + } + return retVal; + } + + bool Page::setSegmentTable(std::vector layout){ + unsigned int place = 0; + char table[255]; + for (unsigned int i = 0; i < layout.size(); i++){ + while (layout[i]>=255){ + if (place >= 255) return false; + table[place] = 255; + layout[i] -= 255; + place++; + } + if (place >= 255) return false; + table[place] = layout[i]; + place++; + } + setSegmentTable(table,place); + return true; + } + + void Page::setSegmentTable(char* newVal, unsigned int length){ + if(checkDataSize(27 + length)){ + memcpy(data + 27, newVal, length); + } + } + + char* Page::getFullPayload(){ + return data + 27 + getPageSegments(); + } + + std::string Page::toPrettyString(){ + std::stringstream r; + r << "Size(" << datasize << ")(" << dataSum << ")" << std::endl; + r << "Magic_Number: " << std::string(data, 4) << std::endl; + r << "Version: " << (int)getVersion() << std::endl; + r << "Header_type: " << std::hex << (int)getHeaderType() << std::dec; + if (getHeaderType() & 0x01){ + r << " continued"; + } + if (getHeaderType() & 0x02){ + r << " bos"; + } + if (getHeaderType() & 0x04){ + r << " eos"; + } + r << std::endl; + r << "Granule_position: " << getGranulePosition() << std::endl; + r << "Bitstream_SN: " << getBitstreamSerialNumber() << std::endl; + r << "Page_sequence_number: " << getPageSequenceNumber() << std::endl; + r << "CRC_checksum: " << std::hex << getCRCChecksum()<< std::dec << std::endl; + r << " Calced Checksum: " << std::hex << calcChecksum() << std::dec << std::endl; + r << "CRC_checksum write: " << std::hex << getCRCChecksum()<< std::dec << std::endl; + r << "Page_segments: " << (int)getPageSegments() << std::endl; + r << "SegmentTable: "; + std::deque temp = getSegmentTableDeque(); + for (std::deque::iterator i = temp.begin(); i != temp.end(); i++){ + r << (*i) << " "; + } + r << std::endl; + return r.str(); + } + + long unsigned int Compute(char* buffer, unsigned int count){ + long unsigned int m_crc = ~0u; + //const unsigned char* ptr = (const unsigned char *) buffer; + for (unsigned int i = 0; i < count; i++) { + buffer++; + m_crc ^= ((unsigned long int)buffer << 24); + for (int i = 0; i < 8; i++) { + if (m_crc & 0x80000000) { + m_crc = (m_crc << 1) ^ 0x04C11DB7; + }else { + m_crc <<= 1; + } + } + } + return m_crc; + } + + long unsigned int Page::calcChecksum(){ + long unsigned int retVal = 0; + long unsigned int oldChecksum = getCRCChecksum(); + setCRCChecksum (0); + retVal = Compute(data, datasize); + setCRCChecksum (oldChecksum); + return retVal; + } + + bool Page::checkDataSize(unsigned int size){ + if (size > datasize){ + void* tmp = realloc(data,size); + if (tmp){ + data = (char*)tmp; + datasize = size; + return true; + }else{ + return false; + } + }else{ + return true; + } + } +} diff --git a/lib/ogg.h b/lib/ogg.h new file mode 100644 index 00000000..5d2e1d2d --- /dev/null +++ b/lib/ogg.h @@ -0,0 +1,40 @@ +#include +#include +#include + + +namespace OGG{ + class Page{ + public: + Page(); + bool read(std::string & newData); + long unsigned int getMagicNumber(); + void setMagicNumber(); + char getVersion(); + void setVersion(char newVal = 0); + char getHeaderType(); + void setHeaderType(char newVal); + long long unsigned int getGranulePosition(); + void setGranulePosition(long long unsigned int newVal); + long unsigned int getBitstreamSerialNumber(); + void setBitstreamSerialNumber(long unsigned int newVal); + long unsigned int getPageSequenceNumber(); + void setPageSequenceNumber(long unsigned int newVal); + long unsigned int getCRCChecksum(); + void setCRCChecksum(long unsigned int newVal); + char getPageSegments(); + inline void setPageSegments(char newVal); + char* getSegmentTable(); + std::deque getSegmentTableDeque(); + bool setSegmentTable(std::vector layout); + void setSegmentTable(char* newVal, unsigned int length); + char* getFullPayload(); + std::string toPrettyString(); + private: + long unsigned int calcChecksum(); + char* data; + unsigned int datasize; + unsigned int dataSum; + bool checkDataSize(unsigned int size); + }; +}