+2018-09-10 Carl Hetherington <cth@carlh.net>
+
+ * Basic export of multiple reels to multiple files.
+
2018-09-09 Carl Hetherington <cth@carlh.net>
* Updated fr_FR translation from Thierry Journet.
using std::runtime_error;
using std::cout;
using std::pair;
+using std::list;
using boost::shared_ptr;
using boost::bind;
using boost::weak_ptr;
-
-FFmpegEncoder::FFmpegEncoder (shared_ptr<const Film> film, weak_ptr<Job> job, boost::filesystem::path output, ExportFormat format, bool mixdown_to_stereo, int x264_crf)
+FFmpegEncoder::FFmpegEncoder (
+ shared_ptr<const Film> film,
+ weak_ptr<Job> job,
+ boost::filesystem::path output,
+ ExportFormat format,
+ bool mixdown_to_stereo,
+ bool split_reels,
+ int x264_crf
+ )
: Encoder (film, job)
- , _file_encoder (
- _film->frame_size(),
- _film->video_frame_rate(),
- _film->audio_frame_rate(),
- mixdown_to_stereo ? 2 : film->audio_channels(),
- _film->log(),
- format,
- x264_crf,
- output
- )
, _history (1000)
{
+ int const files = split_reels ? film->reels().size() : 1;
+ for (int i = 0; i < files; ++i) {
+
+ boost::filesystem::path filename = output;
+ if (files > 1) {
+ string extension = boost::filesystem::extension (filename);
+ filename = boost::filesystem::change_extension (filename, "");
+ /// TRANSLATORS: _reel%1.%2 here is to be added to an export filename to indicate
+ /// which reel it is. Preserve the %1 and %2; %1 will be replaced with the reel number
+ /// and %2 with the file extension.
+ filename = filename.string() + String::compose(_("_reel%1%2"), i + 1, extension);
+ }
+
+ _file_encoders.push_back (
+ shared_ptr<FFmpegFileEncoder>(
+ new FFmpegFileEncoder(
+ _film->frame_size(),
+ _film->video_frame_rate(),
+ _film->audio_frame_rate(),
+ mixdown_to_stereo ? 2 : film->audio_channels(),
+ _film->log(),
+ format,
+ x264_crf,
+ filename
+ )
+ )
+ );
+ }
+
_player->set_always_burn_open_subtitles ();
_player->set_play_referenced ();
job->sub (_("Encoding"));
}
+ list<DCPTimePeriod> reel_periods = _film->reels ();
+ list<DCPTimePeriod>::const_iterator reel = reel_periods.begin ();
+ list<shared_ptr<FFmpegFileEncoder> >::iterator encoder = _file_encoders.begin ();
+
DCPTime const video_frame = DCPTime::from_frames (1, _film->video_frame_rate ());
int const audio_frames = video_frame.frames_round(_film->audio_frame_rate());
float* interleaved = new float[_output_audio_channels * audio_frames];
shared_ptr<AudioBuffers> deinterleaved (new AudioBuffers (_output_audio_channels, audio_frames));
for (DCPTime i; i < _film->length(); i += video_frame) {
+
+ if (!reel->contains(i)) {
+ ++reel;
+ ++encoder;
+ DCPOMATIC_ASSERT (reel != reel_periods.end());
+ DCPOMATIC_ASSERT (encoder != _file_encoders.end());
+ }
+
pair<shared_ptr<PlayerVideo>, DCPTime> v = _butler->get_video ();
- _file_encoder.video (v.first, v.second);
+ (*encoder)->video (v.first, v.second);
_history.event ();
deinterleaved->data(k)[j] = *p++;
}
}
- _file_encoder.audio (deinterleaved);
+ (*encoder)->audio (deinterleaved);
}
delete[] interleaved;
- _file_encoder.flush ();
+ BOOST_FOREACH (shared_ptr<FFmpegFileEncoder> i, _file_encoders) {
+ i->flush ();
+ }
}
float
class FFmpegEncoder : public Encoder
{
public:
- FFmpegEncoder (boost::shared_ptr<const Film> film, boost::weak_ptr<Job> job, boost::filesystem::path output, ExportFormat format, bool mixdown_to_stereo, int x264_crf);
+ FFmpegEncoder (
+ boost::shared_ptr<const Film> film,
+ boost::weak_ptr<Job> job,
+ boost::filesystem::path output,
+ ExportFormat format,
+ bool mixdown_to_stereo,
+ bool split_reels,
+ int x264_crf
+ );
void go ();
}
private:
- FFmpegFileEncoder _file_encoder;
+ std::list<boost::shared_ptr<FFmpegFileEncoder> > _file_encoders;
int _output_audio_channels;
mutable boost::mutex _mutex;
ExportDialog* d = new ExportDialog (this);
if (d->ShowModal() == wxID_OK) {
shared_ptr<TranscodeJob> job (new TranscodeJob (_film));
- job->set_encoder (shared_ptr<FFmpegEncoder> (new FFmpegEncoder (_film, job, d->path(), d->format(), d->mixdown_to_stereo(), d->x264_crf())));
+ job->set_encoder (
+ shared_ptr<FFmpegEncoder> (
+ new FFmpegEncoder (_film, job, d->path(), d->format(), d->mixdown_to_stereo(), d->split_reels(), d->x264_crf())
+ )
+ );
JobManager::instance()->add (job);
}
d->Destroy ();
add_spacer ();
_mixdown = new wxCheckBox (this, wxID_ANY, _("Mix audio down to stereo"));
add (_mixdown, false);
+ add_spacer ();
+ _split_reels = new wxCheckBox (this, wxID_ANY, _("Write reels into separate files"));
+ add (_split_reels, false);
_x264_crf_label[0] = add (_("Quality"), true);
_x264_crf = new wxSlider (this, wxID_ANY, 23, 0, 51, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL | wxSL_LABELS);
add (_x264_crf, false);
return _mixdown->GetValue ();
}
+bool
+ExportDialog::split_reels () const
+{
+ return _split_reels->GetValue ();
+}
+
int
ExportDialog::x264_crf () const
{
boost::filesystem::path path () const;
ExportFormat format () const;
bool mixdown_to_stereo () const;
+ bool split_reels () const;
int x264_crf () const;
private:
wxChoice* _format;
wxCheckBox* _mixdown;
+ wxCheckBox* _split_reels;
wxSlider* _x264_crf;
wxStaticText* _x264_crf_label[2];
FilePickerCtrl* _file;
film->write_metadata ();
shared_ptr<Job> job (new TranscodeJob (film));
- FFmpegEncoder encoder (film, job, String::compose("build/test/%1.%2", name, extension), format, false, 23);
+ FFmpegEncoder encoder (film, job, String::compose("build/test/%1.%2", name, extension), format, false, false, 23);
encoder.go ();
}
film->write_metadata ();
shared_ptr<Job> job (new TranscodeJob (film));
- FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test5.mov", EXPORT_FORMAT_PRORES, false, 23);
+ FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test5.mov", EXPORT_FORMAT_PRORES, false, false, 23);
encoder.go ();
}
film->write_metadata();
shared_ptr<Job> job (new TranscodeJob (film));
- FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test6.mov", EXPORT_FORMAT_PRORES, false, 23);
+ FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test6.mov", EXPORT_FORMAT_PRORES, false, false, 23);
encoder.go ();
}
s->only_text()->set_effect_colour (dcp::Colour (0, 255, 255));
shared_ptr<Job> job (new TranscodeJob (film));
- FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test7.mov", EXPORT_FORMAT_PRORES, false, 23);
+ FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_prores_test7.mov", EXPORT_FORMAT_PRORES, false, false, 23);
encoder.go ();
}
film->write_metadata();
shared_ptr<Job> job (new TranscodeJob (film));
- FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test2.mp4", EXPORT_FORMAT_H264, false, 23);
+ FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test2.mp4", EXPORT_FORMAT_H264, false, false, 23);
encoder.go ();
}
film->write_metadata();
shared_ptr<Job> job (new TranscodeJob (film));
- FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test3.mp4", EXPORT_FORMAT_H264, false, 23);
+ FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test3.mp4", EXPORT_FORMAT_H264, false, false, 23);
encoder.go ();
}
film->set_container(Ratio::from_id("185"));
shared_ptr<Job> job(new TranscodeJob(film));
- FFmpegEncoder encoder(film, job, "build/test/ffmpeg_encoder_h264_test4.mp4", EXPORT_FORMAT_H264, false, 23);
+ FFmpegEncoder encoder(film, job, "build/test/ffmpeg_encoder_h264_test4.mp4", EXPORT_FORMAT_H264, false, false, 23);
encoder.go();
}
Rs->audio->set_mapping (map);
shared_ptr<Job> job (new TranscodeJob (film));
- FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test5.mp4", EXPORT_FORMAT_H264, true, 23);
+ FFmpegEncoder encoder (film, job, "build/test/ffmpeg_encoder_h264_test5.mp4", EXPORT_FORMAT_H264, true, false, 23);
encoder.go ();
check_ffmpeg ("build/test/ffmpeg_encoder_h264_test5.mp4", "test/data/ffmpeg_encoder_h264_test5.mp4", 1);