From 7bd8eecb8ba8535978d58408dc73ce7528034c7e Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 4 Aug 2022 23:55:17 +0200 Subject: [PATCH] wip: got stuck... because PlayerVideo is related to the render size because its subtitles are prepared for the _video_container_size that the Player knows about. I think the only way around this would be to store the subs in PlayerVideo in some independent way and to scale/convert to bitmap later. --- src/lib/butler.cc | 10 +++- src/lib/butler.h | 4 ++ src/lib/dcp_video.cc | 18 ++++-- src/lib/dcp_video.h | 5 +- src/lib/ffmpeg_encoder.cc | 2 + src/lib/ffmpeg_file_encoder.cc | 4 +- src/lib/j2k_encoder.cc | 3 +- src/lib/pixel_quanta.cc | 14 +++++ src/lib/pixel_quanta.h | 2 + src/lib/player.cc | 3 +- src/lib/player_video.cc | 102 ++++++++++++++++++--------------- src/lib/player_video.h | 70 +++++++++++++--------- src/lib/video_ring_buffers.cc | 4 +- src/lib/video_ring_buffers.h | 2 +- src/wx/simple_video_view.cc | 6 +- src/wx/video_waveform_plot.cc | 7 ++- test/player_video_test.cc | 73 +++++++++++++++++++++++ 17 files changed, 240 insertions(+), 89 deletions(-) create mode 100644 test/player_video_test.cc diff --git a/src/lib/butler.cc b/src/lib/butler.cc index ce35b1f39..ad3834dee 100644 --- a/src/lib/butler.cc +++ b/src/lib/butler.cc @@ -57,6 +57,8 @@ 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 display_container Same as above for the `display_container` value. + * @param film_container Same as above for the `film_container` value. * @param alignment Same as above for the `alignment' value. * @param fast Same as above for the `fast' flag. */ @@ -66,6 +68,8 @@ Butler::Butler ( AudioMapping audio_mapping, int audio_channels, function pixel_format, + dcp::Size display_container, + dcp::Size film_container, VideoRange video_range, Image::Alignment alignment, bool fast, @@ -84,6 +88,8 @@ Butler::Butler ( , _audio_channels (audio_channels) , _disable_audio (audio == Audio::DISABLED) , _pixel_format (pixel_format) + , _display_container(display_container) + , _film_container(film_container) , _video_range (video_range) , _alignment (alignment) , _fast (fast) @@ -326,7 +332,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, _alignment, _fast, _prepare_only_proxy); + video->prepare(_pixel_format, _display_container, _film_container, _video_range, _alignment, _fast, _prepare_only_proxy); LOG_TIMING("finish-prepare in %1", thread_id()); } } @@ -410,7 +416,7 @@ Butler::player_change (ChangeType type, int property) if (type == ChangeType::DONE) { auto film = _film.lock(); if (film) { - _video.reset_metadata (film, _player->video_container_size()); + _video.reset_metadata(film); } } return; diff --git a/src/lib/butler.h b/src/lib/butler.h index 87408646b..711c91000 100644 --- a/src/lib/butler.h +++ b/src/lib/butler.h @@ -50,6 +50,8 @@ public: AudioMapping map, int audio_channels, std::function pixel_format, + dcp::Size display_container, + dcp::Size film_container, VideoRange video_range, Image::Alignment alignment, bool fast, @@ -130,6 +132,8 @@ private: bool _disable_audio; std::function _pixel_format; + dcp::Size _display_container; + dcp::Size _film_container; VideoRange _video_range; Image::Alignment _alignment; bool _fast; diff --git a/src/lib/dcp_video.cc b/src/lib/dcp_video.cc index 14f23bd37..0e42f0a12 100644 --- a/src/lib/dcp_video.cc +++ b/src/lib/dcp_video.cc @@ -80,9 +80,10 @@ using namespace boost::placeholders; * @param bw J2K bandwidth to use (see Config::j2k_bandwidth ()) */ DCPVideo::DCPVideo ( - shared_ptr frame, int index, int dcp_fps, int bw, Resolution r + shared_ptr frame, dcp::Size container, int index, int dcp_fps, int bw, Resolution r ) : _frame (frame) + , _container(container) , _index (index) , _frames_per_second (dcp_fps) , _j2k_bandwidth (bw) @@ -101,11 +102,18 @@ DCPVideo::DCPVideo (shared_ptr frame, shared_ptr -DCPVideo::convert_to_xyz (shared_ptr frame, dcp::NoteHandler note) +DCPVideo::convert_to_xyz (shared_ptr frame, dcp::Size container, dcp::NoteHandler note) { shared_ptr xyz; - auto image = frame->image (bind(&PlayerVideo::keep_xyz_or_rgb, _1), VideoRange::FULL, false); + auto image = frame->image( + bind(&PlayerVideo::keep_xyz_or_rgb, _1), + container, + container, + VideoRange::FULL, + false + ); + if (frame->colour_conversion()) { xyz = dcp::rgb_to_xyz ( image->data()[0], @@ -134,7 +142,7 @@ DCPVideo::encode_locally () const int const minimum_size = 16384; LOG_DEBUG_ENCODE("Using minimum frame size %1", minimum_size); - auto xyz = convert_to_xyz (_frame, boost::bind(&Log::dcp_log, dcpomatic_log.get(), _1, _2)); + auto xyz = convert_to_xyz(_frame, _container, boost::bind(&Log::dcp_log, dcpomatic_log.get(), _1, _2)); int noise_amount = 2; int pixel_skip = 16; while (true) { @@ -159,7 +167,7 @@ DCPVideo::encode_locally () const * convert_to_xyz() again because compress_j2k() corrupts its xyz parameter. */ - xyz = convert_to_xyz (_frame, boost::bind(&Log::dcp_log, dcpomatic_log.get(), _1, _2)); + xyz = convert_to_xyz(_frame, _container, boost::bind(&Log::dcp_log, dcpomatic_log.get(), _1, _2)); auto size = xyz->size (); auto pixels = size.width * size.height; dcpomatic::RNG rng(42); diff --git a/src/lib/dcp_video.h b/src/lib/dcp_video.h index 3bd516ccd..0c2119099 100644 --- a/src/lib/dcp_video.h +++ b/src/lib/dcp_video.h @@ -42,7 +42,7 @@ class PlayerVideo; class DCPVideo { public: - DCPVideo (std::shared_ptr, int index, int dcp_fps, int bandwidth, Resolution r); + DCPVideo (std::shared_ptr, dcp::Size container, int index, int dcp_fps, int bandwidth, Resolution resolution); DCPVideo (std::shared_ptr, cxml::ConstNodePtr); DCPVideo (DCPVideo const&) = default; @@ -59,13 +59,14 @@ public: bool same (std::shared_ptr other) const; - static std::shared_ptr convert_to_xyz (std::shared_ptr frame, dcp::NoteHandler note); + static std::shared_ptr convert_to_xyz(std::shared_ptr frame, dcp::Size container, dcp::NoteHandler note); private: void add_metadata (xmlpp::Element *) const; std::shared_ptr _frame; + dcp::Size _container; int _index; ///< frame index within the DCP's intrinsic duration int _frames_per_second; ///< Frames per second that we will use for the DCP int _j2k_bandwidth; ///< J2K bandwidth to use diff --git a/src/lib/ffmpeg_encoder.cc b/src/lib/ffmpeg_encoder.cc index 6b31c4201..05131488a 100644 --- a/src/lib/ffmpeg_encoder.cc +++ b/src/lib/ffmpeg_encoder.cc @@ -112,6 +112,8 @@ FFmpegEncoder::FFmpegEncoder ( map, _output_audio_channels, bind(&PlayerVideo::force, FFmpegFileEncoder::pixel_format(format)), + _film->frame_size(), + _film->frame_size(), VideoRange::VIDEO, Image::Alignment::PADDED, false, diff --git a/src/lib/ffmpeg_file_encoder.cc b/src/lib/ffmpeg_file_encoder.cc index 0d5167c49..3af2db7ce 100644 --- a/src/lib/ffmpeg_file_encoder.cc +++ b/src/lib/ffmpeg_file_encoder.cc @@ -402,7 +402,9 @@ FFmpegFileEncoder::video (shared_ptr video, DCPTime time) { /* All our output formats are video range at the moment */ auto image = video->image ( - bind (&PlayerVideo::force, _pixel_format), + bind(&PlayerVideo::force, _pixel_format), + _video_frame_size, + _video_frame_size, VideoRange::VIDEO, false ); diff --git a/src/lib/j2k_encoder.cc b/src/lib/j2k_encoder.cc index 53e1c272f..3e1bbc864 100644 --- a/src/lib/j2k_encoder.cc +++ b/src/lib/j2k_encoder.cc @@ -225,7 +225,7 @@ J2KEncoder::encode (shared_ptr pv, DCPTime time) LOG_DEBUG_ENCODE("Frame @ %1 FAKE", to_string(time)); _writer->fake_write (position, pv->eyes ()); frame_done (); - } else if (pv->has_j2k() && !_film->reencode_j2k()) { + } else if (pv->has_j2k(_film->frame_size(), _film->frame_size()) && !_film->reencode_j2k()) { LOG_DEBUG_ENCODE("Frame @ %1 J2K", to_string(time)); /* This frame already has J2K data, so just write it */ _writer->write (pv->j2k(), position, pv->eyes ()); @@ -239,6 +239,7 @@ J2KEncoder::encode (shared_ptr pv, DCPTime time) LOG_TIMING ("add-frame-to-queue queue=%1", _queue.size ()); _queue.push_back (DCPVideo( pv, + _film->frame_size(), position, _film->video_frame_rate(), _film->j2k_bandwidth(), diff --git a/src/lib/pixel_quanta.cc b/src/lib/pixel_quanta.cc index 7c1d285cf..ad3ee1d7a 100644 --- a/src/lib/pixel_quanta.cc +++ b/src/lib/pixel_quanta.cc @@ -66,3 +66,17 @@ max (PixelQuanta const& a, PixelQuanta const& b) return { std::max(a.x, b.x), std::max(a.y, b.y) }; } + +bool +operator==(PixelQuanta const& a, PixelQuanta const& b) +{ + return a.x == b.x && a.y == b.y; +} + + +bool +operator!=(PixelQuanta const& a, PixelQuanta const& b) +{ + return a.x != b.x || a.y != b.y; +} + diff --git a/src/lib/pixel_quanta.h b/src/lib/pixel_quanta.h index 37d2321f4..46bfdffd0 100644 --- a/src/lib/pixel_quanta.h +++ b/src/lib/pixel_quanta.h @@ -62,6 +62,8 @@ public: PixelQuanta max (PixelQuanta const& a, PixelQuanta const& b); +bool operator==(PixelQuanta const& a, PixelQuanta const& b); +bool operator!=(PixelQuanta const& a, PixelQuanta const& b); #endif diff --git a/src/lib/player.cc b/src/lib/player.cc index de9be2b71..23a56ddfe 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -302,10 +302,9 @@ Player::playlist_content_change (ChangeType type, int property, bool frequent) { if (property == VideoContentProperty::CROP) { if (type == ChangeType::DONE) { - auto const vcs = video_container_size(); boost::mutex::scoped_lock lm (_mutex); for (auto const& i: _delay) { - i.first->reset_metadata (_film, vcs); + i.first->reset_metadata(_film); } } } else { diff --git a/src/lib/player_video.cc b/src/lib/player_video.cc index d45bf9f43..2fe917393 100644 --- a/src/lib/player_video.cc +++ b/src/lib/player_video.cc @@ -26,6 +26,7 @@ #include "j2k_image_proxy.h" #include "player.h" #include "player_video.h" +#include "util.h" #include "video_content.h" #include extern "C" { @@ -51,8 +52,8 @@ PlayerVideo::PlayerVideo ( shared_ptr in, Crop crop, boost::optional fade, - dcp::Size inter_size, - dcp::Size out_size, + dcp::Size size_in_film, + PixelQuanta pixel_quanta, Eyes eyes, Part part, optional colour_conversion, @@ -64,8 +65,8 @@ PlayerVideo::PlayerVideo ( : _in (in) , _crop (crop) , _fade (fade) - , _inter_size (inter_size) - , _out_size (out_size) + , _size_in_film(size_in_film) + , _pixel_quanta(pixel_quanta) , _eyes (eyes) , _part (part) , _colour_conversion (colour_conversion) @@ -83,8 +84,8 @@ PlayerVideo::PlayerVideo (shared_ptr node, shared_ptr socket _crop = Crop (node); _fade = node->optional_number_child ("Fade"); - _inter_size = dcp::Size (node->number_child ("InterWidth"), node->number_child ("InterHeight")); - _out_size = dcp::Size (node->number_child ("OutWidth"), node->number_child ("OutHeight")); + _size_in_film = dcp::Size(node->number_child("SizeInFilmWidth"), node->number_child("SizeInFilmHeight")); + _pixel_quanta = PixelQuanta(node->number_child("PixelQuantumX"), node->number_child("PixelQuantumY")); _eyes = static_cast(node->number_child("Eyes")); _part = static_cast(node->number_child("Part")); _video_range = static_cast(node->number_child("VideoRange")); @@ -116,22 +117,29 @@ PlayerVideo::set_text (PositionImage image) shared_ptr -PlayerVideo::image (function pixel_format, VideoRange video_range, bool fast) const +PlayerVideo::image( + function pixel_format, + dcp::Size display_container, + dcp::Size film_container, + 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, fast); + if (!_image || _crop != _image_crop || _size_in_film != _image_size_in_film || _pixel_quanta != _image_pixel_quanta || _fade != _image_fade) { + make_image(pixel_format, display_container, film_container, video_range, fast); } return _image; } shared_ptr -PlayerVideo::raw_image () const +PlayerVideo::raw_image(dcp::Size display_container, dcp::Size film_container) const { - return _in->image(Image::Alignment::COMPACT, _inter_size).image; + auto const inter_size = scale_for_display(_size_in_film, display_container, film_container, _pixel_quanta); + return _in->image(Image::Alignment::COMPACT, inter_size).image; } @@ -142,14 +150,22 @@ PlayerVideo::raw_image () const * @param fast true to be fast at the expense of quality. */ void -PlayerVideo::make_image (function pixel_format, VideoRange video_range, bool fast) const +PlayerVideo::make_image ( + function pixel_format, + dcp::Size display_container, + dcp::Size film_container, + VideoRange video_range, + bool fast + ) const { _image_crop = _crop; - _image_inter_size = _inter_size; - _image_out_size = _out_size; + _image_size_in_film = _size_in_film; + _image_pixel_quanta = _pixel_quanta; _image_fade = _fade; - auto prox = _in->image (Image::Alignment::PADDED, _inter_size); + auto const inter_size = scale_for_display(_size_in_film, display_container, film_container, _pixel_quanta); + + auto prox = _in->image (Image::Alignment::PADDED, inter_size); _error = prox.error; auto total_crop = _crop; @@ -185,7 +201,7 @@ 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, Image::Alignment::COMPACT, fast + total_crop, inter_size, display_container, yuv_to_rgb, _video_range, pixel_format(prox.image->pixel_format()), video_range, Image::Alignment::COMPACT, fast ); if (_text) { @@ -206,10 +222,10 @@ PlayerVideo::add_metadata (xmlpp::Node* node) const node->add_child("Fade")->add_child_text (raw_convert (_fade.get ())); } _in->add_metadata (node->add_child ("In")); - node->add_child("InterWidth")->add_child_text (raw_convert (_inter_size.width)); - node->add_child("InterHeight")->add_child_text (raw_convert (_inter_size.height)); - node->add_child("OutWidth")->add_child_text (raw_convert (_out_size.width)); - node->add_child("OutHeight")->add_child_text (raw_convert (_out_size.height)); + node->add_child("SizeInFilmWidth")->add_child_text(raw_convert(_size_in_film.width)); + node->add_child("SizeInFilmHeight")->add_child_text(raw_convert(_size_in_film.height)); + node->add_child("PixelQuantumX")->add_child_text(raw_convert(_pixel_quanta.x)); + node->add_child("PixelQuantumY")->add_child_text(raw_convert(_pixel_quanta.y)); node->add_child("Eyes")->add_child_text (raw_convert (static_cast (_eyes))); node->add_child("Part")->add_child_text (raw_convert (static_cast (_part))); node->add_child("VideoRange")->add_child_text(raw_convert(static_cast(_video_range))); @@ -237,7 +253,7 @@ PlayerVideo::write_to_socket (shared_ptr socket) const bool -PlayerVideo::has_j2k () const +PlayerVideo::has_j2k(dcp::Size display_container, dcp::Size film_container) const { /* XXX: maybe other things */ @@ -246,7 +262,8 @@ PlayerVideo::has_j2k () const return false; } - return _crop == Crop() && _out_size == j2k->size() && _inter_size == j2k->size() && !_text && !_fade && !_colour_conversion; + auto const inter_size = scale_for_display(_size_in_film, display_container, film_container, _pixel_quanta); + return _crop == Crop() && film_container == j2k->size() && inter_size == j2k->size() && !_text && !_fade && !_colour_conversion; } @@ -259,21 +276,14 @@ PlayerVideo::j2k () const } -Position -PlayerVideo::inter_position () const -{ - return Position ((_out_size.width - _inter_size.width) / 2, (_out_size.height - _inter_size.height) / 2); -} - - /** @return true if this PlayerVideo is definitely the same as another, false if it is probably not */ bool PlayerVideo::same (shared_ptr other) const { if (_crop != other->_crop || _fade != other->_fade || - _inter_size != other->_inter_size || - _out_size != other->_out_size || + _size_in_film != other->_size_in_film || + _pixel_quanta != other->_pixel_quanta || _eyes != other->_eyes || _part != other->_part || _colour_conversion != other->_colour_conversion || @@ -311,12 +321,21 @@ PlayerVideo::keep_xyz_or_rgb (AVPixelFormat p) void -PlayerVideo::prepare (function pixel_format, VideoRange video_range, Image::Alignment alignment, bool fast, bool proxy_only) +PlayerVideo::prepare( + function pixel_format, + dcp::Size display_container, + dcp::Size film_container, + VideoRange video_range, + Image::Alignment alignment, + bool fast, + bool proxy_only + ) { - _in->prepare (alignment, _inter_size); + auto const inter_size = scale_for_display(_size_in_film, display_container, film_container, _pixel_quanta); + _in->prepare(alignment, inter_size); boost::mutex::scoped_lock lm (_mutex); if (!_image && !proxy_only) { - make_image (pixel_format, video_range, fast); + make_image(pixel_format, display_container, film_container, video_range, fast); } } @@ -336,8 +355,8 @@ PlayerVideo::shallow_copy () const _in, _crop, _fade, - _inter_size, - _out_size, + _size_in_film, + _pixel_quanta, _eyes, _part, _colour_conversion, @@ -349,11 +368,11 @@ PlayerVideo::shallow_copy () const } -/** Re-read crop, fade, inter/out size, colour conversion and video range from our content. +/** Re-read crop, fade, colour conversion and video range from our content. * @return true if this was possible, false if not. */ bool -PlayerVideo::reset_metadata (shared_ptr film, dcp::Size player_video_container_size) +PlayerVideo::reset_metadata (shared_ptr film) { auto content = _content.lock(); if (!content || !_video_frame) { @@ -362,13 +381,6 @@ PlayerVideo::reset_metadata (shared_ptr film, dcp::Size player_video _crop = content->video->actual_crop(); _fade = content->video->fade(film, _video_frame.get()); - _inter_size = scale_for_display( - content->video->scaled_size(film->frame_size()), - player_video_container_size, - film->frame_size(), - content->video->pixel_quanta() - ); - _out_size = player_video_container_size; _colour_conversion = content->video->colour_conversion(); _video_range = content->video->range(); diff --git a/src/lib/player_video.h b/src/lib/player_video.h index f2781c1a0..3be0bafbc 100644 --- a/src/lib/player_video.h +++ b/src/lib/player_video.h @@ -26,6 +26,7 @@ #include "colour_conversion.h" #include "dcpomatic_time.h" #include "image.h" +#include "pixel_quanta.h" #include "position.h" #include "position_image.h" #include "types.h" @@ -52,8 +53,8 @@ public: std::shared_ptr image, Crop crop, boost::optional fade, - dcp::Size inter_size, - dcp::Size out_size, + dcp::Size size_in_film, + PixelQuanta pixel_quanta, Eyes eyes, Part part, boost::optional colour_conversion, @@ -75,9 +76,28 @@ public: return _text; } - 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, bool fast) const; - std::shared_ptr raw_image () const; + void prepare( + std::function pixel_format, + dcp::Size display_container, + dcp::Size film_container, + VideoRange video_range, + Image::Alignment alignment, + bool fast, + bool proxy_only + ); + + std::shared_ptr image( + std::function pixel_format, + dcp::Size display_container, + dcp::Size film_container, + VideoRange video_range, + bool fast + ) const; + + std::shared_ptr raw_image( + dcp::Size display_container, + dcp::Size film_container + ) const; static AVPixelFormat force (AVPixelFormat); static AVPixelFormat keep_xyz_or_rgb (AVPixelFormat); @@ -85,9 +105,13 @@ public: void add_metadata (xmlpp::Node* node) const; void write_to_socket (std::shared_ptr socket) const; - bool reset_metadata (std::shared_ptr film, dcp::Size player_video_container_size); + bool reset_metadata(std::shared_ptr film); + + bool has_j2k( + dcp::Size display_container, + dcp::Size film_container + ) const; - bool has_j2k () const; std::shared_ptr j2k () const; Eyes eyes () const { @@ -102,18 +126,6 @@ public: return _colour_conversion; } - /** @return Position of the content within the overall image once it has been scaled up */ - Position inter_position () const; - - /** @return Size of the content within the overall image once it has been scaled up */ - dcp::Size inter_size () const { - return _inter_size; - } - - dcp::Size out_size () const { - return _out_size; - } - bool same (std::shared_ptr other) const; size_t memory_used () const; @@ -127,13 +139,19 @@ public: } private: - void make_image (std::function pixel_format, VideoRange video_range, bool fast) const; + void make_image( + std::function pixel_format, + dcp::Size display_container, + dcp::Size film_container, + VideoRange video_range, + bool fast + ) const; std::shared_ptr _in; Crop _crop; boost::optional _fade; - dcp::Size _inter_size; - dcp::Size _out_size; + dcp::Size _size_in_film; + PixelQuanta _pixel_quanta; Eyes _eyes; Part _part; boost::optional _colour_conversion; @@ -148,10 +166,10 @@ private: mutable std::shared_ptr _image; /** _crop that was used to make _image */ mutable Crop _image_crop; - /** _inter_size that was used to make _image */ - mutable dcp::Size _image_inter_size; - /** _out_size that was used to make _image */ - mutable dcp::Size _image_out_size; + /** _size_in_film that was used to make _image */ + mutable dcp::Size _image_size_in_film; + /** _pixel_quanta that was used to make _image */ + mutable PixelQuanta _image_pixel_quanta; /** _fade that was used to make _image */ mutable boost::optional _image_fade; /** true if there was an error when decoding our image */ diff --git a/src/lib/video_ring_buffers.cc b/src/lib/video_ring_buffers.cc index 63c52ee06..f44dc9c7a 100644 --- a/src/lib/video_ring_buffers.cc +++ b/src/lib/video_ring_buffers.cc @@ -94,11 +94,11 @@ VideoRingBuffers::memory_used () const void -VideoRingBuffers::reset_metadata (shared_ptr film, dcp::Size player_video_container_size) +VideoRingBuffers::reset_metadata (shared_ptr film) { boost::mutex::scoped_lock lm (_mutex); for (auto const& i: _data) { - i.first->reset_metadata (film, player_video_container_size); + i.first->reset_metadata(film); } } diff --git a/src/lib/video_ring_buffers.h b/src/lib/video_ring_buffers.h index 47fda01f7..df06122d0 100644 --- a/src/lib/video_ring_buffers.h +++ b/src/lib/video_ring_buffers.h @@ -45,7 +45,7 @@ public: Frame size () const; bool empty () const; - void reset_metadata (std::shared_ptr film, dcp::Size player_video_container_size); + void reset_metadata(std::shared_ptr film); std::pair memory_used () const; diff --git a/src/wx/simple_video_view.cc b/src/wx/simple_video_view.cc index 00d81ab47..87d7ddadd 100644 --- a/src/wx/simple_video_view.cc +++ b/src/wx/simple_video_view.cc @@ -241,7 +241,11 @@ SimpleVideoView::update () _state_timer.set ("get image"); - _image = player_video().first->image(boost::bind(&PlayerVideo::force, AV_PIX_FMT_RGB24), VideoRange::FULL, true); + _image = player_video().first->image( + boost::bind(&PlayerVideo::force, AV_PIX_FMT_RGB24), + VideoRange::FULL, + true + ); _state_timer.set ("ImageChanged"); _viewer->image_changed (player_video().first); diff --git a/src/wx/video_waveform_plot.cc b/src/wx/video_waveform_plot.cc index 8e3284682..6ec173469 100644 --- a/src/wx/video_waveform_plot.cc +++ b/src/wx/video_waveform_plot.cc @@ -195,10 +195,15 @@ VideoWaveformPlot::set_image (shared_ptr image) return; } + auto film = _film.lock (); + if (!film) { + return; + } + /* We must copy the PlayerVideo here as we will call ::image() on it, potentially with a different pixel_format than was used when ::prepare() was called. */ - _image = DCPVideo::convert_to_xyz (image->shallow_copy(), [](dcp::NoteType, string) {}); + _image = DCPVideo::convert_to_xyz(image->shallow_copy(), film->frame_size(), [](dcp::NoteType, string) {}); _dirty = true; Refresh (); } diff --git a/test/player_video_test.cc b/test/player_video_test.cc new file mode 100644 index 000000000..c4241ed9b --- /dev/null +++ b/test/player_video_test.cc @@ -0,0 +1,73 @@ +/* + Copyright (C) 2022 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + + +#include "lib/colour_conversion.h" +#include "lib/j2k_image_proxy.h" +#include "lib/player_video.h" +#include +#include +#include +#include +#include + + +using std::make_shared; +using std::weak_ptr; +using boost::optional; + + +BOOST_AUTO_TEST_CASE(player_video_j2k_passthrough_test) +{ + auto size = dcp::Size(4096, 2048); + auto image = make_shared(size); + for (int x = 0; x < size.width; ++x) { + image->data(0)[x] = x; + image->data(1)[x] = x; + image->data(2)[x] = x; + } + for (int y = 1; y < size.height; ++y) { + memcpy(image->data(0) + y * size.width, image->data(0), size.width); + memcpy(image->data(1) + y * size.width, image->data(1), size.width); + memcpy(image->data(2) + y * size.width, image->data(2), size.width); + } + auto compressed = compress_j2k(image, 250000000LL, 24, false, true); + auto decompressed = decompress_j2k(compressed, 0); + auto frame = make_shared(compressed.data(), compressed.size()); + auto proxy = make_shared(frame, size, AV_PIX_FMT_XYZ12LE, optional()); + auto video = make_shared(proxy, Crop(), optional(), size, size, Eyes::BOTH, Part::WHOLE, optional(), VideoRange::FULL, weak_ptr(), optional(), false); + auto out_image = video->image([](AVPixelFormat) { return AV_PIX_FMT_XYZ12LE; }, VideoRange::FULL, false); + + BOOST_REQUIRE_EQUAL(out_image->size().width, size.width); + BOOST_REQUIRE_EQUAL(out_image->size().height, size.height); + + for (int c = 0; c < 3; ++c) { + for (auto y = 0; y < size.height; ++y) { + auto in = decompressed->data(c) + y * size.width; + auto out = reinterpret_cast(out_image->data()[0] + y * out_image->stride()[0]) + c; + for (int x = 0; x < size.width; ++x) { + BOOST_REQUIRE_MESSAGE(*in == (*out >> 4), *in << " != " << *out << " at x=" << x << ", y=" << y << ", c=" << c); + ++in; + out += 3; + } + } + } +} + -- 2.30.2