diff --git a/Recorder.cpp b/Recorder.cpp index d6daa8e..5db2708 100644 --- a/Recorder.cpp +++ b/Recorder.cpp @@ -122,7 +122,14 @@ void PNGRecorder::addFrame(FrameBuffer *frame_buffer, float) } -const char* VideoRecorder::profile_name[4] = { "H264 (low)", "H264 (high)", "Apple ProRes 4444", "WebM VP9" }; +const char* VideoRecorder::profile_name[VideoRecorder::DEFAULT] = { + "H264 (Standard)", + "H264 (high)", + "Apple ProRes (Standard)", + "Apple ProRes (HQ 4444)", + "WebM VP8 (Standard)", + "Multiple JPEG" +}; const std::vector VideoRecorder::profile_description { // Control x264 encoder quality : // pass=4 @@ -138,18 +145,28 @@ const std::vector VideoRecorder::profile_description { "x264enc pass=4 quantizer=23 speed-preset=3 ! video/x-h264, profile=baseline ! h264parse ! ", "x264enc pass=5 quantizer=18 speed-preset=4 ! video/x-h264, profile=high ! h264parse ! ", // Apple ProRes encoding parameters - // pass=2 + // pass // cbr (0) – Constant Bitrate Encoding // quant (2) – Constant Quantizer // pass1 (512) – VBR Encoding - Pass 1 - "avenc_prores bitrate=60000 pass=2 ! ", - // WebM VP9 encoding parameters - // https://www.webmproject.org/docs/encoder-parameters/ - // https://developers.google.com/media/vp9/settings/vod/ - "vp9enc end-usage=vbr end-usage=vbr cpu-used=3 max-quantizer=35 target-bitrate=200000 keyframe-max-dist=360 token-partitions=2 static-threshold=1000 ! " - + // profile + // 0 ‘proxy’ + // 1 ‘lt’ + // 2 ‘standard’ + // 3 ‘hq’ + // 4 ‘4444’ + "avenc_prores_ks pass=2 profile=2 quantizer=25 ! ", + "avenc_prores_ks pass=2 profile=4 quantizer=8 ! ", + "vp8enc end-usage=vbr cpu-used=8 max-quantizer=35 deadline=100000 target-bitrate=200000 keyframe-max-dist=360 token-partitions=2 static-threshold=100 ! ", + "jpegenc ! " }; +// Too slow +//// WebM VP9 encoding parameters +//// https://www.webmproject.org/docs/encoder-parameters/ +//// https://developers.google.com/media/vp9/settings/vod/ +//"vp9enc end-usage=vbr end-usage=vbr cpu-used=3 max-quantizer=35 target-bitrate=200000 keyframe-max-dist=360 token-partitions=2 static-threshold=1000 ! " + // FAILED // x265 encoder quality // string description = "appsrc name=src ! videoconvert ! " @@ -158,14 +175,8 @@ const std::vector VideoRecorder::profile_description { VideoRecorder::VideoRecorder() : Recorder(), frame_buffer_(nullptr), width_(0), height_(0), - recording_(false), accept_buffer_(false), pipeline_(nullptr), src_(nullptr), timeframe_(0), timestamp_(0) + recording_(false), accept_buffer_(false), pipeline_(nullptr), src_(nullptr), timestamp_(0) { - // auto filename - std::string path = SystemToolkit::path_directory(Settings::application.record.path); - if (path.empty()) - path = SystemToolkit::home_path(); - - filename_ = path + SystemToolkit::date_time_string() + "_vimix.mov"; // configure fix parameter frame_duration_ = gst_util_uint64_scale_int (1, GST_SECOND, 30); // 30 FPS @@ -213,7 +224,27 @@ void VideoRecorder::addFrame (FrameBuffer *frame_buffer, float dt) // create a gstreamer pipeline string description = "appsrc name=src ! videoconvert ! "; description += profile_description[Settings::application.record.profile]; - description += "qtmux ! filesink name=sink"; + + // verify location path (path is always terminated by the OS dependent separator) + std::string path = SystemToolkit::path_directory(Settings::application.record.path); + if (path.empty()) + path = SystemToolkit::home_path(); + + // setup filename & muxer + if( Settings::application.record.profile == JPEG_MULTI) { + std::string folder = path + SystemToolkit::date_time_string() + "_vimix_jpg"; + filename_ = SystemToolkit::full_filename(folder, "%05d.jpg"); + if (SystemToolkit::create_directory(folder)) + description += "multifilesink name=sink"; + } + else if( Settings::application.record.profile == VP8) { + filename_ = path + SystemToolkit::date_time_string() + "_vimix.webm"; + description += "webmmux ! filesink name=sink"; + } + else { + filename_ = path + SystemToolkit::date_time_string() + "_vimix.mov"; + description += "qtmux ! filesink name=sink"; + } // parse pipeline descriptor GError *error = NULL; @@ -389,6 +420,9 @@ void VideoRecorder::addFrame (FrameBuffer *frame_buffer, float dt) finished_ = true; } } + +// if (timestamp_ > 10000000000) +// stop(); } void VideoRecorder::stop () diff --git a/Recorder.h b/Recorder.h index 58b7dd9..17b62c0 100644 --- a/Recorder.h +++ b/Recorder.h @@ -75,7 +75,16 @@ class VideoRecorder : public Recorder public: - static const char* profile_name[4]; + typedef enum { + H264_STANDARD = 0, + H264_HQ, + PRORES_STANDARD, + PRORES_HQ, + VP8, + JPEG_MULTI, + DEFAULT + } Profile; + static const char* profile_name[DEFAULT]; static const std::vector profile_description; VideoRecorder(); diff --git a/SystemToolkit.cpp b/SystemToolkit.cpp index c5715e8..a24efe3 100644 --- a/SystemToolkit.cpp +++ b/SystemToolkit.cpp @@ -204,7 +204,7 @@ std::string SystemToolkit::username() return string(user); } -bool create_directory(const string& path) +bool SystemToolkit::create_directory(const string& path) { return !mkdir(path.c_str(), 0755) || errno == EEXIST; diff --git a/SystemToolkit.h b/SystemToolkit.h index d882b82..00ab692 100644 --- a/SystemToolkit.h +++ b/SystemToolkit.h @@ -54,6 +54,9 @@ namespace SystemToolkit // true of file exists bool file_exists(const std::string& path); + bool create_directory(const std::string& path); + + // try to open the file with system void open(const std::string& path);