DCPFilmEncoder::DCPFilmEncoder(shared_ptr<const Film> film, weak_ptr<Job> job)
: FilmEncoder(film, job)
, _writer(film, job)
- , _j2k_encoder(film, _writer)
+ , _encoder(new J2KEncoder(film, _writer))
, _finishing (false)
, _non_burnt_subtitles (false)
{
DCPFilmEncoder::go()
{
_writer.start();
- _j2k_encoder.begin();
+ _encoder->begin();
{
auto job = _job.lock ();
}
_finishing = true;
- _j2k_encoder.end();
+ _encoder->end();
_writer.finish(_film->dir(_film->dcp_name()));
}
void
DCPFilmEncoder::pause()
{
- _j2k_encoder.pause();
+ _encoder->pause();
}
void
DCPFilmEncoder::resume()
{
- _j2k_encoder.resume();
+ _encoder->resume();
}
void
DCPFilmEncoder::video(shared_ptr<PlayerVideo> data, DCPTime time)
{
- _j2k_encoder.encode(data, time);
+ _encoder->encode(data, time);
}
void
optional<float>
DCPFilmEncoder::current_rate() const
{
- return _j2k_encoder.current_encoding_rate();
+ return _encoder->current_encoding_rate();
}
Frame
DCPFilmEncoder::frames_done() const
{
- return _j2k_encoder.video_frames_enqueued();
+ return _encoder->video_frames_enqueued();
}
void atmos (std::shared_ptr<const dcp::AtmosFrame>, dcpomatic::DCPTime, AtmosMetadata metadata);
Writer _writer;
- J2KEncoder _j2k_encoder;
+ std::unique_ptr<VideoEncoder> _encoder;
bool _finishing;
bool _non_burnt_subtitles;
* @param writer Writer that we are using.
*/
J2KEncoder::J2KEncoder(shared_ptr<const Film> film, Writer& writer)
- : _film (film)
- , _history (200)
- , _writer (writer)
+ : VideoEncoder(film, writer)
{
#ifdef DCPOMATIC_GROK
auto grok = Config::instance()->grok().get_value_or({});
}
-/** @return an estimate of the current number of frames we are encoding per second,
- * if known.
- */
-optional<float>
-J2KEncoder::current_encoding_rate () const
-{
- return _history.rate ();
-}
-
-
-/** @return Number of video frames that have been queued for encoding */
-int
-J2KEncoder::video_frames_enqueued () const
-{
- if (!_last_player_video_time) {
- return 0;
- }
-
- return _last_player_video_time->frames_floor (_film->video_frame_rate ());
-}
-
-
/** Should be called when a frame has been encoded successfully */
void
J2KEncoder::frame_done ()
void
J2KEncoder::encode (shared_ptr<PlayerVideo> pv, DCPTime time)
{
+ VideoEncoder::encode(pv, time);
+
_waker.nudge ();
size_t threads = 0;
}
_last_player_video[pv->eyes()] = pv;
- _last_player_video_time = time;
}
#include "exception_store.h"
#include "j2k_encoder_thread.h"
#include "writer.h"
+#include "video_encoder.h"
#include <boost/optional.hpp>
#include <boost/signals2.hpp>
#include <boost/thread.hpp>
* This class keeps a queue of frames to be encoded and distributes
* the work around threads and encoding servers.
*/
-class J2KEncoder : public ExceptionStore
+class J2KEncoder : public VideoEncoder, public ExceptionStore
{
public:
J2KEncoder(std::shared_ptr<const Film> film, Writer& writer);
J2KEncoder& operator= (J2KEncoder const&) = delete;
/** Called to indicate that a processing run is about to begin */
- void begin ();
+ void begin() override;
/** Called to pass a bit of video to be encoded as the next DCP frame */
- void encode (std::shared_ptr<PlayerVideo> pv, dcpomatic::DCPTime time);
+ void encode (std::shared_ptr<PlayerVideo> pv, dcpomatic::DCPTime time) override;
- void pause();
- void resume();
+ void pause() override;
+ void resume() override;
/** Called when a processing run has finished */
- void end();
-
- boost::optional<float> current_encoding_rate () const;
- int video_frames_enqueued () const;
+ void end() override;
DCPVideo pop();
void retry(DCPVideo frame);
void remake_threads(int cpu, int gpu, std::list<EncodeServerDescription> servers);
void terminate_threads ();
- /** Film that we are encoding */
- std::shared_ptr<const Film> _film;
-
- EventHistory _history;
-
boost::mutex _threads_mutex;
std::vector<std::shared_ptr<J2KEncoderThread>> _threads;
/** condition to manage thread wakeups when we have too much to do */
boost::condition _full_condition;
- Writer& _writer;
Waker _waker;
EnumIndexedVector<std::shared_ptr<PlayerVideo>, Eyes> _last_player_video;
- boost::optional<dcpomatic::DCPTime> _last_player_video_time;
boost::signals2::scoped_connection _server_found_connection;
--- /dev/null
+/*
+ Copyright (C) 2024 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "video_encoder.h"
+
+
+using std::shared_ptr;
+using boost::optional;
+
+
+VideoEncoder::VideoEncoder(shared_ptr<const Film> film, Writer& writer)
+ : _film(film)
+ , _writer(writer)
+ , _history(200)
+{
+
+}
+
+
+void
+VideoEncoder::encode(shared_ptr<PlayerVideo>, dcpomatic::DCPTime time)
+{
+ _last_player_video_time = time;
+}
+
+
+/** @return Number of video frames that have been queued for encoding */
+int
+VideoEncoder::video_frames_enqueued() const
+{
+ if (!_last_player_video_time) {
+ return 0;
+ }
+
+ return _last_player_video_time->frames_floor(_film->video_frame_rate());
+}
+
+
+/** @return an estimate of the current number of frames we are encoding per second,
+ * if known.
+ */
+optional<float>
+VideoEncoder::current_encoding_rate() const
+{
+ return _history.rate();
+}
--- /dev/null
+/*
+ Copyright (C) 2024 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#ifndef DCPOMATIC_VIDEO_ENCODER_H
+#define DCPOMATIC_VIDEO_ENCODER_H
+
+
+#include "dcpomatic_time.h"
+#include "event_history.h"
+#include "film.h"
+#include "player_video.h"
+
+
+class Writer;
+
+
+class VideoEncoder
+{
+public:
+ VideoEncoder(std::shared_ptr<const Film> film, Writer& writer);
+ virtual ~VideoEncoder() {}
+
+ VideoEncoder(VideoEncoder const&) = delete;
+ VideoEncoder& operator=(VideoEncoder const&) = delete;
+
+ /** Called to indicate that a processing run is about to begin */
+ virtual void begin() {}
+
+ /** Called to pass a bit of video to be encoded as the next DCP frame */
+ virtual void encode(std::shared_ptr<PlayerVideo> pv, dcpomatic::DCPTime time);
+
+ virtual void pause() = 0;
+ virtual void resume() = 0;
+
+ /** Called when a processing run has finished */
+ virtual void end() = 0;
+
+ int video_frames_enqueued() const;
+ boost::optional<float> current_encoding_rate() const;
+
+protected:
+ /** Film that we are encoding */
+ std::shared_ptr<const Film> _film;
+ Writer& _writer;
+ EventHistory _history;
+ boost::optional<dcpomatic::DCPTime> _last_player_video_time;
+};
+
+
+#endif
+
verify_dcp_job.cc
video_content.cc
video_decoder.cc
+ video_encoder.cc
video_filter_graph.cc
video_filter_graph_set.cc
video_frame_type.cc
auto film = new_test_film2("frames_not_lost", content);
film->write_metadata();
auto job = make_dcp(film, TranscodeJob::ChangedBehaviour::IGNORE);
- auto& encoder = dynamic_pointer_cast<DCPFilmEncoder>(job->_encoder)->_j2k_encoder;
+ auto encoder = dynamic_cast<J2KEncoder*>(dynamic_pointer_cast<DCPFilmEncoder>(job->_encoder)->_encoder.get());
while (JobManager::instance()->work_to_do()) {
- encoder.remake_threads(rand() % 8, 0, {});
+ encoder->remake_threads(rand() % 8, 0, {});
dcpomatic_sleep_seconds(1);
}