Skip to content

Commit

Permalink
#262 done, GCB reading fixed, minor native code cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
koral-- committed Apr 25, 2016
1 parent e84970b commit 42036e2
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 56 deletions.
2 changes: 1 addition & 1 deletion src/main/jni/bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Java_pl_droidsonroids_gif_GifInfoHandle_renderFrame(JNIEnv *env, jclass __unused
if (lockPixels(env, jbitmap, info, &pixels) != 0) {
return 0;
}
DDGifSlurp(info, true);
DDGifSlurp(info, true, false);
if (info->currentIndex == 0)
prepareCanvas(pixels, info);
const uint_fast32_t frameDuration = getBitmap((argb *) pixels, info);
Expand Down
47 changes: 35 additions & 12 deletions src/main/jni/control.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,46 @@ static uint_fast32_t seekBitmap(GifInfo *info, JNIEnv *env, jint desiredIndex, j
if (lockPixels(env, jbitmap, info, &pixels) != 0) {
return 0;
}
uint_fast32_t duration = seek(info, desiredIndex, pixels);
uint_fast32_t duration = seek(info, (uint_fast32_t) desiredIndex, pixels);
unlockPixels(env, jbitmap);
return duration;
}

uint_fast32_t seek(GifInfo *info, jint desiredIndex, const void *pixels) {
if (desiredIndex < info->currentIndex && !reset(info)) {
info->gifFilePtr->Error = D_GIF_ERR_REWIND_FAILED;
return 0;
}
if (desiredIndex >= info->gifFilePtr->ImageCount) {
desiredIndex = (jint) (info->gifFilePtr->ImageCount - 1);
}
if (info->currentIndex == 0)
uint_fast32_t seek(GifInfo *info, uint_fast32_t desiredIndex, const void *pixels) {
GifFileType *const gifFilePtr = info->gifFilePtr;
if (desiredIndex < info->currentIndex || info->currentIndex == 0) {
if (!reset(info)) {
gifFilePtr->Error = D_GIF_ERR_REWIND_FAILED;
return 0;
}
prepareCanvas(pixels, info);
}
if (desiredIndex >= gifFilePtr->ImageCount) {
desiredIndex = gifFilePtr->ImageCount - 1;
}

uint_fast32_t i;
for (i = desiredIndex; i > info->currentIndex; i--) {
const GifImageDesc imageDesc = info->gifFilePtr->SavedImages[i].ImageDesc;
if (gifFilePtr->SWidth == imageDesc.Width && gifFilePtr->SHeight == imageDesc.Height) {
const GraphicsControlBlock controlBlock = info->controlBlock[i];
if (controlBlock.TransparentColor == NO_TRANSPARENT_COLOR) {
break;
} else if (controlBlock.DisposalMode == DISPOSE_BACKGROUND) {
break;
}
}
}

if (i > 0) {
while (info->currentIndex < i - 1) {
DDGifSlurp(info, false, true);
++info->currentIndex;
}
}

do {
DDGifSlurp(info, true);
DDGifSlurp(info, true, false);
drawNextBitmap((argb *) pixels, info);
} while (info->currentIndex++ < desiredIndex);
--info->currentIndex;
Expand Down Expand Up @@ -122,7 +145,7 @@ Java_pl_droidsonroids_gif_GifInfoHandle_restoreRemainder(JNIEnv *__unused env,
(info->loopCount > 0 && info->currentLoop == info->loopCount))
return -1;
info->nextStartTime = getRealTime() + info->lastFrameRemainder;
const long remainder = info->lastFrameRemainder;
const long long remainder = info->lastFrameRemainder;
info->lastFrameRemainder = -1;
return remainder;
}
45 changes: 24 additions & 21 deletions src/main/jni/decoding.c
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
#include "gif.h"

void DDGifSlurp(GifInfo *info, bool shouldDecode) {
void DDGifSlurp(GifInfo *info, bool decode, bool exitAfterFrame) {
GifRecordType RecordType;
GifByteType *ExtData;
int ExtFunction;
GifFileType *gifFilePtr;
gifFilePtr = info->gifFilePtr;
uint_fast32_t lastAllocatedGCB = 0;
do {
if (DGifGetRecordType(gifFilePtr, &RecordType) == GIF_ERROR)
return;
bool isInitialPass = !decode && !exitAfterFrame;
switch (RecordType) {
case IMAGE_DESC_RECORD_TYPE:

if (DGifGetImageDesc(gifFilePtr, !shouldDecode) == GIF_ERROR)
if (DGifGetImageDesc(gifFilePtr, isInitialPass) == GIF_ERROR)
return;

if (!shouldDecode) {
if (isInitialPass) {
SavedImage *sp = &gifFilePtr->SavedImages[gifFilePtr->ImageCount - 1];

int_fast32_t topOverflow = gifFilePtr->Image.Top + gifFilePtr->Image.Height - gifFilePtr->SHeight;
Expand All @@ -35,7 +37,7 @@ void DDGifSlurp(GifInfo *info, bool shouldDecode) {
}
}

if (shouldDecode) {
if (decode) {
int_fast32_t widthOverflow = gifFilePtr->Image.Width - info->originalWidth;
int_fast32_t heightOverflow = gifFilePtr->Image.Height - info->originalHeight;
if (widthOverflow > 0 || heightOverflow > 0) {
Expand All @@ -60,8 +62,7 @@ void DDGifSlurp(GifInfo *info, bool shouldDecode) {
if (DGifGetLine(gifFilePtr, info->rasterBits + j * gifFilePtr->Image.Width, gifFilePtr->Image.Width) == GIF_ERROR)
return;
}
}
else {
} else {
if (DGifGetLine(gifFilePtr, info->rasterBits, gifFilePtr->Image.Width * gifFilePtr->Image.Height) == GIF_ERROR) {
return;
}
Expand All @@ -79,43 +80,45 @@ void DDGifSlurp(GifInfo *info, bool shouldDecode) {
*dst = *src;
dst++;
src += info->sampleSize;
}
while (src < srcEndLine);
} while (src < srcEndLine);
dst = dstEndLine;
src = srcNextLineStart;
}
while (src < srcEndImage);
} while (src < srcEndImage);
}
return;
}
else {
} else {
do {
if (DGifGetCodeNext(gifFilePtr, &ExtData) == GIF_ERROR) {
return;
}
} while (ExtData != NULL);
if (exitAfterFrame) {
return;
}
while (ExtData != NULL);
}
break;

case EXTENSION_RECORD_TYPE:
if (DGifGetExtension(gifFilePtr, &ExtFunction, &ExtData) == GIF_ERROR)
return;
if (!shouldDecode) {
GraphicsControlBlock *tmpInfos = reallocarray(info->controlBlock, info->gifFilePtr->ImageCount + 1, sizeof(GraphicsControlBlock));
if (tmpInfos == NULL) {
gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
return;
if (isInitialPass) {
if (lastAllocatedGCB < info->gifFilePtr->ImageCount) {
GraphicsControlBlock *tmpInfos = reallocarray(info->controlBlock, info->gifFilePtr->ImageCount + 1, sizeof(GraphicsControlBlock));
if (tmpInfos == NULL) {
gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
return;
}
lastAllocatedGCB = info->gifFilePtr->ImageCount;
info->controlBlock = tmpInfos;
info->controlBlock[gifFilePtr->ImageCount].DelayTime = DEFAULT_FRAME_DURATION_MS;
}
info->controlBlock = tmpInfos;
info->controlBlock[gifFilePtr->ImageCount].DelayTime = DEFAULT_FRAME_DURATION_MS;
if (readExtensions(ExtFunction, ExtData, info) == GIF_ERROR)
return;
}
while (ExtData != NULL) {
if (DGifGetExtensionNext(info->gifFilePtr, &ExtData) == GIF_ERROR)
return;
if (!shouldDecode) {
if (isInitialPass) {
if (readExtensions(ExtFunction, ExtData, info) == GIF_ERROR)
return;
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/jni/drawing.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ static inline void disposeFrameIfNeeded(argb *bm, GifInfo *info) {
// and completely covers current area
uint_fast8_t curDisposal = info->controlBlock[info->currentIndex - 1].DisposalMode;
bool nextTrans = info->controlBlock[info->currentIndex].TransparentColor != NO_TRANSPARENT_COLOR;
unsigned char nextDisposal = info->controlBlock[info->currentIndex].DisposalMode;
uint_fast8_t nextDisposal = info->controlBlock[info->currentIndex].DisposalMode;

if ((curDisposal == DISPOSE_PREVIOUS || nextDisposal == DISPOSE_PREVIOUS) && info->backupPtr == NULL) {
info->backupPtr = calloc(info->stride * fGif->SHeight, sizeof(argb));
Expand Down Expand Up @@ -121,7 +121,7 @@ static inline void disposeFrameIfNeeded(argb *bm, GifInfo *info) {
memcpy(backup, bm, info->stride * fGif->SHeight * sizeof(argb));
}

void prepareCanvas(argb *bm, GifInfo *info) {
void prepareCanvas(const argb *bm, GifInfo *info) {
if (info->gifFilePtr->SColorMap && info->controlBlock->TransparentColor == NO_TRANSPARENT_COLOR) {
argb bgColArgb;
bgColArgb.rgb = info->gifFilePtr->SColorMap->Colors[info->gifFilePtr->SBackGroundColor];
Expand Down
16 changes: 8 additions & 8 deletions src/main/jni/gif.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ struct GifInfo {
GifFileType *gifFilePtr;
GifWord originalWidth, originalHeight;
uint_fast16_t sampleSize;
long lastFrameRemainder;
long nextStartTime;
long long lastFrameRemainder;
long long nextStartTime;
uint_fast32_t currentIndex;
GraphicsControlBlock *controlBlock;
argb *backupPtr;
long startPos;
long long startPos;
unsigned char *rasterBits;
char *comment;
uint_fast16_t loopCount;
Expand Down Expand Up @@ -132,7 +132,7 @@ typedef struct {
typedef struct {
GifFileType *GifFileIn;
int Error;
long startPos;
long long startPos;
RewindFunc rewindFunc;
jlong sourceLength;
} GifSourceDescriptor;
Expand Down Expand Up @@ -175,7 +175,7 @@ static int getComment(GifByteType *Bytes, GifInfo *);

static int readExtensions(int ExtFunction, GifByteType *ExtData, GifInfo *info);

__attribute__ ((visibility ("default"))) void DDGifSlurp(GifInfo *info, bool shouldDecode);
__attribute__ ((visibility ("default"))) void DDGifSlurp(GifInfo *info, bool decode, bool exitAfterFrame);

void throwGifIOException(int errorCode, JNIEnv *env);

Expand All @@ -197,18 +197,18 @@ int lockPixels(JNIEnv *env, jobject jbitmap, GifInfo *info, void **pixels);

void unlockPixels(JNIEnv *env, jobject jbitmap);

__attribute__ ((visibility ("default"))) long calculateInvalidationDelay(GifInfo *info, long renderStartTime, uint_fast32_t frameDuration);
__attribute__ ((visibility ("default"))) long long calculateInvalidationDelay(GifInfo *info, long renderStartTime, uint_fast32_t frameDuration);

__attribute__ ((visibility ("default"))) jint restoreSavedState(GifInfo *info, JNIEnv *env, jlongArray state, void *pixels);

__attribute__ ((visibility ("default"))) void prepareCanvas(argb *bm, GifInfo *info);
__attribute__ ((visibility ("default"))) void prepareCanvas(const argb *bm, GifInfo *info);

__attribute__ ((visibility ("default"))) void drawNextBitmap(argb *bm, GifInfo *info);

uint_fast32_t getFrameDuration(GifInfo *info);

__attribute__ ((visibility ("default"))) JNIEnv *getEnv();

__attribute__ ((visibility ("default"))) uint_fast32_t seek(GifInfo *info, jint desiredIndex, const void *pixels);
__attribute__ ((visibility ("default"))) uint_fast32_t seek(GifInfo *info, uint_fast32_t desiredIndex, const void *pixels);

#endif
4 changes: 2 additions & 2 deletions src/main/jni/metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Java_pl_droidsonroids_gif_GifInfoHandle_getCurrentPosition(JNIEnv *__unused env,
sum += info->controlBlock[i].DelayTime;
}

long remainder;
long long remainder;
if (info->lastFrameRemainder == -1) {
remainder = info->nextStartTime - getRealTime();
if (remainder < 0) { //in case of if frame hasn't been rendered until nextStartTime passed
Expand Down Expand Up @@ -167,7 +167,7 @@ jint restoreSavedState(GifInfo *info, JNIEnv *env, jlongArray state, void *pixel
if (info->currentIndex == 0)
prepareCanvas(pixels, info);
while (info->currentIndex < savedIndex) {
DDGifSlurp(info, true);
DDGifSlurp(info, true, false);
lastFrameDuration = getBitmap((argb *) pixels, info);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/jni/open_close.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ GifInfo *createGifHandle(GifSourceDescriptor *descriptor, JNIEnv *env, jboolean
info->isOpaque = JNI_FALSE;
info->sampleSize = 1;

DDGifSlurp(info, false);
DDGifSlurp(info, false, false);
if (justDecodeMetaData == JNI_TRUE) {
info->rasterBits = NULL;
} else {
Expand Down
9 changes: 4 additions & 5 deletions src/main/jni/opengl.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ static void *slurp(void *pVoidInfo) {
GifInfo *info = pVoidInfo;
while (1) {
long renderStartTime = getRealTime();
DDGifSlurp(info, true);
DDGifSlurp(info, true, false);
TexImageDescriptor *texImageDescriptor = info->frameBufferDescriptor;
if (info->currentIndex == 0)
prepareCanvas(texImageDescriptor->frameBuffer, info);
const uint_fast32_t frameDuration = getBitmap((argb *) texImageDescriptor->frameBuffer, info);

const long invalidationDelayMillis = calculateInvalidationDelay(info, renderStartTime, frameDuration);
const long long invalidationDelayMillis = calculateInvalidationDelay(info, renderStartTime, frameDuration);
int pollResult = poll(&texImageDescriptor->eventPollFd, 1, (int) invalidationDelayMillis);
eventfd_t eventValue;
if (pollResult < 0) {
Expand Down Expand Up @@ -120,8 +120,7 @@ Java_pl_droidsonroids_gif_GifInfoHandle_stopDecoderThread(JNIEnv *env, jclass __
}

__unused JNIEXPORT void JNICALL
Java_pl_droidsonroids_gif_GifInfoHandle_renderGLFrame(JNIEnv *env, jclass __unused handleClass, jlong gifInfo,
jint desiredIndex) {
Java_pl_droidsonroids_gif_GifInfoHandle_renderGLFrame(JNIEnv *env, jclass __unused handleClass, jlong gifInfo, jint desiredIndex) {
GifInfo *info = (GifInfo *) gifInfo;
if (info == NULL) {
return;
Expand All @@ -144,7 +143,7 @@ Java_pl_droidsonroids_gif_GifInfoHandle_renderGLFrame(JNIEnv *env, jclass __unus
texImageDescriptor->eventPollFd.fd = -1;
}

seek(info, desiredIndex, texImageDescriptor->frameBuffer);
seek(info, (uint_fast32_t) desiredIndex, texImageDescriptor->frameBuffer);

const GLsizei width = (const GLsizei) info->gifFilePtr->SWidth;
const GLsizei height = (const GLsizei) info->gifFilePtr->SHeight;
Expand Down
4 changes: 2 additions & 2 deletions src/main/jni/surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static void *slurp(void *pVoidInfo) {
}
surfaceDescriptor->slurpHelper = 0;
pthread_mutex_unlock(&surfaceDescriptor->slurpMutex);
DDGifSlurp(info, true);
DDGifSlurp(info, true, false);
pthread_mutex_lock(&surfaceDescriptor->renderMutex);
surfaceDescriptor->renderHelper = 1;
pthread_cond_signal(&surfaceDescriptor->renderCond);
Expand Down Expand Up @@ -128,7 +128,7 @@ Java_pl_droidsonroids_gif_GifInfoHandle_bindSurface(JNIEnv *env, jclass __unused
const size_t bufferSize = buffer.stride * buffer.height * sizeof(argb);

info->stride = buffer.stride;
long invalidationDelayMillis;
long long invalidationDelayMillis;
if (surfaceDescriptor->surfaceBackupPtr) {
memcpy(buffer.bits, surfaceDescriptor->surfaceBackupPtr, bufferSize);
invalidationDelayMillis = 0;
Expand Down
4 changes: 2 additions & 2 deletions src/main/jni/time.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#include "gif.h"

long calculateInvalidationDelay(GifInfo *info, long renderStartTime, uint_fast32_t frameDuration) {
long long calculateInvalidationDelay(GifInfo *info, long renderStartTime, uint_fast32_t frameDuration) {
if (frameDuration) {
long invalidationDelay = frameDuration;
long long invalidationDelay = frameDuration;
if (info->speedFactor != 1.0) {
invalidationDelay /= info->speedFactor;
}
Expand Down

0 comments on commit 42036e2

Please sign in to comment.