UnTransmoggrify.cpp

Go to the documentation of this file.
00001 //===========================================================================
00002 //Copyright (C) 2003, 2004 Zentaro Kavanagh
00003 //
00004 //Redistribution and use in source and binary forms, with or without
00005 //modification, are permitted provided that the following conditions
00006 //are met:
00007 //
00008 //- Redistributions of source code must retain the above copyright
00009 //  notice, this list of conditions and the following disclaimer.
00010 //
00011 //- Redistributions in binary form must reproduce the above copyright
00012 //  notice, this list of conditions and the following disclaimer in the
00013 //  documentation and/or other materials provided with the distribution.
00014 //
00015 //- Neither the name of Zentaro Kavanagh nor the names of contributors 
00016 //  may be used to endorse or promote products derived from this software 
00017 //  without specific prior written permission.
00018 //
00019 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020 //``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00022 //PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ORGANISATION OR
00023 //CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00024 //EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00025 //PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00026 //PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00027 //LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00028 //NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00029 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 //===========================================================================
00031 
00032 // OggDump.cpp : Defines the entry point for the console application.
00033 //
00034 
00035 #include "stdafx.h"
00036 #include <libOOOgg/libOOOgg.h>
00037 #include <libOOOgg/dllstuff.h>
00038 #include <libilliCore/iBE_Math.h>
00039 #include <libilliCore/iLE_Math.h>
00040 
00041 #include "OggFileWriter.h"
00042 #include <iostream>
00043 #include <fstream>
00044 
00045 unsigned long bytePos;
00046 
00047 OggPageInterleaver* interleaver;
00048 
00049 OggFileWriter* fileWriter;
00050 
00051 OggPage* pendingPage = NULL;
00052 OggMuxStream* pendingStream = NULL;
00053 bool isFirstPage = true;
00054 bool hasPageWaiting = false;
00055 
00056 unsigned long granFixCount = 0;
00057 
00058 struct sStreamInfo {
00059         unsigned long mSerialNo;
00060         unsigned long mUptoSeqNo;
00061         OggMuxStream* mMuxStream;
00062 
00063 };
00064 
00065 vector<sStreamInfo*> streamList;
00066 
00067 
00068 bool fixifyPage(OggPage* inOggPage, sStreamInfo* inStreamInfo)
00069 {
00070         //Fix the granule pos bug
00071         if (inOggPage->numPackets() == 1) {
00072                 if ((inOggPage->getPacket(0)->isTruncated()) && (inStreamInfo->mUptoSeqNo < inStreamInfo->mMuxStream->numHeaders())) {
00073 
00074                         inOggPage->header()->setGranulePos(-1);
00075                 }
00076         }
00077 
00078         //Fix sequence number bug
00079         inOggPage->header()->setPageSequenceNo(inStreamInfo->mUptoSeqNo++);
00080 
00081         //Recompute checksum
00082         inOggPage->computeAndSetCRCChecksum();
00083 
00084         return true;
00085 }
00086 
00087 
00088 bool setMuxState(OggPage* inOggPage, OggMuxStream* inMuxStream) 
00089 {
00090                 if (strncmp((const char*)inOggPage->getPacket(0)->packetData(), "\001vorbis", 7) == 0) {
00091                         inMuxStream->setConversionParams(iLE_Math::charArrToULong(inOggPage->getPacket(0)->packetData() + 12), 1, 10000000);
00092                         inMuxStream->setNumHeaders(3);
00093                         return true;
00094                 } else if ((strncmp((char*)inOggPage->getPacket(0)->packetData(), "\200theora", 7)) == 0){
00095                         //mGranulePosShift = (((inOggPage->getPacket(0)->packetData()[40]) % 4) << 3) + ((inOggPage->getPacket(0)->packetData()[41]) >> 5);
00096                         inMuxStream->setConversionParams(
00097                                                 iBE_Math::charArrToULong(inOggPage->getPacket(0)->packetData() + 22) 
00098                                         ,       iBE_Math::charArrToULong(inOggPage->getPacket(0)->packetData() + 26)
00099                                         ,       10000000
00100                                         ,       (((inOggPage->getPacket(0)->packetData()[40]) % 4) << 3) + ((inOggPage->getPacket(0)->packetData()[41]) >> 5));
00101                         inMuxStream->setNumHeaders(3);
00102                         return true;
00103                 } else {
00104                         return false;
00105                 }
00106 
00107 }
00108 
00109 //This will be called by the callback
00110 bool pageCB(OggPage* inOggPage, void*  /* inUserData  ignored */) 
00111 {
00112         sStreamInfo* locCurrentInfo = NULL;
00113         if (inOggPage->header()->isBOS()) {
00114                 sStreamInfo* locStreamInfo = new sStreamInfo;
00115                 locStreamInfo->mSerialNo = inOggPage->header()->StreamSerialNo();
00116                 locStreamInfo->mUptoSeqNo = 0;
00117                 locStreamInfo->mMuxStream = interleaver->newStream();
00118                 locStreamInfo->mMuxStream->setIsActive(true);
00119                 streamList.push_back(locStreamInfo);
00120 
00121                 if (!setMuxState(inOggPage, locStreamInfo->mMuxStream)) {
00122                         cout<<"Only handles theora and vorbis... ABORT ABORT ABORT!!"<<endl;
00123                         throw 0;
00124                 }
00125 
00126                 locCurrentInfo = locStreamInfo;
00127 
00128                 
00129         } else {
00130                 for (size_t i = 0; i < streamList.size(); i++) {
00131                         if (streamList[i]->mSerialNo == inOggPage->header()->StreamSerialNo()) {
00132                                 locCurrentInfo = streamList[i];
00133                                 break;
00134                         }       
00135                 }
00136         }
00137 
00138         if (locCurrentInfo == NULL) {
00139                 throw 0;
00140         }
00141 
00142         fixifyPage(inOggPage, locCurrentInfo);
00143 
00144 
00145 
00146         if (isFirstPage) {
00147                 if (strncmp((const char*)inOggPage->getPacket(0)->packetData(), "\001vorbis", 7) == 0) {
00148                         //First page is vorbis.
00149 
00150                         //Hold it for later.
00151                         pendingPage = inOggPage;
00152                         pendingStream = locCurrentInfo->mMuxStream;
00153                         isFirstPage = false;
00154                         hasPageWaiting = true;
00155                 }
00156         } else {
00157                 if (hasPageWaiting) {
00158                         if ((strncmp((char*)inOggPage->getPacket(0)->packetData(), "\200theora", 7)) == 0) {
00159                                 //Was vorbis, then theora... need to send the theora first, then the vorbis... then carry on
00160                                 locCurrentInfo->mMuxStream->acceptOggPage(inOggPage);
00161                                 pendingStream->acceptOggPage(pendingPage);
00162                         } else {
00163                                 //Was vorbis... but no theora followed, send the pending page... and carry on as normal
00164                                 pendingStream->acceptOggPage(pendingPage);
00165                                 locCurrentInfo->mMuxStream->acceptOggPage(inOggPage);
00166                         }
00167 
00168                         hasPageWaiting = false;
00169                         pendingPage = NULL;
00170                 } else {
00171                         locCurrentInfo->mMuxStream->acceptOggPage(inOggPage);
00172                 }
00173         }
00174 
00175 
00176 
00177 
00178 
00179 
00180         //cout<<"Page Location : "<<bytePos;
00181         //bytePos += inOggPage->pageSize();
00182         //cout<<" to "<<bytePos<<endl;
00183         //OggPacket* locPack = NULL;
00184         //cout << inOggPage->header()->toString();
00185         //cout << "Num Packets : " << inOggPage->numPackets() << endl;;
00186         //for (unsigned long i = 0; i < inOggPage->numPackets(); i++) {
00187         //      locPack = inOggPage->getPacket(i);
00188         //      cout << "------ Packet  " << i << " (" << locPack->packetSize() << " bytes) -------";
00189         //      
00190         //      if (locPack->isContinuation()) {
00191         //              cout<<"  ** CONT **";
00192         //      }
00193         //      if (locPack->isTruncated()) {
00194         //              cout<<" ** TRUNC **";
00195         //      }
00196         //      cout<<endl;
00197         //      cout << locPack->toPackDumpString();
00198         //}
00199         
00200         return true;
00201 }
00202 
00203 
00204 #ifdef WIN32
00205 int __cdecl _tmain(int argc, _TCHAR* argv[])
00206 #else
00207 int main (int argc, char * argv[])
00208 #endif
00209 {
00210         //This program just dumps the pages out of a file in ogg format.
00211         // Currently does not error checking. Check your command line carefully !
00212         // USAGE :: OggDump <OggFile>
00213         //
00214 
00215 
00216         bytePos = 0;
00217 
00218         if (argc < 3) {
00219                 cout<<"Usage : OOOggDump <filename>"<<endl;
00220         } else {
00221 
00222                 int x;
00223                 cin>>x;
00224 
00225                 string locOutFilename = argv[2];
00226                 fileWriter = new OggFileWriter(locOutFilename);
00227                 interleaver = new OggPageInterleaver(fileWriter, fileWriter);
00228 
00229                 OggDataBuffer testOggBuff;
00230 
00231 
00232                 
00233                 testOggBuff.registerStaticCallback(&pageCB, NULL);
00234 
00235                 fstream testFile;
00236                 testFile.open(argv[1], ios_base::in | ios_base::binary);
00237                 
00238                 const unsigned short BUFF_SIZE = 8092;
00239                 char* locBuff = new char[BUFF_SIZE];
00240                 while (!testFile.eof()) {
00241                         testFile.read(locBuff, BUFF_SIZE);
00242                         unsigned long locBytesRead = testFile.gcount();
00243                 testOggBuff.feed((const unsigned char*)locBuff, locBytesRead);
00244                 }
00245 
00246                 delete[] locBuff;
00247 
00248                 delete interleaver;
00249                 delete fileWriter;
00250 
00251         }
00252 
00253         return 0;
00254 }
00255 

Generated on Thu Feb 16 23:48:20 2006 for oggdsf by  doxygen 1.3.9