Hey devs! It's far from finished, but here's a glimpse at the new
video pipeline layer for mplayer-g2. The main functions of interest
are vp_pull_image, vp_get_image, and vp_release_image. vp_config and
vp_insert_filter are somewhat relevant to the dreaded auto-insertion
hack too. :)
Please read and make comments. I have no idea if the code actually
compiles but it should be roughly correct. Some key points:
Image dimensions: You don't pick the image size when requesting an
image like you did in G1. Instead it's implicit from how config() was
called. Along with this change, there's a much clearer distinction
between actual picture dimensions and allocated (stride). Thus filters
will be sure to have the correct values for width/height so they don't
end up processing extra junk/blackspace outside the image (possibly
causing them to behave wrong!).
Aspect: Use sample aspect ratio rather than display aspect ratio! This
means we don't have to constantly recompute d_width/d_height (making
bad estimates and introducing error) every time we crop/expand/etc.
Most filters can just pass sample aspect through unchanged, or making
simple changes such as doubling the sample width or height (the only
notable exception is scale). Monitor aspect can get figured in at the
_end_ of the chain (where it belongs) instead of the beginning.
Stride restrictions: Greatly simplified, and the flag names are
actually consistent with what they mean now. From vp.h:
// Note: Stride restrictions are for compatibility with legacy codecs ONLY!
// ALL filters and vo MUST accept any stride as input!
// Aligned stride is always implicitly preferred when not forbidden!!
PTS: We now use a discrete time base fraction instead of floats.
Filters are free to modify the time base if they wish. This should
prevent error accumulation during lengthy encodes and help mencoder
automatically select a good time base for the output file. Decoders
should select the correct natural timebase (msec for asf, 60000/1001
for ntsc mpeg, 50/1 for pal mpeg, fps for fixed-fps formats, etc.).
DR and slices: "Slices" are replaced with an indirect buffer type,
indirect meaning that you can't write directly to it, only through
the draw_indirect() function. Both DR and indirect rendering (slices)
are accomplished by requesting special buffer types from vp_get_image.
Rather than falling back to automatic (allocated) buffer, vp_get_image
will _fail_ if DR/indirect buffer is not available! This is to give
the source filter/codec more flexibility in deciding which buffer type
to use. (For example, it may be better to fallback to export instead
of automatic buffer if DR fails.) Unlike in G1, indirect rendering
does not have to be done in "slices", but any region can be drawn via
draw_indirect().
The auto-insertion hack: ... :)) It should be pretty self-explanatory.
Basically, when a new filter is auto-inserted at vp_config() time, the
link between the two filters is split in two. The part connected to
the dest filter remains in place, and a new "sister" link is created
to remain with the source filter. Then scale (or whatever you like) is
inserted in between. When execution gets back to vp_pull_image, it
sees that the link it's processing has a sister, so it stuffs the
image back to the sister and clears the sister field, then calls
pull_image on the link again, this time getting an image from the
newly inserted conversion filter. It's hard to explain so RTFS!! :)
Comments are welcome, but please make an attempt to understand the
code before just flaming!
Rich