Export CmdPipeWriter: add option to use tmpfile
Investigate issues with mp3 export (#9193)
This commit is contained in:
parent
d1b72b28ec
commit
b8d07b8be2
|
@ -24,6 +24,9 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include "pbd/gstdio_compat.h"
|
||||||
|
|
||||||
#include <glibmm/convert.h>
|
#include <glibmm/convert.h>
|
||||||
#include <glibmm/miscutils.h>
|
#include <glibmm/miscutils.h>
|
||||||
#include <glibmm/timer.h>
|
#include <glibmm/timer.h>
|
||||||
|
@ -376,6 +379,20 @@ ExportGraphBuilder::Encoder::init_writer (boost::shared_ptr<AudioGrapher::CmdPip
|
||||||
|
|
||||||
int quality = config.format->codec_quality ();
|
int quality = config.format->codec_quality ();
|
||||||
|
|
||||||
|
gchar* tmpfile_name = NULL;
|
||||||
|
#if 0
|
||||||
|
gint fd = -1;
|
||||||
|
#else // write to tmp-file, do not pipe to ffmpeg
|
||||||
|
gint fd = g_file_open_tmp ("ardour-export.XXXXXX", &tmpfile_name, NULL);
|
||||||
|
if (fd < 0) {
|
||||||
|
tmpfile_name = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Note mp3 encoding adds silence at start and end
|
||||||
|
* https://lame.sourceforge.io/tech-FAQ.txt
|
||||||
|
*/
|
||||||
|
|
||||||
int a=0;
|
int a=0;
|
||||||
char **argp = (char**) calloc (100, sizeof(char*));
|
char **argp = (char**) calloc (100, sizeof(char*));
|
||||||
char tmp[64];
|
char tmp[64];
|
||||||
|
@ -397,7 +414,11 @@ ExportGraphBuilder::Encoder::init_writer (boost::shared_ptr<AudioGrapher::CmdPip
|
||||||
snprintf (tmp, sizeof(tmp), "%d", config.format->sample_rate());
|
snprintf (tmp, sizeof(tmp), "%d", config.format->sample_rate());
|
||||||
argp[a++] = strdup (tmp);
|
argp[a++] = strdup (tmp);
|
||||||
argp[a++] = strdup ("-i");
|
argp[a++] = strdup ("-i");
|
||||||
argp[a++] = strdup ("pipe:0");
|
if (fd >= 0) {
|
||||||
|
argp[a++] = strdup (tmpfile_name);
|
||||||
|
} else {
|
||||||
|
argp[a++] = strdup ("pipe:0");
|
||||||
|
}
|
||||||
|
|
||||||
argp[a++] = strdup ("-f");
|
argp[a++] = strdup ("-f");
|
||||||
argp[a++] = strdup ("mp3");
|
argp[a++] = strdup ("mp3");
|
||||||
|
@ -445,7 +466,7 @@ ExportGraphBuilder::Encoder::init_writer (boost::shared_ptr<AudioGrapher::CmdPip
|
||||||
ARDOUR::SystemExec* exec = new ARDOUR::SystemExec (ffmpeg_exe, argp, true);
|
ARDOUR::SystemExec* exec = new ARDOUR::SystemExec (ffmpeg_exe, argp, true);
|
||||||
|
|
||||||
PBD::info << "Encode command: { " << exec->to_s () << "}" << endmsg;
|
PBD::info << "Encode command: { " << exec->to_s () << "}" << endmsg;
|
||||||
writer.reset (new AudioGrapher::CmdPipeWriter<T> (exec, writer_filename, false));
|
writer.reset (new AudioGrapher::CmdPipeWriter<T> (exec, writer_filename, fd, tmpfile_name));
|
||||||
writer->FileWritten.connect_same_thread (copy_files_connection, boost::bind (&ExportGraphBuilder::Encoder::copy_files, this, _1));
|
writer->FileWritten.connect_same_thread (copy_files_connection, boost::bind (&ExportGraphBuilder::Encoder::copy_files, this, _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,37 +29,32 @@ class CmdPipeWriter
|
||||||
, public FlagDebuggable<>
|
, public FlagDebuggable<>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CmdPipeWriter (ARDOUR::SystemExec* proc, std::string const& path, bool pipe1)
|
CmdPipeWriter (ARDOUR::SystemExec* proc, std::string const& path, int tmp_fd = -1, gchar* tmp_file = 0)
|
||||||
: samples_written (0)
|
: samples_written (0)
|
||||||
, _proc (proc)
|
, _proc (proc)
|
||||||
, _path (path)
|
, _path (path)
|
||||||
, encoder_file (0)
|
, _tmp_fd (tmp_fd)
|
||||||
|
, _tmp_file (tmp_file)
|
||||||
{
|
{
|
||||||
add_supported_flag (ProcessContext<T>::EndOfInput);
|
add_supported_flag (ProcessContext<T>::EndOfInput);
|
||||||
|
|
||||||
if (pipe1) {
|
if (tmp_fd >= 0) {
|
||||||
proc->ReadStdout.connect_same_thread (exec_connections, boost::bind (&CmdPipeWriter::write_ffile, this, _1, _2));
|
;
|
||||||
proc->Terminated.connect_same_thread (exec_connections, boost::bind (&CmdPipeWriter::close_ffile, this));
|
} else if (proc->start (ARDOUR::SystemExec::ShareWithParent)) {
|
||||||
|
|
||||||
encoder_file = g_fopen (path.c_str(), "wb");
|
|
||||||
|
|
||||||
if (!encoder_file) {
|
|
||||||
throw ARDOUR::ExportFailed ("Output file cannot be written to.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proc->start (ARDOUR::SystemExec::IgnoreAndClose)) {
|
|
||||||
if (encoder_file) {
|
|
||||||
fclose (encoder_file);
|
|
||||||
encoder_file = 0;
|
|
||||||
g_unlink (path.c_str());
|
|
||||||
}
|
|
||||||
throw ARDOUR::ExportFailed ("External encoder (ffmpeg) cannot be started.");
|
throw ARDOUR::ExportFailed ("External encoder (ffmpeg) cannot be started.");
|
||||||
}
|
}
|
||||||
|
proc->Terminated.connect_same_thread (exec_connections, boost::bind (&CmdPipeWriter::encode_complete, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~CmdPipeWriter () {
|
virtual ~CmdPipeWriter () {
|
||||||
delete _proc;
|
delete _proc;
|
||||||
|
if (_tmp_fd >= 0) {
|
||||||
|
::close (_tmp_fd);
|
||||||
|
}
|
||||||
|
if (_tmp_file) {
|
||||||
|
g_unlink (_tmp_file);
|
||||||
|
g_free (_tmp_file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
samplecnt_t get_samples_written() const { return samples_written; }
|
samplecnt_t get_samples_written() const { return samples_written; }
|
||||||
|
@ -74,13 +69,19 @@ public:
|
||||||
{
|
{
|
||||||
check_flags (*this, c);
|
check_flags (*this, c);
|
||||||
|
|
||||||
if (!_proc || !_proc->is_running()) {
|
if (_tmp_fd < 0 && (!_proc || !_proc->is_running())) {
|
||||||
throw Exception (*this, boost::str (boost::format
|
throw Exception (*this, boost::str (boost::format
|
||||||
("Target encoder process is not running")));
|
("Target encoder process is not running")));
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t bytes_per_sample = sizeof (T);
|
const size_t bytes_per_sample = sizeof (T);
|
||||||
samplecnt_t const written = _proc->write_to_stdin ((const void*) c.data(), c.samples() * bytes_per_sample) / bytes_per_sample;
|
samplecnt_t written;
|
||||||
|
if (_tmp_fd >= 0) {
|
||||||
|
written = write (_tmp_fd, (const void*) c.data(), c.samples() * bytes_per_sample) / bytes_per_sample;
|
||||||
|
} else {
|
||||||
|
written = _proc->write_to_stdin ((const void*) c.data(), c.samples() * bytes_per_sample) / bytes_per_sample;
|
||||||
|
}
|
||||||
|
|
||||||
samples_written += written;
|
samples_written += written;
|
||||||
|
|
||||||
if (throw_level (ThrowProcess) && written != c.samples()) {
|
if (throw_level (ThrowProcess) && written != c.samples()) {
|
||||||
|
@ -89,17 +90,16 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.has_flag(ProcessContext<T>::EndOfInput)) {
|
if (c.has_flag(ProcessContext<T>::EndOfInput)) {
|
||||||
if (encoder_file) {
|
if (_tmp_fd >= 0) {
|
||||||
_proc->close_stdin ();
|
::close (_tmp_fd);
|
||||||
_proc->wait ();
|
_tmp_fd = -1;
|
||||||
int timeout = 500;
|
if (_proc->start (ARDOUR::SystemExec::ShareWithParent)) {
|
||||||
while (encoder_file && --timeout) {
|
throw ARDOUR::ExportFailed ("External encoder (ffmpeg) cannot be started.");
|
||||||
Glib::usleep(10000);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_proc->close_stdin ();
|
_proc->close_stdin ();
|
||||||
FileWritten (_path);
|
|
||||||
}
|
}
|
||||||
|
_proc->wait ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,18 +111,18 @@ private:
|
||||||
CmdPipeWriter (CmdPipeWriter const & other) {}
|
CmdPipeWriter (CmdPipeWriter const & other) {}
|
||||||
|
|
||||||
samplecnt_t samples_written;
|
samplecnt_t samples_written;
|
||||||
PBD::SystemExec* _proc;
|
ARDOUR::SystemExec* _proc;
|
||||||
std::string _path;
|
std::string _path;
|
||||||
|
std::vector<char> _tmpfile_path_buf;
|
||||||
|
int _tmp_fd;
|
||||||
|
gchar* _tmp_file;
|
||||||
|
|
||||||
FILE* encoder_file;
|
void encode_complete () {
|
||||||
|
if (_tmp_file) {
|
||||||
void write_ffile (std::string d, size_t s) {
|
g_unlink (_tmp_file);
|
||||||
fwrite (d.c_str(), sizeof(char), s, encoder_file);
|
g_free (_tmp_file);
|
||||||
}
|
_tmp_file = NULL;
|
||||||
|
}
|
||||||
void close_ffile () {
|
|
||||||
fclose (encoder_file);
|
|
||||||
encoder_file = 0;
|
|
||||||
FileWritten (_path);
|
FileWritten (_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user