]> git.ipfire.org Git - thirdparty/xz.git/commitdiff
liblzma: Use lzma_block_buffer_bound64() in threaded encoder.
authorLasse Collin <lasse.collin@tukaani.org>
Sat, 23 Mar 2013 19:55:13 +0000 (21:55 +0200)
committerLasse Collin <lasse.collin@tukaani.org>
Sat, 23 Mar 2013 19:55:13 +0000 (21:55 +0200)
Now it uses lzma_block_uncomp_encode() if the data doesn't
fit into the space calculated by lzma_block_buffer_bound64().

src/liblzma/common/stream_encoder_mt.c

index e30e9dca53c6ca81fe1e7db94725a70e59d7aa18..cd7b291dec9cf135d53fccf119cba27749bb3e04 100644 (file)
@@ -13,6 +13,7 @@
 #include "filter_encoder.h"
 #include "easy_preset.h"
 #include "block_encoder.h"
+#include "block_buffer_encoder.h"
 #include "index_encoder.h"
 #include "outqueue.h"
 
@@ -279,19 +280,55 @@ worker_encode(worker_thread *thr, worker_state state)
                                thr->block_encoder.coder, thr->allocator,
                                thr->in, &in_pos, in_limit, thr->outbuf->buf,
                                &thr->outbuf->size, out_size, action);
-       } while (ret == LZMA_OK);
+       } while (ret == LZMA_OK && thr->outbuf->size < out_size);
+
+       switch (ret) {
+       case LZMA_STREAM_END:
+               assert(state == THR_FINISH);
+
+               // Encode the Block Header. By doing it after
+               // the compression, we can store the Compressed Size
+               // and Uncompressed Size fields.
+               ret = lzma_block_header_encode(&thr->block_options,
+                               thr->outbuf->buf);
+               if (ret != LZMA_OK) {
+                       worker_error(thr, ret);
+                       return THR_STOP;
+               }
 
-       if (ret != LZMA_STREAM_END) {
-               worker_error(thr, ret);
-               return THR_STOP;
-       }
+               break;
 
-       assert(state == THR_FINISH);
+       case LZMA_OK:
+               // The data was incompressible. Encode it using uncompressed
+               // LZMA2 chunks.
+               //
+               // First wait that we have gotten all the input.
+               mythread_sync(thr->mutex) {
+                       while (thr->state == THR_RUN)
+                               pthread_cond_wait(&thr->cond, &thr->mutex);
 
-       // Encode the Block Header. By doing it after the compression,
-       // we can store the Compressed Size and Uncompressed Size fields.
-       ret = lzma_block_header_encode(&thr->block_options, thr->outbuf->buf);
-       if (ret != LZMA_OK) {
+                       state = thr->state;
+                       in_size = thr->in_size;
+               }
+
+               if (state >= THR_STOP)
+                       return state;
+
+               // Do the encoding. This takes care of the Block Header too.
+               thr->outbuf->size = 0;
+               ret = lzma_block_uncomp_encode(&thr->block_options,
+                               thr->in, in_size, thr->outbuf->buf,
+                               &thr->outbuf->size, out_size);
+
+               // It shouldn't fail.
+               if (ret != LZMA_OK) {
+                       worker_error(thr, LZMA_PROG_ERROR);
+                       return THR_STOP;
+               }
+
+               break;
+
+       default:
                worker_error(thr, ret);
                return THR_STOP;
        }
@@ -842,12 +879,9 @@ get_options(const lzma_mt *options, lzma_options_easy *opt_easy,
        // Calculate the maximum amount output that a single output buffer
        // may need to hold. This is the same as the maximum total size of
        // a Block.
-       //
-       // FIXME: As long as the encoder keeps the whole input buffer
-       // available and doesn't start writing output before finishing
-       // the Block, it could use lzma_stream_buffer_bound() and use
-       // uncompressed LZMA2 chunks if the data doesn't compress.
-       *outbuf_size_max = *block_size + *block_size / 16 + 16384;
+       *outbuf_size_max = lzma_block_buffer_bound64(*block_size);
+       if (*outbuf_size_max == 0)
+               return LZMA_MEM_ERROR;
 
        return LZMA_OK;
 }