OggStream.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 "oggstream.h"
00033 
00034 OggStream::OggStream(OggPage* inBOSPage, OggDemuxSourceFilter* inOwningFilter, bool inAllowSeek)
00035         :       mCodecHeaders(NULL)
00036         ,       mOwningFilter(inOwningFilter)
00037         ,       mAllowSeek(inAllowSeek)
00038         ,       mSerialNo(0)
00039         ,       mSourcePin(NULL)
00040         ,       mNumHeadersNeeded(0)
00041         ,       mStreamReady(false)
00042         //,     mPartialPacket(NULL)
00043         ,       mFirstRun(true)
00044         ,       mSendExcess(true)
00045         ,       mLastEndGranulePos(0)
00046         ,       mLastStartGranulePos(0)
00047         ,       mStreamLock(NULL)
00048         ,       mAllowDispatch(false)
00049 {
00050         
00051         //Need to do something here !
00052         mSerialNo = inBOSPage->header()->StreamSerialNo();
00053         //string locLogName = "G:\\logs\\oggstream" + StringHelper::numToString(mSerialNo) + ".log";
00054         //debugLog.open(locLogName.c_str(), ios_base::out);
00055         mStreamLock = new CCritSec;
00056         //This may need to be moved to derived class
00057         //Yep, Sure did !
00058         //InitCodec(inBOSPage->getPacket(0));
00059 
00060         //Set the packetisers callback to our acceptstampedoggpacket function.
00061         mPacketiser.setPacketSink(this);
00062 
00063 }
00064 
00065 OggStream::~OggStream(void)
00066 {
00067         //debugLog<<"Destructor..."<<endl;
00068         //debugLog.close();
00069         delete mSourcePin;
00070 
00071 
00072         delete mCodecHeaders;
00073         //delete mPartialPacket;
00074         delete mStreamLock;
00075         //Don't try to delete owning filter !!
00076 }
00077 
00078 bool OggStream::streamReady() {
00079         return mStreamReady;
00080 
00081 }
00082 
00083 unsigned long OggStream::serialNo() {
00084         return mSerialNo;
00085 }
00086 void OggStream::setAllowDispatch(bool inAllowDispatch) {
00087         mAllowDispatch = inAllowDispatch;
00088 }
00089 bool OggStream::acceptStampedOggPacket(StampedOggPacket* inPacket) {
00090     if (!mStreamReady) {
00091                 //Streams not ready, still headers.
00092                 //Stream is ready when all header packets are seen.
00093                 // Any data packets the are on the same page as the headers are excess packets. ???? Maybe not any more.
00094                 processHeaderPacket(inPacket);
00095 
00096                 if(mNumHeadersNeeded <= 0) {
00097                         //Make sure we create the pin if we got everything already
00098                         AddPin();
00099                         //Add pin will set streamready to true if it was all good.
00100                 }
00101 
00102                 //This branch we keep the incoming packet so don't delete
00103         } else {
00104                 //Data packets...
00105                 if (mAllowDispatch) {
00106                         if (mFirstRun) {
00107                                 mFirstRun = false;
00108                                 //debugLog<<"Delviering codec headers..."<<endl;
00109                                 //Deliver the header data
00110                                 deliverCodecHeaders();
00111                         }               
00112                         
00113                         processDataPacket(inPacket);
00114                         delete inPacket;
00115                 } else {
00116                         delete inPacket;
00117                         return false;
00118                 }
00119         }
00120         
00121         return true;
00122 }
00123 
00124 
00125 //ANX::: Need to override here to ensure the anxdata header isn't passed through.
00126 bool OggStream::processHeaderPacket(StampedOggPacket* inPacket) {
00127         //FIX::: Return values
00128 
00129         //We don't delete the packet... the codecheader list will delete when it's done.
00130         //StampedOggPacket* locPacket = processPacket(inPacket);
00131         if (inPacket != NULL) {
00132                 //We got a comlpete packet
00133                 //debugLog<<"Adding codec header..."<<endl;
00134                 mCodecHeaders->addPacket(inPacket);
00135                 mNumHeadersNeeded--;
00136                 //debugLog<<"Headers still needed = "<<mNumHeadersNeeded<<endl;
00137         }
00138         return true;
00139 }
00140 
00141 bool OggStream::processDataPacket(StampedOggPacket* inPacket) {
00142         //We must delete the packet we get back when we have finished
00143         //StampedOggPacket* locPacket = processPacket(inPacket);
00144         if (inPacket != NULL) {
00145                 dispatchPacket(inPacket);
00146                 //delete locPacket;
00147                 inPacket = NULL;
00148         }
00149 
00150         return true;
00151 }
00152 
00153 
00154 OggDemuxSourcePin* OggStream::getPin() {
00155         return mSourcePin;
00156 }
00157 
00158 
00159 CMediaType* OggStream::createMediaType(GUID inMajorType, GUID inSubType, GUID inFormatType, unsigned long inFormatSize, BYTE* inFormatBlock) {
00160         AM_MEDIA_TYPE locAMMediaType;
00161         locAMMediaType.majortype = inMajorType;
00162 
00163         locAMMediaType.subtype = inSubType;
00164         locAMMediaType.formattype = inFormatType;
00165         locAMMediaType.cbFormat = inFormatSize; //0;//sizeof(sSpeexFormatBlock);
00166         locAMMediaType.pbFormat = inFormatBlock; //(BYTE*)locSpeexFormatInfo;
00167         locAMMediaType.pUnk = NULL;
00168         
00169                         
00170         //LEAK CHECK::: Does this get deleted ?
00171         return new CMediaType(locAMMediaType);
00172 }
00173 
00174 unsigned long OggStream::numCodecHeaders() {
00175         //TODO::: Check for null.
00176         //debugLog<<"Num codec headers = "<<mCodecHeaders->numPackets()<<endl;
00177         return mCodecHeaders->numPackets();
00178 }
00179 void OggStream::flush() {
00180         CAutoLock locLock(mStreamLock);
00181         //delete mPartialPacket;
00182         //TODO::: Tell the packetiser to flush.
00183         //mPartialPacket = NULL;
00184         mPacketiser.reset();
00185 }
00186 
00187 void OggStream::flush(unsigned short inNumPacketsToIgnore) {
00188         CAutoLock locLock(mStreamLock);
00189         //delete mPartialPacket;
00190         //TODO::: Tell the packetiser to flush.
00191         //mPartialPacket = NULL;
00192         //debugLog<<"Flush and ignore "<<inNumPacketsToIgnore<<endl;
00193         mPacketiser.reset();
00194         mPacketiser.setNumIgnorePackets(inNumPacketsToIgnore);
00195 }
00196 //ANX::: Need to override here to create anx pins
00197 bool OggStream::AddPin() {
00198         createFormatBlock();
00199         CMediaType* locMediaType = createMediaType(     getMajorTypeGUID(),
00200                                                                                                 getSubtypeGUID(), 
00201                                                                                                 getFormatGUID(), 
00202                                                                                                 getFormatBlockSize(), 
00203                                                                                                 getFormatBlock());
00204 
00205         //LEAK CHECK::: Where does this get deleted ?
00206         OggDemuxSourcePin* locSourcePin = new OggDemuxSourcePin(        NAME("Ogg Source Pin"), 
00207                                                                                                                                 mOwningFilter, 
00208                                                                                                                                 mOwningFilter->m_pLock, 
00209                                                                                                                                 mCodecHeaders, 
00210                                                                                                                                 locMediaType, 
00211                                                                                                                                 getPinName(),
00212                                                                                                                                 mAllowSeek,
00213                                                                                                                                 getNumBuffers(),
00214                                                                                                                                 getBufferSize()
00215                                                                                                                         );
00216         mStreamReady = true;
00217         mSourcePin = locSourcePin;
00218         
00219         return true;
00220         
00221 }
00222 
00223 void OggStream::setLastEndGranPos(__int64 inGranPos) {
00224         //osDebug<<"*************************** ERROR ERROR ERROR **********************"<<endl;
00225         //debugLog<<"*************************** ERROR ERROR ERROR **********************"<<endl;
00226         mLastEndGranulePos = inGranPos;
00227 }
00228 bool OggStream::acceptOggPage(OggPage* inOggPage) {             //Gives away page.
00229         
00230         //debugLog<<"Accepting ogg page..."<<endl;
00231 
00232 
00233         //TODO::: Is this even necessary any more ?????
00234 
00235         //Chaining hack for icecast.
00236         if ( (!mAllowSeek) && (inOggPage->header()->isBOS() )) {
00237                 //debugLog<<"ice case hack"<<endl;
00238                 //A BOS page can only be sent here if it's a chain... otherwise
00239                 // it would have already been stripped by the demux if it was at the
00240                 // start of the file.
00241                 //debugLog<<"Detected chain... setting seek timebase to -1"<<endl;
00242                 mOwningFilter->mSeekTimeBase = -1;              
00243 
00244         }
00245 
00246         //FIX::: Add proper error checking.
00247 
00248         //debugLog<<"acceptOggPage : "<<endl<<inOggPage->header()->toString()<<endl<<endl;;
00249         //StampedOggPacket* locPacket = NULL;
00251         mLastStartGranulePos = mLastEndGranulePos;
00252         mLastEndGranulePos = inOggPage->header()->GranulePos();
00253 
00254         //Put the page through the packetiser.
00255         return mPacketiser.acceptOggPage(inOggPage);
00256 
00257 }
00258 
00259 void OggStream::setSendExcess(bool inSendExcess) {
00260         mSendExcess = inSendExcess;
00261 }
00262 
00263 bool OggStream::deliverCodecHeaders() {
00264         StampedOggPacket* locPacket = NULL;
00265         for (unsigned long i = 0; i < mCodecHeaders->numPackets(); i++) {
00266                 locPacket = mCodecHeaders->getPacket(i);
00267 
00268                 dispatchPacket(locPacket);
00269         }
00270         return true;
00271 }
00272 
00273 //ANX::: Maybe also needs override. ??
00274 bool OggStream::dispatchPacket(StampedOggPacket* inPacket) { //We don't own this packet.
00275         //debugLog<<"Ogg Stream : Packet stamps = "<<inPacket->startTime()<<" - "<<inPacket->endTime()<<endl;
00276         return mSourcePin->deliverOggPacket(inPacket);          
00277 }
00278 
00279 void OggStream::setSerialNo(unsigned long inSerialNo) {
00280         mSerialNo = inSerialNo;
00281 }
00282 

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