Merge master.
[dcpomatic.git] / test / test.cc
index 75199fac7ebd834e29d918405d1915a76b264a51..15c34ca78dc23206f0efaa9f83e512701db202de 100644 (file)
@@ -94,25 +94,18 @@ BOOST_AUTO_TEST_CASE (make_black_test)
        libdcp::Size in_size (512, 512);
        libdcp::Size out_size (1024, 1024);
 
-       {
-               /* Plain RGB input */
-               boost::shared_ptr<Image> foo (new SimpleImage (AV_PIX_FMT_RGB24, in_size, true));
-               foo->make_black ();
-               boost::shared_ptr<Image> bar = foo->scale_and_convert_to_rgb (out_size, 0, Scaler::from_id ("bicubic"), true);
-               
-               uint8_t* p = bar->data()[0];
-               for (int y = 0; y < bar->size().height; ++y) {
-                       uint8_t* q = p;
-                       for (int x = 0; x < bar->line_size()[0]; ++x) {
-                               BOOST_CHECK_EQUAL (*q++, 0);
-                       }
-                       p += bar->stride()[0];
-               }
-       }
-
-       {
-               /* YUV420P input */
-               boost::shared_ptr<Image> foo (new SimpleImage (AV_PIX_FMT_YUV420P, in_size, true));
+       list<AVPixelFormat> pix_fmts;
+       pix_fmts.push_back (AV_PIX_FMT_RGB24);
+       pix_fmts.push_back (AV_PIX_FMT_YUV420P);
+       pix_fmts.push_back (AV_PIX_FMT_YUV422P10LE);
+       pix_fmts.push_back (AV_PIX_FMT_YUV444P9LE);
+       pix_fmts.push_back (AV_PIX_FMT_YUV444P9BE);
+       pix_fmts.push_back (AV_PIX_FMT_YUV444P10LE);
+       pix_fmts.push_back (AV_PIX_FMT_YUV444P10BE);
+
+       int N = 0;
+       for (list<AVPixelFormat>::const_iterator i = pix_fmts.begin(); i != pix_fmts.end(); ++i) {
+               boost::shared_ptr<Image> foo (new SimpleImage (*i, in_size, true));
                foo->make_black ();
                boost::shared_ptr<Image> bar = foo->scale_and_convert_to_rgb (out_size, 0, Scaler::from_id ("bicubic"), true);
                
@@ -124,22 +117,8 @@ BOOST_AUTO_TEST_CASE (make_black_test)
                        }
                        p += bar->stride()[0];
                }
-       }
 
-       {
-               /* YUV422P10LE input */
-               boost::shared_ptr<Image> foo (new SimpleImage (AV_PIX_FMT_YUV422P10LE, in_size, true));
-               foo->make_black ();
-               boost::shared_ptr<Image> bar = foo->scale_and_convert_to_rgb (out_size, 0, Scaler::from_id ("bicubic"), true);
-               
-               uint8_t* p = bar->data()[0];
-               for (int y = 0; y < bar->size().height; ++y) {
-                       uint8_t* q = p;
-                       for (int x = 0; x < bar->line_size()[0]; ++x) {
-                               BOOST_CHECK_EQUAL (*q++, 0);
-                       }
-                       p += bar->stride()[0];
-               }
+               ++N;
        }
 }
 
@@ -480,7 +459,7 @@ BOOST_AUTO_TEST_CASE (make_dcp_test)
        film->set_content ("../../../test/test.mp4");
        film->set_format (Format::from_nickname ("Flat"));
        film->set_dcp_content_type (DCPContentType::from_pretty_name ("Test"));
-       film->make_dcp (true);
+       film->make_dcp ();
        film->write_metadata ();
 
        while (JobManager::instance()->work_to_do ()) {
@@ -512,7 +491,7 @@ BOOST_AUTO_TEST_CASE (make_dcp_with_range_test)
        film->set_format (Format::from_nickname ("Flat"));
        film->set_dcp_content_type (DCPContentType::from_pretty_name ("Test"));
        film->set_trim_end (42);
-       film->make_dcp (true);
+       film->make_dcp ();
 
        while (JobManager::instance()->work_to_do() && !JobManager::instance()->errors()) {
                dvdomatic_sleep (1);
@@ -521,8 +500,8 @@ BOOST_AUTO_TEST_CASE (make_dcp_with_range_test)
        BOOST_CHECK_EQUAL (JobManager::instance()->errors(), false);
 }
 
-/* Test the constructor of DCPFrameRate */
-BOOST_AUTO_TEST_CASE (dcp_frame_rate_test)
+/* Test best_dcp_frame_rate and FrameRateConversion */
+BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test)
 {
        /* Run some tests with a limited range of allowed rates */
        
@@ -532,71 +511,82 @@ BOOST_AUTO_TEST_CASE (dcp_frame_rate_test)
        afr.push_back (30);
        Config::instance()->set_allowed_dcp_frame_rates (afr);
 
-       DCPFrameRate dfr = DCPFrameRate (60);
-       BOOST_CHECK_EQUAL (dfr.frames_per_second, 30);
-       BOOST_CHECK_EQUAL (dfr.skip, true);
-       BOOST_CHECK_EQUAL (dfr.repeat, false);
-       BOOST_CHECK_EQUAL (dfr.change_speed, false);
+       int best = best_dcp_frame_rate (60);
+       FrameRateConversion frc = FrameRateConversion (60, best);
+       BOOST_CHECK_EQUAL (best, 30);
+       BOOST_CHECK_EQUAL (frc.skip, true);
+       BOOST_CHECK_EQUAL (frc.repeat, false);
+       BOOST_CHECK_EQUAL (frc.change_speed, false);
        
-       dfr = DCPFrameRate (50);
-       BOOST_CHECK_EQUAL (dfr.frames_per_second, 25);
-       BOOST_CHECK_EQUAL (dfr.skip, true);
-       BOOST_CHECK_EQUAL (dfr.repeat, false);
-       BOOST_CHECK_EQUAL (dfr.change_speed, false);
-
-       dfr = DCPFrameRate (48);
-       BOOST_CHECK_EQUAL (dfr.frames_per_second, 24);
-       BOOST_CHECK_EQUAL (dfr.skip, true);
-       BOOST_CHECK_EQUAL (dfr.repeat, false);
-       BOOST_CHECK_EQUAL (dfr.change_speed, false);
+       best = best_dcp_frame_rate (50);
+       frc = FrameRateConversion (50, best);
+       BOOST_CHECK_EQUAL (best, 25);
+       BOOST_CHECK_EQUAL (frc.skip, true);
+       BOOST_CHECK_EQUAL (frc.repeat, false);
+       BOOST_CHECK_EQUAL (frc.change_speed, false);
+
+       best = best_dcp_frame_rate (48);
+       frc = FrameRateConversion (48, best);
+       BOOST_CHECK_EQUAL (best, 24);
+       BOOST_CHECK_EQUAL (frc.skip, true);
+       BOOST_CHECK_EQUAL (frc.repeat, false);
+       BOOST_CHECK_EQUAL (frc.change_speed, false);
        
-       dfr = DCPFrameRate (30);
-       BOOST_CHECK_EQUAL (dfr.skip, false);
-       BOOST_CHECK_EQUAL (dfr.frames_per_second, 30);
-       BOOST_CHECK_EQUAL (dfr.repeat, false);
-       BOOST_CHECK_EQUAL (dfr.change_speed, false);
-
-       dfr = DCPFrameRate (29.97);
-       BOOST_CHECK_EQUAL (dfr.skip, false);
-       BOOST_CHECK_EQUAL (dfr.frames_per_second, 30);
-       BOOST_CHECK_EQUAL (dfr.repeat, false);
-       BOOST_CHECK_EQUAL (dfr.change_speed, true);
+       best = best_dcp_frame_rate (30);
+       frc = FrameRateConversion (30, best);
+       BOOST_CHECK_EQUAL (best, 30);
+       BOOST_CHECK_EQUAL (frc.skip, false);
+       BOOST_CHECK_EQUAL (frc.repeat, false);
+       BOOST_CHECK_EQUAL (frc.change_speed, false);
+
+       best = best_dcp_frame_rate (29.97);
+       frc = FrameRateConversion (29.97, best);
+       BOOST_CHECK_EQUAL (best, 30);
+       BOOST_CHECK_EQUAL (frc.skip, false);
+       BOOST_CHECK_EQUAL (frc.repeat, false);
+       BOOST_CHECK_EQUAL (frc.change_speed, true);
        
-       dfr = DCPFrameRate (25);
-       BOOST_CHECK_EQUAL (dfr.skip, false);
-       BOOST_CHECK_EQUAL (dfr.frames_per_second, 25);
-       BOOST_CHECK_EQUAL (dfr.repeat, false);
-       BOOST_CHECK_EQUAL (dfr.change_speed, false);
-
-       dfr = DCPFrameRate (24);
-       BOOST_CHECK_EQUAL (dfr.skip, false);
-       BOOST_CHECK_EQUAL (dfr.frames_per_second, 24);
-       BOOST_CHECK_EQUAL (dfr.repeat, false);
-       BOOST_CHECK_EQUAL (dfr.change_speed, false);
-
-       dfr = DCPFrameRate (14.5);
-       BOOST_CHECK_EQUAL (dfr.skip, false);
-       BOOST_CHECK_EQUAL (dfr.frames_per_second, 30);
-       BOOST_CHECK_EQUAL (dfr.repeat, true);
-       BOOST_CHECK_EQUAL (dfr.change_speed, true);
-
-       dfr = DCPFrameRate (12.6);
-       BOOST_CHECK_EQUAL (dfr.skip, false);
-       BOOST_CHECK_EQUAL (dfr.frames_per_second, 25);
-       BOOST_CHECK_EQUAL (dfr.repeat, true);
-       BOOST_CHECK_EQUAL (dfr.change_speed, true);
-
-       dfr = DCPFrameRate (12.4);
-       BOOST_CHECK_EQUAL (dfr.skip, false);
-       BOOST_CHECK_EQUAL (dfr.frames_per_second, 25);
-       BOOST_CHECK_EQUAL (dfr.repeat, true);
-       BOOST_CHECK_EQUAL (dfr.change_speed, true);
-
-       dfr = DCPFrameRate (12);
-       BOOST_CHECK_EQUAL (dfr.skip, false);
-       BOOST_CHECK_EQUAL (dfr.frames_per_second, 24);
-       BOOST_CHECK_EQUAL (dfr.repeat, true);
-       BOOST_CHECK_EQUAL (dfr.change_speed, false);
+       best = best_dcp_frame_rate (25);
+       frc = FrameRateConversion (25, best);
+       BOOST_CHECK_EQUAL (best, 25);
+       BOOST_CHECK_EQUAL (frc.skip, false);
+       BOOST_CHECK_EQUAL (frc.repeat, false);
+       BOOST_CHECK_EQUAL (frc.change_speed, false);
+
+       best = best_dcp_frame_rate (24);
+       frc = FrameRateConversion (24, best);
+       BOOST_CHECK_EQUAL (best, 24);
+       BOOST_CHECK_EQUAL (frc.skip, false);
+       BOOST_CHECK_EQUAL (frc.repeat, false);
+       BOOST_CHECK_EQUAL (frc.change_speed, false);
+
+       best = best_dcp_frame_rate (14.5);
+       frc = FrameRateConversion (14.5, best);
+       BOOST_CHECK_EQUAL (best, 30);
+       BOOST_CHECK_EQUAL (frc.skip, false);
+       BOOST_CHECK_EQUAL (frc.repeat, true);
+       BOOST_CHECK_EQUAL (frc.change_speed, true);
+
+       best = best_dcp_frame_rate (12.6);
+       frc = FrameRateConversion (12.6, best);
+       BOOST_CHECK_EQUAL (best, 25);
+       BOOST_CHECK_EQUAL (frc.skip, false);
+       BOOST_CHECK_EQUAL (frc.repeat, true);
+       BOOST_CHECK_EQUAL (frc.change_speed, true);
+
+       best = best_dcp_frame_rate (12.4);
+       frc = FrameRateConversion (12.4, best);
+       BOOST_CHECK_EQUAL (best, 25);
+       BOOST_CHECK_EQUAL (frc.skip, false);
+       BOOST_CHECK_EQUAL (frc.repeat, true);
+       BOOST_CHECK_EQUAL (frc.change_speed, true);
+
+       best = best_dcp_frame_rate (12);
+       frc = FrameRateConversion (12, best);
+       BOOST_CHECK_EQUAL (best, 24);
+       BOOST_CHECK_EQUAL (frc.skip, false);
+       BOOST_CHECK_EQUAL (frc.repeat, true);
+       BOOST_CHECK_EQUAL (frc.change_speed, false);
 
        /* Now add some more rates and see if it will use them
           in preference to skip/repeat.
@@ -607,29 +597,59 @@ BOOST_AUTO_TEST_CASE (dcp_frame_rate_test)
        afr.push_back (60);
        Config::instance()->set_allowed_dcp_frame_rates (afr);
 
-       dfr = DCPFrameRate (60);
-       BOOST_CHECK_EQUAL (dfr.frames_per_second, 60);
-       BOOST_CHECK_EQUAL (dfr.skip, false);
-       BOOST_CHECK_EQUAL (dfr.repeat, false);
-       BOOST_CHECK_EQUAL (dfr.change_speed, false);
+       best = best_dcp_frame_rate (60);
+       frc = FrameRateConversion (60, best);
+       BOOST_CHECK_EQUAL (best, 60);
+       BOOST_CHECK_EQUAL (frc.skip, false);
+       BOOST_CHECK_EQUAL (frc.repeat, false);
+       BOOST_CHECK_EQUAL (frc.change_speed, false);
+       
+       best = best_dcp_frame_rate (50);
+       frc = FrameRateConversion (50, best);
+       BOOST_CHECK_EQUAL (best, 50);
+       BOOST_CHECK_EQUAL (frc.skip, false);
+       BOOST_CHECK_EQUAL (frc.repeat, false);
+       BOOST_CHECK_EQUAL (frc.change_speed, false);
+
+       best = best_dcp_frame_rate (48);
+       frc = FrameRateConversion (48, best);
+       BOOST_CHECK_EQUAL (best, 48);
+       BOOST_CHECK_EQUAL (frc.skip, false);
+       BOOST_CHECK_EQUAL (frc.repeat, false);
+       BOOST_CHECK_EQUAL (frc.change_speed, false);
+
+       /* Check some out-there conversions (not the best) */
        
-       dfr = DCPFrameRate (50);
-       BOOST_CHECK_EQUAL (dfr.frames_per_second, 50);
-       BOOST_CHECK_EQUAL (dfr.skip, false);
-       BOOST_CHECK_EQUAL (dfr.repeat, false);
-       BOOST_CHECK_EQUAL (dfr.change_speed, false);
-
-       dfr = DCPFrameRate (48);
-       BOOST_CHECK_EQUAL (dfr.frames_per_second, 48);
-       BOOST_CHECK_EQUAL (dfr.skip, false);
-       BOOST_CHECK_EQUAL (dfr.repeat, false);
-       BOOST_CHECK_EQUAL (dfr.change_speed, false);
+       frc = FrameRateConversion (14.99, 24);
+       BOOST_CHECK_EQUAL (frc.skip, false);
+       BOOST_CHECK_EQUAL (frc.repeat, true);
+       BOOST_CHECK_EQUAL (frc.change_speed, true);
+
+       /* Check some conversions with limited DCP targets */
+
+       afr.clear ();
+       afr.push_back (24);
+       Config::instance()->set_allowed_dcp_frame_rates (afr);
+
+       best = best_dcp_frame_rate (25);
+       frc = FrameRateConversion (25, best);
+       BOOST_CHECK_EQUAL (best, 24);
+       BOOST_CHECK_EQUAL (frc.skip, false);
+       BOOST_CHECK_EQUAL (frc.repeat, false);
+       BOOST_CHECK_EQUAL (frc.change_speed, true);
 }
 
 BOOST_AUTO_TEST_CASE (audio_sampling_rate_test)
 {
+       std::list<int> afr;
+       afr.push_back (24);
+       afr.push_back (25);
+       afr.push_back (30);
+       Config::instance()->set_allowed_dcp_frame_rates (afr);
+
        shared_ptr<Film> f = new_test_film ("audio_sampling_rate_test");
-       f->set_frames_per_second (24);
+       f->set_source_frame_rate (24);
+       f->set_dcp_frame_rate (24);
 
        f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
        BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 48000);
@@ -640,20 +660,43 @@ BOOST_AUTO_TEST_CASE (audio_sampling_rate_test)
        f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 80000, 0)));
        BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 96000);
 
-       f->set_frames_per_second (23.976);
+       f->set_source_frame_rate (23.976);
+       f->set_dcp_frame_rate (best_dcp_frame_rate (23.976));
        f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
        BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 47952);
 
-       f->set_frames_per_second (29.97);
+       f->set_source_frame_rate (29.97);
+       f->set_dcp_frame_rate (best_dcp_frame_rate (29.97));
+       BOOST_CHECK_EQUAL (f->dcp_frame_rate (), 30);
        f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
        BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 47952);
+
+       f->set_source_frame_rate (25);
+       f->set_dcp_frame_rate (24);
+       f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
+       BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 50000);
+
+       f->set_source_frame_rate (25);
+       f->set_dcp_frame_rate (24);
+       f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 44100, 0)));
+       BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 50000);
+
+       /* Check some out-there conversions (not the best) */
+       
+       f->set_source_frame_rate (14.99);
+       f->set_dcp_frame_rate (25);
+       f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 16000, 0)));
+       /* The FrameRateConversion within target_audio_sample_rate should choose to double-up
+          the 14.99 fps video to 30 and then run it slow at 25.
+       */
+       BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), rint (48000 * 2 * 14.99 / 25));
 }
 
 class TestJob : public Job
 {
 public:
-       TestJob (shared_ptr<Film> f, shared_ptr<Job> req)
-               : Job (f, req)
+       TestJob (shared_ptr<Film> f)
+               : Job (f)
        {
 
        }
@@ -684,8 +727,8 @@ BOOST_AUTO_TEST_CASE (job_manager_test)
 {
        shared_ptr<Film> f;
 
-       /* Single job, no dependency */
-       shared_ptr<TestJob> a (new TestJob (f, shared_ptr<Job> ()));
+       /* Single job */
+       shared_ptr<TestJob> a (new TestJob (f));
 
        JobManager::instance()->add (a);
        dvdomatic_sleep (1);
@@ -693,37 +736,6 @@ BOOST_AUTO_TEST_CASE (job_manager_test)
        a->set_finished_ok ();
        dvdomatic_sleep (2);
        BOOST_CHECK_EQUAL (a->finished_ok(), true);
-
-       /* Two jobs, dependency */
-       a.reset (new TestJob (f, shared_ptr<Job> ()));
-       shared_ptr<TestJob> b (new TestJob (f, a));
-
-       JobManager::instance()->add (a);
-       JobManager::instance()->add (b);
-       dvdomatic_sleep (2);
-       BOOST_CHECK_EQUAL (a->running(), true);
-       BOOST_CHECK_EQUAL (b->running(), false);
-       a->set_finished_ok ();
-       dvdomatic_sleep (2);
-       BOOST_CHECK_EQUAL (a->finished_ok(), true);
-       BOOST_CHECK_EQUAL (b->running(), true);
-       b->set_finished_ok ();
-       dvdomatic_sleep (2);
-       BOOST_CHECK_EQUAL (b->finished_ok(), true);
-
-       /* Two jobs, dependency, first fails */
-       a.reset (new TestJob (f, shared_ptr<Job> ()));
-       b.reset (new TestJob (f, a));
-
-       JobManager::instance()->add (a);
-       JobManager::instance()->add (b);
-       dvdomatic_sleep (2);
-       BOOST_CHECK_EQUAL (a->running(), true);
-       BOOST_CHECK_EQUAL (b->running(), false);
-       a->set_finished_error ();
-       dvdomatic_sleep (2);
-       BOOST_CHECK_EQUAL (a->finished_in_error(), true);
-       BOOST_CHECK_EQUAL (b->running(), false);
 }
 
 BOOST_AUTO_TEST_CASE (compact_image_test)