7397
|
1 The libMPcodecs API details, hints - by A'rpi
|
|
2 ==================================
|
|
3
|
7399
|
4 See also: colorspaces.txt, codec-devel.txt, dr-methods.txt, codecs.conf.txt
|
7397
|
5
|
|
6 The VIDEO path:
|
|
7 ===============
|
|
8
|
|
9 [MPlayer core]
|
|
10 | (1)
|
|
11 _____V______ (2) /~~~~~~~~~~\ (3,4) |~~~~~~|
|
|
12 | | -----> | vd_XXX.c | -------> | vd.c |
|
|
13 | decvideo | \__________/ <-(3a)-- |______|
|
|
14 | | -----, ,.............(3a,4a).....:
|
|
15 ~~~~~~~~~~~~ (6) V V
|
|
16 /~~~~~~~~\ /~~~~~~~~\ (8)
|
|
17 | vf_X.c | --> | vf_Y.c | ----> vf_vo.c / ve_XXX.c
|
|
18 \________/ \________/
|
|
19 | ^
|
|
20 (7) | |~~~~~~| : (7a)
|
|
21 `-> | vf.c |...:
|
|
22 |______|
|
|
23
|
|
24 Short description of video path:
|
|
25 1. mplayer/mencoder core requests the decoding of a compressed video frame:
|
|
26 calls decvideo.c::decode_video()
|
|
27
|
|
28 2. decode_video() calls the previously ( init_video() ) selected video codec
|
|
29 (vd_XXXX.c file, where XXXX == vfm name, see the 'driver' line of codecs.conf)
|
|
30
|
|
31 3. the codec should initialize output device before decoding the first frame,
|
|
32 it may happen in init() or at the middle of the first decode(). see 3.a.
|
|
33 it means calling vd.c::mpcodecs_config_vo() with the image dimensions,
|
|
34 and the _preferred_ (mean: internal, native, best) colorspace.
|
|
35 NOTE: this colorspace may not be equal to the actually used colorspace, it's
|
|
36 just a _hint_ for the csp matching algorithm, and mainly used _only_ when
|
|
37 csp conversion is required, as input format of the converter.
|
|
38
|
|
39 3.a. selecting the best output colorspace:
|
|
40 the vd.c::mpcodecs_config_vo() function will go through the outfmt list
|
|
41 defined by codecs.conf's 'out' lines, and query both vd (codec) and vo
|
|
42 (output device/filter/encoder) if it's supported or not.
|
|
43
|
|
44 For the vo, it calls the query_format() func of vf_XXX.c or ve_XXX.c.
|
|
45 It should return a set of feature flags, the most important ons for this
|
|
46 stage are: VFCAP_CSP_SUPPORTED (csp supported directly or by conversion)
|
|
47 and VFCAP_CSP_SUPPORTED_BY_HW (csp supported WITHOUT any conversion).
|
|
48
|
|
49 For the vd (codec), control() with VDCTRL_QUERY_FORMAT will be called.
|
|
50 If it doesn't implement VDCTRL_QUERY_FORMAT, (ie answers CONTROL_UNKNOWN
|
|
51 or CONTROL_NA) it will be assumed to be CONTROL_TRUE (csp supported)!
|
|
52
|
|
53 So, by default, if the list of supported colorspaces is constant, doesn't
|
|
54 depend on the actual file's/stream's header, it's enough to list them
|
|
55 in codecs.conf ('out' field), and don't implement VDCTRL_QUERY_FORMAT.
|
|
56 It's the case for the most codecs.
|
|
57
|
|
58 If the supported csp list depends on the file being decoded, list the
|
|
59 possible out formats (colorspaces) in codecs.conf, and implement the
|
|
60 VDCTRL_QUERY_FORMAT to test the availability of the given csp for the
|
|
61 given video file/stream.
|
|
62
|
|
63 The vd.c core will find the best matching colorspace, depending on the
|
|
64 VFCAP_CSP_SUPPORTED_BY_HW flag (see vfcap.h). If no match at all, it
|
|
65 will try again with the 'scale' filter inserted between vd and vo.
|
|
66 If still no match, it will fail :(
|
|
67
|
|
68 4. requesting buffer for the decoded frame:
|
|
69 The codec have to call mpcodecs_get_image() with proper imgtype & imgflag.
|
|
70 It will find the optimal buffering setup (preferred stride, alignment etc)
|
|
71 and return a pointer to the allocated and filled up mpi (mp_image_t*) struct.
|
|
72 The 'imgtype' controls the buffering setup, ie STATIC (just one buffer,
|
|
73 it 'remembers' its contents between frames), TEMP (write-only, full update),
|
|
74 EXPORT (memory allocation is done by the codec, not recommended) and so on.
|
|
75 The 'imgflags' set up the limits for the buffer, ie stride limitations,
|
|
76 readability, remembering content etc. See mp_image.h for the short descr.
|
|
77 See dr-methods.txt for the explanation of buffer importing and mpi imgtypes.
|
|
78
|
|
79 Always try to implement stride support! (stride == bytes per line)
|
|
80 If no stride support, then stride==bytes_per_pixel*image_width.
|
|
81 If you have stride supoprt in your decoder, use the mpi->stride[] value
|
|
82 for the byte_per_line for each plane.
|
|
83 Also take care of other imgflags, like MP_IMGFLAG_PRESERVE and
|
|
84 MP_IMGFLAG_READABLE, MP_IMGFLAG_COMMON_STRIDE and MP_IMGFLAG_COMMON_PLANE!
|
|
85 The file mp_image.h contains description of flags in comments, read it!
|
|
86 Ask for help on -dev-eng, describing the behaviour your codec, if unsure.
|
|
87
|
|
88 4.a. buffer allocation, vd.c::mpcodecs_get_image():
|
|
89 If the requested buffer imgtype!=EXPORT, then vd.c will try to do
|
|
90 direct rendering, ie. asks the next filter/vo for the buffer allocation.
|
|
91 It's done by calling get_image() of the vf_XXX.c file.
|
|
92 If it was successful, the imgflag MP_IMGFLAG_DIRECT will be set, and one
|
|
93 memcpy() will be saved when passing the data from vd to the next filter/vo.
|
|
94 See dr-methods.txt for details and examples.
|
|
95
|
|
96 5. decode the frame, to the mpi structure requested at 4, then return the mpi
|
|
97 to decvideo.c. Return NULL if the decoding failed or skipped frame.
|
|
98
|
|
99 6. decvideo.c::decode_video() will now pass the 'mpi' to the next filter (vf_X).
|
|
100
|
|
101 7. the filter's (vf_X) put_image() then requests a new mpi buffer by calling
|
|
102 vf.c::vf_get_image().
|
|
103
|
|
104 7.a. vf.c::vf_get_image() will try to get direct rendering, by asking the
|
|
105 next fliter to do the buffer allocation (calls vf_Y's get_image()).
|
|
106 if it fails, it will fallback to normal system memory allocation.
|
|
107
|
|
108 8. when we're over the whole filter chain (multiple filters can be connected,
|
|
109 even the same filter multiple times) then the last, 'leaf' filter will be
|
|
110 called. The only difference between leaf and non-leaf filter is that leaf
|
|
111 filter have to implement the whole filter api.
|
|
112 Leaf filters are now: vf_vo.c (wrapper over libvo) and ve_XXX.c (video
|
|
113 encoders used by mencoder).
|
|
114
|
8001
|
115 The VIDEO FILTER API:
|
|
116 =====================
|
|
117 filename: vf_FILTERNAME.c
|
|
118
|
|
119 vf_info_t* info;
|
|
120 pointer to the filter description structure:
|
|
121
|
|
122 const char *info; // description of the filter
|
|
123 const char *name; // short name of the filter, must be FILTERNAME
|
|
124 const char *author; // name and email/url of the author(s)
|
|
125 const char *comment;// comment, url to papers describing algo etc.
|
|
126 int (*open)(struct vf_instance_s* vf,char* args);
|
|
127 // pointer to the open() function:
|
|
128
|
8020
|
129 Sample:
|
|
130
|
|
131 vf_info_t vf_info_foobar = {
|
|
132 "Universal Foo and Bar filter",
|
|
133 "foobar",
|
|
134 "Ms. Foo Bar",
|
|
135 "based on algo described at http://www.foo-bar.org",
|
|
136 open
|
|
137 };
|
|
138
|
8001
|
139 The open() function:
|
|
140
|
|
141 open() is called when the filter is appended/inserted to the filter chain.
|
|
142 it'll receive the handler (vf) and the optional filter parameters as
|
|
143 char* string. Note, that encoders (ve_*) and vo wrapper (vf_vo.c) have
|
|
144 non-string arg, but it's specially handled by mplayer/mencoder.
|
|
145
|
|
146 The open() function should fill the vf_instance_t structure, with the
|
|
147 implemented functions' pointers (see bellow).
|
|
148 It can optinally allocate memory for its internal data (vf_priv_t) and
|
|
149 store the pointer in vf->priv.
|
|
150
|
|
151 The open() func should parse (or at least check syntax) of parameters,
|
|
152 and fail (return 0) if error.
|
|
153
|
|
154 Sample:
|
|
155
|
|
156 static int open(vf_instance_t *vf, char* args){
|
|
157 vf->query_format=query_format;
|
|
158 vf->config=config;
|
|
159 vf->put_image=put_image;
|
|
160 // allocate local storage:
|
|
161 vf->priv=malloc(sizeof(struct vf_priv_s));
|
|
162 vf->priv->w=
|
|
163 vf->priv->h=-1;
|
|
164 if(args) // parse args:
|
|
165 if(sscanf(args, "%d:%d", &vf->priv->w, &vf->priv->h)!=2) return 0;
|
|
166 return 1;
|
|
167 }
|
|
168
|
|
169 Functions in vf_instance_s:
|
|
170
|
|
171 NOTE: All these are optional, their func pointer is either NULL or points to
|
|
172 a default implementation. If you implement them, don't forget to set
|
|
173 vf->FUNCNAME in your open() !
|
|
174
|
|
175 int (*query_format)(struct vf_instance_s* vf,
|
|
176 unsigned int fmt);
|
|
177
|
|
178 The query_format() func. is called one or more times before the config(),
|
|
179 to find out the capabilities and/or support status of a given colorspace (fmt).
|
|
180 For the return values, see vfcap.h!
|
|
181 Normally, a filter should return at least VFCAP_CSP_SUPPORTED for all supported
|
8020
|
182 colorspaces it accepts as input, and 0 for the unsupported ones.
|
|
183 If your filter does linear conversion, it should query the next filter,
|
|
184 and merge in its capability flags. Note: you should always ensure that the
|
|
185 next filter will accept at least one of your possible output colorspaces!
|
8001
|
186
|
|
187 Sample:
|
|
188
|
|
189 static int query_format(struct vf_instance_s* vf, unsigned int fmt){
|
|
190 switch(fmt){
|
|
191 case IMGFMT_YV12:
|
|
192 case IMGFMT_I420:
|
|
193 case IMGFMT_IYUV:
|
|
194 case IMGFMT_422P:
|
|
195 return vf_next_query_format(vf,IMGFMT_YUY2) & (~VFCAP_CSP_SUPPORTED_BY_HW);
|
|
196 }
|
|
197 return 0;
|
|
198 }
|
|
199
|
8020
|
200 For the more complex case, when you have an N->M colorspace mapping matrix,
|
|
201 see vf_scale or vf_rgb2bgr for examples.
|
|
202
|
8001
|
203
|
|
204 int (*config)(struct vf_instance_s* vf,
|
|
205 int width, int height, int d_width, int d_height,
|
|
206 unsigned int flags, unsigned int outfmt);
|
|
207
|
|
208 The config() is called to initialize/confugre the filter before using it.
|
|
209 Its parameters are already well-known from libvo:
|
|
210 width, height: size of the coded image
|
|
211 d_width, d_height: wanted display size (usually aspect corrected w/h)
|
8020
|
212 Filters should use width,height as input image dimension, but the
|
|
213 resizing filters (crop, expand, scale, rotate, etc) should update
|
|
214 d_width/d_height (display size) to preserve the correct aspect ratio!
|
|
215 Filters should not rely on d_width, d_height as input parameters,
|
|
216 the only exception is when a filter replaces some libvo functionality
|
|
217 (like -vop scale with -zoom, or OSD rendering wiht -vop expand).
|
8001
|
218 flags: the "good" old flags set of libvo:
|
|
219 0x01 - force fullscreen (-fs)
|
|
220 0x02 - allow mode switching (-vm)
|
|
221 0x04 - allow software scaling (-zoom)
|
|
222 0x08 - flipping (-flip)
|
|
223 (Usually you don't have to worry about flags, just pass it to next config.)
|
|
224 outfmt: the selected colorspace/pixelformat. You'll receive images in this
|
|
225 format.
|
|
226
|
|
227 Sample:
|
|
228
|
|
229 static int config(struct vf_instance_s* vf,
|
|
230 int width, int height, int d_width, int d_height,
|
|
231 unsigned int flags, unsigned int outfmt){
|
|
232 // use d_width/d_height if not set by user:
|
|
233 if(vf->priv->w==-1) vf->priv->w=d_width;
|
|
234 if(vf->priv->h==-1) vf->priv->h=d_width;
|
|
235 // initialize your filter code
|
|
236 ...
|
|
237 // ok now config the rest of the filter chain, with our output parameters:
|
|
238 return vf_next_config(vf,vf->priv->w,vf->priv->h,d_width,d_height,flags,outfmt);
|
|
239 }
|
|
240
|
|
241 void (*uninit)(struct vf_instance_s* vf);
|
|
242
|
|
243 Okey, uninit() is the simplest, it's called at the end. You can free your
|
|
244 private buffers etc here.
|
|
245
|
|
246 int (*put_image)(struct vf_instance_s* vf,
|
|
247 mp_image_t *mpi);
|
|
248
|
|
249 Ah, put_image(). This is the main filter function it should convert/filter/
|
|
250 transform the image data from one format/size/color/whatever to another.
|
|
251 Its input parameter is an mpi (mplayer image) structure, see mp_image.h.
|
|
252 Your filter has to request a new image buffer for the output, using the
|
|
253 vf_get_image() function. NOTE: even if you don't want to modify the image,
|
|
254 just pass it to the next filter, you have to either
|
|
255 - do not implement put_image() at all - then it will be skipped
|
|
256 - request a new image with type==EXPORT and copy the pointers
|
|
257 NEVER pass the mpi as-is, it's local to filters and may cause trouble.
|
|
258
|
|
259 If you completely copy/transform the image, then you probably want this:
|
|
260
|
|
261 dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
|
262 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
|
263 vf->priv->w, vf->priv->h);
|
|
264
|
|
265 It will allocate a new image, and return an mp_image structure filled by
|
|
266 buffer pointers and stride (bytes per line) values, in size of vf->priv->w
|
|
267 times vf->priv->h. If your filter cannot handle stride, then left out
|
|
268 MP_IMGFLAG_ACCEPT_STRIDE. Note, that you can do this, but it isn't recommended,
|
|
269 the whole video path is designed to use strides to get optimal throughput.
|
|
270 If your filter allocates output image buffers, then use MP_IMGTYPE_EXPORT,
|
|
271 and fill the returned dmpi's planes[], stride[] with your buffer parameters.
|
|
272 Note, it is not recommended (no direct rendering), so if you can, use
|
|
273 vf_get_image() for buffer allocation!
|
|
274 For other image types and flags see mp_image.h, it has comments.
|
|
275 If you are unsure, feel free to ask on the -dev-eng maillist. Please
|
|
276 describe the behaviour of your filter, an dits limitations, so we can
|
|
277 suggest the optimal buffer type + flags for your code.
|
|
278
|
|
279 Now, that you have the input (mpi) and output (dmpi) buffers, you can do
|
|
280 the conversion. If you didn't notice yet, mp_image has some useful info
|
|
281 fields, may help you a lot creating if() or for() structures:
|
|
282 flags: MP_IMGFLAG_PLANAR, MP_IMGFLAG_YUV, MP_IMGFLAG_SWAPPED
|
|
283 helps you to handle various pixel formats in single code.
|
|
284 bpp: bits per pixel
|
|
285 WARNING! It's number of bits _allocated_ to store a pixel,
|
|
286 it is not the number of bits actually used to keep colors!
|
|
287 So, it's 16 for both 15 and 16bit color depth, and is 32 for
|
|
288 32bpp (actually 24bit color depth) mode!
|
|
289 It's 1 for 1bpp, 9 for YVU9, and is 12 for YV12 mode. Get it?
|
|
290 For planar formats, you also have chroma_width, chroma_height and
|
8020
|
291 chroma_x_shift, chroma_y_shift too, they specify the chroma subsampling
|
|
292 for yuv formats:
|
|
293 chroma_width = luma_width >>chroma_x_shift;
|
|
294 chroma_height= luma_height>>chroma_y_shift;
|
8001
|
295
|
|
296 If you're done, call the rest of the filter chain to process your output
|
|
297 image:
|
|
298 return vf_next_put_image(vf,dmpi);
|
|
299
|
|
300
|
|
301 Ok, the rest is for advanced functionality only:
|
|
302
|
|
303 int (*control)(struct vf_instance_s* vf,
|
|
304 int request, void* data);
|
|
305
|
|
306 You can control the filter in runtime from mplayer/mencoder/dec_video:
|
|
307 #define VFCTRL_QUERY_MAX_PP_LEVEL 4 /* test for postprocessing support (max level) */
|
|
308 #define VFCTRL_SET_PP_LEVEL 5 /* set postprocessing level */
|
|
309 #define VFCTRL_SET_EQUALIZER 6 /* set color options (brightness,contrast etc) */
|
|
310 #define VFCTRL_GET_EQUALIZER 8 /* gset color options (brightness,contrast etc) */
|
|
311 #define VFCTRL_DRAW_OSD 7
|
|
312 #define VFCTRL_CHANGE_RECTANGLE 9 /* Change the rectangle boundaries */
|
|
313
|
8020
|
314
|
8001
|
315 void (*get_image)(struct vf_instance_s* vf,
|
|
316 mp_image_t *mpi);
|
|
317
|
|
318 This is for direct rendering support, works the same way as in libvo drivers.
|
|
319 It makes in-place pixel modifications possible.
|
|
320 If you implement it (vf->get_image!=NULL) then it will be called to do the
|
|
321 buffer allocation. You SHOULD check the buffer restrictions (stride, type,
|
|
322 readability etc) and if all OK, then allocate the requested buffer using
|
|
323 the vf_get_image() func and copying the buffer pointers.
|
|
324
|
8020
|
325 NOTE: You HAVE TO save dmpi pointer, as you'll need it in put_image() later.
|
|
326 It is not guaranteed that you'll get the same mpi for put_image() as in
|
|
327 get_image() (think of out-of-order decoding, get_image is called in decoding
|
|
328 order, while put_image is called for display) so the only safe place to save
|
|
329 it is in the mpi struct itself: mpi->priv=(void*)dmpi;
|
|
330
|
|
331
|
8001
|
332 void (*draw_slice)(struct vf_instance_s* vf,
|
|
333 unsigned char** src, int* stride, int w,int h, int x, int y);
|
|
334
|
|
335 It's the good old draw_slice callback, already known from libvo.
|
8020
|
336 If your filter can operate on partial images, you can implement this one
|
8001
|
337 to improve performance (cache utilization).
|
|
338
|
8020
|
339 Ah, and there is two set of capability/requirement flags (vfcap.h type)
|
8001
|
340 in vf_instance_t, used by default query_format() implementation, and by
|
|
341 the automatic colorspace/stride matching code (vf_next_config()).
|
|
342
|
|
343 // caps:
|
|
344 unsigned int default_caps; // used by default query_format()
|
|
345 unsigned int default_reqs; // used by default config()
|
|
346
|
7397
|
347
|
|
348 The AUDIO path:
|
|
349 ===============
|
|
350 TODO!!!
|