using std::cout;
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
+using boost::optional;
DCPDecoder::DCPDecoder (shared_ptr<const DCPContent> c, shared_ptr<Log> log)
: DCP (c)
if (_mono_reader) {
video->emit (
shared_ptr<ImageProxy> (
- new J2KImageProxy (_mono_reader->get_frame (entry_point + frame), asset->size(), AV_PIX_FMT_XYZ12LE)
+ new J2KImageProxy (
+ _mono_reader->get_frame (entry_point + frame),
+ asset->size(),
+ AV_PIX_FMT_XYZ12LE,
+ _forced_reduction
+ )
),
_offset + frame
);
} else {
video->emit (
shared_ptr<ImageProxy> (
- new J2KImageProxy (_stereo_reader->get_frame (entry_point + frame), asset->size(), dcp::EYE_LEFT, AV_PIX_FMT_XYZ12LE)),
+ new J2KImageProxy (
+ _stereo_reader->get_frame (entry_point + frame),
+ asset->size(),
+ dcp::EYE_LEFT,
+ AV_PIX_FMT_XYZ12LE,
+ _forced_reduction
+ )
+ ),
_offset + frame
);
video->emit (
shared_ptr<ImageProxy> (
- new J2KImageProxy (_stereo_reader->get_frame (entry_point + frame), asset->size(), dcp::EYE_RIGHT, AV_PIX_FMT_XYZ12LE)),
+ new J2KImageProxy (
+ _stereo_reader->get_frame (entry_point + frame),
+ asset->size(),
+ dcp::EYE_RIGHT,
+ AV_PIX_FMT_XYZ12LE,
+ _forced_reduction
+ )
+ ),
_offset + frame
);
}
{
_decode_referenced = true;
}
+
+void
+DCPDecoder::set_forced_reduction (optional<int> reduction)
+{
+ _forced_reduction = reduction;
+}
}
void set_decode_referenced ();
+ void set_forced_reduction (boost::optional<int> reduction);
bool pass ();
void seek (ContentTime t, bool accurate);
boost::shared_ptr<dcp::SoundAssetReader> _sound_reader;
bool _decode_referenced;
+ boost::optional<int> _forced_reduction;
};
}
-J2KImageProxy::J2KImageProxy (shared_ptr<const dcp::MonoPictureFrame> frame, dcp::Size size, AVPixelFormat pixel_format)
+J2KImageProxy::J2KImageProxy (
+ shared_ptr<const dcp::MonoPictureFrame> frame,
+ dcp::Size size,
+ AVPixelFormat pixel_format,
+ optional<int> forced_reduction
+ )
: _data (frame->j2k_size ())
, _size (size)
, _pixel_format (pixel_format)
+ , _forced_reduction (forced_reduction)
{
memcpy (_data.data().get(), frame->j2k_data(), _data.size ());
}
-J2KImageProxy::J2KImageProxy (shared_ptr<const dcp::StereoPictureFrame> frame, dcp::Size size, dcp::Eye eye, AVPixelFormat pixel_format)
+J2KImageProxy::J2KImageProxy (
+ shared_ptr<const dcp::StereoPictureFrame> frame,
+ dcp::Size size,
+ dcp::Eye eye,
+ AVPixelFormat pixel_format,
+ optional<int> forced_reduction
+ )
: _size (size)
, _eye (eye)
, _pixel_format (pixel_format)
+ , _forced_reduction (forced_reduction)
{
switch (eye) {
case dcp::EYE_LEFT:
int reduce = 0;
- while (target_size && (_size.width / pow(2, reduce)) > target_size->width && (_size.height / pow(2, reduce)) > target_size->height) {
- ++reduce;
+ if (_forced_reduction) {
+ reduce = *_forced_reduction;
+ } else {
+ while (target_size && (_size.width / pow(2, reduce)) > target_size->width && (_size.height / pow(2, reduce)) > target_size->height) {
+ ++reduce;
+ }
+
+ --reduce;
+ reduce = max (0, reduce);
}
- --reduce;
- reduce = max (0, reduce);
_decompressed = dcp::decompress_j2k (const_cast<uint8_t*> (_data.data().get()), _data.size (), reduce);
if (_decompressed->precision(0) < 12) {
{
public:
J2KImageProxy (boost::filesystem::path path, dcp::Size, AVPixelFormat pixel_format);
- J2KImageProxy (boost::shared_ptr<const dcp::MonoPictureFrame> frame, dcp::Size, AVPixelFormat pixel_format);
- J2KImageProxy (boost::shared_ptr<const dcp::StereoPictureFrame> frame, dcp::Size, dcp::Eye, AVPixelFormat pixel_format);
+
+ J2KImageProxy (
+ boost::shared_ptr<const dcp::MonoPictureFrame> frame,
+ dcp::Size,
+ AVPixelFormat pixel_format,
+ boost::optional<int> forced_reduction
+ );
+
+ J2KImageProxy (
+ boost::shared_ptr<const dcp::StereoPictureFrame> frame,
+ dcp::Size,
+ dcp::Eye,
+ AVPixelFormat pixel_format,
+ boost::optional<int> forced_reduction
+ );
+
J2KImageProxy (boost::shared_ptr<cxml::Node> xml, boost::shared_ptr<Socket> socket);
boost::shared_ptr<Image> image (
mutable boost::optional<dcp::Size> _target_size;
AVPixelFormat _pixel_format;
mutable boost::mutex _mutex;
+ boost::optional<int> _forced_reduction;
};
shared_ptr<DCPDecoder> dcp = dynamic_pointer_cast<DCPDecoder> (decoder);
if (dcp && _play_referenced) {
- dcp->set_decode_referenced ();
+ if (_play_referenced) {
+ dcp->set_decode_referenced ();
+ }
+ dcp->set_forced_reduction (_dcp_decode_reduction);
}
shared_ptr<Piece> piece (new Piece (i, decoder, frc));
void
Player::seek (DCPTime time, bool accurate)
{
+ if (!_have_valid_pieces) {
+ setup_pieces ();
+ }
+
if (_audio_processor) {
_audio_processor->flush ();
}
cut->copy_from (audio.get(), remaining_frames, discard_frames, 0);
return make_pair(cut, time + discard_time);
}
+
+void
+Player::set_dcp_decode_reduction (optional<int> reduction)
+{
+ if (reduction == _dcp_decode_reduction) {
+ return;
+ }
+
+ _dcp_decode_reduction = reduction;
+ _have_valid_pieces = false;
+ Changed (false);
+}
void set_always_burn_subtitles (bool burn);
void set_fast ();
void set_play_referenced ();
+ void set_dcp_decode_reduction (boost::optional<int> reduction);
/** Emitted when something has changed such that if we went back and emitted
* the last frame again it would look different. This is not emitted after
/** Time just after the last audio frame we emitted, or the time of the last accurate seek */
boost::optional<DCPTime> _last_audio_time;
+ boost::optional<int> _dcp_decode_reduction;
+
typedef std::map<boost::weak_ptr<Piece>, boost::shared_ptr<PlayerVideo> > LastVideoMap;
LastVideoMap _last_video;
/*
- Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2016-2017 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
#include <dcp/exceptions.h>
using boost::shared_ptr;
+using boost::optional;
VideoMXFDecoder::VideoMXFDecoder (shared_ptr<const VideoMXFContent> content, shared_ptr<Log> log)
: _content (content)
if (_mono_reader) {
video->emit (
- shared_ptr<ImageProxy> (new J2KImageProxy (_mono_reader->get_frame(frame), _size, AV_PIX_FMT_XYZ12LE)), frame
+ shared_ptr<ImageProxy> (
+ new J2KImageProxy (_mono_reader->get_frame(frame), _size, AV_PIX_FMT_XYZ12LE, optional<int>())
+ ),
+ frame
);
} else {
video->emit (
- shared_ptr<ImageProxy> (new J2KImageProxy (_stereo_reader->get_frame(frame), _size, dcp::EYE_LEFT, AV_PIX_FMT_XYZ12LE)), frame
+ shared_ptr<ImageProxy> (
+ new J2KImageProxy (_stereo_reader->get_frame(frame), _size, dcp::EYE_LEFT, AV_PIX_FMT_XYZ12LE, optional<int>())
+ ),
+ frame
);
video->emit (
- shared_ptr<ImageProxy> (new J2KImageProxy (_stereo_reader->get_frame(frame), _size, dcp::EYE_RIGHT, AV_PIX_FMT_XYZ12LE)), frame
+ shared_ptr<ImageProxy> (
+ new J2KImageProxy (_stereo_reader->get_frame(frame), _size, dcp::EYE_RIGHT, AV_PIX_FMT_XYZ12LE, optional<int>())
+ ),
+ frame
);
}
enum {
ID_file_open = 1,
+ ID_view_scale_appropriate,
+ ID_view_scale_full,
+ ID_view_scale_half,
+ ID_view_scale_quarter,
ID_help_report_a_problem,
ID_tools_check_for_updates,
};
Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_open, this), ID_file_open);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_exit, this), wxID_EXIT);
+ Bind (wxEVT_MENU, boost::bind (&DOMFrame::set_decode_reduction, this, optional<int>()), ID_view_scale_appropriate);
+ Bind (wxEVT_MENU, boost::bind (&DOMFrame::set_decode_reduction, this, optional<int>(0)), ID_view_scale_full);
+ Bind (wxEVT_MENU, boost::bind (&DOMFrame::set_decode_reduction, this, optional<int>(1)), ID_view_scale_half);
+ Bind (wxEVT_MENU, boost::bind (&DOMFrame::set_decode_reduction, this, optional<int>(2)), ID_view_scale_quarter);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::help_about, this), wxID_ABOUT);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::help_report_a_problem, this), ID_help_report_a_problem);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_check_for_updates, this), ID_tools_check_for_updates);
UpdateChecker::instance()->StateChanged.connect (boost::bind (&DOMFrame::update_checker_state_changed, this));
}
+ void set_decode_reduction (optional<int> reduction)
+ {
+ _viewer->set_dcp_decode_reduction (reduction);
+ }
+
void load_dcp (boost::filesystem::path dir)
{
_film.reset (new Film (optional<boost::filesystem::path>()));
edit->Append (wxID_PREFERENCES, _("&Preferences...\tCtrl-P"));
#endif
+ wxMenu* view = new wxMenu;
+ view->AppendRadioItem (ID_view_scale_appropriate, _("Set decode resolution to match display"));
+ view->AppendRadioItem (ID_view_scale_full, _("Decode at full resolution"));
+ view->AppendRadioItem (ID_view_scale_half, _("Decode at half resolution"));
+ view->AppendRadioItem (ID_view_scale_quarter, _("Decode at quarter resolution"));
+
wxMenu* tools = new wxMenu;
tools->Append (ID_tools_check_for_updates, _("Check for updates"));
help->Append (ID_help_report_a_problem, _("Report a problem..."));
m->Append (file, _("&File"));
+#ifndef __WXOSX__
+ m->Append (edit, _("&Edit"));
+#endif
+ m->Append (view, _("&View"));
m->Append (tools, _("&Tools"));
m->Append (help, _("&Help"));
}
return total / _latency_history.size();
}
+
+void
+FilmViewer::set_dcp_decode_reduction (optional<int> reduction)
+{
+ _player->set_dcp_decode_reduction (reduction);
+}
void set_position (DCPTime p);
void set_coalesce_player_changes (bool c);
+ void set_dcp_decode_reduction (boost::optional<int> reduction);
void refresh ();