Architecture: i386
Depends: libc6 (>= 2.15), libwxgtk2.8-0 (>= 2.8.12.1), libssh-4 (>= 0.5.2), libboost-filesystem1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libsndfile1 (>= 1.0.25), libmagick++4 (>= 8:6.6.9.7), libxml++2.6-2 (>= 2.34.1)
Description: Generator of Digital Cinema Packages (DCPs)
- DVD-o-matic generates Digital Cinema Packages (DCPs) from video and audio
+ DCP-o-matic generates Digital Cinema Packages (DCPs) from video and audio
files (such as those from DVDs or Blu-Rays) for presentation on DCI-compliant
digital projectors.
+
+ Package: dvdomatic-dbg
+ Architecture: i386
+ Section: debug
+ Priority: extra
+ Depends: ${dvdomatic:Depends}, ${misc:Depends}
+ Description: debugging symbols for dvdomatic
+ This package contains the debugging symbols for dvdomatic.
+
Architecture: amd64
Depends: libc6 (>= 2.15), libwxgtk2.8-0 (>= 2.8.12.1), libssh-4 (>= 0.5.2), libboost-filesystem1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libsndfile1 (>= 1.0.25), libmagick++4 (>= 8:6.6.9.7), libxml++2.6-2 (>= 2.34.1)
Description: Generator of Digital Cinema Packages (DCPs)
- DVD-o-matic generates Digital Cinema Packages (DCPs) from video and audio
+ DCP-o-matic generates Digital Cinema Packages (DCPs) from video and audio
files (such as those from DVDs or Blu-Rays) for presentation on DCI-compliant
digital projectors.
+
+ Package: dvdomatic-dbg
+ Architecture: amd64
+ Section: debug
+ Priority: extra
+ Depends: ${dvdomatic:Depends}, ${misc:Depends}
+ Description: debugging symbols for dvdomatic
+ This package contains the debugging symbols for dvdomatic.
+
Architecture: i386
Depends: libc6 (>= 2.15), libwxgtk2.8-0 (>= 2.8.12.1), libssh-4 (>= 0.5.2), libboost-filesystem1.49.0 (>= 1.49.0), libboost-thread1.49.0 (>= 1.49.0), libsndfile1 (>= 1.0.25), libmagick++5 (>= 8:6.7.7.10), libxml++2.6-2 (>= 2.34.2)
Description: Generator of Digital Cinema Packages (DCPs)
- DVD-o-matic generates Digital Cinema Packages (DCPs) from video and audio
+ DCP-o-matic generates Digital Cinema Packages (DCPs) from video and audio
files (such as those from DVDs or Blu-Rays) for presentation on DCI-compliant
digital projectors.
+
+ Package: dvdomatic-dbg
+ Architecture: i386
+ Section: debug
+ Priority: extra
+ Depends: ${dvdomatic:Depends}, ${misc:Depends}
+ Description: debugging symbols for dvdomatic
+ This package contains the debugging symbols for dvdomatic.
Architecture: amd64
Depends: libc6 (>= 2.15), libwxgtk2.8-0 (>= 2.8.12.1), libssh-4 (>= 0.5.2), libboost-filesystem1.49.0 (>= 1.49.0), libboost-thread1.49.0 (>= 1.49.0), libsndfile1 (>= 1.0.25), libmagick++5 (>= 8:6.7.7.10), libxml++2.6-2 (>= 2.34.2)
Description: Generator of Digital Cinema Packages (DCPs)
- DVD-o-matic generates Digital Cinema Packages (DCPs) from video and audio
+ DCP-o-matic generates Digital Cinema Packages (DCPs) from video and audio
files (such as those from DVDs or Blu-Rays) for presentation on DCI-compliant
digital projectors.
+
+ Package: dvdomatic-dbg
+ Architecture: amd64
+ Section: debug
+ Priority: extra
+ Depends: ${dvdomatic:Depends}, ${misc:Depends}
+ Description: debugging symbols for dvdomatic
+ This package contains the debugging symbols for dvdomatic.
+
./waf --nocache build
override_dh_auto_install:
- ./waf --nocache install --destdir=debian/dvdomatic
+ ./waf --nocache install --destdir=debian/dcpomatic
+ .PHONY: override_dh_strip
+ override_dh_strip:
+ dh_strip --dbg-package=dvdomatic-dbg
* @param e Encoder to use.
*/
-ABTranscoder::ABTranscoder (
- shared_ptr<Film> a, shared_ptr<Film> b, DecodeOptions o, Job* j, shared_ptr<Encoder> e)
+ABTranscoder::ABTranscoder (shared_ptr<Film> a, shared_ptr<Film> b, shared_ptr<Job> j)
: _film_a (a)
, _film_b (b)
+ , _player_a (_film_a->player ())
+ , _player_b (_film_b->player ())
, _job (j)
- , _encoder (e)
+ , _encoder (new Encoder (_film_a))
, _combiner (new Combiner (a->log()))
{
- _da = decoder_factory (_film_a, o);
- _db = decoder_factory (_film_b, o);
-
- shared_ptr<AudioStream> st = _film_a->audio_stream();
- if (st) {
- _matcher.reset (new Matcher (_film_a->log(), st->sample_rate(), _film_a->source_frame_rate()));
- }
- _delay_line.reset (new DelayLine (_film_a->log(), _film_a->audio_delay() / 1000.0f));
+ _matcher.reset (new Matcher (_film_a->log(), _film_a->audio_frame_rate(), _film_a->video_frame_rate()));
+ _delay_line.reset (new DelayLine (_film_a->log(), _film_a->audio_delay() * _film_a->audio_frame_rate() / 1000));
_gain.reset (new Gain (_film_a->log(), _film_a->audio_gain()));
- int const sr = st ? st->sample_rate() : 0;
+ _player_a->Video.connect (bind (&Combiner::process_video, _combiner, _1, _2, _3, _4));
+ _player_b->Video.connect (bind (&Combiner::process_video_b, _combiner, _1, _2, _3, _4));
+
+ int const trim_start = _film_a->trim_type() == Film::ENCODE ? _film_a->trim_start() : 0;
+ int const trim_end = _film_a->trim_type() == Film::ENCODE ? _film_a->trim_end() : 0;
+ _trimmer.reset (new Trimmer (
- _film_a->log(), trim_start, trim_end, _film_a->length().get(),
- sr, _film_a->source_frame_rate(), _film_a->dcp_frame_rate()
++ _film_a->log(), trim_start, trim_end, _film_a->content_length(),
++ _film_a->audio_frame_rate(), _film_a->video_frame_rate(), _film_a->dcp_frame_rate()
+ ));
+
- /* Set up the decoder to use the film's set streams */
- _da.video->set_subtitle_stream (_film_a->subtitle_stream ());
- _db.video->set_subtitle_stream (_film_a->subtitle_stream ());
- if (_film_a->audio_stream ()) {
- _da.audio->set_audio_stream (_film_a->audio_stream ());
- }
-
- _da.video->Video.connect (bind (&Combiner::process_video, _combiner, _1, _2, _3, _4));
- _db.video->Video.connect (bind (&Combiner::process_video_b, _combiner, _1, _2, _3, _4));
+
_combiner->connect_video (_delay_line);
- if (_matcher) {
- _delay_line->connect_video (_matcher);
- _matcher->connect_video (_trimmer);
- } else {
- _delay_line->connect_video (_trimmer);
- }
+ _delay_line->connect_video (_matcher);
- _matcher->connect_video (_encoder);
++ _matcher->connect_video (_trimmer);
+ _trimmer->connect_video (_encoder);
- _da.audio->connect_audio (_delay_line);
- if (_matcher) {
- _delay_line->connect_audio (_matcher);
- _matcher->connect_audio (_gain);
- } else {
- _delay_line->connect_audio (_gain);
- }
+ _player_a->connect_audio (_delay_line);
+ _delay_line->connect_audio (_matcher);
+ _matcher->connect_audio (_gain);
- _gain->connect_audio (_encoder);
+ _gain->connect_audio (_trimmer);
+ _trimmer->connect_audio (_encoder);
}
void
break;
}
}
-
- if (_delay_line) {
- _delay_line->process_end ();
- }
- if (_matcher) {
- _matcher->process_end ();
- }
- if (_gain) {
- _gain->process_end ();
- }
+
+ _delay_line->process_end ();
- if (_matcher) {
- _matcher->process_end ();
- }
++ _matcher->process_end ();
+ _gain->process_end ();
++ _trimmer->process_end ();
_encoder->process_end ();
}
class DelayLine;
class Gain;
class Combiner;
+class Player;
+ class Trimmer;
/** @class ABTranscoder
* @brief A transcoder which uses one Film for the left half of the screen, and a different one
#include "audio_sink.h"
using boost::shared_ptr;
+using boost::weak_ptr;
using boost::bind;
- process_audio_proxy (weak_ptr<AudioSink> sink, shared_ptr<AudioBuffers> audio)
+static void
++process_audio_proxy (weak_ptr<AudioSink> sink, shared_ptr<const AudioBuffers> audio)
+{
+ shared_ptr<AudioSink> p = sink.lock ();
+ if (p) {
+ p->process_audio (audio);
+ }
+}
+
void
AudioSource::connect_audio (shared_ptr<AudioSink> s)
{
}
void
- Encoder::process_video (shared_ptr<Image> image, bool same, shared_ptr<Subtitle> sub)
-Encoder::process_video (shared_ptr<const Image> image, bool same, boost::shared_ptr<Subtitle> sub)
++Encoder::process_video (shared_ptr<const Image> image, bool same, shared_ptr<Subtitle> sub)
{
- FrameRateConversion frc (_film->source_frame_rate(), _film->dcp_frame_rate());
+ FrameRateConversion frc (_film->video_frame_rate(), _film->dcp_frame_rate());
if (frc.skip && (_video_frames_in % 2)) {
++_video_frames_in;
}
void
- Matcher::process_video (shared_ptr<Image> image, bool same, boost::shared_ptr<Subtitle> sub, double t)
-Matcher::process_video (boost::shared_ptr<const Image> image, bool same, boost::shared_ptr<Subtitle> sub, double t)
++Matcher::process_video (shared_ptr<const Image> image, bool same, boost::shared_ptr<Subtitle> sub, double t)
{
_pixel_format = image->pixel_format ();
_size = image->size ();
}
void
- Matcher::process_audio (shared_ptr<AudioBuffers> b, double t)
-Matcher::process_audio (boost::shared_ptr<const AudioBuffers> b, double t)
++Matcher::process_audio (shared_ptr<const AudioBuffers> b, double t)
{
_channels = b->channels ();
--- /dev/null
- Player::process_video (shared_ptr<Image> i, bool same, shared_ptr<Subtitle> s, double t)
+/*
+ Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "player.h"
+#include "film.h"
+#include "ffmpeg_decoder.h"
+#include "ffmpeg_content.h"
+#include "imagemagick_decoder.h"
+#include "imagemagick_content.h"
+#include "sndfile_decoder.h"
+#include "sndfile_content.h"
+#include "playlist.h"
+#include "job.h"
+
+using std::list;
+using std::cout;
+using std::vector;
+using boost::shared_ptr;
+using boost::weak_ptr;
+using boost::dynamic_pointer_cast;
+
+Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
+ : _film (f)
+ , _playlist (p)
+ , _video (true)
+ , _audio (true)
+ , _subtitles (true)
+ , _have_valid_decoders (false)
+{
+ _playlist->Changed.connect (bind (&Player::playlist_changed, this));
+ _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2));
+}
+
+void
+Player::disable_video ()
+{
+ _video = false;
+}
+
+void
+Player::disable_audio ()
+{
+ _audio = false;
+}
+
+void
+Player::disable_subtitles ()
+{
+ _subtitles = false;
+}
+
+bool
+Player::pass ()
+{
+ if (!_have_valid_decoders) {
+ setup_decoders ();
+ _have_valid_decoders = true;
+ }
+
+ bool done = true;
+
+ if (_video && _video_decoder < _video_decoders.size ()) {
+
+ /* Run video decoder; this may also produce audio */
+
+ if (_video_decoders[_video_decoder]->pass ()) {
+ _video_decoder++;
+ }
+
+ if (_video_decoder < _video_decoders.size ()) {
+ done = false;
+ }
+
+ }
+
+ if (!_video && _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG && _sequential_audio_decoder < _audio_decoders.size ()) {
+
+ /* We're not producing video, so we may need to run FFmpeg content to get the audio */
+
+ if (_audio_decoders[_sequential_audio_decoder]->pass ()) {
+ _sequential_audio_decoder++;
+ }
+
+ if (_sequential_audio_decoder < _audio_decoders.size ()) {
+ done = false;
+ }
+
+ }
+
+ if (_audio && _playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
+
+ /* We're getting audio from SndfileContent */
+
+ for (vector<shared_ptr<AudioDecoder> >::iterator i = _audio_decoders.begin(); i != _audio_decoders.end(); ++i) {
+ if (!(*i)->pass ()) {
+ done = false;
+ }
+ }
+
+ Audio (_audio_buffers, _audio_time.get());
+ _audio_buffers.reset ();
+ _audio_time = boost::none;
+ }
+
+ return done;
+}
+
+void
+Player::set_progress (shared_ptr<Job> job)
+{
+ /* Assume progress can be divined from how far through the video we are */
+
+ if (_video_decoder >= _video_decoders.size() || !_playlist->video_length()) {
+ return;
+ }
+
+ job->set_progress ((_video_start[_video_decoder] + _video_decoders[_video_decoder]->video_frame()) / _playlist->video_length ());
+}
+
+void
- Player::process_audio (weak_ptr<const AudioContent> c, shared_ptr<AudioBuffers> b, double t)
++Player::process_video (shared_ptr<const Image> i, bool same, shared_ptr<Subtitle> s, double t)
+{
+ Video (i, same, s, _video_start[_video_decoder] + t);
+}
+
+void
++Player::process_audio (weak_ptr<const AudioContent> c, shared_ptr<const AudioBuffers> b, double t)
+{
+ AudioMapping mapping = _film->audio_mapping ();
+ if (!_audio_buffers) {
+ _audio_buffers.reset (new AudioBuffers (mapping.dcp_channels(), b->frames ()));
+ _audio_buffers->make_silent ();
+ _audio_time = t;
+ if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
+ _audio_time = _audio_time.get() + _audio_start[_sequential_audio_decoder];
+ }
+ }
+
+ for (int i = 0; i < b->channels(); ++i) {
+ list<libdcp::Channel> dcp = mapping.content_to_dcp (AudioMapping::Channel (c, i));
+ for (list<libdcp::Channel>::iterator j = dcp.begin(); j != dcp.end(); ++j) {
+ _audio_buffers->accumulate (b, i, static_cast<int> (*j));
+ }
+ }
+
+ if (_playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
+ /* We can just emit this audio now as it will all be here */
+ Audio (_audio_buffers, t);
+ _audio_buffers.reset ();
+ _audio_time = boost::none;
+ }
+}
+
+/** @return true on error */
+bool
+Player::seek (double t)
+{
+ if (!_have_valid_decoders) {
+ setup_decoders ();
+ _have_valid_decoders = true;
+ }
+
++ if (_video_decoders.empty ()) {
++ return true;
++ }
++
+ /* Find the decoder that contains this position */
+ _video_decoder = 0;
+ while (1) {
+ ++_video_decoder;
+ if (_video_decoder >= _video_decoders.size () || t < _video_start[_video_decoder]) {
+ --_video_decoder;
+ t -= _video_start[_video_decoder];
+ break;
+ }
+ }
+
+ if (_video_decoder < _video_decoders.size()) {
+ _video_decoders[_video_decoder]->seek (t);
+ } else {
+ return true;
+ }
+
+ /* XXX: don't seek audio because we don't need to... */
+
+ return false;
+}
+
+
+void
+Player::seek_back ()
+{
+ /* XXX */
+}
+
+void
+Player::seek_forward ()
+{
+ /* XXX */
+}
+
+
+void
+Player::setup_decoders ()
+{
+ _video_decoders.clear ();
+ _video_decoder = 0;
+ _audio_decoders.clear ();
+ _sequential_audio_decoder = 0;
+
+ _video_start.clear();
+ _audio_start.clear();
+
+ double video_so_far = 0;
+ double audio_so_far = 0;
+
+ list<shared_ptr<const VideoContent> > vc = _playlist->video ();
+ for (list<shared_ptr<const VideoContent> >::iterator i = vc.begin(); i != vc.end(); ++i) {
+
+ shared_ptr<const VideoContent> video_content;
+ shared_ptr<const AudioContent> audio_content;
+ shared_ptr<VideoDecoder> video_decoder;
+ shared_ptr<AudioDecoder> audio_decoder;
+
+ /* XXX: into content? */
+
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
+ if (fc) {
+ shared_ptr<FFmpegDecoder> fd (
+ new FFmpegDecoder (
+ _film, fc, _video,
+ _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG,
+ _subtitles
+ )
+ );
+
+ video_content = fc;
+ audio_content = fc;
+ video_decoder = fd;
+ audio_decoder = fd;
+ }
+
+ shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i);
+ if (ic) {
+ video_content = ic;
+ video_decoder.reset (new ImageMagickDecoder (_film, ic));
+ }
+
+ video_decoder->connect_video (shared_from_this ());
+ _video_decoders.push_back (video_decoder);
+ _video_start.push_back (video_so_far);
+ video_so_far += video_content->video_length() / video_content->video_frame_rate();
+
+ if (audio_decoder && _playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
+ audio_decoder->Audio.connect (bind (&Player::process_audio, this, audio_content, _1, _2));
+ _audio_decoders.push_back (audio_decoder);
+ _audio_start.push_back (audio_so_far);
+ audio_so_far += double(audio_content->audio_length()) / audio_content->audio_frame_rate();
+ }
+ }
+
+ _video_decoder = 0;
+ _sequential_audio_decoder = 0;
+
+ if (_playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
+
+ list<shared_ptr<const AudioContent> > ac = _playlist->audio ();
+ for (list<shared_ptr<const AudioContent> >::iterator i = ac.begin(); i != ac.end(); ++i) {
+
+ shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
+ assert (sc);
+
+ shared_ptr<AudioDecoder> d (new SndfileDecoder (_film, sc));
+ d->Audio.connect (bind (&Player::process_audio, this, sc, _1, _2));
+ _audio_decoders.push_back (d);
+ _audio_start.push_back (audio_so_far);
+ }
+ }
+}
+
+double
+Player::last_video_time () const
+{
+ return _video_start[_video_decoder] + _video_decoders[_video_decoder]->last_content_time ();
+}
+
+void
+Player::content_changed (weak_ptr<Content> w, int p)
+{
+ shared_ptr<Content> c = w.lock ();
+ if (!c) {
+ return;
+ }
+
+ if (p == VideoContentProperty::VIDEO_LENGTH) {
+ if (dynamic_pointer_cast<FFmpegContent> (c)) {
+ /* FFmpeg content length changes are serious; we need new decoders */
+ _have_valid_decoders = false;
+ }
+ }
+}
+
+void
+Player::playlist_changed ()
+{
+ _have_valid_decoders = false;
+}
--- /dev/null
- void process_video (boost::shared_ptr<Image> i, bool same, boost::shared_ptr<Subtitle> s, double);
- void process_audio (boost::weak_ptr<const AudioContent>, boost::shared_ptr<AudioBuffers>, double);
+/*
+ Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef DCPOMATIC_PLAYER_H
+#define DCPOMATIC_PLAYER_H
+
+#include <list>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include "video_source.h"
+#include "audio_source.h"
+#include "video_sink.h"
+#include "audio_sink.h"
+
+class VideoDecoder;
+class AudioDecoder;
+class Job;
+class Film;
+class Playlist;
+class AudioContent;
+
+/** @class Player
+ * @brief A class which can `play' a Playlist; emitting its audio and video.
+ */
+
+class Player : public TimedVideoSource, public TimedAudioSource, public TimedVideoSink, public boost::enable_shared_from_this<Player>
+{
+public:
+ Player (boost::shared_ptr<const Film>, boost::shared_ptr<const Playlist>);
+
+ void disable_video ();
+ void disable_audio ();
+ void disable_subtitles ();
+
+ bool pass ();
+ void set_progress (boost::shared_ptr<Job>);
+ bool seek (double);
+ void seek_back ();
+ void seek_forward ();
+
+ double last_video_time () const;
+
+private:
++ void process_video (boost::shared_ptr<const Image> i, bool same, boost::shared_ptr<Subtitle> s, double);
++ void process_audio (boost::weak_ptr<const AudioContent>, boost::shared_ptr<const AudioBuffers>, double);
+ void setup_decoders ();
+ void playlist_changed ();
+ void content_changed (boost::weak_ptr<Content>, int);
+
+ boost::shared_ptr<const Film> _film;
+ boost::shared_ptr<const Playlist> _playlist;
+
+ bool _video;
+ bool _audio;
+ bool _subtitles;
+
+ /** Our decoders are ready to go; if this is false the decoders must be (re-)created before they are used */
+ bool _have_valid_decoders;
+ /** Video decoders in order of presentation */
+ std::vector<boost::shared_ptr<VideoDecoder> > _video_decoders;
+ /** Start positions of each video decoder in seconds*/
+ std::vector<double> _video_start;
+ /** Index of current video decoder */
+ size_t _video_decoder;
+ /** Audio decoders in order of presentation (if they are from FFmpeg) */
+ std::vector<boost::shared_ptr<AudioDecoder> > _audio_decoders;
+ /** Start positions of each audio decoder (if they are from FFmpeg) in seconds */
+ std::vector<double> _audio_start;
+ /** Current audio decoder index if we are running them sequentially; otherwise undefined */
+ size_t _sequential_audio_decoder;
+
+ boost::shared_ptr<AudioBuffers> _audio_buffers;
+ boost::optional<double> _audio_time;
+};
+
+#endif
#
msgid ""
msgstr ""
-"Project-Id-Version: LIBDVDOMATIC\n"
+"Project-Id-Version: LIBDCPOMATIC\n"
"Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2013-04-09 11:14+0100\n"
+ "POT-Creation-Date: 2013-04-22 15:06+0100\n"
"PO-Revision-Date: 2013-04-02 19:10-0500\n"
"Last-Translator: Manuel AC <manuel.acevedo@civantos.>\n"
"Language-Team: Manuel AC <manuel.acevedo@civantos.com>\n"
msgid "Horizontal deblocking filter A"
msgstr "Horizontal deblocking filter A"
- #: src/lib/job.cc:92 src/lib/job.cc:101
+ #: src/lib/job.cc:96 src/lib/job.cc:105
msgid ""
"It is not known what caused this error. The best idea is to report the "
-"problem to the DVD-o-matic mailing list (dvdomatic@carlh.net)"
+"problem to the DCP-o-matic mailing list (dcpomatic@carlh.net)"
msgstr ""
"Error desconocido. La mejor idea es informar del problema a la lista de "
-"correo de DVD-O-matic (dvdomatic@carlh.net)"
+"correo de DCP-o-matic (dcpomatic@carlh.net)"
#: src/lib/filter.cc:82
msgid "Kernel deinterlacer"
#
msgid ""
msgstr ""
-"Project-Id-Version: DVD-o-matic FRENCH\n"
+"Project-Id-Version: DCP-o-matic FRENCH\n"
"Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2013-04-09 11:14+0100\n"
+ "POT-Creation-Date: 2013-04-22 15:06+0100\n"
"PO-Revision-Date: 2013-03-20 00:39+0100\n"
"Last-Translator: FreeDCP.net <freedcp.net@gmail.com>\n"
"Language-Team: \n"
msgid "Horizontal deblocking filter A"
msgstr "Filtre dé-bloc horizontal"
- #: src/lib/job.cc:92 src/lib/job.cc:101
+ #: src/lib/job.cc:96 src/lib/job.cc:105
msgid ""
"It is not known what caused this error. The best idea is to report the "
-"problem to the DVD-o-matic mailing list (dvdomatic@carlh.net)"
+"problem to the DCP-o-matic mailing list (dcpomatic@carlh.net)"
msgstr ""
-"Erreur indéterminée. Merci de rapporter le problème à la liste DVD-o-matic "
-"(dvdomatic@carlh.net)"
+"Erreur indéterminée. Merci de rapporter le problème à la liste DCP-o-matic "
+"(dcpomatic@carlh.net)"
#: src/lib/filter.cc:82
msgid "Kernel deinterlacer"
msgid "Horizontal deblocking filter A"
msgstr "Filtro A sblocco orizzontale"
- #: src/lib/job.cc:92 src/lib/job.cc:101
+ #: src/lib/job.cc:96 src/lib/job.cc:105
msgid ""
"It is not known what caused this error. The best idea is to report the "
-"problem to the DVD-o-matic mailing list (dvdomatic@carlh.net)"
+"problem to the DCP-o-matic mailing list (dcpomatic@carlh.net)"
msgstr ""
"Non sappiamo cosa ha causato questo errore. La cosa migliore è inviare un "
-"report del problema alla mailing list di DVD-o-matic (dvdomatic@carlh.net)"
+"report del problema alla mailing list di DCP-o-matic (dcpomatic@carlh.net)"
#: src/lib/filter.cc:82
msgid "Kernel deinterlacer"
#
msgid ""
msgstr ""
-"Project-Id-Version: DVD-o-matic\n"
+"Project-Id-Version: DCP-o-matic\n"
"Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2013-04-09 11:14+0100\n"
+ "POT-Creation-Date: 2013-04-22 15:06+0100\n"
"PO-Revision-Date: 2013-04-10 15:35+0100\n"
"Last-Translator: Adam Klotblixt <adam.klotblixt@gmail.com>\n"
"Language-Team: \n"
msgid "Horizontal deblocking filter A"
msgstr "Filter för horisontal kantighetsutjämning A"
- #: src/lib/job.cc:92 src/lib/job.cc:101
+ #: src/lib/job.cc:96 src/lib/job.cc:105
msgid ""
"It is not known what caused this error. The best idea is to report the "
-"problem to the DVD-o-matic mailing list (dvdomatic@carlh.net)"
+"problem to the DCP-o-matic mailing list (dcpomatic@carlh.net)"
msgstr ""
"Det är inte känt vad som orsakade detta fel. Bästa sättet att rapportera "
-"problemet är till DVD-o-matics mejl-lista (dvdomatic@carlh.net)"
+"problemet är till DCP-o-matics mejl-lista (dcpomatic@carlh.net)"
#: src/lib/filter.cc:82
msgid "Kernel deinterlacer"
#include "gain.h"
#include "video_decoder.h"
#include "audio_decoder.h"
+#include "player.h"
+ #include "trimmer.h"
using std::string;
using boost::shared_ptr;
* @param j Job that we are running under, or 0.
* @param e Encoder to use.
*/
-Transcoder::Transcoder (shared_ptr<Film> f, DecodeOptions o, Job* j, shared_ptr<Encoder> e)
+Transcoder::Transcoder (shared_ptr<Film> f, shared_ptr<Job> j)
: _job (j)
- , _encoder (e)
- , _decoders (decoder_factory (f, o))
+ , _player (f->player ())
+ , _encoder (new Encoder (f))
{
- assert (_encoder);
-
- shared_ptr<AudioStream> st = f->audio_stream();
- if (st) {
- _matcher.reset (new Matcher (f->log(), st->sample_rate(), f->source_frame_rate()));
- }
- _delay_line.reset (new DelayLine (f->log(), f->audio_delay() / 1000.0f));
+ _matcher.reset (new Matcher (f->log(), f->audio_frame_rate(), f->video_frame_rate()));
+ _delay_line.reset (new DelayLine (f->log(), f->audio_delay() * f->audio_frame_rate() / 1000));
_gain.reset (new Gain (f->log(), f->audio_gain()));
- int const sr = st ? st->sample_rate() : 0;
+ int const trim_start = f->trim_type() == Film::ENCODE ? f->trim_start() : 0;
+ int const trim_end = f->trim_type() == Film::ENCODE ? f->trim_end() : 0;
+ _trimmer.reset (new Trimmer (
- f->log(), trim_start, trim_end, f->length().get_value_or(0),
- sr, f->source_frame_rate(), f->dcp_frame_rate()
++ f->log(), trim_start, trim_end, f->content_length(),
++ f->audio_frame_rate(), f->video_frame_rate(), f->dcp_frame_rate()
+ ));
-
- /* Set up the decoder to use the film's set streams */
- _decoders.video->set_subtitle_stream (f->subtitle_stream ());
- if (f->audio_stream ()) {
- _decoders.audio->set_audio_stream (f->audio_stream ());
++
+ if (!f->with_subtitles ()) {
+ _player->disable_subtitles ();
}
- _decoders.video->connect_video (_delay_line);
- if (_matcher) {
- _delay_line->connect_video (_matcher);
- _matcher->connect_video (_trimmer);
- } else {
- _delay_line->connect_video (_trimmer);
- }
+ _player->connect_video (_delay_line);
+ _delay_line->connect_video (_matcher);
- _matcher->connect_video (_encoder);
++ _matcher->connect_video (_trimmer);
+ _trimmer->connect_video (_encoder);
- _decoders.audio->connect_audio (_delay_line);
- if (_matcher) {
- _delay_line->connect_audio (_matcher);
- _matcher->connect_audio (_gain);
- } else {
- _delay_line->connect_audio (_gain);
- }
+ _player->connect_audio (_delay_line);
+ _delay_line->connect_audio (_matcher);
+ _matcher->connect_audio (_gain);
- _gain->connect_audio (_encoder);
+ _gain->connect_audio (_trimmer);
+ _trimmer->connect_audio (_encoder);
}
-/** Run the decoder, passing its output to the encoder, until the decoder
- * has no more data to present.
- */
void
Transcoder::go ()
{
_encoder->process_begin ();
-
- bool done[2] = { false, false };
-
while (1) {
- if (!done[0]) {
- done[0] = _decoders.video->pass ();
- if (_job) {
- _decoders.video->set_progress (_job);
- }
- }
-
- if (!done[1] && _decoders.audio && dynamic_pointer_cast<Decoder> (_decoders.audio) != dynamic_pointer_cast<Decoder> (_decoders.video)) {
- done[1] = _decoders.audio->pass ();
- } else {
- done[1] = true;
- }
-
- if (done[0] && done[1]) {
+ if (_player->pass ()) {
break;
}
+ _player->set_progress (_job);
}
-
+
_delay_line->process_end ();
- _matcher->process_end ();
+ if (_matcher) {
+ _matcher->process_end ();
+ }
_gain->process_end ();
_encoder->process_end ();
}
class Matcher;
class VideoFilter;
class Gain;
-class VideoDecoder;
-class AudioDecoder;
class DelayLine;
+class Player;
+ class Trimmer;
/** @class Transcoder
- * @brief A class which takes a Film and some Options, then uses those to transcode the film.
*
* A decoder is selected according to the content type, and the encoder can be specified
* as a parameter to the constructor.
#include "i18n.h"
-using std::cout;
using std::string;
using std::stringstream;
-using std::list;
+using std::setfill;
using std::ostream;
+using std::endl;
using std::vector;
+using std::hex;
+using std::setw;
using std::ifstream;
-using std::istream;
+using std::ios;
using std::min;
using std::max;
+using std::list;
using std::multimap;
+using std::istream;
+using std::numeric_limits;
using std::pair;
using boost::shared_ptr;
+using boost::thread;
using boost::lexical_cast;
+ using boost::optional;
using libdcp::Size;
- thread::id ui_thread;
+ boost::thread::id ui_thread;
/** Convert some number of seconds to a string representation
* in hours, minutes and seconds.
* @return MD5 digest of file's contents.
*/
string
-md5_digest (string file)
+md5_digest (boost::filesystem::path file)
{
- ifstream f (file.string().c_str(), ios::binary);
- ifstream f (file.c_str(), std::ios::binary);
++ ifstream f (file.string().c_str(), std::ios::binary);
if (!f.good ()) {
- throw OpenFileError (file);
+ throw OpenFileError (file.string());
}
- f.seekg (0, ios::end);
+ f.seekg (0, std::ios::end);
int bytes = f.tellg ();
- f.seekg (0, ios::beg);
+ f.seekg (0, std::ios::beg);
int const buffer_size = 64 * 1024;
char buffer[buffer_size];
}
}
- AudioBuffers::accumulate (shared_ptr<AudioBuffers> from, int from_channel, int to_channel)
+/** Add data from from `from', `from_channel' to our channel `to_channel' */
+void
++AudioBuffers::accumulate (shared_ptr<const AudioBuffers> from, int from_channel, int to_channel)
+{
+ int const N = frames ();
+ assert (from->frames() == N);
+
+ float* s = from->data (from_channel);
+ float* d = _data[to_channel];
+
+ for (int i = 0; i < N; ++i) {
+ *d++ += *s++;
+ }
+}
+
/** Trip an assert if the caller is not in the UI thread */
void
ensure_ui_thread ()
void copy_from (AudioBuffers* from, int frames_to_copy, int read_offset, int write_offset);
void move (int from, int to, int frames);
- void accumulate (boost::shared_ptr<AudioBuffers>, int, int);
++ void accumulate (boost::shared_ptr<const AudioBuffers>, int, int);
private:
/** Number of channels */
#include "video_sink.h"
using boost::shared_ptr;
+using boost::weak_ptr;
using boost::bind;
- process_video_proxy (weak_ptr<VideoSink> sink, shared_ptr<Image> i, bool same, shared_ptr<Subtitle> s)
+static void
++process_video_proxy (weak_ptr<VideoSink> sink, shared_ptr<const Image> i, bool same, shared_ptr<Subtitle> s)
+{
+ shared_ptr<VideoSink> p = sink.lock ();
+ if (p) {
+ p->process_video (i, same, s);
+ }
+}
+
void
VideoSource::connect_video (shared_ptr<VideoSink> s)
{
--- /dev/null
- int log_level = 1;
+/*
+ Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <iostream>
+#include <iomanip>
+#include <getopt.h>
+#include <libdcp/test_mode.h>
+#include <libdcp/version.h>
+#include "format.h"
+#include "film.h"
+#include "filter.h"
+#include "transcode_job.h"
+#include "job_manager.h"
+#include "ab_transcode_job.h"
+#include "util.h"
+#include "scaler.h"
+#include "version.h"
+#include "cross.h"
+#include "config.h"
+#include "log.h"
+
+using std::string;
+using std::cerr;
+using std::cout;
+using std::vector;
+using std::pair;
+using std::list;
+using boost::shared_ptr;
+
+static void
+help (string n)
+{
+ cerr << "Syntax: " << n << " [OPTION] <FILM>\n"
+ << " -v, --version show DCP-o-matic version\n"
+ << " -h, --help show this help\n"
+ << " -d, --deps list DCP-o-matic dependency details and quit\n"
+ << " -t, --test run in test mode (repeatable UUID generation, timestamps etc.)\n"
+ << " -n, --no-progress do not print progress to stdout\n"
+ << " -r, --no-remote do not use any remote servers\n"
+ << "\n"
+ << "<FILM> is the film directory.\n";
+}
+
+int
+main (int argc, char* argv[])
+{
+ string film_dir;
+ bool test_mode = false;
+ bool progress = true;
+ bool no_remote = false;
++ int log_level = 0;
+
+ int option_index = 0;
+ while (1) {
+ static struct option long_options[] = {
+ { "version", no_argument, 0, 'v'},
+ { "help", no_argument, 0, 'h'},
+ { "deps", no_argument, 0, 'd'},
+ { "test", no_argument, 0, 't'},
+ { "no-progress", no_argument, 0, 'n'},
+ { "no-remote", no_argument, 0, 'r'},
+ { "log-level", required_argument, 0, 'l' },
+ { 0, 0, 0, 0 }
+ };
+
+ int c = getopt_long (argc, argv, "vhdtnrl:", long_options, &option_index);
+
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'v':
+ cout << "dcpomatic version " << dcpomatic_version << " " << dcpomatic_git_commit << "\n";
+ exit (EXIT_SUCCESS);
+ case 'h':
+ help (argv[0]);
+ exit (EXIT_SUCCESS);
+ case 'd':
+ cout << dependency_version_summary () << "\n";
+ exit (EXIT_SUCCESS);
+ case 't':
+ test_mode = true;
+ break;
+ case 'n':
+ progress = false;
+ break;
+ case 'r':
+ no_remote = true;
+ break;
+ case 'l':
+ log_level = atoi (optarg);
+ break;
+ }
+ }
+
+ if (optind >= argc) {
+ help (argv[0]);
+ exit (EXIT_FAILURE);
+ }
+
+ film_dir = argv[optind];
+
+ dcpomatic_setup ();
+
+ if (no_remote) {
+ Config::instance()->set_servers (vector<ServerDescription*> ());
+ }
+
+ cout << "DCP-o-matic " << dcpomatic_version << " git " << dcpomatic_git_commit;
+ char buf[256];
+ if (gethostname (buf, 256) == 0) {
+ cout << " on " << buf;
+ }
+ cout << "\n";
+
+ if (test_mode) {
+ libdcp::enable_test_mode ();
+ cout << dependency_version_summary() << "\n";
+ }
+
+ shared_ptr<Film> film;
+ try {
+ film.reset (new Film (film_dir, true));
+ } catch (std::exception& e) {
+ cerr << argv[0] << ": error reading film `" << film_dir << "' (" << e.what() << ")\n";
+ exit (EXIT_FAILURE);
+ }
+
+ film->log()->set_level ((Log::Level) log_level);
+
+ cout << "\nMaking ";
+ if (film->ab()) {
+ cout << "A/B ";
+ }
+ cout << "DCP for " << film->name() << "\n";
+ cout << "Test mode: " << (test_mode ? "yes" : "no") << "\n";
+// cout << "Content: " << film->content() << "\n";
+ pair<string, string> const f = Filter::ffmpeg_strings (film->filters ());
+ cout << "Filters: " << f.first << " " << f.second << "\n";
+
+ film->make_dcp ();
+
+ bool should_stop = false;
+ bool first = true;
+ bool error = false;
+ while (!should_stop) {
+
+ dcpomatic_sleep (5);
+
+ list<shared_ptr<Job> > jobs = JobManager::instance()->get ();
+
+ if (!first && progress) {
+ cout << "\033[" << jobs.size() << "A";
+ cout.flush ();
+ }
+
+ first = false;
+
+ int unfinished = 0;
+ int finished_in_error = 0;
+
+ for (list<shared_ptr<Job> >::iterator i = jobs.begin(); i != jobs.end(); ++i) {
+ if (progress) {
+ cout << (*i)->name() << ": ";
+
+ float const p = (*i)->overall_progress ();
+
+ if (p >= 0) {
+ cout << (*i)->status() << " \n";
+ } else {
+ cout << ": Running \n";
+ }
+ }
+
+ if (!(*i)->finished ()) {
+ ++unfinished;
+ }
+
+ if ((*i)->finished_in_error ()) {
+ ++finished_in_error;
+ error = true;
+ }
+
+ if (!progress && (*i)->finished_in_error ()) {
+ /* We won't see this error if we haven't been showing progress,
+ so show it now.
+ */
+ cout << (*i)->status() << "\n";
+ }
+ }
+
+ if (unfinished == 0 || finished_in_error != 0) {
+ should_stop = true;
+ }
+ }
+
+ return error ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+
#
msgid ""
msgstr ""
-"Project-Id-Version: DVDOMATIC\n"
+"Project-Id-Version: DCPOMATIC\n"
"Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2013-04-09 11:14+0100\n"
+ "POT-Creation-Date: 2013-04-22 15:06+0100\n"
"PO-Revision-Date: 2013-03-23 21:08-0500\n"
"Last-Translator: Manuel AC <manuel.acevedo@civantos.>\n"
"Language-Team: Manuel AC <manuel.acevedo@civantos.com>\n"
#
msgid ""
msgstr ""
-"Project-Id-Version: DVD-o-matic FRENCH\n"
+"Project-Id-Version: DCP-o-matic FRENCH\n"
"Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2013-04-09 11:14+0100\n"
+ "POT-Creation-Date: 2013-04-22 15:06+0100\n"
"PO-Revision-Date: 2013-03-13 22:33+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
#
msgid ""
msgstr ""
-"Project-Id-Version: DVD-o-matic\n"
+"Project-Id-Version: DCP-o-matic\n"
"Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2013-04-09 11:14+0100\n"
+ "POT-Creation-Date: 2013-04-22 15:06+0100\n"
"PO-Revision-Date: 2013-04-09 10:12+0100\n"
"Last-Translator: Adam Klotblixt <adam.klotblixt@gmail.com>\n"
"Language-Team: \n"
return;
}
- shared_ptr<Image> input = _raw_frame;
- boost::shared_ptr<const Image> input = _raw_frame;
++ shared_ptr<const Image> input = _raw_frame;
pair<string, string> const s = Filter::ffmpeg_strings (_film->filters());
if (!s.second.empty ()) {
wxToggleButton* _play_button;
wxTimer _timer;
- boost::shared_ptr<Image> _raw_frame;
- Decoders _decoders;
+ boost::shared_ptr<const Image> _raw_frame;
boost::shared_ptr<Subtitle> _raw_sub;
- boost::shared_ptr<Image> _display_frame;
+ boost::shared_ptr<const Image> _display_frame;
/* The x offset at which we display the actual film content; this corresponds
to the film's padding converted to our coordinates.
*/
#
msgid ""
msgstr ""
-"Project-Id-Version: libdvdomatic-wx\n"
+"Project-Id-Version: libdcpomatic-wx\n"
"Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2013-04-09 11:14+0100\n"
+ "POT-Creation-Date: 2013-04-22 15:06+0100\n"
"PO-Revision-Date: 2013-04-02 19:08-0500\n"
"Last-Translator: Manuel AC <manuel.acevedo@civantos.>\n"
"Language-Team: Manuel AC <manuel.acevedo@civantos.com>\n"
msgstr "%"
#: src/wx/config_dialog.cc:61
-msgid "(restart DVD-o-matic to see language changes)"
+msgid "(restart DCP-o-matic to see language changes)"
msgstr ""
- #: src/wx/film_editor.cc:1269
+ #: src/wx/film_editor.cc:1276
msgid "1 channel"
msgstr "1 canal"
#
msgid ""
msgstr ""
-"Project-Id-Version: DVD-o-matic FRENCH\n"
+"Project-Id-Version: DCP-o-matic FRENCH\n"
"Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2013-04-09 11:14+0100\n"
+ "POT-Creation-Date: 2013-04-22 15:06+0100\n"
"PO-Revision-Date: 2013-03-20 00:34+0100\n"
"Last-Translator: FreeDCP.net <freedcp.net@gmail.com>\n"
"Language-Team: \n"
msgstr "%"
#: src/wx/config_dialog.cc:61
-msgid "(restart DVD-o-matic to see language changes)"
+msgid "(restart DCP-o-matic to see language changes)"
msgstr ""
- #: src/wx/film_editor.cc:1269
+ #: src/wx/film_editor.cc:1276
msgid "1 channel"
msgstr "1 canal"
msgstr "%"
#: src/wx/config_dialog.cc:61
-msgid "(restart DVD-o-matic to see language changes)"
-msgstr "(riavviare DVD-o-matic per vedere i cambiamenti di lingua)"
+msgid "(restart DCP-o-matic to see language changes)"
+msgstr "(riavviare DCP-o-matic per vedere i cambiamenti di lingua)"
- #: src/wx/film_editor.cc:1269
+ #: src/wx/film_editor.cc:1276
msgid "1 channel"
msgstr "Canale 1"
#
msgid ""
msgstr ""
-"Project-Id-Version: DVD-o-matic\n"
+"Project-Id-Version: DCP-o-matic\n"
"Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2013-04-09 11:14+0100\n"
+ "POT-Creation-Date: 2013-04-22 15:06+0100\n"
"PO-Revision-Date: 2013-04-09 10:13+0100\n"
"Last-Translator: Adam Klotblixt <adam.klotblixt@gmail.com>\n"
"Language-Team: \n"
msgstr "%"
#: src/wx/config_dialog.cc:61
-msgid "(restart DVD-o-matic to see language changes)"
-msgstr "(starta om DVD-o-matic för att se språkändringar)"
+msgid "(restart DCP-o-matic to see language changes)"
+msgstr "(starta om DCP-o-matic för att se språkändringar)"
- #: src/wx/film_editor.cc:1269
+ #: src/wx/film_editor.cc:1276
msgid "1 channel"
msgstr "1 kanal"