## An ffmpeg and SDL Tutorial
Part 1
Part 2
Part 3
Part 4
Part 5
Part 6
Part 7
Part 8
End
ffmpeg is a wonderful library for creating video applications or even general
purpose utilities. ffmpeg takes care of all the hard work of video processing
by doing all the decoding, encoding, muxing and demuxing for you. This can
make media applications much simpler to write. It's simple, written in C,
fast, and can decode almost any codec you'll find in use today, as well as
encode several other formats.
The only prolem is that documentation is basically nonexistent. There is a
single tutorial that shows the basics of ffmpeg and auto-generated doxygen
documents. That's it. So, when I decided to learn about ffmpeg, and in the
process about how digital video and audio applications work, I decided to
document the process and present it as a tutorial.
There is a sample program that comes with ffmpeg called ffplay. It is a simple
C program that implements a complete video player using ffmpeg. This tutorial
will begin with an updated version of the original tutorial, written by Martin
Bohme (I have stolen liberally borrowed from that work), and work from there
to developing a working video player, based on Fabrice Bellard's ffplay.c. In
each tutorial, I'll introduce a new idea (or two) and explain how we implement
it. Each tutorial will have a C file so you can download it, compile it, and
follow along at home. The source files will show you how the real program
works, how we move all the pieces around, as well as showing you the technical
details that are unimportant to the tutorial. By the time we are finished, we
will have a working video player written in less than 1000 lines of code!
In making the player, we will be using SDL to output the audio and video of
the media file. SDL is an excellent cross-platform multimedia library that's
used in MPEG playback software, emulators, and many video games. You will need
to download and install the SDL development libraries for your system in order
to compile the programs in this tutorial.
This tutorial is meant for people with a decent programming background. At the
very least you should know C and have some idea about concepts like queues,
mutexes, and so on. You should know some basics about multimedia; things like
waveforms and such, but you don't need to know a lot, as I explain a lot of
those concepts in this tutorial.
There are printable HTML files along the way as well as old school ASCII
files. You can also get a tarball of the text files and source code or just
the source. You can get a printable page of the full thing in HTML or in text.
**UPDATE:** I've fixed a code error in Tutorial 7 and 8, as well as adding
-lavutil.
Please feel free to email me with bugs, questions, comments, ideas, features,
whatever, at _dranger at gmail dot com_.
_**>>** Proceed with the tutorial!_
## Tutorial 01: Making Screencaps
Code: tutorial01.c
### Overview
Movie files have a few basic components. First, the file itself is called a
**container**, and the type of container determines where the information in
the file goes. Examples of containers are AVI and Quicktime. Next, you have a
bunch of **streams**; for example, you usually have an audio stream and a
video stream. (A "stream" is just a fancy word for "a succession of data
elements made available over time".) The data elements in a stream are called
**frames**. Each stream is encoded by a different kind of **codec**. The codec
defines how the actual data is COded and DECoded - hence the name CODEC.
Examples of codecs are DivX and MP3. **Packets** are then read from the
stream. Packets are pieces of data that can contain bits of data that are
decoded into raw frames that we can finally manipulate for our application.
For our purposes, each packet contains complete frames, or multiple frames in
the case of audio.
At its very basic level, dealing with video and audio streams is very easy:
10 OPEN video_stream FROM video.avi
20 READ packet FROM video_stream INTO frame
30 IF frame NOT COMPLETE GOTO 20
40 DO SOMETHING WITH frame
50 GOTO 20
Handling multimedia with ffmpeg is pretty much as simple as this program,
although some programs might have a very complex "DO SOMETHING" step. So in
this tutorial, we're going to open a file, read from the video stream inside
it, and our DO SOMETHING is going to be writing the frame to a PPM file.
### Opening the File
First, let's see how we open a file in the first place. With ffmpeg, you have
to first initialize the library. (Note that some systems might have to use
<ffmpeg/avcodec.h> and <ffmpeg/avformat.h> instead.)
#include <avcodec.h>
#include <avformat.h>
...
int main(int argc, charg *argv[]) {
av_register_all();
This registers all available file formats and codecs with the library so they
will be used automatically when a file with the corresponding format/codec is
opened. Note that you only need to call av_register_all() once, so we do it
here in main(). If you like, it's possible to register only certain individual
file formats and codecs, but there's usually no reason why you would have to
do that.
Now we can actually open the file:
AVFormatContext *pFormatCtx;
// Open video file
if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
return -1; // Couldn't open file
We get our filename from the first argument. This function reads the file
header and stores information about the file format in the AVFormatContext
structure we have given it. The last three arguments are used to specify the
file format, buffer size, and format options, but by setting this to NULL or
0, libavformat will auto-detect these.
This function only looks at the header, so next we need to check out the
stream information in the file.:
// Retrieve stream information
if(av_find_stream_info(pFormatCtx)<0)
return -1; // Couldn't find stream information
This function populates pFormatCtx->streams with the proper information. We
introduce a handy debugging function to show us what's inside:
// Dump information about file onto standard error
dump_format(pFormatCtx, 0, argv[1], 0);
Now pFormatCtx->streams is just an array of pointers, of size
pFormatCtx->nb_streams, so let's walk through it until we find a video stream.
int i;
AVCodecContext *pCodecCtx;
// Find the first video stream
videoStream=-1;
for(i=0; i<pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) {
videoStream=i;
break;
}
if(videoStream==-1)
return -1; // Didn't find a video stream
// Get a pointer to the codec context for the video stream
pCodecCtx=pFormatCtx->streams[videoStream]->codec;
The stream's information about the codec is in what we call the "codec
context." This contains all the information about the codec that the stream is
using, and now we have a pointer to it. But we still have to find the actual
codec and open it:
AVCodec *pCodec;
// Find the decoder for the video stream
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL) {
fprintf(stderr, "Unsupported codec!\n");
return -1; // Codec not found
}
// Open codec
if(avcodec_open(pCodecCtx, pCodec)<0)
return -1; // Could not open codec
Some of you might remember from the old tutorial that there were two other
parts to this code: adding CODEC_FLAG_TRUNCATED to pCodecCtx->flags and adding
a hack to correct grossly incorrect frame rates. These two fixes aren't in
ffplay.c anymore, so I have to assume that they are not necessary anymore.
There's another difference to point out since we removed that code:
pCodecCtx->time_base now holds the frame rate information. time_base is a
struct that has the numerator and de
ffmpeg原版(英文)教程
5星 · 超过95%的资源 需积分: 10 45 浏览量
2010-03-10
17:57:12
上传
评论 1
收藏 92KB GZ 举报
yzyang007
- 粉丝: 0
- 资源: 1