diff options
-rw-r--r-- | doc/visualization.html | 118 | ||||
-rw-r--r-- | visualization/renderer/main.cpp | 5 | ||||
-rw-r--r-- | visualization/renderer/qmpsettingsro.cpp | 52 | ||||
-rw-r--r-- | visualization/renderer/qmpsettingsro.hpp | 1 | ||||
-rw-r--r-- | visualization/renderer/qmpvisrendercore.cpp | 5 |
5 files changed, 178 insertions, 3 deletions
diff --git a/doc/visualization.html b/doc/visualization.html index 6ad44dd..207d3a5 100644 --- a/doc/visualization.html +++ b/doc/visualization.html @@ -69,7 +69,7 @@ <li>Enable VSync: Enable vertical synchronization.</li> <li>Save Viewport: Restore last camera configuration when the visualization is started.</li> <li>Window Width/Height: Change the window size. If the size equals to your screen size, the visualization will start in fullscreen mode.</li> - <li>FPS: FPS limit of the visualization.</li> + <li>Target FPS: FPS limit of the visualization.</li> <li>Supersampling: Supersample anti-aliasing for the 3D visualization scene. 1 means no SSAA.</li> <li>Multisampling: Multisample anti-aliasing for the 3D visualization scene. 0 means no MSAA.</li> <li>FOV: Field of view.</li> @@ -87,6 +87,122 @@ </ul> </li> </ul> + <h2>Visualization Renderer</h2> + The visualization plugin comes with a standalone application that generates high quality rendering of a midi file. + <h3>Command line usage</h3> + <pre style="font-variant-ligatures:none;"> +Usage: ./qmpvisrender [options] file +Renderer a visualization of a midi file. + +Options: + -h, --help Displays help on commandline options. + --help-all Displays help including Qt specific options. + -v, --version Displays version information. + -f, --output-file <filename> File name of the output file. + --receiver <command> Specify a program and its arguments to + process the rendered frames. Supports + parameter substitution. See documentation for + details. + -e, --receiver-execution <mode> Execution mode of the receiver command. + Valid options are 'one-shot' and 'per-frame' + -s, --show-window Do not hide the visualization window. + -c, --config <qmprc file> Load options from the configuration file. + -o, --option <key-value pair> Set option for the visualization module. + --list-options Show a list of recognized options. + +Arguments: + file MIDI file to render + </pre> + <h3>Basic usage</h3> + You will most likely to load your QMidiPlayer configuration file so that + you can get the exact same results as viewed in QMidiPlayer. + You should also make sure ffmpeg is ready to use. Then you can run + <code>qmpvisrender -c <path-to-configuration-file> <MIDI file to render></code> + and wait for the results. The output file is named output.mp4 and will be found + in the current work directory. + <h3>Supplementary materials for commandline options</h3> + <p> + When specifying a value for an option under the "Visualization" category, the category part + in the key may be omitted, so "-o Visualization/wwidth=1920" would become "-o wwidth=1920". + </p> + <p> + The renderer performs parameter substitution before invoking the receiver command line. + </p> + <table> + <style> + td,th{ + padding-top:0.5em; + padding-bottom:0.5em; + } + </style> + <tr><th>Placeholder</th><th>Substituted with</th><th>Remarks</th></tr> + <tr><td><code>%w</code></td><td>width of an output frame in pixels</td><td></td></tr> + <tr><td><code>%h</code></td><td>height of an output frame in pixels</td><td></td></tr> + <tr><td><code>%r</code></td><td>framerate which the output frames should be played at</td><td></td></tr> + <tr><td><code>%i</code></td><td>input format specification for ffmpeg</td><td>shorthand for "-f rawvideo -pixel_format rgba -video_size %wx%h -framerate %r -i pipe:"</td></tr> + <tr><td><code>%o</code></td><td>output file name specified by the --output-file option</td><td>If the receiver execution mode is "per-frame", "%f" in the output file name will also be replaced.</td></tr> + <tr><td><code>%f</code></td><td>a six-digit frame number</td><td>only works if the receiver execution mode is "per-frame".</td></tr> + </table> + <p> + To add a literal space in the receiver command, put a single backslash before the space. + To add a percent sign, either put two consecutive percent signs or use a backslash followed + by a percent sign. + </p> + <p> + The default receiver command is <code>ffmpeg %i -vf vflip -pix_fmt yuv420p -c:v libx264 -preset slow -crf 22 %o</code>. + In case the output quality doesn't satisfy your needs, consider lowering the number after '-crf' or selecting a even slower + profile ('slower' or 'veryslow'). + </p> + <h3>How it works</h3> + <p> + Notice: you don't have to understand anything under this section to use this tool. + You may try out the examples below or simply adhere to the basic usage shown above even this + section makes zero sense to you. + </p> + <p> + The renderer feeds a sequence of images into one command or a series of commands that process + the images through a pipe. That's it! + </p> + <p> + The data is an stream of raw RGBA values, where each color takes one byte in every pixel. The frame + size is the same as used by the visualization module, and the frames should be played back at a fixed + frame rate. The pixel data starts from the bottom-left of a frame and follows row-major ordering (so + you may want to flip the frame when using the frame with some applications). + </p> + <p> + The renderer supports two modes of receiver program operation. If the mode is set to 'one-shot', + the receiver is only started once and gets all rendered frames. If it is set to 'per-frame', + the receiver will be started every time a frame is rendered, and will only get one frame to process. + </p> + <h3>Examples</h3> + <p> + If you wish to try these examples, make sure you have the required receiver program ready to run. + </p> + <ol> + <li>Render to a vp9 encoded webm video.</li> + <pre style="white-space:pre-wrap;"> +qmpvisrender -c ~/.config/qmprc --output-file test.webm --receiver 'ffmpeg %i -vf vflip -c:v libvpx-vp9 -crf 30 -b:v 0 %o' <midi file> + </pre> + <li>Render to a h264 encoded mp4 video with hardware encoding acceleration using VA-API.</li> + <pre style="white-space:pre-wrap;"> +qmpvisrender -c ~/.config/qmprc --output-file test.mp4 --receiver 'ffmpeg -vaapi_device /dev/dri/renderD128 %i -vf vflip,format=nv12,hwupload -c:v h264_vaapi -b:v 5M %o' <midi file> + </pre> + <li>Render the frames into png files using imagemagick.</li> + <pre style="white-space:pre-wrap;"> +qmpvisrender -c ~/.config/qmprc --receiver-execution per-frame --receiver 'convert -size %wx%h -depth 8 RGBA:- -flip pngout/%f.png' <midi file> + </pre> + <li>Show the visualization window. Discard all rendered frames.</li> + <pre style="white-space:pre-wrap;"> +qmpvisrender -c ~/.config/qmprc -s --receiver 'dd of=/dev/null bs=24M' <midi file> + </pre> + <li>Save the raw frame data.</li> + <pre style="white-space:pre-wrap;"> +qmpvisrender -c ~/.config/qmprc --receiver-execution per-frame --receiver 'tee rawoutput/%f.raw' <midi file> + </pre> + </ol> + <h3>Useful stuff to refer to</h3> + <a target="_blank" href="https://www.ffmpeg.org/ffmpeg.html">ffmpeg documentation</a> + and <a target="_blank" href="https://www.ffmpeg.org/ffmpeg-codecs.html">ffmpeg codecs documentation</a>, if you want to tweak the ffmpeg encoder. </div> </body> </html> diff --git a/visualization/renderer/main.cpp b/visualization/renderer/main.cpp index 82e8983..c651c54 100644 --- a/visualization/renderer/main.cpp +++ b/visualization/renderer/main.cpp @@ -18,7 +18,7 @@ int main(int argc,char **argv) "receiver", "Specify a program and its arguments to process the rendered frames. Supports parameter substitution. See documentation for details.", "command", - "ffmpeg -f rawvideo -pixel_format rgba -video_size %wx%h -framerate %r -i pipe: -vf vflip -pix_fmt yuv420p -c:v libx264 -preset slow -crf 22 %o" + "ffmpeg %i -vf vflip -pix_fmt yuv420p -c:v libx264 -preset slow -crf 22 %o" }); clp.addOption({ {"e","receiver-execution"}, @@ -29,10 +29,11 @@ int main(int argc,char **argv) clp.addOption({{"s","show-window"},"Do not hide the visualization window."}); clp.addOption({{"c","config"},"Load options from the configuration file.","qmprc file"}); clp.addOption({{"o","option"},"Set option for the visualization module.","key-value pair"}); + clp.addOption({"list-options","Show a list of recognized options and quit."}); clp.addPositionalArgument("file","MIDI file to render"); clp.process(a.arguments()); qmpVisRenderCore core(&clp); - if(clp.positionalArguments().empty()) + if(clp.positionalArguments().empty()&&!clp.isSet("list-options")) clp.showHelp(1); core.loadSettings(); if(!core.loadVisualizationLibrary()) diff --git a/visualization/renderer/qmpsettingsro.cpp b/visualization/renderer/qmpsettingsro.cpp index bf8096f..034f073 100644 --- a/visualization/renderer/qmpsettingsro.cpp +++ b/visualization/renderer/qmpsettingsro.cpp @@ -1,6 +1,8 @@ #include <QScopedPointer> #include <QSettings> +#include <cstdio> + #include "qmpsettingsro.hpp" qmpSettingsRO::qmpSettingsRO() @@ -172,3 +174,53 @@ void qmpSettingsRO::setopt(std::string key, std::string val) if(key.find("Visualization/")!=0) settings.insert("Visualization/"+QString(key.c_str()),QString(val.c_str())); } + +void qmpSettingsRO::listopt() +{ + for(auto&k:optionlist) + { + printf("Option key: %s\n",k.c_str()); + if(options[k].desc.length()) + printf("Description: %s\n",options[k].desc.c_str()); + switch(options[k].type) + { + case qmpOptionR::ParameterType::parameter_int: + printf("Type: int\n"); + printf("Range: [%d,%d]\n",options[k].minv.toInt(),options[k].maxv.toInt()); + printf("Default value: %d\n",options[k].defaultval.toInt()); + break; + case qmpOptionR::ParameterType::parameter_uint: + printf("Type: uint\n"); + printf("Range: [%u,%u]\n",options[k].minv.toUInt(),options[k].maxv.toUInt()); + printf("Default value: %u\n",options[k].defaultval.toUInt()); + break; + case qmpOptionR::ParameterType::parameter_double: + printf("Type: double\n"); + printf("Range: [%.2f,%.2f]\n",options[k].minv.toDouble(),options[k].maxv.toDouble()); + printf("Default value: %.f2\n",options[k].defaultval.toDouble()); + break; + case qmpOptionR::ParameterType::parameter_bool: + printf("Type: bool\n"); + printf("Default value: %s\n",options[k].defaultval.toBool()?"true":"false"); + break; + case qmpOptionR::ParameterType::parameter_str: + printf("Type: str\n"); + printf("Default value: %s\n",options[k].defaultval.toString().toStdString().c_str()); + break; + case qmpOptionR::ParameterType::parameter_url: + printf("Type: url\n"); + printf("Default value: %s\n",options[k].defaultval.toString().toStdString().c_str()); + break; + case qmpOptionR::ParameterType::parameter_enum: + printf("Type: enum\n"); + printf("Possible values: "); + for(size_t i=0;i<options[k].enumlist.size();++i) + printf("%s%s",options[k].enumlist[i].c_str(),i==options[k].enumlist.size()-1?"\n":", "); + printf("Default value: %s\n",options[k].enumlist[options[k].defaultval.toInt()].c_str()); + break; + default: + printf("Type: unknown\n"); + } + puts(""); + } +} diff --git a/visualization/renderer/qmpsettingsro.hpp b/visualization/renderer/qmpsettingsro.hpp index 5c5361d..c5dd8af 100644 --- a/visualization/renderer/qmpsettingsro.hpp +++ b/visualization/renderer/qmpsettingsro.hpp @@ -65,6 +65,7 @@ public: void load(const char* path); void setopt(std::string key,std::string val); + void listopt(); private: std::map<std::string,qmpOptionR> options; std::vector<std::string> optionlist; diff --git a/visualization/renderer/qmpvisrendercore.cpp b/visualization/renderer/qmpvisrendercore.cpp index 304d061..f8044f5 100644 --- a/visualization/renderer/qmpvisrendercore.cpp +++ b/visualization/renderer/qmpvisrendercore.cpp @@ -39,6 +39,11 @@ bool qmpVisRenderCore::loadVisualizationLibrary() switchmode(&qmpVisRenderCore::framefunc,!clp->isSet("show-window")); vp->init(); resetcb(nullptr,nullptr); + if(clp->isSet("list-options")) + { + msettings->listopt(); + exit(0); + } return true; } |