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
00033 #include "mmsgui/mmsgifloader.h"
00034 #include "mmsgui/fb/mmsfbsurface.h"
00035 #include <cstring>
00036 #include <cstdlib>
00037
00038 extern "C" {
00039 #include <sys/time.h>
00040 #include <time.h>
00041 }
00042
00043
00044
00045 MMSGIFLoader::MMSGIFLoader(MMSIM_DESC *_desc,
00046 MMSFBLayer *_layer) :
00047 desc(_desc),
00048 layer(_layer),
00049 myfile(NULL) {
00050
00051 this->desc->loading = true;
00052
00053 pthread_cond_init(&this->cond, NULL);
00054 pthread_mutex_init(&this->mutex, NULL);
00055 }
00056
00057 bool MMSGIFLoader::loadHeader() {
00058 unsigned char buffer[1024];
00059 size_t count = 0;
00060
00061 this->myfile = new MMSFile(this->desc->imagefile);
00062 if (!this->myfile) return false;
00063
00064
00065 if (!this->myfile->readBuffer((void*)buffer, &count, 1, 6)) {
00066
00067 return false;
00068 }
00069
00070
00071 memset(&this->gif_header, 0, sizeof(this->gif_header));
00072 if (count < 6) {
00073
00074 return false;
00075 }
00076 memcpy(gif_header.signature, &(buffer[0]), 3);
00077 memcpy(gif_header.version, &(buffer[3]), 3);
00078 if (memcmp(gif_header.signature, "GIF", 3)!=0) {
00079
00080 return false;
00081 }
00082
00083 #ifdef GIFTRACE
00084 DEBUGOUT("FILE=%s\n", this->desc->imagefile.c_str());
00085 DEBUGOUT("HEADER\nSIGNATURE='%s'\nVERSION='%s'\n\n", this->gif_header.signature, this->gif_header.version);
00086 #endif
00087
00088
00089 if (!this->myfile->readBuffer((void*)buffer, &count, 1, 7)) {
00090
00091 return false;
00092 }
00093
00094
00095 memset(&this->gif_lsd, 0, sizeof(this->gif_lsd));
00096 this->gif_lsd.width = *((unsigned short*)&buffer[0]);
00097 this->gif_lsd.height = *((unsigned short*)&buffer[2]);
00098 this->gif_lsd.flags = buffer[4];
00099 this->gif_lsd.bgcolor = buffer[5];
00100 this->gif_lsd.ratio = buffer[6];
00101 this->gif_lsd.global_color_table = ((this->gif_lsd.flags & 0x80) == 0x80);
00102
00103 #ifdef GIFTRACE
00104 DEBUGOUT("LOGICAL SCREEN DESCRIPTOR\nWIDTH='%u'\nHEIGHT='%u'\nFLAGS='%x'\nBGCOLOR='0x%02x'\nRATIO='%u'\nGCT=%s\n\n", gif_lsd.width, gif_lsd.height,
00105 this->gif_lsd.flags, this->gif_lsd.bgcolor, this->gif_lsd.ratio,
00106 (this->gif_lsd.global_color_table)?"yes":"no");
00107 #endif
00108
00109 if (gif_lsd.global_color_table) {
00110
00111 memset(&this->gif_gct, 0, sizeof(this->gif_gct));
00112 int y = (this->gif_lsd.flags & 0x07) + 1;
00113 this->gif_gct.size = 2;
00114 while (y-->1) this->gif_gct.size*=2;
00115 if (!this->myfile->readBuffer((void*)this->gif_gct.table, &count, 1, 3 * this->gif_gct.size)) {
00116
00117 return false;
00118 }
00119
00120 if (count < size_t(3 * this->gif_gct.size)) {
00121
00122 return false;
00123 }
00124
00125 #ifdef GIFTRACE
00126 DEBUGOUT("GLOBAL COLOR TABLE\nSIZE='%d'\n\n", this->gif_gct.size);
00127 #endif
00128 }
00129
00130 return true;
00131 }
00132
00133 bool MMSGIFLoader::loadBlocks() {
00134
00135 unsigned char buffer[1024];
00136 size_t count = 0;
00137 MMS_GIF_GCE gif_gce;
00138 MMS_GIF_GCE gif_gce_old;
00139 bool loop_forever = false;
00140
00141 memset(&gif_gce, 0, sizeof(gif_gce));
00142 memset(&gif_gce_old, 0, sizeof(gif_gce_old));
00143
00144
00145
00146
00147 while (1) {
00148
00149 if (!this->myfile->readBuffer((void*)buffer, &count, 1, 1)) {
00150
00151 return false;
00152 }
00153
00154
00155
00156
00157
00158
00159
00160 switch (buffer[0]) {
00161 case 0x21:
00162
00163
00164 if (!this->myfile->readBuffer((void*)buffer, &count, 1, 1)) {
00165
00166 return false;
00167 }
00168
00169
00170
00171 switch (buffer[0]) {
00172 case 0xff:
00173
00174
00175 if (!this->myfile->readBuffer((void*)buffer, &count, 1, 12)) {
00176
00177 return false;
00178 }
00179
00180
00181 while (1) {
00182 if (!this->myfile->readBuffer((void*)buffer, &count, 1, 1)) {
00183
00184 return false;
00185 }
00186 if (buffer[0]) {
00187 if (!this->myfile->readBuffer((void*)buffer, &count, 1, buffer[0])) {
00188
00189 return false;
00190 }
00191 continue;
00192 }
00193 break;
00194 }
00195
00196 #ifdef GIFTRACE
00197 DEBUGOUT("APPLICATION EXTENSION, skipped\n\n");
00198 #endif
00199
00200
00201 loop_forever = true;
00202
00203 break;
00204
00205 case 0xf9:
00206
00207 if (!this->myfile->readBuffer((void*)buffer, &count, 1, 6)) {
00208
00209 return false;
00210 }
00211 memcpy(&gif_gce_old, &gif_gce, sizeof(gif_gce));
00212 memset(&gif_gce, 0, sizeof(gif_gce));
00213 gif_gce.flags = buffer[1];
00214 gif_gce.delaytime = *((unsigned short*)&buffer[2]);
00215 gif_gce.transcolor = buffer[4];
00216 gif_gce.transparent_color = ((gif_gce.flags & 0x01) == 0x01);
00217 gif_gce.disposal = (gif_gce.flags >> 2) & 0x07;
00218
00219 #ifdef GIFTRACE
00220 DEBUGOUT("GRAPHIC CONTROL EXTENSION\nFLAGS='%x',DELAYTIME='%d',TRANSCOLOR='0x%02x'\n\n",
00221 gif_gce.flags, gif_gce.delaytime, (gif_gce.transparent_color)?gif_gce.transcolor:-1);
00222 #endif
00223
00224 break;
00225
00226 case 0x01:
00227
00228
00229 if (!this->myfile->readBuffer((void*)buffer, &count, 1, 13)) {
00230
00231 return false;
00232 }
00233
00234
00235 while (1) {
00236 if (!this->myfile->readBuffer((void*)buffer, &count, 1, 1)) {
00237
00238 return false;
00239 }
00240 if (buffer[0]) {
00241 if (!this->myfile->readBuffer((void*)buffer, &count, 1, buffer[0])) {
00242
00243 return false;
00244 }
00245 continue;
00246 }
00247 break;
00248 }
00249
00250
00251 #ifdef GIFTRACE
00252 DEBUGOUT("PLAIN TEXT EXTENSION, skipped\n\n");
00253 #endif
00254
00255 break;
00256
00257 case 0xfe:
00258
00259
00260
00261 while (1) {
00262 if (!this->myfile->readBuffer((void*)buffer, &count, 1, 1)) {
00263
00264 return false;
00265 }
00266 if (buffer[0]) {
00267 if (!this->myfile->readBuffer((void*)buffer, &count, 1, buffer[0])) {
00268
00269 return false;
00270 }
00271 continue;
00272 }
00273 break;
00274 }
00275
00276 #ifdef GIFTRACE
00277 DEBUGOUT("COMMENT EXTENSION, skipped\n\n");
00278 #endif
00279
00280 break;
00281 }
00282 break;
00283
00284 case 0x2c: {
00285
00286 if (!this->myfile->readBuffer((void*)buffer, &count, 1, 9)) {
00287
00288 return false;
00289 }
00290
00291
00292 MMSFBSurface *newsuf;
00293 if (!this->layer->createSurface(&newsuf, gif_lsd.width, gif_lsd.height)) {
00294
00295 return false;
00296 }
00297
00298
00299 MMSFBSurfacePixelFormat pixelformat;
00300 if (!newsuf->getPixelFormat(&pixelformat)) {
00301
00302 delete newsuf;
00303 return false;
00304 }
00305
00306
00307 int pixel_size;
00308 switch (pixelformat) {
00309 case MMSFB_PF_ARGB:
00310 pixel_size = 4;
00311 break;
00312 case MMSFB_PF_ARGB4444:
00313 pixel_size = 2;
00314 break;
00315 default:
00316
00317 printf("GIF Loader currently does not support the %s pixelformat!\n",
00318 getMMSFBPixelFormatString(pixelformat).c_str());
00319 delete newsuf;
00320 return false;
00321 }
00322
00323
00324 MMS_GIF_ID gif_id;
00325 MMS_GIF_CT gif_lct;
00326 MMS_GIF_CT *my_color_table;
00327 memset(&gif_id, 0, sizeof(gif_id));
00328 gif_id.x = *((unsigned short*)&buffer[0]);
00329 gif_id.y = *((unsigned short*)&buffer[2]);
00330 gif_id.w = *((unsigned short*)&buffer[4]);
00331 gif_id.h = *((unsigned short*)&buffer[6]);
00332 gif_id.flags = buffer[8];
00333 gif_id.local_color_table = ((gif_id.flags & 0x80) == 0x80);
00334 gif_id.interlaced = ((gif_id.flags & 0x40) == 0x40);
00335 unsigned int line_size = gif_id.w * pixel_size;
00336 unsigned int image_size = line_size * gif_id.h;
00337 char interlace_pass = 0;
00338
00339 #ifdef GIFTRACE
00340 DEBUGOUT("IMAGE DESCRIPTOR\nX='%d',Y='%d',W='%d',H='%d',FLAGS='%x',LCT=%s,INTERLACED=%s\n\n",
00341 gif_id.x, gif_id.y, gif_id.w, gif_id.h, gif_id.flags,
00342 (gif_id.local_color_table)?"yes":"no", (gif_id.interlaced)?"yes":"no");
00343 #endif
00344
00345 if (gif_id.local_color_table) {
00346
00347 memset(&gif_lct, 0, sizeof(gif_lct));
00348 int y = (gif_id.flags & 0x07) + 1;
00349 gif_lct.size = 2;
00350 while (y-->1) gif_lct.size*=2;
00351 if (!this->myfile->readBuffer((void*)gif_lct.table, &count, 1, 3 * gif_lct.size)) {
00352
00353 delete newsuf;
00354 return false;
00355 }
00356
00357 if (count < (size_t)(3 * gif_lct.size)) {
00358
00359 delete newsuf;
00360 return false;
00361 }
00362
00363 #ifdef GIFTRACE
00364 DEBUGOUT("LOCAL COLOR TABLE\nSIZE='%d'\n\n", gif_lct.size);
00365 #endif
00366
00367 my_color_table = &gif_lct;
00368 }
00369 else {
00370
00371 my_color_table = &(this->gif_gct);
00372 }
00373
00374
00375 if (!this->myfile->readBuffer((void*)buffer, &count, 1, 1)) {
00376
00377 delete newsuf;
00378 return false;
00379 }
00380 int initial_code_size = buffer[0];
00381 int code_size = buffer[0];
00382 int clr_code = 1 << code_size;
00383 int end_code = clr_code + 1;
00384 int max_code = clr_code << 1;
00385 int next_code = clr_code + 2;
00386 code_size++;
00387
00388 unsigned char data_table[128*1024];
00389 unsigned int index_table[4*1024+1];
00390 memset(data_table, 0, sizeof(data_table));
00391 memset(index_table, 0, sizeof(index_table));
00392 for (int t = 0; t < clr_code + 3; t++)
00393 data_table[t]=index_table[t]=t;
00394 bool end_of_stream = false;
00395
00396
00397 int ci;
00398 if (this->desc->sufcount <= 0) {
00399
00400 if (this->gif_lsd.global_color_table) {
00401 if ((gif_gce.transparent_color) && (this->gif_lsd.bgcolor == gif_gce.transcolor)) {
00402
00403 newsuf->clear();
00404 }
00405 else {
00406
00407 ci = this->gif_lsd.bgcolor*3;
00408 newsuf->clear(gif_gct.table[ci], gif_gct.table[ci+1], gif_gct.table[ci+2], 0xff);
00409 }
00410 }
00411 else {
00412
00413 newsuf->clear();
00414 }
00415 }
00416 else {
00417
00418 switch (gif_gce_old.disposal) {
00419 case 0:
00420 case 1:
00421 newsuf->blit(desc->suf[desc->sufcount-1].surface, NULL, 0, 0);
00422 break;
00423 case 2:
00424 ci = this->gif_lsd.bgcolor*3;
00425 if ((gif_gce_old.transparent_color) && (this->gif_lsd.bgcolor == gif_gce_old.transcolor)) {
00426
00427 newsuf->blit(desc->suf[0].surface, NULL, 0, 0);
00428 }
00429 else {
00430
00431 newsuf->setColor(gif_gct.table[ci], gif_gct.table[ci+1], gif_gct.table[ci+2], 0xff);
00432 newsuf->fillRectangle(gif_id.x, gif_id.y, gif_id.w, gif_id.h);
00433 }
00434 break;
00435 case 3:
00436 if (desc->sufcount >= 2) {
00437 newsuf->blit(desc->suf[desc->sufcount-2].surface, NULL, 0, 0);
00438 }
00439 break;
00440 }
00441 }
00442
00443
00444 unsigned char *sufbuf, *sufbuf_start, *sufbuf_end;
00445 int pitch;
00446 newsuf->lock(MMSFB_LOCK_WRITE, (void**)&sufbuf, &pitch);
00447 sufbuf+= gif_id.x * pixel_size + gif_id.y * pitch;
00448 sufbuf_start = sufbuf;
00449 sufbuf_end = sufbuf_start + gif_lsd.height * pitch;
00450
00451 unsigned int outlen = 0;
00452 int oddbits = 0;
00453 bool first = true;
00454
00455 while (1) {
00456
00457
00458 unsigned char len;
00459 if (!this->myfile->readBuffer((void*)&len, &count, 1, 1)) {
00460
00461 newsuf->unlock();
00462 delete newsuf;
00463 return false;
00464 }
00465
00466
00467 int bits = 2*8;
00468 int bitlen = bits + (((int)len) << 3);
00469 if (oddbits > 0)
00470 bits-=oddbits;
00471
00472 if (!len) {
00473
00474 break;
00475 }
00476
00477
00478
00479 if (!this->myfile->readBuffer((void*)&buffer[2], &count, 1, len)) {
00480
00481 newsuf->unlock();
00482 delete newsuf;
00483 return false;
00484 }
00485
00486 if (count < len) {
00487
00488 newsuf->unlock();
00489 delete newsuf;
00490 return false;
00491 }
00492
00493 #ifdef GIFTRACE
00494 DEBUGOUT("pixel indexes=\n");
00495 #endif
00496
00497
00498 do {
00499
00500 int code = 0;
00501 for (int i = 0; i < code_size; i++, bits++)
00502 code = code | ((buffer[bits >> 3] & (1 << (bits & 0x07))) != 0) << i;
00503 if (code == clr_code) {
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 code_size = initial_code_size;
00514 clr_code = 1 << code_size;
00515 end_code = clr_code + 1;
00516 max_code = clr_code << 1;
00517 next_code = clr_code + 2;
00518 code_size++;
00519 memset(data_table, 0, sizeof(data_table));
00520 memset(index_table, 0, sizeof(index_table));
00521 for (int t = 0; t < clr_code + 3; t++)
00522 data_table[t]=index_table[t]=t;
00523 first = true;
00524 continue;
00525 }
00526
00527 if (code == end_code) {
00528
00529 #ifdef GIFTRACE
00530 DEBUGOUT("\nend of stream\n");
00531 #endif
00532 end_of_stream = true;
00533 break;
00534 }
00535
00536
00537 unsigned char oc[8192];
00538 int oclen;
00539
00540 if (first) {
00541
00542 first = false;
00543
00544 *oc = data_table[index_table[code]];
00545 oclen = 1;
00546 }
00547 else {
00548
00549
00550 if (code < next_code) {
00551
00552 memcpy(&data_table[index_table[next_code]], oc, oclen);
00553 data_table[index_table[next_code]+oclen] = data_table[index_table[code]];
00554 index_table[next_code+1] = index_table[next_code]+oclen+1;
00555 next_code++;
00556
00557
00558 oclen = index_table[code+1] - index_table[code];
00559 memcpy(oc, &data_table[index_table[code]], oclen);
00560 }
00561 else {
00562
00563 memcpy(&data_table[index_table[next_code]], oc, oclen);
00564 data_table[index_table[next_code]+oclen] = *oc;
00565 index_table[next_code+1] = index_table[next_code]+oclen+1;
00566 next_code++;
00567
00568
00569 oclen = index_table[next_code] - index_table[next_code-1];
00570 memcpy(oc, &data_table[index_table[next_code-1]], oclen);
00571 }
00572
00573 }
00574
00575
00576 if (!gif_id.interlaced) {
00577
00578 for (int x = 0; x < oclen; x++) {
00579 if ((gif_gce.transparent_color) && (oc[x] == gif_gce.transcolor)) {
00580
00581 outlen+=pixel_size;
00582 sufbuf+=pixel_size;
00583
00584 #ifdef GIFTRACE
00585 DEBUGOUT (",--");
00586 #endif
00587 }
00588 else {
00589
00590 int ci = oc[x]*3;
00591
00592 switch (pixelformat) {
00593 case MMSFB_PF_ARGB:
00594 sufbuf[0] = my_color_table->table[ci+2];
00595 sufbuf[1] = my_color_table->table[ci+1];
00596 sufbuf[2] = my_color_table->table[ci];
00597 sufbuf[3] = 0xff;
00598 break;
00599 case MMSFB_PF_ARGB4444:
00600 sufbuf[0] = (my_color_table->table[ci+2] >> 4)
00601 | (my_color_table->table[ci+1] & 0xf0);
00602 sufbuf[1] = (my_color_table->table[ci] >> 4)
00603 | 0xf0;
00604 break;
00605 default:
00606 break;
00607 }
00608
00609 outlen+=pixel_size;
00610 sufbuf+=pixel_size;
00611
00612 #ifdef GIFTRACE
00613 DEBUGOUT (",%02x", oc[x]);
00614 #endif
00615 }
00616
00617 if (outlen % line_size == 0)
00618 sufbuf+=pitch - line_size;
00619 }
00620 }
00621 else {
00622
00623 for (int x = 0; x < oclen; x++) {
00624 if ((gif_gce.transparent_color) && (oc[x] == gif_gce.transcolor)) {
00625
00626 outlen+=pixel_size;
00627 sufbuf+=pixel_size;
00628
00629 #ifdef GIFTRACE
00630 DEBUGOUT (",--");
00631 #endif
00632 }
00633 else {
00634
00635 int ci = oc[x]*3;
00636
00637 switch (pixelformat) {
00638 case MMSFB_PF_ARGB:
00639 sufbuf[0] = my_color_table->table[ci+2];
00640 sufbuf[1] = my_color_table->table[ci+1];
00641 sufbuf[2] = my_color_table->table[ci];
00642 sufbuf[3] = 0xff;
00643 break;
00644 case MMSFB_PF_ARGB4444:
00645 sufbuf[0] = (my_color_table->table[ci+2] >> 4)
00646 | (my_color_table->table[ci+1] & 0xf0);
00647 sufbuf[1] = (my_color_table->table[ci] >> 4)
00648 | 0xf0;
00649 break;
00650 default:
00651 break;
00652 }
00653
00654 outlen+=pixel_size;
00655 sufbuf+=pixel_size;
00656
00657 #ifdef GIFTRACE
00658 DEBUGOUT (",%02x", oc[x]);
00659 #endif
00660 }
00661
00662
00663 if (outlen % line_size == 0) {
00664 sufbuf+=pitch - line_size;
00665
00666 switch (interlace_pass) {
00667 case 0:
00668 sufbuf+=pitch * 7;
00669 if (sufbuf >= sufbuf_end) {
00670 sufbuf=sufbuf_start + (pitch << 2);
00671 interlace_pass++;
00672 }
00673 break;
00674 case 1:
00675 sufbuf+=pitch * 7;
00676 if (sufbuf >= sufbuf_end) {
00677 sufbuf=sufbuf_start + (pitch << 1);
00678 interlace_pass++;
00679 }
00680 break;
00681 case 2:
00682 sufbuf+=pitch * 3;
00683 if (sufbuf >= sufbuf_end) {
00684 sufbuf=sufbuf_start + pitch;
00685 interlace_pass++;
00686 }
00687 break;
00688 case 3:
00689 sufbuf+=pitch;
00690 break;
00691 }
00692 }
00693
00694 }
00695 }
00696
00697
00698 if (next_code >= max_code) {
00699 if (code_size < 12) {
00700
00701 max_code = max_code << 1;
00702 code_size++;
00703 }
00704 }
00705
00706 } while (bits <= bitlen - code_size);
00707
00708 if (end_of_stream)
00709 break;
00710
00711 oddbits = bitlen - bits;
00712 if (oddbits > 0) {
00713
00714
00715 if (oddbits > 8) {
00716 buffer[0] = buffer[bits >> 3];
00717 buffer[1] = buffer[(bits >> 3) + 1];
00718 }
00719 else
00720 buffer[1] = buffer[bits >> 3];
00721 }
00722
00723 #ifdef GIFTRACE
00724 DEBUGOUT("\n\n");
00725 #endif
00726 }
00727
00728
00729 if ((!end_of_stream) || (outlen != image_size)) {
00730
00731 #ifdef GIFTRACE
00732 DEBUGOUT("bad format, outlen=%d, needed len=%d\n", outlen, image_size);
00733 #endif
00734 newsuf->unlock();
00735 delete newsuf;
00736 return false;
00737 }
00738
00739 newsuf->unlock();
00740
00741
00742 if (desc->sufcount < MMSIM_MAX_DESC_SUF) {
00743
00744 desc->suf[desc->sufcount+1].delaytime = MMSIM_DESC_SUF_LOADING;
00745
00746
00747 desc->suf[desc->sufcount].surface = newsuf;
00748
00749
00750 if (gif_gce.delaytime > 10)
00751 desc->suf[desc->sufcount].delaytime = 10 * (unsigned int)gif_gce.delaytime;
00752 else
00753 desc->suf[desc->sufcount].delaytime = 100;
00754
00755 desc->sufcount++;
00756 if(desc->sufcount == 1) {
00757 pthread_cond_signal(&this->cond);
00758 pthread_mutex_unlock(&this->mutex);
00759 }
00760 }
00761 else {
00762
00763 #ifdef GIFTRACE
00764 DEBUGOUT("no free index\n");
00765 #endif
00766 delete newsuf;
00767 }
00768 }
00769 break;
00770
00771 case 0x3b:
00772
00773
00774 #ifdef GIFTRACE
00775 DEBUGOUT("TRAILER, end of the GIF stream\n\n");
00776 #endif
00777
00778 if ((!loop_forever)&&(desc->sufcount>0))
00779
00780 desc->suf[desc->sufcount-1].delaytime = 0;
00781
00782 return true;
00783
00784 break;
00785 }
00786
00787 }
00788
00789 return true;
00790
00791 }
00792
00793 void MMSGIFLoader::threadMain() {
00794 pthread_mutex_lock(&this->mutex);
00795
00796
00797 if (loadHeader()) {
00798
00799 if(!loadBlocks()) {
00800 pthread_cond_signal(&this->cond);
00801 pthread_mutex_unlock(&this->mutex);
00802 }
00803 }
00804
00805 if (this->myfile)
00806 delete this->myfile;
00807
00808
00809 this->desc->suf[this->desc->sufcount].delaytime = MMSIM_DESC_SUF_END;
00810
00811
00812 this->desc->loading = false;
00813
00814 pthread_cond_destroy(&this->cond);
00815 pthread_mutex_destroy(&this->mutex);
00816 pthread_exit(NULL);
00817 }
00818
00819
00820
00821
00822
00823 void MMSGIFLoader::block() {
00824 struct timeval tsGet;
00825 struct timespec ts;
00826 gettimeofday(&tsGet, NULL);
00827
00828 ts.tv_sec = tsGet.tv_sec + 5;
00829 ts.tv_nsec = tsGet.tv_usec * 1000;
00830 pthread_mutex_lock(&this->mutex);
00831 while(this->desc->loading && this->desc->sufcount <= 0)
00832 pthread_cond_timedwait(&this->cond, &this->mutex, &ts);
00833 pthread_mutex_unlock(&this->mutex);
00834 }
00835
00836 bool isGIF(string file) {
00837 MMSFile *myfile;
00838 unsigned char *gif_header;
00839 size_t count = 0;
00840
00841 myfile = new MMSFile(file);
00842 if (!myfile) return false;
00843
00844 if (!myfile->readBufferEx((void**)&gif_header, &count, 1, 3)) {
00845
00846 delete myfile;
00847 return false;
00848 }
00849 delete myfile;
00850
00851
00852 if (count < 3) {
00853
00854 free(gif_header);
00855 return false;
00856 }
00857 if (memcmp(gif_header, "GIF", 3)!=0) {
00858
00859 free(gif_header);
00860 return false;
00861 }
00862
00863 free(gif_header);
00864 return true;
00865 }
00866