diff options
-rw-r--r-- | libs/ardour/ardour/export_format_base.h | 6 | ||||
-rw-r--r-- | libs/ardour/ardour/export_formats.h | 11 | ||||
-rw-r--r-- | libs/ardour/ardour/export_graph_builder.h | 6 | ||||
-rw-r--r-- | libs/ardour/enums.cc | 2 | ||||
-rw-r--r-- | libs/ardour/export_format_manager.cc | 7 | ||||
-rw-r--r-- | libs/ardour/export_formats.cc | 33 | ||||
-rw-r--r-- | libs/ardour/export_graph_builder.cc | 81 | ||||
-rw-r--r-- | libs/ardour/export_profile_manager.cc | 2 |
8 files changed, 144 insertions, 4 deletions
diff --git a/libs/ardour/ardour/export_format_base.h b/libs/ardour/ardour/export_format_base.h index ee2739eee1..04566f081e 100644 --- a/libs/ardour/ardour/export_format_base.h +++ b/libs/ardour/ardour/export_format_base.h @@ -43,7 +43,8 @@ class LIBARDOUR_API ExportFormatBase { enum Type { T_None = 0, - T_Sndfile + T_Sndfile, + T_FFMPEG }; enum FormatId { @@ -56,7 +57,8 @@ class LIBARDOUR_API ExportFormatBase { F_IRCAM = SF_FORMAT_IRCAM, F_RAW = SF_FORMAT_RAW, F_FLAC = SF_FORMAT_FLAC, - F_Ogg = SF_FORMAT_OGG + F_Ogg = SF_FORMAT_OGG, + F_FFMPEG = 0xF10000 }; enum Endianness { diff --git a/libs/ardour/ardour/export_formats.h b/libs/ardour/ardour/export_formats.h index 4c9c205725..8e51827b89 100644 --- a/libs/ardour/ardour/export_formats.h +++ b/libs/ardour/ardour/export_formats.h @@ -210,6 +210,17 @@ class LIBARDOUR_API ExportFormatBWF : public ExportFormat, public HasSampleForma virtual bool has_broadcast_info () const { return true; } }; + +class LIBARDOUR_API ExportFormatFFMPEG : public ExportFormat { + public: + ExportFormatFFMPEG (std::string const& name, std::string const& ext); + ~ExportFormatFFMPEG () {}; + + bool set_compatibility_state (ExportFormatCompatibility const & compatibility); + Type get_type () const { return T_FFMPEG; } + SampleFormat get_explicit_sample_format () const { return SF_Float; } +}; + } // namespace ARDOUR #endif /* __ardour_export_formats__ */ diff --git a/libs/ardour/ardour/export_graph_builder.h b/libs/ardour/ardour/export_graph_builder.h index ebc3fdadfc..00cf8226be 100644 --- a/libs/ardour/ardour/export_graph_builder.h +++ b/libs/ardour/ardour/export_graph_builder.h @@ -39,6 +39,7 @@ namespace AudioGrapher { template <typename T> class SampleFormatConverter; template <typename T> class Interleaver; template <typename T> class SndfileWriter; + template <typename T> class CmdPipeWriter; template <typename T> class SilenceTrimmer; template <typename T> class TmpFile; template <typename T> class Threader; @@ -102,7 +103,11 @@ class LIBARDOUR_API ExportGraphBuilder typedef boost::shared_ptr<AudioGrapher::SndfileWriter<int> > IntWriterPtr; typedef boost::shared_ptr<AudioGrapher::SndfileWriter<short> > ShortWriterPtr; + typedef boost::shared_ptr<AudioGrapher::CmdPipeWriter<Sample> > FloatPipePtr; + template<typename T> void init_writer (boost::shared_ptr<AudioGrapher::SndfileWriter<T> > & writer); + template<typename T> void init_writer (boost::shared_ptr<AudioGrapher::CmdPipeWriter<T> > & writer); + void copy_files (std::string orig_path); FileSpec config; @@ -115,6 +120,7 @@ class LIBARDOUR_API ExportGraphBuilder FloatWriterPtr float_writer; IntWriterPtr int_writer; ShortWriterPtr short_writer; + FloatPipePtr pipe_writer; }; // sample format converter diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc index 853391c3d9..dd7c00f25f 100644 --- a/libs/ardour/enums.cc +++ b/libs/ardour/enums.cc @@ -577,6 +577,7 @@ setup_enum_writer () REGISTER_CLASS_ENUM (ExportFormatBase, T_None); REGISTER_CLASS_ENUM (ExportFormatBase, T_Sndfile); + REGISTER_CLASS_ENUM (ExportFormatBase, T_FFMPEG); REGISTER (_ExportFormatBase_Type); REGISTER_CLASS_ENUM (ExportFormatBase, F_None); @@ -589,6 +590,7 @@ setup_enum_writer () REGISTER_CLASS_ENUM (ExportFormatBase, F_FLAC); REGISTER_CLASS_ENUM (ExportFormatBase, F_Ogg); REGISTER_CLASS_ENUM (ExportFormatBase, F_CAF); + REGISTER_CLASS_ENUM (ExportFormatBase, F_FFMPEG); REGISTER (_ExportFormatBase_FormatId); REGISTER_CLASS_ENUM (ExportFormatBase, E_FileDefault); diff --git a/libs/ardour/export_format_manager.cc b/libs/ardour/export_format_manager.cc index 2b5fc1868b..3581fb890e 100644 --- a/libs/ardour/export_format_manager.cc +++ b/libs/ardour/export_format_manager.cc @@ -19,6 +19,7 @@ */ #include "ardour/export_format_manager.h" +#include "ardour/filesystem_paths.h" #include "ardour/export_format_specification.h" #include "ardour/export_format_compatibility.h" @@ -210,6 +211,12 @@ ExportFormatManager::init_formats () f_ptr.reset (new ExportFormatFLAC ()); add_format (f_ptr); } catch (ExportFormatIncompatible & e) {} + + std::string unused; + if (ArdourVideoToolPaths::transcoder_exe (unused, unused)) { + f_ptr.reset (new ExportFormatFFMPEG ("MP3", "mp3")); + add_format (f_ptr); + } } void diff --git a/libs/ardour/export_formats.cc b/libs/ardour/export_formats.cc index 7fa30c6b51..0ab02046c3 100644 --- a/libs/ardour/export_formats.cc +++ b/libs/ardour/export_formats.cc @@ -365,4 +365,37 @@ ExportFormatBWF::set_compatibility_state (ExportFormatCompatibility const & comp return compatible; } + +/*** FFMPEG Pipe ***/ + +ExportFormatFFMPEG::ExportFormatFFMPEG (std::string const& name, std::string const& ext) +{ + set_name (name); + set_format_id (F_FFMPEG); + sample_formats.insert (SF_Float); + + add_sample_rate (SR_22_05); + add_sample_rate (SR_44_1); + add_sample_rate (SR_48); + add_sample_rate (SR_88_2); + add_sample_rate (SR_96); + add_sample_rate (SR_176_4); + add_sample_rate (SR_192); + add_sample_rate (SR_Session); + + add_endianness (E_Little); + + set_extension (ext); + set_quality (Q_LossyCompression); +} + +bool +ExportFormatFFMPEG::set_compatibility_state (ExportFormatCompatibility const & compatibility) +{ + bool compatible = compatibility.has_format (F_FFMPEG); + set_compatible (compatible); + return compatible; +} + + }; // namespace ARDOUR diff --git a/libs/ardour/export_graph_builder.cc b/libs/ardour/export_graph_builder.cc index b89e73d0ed..b2eaafce21 100644 --- a/libs/ardour/export_graph_builder.cc +++ b/libs/ardour/export_graph_builder.cc @@ -26,6 +26,7 @@ #include "audiographer/process_context.h" #include "audiographer/general/chunker.h" +#include "audiographer/general/cmdpipe_writer.h" #include "audiographer/general/interleaver.h" #include "audiographer/general/normalizer.h" #include "audiographer/general/analyser.h" @@ -42,11 +43,14 @@ #include "ardour/audioengine.h" #include "ardour/export_channel_configuration.h" +#include "ardour/export_failed.h" #include "ardour/export_filename.h" #include "ardour/export_format_specification.h" #include "ardour/export_timespan.h" +#include "ardour/filesystem_paths.h" #include "ardour/session_directory.h" #include "ardour/sndfile_helpers.h" +#include "ardour/system_exec.h" #include "pbd/file_utils.h" #include "pbd/cpus.h" @@ -212,8 +216,13 @@ boost::shared_ptr<AudioGrapher::Sink<Sample> > ExportGraphBuilder::Encoder::init (FileSpec const & new_config) { config = new_config; - init_writer (float_writer); - return float_writer; + if (config.format->format_id() == ExportFormatBase::F_FFMPEG) { + init_writer (pipe_writer); + return pipe_writer; + } else { + init_writer (float_writer); + return float_writer; + } } template <> @@ -257,6 +266,10 @@ ExportGraphBuilder::Encoder::destroy_writer (bool delete_out_file) short_writer->close (); } + if (pipe_writer) { + pipe_writer->close (); + } + if (std::remove(writer_filename.c_str() ) != 0) { std::cout << "Encoder::destroy_writer () : Error removing file: " << strerror(errno) << std::endl; } @@ -265,6 +278,7 @@ ExportGraphBuilder::Encoder::destroy_writer (bool delete_out_file) float_writer.reset (); int_writer.reset (); short_writer.reset (); + pipe_writer.reset (); } bool @@ -293,6 +307,69 @@ ExportGraphBuilder::Encoder::init_writer (boost::shared_ptr<AudioGrapher::Sndfil writer->FileWritten.connect_same_thread (copy_files_connection, boost::bind (&ExportGraphBuilder::Encoder::copy_files, this, _1)); } +template<typename T> +void +ExportGraphBuilder::Encoder::init_writer (boost::shared_ptr<AudioGrapher::CmdPipeWriter<T> > & writer) +{ + unsigned channels = config.channel_config->get_n_chans(); + config.filename->set_channel_config(config.channel_config); + writer_filename = config.filename->get_path (config.format); + + std::string ffmpeg_exe; + std::string unused; + + if (!ArdourVideoToolPaths::transcoder_exe (ffmpeg_exe, unused)) { + throw ExportFailed ("External encoder (ffmpeg) is not available."); + } + + int quality = 3; // TODO get from config.format + + int a=0; + char **argp = (char**) calloc (100, sizeof(char*)); + char tmp[64]; + argp[a++] = strdup(ffmpeg_exe.c_str()); + argp[a++] = strdup ("-f"); + argp[a++] = strdup ("f32le"); + argp[a++] = strdup ("-acodec"); + argp[a++] = strdup ("pcm_f32le"); + argp[a++] = strdup ("-ac"); + snprintf (tmp, sizeof(tmp), "%d", channels); + argp[a++] = strdup (tmp); + argp[a++] = strdup ("-ar"); + snprintf (tmp, sizeof(tmp), "%d", config.format->sample_rate()); + argp[a++] = strdup (tmp); + argp[a++] = strdup ("-i"); + argp[a++] = strdup ("pipe:0"); + + argp[a++] = strdup ("-y"); + if (quality < 10) { + /* variable rate, lower is better */ + snprintf (tmp, sizeof(tmp), "%d", quality); + argp[a++] = strdup ("-q:a"); argp[a++] = strdup (tmp); + } else { + /* fixed bitrate, higher is better */ + snprintf (tmp, sizeof(tmp), "%dk", quality); // eg. "192k" + argp[a++] = strdup ("-b:a"); argp[a++] = strdup (tmp); + } + + /* TODO: add SessionMetadata::Metadata() + * see gtk2_ardour/export_video_dialog.cc + * and gtk2_ardour/transcode_ffmpeg.cc + */ + + argp[a++] = strdup (writer_filename.c_str()); + argp[a] = (char *)0; + + /* argp is free()d in ~SystemExec, + * SystemExec is deleted when writer is destroyed */ + ARDOUR::SystemExec* exec = new ARDOUR::SystemExec (ffmpeg_exe, argp); + if (exec->start(0)) { + throw ExportFailed ("External encoder (ffmpeg) cannot be started."); + } + writer.reset (new AudioGrapher::CmdPipeWriter<T> (exec, writer_filename)); + writer->FileWritten.connect_same_thread (copy_files_connection, boost::bind (&ExportGraphBuilder::Encoder::copy_files, this, _1)); +} + void ExportGraphBuilder::Encoder::copy_files (std::string orig_path) { diff --git a/libs/ardour/export_profile_manager.cc b/libs/ardour/export_profile_manager.cc index f99755e158..28cccde3cd 100644 --- a/libs/ardour/export_profile_manager.cc +++ b/libs/ardour/export_profile_manager.cc @@ -954,6 +954,8 @@ ExportProfileManager::check_format (ExportFormatSpecPtr format, uint32_t channel switch (format->type()) { case ExportFormatBase::T_Sndfile: return check_sndfile_format (format, channels); + case ExportFormatBase::T_FFMPEG: + return true; default: throw ExportFailed (X_("Invalid format given for ExportFileFactory::check!")); |