X-Git-Url: https://git.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=test%2Fvideo_level_test.cc;h=fd221468499728646f6cafc6d4ebf8f2e0bc536e;hp=88fb2390cfc38810951ee86fc34f99820bff822a;hb=6d686ea45f5cd01a0d11f92a903ac77779ad8562;hpb=41262015eb2bb1fc3da8585883420975de381a65 diff --git a/test/video_level_test.cc b/test/video_level_test.cc index 88fb2390c..fd2214684 100644 --- a/test/video_level_test.cc +++ b/test/video_level_test.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Carl Hetherington + Copyright (C) 2020-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -28,6 +28,7 @@ #include "lib/content_factory.h" #include "lib/content_video.h" #include "lib/dcp_content.h" +#include "lib/decoder_factory.h" #include "lib/film.h" #include "lib/ffmpeg_content.h" #include "lib/ffmpeg_decoder.h" @@ -37,6 +38,8 @@ #include "lib/image_decoder.h" #include "lib/ffmpeg_encoder.h" #include "lib/job_manager.h" +#include "lib/player.h" +#include "lib/player_video.h" #include "lib/transcode_job.h" #include "lib/video_decoder.h" #include "test.h" @@ -51,7 +54,6 @@ using std::min; -using std::make_pair; using std::max; using std::pair; using std::string; @@ -68,7 +70,7 @@ static shared_ptr grey_image (dcp::Size size, uint8_t pixel) { - auto grey = make_shared(AV_PIX_FMT_RGB24, size, true); + auto grey = make_shared(AV_PIX_FMT_RGB24, size, Image::Alignment::PADDED); for (int y = 0; y < size.height; ++y) { uint8_t* p = grey->data()[0] + y * grey->stride()[0]; for (int x = 0; x < size.width; ++x) { @@ -90,8 +92,8 @@ BOOST_AUTO_TEST_CASE (ffmpeg_image_full_range_not_changed) write_image (grey_image(size, grey_pixel), file); - FFmpegImageProxy proxy (file, VideoRange::FULL); - ImageProxy::Result result = proxy.image (); + FFmpegImageProxy proxy (file); + ImageProxy::Result result = proxy.image (Image::Alignment::COMPACT); BOOST_REQUIRE (!result.error); for (int y = 0; y < size.height; ++y) { @@ -105,19 +107,30 @@ BOOST_AUTO_TEST_CASE (ffmpeg_image_full_range_not_changed) BOOST_AUTO_TEST_CASE (ffmpeg_image_video_range_expanded) { - dcp::Size size(640, 480); + dcp::Size size(1998, 1080); uint8_t const grey_pixel = 128; - uint8_t const expanded_grey_pixel = static_cast((grey_pixel - 16) * 256.0 / 219); + uint8_t const expanded_grey_pixel = static_cast(lrintf((grey_pixel - 16) * 256.0 / 219)); boost::filesystem::path const file = "build/test/ffmpeg_image_video_range_expanded.png"; - write_image (grey_image(size, grey_pixel), file); + write_image(grey_image(size, grey_pixel), file); - FFmpegImageProxy proxy (file, VideoRange::VIDEO); - ImageProxy::Result result = proxy.image (); - BOOST_REQUIRE (!result.error); + auto content = content_factory(file).front(); + auto film = new_test_film2 ("ffmpeg_image_video_range_expanded", { content }); + content->video->set_range (VideoRange::VIDEO); + auto player = make_shared(film, film->playlist()); + + shared_ptr player_video; + player->Video.connect([&player_video](shared_ptr pv, dcpomatic::DCPTime) { + player_video = pv; + }); + while (!player_video) { + BOOST_REQUIRE (!player->pass()); + } + + auto image = player_video->image ([](AVPixelFormat f) { return f; }, VideoRange::FULL, false); for (int y = 0; y < size.height; ++y) { - uint8_t* p = result.image->data()[0] + y * result.image->stride()[0]; + uint8_t* p = image->data()[0] + y * image->stride()[0]; for (int x = 0; x < size.width; ++x) { BOOST_REQUIRE_EQUAL (*p++, expanded_grey_pixel); } @@ -125,17 +138,6 @@ BOOST_AUTO_TEST_CASE (ffmpeg_image_video_range_expanded) } -static optional content_video; - - -static -void -video_handler (ContentVideo cv) -{ - content_video = cv; -} - - static pair pixel_range (shared_ptr image) @@ -195,33 +197,23 @@ pixel_range (shared_ptr image) } +/** @return pixel range of the first frame in @ref content in its raw form, i.e. + * straight out of the decoder with no level processing, scaling etc. + */ static pair -pixel_range (shared_ptr film, shared_ptr content) -{ - shared_ptr decoder(new FFmpegDecoder(film, content, false)); - decoder->video->Data.connect (bind(&video_handler, _1)); - content_video = boost::none; - while (!content_video) { - BOOST_REQUIRE (!decoder->pass()); - } - - return pixel_range (content_video->image->image().image); -} - - -static -pair -pixel_range (shared_ptr film, shared_ptr content) +pixel_range (shared_ptr film, shared_ptr content) { - shared_ptr decoder(new ImageDecoder(film, content)); - decoder->video->Data.connect (bind(&video_handler, _1)); - content_video = boost::none; + auto decoder = decoder_factory(film, content, false, false, shared_ptr()); + optional content_video; + decoder->video->Data.connect ([&content_video](ContentVideo cv) { + content_video = cv; + }); while (!content_video) { BOOST_REQUIRE (!decoder->pass()); } - return pixel_range (content_video->image->image().image); + return pixel_range (content_video->image->image(Image::Alignment::COMPACT).image); } @@ -232,9 +224,9 @@ pixel_range (boost::filesystem::path dcp_path) dcp::DCP dcp (dcp_path); dcp.read (); - shared_ptr picture = dynamic_pointer_cast(dcp.cpls().front()->reels().front()->main_picture()->asset()); + auto picture = dynamic_pointer_cast(dcp.cpls().front()->reels().front()->main_picture()->asset()); BOOST_REQUIRE (picture); - shared_ptr frame = picture->start_read()->get_frame(0)->xyz_image(); + auto frame = picture->start_read()->get_frame(0)->xyz_image(); int const width = frame->size().width; int const height = frame->size().height; @@ -267,13 +259,13 @@ static shared_ptr movie_V (string name) { - shared_ptr film = new_test_film2 (name); - shared_ptr content = dynamic_pointer_cast(content_factory("test/data/rgb_grey_testcard.mp4").front()); + auto film = new_test_film2 (name); + auto content = dynamic_pointer_cast(content_factory("test/data/rgb_grey_testcard.mp4").front()); BOOST_REQUIRE (content); film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs()); - pair range = pixel_range (film, content); + auto range = pixel_range (film, content); BOOST_CHECK_EQUAL (range.first, 15); BOOST_CHECK_EQUAL (range.second, 243); @@ -285,14 +277,14 @@ static shared_ptr movie_VoF (string name) { - shared_ptr film = new_test_film2 (name); - shared_ptr content = dynamic_pointer_cast(content_factory("test/data/rgb_grey_testcard.mp4").front()); + auto film = new_test_film2 (name); + auto content = dynamic_pointer_cast(content_factory("test/data/rgb_grey_testcard.mp4").front()); BOOST_REQUIRE (content); film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs()); content->video->set_range (VideoRange::FULL); - pair range = pixel_range (film, content); + auto range = pixel_range (film, content); BOOST_CHECK_EQUAL (range.first, 15); BOOST_CHECK_EQUAL (range.second, 243); @@ -304,13 +296,13 @@ static shared_ptr movie_F (string name) { - shared_ptr film = new_test_film2 (name); - shared_ptr content = dynamic_pointer_cast(content_factory("test/data/rgb_grey_testcard.mov").front()); + auto film = new_test_film2 (name); + auto content = dynamic_pointer_cast(content_factory("test/data/rgb_grey_testcard.mov").front()); BOOST_REQUIRE (content); film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs()); - pair range = pixel_range (film, content); + auto range = pixel_range (film, content); BOOST_CHECK_EQUAL (range.first, 0); BOOST_CHECK_EQUAL (range.second, 1023); @@ -322,14 +314,14 @@ static shared_ptr movie_FoV (string name) { - shared_ptr film = new_test_film2 (name); - shared_ptr content = dynamic_pointer_cast(content_factory("test/data/rgb_grey_testcard.mov").front()); + auto film = new_test_film2 (name); + auto content = dynamic_pointer_cast(content_factory("test/data/rgb_grey_testcard.mov").front()); BOOST_REQUIRE (content); film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs()); content->video->set_range (VideoRange::VIDEO); - pair range = pixel_range (film, content); + auto range = pixel_range (film, content); BOOST_CHECK_EQUAL (range.first, 0); BOOST_CHECK_EQUAL (range.second, 1023); @@ -341,13 +333,13 @@ static shared_ptr image_F (string name) { - shared_ptr film = new_test_film2 (name); - shared_ptr content = dynamic_pointer_cast(content_factory("test/data/rgb_grey_testcard.png").front()); + auto film = new_test_film2 (name); + auto content = dynamic_pointer_cast(content_factory("test/data/rgb_grey_testcard.png").front()); BOOST_REQUIRE (content); film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs()); - pair range = pixel_range (film, content); + auto range = pixel_range (film, content); BOOST_CHECK_EQUAL (range.first, 0); BOOST_CHECK_EQUAL (range.second, 255); @@ -359,16 +351,19 @@ static shared_ptr image_FoV (string name) { - shared_ptr film = new_test_film2 (name); - shared_ptr content = dynamic_pointer_cast(content_factory("test/data/rgb_grey_testcard.png").front()); + auto film = new_test_film2 (name); + auto content = dynamic_pointer_cast(content_factory("test/data/rgb_grey_testcard.png").front()); BOOST_REQUIRE (content); film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs()); content->video->set_range (VideoRange::VIDEO); - pair range = pixel_range (film, content); - BOOST_CHECK_EQUAL (range.first, 11); - BOOST_CHECK_EQUAL (range.second, 250); + auto range = pixel_range (film, content); + /* We are taking some full-range content and saying it should be read as video range, after which its + * pixels will still be full range. + */ + BOOST_CHECK_EQUAL (range.first, 0); + BOOST_CHECK_EQUAL (range.second, 255); return film; } @@ -379,12 +374,12 @@ shared_ptr dcp_F (string name) { boost::filesystem::path const dcp = "test/data/RgbGreyTestcar_TST-1_F_MOS_2K_20201115_SMPTE_OV"; - shared_ptr film = new_test_film2 (name); - shared_ptr content(new DCPContent(dcp)); - film->examine_and_add_content (shared_ptr(new DCPContent(dcp))); + auto film = new_test_film2 (name); + auto content = make_shared(dcp); + film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs()); - pair range = pixel_range (dcp); + auto range = pixel_range (dcp); BOOST_CHECK_EQUAL (range.first, 0); BOOST_CHECK_EQUAL (range.second, 4081); @@ -411,11 +406,9 @@ static pair V_movie_range (shared_ptr film) { - shared_ptr job (new TranscodeJob(film)); + auto job = make_shared(film, TranscodeJob::ChangedBehaviour::IGNORE); job->set_encoder ( - shared_ptr( - new FFmpegEncoder (film, job, film->file("export.mov"), ExportFormat::PRORES, true, false, false, 23) - ) + make_shared(film, job, film->file("export.mov"), ExportFormat::PRORES_HQ, true, false, false, 23) ); JobManager::instance()->add (job); BOOST_REQUIRE (!wait_for_jobs()); @@ -434,61 +427,58 @@ V_movie_range (shared_ptr film) BOOST_AUTO_TEST_CASE (movie_V_to_dcp) { - pair range = dcp_range (movie_V("movie_V_to_dcp")); + auto range = dcp_range (movie_V("movie_V_to_dcp")); /* Video range has been correctly expanded to full for the DCP */ - BOOST_CHECK_EQUAL (range.first, 0); - BOOST_CHECK_EQUAL (range.second, 4083); + check_int_close (range, {0, 4083}, 2); } BOOST_AUTO_TEST_CASE (movie_VoF_to_dcp) { - pair range = dcp_range (movie_VoF("movie_VoF_to_dcp")); + auto range = dcp_range (movie_VoF("movie_VoF_to_dcp")); /* We said that video range data was really full range, so here we are in the DCP * with video-range data. */ - BOOST_CHECK_EQUAL (range.first, 350); - BOOST_CHECK_EQUAL (range.second, 3832); + check_int_close (range, {350, 3832}, 2); } BOOST_AUTO_TEST_CASE (movie_F_to_dcp) { - pair range = dcp_range (movie_F("movie_F_to_dcp")); + auto range = dcp_range (movie_F("movie_F_to_dcp")); /* The nearly-full-range of the input has been preserved */ - BOOST_CHECK_EQUAL (range.first, 0); - BOOST_CHECK_EQUAL (range.second, 4083); + check_int_close (range, {0, 4083}, 2); } BOOST_AUTO_TEST_CASE (video_FoV_to_dcp) { - pair range = dcp_range (movie_FoV("video_FoV_to_dcp")); + auto range = dcp_range (movie_FoV("video_FoV_to_dcp")); /* The nearly-full-range of the input has become even more full, and clipped */ - BOOST_CHECK_EQUAL (range.first, 0); - BOOST_CHECK_EQUAL (range.second, 4095); + check_int_close (range, {0, 4095}, 2); } BOOST_AUTO_TEST_CASE (image_F_to_dcp) { - pair range = dcp_range (image_F("image_F_to_dcp")); - BOOST_CHECK_EQUAL (range.first, 0); - BOOST_CHECK_EQUAL (range.second, 4083); + auto range = dcp_range (image_F("image_F_to_dcp")); + check_int_close (range, {0, 4083}, 3); } BOOST_AUTO_TEST_CASE (image_FoV_to_dcp) { - pair range = dcp_range (image_FoV("image_FoV_to_dcp")); - BOOST_CHECK_EQUAL (range.first, 430); - BOOST_CHECK_EQUAL (range.second, 4012); + auto range = dcp_range (image_FoV("image_FoV_to_dcp")); + /* The nearly-full-range of the input has become even more full, and clipped. + * XXX: I'm not sure why this doesn't quite hit 4095. + */ + check_int_close (range, {0, 4095}, 16); } BOOST_AUTO_TEST_CASE (movie_V_to_V_movie) { - pair range = V_movie_range (movie_V("movie_V_to_V_movie")); + auto range = V_movie_range (movie_V("movie_V_to_V_movie")); BOOST_CHECK_EQUAL (range.first, 60); BOOST_CHECK_EQUAL (range.second, 998); } @@ -496,7 +486,7 @@ BOOST_AUTO_TEST_CASE (movie_V_to_V_movie) BOOST_AUTO_TEST_CASE (movie_VoF_to_V_movie) { - pair range = V_movie_range (movie_VoF("movie_VoF_to_V_movie")); + auto range = V_movie_range (movie_VoF("movie_VoF_to_V_movie")); BOOST_CHECK_EQUAL (range.first, 116); BOOST_CHECK_EQUAL (range.second, 939); } @@ -504,7 +494,7 @@ BOOST_AUTO_TEST_CASE (movie_VoF_to_V_movie) BOOST_AUTO_TEST_CASE (movie_F_to_V_movie) { - pair range = V_movie_range (movie_F("movie_F_to_V_movie")); + auto range = V_movie_range (movie_F("movie_F_to_V_movie")); BOOST_CHECK_EQUAL (range.first, 4); BOOST_CHECK_EQUAL (range.second, 1019); } @@ -512,7 +502,7 @@ BOOST_AUTO_TEST_CASE (movie_F_to_V_movie) BOOST_AUTO_TEST_CASE (movie_FoV_to_V_movie) { - pair range = V_movie_range (movie_FoV("movie_FoV_to_V_movie")); + auto range = V_movie_range (movie_FoV("movie_FoV_to_V_movie")); BOOST_CHECK_EQUAL (range.first, 4); BOOST_CHECK_EQUAL (range.second, 1019); } @@ -520,7 +510,7 @@ BOOST_AUTO_TEST_CASE (movie_FoV_to_V_movie) BOOST_AUTO_TEST_CASE (image_F_to_V_movie) { - pair range = V_movie_range (image_F("image_F_to_V_movie")); + auto range = V_movie_range (image_F("image_F_to_V_movie")); BOOST_CHECK_EQUAL (range.first, 64); BOOST_CHECK_EQUAL (range.second, 960); } @@ -528,15 +518,15 @@ BOOST_AUTO_TEST_CASE (image_F_to_V_movie) BOOST_AUTO_TEST_CASE (image_FoV_to_V_movie) { - pair range = V_movie_range (image_FoV("image_FoV_to_V_movie")); - BOOST_CHECK_EQUAL (range.first, 102); - BOOST_CHECK_EQUAL (range.second, 923); + auto range = V_movie_range (image_FoV("image_FoV_to_V_movie")); + BOOST_CHECK_EQUAL (range.first, 64); + BOOST_CHECK_EQUAL (range.second, 960); } BOOST_AUTO_TEST_CASE (dcp_F_to_V_movie) { - pair range = V_movie_range (dcp_F("dcp_F_to_V_movie")); + auto range = V_movie_range (dcp_F("dcp_F_to_V_movie")); BOOST_CHECK_EQUAL (range.first, 64); BOOST_CHECK_EQUAL (range.second, 944); }