diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-01 18:11:20 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-01 18:11:20 +0000 |
commit | 5526773cbfbb6b9f3ef4fbec96bebc5014cf78ff (patch) | |
tree | d3330a625797dd9c535d4d0d320a25aa7f60bea2 /remoting/base | |
parent | 57ddb39b9db7d242c7cf136381bed5650b2355c4 (diff) | |
download | chromium_src-5526773cbfbb6b9f3ef4fbec96bebc5014cf78ff.zip chromium_src-5526773cbfbb6b9f3ef4fbec96bebc5014cf78ff.tar.gz chromium_src-5526773cbfbb6b9f3ef4fbec96bebc5014cf78ff.tar.bz2 |
Zlib compressor for Chromoting
A simple implementation of compressor using zlib.
Review URL: http://codereview.chromium.org/2841032
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51386 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/base')
-rw-r--r-- | remoting/base/compressor.h | 49 | ||||
-rw-r--r-- | remoting/base/compressor_zlib.cc | 73 | ||||
-rw-r--r-- | remoting/base/compressor_zlib.h | 33 | ||||
-rw-r--r-- | remoting/base/compressor_zlib_unittest.cc | 52 |
4 files changed, 207 insertions, 0 deletions
diff --git a/remoting/base/compressor.h b/remoting/base/compressor.h new file mode 100644 index 0000000..4c242bd --- /dev/null +++ b/remoting/base/compressor.h @@ -0,0 +1,49 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_BASE_COMPRESSOR_H_ +#define REMOTING_BASE_COMPRESSOR_H_ + +#include "base/basictypes.h" + +namespace remoting { + +// An object to compress data losslessly. Compressed data can be fully +// recovered by a Decompressor. +// +// Note that a Compressor can only be used on one stream during its +// lifetime. This object should be destroyed after use. +class Compressor { + public: + virtual ~Compressor() {} + + // Compress |input_data| with |input_size| bytes. + // + // |output_data| is provided by the caller and |output_size| is the + // size of |output_data|. + // + // Compressed data is written to |output_data|. |consumed| will + // contain the number of bytes consumed from the input. |written| + // contains the number of bytes written to output. + virtual void Write(const uint8* input_data, int input_size, + uint8* output_data, int output_size, + int* consumed, int* written) = 0; + + // Flush all the remaining data in the compressor. + // + // |output_data| is provided by the caller and |output_size| is called + // with the size of |output_data|. + // + // Output data is written to |output_data| and |written| contains the + // number of bytes written. + // + // Returns true if |output_data| is not large enough to carry all + // compressed data and caller needs to call Flush() again. + virtual bool Flush(uint8* output_data, int output_size, + int* written) = 0; +}; + +} // namespace remoting + +#endif // REMOTING_BASE_COMPRESSOR_H_ diff --git a/remoting/base/compressor_zlib.cc b/remoting/base/compressor_zlib.cc new file mode 100644 index 0000000..e08d2f9 --- /dev/null +++ b/remoting/base/compressor_zlib.cc @@ -0,0 +1,73 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/base/compressor_zlib.h" + +#if defined(USE_SYSTEM_ZLIB) +#include <zlib.h> +// The code below uses the MOZ_Z_ forms of these functions in order that things +// should work on Windows. In order to make this code cross platform, we map +// back to the normal functions here in the case that we are using the system +// zlib. +#define MOZ_Z_deflate deflate +#define MOZ_Z_deflateEnd deflateEnd +#define MOZ_Z_deflateInit_ deflateInit_ +#else +#include "third_party/zlib/zlib.h" +#endif +#include "base/logging.h" + +namespace remoting { + +CompressorZlib::CompressorZlib() { + stream_.reset(new z_stream()); + + stream_->next_in = Z_NULL; + stream_->zalloc = Z_NULL; + stream_->zfree = Z_NULL; + stream_->opaque = Z_NULL; + + deflateInit(stream_.get(), Z_BEST_SPEED); +} + +CompressorZlib::~CompressorZlib() { + deflateEnd(stream_.get()); +} + +void CompressorZlib::Write(const uint8* input_data, int input_size, + uint8* output_data, int output_size, + int* consumed, int* written) { + // Setup I/O parameters. + stream_->avail_in = input_size; + stream_->next_in = (Bytef*)input_data; + stream_->avail_out = output_size; + stream_->next_out = (Bytef*)output_data; + + int ret = deflate(stream_.get(), Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR) { + NOTREACHED() << "zlib compression failed"; + } + + *consumed = input_size - stream_->avail_in; + *written = output_size - stream_->avail_out; +} + +bool CompressorZlib::Flush(uint8* output_data, int output_size, + int* written) { + // Setup I/O parameters. + stream_->avail_in = 0; + stream_->next_in = NULL; + stream_->avail_out = output_size; + stream_->next_out = (Bytef*)output_data; + + int ret = deflate(stream_.get(), Z_FINISH); + if (ret == Z_STREAM_ERROR) { + NOTREACHED() << "zlib compression failed"; + } + + *written = output_size - stream_->avail_out; + return ret == Z_OK; +} + +} // namespace remoting diff --git a/remoting/base/compressor_zlib.h b/remoting/base/compressor_zlib.h new file mode 100644 index 0000000..93bd5ca --- /dev/null +++ b/remoting/base/compressor_zlib.h @@ -0,0 +1,33 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_BASE_COMPRESSOR_ZLIB_H_ +#define REMOTING_BASE_COMPRESSOR_ZLIB_H_ + +#include "base/scoped_ptr.h" +#include "remoting/base/compressor.h" + +typedef struct z_stream_s z_stream; + +namespace remoting { + +// A lossless compressor using zlib. +class CompressorZlib : public Compressor { + public: + CompressorZlib(); + virtual ~CompressorZlib(); + + // Compressor implementations. + virtual void Write(const uint8* input_data, int input_size, + uint8* output_data, int output_size, + int* consumed, int* written); + virtual bool Flush(uint8* output_data, int output_size, int* written); + + private: + scoped_ptr<z_stream> stream_; +}; + +} // namespace remoting + +#endif // REMOTING_BASE_COMPRESSOR_ZLIB_H_ diff --git a/remoting/base/compressor_zlib_unittest.cc b/remoting/base/compressor_zlib_unittest.cc new file mode 100644 index 0000000..9d65aad --- /dev/null +++ b/remoting/base/compressor_zlib_unittest.cc @@ -0,0 +1,52 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stdlib.h> + +#include "remoting/base/compressor_zlib.h" +#include "testing/gtest/include/gtest/gtest.h" + +static void GenerateTestData(uint8* data, int size, int seed) { + srand(seed); + for (int i = 0; i < size; ++i) + data[i] = rand() % 256; +} + +// Keep compressing |input_data| into |output_data| until the last +// bytes is consumed. +static void Compress(remoting::Compressor* compressor, + const uint8* input_data, int input_size, + uint8* output_data, int output_size) { + + // Feed data into the compress until the end. + // This loop will rewrite |output_data| continuously. + while (input_size) { + int consumed, written; + compressor->Write(input_data, input_size, + output_data, output_size, + &consumed, &written); + input_data += consumed; + input_size -= consumed; + } + + // And then flush the remaining data from the compressor. + int written; + while (compressor->Flush(output_data, output_size, &written)) { + } +} + +TEST(CompressorZlibTest, SimpleCompress) { + static const int kRawDataSize = 1024 * 128; + static const int kCompressedDataSize = 256; + uint8 raw_data[kRawDataSize]; + uint8 compressed_data[kCompressedDataSize]; + + // Generate the test data.g + GenerateTestData(raw_data, kRawDataSize, 99); + + // Then use the compressor to compress. + remoting::CompressorZlib compressor; + Compress(&compressor, raw_data, kRawDataSize, + compressed_data, kCompressedDataSize); +} |