_allowed_dcp_frame_rates.push_back (24);
_allowed_dcp_frame_rates.push_back (25);
_allowed_dcp_frame_rates.push_back (30);
+ _allowed_dcp_frame_rates.push_back (48);
+ _allowed_dcp_frame_rates.push_back (50);
+ _allowed_dcp_frame_rates.push_back (60);
ifstream f (file().c_str ());
string line;
log()->log (String::compose (N_("Content length %1"), length().get()));
}
log()->log (String::compose (N_("Content digest %1"), content_digest()));
+ log()->log (String::compose ("Content at %1 fps, DCP at %2 fps", source_frame_rate(), dcp_frame_rate()));
log()->log (String::compose (N_("%1 threads"), Config::instance()->num_local_encoding_threads()));
log()->log (String::compose (N_("J2K bandwidth %1"), j2k_bandwidth()));
#ifdef DVDOMATIC_DEBUG
_external_audio_stream = audio_stream_factory (v, version);
} else if (k == N_("subtitle_stream")) {
_subtitle_streams.push_back (subtitle_stream_factory (v, version));
- } else if (k == N_("source_frame_rate") || (version < 4 && k == "frames_per_second")) {
+ } else if (k == N_("source_frame_rate")) {
_source_frame_rate = atof (v.c_str ());
+ } else if (version < 4 && k == "frames_per_second") {
+ _source_frame_rate = atof (v.c_str ());
+ /* Fill in what would have been used for DCP frame rate by the older version */
+ _dcp_frame_rate = best_dcp_frame_rate (_source_frame_rate);
}
}
set_size (d.video->native_size ());
set_source_frame_rate (d.video->frames_per_second ());
+ set_dcp_frame_rate (best_dcp_frame_rate (source_frame_rate ()));
set_subtitle_streams (d.video->subtitle_streams ());
if (d.audio) {
set_content_audio_streams (d.audio->audio_streams ());
video_control (add_label_to_sizer (grid, _film_panel, _("Original Frame Rate")));
_source_frame_rate = new wxStaticText (_film_panel, wxID_ANY, wxT (""));
grid->Add (video_control (_source_frame_rate), 1, wxALIGN_CENTER_VERTICAL);
+
+ {
+ add_label_to_sizer (grid, _film_panel, _("DCP Frame Rate"));
+ wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
+ _dcp_frame_rate = new wxChoice (_film_panel, wxID_ANY);
+ s->Add (_dcp_frame_rate, 1, wxALIGN_CENTER_VERTICAL);
+ _best_dcp_frame_rate = new wxButton (_film_panel, wxID_ANY, _("Use best"));
+ s->Add (_best_dcp_frame_rate, 1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 6);
+ grid->Add (s, 1);
+ }
video_control (add_label_to_sizer (grid, _film_panel, _("Original Size")));
_original_size = new wxStaticText (_film_panel, wxID_ANY, wxT (""));
for (vector<DCPContentType const *>::const_iterator i = ct.begin(); i != ct.end(); ++i) {
_dcp_content_type->Append (std_to_wx ((*i)->pretty_name ()));
}
+
+ list<int> const dfr = Config::instance()->allowed_dcp_frame_rates ();
+ for (list<int>::const_iterator i = dfr.begin(); i != dfr.end(); ++i) {
+ _dcp_frame_rate->Append (std_to_wx (boost::lexical_cast<string> (*i)));
+ }
}
void
_filters_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::edit_filters_clicked), 0, this);
_scaler->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::scaler_changed), 0, this);
_dcp_content_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_content_type_changed), 0, this);
+ _dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_frame_rate_changed), 0, this);
+ _best_dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::best_dcp_frame_rate_clicked), 0, this);
_dcp_ab->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::dcp_ab_toggled), 0, this);
_still_duration->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::still_duration_changed), 0, this);
_trim_start->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_start_changed), 0, this);
}
_film->set_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1e6);
-}
+}
+
+void
+FilmEditor::dcp_frame_rate_changed (wxCommandEvent &)
+{
+ if (!_film) {
+ return;
+ }
+
+ _film->set_dcp_frame_rate (
+ boost::lexical_cast<int> (
+ wx_to_std (_dcp_frame_rate->GetString (_dcp_frame_rate->GetSelection ()))
+ )
+ );
+}
/** Called when the metadata stored in the Film object has changed;
setup_audio_details ();
break;
}
+ case Film::DCP_FRAME_RATE:
+ for (unsigned int i = 0; i < _dcp_frame_rate->GetCount(); ++i) {
+ if (wx_to_std (_dcp_frame_rate->GetString(i)) == boost::lexical_cast<string> (_film->dcp_frame_rate())) {
+ if (_dcp_frame_rate->GetSelection() != int(i)) {
+ _dcp_frame_rate->SetSelection (i);
+ break;
+ }
+ }
+ }
}
}
film_changed (Film::CONTENT_AUDIO_STREAMS);
film_changed (Film::SUBTITLE_STREAMS);
film_changed (Film::SOURCE_FRAME_RATE);
+ film_changed (Film::DCP_FRAME_RATE);
}
/** Updates the sensitivity of lots of widgets to a given value.
_scaler->Enable (s);
_audio_stream->Enable (s);
_dcp_content_type->Enable (s);
+ _dcp_frame_rate->Enable (s);
_trim_start->Enable (s);
_trim_end->Enable (s);
_dcp_ab->Enable (s);
_audio_dialog->Show ();
_audio_dialog->set_film (_film);
}
+
+void
+FilmEditor::best_dcp_frame_rate_clicked (wxCommandEvent &)
+{
+ if (!_film) {
+ return;
+ }
+
+ _film->set_dcp_frame_rate (best_dcp_frame_rate (_film->source_frame_rate ()));
+}
void subtitle_stream_changed (wxCommandEvent &);
void use_audio_changed (wxCommandEvent &);
void external_audio_changed (wxCommandEvent &);
+ void dcp_frame_rate_changed (wxCommandEvent &);
+ void best_dcp_frame_rate_clicked (wxCommandEvent &);
/* Handle changes to the model */
void film_changed (Film::Property);
wxChoice* _dcp_content_type;
/** The Film's source frame rate */
wxStaticText* _source_frame_rate;
+ wxChoice* _dcp_frame_rate;
+ wxButton* _best_dcp_frame_rate;
/** The Film's original size */
wxStaticText* _original_size;
/** The Film's length */
BOOST_CHECK_EQUAL (frc.skip, false);
BOOST_CHECK_EQUAL (frc.repeat, false);
BOOST_CHECK_EQUAL (frc.change_speed, false);
+
+ /* Check some out-there conversions (not the best) */
+
+ frc = FrameRateConversion (14.99, 24);
+ BOOST_CHECK_EQUAL (frc.skip, false);
+ BOOST_CHECK_EQUAL (frc.repeat, true);
+ BOOST_CHECK_EQUAL (frc.change_speed, true);
+
+ /* Check some conversions with limited DCP targets */
+
+ afr.clear ();
+ afr.push_back (24);
+ Config::instance()->set_allowed_dcp_frame_rates (afr);
+
+ best = best_dcp_frame_rate (25);
+ frc = FrameRateConversion (25, best);
+ BOOST_CHECK_EQUAL (best, 24);
+ BOOST_CHECK_EQUAL (frc.skip, false);
+ BOOST_CHECK_EQUAL (frc.repeat, false);
+ BOOST_CHECK_EQUAL (frc.change_speed, true);
}
BOOST_AUTO_TEST_CASE (audio_sampling_rate_test)
{
+ std::list<int> afr;
+ afr.push_back (24);
+ afr.push_back (25);
+ afr.push_back (30);
+ Config::instance()->set_allowed_dcp_frame_rates (afr);
+
shared_ptr<Film> f = new_test_film ("audio_sampling_rate_test");
f->set_source_frame_rate (24);
f->set_dcp_frame_rate (24);
f->set_source_frame_rate (29.97);
f->set_dcp_frame_rate (best_dcp_frame_rate (29.97));
+ BOOST_CHECK_EQUAL (f->dcp_frame_rate (), 30);
f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 47952);
+
+ f->set_source_frame_rate (25);
+ f->set_dcp_frame_rate (24);
+ f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 48000, 0)));
+ BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 50000);
+
+ f->set_source_frame_rate (25);
+ f->set_dcp_frame_rate (24);
+ f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 44100, 0)));
+ BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), 50000);
+
+ /* Check some out-there conversions (not the best) */
+
+ f->set_source_frame_rate (14.99);
+ f->set_dcp_frame_rate (25);
+ f->set_content_audio_stream (shared_ptr<AudioStream> (new FFmpegAudioStream ("a", 42, 16000, 0)));
+ /* The FrameRateConversion within target_audio_sample_rate should choose to double-up
+ the 14.99 fps video to 30 and then run it slow at 25.
+ */
+ BOOST_CHECK_EQUAL (f->target_audio_sample_rate(), rint (48000 * 2 * 14.99 / 25));
}
class TestJob : public Job