提交 bff7d0ca 编写于 作者: B bae

8007918: Better image writing

Reviewed-by: mschoene, prr, jgodinez
上级 e8b18802
...@@ -183,8 +183,7 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -183,8 +183,7 @@ public class JPEGImageWriter extends ImageWriter {
return null; return null;
} }
}); });
initWriterIDs(ImageOutputStream.class, initWriterIDs(JPEGQTable.class,
JPEGQTable.class,
JPEGHuffmanTable.class); JPEGHuffmanTable.class);
} }
...@@ -200,11 +199,13 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -200,11 +199,13 @@ public class JPEGImageWriter extends ImageWriter {
public void setOutput(Object output) { public void setOutput(Object output) {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
super.setOutput(output); // validates output super.setOutput(output); // validates output
resetInternalState(); resetInternalState();
ios = (ImageOutputStream) output; // so this will always work ios = (ImageOutputStream) output; // so this will always work
// Set the native destination // Set the native destination
setDest(structPointer, ios); setDest(structPointer);
} finally { } finally {
clearThreadLock(); clearThreadLock();
} }
...@@ -359,6 +360,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -359,6 +360,8 @@ public class JPEGImageWriter extends ImageWriter {
ImageWriteParam param) throws IOException { ImageWriteParam param) throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
writeOnThread(streamMetadata, image, param); writeOnThread(streamMetadata, image, param);
} finally { } finally {
clearThreadLock(); clearThreadLock();
...@@ -1082,13 +1085,18 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1082,13 +1085,18 @@ public class JPEGImageWriter extends ImageWriter {
haveMetadata, haveMetadata,
restartInterval); restartInterval);
if (aborted) { cbLock.lock();
processWriteAborted(); try {
} else { if (aborted) {
processImageComplete(); processWriteAborted();
} } else {
processImageComplete();
}
ios.flush(); ios.flush();
} finally {
cbLock.unlock();
}
currentImage++; // After a successful write currentImage++; // After a successful write
} }
...@@ -1096,6 +1104,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1096,6 +1104,8 @@ public class JPEGImageWriter extends ImageWriter {
throws IOException { throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
prepareWriteSequenceOnThread(streamMetadata); prepareWriteSequenceOnThread(streamMetadata);
} finally { } finally {
clearThreadLock(); clearThreadLock();
...@@ -1175,6 +1185,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1175,6 +1185,8 @@ public class JPEGImageWriter extends ImageWriter {
throws IOException { throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if (sequencePrepared == false) { if (sequencePrepared == false) {
throw new IllegalStateException("sequencePrepared not called!"); throw new IllegalStateException("sequencePrepared not called!");
} }
...@@ -1188,6 +1200,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1188,6 +1200,8 @@ public class JPEGImageWriter extends ImageWriter {
public void endWriteSequence() throws IOException { public void endWriteSequence() throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if (sequencePrepared == false) { if (sequencePrepared == false) {
throw new IllegalStateException("sequencePrepared not called!"); throw new IllegalStateException("sequencePrepared not called!");
} }
...@@ -1200,6 +1214,10 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1200,6 +1214,10 @@ public class JPEGImageWriter extends ImageWriter {
public synchronized void abort() { public synchronized void abort() {
setThreadLock(); setThreadLock();
try { try {
/**
* NB: we do not check the call back lock here, we allow to abort
* the reader any time.
*/
super.abort(); super.abort();
abortWrite(structPointer); abortWrite(structPointer);
} finally { } finally {
...@@ -1223,6 +1241,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1223,6 +1241,8 @@ public class JPEGImageWriter extends ImageWriter {
public void reset() { public void reset() {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
super.reset(); super.reset();
} finally { } finally {
clearThreadLock(); clearThreadLock();
...@@ -1232,6 +1252,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1232,6 +1252,8 @@ public class JPEGImageWriter extends ImageWriter {
public void dispose() { public void dispose() {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if (structPointer != 0) { if (structPointer != 0) {
disposerRecord.dispose(); disposerRecord.dispose();
structPointer = 0; structPointer = 0;
...@@ -1251,13 +1273,18 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1251,13 +1273,18 @@ public class JPEGImageWriter extends ImageWriter {
* sending warnings to listeners. * sending warnings to listeners.
*/ */
void warningOccurred(int code) { void warningOccurred(int code) {
if ((code < 0) || (code > MAX_WARNING)){ cbLock.lock();
throw new InternalError("Invalid warning index"); try {
if ((code < 0) || (code > MAX_WARNING)){
throw new InternalError("Invalid warning index");
}
processWarningOccurred
(currentImage,
"com.sun.imageio.plugins.jpeg.JPEGImageWriterResources",
Integer.toString(code));
} finally {
cbLock.unlock();
} }
processWarningOccurred
(currentImage,
"com.sun.imageio.plugins.jpeg.JPEGImageWriterResources",
Integer.toString(code));
} }
/** /**
...@@ -1274,21 +1301,41 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1274,21 +1301,41 @@ public class JPEGImageWriter extends ImageWriter {
* library warnings from being printed to stderr. * library warnings from being printed to stderr.
*/ */
void warningWithMessage(String msg) { void warningWithMessage(String msg) {
processWarningOccurred(currentImage, msg); cbLock.lock();
try {
processWarningOccurred(currentImage, msg);
} finally {
cbLock.unlock();
}
} }
void thumbnailStarted(int thumbnailIndex) { void thumbnailStarted(int thumbnailIndex) {
processThumbnailStarted(currentImage, thumbnailIndex); cbLock.lock();
try {
processThumbnailStarted(currentImage, thumbnailIndex);
} finally {
cbLock.unlock();
}
} }
// Provide access to protected superclass method // Provide access to protected superclass method
void thumbnailProgress(float percentageDone) { void thumbnailProgress(float percentageDone) {
processThumbnailProgress(percentageDone); cbLock.lock();
try {
processThumbnailProgress(percentageDone);
} finally {
cbLock.unlock();
}
} }
// Provide access to protected superclass method // Provide access to protected superclass method
void thumbnailComplete() { void thumbnailComplete() {
processThumbnailComplete(); cbLock.lock();
try {
processThumbnailComplete();
} finally {
cbLock.unlock();
}
} }
///////// End of Package-access API ///////// End of Package-access API
...@@ -1615,16 +1662,14 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1615,16 +1662,14 @@ public class JPEGImageWriter extends ImageWriter {
////////////// Native methods and callbacks ////////////// Native methods and callbacks
/** Sets up static native structures. */ /** Sets up static native structures. */
private static native void initWriterIDs(Class iosClass, private static native void initWriterIDs(Class qTableClass,
Class qTableClass,
Class huffClass); Class huffClass);
/** Sets up per-writer native structure and returns a pointer to it. */ /** Sets up per-writer native structure and returns a pointer to it. */
private native long initJPEGImageWriter(); private native long initJPEGImageWriter();
/** Sets up native structures for output stream */ /** Sets up native structures for output stream */
private native void setDest(long structPointer, private native void setDest(long structPointer);
ImageOutputStream ios);
/** /**
* Returns <code>true</code> if the write was aborted. * Returns <code>true</code> if the write was aborted.
...@@ -1749,7 +1794,12 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1749,7 +1794,12 @@ public class JPEGImageWriter extends ImageWriter {
} }
raster.setRect(sourceLine); raster.setRect(sourceLine);
if ((y > 7) && (y%8 == 0)) { // Every 8 scanlines if ((y > 7) && (y%8 == 0)) { // Every 8 scanlines
processImageProgress((float) y / (float) sourceHeight * 100.0F); cbLock.lock();
try {
processImageProgress((float) y / (float) sourceHeight * 100.0F);
} finally {
cbLock.unlock();
}
} }
} }
...@@ -1777,6 +1827,25 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1777,6 +1827,25 @@ public class JPEGImageWriter extends ImageWriter {
} }
} }
/**
* This method is called from native code in order to write encoder
* output to the destination.
*
* We block any attempt to change the writer state during this
* method, in order to prevent a corruption of the native encoder
* state.
*/
private void writeOutputData(byte[] data, int offset, int len)
throws IOException
{
cbLock.lock();
try {
ios.write(data, offset, len);
} finally {
cbLock.unlock();
}
}
private Thread theThread = null; private Thread theThread = null;
private int theLockCount = 0; private int theLockCount = 0;
...@@ -1811,4 +1880,34 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1811,4 +1880,34 @@ public class JPEGImageWriter extends ImageWriter {
theThread = null; theThread = null;
} }
} }
private CallBackLock cbLock = new CallBackLock();
private static class CallBackLock {
private State lockState;
CallBackLock() {
lockState = State.Unlocked;
}
void check() {
if (lockState != State.Unlocked) {
throw new IllegalStateException("Access to the writer is not allowed");
}
}
private void lock() {
lockState = State.Locked;
}
private void unlock() {
lockState = State.Unlocked;
}
private static enum State {
Unlocked,
Locked
}
}
} }
...@@ -66,7 +66,7 @@ static jmethodID JPEGImageReader_acceptPixelsID; ...@@ -66,7 +66,7 @@ static jmethodID JPEGImageReader_acceptPixelsID;
static jmethodID JPEGImageReader_pushBackID; static jmethodID JPEGImageReader_pushBackID;
static jmethodID JPEGImageReader_passStartedID; static jmethodID JPEGImageReader_passStartedID;
static jmethodID JPEGImageReader_passCompleteID; static jmethodID JPEGImageReader_passCompleteID;
static jmethodID ImageOutputStream_writeID; static jmethodID JPEGImageWriter_writeOutputDataID;
static jmethodID JPEGImageWriter_warningOccurredID; static jmethodID JPEGImageWriter_warningOccurredID;
static jmethodID JPEGImageWriter_warningWithMessageID; static jmethodID JPEGImageWriter_warningWithMessageID;
static jmethodID JPEGImageWriter_writeMetadataID; static jmethodID JPEGImageWriter_writeMetadataID;
...@@ -2290,7 +2290,7 @@ imageio_empty_output_buffer (j_compress_ptr cinfo) ...@@ -2290,7 +2290,7 @@ imageio_empty_output_buffer (j_compress_ptr cinfo)
(*env)->CallVoidMethod(env, (*env)->CallVoidMethod(env,
sb->stream, sb->stream,
ImageOutputStream_writeID, JPEGImageWriter_writeOutputDataID,
sb->hstreamBuffer, sb->hstreamBuffer,
0, 0,
sb->bufferLength); sb->bufferLength);
...@@ -2327,7 +2327,7 @@ imageio_term_destination (j_compress_ptr cinfo) ...@@ -2327,7 +2327,7 @@ imageio_term_destination (j_compress_ptr cinfo)
(*env)->CallVoidMethod(env, (*env)->CallVoidMethod(env,
sb->stream, sb->stream,
ImageOutputStream_writeID, JPEGImageWriter_writeOutputDataID,
sb->hstreamBuffer, sb->hstreamBuffer,
0, 0,
datacount); datacount);
...@@ -2365,13 +2365,12 @@ JNIEXPORT void JNICALL ...@@ -2365,13 +2365,12 @@ JNIEXPORT void JNICALL
Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_initWriterIDs Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_initWriterIDs
(JNIEnv *env, (JNIEnv *env,
jclass cls, jclass cls,
jclass IOSClass,
jclass qTableClass, jclass qTableClass,
jclass huffClass) { jclass huffClass) {
ImageOutputStream_writeID = (*env)->GetMethodID(env, JPEGImageWriter_writeOutputDataID = (*env)->GetMethodID(env,
IOSClass, cls,
"write", "writeOutputData",
"([BII)V"); "([BII)V");
JPEGImageWriter_warningOccurredID = (*env)->GetMethodID(env, JPEGImageWriter_warningOccurredID = (*env)->GetMethodID(env,
...@@ -2495,8 +2494,7 @@ JNIEXPORT void JNICALL ...@@ -2495,8 +2494,7 @@ JNIEXPORT void JNICALL
Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_setDest Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_setDest
(JNIEnv *env, (JNIEnv *env,
jobject this, jobject this,
jlong ptr, jlong ptr) {
jobject destination) {
imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_compress_ptr cinfo; j_compress_ptr cinfo;
...@@ -2510,7 +2508,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_setDest ...@@ -2510,7 +2508,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_setDest
cinfo = (j_compress_ptr) data->jpegObj; cinfo = (j_compress_ptr) data->jpegObj;
imageio_set_stream(env, data->jpegObj, data, destination); imageio_set_stream(env, data->jpegObj, data, this);
// Don't call the init method, as that depends on pinned arrays // Don't call the init method, as that depends on pinned arrays
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册