OggValidationState.cpp

Go to the documentation of this file.
00001 #include "stdafx.h"
00002 #include "OggValidationState.h"
00003 
00004 OggValidationState::OggValidationState(void)
00005         :       mNumBOS(0)
00006         ,       mNumEOS(0)
00007         ,       mExpectingBOS(false)
00008         ,       mIsValid(false)
00009         ,       mState(FVS_SEEN_NOTHING)
00010 
00011 {
00012 }
00013 
00014 OggValidationState::~OggValidationState(void)
00015 {
00016 }
00017 
00018 
00019 OggStreamValidationState* OggValidationState::getStreamBySerialNo(unsigned long inSerialNo) {
00020         //Find this stream.... or make a new one.
00021 
00022         for (size_t i = 0; i < mStreams.size(); i++) {
00023                 if (mStreams[i]->mSerialNo == inSerialNo) {
00024                         return mStreams[i];
00025                 }
00026         }
00027 
00028         OggStreamValidationState* retStream = new OggStreamValidationState;
00029 
00030         retStream->mSerialNo = inSerialNo;
00031         mStreams.push_back(retStream);
00032 
00033         return retStream;
00034 }
00035 unsigned long OggValidationState::numStreams() {
00036         return (unsigned long)mStreams.size();
00037 }
00038 
00039 OggStreamValidationState* OggValidationState::getStream(unsigned long inIndex) {
00040         //gets the indexed string from the vector
00041 
00042         if (inIndex < mStreams.size()) {
00043         return mStreams[inIndex];
00044         } else {
00045                 return NULL;
00046         }
00047 
00048 }
00049 
00050 bool OggValidationState::notify(bool isBOS, bool isEOS) {
00051         bool locOK = true;
00052         if (mState == FVS_SEEN_NOTHING) {
00053                 mState = FVS_AWAITING_BOS;
00054                 //throw 0;
00055         }
00056 
00057         mIsValid = false;
00058 
00059         if (isBOS) {
00060                 mNumBOS++;
00061                 if (mState == FVS_AWAITING_BOS) {
00062                         //Valid case.
00063                         
00064                 } else {
00065                         //Unexpected BOS page.
00066                         mState = FVS_INVALID;
00067                         locOK = false;
00068                 }
00069 
00070                 if (mNumBOS == mNumEOS) {
00071                         //Start of chain
00072                 }
00073         }
00074 
00075         if (isEOS) {
00076                 mNumEOS++;
00077                 if (mState == FVS_AWAITING_BOS || mState == FVS_AWAITING_EOS) {
00078                         
00079                         if (mNumBOS == mNumEOS) {
00080                                 //Valid case. Chain.
00081                                 //We are here because we've seen an equal number of EOS and BOS and at least 1 EOS(this one)
00082                                 // This happens whenever a complete chain of streams complete and/or the end of a complete physical bitstream.
00083                                 // 
00084                                 //This is the only place it's possible for isValid to become true.
00085                                 // It is true when an equal number of eos and bos pages are seen,
00086                                 //  and all streams are also considered fully valid.
00087 
00088                                 //If this EOS balanced the eos = bos then we can accept bos pages again.
00089                                 mState = FVS_AWAITING_BOS;
00090                                 
00091         
00092                                 if (mStreams.size() != 0) {
00093                                         mIsValid = true;
00094                                         for (size_t i = 0; i < mStreams.size(); i++) {
00095                                                 mIsValid &= (mStreams[i]->mState == OggStreamValidationState::VS_FULLY_VALID);
00096                                         }
00097                                 }
00098                         } else {
00099                                 mState = FVS_AWAITING_EOS;
00100                         }
00101                 } else {
00102                         mState = FVS_INVALID;
00103                         locOK = false;
00104                 }
00105 
00106                 //Check for entire stream validity
00107                 
00108 
00109         }
00110 
00111         if (!isBOS && !isEOS) {
00112                 //This is used because BOS pages must follow each other, after a non BOS page, no more BOS
00113                 // pages can occur until all currently open streams have seen an EOS.
00114                 if (mState == FVS_AWAITING_BOS || mState == FVS_AWAITING_EOS) {
00115                         //Valid case.
00116                         //This happens the first non-bos, non-eos page, when in awaiting BOS state.
00117 
00118                         mState = FVS_AWAITING_EOS;
00119                 } else {
00120 
00121                         mState = FVS_INVALID;
00122                         locOK = false;
00123                 }
00124         }
00125 
00126         return mIsValid;
00127 
00128 }
00129 
00130 bool OggValidationState::isValid() {
00131         return mIsValid;
00132 }
00133 bool OggValidationState::acceptOggPage(OggPage* inOggPage) {                    //AOP:::Needs validation
00134         //Validate the page header
00135         
00136         
00137         OggStreamValidationState* locStreamState = getStreamBySerialNo(inOggPage->header()->StreamSerialNo());
00138 
00139         OggPageHeader* locHeader = inOggPage->header();
00140 
00141         //If this stream previously was valid, it should have no more data... so it's no longer valid.
00142         if (locStreamState->mState == OggStreamValidationState::VS_FULLY_VALID) {
00143                 error_write(OVE_DATA_AFTER_VALID_STREAM,inOggPage,  locStreamState);
00144                 mIsValid = false;
00145                 locStreamState->mState = OggStreamValidationState::VS_INVALID;
00146                 //Should return ?
00147         }
00148 
00149         const int UNUSED_HEADER_MASK =  248; //11111000
00150         const int OGG_FLAG_CONTINUATION = 1;
00151         if ((locHeader->HeaderFlags() & UNUSED_HEADER_MASK) != 0) {
00152                 //Unused header bits are set.
00153                 error_write(OVE_UNUSED_HEADER_BITS_SET, inOggPage, locStreamState);
00154                 mIsValid = false;
00155                 locStreamState->mState = OggStreamValidationState::VS_INVALID;
00156         }
00157 
00158         if (locStreamState->mState == OggStreamValidationState::VS_WAITING_FOR_CONTINUATION) {
00159                 //Last page had an incomplete packet, so expecting a continuation flag on this page
00160                 if ((locHeader->HeaderFlags() & OGG_FLAG_CONTINUATION) != 0) {
00161                         //Valid case.
00162 
00163                         //Got the continuation we were expecting.
00164                         locStreamState->mState = OggStreamValidationState::VS_SEEN_BOS;
00165                 } else {
00166                         //There should have been a continuation flag here.
00167                         error_write(OVE_CONTINUATION_FLAG_EXPECTED, inOggPage, locStreamState);
00168                         mIsValid = false;
00169                         locStreamState->mState = OggStreamValidationState::VS_INVALID;
00170                 }
00171         } else {
00172                 if ((locHeader->HeaderFlags() & OGG_FLAG_CONTINUATION) != 0) {
00173                         //We have a continuation flag we weren't expecting.
00174                         error_write(OVE_UNEXPECTED_CONTINUATION_FLAG, inOggPage, locStreamState);
00175                         mIsValid = false;
00176                         locStreamState->mState = OggStreamValidationState::VS_INVALID;
00177 
00178                 }
00179         }
00180         
00181         
00182         //----------------------------------------------------------------------
00183         //Verify structure version is 0 (RFC 3533 Sec. 6.1)
00184         if (locHeader->StructureVersion() != 0) {
00185                 error_write(OVE_STRUCTURE_VERSION_NOT_ZERO, inOggPage, locStreamState);
00186                 mIsValid = false;
00187         }
00188         //----------------------------------------------------------------------
00189         //Verify BOS integrity.
00190         
00191         if (locHeader->isBOS()) {
00192                 
00193                 
00194 
00195                 if (locStreamState->mState == OggStreamValidationState::VS_SEEN_NOTHING) {
00196                         //Valid case.
00197                         locStreamState->mState = OggStreamValidationState::VS_SEEN_BOS;
00198                 }
00199 
00200 
00201 
00202                 //Check is BOS is first page in stream
00203                 if (locStreamState->mSeenAnything == true) {
00204                         error_write(OVE_BOS_PAGE_NOT_AT_START,inOggPage,  locStreamState);
00205                         mIsValid = false;
00206                 }
00207                 //Check if this is the second or more BOS page.
00208                 if (locStreamState->mSeenBOS) {
00209                         error_write(OVE_MORE_THAN_ONE_BOS,inOggPage, locStreamState);
00210                         mIsValid = false;
00211                 }
00212 
00213                 locStreamState->mSeenBOS = true;
00214 
00215         }
00216 
00217         //----------------------------------------------------------------------
00218         //Verify EOS integrity
00219         if (locHeader->isEOS()) {
00220                 
00221                 
00222                 
00223                 if (locStreamState->mState == OggStreamValidationState::VS_SEEN_BOS) {
00224                         //Valid case.
00225                         locStreamState->mState = OggStreamValidationState::VS_FULLY_VALID;
00226                 }
00227 
00228 
00229                 //Check is BOS has been seen before this EOS
00230                 if (locStreamState->mSeenBOS == false) {
00231                         error_write(OVE_EOS_BEFORE_BOS,inOggPage, locStreamState);
00232                         mIsValid = false;
00233                 }
00234                 //Check if this is the second or more BOS page.
00235                 if (locStreamState->mSeenEOS) {
00236                         error_write(OVE_MORE_THAN_ONE_EOS, inOggPage, locStreamState);
00237                         mIsValid = false;
00238                 }
00239         
00240                 locStreamState->mSeenEOS = true;
00241         }
00242 
00243         //----------------------------------------------------------------------
00244         //Verify Granule pos
00245         if (locHeader->GranulePos() != -1) {
00246                 //Check if the granule pos decreased.
00247                 if (locHeader->GranulePos() < locStreamState->mGranulePosUpto) {
00248                         error_write(OVE_GRANULE_POS_DECREASED, inOggPage, locStreamState);
00249                         mIsValid = false;
00250                 }
00251 
00252                 
00253                 locStreamState->mGranulePosUpto = locHeader->GranulePos();
00254 
00255         } else {
00256                 //No packets end here
00257         }
00258 
00259         
00260         //----------------------------------------------------------------------
00261 
00262         //Verify sequence No
00263         if (locHeader->PageSequenceNo() == locStreamState->mSequenceNoUpto) {
00264                 //error_write(OVE_SEQUENCE_NO_REPEATED, inOggPage, locStreamState);
00265                 //mIsValid = false;
00266         } else if (locHeader->PageSequenceNo() < locStreamState->mSequenceNoUpto) {
00267                 error_write(OVE_SEQUENCE_NO_DECREASED, inOggPage, locStreamState);
00268                 mIsValid = false;
00269         } else {
00270                 locStreamState->mSequenceNoUpto = locHeader->PageSequenceNo();
00271         }
00272         //----------------------------------------------------------------------
00273 
00274         //----------------------------------------------------------------------
00275 
00276         //Check for incomplete last packet
00277         if (inOggPage->numPackets() > 0) {
00278                 if (inOggPage->getPacket(inOggPage->numPackets() - 1)->isTruncated() == true)  {
00279                         //Valid case
00280                         //If the last packet is incomplete.
00281                         if (OggStreamValidationState::VS_SEEN_BOS) {                    //TODO::: Bug ????
00282                                 //...And we've seen a BOS page
00283 
00284                                 //Now we wait for the continuation
00285                                 locStreamState->mState = OggStreamValidationState::VS_WAITING_FOR_CONTINUATION;
00286                         } else {
00287                                 //Does this mean anythign ?
00288                                 //Normal untruncated packet.
00289                         }
00290                 }
00291         }
00292         //----------------------------------------------------------------------
00293         //----------------------------------------------------------------------
00294 
00295 
00296         notify(inOggPage->header()->isBOS(), inOggPage->header()->isEOS());
00297         return true;
00298 }
00299 
00300 OggValidationState::eOggValidationState OggValidationState::validationState() {
00301         return mState;
00302 }
00303 void OggValidationState::error_write(short int inErrNo, OggPage* inOggPage, OggStreamValidationState* inStreamState) {
00304 
00305         string locErrorString = "";
00306         switch (inErrNo) {
00307                 case OVE_OK:
00308                         //Do nothing
00309                         return;
00310                         break;
00311                 case OVE_STRUCTURE_VERSION_NOT_ZERO:
00312                         locErrorString = (int)inOggPage->header()->StructureVersion();
00313                         locErrorString = "Structure version(" + locErrorString +") is not 0, (RFC 3533 Sec. 6.1)";
00314                         break;
00315                 case OVE_MORE_THAN_ONE_BOS:
00316                         locErrorString = "More than one BOS page in stream.";
00317                         break;
00318                 case OVE_MORE_THAN_ONE_EOS:
00319                         locErrorString = "More than one EOS page in stream.";
00320                         break;
00321                 case OVE_BOS_PAGE_NOT_AT_START:
00322                         locErrorString = "BOS found not as first page in stream.";
00323                         break;
00324                 case OVE_EOS_BEFORE_BOS:
00325                         locErrorString = "EOS page found before BOS page";
00326                         break;
00327                 case OVE_DATA_AFTER_VALID_STREAM:
00328                         locErrorString = "More data was received for a stream that was previously complete and valid.";
00329                         break;
00330                 case OVE_UNUSED_HEADER_BITS_SET:
00331                         locErrorString = "One or more unused header flags (XXXXXebc) are set.";
00332                         break;
00333                 case OVE_CONTINUATION_FLAG_EXPECTED:
00334                         locErrorString = "Page did not set continuation flag after incomplete packet.";
00335                         break;
00336                 case OVE_UNEXPECTED_CONTINUATION_FLAG:
00337                         locErrorString = "Continuation flag with no previous incomplete packet.";
00338                         break;
00339 
00340                 //Process errors
00341                 case OggDataBuffer::PROCESS_FAILED_TO_SET_HEADER:
00342                         locErrorString = "Lost Sync.";
00343                         break;
00344                 default:
00345                         locErrorString = "Unnamed Error"; 
00346                         break;
00347         }
00348 
00349         if (inStreamState != NULL) {
00350         inStreamState->mErrorCount++;
00351         }
00352 
00353         cout << "ERROR "<<(int)inErrNo<<":  "<<locErrorString<<endl;
00354 
00355 }
00356 
00357 

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