Untested trim of start and end.
authorCarl Hetherington <cth@carlh.net>
Sun, 4 Nov 2012 02:12:12 +0000 (02:12 +0000)
committerCarl Hetherington <cth@carlh.net>
Sun, 4 Nov 2012 02:12:12 +0000 (02:12 +0000)
16 files changed:
src/lib/decoder.cc
src/lib/decoder.h
src/lib/ffmpeg_decoder.cc
src/lib/ffmpeg_decoder.h
src/lib/film.cc
src/lib/film.h
src/lib/imagemagick_decoder.cc
src/lib/imagemagick_decoder.h
src/lib/tiff_decoder.cc
src/lib/tiff_decoder.h
src/wx/dcp_range_dialog.cc
src/wx/dcp_range_dialog.h
src/wx/film_editor.cc
src/wx/film_editor.h
src/wx/properties_dialog.cc
test/test.cc

index 32d0bab64a2df1c77228a45994e727dcd3a05578..6da45a788cdc2573268c0772533bc540f8d4f99c 100644 (file)
@@ -142,27 +142,13 @@ Decoder::go ()
 
        while (pass () == false) {
                if (_job && _film->dcp_length()) {
-                       _job->set_progress (float (_video_frame_index) / _film->dcp_length().get());
+                       _job->set_progress (float ((_video_frame_index - _film->dcp_trim_start())) / _film->dcp_length().get());
                }
        }
 
        process_end ();
 }
 
-/** Run one pass.  This may or may not generate any actual video / audio data;
- *  some decoders may require several passes to generate a single frame.
- *  @return true if we have finished processing all data; otherwise false.
- */
-bool
-Decoder::pass ()
-{
-       if (!_ignore_length && _video_frame_index >= _film->dcp_length()) {
-               return true;
-       }
-
-       return do_pass ();
-}
-
 /** Called by subclasses to tell the world that some audio data is ready
  *  @param data Audio data, in Film::audio_sample_format.
  *  @param size Number of bytes of data.
@@ -265,6 +251,8 @@ Decoder::emit_audio (uint8_t* data, int size)
 void
 Decoder::process_video (AVFrame* frame)
 {
+       assert (_film->length());
+       
        if (_minimal) {
                ++_video_frame_index;
                return;
@@ -282,6 +270,11 @@ Decoder::process_video (AVFrame* frame)
                return;
        }
 
+       if (_film->dcp_trim_start() > _video_frame_index || (_film->length().get() - _film->dcp_trim_end()) < _video_frame_index) {
+               ++_video_frame_index;
+               return;
+       }
+
        shared_ptr<FilterGraph> graph;
 
        list<shared_ptr<FilterGraph> >::iterator i = _filter_graphs.begin();
index 6cd7757b6562c05a36ee099f8b57b4a4769f5f39..e8e73cc9f851688b720a7539ff577db5d2d29a94 100644 (file)
@@ -76,7 +76,7 @@ public:
        virtual int sample_aspect_ratio_denominator () const = 0;
        
        void process_begin ();
-       bool pass ();
+       virtual bool pass () = 0;
        void process_end ();
        void go ();
 
@@ -105,8 +105,6 @@ public:
 
 protected:
        
-       /** perform a single pass at our content */
-       virtual bool do_pass () = 0;
        virtual PixelFormat pixel_format () const = 0;
        
        void process_video (AVFrame *);
index 09f699543c790c6755b59cb6d54530833c793039..198925bd3a4285a9ed35e50a8ed2fff14de9bef4 100644 (file)
@@ -218,7 +218,7 @@ FFmpegDecoder::setup_subtitle ()
 
 
 bool
-FFmpegDecoder::do_pass ()
+FFmpegDecoder::pass ()
 {
        int r = av_read_frame (_format_context, &_packet);
        
index c04dba5b3cbd0be52b68e46282403b74bbaee01d..3f96c1632545abacd6599b30853955876dcda98e 100644 (file)
@@ -69,7 +69,7 @@ public:
 
 private:
 
-       bool do_pass ();
+       bool pass ();
        PixelFormat pixel_format () const;
        int time_base_numerator () const;
        int time_base_denominator () const;
index 70c8f7db2e66457e9e408bb0a019385bb17e3163..b2abe4759db685f37b7ffbbd65762535cd2a4fc8 100644 (file)
@@ -82,6 +82,8 @@ Film::Film (string d, bool must_exist)
        , _dcp_content_type (0)
        , _format (0)
        , _scaler (Scaler::from_id ("bicubic"))
+       , _dcp_trim_start (0)
+       , _dcp_trim_end (0)
        , _dcp_ab (false)
        , _audio_stream (-1)
        , _audio_gain (0)
@@ -141,7 +143,8 @@ Film::Film (Film const & o)
        , _crop              (o._crop)
        , _filters           (o._filters)
        , _scaler            (o._scaler)
-       , _dcp_frames        (o._dcp_frames)
+       , _dcp_trim_start    (o._dcp_trim_start)
+       , _dcp_trim_end      (o._dcp_trim_end)
        , _dcp_ab            (o._dcp_ab)
        , _audio_stream      (o._audio_stream)
        , _audio_gain        (o._audio_gain)
@@ -402,7 +405,8 @@ Film::write_metadata () const
                f << "filter " << (*i)->id () << "\n";
        }
        f << "scaler " << _scaler->id () << "\n";
-       f << "dcp_frames " << _dcp_frames.get_value_or(0) << "\n";
+       f << "dcp_trim_start " << _dcp_trim_start << "\n";
+       f << "dcp_trim_end " << _dcp_trim_end << "\n";
        f << "dcp_ab " << (_dcp_ab ? "1" : "0") << "\n";
        f << "selected_audio_stream " << _audio_stream << "\n";
        f << "audio_gain " << _audio_gain << "\n";
@@ -481,11 +485,10 @@ Film::read_metadata ()
                        _filters.push_back (Filter::from_id (v));
                } else if (k == "scaler") {
                        _scaler = Scaler::from_id (v);
-               } else if (k == "dcp_frames") {
-                       int const vv = atoi (v.c_str ());
-                       if (vv) {
-                               _dcp_frames = vv;
-                       }
+               } else if (k == "dcp_trim_start") {
+                       _dcp_trim_start = atoi (v.c_str ());
+               } else if (k == "dcp_trim_end") {
+                       _dcp_trim_end = atoi (v.c_str ());
                } else if (k == "dcp_ab") {
                        _dcp_ab = (v == "1");
                } else if (k == "selected_audio_stream") {
@@ -699,11 +702,7 @@ Film::dcp_length () const
                return boost::optional<int> ();
        }
 
-       if (dcp_frames()) {
-               return min (dcp_frames().get(), length().get());
-       }
-
-       return length();
+       return length().get() - dcp_trim_start() - dcp_trim_end();
 }
 
 /** @return a DCI-compliant name for a DCP of this film */
@@ -1012,23 +1011,23 @@ Film::set_scaler (Scaler const * s)
 }
 
 void
-Film::set_dcp_frames (int f)
+Film::set_dcp_trim_start (int t)
 {
        {
                boost::mutex::scoped_lock lm (_state_mutex);
-               _dcp_frames = f;
+               _dcp_trim_start = t;
        }
-       signal_changed (DCP_FRAMES);
+       signal_changed (DCP_TRIM_START);
 }
 
 void
-Film::unset_dcp_frames ()
+Film::set_dcp_trim_end (int t)
 {
        {
                boost::mutex::scoped_lock lm (_state_mutex);
-               _dcp_frames = boost::none;
+               _dcp_trim_end = t;
        }
-       signal_changed (DCP_FRAMES);
+       signal_changed (DCP_TRIM_END);
 }
 
 void
index ff312fcb537155a27683351deeefa1aac5317d04..eeaae2acdaba9b3dab123a22381f723349826559 100644 (file)
@@ -117,7 +117,8 @@ public:
                CROP,
                FILTERS,
                SCALER,
-               DCP_FRAMES,
+               DCP_TRIM_START,
+               DCP_TRIM_END,
                DCP_AB,
                AUDIO_STREAM,
                AUDIO_GAIN,
@@ -186,11 +187,16 @@ public:
                return _scaler;
        }
 
-       boost::optional<int> dcp_frames () const {
+       int dcp_trim_start () const {
                boost::mutex::scoped_lock lm (_state_mutex);
-               return _dcp_frames;
+               return _dcp_trim_start;
        }
 
+       int dcp_trim_end () const {
+               boost::mutex::scoped_lock lm (_state_mutex);
+               return _dcp_trim_end;
+       }
+       
        bool dcp_ab () const {
                boost::mutex::scoped_lock lm (_state_mutex);
                return _dcp_ab;
@@ -344,8 +350,8 @@ public:
        void set_bottom_crop (int);
        void set_filters (std::vector<Filter const *>);
        void set_scaler (Scaler const *);
-       void set_dcp_frames (int);
-       void unset_dcp_frames ();
+       void set_dcp_trim_start (int);
+       void set_dcp_trim_end (int);
        void set_dcp_ab (bool);
        void set_audio_stream (int);
        void set_audio_gain (float);
@@ -416,8 +422,8 @@ private:
        std::vector<Filter const *> _filters;
        /** Scaler algorithm to use */
        Scaler const * _scaler;
-       /** Maximum number of frames to put in the DCP, if applicable */
-       boost::optional<int> _dcp_frames;
+       int _dcp_trim_start;
+       int _dcp_trim_end;
        /** true to create an A/B comparison DCP, where the left half of the image
            is the video without any filters or post-processing, and the right half
            has the specified filters and post-processing.
index 76d89b7d8e4ef48266a02d0727129aa643737623..8abefdbb9938b873d001f86ed9fac54c262a0310 100644 (file)
@@ -41,7 +41,7 @@ ImageMagickDecoder::native_size () const
 }
 
 bool
-ImageMagickDecoder::do_pass ()
+ImageMagickDecoder::pass ()
 {
        using namespace MagickCore;
        
index 13b53b68523be8f9df2b4a63d293f149d7cc4fe7..c8e47d47dc3ccef2de16accbafdd8892e637f622 100644 (file)
@@ -59,7 +59,7 @@ public:
        }
 
 protected:
-       bool do_pass ();
+       bool pass ();
        PixelFormat pixel_format () const;
 
        int time_base_numerator () const {
index 9058fcc2a5ba6ab82c8b94081c9f60e2b3517fa4..e75f2c4829d23cde369ead11cc9a680f646cddfc 100644 (file)
@@ -131,7 +131,7 @@ TIFFDecoder::audio_channel_layout () const
 }
 
 bool
-TIFFDecoder::do_pass ()
+TIFFDecoder::pass ()
 {
        if (_iter == _files.end ()) {
                return true;
index 1c287ee065385ab7bd40b9d4ee0f5971f25ee3db..7bbff7dfed6bb59acfea86db824932d711c590b3 100644 (file)
@@ -56,7 +56,7 @@ public:
        }
 
 private:
-       bool do_pass ();
+       bool pass ();
        PixelFormat pixel_format () const;
        int time_base_numerator () const;
        int time_base_denominator () const;
index 5ecd3168e8d2b5ac03d5970552b49280e57abee1..e249f6fc6f88346e95093965433ea0e022d99ea2 100644 (file)
@@ -27,36 +27,23 @@ DCPRangeDialog::DCPRangeDialog (wxWindow* p, shared_ptr<Film> f)
        : wxDialog (p, wxID_ANY, wxString (_("DCP Range")))
        , _film (f)
 {
-       wxFlexGridSizer* table = new wxFlexGridSizer (2, 6, 6);
+       wxFlexGridSizer* table = new wxFlexGridSizer (3, 6, 6);
 
-       _whole = new wxRadioButton (this, wxID_ANY, _("Whole film"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
-       table->Add (_whole, 1);
-       table->AddSpacer (0);
-       
-       _first = new wxRadioButton (this, wxID_ANY, _("First"));
-       table->Add (_first);
-       {
-               wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
-               _n_frames = new wxSpinCtrl (this, wxID_ANY);
-               s->Add (_n_frames);
-               add_label_to_sizer (s, this, "frames");
-               table->Add (s);
-       }
+       add_label_to_sizer (table, this, "Trim start");
+       _trim_start = new wxSpinCtrl (this, wxID_ANY);
+       table->Add (_trim_start, 1);
+       add_label_to_sizer (table, this, "frames");
 
-       _n_frames->SetRange (1, INT_MAX - 1);
-       if (_film->dcp_frames()) {
-               _whole->SetValue (false);
-               _first->SetValue (true);
-               _n_frames->SetValue (_film->dcp_frames().get());
-       } else {
-               _whole->SetValue (true);
-               _first->SetValue (false);
-               _n_frames->SetValue (24);
-       }
+       add_label_to_sizer (table, this, "Trim end");
+       _trim_end = new wxSpinCtrl (this, wxID_ANY);
+       table->Add (_trim_end, 1);
+       add_label_to_sizer (table, this, "frames");
 
-       _whole->Connect (wxID_ANY, wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler (DCPRangeDialog::whole_toggled), 0, this);
-       _first->Connect (wxID_ANY, wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler (DCPRangeDialog::first_toggled), 0, this);
-       _n_frames->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (DCPRangeDialog::n_frames_changed), 0, this);
+       _trim_start->SetValue (_film->dcp_trim_start());
+       _trim_end->SetValue (_film->dcp_trim_end());
+
+       _trim_start->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (DCPRangeDialog::emit_changed), 0, this);
+       _trim_end->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (DCPRangeDialog::emit_changed), 0, this);
 
        wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
        overall_sizer->Add (table, 0, wxALL, 6);
@@ -68,43 +55,10 @@ DCPRangeDialog::DCPRangeDialog (wxWindow* p, shared_ptr<Film> f)
 
        SetSizer (overall_sizer);
        overall_sizer->SetSizeHints (this);
-
-       set_sensitivity ();
-}
-
-void
-DCPRangeDialog::whole_toggled (wxCommandEvent &)
-{
-       set_sensitivity ();
-       emit_changed ();
 }
 
 void
-DCPRangeDialog::first_toggled (wxCommandEvent &)
+DCPRangeDialog::emit_changed (wxCommandEvent &)
 {
-       set_sensitivity ();
-       emit_changed ();
-}
-
-void
-DCPRangeDialog::set_sensitivity ()
-{
-       _n_frames->Enable (_first->GetValue ());
-}
-
-void
-DCPRangeDialog::n_frames_changed (wxCommandEvent &)
-{
-       emit_changed ();
-}
-
-void
-DCPRangeDialog::emit_changed ()
-{
-       int frames = 0;
-       if (!_whole->GetValue ()) {
-               frames = _n_frames->GetValue ();
-       }
-
-       Changed (frames);
+       Changed (_trim_start->GetValue(), _trim_end->GetValue());
 }
index e3f875e516b3523c3ff35256f55d90ba6af12148..2196c2611ad3459858e01f59a2b2e236e39e1534 100644 (file)
@@ -28,18 +28,15 @@ class DCPRangeDialog : public wxDialog
 public:
        DCPRangeDialog (wxWindow *, boost::shared_ptr<Film>);
 
-       boost::signals2::signal<void (int)> Changed;
+       boost::signals2::signal<void (int, int)> Changed;
 
 private:
-       void whole_toggled (wxCommandEvent &);
-       void first_toggled (wxCommandEvent &);
-       void n_frames_changed (wxCommandEvent &);
+       void trim_start_changed (wxCommandEvent &);
+       void trim_end_changed (wxCommandEvent &);
        
-       void set_sensitivity ();
-       void emit_changed ();
+       void emit_changed (wxCommandEvent &);
        
        boost::shared_ptr<Film> _film;
-       wxRadioButton* _whole;
-       wxRadioButton* _first;
-       wxSpinCtrl* _n_frames;
+       wxSpinCtrl* _trim_start;
+       wxSpinCtrl* _trim_end;
 };
index 8bcbd2beb66899fc5e140632db7952854dbe8305..7038a18b0367a18e436cd70aac26114df1e44fe9 100644 (file)
@@ -502,20 +502,23 @@ FilmEditor::film_changed (Film::Property p)
                break;
        case Film::THUMBS:
                break;
-       case Film::DCP_FRAMES:
-               if (!_film->dcp_frames()) {
-                       _dcp_range->SetLabel (wxT ("Whole film"));
-               } else {
-                       _dcp_range->SetLabel (std_to_wx (String::compose ("First %1 frames", _film->dcp_frames().get())));
-               }
-               _sizer->Layout ();
-               break;
        case Film::DCP_AB:
                _dcp_ab->SetValue (_film->dcp_ab ());
                break;
        case Film::SCALER:
                _scaler->SetSelection (Scaler::as_index (_film->scaler ()));
                break;
+       case Film::DCP_TRIM_START:
+       case Film::DCP_TRIM_END:
+               if (_film->dcp_trim_start() == 0 && _film->dcp_trim_end() == 0) {
+                       _dcp_range->SetLabel (wxT ("Whole film"));
+               } else {
+                       _dcp_range->SetLabel (
+                               std_to_wx (String::compose ("Trim %1 frames from start and %2 frames from end", _film->dcp_trim_start(), _film->dcp_trim_end()))
+                               );
+               }
+               _sizer->Layout ();
+               break;
        case Film::AUDIO_GAIN:
                _audio_gain->SetValue (_film->audio_gain ());
                break;
@@ -616,7 +619,8 @@ FilmEditor::set_film (shared_ptr<Film> f)
        film_changed (Film::FORMAT);
        film_changed (Film::CROP);
        film_changed (Film::FILTERS);
-       film_changed (Film::DCP_FRAMES);
+       film_changed (Film::DCP_TRIM_START);
+       film_changed (Film::DCP_TRIM_END);
        film_changed (Film::DCP_AB);
        film_changed (Film::SIZE);
        film_changed (Film::LENGTH);
@@ -764,18 +768,15 @@ void
 FilmEditor::change_dcp_range_clicked (wxCommandEvent &)
 {
        DCPRangeDialog* d = new DCPRangeDialog (this, _film);
-       d->Changed.connect (bind (&FilmEditor::dcp_range_changed, this, _1));
+       d->Changed.connect (bind (&FilmEditor::dcp_range_changed, this, _1, _2));
        d->ShowModal ();
 }
 
 void
-FilmEditor::dcp_range_changed (int frames)
+FilmEditor::dcp_range_changed (int start, int end)
 {
-       if (frames == 0) {
-               _film->unset_dcp_frames ();
-       } else {
-               _film->set_dcp_frames (frames);
-       }
+       _film->set_dcp_trim_start (start);
+       _film->set_dcp_trim_end (end);
 }
 
 void
index 936dd7d6b5b020ead597a13c37b5f4866ffde5a9..e9f8d35e5ca349e1bdaed1ecf19826847366bc9d 100644 (file)
@@ -54,7 +54,7 @@ private:
        void bottom_crop_changed (wxCommandEvent &);
        void content_changed (wxCommandEvent &);
        void format_changed (wxCommandEvent &);
-       void dcp_range_changed (int);
+       void dcp_range_changed (int, int);
        void dcp_content_type_changed (wxCommandEvent &);
        void dcp_ab_toggled (wxCommandEvent &);
        void scaler_changed (wxCommandEvent &);
index 0ffbd06cba7478d3dda36ab264f8568709b0c3af..61e1f34f0ab1d8513d18a464dae7cd4fb835e5ef 100644 (file)
@@ -92,7 +92,8 @@ PropertiesDialog::frames_already_encoded () const
        }
        
        if (_film->dcp_length()) {
-               u << " (" << (_film->encoded_frames() * 100 / _film->dcp_length().get()) << "%)";
+               /* XXX: encoded_frames() should check which frames have been encoded */
+               u << " (" << ((_film->encoded_frames() - _film->dcp_trim_start()) * 100 / _film->dcp_length().get()) << "%)";
        }
        return u.str ();
 }
index af5c1f501902d1b0049b19e8efad3b3e425c35d0..f05c7ad83fa0483b57f250be68a512389bd090ad 100644 (file)
@@ -99,7 +99,8 @@ BOOST_AUTO_TEST_CASE (film_metadata_test)
        f_filters.push_back (Filter::from_id ("pphb"));
        f_filters.push_back (Filter::from_id ("unsharp"));
        f->set_filters (f_filters);
-       f->set_dcp_frames (42);
+       f->set_dcp_trim_start (42);
+       f->set_dcp_trim_start (99);
        f->set_dcp_ab (true);
        f->write_metadata ();
 
@@ -120,7 +121,8 @@ BOOST_AUTO_TEST_CASE (film_metadata_test)
        BOOST_CHECK_EQUAL (g_filters.size(), 2);
        BOOST_CHECK_EQUAL (g_filters.front(), Filter::from_id ("pphb"));
        BOOST_CHECK_EQUAL (g_filters.back(), Filter::from_id ("unsharp"));
-       BOOST_CHECK_EQUAL (g->dcp_frames(), 42);
+       BOOST_CHECK_EQUAL (g->dcp_trim_start(), 42);
+       BOOST_CHECK_EQUAL (g->dcp_trim_end(), 99);
        BOOST_CHECK_EQUAL (g->dcp_ab(), true);
        
        g->write_metadata ();
@@ -392,7 +394,7 @@ BOOST_AUTO_TEST_CASE (make_dcp_with_range_test)
        film->examine_content ();
        film->set_format (Format::from_nickname ("Flat"));
        film->set_dcp_content_type (DCPContentType::from_pretty_name ("Test"));
-       film->set_dcp_frames (42);
+       film->set_dcp_trim_end (42);
        film->make_dcp (true);
 
        while (JobManager::instance()->work_to_do() && !JobManager::instance()->errors()) {