summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-01-18 21:49:49 +0000
committerCarl Hetherington <cth@carlh.net>2013-01-18 21:49:49 +0000
commit5e4ab7ebd9a6b62b64fbaf91d7aa1a2a9d4bdec4 (patch)
treecf863264ba3cd7cab9b6c65a0c821650534f537c /src/lib
parent940b64c80c8ed5d434de596d77fdb31762e3fbb3 (diff)
Untested direct write of audio to MXF.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/dcp_video_frame.cc2
-rw-r--r--src/lib/dcp_video_frame.h2
-rw-r--r--src/lib/encoder.cc59
-rw-r--r--src/lib/encoder.h8
-rw-r--r--src/lib/writer.cc35
-rw-r--r--src/lib/writer.h12
6 files changed, 43 insertions, 75 deletions
diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc
index da864ad9f..89db5761a 100644
--- a/src/lib/dcp_video_frame.cc
+++ b/src/lib/dcp_video_frame.cc
@@ -405,7 +405,7 @@ EncodedData::~EncodedData ()
* @param frame DCP Frame index.
*/
void
-EncodedData::write (shared_ptr<const Film> film, int frame)
+EncodedData::write (shared_ptr<const Film> film, int frame) const
{
string const tmp_j2k = film->frame_out_path (frame, true);
diff --git a/src/lib/dcp_video_frame.h b/src/lib/dcp_video_frame.h
index b446352c7..2ad2b0d44 100644
--- a/src/lib/dcp_video_frame.h
+++ b/src/lib/dcp_video_frame.h
@@ -48,7 +48,7 @@ public:
virtual ~EncodedData ();
void send (boost::shared_ptr<Socket> socket);
- void write (boost::shared_ptr<const Film>, int);
+ void write (boost::shared_ptr<const Film>, int) const;
/** @return data */
uint8_t* data () const {
diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc
index bad420f35..c2416b87e 100644
--- a/src/lib/encoder.cc
+++ b/src/lib/encoder.cc
@@ -57,37 +57,18 @@ Encoder::Encoder (shared_ptr<const Film> f)
: _film (f)
, _just_skipped (false)
, _video_frames_in (0)
- , _audio_frames_in (0)
, _video_frames_out (0)
- , _audio_frames_out (0)
#ifdef HAVE_SWRESAMPLE
, _swr_context (0)
#endif
, _have_a_real_frame (false)
, _terminate_encoder (false)
{
- if (_film->audio_stream()) {
- /* Create sound output files with .tmp suffixes; we will rename
- them if and when we complete.
- */
- for (int i = 0; i < dcp_audio_channels (_film->audio_channels()); ++i) {
- SF_INFO sf_info;
- sf_info.samplerate = dcp_audio_sample_rate (_film->audio_stream()->sample_rate());
- /* We write mono files */
- sf_info.channels = 1;
- sf_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_24;
- SNDFILE* f = sf_open (_film->multichannel_audio_out_path (i, true).c_str (), SFM_WRITE, &sf_info);
- if (f == 0) {
- throw CreateFileError (_film->multichannel_audio_out_path (i, true));
- }
- _sound_files.push_back (f);
- }
- }
+
}
Encoder::~Encoder ()
{
- close_sound_files ();
terminate_worker_threads ();
if (_writer) {
_writer->finish ();
@@ -162,25 +143,13 @@ Encoder::process_end ()
}
out->set_frames (frames);
- write_audio (out);
+ _writer->write (out);
}
swr_free (&_swr_context);
}
#endif
- if (_film->audio_stream()) {
- close_sound_files ();
-
- /* Rename .wav.tmp files to .wav */
- for (int i = 0; i < dcp_audio_channels (_film->audio_channels()); ++i) {
- if (boost::filesystem::exists (_film->multichannel_audio_out_path (i, false))) {
- boost::filesystem::remove (_film->multichannel_audio_out_path (i, false));
- }
- boost::filesystem::rename (_film->multichannel_audio_out_path (i, true), _film->multichannel_audio_out_path (i, false));
- }
- }
-
boost::mutex::scoped_lock lock (_worker_mutex);
_film->log()->log ("Clearing queue of " + lexical_cast<string> (_encode_queue.size ()));
@@ -386,32 +355,10 @@ Encoder::process_audio (shared_ptr<AudioBuffers> data)
data = b;
}
- write_audio (data);
-
- _audio_frames_in += data->frames ();
+ _writer->write (data);
}
void
-Encoder::write_audio (shared_ptr<const AudioBuffers> audio)
-{
- for (int i = 0; i < audio->channels(); ++i) {
- sf_write_float (_sound_files[i], audio->data(i), audio->frames());
- }
-
- _audio_frames_out += audio->frames ();
-}
-
-void
-Encoder::close_sound_files ()
-{
- for (vector<SNDFILE*>::iterator i = _sound_files.begin(); i != _sound_files.end(); ++i) {
- sf_close (*i);
- }
-
- _sound_files.clear ();
-}
-
-void
Encoder::terminate_worker_threads ()
{
boost::mutex::scoped_lock lock (_worker_mutex);
diff --git a/src/lib/encoder.h b/src/lib/encoder.h
index a277aca51..fc89d674a 100644
--- a/src/lib/encoder.h
+++ b/src/lib/encoder.h
@@ -39,7 +39,6 @@ extern "C" {
#include <libswresample/swresample.h>
}
#endif
-#include <sndfile.h>
#include "util.h"
#include "video_sink.h"
#include "audio_sink.h"
@@ -91,7 +90,6 @@ private:
void frame_done ();
void frame_skipped ();
- void close_sound_files ();
void write_audio (boost::shared_ptr<const AudioBuffers> audio);
void encoder_thread (ServerDescription *);
@@ -113,19 +111,13 @@ private:
/** Number of video frames received so far */
SourceFrame _video_frames_in;
- /** Number of audio frames received so far */
- int64_t _audio_frames_in;
/** Number of video frames written for the DCP so far */
int _video_frames_out;
- /** Number of audio frames written for the DCP so far */
- int64_t _audio_frames_out;
#if HAVE_SWRESAMPLE
SwrContext* _swr_context;
#endif
- std::vector<SNDFILE*> _sound_files;
-
bool _have_a_real_frame;
bool _terminate_encoder;
std::list<boost::shared_ptr<DCPVideoFrame> > _encode_queue;
diff --git a/src/lib/writer.cc b/src/lib/writer.cc
index 0381ee378..fbd371550 100644
--- a/src/lib/writer.cc
+++ b/src/lib/writer.cc
@@ -18,6 +18,7 @@
*/
#include <libdcp/picture_asset.h>
+#include <libdcp/sound_asset.h>
#include "writer.h"
#include "compose.hpp"
#include "film.h"
@@ -48,20 +49,41 @@ Writer::Writer (shared_ptr<const Film> f)
_picture_asset_writer = _picture_asset->start_write ();
+ if (_film->audio_channels() > 0) {
+ _sound_asset.reset (
+ new libdcp::SoundAsset (
+ _film->dir (_film->dcp_name()),
+ String::compose ("audio_%1.mxf", 0),
+ DCPFrameRate (_film->frames_per_second()).frames_per_second,
+ _film->audio_channels(),
+ _film->audio_stream()->sample_rate()
+ )
+ );
+
+ _sound_asset_writer = _sound_asset->start_write ();
+ }
+
_thread = new boost::thread (boost::bind (&Writer::thread, this));
}
void
-Writer::write (shared_ptr<EncodedData> encoded, int frame)
+Writer::write (shared_ptr<const EncodedData> encoded, int frame)
{
boost::mutex::scoped_lock lock (_mutex);
_queue.push_back (make_pair (encoded, frame));
_condition.notify_all ();
}
+/** This method is not thread safe */
+void
+Writer::write (shared_ptr<const AudioBuffers> audio)
+{
+ _sound_asset_writer->write (audio->data(), audio->frames());
+}
+
struct QueueSorter
{
- bool operator() (pair<shared_ptr<EncodedData>, int> const & a, pair<shared_ptr<EncodedData>, int> const & b) {
+ bool operator() (pair<shared_ptr<const EncodedData>, int> const & a, pair<shared_ptr<const EncodedData>, int> const & b) {
return a.second < b.second;
}
};
@@ -94,7 +116,7 @@ Writer::thread ()
/* Write any frames that we can write; i.e. those that are in sequence */
while (!_queue.empty() && _queue.front().second == (_last_written_frame + 1)) {
- pair<boost::shared_ptr<EncodedData>, int> encoded = _queue.front ();
+ pair<boost::shared_ptr<const EncodedData>, int> encoded = _queue.front ();
_queue.pop_front ();
lock.unlock ();
@@ -115,7 +137,7 @@ Writer::thread ()
Put some to disk.
*/
- pair<boost::shared_ptr<EncodedData>, int> encoded = _queue.back ();
+ pair<boost::shared_ptr<const EncodedData>, int> encoded = _queue.back ();
_queue.pop_back ();
if (!encoded.first) {
/* This is a `repeat-last' frame, so no need to write it to disk */
@@ -138,7 +160,7 @@ Writer::thread ()
lock.unlock ();
_film->log()->log (String::compose ("Writer pulls %1 back from disk", fetch));
- shared_ptr<EncodedData> encoded;
+ shared_ptr<const EncodedData> encoded;
if (boost::filesystem::exists (_film->frame_out_path (fetch, false))) {
/* It's an actual frame (not a repeat-last); load it in */
encoded.reset (new EncodedData (_film->frame_out_path (fetch, false)));
@@ -169,6 +191,7 @@ Writer::finish ()
_thread = 0;
_picture_asset_writer->finalize ();
+ _sound_asset_writer->finalize ();
}
/** Tell the writer that frame `f' should be a repeat of the frame before it */
@@ -176,5 +199,5 @@ void
Writer::repeat (int f)
{
boost::mutex::scoped_lock lock (_mutex);
- _queue.push_back (make_pair (shared_ptr<EncodedData> (), f));
+ _queue.push_back (make_pair (shared_ptr<const EncodedData> (), f));
}
diff --git a/src/lib/writer.h b/src/lib/writer.h
index 8156308a6..77f98f160 100644
--- a/src/lib/writer.h
+++ b/src/lib/writer.h
@@ -24,10 +24,13 @@
class Film;
class EncodedData;
+class AudioBuffers;
namespace libdcp {
class MonoPictureAsset;
class MonoPictureAssetWriter;
+ class SoundAsset;
+ class SoundAssetWriter;
}
class Writer
@@ -35,7 +38,8 @@ class Writer
public:
Writer (boost::shared_ptr<const Film>);
- void write (boost::shared_ptr<EncodedData>, int);
+ void write (boost::shared_ptr<const EncodedData>, int);
+ void write (boost::shared_ptr<const AudioBuffers>);
void repeat (int f);
void finish ();
@@ -47,14 +51,16 @@ private:
boost::thread* _thread;
bool _finish;
- std::list<std::pair<boost::shared_ptr<EncodedData>, int> > _queue;
+ std::list<std::pair<boost::shared_ptr<const EncodedData>, int> > _queue;
mutable boost::mutex _mutex;
boost::condition _condition;
- boost::shared_ptr<EncodedData> _last_written;
+ boost::shared_ptr<const EncodedData> _last_written;
std::list<int> _pending;
int _last_written_frame;
static const unsigned int _maximum_frames_in_memory;
boost::shared_ptr<libdcp::MonoPictureAsset> _picture_asset;
boost::shared_ptr<libdcp::MonoPictureAssetWriter> _picture_asset_writer;
+ boost::shared_ptr<libdcp::SoundAsset> _sound_asset;
+ boost::shared_ptr<libdcp::SoundAssetWriter> _sound_asset_writer;
};