From dcd9afacd67975a9e20a6d1c4b3998c2890f1c16 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 9 Sep 2021 01:03:15 +0200 Subject: Add new GLError constructor. --- src/lib/exceptions.cc | 7 +++++++ src/lib/exceptions.h | 1 + 2 files changed, 8 insertions(+) (limited to 'src/lib') diff --git a/src/lib/exceptions.cc b/src/lib/exceptions.cc index ebb607b94..3f87a2ebe 100644 --- a/src/lib/exceptions.cc +++ b/src/lib/exceptions.cc @@ -132,6 +132,13 @@ GLError::GLError (char const* last, int e) } +GLError::GLError (char const* message) + : runtime_error (message) +{ + +} + + CopyError::CopyError (string m, optional n) : runtime_error (String::compose("%1%2", m, n ? String::compose(" (%1)", *n) : "")) , _message (m) diff --git a/src/lib/exceptions.h b/src/lib/exceptions.h index d0ba1f068..9b7837a46 100644 --- a/src/lib/exceptions.h +++ b/src/lib/exceptions.h @@ -378,6 +378,7 @@ class GLError : public std::runtime_error { public: GLError (char const* last, int e); + GLError (char const* message); }; -- cgit v1.2.3 From 7245e46453a82886739a45bd78fcdf9e8401367c Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 11 Sep 2021 18:52:05 +0200 Subject: When the player is used in OpenGL mode, pass unscaled XYZ data through to the shader and do colourspace conversion there. --- src/lib/butler.cc | 2 +- src/lib/butler.h | 11 ++++++ src/lib/j2k_image_proxy.cc | 2 +- src/lib/player_video.cc | 12 +++++-- src/lib/player_video.h | 3 +- src/tools/dcpomatic_player.cc | 1 + src/wx/film_viewer.cc | 13 +++++++ src/wx/film_viewer.h | 6 ++++ src/wx/gl_video_view.cc | 80 +++++++++++++++++++++++++++++++++---------- src/wx/gl_video_view.h | 4 +-- src/wx/video_view.h | 6 ++++ 11 files changed, 114 insertions(+), 26 deletions(-) (limited to 'src/lib') diff --git a/src/lib/butler.cc b/src/lib/butler.cc index 5a8e646aa..cbd5ba15d 100644 --- a/src/lib/butler.cc +++ b/src/lib/butler.cc @@ -323,7 +323,7 @@ try /* If the weak_ptr cannot be locked the video obviously no longer requires any work */ if (video) { LOG_TIMING("start-prepare in %1", thread_id()); - video->prepare (_pixel_format, _video_range, _aligned, _fast); + video->prepare (_pixel_format, _video_range, _aligned, _fast, _prepare_only_proxy); LOG_TIMING("finish-prepare in %1", thread_id()); } } diff --git a/src/lib/butler.h b/src/lib/butler.h index a231fd099..d31442f6c 100644 --- a/src/lib/butler.h +++ b/src/lib/butler.h @@ -80,6 +80,9 @@ public: boost::optional get_closed_caption (); void disable_audio (); + void set_prepare_only_proxy (bool p) { + _prepare_only_proxy = p; + } std::pair memory_used () const; @@ -127,6 +130,14 @@ private: bool _aligned; bool _fast; + /** true to ask PlayerVideo::prepare to only prepare the ImageProxy and not also + * the final image. We want to do this when the viewer is intending to call + * PlayerVideo::raw_image() and do the things in PlayerVideo::make_imgae() itself: + * this is the case for the GLVideoView which can do scale, pixfmt conversion etc. + * in the shader. + */ + bool _prepare_only_proxy = false; + /** If we are waiting to be refilled following a seek, this is the time we were seeking to. */ diff --git a/src/lib/j2k_image_proxy.cc b/src/lib/j2k_image_proxy.cc index 144da396d..c98273ad2 100644 --- a/src/lib/j2k_image_proxy.cc +++ b/src/lib/j2k_image_proxy.cc @@ -145,7 +145,7 @@ J2KImageProxy::prepare (optional target_size) const try { /* XXX: should check that potentially trashing _data here doesn't matter */ auto decompressed = dcp::decompress_j2k (const_cast(_data->data()), _data->size(), reduce); - _image.reset (new Image (_pixel_format, decompressed->size(), true)); + _image.reset (new Image (_pixel_format, decompressed->size(), false)); int const shift = 16 - decompressed->precision (0); diff --git a/src/lib/player_video.cc b/src/lib/player_video.cc index b0e75972c..0a6ce0d99 100644 --- a/src/lib/player_video.cc +++ b/src/lib/player_video.cc @@ -121,6 +121,14 @@ PlayerVideo::image (function pixel_format, VideoR return _image; } + +shared_ptr +PlayerVideo::raw_image () const +{ + return _in->image(_inter_size).image; +} + + /** Create an image for this frame. A lock must be held on _mutex. * @param pixel_format Function which is called to decide what pixel format the output image should be; * it is passed the pixel format of the input image from the ImageProxy, and should return the desired @@ -290,11 +298,11 @@ PlayerVideo::keep_xyz_or_rgb (AVPixelFormat p) } void -PlayerVideo::prepare (function pixel_format, VideoRange video_range, bool aligned, bool fast) +PlayerVideo::prepare (function pixel_format, VideoRange video_range, bool aligned, bool fast, bool proxy_only) { _in->prepare (_inter_size); boost::mutex::scoped_lock lm (_mutex); - if (!_image) { + if (!_image && !proxy_only) { make_image (pixel_format, video_range, aligned, fast); } } diff --git a/src/lib/player_video.h b/src/lib/player_video.h index f29684832..8134c8d4e 100644 --- a/src/lib/player_video.h +++ b/src/lib/player_video.h @@ -71,8 +71,9 @@ public: void set_text (PositionImage); - void prepare (std::function pixel_format, VideoRange video_range, bool aligned, bool fast); + void prepare (std::function pixel_format, VideoRange video_range, bool aligned, bool fast, bool proxy_only); std::shared_ptr image (std::function pixel_format, VideoRange video_range, bool aligned, bool fast) const; + std::shared_ptr raw_image () const; static AVPixelFormat force (AVPixelFormat, AVPixelFormat); static AVPixelFormat keep_xyz_or_rgb (AVPixelFormat); diff --git a/src/tools/dcpomatic_player.cc b/src/tools/dcpomatic_player.cc index 23aabadd8..e409b9731 100644 --- a/src/tools/dcpomatic_player.cc +++ b/src/tools/dcpomatic_player.cc @@ -197,6 +197,7 @@ public: _controls = new StandardControls (_overall_panel, _viewer, false); } _viewer->set_dcp_decode_reduction (Config::instance()->decode_reduction ()); + _viewer->set_optimise_for_j2k (true); _viewer->PlaybackPermitted.connect (bind(&DOMFrame::playback_permitted, this)); _viewer->Started.connect (bind(&DOMFrame::playback_started, this, _1)); _viewer->Stopped.connect (bind(&DOMFrame::playback_stopped, this, _1)); diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 77c2e85d6..749e4ceb7 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -229,6 +229,10 @@ FilmViewer::recreate_butler () _butler->disable_audio (); } + if (dynamic_pointer_cast(_video_view) && _optimise_for_j2k) { + _butler->set_prepare_only_proxy (true); + } + _closed_captions_dialog->set_butler (_butler); resume (); @@ -772,3 +776,12 @@ FilmViewer::image_changed (shared_ptr pv) { emit (boost::bind(boost::ref(ImageChanged), pv)); } + + +void +FilmViewer::set_optimise_for_j2k (bool o) +{ + _optimise_for_j2k = o; + _video_view->set_optimise_for_j2k (o); +} + diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index c467eedc1..5e5bb7916 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -98,6 +98,7 @@ public: void set_outline_subtitles (boost::optional>); void set_eyes (Eyes e); void set_pad_black (bool p); + void set_optimise_for_j2k (bool o); void slow_refresh (); @@ -187,6 +188,11 @@ private: boost::optional _dcp_decode_reduction; + /** true to assume that this viewer is only being used for JPEG2000 sources + * so it can optimise accordingly. + */ + bool _optimise_for_j2k = false; + ClosedCaptionsDialog* _closed_captions_dialog = nullptr; bool _outline_content = false; diff --git a/src/wx/gl_video_view.cc b/src/wx/gl_video_view.cc index 7c26ae616..8fcdc3c0b 100644 --- a/src/wx/gl_video_view.cc +++ b/src/wx/gl_video_view.cc @@ -189,12 +189,22 @@ static constexpr char fragment_source[] = "in vec2 TexCoord;\n" "\n" "uniform sampler2D texture_sampler;\n" -"uniform int draw_border;\n" +/* type = 0: draw border + * type = 1: draw XYZ image + * type = 2: draw RGB image + */ +"uniform int type = 0;\n" "uniform vec4 border_colour;\n" +"uniform mat4 colour_conversion;\n" "\n" "out vec4 FragColor;\n" "\n" "vec4 cubic(float x)\n" +"\n" +"#define IN_GAMMA 2.2\n" +"#define OUT_GAMMA 0.384615385\n" // 1 / 2.6 +"#define DCI_COEFFICIENT 0.91655528\n" // 48 / 53.37 +"\n" "{\n" " float x2 = x * x;\n" " float x3 = x2 * x;\n" @@ -241,10 +251,23 @@ static constexpr char fragment_source[] = "\n" "void main()\n" "{\n" -" if (draw_border == 1) {\n" -" FragColor = border_colour;\n" -" } else {\n" -" FragColor = texture_bicubic(texture_sampler, TexCoord);\n" +" switch (type) {\n" +" case 0:\n" +" FragColor = border_colour;\n" +" break;\n" +" case 1:\n" +" FragColor = texture_bicubic(texture_sampler, TexCoord);\n" +" FragColor.x = pow(FragColor.x, IN_GAMMA) / DCI_COEFFICIENT;\n" +" FragColor.y = pow(FragColor.y, IN_GAMMA) / DCI_COEFFICIENT;\n" +" FragColor.z = pow(FragColor.z, IN_GAMMA) / DCI_COEFFICIENT;\n" +" FragColor = colour_conversion * FragColor;\n" +" FragColor.x = pow(FragColor.x, OUT_GAMMA);\n" +" FragColor.y = pow(FragColor.y, OUT_GAMMA);\n" +" FragColor.z = pow(FragColor.z, OUT_GAMMA);\n" +" break;\n" +" case 2:\n" +" FragColor = texture_bicubic(texture_sampler, TexCoord);\n" +" break;\n" " }\n" "}\n"; @@ -383,10 +406,23 @@ GLVideoView::setup_shaders () glUseProgram (program); - _draw_border = glGetUniformLocation (program, "draw_border"); + _fragment_type = glGetUniformLocation (program, "type"); check_gl_error ("glGetUniformLocation"); set_border_colour (program); + auto conversion = dcp::ColourConversion::rec709_to_xyz(); + boost::numeric::ublas::matrix matrix = conversion.xyz_to_rgb (); + GLfloat gl_matrix[] = { + static_cast(matrix(0, 0)), static_cast(matrix(0, 1)), static_cast(matrix(0, 2)), 0.0f, + static_cast(matrix(1, 0)), static_cast(matrix(1, 1)), static_cast(matrix(1, 2)), 0.0f, + static_cast(matrix(2, 0)), static_cast(matrix(2, 1)), static_cast(matrix(2, 2)), 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + + auto colour_conversion = glGetUniformLocation (program, "colour_conversion"); + check_gl_error ("glGetUniformLocation"); + glUniformMatrix4fv (colour_conversion, 1, GL_TRUE, gl_matrix); + glLineWidth (2.0f); } @@ -424,10 +460,10 @@ GLVideoView::draw (Position, dcp::Size) glBindTexture(GL_TEXTURE_2D, _texture); glBindVertexArray(_vao); check_gl_error ("glBindVertexArray"); - glUniform1i(_draw_border, 0); + glUniform1i(_fragment_type, _optimise_for_j2k ? 1 : 2); glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); if (_viewer->outline_content()) { - glUniform1i(_draw_border, 1); + glUniform1i(_fragment_type, 1); glDrawElements (GL_LINES, 8, GL_UNSIGNED_INT, reinterpret_cast(6 * sizeof(int))); check_gl_error ("glDrawElements"); } @@ -440,30 +476,35 @@ GLVideoView::draw (Position, dcp::Size) void -GLVideoView::set_image (shared_ptr image) +GLVideoView::set_image (shared_ptr pv) { - if (!image) { - _size = optional(); - return; - } - + auto image = _optimise_for_j2k ? pv->raw_image() : pv->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true); - DCPOMATIC_ASSERT (image->pixel_format() == AV_PIX_FMT_RGB24); DCPOMATIC_ASSERT (!image->aligned()); + /** If _optimise_for_j2k is true we render a XYZ image, doing the colourspace + * conversion, scaling and video range conversion in the GL shader. + * Othewise we render a RGB image without any shader-side processing. + */ + + /* XXX: video range conversion */ + /* XXX: subs */ + if (image->size() != _size) { _have_storage = false; } _size = image->size (); - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + glPixelStorei (GL_UNPACK_ALIGNMENT, _optimise_for_j2k ? 2 : 1); check_gl_error ("glPixelStorei"); + auto const format = _optimise_for_j2k ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE; + if (_have_storage) { - glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, _size->width, _size->height, GL_RGB, GL_UNSIGNED_BYTE, image->data()[0]); + glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, _size->width, _size->height, GL_RGB, format, image->data()[0]); check_gl_error ("glTexSubImage2D"); } else { - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, _size->width, _size->height, 0, GL_RGB, GL_UNSIGNED_BYTE, image->data()[0]); + glTexImage2D (GL_TEXTURE_2D, 0, _optimise_for_j2k ? GL_RGBA12 : GL_RGBA8, _size->width, _size->height, 0, GL_RGB, format, image->data()[0]); check_gl_error ("glTexImage2D"); auto const canvas_size = _canvas_size.load(); @@ -517,6 +558,7 @@ GLVideoView::set_image (shared_ptr image) check_gl_error ("glTexParameterf"); } + void GLVideoView::start () { @@ -566,7 +608,7 @@ GLVideoView::set_image_and_draw () { auto pv = player_video().first; if (pv) { - set_image (pv->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true)); + set_image (pv); draw (pv->inter_position(), pv->inter_size()); _viewer->image_changed (pv); } diff --git a/src/wx/gl_video_view.h b/src/wx/gl_video_view.h index bac195fb1..4bab64348 100644 --- a/src/wx/gl_video_view.h +++ b/src/wx/gl_video_view.h @@ -58,7 +58,7 @@ public: } private: - void set_image (std::shared_ptr image); + void set_image (std::shared_ptr pv); void set_image_and_draw (); void draw (Position inter_position, dcp::Size inter_size); void thread (); @@ -86,7 +86,7 @@ private: boost::atomic _one_shot; GLuint _vao; - GLint _draw_border; + GLint _fragment_type; bool _setup_shaders_done = false; std::shared_ptr _timer; diff --git a/src/wx/video_view.h b/src/wx/video_view.h index 9517a3bf4..5353f213f 100644 --- a/src/wx/video_view.h +++ b/src/wx/video_view.h @@ -127,6 +127,10 @@ public: _three_d = t; } + void set_optimise_for_j2k (bool o) { + _optimise_for_j2k = o; + } + protected: NextFrameResult get_next_frame (bool non_blocking); boost::optional time_until_next_frame () const; @@ -168,6 +172,8 @@ protected: StateTimer _state_timer; + bool _optimise_for_j2k = false; + private: /** Mutex protecting all the state in this class */ mutable boost::mutex _mutex; -- cgit v1.2.3 From 6cac49dc50dae6b173135df101d532f20031ca70 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 14 Sep 2021 01:36:38 +0200 Subject: Setup Butler::_prepare_only_proxy on construction. --- src/lib/butler.cc | 4 +++- src/lib/butler.h | 6 ++---- src/lib/ffmpeg_encoder.cc | 2 +- src/wx/film_viewer.cc | 7 ++----- test/butler_test.cc | 2 +- test/dcp_playback_test.cc | 3 ++- test/player_test.cc | 6 +++--- 7 files changed, 14 insertions(+), 16 deletions(-) (limited to 'src/lib') diff --git a/src/lib/butler.cc b/src/lib/butler.cc index cbd5ba15d..ca0887a4c 100644 --- a/src/lib/butler.cc +++ b/src/lib/butler.cc @@ -68,7 +68,8 @@ Butler::Butler ( function pixel_format, VideoRange video_range, bool aligned, - bool fast + bool fast, + bool prepare_only_proxy ) : _film (film) , _player (player) @@ -85,6 +86,7 @@ Butler::Butler ( , _video_range (video_range) , _aligned (aligned) , _fast (fast) + , _prepare_only_proxy (prepare_only_proxy) { _player_video_connection = _player->Video.connect (bind (&Butler::video, this, _1, _2)); _player_audio_connection = _player->Audio.connect (bind (&Butler::audio, this, _1, _2, _3)); diff --git a/src/lib/butler.h b/src/lib/butler.h index d31442f6c..320e56bf9 100644 --- a/src/lib/butler.h +++ b/src/lib/butler.h @@ -46,7 +46,8 @@ public: std::function pixel_format, VideoRange video_range, bool aligned, - bool fast + bool fast, + bool prepare_only_proxy ); ~Butler (); @@ -80,9 +81,6 @@ public: boost::optional get_closed_caption (); void disable_audio (); - void set_prepare_only_proxy (bool p) { - _prepare_only_proxy = p; - } std::pair memory_used () const; diff --git a/src/lib/ffmpeg_encoder.cc b/src/lib/ffmpeg_encoder.cc index 61ca1ae00..77f27d519 100644 --- a/src/lib/ffmpeg_encoder.cc +++ b/src/lib/ffmpeg_encoder.cc @@ -108,7 +108,7 @@ FFmpegEncoder::FFmpegEncoder ( } _butler = std::make_shared( - _film, _player, map, _output_audio_channels, bind(&PlayerVideo::force, _1, FFmpegFileEncoder::pixel_format(format)), VideoRange::VIDEO, true, false + _film, _player, map, _output_audio_channels, bind(&PlayerVideo::force, _1, FFmpegFileEncoder::pixel_format(format)), VideoRange::VIDEO, true, false, false ); } diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 749e4ceb7..98948b1f2 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -222,17 +222,14 @@ FilmViewer::recreate_butler () bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, - true + true, + dynamic_pointer_cast(_video_view) && _optimise_for_j2k ); if (!Config::instance()->sound() && !_audio.isStreamOpen()) { _butler->disable_audio (); } - if (dynamic_pointer_cast(_video_view) && _optimise_for_j2k) { - _butler->set_prepare_only_proxy (true); - } - _closed_captions_dialog->set_butler (_butler); resume (); diff --git a/test/butler_test.cc b/test/butler_test.cc index dbd7a287e..65c9139d7 100644 --- a/test/butler_test.cc +++ b/test/butler_test.cc @@ -59,7 +59,7 @@ BOOST_AUTO_TEST_CASE (butler_test1) map.set (i, i, 1); } - Butler butler (film, make_shared(film), map, 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, false); + Butler butler (film, make_shared(film), map, 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, false, false); BOOST_CHECK (butler.get_video(true, 0).second == DCPTime()); BOOST_CHECK (butler.get_video(true, 0).second == DCPTime::from_frames(1, 24)); diff --git a/test/dcp_playback_test.cc b/test/dcp_playback_test.cc index ef1b623e7..efe7138e1 100644 --- a/test/dcp_playback_test.cc +++ b/test/dcp_playback_test.cc @@ -53,7 +53,8 @@ BOOST_AUTO_TEST_CASE (dcp_playback_test) bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, - true + true, + false ); auto audio_buffer = new float[2000 * 6]; diff --git a/test/player_test.cc b/test/player_test.cc index c325537fa..1f5b543aa 100644 --- a/test/player_test.cc +++ b/test/player_test.cc @@ -234,7 +234,7 @@ BOOST_AUTO_TEST_CASE (player_seek_test) player->set_always_burn_open_subtitles (); player->set_play_referenced (); - auto butler = std::make_shared(film, player, AudioMapping(), 2, bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true); + auto butler = std::make_shared(film, player, AudioMapping(), 2, bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true, false); butler->disable_audio(); for (int i = 0; i < 10; ++i) { @@ -266,7 +266,7 @@ BOOST_AUTO_TEST_CASE (player_seek_test2) player->set_always_burn_open_subtitles (); player->set_play_referenced (); - auto butler = std::make_shared(film, player, AudioMapping(), 2, bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true); + auto butler = std::make_shared(film, player, AudioMapping(), 2, bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true, false); butler->disable_audio(); butler->seek(DCPTime::from_seconds(5), true); @@ -357,7 +357,7 @@ BOOST_AUTO_TEST_CASE (player_trim_crash) auto player = std::make_shared(film); player->set_fast (); - auto butler = std::make_shared(film, player, AudioMapping(), 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true); + auto butler = std::make_shared(film, player, AudioMapping(), 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true, false); /* Wait for the butler to fill */ dcpomatic_sleep_seconds (5); -- cgit v1.2.3 From 4bbcf55dc0e644c20b1eaabee2da3219c4e7635f Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 14 Sep 2021 01:36:50 +0200 Subject: Add accessor for _text. --- src/lib/player_video.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/lib') diff --git a/src/lib/player_video.h b/src/lib/player_video.h index 8134c8d4e..553d3c5bc 100644 --- a/src/lib/player_video.h +++ b/src/lib/player_video.h @@ -70,6 +70,9 @@ public: std::shared_ptr shallow_copy () const; void set_text (PositionImage); + boost::optional text () const { + return _text; + } void prepare (std::function pixel_format, VideoRange video_range, bool aligned, bool fast, bool proxy_only); std::shared_ptr image (std::function pixel_format, VideoRange video_range, bool aligned, bool fast) const; -- cgit v1.2.3 From 23aa3071850761144798112a5aaea61304de8586 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 14 Sep 2021 21:11:56 +0200 Subject: Support subs and tidy up a few things. --- src/lib/image.cc | 2 +- src/lib/player_video.h | 4 ++ src/wx/gl_video_view.cc | 166 +++++++++++++++++++++++++++++++++++------------- src/wx/gl_video_view.h | 31 ++++++++- 4 files changed, 158 insertions(+), 45 deletions(-) (limited to 'src/lib') diff --git a/src/lib/image.cc b/src/lib/image.cc index 8e6c5717b..d2f8fbbfd 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -1154,7 +1154,7 @@ merge (list images) all.extend (dcpomatic::Rect(i.position, i.image->size().width, i.image->size().height)); } - auto merged = make_shared(images.front().image->pixel_format(), dcp::Size(all.width, all.height), true); + auto merged = make_shared(images.front().image->pixel_format(), dcp::Size(all.width, all.height), false); merged->make_transparent (); for (auto const& i: images) { merged->alpha_blend (i.image, i.position - all.position()); diff --git a/src/lib/player_video.h b/src/lib/player_video.h index 553d3c5bc..347d10667 100644 --- a/src/lib/player_video.h +++ b/src/lib/player_video.h @@ -109,6 +109,10 @@ public: return _inter_size; } + dcp::Size out_size () const { + return _out_size; + } + bool same (std::shared_ptr other) const; size_t memory_used () const; diff --git a/src/wx/gl_video_view.cc b/src/wx/gl_video_view.cc index 239f0ece0..9f5865e35 100644 --- a/src/wx/gl_video_view.cc +++ b/src/wx/gl_video_view.cc @@ -285,16 +285,20 @@ GLVideoView::ensure_context () /* Offset of video texture triangles in indices */ static constexpr int indices_video_texture = 0; +/* Offset of subtitle texture triangles in indices */ +static constexpr int indices_subtitle_texture = 6; /* Offset of border lines in indices */ -static constexpr int indices_border = 6; +static constexpr int indices_border = 12; static constexpr unsigned int indices[] = { 0, 1, 3, // video texture triangle #1 1, 2, 3, // video texture triangle #2 - 4, 5, // border line #1 - 5, 6, // border line #2 - 6, 7, // border line #3 - 7, 4, // border line #4 + 4, 5, 7, // subtitle texture triangle #1 + 5, 6, 7, // subtitle texture triangle #2 + 8, 9, // border line #1 + 9, 10, // border line #2 + 10, 11, // border line #3 + 11, 8, // border line #4 }; @@ -428,6 +432,12 @@ GLVideoView::setup_shaders () glUniformMatrix4fv (colour_conversion, 1, GL_TRUE, gl_matrix); glLineWidth (2.0f); + glEnable (GL_BLEND); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + /* Reserve space for the GL_ARRAY_BUFFER */ + glBufferData(GL_ARRAY_BUFFER, 12 * 5 * sizeof(float), nullptr, GL_STATIC_DRAW); + check_gl_error ("glBufferData"); } @@ -464,9 +474,15 @@ GLVideoView::draw (Position, dcp::Size) glBindVertexArray(_vao); check_gl_error ("glBindVertexArray"); glUniform1i(_fragment_type, _optimise_for_j2k ? 1 : 2); - glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_INT, reinterpret_cast(indices_video_texture)); + _video_texture->bind(); + glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_INT, reinterpret_cast(indices_video_texture * sizeof(int))); + if (_have_subtitle_to_render) { + glUniform1i(_fragment_type, 2); + _subtitle_texture->bind(); + glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_INT, reinterpret_cast(indices_subtitle_texture * sizeof(int))); + } if (_viewer->outline_content()) { - glUniform1i(_fragment_type, 1); + glUniform1i(_fragment_type, 0); glDrawElements (GL_LINES, 8, GL_UNSIGNED_INT, reinterpret_cast(indices_border * sizeof(int))); check_gl_error ("glDrawElements"); } @@ -491,51 +507,92 @@ GLVideoView::set_image (shared_ptr pv) */ /* XXX: video range conversion */ - /* XXX: subs */ - auto const changed = _video_texture->set (video); + _video_texture->set (video); - if (changed) { - auto const canvas_size = _canvas_size.load(); - int const canvas_width = canvas_size.GetWidth(); - int const canvas_height = canvas_size.GetHeight(); + auto const text = pv->text(); + _have_subtitle_to_render = static_cast(text) && _optimise_for_j2k; + if (_have_subtitle_to_render) { + /* opt: only do this if it's a new subtitle? */ + DCPOMATIC_ASSERT (!text->image->aligned()); + _subtitle_texture->set (text->image); + } - float const video_x = float(video->size().width) / canvas_width; - float const video_y = float(video->size().height) / canvas_height; - auto x_pixels_to_gl = [canvas_width](int x) { - return (x * 2.0f / canvas_width) - 1.0f; - }; + auto const canvas_size = _canvas_size.load(); + int const canvas_width = canvas_size.GetWidth(); + int const canvas_height = canvas_size.GetHeight(); + auto inter_position = player_video().first->inter_position(); + auto inter_size = player_video().first->inter_size(); + auto out_size = player_video().first->out_size(); - auto y_pixels_to_gl = [canvas_height](int y) { - return (y * 2.0f / canvas_height) - 1.0f; + _last_canvas_size.set_next (canvas_size); + _last_video_size.set_next (video->size()); + _last_inter_position.set_next (inter_position); + _last_inter_size.set_next (inter_size); + _last_out_size.set_next (out_size); + + auto x_pixels_to_gl = [canvas_width](int x) { + return (x * 2.0f / canvas_width) - 1.0f; + }; + + auto y_pixels_to_gl = [canvas_height](int y) { + return (y * 2.0f / canvas_height) - 1.0f; + }; + + if (_last_canvas_size.changed() || _last_inter_position.changed() || _last_inter_size.changed() || _last_out_size.changed()) { + float const video_x1 = x_pixels_to_gl(_optimise_for_j2k ? inter_position.x : 0); + float const video_x2 = x_pixels_to_gl(_optimise_for_j2k ? (inter_position.x + inter_size.width) : out_size.width); + float const video_y1 = y_pixels_to_gl(_optimise_for_j2k ? inter_position.y : 0); + float const video_y2 = y_pixels_to_gl(_optimise_for_j2k ? (inter_position.y + inter_size.height) : out_size.height); + float video_vertices[] = { + // positions // texture coords + video_x2, video_y2, 0.0f, 1.0f, 0.0f, // video texture top right (index 0) + video_x2, video_y1, 0.0f, 1.0f, 1.0f, // video texture bottom right (index 1) + video_x1, video_y1, 0.0f, 0.0f, 1.0f, // video texture bottom left (index 2) + video_x1, video_y2, 0.0f, 0.0f, 0.0f, // video texture top left (index 3) }; - auto inter_position = player_video().first->inter_position(); - auto inter_size = player_video().first->inter_size(); + glBufferSubData (GL_ARRAY_BUFFER, 0, sizeof(video_vertices), video_vertices); + check_gl_error ("glBufferSubData (video)"); - float const border_x1 = x_pixels_to_gl (inter_position.x) + 1.0f - video_x; - float const border_y1 = y_pixels_to_gl (inter_position.y) + 1.0f - video_y; - float const border_x2 = x_pixels_to_gl (inter_position.x + inter_size.width) + 1.0f - video_x; - float const border_y2 = y_pixels_to_gl (inter_position.y + inter_size.height) + 1.0f - video_y; + float const border_x1 = x_pixels_to_gl(inter_position.x); + float const border_y1 = y_pixels_to_gl(inter_position.y); + float const border_x2 = x_pixels_to_gl(inter_position.x + inter_size.width); + float const border_y2 = y_pixels_to_gl(inter_position.y + inter_size.height); - float vertices[] = { - // positions // texture coords - video_x, video_y, 0.0f, 1.0f, 0.0f, // video texture top right (index 0) - video_x, -video_y, 0.0f, 1.0f, 1.0f, // video texture bottom right (index 1) - -video_x, -video_y, 0.0f, 0.0f, 1.0f, // video texture bottom left (index 2) - -video_x, video_y, 0.0f, 0.0f, 0.0f, // video texture top left (index 3) + float border_vertices[] = { + // positions // texture coords border_x1, border_y1, 0.0f, 0.0f, 0.0f, // border bottom left (index 4) border_x1, border_y2, 0.0f, 0.0f, 0.0f, // border top left (index 5) border_x2, border_y2, 0.0f, 0.0f, 0.0f, // border top right (index 6) border_x2, border_y1, 0.0f, 0.0f, 0.0f, // border bottom right (index 7) }; - /* Set the vertex shader's input data (GL_ARRAY_BUFFER) */ - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - check_gl_error ("glBufferData"); + glBufferSubData (GL_ARRAY_BUFFER, 8 * 5 * sizeof(float), sizeof(border_vertices), border_vertices); + check_gl_error ("glBufferSubData (border)"); } + if (_have_subtitle_to_render) { + float const subtitle_x1 = x_pixels_to_gl(inter_position.x + text->position.x); + float const subtitle_x2 = x_pixels_to_gl(inter_position.x + text->position.x + text->image->size().width); + float const subtitle_y1 = y_pixels_to_gl(inter_position.y + text->position.y + text->image->size().height); + float const subtitle_y2 = y_pixels_to_gl(inter_position.y + text->position.y); + + float vertices[] = { + // positions // texture coords + subtitle_x2, subtitle_y1, 0.0f, 1.0f, 0.0f, // subtitle texture top right (index 4) + subtitle_x2, subtitle_y2, 0.0f, 1.0f, 1.0f, // subtitle texture bottom right (index 5) + subtitle_x1, subtitle_y2, 0.0f, 0.0f, 1.0f, // subtitle texture bottom left (index 6) + subtitle_x1, subtitle_y1, 0.0f, 0.0f, 0.0f, // subtitle texture top left (index 7) + }; + + glBufferSubData (GL_ARRAY_BUFFER, 4 * 5 * sizeof(float), sizeof(vertices), vertices); + check_gl_error ("glBufferSubData (subtitle)"); + } + + /* opt: where should these go? */ + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); check_gl_error ("glTexParameteri"); @@ -649,7 +706,7 @@ try #endif _video_texture.reset(new Texture(_optimise_for_j2k ? 2 : 1)); - _video_texture->bind(); + _subtitle_texture.reset(new Texture(1)); while (true) { boost::mutex::scoped_lock lm (_playing_mutex); @@ -719,7 +776,7 @@ Texture::bind () } -bool +void Texture::set (shared_ptr image) { auto const create = !_size || image->size() != _size; @@ -728,17 +785,40 @@ Texture::set (shared_ptr image) glPixelStorei (GL_UNPACK_ALIGNMENT, _unpack_alignment); check_gl_error ("glPixelStorei"); - auto const format = image->pixel_format() == AV_PIX_FMT_RGB24 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT; - auto const internal_format = image->pixel_format() == AV_PIX_FMT_RGB24 ? GL_RGBA8 : GL_RGBA12; + DCPOMATIC_ASSERT (!image->aligned()); + + GLint internal_format; + GLenum format; + GLenum type; + + switch (image->pixel_format()) { + case AV_PIX_FMT_BGRA: + internal_format = GL_RGBA8; + format = GL_BGRA; + type = GL_UNSIGNED_BYTE; + break; + case AV_PIX_FMT_RGBA: + internal_format = GL_RGBA8; + format = GL_RGBA; + type = GL_UNSIGNED_BYTE; + break; + case AV_PIX_FMT_XYZ12: + internal_format = GL_RGBA12; + format = GL_RGB; + type = GL_UNSIGNED_SHORT; + break; + default: + throw PixelFormatError ("Texture::set", image->pixel_format()); + } + + bind (); if (create) { - glTexImage2D (GL_TEXTURE_2D, 0, internal_format, _size->width, _size->height, 0, GL_RGB, format, image->data()[0]); + glTexImage2D (GL_TEXTURE_2D, 0, internal_format, _size->width, _size->height, 0, format, type, image->data()[0]); check_gl_error ("glTexImage2D"); } else { - glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, _size->width, _size->height, GL_RGB, format, image->data()[0]); + glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, _size->width, _size->height, format, type, image->data()[0]); check_gl_error ("glTexSubImage2D"); } - - return create; } diff --git a/src/wx/gl_video_view.h b/src/wx/gl_video_view.h index 4e61b5b4c..d7f8429af 100644 --- a/src/wx/gl_video_view.h +++ b/src/wx/gl_video_view.h @@ -45,7 +45,7 @@ public: Texture& operator= (Texture const&) = delete; void bind (); - bool set (std::shared_ptr image); + void set (std::shared_ptr image); private: GLuint _name; @@ -93,8 +93,37 @@ private: wxGLCanvas* _canvas; wxGLContext* _context; + template + class Last + { + public: + void set_next (T const& next) { + _next = next; + } + + bool changed () const { + return !_value || *_value != _next; + } + + void update () { + _value = _next; + } + + private: + boost::optional _value; + T _next; + }; + + Last _last_canvas_size; + Last _last_video_size; + Last> _last_inter_position; + Last _last_inter_size; + Last _last_out_size; + boost::atomic _canvas_size; std::unique_ptr _video_texture; + std::unique_ptr _subtitle_texture; + bool _have_subtitle_to_render = false; bool _vsync_enabled; boost::thread _thread; -- cgit v1.2.3 From c59981ce92898f6be6987f10ebb29161e36e6766 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 15 Sep 2021 00:42:15 +0200 Subject: Some const correctness. --- src/lib/bitmap_text.h | 4 ++-- src/lib/content_text.h | 2 +- src/lib/image_proxy.h | 5 ++--- src/lib/player_video.h | 2 +- src/lib/position_image.h | 4 ++-- src/lib/text_decoder.cc | 4 ++-- src/lib/text_decoder.h | 4 ++-- 7 files changed, 12 insertions(+), 13 deletions(-) (limited to 'src/lib') diff --git a/src/lib/bitmap_text.h b/src/lib/bitmap_text.h index b8861c10a..46b6fd142 100644 --- a/src/lib/bitmap_text.h +++ b/src/lib/bitmap_text.h @@ -31,12 +31,12 @@ class Image; class BitmapText { public: - BitmapText (std::shared_ptr i, dcpomatic::Rect r) + BitmapText (std::shared_ptr i, dcpomatic::Rect r) : image (i) , rectangle (r) {} - std::shared_ptr image; + std::shared_ptr image; /** Area that the subtitle covers on its corresponding video, expressed in * proportions of the image size; e.g. rectangle.x = 0.5 would mean that * the rectangle starts half-way across the video. diff --git a/src/lib/content_text.h b/src/lib/content_text.h index c6d7d6ec2..5edb9af20 100644 --- a/src/lib/content_text.h +++ b/src/lib/content_text.h @@ -48,7 +48,7 @@ private: class ContentBitmapText : public ContentText { public: - ContentBitmapText (dcpomatic::ContentTime f, std::shared_ptr im, dcpomatic::Rect r) + ContentBitmapText (dcpomatic::ContentTime f, std::shared_ptr im, dcpomatic::Rect r) : ContentText (f) , sub (im, r) {} diff --git a/src/lib/image_proxy.h b/src/lib/image_proxy.h index 22946ed98..cf1fb9a2d 100644 --- a/src/lib/image_proxy.h +++ b/src/lib/image_proxy.h @@ -64,7 +64,7 @@ public: ImageProxy& operator= (ImageProxy const&) = delete; struct Result { - Result (std::shared_ptr image_, int log2_scaling_) + Result (std::shared_ptr image_, int log2_scaling_) : image (image_) , log2_scaling (log2_scaling_) , error (false) @@ -76,8 +76,7 @@ public: , error (error_) {} - /** Image (which will be aligned) */ - std::shared_ptr image; + std::shared_ptr image; /** log2 of any scaling down that has already been applied to the image; * e.g. if the image is already half the size of the original, this value * will be 1. diff --git a/src/lib/player_video.h b/src/lib/player_video.h index 347d10667..872bc9864 100644 --- a/src/lib/player_video.h +++ b/src/lib/player_video.h @@ -76,7 +76,7 @@ public: void prepare (std::function pixel_format, VideoRange video_range, bool aligned, bool fast, bool proxy_only); std::shared_ptr image (std::function pixel_format, VideoRange video_range, bool aligned, bool fast) const; - std::shared_ptr raw_image () const; + std::shared_ptr raw_image () const; static AVPixelFormat force (AVPixelFormat, AVPixelFormat); static AVPixelFormat keep_xyz_or_rgb (AVPixelFormat); diff --git a/src/lib/position_image.h b/src/lib/position_image.h index 2b7e7080a..ee352647c 100644 --- a/src/lib/position_image.h +++ b/src/lib/position_image.h @@ -35,12 +35,12 @@ class PositionImage public: PositionImage () {} - PositionImage (std::shared_ptr i, Position p) + PositionImage (std::shared_ptr i, Position p) : image (i) , position (p) {} - std::shared_ptr image; + std::shared_ptr image; Position position; bool same (PositionImage const & other) const; diff --git a/src/lib/text_decoder.cc b/src/lib/text_decoder.cc index 6ee6ed079..8111154e3 100644 --- a/src/lib/text_decoder.cc +++ b/src/lib/text_decoder.cc @@ -61,7 +61,7 @@ TextDecoder::TextDecoder ( * of the video frame) */ void -TextDecoder::emit_bitmap_start (ContentTime from, shared_ptr image, dcpomatic::Rect rect) +TextDecoder::emit_bitmap_start (ContentTime from, shared_ptr image, dcpomatic::Rect rect) { BitmapStart (ContentBitmapText (from, image, rect)); _position = from; @@ -286,7 +286,7 @@ TextDecoder::emit_plain (ContentTimePeriod period, sub::Subtitle const & s) * of the video frame) */ void -TextDecoder::emit_bitmap (ContentTimePeriod period, shared_ptr image, dcpomatic::Rect rect) +TextDecoder::emit_bitmap (ContentTimePeriod period, shared_ptr image, dcpomatic::Rect rect) { emit_bitmap_start (period.from, image, rect); emit_stop (period.to); diff --git a/src/lib/text_decoder.h b/src/lib/text_decoder.h index 6e96b6b91..d1355afb0 100644 --- a/src/lib/text_decoder.h +++ b/src/lib/text_decoder.h @@ -52,8 +52,8 @@ public: return _position; } - void emit_bitmap_start (dcpomatic::ContentTime from, std::shared_ptr image, dcpomatic::Rect rect); - void emit_bitmap (dcpomatic::ContentTimePeriod period, std::shared_ptr image, dcpomatic::Rect rect); + void emit_bitmap_start (dcpomatic::ContentTime from, std::shared_ptr image, dcpomatic::Rect rect); + void emit_bitmap (dcpomatic::ContentTimePeriod period, std::shared_ptr image, dcpomatic::Rect rect); void emit_plain_start (dcpomatic::ContentTime from, std::list s); void emit_plain_start (dcpomatic::ContentTime from, sub::Subtitle const & subtitle); void emit_plain (dcpomatic::ContentTimePeriod period, std::list s); -- cgit v1.2.3 From 9bfa07293928c371d59db2091ba2b7e715ce5994 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 15 Sep 2021 01:00:33 +0200 Subject: Various alignment adjustments. --- src/lib/encoder.cc | 2 +- src/lib/ffmpeg_decoder.cc | 2 +- src/lib/ffmpeg_image_proxy.cc | 4 ++-- src/lib/ffmpeg_image_proxy.h | 1 + src/lib/hints.cc | 2 +- src/lib/image.cc | 16 +++++++++------- src/lib/image.h | 6 +++--- src/lib/image_examiner.cc | 2 +- src/lib/image_proxy.h | 3 ++- src/lib/j2k_image_proxy.cc | 12 ++++++------ src/lib/j2k_image_proxy.h | 3 ++- src/lib/player.cc | 5 +++-- src/lib/player.h | 5 ++++- src/lib/player_video.cc | 10 +++++----- src/lib/raw_image_proxy.cc | 7 ++++--- src/lib/raw_image_proxy.h | 1 + src/lib/util.cc | 2 +- src/lib/video_filter_graph.cc | 4 ++-- src/tools/server_test.cc | 2 +- src/wx/film_viewer.cc | 4 ++-- src/wx/gl_video_view.cc | 7 +++++-- test/butler_test.cc | 2 +- test/dcp_decoder_test.cc | 6 +++--- test/dcp_playback_test.cc | 6 ++---- test/ffmpeg_audio_only_test.cc | 2 +- test/ffmpeg_audio_test.cc | 6 +++--- test/ffmpeg_decoder_sequential_test.cc | 2 +- test/image_test.cc | 24 ++++++++++++------------ test/overlap_video_test.cc | 2 +- test/pixel_formats_test.cc | 2 +- test/player_test.cc | 14 +++++++------- test/test.cc | 4 ++-- test/time_calculation_test.cc | 10 +++++----- test/upmixer_a_test.cc | 2 +- test/vf_test.cc | 2 +- test/video_level_test.cc | 4 ++-- 36 files changed, 100 insertions(+), 88 deletions(-) (limited to 'src/lib') diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index fe27cb7dd..0b7c241d8 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -41,7 +41,7 @@ Encoder::Encoder (std::shared_ptr film, std::weak_ptr job) : _film (film) , _job (job) - , _player (new Player(film)) + , _player (new Player(film, true)) { } diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 72372fca8..70f9b0545 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -86,7 +86,7 @@ FFmpegDecoder::FFmpegDecoder (shared_ptr film, shared_ptr(this, c); _pts_offset = pts_offset (c->ffmpeg_audio_streams(), c->first_video(), c->active_video_frame_rate(film)); /* It doesn't matter what size or pixel format this is, it just needs to be black */ - _black_image.reset (new Image (AV_PIX_FMT_RGB24, dcp::Size (128, 128), true)); + _black_image = make_shared(AV_PIX_FMT_RGB24, dcp::Size (128, 128), true); _black_image->make_black (); } else { _pts_offset = {}; diff --git a/src/lib/ffmpeg_image_proxy.cc b/src/lib/ffmpeg_image_proxy.cc index e7d5b424d..dd2f80e0e 100644 --- a/src/lib/ffmpeg_image_proxy.cc +++ b/src/lib/ffmpeg_image_proxy.cc @@ -122,7 +122,7 @@ FFmpegImageProxy::avio_seek (int64_t const pos, int whence) ImageProxy::Result -FFmpegImageProxy::image (optional) const +FFmpegImageProxy::image (bool aligned, optional) const { auto constexpr name_for_errors = "FFmpegImageProxy::image"; @@ -205,7 +205,7 @@ FFmpegImageProxy::image (optional) const throw DecodeError (N_("avcodec_receive_frame"), name_for_errors, r, *_path); } - _image = make_shared(frame); + _image = make_shared(frame, aligned); av_packet_unref (&packet); av_frame_free (&frame); diff --git a/src/lib/ffmpeg_image_proxy.h b/src/lib/ffmpeg_image_proxy.h index 21109c9d6..f4e5bf66c 100644 --- a/src/lib/ffmpeg_image_proxy.h +++ b/src/lib/ffmpeg_image_proxy.h @@ -32,6 +32,7 @@ public: FFmpegImageProxy (std::shared_ptr socket); Result image ( + bool aligned, boost::optional size = boost::optional () ) const; diff --git a/src/lib/hints.cc b/src/lib/hints.cc index 64122db8d..f21c51db9 100644 --- a/src/lib/hints.cc +++ b/src/lib/hints.cc @@ -408,7 +408,7 @@ try emit (bind(boost::ref(Progress), _("Examining audio, subtitles and closed captions"))); } - auto player = make_shared(film); + auto player = make_shared(film, false); player->set_ignore_video (); if (check_loudness_done) { /* We don't need to analyse audio because we already loaded a suitable analysis */ diff --git a/src/lib/image.cc b/src/lib/image.cc index d2f8fbbfd..ce3f5817d 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -1027,10 +1027,10 @@ Image::Image (Image const & other) } } -Image::Image (AVFrame const * frame) +Image::Image (AVFrame const * frame, bool aligned) : _size (frame->width, frame->height) , _pixel_format (static_cast(frame->format)) - , _aligned (true) + , _aligned (aligned) { DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE); @@ -1139,7 +1139,7 @@ Image::aligned () const PositionImage -merge (list images) +merge (list images, bool aligned) { if (images.empty ()) { return {}; @@ -1154,7 +1154,7 @@ merge (list images) all.extend (dcpomatic::Rect(i.position, i.image->size().width, i.image->size().height)); } - auto merged = make_shared(images.front().image->pixel_format(), dcp::Size(all.width, all.height), false); + auto merged = make_shared(images.front().image->pixel_format(), dcp::Size(all.width, all.height), aligned); merged->make_transparent (); for (auto const& i: images) { merged->alpha_blend (i.image, i.position - all.position()); @@ -1312,16 +1312,18 @@ Image::fade (float f) } } + shared_ptr -Image::ensure_aligned (shared_ptr image) +Image::ensure_aligned (shared_ptr image, bool aligned) { - if (image->aligned()) { + if (image->aligned() == aligned) { return image; } - return make_shared(image, true); + return make_shared(image, aligned); } + size_t Image::memory_used () const { diff --git a/src/lib/image.h b/src/lib/image.h index cb8f11ffc..3cba8f7e5 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -41,7 +41,7 @@ class Image : public std::enable_shared_from_this { public: Image (AVPixelFormat p, dcp::Size s, bool aligned); - explicit Image (AVFrame const *); + explicit Image (AVFrame const *, bool aligned); explicit Image (Image const &); Image (std::shared_ptr, bool); Image& operator= (Image const &); @@ -94,7 +94,7 @@ public: void png_error (char const * message); - static std::shared_ptr ensure_aligned (std::shared_ptr image); + static std::shared_ptr ensure_aligned (std::shared_ptr image, bool aligned); private: friend struct pixel_formats_test; @@ -115,7 +115,7 @@ private: bool _aligned; }; -extern PositionImage merge (std::list images); +extern PositionImage merge (std::list images, bool aligned); extern bool operator== (Image const & a, Image const & b); #endif diff --git a/src/lib/image_examiner.cc b/src/lib/image_examiner.cc index 89d1517ce..8b2096214 100644 --- a/src/lib/image_examiner.cc +++ b/src/lib/image_examiner.cc @@ -67,7 +67,7 @@ ImageExaminer::ImageExaminer (shared_ptr film, shared_ptrpath(0)); - _video_size = proxy.image().image->size(); + _video_size = proxy.image(false).image->size(); } if (content->still ()) { diff --git a/src/lib/image_proxy.h b/src/lib/image_proxy.h index cf1fb9a2d..8817845d9 100644 --- a/src/lib/image_proxy.h +++ b/src/lib/image_proxy.h @@ -91,6 +91,7 @@ public: * can be used as an optimisation. */ virtual Result image ( + bool aligned, boost::optional size = boost::optional () ) const = 0; @@ -102,7 +103,7 @@ public: * This method may be called in a different thread to image(). * @return log2 of any scaling down that will be applied to the image. */ - virtual int prepare (boost::optional = boost::optional()) const { return 0; } + virtual int prepare (bool, boost::optional = boost::optional()) const { return 0; } virtual size_t memory_used () const = 0; }; diff --git a/src/lib/j2k_image_proxy.cc b/src/lib/j2k_image_proxy.cc index c98273ad2..21507ca15 100644 --- a/src/lib/j2k_image_proxy.cc +++ b/src/lib/j2k_image_proxy.cc @@ -108,7 +108,7 @@ J2KImageProxy::J2KImageProxy (shared_ptr xml, shared_ptr soc if (xml->optional_number_child("Eye")) { _eye = static_cast(xml->number_child("Eye")); } - shared_ptr data(new ArrayData(xml->number_child("Size"))); + auto data = make_shared(xml->number_child("Size")); /* This only matters when we are using J2KImageProxy for the preview, which will never use this constructor (which is only used for passing data to encode servers). So we can put anything in here. It's a bit of a hack. @@ -120,7 +120,7 @@ J2KImageProxy::J2KImageProxy (shared_ptr xml, shared_ptr soc int -J2KImageProxy::prepare (optional target_size) const +J2KImageProxy::prepare (bool aligned, optional target_size) const { boost::mutex::scoped_lock lm (_mutex); @@ -145,7 +145,7 @@ J2KImageProxy::prepare (optional target_size) const try { /* XXX: should check that potentially trashing _data here doesn't matter */ auto decompressed = dcp::decompress_j2k (const_cast(_data->data()), _data->size(), reduce); - _image.reset (new Image (_pixel_format, decompressed->size(), false)); + _image = make_shared(_pixel_format, decompressed->size(), aligned); int const shift = 16 - decompressed->precision (0); @@ -169,7 +169,7 @@ J2KImageProxy::prepare (optional target_size) const } } } catch (dcp::J2KDecompressionError& e) { - _image = make_shared(_pixel_format, _size, true); + _image = make_shared(_pixel_format, _size, aligned); _image->make_black (); _error = true; } @@ -182,9 +182,9 @@ J2KImageProxy::prepare (optional target_size) const ImageProxy::Result -J2KImageProxy::image (optional target_size) const +J2KImageProxy::image (bool aligned, optional target_size) const { - int const r = prepare (target_size); + int const r = prepare (aligned, target_size); /* I think this is safe without a lock on mutex. _image is guaranteed to be set up when prepare() has happened. diff --git a/src/lib/j2k_image_proxy.h b/src/lib/j2k_image_proxy.h index 5235d8e42..a23ec6d98 100644 --- a/src/lib/j2k_image_proxy.h +++ b/src/lib/j2k_image_proxy.h @@ -57,6 +57,7 @@ public: J2KImageProxy (dcp::ArrayData data, dcp::Size size, AVPixelFormat pixel_format); Result image ( + bool aligned, boost::optional size = boost::optional () ) const; @@ -64,7 +65,7 @@ public: void write_to_socket (std::shared_ptr) const; /** @return true if our image is definitely the same as another, false if it is probably not */ bool same (std::shared_ptr) const; - int prepare (boost::optional = boost::optional()) const; + int prepare (bool aligned, boost::optional = boost::optional()) const; std::shared_ptr j2k () const { return _data; diff --git a/src/lib/player.cc b/src/lib/player.cc index 5de089ba9..810d949d9 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -95,11 +95,12 @@ int const PlayerProperty::DCP_DECODE_REDUCTION = 704; int const PlayerProperty::PLAYBACK_LENGTH = 705; -Player::Player (shared_ptr film) +Player::Player (shared_ptr film, bool aligned) : _film (film) , _suspended (0) , _tolerant (film->tolerant()) , _audio_merger (_film->audio_frame_rate()) + , _aligned_subtitles (aligned) { construct (); } @@ -827,7 +828,7 @@ Player::open_subtitles_for_frame (DCPTime time) const return {}; } - return merge (captions); + return merge (captions, _aligned_subtitles); } diff --git a/src/lib/player.h b/src/lib/player.h index 6cefbe232..767218379 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -76,7 +76,7 @@ public: class Player : public std::enable_shared_from_this { public: - Player (std::shared_ptr); + Player (std::shared_ptr, bool aligned_subtitles); Player (std::shared_ptr, std::shared_ptr playlist); Player (Player const& Player) = delete; @@ -233,6 +233,9 @@ private: dcpomatic::DCPTime _playback_length; + /** aligned flag for subtitle images that we create */ + bool _aligned_subtitles = true; + boost::signals2::scoped_connection _film_changed_connection; boost::signals2::scoped_connection _playlist_change_connection; boost::signals2::scoped_connection _playlist_content_change_connection; diff --git a/src/lib/player_video.cc b/src/lib/player_video.cc index 0a6ce0d99..a687e7ea5 100644 --- a/src/lib/player_video.cc +++ b/src/lib/player_video.cc @@ -122,10 +122,10 @@ PlayerVideo::image (function pixel_format, VideoR } -shared_ptr +shared_ptr PlayerVideo::raw_image () const { - return _in->image(_inter_size).image; + return _in->image(false, _inter_size).image; } @@ -144,7 +144,7 @@ PlayerVideo::make_image (function pixel_format, V _image_out_size = _out_size; _image_fade = _fade; - auto prox = _in->image (_inter_size); + auto prox = _in->image (true, _inter_size); _error = prox.error; auto total_crop = _crop; @@ -184,7 +184,7 @@ PlayerVideo::make_image (function pixel_format, V ); if (_text) { - _image->alpha_blend (Image::ensure_aligned (_text->image), _text->position); + _image->alpha_blend (Image::ensure_aligned(_text->image, true), _text->position); } if (_fade) { @@ -300,7 +300,7 @@ PlayerVideo::keep_xyz_or_rgb (AVPixelFormat p) void PlayerVideo::prepare (function pixel_format, VideoRange video_range, bool aligned, bool fast, bool proxy_only) { - _in->prepare (_inter_size); + _in->prepare (aligned, _inter_size); boost::mutex::scoped_lock lm (_mutex); if (!_image && !proxy_only) { make_image (pixel_format, video_range, aligned, fast); diff --git a/src/lib/raw_image_proxy.cc b/src/lib/raw_image_proxy.cc index fed40c45e..ac8ff0763 100644 --- a/src/lib/raw_image_proxy.cc +++ b/src/lib/raw_image_proxy.cc @@ -64,9 +64,10 @@ RawImageProxy::RawImageProxy (shared_ptr xml, shared_ptr soc ImageProxy::Result -RawImageProxy::image (optional) const +RawImageProxy::image (bool aligned, optional) const { - return Result (_image, 0); + /* This ensure_aligned could be wasteful */ + return Result (Image::ensure_aligned(_image, aligned), 0); } @@ -95,7 +96,7 @@ RawImageProxy::same (shared_ptr other) const return false; } - return (*_image.get()) == (*rp->image().image.get()); + return (*_image.get()) == (*rp->image(_image->aligned()).image.get()); } diff --git a/src/lib/raw_image_proxy.h b/src/lib/raw_image_proxy.h index ec30f5a29..7e0861104 100644 --- a/src/lib/raw_image_proxy.h +++ b/src/lib/raw_image_proxy.h @@ -33,6 +33,7 @@ public: RawImageProxy (std::shared_ptr xml, std::shared_ptr socket); Result image ( + bool aligned, boost::optional size = boost::optional () ) const; diff --git a/src/lib/util.cc b/src/lib/util.cc index 0646a4787..c65b2bc85 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -956,7 +956,7 @@ emit_subtitle_image (ContentTimePeriod period, dcp::SubtitleImage sub, dcp::Size { /* XXX: this is rather inefficient; decoding the image just to get its size */ FFmpegImageProxy proxy (sub.png_image()); - auto image = proxy.image().image; + auto image = proxy.image(false).image; /* set up rect with height and width */ dcpomatic::Rect rect(0, 0, image->size().width / double(size.width), image->size().height / double(size.height)); diff --git a/src/lib/video_filter_graph.cc b/src/lib/video_filter_graph.cc index a61da6773..b4198da72 100644 --- a/src/lib/video_filter_graph.cc +++ b/src/lib/video_filter_graph.cc @@ -59,7 +59,7 @@ VideoFilterGraph::process (AVFrame* frame) list, int64_t>> images; if (_copy) { - images.push_back (make_pair(make_shared(frame), frame->best_effort_timestamp)); + images.push_back (make_pair(make_shared(frame, true), frame->best_effort_timestamp)); } else { int r = av_buffersrc_write_frame (_buffer_src_context, frame); if (r < 0) { @@ -71,7 +71,7 @@ VideoFilterGraph::process (AVFrame* frame) break; } - images.push_back (make_pair(make_shared(_frame), frame->best_effort_timestamp)); + images.push_back (make_pair(make_shared(_frame, true), frame->best_effort_timestamp)); av_frame_unref (_frame); } } diff --git a/src/tools/server_test.cc b/src/tools/server_test.cc index 6c7371253..e32fd327e 100644 --- a/src/tools/server_test.cc +++ b/src/tools/server_test.cc @@ -155,7 +155,7 @@ main (int argc, char* argv[]) film = make_shared(film_dir); film->read_metadata (); - auto player = make_shared(film); + auto player = make_shared(film, false); player->Video.connect (bind(&process_video, _1)); while (!player->pass ()) {} } catch (std::exception& e) { diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 98948b1f2..735ba02eb 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -169,7 +169,7 @@ FilmViewer::set_film (shared_ptr film) } try { - _player = make_shared(_film); + _player = make_shared(_film, !_optimise_for_j2k); _player->set_fast (); if (_dcp_decode_reduction) { _player->set_dcp_decode_reduction (_dcp_decode_reduction); @@ -221,7 +221,7 @@ FilmViewer::recreate_butler () _audio_channels, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, - false, + !_optimise_for_j2k, true, dynamic_pointer_cast(_video_view) && _optimise_for_j2k ); diff --git a/src/wx/gl_video_view.cc b/src/wx/gl_video_view.cc index 4c51326d3..6288a24a3 100644 --- a/src/wx/gl_video_view.cc +++ b/src/wx/gl_video_view.cc @@ -497,9 +497,12 @@ GLVideoView::draw (Position, dcp::Size) void GLVideoView::set_image (shared_ptr pv) { - auto video = _optimise_for_j2k ? pv->raw_image() : pv->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true); + shared_ptr video = _optimise_for_j2k ? pv->raw_image() : pv->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true); - DCPOMATIC_ASSERT (!video->aligned()); + /* Only the player's black frames should be aligned at this stage, so this should + * almost always have no work to do. + */ + video = Image::ensure_aligned (video, false); /** If _optimise_for_j2k is true we render a XYZ image, doing the colourspace * conversion, scaling and video range conversion in the GL shader. diff --git a/test/butler_test.cc b/test/butler_test.cc index 65c9139d7..99bd95fce 100644 --- a/test/butler_test.cc +++ b/test/butler_test.cc @@ -59,7 +59,7 @@ BOOST_AUTO_TEST_CASE (butler_test1) map.set (i, i, 1); } - Butler butler (film, make_shared(film), map, 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, false, false); + Butler butler (film, make_shared(film, false), map, 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, false, false); BOOST_CHECK (butler.get_video(true, 0).second == DCPTime()); BOOST_CHECK (butler.get_video(true, 0).second == DCPTime::from_frames(1, 24)); diff --git a/test/dcp_decoder_test.cc b/test/dcp_decoder_test.cc index a52a0ccc5..9461effc5 100644 --- a/test/dcp_decoder_test.cc +++ b/test/dcp_decoder_test.cc @@ -87,7 +87,7 @@ BOOST_AUTO_TEST_CASE (check_reuse_old_data_test) ov_content = make_shared(ov->dir(ov->dcp_name(false))); test->examine_and_add_content (ov_content); BOOST_REQUIRE (!wait_for_jobs()); - auto player = make_shared(test); + auto player = make_shared(test, false); auto decoder = std::dynamic_pointer_cast(player->_pieces.front()->decoder); BOOST_REQUIRE (decoder); @@ -105,7 +105,7 @@ BOOST_AUTO_TEST_CASE (check_reuse_old_data_test) auto vf_content = make_shared(vf->dir(vf->dcp_name(false))); test->examine_and_add_content (vf_content); BOOST_REQUIRE (!wait_for_jobs()); - player.reset (new Player(test)); + player = make_shared(test, false); decoder = std::dynamic_pointer_cast(player->_pieces.front()->decoder); BOOST_REQUIRE (decoder); @@ -123,7 +123,7 @@ BOOST_AUTO_TEST_CASE (check_reuse_old_data_test) auto encrypted_content = make_shared(encrypted->dir(encrypted->dcp_name(false))); test->examine_and_add_content (encrypted_content); BOOST_REQUIRE (!wait_for_jobs()); - player = make_shared(test); + player = make_shared(test, false); decoder = std::dynamic_pointer_cast(player->_pieces.front()->decoder); BOOST_REQUIRE (decoder); diff --git a/test/dcp_playback_test.cc b/test/dcp_playback_test.cc index efe7138e1..2ea638d74 100644 --- a/test/dcp_playback_test.cc +++ b/test/dcp_playback_test.cc @@ -28,9 +28,7 @@ using std::make_shared; -using std::pair; -using std::shared_ptr; -using boost::optional; +using std::make_shared; #if BOOST_VERSION >= 106100 using namespace boost::placeholders; #endif @@ -47,7 +45,7 @@ BOOST_AUTO_TEST_CASE (dcp_playback_test) auto butler = std::make_shared( film, - shared_ptr(new Player(film)), + make_shared(film, false), AudioMapping(6, 6), 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), diff --git a/test/ffmpeg_audio_only_test.cc b/test/ffmpeg_audio_only_test.cc index a68f7cf57..9f185fdf3 100644 --- a/test/ffmpeg_audio_only_test.cc +++ b/test/ffmpeg_audio_only_test.cc @@ -101,7 +101,7 @@ test (boost::filesystem::path file) ref_buffer_size = info.samplerate * info.channels; ref_buffer = new float[ref_buffer_size]; - auto player = make_shared(film); + auto player = make_shared(film, false); player->Audio.connect (bind (&audio, _1, info.channels)); while (!player->pass ()) {} diff --git a/test/ffmpeg_audio_test.cc b/test/ffmpeg_audio_test.cc index 5a36b99f4..0cc602a9a 100644 --- a/test/ffmpeg_audio_test.cc +++ b/test/ffmpeg_audio_test.cc @@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_audio_test2) film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs ()); - auto player = make_shared(film); + auto player = make_shared(film, false); while (!player->pass ()) {} } @@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_audio_test3) film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs ()); - auto player = make_shared(film); + auto player = make_shared(film, false); player->set_fast (); while (!player->pass ()) {} } @@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_audio_test4) film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs ()); - auto player = make_shared(film); + auto player = make_shared(film, false); player->set_fast (); BOOST_CHECK_NO_THROW (while (!player->pass()) {}); } diff --git a/test/ffmpeg_decoder_sequential_test.cc b/test/ffmpeg_decoder_sequential_test.cc index b2069a8b1..7d6d547ff 100644 --- a/test/ffmpeg_decoder_sequential_test.cc +++ b/test/ffmpeg_decoder_sequential_test.cc @@ -75,7 +75,7 @@ ffmpeg_decoder_sequential_test_one (boost::filesystem::path file, float fps, int film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs()); film->write_metadata (); - auto player = make_shared(film); + auto player = make_shared(film, false); BOOST_REQUIRE (content->video_frame_rate()); BOOST_CHECK_CLOSE (content->video_frame_rate().get(), fps, 0.01); diff --git a/test/image_test.cc b/test/image_test.cc index 3993b3efb..9d0d43664 100644 --- a/test/image_test.cc +++ b/test/image_test.cc @@ -148,7 +148,7 @@ void alpha_blend_test_one (AVPixelFormat format, string suffix) { auto proxy = make_shared(TestPaths::private_data() / "prophet_frame.tiff"); - auto raw = proxy->image().image; + auto raw = proxy->image(false).image; auto background = raw->convert_pixel_format (dcp::YUVToRGB::REC709, format, true, false); auto overlay = make_shared(AV_PIX_FMT_BGRA, dcp::Size(431, 891), true); @@ -221,7 +221,7 @@ BOOST_AUTO_TEST_CASE (merge_test1) list all; all.push_back (PositionImage (A, Position(0, 0))); - auto merged = merge (all); + auto merged = merge (all, false); BOOST_CHECK (merged.position == Position(0, 0)); BOOST_CHECK_EQUAL (memcmp (merged.image->data()[0], A->data()[0], stride * 48), 0); @@ -254,7 +254,7 @@ BOOST_AUTO_TEST_CASE (merge_test2) list all; all.push_back (PositionImage(A, Position(0, 0))); all.push_back (PositionImage(B, Position(0, 0))); - auto merged = merge (all); + auto merged = merge (all, false); BOOST_CHECK (merged.position == Position(0, 0)); @@ -274,7 +274,7 @@ BOOST_AUTO_TEST_CASE (merge_test2) BOOST_AUTO_TEST_CASE (crop_scale_window_test) { auto proxy = make_shared("test/data/flat_red.png"); - auto raw = proxy->image().image; + auto raw = proxy->image(false).image; auto out = raw->crop_scale_window( Crop(), dcp::Size(1998, 836), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_YUV420P, VideoRange::FULL, true, false ); @@ -300,7 +300,7 @@ BOOST_AUTO_TEST_CASE (crop_scale_window_test2) BOOST_AUTO_TEST_CASE (crop_scale_window_test3) { auto proxy = make_shared(TestPaths::private_data() / "player_seek_test_0.png"); - auto xyz = proxy->image().image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, true, false); + auto xyz = proxy->image(false).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, true, false); auto cropped = xyz->crop_scale_window( Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, false, false ); @@ -312,7 +312,7 @@ BOOST_AUTO_TEST_CASE (crop_scale_window_test3) BOOST_AUTO_TEST_CASE (crop_scale_window_test4) { auto proxy = make_shared(TestPaths::private_data() / "player_seek_test_0.png"); - auto xyz = proxy->image().image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, true, false); + auto xyz = proxy->image(false).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, true, false); auto cropped = xyz->crop_scale_window( Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_XYZ12LE, VideoRange::FULL, false, false ); @@ -324,7 +324,7 @@ BOOST_AUTO_TEST_CASE (crop_scale_window_test4) BOOST_AUTO_TEST_CASE (crop_scale_window_test5) { auto proxy = make_shared(TestPaths::private_data() / "player_seek_test_0.png"); - auto xyz = proxy->image().image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_XYZ12LE, true, false); + auto xyz = proxy->image(false).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_XYZ12LE, true, false); auto cropped = xyz->crop_scale_window( Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, false, false ); @@ -336,7 +336,7 @@ BOOST_AUTO_TEST_CASE (crop_scale_window_test5) BOOST_AUTO_TEST_CASE (crop_scale_window_test6) { auto proxy = make_shared(TestPaths::private_data() / "player_seek_test_0.png"); - auto xyz = proxy->image().image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_XYZ12LE, true, false); + auto xyz = proxy->image(false).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_XYZ12LE, true, false); auto cropped = xyz->crop_scale_window( Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_XYZ12LE, VideoRange::FULL, false, false ); @@ -351,7 +351,7 @@ BOOST_AUTO_TEST_CASE (crop_scale_window_test7) using namespace boost::filesystem; for (int left_crop = 0; left_crop < 8; ++left_crop) { auto proxy = make_shared("test/data/rgb_grey_testcard.png"); - auto yuv = proxy->image().image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_YUV420P, true, false); + auto yuv = proxy->image(false).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_YUV420P, true, false); int rounded = left_crop - (left_crop % 2); auto cropped = yuv->crop_scale_window( Crop(left_crop, 0, 0, 0), @@ -374,7 +374,7 @@ BOOST_AUTO_TEST_CASE (crop_scale_window_test7) BOOST_AUTO_TEST_CASE (as_png_test) { auto proxy = make_shared("test/data/3d_test/000001.png"); - auto image_rgb = proxy->image().image; + auto image_rgb = proxy->image(false).image; auto image_bgr = image_rgb->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_BGRA, true, false); image_rgb->as_png().write ("build/test/as_png_rgb.png"); image_bgr->as_png().write ("build/test/as_png_bgr.png"); @@ -402,7 +402,7 @@ static void fade_test_format_red (AVPixelFormat f, float amount, string name) { auto proxy = make_shared("test/data/flat_red.png"); - auto red = proxy->image().image->convert_pixel_format(dcp::YUVToRGB::REC709, f, true, false); + auto red = proxy->image(false).image->convert_pixel_format(dcp::YUVToRGB::REC709, f, true, false); red->fade (amount); string const filename = "fade_test_red_" + name + ".png"; red->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, true, false)->as_png().write("build/test/" + filename); @@ -506,7 +506,7 @@ BOOST_AUTO_TEST_CASE (make_black_test) BOOST_AUTO_TEST_CASE (make_part_black_test) { auto proxy = make_shared("test/data/flat_red.png"); - auto original = proxy->image().image; + auto original = proxy->image(false).image; list pix_fmts = { AV_PIX_FMT_RGB24, diff --git a/test/overlap_video_test.cc b/test/overlap_video_test.cc index 724f4e75b..d0d5a8bbf 100644 --- a/test/overlap_video_test.cc +++ b/test/overlap_video_test.cc @@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE (overlap_video_test1) B->video->set_length (24); B->set_position (film, dcpomatic::DCPTime::from_seconds(1)); - auto player = make_shared(film); + auto player = make_shared(film, false); auto pieces = player->_pieces; BOOST_REQUIRE_EQUAL (pieces.size(), 2U); BOOST_CHECK_EQUAL (pieces.front()->content, A); diff --git a/test/pixel_formats_test.cc b/test/pixel_formats_test.cc index f59c594e9..a4d42e399 100644 --- a/test/pixel_formats_test.cc +++ b/test/pixel_formats_test.cc @@ -88,7 +88,7 @@ BOOST_AUTO_TEST_CASE (pixel_formats_test) f->height = 480; f->format = static_cast (i.format); av_frame_get_buffer (f, true); - Image t (f); + Image t (f, false); BOOST_CHECK_EQUAL(t.planes(), i.planes); BOOST_CHECK_EQUAL(t.sample_size(0).height, i.lines[0]); BOOST_CHECK_EQUAL(t.sample_size(1).height, i.lines[1]); diff --git a/test/player_test.cc b/test/player_test.cc index 1f5b543aa..c1e2d2cbe 100644 --- a/test/player_test.cc +++ b/test/player_test.cc @@ -84,7 +84,7 @@ BOOST_AUTO_TEST_CASE (player_silence_padding_test) accumulated = std::make_shared(film->audio_channels(), 0); - auto player = std::make_shared(film); + auto player = std::make_shared(film, false); player->Audio.connect (bind (&accumulate, _1, _2)); while (!player->pass ()) {} BOOST_REQUIRE (accumulated->frames() >= 48000); @@ -164,7 +164,7 @@ BOOST_AUTO_TEST_CASE (player_subframe_test) /* Length should be rounded up from B's length to the next video frame */ BOOST_CHECK (film->length() == DCPTime::from_frames(3 * 24 + 1, 24)); - auto player = std::make_shared(film); + auto player = std::make_shared(film, false); player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_black._periods.size(), 1U); BOOST_CHECK (player->_black._periods.front() == DCPTimePeriod(DCPTime::from_frames(3 * 24, 24), DCPTime::from_frames(3 * 24 + 1, 24))); @@ -206,7 +206,7 @@ BOOST_AUTO_TEST_CASE (player_interleave_test) film->examine_and_add_content (s); BOOST_REQUIRE (!wait_for_jobs ()); - auto player = std::make_shared(film); + auto player = std::make_shared(film, false); player->Video.connect (bind (&video, _1, _2)); player->Audio.connect (bind (&audio, _1, _2)); video_frames = audio_frames = 0; @@ -229,7 +229,7 @@ BOOST_AUTO_TEST_CASE (player_seek_test) BOOST_REQUIRE (!wait_for_jobs ()); dcp->only_text()->set_use (true); - auto player = std::make_shared(film); + auto player = std::make_shared(film, false); player->set_fast (); player->set_always_burn_open_subtitles (); player->set_play_referenced (); @@ -261,7 +261,7 @@ BOOST_AUTO_TEST_CASE (player_seek_test2) BOOST_REQUIRE (!wait_for_jobs ()); dcp->only_text()->set_use (true); - auto player = std::make_shared(film); + auto player = std::make_shared(film, false); player->set_fast (); player->set_always_burn_open_subtitles (); player->set_play_referenced (); @@ -335,7 +335,7 @@ BOOST_AUTO_TEST_CASE (player_ignore_video_and_audio_test) text->only_text()->set_type (TextType::CLOSED_CAPTION); text->only_text()->set_use (true); - auto player = std::make_shared(film); + auto player = std::make_shared(film, false); player->set_ignore_video (); player->set_ignore_audio (); @@ -355,7 +355,7 @@ BOOST_AUTO_TEST_CASE (player_trim_crash) film->examine_and_add_content (boon); BOOST_REQUIRE (!wait_for_jobs()); - auto player = std::make_shared(film); + auto player = std::make_shared(film, false); player->set_fast (); auto butler = std::make_shared(film, player, AudioMapping(), 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true, false); diff --git a/test/test.cc b/test/test.cc index 4dab0cff1..3395d9672 100644 --- a/test/test.cc +++ b/test/test.cc @@ -364,9 +364,9 @@ double rms_error (boost::filesystem::path ref, boost::filesystem::path check) { FFmpegImageProxy ref_proxy (ref); - auto ref_image = ref_proxy.image().image; + auto ref_image = ref_proxy.image(false).image; FFmpegImageProxy check_proxy (check); - auto check_image = check_proxy.image().image; + auto check_image = check_proxy.image(false).image; BOOST_REQUIRE_EQUAL (ref_image->pixel_format(), check_image->pixel_format()); AVPixelFormat const format = ref_image->pixel_format(); diff --git a/test/time_calculation_test.cc b/test/time_calculation_test.cc index ffe77c2b7..285285395 100644 --- a/test/time_calculation_test.cc +++ b/test/time_calculation_test.cc @@ -197,7 +197,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1) film->set_sequence (false); film->add_content (content); - auto player = make_shared(film); + auto player = make_shared(film, false); /* Position 0, no trim, content rate = DCP rate */ content->set_position (film, DCPTime()); @@ -206,7 +206,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1) film->set_video_frame_rate (24); player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U); - shared_ptr piece = player->_pieces.front (); + auto piece = player->_pieces.front(); BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0); BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.5)), 12); BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.0)), 72); @@ -403,7 +403,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2) film->set_sequence (false); film->add_content (content); - auto player = make_shared(film); + auto player = make_shared(film, false); /* Position 0, no trim, content rate = DCP rate */ content->set_position (film, DCPTime()); @@ -412,7 +412,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2) film->set_video_frame_rate (24); player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U); - shared_ptr piece = player->_pieces.front (); + auto piece = player->_pieces.front (); BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0).get(), 0); BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 12).get(), DCPTime::from_seconds(0.5).get()); BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 72).get(), DCPTime::from_seconds(3.0).get()); @@ -580,7 +580,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3) film->set_sequence (false); film->add_content (content); - auto player = make_shared(film); + auto player = make_shared(film, false); /* Position 0, no trim, video/audio content rate = video/audio DCP rate */ content->set_position (film, DCPTime()); diff --git a/test/upmixer_a_test.cc b/test/upmixer_a_test.cc index 0dc496275..3310a9277 100644 --- a/test/upmixer_a_test.cc +++ b/test/upmixer_a_test.cc @@ -89,7 +89,7 @@ BOOST_AUTO_TEST_CASE (upmixer_a_test) Ls = sf_open ("build/test/upmixer_a_test/Ls.wav", SFM_WRITE, &info); Rs = sf_open ("build/test/upmixer_a_test/Rs.wav", SFM_WRITE, &info); - auto player = make_shared(film); + auto player = make_shared(film, false); player->Audio.connect (bind (&write, _1, _2)); while (!player->pass()) {} diff --git a/test/vf_test.cc b/test/vf_test.cc index b7e976041..d25eb3cca 100644 --- a/test/vf_test.cc +++ b/test/vf_test.cc @@ -291,7 +291,7 @@ BOOST_AUTO_TEST_CASE (vf_test5) make_and_verify_dcp (vf, {dcp::VerificationNote::Code::EXTERNAL_ASSET}); /* Check that the selected reel assets are right */ - auto player = make_shared(vf); + auto player = make_shared(vf, false); auto a = player->get_reel_assets(); BOOST_REQUIRE_EQUAL (a.size(), 4U); auto i = a.begin(); diff --git a/test/video_level_test.cc b/test/video_level_test.cc index be54cd3f9..8d82e9d76 100644 --- a/test/video_level_test.cc +++ b/test/video_level_test.cc @@ -94,7 +94,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_image_full_range_not_changed) write_image (grey_image(size, grey_pixel), file); FFmpegImageProxy proxy (file); - ImageProxy::Result result = proxy.image (); + ImageProxy::Result result = proxy.image (false); BOOST_REQUIRE (!result.error); for (int y = 0; y < size.height; ++y) { @@ -214,7 +214,7 @@ pixel_range (shared_ptr film, shared_ptr content) BOOST_REQUIRE (!decoder->pass()); } - return pixel_range (content_video->image->image().image); + return pixel_range (content_video->image->image(false).image); } -- cgit v1.2.3 From 3799e91d126d243d41c44dcb0ca1bfa66b53a57e Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 15 Sep 2021 23:36:21 +0200 Subject: Replace aligned bool with enum Alignment. --- src/lib/butler.cc | 8 ++-- src/lib/butler.h | 4 +- src/lib/dcp_video.cc | 6 ++- src/lib/encoder.cc | 2 +- src/lib/ffmpeg_decoder.cc | 56 +++++++++++----------- src/lib/ffmpeg_encoder.cc | 16 +++---- src/lib/ffmpeg_file_encoder.cc | 14 ++---- src/lib/ffmpeg_image_proxy.cc | 4 +- src/lib/ffmpeg_image_proxy.h | 2 +- src/lib/hints.cc | 5 +- src/lib/image.cc | 73 +++++++++++++++-------------- src/lib/image.h | 25 ++++++---- src/lib/image_examiner.cc | 2 +- src/lib/image_proxy.h | 14 ++++-- src/lib/j2k_image_proxy.cc | 12 ++--- src/lib/j2k_image_proxy.h | 4 +- src/lib/player.cc | 10 ++-- src/lib/player.h | 7 +-- src/lib/player_video.cc | 24 +++++----- src/lib/player_video.h | 13 +++--- src/lib/raw_image_proxy.cc | 10 ++-- src/lib/raw_image_proxy.h | 2 +- src/lib/render_text.cc | 2 +- src/lib/util.cc | 63 ++++++++++++------------- src/lib/video_filter_graph.cc | 5 +- src/tools/server_test.cc | 2 +- src/wx/film_viewer.cc | 10 +--- src/wx/gl_video_view.cc | 8 ++-- src/wx/simple_video_view.cc | 22 ++++++--- src/wx/video_waveform_plot.cc | 4 +- test/butler_test.cc | 2 +- test/client_server_test.cc | 10 ++-- test/dcp_decoder_test.cc | 6 +-- test/dcp_playback_test.cc | 6 +-- test/ffmpeg_audio_only_test.cc | 2 +- test/ffmpeg_audio_test.cc | 6 +-- test/ffmpeg_decoder_sequential_test.cc | 2 +- test/image_test.cc | 85 +++++++++++++++++----------------- test/low_bitrate_test.cc | 20 +++++++- test/overlap_video_test.cc | 3 +- test/pixel_formats_test.cc | 2 +- test/player_test.cc | 47 +++++++++---------- test/test.cc | 4 +- test/time_calculation_test.cc | 7 ++- test/upmixer_a_test.cc | 2 +- test/vf_test.cc | 2 +- test/video_level_test.cc | 9 ++-- 47 files changed, 331 insertions(+), 313 deletions(-) (limited to 'src/lib') diff --git a/src/lib/butler.cc b/src/lib/butler.cc index ca0887a4c..5a5cc4912 100644 --- a/src/lib/butler.cc +++ b/src/lib/butler.cc @@ -57,7 +57,7 @@ using namespace boost::placeholders; /** @param pixel_format Pixel format functor that will be used when calling ::image on PlayerVideos coming out of this * butler. This will be used (where possible) to prepare the PlayerVideos so that calling image() on them is quick. - * @param aligned Same as above for the `aligned' flag. + * @param alignment Same as above for the `alignment' value. * @param fast Same as above for the `fast' flag. */ Butler::Butler ( @@ -67,7 +67,7 @@ Butler::Butler ( int audio_channels, function pixel_format, VideoRange video_range, - bool aligned, + Image::Alignment alignment, bool fast, bool prepare_only_proxy ) @@ -84,7 +84,7 @@ Butler::Butler ( , _disable_audio (false) , _pixel_format (pixel_format) , _video_range (video_range) - , _aligned (aligned) + , _alignment (alignment) , _fast (fast) , _prepare_only_proxy (prepare_only_proxy) { @@ -325,7 +325,7 @@ try /* If the weak_ptr cannot be locked the video obviously no longer requires any work */ if (video) { LOG_TIMING("start-prepare in %1", thread_id()); - video->prepare (_pixel_format, _video_range, _aligned, _fast, _prepare_only_proxy); + video->prepare (_pixel_format, _video_range, _alignment, _fast, _prepare_only_proxy); LOG_TIMING("finish-prepare in %1", thread_id()); } } diff --git a/src/lib/butler.h b/src/lib/butler.h index 320e56bf9..cd3891754 100644 --- a/src/lib/butler.h +++ b/src/lib/butler.h @@ -45,7 +45,7 @@ public: int audio_channels, std::function pixel_format, VideoRange video_range, - bool aligned, + Image::Alignment alignment, bool fast, bool prepare_only_proxy ); @@ -125,7 +125,7 @@ private: std::function _pixel_format; VideoRange _video_range; - bool _aligned; + Image::Alignment _alignment; bool _fast; /** true to ask PlayerVideo::prepare to only prepare the ImageProxy and not also diff --git a/src/lib/dcp_video.cc b/src/lib/dcp_video.cc index 4a505a7e1..9daeb45c8 100644 --- a/src/lib/dcp_video.cc +++ b/src/lib/dcp_video.cc @@ -59,19 +59,21 @@ DCPOMATIC_ENABLE_WARNINGS #include "i18n.h" + using std::cout; using std::make_shared; using std::shared_ptr; using std::string; -using dcp::Size; using dcp::ArrayData; using dcp::raw_convert; #if BOOST_VERSION >= 106100 using namespace boost::placeholders; #endif + #define DCI_COEFFICENT (48.0 / 52.37) + /** Construct a DCP video frame. * @param frame Input frame. * @param index Index of the frame within the DCP. @@ -103,7 +105,7 @@ DCPVideo::convert_to_xyz (shared_ptr frame, dcp::NoteHandler { shared_ptr xyz; - auto image = frame->image (bind(&PlayerVideo::keep_xyz_or_rgb, _1), VideoRange::FULL, true, false); + auto image = frame->image (bind(&PlayerVideo::keep_xyz_or_rgb, _1), VideoRange::FULL, Image::Alignment::PADDED, false); if (frame->colour_conversion()) { xyz = dcp::rgb_to_xyz ( image->data()[0], diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index 0b7c241d8..1d688c318 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -41,7 +41,7 @@ Encoder::Encoder (std::shared_ptr film, std::weak_ptr job) : _film (film) , _job (job) - , _player (new Player(film, true)) + , _player (new Player(film, Image::Alignment::PADDED)) { } diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 70f9b0545..2baa99876 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -18,31 +18,33 @@ */ + /** @file src/ffmpeg_decoder.cc * @brief A decoder using FFmpeg to decode content. */ -#include "filter.h" -#include "exceptions.h" -#include "image.h" -#include "util.h" -#include "log.h" + +#include "audio_buffers.h" +#include "audio_content.h" +#include "audio_decoder.h" +#include "compose.hpp" #include "dcpomatic_log.h" -#include "ffmpeg_decoder.h" -#include "text_decoder.h" +#include "exceptions.h" #include "ffmpeg_audio_stream.h" -#include "ffmpeg_subtitle_stream.h" -#include "video_filter_graph.h" -#include "audio_buffers.h" #include "ffmpeg_content.h" -#include "raw_image_proxy.h" -#include "video_decoder.h" +#include "ffmpeg_decoder.h" +#include "ffmpeg_subtitle_stream.h" #include "film.h" -#include "audio_decoder.h" -#include "compose.hpp" -#include "text_content.h" -#include "audio_content.h" +#include "filter.h" #include "frame_interval_checker.h" +#include "image.h" +#include "log.h" +#include "raw_image_proxy.h" +#include "text_content.h" +#include "text_decoder.h" +#include "util.h" +#include "video_decoder.h" +#include "video_filter_graph.h" #include #include #include @@ -52,28 +54,22 @@ extern "C" { #include } #include -#include #include #include +#include #include #include "i18n.h" + using std::cout; -using std::string; -using std::vector; -using std::list; +using std::dynamic_pointer_cast; +using std::make_shared; using std::min; -using std::pair; -using std::max; -using std::map; using std::shared_ptr; -using std::make_shared; -using std::make_pair; -using boost::is_any_of; -using boost::split; +using std::string; +using std::vector; using boost::optional; -using std::dynamic_pointer_cast; using dcp::Size; using namespace dcpomatic; @@ -86,7 +82,7 @@ FFmpegDecoder::FFmpegDecoder (shared_ptr film, shared_ptr(this, c); _pts_offset = pts_offset (c->ffmpeg_audio_streams(), c->first_video(), c->active_video_frame_rate(film)); /* It doesn't matter what size or pixel format this is, it just needs to be black */ - _black_image = make_shared(AV_PIX_FMT_RGB24, dcp::Size (128, 128), true); + _black_image = make_shared(AV_PIX_FMT_RGB24, dcp::Size (128, 128), Image::Alignment::PADDED); _black_image->make_black (); } else { _pts_offset = {}; @@ -684,7 +680,7 @@ FFmpegDecoder::process_bitmap_subtitle (AVSubtitleRect const * rect, ContentTime /* Note BGRA is expressed little-endian, so the first byte in the word is B, second G, third R, fourth A. */ - auto image = make_shared(AV_PIX_FMT_BGRA, dcp::Size (rect->w, rect->h), true); + auto image = make_shared(AV_PIX_FMT_BGRA, dcp::Size (rect->w, rect->h), Image::Alignment::PADDED); #ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT /* Start of the first line in the subtitle */ diff --git a/src/lib/ffmpeg_encoder.cc b/src/lib/ffmpeg_encoder.cc index 77f27d519..dd773168a 100644 --- a/src/lib/ffmpeg_encoder.cc +++ b/src/lib/ffmpeg_encoder.cc @@ -18,26 +18,25 @@ */ + +#include "butler.h" +#include "cross.h" #include "ffmpeg_encoder.h" #include "film.h" +#include "image.h" #include "job.h" +#include "log.h" #include "player.h" #include "player_video.h" -#include "log.h" -#include "image.h" -#include "cross.h" -#include "butler.h" #include "compose.hpp" #include #include "i18n.h" + using std::cout; using std::list; using std::make_shared; -using std::map; -using std::pair; -using std::runtime_error; using std::shared_ptr; using std::string; using std::weak_ptr; @@ -48,6 +47,7 @@ using namespace dcpomatic; using namespace boost::placeholders; #endif + /** @param key Key to use to encrypt MP4 outputs */ FFmpegEncoder::FFmpegEncoder ( shared_ptr film, @@ -108,7 +108,7 @@ FFmpegEncoder::FFmpegEncoder ( } _butler = std::make_shared( - _film, _player, map, _output_audio_channels, bind(&PlayerVideo::force, _1, FFmpegFileEncoder::pixel_format(format)), VideoRange::VIDEO, true, false, false + _film, _player, map, _output_audio_channels, bind(&PlayerVideo::force, _1, FFmpegFileEncoder::pixel_format(format)), VideoRange::VIDEO, Image::Alignment::PADDED, false, false ); } diff --git a/src/lib/ffmpeg_file_encoder.cc b/src/lib/ffmpeg_file_encoder.cc index 533fd151c..ef02f30c8 100644 --- a/src/lib/ffmpeg_file_encoder.cc +++ b/src/lib/ffmpeg_file_encoder.cc @@ -19,16 +19,16 @@ */ +#include "compose.hpp" +#include "cross.h" #include "ffmpeg_encoder.h" #include "ffmpeg_wrapper.h" #include "film.h" +#include "image.h" #include "job.h" +#include "log.h" #include "player.h" #include "player_video.h" -#include "log.h" -#include "image.h" -#include "cross.h" -#include "compose.hpp" extern "C" { #include } @@ -39,13 +39,9 @@ extern "C" { using std::cout; using std::make_shared; -using std::pair; -using std::runtime_error; using std::shared_ptr; using std::string; -using std::weak_ptr; using boost::bind; -using boost::optional; using namespace dcpomatic; #if BOOST_VERSION >= 106100 using namespace boost::placeholders; @@ -406,7 +402,7 @@ FFmpegFileEncoder::video (shared_ptr video, DCPTime time) auto image = video->image ( bind (&PlayerVideo::force, _1, _pixel_format), VideoRange::VIDEO, - true, + Image::Alignment::PADDED, false ); diff --git a/src/lib/ffmpeg_image_proxy.cc b/src/lib/ffmpeg_image_proxy.cc index dd2f80e0e..4b3c3084c 100644 --- a/src/lib/ffmpeg_image_proxy.cc +++ b/src/lib/ffmpeg_image_proxy.cc @@ -122,7 +122,7 @@ FFmpegImageProxy::avio_seek (int64_t const pos, int whence) ImageProxy::Result -FFmpegImageProxy::image (bool aligned, optional) const +FFmpegImageProxy::image (Image::Alignment alignment, optional) const { auto constexpr name_for_errors = "FFmpegImageProxy::image"; @@ -205,7 +205,7 @@ FFmpegImageProxy::image (bool aligned, optional) const throw DecodeError (N_("avcodec_receive_frame"), name_for_errors, r, *_path); } - _image = make_shared(frame, aligned); + _image = make_shared(frame, alignment); av_packet_unref (&packet); av_frame_free (&frame); diff --git a/src/lib/ffmpeg_image_proxy.h b/src/lib/ffmpeg_image_proxy.h index f4e5bf66c..48317ed75 100644 --- a/src/lib/ffmpeg_image_proxy.h +++ b/src/lib/ffmpeg_image_proxy.h @@ -32,7 +32,7 @@ public: FFmpegImageProxy (std::shared_ptr socket); Result image ( - bool aligned, + Image::Alignment alignment, boost::optional size = boost::optional () ) const; diff --git a/src/lib/hints.cc b/src/lib/hints.cc index f21c51db9..46704ebf8 100644 --- a/src/lib/hints.cc +++ b/src/lib/hints.cc @@ -51,11 +51,8 @@ using std::cout; using std::make_shared; using std::max; -using std::min; -using std::pair; using std::shared_ptr; using std::string; -using std::vector; using std::weak_ptr; using boost::optional; using boost::bind; @@ -408,7 +405,7 @@ try emit (bind(boost::ref(Progress), _("Examining audio, subtitles and closed captions"))); } - auto player = make_shared(film, false); + auto player = make_shared(film, Image::Alignment::COMPACT); player->set_ignore_video (); if (check_loudness_done) { /* We don't need to analyse audio because we already loaded a suitable analysis */ diff --git a/src/lib/image.cc b/src/lib/image.cc index ce3f5817d..30589ef9c 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -64,8 +64,8 @@ using std::string; using dcp::Size; -/** The memory alignment, in bytes, used for each row of an image if aligment is requested */ -#define ALIGNMENT 64 +/** The memory alignment, in bytes, used for each row of an image if Alignment::PADDED is requested */ +int constexpr ALIGNMENT = 64; /* U/V black value for 8-bit colour */ static uint8_t const eight_bit_uv = (1 << 7) - 1; @@ -177,19 +177,19 @@ Image::crop_scale_window ( VideoRange video_range, AVPixelFormat out_format, VideoRange out_video_range, - bool out_aligned, + Alignment out_alignment, bool fast ) const { /* Empirical testing suggests that sws_scale() will crash if - the input image is not aligned. + the input image is not padded. */ - DCPOMATIC_ASSERT (aligned ()); + DCPOMATIC_ASSERT (alignment() == Alignment::PADDED); DCPOMATIC_ASSERT (out_size.width >= inter_size.width); DCPOMATIC_ASSERT (out_size.height >= inter_size.height); - auto out = make_shared(out_format, out_size, out_aligned); + auto out = make_shared(out_format, out_size, out_alignment); out->make_black (); auto in_desc = av_pix_fmt_desc_get (_pixel_format); @@ -310,27 +310,27 @@ Image::crop_scale_window ( } shared_ptr -Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const +Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const { - return scale(size(), yuv_to_rgb, out_format, out_aligned, fast); + return scale(size(), yuv_to_rgb, out_format, out_alignment, fast); } /** @param out_size Size to scale to. * @param yuv_to_rgb YUVToRGB transform transform to use, if required. * @param out_format Output pixel format. - * @param out_aligned true to make an aligned output image. + * @param out_aligment Output alignment. * @param fast Try to be fast at the possible expense of quality; at present this means using * fast bilinear rather than bicubic scaling. */ shared_ptr -Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const +Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const { /* Empirical testing suggests that sws_scale() will crash if - the input image is not aligned. + the input image alignment is not PADDED. */ - DCPOMATIC_ASSERT (aligned ()); + DCPOMATIC_ASSERT (alignment() == Alignment::PADDED); - auto scaled = make_shared(out_format, out_size, out_aligned); + auto scaled = make_shared(out_format, out_size, out_alignment); auto scale_context = sws_getContext ( size().width, size().height, pixel_format(), out_size.width, out_size.height, out_format, @@ -736,7 +736,7 @@ Image::alpha_blend (shared_ptr other, Position position) } case AV_PIX_FMT_YUV420P: { - auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, false, false); + auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false); dcp::Size const ts = size(); dcp::Size const os = yuv->size(); for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) { @@ -771,7 +771,7 @@ Image::alpha_blend (shared_ptr other, Position position) } case AV_PIX_FMT_YUV420P10: { - auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, false, false); + auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false); dcp::Size const ts = size(); dcp::Size const os = yuv->size(); for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) { @@ -806,7 +806,7 @@ Image::alpha_blend (shared_ptr other, Position position) } case AV_PIX_FMT_YUV422P10LE: { - auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, false, false); + auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false); dcp::Size const ts = size(); dcp::Size const os = yuv->size(); for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) { @@ -934,16 +934,17 @@ Image::bytes_per_pixel (int c) const * * @param p Pixel format. * @param s Size in pixels. - * @param aligned true to make each row of this image aligned to a ALIGNMENT-byte boundary. + * @param alignment PADDED to make each row of this image aligned to a ALIGNMENT-byte boundary, otherwise COMPACT. */ -Image::Image (AVPixelFormat p, dcp::Size s, bool aligned) +Image::Image (AVPixelFormat p, dcp::Size s, Alignment alignment) : _size (s) , _pixel_format (p) - , _aligned (aligned) + , _alignment (alignment) { allocate (); } + void Image::allocate () { @@ -958,7 +959,7 @@ Image::allocate () for (int i = 0; i < planes(); ++i) { _line_size[i] = ceil (_size.width * bytes_per_pixel(i)); - _stride[i] = stride_round_up (i, _line_size, _aligned ? ALIGNMENT : 1); + _stride[i] = stride_round_up (i, _line_size, _alignment == Alignment::PADDED ? ALIGNMENT : 1); /* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm) uses a 16-byte fetch to read three bytes (R/G/B) of image data. @@ -1011,7 +1012,7 @@ Image::Image (Image const & other) : std::enable_shared_from_this(other) , _size (other._size) , _pixel_format (other._pixel_format) - , _aligned (other._aligned) + , _alignment (other._alignment) { allocate (); @@ -1027,10 +1028,10 @@ Image::Image (Image const & other) } } -Image::Image (AVFrame const * frame, bool aligned) +Image::Image (AVFrame const * frame, Alignment alignment) : _size (frame->width, frame->height) , _pixel_format (static_cast(frame->format)) - , _aligned (aligned) + , _alignment (alignment) { DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE); @@ -1049,10 +1050,10 @@ Image::Image (AVFrame const * frame, bool aligned) } } -Image::Image (shared_ptr other, bool aligned) +Image::Image (shared_ptr other, Alignment alignment) : _size (other->_size) , _pixel_format (other->_pixel_format) - , _aligned (aligned) + , _alignment (alignment) { allocate (); @@ -1093,7 +1094,7 @@ Image::swap (Image & other) std::swap (_stride[i], other._stride[i]); } - std::swap (_aligned, other._aligned); + std::swap (_alignment, other._alignment); } Image::~Image () @@ -1131,15 +1132,15 @@ Image::size () const return _size; } -bool -Image::aligned () const +Image::Alignment +Image::alignment () const { - return _aligned; + return _alignment; } PositionImage -merge (list images, bool aligned) +merge (list images, Image::Alignment alignment) { if (images.empty ()) { return {}; @@ -1154,7 +1155,7 @@ merge (list images, bool aligned) all.extend (dcpomatic::Rect(i.position, i.image->size().width, i.image->size().height)); } - auto merged = make_shared(images.front().image->pixel_format(), dcp::Size(all.width, all.height), aligned); + auto merged = make_shared(images.front().image->pixel_format(), dcp::Size(all.width, all.height), alignment); merged->make_transparent (); for (auto const& i: images) { merged->alpha_blend (i.image, i.position - all.position()); @@ -1167,7 +1168,7 @@ merge (list images, bool aligned) bool operator== (Image const & a, Image const & b) { - if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.aligned() != b.aligned()) { + if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.alignment() != b.alignment()) { return false; } @@ -1314,13 +1315,13 @@ Image::fade (float f) shared_ptr -Image::ensure_aligned (shared_ptr image, bool aligned) +Image::ensure_alignment (shared_ptr image, Image::Alignment alignment) { - if (image->aligned() == aligned) { + if (image->alignment() == alignment) { return image; } - return make_shared(image, aligned); + return make_shared(image, alignment); } @@ -1395,7 +1396,7 @@ Image::as_png () const DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4); DCPOMATIC_ASSERT (planes() == 1); if (pixel_format() != AV_PIX_FMT_RGBA) { - return convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, true, false)->as_png(); + return convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, Image::Alignment::PADDED, false)->as_png(); } /* error handling? */ diff --git a/src/lib/image.h b/src/lib/image.h index 3cba8f7e5..128b546b5 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -40,10 +40,15 @@ class Socket; class Image : public std::enable_shared_from_this { public: - Image (AVPixelFormat p, dcp::Size s, bool aligned); - explicit Image (AVFrame const *, bool aligned); + enum class Alignment { + COMPACT, + PADDED + }; + + Image (AVPixelFormat p, dcp::Size s, Alignment alignment); + explicit Image (AVFrame const *, Alignment alignment); explicit Image (Image const &); - Image (std::shared_ptr, bool); + Image (std::shared_ptr, Alignment alignment); Image& operator= (Image const &); ~Image (); @@ -53,7 +58,7 @@ public: /** @return array of sizes of the data in each line, in bytes (including any alignment padding) */ int const * stride () const; dcp::Size size () const; - bool aligned () const; + Alignment alignment () const; int planes () const; int vertical_factor (int) const; @@ -61,8 +66,8 @@ public: dcp::Size sample_size (int) const; float bytes_per_pixel (int) const; - std::shared_ptr convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool aligned, bool fast) const; - std::shared_ptr scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool aligned, bool fast) const; + std::shared_ptr convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment alignment, bool fast) const; + std::shared_ptr scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment alignment, bool fast) const; std::shared_ptr crop_scale_window ( Crop crop, dcp::Size inter_size, @@ -71,7 +76,7 @@ public: VideoRange video_range, AVPixelFormat out_format, VideoRange out_video_range, - bool aligned, + Alignment alignment, bool fast ) const; @@ -94,7 +99,7 @@ public: void png_error (char const * message); - static std::shared_ptr ensure_aligned (std::shared_ptr image, bool aligned); + static std::shared_ptr ensure_alignment (std::shared_ptr image, Alignment alignment); private: friend struct pixel_formats_test; @@ -112,10 +117,10 @@ private: uint8_t** _data; ///< array of pointers to components int* _line_size; ///< array of sizes of the data in each line, in bytes (without any alignment padding bytes) int* _stride; ///< array of strides for each line, in bytes (including any alignment padding bytes) - bool _aligned; + Alignment _alignment; }; -extern PositionImage merge (std::list images, bool aligned); +extern PositionImage merge (std::list images, Image::Alignment alignment); extern bool operator== (Image const & a, Image const & b); #endif diff --git a/src/lib/image_examiner.cc b/src/lib/image_examiner.cc index 8b2096214..ae12d7adb 100644 --- a/src/lib/image_examiner.cc +++ b/src/lib/image_examiner.cc @@ -67,7 +67,7 @@ ImageExaminer::ImageExaminer (shared_ptr film, shared_ptrpath(0)); - _video_size = proxy.image(false).image->size(); + _video_size = proxy.image(Image::Alignment::COMPACT).image->size(); } if (content->still ()) { diff --git a/src/lib/image_proxy.h b/src/lib/image_proxy.h index 8817845d9..a37be580f 100644 --- a/src/lib/image_proxy.h +++ b/src/lib/image_proxy.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Carl Hetherington + Copyright (C) 2014-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,13 +18,17 @@ */ + #ifndef DCPOMATIC_IMAGE_PROXY_H #define DCPOMATIC_IMAGE_PROXY_H + /** @file src/lib/image_proxy.h * @brief ImageProxy and subclasses. */ + +#include "image.h" extern "C" { #include } @@ -32,6 +36,7 @@ extern "C" { #include #include + class Image; class Socket; @@ -43,6 +48,7 @@ namespace cxml { class Node; } + /** @class ImageProxy * @brief A class which holds an Image, and can produce it on request. * @@ -91,7 +97,7 @@ public: * can be used as an optimisation. */ virtual Result image ( - bool aligned, + Image::Alignment alignment, boost::optional size = boost::optional () ) const = 0; @@ -103,10 +109,12 @@ public: * This method may be called in a different thread to image(). * @return log2 of any scaling down that will be applied to the image. */ - virtual int prepare (bool, boost::optional = boost::optional()) const { return 0; } + virtual int prepare (Image::Alignment, boost::optional = boost::optional()) const { return 0; } virtual size_t memory_used () const = 0; }; + std::shared_ptr image_proxy_factory (std::shared_ptr xml, std::shared_ptr socket); + #endif diff --git a/src/lib/j2k_image_proxy.cc b/src/lib/j2k_image_proxy.cc index 21507ca15..00d3cf2ef 100644 --- a/src/lib/j2k_image_proxy.cc +++ b/src/lib/j2k_image_proxy.cc @@ -42,10 +42,8 @@ DCPOMATIC_ENABLE_WARNINGS using std::cout; using std::dynamic_pointer_cast; -using std::make_pair; using std::make_shared; using std::max; -using std::pair; using std::shared_ptr; using std::string; using boost::optional; @@ -120,7 +118,7 @@ J2KImageProxy::J2KImageProxy (shared_ptr xml, shared_ptr soc int -J2KImageProxy::prepare (bool aligned, optional target_size) const +J2KImageProxy::prepare (Image::Alignment alignment, optional target_size) const { boost::mutex::scoped_lock lm (_mutex); @@ -145,7 +143,7 @@ J2KImageProxy::prepare (bool aligned, optional target_size) const try { /* XXX: should check that potentially trashing _data here doesn't matter */ auto decompressed = dcp::decompress_j2k (const_cast(_data->data()), _data->size(), reduce); - _image = make_shared(_pixel_format, decompressed->size(), aligned); + _image = make_shared(_pixel_format, decompressed->size(), alignment); int const shift = 16 - decompressed->precision (0); @@ -169,7 +167,7 @@ J2KImageProxy::prepare (bool aligned, optional target_size) const } } } catch (dcp::J2KDecompressionError& e) { - _image = make_shared(_pixel_format, _size, aligned); + _image = make_shared(_pixel_format, _size, alignment); _image->make_black (); _error = true; } @@ -182,9 +180,9 @@ J2KImageProxy::prepare (bool aligned, optional target_size) const ImageProxy::Result -J2KImageProxy::image (bool aligned, optional target_size) const +J2KImageProxy::image (Image::Alignment alignment, optional target_size) const { - int const r = prepare (aligned, target_size); + int const r = prepare (alignment, target_size); /* I think this is safe without a lock on mutex. _image is guaranteed to be set up when prepare() has happened. diff --git a/src/lib/j2k_image_proxy.h b/src/lib/j2k_image_proxy.h index a23ec6d98..d925bef86 100644 --- a/src/lib/j2k_image_proxy.h +++ b/src/lib/j2k_image_proxy.h @@ -57,7 +57,7 @@ public: J2KImageProxy (dcp::ArrayData data, dcp::Size size, AVPixelFormat pixel_format); Result image ( - bool aligned, + Image::Alignment alignment, boost::optional size = boost::optional () ) const; @@ -65,7 +65,7 @@ public: void write_to_socket (std::shared_ptr) const; /** @return true if our image is definitely the same as another, false if it is probably not */ bool same (std::shared_ptr) const; - int prepare (bool aligned, boost::optional = boost::optional()) const; + int prepare (Image::Alignment alignment, boost::optional = boost::optional()) const; std::shared_ptr j2k () const { return _data; diff --git a/src/lib/player.cc b/src/lib/player.cc index 810d949d9..7c1a57aa9 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -95,12 +95,12 @@ int const PlayerProperty::DCP_DECODE_REDUCTION = 704; int const PlayerProperty::PLAYBACK_LENGTH = 705; -Player::Player (shared_ptr film, bool aligned) +Player::Player (shared_ptr film, Image::Alignment subtitle_alignment) : _film (film) , _suspended (0) , _tolerant (film->tolerant()) , _audio_merger (_film->audio_frame_rate()) - , _aligned_subtitles (aligned) + , _subtitle_alignment (subtitle_alignment) { construct (); } @@ -332,7 +332,7 @@ Player::set_video_container_size (dcp::Size s) _video_container_size = s; - _black_image.reset (new Image (AV_PIX_FMT_RGB24, _video_container_size, true)); + _black_image = make_shared(AV_PIX_FMT_RGB24, _video_container_size, Image::Alignment::PADDED); _black_image->make_black (); } @@ -828,7 +828,7 @@ Player::open_subtitles_for_frame (DCPTime time) const return {}; } - return merge (captions, _aligned_subtitles); + return merge (captions, _subtitle_alignment); } @@ -1056,7 +1056,7 @@ Player::bitmap_text_start (weak_ptr wp, weak_ptr wc, C } dcp::Size scaled_size (width, height); - ps.bitmap.push_back (BitmapText(image->scale(scaled_size, dcp::YUVToRGB::REC601, image->pixel_format(), true, _fast), subtitle.sub.rectangle)); + ps.bitmap.push_back (BitmapText(image->scale(scaled_size, dcp::YUVToRGB::REC601, image->pixel_format(), Image::Alignment::PADDED, _fast), subtitle.sub.rectangle)); DCPTime from (content_time_to_dcp (piece, subtitle.from())); _active_texts[static_cast(text->type())].add_from (wc, ps, from); diff --git a/src/lib/player.h b/src/lib/player.h index 767218379..b74aeeefd 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -34,6 +34,7 @@ #include "content_video.h" #include "empty.h" #include "film.h" +#include "image.h" #include "piece.h" #include "player_text.h" #include "position_image.h" @@ -76,7 +77,7 @@ public: class Player : public std::enable_shared_from_this { public: - Player (std::shared_ptr, bool aligned_subtitles); + Player (std::shared_ptr, Image::Alignment subtitle_alignment); Player (std::shared_ptr, std::shared_ptr playlist); Player (Player const& Player) = delete; @@ -233,8 +234,8 @@ private: dcpomatic::DCPTime _playback_length; - /** aligned flag for subtitle images that we create */ - bool _aligned_subtitles = true; + /** Alignment for subtitle images that we create */ + Image::Alignment _subtitle_alignment = Image::Alignment::PADDED; boost::signals2::scoped_connection _film_changed_connection; boost::signals2::scoped_connection _playlist_change_connection; diff --git a/src/lib/player_video.cc b/src/lib/player_video.cc index a687e7ea5..2d60efe10 100644 --- a/src/lib/player_video.cc +++ b/src/lib/player_video.cc @@ -94,7 +94,7 @@ PlayerVideo::PlayerVideo (shared_ptr node, shared_ptr socket if (node->optional_number_child("SubtitleX")) { auto image = make_shared ( - AV_PIX_FMT_BGRA, dcp::Size(node->number_child("SubtitleWidth"), node->number_child("SubtitleHeight")), true + AV_PIX_FMT_BGRA, dcp::Size(node->number_child("SubtitleWidth"), node->number_child("SubtitleHeight")), Image::Alignment::PADDED ); image->read_from_socket (socket); @@ -110,13 +110,13 @@ PlayerVideo::set_text (PositionImage image) } shared_ptr -PlayerVideo::image (function pixel_format, VideoRange video_range, bool aligned, bool fast) const +PlayerVideo::image (function pixel_format, VideoRange video_range, Image::Alignment alignment, bool fast) const { /* XXX: this assumes that image() and prepare() are only ever called with the same parameters (except crop, inter size, out size, fade) */ boost::mutex::scoped_lock lm (_mutex); if (!_image || _crop != _image_crop || _inter_size != _image_inter_size || _out_size != _image_out_size || _fade != _image_fade) { - make_image (pixel_format, video_range, aligned, fast); + make_image (pixel_format, video_range, alignment, fast); } return _image; } @@ -125,7 +125,7 @@ PlayerVideo::image (function pixel_format, VideoR shared_ptr PlayerVideo::raw_image () const { - return _in->image(false, _inter_size).image; + return _in->image(Image::Alignment::COMPACT, _inter_size).image; } @@ -133,18 +133,18 @@ PlayerVideo::raw_image () const * @param pixel_format Function which is called to decide what pixel format the output image should be; * it is passed the pixel format of the input image from the ImageProxy, and should return the desired * output pixel format. Two functions force and keep_xyz_or_rgb are provided for use here. - * @param aligned true if the output image should be aligned to 32-byte boundaries. + * @param alignment PADDED if the output image should be aligned to 32-byte boundaries, otherwise COMPACT. * @param fast true to be fast at the expense of quality. */ void -PlayerVideo::make_image (function pixel_format, VideoRange video_range, bool aligned, bool fast) const +PlayerVideo::make_image (function pixel_format, VideoRange video_range, Image::Alignment alignment, bool fast) const { _image_crop = _crop; _image_inter_size = _inter_size; _image_out_size = _out_size; _image_fade = _fade; - auto prox = _in->image (true, _inter_size); + auto prox = _in->image (Image::Alignment::PADDED, _inter_size); _error = prox.error; auto total_crop = _crop; @@ -180,11 +180,11 @@ PlayerVideo::make_image (function pixel_format, V } _image = prox.image->crop_scale_window ( - total_crop, _inter_size, _out_size, yuv_to_rgb, _video_range, pixel_format (prox.image->pixel_format()), video_range, aligned, fast + total_crop, _inter_size, _out_size, yuv_to_rgb, _video_range, pixel_format (prox.image->pixel_format()), video_range, alignment, fast ); if (_text) { - _image->alpha_blend (Image::ensure_aligned(_text->image, true), _text->position); + _image->alpha_blend (Image::ensure_alignment(_text->image, Image::Alignment::PADDED), _text->position); } if (_fade) { @@ -298,12 +298,12 @@ PlayerVideo::keep_xyz_or_rgb (AVPixelFormat p) } void -PlayerVideo::prepare (function pixel_format, VideoRange video_range, bool aligned, bool fast, bool proxy_only) +PlayerVideo::prepare (function pixel_format, VideoRange video_range, Image::Alignment alignment, bool fast, bool proxy_only) { - _in->prepare (aligned, _inter_size); + _in->prepare (alignment, _inter_size); boost::mutex::scoped_lock lm (_mutex); if (!_image && !proxy_only) { - make_image (pixel_format, video_range, aligned, fast); + make_image (pixel_format, video_range, alignment, fast); } } diff --git a/src/lib/player_video.h b/src/lib/player_video.h index 872bc9864..d24620c7e 100644 --- a/src/lib/player_video.h +++ b/src/lib/player_video.h @@ -23,11 +23,12 @@ #define DCPOMATIC_PLAYER_VIDEO_H -#include "types.h" -#include "position.h" -#include "dcpomatic_time.h" #include "colour_conversion.h" +#include "dcpomatic_time.h" +#include "image.h" +#include "position.h" #include "position_image.h" +#include "types.h" extern "C" { #include } @@ -74,8 +75,8 @@ public: return _text; } - void prepare (std::function pixel_format, VideoRange video_range, bool aligned, bool fast, bool proxy_only); - std::shared_ptr image (std::function pixel_format, VideoRange video_range, bool aligned, bool fast) const; + void prepare (std::function pixel_format, VideoRange video_range, Image::Alignment alignment, bool fast, bool proxy_only); + std::shared_ptr image (std::function pixel_format, VideoRange video_range, Image::Alignment alignment, bool fast) const; std::shared_ptr raw_image () const; static AVPixelFormat force (AVPixelFormat, AVPixelFormat); @@ -126,7 +127,7 @@ public: } private: - void make_image (std::function pixel_format, VideoRange video_range, bool aligned, bool fast) const; + void make_image (std::function pixel_format, VideoRange video_range, Image::Alignment alignment, bool fast) const; std::shared_ptr _in; Crop _crop; diff --git a/src/lib/raw_image_proxy.cc b/src/lib/raw_image_proxy.cc index ac8ff0763..fb0d16df8 100644 --- a/src/lib/raw_image_proxy.cc +++ b/src/lib/raw_image_proxy.cc @@ -58,16 +58,16 @@ RawImageProxy::RawImageProxy (shared_ptr xml, shared_ptr soc xml->number_child("Width"), xml->number_child("Height") ); - _image = make_shared(static_cast(xml->number_child("PixelFormat")), size, true); + _image = make_shared(static_cast(xml->number_child("PixelFormat")), size, Image::Alignment::PADDED); _image->read_from_socket (socket); } ImageProxy::Result -RawImageProxy::image (bool aligned, optional) const +RawImageProxy::image (Image::Alignment alignment, optional) const { - /* This ensure_aligned could be wasteful */ - return Result (Image::ensure_aligned(_image, aligned), 0); + /* This ensure_alignment could be wasteful */ + return Result (Image::ensure_alignment(_image, alignment), 0); } @@ -96,7 +96,7 @@ RawImageProxy::same (shared_ptr other) const return false; } - return (*_image.get()) == (*rp->image(_image->aligned()).image.get()); + return (*_image.get()) == (*rp->image(_image->alignment()).image.get()); } diff --git a/src/lib/raw_image_proxy.h b/src/lib/raw_image_proxy.h index 7e0861104..c9885654b 100644 --- a/src/lib/raw_image_proxy.h +++ b/src/lib/raw_image_proxy.h @@ -33,7 +33,7 @@ public: RawImageProxy (std::shared_ptr xml, std::shared_ptr socket); Result image ( - bool aligned, + Image::Alignment alignment, boost::optional size = boost::optional () ) const; diff --git a/src/lib/render_text.cc b/src/lib/render_text.cc index 7bb7d6b45..96b832c57 100644 --- a/src/lib/render_text.cc +++ b/src/lib/render_text.cc @@ -96,7 +96,7 @@ static shared_ptr create_image (dcp::Size size) { /* FFmpeg BGRA means first byte blue, second byte green, third byte red, fourth byte alpha */ - auto image = make_shared(AV_PIX_FMT_BGRA, size, false); + auto image = make_shared(AV_PIX_FMT_BGRA, size, Image::Alignment::COMPACT); image->make_black (); return image; } diff --git a/src/lib/util.cc b/src/lib/util.cc index c65b2bc85..981cfa521 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -22,31 +22,33 @@ * @brief Some utility functions and classes. */ + #define UNICODE 1 -#include "util.h" -#include "exceptions.h" -#include "dcp_content_type.h" -#include "filter.h" + +#include "audio_buffers.h" +#include "audio_processor.h" #include "cinema_sound_processor.h" +#include "compose.hpp" #include "config.h" -#include "ratio.h" -#include "job.h" #include "cross.h" -#include "video_content.h" -#include "rect.h" -#include "digester.h" -#include "audio_processor.h" #include "crypto.h" -#include "compose.hpp" -#include "audio_buffers.h" -#include "string_text.h" -#include "font.h" -#include "render_text.h" +#include "dcp_content_type.h" +#include "digester.h" +#include "exceptions.h" #include "ffmpeg_image_proxy.h" +#include "filter.h" +#include "font.h" #include "image.h" -#include "text_decoder.h" +#include "job.h" #include "job_manager.h" +#include "ratio.h" +#include "rect.h" +#include "render_text.h" +#include "string_text.h" +#include "text_decoder.h" +#include "util.h" +#include "video_content.h" #include "warnings.h" #include #include @@ -93,25 +95,23 @@ DCPOMATIC_ENABLE_WARNINGS #include "i18n.h" -using std::string; -using std::wstring; -using std::setfill; -using std::ostream; + +using std::bad_alloc; +using std::cout; using std::endl; -using std::vector; -using std::min; -using std::max; -using std::map; -using std::list; -using std::multimap; using std::istream; +using std::list; +using std::make_pair; +using std::make_shared; +using std::map; +using std::min; +using std::ostream; using std::pair; -using std::cout; -using std::bad_alloc; using std::set_terminate; -using std::make_pair; using std::shared_ptr; -using std::make_shared; +using std::string; +using std::vector; +using std::wstring; using boost::thread; using boost::optional; using boost::lexical_cast; @@ -122,6 +122,7 @@ using dcp::raw_convert; using dcp::locale_convert; using namespace dcpomatic; + /** Path to our executable, required by the stacktrace stuff and filled * in during App::onInit(). */ @@ -956,7 +957,7 @@ emit_subtitle_image (ContentTimePeriod period, dcp::SubtitleImage sub, dcp::Size { /* XXX: this is rather inefficient; decoding the image just to get its size */ FFmpegImageProxy proxy (sub.png_image()); - auto image = proxy.image(false).image; + auto image = proxy.image(Image::Alignment::COMPACT).image; /* set up rect with height and width */ dcpomatic::Rect rect(0, 0, image->size().width / double(size.width), image->size().height / double(size.height)); diff --git a/src/lib/video_filter_graph.cc b/src/lib/video_filter_graph.cc index b4198da72..0c7e23b05 100644 --- a/src/lib/video_filter_graph.cc +++ b/src/lib/video_filter_graph.cc @@ -38,7 +38,6 @@ using std::make_shared; using std::pair; using std::shared_ptr; using std::string; -using std::vector; VideoFilterGraph::VideoFilterGraph (dcp::Size s, AVPixelFormat p, dcp::Fraction r) @@ -59,7 +58,7 @@ VideoFilterGraph::process (AVFrame* frame) list, int64_t>> images; if (_copy) { - images.push_back (make_pair(make_shared(frame, true), frame->best_effort_timestamp)); + images.push_back (make_pair(make_shared(frame, Image::Alignment::PADDED), frame->best_effort_timestamp)); } else { int r = av_buffersrc_write_frame (_buffer_src_context, frame); if (r < 0) { @@ -71,7 +70,7 @@ VideoFilterGraph::process (AVFrame* frame) break; } - images.push_back (make_pair(make_shared(_frame, true), frame->best_effort_timestamp)); + images.push_back (make_pair(make_shared(_frame, Image::Alignment::PADDED), frame->best_effort_timestamp)); av_frame_unref (_frame); } } diff --git a/src/tools/server_test.cc b/src/tools/server_test.cc index e32fd327e..ff3295599 100644 --- a/src/tools/server_test.cc +++ b/src/tools/server_test.cc @@ -155,7 +155,7 @@ main (int argc, char* argv[]) film = make_shared(film_dir); film->read_metadata (); - auto player = make_shared(film, false); + auto player = make_shared(film, Image::Alignment::COMPACT); player->Video.connect (bind(&process_video, _1)); while (!player->pass ()) {} } catch (std::exception& e) { diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 735ba02eb..5609ebf86 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -63,17 +63,11 @@ extern "C" { using std::bad_alloc; using std::cout; using std::dynamic_pointer_cast; -using std::exception; -using std::list; -using std::make_pair; using std::make_shared; using std::max; -using std::min; -using std::pair; using std::shared_ptr; using std::string; using std::vector; -using std::weak_ptr; using boost::optional; #if BOOST_VERSION >= 106100 using namespace boost::placeholders; @@ -169,7 +163,7 @@ FilmViewer::set_film (shared_ptr film) } try { - _player = make_shared(_film, !_optimise_for_j2k); + _player = make_shared(_film, _optimise_for_j2k ? Image::Alignment::COMPACT : Image::Alignment::PADDED); _player->set_fast (); if (_dcp_decode_reduction) { _player->set_dcp_decode_reduction (_dcp_decode_reduction); @@ -221,7 +215,7 @@ FilmViewer::recreate_butler () _audio_channels, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, - !_optimise_for_j2k, + _optimise_for_j2k ? Image::Alignment::COMPACT : Image::Alignment::PADDED, true, dynamic_pointer_cast(_video_view) && _optimise_for_j2k ); diff --git a/src/wx/gl_video_view.cc b/src/wx/gl_video_view.cc index 6288a24a3..046465864 100644 --- a/src/wx/gl_video_view.cc +++ b/src/wx/gl_video_view.cc @@ -497,12 +497,12 @@ GLVideoView::draw (Position, dcp::Size) void GLVideoView::set_image (shared_ptr pv) { - shared_ptr video = _optimise_for_j2k ? pv->raw_image() : pv->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true); + shared_ptr video = _optimise_for_j2k ? pv->raw_image() : pv->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, true); /* Only the player's black frames should be aligned at this stage, so this should * almost always have no work to do. */ - video = Image::ensure_aligned (video, false); + video = Image::ensure_alignment (video, Image::Alignment::COMPACT); /** If _optimise_for_j2k is true we render a XYZ image, doing the colourspace * conversion, scaling and video range conversion in the GL shader. @@ -517,7 +517,7 @@ GLVideoView::set_image (shared_ptr pv) _have_subtitle_to_render = static_cast(text) && _optimise_for_j2k; if (_have_subtitle_to_render) { /* opt: only do this if it's a new subtitle? */ - DCPOMATIC_ASSERT (!text->image->aligned()); + DCPOMATIC_ASSERT (text->image->alignment() == Image::Alignment::COMPACT); _subtitle_texture->set (text->image); } @@ -788,7 +788,7 @@ Texture::set (shared_ptr image) glPixelStorei (GL_UNPACK_ALIGNMENT, _unpack_alignment); check_gl_error ("glPixelStorei"); - DCPOMATIC_ASSERT (!image->aligned()); + DCPOMATIC_ASSERT (image->alignment() == Image::Alignment::COMPACT); GLint internal_format; GLenum format; diff --git a/src/wx/simple_video_view.cc b/src/wx/simple_video_view.cc index 5dd47ce4c..e54c8390e 100644 --- a/src/wx/simple_video_view.cc +++ b/src/wx/simple_video_view.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2019 Carl Hetherington + Copyright (C) 2019-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,21 +18,23 @@ */ -#include "simple_video_view.h" + +#include "closed_captions_dialog.h" #include "film_viewer.h" +#include "simple_video_view.h" #include "wx_util.h" -#include "closed_captions_dialog.h" -#include "lib/image.h" -#include "lib/dcpomatic_log.h" #include "lib/butler.h" +#include "lib/dcpomatic_log.h" +#include "lib/image.h" #include #include #include + using std::max; +using std::shared_ptr; using std::string; using boost::optional; -using std::shared_ptr; #if BOOST_VERSION >= 106100 using namespace boost::placeholders; #endif @@ -57,6 +59,7 @@ SimpleVideoView::SimpleVideoView (FilmViewer* viewer, wxWindow* parent) _timer.Bind (wxEVT_TIMER, boost::bind(&SimpleVideoView::timer, this)); } + void SimpleVideoView::paint () { @@ -113,6 +116,7 @@ SimpleVideoView::paint () _state_timer.unset(); } + void SimpleVideoView::refresh_panel () { @@ -122,6 +126,7 @@ SimpleVideoView::refresh_panel () _state_timer.unset (); } + void SimpleVideoView::timer () { @@ -145,6 +150,7 @@ SimpleVideoView::timer () } } + void SimpleVideoView::start () { @@ -152,6 +158,7 @@ SimpleVideoView::start () timer (); } + /** Try to get a frame from the butler and display it. * @param non_blocking true to return false quickly if no video is available quickly (i.e. we are waiting for the butler). * false to ask the butler to block until it has video (unless it is suspended). @@ -176,6 +183,7 @@ SimpleVideoView::display_next_frame (bool non_blocking) return SUCCESS; } + void SimpleVideoView::update () { @@ -214,7 +222,7 @@ SimpleVideoView::update () _state_timer.set ("get image"); set_image ( - player_video().first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true) + player_video().first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, true) ); _state_timer.set ("ImageChanged"); diff --git a/src/wx/video_waveform_plot.cc b/src/wx/video_waveform_plot.cc index 2e45f3493..07b2955b3 100644 --- a/src/wx/video_waveform_plot.cc +++ b/src/wx/video_waveform_plot.cc @@ -155,7 +155,7 @@ VideoWaveformPlot::create_waveform () auto const image_size = _image->size(); int const waveform_height = GetSize().GetHeight() - _vertical_margin * 2; - _waveform = make_shared(AV_PIX_FMT_RGB24, dcp::Size (image_size.width, waveform_height), true); + _waveform = make_shared(AV_PIX_FMT_RGB24, dcp::Size (image_size.width, waveform_height), Image::Alignment::PADDED); for (int x = 0; x < image_size.width; ++x) { @@ -182,7 +182,7 @@ VideoWaveformPlot::create_waveform () _waveform = _waveform->scale ( dcp::Size (GetSize().GetWidth() - _x_axis_width, waveform_height), - dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, false, false + dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, Image::Alignment::COMPACT, false ); } diff --git a/test/butler_test.cc b/test/butler_test.cc index 99bd95fce..787d1c324 100644 --- a/test/butler_test.cc +++ b/test/butler_test.cc @@ -59,7 +59,7 @@ BOOST_AUTO_TEST_CASE (butler_test1) map.set (i, i, 1); } - Butler butler (film, make_shared(film, false), map, 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, false, false); + Butler butler (film, make_shared(film, Image::Alignment::COMPACT), map, 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, false, false); BOOST_CHECK (butler.get_video(true, 0).second == DCPTime()); BOOST_CHECK (butler.get_video(true, 0).second == DCPTime::from_frames(1, 24)); diff --git a/test/client_server_test.cc b/test/client_server_test.cc index f518f9383..7a99f7227 100644 --- a/test/client_server_test.cc +++ b/test/client_server_test.cc @@ -66,7 +66,7 @@ do_remote_encode (shared_ptr frame, EncodeServerDescription descriptio BOOST_AUTO_TEST_CASE (client_server_test_rgb) { - auto image = make_shared(AV_PIX_FMT_RGB24, dcp::Size (1998, 1080), true); + auto image = make_shared(AV_PIX_FMT_RGB24, dcp::Size (1998, 1080), Image::Alignment::PADDED); uint8_t* p = image->data()[0]; for (int y = 0; y < 1080; ++y) { @@ -79,7 +79,7 @@ BOOST_AUTO_TEST_CASE (client_server_test_rgb) p += image->stride()[0]; } - auto sub_image = make_shared(AV_PIX_FMT_BGRA, dcp::Size (100, 200), true); + auto sub_image = make_shared(AV_PIX_FMT_BGRA, dcp::Size (100, 200), Image::Alignment::PADDED); p = sub_image->data()[0]; for (int y = 0; y < 200; ++y) { uint8_t* q = p; @@ -153,7 +153,7 @@ BOOST_AUTO_TEST_CASE (client_server_test_rgb) BOOST_AUTO_TEST_CASE (client_server_test_yuv) { - auto image = make_shared(AV_PIX_FMT_YUV420P, dcp::Size (1998, 1080), true); + auto image = make_shared(AV_PIX_FMT_YUV420P, dcp::Size (1998, 1080), Image::Alignment::PADDED); for (int i = 0; i < image->planes(); ++i) { uint8_t* p = image->data()[i]; @@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE (client_server_test_yuv) } } - auto sub_image = make_shared(AV_PIX_FMT_BGRA, dcp::Size (100, 200), true); + auto sub_image = make_shared(AV_PIX_FMT_BGRA, dcp::Size (100, 200), Image::Alignment::PADDED); uint8_t* p = sub_image->data()[0]; for (int y = 0; y < 200; ++y) { uint8_t* q = p; @@ -236,7 +236,7 @@ BOOST_AUTO_TEST_CASE (client_server_test_yuv) BOOST_AUTO_TEST_CASE (client_server_test_j2k) { - auto image = make_shared(AV_PIX_FMT_YUV420P, dcp::Size (1998, 1080), true); + auto image = make_shared(AV_PIX_FMT_YUV420P, dcp::Size (1998, 1080), Image::Alignment::PADDED); for (int i = 0; i < image->planes(); ++i) { uint8_t* p = image->data()[i]; diff --git a/test/dcp_decoder_test.cc b/test/dcp_decoder_test.cc index 9461effc5..66cd402c4 100644 --- a/test/dcp_decoder_test.cc +++ b/test/dcp_decoder_test.cc @@ -87,7 +87,7 @@ BOOST_AUTO_TEST_CASE (check_reuse_old_data_test) ov_content = make_shared(ov->dir(ov->dcp_name(false))); test->examine_and_add_content (ov_content); BOOST_REQUIRE (!wait_for_jobs()); - auto player = make_shared(test, false); + auto player = make_shared(test, Image::Alignment::COMPACT); auto decoder = std::dynamic_pointer_cast(player->_pieces.front()->decoder); BOOST_REQUIRE (decoder); @@ -105,7 +105,7 @@ BOOST_AUTO_TEST_CASE (check_reuse_old_data_test) auto vf_content = make_shared(vf->dir(vf->dcp_name(false))); test->examine_and_add_content (vf_content); BOOST_REQUIRE (!wait_for_jobs()); - player = make_shared(test, false); + player = make_shared(test, Image::Alignment::COMPACT); decoder = std::dynamic_pointer_cast(player->_pieces.front()->decoder); BOOST_REQUIRE (decoder); @@ -123,7 +123,7 @@ BOOST_AUTO_TEST_CASE (check_reuse_old_data_test) auto encrypted_content = make_shared(encrypted->dir(encrypted->dcp_name(false))); test->examine_and_add_content (encrypted_content); BOOST_REQUIRE (!wait_for_jobs()); - player = make_shared(test, false); + player = make_shared(test, Image::Alignment::COMPACT); decoder = std::dynamic_pointer_cast(player->_pieces.front()->decoder); BOOST_REQUIRE (decoder); diff --git a/test/dcp_playback_test.cc b/test/dcp_playback_test.cc index 2ea638d74..28368dc34 100644 --- a/test/dcp_playback_test.cc +++ b/test/dcp_playback_test.cc @@ -45,12 +45,12 @@ BOOST_AUTO_TEST_CASE (dcp_playback_test) auto butler = std::make_shared( film, - make_shared(film, false), + make_shared(film, Image::Alignment::COMPACT), AudioMapping(6, 6), 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, - false, + Image::Alignment::COMPACT, true, false ); @@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE (dcp_playback_test) } /* assuming DCP is 24fps/48kHz */ butler->get_audio (audio_buffer, 2000); - p.first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true); + p.first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, true); } delete[] audio_buffer; } diff --git a/test/ffmpeg_audio_only_test.cc b/test/ffmpeg_audio_only_test.cc index 9f185fdf3..40c909b39 100644 --- a/test/ffmpeg_audio_only_test.cc +++ b/test/ffmpeg_audio_only_test.cc @@ -101,7 +101,7 @@ test (boost::filesystem::path file) ref_buffer_size = info.samplerate * info.channels; ref_buffer = new float[ref_buffer_size]; - auto player = make_shared(film, false); + auto player = make_shared(film, Image::Alignment::COMPACT); player->Audio.connect (bind (&audio, _1, info.channels)); while (!player->pass ()) {} diff --git a/test/ffmpeg_audio_test.cc b/test/ffmpeg_audio_test.cc index 0cc602a9a..6bdadce97 100644 --- a/test/ffmpeg_audio_test.cc +++ b/test/ffmpeg_audio_test.cc @@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_audio_test2) film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs ()); - auto player = make_shared(film, false); + auto player = make_shared(film, Image::Alignment::COMPACT); while (!player->pass ()) {} } @@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_audio_test3) film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs ()); - auto player = make_shared(film, false); + auto player = make_shared(film, Image::Alignment::COMPACT); player->set_fast (); while (!player->pass ()) {} } @@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_audio_test4) film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs ()); - auto player = make_shared(film, false); + auto player = make_shared(film, Image::Alignment::COMPACT); player->set_fast (); BOOST_CHECK_NO_THROW (while (!player->pass()) {}); } diff --git a/test/ffmpeg_decoder_sequential_test.cc b/test/ffmpeg_decoder_sequential_test.cc index 7d6d547ff..73eea719f 100644 --- a/test/ffmpeg_decoder_sequential_test.cc +++ b/test/ffmpeg_decoder_sequential_test.cc @@ -75,7 +75,7 @@ ffmpeg_decoder_sequential_test_one (boost::filesystem::path file, float fps, int film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs()); film->write_metadata (); - auto player = make_shared(film, false); + auto player = make_shared(film, Image::Alignment::COMPACT); BOOST_REQUIRE (content->video_frame_rate()); BOOST_CHECK_CLOSE (content->video_frame_rate().get(), fps, 0.01); diff --git a/test/image_test.cc b/test/image_test.cc index 9d0d43664..395aef8fd 100644 --- a/test/image_test.cc +++ b/test/image_test.cc @@ -39,13 +39,12 @@ using std::cout; using std::list; using std::make_shared; -using std::shared_ptr; using std::string; BOOST_AUTO_TEST_CASE (aligned_image_test) { - auto s = new Image (AV_PIX_FMT_RGB24, dcp::Size (50, 50), true); + auto s = new Image (AV_PIX_FMT_RGB24, dcp::Size (50, 50), Image::Alignment::PADDED); BOOST_CHECK_EQUAL (s->planes(), 1); /* 192 is 150 aligned to the nearest 64 bytes */ BOOST_CHECK_EQUAL (s->stride()[0], 192); @@ -72,7 +71,7 @@ BOOST_AUTO_TEST_CASE (aligned_image_test) BOOST_CHECK_EQUAL (t->stride()[0], s->stride()[0]); /* assignment operator */ - auto u = new Image (AV_PIX_FMT_YUV422P, dcp::Size (150, 150), false); + auto u = new Image (AV_PIX_FMT_YUV422P, dcp::Size (150, 150), Image::Alignment::COMPACT); *u = *s; BOOST_CHECK_EQUAL (u->planes(), 1); BOOST_CHECK_EQUAL (u->stride()[0], 192); @@ -96,7 +95,7 @@ BOOST_AUTO_TEST_CASE (aligned_image_test) BOOST_AUTO_TEST_CASE (compact_image_test) { - auto s = new Image (AV_PIX_FMT_RGB24, dcp::Size (50, 50), false); + auto s = new Image (AV_PIX_FMT_RGB24, dcp::Size (50, 50), Image::Alignment::COMPACT); BOOST_CHECK_EQUAL (s->planes(), 1); BOOST_CHECK_EQUAL (s->stride()[0], 50 * 3); BOOST_CHECK_EQUAL (s->line_size()[0], 50 * 3); @@ -122,7 +121,7 @@ BOOST_AUTO_TEST_CASE (compact_image_test) BOOST_CHECK_EQUAL (t->stride()[0], s->stride()[0]); /* assignment operator */ - auto u = new Image (AV_PIX_FMT_YUV422P, dcp::Size (150, 150), true); + auto u = new Image (AV_PIX_FMT_YUV422P, dcp::Size (150, 150), Image::Alignment::PADDED); *u = *s; BOOST_CHECK_EQUAL (u->planes(), 1); BOOST_CHECK_EQUAL (u->stride()[0], 50 * 3); @@ -148,10 +147,10 @@ void alpha_blend_test_one (AVPixelFormat format, string suffix) { auto proxy = make_shared(TestPaths::private_data() / "prophet_frame.tiff"); - auto raw = proxy->image(false).image; - auto background = raw->convert_pixel_format (dcp::YUVToRGB::REC709, format, true, false); + auto raw = proxy->image(Image::Alignment::COMPACT).image; + auto background = raw->convert_pixel_format (dcp::YUVToRGB::REC709, format, Image::Alignment::PADDED, false); - auto overlay = make_shared(AV_PIX_FMT_BGRA, dcp::Size(431, 891), true); + auto overlay = make_shared(AV_PIX_FMT_BGRA, dcp::Size(431, 891), Image::Alignment::PADDED); overlay->make_transparent (); for (int y = 0; y < 128; ++y) { @@ -180,7 +179,7 @@ alpha_blend_test_one (AVPixelFormat format, string suffix) background->alpha_blend (overlay, Position (13, 17)); - auto save = background->convert_pixel_format (dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, false, false); + auto save = background->convert_pixel_format (dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, Image::Alignment::COMPACT, false); write_image (save, "build/test/image_test_" + suffix + ".png"); check_image ("build/test/image_test_" + suffix + ".png", TestPaths::private_data() / ("image_test_" + suffix + ".png")); @@ -205,7 +204,7 @@ BOOST_AUTO_TEST_CASE (merge_test1) { int const stride = 48 * 4; - auto A = make_shared(AV_PIX_FMT_BGRA, dcp::Size (48, 48), false); + auto A = make_shared(AV_PIX_FMT_BGRA, dcp::Size (48, 48), Image::Alignment::COMPACT); A->make_transparent (); auto a = A->data()[0]; @@ -221,7 +220,7 @@ BOOST_AUTO_TEST_CASE (merge_test1) list all; all.push_back (PositionImage (A, Position(0, 0))); - auto merged = merge (all, false); + auto merged = merge (all, Image::Alignment::COMPACT); BOOST_CHECK (merged.position == Position(0, 0)); BOOST_CHECK_EQUAL (memcmp (merged.image->data()[0], A->data()[0], stride * 48), 0); @@ -231,7 +230,7 @@ BOOST_AUTO_TEST_CASE (merge_test1) /** Test merge (list) with two images */ BOOST_AUTO_TEST_CASE (merge_test2) { - auto A = make_shared(AV_PIX_FMT_BGRA, dcp::Size (48, 1), false); + auto A = make_shared(AV_PIX_FMT_BGRA, dcp::Size (48, 1), Image::Alignment::COMPACT); A->make_transparent (); auto a = A->data()[0]; for (int x = 0; x < 16; ++x) { @@ -241,7 +240,7 @@ BOOST_AUTO_TEST_CASE (merge_test2) a[x * 4 + 3] = 255; } - auto B = make_shared(AV_PIX_FMT_BGRA, dcp::Size (48, 1), false); + auto B = make_shared(AV_PIX_FMT_BGRA, dcp::Size (48, 1), Image::Alignment::COMPACT); B->make_transparent (); auto b = B->data()[0]; for (int x = 0; x < 16; ++x) { @@ -254,7 +253,7 @@ BOOST_AUTO_TEST_CASE (merge_test2) list all; all.push_back (PositionImage(A, Position(0, 0))); all.push_back (PositionImage(B, Position(0, 0))); - auto merged = merge (all, false); + auto merged = merge (all, Image::Alignment::COMPACT); BOOST_CHECK (merged.position == Position(0, 0)); @@ -274,11 +273,11 @@ BOOST_AUTO_TEST_CASE (merge_test2) BOOST_AUTO_TEST_CASE (crop_scale_window_test) { auto proxy = make_shared("test/data/flat_red.png"); - auto raw = proxy->image(false).image; + auto raw = proxy->image(Image::Alignment::COMPACT).image; auto out = raw->crop_scale_window( - Crop(), dcp::Size(1998, 836), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_YUV420P, VideoRange::FULL, true, false + Crop(), dcp::Size(1998, 836), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_YUV420P, VideoRange::FULL, Image::Alignment::PADDED, false ); - auto save = out->scale(dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, false, false); + auto save = out->scale(dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, Image::Alignment::COMPACT, false); write_image(save, "build/test/crop_scale_window_test.png"); check_image("test/data/crop_scale_window_test.png", "build/test/crop_scale_window_test.png"); } @@ -287,12 +286,12 @@ BOOST_AUTO_TEST_CASE (crop_scale_window_test) /** Special cases of Image::crop_scale_window which triggered some valgrind warnings */ BOOST_AUTO_TEST_CASE (crop_scale_window_test2) { - auto image = make_shared(AV_PIX_FMT_XYZ12LE, dcp::Size(2048, 858), true); + auto image = make_shared(AV_PIX_FMT_XYZ12LE, dcp::Size(2048, 858), Image::Alignment::PADDED); image->crop_scale_window ( - Crop(279, 0, 0, 0), dcp::Size(1069, 448), dcp::Size(1069, 578), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, false, false + Crop(279, 0, 0, 0), dcp::Size(1069, 448), dcp::Size(1069, 578), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, Image::Alignment::COMPACT, false ); image->crop_scale_window ( - Crop(2048, 0, 0, 0), dcp::Size(1069, 448), dcp::Size(1069, 578), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, false, false + Crop(2048, 0, 0, 0), dcp::Size(1069, 448), dcp::Size(1069, 578), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, Image::Alignment::COMPACT, false ); } @@ -300,9 +299,9 @@ BOOST_AUTO_TEST_CASE (crop_scale_window_test2) BOOST_AUTO_TEST_CASE (crop_scale_window_test3) { auto proxy = make_shared(TestPaths::private_data() / "player_seek_test_0.png"); - auto xyz = proxy->image(false).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, true, false); + auto xyz = proxy->image(Image::Alignment::COMPACT).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, Image::Alignment::PADDED, false); auto cropped = xyz->crop_scale_window( - Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, false, false + Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, Image::Alignment::COMPACT, false ); write_image(cropped, "build/test/crop_scale_window_test3.png"); check_image("test/data/crop_scale_window_test3.png", "build/test/crop_scale_window_test3.png"); @@ -312,9 +311,9 @@ BOOST_AUTO_TEST_CASE (crop_scale_window_test3) BOOST_AUTO_TEST_CASE (crop_scale_window_test4) { auto proxy = make_shared(TestPaths::private_data() / "player_seek_test_0.png"); - auto xyz = proxy->image(false).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, true, false); + auto xyz = proxy->image(Image::Alignment::COMPACT).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, Image::Alignment::PADDED, false); auto cropped = xyz->crop_scale_window( - Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_XYZ12LE, VideoRange::FULL, false, false + Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_XYZ12LE, VideoRange::FULL, Image::Alignment::COMPACT, false ); write_image(cropped, "build/test/crop_scale_window_test4.png"); check_image("test/data/crop_scale_window_test4.png", "build/test/crop_scale_window_test4.png", 35000); @@ -324,9 +323,9 @@ BOOST_AUTO_TEST_CASE (crop_scale_window_test4) BOOST_AUTO_TEST_CASE (crop_scale_window_test5) { auto proxy = make_shared(TestPaths::private_data() / "player_seek_test_0.png"); - auto xyz = proxy->image(false).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_XYZ12LE, true, false); + auto xyz = proxy->image(Image::Alignment::COMPACT).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_XYZ12LE, Image::Alignment::PADDED, false); auto cropped = xyz->crop_scale_window( - Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, false, false + Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, Image::Alignment::COMPACT, false ); write_image(cropped, "build/test/crop_scale_window_test5.png"); check_image("test/data/crop_scale_window_test5.png", "build/test/crop_scale_window_test5.png"); @@ -336,9 +335,9 @@ BOOST_AUTO_TEST_CASE (crop_scale_window_test5) BOOST_AUTO_TEST_CASE (crop_scale_window_test6) { auto proxy = make_shared(TestPaths::private_data() / "player_seek_test_0.png"); - auto xyz = proxy->image(false).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_XYZ12LE, true, false); + auto xyz = proxy->image(Image::Alignment::COMPACT).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_XYZ12LE, Image::Alignment::PADDED, false); auto cropped = xyz->crop_scale_window( - Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_XYZ12LE, VideoRange::FULL, false, false + Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_XYZ12LE, VideoRange::FULL, Image::Alignment::COMPACT, false ); write_image(cropped, "build/test/crop_scale_window_test6.png"); check_image("test/data/crop_scale_window_test6.png", "build/test/crop_scale_window_test6.png", 35000); @@ -351,7 +350,7 @@ BOOST_AUTO_TEST_CASE (crop_scale_window_test7) using namespace boost::filesystem; for (int left_crop = 0; left_crop < 8; ++left_crop) { auto proxy = make_shared("test/data/rgb_grey_testcard.png"); - auto yuv = proxy->image(false).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_YUV420P, true, false); + auto yuv = proxy->image(Image::Alignment::COMPACT).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_YUV420P, Image::Alignment::PADDED, false); int rounded = left_crop - (left_crop % 2); auto cropped = yuv->crop_scale_window( Crop(left_crop, 0, 0, 0), @@ -361,7 +360,7 @@ BOOST_AUTO_TEST_CASE (crop_scale_window_test7) VideoRange::VIDEO, AV_PIX_FMT_RGB24, VideoRange::VIDEO, - true, + Image::Alignment::PADDED, false ); path file = String::compose("crop_scale_window_test7-%1.png", left_crop); @@ -374,8 +373,8 @@ BOOST_AUTO_TEST_CASE (crop_scale_window_test7) BOOST_AUTO_TEST_CASE (as_png_test) { auto proxy = make_shared("test/data/3d_test/000001.png"); - auto image_rgb = proxy->image(false).image; - auto image_bgr = image_rgb->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_BGRA, true, false); + auto image_rgb = proxy->image(Image::Alignment::COMPACT).image; + auto image_bgr = image_rgb->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_BGRA, Image::Alignment::PADDED, false); image_rgb->as_png().write ("build/test/as_png_rgb.png"); image_bgr->as_png().write ("build/test/as_png_bgr.png"); @@ -388,11 +387,11 @@ BOOST_AUTO_TEST_CASE (as_png_test) static void fade_test_format_black (AVPixelFormat f, string name) { - Image yuv (f, dcp::Size(640, 480), true); + Image yuv (f, dcp::Size(640, 480), Image::Alignment::PADDED); yuv.make_black (); yuv.fade (0); string const filename = "fade_test_black_" + name + ".png"; - yuv.convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, true, false)->as_png().write("build/test/" + filename); + yuv.convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, Image::Alignment::PADDED, false)->as_png().write("build/test/" + filename); check_image ("test/data/" + filename, "build/test/" + filename); } @@ -402,10 +401,10 @@ static void fade_test_format_red (AVPixelFormat f, float amount, string name) { auto proxy = make_shared("test/data/flat_red.png"); - auto red = proxy->image(false).image->convert_pixel_format(dcp::YUVToRGB::REC709, f, true, false); + auto red = proxy->image(Image::Alignment::COMPACT).image->convert_pixel_format(dcp::YUVToRGB::REC709, f, Image::Alignment::PADDED, false); red->fade (amount); string const filename = "fade_test_red_" + name + ".png"; - red->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, true, false)->as_png().write("build/test/" + filename); + red->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, Image::Alignment::PADDED, false)->as_png().write("build/test/" + filename); check_image ("test/data/" + filename, "build/test/" + filename); } @@ -482,9 +481,9 @@ BOOST_AUTO_TEST_CASE (make_black_test) int N = 0; for (auto i: pix_fmts) { - auto foo = make_shared(i, in_size, true); + auto foo = make_shared(i, in_size, Image::Alignment::PADDED); foo->make_black (); - auto bar = foo->scale (out_size, dcp::YUVToRGB::REC601, AV_PIX_FMT_RGB24, true, false); + auto bar = foo->scale (out_size, dcp::YUVToRGB::REC601, AV_PIX_FMT_RGB24, Image::Alignment::PADDED, false); uint8_t* p = bar->data()[0]; for (int y = 0; y < bar->size().height; ++y) { @@ -506,7 +505,7 @@ BOOST_AUTO_TEST_CASE (make_black_test) BOOST_AUTO_TEST_CASE (make_part_black_test) { auto proxy = make_shared("test/data/flat_red.png"); - auto original = proxy->image(false).image; + auto original = proxy->image(Image::Alignment::COMPACT).image; list pix_fmts = { AV_PIX_FMT_RGB24, @@ -526,9 +525,9 @@ BOOST_AUTO_TEST_CASE (make_part_black_test) int N = 0; for (auto i: pix_fmts) { for (auto j: positions) { - auto foo = original->convert_pixel_format(dcp::YUVToRGB::REC601, i, true, false); + auto foo = original->convert_pixel_format(dcp::YUVToRGB::REC601, i, Image::Alignment::PADDED, false); foo->make_part_black (j.first, j.second); - auto bar = foo->convert_pixel_format (dcp::YUVToRGB::REC601, AV_PIX_FMT_RGB24, true, false); + auto bar = foo->convert_pixel_format (dcp::YUVToRGB::REC601, AV_PIX_FMT_RGB24, Image::Alignment::PADDED, false); auto p = bar->data()[0]; for (int y = 0; y < bar->size().height; ++y) { @@ -569,10 +568,10 @@ BOOST_AUTO_TEST_CASE (make_part_black_test) */ BOOST_AUTO_TEST_CASE (over_crop_test) { - auto image = make_shared(AV_PIX_FMT_RGB24, dcp::Size(128, 128), true); + auto image = make_shared(AV_PIX_FMT_RGB24, dcp::Size(128, 128), Image::Alignment::PADDED); image->make_black (); auto scaled = image->crop_scale_window ( - Crop(0, 0, 128, 128), dcp::Size(1323, 565), dcp::Size(1349, 565), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, true, true + Crop(0, 0, 128, 128), dcp::Size(1323, 565), dcp::Size(1349, 565), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, Image::Alignment::PADDED, true ); string const filename = "over_crop_test.png"; write_image (scaled, "build/test/" + filename); diff --git a/test/low_bitrate_test.cc b/test/low_bitrate_test.cc index 33ce2635d..7050dd771 100644 --- a/test/low_bitrate_test.cc +++ b/test/low_bitrate_test.cc @@ -35,10 +35,26 @@ using std::make_shared; BOOST_AUTO_TEST_CASE (low_bitrate_test) { - auto image = make_shared(AV_PIX_FMT_RGB24, dcp::Size(1998, 1080), true); + auto image = make_shared(AV_PIX_FMT_RGB24, dcp::Size(1998, 1080), Image::Alignment::PADDED); image->make_black (); + auto proxy = make_shared(image); - auto frame = make_shared(proxy, Crop(), boost::optional(), dcp::Size(1998, 1080), dcp::Size(1998, 1080), Eyes::BOTH, Part::WHOLE, boost::optional(), VideoRange::FULL, std::weak_ptr(), boost::optional(), false); + + auto frame = make_shared( + proxy, + Crop(), + boost::optional(), + dcp::Size(1998, 1080), + dcp::Size(1998, 1080), + Eyes::BOTH, + Part::WHOLE, + boost::optional(), + VideoRange::FULL, + std::weak_ptr(), + boost::optional(), + false + ); + auto dcp_video = make_shared(frame, 0, 24, 100000000, Resolution::TWO_K); auto j2k = dcp_video->encode_locally(); BOOST_REQUIRE (j2k.size() >= 16536); diff --git a/test/overlap_video_test.cc b/test/overlap_video_test.cc index d0d5a8bbf..3c969921d 100644 --- a/test/overlap_video_test.cc +++ b/test/overlap_video_test.cc @@ -40,7 +40,6 @@ using std::dynamic_pointer_cast; using std::make_shared; -using std::shared_ptr; BOOST_AUTO_TEST_CASE (overlap_video_test1) @@ -57,7 +56,7 @@ BOOST_AUTO_TEST_CASE (overlap_video_test1) B->video->set_length (24); B->set_position (film, dcpomatic::DCPTime::from_seconds(1)); - auto player = make_shared(film, false); + auto player = make_shared(film, Image::Alignment::COMPACT); auto pieces = player->_pieces; BOOST_REQUIRE_EQUAL (pieces.size(), 2U); BOOST_CHECK_EQUAL (pieces.front()->content, A); diff --git a/test/pixel_formats_test.cc b/test/pixel_formats_test.cc index a4d42e399..12a95bd69 100644 --- a/test/pixel_formats_test.cc +++ b/test/pixel_formats_test.cc @@ -88,7 +88,7 @@ BOOST_AUTO_TEST_CASE (pixel_formats_test) f->height = 480; f->format = static_cast (i.format); av_frame_get_buffer (f, true); - Image t (f, false); + Image t (f, Image::Alignment::COMPACT); BOOST_CHECK_EQUAL(t.planes(), i.planes); BOOST_CHECK_EQUAL(t.sample_size(0).height, i.lines[0]); BOOST_CHECK_EQUAL(t.sample_size(1).height, i.lines[1]); diff --git a/test/player_test.cc b/test/player_test.cc index c1e2d2cbe..2caa34753 100644 --- a/test/player_test.cc +++ b/test/player_test.cc @@ -25,21 +25,21 @@ */ -#include "lib/film.h" -#include "lib/ffmpeg_content.h" -#include "lib/dcp_content_type.h" -#include "lib/ratio.h" #include "lib/audio_buffers.h" -#include "lib/player.h" -#include "lib/video_content.h" -#include "lib/image_content.h" -#include "lib/string_text_file_content.h" -#include "lib/content_factory.h" -#include "lib/dcp_content.h" -#include "lib/text_content.h" #include "lib/butler.h" #include "lib/compose.hpp" +#include "lib/content_factory.h" #include "lib/cross.h" +#include "lib/dcp_content.h" +#include "lib/dcp_content_type.h" +#include "lib/ffmpeg_content.h" +#include "lib/film.h" +#include "lib/image_content.h" +#include "lib/player.h" +#include "lib/ratio.h" +#include "lib/string_text_file_content.h" +#include "lib/text_content.h" +#include "lib/video_content.h" #include "test.h" #include #include @@ -48,7 +48,6 @@ using std::cout; using std::list; -using std::pair; using std::shared_ptr; using std::make_shared; using boost::bind; @@ -84,7 +83,7 @@ BOOST_AUTO_TEST_CASE (player_silence_padding_test) accumulated = std::make_shared(film->audio_channels(), 0); - auto player = std::make_shared(film, false); + auto player = std::make_shared(film, Image::Alignment::COMPACT); player->Audio.connect (bind (&accumulate, _1, _2)); while (!player->pass ()) {} BOOST_REQUIRE (accumulated->frames() >= 48000); @@ -164,7 +163,7 @@ BOOST_AUTO_TEST_CASE (player_subframe_test) /* Length should be rounded up from B's length to the next video frame */ BOOST_CHECK (film->length() == DCPTime::from_frames(3 * 24 + 1, 24)); - auto player = std::make_shared(film, false); + auto player = std::make_shared(film, Image::Alignment::COMPACT); player->setup_pieces (); BOOST_REQUIRE_EQUAL (player->_black._periods.size(), 1U); BOOST_CHECK (player->_black._periods.front() == DCPTimePeriod(DCPTime::from_frames(3 * 24, 24), DCPTime::from_frames(3 * 24 + 1, 24))); @@ -206,7 +205,7 @@ BOOST_AUTO_TEST_CASE (player_interleave_test) film->examine_and_add_content (s); BOOST_REQUIRE (!wait_for_jobs ()); - auto player = std::make_shared(film, false); + auto player = std::make_shared(film, Image::Alignment::COMPACT); player->Video.connect (bind (&video, _1, _2)); player->Audio.connect (bind (&audio, _1, _2)); video_frames = audio_frames = 0; @@ -229,12 +228,12 @@ BOOST_AUTO_TEST_CASE (player_seek_test) BOOST_REQUIRE (!wait_for_jobs ()); dcp->only_text()->set_use (true); - auto player = std::make_shared(film, false); + auto player = std::make_shared(film, Image::Alignment::COMPACT); player->set_fast (); player->set_always_burn_open_subtitles (); player->set_play_referenced (); - auto butler = std::make_shared(film, player, AudioMapping(), 2, bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true, false); + auto butler = std::make_shared(film, player, AudioMapping(), 2, bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, true, false); butler->disable_audio(); for (int i = 0; i < 10; ++i) { @@ -242,7 +241,7 @@ BOOST_AUTO_TEST_CASE (player_seek_test) butler->seek (t, true); auto video = butler->get_video(true, 0); BOOST_CHECK_EQUAL(video.second.get(), t.get()); - write_image(video.first->image(bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true), String::compose("build/test/player_seek_test_%1.png", i)); + write_image(video.first->image(bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, true), String::compose("build/test/player_seek_test_%1.png", i)); /* This 14.08 is empirically chosen (hopefully) to accept changes in rendering between the reference and a test machine (17.10 and 16.04 seem to anti-alias a little differently) but to reject gross errors e.g. missing fonts or missing text altogether. @@ -261,12 +260,12 @@ BOOST_AUTO_TEST_CASE (player_seek_test2) BOOST_REQUIRE (!wait_for_jobs ()); dcp->only_text()->set_use (true); - auto player = std::make_shared(film, false); + auto player = std::make_shared(film, Image::Alignment::COMPACT); player->set_fast (); player->set_always_burn_open_subtitles (); player->set_play_referenced (); - auto butler = std::make_shared(film, player, AudioMapping(), 2, bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true, false); + auto butler = std::make_shared(film, player, AudioMapping(), 2, bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, true, false); butler->disable_audio(); butler->seek(DCPTime::from_seconds(5), true); @@ -277,7 +276,7 @@ BOOST_AUTO_TEST_CASE (player_seek_test2) auto video = butler->get_video(true, 0); BOOST_CHECK_EQUAL(video.second.get(), t.get()); write_image( - video.first->image(bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true), String::compose("build/test/player_seek_test2_%1.png", i) + video.first->image(bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, true), String::compose("build/test/player_seek_test2_%1.png", i) ); check_image(TestPaths::private_data() / String::compose("player_seek_test2_%1.png", i), String::compose("build/test/player_seek_test2_%1.png", i), 14.08); } @@ -335,7 +334,7 @@ BOOST_AUTO_TEST_CASE (player_ignore_video_and_audio_test) text->only_text()->set_type (TextType::CLOSED_CAPTION); text->only_text()->set_use (true); - auto player = std::make_shared(film, false); + auto player = std::make_shared(film, Image::Alignment::COMPACT); player->set_ignore_video (); player->set_ignore_audio (); @@ -355,9 +354,9 @@ BOOST_AUTO_TEST_CASE (player_trim_crash) film->examine_and_add_content (boon); BOOST_REQUIRE (!wait_for_jobs()); - auto player = std::make_shared(film, false); + auto player = std::make_shared(film, Image::Alignment::COMPACT); player->set_fast (); - auto butler = std::make_shared(film, player, AudioMapping(), 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true, false); + auto butler = std::make_shared(film, player, AudioMapping(), 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, true, false); /* Wait for the butler to fill */ dcpomatic_sleep_seconds (5); diff --git a/test/test.cc b/test/test.cc index 3395d9672..8417b30d2 100644 --- a/test/test.cc +++ b/test/test.cc @@ -364,9 +364,9 @@ double rms_error (boost::filesystem::path ref, boost::filesystem::path check) { FFmpegImageProxy ref_proxy (ref); - auto ref_image = ref_proxy.image(false).image; + auto ref_image = ref_proxy.image(Image::Alignment::COMPACT).image; FFmpegImageProxy check_proxy (check); - auto check_image = check_proxy.image(false).image; + auto check_image = check_proxy.image(Image::Alignment::COMPACT).image; BOOST_REQUIRE_EQUAL (ref_image->pixel_format(), check_image->pixel_format()); AVPixelFormat const format = ref_image->pixel_format(); diff --git a/test/time_calculation_test.cc b/test/time_calculation_test.cc index 285285395..4ab5d0942 100644 --- a/test/time_calculation_test.cc +++ b/test/time_calculation_test.cc @@ -36,7 +36,6 @@ using std::list; using std::make_shared; -using std::shared_ptr; using std::string; using namespace dcpomatic; @@ -197,7 +196,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1) film->set_sequence (false); film->add_content (content); - auto player = make_shared(film, false); + auto player = make_shared(film, Image::Alignment::COMPACT); /* Position 0, no trim, content rate = DCP rate */ content->set_position (film, DCPTime()); @@ -403,7 +402,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2) film->set_sequence (false); film->add_content (content); - auto player = make_shared(film, false); + auto player = make_shared(film, Image::Alignment::COMPACT); /* Position 0, no trim, content rate = DCP rate */ content->set_position (film, DCPTime()); @@ -580,7 +579,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3) film->set_sequence (false); film->add_content (content); - auto player = make_shared(film, false); + auto player = make_shared(film, Image::Alignment::COMPACT); /* Position 0, no trim, video/audio content rate = video/audio DCP rate */ content->set_position (film, DCPTime()); diff --git a/test/upmixer_a_test.cc b/test/upmixer_a_test.cc index 3310a9277..af6c8b9e2 100644 --- a/test/upmixer_a_test.cc +++ b/test/upmixer_a_test.cc @@ -89,7 +89,7 @@ BOOST_AUTO_TEST_CASE (upmixer_a_test) Ls = sf_open ("build/test/upmixer_a_test/Ls.wav", SFM_WRITE, &info); Rs = sf_open ("build/test/upmixer_a_test/Rs.wav", SFM_WRITE, &info); - auto player = make_shared(film, false); + auto player = make_shared(film, Image::Alignment::COMPACT); player->Audio.connect (bind (&write, _1, _2)); while (!player->pass()) {} diff --git a/test/vf_test.cc b/test/vf_test.cc index d25eb3cca..4db48dd60 100644 --- a/test/vf_test.cc +++ b/test/vf_test.cc @@ -291,7 +291,7 @@ BOOST_AUTO_TEST_CASE (vf_test5) make_and_verify_dcp (vf, {dcp::VerificationNote::Code::EXTERNAL_ASSET}); /* Check that the selected reel assets are right */ - auto player = make_shared(vf, false); + auto player = make_shared(vf, Image::Alignment::COMPACT); auto a = player->get_reel_assets(); BOOST_REQUIRE_EQUAL (a.size(), 4U); auto i = a.begin(); diff --git a/test/video_level_test.cc b/test/video_level_test.cc index 8d82e9d76..54513464c 100644 --- a/test/video_level_test.cc +++ b/test/video_level_test.cc @@ -54,7 +54,6 @@ using std::min; -using std::make_pair; using std::max; using std::pair; using std::string; @@ -71,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) { @@ -94,7 +93,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_image_full_range_not_changed) write_image (grey_image(size, grey_pixel), file); FFmpegImageProxy proxy (file); - ImageProxy::Result result = proxy.image (false); + ImageProxy::Result result = proxy.image (Image::Alignment::COMPACT); BOOST_REQUIRE (!result.error); for (int y = 0; y < size.height; ++y) { @@ -128,7 +127,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_image_video_range_expanded) BOOST_REQUIRE (!player->pass()); } - auto image = player_video->image ([](AVPixelFormat f) { return f; }, VideoRange::FULL, true, false); + auto image = player_video->image ([](AVPixelFormat f) { return f; }, VideoRange::FULL, Image::Alignment::PADDED, false); for (int y = 0; y < size.height; ++y) { uint8_t* p = image->data()[0] + y * image->stride()[0]; @@ -214,7 +213,7 @@ pixel_range (shared_ptr film, shared_ptr content) BOOST_REQUIRE (!decoder->pass()); } - return pixel_range (content_video->image->image(false).image); + return pixel_range (content_video->image->image(Image::Alignment::COMPACT).image); } -- cgit v1.2.3 From 571a29b441ce6fe4a1e35bbcbcf4ea6abc885c22 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 23 Sep 2021 00:07:26 +0200 Subject: Remove unused using --- src/lib/player.cc | 1 - src/lib/render_text.cc | 2 -- src/wx/video_view.cc | 1 - 3 files changed, 4 deletions(-) (limited to 'src/lib') diff --git a/src/lib/player.cc b/src/lib/player.cc index 7c1a57aa9..7951926e6 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -70,7 +70,6 @@ using std::dynamic_pointer_cast; using std::list; using std::make_pair; using std::make_shared; -using std::map; using std::max; using std::min; using std::min; diff --git a/src/lib/render_text.cc b/src/lib/render_text.cc index 96b832c57..76c0fb79d 100644 --- a/src/lib/render_text.cc +++ b/src/lib/render_text.cc @@ -48,8 +48,6 @@ using std::min; using std::pair; using std::shared_ptr; using std::string; -using boost::optional; -using boost::algorithm::replace_all; using namespace dcpomatic; diff --git a/src/wx/video_view.cc b/src/wx/video_view.cc index 4d80e2535..1d10beb30 100644 --- a/src/wx/video_view.cc +++ b/src/wx/video_view.cc @@ -28,7 +28,6 @@ #include -using std::pair; using std::shared_ptr; using boost::optional; -- cgit v1.2.3 From 67ff55886b1ee86d99c2ea27d10c73b85b0504b7 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 23 Sep 2021 00:09:47 +0200 Subject: Various alignment tidying/fixups. --- src/lib/dcp_video.cc | 2 +- src/lib/ffmpeg_file_encoder.cc | 1 - src/lib/player_video.cc | 13 ++++++------- src/lib/player_video.h | 4 ++-- src/lib/util.cc | 2 +- src/wx/film_viewer.cc | 6 ++++-- src/wx/gl_video_view.cc | 2 +- src/wx/simple_video_view.cc | 7 +++---- src/wx/simple_video_view.h | 4 ---- test/dcp_playback_test.cc | 2 +- test/player_test.cc | 6 +++--- test/video_level_test.cc | 2 +- 12 files changed, 23 insertions(+), 28 deletions(-) (limited to 'src/lib') diff --git a/src/lib/dcp_video.cc b/src/lib/dcp_video.cc index 9daeb45c8..3a85a5ac6 100644 --- a/src/lib/dcp_video.cc +++ b/src/lib/dcp_video.cc @@ -105,7 +105,7 @@ DCPVideo::convert_to_xyz (shared_ptr frame, dcp::NoteHandler { shared_ptr xyz; - auto image = frame->image (bind(&PlayerVideo::keep_xyz_or_rgb, _1), VideoRange::FULL, Image::Alignment::PADDED, false); + auto image = frame->image (bind(&PlayerVideo::keep_xyz_or_rgb, _1), VideoRange::FULL, false); if (frame->colour_conversion()) { xyz = dcp::rgb_to_xyz ( image->data()[0], diff --git a/src/lib/ffmpeg_file_encoder.cc b/src/lib/ffmpeg_file_encoder.cc index ef02f30c8..705557f79 100644 --- a/src/lib/ffmpeg_file_encoder.cc +++ b/src/lib/ffmpeg_file_encoder.cc @@ -402,7 +402,6 @@ FFmpegFileEncoder::video (shared_ptr video, DCPTime time) auto image = video->image ( bind (&PlayerVideo::force, _1, _pixel_format), VideoRange::VIDEO, - Image::Alignment::PADDED, false ); diff --git a/src/lib/player_video.cc b/src/lib/player_video.cc index 2d60efe10..7c36af31b 100644 --- a/src/lib/player_video.cc +++ b/src/lib/player_video.cc @@ -110,13 +110,13 @@ PlayerVideo::set_text (PositionImage image) } shared_ptr -PlayerVideo::image (function pixel_format, VideoRange video_range, Image::Alignment alignment, bool fast) const +PlayerVideo::image (function pixel_format, VideoRange video_range, bool fast) const { /* XXX: this assumes that image() and prepare() are only ever called with the same parameters (except crop, inter size, out size, fade) */ boost::mutex::scoped_lock lm (_mutex); if (!_image || _crop != _image_crop || _inter_size != _image_inter_size || _out_size != _image_out_size || _fade != _image_fade) { - make_image (pixel_format, video_range, alignment, fast); + make_image (pixel_format, video_range, fast); } return _image; } @@ -133,11 +133,10 @@ PlayerVideo::raw_image () const * @param pixel_format Function which is called to decide what pixel format the output image should be; * it is passed the pixel format of the input image from the ImageProxy, and should return the desired * output pixel format. Two functions force and keep_xyz_or_rgb are provided for use here. - * @param alignment PADDED if the output image should be aligned to 32-byte boundaries, otherwise COMPACT. * @param fast true to be fast at the expense of quality. */ void -PlayerVideo::make_image (function pixel_format, VideoRange video_range, Image::Alignment alignment, bool fast) const +PlayerVideo::make_image (function pixel_format, VideoRange video_range, bool fast) const { _image_crop = _crop; _image_inter_size = _inter_size; @@ -180,11 +179,11 @@ PlayerVideo::make_image (function pixel_format, V } _image = prox.image->crop_scale_window ( - total_crop, _inter_size, _out_size, yuv_to_rgb, _video_range, pixel_format (prox.image->pixel_format()), video_range, alignment, fast + total_crop, _inter_size, _out_size, yuv_to_rgb, _video_range, pixel_format (prox.image->pixel_format()), video_range, Image::Alignment::COMPACT, fast ); if (_text) { - _image->alpha_blend (Image::ensure_alignment(_text->image, Image::Alignment::PADDED), _text->position); + _image->alpha_blend (_text->image, _text->position); } if (_fade) { @@ -303,7 +302,7 @@ PlayerVideo::prepare (function pixel_format, Vide _in->prepare (alignment, _inter_size); boost::mutex::scoped_lock lm (_mutex); if (!_image && !proxy_only) { - make_image (pixel_format, video_range, alignment, fast); + make_image (pixel_format, video_range, fast); } } diff --git a/src/lib/player_video.h b/src/lib/player_video.h index d24620c7e..237d2e3fe 100644 --- a/src/lib/player_video.h +++ b/src/lib/player_video.h @@ -76,7 +76,7 @@ public: } void prepare (std::function pixel_format, VideoRange video_range, Image::Alignment alignment, bool fast, bool proxy_only); - std::shared_ptr image (std::function pixel_format, VideoRange video_range, Image::Alignment alignment, bool fast) const; + std::shared_ptr image (std::function pixel_format, VideoRange video_range, bool fast) const; std::shared_ptr raw_image () const; static AVPixelFormat force (AVPixelFormat, AVPixelFormat); @@ -127,7 +127,7 @@ public: } private: - void make_image (std::function pixel_format, VideoRange video_range, Image::Alignment alignment, bool fast) const; + void make_image (std::function pixel_format, VideoRange video_range, bool fast) const; std::shared_ptr _in; Crop _crop; diff --git a/src/lib/util.cc b/src/lib/util.cc index 981cfa521..d3af74376 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -957,7 +957,7 @@ emit_subtitle_image (ContentTimePeriod period, dcp::SubtitleImage sub, dcp::Size { /* XXX: this is rather inefficient; decoding the image just to get its size */ FFmpegImageProxy proxy (sub.png_image()); - auto image = proxy.image(Image::Alignment::COMPACT).image; + auto image = proxy.image(Image::Alignment::PADDED).image; /* set up rect with height and width */ dcpomatic::Rect rect(0, 0, image->size().width / double(size.width), image->size().height / double(size.height)); diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 5609ebf86..0131aa294 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -208,6 +208,8 @@ FilmViewer::recreate_butler () return; } + auto const j2k_gl_optimised = dynamic_pointer_cast(_video_view) && _optimise_for_j2k; + _butler = std::make_shared( _film, _player, @@ -215,9 +217,9 @@ FilmViewer::recreate_butler () _audio_channels, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, - _optimise_for_j2k ? Image::Alignment::COMPACT : Image::Alignment::PADDED, + j2k_gl_optimised ? Image::Alignment::COMPACT : Image::Alignment::PADDED, true, - dynamic_pointer_cast(_video_view) && _optimise_for_j2k + j2k_gl_optimised ); if (!Config::instance()->sound() && !_audio.isStreamOpen()) { diff --git a/src/wx/gl_video_view.cc b/src/wx/gl_video_view.cc index 046465864..04e0bac46 100644 --- a/src/wx/gl_video_view.cc +++ b/src/wx/gl_video_view.cc @@ -497,7 +497,7 @@ GLVideoView::draw (Position, dcp::Size) void GLVideoView::set_image (shared_ptr pv) { - shared_ptr video = _optimise_for_j2k ? pv->raw_image() : pv->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, true); + shared_ptr video = _optimise_for_j2k ? pv->raw_image() : pv->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, true); /* Only the player's black frames should be aligned at this stage, so this should * almost always have no work to do. diff --git a/src/wx/simple_video_view.cc b/src/wx/simple_video_view.cc index e54c8390e..1ac56bbfe 100644 --- a/src/wx/simple_video_view.cc +++ b/src/wx/simple_video_view.cc @@ -72,6 +72,7 @@ SimpleVideoView::paint () if (!_image) { dc.Clear (); } else { + DCPOMATIC_ASSERT (_image->alignment() == Image::Alignment::COMPACT); out_size = _image->size(); wxImage frame (out_size.width, out_size.height, _image->data()[0], true); wxBitmap frame_bitmap (frame); @@ -188,7 +189,7 @@ void SimpleVideoView::update () { if (!player_video().first) { - set_image (shared_ptr()); + _image.reset (); refresh_panel (); return; } @@ -221,9 +222,7 @@ SimpleVideoView::update () _state_timer.set ("get image"); - set_image ( - player_video().first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, true) - ); + _image = player_video().first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, true); _state_timer.set ("ImageChanged"); _viewer->image_changed (player_video().first); diff --git a/src/wx/simple_video_view.h b/src/wx/simple_video_view.h index 26d1299b1..cbb162023 100644 --- a/src/wx/simple_video_view.h +++ b/src/wx/simple_video_view.h @@ -42,10 +42,6 @@ public: NextFrameResult display_next_frame (bool non_blocking) override; private: - void set_image (std::shared_ptr image) { - _image = image; - } - void refresh_panel (); void paint (); void timer (); diff --git a/test/dcp_playback_test.cc b/test/dcp_playback_test.cc index 28368dc34..6c2b0447c 100644 --- a/test/dcp_playback_test.cc +++ b/test/dcp_playback_test.cc @@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE (dcp_playback_test) } /* assuming DCP is 24fps/48kHz */ butler->get_audio (audio_buffer, 2000); - p.first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, true); + p.first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, true); } delete[] audio_buffer; } diff --git a/test/player_test.cc b/test/player_test.cc index 2caa34753..60bfee1a4 100644 --- a/test/player_test.cc +++ b/test/player_test.cc @@ -241,7 +241,7 @@ BOOST_AUTO_TEST_CASE (player_seek_test) butler->seek (t, true); auto video = butler->get_video(true, 0); BOOST_CHECK_EQUAL(video.second.get(), t.get()); - write_image(video.first->image(bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, true), String::compose("build/test/player_seek_test_%1.png", i)); + write_image(video.first->image(bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, true), String::compose("build/test/player_seek_test_%1.png", i)); /* This 14.08 is empirically chosen (hopefully) to accept changes in rendering between the reference and a test machine (17.10 and 16.04 seem to anti-alias a little differently) but to reject gross errors e.g. missing fonts or missing text altogether. @@ -265,7 +265,7 @@ BOOST_AUTO_TEST_CASE (player_seek_test2) player->set_always_burn_open_subtitles (); player->set_play_referenced (); - auto butler = std::make_shared(film, player, AudioMapping(), 2, bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, true, false); + auto butler = std::make_shared(film, player, AudioMapping(), 2, bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::PADDED, true, false); butler->disable_audio(); butler->seek(DCPTime::from_seconds(5), true); @@ -276,7 +276,7 @@ BOOST_AUTO_TEST_CASE (player_seek_test2) auto video = butler->get_video(true, 0); BOOST_CHECK_EQUAL(video.second.get(), t.get()); write_image( - video.first->image(bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, true), String::compose("build/test/player_seek_test2_%1.png", i) + video.first->image(bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, true), String::compose("build/test/player_seek_test2_%1.png", i) ); check_image(TestPaths::private_data() / String::compose("player_seek_test2_%1.png", i), String::compose("build/test/player_seek_test2_%1.png", i), 14.08); } diff --git a/test/video_level_test.cc b/test/video_level_test.cc index 54513464c..ada9b602a 100644 --- a/test/video_level_test.cc +++ b/test/video_level_test.cc @@ -127,7 +127,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_image_video_range_expanded) BOOST_REQUIRE (!player->pass()); } - auto image = player_video->image ([](AVPixelFormat f) { return f; }, VideoRange::FULL, Image::Alignment::PADDED, false); + auto image = player_video->image ([](AVPixelFormat f) { return f; }, VideoRange::FULL, false); for (int y = 0; y < size.height; ++y) { uint8_t* p = image->data()[0] + y * image->stride()[0]; -- cgit v1.2.3 From 6e1ceb315f01a233e8c449e649fa44551aa30491 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 23 Sep 2021 23:54:13 +0200 Subject: Check that the image used to make a Cairo::ImageSurface is the right alignment and pixel format. --- src/lib/render_text.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/lib') diff --git a/src/lib/render_text.cc b/src/lib/render_text.cc index 76c0fb79d..94b412856 100644 --- a/src/lib/render_text.cc +++ b/src/lib/render_text.cc @@ -93,7 +93,9 @@ set_source_rgba (Cairo::RefPtr context, dcp::Colour colour, floa static shared_ptr create_image (dcp::Size size) { - /* FFmpeg BGRA means first byte blue, second byte green, third byte red, fourth byte alpha */ + /* FFmpeg BGRA means first byte blue, second byte green, third byte red, fourth byte alpha. + * This must be COMPACT as we're using it with Cairo::ImageSurface::create + */ auto image = make_shared(AV_PIX_FMT_BGRA, size, Image::Alignment::COMPACT); image->make_black (); return image; @@ -103,6 +105,11 @@ create_image (dcp::Size size) static Cairo::RefPtr create_surface (shared_ptr image) { + /* XXX: I don't think it's guaranteed that format_stride_for_width will return a stride without any padding, + * so it's lucky that this works. + */ + DCPOMATIC_ASSERT (image->alignment() == Image::Alignment::COMPACT); + DCPOMATIC_ASSERT (image->pixel_format() == AV_PIX_FMT_BGRA); return Cairo::ImageSurface::create ( image->data()[0], Cairo::FORMAT_ARGB32, -- cgit v1.2.3 From 7c05a521d19b2613cfdf698ddc9f88c462ceaf18 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 23 Sep 2021 23:54:28 +0200 Subject: Make merge return the right alignment even if it's not doing anything. --- src/lib/image.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/lib') diff --git a/src/lib/image.cc b/src/lib/image.cc index 30589ef9c..a4e04bb62 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -1147,7 +1147,8 @@ merge (list images, Image::Alignment alignment) } if (images.size() == 1) { - return images.front (); + images.front().image = Image::ensure_alignment(images.front().image, alignment); + return images.front(); } dcpomatic::Rect all (images.front().position, images.front().image->size().width, images.front().image->size().height); -- cgit v1.2.3