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.
void
Decoder::process_video (AVFrame* frame)
{
+ assert (_film->length());
+
if (_minimal) {
++_video_frame_index;
return;
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();
virtual int sample_aspect_ratio_denominator () const = 0;
void process_begin ();
- bool pass ();
+ virtual bool pass () = 0;
void process_end ();
void go ();
protected:
- /** perform a single pass at our content */
- virtual bool do_pass () = 0;
virtual PixelFormat pixel_format () const = 0;
void process_video (AVFrame *);
bool
-FFmpegDecoder::do_pass ()
+FFmpegDecoder::pass ()
{
int r = av_read_frame (_format_context, &_packet);
private:
- bool do_pass ();
+ bool pass ();
PixelFormat pixel_format () const;
int time_base_numerator () const;
int time_base_denominator () const;
, _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)
, _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)
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";
_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") {
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 */
}
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
CROP,
FILTERS,
SCALER,
- DCP_FRAMES,
+ DCP_TRIM_START,
+ DCP_TRIM_END,
DCP_AB,
AUDIO_STREAM,
AUDIO_GAIN,
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;
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);
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.
}
bool
-ImageMagickDecoder::do_pass ()
+ImageMagickDecoder::pass ()
{
using namespace MagickCore;
}
protected:
- bool do_pass ();
+ bool pass ();
PixelFormat pixel_format () const;
int time_base_numerator () const {
}
bool
-TIFFDecoder::do_pass ()
+TIFFDecoder::pass ()
{
if (_iter == _files.end ()) {
return true;
}
private:
- bool do_pass ();
+ bool pass ();
PixelFormat pixel_format () const;
int time_base_numerator () const;
int time_base_denominator () const;
: 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);
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());
}
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;
};
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;
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);
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
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 &);
}
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 ();
}
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 ();
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 ();
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()) {