summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-02-22 18:58:31 +0000
committerCarl Hetherington <cth@carlh.net>2013-02-22 18:58:31 +0000
commit62365221dd3cd80d6b771e9bf22b4f9365ee096a (patch)
tree6d75b967b7e250a93eb3b600ce89706b2018f069 /src
parentfa6c885de512cdde0590c2bbe9ea424030a12c6b (diff)
parent5943bde6f1a29c84b3f79710535a41bb98f6ce7d (diff)
Merge branch 'master' into i18n
Diffstat (limited to 'src')
-rw-r--r--src/lib/dcp_video_frame.cc22
-rw-r--r--src/lib/encoder.cc42
-rw-r--r--src/lib/encoder.h2
-rw-r--r--src/lib/ffmpeg_decoder.cc26
-rw-r--r--src/lib/ffmpeg_decoder.h2
-rw-r--r--src/lib/film.cc16
-rw-r--r--src/lib/film.h2
-rw-r--r--src/lib/image.cc19
-rw-r--r--src/lib/image.h1
-rw-r--r--src/lib/server.cc10
-rw-r--r--src/lib/subtitle.cc4
-rw-r--r--src/lib/util.cc128
-rw-r--r--src/lib/util.h22
-rw-r--r--src/lib/writer.cc4
-rw-r--r--src/tools/dvdomatic.cc36
-rw-r--r--src/tools/makedcp.cc2
-rw-r--r--src/tools/servomatictest.cc52
-rw-r--r--src/tools/wscript2
-rw-r--r--src/wx/film_viewer.cc12
-rw-r--r--src/wx/job_manager_view.cc6
-rw-r--r--src/wx/job_wrapper.cc4
-rw-r--r--src/wx/job_wrapper.h2
-rw-r--r--src/wx/wx_util.cc8
-rw-r--r--src/wx/wx_util.h1
24 files changed, 201 insertions, 224 deletions
diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc
index 4f3fda44a..9b96724b0 100644
--- a/src/lib/dcp_video_frame.cc
+++ b/src/lib/dcp_video_frame.cc
@@ -316,7 +316,7 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv)
shared_ptr<Socket> socket (new Socket);
- socket->connect (*endpoint_iterator, 30);
+ socket->connect (*endpoint_iterator);
stringstream s;
s << "encode please\n"
@@ -352,21 +352,17 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv)
_input->lines(0), _input->lines(1), _input->lines(2),
_input->line_size()[0], _input->line_size()[1], _input->line_size()[2]
));
-
- socket->write ((uint8_t *) s.str().c_str(), s.str().length() + 1, 30);
+
+ socket->write (s.str().length() + 1);
+ socket->write ((uint8_t *) s.str().c_str(), s.str().length() + 1);
_input->write_to_socket (socket);
if (_subtitle) {
_subtitle->image()->write_to_socket (socket);
}
- char buffer[32];
- socket->read_indefinite ((uint8_t *) buffer, sizeof (buffer), 30);
- socket->consume (strlen (buffer) + 1);
- shared_ptr<EncodedData> e (new RemotelyEncodedData (atoi (buffer)));
-
- /* now read the rest */
- socket->read_definite_and_consume (e->data(), e->size(), 30);
+ shared_ptr<EncodedData> e (new RemotelyEncodedData (socket->read_uint32 ()));
+ socket->read (e->data(), e->size());
_log->log (String::compose ("Finished remotely-encoded frame %1", _frame));
@@ -438,10 +434,8 @@ EncodedData::write_info (shared_ptr<const Film> film, int frame, libdcp::FrameIn
void
EncodedData::send (shared_ptr<Socket> socket)
{
- stringstream s;
- s << _size;
- socket->write ((uint8_t *) s.str().c_str(), s.str().length() + 1, 30);
- socket->write (_data, _size, 30);
+ socket->write (_size);
+ socket->write (_data, _size);
}
LocallyEncodedData::LocallyEncodedData (uint8_t* d, int s)
diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc
index d64622cba..f25256379 100644
--- a/src/lib/encoder.cc
+++ b/src/lib/encoder.cc
@@ -140,7 +140,7 @@ Encoder::process_end ()
}
out->set_frames (frames);
- _writer->write (out);
+ write_audio (out);
}
swr_free (&_swr_context);
@@ -319,23 +319,7 @@ Encoder::process_audio (shared_ptr<AudioBuffers> data)
}
#endif
- if (_film->audio_channels() == 1) {
- /* We need to switch things around so that the mono channel is on
- the centre channel of a 5.1 set (with other channels silent).
- */
-
- shared_ptr<AudioBuffers> b (new AudioBuffers (6, data->frames ()));
- b->make_silent (libdcp::LEFT);
- b->make_silent (libdcp::RIGHT);
- memcpy (b->data()[libdcp::CENTRE], data->data()[0], data->frames() * sizeof(float));
- b->make_silent (libdcp::LFE);
- b->make_silent (libdcp::LS);
- b->make_silent (libdcp::RS);
-
- data = b;
- }
-
- _writer->write (data);
+ write_audio (data);
}
void
@@ -435,3 +419,25 @@ Encoder::encoder_thread (ServerDescription* server)
_condition.notify_all ();
}
}
+
+void
+Encoder::write_audio (shared_ptr<const AudioBuffers> data)
+{
+ if (_film->audio_channels() == 1) {
+ /* We need to switch things around so that the mono channel is on
+ the centre channel of a 5.1 set (with other channels silent).
+ */
+
+ shared_ptr<AudioBuffers> b (new AudioBuffers (6, data->frames ()));
+ b->make_silent (libdcp::LEFT);
+ b->make_silent (libdcp::RIGHT);
+ memcpy (b->data()[libdcp::CENTRE], data->data()[0], data->frames() * sizeof(float));
+ b->make_silent (libdcp::LFE);
+ b->make_silent (libdcp::LS);
+ b->make_silent (libdcp::RS);
+
+ data = b;
+ }
+
+ _writer->write (data);
+}
diff --git a/src/lib/encoder.h b/src/lib/encoder.h
index 69a5c5a23..86880bc34 100644
--- a/src/lib/encoder.h
+++ b/src/lib/encoder.h
@@ -88,7 +88,7 @@ private:
void frame_done ();
- void write_audio (boost::shared_ptr<const AudioBuffers> audio);
+ void write_audio (boost::shared_ptr<const AudioBuffers> data);
void encoder_thread (ServerDescription *);
void terminate_threads ();
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index 1f11f70a0..d4ed76e37 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -127,7 +127,7 @@ FFmpegDecoder::setup_general ()
/* This is a hack; sometimes it seems that _audio_codec_context->channel_layout isn't set up,
so bodge it here. No idea why we should have to do this.
*/
-
+
if (s->codec->channel_layout == 0) {
s->codec->channel_layout = av_get_default_channel_layout (s->codec->channels);
}
@@ -247,7 +247,7 @@ FFmpegDecoder::pass ()
);
assert (_audio_codec_context->channels == _film->audio_channels());
- Audio (deinterleave_audio (_frame->data[0], data_size));
+ Audio (deinterleave_audio (_frame->data, data_size));
}
}
@@ -320,7 +320,7 @@ FFmpegDecoder::pass ()
);
assert (_audio_codec_context->channels == _film->audio_channels());
- Audio (deinterleave_audio (_frame->data[0], data_size));
+ Audio (deinterleave_audio (_frame->data, data_size));
}
}
@@ -350,8 +350,11 @@ FFmpegDecoder::pass ()
return false;
}
+/** @param data pointer to array of pointers to buffers.
+ * Only the first buffer will be used for non-planar data, otherwise there will be one per channel.
+ */
shared_ptr<AudioBuffers>
-FFmpegDecoder::deinterleave_audio (uint8_t* data, int size)
+FFmpegDecoder::deinterleave_audio (uint8_t** data, int size)
{
assert (_film->audio_channels());
assert (bytes_per_audio_sample());
@@ -370,7 +373,7 @@ FFmpegDecoder::deinterleave_audio (uint8_t* data, int size)
switch (audio_sample_format()) {
case AV_SAMPLE_FMT_S16:
{
- int16_t* p = reinterpret_cast<int16_t *> (data);
+ int16_t* p = reinterpret_cast<int16_t *> (data[0]);
int sample = 0;
int channel = 0;
for (int i = 0; i < total_samples; ++i) {
@@ -387,10 +390,10 @@ FFmpegDecoder::deinterleave_audio (uint8_t* data, int size)
case AV_SAMPLE_FMT_S16P:
{
- int16_t* p = reinterpret_cast<int16_t *> (data);
+ int16_t** p = reinterpret_cast<int16_t **> (data);
for (int i = 0; i < _film->audio_channels(); ++i) {
for (int j = 0; j < frames; ++j) {
- audio->data(i)[j] = static_cast<float>(*p++) / (1 << 15);
+ audio->data(i)[j] = static_cast<float>(p[i][j]) / (1 << 15);
}
}
}
@@ -398,7 +401,7 @@ FFmpegDecoder::deinterleave_audio (uint8_t* data, int size)
case AV_SAMPLE_FMT_S32:
{
- int32_t* p = reinterpret_cast<int32_t *> (data);
+ int32_t* p = reinterpret_cast<int32_t *> (data[0]);
int sample = 0;
int channel = 0;
for (int i = 0; i < total_samples; ++i) {
@@ -415,7 +418,7 @@ FFmpegDecoder::deinterleave_audio (uint8_t* data, int size)
case AV_SAMPLE_FMT_FLT:
{
- float* p = reinterpret_cast<float*> (data);
+ float* p = reinterpret_cast<float*> (data[0]);
int sample = 0;
int channel = 0;
for (int i = 0; i < total_samples; ++i) {
@@ -432,10 +435,9 @@ FFmpegDecoder::deinterleave_audio (uint8_t* data, int size)
case AV_SAMPLE_FMT_FLTP:
{
- float* p = reinterpret_cast<float*> (data);
+ float** p = reinterpret_cast<float**> (data);
for (int i = 0; i < _film->audio_channels(); ++i) {
- memcpy (audio->data(i), p, frames * sizeof(float));
- p += frames;
+ memcpy (audio->data(i), p[i], frames * sizeof(float));
}
}
break;
diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h
index 17308eb56..c383b8d13 100644
--- a/src/lib/ffmpeg_decoder.h
+++ b/src/lib/ffmpeg_decoder.h
@@ -121,7 +121,7 @@ private:
void setup_subtitle ();
void maybe_add_subtitle ();
- boost::shared_ptr<AudioBuffers> deinterleave_audio (uint8_t* data, int size);
+ boost::shared_ptr<AudioBuffers> deinterleave_audio (uint8_t** data, int size);
void film_changed (Film::Property);
diff --git a/src/lib/film.cc b/src/lib/film.cc
index 77f61cbac..600cdfa02 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -237,11 +237,9 @@ Film::video_mxf_filename () const
return video_state_identifier() + ".mxf";
}
-/** Add suitable Jobs to the JobManager to create a DCP for this Film.
- * @param true to transcode, false to use the WAV and J2K files that are already there.
- */
+/** Add suitable Jobs to the JobManager to create a DCP for this Film */
void
-Film::make_dcp (bool transcode)
+Film::make_dcp ()
{
set_dci_date_today ();
@@ -298,12 +296,10 @@ Film::make_dcp (bool transcode)
shared_ptr<Job> r;
- if (transcode) {
- if (dcp_ab()) {
- r = JobManager::instance()->add (shared_ptr<Job> (new ABTranscodeJob (shared_from_this(), od)));
- } else {
- r = JobManager::instance()->add (shared_ptr<Job> (new TranscodeJob (shared_from_this(), od)));
- }
+ if (dcp_ab()) {
+ r = JobManager::instance()->add (shared_ptr<Job> (new ABTranscodeJob (shared_from_this(), od)));
+ } else {
+ r = JobManager::instance()->add (shared_ptr<Job> (new TranscodeJob (shared_from_this(), od)));
}
}
diff --git a/src/lib/film.h b/src/lib/film.h
index cc77460db..04a483998 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -69,7 +69,7 @@ public:
void examine_content ();
void send_dcp_to_tms ();
- void make_dcp (bool);
+ void make_dcp ();
/** @return Logger.
* It is safe to call this from any thread.
diff --git a/src/lib/image.cc b/src/lib/image.cc
index 0ec6bd26c..73d499fe8 100644
--- a/src/lib/image.cc
+++ b/src/lib/image.cc
@@ -323,7 +323,7 @@ Image::read_from_socket (shared_ptr<Socket> socket)
for (int i = 0; i < components(); ++i) {
uint8_t* p = data()[i];
for (int y = 0; y < lines(i); ++y) {
- socket->read_definite_and_consume (p, line_size()[i], 30);
+ socket->read (p, line_size()[i]);
p += stride()[i];
}
}
@@ -335,7 +335,7 @@ Image::write_to_socket (shared_ptr<Socket> socket) const
for (int i = 0; i < components(); ++i) {
uint8_t* p = data()[i];
for (int y = 0; y < lines(i); ++y) {
- socket->write (p, line_size()[i], 30);
+ socket->write (p, line_size()[i]);
p += stride()[i];
}
}
@@ -503,12 +503,18 @@ FilterBufferImage::FilterBufferImage (AVPixelFormat p, AVFilterBufferRef* b)
: Image (p)
, _buffer (b)
{
-
+ _line_size = (int *) av_malloc (4 * sizeof (int));
+ _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
+
+ for (int i = 0; i < components(); ++i) {
+ _line_size[i] = size().width * bytes_per_pixel(i);
+ }
}
FilterBufferImage::~FilterBufferImage ()
{
avfilter_unref_buffer (_buffer);
+ av_free (_line_size);
}
uint8_t **
@@ -520,13 +526,16 @@ FilterBufferImage::data () const
int *
FilterBufferImage::line_size () const
{
- return _buffer->linesize;
+ return _line_size;
}
int *
FilterBufferImage::stride () const
{
- /* XXX? */
+ /* I've seen images where the _buffer->linesize is larger than the width
+ (by a small amount), suggesting that _buffer->linesize is what we call
+ stride. But I'm not sure.
+ */
return _buffer->linesize;
}
diff --git a/src/lib/image.h b/src/lib/image.h
index 23f13a648..f40ea9280 100644
--- a/src/lib/image.h
+++ b/src/lib/image.h
@@ -117,6 +117,7 @@ private:
FilterBufferImage& operator= (FilterBufferImage const &);
AVFilterBufferRef* _buffer;
+ int* _line_size;
};
/** @class SimpleImage
diff --git a/src/lib/server.cc b/src/lib/server.cc
index d75ab0fb6..3614ed9e4 100644
--- a/src/lib/server.cc
+++ b/src/lib/server.cc
@@ -28,6 +28,7 @@
#include <iostream>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
+#include <boost/scoped_array.hpp>
#include "server.h"
#include "util.h"
#include "scaler.h"
@@ -45,6 +46,7 @@ using boost::algorithm::is_any_of;
using boost::algorithm::split;
using boost::thread;
using boost::bind;
+using boost::scoped_array;
using libdcp::Size;
/** Create a server description from a string of metadata returned from as_metadata().
@@ -82,11 +84,11 @@ Server::Server (Log* log)
int
Server::process (shared_ptr<Socket> socket)
{
- char buffer[512];
- socket->read_indefinite ((uint8_t *) buffer, sizeof (buffer), 30);
- socket->consume (strlen (buffer) + 1);
+ uint32_t length = socket->read_uint32 ();
+ scoped_array<char> buffer (new char[length]);
+ socket->read (reinterpret_cast<uint8_t*> (buffer.get()), length);
- stringstream s (buffer);
+ stringstream s (buffer.get());
multimap<string, string> kv = read_key_value (s);
if (get_required_string (kv, "encode") != "please") {
diff --git a/src/lib/subtitle.cc b/src/lib/subtitle.cc
index bd5f0c879..5bb91af63 100644
--- a/src/lib/subtitle.cc
+++ b/src/lib/subtitle.cc
@@ -134,8 +134,8 @@ subtitle_transformed_area (
* Combining these two translations gives these expressions.
*/
- tx.x = target_x_scale * (sub_area.x + (sub_area.width * (1 - subtitle_scale) / 2));
- tx.y = target_y_scale * (sub_area.y + (sub_area.height * (1 - subtitle_scale) / 2));
+ tx.x = rint (target_x_scale * (sub_area.x + (sub_area.width * (1 - subtitle_scale) / 2)));
+ tx.y = rint (target_y_scale * (sub_area.y + (sub_area.height * (1 - subtitle_scale) / 2)));
return tx;
}
diff --git a/src/lib/util.cc b/src/lib/util.cc
index c0c8be984..4ee304600 100644
--- a/src/lib/util.cc
+++ b/src/lib/util.cc
@@ -485,10 +485,10 @@ colour_lut_index_to_name (int index)
return "";
}
-Socket::Socket ()
+Socket::Socket (int timeout)
: _deadline (_io_service)
, _socket (_io_service)
- , _buffer_data (0)
+ , _timeout (timeout)
{
_deadline.expires_at (posix_time::pos_infin);
check ();
@@ -505,14 +505,13 @@ Socket::check ()
_deadline.async_wait (boost::bind (&Socket::check, this));
}
-/** Blocking connect with timeout.
+/** Blocking connect.
* @param endpoint End-point to connect to.
- * @param timeout Time-out in seconds.
*/
void
-Socket::connect (asio::ip::basic_resolver_entry<asio::ip::tcp> const & endpoint, int timeout)
+Socket::connect (asio::ip::basic_resolver_entry<asio::ip::tcp> const & endpoint)
{
- _deadline.expires_from_now (posix_time::seconds (timeout));
+ _deadline.expires_from_now (posix_time::seconds (_timeout));
system::error_code ec = asio::error::would_block;
_socket.async_connect (endpoint, lambda::var(ec) = lambda::_1);
do {
@@ -524,132 +523,61 @@ Socket::connect (asio::ip::basic_resolver_entry<asio::ip::tcp> const & endpoint,
}
}
-/** Blocking write with timeout.
+/** Blocking write.
* @param data Buffer to write.
* @param size Number of bytes to write.
- * @param timeout Time-out, in seconds.
*/
void
-Socket::write (uint8_t const * data, int size, int timeout)
+Socket::write (uint8_t const * data, int size)
{
- _deadline.expires_from_now (posix_time::seconds (timeout));
+ _deadline.expires_from_now (posix_time::seconds (_timeout));
system::error_code ec = asio::error::would_block;
asio::async_write (_socket, asio::buffer (data, size), lambda::var(ec) = lambda::_1);
+
do {
_io_service.run_one ();
} while (ec == asio::error::would_block);
if (ec) {
- throw NetworkError ("write timed out");
+ throw NetworkError (ec.message ());
}
}
-/** Blocking read with timeout.
+void
+Socket::write (uint32_t v)
+{
+ v = htonl (v);
+ write (reinterpret_cast<uint8_t*> (&v), 4);
+}
+
+/** Blocking read.
* @param data Buffer to read to.
* @param size Number of bytes to read.
- * @param timeout Time-out, in seconds.
*/
-int
-Socket::read (uint8_t* data, int size, int timeout)
+void
+Socket::read (uint8_t* data, int size)
{
- _deadline.expires_from_now (posix_time::seconds (timeout));
+ _deadline.expires_from_now (posix_time::seconds (_timeout));
system::error_code ec = asio::error::would_block;
- int amount_read = 0;
-
- _socket.async_read_some (
- asio::buffer (data, size),
- (lambda::var(ec) = lambda::_1, lambda::var(amount_read) = lambda::_2)
- );
+ asio::async_read (_socket, asio::buffer (data, size), lambda::var(ec) = lambda::_1);
do {
_io_service.run_one ();
} while (ec == asio::error::would_block);
if (ec) {
- amount_read = 0;
- }
-
- return amount_read;
-}
-
-/** Mark some data as being `consumed', so that it will not be returned
- * as data again.
- * @param size Amount of data to consume, in bytes.
- */
-void
-Socket::consume (int size)
-{
- assert (_buffer_data >= size);
-
- _buffer_data -= size;
- if (_buffer_data > 0) {
- /* Shift still-valid data to the start of the buffer */
- memmove (_buffer, _buffer + size, _buffer_data);
+ throw NetworkError (ec.message ());
}
}
-/** Read a definite amount of data from our socket, and mark
- * it as consumed.
- * @param data Where to put the data.
- * @param size Number of bytes to read.
- */
-void
-Socket::read_definite_and_consume (uint8_t* data, int size, int timeout)
-{
- int const from_buffer = min (_buffer_data, size);
- if (from_buffer > 0) {
- /* Get data from our buffer */
- memcpy (data, _buffer, from_buffer);
- consume (from_buffer);
- /* Update our output state */
- data += from_buffer;
- size -= from_buffer;
- }
-
- /* read() the rest */
- while (size > 0) {
- int const n = read (data, size, timeout);
- if (n <= 0) {
- throw NetworkError ("could not read");
- }
-
- data += n;
- size -= n;
- }
-}
-
-/** Read as much data as is available, up to some limit.
- * @param data Where to put the data.
- * @param size Maximum amount of data to read.
- *
- * XXX This method assumes that there is always lots of data to read();
- * if there isn't, it will hang waiting for data that will never arrive.
- */
-void
-Socket::read_indefinite (uint8_t* data, int size, int timeout)
+uint32_t
+Socket::read_uint32 ()
{
- assert (size < int (sizeof (_buffer)));
-
- /* Amount of extra data we need to read () */
- int to_read = size - _buffer_data;
- while (to_read > 0) {
- /* read as much of it as we can (into our buffer) */
- int const n = read (_buffer + _buffer_data, to_read, timeout);
- if (n <= 0) {
- throw NetworkError ("could not read");
- }
-
- to_read -= n;
- _buffer_data += n;
- }
-
- assert (_buffer_data >= size);
-
- /* copy data into the output buffer */
- assert (size >= _buffer_data);
- memcpy (data, _buffer, size);
+ uint32_t v;
+ read (reinterpret_cast<uint8_t *> (&v), 4);
+ return ntohl (v);
}
/** @param other A Rect.
diff --git a/src/lib/util.h b/src/lib/util.h
index c4940a5d7..87735ea8e 100644
--- a/src/lib/util.h
+++ b/src/lib/util.h
@@ -194,39 +194,35 @@ extern std::string get_optional_string (std::multimap<std::string, std::string>
* that are useful for DVD-o-matic.
*
* This class wraps some things that I could not work out how to do with boost;
- * most notably, sync read/write calls with timeouts, and the ability to peek into
- * data being read.
+ * most notably, sync read/write calls with timeouts.
*/
class Socket
{
public:
- Socket ();
+ Socket (int timeout = 30);
/** @return Our underlying socket */
boost::asio::ip::tcp::socket& socket () {
return _socket;
}
- void connect (boost::asio::ip::basic_resolver_entry<boost::asio::ip::tcp> const & endpoint, int timeout);
- void write (uint8_t const * data, int size, int timeout);
+ void connect (boost::asio::ip::basic_resolver_entry<boost::asio::ip::tcp> const & endpoint);
+
+ void write (uint32_t n);
+ void write (uint8_t const * data, int size);
- void read_definite_and_consume (uint8_t* data, int size, int timeout);
- void read_indefinite (uint8_t* data, int size, int timeout);
- void consume (int amount);
+ void read (uint8_t* data, int size);
+ uint32_t read_uint32 ();
private:
void check ();
- int read (uint8_t* data, int size, int timeout);
Socket (Socket const &);
boost::asio::io_service _io_service;
boost::asio::deadline_timer _deadline;
boost::asio::ip::tcp::socket _socket;
- /** a buffer for small reads */
- uint8_t _buffer[1024];
- /** amount of valid data in the buffer */
- int _buffer_data;
+ int _timeout;
};
/** @class AudioBuffers
diff --git a/src/lib/writer.cc b/src/lib/writer.cc
index 8a09f254b..c2cc00328 100644
--- a/src/lib/writer.cc
+++ b/src/lib/writer.cc
@@ -72,13 +72,13 @@ Writer::Writer (shared_ptr<Film> f)
_picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0);
- if (_film->audio_channels() > 0) {
+ if (dcp_audio_channels (_film->audio_channels()) > 0) {
_sound_asset.reset (
new libdcp::SoundAsset (
_film->dir (_film->dcp_name()),
"audio.mxf",
DCPFrameRate (_film->frames_per_second()).frames_per_second,
- _film->audio_channels(),
+ dcp_audio_channels (_film->audio_channels()),
dcp_audio_sample_rate (_film->audio_stream()->sample_rate())
)
);
diff --git a/src/tools/dvdomatic.cc b/src/tools/dvdomatic.cc
index 5d944a934..1b76132f6 100644
--- a/src/tools/dvdomatic.cc
+++ b/src/tools/dvdomatic.cc
@@ -146,7 +146,6 @@ enum {
ID_jobs_send_dcp_to_tms,
ID_jobs_show_dcp,
ID_jobs_examine_content,
- ID_jobs_make_dcp_from_existing_transcode,
ID_help_about
};
@@ -172,7 +171,6 @@ setup_menu (wxMenuBar* m)
add_item (jobs_menu, "S&how DCP", ID_jobs_show_dcp, NEEDS_FILM);
jobs_menu->AppendSeparator ();
add_item (jobs_menu, "&Examine content", ID_jobs_examine_content, NEEDS_FILM);
- add_item (jobs_menu, "Make DCP from existing &transcode", ID_jobs_make_dcp_from_existing_transcode, NEEDS_FILM);
wxMenu* help = new wxMenu;
add_item (help, "About", ID_help_about, ALWAYS);
@@ -210,7 +208,6 @@ public:
Connect (ID_jobs_send_dcp_to_tms, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_send_dcp_to_tms));
Connect (ID_jobs_show_dcp, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_show_dcp));
Connect (ID_jobs_examine_content, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_examine_content));
- Connect (ID_jobs_make_dcp_from_existing_transcode, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::jobs_make_dcp_from_existing_transcode));
Connect (ID_help_about, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler (Frame::help_about));
Connect (wxID_ANY, wxEVT_MENU_OPEN, wxMenuEventHandler (Frame::menu_opened));
@@ -224,12 +221,12 @@ public:
film_viewer = new FilmViewer (film, panel);
JobManagerView* job_manager_view = new JobManagerView (panel);
- wxSizer* top_sizer = new wxBoxSizer (wxHORIZONTAL);
- top_sizer->Add (film_editor, 0, wxALL, 6);
- top_sizer->Add (film_viewer, 1, wxEXPAND | wxALL, 6);
+ _top_sizer = new wxBoxSizer (wxHORIZONTAL);
+ _top_sizer->Add (film_editor, 0, wxALL, 6);
+ _top_sizer->Add (film_viewer, 1, wxEXPAND | wxALL, 6);
wxBoxSizer* main_sizer = new wxBoxSizer (wxVERTICAL);
- main_sizer->Add (top_sizer, 2, wxEXPAND | wxALL, 6);
+ main_sizer->Add (_top_sizer, 2, wxEXPAND | wxALL, 6);
main_sizer->Add (job_manager_view, 1, wxEXPAND | wxALL, 6);
panel->SetSizer (main_sizer);
@@ -244,12 +241,24 @@ public:
} else {
file_changed ("");
}
-
+
set_film ();
+
+ film_editor->Connect (wxID_ANY, wxEVT_SIZE, wxSizeEventHandler (Frame::film_editor_sized), 0, this);
}
private:
+ void film_editor_sized (wxSizeEvent &)
+ {
+ static bool in_layout = false;
+ if (!in_layout) {
+ in_layout = true;
+ _top_sizer->Layout ();
+ in_layout = false;
+ }
+ }
+
void menu_opened (wxMenuEvent& ev)
{
if (ev.GetMenu() != jobs_menu) {
@@ -287,7 +296,7 @@ private:
if (r == wxID_OK) {
if (boost::filesystem::exists (d->get_path())) {
- error_dialog (this, wxString::Format (_("The directory %s already exists"), d->get_path().c_str()));
+ error_dialog (this, wxString::Format (_("The directory %s already exists."), d->get_path().c_str()));
return;
}
@@ -350,12 +359,7 @@ private:
void jobs_make_dcp (wxCommandEvent &)
{
- JobWrapper::make_dcp (this, film, true);
- }
-
- void jobs_make_dcp_from_existing_transcode (wxCommandEvent &)
- {
- JobWrapper::make_dcp (this, film, false);
+ JobWrapper::make_dcp (this, film);
}
void jobs_send_dcp_to_tms (wxCommandEvent &)
@@ -408,6 +412,8 @@ private:
info.SetWebSite (wxT ("http://carlh.net/software/dvdomatic"));
wxAboutBox (info);
}
+
+ wxSizer* _top_sizer;
};
#if wxMINOR_VERSION == 9
diff --git a/src/tools/makedcp.cc b/src/tools/makedcp.cc
index 892bed3b8..0c6390771 100644
--- a/src/tools/makedcp.cc
+++ b/src/tools/makedcp.cc
@@ -155,7 +155,7 @@ main (int argc, char* argv[])
pair<string, string> const f = Filter::ffmpeg_strings (film->filters ());
cout << "Filters: " << f.first << " " << f.second << "\n";
- film->make_dcp (true);
+ film->make_dcp ();
bool should_stop = false;
bool first = true;
diff --git a/src/tools/servomatictest.cc b/src/tools/servomatictest.cc
index 88c2a833e..91ad02120 100644
--- a/src/tools/servomatictest.cc
+++ b/src/tools/servomatictest.cc
@@ -34,22 +34,40 @@
#include "scaler.h"
#include "log.h"
#include "decoder_factory.h"
+#include "video_decoder.h"
-using namespace std;
-using namespace boost;
+using std::cout;
+using std::cerr;
+using std::string;
+using std::pair;
+using boost::shared_ptr;
-static Server* server;
-static Log log_ ("servomatictest.log");
+static ServerDescription* server;
+static FileLog log_ ("servomatictest.log");
+static int frame = 0;
void
-process_video (shared_ptr<Image> image, bool, int frame)
+process_video (shared_ptr<Image> image, bool, shared_ptr<Subtitle> sub)
{
- shared_ptr<DCPVideoFrame> local (new DCPVideoFrame (image, Size (1024, 1024), 0, Scaler::from_id ("bicubic"), frame, 24, "", 0, 250000000, &log_));
- shared_ptr<DCPVideoFrame> remote (new DCPVideoFrame (image, Size (1024, 1024), 0, Scaler::from_id ("bicubic"), frame, 24, "", 0, 250000000, &log_));
+ shared_ptr<DCPVideoFrame> local (
+ new DCPVideoFrame (
+ image, sub,
+ libdcp::Size (1024, 1024), 0, 0, 0,
+ Scaler::from_id ("bicubic"), frame, 24, "", 0, 250000000, &log_)
+ );
+
+ shared_ptr<DCPVideoFrame> remote (
+ new DCPVideoFrame (
+ image, sub,
+ libdcp::Size (1024, 1024), 0, 0, 0,
+ Scaler::from_id ("bicubic"), frame, 24, "", 0, 250000000, &log_)
+ );
cout << "Frame " << frame << ": ";
cout.flush ();
+ ++frame;
+
shared_ptr<EncodedData> local_encoded = local->encode_locally ();
shared_ptr<EncodedData> remote_encoded;
@@ -130,17 +148,21 @@ main (int argc, char* argv[])
dvdomatic_setup ();
- server = new Server (server_host, 1);
- Film film (film_dir, true);
+ server = new ServerDescription (server_host, 1);
+ shared_ptr<Film> film (new Film (film_dir, true));
- shared_ptr<Options> opt (new Options ("fred", "jim", "sheila"));
- opt->out_size = Size (1024, 1024);
- opt->decode_audio = false;
+ DecodeOptions opt;
+ opt.decode_audio = false;
+ opt.decode_subtitles = true;
+ opt.video_sync = true;
- shared_ptr<Decoder> decoder = decoder_factory (film.state_copy(), opt, 0, &log_);
+ Decoders decoders = decoder_factory (film, opt);
try {
- decoder->Video.connect (sigc::ptr_fun (process_video));
- decoder->go ();
+ decoders.video->Video.connect (boost::bind (process_video, _1, _2, _3));
+ bool done = false;
+ while (!done) {
+ done = decoders.video->pass ();
+ }
} catch (std::exception& e) {
cerr << "Error: " << e.what() << "\n";
}
diff --git a/src/tools/wscript b/src/tools/wscript
index 5a837f845..c843c61d8 100644
--- a/src/tools/wscript
+++ b/src/tools/wscript
@@ -1,5 +1,5 @@
def build(bld):
- for t in ['makedcp', 'servomatic_cli']:
+ for t in ['makedcp', 'servomatic_cli', 'servomatictest']:
obj = bld(features = 'cxx cxxprogram')
obj.uselib = 'BOOST_THREAD OPENJPEG DCP AVFORMAT AVFILTER AVCODEC AVUTIL SWSCALE POSTPROC'
obj.includes = ['..']
diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc
index e9992a11f..96656ce09 100644
--- a/src/wx/film_viewer.cc
+++ b/src/wx/film_viewer.cc
@@ -149,7 +149,6 @@ FilmViewer::set_film (shared_ptr<Film> f)
_film->Changed.connect (boost::bind (&FilmViewer::film_changed, this, _1));
film_changed (Film::CONTENT);
- film_changed (Film::CROP);
film_changed (Film::FORMAT);
film_changed (Film::WITH_SUBTITLES);
film_changed (Film::SUBTITLE_OFFSET);
@@ -289,9 +288,16 @@ FilmViewer::raw_to_display ()
}
if (_raw_sub) {
+
+ /* Our output is already cropped by the decoder, so we need to account for that
+ when working out the scale that we are applying.
+ */
+
+ Size const cropped_size = _film->cropped_size (_film->size ());
+
Rect tx = subtitle_transformed_area (
- float (_film_size.width) / _film->size().width,
- float (_film_size.height) / _film->size().height,
+ float (_film_size.width) / cropped_size.width,
+ float (_film_size.height) / cropped_size.height,
_raw_sub->area(), _film->subtitle_offset(), _film->subtitle_scale()
);
diff --git a/src/wx/job_manager_view.cc b/src/wx/job_manager_view.cc
index 8bede709f..7537da287 100644
--- a/src/wx/job_manager_view.cc
+++ b/src/wx/job_manager_view.cc
@@ -98,17 +98,17 @@ JobManagerView::update ()
if (!(*i)->finished ()) {
float const p = (*i)->overall_progress ();
if (p >= 0) {
- _job_records[*i].message->SetLabel (std_to_wx (st));
+ checked_set (_job_records[*i].message, st);
_job_records[*i].gauge->SetValue (p * 100);
} else {
- _job_records[*i].message->SetLabel (_("Running"));
+ checked_set (_job_records[*i].message, wx_to_std (_("Running")));
_job_records[*i].gauge->Pulse ();
}
}
if ((*i)->finished() && !_job_records[*i].finalised) {
_job_records[*i].gauge->SetValue (100);
- _job_records[*i].message->SetLabel (std_to_wx (st));
+ checked_set (_job_records[*i].message, st);
_job_records[*i].finalised = true;
if (!(*i)->error_details().empty ()) {
_job_records[*i].details->Enable (true);
diff --git a/src/wx/job_wrapper.cc b/src/wx/job_wrapper.cc
index cb02ecd02..8ddd3a348 100644
--- a/src/wx/job_wrapper.cc
+++ b/src/wx/job_wrapper.cc
@@ -26,14 +26,14 @@
using boost::shared_ptr;
void
-JobWrapper::make_dcp (wxWindow* parent, shared_ptr<Film> film, bool transcode)
+JobWrapper::make_dcp (wxWindow* parent, shared_ptr<Film> film)
{
if (!film) {
return;
}
try {
- film->make_dcp (transcode);
+ film->make_dcp ();
} catch (BadSettingError& e) {
error_dialog (parent, wxString::Format (_("Bad setting for %s (%s)"), e.setting().c_str(), e.what()));
} catch (std::exception& e) {
diff --git a/src/wx/job_wrapper.h b/src/wx/job_wrapper.h
index 7120e9f10..b0a4693dd 100644
--- a/src/wx/job_wrapper.h
+++ b/src/wx/job_wrapper.h
@@ -24,6 +24,6 @@ class Film;
namespace JobWrapper
{
-void make_dcp (wxWindow *, boost::shared_ptr<Film>, bool);
+void make_dcp (wxWindow *, boost::shared_ptr<Film>);
}
diff --git a/src/wx/wx_util.cc b/src/wx/wx_util.cc
index 632dbc32e..bf78ff4d7 100644
--- a/src/wx/wx_util.cc
+++ b/src/wx/wx_util.cc
@@ -171,6 +171,14 @@ checked_set (wxTextCtrl* widget, string value)
}
void
+checked_set (wxStaticText* widget, string value)
+{
+ if (widget->GetLabel() != std_to_wx (value)) {
+ widget->SetLabel (std_to_wx (value));
+ }
+}
+
+void
checked_set (wxCheckBox* widget, bool value)
{
if (widget->GetValue() != value) {
diff --git a/src/wx/wx_util.h b/src/wx/wx_util.h
index dd069a9d7..6cde08a90 100644
--- a/src/wx/wx_util.h
+++ b/src/wx/wx_util.h
@@ -63,3 +63,4 @@ extern void checked_set (wxChoice* widget, std::string value);
extern void checked_set (wxTextCtrl* widget, std::string value);
extern void checked_set (wxCheckBox* widget, bool value);
extern void checked_set (wxRadioButton* widget, bool value);
+extern void checked_set (wxStaticText* widget, std::string value);