00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "stdafx.h"
00033 #include <libOOOgg/OggPaginator.h>
00034
00035
00036
00037 static unsigned long crc_lookup[256]={
00038 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,
00039 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
00040 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
00041 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
00042 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,
00043 0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
00044 0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,
00045 0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
00046 0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,
00047 0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
00048 0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,
00049 0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
00050 0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,
00051 0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
00052 0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,
00053 0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
00054 0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,
00055 0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
00056 0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,
00057 0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
00058 0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,
00059 0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
00060 0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,
00061 0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
00062 0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,
00063 0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
00064 0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,
00065 0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
00066 0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,
00067 0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
00068 0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,
00069 0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
00070 0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,
00071 0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
00072 0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,
00073 0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
00074 0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,
00075 0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
00076 0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,
00077 0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
00078 0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,
00079 0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
00080 0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,
00081 0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
00082 0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,
00083 0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
00084 0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,
00085 0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
00086 0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,
00087 0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
00088 0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,
00089 0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
00090 0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,
00091 0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
00092 0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,
00093 0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
00094 0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,
00095 0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
00096 0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,
00097 0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
00098 0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,
00099 0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
00100 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
00101 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4
00102 };
00103
00104
00105
00106 OggPaginator::OggPaginator(void)
00107 : mPageCallback(NULL)
00108 , mSettings(NULL)
00109 , mPendingPage(NULL)
00110 , mCurrentPageSize(0)
00111 , mSegmentTableSize(0)
00112 , mPendingPageHasData(false)
00113 , mSequenceNo(0)
00114 , mPacketCount(0)
00115 , mLastGranulePos(0)
00116 {
00117
00118
00119 mHeaderBuff = new unsigned char[300];
00120
00121 }
00122
00123 OggPaginator::~OggPaginator(void)
00124 {
00125 delete mHeaderBuff;
00126 mHeaderBuff = NULL;
00127
00128 }
00129
00130
00131 bool OggPaginator::setParameters(OggPaginatorSettings* inSettings) {
00132 delete mSettings;
00133 mSettings = inSettings;
00134
00135
00136 createFreshPage();
00137 return true;
00138 }
00139
00140 OggPaginatorSettings* OggPaginator::parameters() {
00141 return mSettings;
00142 }
00143
00144
00145 bool OggPaginator::acceptStampedOggPacket(StampedOggPacket* inOggPacket)
00146 {
00147
00148
00149 addPacketToPage(inOggPacket);
00150
00151 delete inOggPacket;
00152
00153 return true;
00154 }
00155 bool OggPaginator::finishStream()
00156 {
00157
00158
00159
00160
00161
00162
00163
00164 if (mPendingPage->numPackets() == 0) {
00165
00166 mPendingPage->header()->setGranulePos(mLastGranulePos);
00167
00168 }
00169
00170 mPendingPage->header()->setHeaderFlags(mPendingPage->header()->HeaderFlags() | 4);
00171 deliverCurrentPage();
00172 return true;
00173 }
00174
00175 bool OggPaginator::setChecksum()
00176 {
00177 unsigned long locChecksum = 0;
00178 unsigned long locTemp = 0;
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 if (mPendingPage != NULL) {
00194
00195 mPendingPage->header()->setCRCChecksum((unsigned long)0);
00196 mPendingPage->header()->rawData(mHeaderBuff, 300);
00197
00198 for(unsigned long i = 0; i < mPendingPage->headerSize(); i++) {
00199
00200 locTemp = ((locChecksum >> 24) & 0xff) ^ mHeaderBuff[i];
00201
00202 locChecksum=(locChecksum << 8) ^ crc_lookup[locTemp];
00203 }
00204
00205
00206
00207 unsigned char* locBuff = NULL;
00208 for(unsigned long i = 0; i < mPendingPage->numPackets(); i++) {
00209 locBuff = mPendingPage->getPacket(i)->packetData();
00210
00211 for (unsigned long j = 0; j < mPendingPage->getPacket(i)->packetSize(); j++) {
00212 locTemp = ((locChecksum >> 24) & 0xff) ^ locBuff[j];
00213 locChecksum = (locChecksum << 8) ^ crc_lookup[locTemp];
00214 }
00215 }
00216
00217 mPendingPage->header()->setCRCChecksum(locChecksum);
00218 }
00219 return true;
00220
00221 }
00222 bool OggPaginator::deliverCurrentPage() {
00223
00224
00225 mPendingPage->header()->setSegmentTable((const unsigned char*)mSegmentTable, mSegmentTableSize);
00226
00227 mPendingPage->header()->setDataSize(mCurrentPageSize - mPendingPage->headerSize());
00228
00229 setChecksum();
00230
00231
00232 mLastGranulePos = mPendingPage->header()->GranulePos();
00233
00234
00235 mPageCallback->acceptOggPage(mPendingPage);
00236 mPendingPage = NULL;
00237 createFreshPage();
00238 return true;
00239
00240 }
00241 bool OggPaginator::createFreshPage() {
00242
00243
00244 mPendingPage = new OggPage;
00245 mCurrentPageSize = OggPageHeader::OGG_BASE_HEADER_SIZE;
00246 mPendingPageHasData = false;
00247 mSegmentTableSize = 0;
00248
00249 mPendingPage->header()->setStreamSerialNo(mSettings->mSerialNo);
00250 mPendingPage->header()->setPageSequenceNo(mSequenceNo);
00251
00252
00253 if (mSequenceNo == 0) {
00254
00255 mPendingPage->header()->setHeaderFlags(OggPageHeader::BOS);
00256 } else {
00257
00258 mPendingPage->header()->setHeaderFlags(OggPageHeader::NO_FLAGS);
00259 }
00260
00261 mPendingPage->header()->setGranulePos(OggPageHeader::UNKNOWN_GRANULE_POS);
00262 mSequenceNo++;
00263 return true;
00264
00265 }
00266 bool OggPaginator::addPacketToPage(StampedOggPacket* inOggPacket) {
00267
00268
00269
00270 mPendingPageHasData = true;
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 long locPacketRemaining = inOggPacket->packetSize();
00285 unsigned long locPacketStartPoint = 0;
00286 unsigned long locConsumed = 0;
00287
00288
00289
00290
00291 while (locPacketRemaining > 0) {
00292
00293
00294 locConsumed = addAsMuchPacketAsPossible(inOggPacket, locPacketStartPoint, locPacketRemaining);
00295
00296
00297
00298 locPacketStartPoint += locConsumed;
00299 locPacketRemaining -= locConsumed;
00300
00301
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311 if (((mPacketCount < mSettings->mNumHeaders) || ((mSettings->mMaxPacksPerPage != 0) && (mPacketCount >= mSettings->mMaxPacksPerPage))) && (mPendingPageHasData)) {
00312
00313
00314
00315
00316 deliverCurrentPage();
00317 }
00318 mPacketCount++;
00319 return true;
00320 }
00321
00322
00323 unsigned long OggPaginator::addAsMuchPacketAsPossible(StampedOggPacket* inOggPacket, unsigned long inStartAt, long inRemaining)
00324 {
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 unsigned long locSpaceLeft = MIN(((255 - mSegmentTableSize) * 255) - 1, mSettings->mMaxPageSize - mCurrentPageSize);
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 locSpaceLeft -= (locSpaceLeft % 255);
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 unsigned long locHowMuchToAdd = MIN(locSpaceLeft, inRemaining);
00370
00371
00372
00373
00374 if ((!mPendingPageHasData) && (inStartAt != 0)) {
00375
00376 mPendingPage->header()->setHeaderFlags((unsigned char)(mPendingPage->header()->HeaderFlags() | OggPageHeader::CONTINUATION));
00377
00378 }
00379
00380 if (locHowMuchToAdd > 0) {
00381
00382 addPartOfPacketToPage(inOggPacket, inStartAt, locHowMuchToAdd);
00383 }
00384
00385
00386
00387 if ((mCurrentPageSize >= mSettings->mMinPageSize) || (mPendingPage->header()->PageSequenceNo() == 0) || (locHowMuchToAdd == 0)) {
00388
00389 deliverCurrentPage();
00390 }
00391 return locHowMuchToAdd;
00392
00393 }
00394
00395 bool OggPaginator::addPartOfPacketToPage(StampedOggPacket* inOggPacket, unsigned long inStartFrom, unsigned long inLength) {
00396
00397
00398
00399
00400
00401 unsigned char* locBuff = new unsigned char[inLength];
00402 memcpy((void*)locBuff, (const void*)(inOggPacket->packetData() + inStartFrom), inLength);
00403
00404
00405
00406
00407
00408
00409
00410 bool locIsLastOfPacket = (inStartFrom + inLength == inOggPacket->packetSize());
00411
00412
00413
00414 StampedOggPacket* locPartialPacket = new StampedOggPacket( locBuff,
00415 inLength,
00416 locIsLastOfPacket,
00417 false,
00418 inOggPacket->startTime(),
00419 inOggPacket->endTime(),
00420 inOggPacket->mStampType);
00421
00422
00423
00424 mPendingPage->addPacket(locPartialPacket);
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437 unsigned long locNumSegsNeeded = (inLength / 255);
00438
00439
00440
00441
00442 for (unsigned long i = 0; i < locNumSegsNeeded; i++) {
00443 mSegmentTable[mSegmentTableSize] = 255;
00444 mSegmentTableSize++;
00445 }
00446
00447
00448
00449 if (locIsLastOfPacket) {
00450
00451
00452
00453
00454 mSegmentTable[mSegmentTableSize] = (unsigned char)(inLength % 255);
00455 mSegmentTableSize++;
00456
00457
00458 locNumSegsNeeded++;
00459 } else {
00460
00461
00462
00463
00464 if ((inLength % 255) != 0) {
00465
00466 }
00467
00468
00469
00470 }
00471
00472
00473
00474
00475 mCurrentPageSize += (locNumSegsNeeded + inLength);
00476
00477
00478
00479 if (locIsLastOfPacket) {
00480
00481 mPendingPage->header()->setGranulePos(inOggPacket->endTime());
00482 }
00483
00484 return true;
00485 }
00486
00487
00488
00489
00490
00491
00492
00493 bool OggPaginator::setPageCallback(IOggCallback* inPageCallback) {
00494 mPageCallback = inPageCallback;
00495 return true;
00496 }
00497
00498 void OggPaginator::setNumHeaders(unsigned long inNumHeaders) {
00499 mSettings->mNumHeaders = inNumHeaders;
00500 }
00501 unsigned long OggPaginator::numHeaders() {
00502 return mSettings->mNumHeaders;
00503
00504 }