summaryrefslogtreecommitdiff
path: root/src/lib
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/lib
parentfa6c885de512cdde0590c2bbe9ea424030a12c6b (diff)
parent5943bde6f1a29c84b3f79710535a41bb98f6ce7d (diff)
Merge branch 'master' into i18n
Diffstat (limited to 'src/lib')
-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
14 files changed, 117 insertions, 183 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())
)
);