diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f4cd583 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# Jetbrains stuff +/.idea/ +*.iml + +# might eventually remove this but, keeping raw files out of git +*.y4m +*.mp4 + +*.exe +*.pdb +*.log +/results.txt diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..4d117d3 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "encoder_benchmark_tool" +version = "0.1.0" +edition = "2021" + +[dependencies] +clap = { version = "4.0.32", features = ["derive"] } +compound_duration = "1.2.0" +crossbeam-channel = "0.5.6" +ctrlc = "3.2.4" +filetime = "0.2.19" +indicatif = "0.17.2" +itertools = "0.10.5" +num_cpus = "1.15.0" +regex = "1.7.0" +rev_buf_reader = "0.3.0" +stoppable_thread = "0.2.1" diff --git a/README.md b/README.md new file mode 100644 index 0000000..8423068 --- /dev/null +++ b/README.md @@ -0,0 +1,507 @@ +## Realtime Video Encoding Benchmark Tool + +A command-line tool wrapper around ffmpeg that provides: + +- reliable way to benchmark real-time video encoding capabilities of your hardware +- determination of encoder-specific settings that your hardware can handle +- optional accurate video encode quality scoring via vmaf +- no storage overhead during benchmarking due to some clever use of data streaming via TCP +- bitrate increasing permutations to find minimum bitrate needed for visually lossless game streaming +- a clean report at the end of the permutation results to help guide hardware decisions & streaming guides + +```shell +# sample output for encoding a 4K@60 input file +[Permutation 2/21] +[ETR: 9m20s] +[Bitrate: 10Mb/s] +[-preset p1 -tune ll -profile:v high -rc cbr -cbr true] +Running benchmark to test whether encoder can keep up with input... + [00:00:25] [####################################] 1923/1923 frames (00:00:00) + Average FPS: 78 + 1%'ile: 68 + 90%'ile: 94 +``` + +For a quick-start guide for common use-cases, see Quick-Run Guide. + +For a quick reference of what to expect for your hardware, or what bitrate to configure in Moonlight when doing at home +game streaming, see the Expected Performance section at the bottom of the readme. + +--- + +## Minimum system specs suggested + +In addition to the mentioned specs below, you should _not_ have drive compression enabled for Windows on the drive you +plan to store the files on. This can heavily limit sequential read speeds and affect the results of the tool. + +```text +OS: Windows, Mac or Linux +Processor: CPU with at least 6 cores +GPU: GPU w/ hardware encoder, in the main x16 PCI slot of your PC (for max PCI bandwidth) +Memory: >= 8GB RAM (higher is always better) +Storage Space: 120GB minimum (all benchmark files take up about 120GB) +Storage Type/Speed: + -if benchmarking <= 1080@120, any SATA ssd will work + -if benchmarking >= 1080@120, you MUST use an nvme drive with > 1GB/s sequential read speeds +``` + +The more cores you have, the faster the quality scoring via vmaf will happen, and the faster the benchmarks will +run overall. Plus, your encoder of choice might be limited based on your CPU itself. + + +--- + +## Installation & Setup requirements + +Note: tool has been tested with ffmpeg version `5.1.2`, so it's highly suggested to use the same version, or at least +version `5.*` of ffmpeg/ffprobe. + +1) Installation of ffmpeg + + - For Windows, recommend downloading the binaries for Windows from + gyan.dev, specifically the `ffmpeg-release-full` one, which should include all needed features and tools + - For Mac/Linux, install both `ffmpeg` and `ffprobe` at mentioned versions above +2) 7-Zip to unzip any downloaded ffmpeg binaries +3) ffmpeg/ffprobe must be available on your path (tool will error out if it can't find + either); quick path setup guide for + Windows + 10+ +4) Download the built executable for your platform from the release section of this repo onto the SSD that you wish to + run the benchmark on +5) Download all the raw video source files onto the same SSD where the executable is (and in the same folder) + from here. If you only wish + to + benchmark one specific resolution, only download that file and make sure to specify it as noted in the **Run using + the executable** section below + +(Note: due to the tool sending encoded video over your local network to test quality, you will not need more storage +space than just what is needed to hold the original source video files). + +--- + +## Running the tool + +Keep in mind, this tool is going to stress the encoder of your choice. It's highly recommended when running this tool +to not use your computer for any other tasks as that can affect the results. + +i.e. if you're using your GPU for encoding, it's best to not have any programs open that could use your GPU. + +#### Run using executable + +For a complete list of all command line arguments, run: + +`./ebt -h` + +Typical usage would be: + +```shell +# general example, note that executable name might be different +./ebt -e -b -s + +# specific example, wanting to encode H264 using your Nvidia GPU at a 10Mb/s bitrate target +./ebt -e h264_nvenc -b 10 -s 1080-60.y4m +``` + +#### Run using cargo + +(See **Contributing** section for version of Rust to install) + +`cargo run --release -- -e h264_nvenc -b 10 -s 1080-60.y4m` + +#### Stopping the benchmark + +Kill the benchmark by hitting `ctrl-c` in the terminal/console where the benchmark is running. + +--- + +## Quick-Run Guide + +This tool can do a lot of things, however it's likely that your use case is very specific. Here are the typical use +cases & commands that you'd use. + +**Note:** the input file that you provide is what determines the resolution you'll be benchmarking. + +### The Benchmark: Run Pre-Configured Encodes to Compare to Others + +This feature of the tool is likely going to be the most popular, as it's intended to compare different systems +encoding performances in a standardized way. + +Note: you must download all the video source files to be able to run the standard benchmark. See the +Installation & Setup Requirements section. + +It does the following: + +- runs pre-configured encoder settings & bitrate values chosen by the author +- runs benchmark on all supported resolutions, outputting fps results to the console & a `benchmark.log` file + +Simple run the following (and choose your encoder): + +`./ebc -e h264_nvenc` + +If you so chose, you can also calculate the quality of the encode as well, although at the target configurations & +bitrates you should expect a vmaf score of 95: + +`./ebc -e h264_nvenc -c` + +You may want the benchmark to stop early if it can't encode at the file's target fps; if so, use the `-d` parameter to +detect encoder overload and stop the benchmark: + +`./ebc -e h264_nvenc -d` + +**Location of Encoder Setting Used**: to see the chosen encoder preset for this benchmark, see the respective encoder's +implementation of `run_standard_only()` method, found in `src/permutations`. These tend to lean on the side of a lower +preset to help keep fps statistics a bit higher (since you can always use more bitrate to improve quality). + +**Location of Bitrate Used:** you can also find the pre-configured bitrate value for that encoder within the encoder's +implementation of `get_resolution_to_bitrate_map()`, found in `src/permutations`. These values are typically the +bitrates for the 120fps findings. + +### Running benchmark over encoder settings + +This will run through all permutations of encoder settings, for your given resolution input file, and produce fps +statistics, at the default bitrate of 10Mb/s. This gives you a good idea of the performance you can expect for your +encoder. + +`./ebt -e h264_nvenc -s 4k-60.y4m` + +You may want to gather fps statistics at higher bitrates that you're more likely to stream at, since output bitrate can +affect encoder performance. Do this by using the following: + +`./ebt -e h264_nvenc -s 4k-60.y4m -b 50` + +If you are curious on how _the minimum bitrate required_ can be identified, this tool can help you find that as well in +the next section. + +### Bitrate & encoder settings combinations to achieve visually lossless game streaming + +When using Moonlight as your game streaming client, it auto-recommends a bitrate for you to stream at. Most of the time +this is pretty accurate for lower resolutions, however depending on your hardware's capabilities you might be able to +get away with less bitrate than it suggests. + +For example: Moonlight auto-selects `80Mb/s` for streaming 4K@60 game content. However from our testing, you really only +need `45-50Mb/s` when encoding using H264_NVENC. + +To simply test what quality scores you can get at a given bitrate, use the following: + +`./ebt -e h264_nvenc -s 4k-60.y4m -c -b 10` + +If you're not sure on what bitrate would achieve visually lossless quality, provide a starting bitrate & max bitrate to +permute over (in 5Mb/s intervals). In the below example, every encoder setting will be tested at +**[10, 15, 20, ..., 100 Mb/s]** (until vmaf score of 95 is achieved): + +`./ebt -e h264_nvenc -s 4k-60.y4m -c -b 10 -m 100` + +When the tool detects that you've hit a `95` vmaf score, it will stop permuting. In the above example, the tool would +stop permuting once it gets to `50Mb/s` since we know that's the point where you get visually lossless 4K@60 with +H264_NVENC, and any higher amount of bitrate does not significantly improve quality and can actually reduce encoder +performance. + +--- + +## Discussion + +### What this benchmark can provide for you + +1) Determine what resolution/fps your specific system can encode in real-time with less guess work +2) Permute over configured encoder settings to identify what settings maximize encoder real-time average fps +3) Make use of quality scores to determine encoder setting & bitrate combinations that provides visually lossless + quality +4) Provide encoder settings in a copy-paste format, making it easy to apply them into OBS Studio/Sunshine + +### How to Interpret FPS Statistics + +The tool will provide you with the following FPS stats when running through permutations: + +```text + Average FPS: 78 + 1%'ile: 68 + 90%'ile: 94 +``` + +Each stat has specific things that it can tell you about what your system can do in real-time. + +- _Average:_ gives an idea of the overall experience you can expect during encoding +- _1%'ile:_ gives an indication of detected dips/low points in framerate +- _90%'ile:_ gives an indication of the upper-limits of the encoding capabilities of your hardware + +When choosing encoder permutation settings to use, you should look at all 3 datapoints before deciding what your system +can handle. + +#### A Good Encoding Experience Example + +Let's say you get the following fps stats: + +```text + Average FPS: 78 + 1%'ile: 68 + 90%'ile: 94 +``` + +You have an average of `78fps` and a 1%'ile of `68fps`, I can confidently say that +my system will produce a smooth and consistent `60fps` encode experience. + +However if I really wanted to, I could look at the 90%'ile and know that my system _could_ periodically do `90fps` but +will drop down to as low as `68fps`. If that fps variance is fine with you, you can feel free to set your target fps +to `90fps`. Just know that at heavier encode times or game content where there's more movement/variance, your encode fps +will drop. + +#### A Bad Encoding Experience Example + +Let's say instead, you see the following stats: + +```text + Average FPS: 78 + 1%'ile: 30 + 90%'ile: 85 +``` + +Notice the 1%'ile `30fps` is much lower than the average and the 90%'ile. In this case, you may end up seeing fps drops +during encoding that are drastic and would most likely provide a bad encoding experience. + +For results like these, it's recommended to try using different hardware/encoding settings to have the 1%'ile be much +closer to the average. Or, just know that you might see some hard dips in FPS and consider not game streaming at all for +a better experience. + +### Real-time encoding terminology + +The benchmark is always checking whether your encoder, at a given resolution/bitrate/fps, can keep up with at least +the given fps. By default however, the actual encoding speed may be much higher than the input file. This is to help +cut down on runtime during benchmarking. + +**Disclaimers** + +_It is possible that when you go to apply these settings in OBS Studio, or Sunshine's game stream hosting software, +that the encoder/ffmpeg version being used there may perform different, i.e. most likely worse than this benchmarking +tool._ + +_This tool only tells you whether your host system can encode the video at the given parameters; it does not tell you +whether the client you intend to stream TO can decode at the same speed. You may find that your client device +cannot decode the incoming video as fast as it's sent._ + +_You may find that what works on your machine, does not work on another with similar hardware. This is expected, and is +why you should run the tool on your machine to get specific results to your setup._ + +### Visually Lossless Terminology + +Any encoded video that scores >= 95 vmaf score is considered visually lossless, and is what you are shooting for in +terms of encoded video quality. Anything lower and you end up seeing minor blockiness or artifacting. + +By default, the tool does not calculate vmaf score to initially focus on producing fps statistics. However, you can have +the tool calculate vmaf score on each permutation by using the `-c` flag. + +Using `-c` in combination with `-- + +### Skipping Duplicate Scoring Permutations by Default + +By default, the benchmark will detect if encoder settings produce the same vmaf score as previously calculated ones. +This is done during the initial pass of all encoder setting permutations for a given bitrate. + +Each subsequence bitrate & encoder settings permutation will effectively ignore duplicated encoder settings that produce +duplicated vmaf results in an effort to cut down on pointless calculation time. + +If you so desire, you can still have those permutations run and end up in the normal produced report by specifying +the `-a` option. + +Note: a footnote to the results file will be added of what encoder settings produced similar results for your reference +later. + +### Detecting video encoder overload & skipping by default + +If you've streamed using OBS Studio before, you might have seen: + +![img.png](docs/obs-encoder-overload.png) + +This tool has logic in it to detect encoder overload as well, by keeping an eye on the current fps during +encoding. For example, if the target fps is `60`, this tool will attempt to encode the source video file at +exactly `60fps`. + +If at any point the tool detects that the current fps is less than the target, the tool will stop and indicate that an +encoder overload has occurred. If you still wish to let these encodes keep going (to see full fps statistics), you can +do this by providing the `-i` option to ignore when the encoder gets overloaded. + +Note: in the stats output file, any encoder/bitrate/fps permutation that results in an overloaded encoder will have +a `[O]` at the beginning of it's result stats. + +### Source input files + +All source files for this tool are captured with OBS Studio as `yuv4` raw video with `4:2:0` chroma subsampling, at +specific resolutions/frame rates. +Raw video at this chroma subsample is the closest you can get to simulating encoding a game that you're playing in +real-time, much like you would +when streaming to Twitch/Youtube. Any higher chroma subsample will produce lower scoring/performing results. + +Input source files are real gameplay captures. The two recorded FPS rates is 60 and 120, however the benchmark tool can +encode at much higher rates if your hardware can support that. + +You can make your own conclusions about > 120 fps or < 60 fps bitrates that you'll need, since it's typically a linear +relationship. For example: + +```text +// these have been calculated as what you'd need for visually lossless quality +// notice how the 120fps requires twice the bitrate +720@60 H264 -> 10Mb/s +720@120 H264 -> 20Mb/s + +// you can guess that lower fps, and higher fps, will have a bitrate that scales accordingly: +720@30 H264 -> 5Mb/s +720@240 H264 -> 40Mb/s +``` + +_Note: if you play a different genre of game, or you have overlays in your OBS studio setup, your encoding performance +may vary. It is difficult/impossible to cover all possible inputs when benchmarking video encoding._ + +### Why results from one machine might not apply to another + +It can be difficult to determine what specific encoder settings would work best on your system without a lot of +trial and error. A few of the factors that can affect this: + +- GPU's encoder generation/hardware +- overall system's performance (combination of motherboard, CPU, and other factors such as storage/RAM) +- driver versions being used to encode the video files + +With this in mind, you may find that what works really well on your system, may not work the same on another's (even +with the same GPU hardware). This is why it's important to run the benchmark on your own system for specific +settings/capabilities of your entire setup. + +### Higher bitrate always increases vmaf score + +This is expected. By convention, using a low encoder preset/tune combination but allowing more data to be sent per +second, will mean a higher quality stream. + +This tool will help you find at what bitrate you reach your max achievable quality at given encoder settings, but if you +can afford it you can always increase the bitrate above that (with diminishing quality returns). This is almost always +the case with at-home game streaming where you're less bandwidth limited. + +Game streaming outside your network or over cellular is where you'll truly become bandwidth limited and where +this tool can be useful. + +### FPS Statistics Do Not Change Much with Higher Bitrates + +This is expected. The bitrate value is simply how much data to transmit _after the encode has happened_, and typically +does not affect how _fast_ +your encoder can encode an input. + +The tool defaults to not permuting over bitrate values due to this fact. The only reason you'd want to also permute over +bitrates or try higher values, is to get a higher vmaf score or to achieve visually lossless video quality. + +### Number of threads used by VMAF in tool + +The tool automatically chooses the maximum available threads on your machine (including hyper-threads). This ensures +maximum performance when doing vmaf calculations. + +There are diminishing returns the more threads you throw at VMAF, but these small gains will make a huge difference when +running through encoder permutations/benchmarks. + +Note: threads higher than your physical core count don't add any extra performance and are effectively +unused. The tool might be more robust in the future to calculate 1 thread per physical core but, there's no issue with +just specifying all threads. + +### Use of 'n_subsample' for calculation speedup in VMAF + +The tool uses a value of the parameter `n_subsample=5` passed to VMAF, to cut down the vmaf calculation to almost half. +This effectively tells VMAF to look every 5th frame when doing the score calculation. + +A negligible score difference of < 1 score point was observed when running through both low fps and high-fps +video content, with and without the use of `n_subsample`. + +Higher values than 5, at least for the 30 second video inputs began to show >= 2 score point differences and provided no +performance benefit. + +--- + +## Encoder Specific Notes + +### H264/HEVC NVENC + +#### Presets & Tunes + +Only the latest presets, i.e. `[p1-p7]` are being used, along with the following tunes: `[ll, ull, hq]` when testing +encoder permutations. All other legacy presets end up mapping to a combination of the mentioned presets/tunes and just +adds extra computation time. + +The use of the `lossless` tune or `lossless` preset effectively ignores the bitrate that you set, so these are not +included in permutations, since we're focused on specific/replicable bitrate targets with vmaf scores. + +#### Profiles + +It was determined that use of any other profile than `high` did not improve results; i.e. either lowered the vmaf score, +or did not increase the average fps. Thus, the tool is sticking to using 'high' for H264, and 'main' for HEVC. + +Documentation used for decisions made when using this codec: + +- + Nvenc Preset Migration Guide +- + Nvidia's Video Codec SDK Documentation + +--- + +## Expected Performance + +While building this tool, the author used specific GPU's for validation. Along the way, he was able to find the maximum +limit of the hardware he has available to him, as well as minimum bitrates needed to achieve visually lossless results. + +Hopefully performance details listed below will help you identify where your specific hardware lies relative to the +author's own system. + +### Minimum Spec'd PC + +- CPU: Intel i5-8400 (6 cores/6 threads) +- RAM: 16GB of G.Skill Ripjaws V DDR4 3200Mhz +- GPU: Asus GTX 1660 Super +- NVME SSD: PNY250GB NVMe PCI Gen3 x4 +- NVENC Arch & Gen: Turing, 7th Gen +- Nvidia Driver: 527.56 + +The following are the minimum bitrates you'd need to achieve visually lossless results on the above Turing GPU: + +Note: HEVC is about 30% more efficient but that doesn't appear to make that huge of a difference in your ending bitrate. + +```text +NVENC H264: 720@60 -> 10Mb/s +NVENC HEVC: 720@60 -> 5-10Mb/s + +NVENC H264: 720@120 -> 25Mb/s +NVENC HEVC: 720@120 -> 20-25Mb/s + +NVENC H264: 1080@60 -> 20Mb/s +NVENC HEVC: 1080@60 -> 15-20Mb/s + +NVENC H264: 1080@120 -> 40Mb/s +NVENC HEVC: 1080@120 -> 35-40Mb/s + +NVENC H264: 2K@60 -> 20-25Mb/s +NVENC HEVC: 2K@60 -> 20-25Mb/s + +NVENC H264: 2K@120 -> 50-55Mb/s +NVENC HEVC: 2K@120 -> 50Mb/s + +NVENC H264: 4K@60 -> 45-50Mb/s +NVENC HEVC: 4K@60 -> 40-45Mb/s + +// Note: Turing GPU used could not get any higher than 4K@75-90 average fps +// however, most likely the bitrate required for visually lossless 4K@120 is ~100Mb/s + +NVENC H264: 4K@120 -> ??? +NVENC HEVC: 4K@120 -> ??? +``` + +Notice that with HEVC you can achieve the same level of visually lossless quality with slightly less bitrate, at least +with NVENC. This is going to be the case with an AV1 encoder on newer GPU's. When at all possible, it's suggested to use +the encoder that provides higher quality at a lower bitrate. +--- + +## Issues, Bugs & Feature Requests + +Feel free to open issues in the repository if you find issues, and we'll try to get around to fixing them or +implementing the feature requests. + +Screenshots or log file uploads are much appreciated! + +--- + +## Contributing + +Project is written in Rust, with version `1.66.0` at time of writing. + +Setup your dev environment for Rust and you'll be able to contribute. \ No newline at end of file diff --git a/docs/obs-encoder-overload.png b/docs/obs-encoder-overload.png new file mode 100644 index 0000000..867743c Binary files /dev/null and b/docs/obs-encoder-overload.png differ diff --git a/references/nvidia-turing/1080-120-h264.txt b/references/nvidia-turing/1080-120-h264.txt new file mode 100644 index 0000000..785e72c --- /dev/null +++ b/references/nvidia-turing/1080-120-h264.txt @@ -0,0 +1,178 @@ +Results from entire permutation: +================================================================================================================================================================== +[Resolution] [FPS] [Bitrate] [Encode Time] [VMAF Time] [VMAF Score] [Encoder Settings] +1920x1080 120 5 32s 52s 49.99189 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 5 31s 51s 50.78878 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 5 31s 51s 49.87901 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 5 31s 51s 51.33805 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 5 31s 51s 47.46562 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 5 31s 51s 51.39954 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 5 31s 51s 47.82333 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 5 31s 51s 51.34720 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 5 32s 52s 50.41552 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 5 31s 51s 51.36192 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 5 32s 52s 50.62050 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 5 31s 51s 51.46517 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 10 31s 50s 70.29657 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 10 31s 50s 71.19142 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 10 31s 51s 69.25217 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 10 31s 51s 71.62771 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 10 31s 51s 66.86445 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 10 31s 50s 71.78528 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 10 31s 51s 66.76498 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 10 31s 52s 71.73936 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 10 32s 52s 69.62772 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 10 31s 50s 71.78707 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 10 32s 52s 69.94501 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 10 31s 50s 72.00939 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 15 31s 49s 79.79058 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 15 31s 50s 80.37565 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 15 31s 50s 79.43720 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 15 32s 49s 80.78581 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 15 31s 50s 77.39177 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 15 31s 49s 80.88729 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 15 31s 51s 77.23794 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 15 31s 50s 80.84431 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 15 32s 50s 79.28085 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 15 31s 49s 80.85456 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 15 33s 50s 79.57948 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 15 31s 49s 81.00658 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 20 31s 49s 85.08440 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 20 31s 49s 85.47128 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 20 31s 49s 84.99984 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 20 31s 49s 85.76170 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 20 31s 49s 83.66228 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 20 31s 49s 85.82275 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 20 31s 49s 83.43204 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 20 31s 49s 85.83939 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 20 32s 50s 84.54772 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 20 31s 49s 85.84438 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 20 33s 50s 84.80801 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 20 31s 49s 86.00859 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 25 31s 49s 88.25314 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 25 31s 48s 88.52682 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 25 31s 49s 88.38203 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 25 31s 50s 88.85011 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 25 31s 49s 87.33513 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 25 31s 49s 88.88587 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 25 31s 49s 87.18569 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 25 31s 49s 88.85275 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 25 32s 49s 87.82487 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 25 31s 49s 88.89854 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 25 33s 49s 88.00738 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 25 31s 49s 89.01835 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 30 31s 48s 90.36114 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 30 31s 48s 90.60395 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 30 31s 49s 90.70490 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 30 31s 49s 90.82680 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 30 31s 49s 89.70013 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 30 31s 49s 90.90486 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 30 31s 50s 89.63236 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 30 31s 49s 90.88116 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 30 32s 50s 89.98054 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 30 31s 48s 90.86143 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 30 33s 49s 90.14933 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 30 31s 48s 90.99081 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 35 31s 49s 91.86444 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 35 31s 48s 92.03297 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 35 31s 48s 92.23409 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 35 31s 48s 92.23190 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 35 31s 49s 91.42215 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 35 31s 49s 92.27628 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 35 31s 49s 91.33764 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 35 31s 49s 92.25399 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 35 32s 49s 91.46214 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 35 31s 48s 92.26575 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 35 33s 49s 91.57964 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 35 31s 48s 92.37749 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 40 31s 48s 92.97674 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 40 31s 49s 93.11378 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 40 31s 48s 93.38796 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 40 31s 49s 93.27600 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 40 31s 49s 92.60187 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 40 31s 48s 93.31536 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 40 31s 49s 92.58385 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 40 31s 48s 93.33156 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 40 32s 49s 92.55917 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 40 31s 48s 93.31236 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 40 !!! Overloaded !!! -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 40 31s 49s 93.38749 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 45 31s 48s 93.81015 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 45 31s 49s 93.93367 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 45 31s 49s 94.24088 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 45 31s 48s 94.08202 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 45 31s 49s 93.49768 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 45 31s 49s 94.09909 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 45 31s 49s 93.49147 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 45 31s 48s 94.09524 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 45 32s 49s 93.40893 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 45 31s 48s 94.10186 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 45 !!! Overloaded !!! -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 45 31s 49s 94.17725 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 50 31s 48s 94.43179 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 50 31s 48s 94.55545 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 50 31s 49s 94.84044 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 50 31s 48s 94.65708 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 50 31s 49s 94.21484 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 50 31s 48s 94.69174 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 50 31s 49s 94.17100 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 50 31s 48s 94.69593 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 50 32s 49s 94.04288 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 50 31s 48s 94.69225 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 50 !!! Overloaded !!! -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 50 31s 49s 94.74464 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 55 31s 48s 94.90863 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 55 31s 48s 95.00902 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 55 31s 48s 95.29723 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 55 31s 49s 95.10140 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 55 !!! Overloaded !!! -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 55 31s 48s 95.12882 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 55 31s 49s 94.71027 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 55 31s 49s 95.13551 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 55 32s 49s 94.54959 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 55 31s 48s 95.13809 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 120 55 !!! Overloaded !!! -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 120 55 31s 49s 95.18288 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +================================================================================================================================================================== +Benchmark runtime: 3h7m53s + +Encoder settings that produced identical scores: +================================================================================================================================================================== +Identical score: 49.991886 + Encoded: [-preset p1 -tune hq -profile:v high -rc cbr -cbr true] + Ignored: [-preset p1 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p1 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 50.788776 + Encoded: [-preset p2 -tune hq -profile:v high -rc cbr -cbr true] + Ignored: [-preset p2 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p2 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 51.338055 + Encoded: [-preset p3 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p3 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 51.399544 + Encoded: [-preset p4 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p4 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 51.347202 + Encoded: [-preset p5 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p5 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 51.36192 + Encoded: [-preset p6 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p6 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 51.465168 + Encoded: [-preset p7 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p7 -tune ull -profile:v high -rc cbr -cbr true] + + +================================================================================================================================================================== diff --git a/references/nvidia-turing/1080-120-hevc.txt b/references/nvidia-turing/1080-120-hevc.txt new file mode 100644 index 0000000..5beada4 --- /dev/null +++ b/references/nvidia-turing/1080-120-hevc.txt @@ -0,0 +1,138 @@ +Results from entire permutation: +================================================================================================================================================================== +[Resolution] [FPS] [Bitrate] [Encode Time] [VMAF Time] [VMAF Score] [Encoder Settings] +1920x1080 120 5 34s 53s 75.70850 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 5 31s 52s 75.75812 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 5 31s 52s 75.60134 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 5 31s 52s 75.51202 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 5 31s 52s 75.87301 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 5 31s 53s 74.97031 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 5 31s 51s 75.99516 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 5 31s 52s 75.06538 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 5 31s 51s 75.96230 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 5 31s 52s 75.27930 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 5 31s 52s 75.35414 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 5 31s 51s 76.03626 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 10 31s 51s 84.90907 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 10 31s 52s 85.13658 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 10 31s 51s 85.09588 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 10 31s 52s 84.74118 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 10 31s 52s 85.29262 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 10 !!! Overloaded !!! -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 10 31s 52s 85.41980 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 10 31s 52s 84.47678 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 10 31s 52s 85.43459 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 10 31s 52s 84.59978 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 10 31s 52s 84.62061 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 10 31s 52s 85.46388 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 15 31s 52s 89.01357 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 15 31s 52s 89.22966 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 15 31s 52s 89.23589 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 15 31s 52s 88.81435 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 15 31s 52s 89.39216 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 15 31s 52s 88.50737 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 15 31s 52s 89.47044 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 15 31s 52s 88.58233 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 15 31s 52s 89.48505 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 15 31s 53s 88.63686 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 15 31s 52s 88.64904 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 15 31s 52s 89.52385 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 20 31s 52s 91.29855 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 20 31s 52s 91.54755 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 20 31s 52s 91.48146 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 20 31s 52s 91.10006 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 20 31s 52s 91.63572 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 20 31s 53s 90.88873 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 20 31s 53s 91.72107 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 20 31s 53s 90.90729 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 20 31s 52s 91.72432 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 20 31s 53s 90.99638 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 20 31s 53s 91.01141 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 20 31s 53s 91.73863 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 25 31s 52s 92.73186 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 25 31s 53s 92.96626 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 25 31s 52s 92.90308 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 25 31s 53s 92.56429 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 25 31s 52s 92.99535 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 25 31s 53s 92.36080 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 25 31s 53s 93.09842 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 25 31s 53s 92.42175 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 25 31s 53s 93.11068 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 25 31s 53s 92.47523 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 25 31s 53s 92.49652 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 25 31s 53s 93.10513 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 30 31s 53s 93.72655 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 30 31s 53s 93.96207 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 30 31s 53s 93.85986 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 30 31s 53s 93.53531 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 30 31s 54s 93.94278 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 30 31s 53s 93.37828 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 30 31s 53s 94.02118 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 30 31s 53s 93.44228 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 30 31s 53s 94.02806 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 30 31s 53s 93.49054 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 30 31s 53s 93.49233 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 30 31s 54s 94.03491 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 35 31s 53s 94.42563 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 35 31s 53s 94.65247 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 35 31s 53s 94.54723 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 35 31s 53s 94.24657 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 35 31s 53s 94.62567 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 35 31s 53s 94.12370 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 35 31s 54s 94.69470 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 35 31s 53s 94.16495 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 35 31s 53s 94.70782 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 35 31s 54s 94.21577 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 35 31s 54s 94.21889 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 35 31s 53s 94.71122 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 40 31s 54s 94.94276 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 40 31s 53s 95.15784 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 40 31s 53s 95.06442 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 40 31s 53s 94.79282 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 40 31s 53s 95.13419 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 40 !!! Overloaded !!! -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 40 31s 54s 95.19332 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 40 31s 54s 94.73313 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 40 31s 54s 95.19762 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 120 40 31s 55s 94.77101 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 40 31s 54s 94.76874 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 120 40 31s 54s 95.20499 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +================================================================================================================================================================== +Benchmark runtime: 2h26m35s + +Encoder settings that produced identical scores: +================================================================================================================================================================== +Identical score: 75.7085 + Encoded: [-preset p1 -tune hq -profile:v main -rc cbr -cbr true] + Ignored: [-preset p1 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p1 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 75.60134 + Encoded: [-preset p2 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p2 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 75.87301 + Encoded: [-preset p3 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p3 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 75.995155 + Encoded: [-preset p4 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p4 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 75.962296 + Encoded: [-preset p5 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p5 -tune ull -profile:v main -rc cbr -cbr true] + Ignored: [-preset p6 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p6 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 76.03626 + Encoded: [-preset p7 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p7 -tune ull -profile:v main -rc cbr -cbr true] + + +================================================================================================================================================================== diff --git a/references/nvidia-turing/1080-60-h264.txt b/references/nvidia-turing/1080-60-h264.txt new file mode 100644 index 0000000..fda782f --- /dev/null +++ b/references/nvidia-turing/1080-60-h264.txt @@ -0,0 +1,106 @@ +Results from entire permutation: +================================================================================================================================================================== +[Resolution] [FPS] [Bitrate] [Encode Time] [VMAF Time] [VMAF Score] [Encoder Settings] +1920x1080 60 5 16s 27s 74.50902 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 5 16s 27s 75.34191 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 5 16s 26s 72.95963 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 5 16s 26s 75.88480 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 5 16s 26s 69.81652 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 5 16s 26s 76.10236 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 5 16s 26s 69.58448 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 5 16s 26s 75.95850 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 5 16s 27s 73.08858 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 5 15s 27s 75.94342 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 5 16s 27s 73.41910 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 5 16s 26s 76.35578 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 10 16s 26s 87.40918 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 10 15s 26s 87.76508 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 10 16s 26s 86.76790 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 10 16s 26s 88.10063 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 10 16s 26s 84.52326 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 10 16s 26s 88.20581 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 10 16s 26s 84.22622 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 10 15s 26s 88.14150 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 10 16s 27s 86.50469 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 10 15s 26s 88.17024 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 10 17s 27s 86.74608 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 10 16s 25s 88.36306 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 15 16s 25s 91.88810 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 15 16s 25s 92.09664 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 15 16s 26s 91.67593 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 15 16s 25s 92.31938 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 15 16s 25s 90.19402 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 15 16s 26s 92.39477 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 15 16s 26s 90.05708 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 15 16s 25s 92.38586 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 15 16s 26s 91.29316 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 15 16s 26s 92.37621 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 15 17s 26s 91.50388 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 15 16s 25s 92.51978 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 20 15s 25s 94.03944 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 20 15s 25s 94.21046 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 20 16s 25s 93.98454 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 20 16s 25s 94.35272 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 20 16s 25s 92.95072 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 20 15s 25s 94.41286 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 20 16s 25s 92.90145 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 20 16s 25s 94.42652 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 20 16s 25s 93.64183 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 20 15s 25s 94.46563 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 20 17s 25s 93.73206 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 20 16s 25s 94.52225 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 25 15s 25s 95.30466 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 25 16s 25s 95.42963 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 25 16s 25s 95.32159 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 25 16s 25s 95.57478 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 25 16s 25s 94.45645 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 25 15s 25s 95.58061 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 25 16s 25s 94.48894 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 25 15s 25s 95.59511 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 25 16s 25s 94.98222 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 25 15s 25s 95.62213 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1920x1080 60 25 18s 26s 95.07385 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1920x1080 60 25 16s 25s 95.67976 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +================================================================================================================================================================== +Benchmark runtime: 48m43s + +Encoder settings that produced identical scores: +================================================================================================================================================================== +Identical score: 74.50902 + Encoded: [-preset p1 -tune hq -profile:v high -rc cbr -cbr true] + Ignored: [-preset p1 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p1 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 75.34191 + Encoded: [-preset p2 -tune hq -profile:v high -rc cbr -cbr true] + Ignored: [-preset p2 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p2 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 75.8848 + Encoded: [-preset p3 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p3 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 76.102356 + Encoded: [-preset p4 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p4 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 75.9585 + Encoded: [-preset p5 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p5 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 75.94342 + Encoded: [-preset p6 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p6 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 76.35578 + Encoded: [-preset p7 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p7 -tune ull -profile:v high -rc cbr -cbr true] + + +================================================================================================================================================================== diff --git a/references/nvidia-turing/1080-60-hevc.txt b/references/nvidia-turing/1080-60-hevc.txt new file mode 100644 index 0000000..309ca28 --- /dev/null +++ b/references/nvidia-turing/1080-60-hevc.txt @@ -0,0 +1,90 @@ +Results from entire permutation: +================================================================================================================================================================== +[Resolution] [FPS] [Bitrate] [Encode Time] [VMAF Time] [VMAF Score] [Encoder Settings] +1920x1080 60 5 16s 27s 85.60248 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 5 16s 27s 85.82336 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 5 16s 27s 85.94729 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 5 16s 27s 85.24741 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 5 16s 28s 86.19556 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 5 16s 28s 84.77348 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 5 16s 27s 86.34673 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 5 16s 27s 84.80721 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 5 16s 26s 86.33817 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 5 16s 26s 84.88064 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 5 16s 26s 84.92223 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 5 15s 26s 86.38570 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 10 16s 26s 91.63816 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 10 16s 28s 91.76040 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 10 15s 26s 91.92679 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 10 16s 27s 91.33148 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 10 16s 27s 92.11054 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 10 16s 27s 90.96395 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 10 15s 26s 92.18690 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 10 16s 27s 90.99364 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 10 16s 27s 92.19357 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 10 16s 27s 91.01091 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 10 16s 27s 91.04804 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 10 15s 26s 92.23741 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 15 16s 27s 94.10514 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 15 16s 27s 94.06136 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 15 16s 27s 94.29094 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 15 16s 28s 93.70378 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 15 15s 27s 94.40025 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 15 16s 27s 93.46300 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 15 16s 27s 94.48074 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 15 16s 27s 93.49157 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 15 16s 27s 94.47823 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 15 16s 27s 93.53397 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 15 16s 27s 93.55904 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 15 16s 27s 94.50688 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 20 15s 27s 95.33635 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 20 16s 27s 95.34302 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 20 16s 27s 95.46912 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 20 16s 28s 94.97389 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 20 16s 28s 95.54969 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 20 16s 28s 94.80326 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 20 15s 28s 95.62080 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 20 16s 27s 94.80145 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 20 16s 27s 95.60349 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1920x1080 60 20 16s 27s 94.86880 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 20 16s 28s 94.88090 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1920x1080 60 20 15s 27s 95.64832 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +================================================================================================================================================================== +Benchmark runtime: 41m31s + +Encoder settings that produced identical scores: +================================================================================================================================================================== +Identical score: 85.60248 + Encoded: [-preset p1 -tune hq -profile:v main -rc cbr -cbr true] + Ignored: [-preset p1 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p1 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 85.94729 + Encoded: [-preset p2 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p2 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 86.19556 + Encoded: [-preset p3 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p3 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 86.346725 + Encoded: [-preset p4 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p4 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 86.33817 + Encoded: [-preset p5 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p5 -tune ull -profile:v main -rc cbr -cbr true] + Ignored: [-preset p6 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p6 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 86.385704 + Encoded: [-preset p7 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p7 -tune ull -profile:v main -rc cbr -cbr true] + + +================================================================================================================================================================== diff --git a/references/nvidia-turing/4k-60-h264.txt b/references/nvidia-turing/4k-60-h264.txt new file mode 100644 index 0000000..35246fc --- /dev/null +++ b/references/nvidia-turing/4k-60-h264.txt @@ -0,0 +1,158 @@ +Results from entire permutation: +================================================================================================================================================================== +[Resolution] [FPS] [Bitrate] [Encode Time] [VMAF Time] [VMAF Score] [Encoder Settings] +3840x2160 60 10 18s 1m28s 76.68040 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 10 22s 1m28s 77.12575 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 10 23s 1m28s 75.60857 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 10 23s 1m28s 77.59946 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 10 24s 1m28s 72.22140 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 10 24s 1m28s 77.67113 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 10 30s 1m29s 72.37341 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 10 30s 1m29s 77.74998 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 10 32s 1m30s 75.76579 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 10 30s 1m29s 77.74480 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 10 !!! Overloaded !!! -preset p7 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 10 !!! Overloaded !!! -preset p7 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 10 !!! Overloaded !!! -preset p7 -tune ull -profile:v high -rc cbr -cbr true +3840x2160 60 15 23s 1m27s 83.70285 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 15 26s 1m27s 84.04021 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 15 26s 1m27s 82.89784 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 15 26s 1m27s 84.46037 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 15 27s 1m27s 79.77464 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 15 27s 1m27s 84.53457 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 15 30s 1m28s 79.90364 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 15 30s 1m28s 84.54087 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 15 32s 1m29s 82.87410 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 15 30s 1m28s 84.49250 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 15 !!! Overloaded !!! -preset p7 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 15 !!! Overloaded !!! -preset p7 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 15 !!! Overloaded !!! -preset p7 -tune ull -profile:v high -rc cbr -cbr true +3840x2160 60 20 23s 1m26s 87.77959 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 20 26s 1m29s 88.03502 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 20 26s 1m27s 87.16351 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 20 26s 1m26s 88.34522 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 20 27s 1m27s 84.60921 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 20 26s 1m26s 88.39782 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 20 30s 1m27s 84.66978 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 20 30s 1m27s 88.43704 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 20 32s 1m27s 87.11238 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 20 30s 1m29s 88.46435 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 20 !!! Overloaded !!! -preset p7 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 20 !!! Overloaded !!! -preset p7 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 20 !!! Overloaded !!! -preset p7 -tune ull -profile:v high -rc cbr -cbr true +3840x2160 60 25 23s 1m26s 90.09315 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 25 26s 1m26s 90.30676 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 25 26s 1m29s 89.69839 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 25 26s 1m26s 90.60007 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 25 26s 1m26s 87.49775 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 25 26s 1m26s 90.59245 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 25 30s 1m27s 87.54654 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 25 30s 1m26s 90.67023 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 25 32s 1m27s 89.56701 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 25 30s 1m26s 90.65359 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 25 !!! Overloaded !!! -preset p7 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 25 !!! Overloaded !!! -preset p7 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 25 !!! Overloaded !!! -preset p7 -tune ull -profile:v high -rc cbr -cbr true +3840x2160 60 30 23s 1m26s 91.81829 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 30 26s 1m26s 92.04691 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 30 26s 1m26s 91.43076 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 30 27s 1m26s 92.27461 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 30 27s 1m26s 89.51134 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 30 26s 1m26s 92.28146 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 30 30s 1m28s 89.55003 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 30 30s 1m26s 92.29030 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 30 32s 1m26s 91.26761 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 30 30s 1m26s 92.32927 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 30 !!! Overloaded !!! -preset p7 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 30 !!! Overloaded !!! -preset p7 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 30 !!! Overloaded !!! -preset p7 -tune ull -profile:v high -rc cbr -cbr true +3840x2160 60 35 23s 1m26s 93.13573 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 35 27s 1m26s 93.29479 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 35 26s 1m26s 92.68586 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 35 27s 1m26s 93.47095 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 35 27s 1m26s 91.12012 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 35 27s 1m26s 93.52312 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 35 30s 1m26s 91.13619 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 35 30s 1m26s 93.55276 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 35 32s 1m27s 92.51475 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 35 30s 1m27s 93.53512 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 35 !!! Overloaded !!! -preset p7 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 35 !!! Overloaded !!! -preset p7 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 35 !!! Overloaded !!! -preset p7 -tune ull -profile:v high -rc cbr -cbr true +3840x2160 60 40 23s 1m26s 93.97160 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 40 27s 1m26s 94.12282 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 40 27s 1m26s 93.52248 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 40 27s 1m26s 94.30790 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 40 27s 1m27s 92.10780 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 40 27s 1m26s 94.29990 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 40 30s 1m26s 92.16416 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 40 30s 1m26s 94.35481 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 40 32s 1m27s 93.40947 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 40 30s 1m26s 94.35061 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 40 !!! Overloaded !!! -preset p7 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 40 !!! Overloaded !!! -preset p7 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 40 !!! Overloaded !!! -preset p7 -tune ull -profile:v high -rc cbr -cbr true +3840x2160 60 45 23s 1m26s 94.68674 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 45 27s 1m26s 94.80742 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 45 27s 1m26s 94.28408 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 45 27s 1m26s 94.96565 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 45 27s 1m26s 92.99207 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 45 27s 1m26s 94.97440 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 45 30s 1m27s 93.06584 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 45 30s 1m27s 94.98957 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 45 32s 1m30s 94.08474 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 45 30s 1m27s 94.98637 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 45 !!! Overloaded !!! -preset p7 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 45 !!! Overloaded !!! -preset p7 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 45 !!! Overloaded !!! -preset p7 -tune ull -profile:v high -rc cbr -cbr true +3840x2160 60 50 23s 1m26s 95.23787 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 50 27s 1m26s 95.30165 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 50 27s 1m26s 94.80300 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 50 27s 1m26s 95.41363 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 50 27s 1m29s 93.70727 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 50 27s 1m26s 95.45330 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 50 30s 1m27s 93.78199 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 50 30s 1m27s 95.47023 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 50 32s 1m27s 94.61900 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 50 30s 1m26s 95.45727 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 50 !!! Overloaded !!! -preset p7 -tune hq -profile:v high -rc cbr -cbr true +3840x2160 60 50 !!! Overloaded !!! -preset p7 -tune ll -profile:v high -rc cbr -cbr true +3840x2160 60 50 !!! Overloaded !!! -preset p7 -tune ull -profile:v high -rc cbr -cbr true +================================================================================================================================================================== +Benchmark runtime: 3h18m7s + +Encoder settings that produced identical scores: +================================================================================================================================================================== +Identical score: 76.680405 + Encoded: [-preset p1 -tune hq -profile:v high -rc cbr -cbr true] + Ignored: [-preset p1 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p1 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 77.12575 + Encoded: [-preset p2 -tune hq -profile:v high -rc cbr -cbr true] + Ignored: [-preset p2 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p2 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 77.599464 + Encoded: [-preset p3 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p3 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 77.671135 + Encoded: [-preset p4 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p4 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 77.749985 + Encoded: [-preset p5 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p5 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 77.744804 + Encoded: [-preset p6 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p6 -tune ull -profile:v high -rc cbr -cbr true] + + +================================================================================================================================================================== diff --git a/references/nvidia-turing/4k-60-hevc.txt b/references/nvidia-turing/4k-60-hevc.txt new file mode 100644 index 0000000..9528995 --- /dev/null +++ b/references/nvidia-turing/4k-60-hevc.txt @@ -0,0 +1,150 @@ +Results from entire permutation: +================================================================================================================================================================== +[Resolution] [FPS] [Bitrate] [Encode Time] [VMAF Time] [VMAF Score] [Encoder Settings] +3840x2160 60 10 26s 1m32s 82.95334 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 10 23s 1m29s 83.13516 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 10 23s 1m29s 83.18951 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 10 23s 1m29s 82.32758 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 10 23s 1m29s 83.54450 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 10 23s 1m29s 81.85211 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 10 24s 1m29s 83.57703 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 10 23s 1m29s 82.00096 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 10 26s 1m29s 83.56860 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 10 !!! Overloaded !!! -preset p6 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 10 !!! Overloaded !!! -preset p7 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 10 26s 1m29s 83.65735 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 15 23s 1m29s 87.24523 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 15 23s 1m29s 87.25827 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 15 23s 1m29s 87.53083 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 15 23s 1m30s 86.49188 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 15 23s 1m29s 87.77304 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 15 23s 1m30s 86.14337 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 15 24s 1m32s 87.88035 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 15 24s 1m29s 86.20297 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 15 27s 1m29s 87.86755 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 15 !!! Overloaded !!! -preset p6 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 15 !!! Overloaded !!! -preset p7 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 15 27s 1m29s 87.90140 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 20 23s 1m29s 89.75600 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 20 23s 1m29s 89.71399 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 20 23s 1m29s 90.07269 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 20 23s 1m29s 89.01703 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 20 23s 1m29s 90.28008 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 20 23s 1m29s 88.67458 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 20 24s 1m29s 90.35348 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 20 24s 1m29s 88.73602 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 20 27s 1m29s 90.37288 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 20 !!! Overloaded !!! -preset p6 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 20 !!! Overloaded !!! -preset p7 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 20 27s 1m29s 90.42415 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 25 22s 1m29s 91.34556 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 25 23s 1m29s 91.26055 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 25 22s 1m29s 91.59132 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 25 23s 1m29s 90.58596 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 25 23s 1m29s 91.76597 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 25 23s 1m29s 90.27117 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 25 25s 1m29s 91.85982 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 25 24s 1m29s 90.33717 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 25 27s 1m29s 91.85974 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 25 !!! Overloaded !!! -preset p6 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 25 !!! Overloaded !!! -preset p7 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 25 27s 1m29s 91.91479 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 30 23s 1m29s 92.51829 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 30 22s 1m29s 92.36660 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 30 23s 1m29s 92.81517 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 30 23s 1m29s 91.78934 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 30 23s 1m29s 92.92507 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 30 23s 1m29s 91.51199 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 30 25s 1m29s 93.00259 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 30 24s 1m29s 91.56116 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 30 27s 1m30s 93.00529 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 30 !!! Overloaded !!! -preset p6 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 30 !!! Overloaded !!! -preset p7 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 30 27s 1m29s 93.02785 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 35 23s 1m27s 93.42834 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 35 23s 1m27s 93.21355 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 35 23s 1m29s 93.59796 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 35 23s 1m27s 92.66579 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 35 23s 1m29s 93.72364 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 35 23s 1m27s 92.42847 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 35 25s 1m29s 93.79159 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 35 25s 1m29s 92.47926 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 35 27s 1m30s 93.78342 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 35 !!! Overloaded !!! -preset p6 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 35 !!! Overloaded !!! -preset p7 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 35 27s 1m30s 93.82080 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 40 23s 1m29s 94.10795 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 40 24s 1m29s 93.88819 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 40 23s 1m28s 94.27808 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 40 23s 1m28s 93.41139 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 40 23s 1m28s 94.34898 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 40 23s 1m28s 93.20591 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 40 25s 1m28s 94.45242 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 40 25s 1m28s 93.26141 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 40 27s 1m28s 94.43142 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 40 !!! Overloaded !!! -preset p6 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 40 !!! Overloaded !!! -preset p7 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 40 27s 1m28s 94.48958 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 45 23s 1m27s 94.61506 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 45 23s 1m27s 94.40565 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 45 23s 1m27s 94.78809 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 45 23s 1m27s 93.99464 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 45 23s 1m27s 94.83579 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 45 23s 1m27s 93.78939 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 45 25s 1m27s 94.87885 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 45 25s 1m27s 93.83456 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 45 27s 1m28s 94.89469 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 45 !!! Overloaded !!! -preset p6 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 45 !!! Overloaded !!! -preset p7 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 45 27s 1m28s 94.92305 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 50 23s 1m27s 95.03426 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 50 23s 1m27s 94.84890 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 50 23s 1m27s 95.16911 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 50 23s 1m27s 94.45891 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 50 23s 1m27s 95.24308 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 50 23s 1m27s 94.30659 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 50 25s 1m27s 95.29591 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 50 25s 1m27s 94.35288 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 50 27s 1m28s 95.28676 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +3840x2160 60 50 !!! Overloaded !!! -preset p6 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 50 !!! Overloaded !!! -preset p7 -tune hq -profile:v main -rc cbr -cbr true +3840x2160 60 50 27s 1m27s 95.34104 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +================================================================================================================================================================== +Benchmark runtime: 3h10m33s + +Encoder settings that produced identical scores: +================================================================================================================================================================== +Identical score: 82.95334 + Encoded: [-preset p1 -tune hq -profile:v main -rc cbr -cbr true] + Ignored: [-preset p1 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p1 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 83.18951 + Encoded: [-preset p2 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p2 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 83.5445 + Encoded: [-preset p3 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p3 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 83.57703 + Encoded: [-preset p4 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p4 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 83.5686 + Encoded: [-preset p5 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p5 -tune ull -profile:v main -rc cbr -cbr true] + Ignored: [-preset p6 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p6 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 83.65735 + Encoded: [-preset p7 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p7 -tune ull -profile:v main -rc cbr -cbr true] + + +================================================================================================================================================================== diff --git a/references/nvidia-turing/720-120-h264.txt b/references/nvidia-turing/720-120-h264.txt new file mode 100644 index 0000000..701f9e3 --- /dev/null +++ b/references/nvidia-turing/720-120-h264.txt @@ -0,0 +1,130 @@ +Results from entire permutation: +================================================================================================================================================================== +[Resolution] [FPS] [Bitrate] [Encode Time] [VMAF Time] [VMAF Score] [Encoder Settings] +1280x720 120 5 13s 21s 64.90092 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 5 13s 21s 65.52699 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 5 13s 22s 64.28435 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 5 13s 21s 66.20261 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 5 13s 22s 62.64022 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 5 13s 22s 66.50801 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 5 13s 22s 62.48967 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 5 13s 21s 66.51543 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 5 14s 22s 64.30239 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 5 13s 22s 66.50776 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 5 14s 23s 64.78190 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 5 13s 21s 66.71972 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 10 13s 21s 82.38084 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 10 13s 21s 82.72018 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 10 13s 21s 82.60147 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 10 13s 21s 83.15195 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 10 13s 22s 81.58021 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 10 13s 21s 83.26570 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 10 13s 22s 81.42077 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 10 13s 21s 83.26820 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 10 14s 22s 81.93056 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 10 13s 21s 83.32438 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 10 14s 22s 82.17594 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 10 13s 21s 83.42992 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 15 13s 21s 88.64359 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 15 13s 21s 88.86626 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 15 13s 21s 88.99073 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 15 13s 21s 89.15865 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 15 13s 21s 88.18552 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 15 13s 21s 89.26521 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 15 13s 21s 88.10307 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 15 13s 21s 89.23954 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 15 14s 21s 88.10242 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 15 13s 21s 89.25559 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 15 14s 22s 88.28796 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 15 13s 21s 89.32179 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 20 13s 21s 91.76273 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 20 13s 21s 91.92176 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 20 13s 21s 92.09645 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 20 13s 21s 92.14625 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 20 13s 21s 91.37338 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 20 13s 21s 92.18753 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 20 13s 21s 91.32249 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 20 13s 21s 92.21945 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 20 14s 22s 91.23981 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 20 13s 21s 92.21704 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 20 14s 21s 91.31812 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 20 13s 21s 92.26194 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 25 13s 21s 93.54258 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 25 13s 21s 93.64291 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 25 13s 21s 93.87661 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 25 13s 21s 93.83606 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 25 13s 21s 93.26871 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 25 13s 21s 93.90572 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 25 13s 21s 93.24361 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 25 13s 21s 93.90061 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 25 14s 21s 93.12077 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 25 13s 21s 93.90311 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 25 14s 21s 93.20306 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 25 13s 21s 93.92645 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 30 13s 21s 94.72880 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 30 13s 21s 94.79089 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 30 13s 21s 94.97000 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 30 13s 21s 94.91792 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 30 13s 21s 94.43682 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 30 13s 21s 94.96603 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 30 13s 21s 94.45422 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 30 13s 21s 94.96150 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 30 14s 21s 94.33981 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 30 13s 21s 94.95192 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 30 14s 21s 94.38073 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 30 13s 21s 94.99083 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 35 13s 20s 95.48203 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 35 13s 21s 95.53185 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 35 13s 21s 95.73418 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 35 13s 20s 95.66804 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 35 13s 21s 95.25681 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 35 13s 21s 95.69057 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 35 13s 21s 95.24973 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 35 13s 20s 95.71408 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 35 14s 22s 95.13821 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 35 13s 21s 95.70564 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1280x720 120 35 14s 21s 95.16508 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1280x720 120 35 13s 21s 95.71584 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +================================================================================================================================================================== +Benchmark runtime: 54m39s + +Encoder settings that produced identical scores: +================================================================================================================================================================== +Identical score: 64.90092 + Encoded: [-preset p1 -tune hq -profile:v high -rc cbr -cbr true] + Ignored: [-preset p1 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p1 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 65.52699 + Encoded: [-preset p2 -tune hq -profile:v high -rc cbr -cbr true] + Ignored: [-preset p2 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p2 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 66.202614 + Encoded: [-preset p3 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p3 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 66.50801 + Encoded: [-preset p4 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p4 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 66.515434 + Encoded: [-preset p5 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p5 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 66.50776 + Encoded: [-preset p6 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p6 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 66.71972 + Encoded: [-preset p7 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p7 -tune ull -profile:v high -rc cbr -cbr true] + + +================================================================================================================================================================== diff --git a/references/nvidia-turing/720-120-hevc.txt b/references/nvidia-turing/720-120-hevc.txt new file mode 100644 index 0000000..b2d4336 --- /dev/null +++ b/references/nvidia-turing/720-120-hevc.txt @@ -0,0 +1,114 @@ +Results from entire permutation: +================================================================================================================================================================== +[Resolution] [FPS] [Bitrate] [Encode Time] [VMAF Time] [VMAF Score] [Encoder Settings] +1280x720 120 5 13s 24s 79.96729 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 5 13s 21s 80.34641 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 5 13s 21s 80.04669 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 5 13s 21s 79.97925 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 5 13s 21s 80.37294 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 5 13s 22s 79.36954 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 5 13s 21s 80.61272 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 5 13s 22s 79.51860 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 5 13s 21s 80.61639 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 5 13s 22s 79.73672 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 5 13s 22s 79.71426 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 5 13s 21s 80.70410 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 10 13s 21s 88.31471 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 10 13s 21s 88.68100 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 10 13s 21s 88.46787 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 10 13s 21s 88.34640 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 10 13s 21s 88.64894 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 10 13s 21s 87.82439 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 10 13s 21s 88.79509 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 10 13s 21s 87.94421 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 10 13s 21s 88.81303 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 10 13s 21s 88.09540 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 10 13s 21s 88.11457 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 10 13s 21s 88.84178 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 15 13s 21s 91.73531 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 15 13s 21s 91.96697 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 15 13s 21s 91.84264 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 15 13s 21s 91.68526 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 15 13s 21s 91.96220 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 15 13s 21s 91.24697 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 15 13s 21s 92.06578 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 15 13s 21s 91.32030 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 15 13s 21s 92.06978 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 15 13s 21s 91.41628 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 15 13s 21s 91.47504 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 15 13s 21s 92.11024 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 20 13s 21s 93.54683 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 20 13s 21s 93.75029 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 20 13s 21s 93.62348 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 20 13s 21s 93.49738 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 20 13s 21s 93.72205 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 20 13s 21s 93.09705 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 20 13s 21s 93.79974 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 20 13s 21s 93.17129 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 20 13s 21s 93.80541 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 20 13s 21s 93.26453 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 20 13s 21s 93.28241 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 20 13s 21s 93.82545 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 25 13s 21s 94.66199 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 25 13s 21s 94.86075 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 25 13s 21s 94.74052 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 25 13s 21s 94.57156 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 25 13s 21s 94.80500 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 25 13s 21s 94.30806 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 25 13s 21s 94.84731 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 25 13s 21s 94.34428 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 25 13s 21s 94.88469 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 25 13s 21s 94.44082 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 25 13s 21s 94.45293 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 25 13s 21s 94.87225 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 30 13s 21s 95.40022 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 30 13s 21s 95.58849 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 30 13s 21s 95.46679 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 30 13s 21s 95.33219 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 30 13s 21s 95.52958 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 30 13s 21s 95.08572 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 30 13s 21s 95.58263 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 30 13s 22s 95.10243 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 30 13s 21s 95.58719 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1280x720 120 30 13s 22s 95.18350 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 30 13s 22s 95.19385 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1280x720 120 30 13s 21s 95.57690 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +================================================================================================================================================================== +Benchmark runtime: 47m31s + +Encoder settings that produced identical scores: +================================================================================================================================================================== +Identical score: 79.967285 + Encoded: [-preset p1 -tune hq -profile:v main -rc cbr -cbr true] + Ignored: [-preset p1 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p1 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 80.04669 + Encoded: [-preset p2 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p2 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 80.37294 + Encoded: [-preset p3 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p3 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 80.612724 + Encoded: [-preset p4 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p4 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 80.61639 + Encoded: [-preset p5 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p5 -tune ull -profile:v main -rc cbr -cbr true] + Ignored: [-preset p6 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p6 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 80.7041 + Encoded: [-preset p7 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p7 -tune ull -profile:v main -rc cbr -cbr true] + + +================================================================================================================================================================== diff --git a/references/nvidia-turing/720-60-h264.txt b/references/nvidia-turing/720-60-h264.txt new file mode 100644 index 0000000..2ba0f6a --- /dev/null +++ b/references/nvidia-turing/720-60-h264.txt @@ -0,0 +1,82 @@ +Results from entire permutation: +================================================================================================================================================================== +[Resolution] [FPS] [Bitrate] [Encode Time] [VMAF Time] [VMAF Score] [Encoder Settings] +1280x720 60 5 7s 12s 76.79397 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 5 6s 11s 77.43787 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 5 6s 11s 76.78555 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 5 7s 11s 78.04528 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1280x720 60 5 7s 11s 74.96706 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 5 7s 11s 78.24430 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1280x720 60 5 7s 11s 74.68017 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 5 7s 11s 78.27507 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1280x720 60 5 7s 11s 76.26791 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 5 6s 11s 78.36836 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1280x720 60 5 7s 11s 76.65379 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 5 7s 11s 78.58556 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1280x720 60 10 6s 11s 91.65628 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 10 6s 11s 91.92998 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 10 6s 11s 91.33750 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 10 7s 11s 92.28779 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1280x720 60 10 7s 11s 90.38431 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 10 6s 11s 92.36864 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1280x720 60 10 7s 11s 90.33647 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 10 6s 11s 92.39465 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1280x720 60 10 7s 11s 90.97400 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 10 7s 11s 92.41976 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1280x720 60 10 8s 11s 91.17747 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 10 7s 11s 92.61568 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +1280x720 60 15 7s 10s 96.41919 -preset p1 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 15 7s 10s 96.50824 -preset p2 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 15 7s 10s 96.05845 -preset p3 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 15 6s 10s 96.73878 -preset p3 -tune ll -profile:v high -rc cbr -cbr true +1280x720 60 15 7s 11s 95.51065 -preset p4 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 15 6s 10s 96.76241 -preset p4 -tune ll -profile:v high -rc cbr -cbr true +1280x720 60 15 7s 11s 95.48296 -preset p5 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 15 6s 10s 96.75915 -preset p5 -tune ll -profile:v high -rc cbr -cbr true +1280x720 60 15 7s 11s 95.69723 -preset p6 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 15 7s 10s 96.79721 -preset p6 -tune ll -profile:v high -rc cbr -cbr true +1280x720 60 15 8s 11s 95.77204 -preset p7 -tune hq -profile:v high -rc cbr -cbr true +1280x720 60 15 7s 10s 96.91981 -preset p7 -tune ll -profile:v high -rc cbr -cbr true +================================================================================================================================================================== +Benchmark runtime: 13m47s + +Encoder settings that produced identical scores: +================================================================================================================================================================== +Identical score: 76.79397 + Encoded: [-preset p1 -tune hq -profile:v high -rc cbr -cbr true] + Ignored: [-preset p1 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p1 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 77.437874 + Encoded: [-preset p2 -tune hq -profile:v high -rc cbr -cbr true] + Ignored: [-preset p2 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p2 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 78.04528 + Encoded: [-preset p3 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p3 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 78.2443 + Encoded: [-preset p4 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p4 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 78.27507 + Encoded: [-preset p5 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p5 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 78.36836 + Encoded: [-preset p6 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p6 -tune ull -profile:v high -rc cbr -cbr true] + + +Identical score: 78.585556 + Encoded: [-preset p7 -tune ll -profile:v high -rc cbr -cbr true] + Ignored: [-preset p7 -tune ull -profile:v high -rc cbr -cbr true] + + +================================================================================================================================================================== diff --git a/references/nvidia-turing/720-60-hevc.txt b/references/nvidia-turing/720-60-hevc.txt new file mode 100644 index 0000000..8624e0d --- /dev/null +++ b/references/nvidia-turing/720-60-hevc.txt @@ -0,0 +1,66 @@ +Results from entire permutation: +================================================================================================================================================================== +[Resolution] [FPS] [Bitrate] [Encode Time] [VMAF Time] [VMAF Score] [Encoder Settings] +1280x720 60 5 7s 12s 87.81937 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1280x720 60 5 7s 11s 87.46878 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1280x720 60 5 7s 11s 88.16201 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1280x720 60 5 7s 11s 86.93813 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1280x720 60 5 7s 11s 88.47124 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1280x720 60 5 7s 11s 86.83495 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1280x720 60 5 7s 11s 88.70048 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1280x720 60 5 7s 11s 86.93332 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1280x720 60 5 7s 11s 88.76997 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1280x720 60 5 7s 11s 87.09824 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1280x720 60 5 7s 11s 87.19379 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1280x720 60 5 7s 11s 88.81657 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +1280x720 60 10 7s 11s 95.54867 -preset p1 -tune hq -profile:v main -rc cbr -cbr true +1280x720 60 10 7s 11s 95.08237 -preset p2 -tune hq -profile:v main -rc cbr -cbr true +1280x720 60 10 7s 11s 95.81278 -preset p2 -tune ll -profile:v main -rc cbr -cbr true +1280x720 60 10 7s 11s 94.76284 -preset p3 -tune hq -profile:v main -rc cbr -cbr true +1280x720 60 10 7s 11s 95.99773 -preset p3 -tune ll -profile:v main -rc cbr -cbr true +1280x720 60 10 7s 11s 94.63972 -preset p4 -tune hq -profile:v main -rc cbr -cbr true +1280x720 60 10 7s 11s 96.08380 -preset p4 -tune ll -profile:v main -rc cbr -cbr true +1280x720 60 10 7s 11s 94.70326 -preset p5 -tune hq -profile:v main -rc cbr -cbr true +1280x720 60 10 7s 11s 96.10679 -preset p5 -tune ll -profile:v main -rc cbr -cbr true +1280x720 60 10 7s 11s 94.79017 -preset p6 -tune hq -profile:v main -rc cbr -cbr true +1280x720 60 10 7s 11s 94.81934 -preset p7 -tune hq -profile:v main -rc cbr -cbr true +1280x720 60 10 7s 11s 96.15588 -preset p7 -tune ll -profile:v main -rc cbr -cbr true +================================================================================================================================================================== +Benchmark runtime: 10m15s + +Encoder settings that produced identical scores: +================================================================================================================================================================== +Identical score: 87.819374 + Encoded: [-preset p1 -tune hq -profile:v main -rc cbr -cbr true] + Ignored: [-preset p1 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p1 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 88.16201 + Encoded: [-preset p2 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p2 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 88.47124 + Encoded: [-preset p3 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p3 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 88.70048 + Encoded: [-preset p4 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p4 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 88.76997 + Encoded: [-preset p5 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p5 -tune ull -profile:v main -rc cbr -cbr true] + Ignored: [-preset p6 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p6 -tune ull -profile:v main -rc cbr -cbr true] + + +Identical score: 88.81657 + Encoded: [-preset p7 -tune ll -profile:v main -rc cbr -cbr true] + Ignored: [-preset p7 -tune ull -profile:v main -rc cbr -cbr true] + + +================================================================================================================================================================== diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..a12dadf --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,91 @@ +use std::path::Path; + +use clap::{CommandFactory, Parser}; +use clap::error::ErrorKind; + +use crate::DOWNLOAD_URL; + +// list will grow as more permutations are supported +const SUPPORTED_ENCODERS: [&'static str; 2] = ["h264_nvenc", "hevc_nvenc"]; + +#[derive(Parser)] +pub(crate) struct Cli { + /// the encoder you wish to benchmark: [h264_nvenc, hevc_nvenc, etc] + #[arg(short, long, value_name = "encoder_name", default_value = "encoder")] + pub(crate) encoder: String, + /// target bitrate (in Mb/s) to output; in combination with --bitrate-max-permutation, this is the starting permutation + #[arg(short, long, value_name = "bitrate", default_value = "10")] + pub(crate) bitrate: u32, + /// whether to run vmaf score on each permutation or not + #[arg(short, long)] + pub(crate) check_quality: bool, + // stop an encoding session if the encoder can't keep up with the input file's FPS + #[arg(short, long)] + pub(crate) detect_overload: bool, + /// the source file you wish to benchmark; if not provided, will run standard benchmark on all supported resolutions + #[arg(short, long, value_name = "source.y4m", default_value = "")] + pub(crate) source_file: String, + /// runs just the first permutation for given encoder; useful for testing the tool & output + #[arg(short, long)] + pub(crate) test_run: bool, + /// maximum value to increase the bitrate to (in 5Mb/s intervals); if not specified, tool will not permute over bitrate values + #[arg(short, long, value_name = "bitrate")] + pub(crate) max_bitrate_permutation: Option, + /// runs through permutations that have expected duplicate scores; produces more thorough results but will add substantial runtime + #[arg(short, long)] + pub(crate) allow_duplicate_scores: bool, + /// logs useful information to help troubleshooting + #[arg(short, long)] + pub(crate) verbose: bool, + /// lists the supported/implemented encoders that this tool supports + #[arg(short, long)] + pub(crate) list_supported_encoders: bool, +} + +impl Cli { + pub(crate) fn validate(&mut self) { + if self.list_supported_encoders { + println!("Supported encoders: {:?}", SUPPORTED_ENCODERS); + std::process::exit(0); + } + + // this means no encoder was specified + if self.encoder == "encoder" { + let mut cmd = Cli::command(); + cmd.error( + ErrorKind::ArgumentConflict, + format!("Please provide one of the supported encoders via '-e encoder_name'; for a list of supported encoders use the '-l' argument"), + ).exit(); + } + + // check if specified encoder is supported by the tool + if !is_encoder_supported(&self.encoder) { + let mut cmd = Cli::command(); + cmd.error( + ErrorKind::ArgumentConflict, + format!("[{}] is not a supported encoder at the moment", self.encoder), + ).exit(); + } + + // check if source file exists or not + if !self.source_file.is_empty() && !Path::new(self.source_file.as_str()).exists() { + let mut cmd = Cli::command(); + cmd.error( + ErrorKind::ArgumentConflict, + format!("[{}] source file does not exist; if you want to use one of the provided source files, download them from here:\n{}", self.source_file, DOWNLOAD_URL), + ).exit(); + } + + if self.max_bitrate_permutation.is_none() { + self.max_bitrate_permutation = Option::from(self.bitrate); + } + } + + pub(crate) fn has_special_options(&self) -> bool { + return self.check_quality || self.detect_overload || self.allow_duplicate_scores; + } +} + +fn is_encoder_supported(potential_encoder: &String) -> bool { + return SUPPORTED_ENCODERS.contains(&potential_encoder.as_str()); +} \ No newline at end of file diff --git a/src/encode_file_downloader.rs b/src/encode_file_downloader.rs new file mode 100644 index 0000000..b2ed9d7 --- /dev/null +++ b/src/encode_file_downloader.rs @@ -0,0 +1,23 @@ +use std::fs; + +use crate::ENCODE_FILES; + +pub(crate) fn are_all_source_files_present() -> bool { + let existing_video_files = get_video_files(); + + for file in ENCODE_FILES { + if !existing_video_files.contains(&String::from(file)) { + return false; + } + } + + return true; +} + +fn get_video_files() -> Vec { + let paths = fs::read_dir(".").unwrap(); + return paths.filter_map(|e| e.ok()) + .filter(|p| p.file_type().unwrap().is_file()) + .map(|p| p.file_name().to_str().unwrap().to_string()) + .collect::>(); +} \ No newline at end of file diff --git a/src/env.rs b/src/env.rs new file mode 100644 index 0000000..03c40f7 --- /dev/null +++ b/src/env.rs @@ -0,0 +1,29 @@ +use std::process::{Command, Stdio}; + +pub(crate) fn fail_if_environment_not_setup() { + if !is_ffmpeg_installed() { + println!("ffmpeg is either not installed or not setup on your path correctly"); + std::process::exit(1); + } + + if !is_ffprobe_installed() { + println!("ffprobe is either not installed or not setup on your path correctly"); + std::process::exit(1); + } +} + +fn is_ffmpeg_installed() -> bool { + return is_installed("ffmpeg"); +} + +fn is_ffprobe_installed() -> bool { + return is_installed("ffprobe"); +} + +fn is_installed(program: &str) -> bool { + return Command::new(program) + // important cause we don't want the help message to output here + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn().is_ok(); +} \ No newline at end of file diff --git a/src/ffmpeg.rs b/src/ffmpeg.rs new file mode 100644 index 0000000..dbaaf56 --- /dev/null +++ b/src/ffmpeg.rs @@ -0,0 +1,4 @@ +pub mod args; +pub mod report_files; +pub mod ffprobe; +pub mod metadata; diff --git a/src/ffmpeg/args.rs b/src/ffmpeg/args.rs new file mode 100644 index 0000000..1492a19 --- /dev/null +++ b/src/ffmpeg/args.rs @@ -0,0 +1,240 @@ +use std::ffi::c_float; + +use crate::cli::Cli; + +pub static TCP_LISTEN: &str = "tcp://127.0.0.1:2000?listen"; +pub static NO_OUTPUT: &str = "-f null -"; + +#[derive(Clone)] +pub(crate) struct FfmpegArgs { + fps_limit: u32, + report: bool, + send_progress: bool, + first_input: String, + second_input: String, + pub(crate) bitrate: u32, + pub(crate) encoder: String, + pub(crate) encoder_args: String, + pub(crate) output_args: String, + pub(crate) is_vmaf: bool, + pub(crate) stats_period: c_float, +} + +impl Default for FfmpegArgs { + fn default() -> Self { + FfmpegArgs { + fps_limit: 0, + report: false, + send_progress: true, + first_input: String::new(), + second_input: String::new(), + bitrate: u32::default(), + encoder: String::new(), + encoder_args: String::new(), + output_args: NO_OUTPUT.to_string(), + is_vmaf: false, + // the lower the value, the more often the progress bar will update + // but your fps calculations might be a little over-inflated + stats_period: 0.5, + } + } +} + +impl FfmpegArgs { + pub(crate) fn build_ffmpeg_args(benchmark_args: &Cli, encoder_args: &String, current_bitrate: u32) -> FfmpegArgs { + let ffmpeg_args = FfmpegArgs { + first_input: benchmark_args.source_file.to_string(), + bitrate: current_bitrate, + encoder: benchmark_args.encoder.to_string(), + encoder_args: encoder_args.to_string(), + ..Default::default() + }; + + return ffmpeg_args; + } + + pub(crate) fn map_to_vmaf(&self, fps: u32) -> FfmpegArgs { + let mut vmaf_args = self.clone(); + + // required for having high fps inputs score correctly + vmaf_args.fps_limit = fps; + vmaf_args.second_input = self.first_input.clone(); + vmaf_args.first_input = String::from(TCP_LISTEN); + vmaf_args.output_args = String::from(NO_OUTPUT); + vmaf_args.is_vmaf = true; + vmaf_args.send_progress = false; + // vmaf needs to report so we can get the vmaf score + vmaf_args.report = true; + + return vmaf_args; + } + + pub(crate) fn to_string(&self) -> String { + let mut output = String::new(); + + // not all will want to send progress + if self.send_progress { + output.push_str(format!("-progress tcp://127.0.0.1:1234 -stats_period {} ", self.stats_period).as_str()); + } + + if self.report { + output.push_str("-report "); + } + + if self.fps_limit != 0 { + output.push_str(format!("-r {} ", self.fps_limit).as_str()); + } + + output.push_str(["-i", self.first_input.as_str()].join(" ").as_str()); + + if !self.second_input.is_empty() { + if self.fps_limit != 0 { + output.push_str(format!(" -r {}", self.fps_limit).as_str()); + } + + output.push_str([" -i", self.second_input.as_str()].join(" ").as_str()); + } + + if self.is_vmaf { + append_vmaf_only_args(&mut output); + } else { + append_encode_only_args(&mut output, self.bitrate, &self.encoder, &self.encoder_args); + } + + output.push(' '); + output.push_str(self.output_args.as_str()); + + return output; + } + + pub(crate) fn to_vec(&self) -> Vec { + return self.to_string().split(" ").map(|s| s.to_string()).collect(); + } +} + +fn append_encode_only_args(arg_str: &mut String, bitrate: u32, encoder: &String, encoder_args: &String) { + arg_str.push_str([" -b:v", bitrate.to_string().as_str()].join(" ").as_str()); + // adding the rate amount to the end of the bitrate + arg_str.push('M'); + arg_str.push_str([" -c:v", encoder.as_str()].join(" ").as_str()); + arg_str.push(' '); + arg_str.push_str(encoder_args.as_str()); +} + +fn append_vmaf_only_args(arg_str: &mut String) { + arg_str.push_str(format!(" -filter_complex libvmaf='n_threads={}:n_subsample=5'", num_cpus::get()).as_str()); +} + +#[cfg(test)] +mod tests { + use crate::cli::Cli; + use crate::ffmpeg::args::{FfmpegArgs, NO_OUTPUT, TCP_LISTEN}; + + static INPUT_ONE: &str = "1080-60.y4m"; + static INPUT_TWO: &str = "1080-60-2.y4m"; + static BITRATE: u32 = 6; + static FPS_LIMIT: u32 = 60; + static ENCODER: &str = "h264_nvenc"; + static ENCODER_ARGS: &str = "-preset hq -tune hq -profile:v high -rc cbr -multipass qres -rc-lookahead 8"; + + #[test] + fn default_args_test() { + let args = FfmpegArgs::default(); + + // check fields that have defaults + assert_eq!(args.fps_limit, 0); + assert_eq!(args.send_progress, true); + assert_eq!(args.report, false); + assert_eq!(args.bitrate, u32::default()); + assert_eq!(args.output_args, "-f null -"); + assert_eq!(args.is_vmaf, false); + assert_eq!(args.stats_period, 0.5); + + // check fields that do not + assert!(args.first_input.is_empty()); + assert!(args.second_input.is_empty()); + assert!(args.encoder.is_empty()); + assert!(args.encoder_args.is_empty()); + } + + #[test] + fn build_all_args_test() { + let ffmpeg_args = get_two_input_args(); + + assert_eq!(ffmpeg_args.first_input, INPUT_ONE); + assert_eq!(ffmpeg_args.second_input, INPUT_TWO); + assert_eq!(ffmpeg_args.bitrate, BITRATE); + assert_eq!(ffmpeg_args.encoder, ENCODER); + assert_eq!(ffmpeg_args.encoder_args, ENCODER_ARGS); + } + + #[test] + fn build_only_one_input_test() { + let ffmpeg_args = get_one_input_args(); + + assert_eq!(ffmpeg_args.first_input, INPUT_ONE); + assert_eq!(ffmpeg_args.second_input, ""); + assert_eq!(ffmpeg_args.bitrate, BITRATE); + assert_eq!(ffmpeg_args.encoder, ENCODER); + assert_eq!(ffmpeg_args.encoder_args, ENCODER_ARGS); + } + + #[test] + fn to_string_one_input_test() { + assert_eq!(get_one_input_args().to_string(), + "-progress tcp://127.0.0.1:1234 -stats_period 0.5 -i 1080-60.y4m -b:v 6M -c:v h264_nvenc -preset hq -tune hq -profile:v high -rc cbr -multipass qres -rc-lookahead 8 -f null -" + ); + } + + #[test] + fn to_string_two_input_test() { + assert_eq!(get_two_input_args().to_string(), + "-progress tcp://127.0.0.1:1234 -stats_period 0.5 -i 1080-60.y4m -i 1080-60-2.y4m -b:v 6M -c:v h264_nvenc -preset hq -tune hq -profile:v high -rc cbr -multipass qres -rc-lookahead 8 -f null -" + ); + } + + #[test] + fn map_to_vmaf_test() { + let args = get_two_input_args(); + let vmaf_args = args.map_to_vmaf(FPS_LIMIT); + + assert_eq!(vmaf_args.fps_limit, FPS_LIMIT); + assert_eq!(vmaf_args.first_input, String::from(TCP_LISTEN)); + assert_eq!(vmaf_args.second_input, args.first_input); + assert_eq!(vmaf_args.output_args, String::from(NO_OUTPUT)); + assert_eq!(vmaf_args.is_vmaf, true); + assert_eq!(vmaf_args.send_progress, false); + assert_eq!(vmaf_args.report, true); + } + + #[test] + fn map_to_vmaf_to_string_test() { + let vmaf_args = get_two_input_args().map_to_vmaf(FPS_LIMIT); + assert_eq!(vmaf_args.to_string(), + format!("-report -r {} -i tcp://127.0.0.1:2000?listen -r {} -i 1080-60.y4m -filter_complex libvmaf='n_threads={}:n_subsample=5' -f null -", FPS_LIMIT, FPS_LIMIT, num_cpus::get().to_string()) + ); + } + + fn get_one_input_args() -> FfmpegArgs { + let args = Cli { + encoder: ENCODER.to_string(), + bitrate: BITRATE, + check_quality: false, + detect_overload: false, + source_file: INPUT_ONE.to_string(), + test_run: false, + max_bitrate_permutation: None, + allow_duplicate_scores: false, + verbose: false, + list_supported_encoders: false, + }; + + return FfmpegArgs::build_ffmpeg_args(&args, &ENCODER_ARGS.to_string(), args.bitrate); + } + + fn get_two_input_args() -> FfmpegArgs { + let mut args = get_one_input_args(); + args.second_input = INPUT_TWO.to_string(); + return args; + } +} \ No newline at end of file diff --git a/src/ffmpeg/ffprobe.rs b/src/ffmpeg/ffprobe.rs new file mode 100644 index 0000000..a085b37 --- /dev/null +++ b/src/ffmpeg/ffprobe.rs @@ -0,0 +1,58 @@ +use std::process::{Command, Stdio}; + +use crate::ffmpeg::metadata::MetaData; + +pub(crate) fn probe_for_video_metadata(input_file: &String) -> MetaData { + let args = format!("-v error -select_streams v:0 -show_entries stream=duration_ts,r_frame_rate,coded_width,coded_height -of csv=p=0 {}", input_file); + let ffprobe = Command::new("ffprobe") + .args(args.split(" ")) + .stdout(Stdio::piped()) + .output().expect("Unable to run ffprobe to collect metadata on the input video file"); + + let output = String::from_utf8_lossy(&ffprobe.stdout); + return extract_metadata(output.to_string()); +} + +fn extract_metadata(line: String) -> MetaData { + let splits = line.split(",").collect::>(); + + let fps_splits = splits.get(2).unwrap().split("/").collect::>(); + + let metadata = MetaData { + fps: fps_splits.get(0).unwrap().trim().parse::().unwrap(), + frames: splits.get(3).unwrap().to_string().trim().parse::().unwrap(), + width: splits.get(0).unwrap().to_string().trim().parse::().unwrap(), + height: splits.get(1).unwrap().to_string().trim().parse::().unwrap(), + }; + + return metadata; +} + +#[cfg(test)] +mod tests { + use crate::ffmpeg::ffprobe::extract_metadata; + use crate::ffmpeg::metadata::MetaData; + + static PROBE_LINE: &str = "1920,1080,60/1,1923"; + + #[test] + fn extract_metadata_test() { + let extracted = extract_metadata(String::from(PROBE_LINE)); + + let expected = MetaData { + fps: 60, + frames: 1923, + width: 1920, + height: 1080, + }; + + assert_eq!(equals(&expected, &extracted), true); + } + + fn equals(original: &MetaData, other: &MetaData) -> bool { + return original.fps == other.fps + && original.frames == other.frames + && original.height == other.height + && original.width == other.width; + } +} \ No newline at end of file diff --git a/src/ffmpeg/metadata.rs b/src/ffmpeg/metadata.rs new file mode 100644 index 0000000..98ee5da --- /dev/null +++ b/src/ffmpeg/metadata.rs @@ -0,0 +1,17 @@ +#[derive(Copy, Clone)] +pub(crate) struct MetaData { + pub(crate) fps: u32, + pub(crate) frames: u64, + pub(crate) width: u32, + pub(crate) height: u32, +} + +impl MetaData { + pub(crate) fn to_string(&self) -> String { + return format!("Video metadata: fps: {}, total_frames: {}, resolution: {}x{}", self.fps, self.frames, self.width, self.height); + } + + pub(crate) fn get_res(&self) -> String { + return format!("{}x{}", self.width, self.height); + } +} \ No newline at end of file diff --git a/src/ffmpeg/report_files.rs b/src/ffmpeg/report_files.rs new file mode 100644 index 0000000..d424411 --- /dev/null +++ b/src/ffmpeg/report_files.rs @@ -0,0 +1,94 @@ +use std::ffi::c_float; +use std::fs; +use std::fs::{DirEntry, File}; +use std::io::BufRead; +use std::num::ParseFloatError; +use std::path::PathBuf; + +use filetime::FileTime; +use regex::Regex; +use rev_buf_reader::RevBufReader; + +pub(crate) fn get_latest_ffmpeg_report_file() -> PathBuf { + let mut log_file = None; + let mut latest_time = FileTime::zero(); + + let log_entries = get_logs_in_directory("."); + + // defining entry here so we can extend it's scope + let mut entry: Option<&DirEntry>; + let mut index = 0; + + while index != log_entries.len() { + entry = log_entries.get(index); + let file_time = FileTime::from_creation_time(&entry.unwrap().metadata().unwrap()).unwrap(); + if file_time > latest_time { + latest_time = FileTime::from_creation_time(&entry.unwrap().metadata().unwrap()).unwrap(); + log_file = entry; + } + + index = index + 1; + } + + return log_file.unwrap().path(); +} + +pub(crate) fn extract_vmaf_score(line: &str) -> Result { + return capture_group(line, r"VMAF score: ([0-9]+\.[0-9]+)") + .parse::(); +} + +pub(crate) fn read_last_line_at(line_number: i32) -> String { + let log_file = File::open(get_latest_ffmpeg_report_file()).unwrap(); + let reader = RevBufReader::new(log_file); + let mut lines = reader.lines(); + + // read from bottom to just before the line we need + for _ in 0..line_number - 1 { + lines.next().unwrap().unwrap(); + } + + return lines.next().unwrap().unwrap(); +} + +pub(crate) fn capture_group(str: &str, regex: &str) -> String { + let re = Regex::new(regex).unwrap(); + let caps = re.captures(str); + return if caps.is_some() { + caps.unwrap().get(1).unwrap().as_str().to_string() + } else { + String::new() + }; +} + +fn get_logs_in_directory(dir: &str) -> Vec { + let paths = fs::read_dir(dir).unwrap(); + return paths.filter_map(|e| e.ok()) + .filter(|p| p.file_type().unwrap().is_file()) + .collect::>(); +} + +#[cfg(test)] +mod tests { + use std::fs::File; + + use crate::ffmpeg::report_files::{extract_vmaf_score, get_logs_in_directory}; + + static VMAF_LINE: &str = "[Parsed_libvmaf_0 @ 00000169cf14fc00] VMAF score: 98.644730"; + + #[test] + fn extract_vmaf_score_test() { + let score = extract_vmaf_score(VMAF_LINE); + assert!(score.is_ok()); + assert_eq!(score.unwrap(), 98.64473); + } + + #[test] + fn log_files_only_test() { + File::create("tmp.log").expect("Unable to create temporary log file for testing"); + let log_files = get_logs_in_directory("../"); + for file in log_files { + assert!(file.path().extension().unwrap().to_str().unwrap().contains("log")); + } + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..f40afdc --- /dev/null +++ b/src/main.rs @@ -0,0 +1,464 @@ +use std::collections::HashSet; +use std::ffi::c_float; +use std::fs; +use std::process::{Child, Command, Stdio}; +use std::time::{Duration, SystemTime}; + +use clap::Parser; +use compound_duration::format_dhms; +use crossbeam_channel::{bounded, Receiver, select}; +use ctrlc::Error; + +use ffmpeg::metadata::MetaData; + +use crate::cli::Cli; +use crate::encode_file_downloader::are_all_source_files_present; +use crate::env::fail_if_environment_not_setup; +use crate::ffmpeg::args::FfmpegArgs; +use crate::ffmpeg::ffprobe::probe_for_video_metadata; +use crate::ffmpeg::report_files::{extract_vmaf_score, get_latest_ffmpeg_report_file, read_last_line_at}; +use crate::permutations::h264_hevc_nvenc::Nvenc; +use crate::permutations::permute::Permute; +use crate::permutations::result::{log_results_to_file, PermutationResult}; +use crate::progressbar::{draw_yellow_bar, TrialResult}; + +mod progressbar; +mod permutations; +mod ffmpeg; +mod cli; +mod stat_tcp_listener; +mod env; +mod encode_file_downloader; + +// the hard-coded vmaf quality we want to shoot for when doing bitrate permutations +const TARGET_QUALITY: c_float = 95.0; + +pub static TCP_OUTPUT: &str = "-f {} tcp://127.0.0.1:2000"; + +// list of all encode files +const ENCODE_FILES: [&'static str; 8] = ["720-60.y4m", "720-120.y4m", "1080-60.y4m", "1080-120.y4m", "2k-60.y4m", "2k-120.y4m", "4k-60.y4m", "4k-120.y4m"]; + +const DOWNLOAD_URL: &str = "https://www.dropbox.com/sh/x08pkk47lc1v5ex/AADGaoOjOcA0-uPo7I0NaxL-a?dl=0"; + +fn main() { + let runtime = SystemTime::now(); + + fail_if_environment_not_setup(); + let mut cli = Cli::parse(); + cli.validate(); + + let ctrl_channel = setup_ctrl_channel(); + + let is_standard_benchmark = cli.source_file.is_empty(); + + if is_standard_benchmark && !are_all_source_files_present() { + println!("You're missing some video source files to run the standard benchmark; you should have the following: \n{:?}", ENCODE_FILES); + println!("Please download the ones you are missing from: {}", DOWNLOAD_URL); + println!("If you want to run the tool against a specific resolution/fps, download just that source file and specify it with '-s'"); + std::process::exit(1); + } + + // eventually we'll want to support more than just these two + let mut permutation = Nvenc::new(cli.encoder == "hevc_nvenc"); + let encoder_settings = if is_standard_benchmark { permutation.run_standard_only() } else { permutation.init() }; + + // determining if we'll be iterating over X number of input files, or just the provided one + let mut source_files = >::new(); + let specified_source_file = (&cli.source_file).clone(); + if is_standard_benchmark { + for source in ENCODE_FILES { + source_files.push(source); + } + + // set initial source file + cli.source_file = source_files.get(0).unwrap().to_string(); + } else { + source_files.push(specified_source_file.as_str()); + }; + + let total_encoder_permutations = encoder_settings.len(); + let bitrate_permutations = get_bitrate_permutations(cli.bitrate, cli.max_bitrate_permutation.unwrap()); + let total_permutations = if cli.test_run { 1 } else { encoder_settings.len() * bitrate_permutations.len() * source_files.len() }; + + let mut all_results: Vec = Vec::new(); + let mut dup_results: Vec = Vec::new(); + let mut vmaf_scores: HashSet = HashSet::new(); + + let mut permutation_calculation_time: Option = None; + + let mut target_quality_found = false; + + // loop over all permutations of bitrate we want to try + let mut bitrate_index = 0; + + // factor to apply to the ETA for whether we're ignoring any permutations + let mut ignore_factor: c_float = 1f32; + + for input in source_files { + // apply the input to the cli args + cli.source_file = input.to_string(); + + let metadata = probe_for_video_metadata(&cli.source_file); + + // we'll calculate this as if this is the standard benchmark + let res_to_bitrate_map = permutation.get_resolution_to_bitrate_map(metadata.fps); + + // do not check for encoder overload + let ignore_overload = !cli.detect_overload; + + if cli.verbose { + println!("{}", metadata.to_string()); + } + + // this is the actual bitrate we'll use + let mut effective_bitrate = if is_standard_benchmark { *(res_to_bitrate_map.get(metadata.get_res().as_str()).unwrap()) } else { cli.bitrate }; + + log_total_permutations(&cli, &metadata, total_permutations, bitrate_permutations.len(), is_standard_benchmark, effective_bitrate); + + for bitrate in bitrate_permutations.clone() { + if !is_standard_benchmark { + effective_bitrate = bitrate; + } + + if target_quality_found && !is_standard_benchmark { + println!("Found vmaf score >= {}, stopping benchmark...", TARGET_QUALITY); + break; + } + + // for a given bitrate, permute over all possible encoder settings + while let Some((encoder_index, settings)) = permutation.next() { + + // add in loop over all supported input files + let mut result = PermutationResult::new(&metadata, effective_bitrate, &settings, cli.encoder.as_str()); + + let ffmpeg_args = FfmpegArgs::build_ffmpeg_args(&cli, &settings, effective_bitrate); + if cli.verbose { + println!("ffmpeg args: {}", ffmpeg_args.to_string()); + } + + let permutation_start_time = SystemTime::now(); + + let current_index = (bitrate_index * total_encoder_permutations) + (encoder_index + 1); + log_permutation_header(total_permutations, permutation_calculation_time, effective_bitrate, current_index, settings, ignore_factor, is_standard_benchmark); + + // if this permutation was added to the list of duplicates, skip to save calculation time + if !cli.allow_duplicate_scores && will_be_duplicate(&dup_results, &result) { + draw_yellow_bar(metadata.frames); + println!("\n!!! Above encoder settings will produce identical vmaf score as other permutations, skipping... \n"); + continue; + } + + let encode_start_time = SystemTime::now(); + let mut trial_result = run_overload_benchmark(&metadata, &ffmpeg_args, cli.verbose, ignore_overload, &ctrl_channel); + result.was_overloaded = trial_result.was_overloaded; + result.encode_time = encode_start_time.elapsed().unwrap().as_secs(); + + // calculate the fps statistics and store this in the result + calculate_fps_statistics(&mut result, &mut trial_result); + + // log the calculated fps statistics; two spaces match the progress bar + println!(" Average FPS:\t{:.0}", result.fps_stats.avg); + println!(" 1%'ile:\t{}", result.fps_stats.one_perc_low); + println!(" 90%'ile:\t{}", result.fps_stats.ninety_perc); + + // retry once if it was overloaded, but only if we're not ignoring overloads + if !ignore_overload && result.was_overloaded { + println!("Retrying encode just in case this overload was a one-off..."); + let encode_start_time = SystemTime::now(); + let mut trial_result = run_overload_benchmark(&metadata, &ffmpeg_args, cli.verbose, ignore_overload, &ctrl_channel); + result.was_overloaded = trial_result.was_overloaded; + result.encode_time = encode_start_time.elapsed().unwrap().as_secs(); + + // calculate the fps statistics and store this in the result + calculate_fps_statistics(&mut result, &mut trial_result); + + // log the calculated fps statistics; two spaces match the progress bar + println!(" Average FPS:\t{:.0}", result.fps_stats.avg); + println!(" 1%'ile:\t{}", result.fps_stats.one_perc_low); + println!(" 90%'ile:\t{}", result.fps_stats.ninety_perc); + } + + // set the permutation calculation time; if we're doing vmaf score, will update a second time + permutation_calculation_time = Option::from(permutation_start_time.elapsed().unwrap()); + + // if we're not calculating vmaf score, continue to the next permutation + if cli.check_quality { + // if it's still overloaded, we won't be able to check this + if !result.was_overloaded { + let vmaf_start_time = SystemTime::now(); + result.vmaf_score = check_encode_quality(&metadata, &ffmpeg_args, cli.verbose, &ctrl_channel); + result.vmaf_calculation_time = vmaf_start_time.elapsed().unwrap().as_secs(); + + // if this is higher than the target quality, stop at this bitrate during benchmark + if result.vmaf_score >= TARGET_QUALITY { + target_quality_found = true; + } + + // update each permutation count + permutation_calculation_time = Option::from(permutation_start_time.elapsed().unwrap()); + } else { + println!("Will not check vmaf score as encoder cannot handle realtime encoding of given parameters...\n"); + } + + // only do this duplicate mapping during the first bitrate permutation + // notice how we do not add this for overloaded results + if !result.was_overloaded && bitrate_index == 0 { + let score_str = result.vmaf_score.to_string(); + if !vmaf_scores.contains(&score_str) { + all_results.push(result); + vmaf_scores.insert((*score_str).parse().unwrap()); + } else { + dup_results.push(result); + } + } else { + // always keep results; any duplicates will be ignored already + all_results.push(result); + } + } else { + all_results.push(result); + } + + if cli.test_run { + break; + } + } + + if cli.test_run { + break; + } + + // if all permutations resulted in an overload, skip additional bitrate permutations + if did_all_permutions_fail(&all_results) { + println!("None of the permutations on the starting bitrate were successful; stopping benchmark..."); + break; + } + + // only log this after the first bitrate permutation + if cli.check_quality && !cli.allow_duplicate_scores && bitrate_index == 0 { + println!("!!! Permutations past this point will only run if they are expected to have unique vmaf scores !!!"); + + // number of actually calculated permutations out of the original total + ignore_factor = all_results.len() as c_float / total_encoder_permutations as c_float; + } + + // re-init the encoder settings to run with the next bitrate + if is_standard_benchmark { + permutation.run_standard_only(); + } else { + permutation.init(); + } + bitrate_index += 1; + } + } + + let runtime_str = format_dhms(runtime.elapsed().unwrap().as_secs()); + log_results_to_file(all_results, &runtime_str, dup_results, cli.bitrate, is_standard_benchmark); + + println!("Benchmark runtime: {}", runtime_str); +} + +fn did_all_permutions_fail(results: &Vec) -> bool { + return results.into_iter().all(|x| x.was_overloaded == true); +} + +fn calculate_fps_statistics(permutation_result: &mut PermutationResult, trial_result: &mut TrialResult) { + // must use a much larger data type for calculating the average + let mut sum: u64 = 0; + for fps in &trial_result.all_fps { + sum += *fps as u64; + } + + permutation_result.fps_stats.avg = (sum as usize / trial_result.all_fps.len()) as u16; + + // create a sorted list of the fps measurements + trial_result.all_fps.sort(); + + // find the index & calculate 1%ile + let mut index = (0.01 as c_float * trial_result.all_fps.len() as c_float).ceil(); + permutation_result.fps_stats.one_perc_low = *(trial_result.all_fps.get(index as usize).unwrap()); + + // find the index & calculate 90%ile + index = (0.90 as c_float * trial_result.all_fps.len() as c_float).ceil(); + permutation_result.fps_stats.ninety_perc = *(trial_result.all_fps.get(index as usize).unwrap()); +} + +fn will_be_duplicate(duplicates: &Vec, result: &PermutationResult) -> bool { + for dup in duplicates { + if dup.encoder_settings == result.encoder_settings { + return true; + } + } + + return false; +} + +fn log_permutation_header(permutation_count: usize, permutation_calculation_time: Option, bitrate: u32, index: usize, settings: String, ignored_factor: c_float, is_standard: bool) { + if index != 1 && !is_standard { + println!("===================================================================================="); + } + + if !is_standard { + println!("[Permutation {}/{}]", index, permutation_count); + } + + if !is_standard { + if permutation_calculation_time.is_some() { + println!("[ETR: {}]", format_dhms(calculate_eta(permutation_calculation_time.unwrap(), index, permutation_count, ignored_factor))); + } else { + println!("[ETR: Unknown until first permutation is done]"); + } + } + + println!("[Bitrate: {}Mb/s]", bitrate); + println!("[{}]", settings); +} + +fn calculate_eta(elapsed: Duration, current_perm: usize, total_perms: usize, ignored_factor: c_float) -> usize { + let seconds = elapsed.as_secs() as usize; + let remaining_permutations = total_perms - (current_perm - 1); + return (((seconds * remaining_permutations) as c_float) * ignored_factor) as usize; +} + +fn log_total_permutations(cli: &Cli, metadata: &MetaData, permutation_count: usize, bitrate_permutations: usize, is_standard: bool, effective_bitrate: u32) { + println!("===================================================================================="); + if !is_standard { + println!("Permutations:\t{}", permutation_count); + } + println!("Resolution:\t{}x{}", metadata.width, metadata.height); + println!("Encoder:\t{}", cli.encoder); + if bitrate_permutations > 1 { + println!("Min bitrate:\t{}Mb/s", cli.bitrate); + println!("Max bitrate:\t{}Mb/s", cli.max_bitrate_permutation.unwrap()); + } else { + println!("Bitrate:\t{}Mb/s", effective_bitrate); + } + + println!("FPS:\t\t{}", metadata.fps); + + // might move this to print somewhere earlier and not here + if cli.has_special_options() && !is_standard { + println!("\nOptions:"); + if cli.detect_overload { + println!(" -encoder will stop if overload is detected"); + } + + if cli.check_quality { + println!(" -calculating vmaf score"); + } + + if cli.allow_duplicate_scores { + println!(" -allowing duplicate vmaf scores"); + } + } + + println!(); +} + +fn get_bitrate_permutations(starting_bitrate: u32, max_bitrate: u32) -> Vec { + let interval = 5; + let mut bitrates = Vec::new(); + for i in 0..(((max_bitrate - starting_bitrate) / interval) + 1) { + bitrates.push(starting_bitrate + (interval * i)); + } + + return bitrates; +} + +fn check_encode_quality(metadata: &MetaData, ffmpeg_args: &FfmpegArgs, verbose: bool, ctrl_channel: &Result, Error>) -> c_float { + println!("Calculating vmaf score; might take longer than original encode depending on your CPU..."); + + // first spawn the ffmpeg instance to listen for incoming encode + let vmaf_args = ffmpeg_args.map_to_vmaf(metadata.fps); + if verbose { + println!("Vmaf args calculating quality: {}", vmaf_args.to_string()); + } + + let mut vmaf_child = spawn_ffmpeg_child(&vmaf_args); + + // then spawn the ffmpeg instance to perform the encoding + let mut encoder_args = ffmpeg_args.clone(); + + encoder_args.output_args = String::from(insert_format_from(TCP_OUTPUT, &ffmpeg_args.encoder)); + + if verbose { + println!("Encoder fmmpeg args sending to vmaf: {}", encoder_args.to_string()); + } + + spawn_ffmpeg_child(&encoder_args); + + // not the cleanest way to do this but oh well + progressbar::watch_encode_progress(metadata.frames, false, metadata.fps, verbose, ffmpeg_args.stats_period, ctrl_channel); + + // need to wait for the vmaf calculating thread to finish + println!("VMAF calculation finishing up..."); + vmaf_child.wait().expect("Not able to wait on the child thread to finish up"); + + let vmaf_log_file = get_latest_ffmpeg_report_file(); + let vmaf_score_extract = extract_vmaf_score(read_last_line_at(3).as_str()); + let vmaf_score = vmaf_score_extract.unwrap(); + println!("VMAF score: {}\n", vmaf_score); + + // cleanup the log file being used + fs::remove_file(vmaf_log_file.as_path()).unwrap(); + + return vmaf_score; +} + +fn insert_format_from(input: &str, encoder: &String) -> String { + let format = if encoder == "h264_nvenc" { "h264" } else { "hevc" }; + // this should be cleaner when we support more than 1 type + return input.replace("{}", format); +} + +fn run_overload_benchmark(metadata: &MetaData, ffmpeg_args: &FfmpegArgs, verbose: bool, ignore_overload: bool, ctrl_channel: &Result, Error>) -> TrialResult { + let mut child = spawn_ffmpeg_child(ffmpeg_args); + if verbose { + println!("Successfully spawned encoding child") + } + + let trial_result = progressbar::watch_encode_progress(metadata.frames, !ignore_overload, metadata.fps, verbose, ffmpeg_args.stats_period, ctrl_channel); + + if trial_result.was_overloaded && !was_ctrl_c_received(&ctrl_channel) { + let _ = child.kill(); + println!("Encoder was overloaded and could not encode the video file in realtime, stopping..."); + } + + return trial_result; +} + +fn spawn_ffmpeg_child(ffmpeg_args: &FfmpegArgs) -> Child { + return Command::new("ffmpeg") + .args(ffmpeg_args.to_vec()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn().expect("Failed to start instance of ffmpeg"); +} + +// probably want to make this more robust where it kills all child threads instead of waiting +fn setup_ctrl_channel() -> Result, Error> { + let (sender, receiver) = bounded(100); + ctrlc::set_handler(move || { + println!("Received ctrl-c, exiting gracefully..."); + let _ = sender.send(()); + })?; + + Ok(receiver) +} + +fn was_ctrl_c_received(ctrl_c_events: &Result, Error>) -> bool { + select! { + recv(ctrl_c_events.as_ref().unwrap()) -> _ => { + return true; + }, + default() => { + return false; + } + } +} + +fn exit_on_ctrl_c(ctrl_channel: &Result, Error>) { + if was_ctrl_c_received(&ctrl_channel) { + println!("Ctrl-C acknowledged, program exiting..."); + std::process::exit(0); + } +} diff --git a/src/permutations.rs b/src/permutations.rs new file mode 100644 index 0000000..24bfea3 --- /dev/null +++ b/src/permutations.rs @@ -0,0 +1,6 @@ +pub mod permute; +pub mod nvenc; +pub mod result; +pub mod fps_stats; +pub mod h264_hevc_nvenc; +mod resolutions; diff --git a/src/permutations/fps_stats.rs b/src/permutations/fps_stats.rs new file mode 100644 index 0000000..d0916e3 --- /dev/null +++ b/src/permutations/fps_stats.rs @@ -0,0 +1,16 @@ +#[derive(Clone)] +pub(crate) struct FpsStats { + pub(crate) avg: u16, + pub(crate) one_perc_low: u16, + pub(crate) ninety_perc: u16, +} + +impl Default for FpsStats { + fn default() -> Self { + FpsStats { + avg: 0, + one_perc_low: 0, + ninety_perc: 0, + } + } +} \ No newline at end of file diff --git a/src/permutations/h264_hevc_nvenc.rs b/src/permutations/h264_hevc_nvenc.rs new file mode 100644 index 0000000..3180206 --- /dev/null +++ b/src/permutations/h264_hevc_nvenc.rs @@ -0,0 +1,188 @@ +use std::collections::HashMap; + +use itertools::Itertools; + +use crate::permutations::nvenc::{get_nvenc_presets, get_nvenc_tunes}; +use crate::permutations::permute::Permute; +use crate::permutations::resolutions::map_res_to_bitrate; + +pub(crate) struct Nvenc { + presets: Vec<&'static str>, + tunes: Vec<&'static str>, + profiles: Vec<&'static str>, + rate_controls: Vec<&'static str>, + // might be able to make this the size we're expecting + permutations: Vec, + index: i32, +} + +impl Nvenc { + pub(crate) fn new(is_hevc: bool) -> Self { + Self { + presets: get_nvenc_presets(), + tunes: get_nvenc_tunes(), + // this is the only difference between hevc & h264 + profiles: if is_hevc { vec!["main"] } else { vec!["high"] }, + // leaving out vbr rate controls as these are not ideal for game streaming + rate_controls: vec!["cbr"], + permutations: Vec::new(), + // starts at -1, so that first next() will return the first element + index: -1, + } + } + + fn has_next(&self) -> bool { + return self.index != (self.permutations.len() - 1) as i32; + } +} + +#[derive(Copy, Clone)] +struct NvencSettings { + preset: &'static str, + tune: &'static str, + profile: &'static str, + rate_control: &'static str, +} + +impl NvencSettings { + fn to_string(&self) -> String { + let mut args = String::new(); + args.push_str("-preset "); + args.push_str(self.preset); + args.push_str(" -tune "); + args.push_str(self.tune); + args.push_str(" -profile:v "); + args.push_str(self.profile); + args.push_str(" -rc "); + args.push_str(self.rate_control); + // always set this to constant bit rate to ensure reliable stream + args.push_str(" -cbr true"); + + return args; + } +} + +impl Iterator for Nvenc { + type Item = (usize, String); + + fn next(&mut self) -> Option { + if !self.has_next() { + return None; + } + + self.index += 1; + + let usize_index = self.index as usize; + return Option::from((usize_index as usize, self.permutations.get(usize_index).unwrap().to_string())); + } +} + +impl Permute for Nvenc { + fn init(&mut self) -> &Vec { + // reset index, otherwise we won't be able to iterate at all + self.index = -1; + + // clear the vectors if there were entries before + self.permutations.clear(); + + let mut permutations = vec![&self.presets, &self.tunes, &self.profiles, &self.rate_controls] + .into_iter().multi_cartesian_product(); + + loop { + let perm = permutations.next(); + if perm.is_none() { + break; + } + + let unwrapped_perm = perm.unwrap(); + let settings = NvencSettings { + preset: unwrapped_perm.get(0).unwrap(), + tune: unwrapped_perm.get(1).unwrap(), + profile: unwrapped_perm.get(2).unwrap(), + rate_control: unwrapped_perm.get(3).unwrap(), + }; + + self.permutations.push(settings.to_string()); + } + + return &self.permutations; + } + + fn run_standard_only(&mut self) -> &Vec { + // reset index, otherwise we won't be able to iterate at all + self.index = -1; + + // clear the vectors if there were entries before + self.permutations.clear(); + + // note: this only works when hevc/h264 both use just 1 profile, if we add more this will break + self.permutations.push(String::from(format!("-preset p1 -tune ll -profile:v {} -rc cbr -cbr true", self.profiles.get(0).unwrap()))); + return &self.permutations; + } + + fn get_resolution_to_bitrate_map(&self, fps: u32) -> HashMap { + let mut map: HashMap = HashMap::new(); + + // bitrates are within 5Mb/s of each other, using higher one + // note: these are the 60fps bitrate values + let mut bitrates: [u32; 4] = [10, 20, 25, 55]; + + // 120 fps is effectively double the bitrate + if fps == 120 { + bitrates.iter_mut().for_each(|b| *b = *b * 2); + } + + map_res_to_bitrate(&mut map, bitrates); + + return map; + } +} + +#[cfg(test)] +mod tests { + use crate::permutations::h264_hevc_nvenc::Nvenc; + use crate::permutations::permute::Permute; + + #[test] + fn create_h264_test() { + let nvenc = Nvenc::new(false); + assert!(nvenc.profiles.contains(&"high")); + } + + #[test] + fn create_hevc_test() { + let nvenc = Nvenc::new(true); + assert!(nvenc.profiles.contains(&"main")); + } + + #[test] + fn iterate_to_end_test() { + let mut nvenc = Nvenc::new(false); + let perm_count = nvenc.init().len(); + + let mut total = 0; + while let Some((_usize, _string)) = nvenc.next() { + total += 1 + } + + // determine if we iterated over all the permutations correctly + assert_eq!(total, perm_count); + } + + #[test] + fn total_permutations_test() { + let mut nvenc = Nvenc::new(false); + assert_eq!(nvenc.init().len(), get_expected_len(&nvenc)); + } + + #[test] + fn init_twice_not_double_test() { + let mut nvenc = Nvenc::new(false); + nvenc.init(); + assert_eq!(nvenc.init().len(), get_expected_len(&nvenc)); + } + + fn get_expected_len(nvenc: &Nvenc) -> usize { + return nvenc.presets.len() * nvenc.tunes.len() * nvenc.profiles.len() * nvenc.rate_controls.len(); + } +} \ No newline at end of file diff --git a/src/permutations/nvenc.rs b/src/permutations/nvenc.rs new file mode 100644 index 0000000..da158cc --- /dev/null +++ b/src/permutations/nvenc.rs @@ -0,0 +1,7 @@ +pub(crate) fn get_nvenc_presets() -> Vec<&'static str> { + return vec!["p1", "p2", "p3", "p4", "p5", "p6", "p7"]; +} + +pub(crate) fn get_nvenc_tunes() -> Vec<&'static str> { + return vec!["hq", "ll", "ull"]; +} \ No newline at end of file diff --git a/src/permutations/permute.rs b/src/permutations/permute.rs new file mode 100644 index 0000000..460ff11 --- /dev/null +++ b/src/permutations/permute.rs @@ -0,0 +1,12 @@ +use std::collections::HashMap; + +pub(crate) trait Permute: Iterator { + // calculates permutations and returns a reference of said permutations + fn init(&mut self) -> &Vec; + + // overwrites the init values to just include permutations of standard runs + fn run_standard_only(&mut self) -> &Vec; + + // takes in the fps being used; scales the necessary bitrate accordingly + fn get_resolution_to_bitrate_map(&self, fps: u32) -> HashMap; +} \ No newline at end of file diff --git a/src/permutations/resolutions.rs b/src/permutations/resolutions.rs new file mode 100644 index 0000000..0ee8beb --- /dev/null +++ b/src/permutations/resolutions.rs @@ -0,0 +1,10 @@ +use std::collections::HashMap; + +pub(crate) const SUPPORTED_RESOLUTIONS: [&'static str; 4] = ["1280x720", "1920x1080", "2560x1440", "3840x2160"]; + +pub(crate) fn map_res_to_bitrate(map: &mut HashMap, bitrates: [u32; 4]) { + map.insert(SUPPORTED_RESOLUTIONS.get(0).unwrap().to_string(), *bitrates.get(0).unwrap()); + map.insert(SUPPORTED_RESOLUTIONS.get(1).unwrap().to_string(), *bitrates.get(1).unwrap()); + map.insert(SUPPORTED_RESOLUTIONS.get(2).unwrap().to_string(), *bitrates.get(2).unwrap()); + map.insert(SUPPORTED_RESOLUTIONS.get(3).unwrap().to_string(), *bitrates.get(3).unwrap()); +} \ No newline at end of file diff --git a/src/permutations/result.rs b/src/permutations/result.rs new file mode 100644 index 0000000..02cedb4 --- /dev/null +++ b/src/permutations/result.rs @@ -0,0 +1,113 @@ +use std::ffi::c_float; +use std::fs::File; +use std::io::Write; + +use compound_duration::format_dhms; + +use crate::ffmpeg::metadata::MetaData; +use crate::permutations::fps_stats::FpsStats; + +#[derive(Clone)] +pub(crate) struct PermutationResult { + pub(crate) encoder: String, + pub(crate) was_overloaded: bool, + bitrate: u32, + metadata: MetaData, + pub(crate) encoder_settings: String, + // only if the encodes were successful + pub(crate) encode_time: u64, + pub(crate) vmaf_calculation_time: u64, + pub(crate) vmaf_score: c_float, + pub(crate) fps_stats: FpsStats, +} + +impl PermutationResult { + pub(crate) fn new(metadata: &MetaData, bitrate: u32, encoder_settings: &String, encoder: &str) -> Self { + Self { + encoder: String::from(encoder), + was_overloaded: false, + bitrate, + metadata: metadata.clone(), + encoder_settings: encoder_settings.to_string(), + encode_time: 0, + vmaf_calculation_time: 0, + vmaf_score: 0.0, + fps_stats: FpsStats::default(), + } + } + + fn to_string(&self) -> String { + let mut default = String::new(); + + let overloaded_indicator = if self.was_overloaded { "[O]" } else { " " }; + default.push_str(format!("{}{}x{}\t{}\t{}Mb/s", overloaded_indicator, self.metadata.width, + self.metadata.height, self.metadata.fps, self.bitrate).as_str()); + + // adjust tabs based on expected vmaf score, or lack of one + let vmaf_score_str = if self.was_overloaded { format!("{:.5}\t\t", self.vmaf_score) } else if self.vmaf_score != 0.0 { format!("{:.5}\t", self.vmaf_score) } else { format!("0.00000\t\t") }; + + default.push_str(format!("\t\t{}\t\t{}\t\t{}{:.0}\t\t{}\t\t{}\t\t{}", + format_dhms(self.encode_time), format_dhms(self.vmaf_calculation_time), vmaf_score_str, + self.fps_stats.avg, self.fps_stats.one_perc_low, self.fps_stats.ninety_perc, self.encoder_settings).as_str()); + + return default; + } +} + +pub(crate) fn log_results_to_file(results: Vec, runtime_str: &String, dup_results: Vec, bitrate: u32, is_standard: bool) { + // might make this naming here more robust eventually + let first_metadata = results.get(0).unwrap().metadata; + let encoder = results.get(0).unwrap().encoder.as_str(); + let permute_file_name = format!("{}-{}-{}.log", encoder, first_metadata.get_res(), first_metadata.fps).to_string(); + let benchmark_file_name = format!("{}-benchmark.log", encoder).to_string(); + let file_name = if is_standard { benchmark_file_name } else { permute_file_name }; + + let mut w = File::create(file_name).unwrap(); + + writeln!(&mut w, "Results from entire permutation:").unwrap(); + writeln!(&mut w, "==================================================================================================================================================================").unwrap(); + writeln!(&mut w, " [Resolution]\t[FPS]\t[Bitrate]\t[Encode Time]\t[VMAF Time]\t[VMAF Score]\t[Average FPS]\t[1%'ile]\t[90%'ile]\t[Encoder Settings]").unwrap(); + for result in &results { + writeln!(&mut w, "{}", result.to_string()).unwrap(); + } + writeln!(&mut w, "==================================================================================================================================================================").unwrap(); + writeln!(&mut w, "Benchmark runtime: {}\n", runtime_str).unwrap(); + + let has_logged_dup_header = false; + + // log out the duplicated results so we can keep track of them + let initial_perms: Vec = results + .into_iter() + .filter(|res| res.bitrate == bitrate) + .collect(); + + // for each of these, collect the duplicates with the same score + for perm in initial_perms { + let moved = &dup_results; + let dups: Vec<&PermutationResult> = moved + .into_iter() + .filter(|res| res.vmaf_score == perm.vmaf_score) + .collect(); + + // only log entries of duplicates + if dups.is_empty() { + continue; + } + + if !has_logged_dup_header { + writeln!(&mut w, "Encoder settings that produced identical scores:").unwrap(); + writeln!(&mut w, "==================================================================================================================================================================").unwrap(); + } + + writeln!(&mut w, "Identical score: {}", perm.vmaf_score).unwrap(); + writeln!(&mut w, "\tEncoded: [{}]", perm.encoder_settings).unwrap(); + + for dup in dups { + writeln!(&mut w, "\tIgnored: [{}]", dup.encoder_settings).unwrap(); + } + + writeln!(&mut w, "\n").unwrap(); + } + + writeln!(&mut w, "==================================================================================================================================================================").unwrap(); +} \ No newline at end of file diff --git a/src/progressbar.rs b/src/progressbar.rs new file mode 100644 index 0000000..6ce16b6 --- /dev/null +++ b/src/progressbar.rs @@ -0,0 +1,116 @@ +use std::ffi::c_float; +use std::fmt::Write; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::time; +use std::time::SystemTime; + +use crossbeam_channel::Receiver; +use ctrlc::Error; +use indicatif::{ProgressBar, ProgressState, ProgressStyle}; + +use crate::exit_on_ctrl_c; +use crate::stat_tcp_listener::start_listening_to_ffmpeg_stats; + +pub(crate) struct TrialResult { + pub(crate) all_fps: Vec, + pub(crate) was_overloaded: bool, +} + +impl Default for TrialResult { + fn default() -> Self { + TrialResult { + all_fps: vec![], + was_overloaded: false, + } + } +} + +pub(crate) fn watch_encode_progress(total_frames: u64, check_for_overload: bool, target_fps: u32, verbose: bool, stats_period: c_float, ctrl_channel: &Result, Error>) -> TrialResult { + static FRAME: AtomicUsize = AtomicUsize::new(0); + static PREVIOUS_FRAME: AtomicUsize = AtomicUsize::new(0); + + // keep track of all fps metrics to calculate on later on + let mut trial_result = TrialResult::default(); + let bar = ProgressBar::new(total_frames); + set_bar_style(&bar, "green"); + bar.tick(); + + // time it takes for the encoder to need to process the target # of frames + let overload_time = time::Duration::from_secs(5); + let mut checking_overload = false; + let mut first_overload_detected = SystemTime::now(); + + // how many milliseconds has passed since the last frame stat + let interval_adjustment = (1.0 / stats_period) as usize; + + let stat_listener = start_listening_to_ffmpeg_stats(verbose, &FRAME, &PREVIOUS_FRAME); + loop { + // important to not get stuck in this thread + exit_on_ctrl_c(&ctrl_channel); + + // takes into account the stat update period to properly adjust the calculated FPS + let calculated_fps = ((FRAME.load(Ordering::Relaxed) - PREVIOUS_FRAME.load(Ordering::Relaxed)) * interval_adjustment) as u16; + + // only record fps counts that are close to 1/4 of the target; any lower is noise + if calculated_fps >= (target_fps / 4) as u16 { + trial_result.all_fps.push(calculated_fps); + } + + // calculate the number of frames processed since the last second (more accurate than using fps from ffmpeg) + if check_for_overload && calculated_fps < target_fps as u16 { + if !checking_overload { + first_overload_detected = SystemTime::now(); + checking_overload = true; + } + + // check elapsed time since the last encoder overload detection + if checking_overload && first_overload_detected.elapsed().unwrap() > overload_time { + break; + } + } else { + checking_overload = false; + } + + if FRAME.load(Ordering::Relaxed) >= total_frames as usize { + bar.set_position(total_frames); + break; + } + + bar.set_position(FRAME.load(Ordering::Relaxed) as u64); + } + + // change bar style as read + if (FRAME.load(Ordering::Relaxed) as u64) < total_frames { + set_bar_style(&bar, "red"); + bar.abandon() + } else { + bar.finish(); + } + + println!(); + + // kill the tcp reading thread + stat_listener.stop().join().expect("Child thread reading TCP did not finish"); + + trial_result.was_overloaded = (FRAME.load(Ordering::Relaxed) as u64) != total_frames; + // reset the static values + FRAME.store(0, Ordering::Relaxed); + PREVIOUS_FRAME.store(0, Ordering::Relaxed); + + return trial_result; +} + +pub(crate) fn set_bar_style(bar: &ProgressBar, color: &str) { + let template = "{spinner:.%} [{elapsed_precise}] [{wide_bar:.%}] {pos}/{len} frames ({eta_precise})"; + bar.set_style(ProgressStyle::with_template(&str::replace(template, "%", color).as_str()) + .unwrap() + .with_key("eta", |state: &ProgressState, w: &mut dyn Write| write!(w, "{:.1}s", state.eta().as_secs_f64()).unwrap()) + .progress_chars("#>-")); +} + +pub(crate) fn draw_yellow_bar(total_frames: u64) { + let bar = ProgressBar::new(total_frames); + set_bar_style(&bar, "yellow"); + bar.tick(); + bar.abandon(); +} \ No newline at end of file diff --git a/src/stat_tcp_listener.rs b/src/stat_tcp_listener.rs new file mode 100644 index 0000000..d5810a8 --- /dev/null +++ b/src/stat_tcp_listener.rs @@ -0,0 +1,66 @@ +use std::io::{BufRead, BufReader}; +use std::net::{TcpListener, TcpStream}; +use std::num::ParseIntError; +use std::process; +use std::sync::atomic::{AtomicUsize, Ordering}; + +use stoppable_thread::StoppableHandle; + +use crate::ffmpeg::report_files::capture_group; + +static LOCALHOST: &str = "127.0.0.1"; +static PORT: &str = "1234"; + +pub fn start_listening_to_ffmpeg_stats(verbose: bool, frame: &'static AtomicUsize, previous_frame: &'static AtomicUsize) -> StoppableHandle<()> { + let stat_listener = TcpListener::bind(format!("{}:{}", LOCALHOST, PORT)).unwrap(); + + let tcp_reading_thread; + match stat_listener.accept() { + Ok(client) => { + if verbose { + println!("Connected to ffmpeg's -progress output via TCP..."); + } + + tcp_reading_thread = spawn_tcp_reading_thread(client.0, frame, previous_frame); + } + // probably log this error eventually + Err(_e) => { + println!("Not able to connect to client for reading stats, cannot proceed"); + process::exit(1); + } + } + + // eventually we'll want to add code where we kill the listener here + + return tcp_reading_thread; +} + +fn spawn_tcp_reading_thread(stream: TcpStream, frame: &'static AtomicUsize, previous_frame: &'static AtomicUsize) -> StoppableHandle<()> { + return stoppable_thread::spawn(move |stopped| { + let mut reader = BufReader::new(stream.try_clone().unwrap()); + + let mut peek = [0u8]; + while stream.peek(&mut peek).is_ok() { + if stopped.get() { + break; + } + + let mut line = String::new(); + reader.read_line(&mut line).unwrap(); + + if is_frame_line(line.as_str()) { + previous_frame.store(frame.load(Ordering::Relaxed), Ordering::Relaxed); + frame.store(extract_frame(line.as_str()).unwrap() as usize, Ordering::Relaxed); + } + } + }); +} + +fn is_frame_line(input: &str) -> bool { + return input.contains("frame="); +} + +pub fn extract_frame(line: &str) -> Result { + return capture_group(line, r"^frame=([0-9]+)") + .parse::(); +} \ No newline at end of file