diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-01-18 21:49:49 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-01-18 21:49:49 +0000 |
| commit | 5e4ab7ebd9a6b62b64fbaf91d7aa1a2a9d4bdec4 (patch) | |
| tree | cf863264ba3cd7cab9b6c65a0c821650534f537c /src/lib | |
| parent | 940b64c80c8ed5d434de596d77fdb31762e3fbb3 (diff) | |
Untested direct write of audio to MXF.
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/dcp_video_frame.cc | 2 | ||||
| -rw-r--r-- | src/lib/dcp_video_frame.h | 2 | ||||
| -rw-r--r-- | src/lib/encoder.cc | 59 | ||||
| -rw-r--r-- | src/lib/encoder.h | 8 | ||||
| -rw-r--r-- | src/lib/writer.cc | 35 | ||||
| -rw-r--r-- | src/lib/writer.h | 12 |
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; }; |
