Use a .tiff file as input rather than an artificial image.
[j2kbench.git] / j2kbench.cc
index f81e7f6c809e9cf14cee3c52833724142a3af2d0..8af769d0adecb930a48268a877eb97ed9d225ad6 100644 (file)
@@ -1,5 +1,8 @@
 #include <dcp/j2k.h>
 #include <dcp/openjpeg_image.h>
+#include <dcp/colour_conversion.h>
+#include <dcp/rgb_xyz.h>
+#include <Magick++.h>
 #include <boost/thread.hpp>
 #include <boost/foreach.hpp>
 #include <list>
 
 using std::list;
 using std::cout;
+using std::cerr;
 using boost::shared_ptr;
+using boost::optional;
+
+#define WRITE_FIRST 1
 
 void
-thread (int iterations)
+thread (int iterations, shared_ptr<const dcp::OpenJPEGImage> image)
 {
-       int const width = 1998;
-       int const height = 1080;
-
+#ifdef WRITE_FIRST
+       static bool written = false;
+#endif
        for (int i = 0; i < iterations; ++i) {
-               shared_ptr<const dcp::OpenJPEGImage> xyz (new dcp::OpenJPEGImage (dcp::Size (width, height)));
-               int32_t* X = xyz->data(0);
-               int32_t* Y = xyz->data(1);
-               int32_t* Z = xyz->data(2);
-               for (int y = 0; y < height; ++y) {
-                       for (int x = 0; x < width; ++x)  {
-                               *X++ = x;
-                               *Y++ = y;
-                               *Z++ = (x * y) % 4096;
-                       }
+               shared_ptr<const dcp::OpenJPEGImage> copy (new dcp::OpenJPEGImage (*image.get()));
+               dcp::Data data = dcp::compress_j2k (copy, 100000000, 24, false, false);
+#ifdef WRITE_FIRST
+               if (!written) {
+                       FILE* f = fopen ("test.j2k", "wb");
+                       fwrite (data.data().get(), data.size(), 1, f);
+                       fclose (f);
+                       written = true;
                }
+#endif
+       }
+}
+
+shared_ptr<const dcp::OpenJPEGImage>
+load_frame (boost::filesystem::path file)
+{
+       boost::uintmax_t const file_size = boost::filesystem::file_size (file);
+       FILE* f = dcp::fopen_boost (file, "rb");
+       if (!f) {
+               cerr << "Could not open " << file.string() << "\n";
+               exit (EXIT_FAILURE);
+       }
 
-               dcp::compress_j2k (xyz, 100000000, 24, false, false);
+       uint8_t* data = new uint8_t[file_size];
+       if (fread (data, 1, file_size, f) != file_size) {
+               delete[] data;
+               cerr << "Could not read " << file.string() << "\n";
+               exit (EXIT_FAILURE);
        }
+
+       fclose (f);
+       Magick::Blob blob;
+       blob.update (data, file_size);
+       delete[] data;
+
+       Magick::Image* magick_image = new Magick::Image (blob);
+       dcp::Size size (magick_image->columns(), magick_image->rows());
+
+       int const stride = size.width * 6;
+       uint8_t* rgb = new uint8_t[size.height * stride];
+
+       uint8_t* p = rgb;
+       for (int i = 0; i < size.height; ++i) {
+               using namespace MagickCore;
+               magick_image->write (0, i, size.width, 1, "RGB", ShortPixel, p);
+               p += stride;
+       }
+
+       delete magick_image;
+
+       shared_ptr<dcp::OpenJPEGImage> xyz = dcp::rgb_to_xyz (rgb, size, stride, dcp::ColourConversion::rec709_to_xyz(), optional<dcp::NoteHandler> ());
+       delete[] rgb;
+
+       return xyz;
 }
 
 int
 main (int argc, char* argv[])
 {
-       if (argc < 3) {
-               cout << "Syntax: " << argv[0] << " <threads> <iterations>\n";
+       if (argc < 4) {
+               cout << "Syntax: " << argv[0] << " <threads> <iterations> <frame file>\n";
                exit (EXIT_FAILURE);
        }
 
        int const num_threads = atoi (argv[1]);
        int const num_iterations = atoi (argv[2]);
-       cout << num_threads << " threads, " << num_iterations << " iterations.\n";
+       boost::filesystem::path frame_file = argv[3];
+       cout << num_threads << " threads, " << num_iterations << " iterations, frame file " << frame_file.string() << ".\n";
+
+       shared_ptr<const dcp::OpenJPEGImage> image = load_frame (frame_file);
 
        struct timeval start;
        gettimeofday (&start, 0);
 
        list<boost::thread*> threads;
        for (int i = 0; i < num_threads; ++i) {
-               threads.push_back (new boost::thread (boost::bind (&thread, num_iterations)));
+               threads.push_back (new boost::thread (boost::bind (&thread, num_iterations, image)));
        }
 
        BOOST_FOREACH (boost::thread* i, threads) {
@@ -59,5 +109,7 @@ main (int argc, char* argv[])
        struct timeval stop;
        gettimeofday (&stop, 0);
 
-       cout << ((stop.tv_sec + double(stop.tv_usec) / 1000000) - (start.tv_sec + double(start.tv_usec) / 1000000)) << "s\n";
+       double const seconds = ((stop.tv_sec + double(stop.tv_usec) / 1000000) - (start.tv_sec + double(start.tv_usec) / 1000000));
+
+       cout << seconds << "s: " << (num_iterations * num_threads / seconds) << " fps.\n";
 }