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
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
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
00055 }
00056
00057 mIsValid = false;
00058
00059 if (isBOS) {
00060 mNumBOS++;
00061 if (mState == FVS_AWAITING_BOS) {
00062
00063
00064 } else {
00065
00066 mState = FVS_INVALID;
00067 locOK = false;
00068 }
00069
00070 if (mNumBOS == mNumEOS) {
00071
00072 }
00073 }
00074
00075 if (isEOS) {
00076 mNumEOS++;
00077 if (mState == FVS_AWAITING_BOS || mState == FVS_AWAITING_EOS) {
00078
00079 if (mNumBOS == mNumEOS) {
00080
00081
00082
00083
00084
00085
00086
00087
00088
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
00107
00108
00109 }
00110
00111 if (!isBOS && !isEOS) {
00112
00113
00114 if (mState == FVS_AWAITING_BOS || mState == FVS_AWAITING_EOS) {
00115
00116
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) {
00134
00135
00136
00137 OggStreamValidationState* locStreamState = getStreamBySerialNo(inOggPage->header()->StreamSerialNo());
00138
00139 OggPageHeader* locHeader = inOggPage->header();
00140
00141
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
00147 }
00148
00149 const int UNUSED_HEADER_MASK = 248;
00150 const int OGG_FLAG_CONTINUATION = 1;
00151 if ((locHeader->HeaderFlags() & UNUSED_HEADER_MASK) != 0) {
00152
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
00160 if ((locHeader->HeaderFlags() & OGG_FLAG_CONTINUATION) != 0) {
00161
00162
00163
00164 locStreamState->mState = OggStreamValidationState::VS_SEEN_BOS;
00165 } else {
00166
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
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
00184 if (locHeader->StructureVersion() != 0) {
00185 error_write(OVE_STRUCTURE_VERSION_NOT_ZERO, inOggPage, locStreamState);
00186 mIsValid = false;
00187 }
00188
00189
00190
00191 if (locHeader->isBOS()) {
00192
00193
00194
00195 if (locStreamState->mState == OggStreamValidationState::VS_SEEN_NOTHING) {
00196
00197 locStreamState->mState = OggStreamValidationState::VS_SEEN_BOS;
00198 }
00199
00200
00201
00202
00203 if (locStreamState->mSeenAnything == true) {
00204 error_write(OVE_BOS_PAGE_NOT_AT_START,inOggPage, locStreamState);
00205 mIsValid = false;
00206 }
00207
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
00219 if (locHeader->isEOS()) {
00220
00221
00222
00223 if (locStreamState->mState == OggStreamValidationState::VS_SEEN_BOS) {
00224
00225 locStreamState->mState = OggStreamValidationState::VS_FULLY_VALID;
00226 }
00227
00228
00229
00230 if (locStreamState->mSeenBOS == false) {
00231 error_write(OVE_EOS_BEFORE_BOS,inOggPage, locStreamState);
00232 mIsValid = false;
00233 }
00234
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
00245 if (locHeader->GranulePos() != -1) {
00246
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
00257 }
00258
00259
00260
00261
00262
00263 if (locHeader->PageSequenceNo() == locStreamState->mSequenceNoUpto) {
00264
00265
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
00277 if (inOggPage->numPackets() > 0) {
00278 if (inOggPage->getPacket(inOggPage->numPackets() - 1)->isTruncated() == true) {
00279
00280
00281 if (OggStreamValidationState::VS_SEEN_BOS) {
00282
00283
00284
00285 locStreamState->mState = OggStreamValidationState::VS_WAITING_FOR_CONTINUATION;
00286 } else {
00287
00288
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
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
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