OggPageInterleaver.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 #include "stdafx.h"
00032 #include <libOOOgg/OggPageInterleaver.h>
00033 
00034 OggPageInterleaver::OggPageInterleaver(IOggCallback* inFileWriter, INotifyComplete* inNotifier)
00035         :       mFileWriter(inFileWriter)
00036         ,       mNotifier(inNotifier)
00037         ,       mProgressTime(0)
00038         ,       mBytesWritten(0)
00039 {
00040 #ifdef OGGCODECS_LOGGING
00041         debugLog.open("G:\\logs\\interleaver.log", ios_base::out);
00042 #endif
00043 }
00044 
00045 OggPageInterleaver::~OggPageInterleaver(void)
00046 {
00047 #ifdef OGGCODECS_LOGGING
00048         debugLog.close();
00049 #endif
00050 
00051 
00052         //Need to delete stream objects
00053 }
00054 
00055 OggMuxStream* OggPageInterleaver::newStream() {
00056         OggMuxStream* retStream = new OggMuxStream(this);
00057         mInputStreams.push_back(retStream);
00058         return retStream;
00059 }
00060 
00061 void OggPageInterleaver::notifyArrival() {
00062 #ifdef OGGCODECS_LOGGING
00063         debugLog<<endl;
00064         debugLog<<"notifyArrival : "<<endl;
00065 #endif
00066         processData();
00067 }
00068 void OggPageInterleaver::processData() {
00069         /*
00070                 IF ALL EOS THEN
00071                         FINSH UP
00072                         SIGNAL END OF STREAMS
00073                 ELSE
00074                         WHILE IS PROCESSABLE
00075                                 lowestStream = NULL
00076                                 FOR EACH stream in mInputStreams
00077                                         IF NOT stream IS EMPTY THEN
00078                                                 IF lowestStream = NULL THEN
00079                                                         lowestStream = stream
00080                                                 ELSE IF stream.frontTime < lowestStream.frontTime THEN
00081                                                         lowestStream = stream
00082                                                 END IF
00083                                         END IF
00084                                 NEXT stream
00085                                 IF lowestStream = NULL THEN
00086                                         CURSE LOUDLY
00087                                 ELSE
00088                                         WRITE lowestStream.frontPage
00089                                 END IF
00090                         WEND
00091                 END IF
00092         */
00093         //
00094         //Temp
00095 #ifdef OGGCODECS_LOGGING
00096         debugLog<<endl;
00097         debugLog<<"ProcessData : "<<endl;
00098 #endif
00099         
00100         if (isAllEOS()) {
00101                 //debugLog<<"ProcessData : All Streams EOS."<<endl;
00102 
00103                 //Finish up
00104                 while (!isAllEmpty()) {
00105                         //debugLog<<"ProcessData : All Streams EOS : Flushing."<<endl;
00106                         writeLowest();
00107                 }
00108                 //debugLog<<"ProcessData : All Streams EOS : Notify complete."<<endl;
00109                 mNotifier->NotifyComplete();
00110         } else {
00111                 //debugLog<<"ProcessData : All Streams *NOT* EOS."<<endl;
00112                 while (isProcessable()) {
00113                         //debugLog<<"ProcessData : Writing lowest"<<endl;
00114                         writeLowest();
00115                 }
00116                 //debugLog<<"ProcessData : No more processable data"<<endl;
00117                 if (isAllEOS() && isAllEmpty()) {
00118                         //debugLog<<"ProcessData : All EOS and all Empty... Notifying complete..."<<endl;
00119                         mNotifier->NotifyComplete();
00120                 }
00121         }
00122         //debugLog<<"==============="<<endl;
00123 
00124 }
00125 
00126 
00127 
00128 void OggPageInterleaver::writeLowest() {
00129                 OggMuxStream* locLowestStream = NULL;
00130                 for (size_t i = 0; i < mInputStreams.size(); i++) {
00131                         if (!mInputStreams[i]->isEmpty() && mInputStreams[i]->isActive()) {
00132                                 if (locLowestStream == NULL) {
00133                                         if (mInputStreams[i]->peekFront() == NULL) {
00134                                                 int x = 0;
00135                                                 x= x/x;
00136                                         }
00137                                         locLowestStream = mInputStreams[i];
00138                                         //debugLog<<"writeLowest : Defaulting stream "<<i<<" @ Gran = "<<locLowestStream->frontTime()<<" & Time = "<<locLowestStream->scaledFrontTime()<<endl;
00139                                         //debugLog<<"writeLowest : Defaulting stream "<<i<<endl;
00140                                 } else {
00141                                         LOOG_INT64 locCurrLowTime = locLowestStream->scaledFrontTime();
00142                                         LOOG_INT64 locTestLowTime = mInputStreams[i]->scaledFrontTime();
00143 
00144                                         //debuging
00145                                         //LOOG_INT64 locCurrLowTimeUNS = locLowestStream->frontTime();
00146                                         //LOOG_INT64 locTestLowTimeUNS = mInputStreams[i]->frontTime();
00147                                         //debugging end
00148 
00149                                         //debugLog<<"writeLowest : Scaled : Curr = "<<locCurrLowTime<<" -- Test["<<(unsigned long)i<<"] = "<<locTestLowTime<<endl;
00150                                         //debugLog<<"writeLowest : UNSCAL : Curr = "<<locCurrLowTimeUNS<<" -- Test["<<(unsigned long)i<<"] = "<<locTestLowTimeUNS<<endl;
00151 
00152                                         
00153                                         //ASSERT (all header packets have granule pos 0)
00154                                         //
00155 
00156                                         //In english this means... any bos pages go first... then any no gran pos pages (-1 gran pos).. 
00157                                         // then any remaining streams with headers then whoevers got the lowest time.
00158                                         if (
00159                                                 //Precedence goes to BOS pages.
00160                                                 (       (mInputStreams[i]->peekFront() != NULL) && 
00161                                                         (mInputStreams[i]->peekFront()->header()->isBOS()) ) ||
00162                                                 
00163                                                 (       (mInputStreams[i]->peekFront() != NULL) && 
00164                                                         ((mInputStreams[i]->peekFront()->header()->GranulePos()) == -1) ) ||
00165                                                         
00166                                                 //If the tested page hasn't sent all it's headers and the current one either
00167                                                 // a) Has already sent all it's pages OR
00168                                                 // b) Has sent more than the test page
00169                                                 (       (mInputStreams[i]->peekFront() != NULL) && 
00170                                                         (!mInputStreams[i]->sentAllHeaders()) &&
00171                                                         //(!locLowestStream->peekFront()->header()->isBOS()) ) ||
00172                                                         ((locLowestStream->sentAllHeaders()) ||
00173                                                         (mInputStreams[i]->packetsSent() < locLowestStream->packetsSent())) ) ||
00174                                                 
00175                                                 (
00176                                                         (locTestLowTime < locCurrLowTime))
00177                                            ) 
00178                                         {
00179                                                 
00180                                                 //DeBUGGIN BLOCK
00181                                                 if (    (mInputStreams[i]->peekFront() != NULL) && 
00182                                                                 (mInputStreams[i]->peekFront()->header()->isBOS()) ) {
00183                                                         //debugLog<<"WriteLowest : Selecting because BOS"<<endl;
00184                                                 }
00185                                                 if              (       (mInputStreams[i]->peekFront() != NULL) && 
00186                                                                         ((mInputStreams[i]->peekFront()->header()->GranulePos()) == -1) ) {
00187                                                         //debugLog<<"WriteLowest : Selecting because gran pos = -1"<<endl;
00188                                                 }
00189 
00190                                                 if      ((mInputStreams[i]->peekFront() != NULL) && 
00191                                                         (!mInputStreams[i]->sentAllHeaders()) &&
00192                                                         (mInputStreams[i]->packetsSent() < locLowestStream->packetsSent()) ) {
00193 
00194                                                                         //debugLog<<"WriteLowest : Selecting because hasn't sent all headers"<<endl;
00195                                                 }
00196 
00197                                                 if (locTestLowTime < locCurrLowTime) {
00198                                                 
00199                                                         //debugLog<<"WriteLowest : Selecting because test time "<<locTestLowTime<<" less than "<<locCurrLowTime<<endl;
00200                                                 }
00201                                                 //END BEBUGGING BLOCK
00202                                                 locLowestStream = mInputStreams[i];
00203                                                 //debugLog<<"writeLowest : Selecting stream "<<(unsigned long)i<<" @ Gran = "<<locLowestStream->frontTime()<<" & Time = "<<locLowestStream->scaledFrontTime()<<endl;
00204                                         }
00205                                 }
00206                         }
00207                 }
00208                 if (locLowestStream == NULL) {
00209                         throw 0;
00210                 } else {
00211                         //debugLog<<"writeLowest : Writing..."<<endl;
00212                         if (locLowestStream->scaledFrontTime() != -1) {
00213                                 mProgressTime = locLowestStream->scaledFrontTime();
00214                         }
00215                 
00216                         //debugLog<<"writeLowest : Progress Time = "<<mProgressTime<<endl;
00217 
00218                         OggPage* locPageToWrite = locLowestStream->popFront();
00219                         mBytesWritten += locPageToWrite->pageSize();
00220                         //TODO::: Handle case where the popped page is a null pointer. Can it even happen ?? There should never be a null pointer.
00221                         mFileWriter->acceptOggPage(locPageToWrite);             //Gives away page
00222                 }
00223 
00224 }
00225 
00226 LOOG_INT64 OggPageInterleaver::progressTime() 
00227 {
00228         return mProgressTime;
00229 }
00230 
00231 LOOG_INT64 OggPageInterleaver::bytesWritten()
00232 {
00233         return mBytesWritten;
00234 }
00235 bool OggPageInterleaver::isProcessable() {
00236         bool retVal = true;
00237         //ASSERT(mInputStreams.size() >= 1)
00238         for (size_t i = 0; i < mInputStreams.size(); i++) {
00239                 retVal = retVal && (mInputStreams[i]->isProcessable());
00240         }
00241         //if (retVal) {
00242         //      debugLog<<"isPRocessable : TRUE"<<endl;
00243         //} else {
00244         //      debugLog<<"isPRocessable : FALSE"<<endl;
00245         //}
00246         return retVal;
00247 }
00248 bool OggPageInterleaver::isAllEOS() {
00249         bool retVal = true;
00250         //ASSERT(mInputStreams.size() >= 1)
00251         for (size_t i = 0; i < mInputStreams.size(); i++) {
00252                 //if (mInputStreams[i]->isEOS()) {
00253                 //      debugLog<<"isAllEOS : *****                  Stream "<<(unsigned long)i<<" is EOS"<<endl;
00254                 //} else {
00255                 //      debugLog<<"isAllEOS : *****                  Stream "<<(unsigned long)i<<" not EOS"<<endl;
00256                 //}
00257                 retVal = retVal && (mInputStreams[i]->isEOS() || !mInputStreams[i]->isActive());
00258         }
00259         //if (retVal) {
00260         //      debugLog<<"isAllEOS : TRUE"<<endl;
00261         //} else {
00262         //      debugLog<<"isAllEOS : FALSE"<<endl;
00263         //}
00264         return retVal;
00265 }
00266 
00267 bool OggPageInterleaver::isAllEmpty() {
00268         bool retVal = true;
00269         //ASSERT(mInputStreams.size() >= 1)
00270         for (size_t i = 0; i < mInputStreams.size(); i++) {
00271                 retVal = retVal && (mInputStreams[i]->isEmpty());
00272         }
00273         return retVal;
00274 }

Generated on Tue Feb 15 14:54:21 2005 for oggdsf by  doxygen 1.3.9