#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) {
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";
}