1 THE GOAL
2 --------
3 What we are trying to achieve:
5 satisfy:
6 patching of CVS checkout using our patch files placed in our CVS
8 passing of
9 make
10 make distcheck
11 non-srcdir build (ie, mkdir build; cd build; ../configure; make)
13 THE SETUP
14 ---------
15 There is a "mirror" root CVS module that contains "ffmpeg".
16 This directory contains a vendor-branch checkout of upstream FFmpeg CVS
17 of a given day.
19 On head, the following things have been commited on top of this:
20 * patches/, which is a directory with a set of patches, and a series file
21 listing the order, as generated by quilt
22 * the result of having all these patches commited (ie, quilt push -a) to the
23 ffmpeg tree.
25 The patched CVS ffmpeg code needs to be commited to CVS so that a checkout
26 gives the patched code
28 The Quilt state .pc hidden directory must NOT be committed to CVS, because
29 having CVS subdirs inside it confuses the hell out of quilt and causes it to
30 start storing diffs against CVS Entries files, and all hell breaks loose
32 THE WARNING
33 -----------
35 ***
37 NEVER EVER commit stuff in gst-libs/ext/ffmpeg UNLESS your quilt stack is
38 completely applied !
39 This means, ALWAYS make sure quilt push -a has been run without problems.
41 What's more, if you want to be on the safe side, make sure that you can
42 unapply and reapply without problems, by running quilt pop -a then
43 quilt push -a.
45 The ONLY exception to this is when you're working on a branch to update
46 the upstream source you're working with.
48 ***
50 THE WAY
51 -------
52 - If you want to hack on our copy of the FFmpeg code, there are some basic
53 rules you need to respect:
54 - you need to use quilt. If you don't use quilt, you can't hack on it.
55 - we separate patches based on the functionality they patch, and whether
56 or not we want to send stuff upstream. Make sure you work in the right
57 patch. use "quilt applied" to check which patches are applied.
58 - before starting to hack, run cvs diff. There should be NO diffs, and
59 NO files listed with question mark. If there are, somebody before you
60 probably made a mistake. To manage the state correctly, it is vital that
61 none of the files are unknown to CVS.
63 FIRST TIME:
64 - The quilt state is kept in a hidden dir in the gst-libs/ext/ffmpeg dir,
65 but this hidden dir can't be kept in CVS because it confuses patch. Hence
66 when you get a clean gst-ffmpeg checkout you have an ffmpeg tree with
67 patches applied, but no quilt metadata to modify it with.
69 - You need to create the quilt metadata in your checkout:
70 1) Unroll the quilt patches. In gst-libs/ext/ffmpeg, run:
72 tac patches/series | while read p; do patch -p1 -R < "patches/$p"; done
74 2) Now, push all the patches to quilt and it will apply them, but now with
75 the appropriate stored metadata:
77 quilt push -a
79 - if you want to add a file to a patchset, you need to:
80 - be in the right patchset
81 - quilt add (file)
82 - cvs add .pc/(patchsetname)/(file)
83 - cvs commit .pc/(patchsetname) (to update the state of quilt in cvs)
84 - edit the file
85 - cvs add the file if it doesn't exist yet
86 - quilt refresh
87 - quilt push -a (This one is IMPORTANT, otherwise you'll have a huge diff)
88 - cvs commit
90 - if you want to add a patchset, you need to:
91 - go over the procedure with thomas to check it's correct
92 - decide where in the stack to put it. ask for help if you don't know.
93 - go there in the patch stack (use quilt pop/push)
94 - quilt new (patchsetname).patch (don't forget .patch !)
95 - quilt add (files)
96 - cvs add .pc/(patchsetname) the whole tree
97 - cvs commit .pc/(patchsetname)
98 - quilt refresh
99 - quilt push -a
100 - cvs commit
101 - cvs diff (to check if any of the files are unknown to CVS; if they are,
102 you need to add them to CVS)
104 THE UPSTREAM
105 ------------
106 At some points you want to update the upstream snapshot code to a newer date.
107 This is easy if you follow the steps outlined here, but make sure to follow
108 them correctly !
110 - find a good CVS snapshot date for upstream, one that is known to work.
111 You're going to save yourself quite a bit of trouble if you verify this
112 first !
113 - check it out to a local directory:
114 cvs -z9 -d:pserver:anonymous@mplayerhq.hu:/cvsroot/ffmpeg export -D '2004-04-11 23:00 GMT' ffmpeg
115 - compile it and test it, make sure it works
117 - in gst-ffmpeg/gst-libs/ext/ffmpeg:
118 - Pre-flight checks:
119 - first make sure you don't have local changes, all files are either in
120 CVS or in .cvsignore patch, the whole quilt stack is applied, and stuff
121 works.
122 - do a quilt pop -a and quilt push -a to verify everything is ok.
124 - Branch and rollback:
125 - tag HEAD with the branch root point:
126 cvs tag BRANCH-UPDATE-CVS-2004-04-11-23-00-ROOT
127 - branch:
128 cvs tag -b BRANCH-UPDATE-CVS-2004-04-11-23-00
129 - FIXME: lock cvs HEAD
130 - update local copy to branch:
131 cvs update -r BRANCH-UPDATE-CVS-2004-04-11-23-00
132 - peel off all patches:
133 quilt pop -a
134 - commit this
135 cvs commit
136 - check
137 cvs diff
138 you should only have ? for files that are generated somehow (binaries,
139 build files, ...)
140 you get warnings about cvs not finding files to diff that are in .pc
141 or generated by your patches
144 - if you want, you can now compare this state of CVS (which should
145 be last upstream CVS combined with your local unapplied quilt state)
146 - remember to NOT do cvs update from here on, since you popped your quilt
147 state all your added files that are also in CVS are not locally present.
149 - sync with upstream:
150 - in a temp dir, redo the export:
151 cd ..
152 mkdir tmp
153 cd tmp
154 cvs -z9 -d:pserver:anonymous@mplayerhq.hu:/cvsroot/ffmpeg export -D '2004-04-11 23:00 GMT' ffmpeg
155 - rsync it over the old ffmpeg tree
156 rsync -arv ffmpeg ..
157 - go back and commit this new snapshot
158 cd ../ffmpeg
159 cvs commit
160 - check if any new files got added that you should add to cvs
161 cvs diff
162 This will list a lot of local files missing, from your quilt state,
163 which you shouldn't worry about. Just inspect all the ?'s and add
164 files to cvs that belong to upstream and should be in cvs.
165 - if everything's ok and commited, tag the state:
166 cvs tag UPSTREAM-CVS-2004-04-11-23-00
168 - reapply and fix quilt patches one by one
169 - try applying one
170 quilt push
171 - if that didn't work, inspect the patch and figure out how to fix it:
172 - if the patch got applied upstream completely, quilt push will tell
173 you the patch looks like a reverse patch. In that case you can
174 remove the patch from your patches file (patches/series), and
175 remove the .pc/$(patchname) and patches/$(patchname).patch files from
176 cvs.
177 - if the patch conflicts somehow, you can force application with
178 quilt push -f
179 and then resolve all the rejects, and fix the patch completely.
180 Then refresh quilt state with
181 quilt refresh
182 - when the patch is succesfully removed or reworked, commit current state
183 to CVS, then check again if nothing is missing using cvs diff, and
184 resolve problems/apply missing files from your quilt state/...
186 - after reapplying your complete quilt state, test locally if the complete
187 gst-ffmpeg module now works. Compile and test. Resolve all problems
188 (upstream errors, missing symbols, missing files, ...) until you have
189 a working module. commit again.
191 - merge to head:
192 - update locally back to head
193 cvs update -A
194 - FIXME: unlock cvs HEAD
195 - merge from your branch
196 cvs update -j BRANCH-UPDATE-CVS-2004-04-11-23-00
197 - commit
198 cvs commit
199 - check for diffs
200 cvs diff
201 - tag merge point
202 cvs tag BRANCH-UPDATE-CVS-2004-04-11-23-00-MERGE
203 - add upstream date to "THE RECORDS" below
205 - get a drink
207 THE PLUGIN
208 ----------
209 Some notes on how ffmpeg wrapping inside GStreamer currently works:
210 * gstffmpeg{dec,enc,demux,mux}.c are wrappers for specific element types from
211 their ffmpeg counterpart. If you want to wrap a new type of element in
212 wrapper file.
213 The ffmpeg element types, define a whole *list* of elements (in
214 GStreamer, each decoder etc. needs to be its own element).
215 We use a set of tricks for that to keep coding simple: codec
216 mapping and dynamic type creation.
218 * ffmpeg uses CODEC_ID_* enumerations for their codecs. GStreamer uses caps,
219 which consists of a mimetype and a defined set of properties. In ffmpeg,
220 these properties live in a AVCodecContext struct, which contains anything
221 that could configure any codec (which makes it rather messy, but ohwell).
222 To convert from one to the other, we use codec mapping, which is done in
223 gstffmpegcodecmap.[ch]. This is the most important file in the whole
224 ffmpeg wrapping process! It contains functions to go from a codec type
225 (video or audio - used as the output format for decoding or the input
226 format for encoding), a codec id (to identify each format) or a format id
227 (a string identifying a file format - usually the file format extension)
228 to a GstCaps, and the other way around.
230 * to define multiple elements in one source file (which all behave similarly),
231 we dynamically create types for each plugin and let all of them operate on
232 the same struct (GstFFMpegDec, GstFFMpegEnc, ...). The functions in
233 gstffmpeg{dec,enc,demux,mux}.c called gst_ffmpeg*_register() do this.
234 The magic is as follows: for each codec or format, ffmpeg has a single
235 AVCodec or AV{Input,Output}Format, which are packed together in a list of
236 supported codecs/formats. We simply walk through the list, for each of
237 those, we check whether gstffmpegcodecmap.c knows about this single one.
238 If it does, we get the GstCaps for each pad template that belongs to it,
239 and register a type for all of those together. We also leave this inside
240 a caching struct, that will later be used by the base_init() function to
241 fill in information about this specific codec in the class struct of this
242 element (pad templates and codec/format information). Since the actual
243 codec information is the only thing that really makes each codec/format
244 different (they all behave the same through the ffmpeg API), we don't
245 really need to do anything else that is codec-specific, so all other
246 functions are rather simple.
248 * one particular thing that needs mention is how gstffmpeg{mux,demux}.c and
249 gstffmpegprotocol.c interoperate. ffmpeg uses URLProtocols for data input
250 and output. Now, of course, we want to use the *GStreamer* way of doing
251 input and output (filesrc, ...) rather than the ffmpeg way. Therefore, we
252 wrap up a GstPad as a URLProtocol and register this with ffmpeg. This is
253 what gstffmpegprotocol.c does. The URL is called gstreamer://%p, where %p
254 is the address of a GstPad. gstffmpeg{mux,demux}.c then open a file called
255 gstreamer://%p, with %p being their source/sink pad, respectively. This
256 way, we use GStreamer for data input/output through the ffmpeg API. It's
257 rather ugly, but it has worked quite well so far.
259 * there's lots of things that still need doing. See the TODO file for more
260 information.
262 THE RECORDS
263 -----------
264 - list of snapshots used:
266 CVS-2004-04-11-23-00
267 * other updates people didn't enter :)
268 CVS-2006-02-17-04-00
270 THE REMINDERS
271 -------------
272 * the initial ffmpeg checkout was imported using:
273 - get CVS ffmpeg
274 cvs -z3 -d:pserver:anonymous@mplayerhq.hu:/cvsroot/ffmpeg co -D '2004-03-09 06:00 GMT' ffmpeg