summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/ardour/ardour/export_format_base.h6
-rw-r--r--libs/ardour/ardour/export_formats.h11
-rw-r--r--libs/ardour/ardour/export_graph_builder.h6
-rw-r--r--libs/ardour/enums.cc2
-rw-r--r--libs/ardour/export_format_manager.cc7
-rw-r--r--libs/ardour/export_formats.cc33
-rw-r--r--libs/ardour/export_graph_builder.cc81
-rw-r--r--libs/ardour/export_profile_manager.cc2
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!"));