Friday, September 23, 2011

Building a Visual Studio 2010 Project with FFmpeg/libavcodec

It's not supposed to be possible, right? Actually, it is, despite what the interwebs sometimes say. I just wanted to point out an excellent post which gives some great detail on building a Visual Studio project with libavcodec. I'm just going to point out a few things, because I did a few things differently.

Building the Project

To build the project, I almost exactly followed what's posted there on that other blog. The only real differences are:

For the custom build step, I simply did:

copy  "[Your_ffmpeg_directory]\bin\*.dll" $(OutDir)

There's two major differences here. First, notice it's OutDir and not OutputDir. The difference is significant, as OutputDir wasn't defined. The second, is the *, so that I didn't have to retype all those lines (laziness is a good thing... kinda).

That was pretty much it for building the project. Not to bad, eh?

Using FFmpeg/libavcodec

To learn the ropes, I used this tutorial. It's horribly out of date, but it helped a lot. One of the things that helped me is following the tutorial, and as I used functions and things, look at the FFmpeg headers to see the documentation for every function. The documentation is sometimes decent, but what's nice is that it'll tell you if something's been deprecated, and if so, what to use instead.

The trickiest function was avcodec_open2. The reason is because it asks for a AVDictionary** as the third parameter, but I couldn't find any real documentation on what that parameter should be. Honestly, I didn't care either. just wanted libavcodec to detect what to do and decode the dang video. After some experimenting, turns out that passing NULL is okay and libavcodec will auto-detect stuff.

And that's pretty much all there is to it! Lots of reading an outdated tutorial, googling, and reading the FFmpeg documentation (to try and use the current functions, rather than the deprecated ones).

A quick note on building FFmpeg/libavcodec with Visual Studio

If you've found this page wondering how to compile FFmpeg and libavcodec with Visual Studio, just realize that's not supported (Update: see the update below). FFmpeg and libavcodec should be compiled with gcc, and then those compiled libraries can be used in your Visual Studio project. This post is about using the binaries once they've been compiled with gcc. If you are wondering how to compile the libraries with gcc, there's lots of sites out there with instructions on how to do it. The main difficulty will be getting Unixy stuff to work on Windows for the compilation to work, but that's what Cygwin and all those other Unix environments are for.

As for why it's not possible to compile FFmpeg with Microsoft's VC: see this page. It's not a full listing, and the reason that page exists is for people to add to it so that FFmpeg can hopefully be made to be natively compilable with VC and Intel's C compiler.

Update! There's some talk about libav's c99-to-c89 which would allow one to convert the C99 code of FFmpeg to C89 (and then hopefully build with VC). It's still pretty new, but the source repository for it can be found here. I've never tried it, so if you try it out and successfully get it to work and VC to build FFmpeg/libav, leave a comment letting me know!

Double Update! As time has gone on, it looks like c99-to-c89 has matured and you can now build FFmpeg with Visual Studio (even statically). I'm going to give this a try some time (may take me awhile to get around to it) and if it works, I'll rewrite this entire post and focus on that.

Sunday, September 4, 2011

Setting Up Version Control On A Home Server

When I first wrote this, I was using Hamachi to create a VPN tunnel into my home network (so I could access it from the outside). It worked okay, but not great. Its service kept stopping and overall it just wasn't reliable. So I switched options.

The problem

The problem with using a home server is that unless you pay extra for a static IP address, chances are your ISP is giving you a dynamic IP address. Which can (and will) change. Which means if you want to access your home server from the outside world, you need to know your home server's IP address, but since it can (and will) change, it turns out to be less than convenient. And if you're like me, I wanted this to be convenient (that was the whole point of having a home server, anyway).

The solution

Use a dynamic DNS service! I initially signed up for No IP to use their dynamic DNS management. But I really wanted to be able to use my own domain name instead of using a domain name provided by No IP. So I bought a domain through Namecheap.

I intentionally did not buy a domain name from Go Daddy. I hate their marketing campaign and they support (or are indifferent towards) Internet and technology laws that I don't support (like SOPA and PIPA). Namecheap, on the other hand, was waaay cheaper, plus they actively fight poorly written and overpowering laws and bills (like SOPA and PIPA). Sorry for the plug, but I have to recommend them. I'm not a domain/Internet guru, so if you need some kind of advanced capabilities with your domain name, I have no idea if Namecheap supports all the features you might need. But they certainly support all the features I need (and plenty more I don't need).

Alright, so I bought a domain name, and then on my home server, I used ddclient to update my domain to point to my home server's (changing) IP address. It worked so well that I ended up using ddclient to point multiple Namecheap domains to my home server (each domain serves a different purpose, and can, if I later decide, be changed to point to a different IP address if I want to split my server's responsibilities amongst multiple servers).

This allows me to have a version control system at home (which regularly gets backed up to the cloud with all my other home computers), and still gives me total control over everything (I can set up SSH, or I can create Samba shares so I can access my files remotely, etc.). It's actually turned out to be fantastic, and I've been using it for over a year now.

In short, here's what I recommend:

  • Buy a domain name with which you can use dynamic DNS
  • Use ddclient (or if you're on Windows/OS X, google for things like "dynamic ip update client" to find something similar) to update that domain name to point to your server's dynamic IP
  • And that's it!

Note that you may have to set up your router to do some port forwarding. Most (if not all) routers will block external access (for security reasons), so you will probably need to tell your router to allow specific ports (and then forward those ports to the server). If your router does port forwarding based on (local) IP address (i.e. 192.168.x.x, 10.x.x.x, etc.) instead of MAC address, and your router does DHCP, you will probably want to give your server a static (local) IP address instead of a dynamic one assigned by your router's DHCP service (or set your router's DHCP service to always give the same computer (based on its MAC address) the same (local) IP). This is an option that you should be able to find on your router.