diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-02-22 18:58:31 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-02-22 18:58:31 +0000 |
| commit | 62365221dd3cd80d6b771e9bf22b4f9365ee096a (patch) | |
| tree | 6d75b967b7e250a93eb3b600ce89706b2018f069 /src | |
| parent | fa6c885de512cdde0590c2bbe9ea424030a12c6b (diff) | |
| parent | 5943bde6f1a29c84b3f79710535a41bb98f6ce7d (diff) | |
Merge branch 'master' into i18n
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/dcp_video_frame.cc | 22 | ||||
| -rw-r--r-- | src/lib/encoder.cc | 42 | ||||
| -rw-r--r-- | src/lib/encoder.h | 2 | ||||
| -rw-r--r-- | src/lib/ffmpeg_decoder.cc | 26 | ||||
| -rw-r--r-- | src/lib/ffmpeg_decoder.h | 2 | ||||
| -rw-r--r-- | src/lib/film.cc | 16 | ||||
| -rw-r--r-- | src/lib/film.h | 2 | ||||
| -rw-r--r-- | src/lib/image.cc | 19 | ||||
| -rw-r--r-- | src/lib/image.h | 1 | ||||
| -rw-r--r-- | src/lib/server.cc | 10 | ||||
| -rw-r--r-- | src/lib/subtitle.cc | 4 | ||||
| -rw-r--r-- | src/lib/util.cc | 128 | ||||
| -rw-r--r-- | src/lib/util.h | 22 | ||||
| -rw-r--r-- | src/lib/writer.cc | 4 | ||||
| -rw-r--r-- | src/tools/dvdomatic.cc | 36 | ||||
| -rw-r--r-- | src/tools/makedcp.cc | 2 | ||||
| -rw-r--r-- | src/tools/servomatictest.cc | 52 | ||||
| -rw-r--r-- | src/tools/wscript | 2 | ||||
| -rw-r--r-- | src/wx/film_viewer.cc | 12 | ||||
| -rw-r--r-- | src/wx/job_manager_view.cc | 6 | ||||
| -rw-r--r-- | src/wx/job_wrapper.cc | 4 | ||||
| -rw-r--r-- | src/wx/job_wrapper.h | 2 | ||||
| -rw-r--r-- | src/wx/wx_util.cc | 8 | ||||
| -rw-r--r-- | src/wx/wx_util.h | 1 |
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); |
