From 26c6f510ca23f1d21e41e3df65726ffa0852d745 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 10 Apr 2013 15:12:09 +0100 Subject: Try to fix rounding problems with ratios due to old unused integer ops. --- src/lib/format.cc | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) (limited to 'src/lib/format.cc') diff --git a/src/lib/format.cc b/src/lib/format.cc index faadcd797..2f9f87ba9 100644 --- a/src/lib/format.cc +++ b/src/lib/format.cc @@ -72,51 +72,51 @@ Format::setup_formats () { /// TRANSLATORS: these are film picture aspect ratios; "Academy" means 1.37, "Flat" 1.85 and "Scope" 2.39. _formats.push_back ( - new FixedFormat (119, libdcp::Size (1285, 1080), N_("119"), _("1.19"), N_("F") + new FixedFormat (1.19, libdcp::Size (1285, 1080), N_("119"), _("1.19"), N_("F") )); _formats.push_back ( - new FixedFormat (133, libdcp::Size (1436, 1080), N_("133"), _("1.33"), N_("F") + new FixedFormat (4.0 / 3.0, libdcp::Size (1436, 1080), N_("133"), _("4:3"), N_("F") )); _formats.push_back ( - new FixedFormat (138, libdcp::Size (1485, 1080), N_("138"), _("1.375"), N_("F") + new FixedFormat (1.38, libdcp::Size (1485, 1080), N_("138"), _("1.375"), N_("F") )); _formats.push_back ( - new FixedFormat (133, libdcp::Size (1998, 1080), N_("133-in-flat"), _("4:3 within Flat"), N_("F") + new FixedFormat (4.0 / 30, libdcp::Size (1998, 1080), N_("133-in-flat"), _("4:3 within Flat"), N_("F") )); _formats.push_back ( - new FixedFormat (137, libdcp::Size (1480, 1080), N_("137"), _("Academy"), N_("F") + new FixedFormat (1.37, libdcp::Size (1480, 1080), N_("137"), _("Academy"), N_("F") )); _formats.push_back ( - new FixedFormat (166, libdcp::Size (1793, 1080), N_("166"), _("1.66"), N_("F") + new FixedFormat (1.66, libdcp::Size (1793, 1080), N_("166"), _("1.66"), N_("F") )); _formats.push_back ( - new FixedFormat (166, libdcp::Size (1998, 1080), N_("166-in-flat"), _("1.66 within Flat"), N_("F") + new FixedFormat (1.66, libdcp::Size (1998, 1080), N_("166-in-flat"), _("1.66 within Flat"), N_("F") )); _formats.push_back ( - new FixedFormat (178, libdcp::Size (1998, 1080), N_("178-in-flat"), _("16:9 within Flat"), N_("F") + new FixedFormat (1.78, libdcp::Size (1998, 1080), N_("178-in-flat"), _("16:9 within Flat"), N_("F") )); _formats.push_back ( - new FixedFormat (178, libdcp::Size (1920, 1080), N_("178"), _("16:9"), N_("F") + new FixedFormat (1.78, libdcp::Size (1920, 1080), N_("178"), _("16:9"), N_("F") )); _formats.push_back ( - new FixedFormat (185, libdcp::Size (1998, 1080), N_("185"), _("Flat"), N_("F") + new FixedFormat (1.85, libdcp::Size (1998, 1080), N_("185"), _("Flat"), N_("F") )); _formats.push_back ( - new FixedFormat (178, libdcp::Size (2048, 858), N_("178-in-scope"), _("16:9 within Scope"), N_("S") + new FixedFormat (1.78, libdcp::Size (2048, 858), N_("178-in-scope"), _("16:9 within Scope"), N_("S") )); _formats.push_back ( - new FixedFormat (239, libdcp::Size (2048, 858), N_("239"), _("Scope"), N_("S") + new FixedFormat (2.39, libdcp::Size (2048, 858), N_("239"), _("Scope"), N_("S") )); _formats.push_back ( @@ -181,12 +181,12 @@ Format::all () return _formats; } -/** @param r Ratio multiplied by 100 (e.g. 185) +/** @param r Ratio * @param dcp Size (in pixels) of the images that we should put in a DCP. * @param id ID (e.g. 185) * @param n Nick name (e.g. Flat) */ -FixedFormat::FixedFormat (int r, libdcp::Size dcp, string id, string n, string d) +FixedFormat::FixedFormat (float r, libdcp::Size dcp, string id, string n, string d) : Format (dcp, id, n, d) , _ratio (r) { @@ -199,7 +199,7 @@ FixedFormat::FixedFormat (int r, libdcp::Size dcp, string id, string n, string d int Format::dcp_padding (shared_ptr f) const { - int p = rint ((_dcp_size.width - (_dcp_size.height * ratio_as_float(f))) / 2.0); + int p = rint ((_dcp_size.width - (_dcp_size.height * ratio(f))) / 2.0); /* This comes out -ve for Scope; bodge it */ if (p < 0) { @@ -210,7 +210,7 @@ Format::dcp_padding (shared_ptr f) const } float -Format::container_ratio_as_float () const +Format::container_ratio () const { return static_cast (_dcp_size.width) / _dcp_size.height; } @@ -221,14 +221,8 @@ VariableFormat::VariableFormat (libdcp::Size dcp, string id, string n, string d) } -int -VariableFormat::ratio_as_integer (shared_ptr f) const -{ - return rint (ratio_as_float (f) * 100); -} - float -VariableFormat::ratio_as_float (shared_ptr f) const +VariableFormat::ratio (shared_ptr f) const { libdcp::Size const c = f->cropped_size (f->size ()); return float (c.width) / c.height; -- cgit v1.2.3 From 6fe31ddd16a0819fe38ffb7e9520c6a049af078a Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Fri, 12 Apr 2013 00:21:30 +0100 Subject: Fix typo. --- src/lib/format.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/format.cc') diff --git a/src/lib/format.cc b/src/lib/format.cc index 2f9f87ba9..640eee167 100644 --- a/src/lib/format.cc +++ b/src/lib/format.cc @@ -84,7 +84,7 @@ Format::setup_formats () )); _formats.push_back ( - new FixedFormat (4.0 / 30, libdcp::Size (1998, 1080), N_("133-in-flat"), _("4:3 within Flat"), N_("F") + new FixedFormat (4.0 / 3.0, libdcp::Size (1998, 1080), N_("133-in-flat"), _("4:3 within Flat"), N_("F") )); _formats.push_back ( -- cgit v1.2.3 From 98499a61e17e68c438e56fd8854081a4c98b15ad Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 20 Apr 2013 02:26:23 +0100 Subject: Somewhat hacky but seemingly functional frame back/forward (rest of #68). --- src/lib/decoder.h | 2 ++ src/lib/ffmpeg_decoder.cc | 46 +++++++++++++++++++++++++++++++++++++++++----- src/lib/ffmpeg_decoder.h | 4 +++- src/lib/format.cc | 2 +- src/wx/film_viewer.cc | 40 ++++++++++++++++++++++++++++++++++++---- src/wx/film_viewer.h | 6 +++++- 6 files changed, 88 insertions(+), 12 deletions(-) (limited to 'src/lib/format.cc') diff --git a/src/lib/decoder.h b/src/lib/decoder.h index f2f523516..2bc462c33 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -59,6 +59,8 @@ public: virtual bool pass () = 0; virtual bool seek (double); virtual bool seek_to_last (); + virtual void seek_back () {} + virtual void seek_forward () {} boost::signals2::signal OutputChanged; diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 2d7092789..7c88c3c35 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -530,7 +530,7 @@ FFmpegDecoder::filter_and_emit_video () bool FFmpegDecoder::seek (double p) { - return do_seek (p, false); + return do_seek (p, false, false); } bool @@ -540,21 +540,57 @@ FFmpegDecoder::seek_to_last () (used when we change decoder parameters and want to re-fetch the frame) we end up going forwards rather than staying in the same place. */ - return do_seek (last_source_time(), true); + return do_seek (last_source_time(), true, false); +} + +void +FFmpegDecoder::seek_back () +{ + do_seek (last_source_time() - 2.5 / frames_per_second (), true, true); +} + +void +FFmpegDecoder::seek_forward () +{ + do_seek (last_source_time() - 0.5 / frames_per_second(), true, true); } bool -FFmpegDecoder::do_seek (double p, bool backwards) +FFmpegDecoder::do_seek (double p, bool backwards, bool accurate) { int64_t const vt = p / av_q2d (_format_context->streams[_video_stream]->time_base); int const r = av_seek_frame (_format_context, _video_stream, vt, backwards ? AVSEEK_FLAG_BACKWARD : 0); - + avcodec_flush_buffers (_video_codec_context); if (_subtitle_codec_context) { avcodec_flush_buffers (_subtitle_codec_context); } - + + if (accurate) { + while (1) { + int r = av_read_frame (_format_context, &_packet); + if (r < 0) { + return true; + } + + avcodec_get_frame_defaults (_frame); + + if (_packet.stream_index == _video_stream) { + int finished = 0; + int const r = avcodec_decode_video2 (_video_codec_context, _frame, &finished, &_packet); + if (r >= 0 && finished) { + int64_t const bet = av_frame_get_best_effort_timestamp (_frame); + if (bet > vt) { + break; + } + } + } + + av_free_packet (&_packet); + } + } + return r < 0; } diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 2a4d40b1d..0c89b973d 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -102,11 +102,13 @@ public: bool seek (double); bool seek_to_last (); + void seek_forward (); + void seek_back (); private: bool pass (); - bool do_seek (double p, bool); + bool do_seek (double p, bool, bool); PixelFormat pixel_format () const; AVSampleFormat audio_sample_format () const; int bytes_per_audio_sample () const; diff --git a/src/lib/format.cc b/src/lib/format.cc index 640eee167..8c3d0d8ad 100644 --- a/src/lib/format.cc +++ b/src/lib/format.cc @@ -50,7 +50,7 @@ FixedFormat::name () const s << _nickname << N_(" ("); } - s << setprecision(3) << (_ratio / 100.0) << N_(":1"); + s << setprecision(3) << _ratio << N_(":1"); if (!_nickname.empty ()) { s << N_(")"); diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 00f895285..5770c5b70 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -51,6 +51,8 @@ FilmViewer::FilmViewer (shared_ptr f, wxWindow* p) : wxPanel (p) , _panel (new wxPanel (this)) , _slider (new wxSlider (this, wxID_ANY, 0, 0, 4096)) + , _back_button (new wxButton (this, wxID_ANY, wxT("<"))) + , _forward_button (new wxButton (this, wxID_ANY, wxT(">"))) , _frame (new wxStaticText (this, wxID_ANY, wxT(""))) , _timecode (new wxStaticText (this, wxID_ANY, wxT(""))) , _play_button (new wxToggleButton (this, wxID_ANY, _("Play"))) @@ -72,14 +74,18 @@ FilmViewer::FilmViewer (shared_ptr f, wxWindow* p) wxBoxSizer* time_sizer = new wxBoxSizer (wxVERTICAL); time_sizer->Add (_frame, 0, wxEXPAND); time_sizer->Add (_timecode, 0, wxEXPAND); - + + h_sizer->Add (_back_button, 0, wxALL, 2); h_sizer->Add (time_sizer, 0, wxEXPAND); + h_sizer->Add (_forward_button, 0, wxALL, 2); h_sizer->Add (_play_button, 0, wxEXPAND); h_sizer->Add (_slider, 1, wxEXPAND); _v_sizer->Add (h_sizer, 0, wxEXPAND | wxALL, 6); _frame->SetMinSize (wxSize (84, -1)); + _back_button->SetMinSize (wxSize (32, -1)); + _forward_button->SetMinSize (wxSize (32, -1)); _panel->Connect (wxID_ANY, wxEVT_PAINT, wxPaintEventHandler (FilmViewer::paint_panel), 0, this); _panel->Connect (wxID_ANY, wxEVT_SIZE, wxSizeEventHandler (FilmViewer::panel_sized), 0, this); @@ -88,6 +94,8 @@ FilmViewer::FilmViewer (shared_ptr f, wxWindow* p) _slider->Connect (wxID_ANY, wxEVT_SCROLL_PAGEDOWN, wxScrollEventHandler (FilmViewer::slider_moved), 0, this); _play_button->Connect (wxID_ANY, wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler (FilmViewer::play_clicked), 0, this); _timer.Connect (wxID_ANY, wxEVT_TIMER, wxTimerEventHandler (FilmViewer::timer), 0, this); + _back_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmViewer::back_clicked), 0, this); + _forward_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmViewer::forward_clicked), 0, this); set_film (f); @@ -121,7 +129,7 @@ FilmViewer::film_changed (Film::Property p) if (_decoders.video == 0) { break; } - _decoders.video->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3)); + _decoders.video->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3, _4)); _decoders.video->OutputChanged.connect (boost::bind (&FilmViewer::decoder_changed, this)); _decoders.video->set_subtitle_stream (_film->subtitle_stream()); calculate_sizes (); @@ -392,7 +400,7 @@ FilmViewer::check_play_state () } void -FilmViewer::process_video (shared_ptr image, bool, shared_ptr sub) +FilmViewer::process_video (shared_ptr image, bool, shared_ptr sub, double t) { _raw_frame = image; _raw_sub = sub; @@ -401,7 +409,6 @@ FilmViewer::process_video (shared_ptr image, bool, shared_ptr s _got_frame = true; - double const t = _decoders.video->last_source_time (); double const fps = _decoders.video->frames_per_second (); _frame->SetLabel (wxString::Format ("%d", int (rint (t * fps)))); @@ -465,3 +472,28 @@ FilmViewer::active_jobs_changed (bool a) _play_button->Enable (!a); } +void +FilmViewer::back_clicked (wxCommandEvent &) +{ + if (!_decoders.video) { + return; + } + + _decoders.video->seek_back (); + get_frame (); + _panel->Refresh (); + _panel->Update (); +} + +void +FilmViewer::forward_clicked (wxCommandEvent &) +{ + if (!_decoders.video) { + return; + } + + _decoders.video->seek_forward (); + get_frame (); + _panel->Refresh (); + _panel->Update (); +} diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 859bf7ede..a78c772a4 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -48,7 +48,7 @@ private: void slider_moved (wxScrollEvent &); void play_clicked (wxCommandEvent &); void timer (wxTimerEvent &); - void process_video (boost::shared_ptr, bool, boost::shared_ptr); + void process_video (boost::shared_ptr, bool, boost::shared_ptr, double); void calculate_sizes (); void check_play_state (); void update_from_raw (); @@ -56,12 +56,16 @@ private: void raw_to_display (); void get_frame (); void active_jobs_changed (bool); + void back_clicked (wxCommandEvent &); + void forward_clicked (wxCommandEvent &); boost::shared_ptr _film; wxSizer* _v_sizer; wxPanel* _panel; wxSlider* _slider; + wxButton* _back_button; + wxButton* _forward_button; wxStaticText* _frame; wxStaticText* _timecode; wxToggleButton* _play_button; -- cgit v1.2.3