{"id":2489,"date":"2010-05-20T19:49:31","date_gmt":"2010-05-21T02:49:31","guid":{"rendered":"http:\/\/multimedia.cx\/eggs\/?p=2489"},"modified":"2010-06-17T21:59:52","modified_gmt":"2010-06-18T04:59:52","slug":"vp8-and-ffmpeg","status":"publish","type":"post","link":"https:\/\/multimedia.cx\/eggs\/vp8-and-ffmpeg\/","title":{"rendered":"VP8 And FFmpeg"},"content":{"rendered":"<p><strong>UPDATE, 2010-06-17: You don&#8217;t need to struggle through these instructions anymore. libvpx 0.9.1 and FFmpeg 0.6 work together much better. <a href=\"http:\/\/multimedia.cx\/eggs\/libvpx-0-9-1-and-ffmpeg-0-6\/\">Please see this post for simple instructions<\/a> on getting up and running quickly.<\/strong><\/p>\n<p>Let&#8217;s take the VP8 source code (in Google&#8217;s new libvpx library) for a spin; get it to compile and hook it up to <a href=\"http:\/\/ffmpeg.org\/\">FFmpeg<\/a>. I am hesitant to publish specific instructions for building in the somewhat hackish manner available on day 1 (download FFmpeg at a certain revision and apply a patch) since that kind of post has a tendency to rise in Google rankings. I will just need to remember to update this post after the library patches are applied to the official FFmpeg tree.<\/p>\n<p><strong>Statement of libvpx&#8217;s Relationship to FFmpeg<\/strong><br \/>\nI don&#8217;t necessarily speak officially for FFmpeg. But I&#8217;ve been with the project long enough to explain how certain things work.<\/p>\n<p>Certainly, some may wonder if FFmpeg will incorporate Google&#8217;s newly open sourced libvpx library into FFmpeg. In the near term, FFmpeg will support encoding and decoding VP8 via external library as it does with a number of other libraries (most popularly, <a href=\"http:\/\/www.videolan.org\/developers\/x264.html\">libx264<\/a>). FFmpeg will not adopt the code for its own codebase, even if the license may allow it. That just isn&#8217;t how the FFmpeg crew rolls.<\/p>\n<p>In the longer term, expect the FFmpeg project to develop an independent, interoperable implementation of the VP8 decoder. Sometime after that, there may also be an independent VP8 encoder as well.<\/p>\n<p><strong>Building libvpx<\/strong><br \/>\n<a href=\"http:\/\/code.google.com\/p\/webm\/downloads\/list\">Download and build libvpx<\/a>. This is a basic &#8216;configure &#038;&#038; make&#8217; process. The build process creates a static library, a bunch of header files, and 14 utilities. A bunch of these utilities operate on a file format called IVF which is apparently a simple transport method for VP8. I have <a href=\"http:\/\/wiki.multimedia.cx\/index.php?title=IVF\">recorded the file format on the wiki<\/a>.<\/p>\n<p>We could use a decoder for this in the FFmpeg code base for testing VP8 in the future. <strike>Who&#8217;s game?<\/strike> <em>Just as I was proofreading this post, I saw that David Conrad has sent an IVF demuxer to the ffmpeg-devel list.<\/em><\/p>\n<p>There doesn&#8217;t seem to be a &#8216;make install&#8217; step for the library. Instead, go into the overly long directory (on my system, this is generated as vpx-vp8-nopost-nodocs-generic-gnu-v0.9.0), copy the contents of include\/ to \/usr\/local\/include and the static library in lib\/ to \/usr\/local\/lib .<\/p>\n<p><strong>Building FFmpeg with libvpx<\/strong><br \/>\nDownload FFmpeg source code at the revision specified or take your chances with the latest version (as I did). <a href=\"http:\/\/code.google.com\/p\/webm\/downloads\/list\">Download and apply provided patches<\/a>. This part hurts since there is one diff per file. Most of them applied for me.<\/p>\n<p>Configure FFmpeg with <code>'configure --enable-libvpx_vp8 --enable-pthreads'<\/code>. Ideally, this should yield no complaints and &#8216;libvpx_vp8&#8217; should show up in the enabled decoders and encoders sections. The library apparently relies on threading which is why <code>'--enable-pthreads'<\/code> is necessary. After I did this, I was able to create a new webm\/VP8\/Vorbis file simply with:<\/p>\n<pre>\r\n ffmpeg -i input_file output_file.webm\r\n<\/pre>\n<p>Unfortunately, I can&#8217;t complete the round trip as decoding doesn&#8217;t seem to work. Passing the generated .webm file back into FFmpeg results in a bunch of errors of this format:<\/p>\n<pre>\r\n[libvpx_vp8 @ 0x8c4ab20]v0.9.0\r\n[libvpx_vp8 @ 0x8c4ab20]Failed to initialize decoder: Codec does not implement requested capability\r\n<\/pre>\n<p>Maybe this is the FFmpeg revision mismatch biting me.<\/p>\n<p><strong>FFmpeg Presets<\/strong><br \/>\nFFmpeg features support for preset files which contain collections of tuning options to be loaded into the program. Google provided some presets along with their FFmpeg patches:<\/p>\n<ul>\n<li>1080p50<\/li>\n<li>1080p<\/li>\n<li>360p<\/li>\n<li>720p50<\/li>\n<li>720p<\/li>\n<\/ul>\n<p>To invoke one of these (assuming the program has been installed via &#8216;make install&#8217; so that the presets are in the right place):<\/p>\n<pre>\r\n ffmpeg -i input_file -vcodec libvpx_vp8 -vpre 720p output_file.webm\r\n<\/pre>\n<p>This will use a set of parameters that are known to do well when encoding a 720p video. <\/p>\n<p><strong>Code Paths<\/strong><br \/>\nOne of goals with this post was to visualize a call graph after I got the decoder hooked up to FFmpeg. Fortunately, this recon is greatly simplified by libvpx&#8217;s simple_decoder utility. Steps:<\/p>\n<ul>\n<li>Build libvpx with <code>--enable-gprof<\/code><\/li>\n<li>Run simple_decoder on an IVF file<\/li>\n<li>Get the pl_from_gprof.pl and dot_from_pl.pl scripts frome <a href=\"http:\/\/www.graphviz.org\/Resources.php\">Graphviz&#8217;s gprof filters<\/a><\/li>\n<li>gprof simple_decoder | .\/pl_from_gprof.pl | .\/dot_from_pl.pl &gt; 001.dot<\/li>\n<li>Remove the 2 [graph] and 1 [node] modifiers from the dot file (they only make the resulting graph very hard to read)<\/li>\n<li>dot -Tpng 001.dot > 001.png<\/li>\n<\/ul>\n<p>Here are call graphs generated from decoding <a href=\"\/eggs\/wp-content\/uploads\/2010\/05\/vp80-00-comprehensive-001-call-graph.png\">test vectors 001<\/a> and <a href=\"\/eggs\/wp-content\/uploads\/2010\/05\/vp80-00-comprehensive-017-call-graph.png\">017<\/a>. <\/p>\n<p><center><br \/>\n<div id=\"attachment_2501\" style=\"width: 381px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/multimedia.cx\/eggs\/wp-content\/uploads\/2010\/05\/vp80-00-comprehensive-001-call-graph.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2501\" src=\"http:\/\/multimedia.cx\/eggs\/wp-content\/uploads\/2010\/05\/call-graph-sample.png\" alt=\"\" title=\"Call graph sample\" width=\"371\" height=\"139\" class=\"size-full wp-image-2501\" srcset=\"https:\/\/multimedia.cx\/eggs\/wp-content\/uploads\/2010\/05\/call-graph-sample.png 371w, https:\/\/multimedia.cx\/eggs\/wp-content\/uploads\/2010\/05\/call-graph-sample-300x112.png 300w\" sizes=\"auto, (max-width: 371px) 100vw, 371px\" \/><\/a><p id=\"caption-attachment-2501\" class=\"wp-caption-text\">Like this, only much larger and scarier (click for full graph)<\/p><\/div><br \/>\n<\/center><\/p>\n<p>It&#8217;s funny to see several functions calling an empty bubble. Probably nothing to worry about. More interesting is the fact that a lot of <em>function<\/em>_c() functions are called. The &#8216;_c&#8217; at the end is important&#8211; that generally indicates that there are (or could be) SIMD-optimized versions. I know this codebase has plenty of assembly. All of the x86 ASM files appear to be written such that they could be compiled with NASM.<\/p>\n<p><strong>Leftovers<\/strong><br \/>\nOne interesting item in the code was vpx_scale\/leapster. Is this in reference to the Leapster handheld educational gaming unit? Based on <a href=\"http:\/\/www.on2.com\/index.php?id=486&#038;news_id=215\">this item from 2005<\/a> (<a href=\"http:\/\/web.archive.org\/web\/20071204075211\/http:\/\/www.on2.com\/index.php?id=486&#038;news_id=215\">archive.org copy<\/a>), some Leapster titles probably used VP6. This reminds me of finding references to the PlayStation in Duck\/On2&#8217;s original VpVision source release. I don&#8217;t know of any PlayStation games that used Duck&#8217;s original codecs but with thousands to choose from, it&#8217;s possible that we may find a few some day.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>How to make Google&#8217;s new VP8 work (sort of) with FFmpeg<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[219],"tags":[288],"class_list":["post-2489","post","type-post","status-publish","format-standard","hentry","category-vp8","tag-vp8"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/2489","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/comments?post=2489"}],"version-history":[{"count":16,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/2489\/revisions"}],"predecessor-version":[{"id":2569,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/2489\/revisions\/2569"}],"wp:attachment":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/media?parent=2489"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/categories?post=2489"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/tags?post=2489"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}