/* TurboJPEG 1.2.x: TJDecompressor::decompressToYUV() */ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV___3BI_3BI (JNIEnv *env, jobject obj, jbyteArray src, jint jpegSize, jbyteArray dst, jint flags) { tjhandle handle=0; unsigned char *jpegBuf=NULL, *dstBuf=NULL; int jpegSubsamp=-1, jpegWidth=0, jpegHeight=0; gethandle(); if((*env)->GetArrayLength(env, src)<jpegSize) _throwarg("Source buffer is not large enough"); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I")); jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I")); jpegWidth=(int)(*env)->GetIntField(env, obj, _fid); bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I")); jpegHeight=(int)(*env)->GetIntField(env, obj, _fid); if((*env)->GetArrayLength(env, dst) <(jsize)tjBufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp)) _throwarg("Destination buffer is not large enough"); bailif0(jpegBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); if(tjDecompressToYUV(handle, jpegBuf, (unsigned long)jpegSize, dstBuf, flags)==-1) _throwtj(); bailout: if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); if(jpegBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, jpegBuf, 0); return; }
JNIEXPORT void JNICALL TJCompressor_encodeYUV_12 (JNIEnv *env, jobject obj, jarray src, jint srcElementSize, jint width, jint pitch, jint height, jint pf, jbyteArray dst, jint subsamp, jint flags) { tjhandle handle=0; jsize arraySize=0; unsigned char *srcBuf=NULL, *dstBuf=NULL; gethandle(); if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1 || pitch<0) _throwarg("Invalid argument in encodeYUV()"); if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) _throwarg("Mismatch between Java and C API"); arraySize=(pitch==0)? width*tjPixelSize[pf]*height:pitch*height; if((*env)->GetArrayLength(env, src)*srcElementSize<arraySize) _throwarg("Source buffer is not large enough"); if((*env)->GetArrayLength(env, dst) <(jsize)tjBufSizeYUV(width, height, subsamp)) _throwarg("Destination buffer is not large enough"); bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); if(tjEncodeYUV2(handle, srcBuf, width, pitch, height, pf, dstBuf, subsamp, flags)==-1) _throwtj(); bailout: if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); return; }
JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV (JNIEnv *env, jclass cls, jint width, jint height, jint subsamp) { jint retval=(jint)tjBufSizeYUV(width, height, subsamp); if(retval==-1) _throw(tjGetErrorStr()); bailout: return retval; }
JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII (JNIEnv *env, jobject obj, jintArray src, jint width, jint pitch, jint height, jint pf, jbyteArray dst, jint subsamp, jint flags) { tjhandle handle=0; jsize arraySize=0; unsigned char *srcBuf=NULL, *dstBuf=NULL; gethandle(); if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1 || pitch<0) _throw("Invalid argument in compress()"); if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF) _throw("Mismatch between Java and C API"); if(tjPixelSize[pf]!=sizeof(jint)) _throw("Pixel format must be 32-bit when encoding from an integer buffer."); arraySize=(pitch==0)? width*height:pitch*height; if((*env)->GetArrayLength(env, src)<arraySize) _throw("Source buffer is not large enough"); if((*env)->GetArrayLength(env, dst) <(jsize)tjBufSizeYUV(width, height, subsamp)) _throw("Destination buffer is not large enough"); bailif0(srcBuf=(*env)->GetPrimitiveArrayCritical(env, src, 0)); bailif0(dstBuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0)); if(tjEncodeYUV2(handle, srcBuf, width, pitch*sizeof(jint), height, pf, dstBuf, subsamp, flags)==-1) { (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); dstBuf=srcBuf=NULL; _throw(tjGetErrorStr()); } bailout: if(dstBuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstBuf, 0); if(srcBuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcBuf, 0); return; }
/* mind thread */ void *mind_thread(void *arg) { unsigned char *frame = (unsigned char *) calloc(1, (size_t) cd.videoIn->framesizeIn); unsigned char *pixmap = (unsigned char *) calloc(1, (size_t) cd.videoIn->framesizeIn); int frame_size = 0; int jpegss; tjhandle jtd; struct v_frame vframe; printf("Start thread\n"); vframe.pixmap = (unsigned int *) pixmap; jtd = tjInitDecompress(); while (!stop) { /* wait for fresh frames */ pthread_cond_wait(&db_update, &db); /* read buffer */ frame_size = g_size; memcpy(frame, g_buf, frame_size); pthread_mutex_unlock(&db); tjDecompressHeader2(jtd, frame, frame_size, &(vframe.w), &(vframe.h), &jpegss); tjBufSizeYUV(vframe.w, vframe.h, jpegss); tjDecompressToYUV(jtd, frame, frame_size, pixmap, 0); if (jpegss != TJSAMP_422) { printf("Failed: Chrominance subsampling options is %d. \n", jpegss); continue; } vision_frame(&vframe); } tjDestroy(jtd); free(frame); free(pixmap); return NULL; }
static const char * VS_CC check_jpeg(img_hnd_t *ih, int n, FILE *fp, vs_args_t *va) { struct stat st; #ifdef _WIN32 wchar_t tmp[FILENAME_MAX * 2]; MultiByteToWideChar(CP_UTF8, 0, ih->src[n].name, -1, tmp, FILENAME_MAX * 2); if (wstat(tmp, &st)) { #else if (stat(ih->src[n].name, &st)) { #endif return "source file does not exist"; } ih->src[n].image_size = st.st_size; if (ih->src_buff_size < st.st_size) { ih->src_buff_size = st.st_size; free(ih->src_buff); ih->src_buff = malloc(ih->src_buff_size); if (!ih->src_buff) { return "failed to allocate read buffer"; } } unsigned long read = fread(ih->src_buff, 1, st.st_size, fp); fclose(fp); if (read < st.st_size) { return "failed to read jpeg file"; } int subsample, width, height; tjhandle handle = (tjhandle)ih->tjhandle; if (tjDecompressHeader2(handle, ih->src_buff, read, &width, &height, &subsample) != 0) { return tjGetErrorStr(); } if (subsample == TJSAMP_420 || subsample == TJSAMP_422) { width += width & 1; } if (subsample == TJSAMP_420 || subsample == TJSAMP_440) { height += height & 1; } ih->src[n].width = width; ih->src[n].height = height; VSPresetFormat pf = tjsamp_to_vspresetformat(subsample); ih->src[n].format = va->vsapi->getFormatPreset(pf, va->core); uint32_t row_size = tjBufSizeYUV(width, height, subsample) / height; if (row_size > va->max_row_size) { va->max_row_size = row_size; } ih->src[n].read = read_jpeg; return NULL; } const func_check_src check_src_jpeg = check_jpeg;
/* Decompression test */ int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf, unsigned long *jpegsize, unsigned char *dstbuf, int w, int h, int subsamp, int jpegqual, char *filename, int tilew, int tileh) { char tempstr[1024], sizestr[20]="\0", qualstr[6]="\0", *ptr; FILE *file=NULL; tjhandle handle=NULL; int row, col, i, dstbufalloc=0, retval=0; double start, elapsed; int ps=tjPixelSize[pf]; int yuvsize=tjBufSizeYUV(w, h, subsamp), bufsize; int scaledw=(yuv==YUVDECODE)? w : TJSCALED(w, sf); int scaledh=(yuv==YUVDECODE)? h : TJSCALED(h, sf); int pitch=scaledw*ps; int ntilesw=(w+tilew-1)/tilew, ntilesh=(h+tileh-1)/tileh; unsigned char *dstptr, *dstptr2; if(jpegqual>0) { snprintf(qualstr, 6, "_Q%d", jpegqual); qualstr[5]=0; } if((handle=tjInitDecompress())==NULL) _throwtj("executing tjInitDecompress()"); bufsize=(yuv==YUVDECODE? yuvsize:pitch*h); if(dstbuf==NULL) { if((dstbuf=(unsigned char *)malloc(bufsize)) == NULL) _throwunix("allocating image buffer"); dstbufalloc=1; } /* Set the destination buffer to gray so we know whether the decompressor attempted to write to it */ memset(dstbuf, 127, bufsize); /* Execute once to preload cache */ if(yuv==YUVDECODE) { if(tjDecompressToYUV(handle, jpegbuf[0], jpegsize[0], dstbuf, flags)==-1) _throwtj("executing tjDecompressToYUV()"); } else if(tjDecompress2(handle, jpegbuf[0], jpegsize[0], dstbuf, scaledw, pitch, scaledh, pf, flags)==-1) _throwtj("executing tjDecompress2()"); /* Benchmark */ for(i=0, start=gettime(); (elapsed=gettime()-start)<benchtime; i++) { int tile=0; if(yuv==YUVDECODE) { if(tjDecompressToYUV(handle, jpegbuf[0], jpegsize[0], dstbuf, flags)==-1) _throwtj("executing tjDecompressToYUV()"); } else for(row=0, dstptr=dstbuf; row<ntilesh; row++, dstptr+=pitch*tileh) { for(col=0, dstptr2=dstptr; col<ntilesw; col++, tile++, dstptr2+=ps*tilew) { int width=dotile? min(tilew, w-col*tilew):scaledw; int height=dotile? min(tileh, h-row*tileh):scaledh; if(tjDecompress2(handle, jpegbuf[tile], jpegsize[tile], dstptr2, width, pitch, height, pf, flags)==-1) _throwtj("executing tjDecompress2()"); } } } if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()"); handle=NULL; if(quiet) { printf("%s\n", sigfig((double)(w*h)/1000000.*(double)i/elapsed, 4, tempstr, 1024)); } else { printf("D--> Frame rate: %f fps\n", (double)i/elapsed); printf(" Dest. throughput: %f Megapixels/sec\n", (double)(w*h)/1000000.*(double)i/elapsed); } if(yuv==YUVDECODE) { snprintf(tempstr, 1024, "%s_%s%s.yuv", filename, subName[subsamp], qualstr); if((file=fopen(tempstr, "wb"))==NULL) _throwunix("opening YUV image for output"); if(fwrite(dstbuf, yuvsize, 1, file)!=1) _throwunix("writing YUV image"); fclose(file); file=NULL; } else { if(sf.num!=1 || sf.denom!=1) snprintf(sizestr, 20, "%d_%d", sf.num, sf.denom); else if(tilew!=w || tileh!=h) snprintf(sizestr, 20, "%dx%d", tilew, tileh); else snprintf(sizestr, 20, "full"); if(decomponly) snprintf(tempstr, 1024, "%s_%s.%s", filename, sizestr, ext); else snprintf(tempstr, 1024, "%s_%s%s_%s.%s", filename, subName[subsamp], qualstr, sizestr, ext); if(savebmp(tempstr, dstbuf, scaledw, scaledh, pf, (flags&TJFLAG_BOTTOMUP)!=0)==-1) _throwbmp("saving bitmap"); ptr=strrchr(tempstr, '.'); snprintf(ptr, 1024-(ptr-tempstr), "-err.%s", ext); if(srcbuf && sf.num==1 && sf.denom==1) { if(!quiet) printf("Compression error written to %s.\n", tempstr); if(subsamp==TJ_GRAYSCALE) { int index, index2; for(row=0, index=0; row<h; row++, index+=pitch) { for(col=0, index2=index; col<w; col++, index2+=ps) { int rindex=index2+tjRedOffset[pf]; int gindex=index2+tjGreenOffset[pf]; int bindex=index2+tjBlueOffset[pf]; int y=(int)((double)srcbuf[rindex]*0.299 + (double)srcbuf[gindex]*0.587 + (double)srcbuf[bindex]*0.114 + 0.5); if(y>255) y=255; if(y<0) y=0; dstbuf[rindex]=abs(dstbuf[rindex]-y); dstbuf[gindex]=abs(dstbuf[gindex]-y); dstbuf[bindex]=abs(dstbuf[bindex]-y); } } } else { for(row=0; row<h; row++) for(col=0; col<w*ps; col++) dstbuf[pitch*row+col] =abs(dstbuf[pitch*row+col]-srcbuf[pitch*row+col]); } if(savebmp(tempstr, dstbuf, w, h, pf, (flags&TJFLAG_BOTTOMUP)!=0)==-1) _throwbmp("saving bitmap"); } } bailout: if(file) {fclose(file); file=NULL;} if(handle) {tjDestroy(handle); handle=NULL;} if(dstbuf && dstbufalloc) {free(dstbuf); dstbuf=NULL;} return retval; }
void dotestyuv(unsigned char *srcbuf, int w, int h, int subsamp, char *filename) { char tempstr[1024], tempstr2[80]; FILE *file=NULL; tjhandle handle=NULL; unsigned char *dstbuf=NULL; double start, elapsed; int i, retval=0, ps=tjPixelSize[pf]; int yuvsize=0; yuvsize=tjBufSizeYUV(w, h, subsamp); if((dstbuf=(unsigned char *)malloc(yuvsize)) == NULL) _throwunix("allocating image buffer"); if(!quiet) printf(">>>>> %s (%s) <--> YUV %s <<<<<\n", pixFormatStr[pf], (flags&TJFLAG_BOTTOMUP)? "Bottom-up":"Top-down", subNameLong[subsamp]); if(quiet==1) printf("%s\t%s\t%s\tN/A\t", pixFormatStr[pf], (flags&TJFLAG_BOTTOMUP)? "BU":"TD", subNameLong[subsamp]); if((handle=tjInitCompress())==NULL) _throwtj("executing tjInitCompress()"); /* Execute once to preload cache */ if(tjEncodeYUV2(handle, srcbuf, w, 0, h, pf, dstbuf, subsamp, flags)==-1) _throwtj("executing tjEncodeYUV2()"); /* Benchmark */ for(i=0, start=gettime(); (elapsed=gettime()-start)<benchtime; i++) { if(tjEncodeYUV2(handle, srcbuf, w, 0, h, pf, dstbuf, subsamp, flags)==-1) _throwtj("executing tjEncodeYUV2()"); } if(tjDestroy(handle)==-1) _throwtj("executing tjDestroy()"); handle=NULL; if(quiet==1) printf("%-4d %-4d\t", w, h); if(quiet) { printf("%s%c%s%c", sigfig((double)(w*h)/1000000.*(double)i/elapsed, 4, tempstr, 1024), quiet==2? '\n':'\t', sigfig((double)(w*h*ps)/(double)yuvsize, 4, tempstr2, 80), quiet==2? '\n':'\t'); } else { printf("\n%s size: %d x %d\n", "Image", w, h); printf("C--> Frame rate: %f fps\n", (double)i/elapsed); printf(" Output image size: %d bytes\n", yuvsize); printf(" Compression ratio: %f:1\n", (double)(w*h*ps)/(double)yuvsize); printf(" Source throughput: %f Megapixels/sec\n", (double)(w*h)/1000000.*(double)i/elapsed); printf(" Output bit stream: %f Megabits/sec\n", (double)yuvsize*8./1000000.*(double)i/elapsed); } snprintf(tempstr, 1024, "%s_%s.yuv", filename, subName[subsamp]); if((file=fopen(tempstr, "wb"))==NULL) _throwunix("opening reference image"); if(fwrite(dstbuf, yuvsize, 1, file)!=1) _throwunix("writing reference image"); fclose(file); file=NULL; if(!quiet) printf("Reference image written to %s\n", tempstr); bailout: if(file) {fclose(file); file=NULL;} if(dstbuf) {free(dstbuf); dstbuf=NULL;} if(handle) {tjDestroy(handle); handle=NULL;} return; }