__unused JNIEXPORT jlong JNICALL Java_pl_droidsonroids_gif_GifInfoHandle_renderFrame(JNIEnv *env, jclass __unused handleClass, jlong gifInfo, jobject jbitmap) { GifInfo *info = (GifInfo *) (intptr_t) gifInfo; if (info == NULL) return -1; time_t renderStartTime = getRealTime(); void *pixels; if (lockPixels(env, jbitmap, info, &pixels) != 0) { return 0; } DDGifSlurp(info, true); const uint_fast16_t frameDuration = getBitmap((argb *) pixels, info); unlockPixels(env, jbitmap); return calculateInvalidationDelay(info, renderStartTime, frameDuration); }
static void *slurp(void *pVoidInfo) { GifInfo *info = pVoidInfo; while (1) { pthread_mutex_lock(&info->surfaceDescriptor->slurpMutex); while (info->surfaceDescriptor->slurpHelper == 0) pthread_cond_wait(&info->surfaceDescriptor->slurpCond, &info->surfaceDescriptor->slurpMutex); if (info->surfaceDescriptor->slurpHelper == 2) { pthread_mutex_unlock(&info->surfaceDescriptor->slurpMutex); break; } info->surfaceDescriptor->slurpHelper = 0; pthread_mutex_unlock(&info->surfaceDescriptor->slurpMutex); DDGifSlurp(info, true); pthread_mutex_lock(&info->surfaceDescriptor->renderMutex); info->surfaceDescriptor->renderHelper = 1; pthread_cond_signal(&info->surfaceDescriptor->renderCond); pthread_mutex_unlock(&info->surfaceDescriptor->renderMutex); } DetachCurrentThread(); return NULL; }
static void *slurp(void *pVoidInfo) { GifInfo *info = pVoidInfo; SurfaceDescriptor *descriptor = info->frameBufferDescriptor; while (1) { pthread_mutex_lock(&descriptor->slurpMutex); while (descriptor->slurpHelper == 0) { pthread_cond_wait(&descriptor->slurpCond, &descriptor->slurpMutex); } if (descriptor->slurpHelper == 2) { pthread_mutex_unlock(&descriptor->slurpMutex); DetachCurrentThread(); return NULL; } descriptor->slurpHelper = 0; pthread_mutex_unlock(&descriptor->slurpMutex); DDGifSlurp(info, true, false); pthread_mutex_lock(&descriptor->renderMutex); descriptor->renderHelper = 1; pthread_cond_signal(&descriptor->renderCond); pthread_mutex_unlock(&descriptor->renderMutex); } }
GifInfo *createGifInfo(GifSourceDescriptor *descriptor, JNIEnv *env) { if (descriptor->startPos < 0) { descriptor->Error = D_GIF_ERR_NOT_READABLE; } if (descriptor->Error != 0 || descriptor->GifFileIn == NULL) { bool readErrno = descriptor->rewindFunc == fileRewind && (descriptor->Error == D_GIF_ERR_NOT_READABLE || descriptor->Error == D_GIF_ERR_READ_FAILED); throwGifIOException(descriptor->Error, env, readErrno); DGifCloseFile(descriptor->GifFileIn); return NULL; } GifInfo *info = malloc(sizeof(GifInfo)); if (info == NULL) { DGifCloseFile(descriptor->GifFileIn); throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE); return NULL; } info->controlBlock = malloc(sizeof(GraphicsControlBlock)); if (info->controlBlock == NULL) { DGifCloseFile(descriptor->GifFileIn); throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE); return NULL; } setGCBDefaults(info->controlBlock); info->destructor = NULL; info->gifFilePtr = descriptor->GifFileIn; info->startPos = descriptor->startPos; info->currentIndex = 0; info->nextStartTime = 0; info->lastFrameRemainder = -1; info->comment = NULL; info->loopCount = 1; info->currentLoop = 0; info->speedFactor = 1.0; info->sourceLength = descriptor->sourceLength; info->backupPtr = NULL; info->rewindFunction = descriptor->rewindFunc; info->frameBufferDescriptor = NULL; info->isOpaque = false; info->sampleSize = 1; DDGifSlurp(info, false, false); info->rasterBits = NULL; info->rasterSize = 0; info->originalHeight = info->gifFilePtr->SHeight; info->originalWidth = info->gifFilePtr->SWidth; if (descriptor->GifFileIn->SWidth < 1 || descriptor->GifFileIn->SHeight < 1) { DGifCloseFile(descriptor->GifFileIn); throwGifIOException(D_GIF_ERR_INVALID_SCR_DIMS, env, false); return NULL; } if (descriptor->GifFileIn->Error == D_GIF_ERR_NOT_ENOUGH_MEM) { cleanUp(info); throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE); return NULL; } #if defined(STRICT_FORMAT_89A) descriptor->Error = descriptor->GifFileIn->Error; #endif if (descriptor->GifFileIn->ImageCount == 0) { descriptor->Error = D_GIF_ERR_NO_FRAMES; } else if (descriptor->GifFileIn->Error == D_GIF_ERR_REWIND_FAILED) { descriptor->Error = D_GIF_ERR_REWIND_FAILED; } if (descriptor->Error != 0) { cleanUp(info); throwGifIOException(descriptor->Error, env, false); return NULL; } return info; }
jobject createGifHandle(GifSourceDescriptor *descriptor, JNIEnv *env, jboolean justDecodeMetaData) { if (descriptor->startPos < 0) { descriptor->Error = D_GIF_ERR_NOT_READABLE; DGifCloseFile(descriptor->GifFileIn); } if (descriptor->Error != 0 || descriptor->GifFileIn == NULL) { throwGifIOException(descriptor->Error, env); return NULL; } GifInfo *info = malloc(sizeof(GifInfo)); if (info == NULL) { DGifCloseFile(descriptor->GifFileIn); throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE); return NULL; } info->controlBlock = calloc(sizeof(GraphicsControlBlock), 1); info->controlBlock->DelayTime = DEFAULT_FRAME_DURATION_MS; if (info->controlBlock == NULL) { DGifCloseFile(descriptor->GifFileIn); throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE); return NULL; } info->gifFilePtr = descriptor->GifFileIn; info->startPos = descriptor->startPos; info->currentIndex = 0; info->nextStartTime = 0; info->lastFrameRemainder = -1; info->comment = NULL; info->loopCount = 1; info->currentLoop = 0; info->speedFactor = 1.0; info->sourceLength = descriptor->sourceLength; info->backupPtr = NULL; info->rewindFunction = descriptor->rewindFunc; info->surfaceDescriptor = NULL; info->isOpaque = JNI_FALSE; DDGifSlurp(info, false); if (justDecodeMetaData == JNI_TRUE) info->rasterBits = NULL; else { info->rasterBits = malloc( descriptor->GifFileIn->SHeight * descriptor->GifFileIn->SWidth * sizeof(GifPixelType)); if (info->rasterBits == NULL) { descriptor->GifFileIn->Error = D_GIF_ERR_NOT_ENOUGH_MEM; } } if (descriptor->GifFileIn->SWidth < 1 || descriptor->GifFileIn->SHeight < 1) { DGifCloseFile(descriptor->GifFileIn); throwGifIOException(D_GIF_ERR_INVALID_SCR_DIMS, env); return NULL; } if (descriptor->GifFileIn->Error == D_GIF_ERR_NOT_ENOUGH_MEM) { cleanUp(info); throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE); return NULL; } #if defined(STRICT_FORMAT_89A) descriptor->Error = descriptor->GifFileIn->Error; #endif if (descriptor->GifFileIn->ImageCount == 0) { descriptor->Error = D_GIF_ERR_NO_FRAMES; } else if (descriptor->GifFileIn->Error == D_GIF_ERR_REWIND_FAILED) { descriptor->Error = D_GIF_ERR_REWIND_FAILED; } if (descriptor->Error != 0) { cleanUp(info); throwGifIOException(descriptor->Error, env); return NULL; } jclass gifInfoHandleClass = (*env)->FindClass(env, "pl/droidsonroids/gif/GifInfoHandle"); if (gifInfoHandleClass == NULL) { cleanUp(info); return NULL; } jmethodID gifInfoHandleCtorMID = (*env)->GetMethodID(env, gifInfoHandleClass, "<init>", "(JIII)V"); if (gifInfoHandleCtorMID == NULL) { cleanUp(info); return NULL; } return (*env)->NewObject(env, gifInfoHandleClass, gifInfoHandleCtorMID, (jlong) (intptr_t) info, info->gifFilePtr->SWidth, info->gifFilePtr->SHeight, info->gifFilePtr->ImageCount); }