3862
|
1 A Guide To Developing MPlayer Codecs
|
|
2 by Mike Melanson (melanson at pcisys dot net)
|
7349
|
3 updated to libmpcodecs arch by A'rpi
|
3862
|
4
|
7399
|
5 SEE ALSO: libmpcodecs.txt !!!
|
|
6
|
3862
|
7 Introduction
|
|
8 ------------
|
|
9 I've developed a number of open source decoders for the MPlayer project,
|
|
10 for both audio and video data. As such, I feel I'm qualified to document a
|
|
11 few notes about developing new codecs for the codebase.
|
|
12
|
|
13 As always, the best way to learn how to incorporate a new codec is to
|
|
14 study a bunch of existing code. This document is supplementary material to
|
|
15 the code, meant to give some tips, pointers, and a general roadmap.
|
|
16
|
|
17 A note about terminology: "Codec" stands for coder/decoder (or
|
|
18 compressor/decompressor, if you prefer). The term refers to a module that
|
|
19 can both encode and decode data. However, this document focuses primarily
|
|
20 on incorporating decoders. Still, the terms "decoder" and "codec" are
|
|
21 often used interchangeably.
|
|
22
|
|
23 Necessary Materials
|
|
24 -------------------
|
|
25 So you've decided that you want to implement a new decoder for
|
|
26 MPlayer. There are a few things you will need:
|
|
27
|
|
28 - Knowledge of the codec to be implemented: You will need to know the data
|
|
29 format of the chunks that MPlayer will pass to you. You will need to know
|
|
30 how to take apart the data structures inside. You will need to know the
|
|
31 algorithmic operations that need to be performed on the data in order to
|
|
32 reconstruct the original media.
|
|
33
|
|
34 - Sample media: Preferably, lots of it. You will need media encoded in
|
|
35 your data format and stored in a media file format that MPlayer knows how
|
|
36 to parse (these include AVI, ASF, MOV, RM, VIVO, among others). If the
|
|
37 encoded data is stored in a media file format that MPlayer doesn't
|
|
38 understand, then you will either need to somehow convert the format to a
|
|
39 media file format that the program does understand, or write your own
|
|
40 MPlayer file demuxer that can handle the data. Writing a file demuxer
|
|
41 is beyond the scope of this document.
|
|
42 Try to obtain media that stresses all possible modes of a
|
|
43 decoder. If an audio codec is known to work with both mono and stereo
|
|
44 data, search for sample media of both types. If a video codec is known to
|
|
45 work at 7 different bit depths, then, as painful as it may be, do what you
|
|
46 can to obtain sample media encoded for each of the 7 bit depths.
|
|
47
|
|
48 - Latest CVS snapshot: It's always useful to develop code for the very
|
|
49 latest development version of MPlayer. Be sure to update your local CVS
|
|
50 copy often.
|
|
51
|
|
52 - General programming knowledge, working Linux development environment: I
|
|
53 would hope that these items would go without saying, but you never know.
|
|
54
|
|
55 Typical Development Cycle
|
|
56 -------------------------
|
|
57 1) Set up basic infrastructure
|
|
58 First things first, there's a big song and dance to go through in order to
|
|
59 let the MPlayer program know that you have a new codec to incorporate.
|
|
60
|
|
61 First, modify your local copy of codecs.conf. It may be system-shared or
|
|
62 in your home directory. Add a new entry for your codec. If it's an open
|
|
63 source codec, it would be a good idea to place the new entry with the rest
|
|
64 of the open source codecs. When you're confident that you have the entry
|
|
65 right, be sure to add it to etc/codecs.conf in your workspace. See the
|
|
66 file codecs.conf.txt for a detailed description of the format of this
|
|
67 file. Create a new audiocodec or videocodec block with the proper info,
|
|
68 FOURCCs/format numbers, output formats, and a unique driver name. Remember
|
|
69 the driver name.
|
|
70
|
|
71 Next, create a new source file which contains the main decoding function
|
|
72 that MPlayer will call to decode data. Eventually, you may have multiple
|
7349
|
73 files which comprise your decoder, but let's start simple here.
|
|
74 For audio codecs, see ad_sample.c skeleton. For video, choose one of the
|
|
75 existing vd_*.c files which you think is close to your codec in behaviour.
|
3862
|
76
|
7349
|
77 Next, modify the Makefile so that it will compile your new source file.
|
|
78 Also, add your codec to the array in ad.c (for audio) or vd.c (for video).
|
3862
|
79
|
|
80 Next, compile the project and see if you have everything correct so far.
|
|
81
|
|
82 Next, you want to make sure that the encoded data is making it to your
|
|
83 decoding function in the first place. This may sound like a trivial
|
|
84 exercise, but there are a lot of things that can go wrong (and I've
|
|
85 watched most of them go wrong in my experience). At the beginning of your
|
|
86 skeleton decoder function, enter the following code:
|
|
87 int i;
|
|
88 for (i = 0; i < 16; i++)
|
|
89 printf ("%02X ", input[i]);
|
|
90 printf ("\n");
|
|
91 When you compile and run MPlayer, your decoder function will print the
|
|
92 first 16 bytes of each data chunk that it receives. Open the sample media
|
|
93 in a hex editor and reconcile what you see on the screen with what
|
|
94 you find in the file. If the decoder is printing the first 16 bytes of
|
|
95 each block, that's a good sign that you're ready to move on to step
|
|
96 2. Otherwise, you need to figure out why the data isn't getting to your
|
|
97 decoder. Is your decoder even being invoked? If not, why not?
|
|
98
|
|
99 2) Develop the decoder
|
4630
|
100 Go for it. Remember to make it work, first, then make it work fast. Some
|
|
101 specific tips:
|
|
102
|
|
103 What output formats should you support in your decoder? Whatever makes
|
|
104 sense. YUV output is always preferable over RGB output. Generally, if a
|
|
105 codec uses a YUV data as its source data, you will be able to decode a
|
|
106 frame of YUV data. If a codec takes RGB data as its input, as many older
|
|
107 video codecs do, then there's no point in supporting YUV output; just
|
|
108 output as many RGB formats as possible.
|
|
109
|
|
110 The most preferred output format for video data is YV12. This is because
|
|
111 MPlayer supports a multitude of hardware devices that can display, scale,
|
|
112 and filter this type of data directly. MPlayer also has a bunch of
|
|
113 optimized conversion functions that can convert YV12 data to any other
|
|
114 type of output data.
|
|
115
|
|
116 If you do take the RGB output route, you should be aware that MPlayer
|
|
117 actually orders packed RGB data as BGR. If you're decoding into a BGR24
|
|
118 buffer, the output will look like:
|
|
119 B G R B G R B G R B ...
|
|
120 If you're decoding into a BGR32 buffer, there will need to be an
|
|
121 additional (unused) byte after each BGR triplet:
|
|
122 B G R - B G R - B G ...
|
|
123
|
|
124 Make liberal use of sanity checks. Start by including the file mp_msg.h at
|
|
125 the start of your decoder. Then you can use the mp_msg() function as you
|
|
126 would a normal printf() statement. Whenever your decoder notices a strange
|
|
127 bit of data or an odd condition, print a message such as:
|
|
128 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Odd data encountered: %d\n", data);
|
|
129 Obviously, you should make the message a little more
|
|
130 descriptive, for your benefit. MSGL_WARN is a good message level for this
|
|
131 type of information. Look in mp_msg.h for all of the error levels. You can
|
|
132 even make MPlayer bail out completely by using MSGL_FATAL, but that should
|
|
133 never be necessary at the data decoder level.
|
|
134
|
|
135 What conditions should trigger a warning? Anything, and I mean *anything*
|
|
136 out of the ordinary. Many chunks of compressed video data contain headers
|
|
137 with data such as width, height, and chunk size. Reconcile these fields
|
|
138 with the parameters passed into the decoding function (if you set it up to
|
|
139 take those parameters). Such data should match up. If it doesn't, issue a
|
|
140 warning and make an executive decision in the code about which data to
|
|
141 believe (personally, I always lend more weight to the data that was passed
|
|
142 into the decoder function, the data that comes from the container file's
|
|
143 header). If there's supposed to be a magic number embedded in, or computed
|
|
144 from, the chunk's header, issue a warning if it isn't correct.
|
|
145
|
|
146 Whenever you're about the index into a memory array with an index that
|
|
147 could theoretically be out of range, then test that the index is in range,
|
|
148 no matter how tedious it seems. Accessing outside of your memory range is,
|
|
149 after all, the number 1 cause of segmentation faults. Never trust that all
|
|
150 the data passed to you will be correct. If an array index suddenly winds
|
|
151 up out of range, it's probably best to issue a warning about it and bail
|
|
152 out of the decoder (but not the whole application).
|
|
153
|
|
154 Writing all of these warning statements may seem insipid, but consider
|
|
155 that if you don't do it when you start writing your decoder, you'll
|
|
156 probably end up doing it later on when your decoder isn't working properly
|
|
157 and you need to figure out why (believe me, I know).
|
3862
|
158
|
|
159 3) Debug and test the decoder
|
|
160 If you're extremely lucky, the decoder will work the first time. If you're
|
|
161 very lucky, it will work after you've reviewed your code a few times and
|
|
162 corrected a few obvious programming mistakes. Realistically, you will
|
|
163 write the decoder, review it many times and fix many obvious and subtle
|
|
164 programming errors, and still have to go through an elaborate debug
|
|
165 process in order to get the decoder to a minimally functional state.
|
|
166
|
|
167 Big hint: Ask for all warnings. You know, the -Wall option in
|
|
168 gcc? It's very useful to develop your codec while running in debug
|
|
169 mode. In order to compile MPlayer with debug support (which includes -Wall
|
|
170 for all gcc operations), use the --enable-debug option when configuring
|
|
171 the project. Pay attention to all warnings and make it a goal to get
|
|
172 rid of every single one. I'll never forget when the compiler warned me
|
|
173 that there was no point in clamping a signed 16-bit variable within a
|
|
174 signed 16-bit range (the calculation to be clamped was supposed to be
|
|
175 stored in a signed 32-bit variable and then stored in the signed 16-bit
|
|
176 variable). I sat stunned for a moment, feeling like I had just dodged a
|
|
177 bullet as I knew that would have taken me hours to debug that kind of
|
|
178 mistake.
|
|
179
|
|
180 4) Contribute decoder to codebase
|
|
181 Create a patch with the "diff -u" format and email it to the MPlayer
|
|
182 development team for approval. You will likely need to diff the following
|
|
183 files:
|
|
184 - Makefile
|
|
185 - etc/codecs.conf
|
7349
|
186 - ad.c or vd.c
|
|
187 Of course, you will need to include your newly-created file(s):
|
|
188 vd_<name>.c -OR- ad_<name>.c. If you contribute enough decoders, the
|
|
189 development team may even grant you write privileges to the CVS repository.
|
3862
|
190
|
|
191 5) Wait for bug reports to start rolling in
|
|
192 You may think you're finished when you release the codec and if you're
|
|
193 extremely lucky, you will be right. However, it's more likely that people
|
|
194 will start throwing all kinds of oddball media at your decoder that it
|
|
195 never counted on. Cheer up; take comfort in knowing that people are
|
|
196 testing your code and attempting to use it as a real world
|
|
197 application. Download the problem media that people upload to the MPlayer
|
|
198 FTP site and get back to work, implementing fixed code that addresses the
|
|
199 issues. Contribute more patches and encourage people to hammer on your
|
|
200 decoder even more. This is how you make your decoder rock-solid.
|
|
201
|
|
202 EOF
|