{"id":706,"date":"2018-11-13T12:57:55","date_gmt":"2018-11-13T12:57:55","guid":{"rendered":"http:\/\/blogs.gentoo.org\/lu_zero\/?p=706"},"modified":"2018-11-13T12:57:55","modified_gmt":"2018-11-13T12:57:55","slug":"rav1e-and-crav1e-a-fast-and-safe-av1-encoder-some-howto","status":"publish","type":"post","link":"https:\/\/blogs.gentoo.org\/lu_zero\/2018\/11\/13\/rav1e-and-crav1e-a-fast-and-safe-av1-encoder-some-howto\/","title":{"rendered":"rav1e and crav1e &#8211; A fast and safe AV1 encoder &#8211; Some HowTo"},"content":{"rendered":"<p>Over the year I contributed to an <a href=\"https:\/\/aomedia.org\/av1-features\/get-started\/\">AV1<\/a> encoder written in <a href=\"https:\/\/rustlang.org\">rust<\/a>.<\/p>\n<p>Here a small tutorial about what is available right now, there is still lots to do, but I think we could enjoy more user-feedback (and possibly also some help).<\/p>\n<h2>Setting up<\/h2>\n<h3>Install the rust toolchain<\/h3>\n<p>If you do not have <a href=\"https:\/\/rustlang.org\">rust<\/a> installed, it is quite simple to get a full environment using <a href=\"https:\/\/rustup.rs\">rustup<\/a><\/p>\n<pre><code>$ curl https:\/\/sh.rustup.rs -sSf | sh\n# Answer the questions asked and make sure you source the `.profile` file created.\n$ source ~\/.profile\n<\/code><\/pre>\n<h3>Install cmake, perl and nasm<\/h3>\n<p><a href=\"https:\/\/github.com\/xiph\/rav1e\">rav1e<\/a> uses <a href=\"https:\/\/aomedia.googlesource.com\/aom\">libaom<\/a> for testing and and on x86\/x86_64 some components have SIMD variants written directly using <code>nasm<\/code>.<\/p>\n<p>You may follow <a href=\"https:\/\/aomedia.googlesource.com\/aom#building-the-library-and-applications\">the instructions<\/a>, or just install:<br \/>\n&#8211; <a href=\"https:\/\/nasm.us\/\">nasm<\/a> (version 2.13 or better)<br \/>\n&#8211; <a href=\"https:\/\/www.perl.org\/get.html\">perl<\/a> (any recent perl5)<br \/>\n&#8211; <a href=\"https:\/\/cmake.org\/\">cmake<\/a> (any recent version)<\/p>\n<p>Once you have those dependencies in you are set.<\/p>\n<h3>Building rav1e<\/h3>\n<p>We use <strong>cargo<\/strong>, so the process is straightforward:<\/p>\n<pre><code>## Pull in the customized libaom if you want to run all the tests\n$ git submodule update --init\n\n## Build everything\n$ cargo build --release\n\n## Test to make sure everything works as intended\n$ cargo test --features decode_test --release\n\n## Install rav1e\n$ cargo install\n<\/code><\/pre>\n<h2>Using rav1e<\/h2>\n<p>Right now rav1e has a quite simple interface:<\/p>\n<pre><code>rav1e 0.1.0\nAV1 video encoder\n\nUSAGE:\n    rav1e [OPTIONS]  --output \n\nFLAGS:\n    -h, --help       Prints help information\n    -V, --version    Prints version information\n\nOPTIONS:\n    -I, --keyint     Keyframe interval [default: 30]\n    -l, --limit                  Maximum number of frames to encode [default: 0]\n        --low_latency      low latency mode. true or false [default: true]\n    -o, --output                Compressed AV1 in IVF video output\n        --quantizer                 Quantizer (0-255) [default: 100]\n    -r \n    -s, --speed                  Speed level (0(slow)-10(fast)) [default: 3]\n        --tune                    Quality tuning (Will enforce partition sizes &gt;= 8x8) [default: psnr]  [possible\n                                        values: Psnr, Psychovisual]\n\nARGS:\n        Uncompressed YUV4MPEG2 video input\n\n<\/code><\/pre>\n<p>It accepts <code>y4m<\/code> raw source and produces <code>ivf<\/code> files.<\/p>\n<p>You can configure the encoder by setting the <code>speed<\/code> and <code>quantizer<\/code> levels.<\/p>\n<p>The <code>low_latency<\/code> flag can be turned off to run some additional analysis over a set of frames and have additional quality gains.<\/p>\n<h2>Crav1e<\/h2>\n<p>While <a href=\"https:\/\/github.com\/rust-av\/ave\">ave<\/a> and <a href=\"https:\/\/github.com\/sdroege\/gst-plugin-rs\">gst-rs<\/a> will use the <strong>rav1e<\/strong> crate directly, there are a number of software such as <a href=\"https:\/\/handbrake.fr\/\">handbrake<\/a> or <a href=\"https:\/\/videolan.org\">vlc<\/a> that would be much happier to consume a C API.<\/p>\n<p>Thanks to the <code>staticlib<\/code> target and <a href=\"https:\/\/github.com\/eqrion\/cbindgen\/\">cbindgen<\/a> is quite easy to produce a C-ABI library and its matching header.<\/p>\n<h3>Setup<\/h3>\n<p><a href=\"https:\/\/github.com\/lu-zero\/crav1e\">crav1e<\/a> is built using <a href=\"https:\/\/github.com\/rust-lang\/cargo\">cargo<\/a>, so nothing special is needed right now beside <code>nasm<\/code> if you are building it on <code>x86\/x86_64<\/code>.<\/p>\n<h4>Build the library<\/h4>\n<p>This step is completely straightforward, you can build it as <code>release<\/code>:<\/p>\n<pre><code class=\"language-sh\">$ cargo build --release\n<\/code><\/pre>\n<p>or as <code>debug<\/code><\/p>\n<pre><code class=\"language-sh\">$ cargo build\n<\/code><\/pre>\n<p>It will produce a <code>target\/release\/librav1e.a<\/code> or a <code>target\/debug\/librav1e.a<\/code>.<br \/>\nThe C header will be in <code>include\/rav1e.h<\/code>.<\/p>\n<h4>Try the example code<\/h4>\n<p>I provided a quite minimal sample case.<\/p>\n<pre><code class=\"language-sh\">cc -Wall c-examples\/simple_encoding.c -Ltarget\/release\/ -lrav1e -Iinclude\/ -o c-examples\/simple_encoding\n.\/c-examples\/simple_encoding\n<\/code><\/pre>\n<p>If it builds and runs correctly you are set.<\/p>\n<h4>Manually copy the <code>.a<\/code> and the <code>.h<\/code><\/h4>\n<p>Currently <code>cargo install<\/code> does not work for our purposes, but it will change in the future.<\/p>\n<pre><code class=\"language-sh\">$ cp target\/release\/librav1e.a \/usr\/local\/lib\n$ cp include\/rav1e.h \/usr\/local\/include\/\n<\/code><\/pre>\n<h3>Missing pieces<\/h3>\n<p>Right now <code>crav1e<\/code> works well enough but there are few shortcomings I&#8217;m trying to address.<\/p>\n<h4>Shared library support<\/h4>\n<p>The <code>cdylib<\/code> target does exist and produce a nearly usable library but there are some issues with <a href=\"https:\/\/github.com\/rust-lang\/cargo\/issues\/5045\">soname<\/a> support. I&#8217;m trying to <a href=\"https:\/\/github.com\/rust-lang\/cargo\/pull\/6298\">address<\/a> them with upstream, but it might take some time.<\/p>\n<p>Meanwhile some people suggest to use <a href=\"https:\/\/nixos.org\/patchelf.html\">patchelf<\/a> or similar tools to fix the library after the fact.<\/p>\n<h4>Install target<\/h4>\n<p><code>cargo<\/code> is generally awesome, but sadly its support for installing arbitrary files to arbitrary paths is <a href=\"https:\/\/github.com\/rust-lang\/cargo\/issues\/2729\">limited<\/a>, luckily there are people proposing solutions.<\/p>\n<h5><code>pkg-config<\/code> file generation<\/h5>\n<p>I consider a library not proper if a <code>.pc<\/code> file is not provided with it.<\/p>\n<p>Right now there are means to extract the information need to build a <code>pkg-config<\/code> file, but there isn&#8217;t a simple way to do it.<\/p>\n<pre><code>$ cargo rustc -- --print native-static-libs\n<\/code><\/pre>\n<p>Provides what is needed for <code>Libs.private<\/code>, ideally it should be created as part of the install step since you need to know the <code>prefix<\/code>, <code>libdir<\/code> and <code>includedir<\/code> paths.<\/p>\n<h2>Coming next<\/h2>\n<p>Probably the next blog post will be about my efforts to make <a href=\"https:\/\/github.com\/rust-lang\/cargo\">cargo<\/a> able to produce proper <code>cdylib<\/code> or something quite different.<\/p>\n<blockquote><p>\n  <strong>PS<\/strong>: If somebody feels to help me with <a href=\"https:\/\/github.com\/rust-av\/matroska\/issues\/8\">matroska in AV1<\/a> would be great \ud83d\ude42\n<\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>Over the year I contributed to an AV1 encoder written in rust. Here a small tutorial about what is available right now, there is still lots to do, but I think we could enjoy more user-feedback (and possibly also some help). Setting up Install the rust toolchain If you do not have rust installed, it &hellip; <a href=\"https:\/\/blogs.gentoo.org\/lu_zero\/2018\/11\/13\/rav1e-and-crav1e-a-fast-and-safe-av1-encoder-some-howto\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">rav1e and crav1e &#8211; A fast and safe AV1 encoder &#8211; Some HowTo<\/span><\/a><\/p>\n","protected":false},"author":10,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[1],"tags":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p1aGWH-bo","_links":{"self":[{"href":"https:\/\/blogs.gentoo.org\/lu_zero\/wp-json\/wp\/v2\/posts\/706"}],"collection":[{"href":"https:\/\/blogs.gentoo.org\/lu_zero\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.gentoo.org\/lu_zero\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.gentoo.org\/lu_zero\/wp-json\/wp\/v2\/users\/10"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.gentoo.org\/lu_zero\/wp-json\/wp\/v2\/comments?post=706"}],"version-history":[{"count":5,"href":"https:\/\/blogs.gentoo.org\/lu_zero\/wp-json\/wp\/v2\/posts\/706\/revisions"}],"predecessor-version":[{"id":711,"href":"https:\/\/blogs.gentoo.org\/lu_zero\/wp-json\/wp\/v2\/posts\/706\/revisions\/711"}],"wp:attachment":[{"href":"https:\/\/blogs.gentoo.org\/lu_zero\/wp-json\/wp\/v2\/media?parent=706"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.gentoo.org\/lu_zero\/wp-json\/wp\/v2\/categories?post=706"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.gentoo.org\/lu_zero\/wp-json\/wp\/v2\/tags?post=706"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}