Video import/export overhaul and ffmpeg-5.0 compat
* Update commandline parameters for ffmpeg 5.0 * Simplify video-export, allow only standard settings * Check ffmpeg exit code and parse errors * Fix SessionhandleRef on audio-import (clear import status) * Cleanup and reformat sourcecode
This commit is contained in:
parent
391c3e96b3
commit
0b5e502546
|
@ -99,7 +99,8 @@ Editor::embed_audio_from_video (std::string path, samplepos_t n, bool lock_posit
|
||||||
std::string const& gid = ARDOUR::Playlist::generate_pgroup_id ();
|
std::string const& gid = ARDOUR::Playlist::generate_pgroup_id ();
|
||||||
Temporal::timepos_t pos (n);
|
Temporal::timepos_t pos (n);
|
||||||
|
|
||||||
bool ok = (import_sndfiles (paths, Editing::ImportDistinctFiles, Editing::ImportAsTrack, ARDOUR::SrcBest, pos, 1, 1, track, gid, false) == 0);
|
bool ok = import_sndfiles (paths, Editing::ImportDistinctFiles, Editing::ImportAsTrack, ARDOUR::SrcBest, pos, 1, 1, track, gid, false) == 0;
|
||||||
|
import_status.clear();
|
||||||
|
|
||||||
if (ok && track) {
|
if (ok && track) {
|
||||||
if (lock_position_to_video) {
|
if (lock_position_to_video) {
|
||||||
|
@ -110,5 +111,5 @@ Editor::embed_audio_from_video (std::string path, samplepos_t n, bool lock_posit
|
||||||
}
|
}
|
||||||
|
|
||||||
import_status.all_done = true;
|
import_status.all_done = true;
|
||||||
::g_unlink(path.c_str());
|
::g_unlink (path.c_str());
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -22,16 +22,16 @@
|
||||||
|
|
||||||
#include <gtkmm/box.h>
|
#include <gtkmm/box.h>
|
||||||
#include <gtkmm/button.h>
|
#include <gtkmm/button.h>
|
||||||
#include <gtkmm/comboboxtext.h>
|
|
||||||
#include <gtkmm/checkbutton.h>
|
#include <gtkmm/checkbutton.h>
|
||||||
|
#include <gtkmm/comboboxtext.h>
|
||||||
#include <gtkmm/entry.h>
|
#include <gtkmm/entry.h>
|
||||||
#include <gtkmm/label.h>
|
#include <gtkmm/label.h>
|
||||||
#include <gtkmm/progressbar.h>
|
#include <gtkmm/progressbar.h>
|
||||||
|
|
||||||
|
#include "ardour/export_status.h"
|
||||||
#include "ardour/types.h"
|
#include "ardour/types.h"
|
||||||
#include "ardour/template_utils.h"
|
|
||||||
#include "ardour_dialog.h"
|
|
||||||
|
|
||||||
|
#include "ardour_dialog.h"
|
||||||
#include "time_selection.h"
|
#include "time_selection.h"
|
||||||
#include "transcode_ffmpeg.h"
|
#include "transcode_ffmpeg.h"
|
||||||
|
|
||||||
|
@ -42,63 +42,46 @@
|
||||||
* video-encoder presets, progress dialogs and uses
|
* video-encoder presets, progress dialogs and uses
|
||||||
* \ref TranscodeFfmpeg to communicate with ffmpeg.
|
* \ref TranscodeFfmpeg to communicate with ffmpeg.
|
||||||
*/
|
*/
|
||||||
class ExportVideoDialog : public ArdourDialog , public PBD::ScopedConnectionList
|
class ExportVideoDialog : public ArdourDialog, public PBD::ScopedConnectionList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ExportVideoDialog ();
|
ExportVideoDialog ();
|
||||||
~ExportVideoDialog ();
|
~ExportVideoDialog ();
|
||||||
|
|
||||||
std::string get_exported_filename () { return outfn_path_entry.get_text(); }
|
std::string get_exported_filename ()
|
||||||
|
{
|
||||||
void apply_state(TimeSelection &tme, bool range);
|
return outfn_path_entry.get_text ();
|
||||||
|
|
||||||
XMLNode& get_state ();
|
|
||||||
void set_state (const XMLNode &);
|
|
||||||
|
|
||||||
void on_response (int response_id) {
|
|
||||||
Gtk::Dialog::on_response (response_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
void apply_state (TimeSelection& tme, bool range);
|
||||||
TimeSelection export_range;
|
|
||||||
|
XMLNode& get_state ();
|
||||||
|
void set_state (const XMLNode&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
void on_show ();
|
|
||||||
void abort_clicked ();
|
void abort_clicked ();
|
||||||
void launch_export ();
|
void launch_export ();
|
||||||
void encode_pass (int);
|
void encode_video ();
|
||||||
void change_file_extension (std::string);
|
void finished (int);
|
||||||
void width_value_changed ();
|
|
||||||
void height_value_changed ();
|
|
||||||
|
|
||||||
void set_original_file_information ();
|
void set_original_file_information ();
|
||||||
|
void update_progress (ARDOUR::samplecnt_t, ARDOUR::samplecnt_t);
|
||||||
|
gint audio_progress_display ();
|
||||||
|
|
||||||
void open_outfn_dialog ();
|
void open_outfn_dialog ();
|
||||||
void open_invid_dialog ();
|
void open_invid_dialog ();
|
||||||
void scale_checkbox_toggled ();
|
|
||||||
void preset_combo_changed ();
|
|
||||||
void video_codec_combo_changed ();
|
|
||||||
void aspect_checkbox_toggled ();
|
|
||||||
void fps_checkbox_toggled ();
|
|
||||||
|
|
||||||
bool _aborted;
|
bool _aborted;
|
||||||
bool _twopass;
|
|
||||||
bool _firstpass;
|
|
||||||
bool _normalize;
|
bool _normalize;
|
||||||
|
|
||||||
void finished ();
|
|
||||||
void update_progress (ARDOUR::samplecnt_t, ARDOUR::samplecnt_t);
|
|
||||||
|
|
||||||
boost::shared_ptr<ARDOUR::ExportStatus> status;
|
boost::shared_ptr<ARDOUR::ExportStatus> status;
|
||||||
sigc::connection audio_progress_connection;
|
|
||||||
gint audio_progress_display ();
|
|
||||||
float _previous_progress;
|
|
||||||
|
|
||||||
TranscodeFfmpeg *_transcoder;
|
TimeSelection _export_range;
|
||||||
std::string _insnd;
|
sigc::connection _audio_progress_connection;
|
||||||
|
float _previous_progress;
|
||||||
float _video_source_aspect_ratio;
|
TranscodeFfmpeg* _transcoder;
|
||||||
bool _suspend_signals;
|
std::string _insnd;
|
||||||
bool _suspend_dirty;
|
|
||||||
|
|
||||||
Gtk::Label outfn_path_label;
|
Gtk::Label outfn_path_label;
|
||||||
Gtk::Entry outfn_path_entry;
|
Gtk::Entry outfn_path_entry;
|
||||||
|
@ -109,40 +92,16 @@ private:
|
||||||
Gtk::ComboBoxText insnd_combo;
|
Gtk::ComboBoxText insnd_combo;
|
||||||
Gtk::Button transcode_button;
|
Gtk::Button transcode_button;
|
||||||
|
|
||||||
Gtk::VBox* vbox;
|
Gtk::VBox* vbox;
|
||||||
Gtk::Button *cancel_button;
|
Gtk::Button* cancel_button;
|
||||||
Gtk::Button abort_button;
|
Gtk::Button abort_button;
|
||||||
|
|
||||||
Gtk::VBox* progress_box;
|
Gtk::VBox* progress_box;
|
||||||
Gtk::ProgressBar pbar;
|
Gtk::ProgressBar pbar;
|
||||||
|
|
||||||
Gtk::ComboBoxText audio_codec_combo;
|
Gtk::CheckButton normalize_checkbox;
|
||||||
Gtk::ComboBoxText video_codec_combo;
|
Gtk::CheckButton meta_checkbox;
|
||||||
Gtk::ComboBoxText video_bitrate_combo;
|
Gtk::CheckButton debug_checkbox;
|
||||||
Gtk::ComboBoxText audio_bitrate_combo;
|
|
||||||
Gtk::ComboBoxText audio_samplerate_combo;
|
|
||||||
Gtk::ComboBoxText preset_combo;
|
|
||||||
|
|
||||||
Gtk::CheckButton scale_checkbox;
|
|
||||||
Gtk::CheckButton scale_aspect;
|
|
||||||
Gtk::Adjustment width_adjustment;
|
|
||||||
Gtk::SpinButton width_spinner;
|
|
||||||
Gtk::Adjustment height_adjustment;
|
|
||||||
Gtk::SpinButton height_spinner;
|
|
||||||
Gtk::CheckButton aspect_checkbox;
|
|
||||||
Gtk::ComboBoxText aspect_combo;
|
|
||||||
Gtk::CheckButton normalize_checkbox;
|
|
||||||
Gtk::CheckButton twopass_checkbox;
|
|
||||||
Gtk::CheckButton optimizations_checkbox;
|
|
||||||
Gtk::Label optimizations_label;
|
|
||||||
Gtk::CheckButton deinterlace_checkbox;
|
|
||||||
Gtk::CheckButton bframes_checkbox;
|
|
||||||
Gtk::CheckButton fps_checkbox;
|
|
||||||
Gtk::ComboBoxText fps_combo;
|
|
||||||
Gtk::CheckButton meta_checkbox;
|
|
||||||
#if 1 /* tentative debug mode */
|
|
||||||
Gtk::CheckButton debug_checkbox;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __gtk_ardour_export_video_dialog_h__ */
|
#endif /* __gtk_ardour_export_video_dialog_h__ */
|
||||||
|
|
|
@ -18,15 +18,15 @@
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
#include <sstream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sstream>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "pbd/error.h"
|
|
||||||
#include "pbd/convert.h"
|
|
||||||
#include "pbd/file_utils.h"
|
|
||||||
#include "gui_thread.h"
|
#include "gui_thread.h"
|
||||||
|
#include "pbd/convert.h"
|
||||||
|
#include "pbd/error.h"
|
||||||
|
#include "pbd/file_utils.h"
|
||||||
|
|
||||||
#include "ardour/filesystem_paths.h"
|
#include "ardour/filesystem_paths.h"
|
||||||
|
|
||||||
|
@ -39,178 +39,175 @@ using namespace PBD;
|
||||||
using namespace VideoUtils;
|
using namespace VideoUtils;
|
||||||
|
|
||||||
TranscodeFfmpeg::TranscodeFfmpeg (std::string f)
|
TranscodeFfmpeg::TranscodeFfmpeg (std::string f)
|
||||||
: infile(f)
|
: infile (f)
|
||||||
{
|
{
|
||||||
probeok = false;
|
probeok = false;
|
||||||
ffexecok = false;
|
ffexecok = false;
|
||||||
m_duration = 0;
|
m_duration = 0;
|
||||||
m_avoffset = m_lead_in = m_lead_out = 0;
|
m_avoffset = m_lead_in = m_lead_out = 0;
|
||||||
m_width = m_height = 0;
|
m_width = m_height = 0;
|
||||||
m_aspect = m_fps = 0;
|
m_aspect = m_fps = 0;
|
||||||
m_sar = "";
|
m_sar = "";
|
||||||
#if 1 /* tentative debug mode */
|
debug_enable = false;
|
||||||
debug_enable = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!ARDOUR::ArdourVideoToolPaths::transcoder_exe(ffmpeg_exe, ffprobe_exe)) {
|
if (!ARDOUR::ArdourVideoToolPaths::transcoder_exe (ffmpeg_exe, ffprobe_exe)) {
|
||||||
warning << string_compose(
|
warning << string_compose (_("ffmpeg installation was not found on this system.\n"
|
||||||
_(
|
"%1 requires ffmpeg and ffprobe from ffmpeg.org - version 1.1 or newer.\n"
|
||||||
"ffmpeg installation was not found on this system.\n"
|
"Video import and export is not possible until you install tools.\n"
|
||||||
"%1 requires ffmpeg and ffprobe from ffmpeg.org - version 1.1 or newer.\n"
|
"\n"
|
||||||
"Video import and export is not possible until you install tools.\n"
|
"The tools are included with the %1 releases from ardour.org "
|
||||||
"\n"
|
"and also available with the video-server at http://x42.github.com/harvid/\n"
|
||||||
"The tools are included with the %1 releases from ardour.org "
|
"\n"
|
||||||
"and also available with the video-server at http://x42.github.com/harvid/\n"
|
"Important: the files need to be installed in $PATH and named ffmpeg_harvid and ffprobe_harvid.\n"
|
||||||
"\n"
|
"If you already have a suitable ffmpeg installation on your system, we recommend creating "
|
||||||
"Important: the files need to be installed in $PATH and named ffmpeg_harvid and ffprobe_harvid.\n"
|
"symbolic links from ffmpeg to ffmpeg_harvid and from ffprobe to ffprobe_harvid.\n"
|
||||||
"If you already have a suitable ffmpeg installation on your system, we recommend creating "
|
"\n"
|
||||||
"symbolic links from ffmpeg to ffmpeg_harvid and from ffprobe to ffprobe_harvid.\n"
|
"see also http://manual.ardour.org/video-timeline/setup/"),
|
||||||
"\n"
|
PROGRAM_NAME)
|
||||||
"see also http://manual.ardour.org/video-timeline/setup/"
|
<< endmsg;
|
||||||
), PROGRAM_NAME) << endmsg;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ffexecok = true;
|
ffexecok = true;
|
||||||
|
|
||||||
if (infile.empty() || !probe()) {
|
if (infile.empty () || !probe ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
probeok = true;
|
probeok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TranscodeFfmpeg::~TranscodeFfmpeg ()
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TranscodeFfmpeg::probe ()
|
TranscodeFfmpeg::probe ()
|
||||||
{
|
{
|
||||||
ffoutput = "";
|
ffoutput = "";
|
||||||
char **argp;
|
char** argp;
|
||||||
argp=(char**) calloc(7,sizeof(char*));
|
argp = (char**)calloc (7, sizeof (char*));
|
||||||
argp[0] = strdup(ffprobe_exe.c_str());
|
argp[0] = strdup (ffprobe_exe.c_str ());
|
||||||
argp[1] = strdup("-print_format");
|
argp[1] = strdup ("-print_format");
|
||||||
argp[2] = strdup("csv=nk=0");
|
argp[2] = strdup ("csv=nk=0");
|
||||||
argp[3] = strdup("-show_format");
|
argp[3] = strdup ("-show_format");
|
||||||
argp[4] = strdup("-show_streams");
|
argp[4] = strdup ("-show_streams");
|
||||||
argp[5] = strdup(infile.c_str());
|
argp[5] = strdup (infile.c_str ());
|
||||||
argp[6] = 0;
|
argp[6] = 0;
|
||||||
ffcmd = new ARDOUR::SystemExec(ffprobe_exe, argp);
|
ffcmd = new ARDOUR::SystemExec (ffprobe_exe, argp);
|
||||||
ffcmd->ReadStdout.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffprobeparse, this, _1 ,_2));
|
ffcmd->ReadStdout.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffprobeparse, this, _1, _2));
|
||||||
ffcmd->Terminated.connect (*this, invalidator (*this), boost::bind (&TranscodeFfmpeg::ffexit, this), gui_context());
|
ffcmd->Terminated.connect (*this, invalidator (*this), boost::bind (&TranscodeFfmpeg::ffexit, this), gui_context ());
|
||||||
if (ffcmd->start (SystemExec::IgnoreAndClose)) {
|
if (ffcmd->start (SystemExec::IgnoreAndClose)) {
|
||||||
ffexit();
|
ffexit ();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wait for ffprobe process to exit */
|
/* wait for ffprobe process to exit */
|
||||||
ffcmd->wait();
|
ffcmd->wait ();
|
||||||
|
|
||||||
/* wait for interposer thread to copy all data.
|
/* wait for interposer thread to copy all data.
|
||||||
* SystemExec::Terminated is emitted and ffcmd set to NULL */
|
* SystemExec::Terminated is emitted and ffcmd set to NULL */
|
||||||
int timeout = 300; // 1.5 sec
|
int timeout = 300; // 1.5 sec
|
||||||
while (ffcmd && --timeout > 0) {
|
while (ffcmd && --timeout > 0) {
|
||||||
Glib::usleep(5000);
|
Glib::usleep (5000);
|
||||||
ARDOUR::GUIIdle();
|
ARDOUR::GUIIdle ();
|
||||||
}
|
}
|
||||||
if (timeout == 0 || ffoutput.empty()) {
|
if (timeout == 0 || ffoutput.empty ()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse */
|
/* parse */
|
||||||
|
|
||||||
std::vector<std::vector<std::string> > lines;
|
std::vector<std::vector<std::string>> lines;
|
||||||
ParseCSV(ffoutput, lines);
|
ParseCSV (ffoutput, lines);
|
||||||
double timebase = 0;
|
double timebase = 0;
|
||||||
m_width = m_height = 0;
|
m_width = m_height = 0;
|
||||||
m_fps = m_aspect = 0;
|
m_fps = m_aspect = 0;
|
||||||
m_duration = 0;
|
m_duration = 0;
|
||||||
m_sar.clear();
|
m_sar.clear ();
|
||||||
m_codec.clear();
|
m_codec.clear ();
|
||||||
m_audio.clear();
|
m_audio.clear ();
|
||||||
|
|
||||||
#define PARSE_FRACTIONAL_FPS(VAR) \
|
/* clang-format off */
|
||||||
{ \
|
#define PARSE_FRACTIONAL_FPS(VAR) \
|
||||||
std::string::size_type pos; \
|
{ \
|
||||||
VAR = atof(value); \
|
std::string::size_type pos; \
|
||||||
pos = value.find_first_of('/'); \
|
VAR = atof (value); \
|
||||||
if (pos != std::string::npos) { \
|
pos = value.find_first_of ('/'); \
|
||||||
VAR = atof(value.substr(0, pos)) / atof(value.substr(pos+1)); \
|
if (pos != std::string::npos) { \
|
||||||
} \
|
VAR = atof (value.substr (0, pos)) / atof (value.substr (pos + 1)); \
|
||||||
}
|
} \
|
||||||
|
}
|
||||||
|
/* clang-format on */
|
||||||
|
|
||||||
std::string duration_from_format;
|
std::string duration_from_format;
|
||||||
|
|
||||||
for (std::vector<std::vector<std::string> >::iterator i = lines.begin(); i != lines.end(); ++i) {
|
for (std::vector<std::vector<std::string>>::iterator i = lines.begin (); i != lines.end (); ++i) {
|
||||||
if (i->at(0) == X_("format")) {
|
if (i->at (0) == X_("format")) {
|
||||||
/* format,filename,#streams,format-name,format-long-name,start-time,duration,size,bitrate */
|
/* format,filename,#streams,format-name,format-long-name,start-time,duration,size,bitrate */
|
||||||
for (std::vector<std::string>::iterator kv = i->begin(); kv != i->end(); ++kv) {
|
for (std::vector<std::string>::iterator kv = i->begin (); kv != i->end (); ++kv) {
|
||||||
const size_t kvsep = kv->find('=');
|
const size_t kvsep = kv->find ('=');
|
||||||
if(kvsep == std::string::npos) continue;
|
if (kvsep == std::string::npos) {
|
||||||
std::string key = kv->substr(0, kvsep);
|
continue;
|
||||||
std::string value = kv->substr(kvsep + 1);
|
}
|
||||||
|
std::string key = kv->substr (0, kvsep);
|
||||||
|
std::string value = kv->substr (kvsep + 1);
|
||||||
if (key == X_("duration")) {
|
if (key == X_("duration")) {
|
||||||
duration_from_format = value;
|
duration_from_format = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else if (i->at (0) == X_("stream")) {
|
||||||
if (i->at(0) == X_("stream")) {
|
if (i->at (5) == X_("codec_type=video") && m_width == 0) {
|
||||||
if (i->at(5) == X_("codec_type=video") && m_width == 0) {
|
for (std::vector<std::string>::iterator kv = i->begin (); kv != i->end (); ++kv) {
|
||||||
|
const size_t kvsep = kv->find ('=');
|
||||||
for (std::vector<std::string>::iterator kv = i->begin(); kv != i->end(); ++kv) {
|
if (kvsep == std::string::npos)
|
||||||
const size_t kvsep = kv->find('=');
|
continue;
|
||||||
if(kvsep == std::string::npos) continue;
|
std::string key = kv->substr (0, kvsep);
|
||||||
std::string key = kv->substr(0, kvsep);
|
std::string value = kv->substr (kvsep + 1);
|
||||||
std::string value = kv->substr(kvsep + 1);
|
|
||||||
|
|
||||||
if (key == X_("index")) {
|
if (key == X_("index")) {
|
||||||
m_videoidx = atoi(value);
|
m_videoidx = atoi (value);
|
||||||
} else if (key == X_("width")) {
|
} else if (key == X_("width")) {
|
||||||
m_width = atoi(value);
|
m_width = atoi (value);
|
||||||
} else if (key == X_("height")) {
|
} else if (key == X_("height")) {
|
||||||
m_height = atoi(value);
|
m_height = atoi (value);
|
||||||
} else if (key == X_("codec_name")) {
|
} else if (key == X_("codec_name")) {
|
||||||
if (!m_codec.empty()) m_codec += " ";
|
if (!m_codec.empty ()) {
|
||||||
|
m_codec += " ";
|
||||||
|
}
|
||||||
m_codec += value;
|
m_codec += value;
|
||||||
} else if (key == X_("codec_long_name")) {
|
} else if (key == X_("codec_long_name")) {
|
||||||
if (!m_codec.empty()) m_codec += " ";
|
if (!m_codec.empty ()) {
|
||||||
|
m_codec += " ";
|
||||||
|
}
|
||||||
m_codec += "[" + value + "]";
|
m_codec += "[" + value + "]";
|
||||||
} else if (key == X_("codec_tag_string")) {
|
} else if (key == X_("codec_tag_string")) {
|
||||||
if (!m_codec.empty()) m_codec += " ";
|
if (!m_codec.empty ()) {
|
||||||
|
m_codec += " ";
|
||||||
|
}
|
||||||
m_codec += "(" + value + ")";
|
m_codec += "(" + value + ")";
|
||||||
} else if (key == X_("r_frame_rate")) {
|
} else if (key == X_("r_frame_rate")) {
|
||||||
PARSE_FRACTIONAL_FPS(m_fps)
|
PARSE_FRACTIONAL_FPS (m_fps)
|
||||||
} else if (key == X_("avg_frame_rate") && m_fps == 0) {
|
} else if (key == X_("avg_frame_rate") && m_fps == 0) {
|
||||||
PARSE_FRACTIONAL_FPS(m_fps)
|
PARSE_FRACTIONAL_FPS (m_fps)
|
||||||
} else if (key == X_("time_base")) {
|
} else if (key == X_("time_base")) {
|
||||||
PARSE_FRACTIONAL_FPS(timebase)
|
PARSE_FRACTIONAL_FPS (timebase)
|
||||||
} else if (key == X_("timecode") && m_duration == 0 && m_fps > 0) {
|
} else if (key == X_("timecode") && m_duration == 0 && m_fps > 0) {
|
||||||
int h,m,s; char f[32];
|
int h, m, s;
|
||||||
if (sscanf(i->at(16).c_str(), "%d:%d:%d:%32s",&h,&m,&s,f) == 4) {
|
char f[32];
|
||||||
m_duration = (ARDOUR::samplecnt_t) floor(m_fps * (
|
if (sscanf (i->at (16).c_str (), "%d:%d:%d:%32s", &h, &m, &s, f) == 4) {
|
||||||
h * 3600.0
|
m_duration = (ARDOUR::samplecnt_t)floor (m_fps * (h * 3600.0 + m * 60.0 + s * 1.0 + atoi (f) / pow ((double)10, (int)strlen (f))));
|
||||||
+ m * 60.0
|
|
||||||
+ s * 1.0
|
|
||||||
+ atoi(f) / pow((double)10, (int)strlen(f))
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
} else if (key == X_("duration_ts") && m_fps == 0 && timebase !=0 ) {
|
} else if (key == X_("duration_ts") && m_fps == 0 && timebase != 0) {
|
||||||
m_duration = atof(value) * m_fps * timebase;
|
m_duration = atof (value) * m_fps * timebase;
|
||||||
} else if (key == X_("duration") && m_fps != 0 && m_duration == 0) {
|
} else if (key == X_("duration") && m_fps != 0 && m_duration == 0) {
|
||||||
m_duration = atof(value) * m_fps;
|
m_duration = atof (value) * m_fps;
|
||||||
} else if (key == X_("sample_aspect_ratio")) {
|
} else if (key == X_("sample_aspect_ratio")) {
|
||||||
std::string::size_type pos;
|
std::string::size_type pos;
|
||||||
pos = value.find_first_of(':');
|
pos = value.find_first_of (':');
|
||||||
if (pos != std::string::npos && atof(value.substr(pos+1)) != 0) {
|
if (pos != std::string::npos && atof (value.substr (pos + 1)) != 0) {
|
||||||
m_sar = value;
|
m_sar = value;
|
||||||
m_sar.replace(pos, 1, "/");
|
m_sar.replace (pos, 1, "/");
|
||||||
}
|
}
|
||||||
} else if (key == X_("display_aspect_ratio")) {
|
} else if (key == X_("display_aspect_ratio")) {
|
||||||
std::string::size_type pos;
|
std::string::size_type pos;
|
||||||
pos = value.find_first_of(':');
|
pos = value.find_first_of (':');
|
||||||
if (pos != std::string::npos && atof(value.substr(pos+1)) != 0) {
|
if (pos != std::string::npos && atof (value.substr (pos + 1)) != 0) {
|
||||||
m_aspect = atof(value.substr(0, pos)) / atof(value.substr(pos+1));
|
m_aspect = atof (value.substr (0, pos)) / atof (value.substr (pos + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,56 +216,65 @@ TranscodeFfmpeg::probe ()
|
||||||
m_aspect = (double)m_width / (double)m_height;
|
m_aspect = (double)m_width / (double)m_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (i->at(5) == X_("codec_type=audio")) { /* new ffprobe */
|
} else if (i->at (5) == X_("codec_type=audio")) { /* new ffprobe */
|
||||||
FFAudioStream as;
|
FFAudioStream as;
|
||||||
for (std::vector<std::string>::iterator kv = i->begin(); kv != i->end(); ++kv) {
|
for (std::vector<std::string>::iterator kv = i->begin (); kv != i->end (); ++kv) {
|
||||||
const size_t kvsep = kv->find('=');
|
const size_t kvsep = kv->find ('=');
|
||||||
if(kvsep == std::string::npos) continue;
|
if (kvsep == std::string::npos) {
|
||||||
std::string key = kv->substr(0, kvsep);
|
continue;
|
||||||
std::string value = kv->substr(kvsep + 1);
|
}
|
||||||
|
std::string key = kv->substr (0, kvsep);
|
||||||
|
std::string value = kv->substr (kvsep + 1);
|
||||||
|
|
||||||
if (key == X_("channels")) {
|
if (key == X_("channels")) {
|
||||||
as.channels = atoi(value);
|
as.channels = atoi (value);
|
||||||
} else if (key == X_("index")) {
|
} else if (key == X_("index")) {
|
||||||
as.stream_id = value;
|
as.stream_id = value;
|
||||||
} else if (key == X_("codec_long_name")) {
|
} else if (key == X_("codec_long_name")) {
|
||||||
if (!as.name.empty()) as.name += " ";
|
if (!as.name.empty ()) {
|
||||||
|
as.name += " ";
|
||||||
|
}
|
||||||
as.name += value;
|
as.name += value;
|
||||||
} else if (key == X_("codec_name")) {
|
} else if (key == X_("codec_name")) {
|
||||||
if (!as.name.empty()) as.name += " ";
|
if (!as.name.empty ()) {
|
||||||
|
as.name += " ";
|
||||||
|
}
|
||||||
as.name += value;
|
as.name += value;
|
||||||
} else if (key == X_("sample_fmt")) {
|
} else if (key == X_("sample_fmt")) {
|
||||||
if (!as.name.empty()) as.name += " ";
|
if (!as.name.empty ()) {
|
||||||
|
as.name += " ";
|
||||||
|
}
|
||||||
as.name += "FMT:" + value;
|
as.name += "FMT:" + value;
|
||||||
} else if (key == X_("sample_rate")) {
|
} else if (key == X_("sample_rate")) {
|
||||||
if (!as.name.empty()) as.name += " ";
|
if (!as.name.empty ()) {
|
||||||
|
as.name += " ";
|
||||||
|
}
|
||||||
as.name += "SR:" + value;
|
as.name += "SR:" + value;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
m_audio.push_back(as);
|
m_audio.push_back (as);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* end parse */
|
/* end parse */
|
||||||
|
|
||||||
if (m_duration == 0 && !duration_from_format.empty() && m_fps > 0) {
|
if (m_duration == 0 && !duration_from_format.empty () && m_fps > 0) {
|
||||||
warning << "using video-duration from format (container)." << endmsg;
|
warning << "using video-duration from format (container)." << endmsg;
|
||||||
m_duration = atof(duration_from_format) * m_fps;
|
m_duration = atof (duration_from_format) * m_fps;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* DEBUG */
|
#if 0 /* DEBUG */
|
||||||
printf("FPS: %f\n", m_fps);
|
printf ("FPS: %f\n", m_fps);
|
||||||
printf("Duration: %lu frames\n",(unsigned long)m_duration);
|
printf ("Duration: %lu frames\n", (unsigned long)m_duration);
|
||||||
printf("W/H: %ix%i\n",m_width, m_height);
|
printf ("W/H: %ix%i\n", m_width, m_height);
|
||||||
printf("aspect: %f\n",m_aspect);
|
printf ("aspect: %f\n", m_aspect);
|
||||||
printf("codec: %s\n",m_codec.c_str());
|
printf ("codec: %s\n", m_codec.c_str());
|
||||||
if (m_audio.size() > 0) {
|
if (m_audio.size() > 0) {
|
||||||
for (AudioStreams::iterator it = m_audio.begin(); it < m_audio.end(); ++it) {
|
for (AudioStreams::iterator it = m_audio.begin(); it < m_audio.end(); ++it) {
|
||||||
printf("audio: %s - %i channels\n",(*it).stream_id.c_str(), (*it).channels);
|
printf ("audio: %s - %i channels\n",(*it).stream_id.c_str(), (*it).channels);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printf("audio: no audio streams in file.\n");
|
printf ("audio: no audio streams in file.\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -279,11 +285,11 @@ TranscodeFfmpeg::FFSettings
|
||||||
TranscodeFfmpeg::default_encoder_settings ()
|
TranscodeFfmpeg::default_encoder_settings ()
|
||||||
{
|
{
|
||||||
TranscodeFfmpeg::FFSettings ffs;
|
TranscodeFfmpeg::FFSettings ffs;
|
||||||
ffs.clear();
|
ffs.clear ();
|
||||||
ffs["-vcodec"] = "mpeg4";
|
ffs["-vcodec"] = "mpeg4";
|
||||||
ffs["-acodec"] = "ac3";
|
ffs["-acodec"] = "ac3";
|
||||||
ffs["-b:v"] = "5000k";
|
ffs["-b:v"] = "5000k";
|
||||||
ffs["-b:a"] = "160k";
|
ffs["-b:a"] = "160k";
|
||||||
return ffs;
|
return ffs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,39 +297,43 @@ TranscodeFfmpeg::FFSettings
|
||||||
TranscodeFfmpeg::default_meta_data ()
|
TranscodeFfmpeg::default_meta_data ()
|
||||||
{
|
{
|
||||||
TranscodeFfmpeg::FFSettings ffm;
|
TranscodeFfmpeg::FFSettings ffm;
|
||||||
ffm.clear();
|
ffm.clear ();
|
||||||
ffm["comment"] = "Created with " PROGRAM_NAME;
|
ffm["comment"] = "Created with " PROGRAM_NAME;
|
||||||
return ffm;
|
return ffm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TranscodeFfmpeg::encode (std::string outfile, std::string inf_a, std::string inf_v, TranscodeFfmpeg::FFSettings ffs, TranscodeFfmpeg::FFSettings meta, bool map)
|
TranscodeFfmpeg::encode (std::string outfile, std::string inf_a, std::string inf_v, TranscodeFfmpeg::FFSettings ffs, TranscodeFfmpeg::FFSettings meta, bool map)
|
||||||
{
|
{
|
||||||
#define MAX_FFMPEG_ENCODER_ARGS (100)
|
#define MAX_FFMPEG_ENCODER_ARGS (100)
|
||||||
char **argp;
|
int a = 0;
|
||||||
int a=0;
|
|
||||||
|
char** argp = (char**)calloc (MAX_FFMPEG_ENCODER_ARGS, sizeof (char*));
|
||||||
|
argp[a++] = strdup (ffmpeg_exe.c_str ());
|
||||||
|
|
||||||
argp=(char**) calloc(MAX_FFMPEG_ENCODER_ARGS,sizeof(char*));
|
|
||||||
argp[a++] = strdup(ffmpeg_exe.c_str());
|
|
||||||
if (m_avoffset < 0 || m_avoffset > 0) {
|
if (m_avoffset < 0 || m_avoffset > 0) {
|
||||||
std::ostringstream osstream; osstream << m_avoffset;
|
argp[a++] = strdup ("-accurate_seek");
|
||||||
argp[a++] = strdup("-itsoffset");
|
std::ostringstream osstream;
|
||||||
argp[a++] = strdup(osstream.str().c_str());
|
osstream << m_avoffset;
|
||||||
|
argp[a++] = strdup ("-itsoffset");
|
||||||
|
argp[a++] = strdup (osstream.str ().c_str ());
|
||||||
|
argp[a++] = strdup ("-ss");
|
||||||
|
argp[a++] = strdup ("0");
|
||||||
}
|
}
|
||||||
argp[a++] = strdup("-i");
|
|
||||||
argp[a++] = strdup(inf_v.c_str());
|
|
||||||
|
|
||||||
argp[a++] = strdup("-i");
|
argp[a++] = strdup ("-i");
|
||||||
argp[a++] = strdup(inf_a.c_str());
|
argp[a++] = strdup (inf_v.c_str ());
|
||||||
|
|
||||||
for(TranscodeFfmpeg::FFSettings::const_iterator it = ffs.begin(); it != ffs.end(); ++it) {
|
argp[a++] = strdup ("-i");
|
||||||
argp[a++] = strdup(it->first.c_str());
|
argp[a++] = strdup (inf_a.c_str ());
|
||||||
argp[a++] = strdup(it->second.c_str());
|
|
||||||
|
for (TranscodeFfmpeg::FFSettings::const_iterator it = ffs.begin (); it != ffs.end (); ++it) {
|
||||||
|
argp[a++] = strdup (it->first.c_str ());
|
||||||
|
argp[a++] = strdup (it->second.c_str ());
|
||||||
}
|
}
|
||||||
for(TranscodeFfmpeg::FFSettings::const_iterator it = meta.begin(); it != meta.end(); ++it) {
|
for (TranscodeFfmpeg::FFSettings::const_iterator it = meta.begin (); it != meta.end (); ++it) {
|
||||||
argp[a++] = strdup("-metadata");
|
argp[a++] = strdup ("-metadata");
|
||||||
argp[a++] = SystemExec::format_key_value_parameter (it->first.c_str(), it->second.c_str());
|
argp[a++] = SystemExec::format_key_value_parameter (it->first.c_str (), it->second.c_str ());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_fps > 0) {
|
if (m_fps > 0) {
|
||||||
|
@ -333,62 +343,70 @@ TranscodeFfmpeg::encode (std::string outfile, std::string inf_a, std::string inf
|
||||||
|
|
||||||
if (m_lead_in != 0 && m_lead_out != 0) {
|
if (m_lead_in != 0 && m_lead_out != 0) {
|
||||||
std::ostringstream osstream;
|
std::ostringstream osstream;
|
||||||
argp[a++] = strdup("-vf");
|
argp[a++] = strdup ("-vf");
|
||||||
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_in;
|
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_in;
|
||||||
if (!m_sar.empty()) osstream << X_(":sar=") << m_sar;
|
if (!m_sar.empty ()) {
|
||||||
|
osstream << X_(":sar=") << m_sar;
|
||||||
|
}
|
||||||
osstream << X_(" [pre]; ");
|
osstream << X_(" [pre]; ");
|
||||||
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_out;
|
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_out;
|
||||||
if (!m_sar.empty()) osstream << X_(":sar=") << m_sar;
|
if (!m_sar.empty ()) {
|
||||||
|
osstream << X_(":sar=") << m_sar;
|
||||||
|
}
|
||||||
osstream << X_(" [post]; ");
|
osstream << X_(" [post]; ");
|
||||||
osstream << X_("[pre] [in] [post] concat=n=3");
|
osstream << X_("[pre] [in] [post] concat=n=3");
|
||||||
argp[a++] = strdup(osstream.str().c_str());
|
argp[a++] = strdup (osstream.str ().c_str ());
|
||||||
} else if (m_lead_in != 0) {
|
} else if (m_lead_in != 0) {
|
||||||
std::ostringstream osstream;
|
std::ostringstream osstream;
|
||||||
argp[a++] = strdup("-vf");
|
argp[a++] = strdup ("-vf");
|
||||||
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_in;
|
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_in;
|
||||||
if (!m_sar.empty()) osstream << X_(":sar=") << m_sar;
|
if (!m_sar.empty ()) {
|
||||||
|
osstream << X_(":sar=") << m_sar;
|
||||||
|
}
|
||||||
osstream << X_(" [pre]; ");
|
osstream << X_(" [pre]; ");
|
||||||
osstream << X_("[pre] [in] concat=n=2");
|
osstream << X_("[pre] [in] concat=n=2");
|
||||||
argp[a++] = strdup(osstream.str().c_str());
|
argp[a++] = strdup (osstream.str ().c_str ());
|
||||||
} else if (m_lead_out != 0) {
|
} else if (m_lead_out != 0) {
|
||||||
std::ostringstream osstream;
|
std::ostringstream osstream;
|
||||||
argp[a++] = strdup("-vf");
|
argp[a++] = strdup ("-vf");
|
||||||
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_out;
|
osstream << X_("color=c=black:s=") << m_width << X_("x") << m_height << X_(":d=") << m_lead_out;
|
||||||
if (!m_sar.empty()) osstream << X_(":sar=") << m_sar;
|
if (!m_sar.empty ()) {
|
||||||
|
osstream << X_(":sar=") << m_sar;
|
||||||
|
}
|
||||||
osstream << X_(" [post]; ");
|
osstream << X_(" [post]; ");
|
||||||
osstream << X_("[in] [post] concat=n=2");
|
osstream << X_("[in] [post] concat=n=2");
|
||||||
argp[a++] = strdup(osstream.str().c_str());
|
argp[a++] = strdup (osstream.str ().c_str ());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (map) {
|
if (map) {
|
||||||
std::ostringstream osstream;
|
std::ostringstream osstream;
|
||||||
argp[a++] = strdup("-map");
|
argp[a++] = strdup ("-map");
|
||||||
osstream << X_("0:") << m_videoidx;
|
osstream << X_("0:") << m_videoidx;
|
||||||
argp[a++] = strdup(osstream.str().c_str());
|
argp[a++] = strdup (osstream.str ().c_str ());
|
||||||
argp[a++] = strdup("-map");
|
argp[a++] = strdup ("-map");
|
||||||
argp[a++] = strdup("1:0");
|
argp[a++] = strdup ("1:0");
|
||||||
}
|
}
|
||||||
|
|
||||||
argp[a++] = strdup("-y");
|
argp[a++] = strdup ("-y");
|
||||||
argp[a++] = strdup(outfile.c_str());
|
argp[a++] = strdup (outfile.c_str ());
|
||||||
argp[a] = (char *)0;
|
argp[a] = (char*)0;
|
||||||
assert(a<MAX_FFMPEG_ENCODER_ARGS);
|
assert (a < MAX_FFMPEG_ENCODER_ARGS);
|
||||||
/* Note: these are free()d in ~SystemExec */
|
/* Note: these are free()d in ~SystemExec */
|
||||||
#if 1 /* DEBUG */
|
|
||||||
if (debug_enable) { /* tentative debug mode */
|
|
||||||
printf("EXPORT ENCODE:\n");
|
|
||||||
for (int i=0; i< a; ++i) {
|
|
||||||
printf("%s ", argp[i]);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ffcmd = new ARDOUR::SystemExec(ffmpeg_exe, argp);
|
if (debug_enable) {
|
||||||
ffcmd->ReadStdout.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffmpegparse_v, this, _1 ,_2));
|
printf ("EXPORT ENCODE:\n");
|
||||||
ffcmd->Terminated.connect (*this, invalidator (*this), boost::bind (&TranscodeFfmpeg::ffexit, this), gui_context());
|
for (int i = 0; i < a; ++i) {
|
||||||
|
printf ("%s ", argp[i]);
|
||||||
|
}
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
ffcmd = new ARDOUR::SystemExec (ffmpeg_exe, argp);
|
||||||
|
ffcmd->ReadStdout.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffmpegparse_v, this, _1, _2));
|
||||||
|
ffcmd->Terminated.connect (*this, invalidator (*this), boost::bind (&TranscodeFfmpeg::ffexit, this), gui_context ());
|
||||||
|
|
||||||
if (ffcmd->start (SystemExec::MergeWithStdin)) {
|
if (ffcmd->start (SystemExec::MergeWithStdin)) {
|
||||||
ffexit();
|
ffexit ();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -397,106 +415,120 @@ TranscodeFfmpeg::encode (std::string outfile, std::string inf_a, std::string inf
|
||||||
bool
|
bool
|
||||||
TranscodeFfmpeg::extract_audio (std::string outfile, ARDOUR::samplecnt_t /*samplerate*/, unsigned int stream)
|
TranscodeFfmpeg::extract_audio (std::string outfile, ARDOUR::samplecnt_t /*samplerate*/, unsigned int stream)
|
||||||
{
|
{
|
||||||
if (!probeok) return false;
|
if (!probeok || stream >= m_audio.size ()) {
|
||||||
if (stream >= m_audio.size()) return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
char **argp;
|
char** argp;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
argp=(char**) calloc(15,sizeof(char*));
|
argp = (char**)calloc (15, sizeof (char*));
|
||||||
argp[i++] = strdup(ffmpeg_exe.c_str());
|
argp[i++] = strdup (ffmpeg_exe.c_str ());
|
||||||
argp[i++] = strdup("-i");
|
argp[i++] = strdup ("-i");
|
||||||
argp[i++] = strdup(infile.c_str());
|
argp[i++] = strdup (infile.c_str ());
|
||||||
#if 0 /* ffmpeg write original samplerate, use a3/SRC to resample */
|
#if 0 /* ffmpeg write original samplerate, use a3/SRC to resample */
|
||||||
argp[i++] = strdup("-ar");
|
argp[i++] = strdup("-ar");
|
||||||
argp[i] = (char*) calloc(7,sizeof(char)); snprintf(argp[i++], 7, "%"PRId64, samplerate);
|
argp[i] = (char*) calloc(7,sizeof(char)); snprintf(argp[i++], 7, "%"PRId64, samplerate);
|
||||||
#endif
|
#endif
|
||||||
argp[i++] = strdup("-ac");
|
argp[i++] = strdup ("-ac");
|
||||||
argp[i] = (char*) calloc(3,sizeof(char)); snprintf(argp[i++], 3, "%i", m_audio.at(stream).channels);
|
argp[i] = (char*)calloc (3, sizeof (char));
|
||||||
argp[i++] = strdup("-map");
|
snprintf (argp[i++], 3, "%i", m_audio.at (stream).channels);
|
||||||
argp[i] = (char*) calloc(8,sizeof(char)); snprintf(argp[i++], 8, "0:%s", m_audio.at(stream).stream_id.c_str());
|
argp[i++] = strdup ("-map");
|
||||||
argp[i++] = strdup("-vn");
|
argp[i] = (char*)calloc (8, sizeof (char));
|
||||||
argp[i++] = strdup("-acodec");
|
snprintf (argp[i++], 8, "0:%s", m_audio.at (stream).stream_id.c_str ());
|
||||||
argp[i++] = strdup("pcm_f32le");
|
argp[i++] = strdup ("-vn");
|
||||||
argp[i++] = strdup("-y");
|
argp[i++] = strdup ("-acodec");
|
||||||
argp[i++] = strdup(outfile.c_str());
|
argp[i++] = strdup ("pcm_f32le");
|
||||||
argp[i++] = (char *)0;
|
argp[i++] = strdup ("-y");
|
||||||
|
argp[i++] = strdup (outfile.c_str ());
|
||||||
|
argp[i++] = (char*)0;
|
||||||
/* Note: argp is free()d in ~SystemExec */
|
/* Note: argp is free()d in ~SystemExec */
|
||||||
#if 1 /* DEBUG */
|
|
||||||
if (debug_enable) { /* tentative debug mode */
|
|
||||||
printf("EXTRACT AUDIO:\n");
|
|
||||||
for (int i=0; i< 14; ++i) {
|
|
||||||
printf("%s ", argp[i]);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ffcmd = new ARDOUR::SystemExec(ffmpeg_exe, argp);
|
if (debug_enable) {
|
||||||
ffcmd->ReadStdout.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffmpegparse_a, this, _1 ,_2));
|
printf ("EXTRACT AUDIO:\n");
|
||||||
ffcmd->Terminated.connect (*this, invalidator (*this), boost::bind (&TranscodeFfmpeg::ffexit, this), gui_context());
|
for (int i = 0; i < 14; ++i) {
|
||||||
|
printf ("%s ", argp[i]);
|
||||||
|
}
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
ffcmd = new ARDOUR::SystemExec (ffmpeg_exe, argp);
|
||||||
|
ffcmd->ReadStdout.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffmpegparse_a, this, _1, _2));
|
||||||
|
ffcmd->Terminated.connect (*this, invalidator (*this), boost::bind (&TranscodeFfmpeg::ffexit, this), gui_context ());
|
||||||
|
|
||||||
if (ffcmd->start (SystemExec::MergeWithStdin)) {
|
if (ffcmd->start (SystemExec::MergeWithStdin)) {
|
||||||
ffexit();
|
ffexit ();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TranscodeFfmpeg::transcode (std::string outfile, const int outw, const int outh, const int kbitps)
|
TranscodeFfmpeg::transcode (std::string outfile, const int outw, const int outh, const int kbitps)
|
||||||
{
|
{
|
||||||
if (!probeok) return false;
|
if (!probeok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
char **argp;
|
char** argp;
|
||||||
int bitrate = kbitps;
|
int bitrate = kbitps;
|
||||||
int width = outw;
|
int width = outw;
|
||||||
int height = outh;
|
int height = outh;
|
||||||
|
|
||||||
if (width < 1 || width > m_width) { width = m_width; } /* don't allow upscaling */
|
if (width < 1 || width > m_width) {
|
||||||
if (height < 1 || height > m_height) { height = floor(width / m_aspect); }
|
width = m_width;
|
||||||
|
}
|
||||||
|
/* don't allow upscaling */
|
||||||
|
if (height < 1 || height > m_height) {
|
||||||
|
height = floor (width / m_aspect);
|
||||||
|
}
|
||||||
|
|
||||||
if (bitrate == 0) {
|
if (bitrate == 0) {
|
||||||
const double bitperpixel = .7; /* avg quality */
|
const double bitperpixel = .7; /* avg quality */
|
||||||
bitrate = floor(m_fps * width * height * bitperpixel / 10000.0);
|
bitrate = floor (m_fps * width * height * bitperpixel / 10000.0);
|
||||||
} else {
|
} else {
|
||||||
bitrate = bitrate / 10;
|
bitrate = bitrate / 10;
|
||||||
}
|
}
|
||||||
if (bitrate < 10) bitrate = 10;
|
if (bitrate < 10) {
|
||||||
if (bitrate > 1000) bitrate = 1000;
|
bitrate = 10;
|
||||||
|
}
|
||||||
|
if (bitrate > 1000) {
|
||||||
|
bitrate = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
argp=(char**) calloc(16,sizeof(char*));
|
argp = (char**)calloc (15, sizeof (char*));
|
||||||
argp[0] = strdup(ffmpeg_exe.c_str());
|
argp[0] = strdup (ffmpeg_exe.c_str ());
|
||||||
argp[1] = strdup("-i");
|
argp[1] = strdup ("-i");
|
||||||
argp[2] = strdup(infile.c_str());
|
argp[2] = strdup (infile.c_str ());
|
||||||
argp[3] = strdup("-b:v");
|
argp[3] = strdup ("-b:v");
|
||||||
argp[4] = (char*) calloc(7,sizeof(char)); snprintf(argp[4], 7, "%i0k", bitrate);
|
argp[4] = (char*)calloc (7, sizeof (char));
|
||||||
argp[5] = strdup("-s");
|
snprintf (argp[4], 7, "%i0k", bitrate);
|
||||||
argp[6] = (char*) calloc(10,sizeof(char)); snprintf(argp[6], 10, "%ix%i", width, height);
|
argp[5] = strdup ("-s");
|
||||||
argp[7] = strdup("-y");
|
argp[6] = (char*)calloc (10, sizeof (char));
|
||||||
argp[8] = strdup("-vcodec");
|
snprintf (argp[6], 10, "%ix%i", width, height);
|
||||||
argp[9] = strdup("mjpeg");
|
argp[7] = strdup ("-y");
|
||||||
argp[10] = strdup("-an");
|
argp[8] = strdup ("-vcodec");
|
||||||
argp[11] = strdup("-intra");
|
argp[9] = strdup ("mjpeg");
|
||||||
argp[12] = strdup("-g");
|
argp[10] = strdup ("-an");
|
||||||
argp[13] = strdup("1");
|
argp[11] = strdup ("-g");
|
||||||
argp[14] = strdup(outfile.c_str());
|
argp[12] = strdup ("0");
|
||||||
argp[15] = (char *)0;
|
argp[13] = strdup (outfile.c_str ());
|
||||||
|
argp[14] = (char*)0;
|
||||||
/* Note: these are free()d in ~SystemExec */
|
/* Note: these are free()d in ~SystemExec */
|
||||||
#if 1 /* DEBUG */
|
|
||||||
if (debug_enable) { /* tentative debug mode */
|
if (debug_enable) {
|
||||||
printf("TRANSCODE VIDEO:\n");
|
printf ("TRANSCODE VIDEO:\n");
|
||||||
for (int i=0; i< 15; ++i) {
|
for (int i = 0; i < 15; ++i) {
|
||||||
printf("%s ", argp[i]);
|
printf ("%s ", argp[i]);
|
||||||
|
}
|
||||||
|
printf ("\n");
|
||||||
}
|
}
|
||||||
printf("\n");
|
|
||||||
}
|
ffcmd = new ARDOUR::SystemExec (ffmpeg_exe, argp);
|
||||||
#endif
|
ffcmd->ReadStdout.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffmpegparse_v, this, _1, _2));
|
||||||
ffcmd = new ARDOUR::SystemExec(ffmpeg_exe, argp);
|
ffcmd->Terminated.connect (*this, invalidator (*this), boost::bind (&TranscodeFfmpeg::ffexit, this), gui_context ());
|
||||||
ffcmd->ReadStdout.connect_same_thread (*this, boost::bind (&TranscodeFfmpeg::ffmpegparse_v, this, _1 ,_2));
|
|
||||||
ffcmd->Terminated.connect (*this, invalidator (*this), boost::bind (&TranscodeFfmpeg::ffexit, this), gui_context());
|
|
||||||
if (ffcmd->start (SystemExec::MergeWithStdin)) {
|
if (ffcmd->start (SystemExec::MergeWithStdin)) {
|
||||||
ffexit();
|
ffexit ();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -505,75 +537,90 @@ TranscodeFfmpeg::transcode (std::string outfile, const int outw, const int outh,
|
||||||
void
|
void
|
||||||
TranscodeFfmpeg::cancel ()
|
TranscodeFfmpeg::cancel ()
|
||||||
{
|
{
|
||||||
if (!ffcmd || !ffcmd->is_running()) { return;}
|
if (!ffcmd || !ffcmd->is_running ()) {
|
||||||
ffcmd->write_to_stdin("q");
|
return;
|
||||||
#ifdef PLATFORM_WINDOWS
|
}
|
||||||
Sleep(1000);
|
ffcmd->write_to_stdin ("q");
|
||||||
#else
|
Glib::usleep (1000000); /* 1 sec */
|
||||||
sleep (1);
|
|
||||||
#endif
|
|
||||||
if (ffcmd) {
|
if (ffcmd) {
|
||||||
ffcmd->terminate();
|
ffcmd->terminate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TranscodeFfmpeg::ffexit ()
|
TranscodeFfmpeg::ffexit ()
|
||||||
{
|
{
|
||||||
|
int rv = ffcmd->wait ();
|
||||||
delete ffcmd;
|
delete ffcmd;
|
||||||
ffcmd=0;
|
ffcmd = 0;
|
||||||
Finished(); /* EMIT SIGNAL */
|
Finished (rv); /* EMIT SIGNAL */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TranscodeFfmpeg::ffprobeparse (std::string d, size_t /* s */)
|
TranscodeFfmpeg::ffprobeparse (std::string d, size_t /* s */)
|
||||||
{
|
{
|
||||||
ffoutput+=d;
|
ffoutput += d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TranscodeFfmpeg::ffmpegparse_a (std::string d, size_t /* s */)
|
TranscodeFfmpeg::ffmpegparse_a (std::string d, size_t /* s */)
|
||||||
{
|
{
|
||||||
const char *t;
|
const char* t;
|
||||||
int h,m,s; char f[7];
|
int h, m, s;
|
||||||
ARDOUR::samplecnt_t p = -1;
|
char f[7];
|
||||||
|
|
||||||
if (!(t=strstr(d.c_str(), "time="))) { return; }
|
if (!(t = strstr (d.c_str (), "time="))) {
|
||||||
|
Progress (0, 0); /* EMIT SIGNAL */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (sscanf(t+5, "%d:%d:%d.%s",&h,&m,&s,f) == 4) {
|
if (sscanf (t + 5, "%d:%d:%d.%s", &h, &m, &s, f) == 4) {
|
||||||
p = (ARDOUR::samplecnt_t) floor( 100.0 * (
|
ARDOUR::samplecnt_t p;
|
||||||
h * 3600.0
|
p = (ARDOUR::samplecnt_t)floor (100.0 * (h * 3600.0 + m * 60.0 + s * 1.0 + atoi (f) / pow (10.0, (int)strlen (f))));
|
||||||
+ m * 60.0
|
|
||||||
+ s * 1.0
|
|
||||||
+ atoi(f) / pow((double)10, (int)strlen(f))
|
|
||||||
));
|
|
||||||
p = p * m_fps / 100.0;
|
p = p * m_fps / 100.0;
|
||||||
if (p > m_duration ) { p = m_duration; }
|
if (p > m_duration) {
|
||||||
Progress(p, m_duration); /* EMIT SIGNAL */
|
p = m_duration;
|
||||||
|
}
|
||||||
|
Progress (p, m_duration); /* EMIT SIGNAL */
|
||||||
} else {
|
} else {
|
||||||
Progress(0, 0); /* EMIT SIGNAL */
|
Progress (0, 0); /* EMIT SIGNAL */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TranscodeFfmpeg::ffmpegparse_v (std::string d, size_t /* s */)
|
TranscodeFfmpeg::ffmpegparse_v (std::string d, size_t /* s */)
|
||||||
{
|
{
|
||||||
if (strstr(d.c_str(), "ERROR") || strstr(d.c_str(), "Error") || strstr(d.c_str(), "error")) {
|
/* see ffmpeg-src/doc/errno.txt
|
||||||
warning << "ffmpeg-error: " << d << endmsg;
|
* Not all error messages are forwarded to ardour's log,
|
||||||
}
|
* but exit-code other than 0 shows a popup window.
|
||||||
if (strncmp(d.c_str(), "frame=",6)) {
|
*/
|
||||||
#if 1 /* DEBUG */
|
if (strstr (d.c_str (), "No space left on device") || strstr (d.c_str (), "File too large")) {
|
||||||
if (debug_enable) {
|
error << "ffmpeg-error: " << d << endmsg;
|
||||||
d.erase(d.find_last_not_of(" \t\r\n") + 1);
|
|
||||||
printf("ffmpeg: '%s'\n", d.c_str());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ARDOUR::samplecnt_t f = atol(d.substr(6));
|
|
||||||
|
if (strstr (d.c_str (), "ERROR") || strstr (d.c_str (), "Error") || strstr (d.c_str (), "error")) {
|
||||||
|
error << "ffmpeg-error: " << d << endmsg;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (strstr (d.c_str (), "Unrecognized option") || strstr (d.c_str (), "Missing argument") || strstr (d.c_str (), "Invalid argument")) {
|
||||||
|
error << "ffmpeg-error: " << d << endmsg;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp (d.c_str (), "frame=", 6)) {
|
||||||
|
if (debug_enable) {
|
||||||
|
d.erase (d.find_last_not_of (" \t\r\n") + 1);
|
||||||
|
printf ("ffmpeg: '%s'\n", d.c_str ());
|
||||||
|
}
|
||||||
|
Progress (0, 0); /* EMIT SIGNAL */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ARDOUR::samplecnt_t f = atol (d.substr (6));
|
||||||
if (f == 0) {
|
if (f == 0) {
|
||||||
Progress(0, 0); /* EMIT SIGNAL */
|
Progress (0, 0); /* EMIT SIGNAL */
|
||||||
} else {
|
} else {
|
||||||
Progress(f, m_duration); /* EMIT SIGNAL */
|
Progress (f, m_duration); /* EMIT SIGNAL */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,10 @@
|
||||||
#define __ardour_transcode_ffmpeg_h__
|
#define __ardour_transcode_ffmpeg_h__
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "ardour/system_exec.h"
|
#include "ardour/system_exec.h"
|
||||||
#include "ardour/types.h"
|
#include "ardour/types.h"
|
||||||
|
|
||||||
|
|
||||||
/** @class TranscodeFfmpeg
|
/** @class TranscodeFfmpeg
|
||||||
* @brief wrapper around ffmpeg and ffprobe command-line utils
|
* @brief wrapper around ffmpeg and ffprobe command-line utils
|
||||||
*
|
*
|
||||||
|
@ -31,138 +31,175 @@
|
||||||
* transcode video-files and extract aufio tracks and query
|
* transcode video-files and extract aufio tracks and query
|
||||||
* file information.
|
* file information.
|
||||||
*/
|
*/
|
||||||
class TranscodeFfmpeg : public sigc::trackable
|
class TranscodeFfmpeg : public sigc::trackable, public PBD::ScopedConnectionList
|
||||||
, public PBD::ScopedConnectionList
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct FFAudioStream {
|
struct FFAudioStream {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string stream_id;
|
std::string stream_id;
|
||||||
uint32_t channels;
|
uint32_t channels;
|
||||||
};
|
};
|
||||||
typedef std::vector<FFAudioStream> FFAudioStreams;
|
|
||||||
typedef std::map<std::string,std::string> FFSettings;
|
|
||||||
|
|
||||||
|
typedef std::vector<FFAudioStream> FFAudioStreams;
|
||||||
|
typedef std::map<std::string, std::string> FFSettings;
|
||||||
|
|
||||||
/** instantiate a new transcoder. If a file-name is given, the file's
|
/** instantiate a new transcoder. If a file-name is given, the file's
|
||||||
* attributes (fps, duration, geometry etc) are read.
|
* attributes (fps, duration, geometry etc) are read.
|
||||||
*
|
*
|
||||||
* @param f path to the video-file to probe or use as input for \ref extract_audio and \ref transcode .
|
* @param f path to the video-file to probe or use as input for \ref extract_audio and \ref transcode .
|
||||||
*/
|
*/
|
||||||
TranscodeFfmpeg (std::string f);
|
TranscodeFfmpeg (std::string f);
|
||||||
virtual ~TranscodeFfmpeg ();
|
|
||||||
|
|
||||||
/** transcode to (import a video-file)
|
/** transcode to (import a video-file)
|
||||||
*
|
*
|
||||||
* @param outfile full-path (incl. file-extension) of the file to create
|
* @param outfile full-path (incl. file-extension) of the file to create
|
||||||
* @param width video-width, if \c <0 no scaling
|
* @param width video-width, if \c <0 no scaling
|
||||||
* @param height video-height, with \c <0 preserve aspect (\p width \c / \c aspect-ratio)
|
* @param height video-height, with \c <0 preserve aspect (\p width \c / \c aspect-ratio)
|
||||||
* @param kbitps video bitrate, with \c 0 calculate to use 0.7 bits per pixel on average
|
* @param kbitps video bitrate, with \c 0 calculate to use 0.7 bits per pixel on average
|
||||||
* @return \c true if the transcoder process was successfully started.
|
* @return \c true if the transcoder process was successfully started.
|
||||||
*/
|
*/
|
||||||
bool transcode (std::string outfile, const int width=0, const int height=0, const int kbitps =0);
|
bool transcode (std::string outfile, const int width = 0, const int height = 0, const int kbitps = 0);
|
||||||
|
|
||||||
/** Extract an audio track from the given input file to a new 32bit float little-endian PCM WAV file.
|
/** Extract an audio track from the given input file to a new 32bit float little-endian PCM WAV file.
|
||||||
* @param outfile full-path (incl. file-extension) to .wav file to write
|
* @param outfile full-path (incl. file-extension) to .wav file to write
|
||||||
* @param samplerate target samplerate
|
* @param samplerate target samplerate
|
||||||
* @param stream Stream-ID of the audio-track to extract
|
* @param stream Stream-ID of the audio-track to extract
|
||||||
* specified as element-number in \ref get_audio().
|
* specified as element-number in \ref get_audio().
|
||||||
* @return \c true if the transcoder process was successfully started.
|
* @return \c true if the transcoder process was successfully started.
|
||||||
*/
|
*/
|
||||||
bool extract_audio (std::string outfile, ARDOUR::samplecnt_t samplerate, unsigned int stream=0);
|
bool extract_audio (std::string outfile, ARDOUR::samplecnt_t samplerate, unsigned int stream = 0);
|
||||||
|
|
||||||
/** transcode video and mux audio files into a new video-file.
|
/** transcode video and mux audio files into a new video-file.
|
||||||
* @param outfile full-path of output file to create (existing files are overwritten)
|
* @param outfile full-path of output file to create (existing files are overwritten)
|
||||||
* @param inf_a filename of input audio-file
|
* @param inf_a filename of input audio-file
|
||||||
* @param inf_v filename of input video-file
|
* @param inf_v filename of input video-file
|
||||||
* @param ffs additional command-line parameters for 'ffmpeg'. key/value pairs
|
* @param ffs additional command-line parameters for 'ffmpeg'. key/value pairs
|
||||||
* eg ffs["-vcodec"] = "mpeg4"
|
* eg ffs["-vcodec"] = "mpeg4"
|
||||||
* @param meta additional meta-data results in -metadata "<key>"="<value>" command-line
|
* @param meta additional meta-data results in -metadata "<key>"="<value>" command-line
|
||||||
* arguments
|
* arguments
|
||||||
* @param map if set to \c true stream mapping from input streams to output streams is set to use
|
* @param map if set to \c true stream mapping from input streams to output streams is set to use
|
||||||
* only the first available stream from the audio & video file (-map 0.0 -map 1.0).
|
* only the first available stream from the audio & video file (-map 0.0 -map 1.0).
|
||||||
* @return \c true if the encoder process was successfully started.
|
* @return \c true if the encoder process was successfully started.
|
||||||
*/
|
*/
|
||||||
bool encode (std::string outfile, std::string inf_a, std::string inf_v, FFSettings ffs, FFSettings meta, bool map = true);
|
bool encode (std::string outfile, std::string inf_a, std::string inf_v, FFSettings ffs, FFSettings meta, bool map = true);
|
||||||
|
|
||||||
/** @return array with default encoder settings */
|
/** abort any running transcoding process */
|
||||||
FFSettings default_encoder_settings ();
|
void cancel ();
|
||||||
/** @return array with default meta data */
|
|
||||||
FFSettings default_meta_data ();
|
|
||||||
/** abort any running transcoding process */
|
|
||||||
void cancel();
|
|
||||||
/**
|
|
||||||
* @return \c true if the input file was parsed correctly on class creation. */
|
|
||||||
bool probe_ok () { return probeok; }
|
|
||||||
/** @return \c true if the ffmpeg/ffparse executables are avail on this system */
|
|
||||||
bool ffexec_ok () { return ffexecok; }
|
|
||||||
|
|
||||||
/** signal emitted when ffmpeg reports progress updates
|
/** @return array with default encoder settings */
|
||||||
* during \ref encode \ref transcode and \ref extract_audio
|
FFSettings default_encoder_settings ();
|
||||||
* The parameters are current and last video-frame.
|
|
||||||
*/
|
|
||||||
PBD::Signal2<void, ARDOUR::samplecnt_t, ARDOUR::samplecnt_t> Progress;
|
|
||||||
/** signal emitted when the transcoder process terminates. */
|
|
||||||
PBD::Signal0<void> Finished;
|
|
||||||
|
|
||||||
double get_fps () { return m_fps; }
|
/** @return array with default meta data */
|
||||||
double get_aspect () { return m_aspect; }
|
FFSettings default_meta_data ();
|
||||||
int get_width() { return m_width; }
|
|
||||||
int get_height() { return m_height; }
|
|
||||||
ARDOUR::samplecnt_t get_duration() { return m_duration; }
|
|
||||||
std::string get_codec() { return m_codec; }
|
|
||||||
|
|
||||||
FFAudioStreams get_audio() { return m_audio; }
|
/** @return \c true if the input file was parsed correctly on class creation. */
|
||||||
|
bool probe_ok ()
|
||||||
|
{
|
||||||
|
return probeok;
|
||||||
|
}
|
||||||
|
|
||||||
/** override file duration used with the \ref Progress signal.
|
/** @return \c true if the ffmpeg/ffparse executables are avail on this system */
|
||||||
* @param d duration in video-frames = length_in_seconds * get_fps()
|
bool ffexec_ok ()
|
||||||
*/
|
{
|
||||||
void set_duration(ARDOUR::samplecnt_t d) { m_duration = d; }
|
return ffexecok;
|
||||||
|
}
|
||||||
|
|
||||||
/* offset, lead-in/out are in seconds */
|
double get_fps ()
|
||||||
void set_avoffset(double av_offset) { m_avoffset = av_offset; }
|
{
|
||||||
void set_leadinout(double lead_in, double lead_out) { m_lead_in = lead_in; m_lead_out = lead_out; }
|
return m_fps;
|
||||||
|
}
|
||||||
|
|
||||||
void set_fps(double fps) { m_fps = fps; } // on export, used for rounding only.
|
double get_aspect ()
|
||||||
|
{
|
||||||
|
return m_aspect;
|
||||||
|
}
|
||||||
|
|
||||||
#if 1 /* tentative debug mode */
|
int get_width ()
|
||||||
void set_debug (bool onoff) { debug_enable = onoff; }
|
{
|
||||||
#endif
|
return m_width;
|
||||||
protected:
|
}
|
||||||
std::string infile;
|
|
||||||
ARDOUR::SystemExec *ffcmd;
|
|
||||||
|
|
||||||
bool probe ();
|
int get_height ()
|
||||||
|
{
|
||||||
|
return m_height;
|
||||||
|
}
|
||||||
|
|
||||||
double m_fps;
|
ARDOUR::samplecnt_t get_duration ()
|
||||||
double m_aspect;
|
{
|
||||||
std::string m_sar;
|
return m_duration;
|
||||||
ARDOUR::samplecnt_t m_duration;
|
}
|
||||||
int m_width;
|
|
||||||
int m_height;
|
|
||||||
std::string m_codec;
|
|
||||||
|
|
||||||
int m_videoidx;
|
std::string get_codec ()
|
||||||
double m_avoffset;
|
{
|
||||||
double m_lead_in;
|
return m_codec;
|
||||||
double m_lead_out;
|
}
|
||||||
bool ffexecok;
|
|
||||||
bool probeok;
|
|
||||||
|
|
||||||
FFAudioStreams m_audio;
|
FFAudioStreams get_audio ()
|
||||||
|
{
|
||||||
|
return m_audio;
|
||||||
|
}
|
||||||
|
|
||||||
void ffmpegparse_v (std::string d, size_t s);
|
/** override file duration used with the \ref Progress signal.
|
||||||
void ffmpegparse_a (std::string d, size_t s);
|
* @param d duration in video-frames = length_in_seconds * get_fps()
|
||||||
void ffprobeparse (std::string d, size_t s);
|
*/
|
||||||
void ffexit ();
|
void set_duration (ARDOUR::samplecnt_t d)
|
||||||
std::string ffoutput;
|
{
|
||||||
|
m_duration = d;
|
||||||
|
}
|
||||||
|
|
||||||
std::string ffmpeg_exe;
|
/* offset, lead-in/out are in seconds */
|
||||||
std::string ffprobe_exe;
|
void set_avoffset (double av_offset)
|
||||||
#if 1 /* tentative debug mode */
|
{
|
||||||
bool debug_enable;
|
m_avoffset = av_offset;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
void set_leadinout (double lead_in, double lead_out)
|
||||||
|
{
|
||||||
|
m_lead_in = lead_in;
|
||||||
|
m_lead_out = lead_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_debug (bool onoff)
|
||||||
|
{
|
||||||
|
debug_enable = onoff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** signal emitted when ffmpeg reports progress updates
|
||||||
|
* during \ref encode \ref transcode and \ref extract_audio
|
||||||
|
* The parameters are current and last video-frame.
|
||||||
|
*/
|
||||||
|
PBD::Signal2<void, ARDOUR::samplecnt_t, ARDOUR::samplecnt_t> Progress;
|
||||||
|
|
||||||
|
/** signal emitted when the transcoder process terminates. */
|
||||||
|
PBD::Signal1<void, int> Finished;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool probe ();
|
||||||
|
void ffmpegparse_v (std::string d, size_t s);
|
||||||
|
void ffmpegparse_a (std::string d, size_t s);
|
||||||
|
void ffprobeparse (std::string d, size_t s);
|
||||||
|
void ffexit ();
|
||||||
|
|
||||||
|
std::string infile;
|
||||||
|
ARDOUR::SystemExec* ffcmd;
|
||||||
|
double m_fps;
|
||||||
|
double m_aspect;
|
||||||
|
std::string m_sar;
|
||||||
|
ARDOUR::samplecnt_t m_duration;
|
||||||
|
int m_width;
|
||||||
|
int m_height;
|
||||||
|
std::string m_codec;
|
||||||
|
int m_videoidx;
|
||||||
|
double m_avoffset;
|
||||||
|
double m_lead_in;
|
||||||
|
double m_lead_out;
|
||||||
|
bool ffexecok;
|
||||||
|
bool probeok;
|
||||||
|
FFAudioStreams m_audio;
|
||||||
|
std::string ffoutput;
|
||||||
|
std::string ffmpeg_exe;
|
||||||
|
std::string ffprobe_exe;
|
||||||
|
bool debug_enable;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __ardour_transcode_ffmpeg_h__ */
|
#endif /* __ardour_transcode_ffmpeg_h__ */
|
||||||
|
|
|
@ -18,14 +18,14 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <sigc++/bind.h>
|
#include <sigc++/bind.h>
|
||||||
|
|
||||||
|
@ -34,19 +34,20 @@
|
||||||
|
|
||||||
#include "pbd/gstdio_compat.h"
|
#include "pbd/gstdio_compat.h"
|
||||||
|
|
||||||
#include "pbd/error.h"
|
|
||||||
#include "pbd/convert.h"
|
|
||||||
#include "gtkmm2ext/utils.h"
|
|
||||||
#include "ardour/session_directory.h"
|
|
||||||
#include "ardour/profile.h"
|
#include "ardour/profile.h"
|
||||||
#include "ardour/template_utils.h"
|
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
|
#include "ardour/session_directory.h"
|
||||||
|
#include "ardour/template_utils.h"
|
||||||
#include "ardour_ui.h"
|
#include "ardour_ui.h"
|
||||||
|
#include "gtkmm2ext/utils.h"
|
||||||
#include "gui_thread.h"
|
#include "gui_thread.h"
|
||||||
|
#include "pbd/convert.h"
|
||||||
|
#include "pbd/error.h"
|
||||||
|
|
||||||
#include "opts.h"
|
#include "opts.h"
|
||||||
#include "transcode_video_dialog.h"
|
#include "transcode_video_dialog.h"
|
||||||
#include "utils_videotl.h"
|
#include "utils_videotl.h"
|
||||||
|
|
||||||
#include "pbd/i18n.h"
|
#include "pbd/i18n.h"
|
||||||
|
|
||||||
using namespace Gtk;
|
using namespace Gtk;
|
||||||
|
@ -70,16 +71,14 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
|
||||||
, bitrate_checkbox (_("Manual Override"))
|
, bitrate_checkbox (_("Manual Override"))
|
||||||
, bitrate_adjustment (2000, 500, 10000, 10, 100, 0)
|
, bitrate_adjustment (2000, 500, 10000, 10, 100, 0)
|
||||||
, bitrate_spinner (bitrate_adjustment)
|
, bitrate_spinner (bitrate_adjustment)
|
||||||
#if 1 /* tentative debug mode */
|
|
||||||
, debug_checkbox (_("Debug Mode: Print ffmpeg command and output to stdout."))
|
, debug_checkbox (_("Debug Mode: Print ffmpeg command and output to stdout."))
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
set_session (s);
|
set_session (s);
|
||||||
|
|
||||||
transcoder = new TranscodeFfmpeg(infile);
|
transcoder = new TranscodeFfmpeg (infile);
|
||||||
audiofile = "";
|
audiofile = "";
|
||||||
pending_audio_extract = false;
|
pending_audio_extract = false;
|
||||||
aborted = false;
|
aborted = false;
|
||||||
|
|
||||||
set_name ("TranscodeVideoDialog");
|
set_name ("TranscodeVideoDialog");
|
||||||
set_modal (true);
|
set_modal (true);
|
||||||
|
@ -87,24 +86,26 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
|
||||||
set_resizable (false);
|
set_resizable (false);
|
||||||
|
|
||||||
Gtk::Label* l;
|
Gtk::Label* l;
|
||||||
vbox = manage (new VBox);
|
vbox = manage (new VBox);
|
||||||
VBox* options_box = manage (new VBox);
|
VBox* options_box = manage (new VBox);
|
||||||
HBox* path_hbox = manage (new HBox);
|
HBox* path_hbox = manage (new HBox);
|
||||||
|
|
||||||
int w = 0, h = 0;
|
int w = 0, h = 0;
|
||||||
m_aspect = 4.0/3.0;
|
m_aspect = 16.0 / 9.0;
|
||||||
TranscodeFfmpeg::FFAudioStreams as; as.clear();
|
|
||||||
|
TranscodeFfmpeg::FFAudioStreams as;
|
||||||
|
|
||||||
path_hbox->pack_start (path_label, false, false, 3);
|
path_hbox->pack_start (path_label, false, false, 3);
|
||||||
path_hbox->pack_start (path_entry, true, true, 3);
|
path_hbox->pack_start (path_entry, true, true, 3);
|
||||||
path_hbox->pack_start (browse_button, false, false, 3);
|
path_hbox->pack_start (browse_button, false, false, 3);
|
||||||
|
|
||||||
path_entry.set_width_chars(38);
|
height_spinner.set_sensitive (false);
|
||||||
height_spinner.set_sensitive(false);
|
bitrate_spinner.set_sensitive (false);
|
||||||
bitrate_spinner.set_sensitive(false);
|
|
||||||
|
|
||||||
std::string dstdir = video_dest_dir(_session->session_directory().video_path(), video_get_docroot(Config));
|
std::string dstdir = video_dest_dir (_session->session_directory ().video_path (), video_get_docroot (Config));
|
||||||
std::string dstfn = video_dest_file(dstdir, infile);
|
std::string dstfn = video_dest_file (dstdir, infile);
|
||||||
|
|
||||||
|
path_entry.set_width_chars (38);
|
||||||
path_entry.set_text (dstfn);
|
path_entry.set_text (dstfn);
|
||||||
|
|
||||||
l = manage (new Label (_("<b>File Information</b>"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
l = manage (new Label (_("<b>File Information</b>"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||||
|
@ -112,25 +113,24 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
|
||||||
options_box->pack_start (*l, false, true, 4);
|
options_box->pack_start (*l, false, true, 4);
|
||||||
|
|
||||||
bool ffok = false;
|
bool ffok = false;
|
||||||
if (!transcoder->ffexec_ok()) {
|
if (!transcoder->ffexec_ok ()) {
|
||||||
l = manage (new Label (_("ffmpeg installation was not found. Video Import is not possible. See the Log window for more information."), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
l = manage (new Label (_("ffmpeg installation was not found. Video Import is not possible. See the Log window for more information."), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||||
l->set_line_wrap();
|
l->set_line_wrap ();
|
||||||
options_box->pack_start (*l, false, true, 4);
|
options_box->pack_start (*l, false, true, 4);
|
||||||
aspect_checkbox.set_sensitive(false);
|
aspect_checkbox.set_sensitive (false);
|
||||||
bitrate_checkbox.set_sensitive(false);
|
bitrate_checkbox.set_sensitive (false);
|
||||||
}
|
} else if (!transcoder->probe_ok ()) {
|
||||||
else if (!transcoder->probe_ok()) {
|
l = manage (new Label (string_compose (_("File-info can not be read. Most likely '%1' is not a valid video-file or an unsupported video codec or format."), infn), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||||
l = manage (new Label (string_compose(_("File-info can not be read. Most likely '%1' is not a valid video-file or an unsupported video codec or format."), infn), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
|
||||||
options_box->pack_start (*l, false, true, 4);
|
options_box->pack_start (*l, false, true, 4);
|
||||||
aspect_checkbox.set_sensitive(false);
|
aspect_checkbox.set_sensitive (false);
|
||||||
bitrate_checkbox.set_sensitive(false);
|
bitrate_checkbox.set_sensitive (false);
|
||||||
} else {
|
} else {
|
||||||
w = transcoder->get_width();
|
w = transcoder->get_width ();
|
||||||
h = transcoder->get_height();
|
h = transcoder->get_height ();
|
||||||
as = transcoder->get_audio();
|
as = transcoder->get_audio ();
|
||||||
m_aspect = transcoder->get_aspect();
|
m_aspect = transcoder->get_aspect ();
|
||||||
|
|
||||||
if (w > 0 && h > 0 && transcoder->get_fps() > 0 && transcoder->get_duration() > 0) {
|
if (w > 0 && h > 0 && transcoder->get_fps () > 0 && transcoder->get_duration () > 0) {
|
||||||
ffok = true;
|
ffok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,35 +147,35 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
|
||||||
t->attach (*l, 2, 3, 1, 2);
|
t->attach (*l, 2, 3, 1, 2);
|
||||||
|
|
||||||
std::ostringstream osstream;
|
std::ostringstream osstream;
|
||||||
osstream << transcoder->get_fps();
|
osstream << transcoder->get_fps ();
|
||||||
l = manage (new Label (osstream.str(), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
l = manage (new Label (osstream.str (), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||||
t->attach (*l, 1, 2, 0, 1);
|
t->attach (*l, 1, 2, 0, 1);
|
||||||
|
|
||||||
osstream.str("");
|
osstream.str ("");
|
||||||
osstream << w << "x" << h;
|
osstream << w << "x" << h;
|
||||||
l = manage (new Label (osstream.str(), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
l = manage (new Label (osstream.str (), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||||
t->attach (*l, 3, 4, 1, 2);
|
t->attach (*l, 3, 4, 1, 2);
|
||||||
|
|
||||||
osstream.str("");
|
osstream.str ("");
|
||||||
if (transcoder->get_duration() == 0 || transcoder->get_fps() == 0) {
|
if (transcoder->get_duration () == 0 || transcoder->get_fps () == 0) {
|
||||||
osstream << _("??");
|
osstream << _("??");
|
||||||
} else {
|
} else {
|
||||||
unsigned long sec = transcoder->get_duration() / transcoder->get_fps();
|
unsigned long sec = transcoder->get_duration () / transcoder->get_fps ();
|
||||||
osstream << setfill('0') << setw(2);
|
osstream << setfill ('0') << setw (2);
|
||||||
osstream << (sec / 3600) << ":";
|
osstream << (sec / 3600) << ":";
|
||||||
osstream << setfill('0') << setw(2);
|
osstream << setfill ('0') << setw (2);
|
||||||
osstream << ((sec /60 )%60) << ":";
|
osstream << ((sec / 60) % 60) << ":";
|
||||||
osstream << setfill('0') << setw(2);
|
osstream << setfill ('0') << setw (2);
|
||||||
osstream << (sec%60) << ":";
|
osstream << (sec % 60) << ":";
|
||||||
osstream << setfill('0') << setw(2);
|
osstream << setfill ('0') << setw (2);
|
||||||
osstream << (transcoder->get_duration() % (int) floor(transcoder->get_fps()));
|
osstream << (transcoder->get_duration () % (int)floor (transcoder->get_fps ()));
|
||||||
}
|
}
|
||||||
l = manage (new Label (osstream.str(), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
l = manage (new Label (osstream.str (), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||||
t->attach (*l, 3, 4, 0, 1);
|
t->attach (*l, 3, 4, 0, 1);
|
||||||
|
|
||||||
osstream.str("");
|
osstream.str ("");
|
||||||
osstream << transcoder->get_codec();
|
osstream << transcoder->get_codec ();
|
||||||
l = manage (new Label (osstream.str(), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
l = manage (new Label (osstream.str (), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||||
t->attach (*l, 1, 2, 1, 2);
|
t->attach (*l, 1, 2, 1, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,36 +184,36 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
|
||||||
options_box->pack_start (*l, false, true, 4);
|
options_box->pack_start (*l, false, true, 4);
|
||||||
|
|
||||||
if (ffok) {
|
if (ffok) {
|
||||||
video_combo.append_text(_("Reference from Current Location (Previously Transcoded Files Only)"));
|
video_combo.append_text (_("Reference from Current Location (Previously Transcoded Files Only)"));
|
||||||
video_combo.append_text(_("Import/Transcode Video to Session"));
|
video_combo.append_text (_("Import/Transcode Video to Session"));
|
||||||
video_combo.set_active(1);
|
video_combo.set_active (1);
|
||||||
if (as.size() > 0) {
|
if (as.size () > 0) {
|
||||||
video_combo.append_text(_("Do Not Import Video (Audio Import Only)"));
|
video_combo.append_text (_("Do Not Import Video (Audio Import Only)"));
|
||||||
audio_combo.set_sensitive(true);
|
audio_combo.set_sensitive (true);
|
||||||
} else {
|
} else {
|
||||||
audio_combo.set_sensitive(false);
|
audio_combo.set_sensitive (false);
|
||||||
}
|
}
|
||||||
video_combo.set_sensitive(true);
|
video_combo.set_sensitive (true);
|
||||||
transcode_button.set_sensitive(true);
|
transcode_button.set_sensitive (true);
|
||||||
path_entry.set_sensitive (true);
|
path_entry.set_sensitive (true);
|
||||||
browse_button.set_sensitive (true);
|
browse_button.set_sensitive (true);
|
||||||
} else if (as.size() > 0) {
|
} else if (as.size () > 0) {
|
||||||
video_combo.append_text(_("Do Not Import Video (Audio Import Only)"));
|
video_combo.append_text (_("Do Not Import Video (Audio Import Only)"));
|
||||||
video_combo.set_active(0);
|
video_combo.set_active (0);
|
||||||
path_entry.set_text ("");
|
path_entry.set_text ("");
|
||||||
|
|
||||||
video_combo.set_sensitive(false);
|
video_combo.set_sensitive (false);
|
||||||
audio_combo.set_sensitive(true);
|
audio_combo.set_sensitive (true);
|
||||||
transcode_button.set_sensitive(true);
|
transcode_button.set_sensitive (true);
|
||||||
path_entry.set_sensitive (false);
|
path_entry.set_sensitive (false);
|
||||||
browse_button.set_sensitive (false);
|
browse_button.set_sensitive (false);
|
||||||
} else {
|
} else {
|
||||||
video_combo.append_text(_("Do Not Import Video"));
|
video_combo.append_text (_("Do Not Import Video"));
|
||||||
video_combo.set_active(0);
|
video_combo.set_active (0);
|
||||||
path_entry.set_text ("");
|
path_entry.set_text ("");
|
||||||
video_combo.set_sensitive(false);
|
video_combo.set_sensitive (false);
|
||||||
audio_combo.set_sensitive(false);
|
audio_combo.set_sensitive (false);
|
||||||
transcode_button.set_sensitive(false);
|
transcode_button.set_sensitive (false);
|
||||||
path_entry.set_sensitive (false);
|
path_entry.set_sensitive (false);
|
||||||
browse_button.set_sensitive (false);
|
browse_button.set_sensitive (false);
|
||||||
}
|
}
|
||||||
|
@ -230,20 +230,42 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
|
||||||
t->attach (aspect_checkbox, 2, 3, 0, 1);
|
t->attach (aspect_checkbox, 2, 3, 0, 1);
|
||||||
t->attach (height_spinner, 3, 4, 0, 1);
|
t->attach (height_spinner, 3, 4, 0, 1);
|
||||||
|
|
||||||
scale_combo.append_text(_("Original Width"));
|
scale_combo.append_text (_("Original Width"));
|
||||||
if (w > 1920) { scale_combo.append_text("1920 (hd1080)"); }
|
if (w > 1920) {
|
||||||
if (w > 1408) { scale_combo.append_text("1408 (16cif)"); }
|
scale_combo.append_text ("1920 (hd1080)");
|
||||||
if (w > 1280) { scale_combo.append_text("1280 (sxga, hd720)"); }
|
}
|
||||||
if (w > 1024) { scale_combo.append_text("1024 (xga)"); }
|
if (w > 1408) {
|
||||||
if (w > 852) { scale_combo.append_text(" 852 (hd480)"); }
|
scale_combo.append_text ("1408 (16cif)");
|
||||||
if (w > 768) { scale_combo.append_text(" 768 (PAL)"); }
|
}
|
||||||
if (w > 720) { scale_combo.append_text(" 720 (PAL)"); }
|
if (w > 1280) {
|
||||||
if (w > 640) { scale_combo.append_text(" 640 (vga, ega)"); }
|
scale_combo.append_text ("1280 (sxga, hd720)");
|
||||||
if (w > 352) { scale_combo.append_text(" 352 (cif)"); }
|
}
|
||||||
if (w > 320) { scale_combo.append_text(" 320 (cga, qvga)"); }
|
if (w > 1024) {
|
||||||
if (w > 176) { scale_combo.append_text(" 176 (qcif)"); }
|
scale_combo.append_text ("1024 (xga)");
|
||||||
scale_combo.set_active(0);
|
}
|
||||||
height_spinner.set_value(h);
|
if (w > 852) {
|
||||||
|
scale_combo.append_text (" 852 (hd480)");
|
||||||
|
}
|
||||||
|
if (w > 768) {
|
||||||
|
scale_combo.append_text (" 768 (PAL)");
|
||||||
|
}
|
||||||
|
if (w > 720) {
|
||||||
|
scale_combo.append_text (" 720 (PAL)");
|
||||||
|
}
|
||||||
|
if (w > 640) {
|
||||||
|
scale_combo.append_text (" 640 (vga, ega)");
|
||||||
|
}
|
||||||
|
if (w > 352) {
|
||||||
|
scale_combo.append_text (" 352 (cif)");
|
||||||
|
}
|
||||||
|
if (w > 320) {
|
||||||
|
scale_combo.append_text (" 320 (cga, qvga)");
|
||||||
|
}
|
||||||
|
if (w > 176) {
|
||||||
|
scale_combo.append_text (" 176 (qcif)");
|
||||||
|
}
|
||||||
|
scale_combo.set_active (0);
|
||||||
|
height_spinner.set_value (h);
|
||||||
|
|
||||||
l = manage (new Label (_("Bitrate (KBit/s):"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
l = manage (new Label (_("Bitrate (KBit/s):"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||||
t->attach (*l, 0, 1, 1, 2);
|
t->attach (*l, 0, 1, 1, 2);
|
||||||
|
@ -254,52 +276,52 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
|
||||||
t->attach (*l, 0, 1, 2, 3);
|
t->attach (*l, 0, 1, 2, 3);
|
||||||
t->attach (audio_combo, 1, 4, 2, 3);
|
t->attach (audio_combo, 1, 4, 2, 3);
|
||||||
t->attach (ltc_detect, 1, 4, 3, 4);
|
t->attach (ltc_detect, 1, 4, 3, 4);
|
||||||
if (as.size() == 0) {
|
|
||||||
audio_combo.append_text(_("No Audio Track Present"));
|
if (as.size () == 0) {
|
||||||
audio_combo.set_sensitive(false);
|
audio_combo.append_text (_("No Audio Track Present"));
|
||||||
|
audio_combo.set_sensitive (false);
|
||||||
} else {
|
} else {
|
||||||
audio_combo.append_text(_("Do Not Extract Audio"));
|
audio_combo.append_text (_("Do Not Extract Audio"));
|
||||||
for (TranscodeFfmpeg::FFAudioStreams::iterator it = as.begin(); it < as.end(); ++it) {
|
for (TranscodeFfmpeg::FFAudioStreams::iterator it = as.begin (); it < as.end (); ++it) {
|
||||||
audio_combo.append_text((*it).name);
|
audio_combo.append_text ((*it).name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
audio_combo.set_active(0);
|
audio_combo.set_active (0);
|
||||||
ltc_detect.set_sensitive (false);
|
ltc_detect.set_sensitive (false);
|
||||||
|
|
||||||
#if 1 /* tentative debug mode */
|
|
||||||
options_box->pack_start (debug_checkbox, false, true, 4);
|
options_box->pack_start (debug_checkbox, false, true, 4);
|
||||||
#endif
|
|
||||||
|
|
||||||
vbox->pack_start (*path_hbox, false, false);
|
vbox->pack_start (*path_hbox, false, false);
|
||||||
vbox->pack_start (*options_box, false, true);
|
vbox->pack_start (*options_box, false, true);
|
||||||
|
|
||||||
get_vbox()->set_spacing (4);
|
get_vbox ()->set_spacing (4);
|
||||||
get_vbox()->pack_start (*vbox, false, false);
|
get_vbox ()->pack_start (*vbox, false, false);
|
||||||
|
|
||||||
progress_box = manage (new VBox);
|
progress_box = manage (new VBox);
|
||||||
progress_box->set_spacing(6);
|
progress_box->set_spacing (6);
|
||||||
progress_box->pack_start (progress_label, false, false);
|
progress_box->pack_start (progress_label, false, false);
|
||||||
progress_box->pack_start (pbar, false, false);
|
progress_box->pack_start (pbar, false, false);
|
||||||
progress_box->pack_start (abort_button, false, false);
|
progress_box->pack_start (abort_button, false, false);
|
||||||
get_vbox()->pack_start (*progress_box, false, false);
|
get_vbox ()->pack_start (*progress_box, false, false);
|
||||||
|
|
||||||
browse_button.signal_clicked().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::open_browse_dialog));
|
browse_button.signal_clicked ().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::open_browse_dialog));
|
||||||
transcode_button.signal_clicked().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::launch_transcode));
|
transcode_button.signal_clicked ().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::launch_transcode));
|
||||||
abort_button.signal_clicked().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::abort_clicked));
|
abort_button.signal_clicked ().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::abort_clicked));
|
||||||
|
|
||||||
video_combo.signal_changed().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::video_combo_changed));
|
video_combo.signal_changed ().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::video_combo_changed));
|
||||||
audio_combo.signal_changed().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::audio_combo_changed));
|
audio_combo.signal_changed ().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::audio_combo_changed));
|
||||||
scale_combo.signal_changed().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::scale_combo_changed));
|
scale_combo.signal_changed ().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::scale_combo_changed));
|
||||||
aspect_checkbox.signal_toggled().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::aspect_checkbox_toggled));
|
aspect_checkbox.signal_toggled ().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::aspect_checkbox_toggled));
|
||||||
height_spinner.signal_changed().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::update_bitrate));
|
height_spinner.signal_changed ().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::update_bitrate));
|
||||||
bitrate_checkbox.signal_toggled().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::bitrate_checkbox_toggled));
|
bitrate_checkbox.signal_toggled ().connect (sigc::mem_fun (*this, &TranscodeVideoDialog::bitrate_checkbox_toggled));
|
||||||
|
|
||||||
update_bitrate();
|
update_bitrate ();
|
||||||
|
|
||||||
cancel_button = add_button (Stock::CANCEL, RESPONSE_CANCEL);
|
cancel_button = add_button (Stock::CANCEL, RESPONSE_CANCEL);
|
||||||
get_action_area()->pack_start (transcode_button, false, false);
|
get_action_area ()->pack_start (transcode_button, false, false);
|
||||||
|
|
||||||
show_all_children ();
|
show_all_children ();
|
||||||
progress_box->hide();
|
progress_box->hide ();
|
||||||
}
|
}
|
||||||
|
|
||||||
TranscodeVideoDialog::~TranscodeVideoDialog ()
|
TranscodeVideoDialog::~TranscodeVideoDialog ()
|
||||||
|
@ -317,34 +339,37 @@ void
|
||||||
TranscodeVideoDialog::abort_clicked ()
|
TranscodeVideoDialog::abort_clicked ()
|
||||||
{
|
{
|
||||||
aborted = true;
|
aborted = true;
|
||||||
transcoder->cancel();
|
transcoder->cancel ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TranscodeVideoDialog::update_progress (samplecnt_t c, samplecnt_t a)
|
TranscodeVideoDialog::update_progress (samplecnt_t c, samplecnt_t a)
|
||||||
{
|
{
|
||||||
if (a == 0 || c > a) {
|
if (a == 0 || c > a) {
|
||||||
pbar.set_pulse_step(.5);
|
pbar.set_pulse_step (.5);
|
||||||
pbar.pulse();
|
pbar.pulse ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pbar.set_fraction ((double)c / (double) a);
|
pbar.set_fraction ((double)c / (double)a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TranscodeVideoDialog::finished ()
|
TranscodeVideoDialog::finished (int status)
|
||||||
{
|
{
|
||||||
if (aborted) {
|
if (aborted || status != 0) {
|
||||||
::g_unlink(path_entry.get_text().c_str());
|
if (!aborted) {
|
||||||
if (!audiofile.empty()) {
|
ARDOUR_UI::instance ()->popup_error (_("Video transcoding failed."));
|
||||||
::g_unlink(audiofile.c_str());
|
|
||||||
}
|
}
|
||||||
Gtk::Dialog::response(RESPONSE_CANCEL);
|
::g_unlink (path_entry.get_text ().c_str ());
|
||||||
|
if (!audiofile.empty ()) {
|
||||||
|
::g_unlink (audiofile.c_str ());
|
||||||
|
}
|
||||||
|
Gtk::Dialog::response (RESPONSE_CANCEL);
|
||||||
} else {
|
} else {
|
||||||
if (pending_audio_extract) {
|
if (pending_audio_extract) {
|
||||||
StartNextStage();
|
StartNextStage (); /* EMIT SIGNAL */
|
||||||
} else {
|
} else {
|
||||||
Gtk::Dialog::response(RESPONSE_ACCEPT);
|
Gtk::Dialog::response (RESPONSE_ACCEPT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,35 +377,33 @@ TranscodeVideoDialog::finished ()
|
||||||
void
|
void
|
||||||
TranscodeVideoDialog::launch_audioonly ()
|
TranscodeVideoDialog::launch_audioonly ()
|
||||||
{
|
{
|
||||||
if (audio_combo.get_active_row_number() == 0) {
|
if (audio_combo.get_active_row_number () == 0) {
|
||||||
finished();
|
finished (0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dialog_progress_mode();
|
dialog_progress_mode ();
|
||||||
#if 1 /* tentative debug mode */
|
if (debug_checkbox.get_active ()) {
|
||||||
if (debug_checkbox.get_active()) {
|
transcoder->set_debug (true);
|
||||||
transcoder->set_debug(true);
|
|
||||||
}
|
}
|
||||||
#endif
|
transcoder->Progress.connect (*this, invalidator (*this), boost::bind (&TranscodeVideoDialog::update_progress, this, _1, _2), gui_context ());
|
||||||
transcoder->Progress.connect(*this, invalidator (*this), boost::bind (&TranscodeVideoDialog::update_progress , this, _1, _2), gui_context());
|
transcoder->Finished.connect (*this, invalidator (*this), boost::bind (&TranscodeVideoDialog::finished, this, _1), gui_context ());
|
||||||
transcoder->Finished.connect(*this, invalidator (*this), boost::bind (&TranscodeVideoDialog::finished, this), gui_context());
|
launch_extract ();
|
||||||
launch_extract();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TranscodeVideoDialog::launch_extract ()
|
TranscodeVideoDialog::launch_extract ()
|
||||||
{
|
{
|
||||||
audiofile= path_entry.get_text() + ".wav"; /* TODO: mktemp */
|
audiofile = path_entry.get_text () + ".wav"; /* TODO: mktemp */
|
||||||
int audio_stream;
|
|
||||||
pending_audio_extract = false;
|
pending_audio_extract = false;
|
||||||
aborted = false;
|
aborted = false;
|
||||||
audio_stream = audio_combo.get_active_row_number() -1;
|
int audio_stream = audio_combo.get_active_row_number () - 1;
|
||||||
|
|
||||||
progress_label.set_text (_("Extracting Audio.."));
|
progress_label.set_text (_("Extracting Audio.."));
|
||||||
|
|
||||||
if (!transcoder->extract_audio(audiofile, _session->nominal_sample_rate(), audio_stream)) {
|
if (!transcoder->extract_audio (audiofile, _session->nominal_sample_rate (), audio_stream)) {
|
||||||
ARDOUR_UI::instance()->popup_error(_("Audio Extraction Failed."));
|
ARDOUR_UI::instance ()->popup_error (_("Audio Extraction Failed."));
|
||||||
audiofile="";
|
audiofile = "";
|
||||||
Gtk::Dialog::response(RESPONSE_CANCEL);
|
Gtk::Dialog::response (RESPONSE_CANCEL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -388,58 +411,57 @@ TranscodeVideoDialog::launch_extract ()
|
||||||
void
|
void
|
||||||
TranscodeVideoDialog::dialog_progress_mode ()
|
TranscodeVideoDialog::dialog_progress_mode ()
|
||||||
{
|
{
|
||||||
vbox->hide();
|
vbox->hide ();
|
||||||
cancel_button->hide();
|
cancel_button->hide ();
|
||||||
transcode_button.hide();
|
transcode_button.hide ();
|
||||||
pbar.set_size_request(300,-1);
|
pbar.set_size_request (300, -1);
|
||||||
progress_box->show();
|
progress_box->show ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TranscodeVideoDialog::launch_transcode ()
|
TranscodeVideoDialog::launch_transcode ()
|
||||||
{
|
{
|
||||||
if (video_combo.get_active_row_number() != 1) {
|
if (video_combo.get_active_row_number () != 1) {
|
||||||
launch_audioonly();
|
launch_audioonly ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::string outfn = path_entry.get_text();
|
std::string outfn = path_entry.get_text ();
|
||||||
if (!confirm_video_outfn(*this, outfn, video_get_docroot(Config))) return;
|
if (!confirm_video_outfn (*this, outfn, video_get_docroot (Config)))
|
||||||
|
return;
|
||||||
progress_label.set_text (_("Transcoding Video.."));
|
progress_label.set_text (_("Transcoding Video.."));
|
||||||
dialog_progress_mode();
|
dialog_progress_mode ();
|
||||||
#if 1 /* tentative debug mode */
|
if (debug_checkbox.get_active ()) {
|
||||||
if (debug_checkbox.get_active()) {
|
transcoder->set_debug (true);
|
||||||
transcoder->set_debug(true);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
aborted = false;
|
aborted = false;
|
||||||
if (audio_combo.get_active_row_number() != 0) {
|
if (audio_combo.get_active_row_number () != 0) {
|
||||||
pending_audio_extract = true;
|
pending_audio_extract = true;
|
||||||
StartNextStage.connect(*this, invalidator (*this), boost::bind (&TranscodeVideoDialog::launch_extract , this), gui_context());
|
StartNextStage.connect (*this, invalidator (*this), boost::bind (&TranscodeVideoDialog::launch_extract, this), gui_context ());
|
||||||
}
|
}
|
||||||
|
|
||||||
int scale_width, scale_height, bitrate;
|
int scale_width, scale_height, bitrate;
|
||||||
if (scale_combo.get_active_row_number() == 0 ) {
|
if (scale_combo.get_active_row_number () == 0) {
|
||||||
scale_width =0;
|
scale_width = 0;
|
||||||
} else {
|
} else {
|
||||||
scale_width = atoi(scale_combo.get_active_text());
|
scale_width = atoi (scale_combo.get_active_text ());
|
||||||
}
|
}
|
||||||
if (!aspect_checkbox.get_active()) {
|
if (!aspect_checkbox.get_active ()) {
|
||||||
scale_height = 0;
|
scale_height = 0;
|
||||||
} else {
|
} else {
|
||||||
scale_height = (int) floor(height_spinner.get_value());
|
scale_height = (int)floor (height_spinner.get_value ());
|
||||||
}
|
}
|
||||||
if (bitrate_checkbox.get_active() ){
|
if (bitrate_checkbox.get_active ()) {
|
||||||
bitrate = (int) floor(bitrate_spinner.get_value());
|
bitrate = (int)floor (bitrate_spinner.get_value ());
|
||||||
} else {
|
} else {
|
||||||
bitrate = 0;
|
bitrate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
transcoder->Progress.connect(*this, invalidator (*this), boost::bind (&TranscodeVideoDialog::update_progress , this, _1, _2), gui_context());
|
transcoder->Progress.connect (*this, invalidator (*this), boost::bind (&TranscodeVideoDialog::update_progress, this, _1, _2), gui_context ());
|
||||||
transcoder->Finished.connect(*this, invalidator (*this), boost::bind (&TranscodeVideoDialog::finished, this), gui_context());
|
transcoder->Finished.connect (*this, invalidator (*this), boost::bind (&TranscodeVideoDialog::finished, this, _1), gui_context ());
|
||||||
if (!transcoder->transcode(outfn, scale_width, scale_height, bitrate)) {
|
if (!transcoder->transcode (outfn, scale_width, scale_height, bitrate)) {
|
||||||
ARDOUR_UI::instance()->popup_error(_("Transcoding Failed."));
|
ARDOUR_UI::instance ()->popup_error (_("Transcoding Failed."));
|
||||||
Gtk::Dialog::response(RESPONSE_CANCEL);
|
Gtk::Dialog::response (RESPONSE_CANCEL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -447,22 +469,22 @@ TranscodeVideoDialog::launch_transcode ()
|
||||||
void
|
void
|
||||||
TranscodeVideoDialog::video_combo_changed ()
|
TranscodeVideoDialog::video_combo_changed ()
|
||||||
{
|
{
|
||||||
const int i = video_combo.get_active_row_number();
|
const int i = video_combo.get_active_row_number ();
|
||||||
if (i != 1) {
|
if (i != 1) {
|
||||||
scale_combo.set_sensitive(false);
|
scale_combo.set_sensitive (false);
|
||||||
aspect_checkbox.set_sensitive(false);
|
aspect_checkbox.set_sensitive (false);
|
||||||
height_spinner.set_sensitive(false);
|
height_spinner.set_sensitive (false);
|
||||||
bitrate_checkbox.set_sensitive(false);
|
bitrate_checkbox.set_sensitive (false);
|
||||||
bitrate_spinner.set_sensitive(false);
|
bitrate_spinner.set_sensitive (false);
|
||||||
} else {
|
} else {
|
||||||
scale_combo.set_sensitive(true);
|
scale_combo.set_sensitive (true);
|
||||||
aspect_checkbox.set_sensitive(true);
|
aspect_checkbox.set_sensitive (true);
|
||||||
height_spinner.set_sensitive(true);
|
height_spinner.set_sensitive (true);
|
||||||
bitrate_checkbox.set_sensitive(true);
|
bitrate_checkbox.set_sensitive (true);
|
||||||
bitrate_spinner.set_sensitive(true);
|
bitrate_spinner.set_sensitive (true);
|
||||||
}
|
}
|
||||||
if (i == 2 && audio_combo.get_active_row_number() == 0) {
|
if (i == 2 && audio_combo.get_active_row_number () == 0) {
|
||||||
audio_combo.set_active(1);
|
audio_combo.set_active (1);
|
||||||
} else {
|
} else {
|
||||||
//update LTC option sensitivity
|
//update LTC option sensitivity
|
||||||
audio_combo_changed ();
|
audio_combo_changed ();
|
||||||
|
@ -472,17 +494,13 @@ TranscodeVideoDialog::video_combo_changed ()
|
||||||
void
|
void
|
||||||
TranscodeVideoDialog::audio_combo_changed ()
|
TranscodeVideoDialog::audio_combo_changed ()
|
||||||
{
|
{
|
||||||
if (video_combo.get_active_row_number() == 2
|
if (video_combo.get_active_row_number () == 2 && audio_combo.get_active_row_number () == 0) {
|
||||||
&& audio_combo.get_active_row_number() == 0)
|
audio_combo.set_active (1);
|
||||||
{
|
|
||||||
audio_combo.set_active(1);
|
|
||||||
ltc_detect.set_sensitive (false);
|
ltc_detect.set_sensitive (false);
|
||||||
ltc_detect.set_active (false);
|
ltc_detect.set_active (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (video_combo.get_active_row_number() != 2
|
if (video_combo.get_active_row_number () != 2 && audio_combo.get_active_row_number () > 0) {
|
||||||
&& audio_combo.get_active_row_number() > 0)
|
|
||||||
{
|
|
||||||
ltc_detect.set_sensitive (true);
|
ltc_detect.set_sensitive (true);
|
||||||
} else {
|
} else {
|
||||||
ltc_detect.set_sensitive (false);
|
ltc_detect.set_sensitive (false);
|
||||||
|
@ -493,31 +511,31 @@ TranscodeVideoDialog::audio_combo_changed ()
|
||||||
void
|
void
|
||||||
TranscodeVideoDialog::scale_combo_changed ()
|
TranscodeVideoDialog::scale_combo_changed ()
|
||||||
{
|
{
|
||||||
if (!aspect_checkbox.get_active()) {
|
if (!aspect_checkbox.get_active ()) {
|
||||||
int h;
|
int h;
|
||||||
if (scale_combo.get_active_row_number() == 0 ) {
|
if (scale_combo.get_active_row_number () == 0) {
|
||||||
h = transcoder->get_height();
|
h = transcoder->get_height ();
|
||||||
} else {
|
} else {
|
||||||
h = floor(atof(scale_combo.get_active_text()) / m_aspect);
|
h = floor (atof (scale_combo.get_active_text ()) / m_aspect);
|
||||||
}
|
}
|
||||||
height_spinner.set_value(h);
|
height_spinner.set_value (h);
|
||||||
}
|
}
|
||||||
update_bitrate();
|
update_bitrate ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TranscodeVideoDialog::aspect_checkbox_toggled ()
|
TranscodeVideoDialog::aspect_checkbox_toggled ()
|
||||||
{
|
{
|
||||||
height_spinner.set_sensitive(aspect_checkbox.get_active());
|
height_spinner.set_sensitive (aspect_checkbox.get_active ());
|
||||||
scale_combo_changed();
|
scale_combo_changed ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TranscodeVideoDialog::bitrate_checkbox_toggled ()
|
TranscodeVideoDialog::bitrate_checkbox_toggled ()
|
||||||
{
|
{
|
||||||
bitrate_spinner.set_sensitive(bitrate_checkbox.get_active());
|
bitrate_spinner.set_sensitive (bitrate_checkbox.get_active ());
|
||||||
if (!bitrate_checkbox.get_active()) {
|
if (!bitrate_checkbox.get_active ()) {
|
||||||
update_bitrate();
|
update_bitrate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,43 +543,46 @@ void
|
||||||
TranscodeVideoDialog::update_bitrate ()
|
TranscodeVideoDialog::update_bitrate ()
|
||||||
{
|
{
|
||||||
double br = .7; /* avg quality - bits per pixel */
|
double br = .7; /* avg quality - bits per pixel */
|
||||||
if (bitrate_checkbox.get_active() || !transcoder->probe_ok()) { return; }
|
if (bitrate_checkbox.get_active () || !transcoder->probe_ok ()) {
|
||||||
br *= transcoder->get_fps();
|
return;
|
||||||
br *= height_spinner.get_value();
|
}
|
||||||
|
br *= transcoder->get_fps ();
|
||||||
|
br *= height_spinner.get_value ();
|
||||||
|
|
||||||
if (scale_combo.get_active_row_number() == 0 ) {
|
if (scale_combo.get_active_row_number () == 0) {
|
||||||
br *= transcoder->get_width();
|
br *= transcoder->get_width ();
|
||||||
} else {
|
} else {
|
||||||
br *= atof(scale_combo.get_active_text());
|
br *= atof (scale_combo.get_active_text ());
|
||||||
}
|
}
|
||||||
if (br != 0) {
|
if (br != 0) {
|
||||||
bitrate_spinner.set_value(floor(br/10000.0)*10);
|
bitrate_spinner.set_value (floor (br / 10000.0) * 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TranscodeVideoDialog::open_browse_dialog ()
|
TranscodeVideoDialog::open_browse_dialog ()
|
||||||
{
|
{
|
||||||
Gtk::FileChooserDialog dialog(_("Save Transcoded Video File"), Gtk::FILE_CHOOSER_ACTION_SAVE);
|
Gtk::FileChooserDialog dialog (_("Save Transcoded Video File"), Gtk::FILE_CHOOSER_ACTION_SAVE);
|
||||||
dialog.set_filename (path_entry.get_text());
|
dialog.set_filename (path_entry.get_text ());
|
||||||
Gtkmm2ext::add_volume_shortcuts (dialog);
|
Gtkmm2ext::add_volume_shortcuts (dialog);
|
||||||
|
|
||||||
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
|
dialog.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
|
||||||
dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
|
dialog.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK);
|
||||||
|
|
||||||
int result = dialog.run();
|
int result = dialog.run ();
|
||||||
|
|
||||||
if (result == Gtk::RESPONSE_OK) {
|
if (result == Gtk::RESPONSE_OK) {
|
||||||
std::string filename = dialog.get_filename();
|
std::string filename = dialog.get_filename ();
|
||||||
|
|
||||||
if (filename.length()) {
|
if (filename.length ()) {
|
||||||
path_entry.set_text (filename);
|
path_entry.set_text (filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum VtlTranscodeOption
|
enum VtlTranscodeOption
|
||||||
TranscodeVideoDialog::import_option() {
|
TranscodeVideoDialog::import_option ()
|
||||||
int i = video_combo.get_active_row_number();
|
{
|
||||||
return static_cast<VtlTranscodeOption>(i);
|
int i = video_combo.get_active_row_number ();
|
||||||
|
return static_cast<VtlTranscodeOption> (i);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,38 +25,51 @@
|
||||||
#include <gtkmm/button.h>
|
#include <gtkmm/button.h>
|
||||||
#include <gtkmm/checkbutton.h>
|
#include <gtkmm/checkbutton.h>
|
||||||
#include <gtkmm/comboboxtext.h>
|
#include <gtkmm/comboboxtext.h>
|
||||||
#include <gtkmm/label.h>
|
|
||||||
#include <gtkmm/entry.h>
|
#include <gtkmm/entry.h>
|
||||||
|
#include <gtkmm/label.h>
|
||||||
#include <gtkmm/progressbar.h>
|
#include <gtkmm/progressbar.h>
|
||||||
#include <gtkmm/spinbutton.h>
|
#include <gtkmm/spinbutton.h>
|
||||||
|
|
||||||
#include "ardour/types.h"
|
|
||||||
#include "ardour/template_utils.h"
|
#include "ardour/template_utils.h"
|
||||||
|
#include "ardour/types.h"
|
||||||
#include "ardour_dialog.h"
|
#include "ardour_dialog.h"
|
||||||
|
|
||||||
#include "transcode_ffmpeg.h"
|
#include "transcode_ffmpeg.h"
|
||||||
|
|
||||||
enum VtlTranscodeOption {
|
enum VtlTranscodeOption {
|
||||||
VTL_IMPORT_REFERENCE = 0,
|
VTL_IMPORT_REFERENCE = 0,
|
||||||
VTL_IMPORT_TRANSCODED = 1,
|
VTL_IMPORT_TRANSCODED = 1,
|
||||||
VTL_IMPORT_NO_VIDEO = 2
|
VTL_IMPORT_NO_VIDEO = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @class TranscodeVideoDialog
|
/** @class TranscodeVideoDialog
|
||||||
* @brief dialog-box and controller for importing video-files
|
* @brief dialog-box and controller for importing video-files
|
||||||
*/
|
*/
|
||||||
class TranscodeVideoDialog : public ArdourDialog , public PBD::ScopedConnectionList
|
class TranscodeVideoDialog : public ArdourDialog, public PBD::ScopedConnectionList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TranscodeVideoDialog (ARDOUR::Session*, std::string);
|
TranscodeVideoDialog (ARDOUR::Session*, std::string);
|
||||||
~TranscodeVideoDialog ();
|
~TranscodeVideoDialog ();
|
||||||
|
|
||||||
std::string get_filename () { return path_entry.get_text(); }
|
|
||||||
std::string get_audiofile () { return audiofile; }
|
|
||||||
VtlTranscodeOption import_option ();
|
VtlTranscodeOption import_option ();
|
||||||
bool detect_ltc () { return ltc_detect.get_active (); }
|
|
||||||
|
|
||||||
void on_response (int response_id) {
|
std::string get_filename ()
|
||||||
|
{
|
||||||
|
return path_entry.get_text ();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string get_audiofile ()
|
||||||
|
{
|
||||||
|
return audiofile;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool detect_ltc ()
|
||||||
|
{
|
||||||
|
return ltc_detect.get_active ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_response (int response_id)
|
||||||
|
{
|
||||||
Gtk::Dialog::on_response (response_id);
|
Gtk::Dialog::on_response (response_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,29 +87,30 @@ private:
|
||||||
void launch_transcode ();
|
void launch_transcode ();
|
||||||
void launch_extract ();
|
void launch_extract ();
|
||||||
void dialog_progress_mode ();
|
void dialog_progress_mode ();
|
||||||
bool aborted;
|
void finished (int);
|
||||||
bool pending_audio_extract;
|
|
||||||
std::string audiofile;
|
|
||||||
std::string infn;
|
|
||||||
double m_aspect;
|
|
||||||
|
|
||||||
PBD::Signal0<void> StartNextStage;
|
|
||||||
void finished ();
|
|
||||||
void update_progress (ARDOUR::samplecnt_t, ARDOUR::samplecnt_t);
|
void update_progress (ARDOUR::samplecnt_t, ARDOUR::samplecnt_t);
|
||||||
|
|
||||||
TranscodeFfmpeg *transcoder;
|
bool aborted;
|
||||||
|
bool pending_audio_extract;
|
||||||
|
std::string audiofile;
|
||||||
|
std::string infn;
|
||||||
|
double m_aspect;
|
||||||
|
|
||||||
Gtk::Label path_label;
|
PBD::Signal0<void> StartNextStage;
|
||||||
Gtk::Entry path_entry;
|
|
||||||
Gtk::Button browse_button;
|
|
||||||
Gtk::Button transcode_button;
|
|
||||||
|
|
||||||
Gtk::VBox* vbox;
|
TranscodeFfmpeg* transcoder;
|
||||||
Gtk::Button *cancel_button;
|
|
||||||
Gtk::Button abort_button;
|
|
||||||
|
|
||||||
Gtk::VBox* progress_box;
|
Gtk::Label path_label;
|
||||||
Gtk::Label progress_label;
|
Gtk::Entry path_entry;
|
||||||
|
Gtk::Button browse_button;
|
||||||
|
Gtk::Button transcode_button;
|
||||||
|
|
||||||
|
Gtk::VBox* vbox;
|
||||||
|
Gtk::Button* cancel_button;
|
||||||
|
Gtk::Button abort_button;
|
||||||
|
|
||||||
|
Gtk::VBox* progress_box;
|
||||||
|
Gtk::Label progress_label;
|
||||||
Gtk::ProgressBar pbar;
|
Gtk::ProgressBar pbar;
|
||||||
|
|
||||||
Gtk::ComboBoxText video_combo;
|
Gtk::ComboBoxText video_combo;
|
||||||
|
@ -109,10 +123,7 @@ private:
|
||||||
Gtk::CheckButton bitrate_checkbox;
|
Gtk::CheckButton bitrate_checkbox;
|
||||||
Gtk::Adjustment bitrate_adjustment;
|
Gtk::Adjustment bitrate_adjustment;
|
||||||
Gtk::SpinButton bitrate_spinner;
|
Gtk::SpinButton bitrate_spinner;
|
||||||
#if 1 /* tentative debug mode */
|
|
||||||
Gtk::CheckButton debug_checkbox;
|
Gtk::CheckButton debug_checkbox;
|
||||||
#endif
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __gtk_ardour_transcode_video_dialog_h__ */
|
#endif /* __gtk_ardour_transcode_video_dialog_h__ */
|
||||||
|
|
Loading…
Reference in New Issue