(To be fair, knowing ffmpeg exists doesn't mean I'd be able to easily write a video player with it without a lot of research. For that reason I find this tutorial is still quite interesting and valuable.)
For those who are curious how much of a video player can actually be implemented in 1k lines when including a decoder and using existing libraries/OS for nothing more than showing a framebuffer --- I've tried writing toy decoders (no optimisations, pure C, decoding only) for H.261, MPEG-1, and H.262 (MPEG-2). Their line counts are, respectively, 740, 1083, 1461. The MPEG-2 decoder can also decode MPEG-1 since the latter is really an extension of the former. The simplest renderer, using Win32 GDI, is <100 lines. The line counts above are not "code-golfed", although I do tend to write very terse code (avoiding unnecessary abstraction etc.), but also includes things like comments and commented-out debugging code.
That seems to imply that, in 1kLoC of C, you should be able to write a complete video player for MPEG-1, and not much more beyond that. If you're even the slightest bit interested in video compression, I'd recommend giving it a try starting with '261 --- it's not as difficult as it sounds at first glance, and the results are very visible.
(When I have the time, I plan to continue this exercise with H.263, MPEG-4 ASP, and then H.264.)
That's awesome. But isn't H.264 like, 20 times more complicated than H.262? Or maybe not, I just think I remember looking at some big manual, not sure if it was actually H.264. But it seemed super complex. Maybe not as difficult for people who are really good at math.
H.264's complexity increase mainly comes from the large number of prediction modes and macroblock types, which are essentially attempts to encode more efficiently the differences between successive frames.
The maths has actually gotten simpler; the predecessors are all traditional DCT-based (JPEG-like) codecs while H.264 uses a simple integer approximation. Regardless, from a decoder implementation perspective, the theory behind it all is not that important; the spec tells you exactly what you need to do, and the increase in complexity is mainly reflected in needing to write more code to handle the larger number of cases.
H.261 is simple because it has a choice of only two resolutions, one framerate, two frame types (I and P), and 10 macroblock types.
H.262/MPEG-2 is already a significant increase in complexity since it supports a varying set of resolutions, framerates, interlacing, and chroma subsampling, has 3 frame types (I, P, B), 20 macroblock types (dependent on frame type), and more complex motion compensation.
H.263 has no interlacing but adds optional intra prediction, more advanced motion vector encoding, and a few other features.
H.264 has about 50 macroblock types, even more complex intra prediction, and motion compensation has a larger choice of which frames to predict from.
I had to resist the urge to post something similar and yea, it's still way too hard to track down documentation for already solved stuff like this, so there's great value in an article demystifying the process.
> (To be fair, knowing ffmpeg exists doesn't mean I'd be able to easily write a video player with it without a lot of research. For that reason I find this tutorial is still quite interesting and valuable.)
The tutorial is still 1000 lines of C, involving SDL, ffmpeg and threads.
Yikes :)
Last time I did something like this (a UI that among other things, played a live stream from a cheapo IP camera), I used python and the libvlc python bindings. Creating a bare bones media player with it was trivial and it worked very well for what I needed. The only complaint I had at the time was that the documentation was absolutely terrible. A cursory look today reveals that they seem to have improved it, so yay?
And yes, the end result in my case came out MUCH smaller than 1000 lines (but lines of code is a shitty metric anyway).
If you "just" need a media player, IMHO, libvlc is not an awful option (in Python, at least - I have no experience with other bindings): https://wiki.videolan.org/LibVLC/
You got my downvote, there. I saw your comment before I got a chance to read the article, and once I saw the article, and its many pages breaking the components down into introducing the framework, outputting video, sound, etc...
The equivalent to what you're saying would be if he'd just used the HTML5 <video> tag.
This is actually a great article, it taught me a little bit more about FFMPEG under the hood, and knowledge is power.
> ffmpeg takes care of all the hard work of video processing by doing all the decoding, encoding, muxing and demuxing for you.
Seems like a pretty good hint that you are not actually writing a video player in less than 1000 lines.
I mean it's a cool article, but the presentation is misleading and taking credit for something that it is not. And some people who aren't in programming actually see titles like that and think that this type of thing is literally 'easy to program'. Another example is when people say they quickly 'built their own browser'.
Acclaimed video software like VLC also uses FFmpeg/libavcodec to do the encoding/decoding etc, and I don't think anyone is claiming those developers are 'cheating'.
Sadly, the code in this tutorial doesn't work anymore due to upstream changes in FFmpeg. There are quite a few attempts at keeping Dranger's tutorial up to date, but I found the repo below to be one of the better ones.
ffmpeg is awesome. However, there are some issues that all ffmpeg-based players share that I wish someone would tackle (either by fixing ffmpeg or making something new). Seeking performance and reliability (especially single frame seeking) is a big one. Robustness in the face of truncated or otherwise corrupted video files is another. Ffmpeg isn't terrible in these areas, and I realize that there are underlying issues that make these things very hard, but still I believe it is possible to do much better.
Yep. It's a lot of work creating a non-stuttering, fast-seeking player using ffmpeg/libav. For high resolution / high bitrate streams ffmpeg doesn't issue frames smoothely in itself (I-frames takes longer) so I had to create a whole caching structure and issue the frames from a different thread to get it to play smoothely in my application...
On the other hand there are so many edge cases around codecs and assumptions around what is and is not coming so I think that if a different API was created there would likely be a lot of cases where it would break? Something like the NDI API would be great, it is really quick to integrate.
I think its actually mainly just the HN submission actually now that I look at the article again, I see that his first part of the title is "SDL and ffmpeg tutorial".
A lot of folks don't know that ffmpeg isn't just a command line utility (which is pretty powerful in its own right) but also a set of super powerful and reasonably well designed media libraries that can be used to do all kinds of stuff with media. I remember finding this tutorial years ago and it opened up a whole range of possibilities eventually leading to my startup Vidmaker[0] which, while not successful itself, got my cofounders and I acquihired into YouTube. Thank you, dranger, whoever you are.
Wildly off topic, but I ended up on his and Isaac Hoffer’s ‘Top 100 albums of 2004-05’ [0], and wow I’d forgotten how many amazing albums came out in that short span! Wonderful commentary too.
Then I did the math and I guess now I’m an old guy that listens to... classic rock?
Back on topic: For anyone using ffmpeg/libav this tutorial might as well be the official documentation. Absolutely indispensable in my opinion.
The FFmpeg project is amazing but a constantly moving target.
This was very popular around 2015 but is now broken because the API changed.
If you want to try that code you must download an older version of FFmpeg.
I love this guide! I used (an earlier version of) this to write a multimedia-based game in C++ before any of the free game engines had HD video playback support.