[MPlayer-G2-dev] libvo2 documentation and pre22 iz out
Arpi
arpi at thot.banki.hu
Sat May 10 22:04:04 CEST 2003
Hi,
I've just uploaded pre22, with the bsd/darwin patches, and some libvo2
api simplification.
I've also finished libvo2 dosc, here's it for discussion:
Libvo G2 API definition, driver porting tips: [by A'rpi]
=============================================
The main differences to libvo1 (used in mplayer 0.90/main):
drivers now export their own buffers, instead of handling them:
In libvo1, you had to implement draw_slice, draw_frame, draw_image which
did the image blitting (copy to buffer), or get_image to export buffer
when several conditions accepted. Also vo1 drivers did OSD rendering.
In libvo2, you (almost) always export the buffer pointers (planes[]+stride[])
and a flag set describing the buffer behaviour (is it in cvideo ram or fast
system ram, is it visible while rendering into it or it's backbuffer etc).
All the buffer selection (for double/triple etc buffering), video blitting,
colorspace conversion, DR decisions (get_image) is done by vf_vo2.c now.
Actually there is a way (for compatibility?) to let vo2 drivers fo the blitting,
by implementig draw_slice(), for the cases when tere are no actual buffers to
export or it's too problematic to implement for dunno-what reason.
An example for that is old SVGALIB api, when you had to call a draw() function
to get your image displayed, you never see teh actual video buffer.
(actually for some old vga cards it isn't even visible at once, as it's
segmented to 64k blocks... so you can access it via a 64k window)
Buffers:
~~~~~~~~
So, the first decision you have to do, when starting to write/port a vo2 driver:
Are you able to export the buffers (plane pointers and stride(==bytes per line))
or aren't.
The former case (exporting buffers) is simpler:
You have to allocate (calloc()) an array of vo_bufffer_t structures, and put
the pointer into vo->buffers. Then loop though the array and fill each buffer
description struct, ie. put plane pointers/stride there. You can store your
private per-buffer data in vo_buffer_t->priv.
The number of allocated buffers should be put into vo->num_buffers.
The case for indirect access (cannot export buffers, but can blit into it)
is very similar, with the difference that you don't fill the planes/stride
of the buffers, and you set the VO_BUFFER_FLAG_INDIRECT later.
In this case, you have to implement draw_slice() function, which will do
the blitting (copy to the buffer).
You have to fill the buffer_flags, according to the behaviour of your buffers:
VO_BUFFER_FLAG_INDIRECT:
Set this flag, if you don't export buffers (buffer[n]->planes/stride unset)
but you will do the blitting in draw_slice(). Try to avoid this, for
performance reasons.
VO_BUFFER_FLAG_VIDEORAM:
Set this flag, if your buffer is located in slow, linear adressable,
mostly write-only buffer. When this flag set, the buffers won't be used
for storing prediction (I/P) frames or doing in-place filtering.
(so, set this flag, if reading or random addressing of this buffer is
much (at least 2 times) slower than doing the same in system ram)
VO_BUFFER_FLAG_VISIBLE:
Set this flag, if the changes in this buffer are immediatelly visible,
not only when calling show_frame().
So, if your buffers are back-buffers copied to the visible area (usually
the videocard's RAM) by the driver or the hardware (DMA etc) itself, NOT
set this. If your buffers are in the visible video ram area, set this.
[Note: for the case of num_buffers>1, it's always meant to the buffer
addressed in the show_frame(). It's natural, that if you render into
different buffer than show_frame() addressed, it won't be visible...]
This flag is used to make buffering setup decisions, with VISIBLE buffers
you need at least 3 buffer (triple buffering) for flickerless picture,
but with back-buffer (this flag NOT set) it's enough to have only one.
VO_BUFFER_FLAG_TIMER:
Set this flag, when your vo driver (hardware) can display the buffer
content at a given (by PTS) time.
Ie, if your hardware have a timer, what you can program to display the
buffer only when a given timestamp reached. This flag is useful for
hardware mpeg/mjpeg decoder cards, and maybe some advanced TV play-out
hardware. But I can imagine the case, when for example mga_vid implements
vblank (vertical retrace) IRQ handler, and it can check and swap buffers
to have proper interlaced 50/60Hz output rather than usec_sleep() timing.
General driver layout:
~~~~~~~~~~~~~~~~~~~~~~
The layout is very similar to libvo1: You have a preinit, uninit and config
function. The order is:
1. preinit()
2. multiple calls to query_format()
3. 0, 1, 2 or more calls to config()
4. uninit()
preinit: it should detect the availability of the device/driver, and return 0
(error) if it isn't usable. It have 2 parameters, the first one is the
subdevice string (can be used to name the device, or pass extra parameters)
and a special second parameter to pass teh X11 Display connection, required
only by X11-based drivers. Any x11 drivers should return 0 immediatelly when
x11_display==NULL ! non-x11 drivers should ignore that parameter!
query_format: it is called multiple times to auto-negotiate a common colorspace
format and query some driver capability flags. It's used (required) to find
and setup optimal filter path for the rendering.
See vfcap.h for flags, and read bellow the details i next section.
config: it will be called to configure (or change) the device, to a given
source/destination size and colorspace format. NOTE that config() may be
called zero (==never called), one, or more times between preinit and uninit!
You have to be extra carefull to prepare your driver for this, ie it should
NOT crash in uninit() when config() was never called, and second config()
shouldn't crash or open new window/device!!!
To help you, there is vo->config_count, it's always increased by 1,
when config() returns 1, by the caller.
Note2: config() is called only after successfull (return 1) preinit() call!
uninit: called when the apps stop using this driver (usually at exit, or
vo driver change). Note: it's only called after successfull (return 1)
preinit() call!
Driver capability flags ie. what query_format() may return:
~~~~~~~~~~~~~~~~~~~~~~~
The return value of query_format() should be a flag set composed from
these, defined at ../video/vfcap.h:
VFCAP_CSP_SUPPORTED:
The given (parameter of query-format) colorspace is supported.
VFCAP_CSP_SUPPORTED_BY_HW:
The given colorspace is supported directly, without conversion.
Some driver may support multiple colorspaces, but use internal
software converters to handle non-native formats.
This flag can be used to give some modes a priority over the rest.
Note: when you set VFCAP_CSP_SUPPORTED_BY_HW, you also HAVE TO set
VFCAP_CSP_SUPPORTED too!!!
VFCAP_OSD:
The driver/hardware can do OSD rendering.
NOTE: You do NOT need to implement osd rendering controls and set this
flag to have OSD working! It's normally done by vf_vo2.c or vf_expand,
this flag is only needed for hardware-accelerated OSD renderers, or
hardware mpeg/mjpeg decoders wiht overlay image support!
VFCAP_SPU:
Similar to VFCAP_OSD, but teh driver expects compessed/coded SPU stream
instead of OSD bitmaps. Useful (only) for hardware mpeg2 decoders.
VFCAP_HWSCALE_UP:
The vo driver can do upscaling with hardware acceleration.
VFCAP_HWSCALE_DOWN:
The vo driver can do downscaling with hardware acceleration.
VFCAP_SWSCALE:
The vo driver (or the underlaying driver layer) can do software scaling.
NOTE: You do NOT need to implement swscaler support and set this flag to
have software scaling working! It's handled by vf_scale in the filter layer.
VFCAP_FLIP:
The driver/hardware can display the buffer upside-down.
Useful for codecs which produce upside-down pictures.
VFCAP_FLIPPED:
Set if the driver/hardware always display the picture upside-down!
VFCAP_TIMER:
Obsolete, see vo->buffer-flags&VO_BUFFER_FLAG_TIMER !
VFCAP_ACCEPT_STRIDE:
Set if your draw_slice() does NOT ignore stride[] values.
NOTE: it should be set for most cases when draw_slice is implemented,
unless yo uhave a very good reason to not support stride (ie. the
underlaying driver layer's draw/blit function doesn't have such parameter)
Note: the rest of vfcap.h belongs to filters only, they are N/A for vo drivers.
control():
~~~~~~~~~~
There is a control() intercace to pass driver-dependent and extra/optional
functions:
VOCTRL_RESIZE_DEST:
Asks the driver to redefine (move/resize) the display area.
The parameters passed in a int[4] array: w,h,x,y. -1 means unchanged.
VOCTRL_RESIZE_SRC:
Asks the driver to redefine (move/resize) the image source area.
The parameters passed in a int[4] array: w,h,x,y.
This is useful to implement zooming or panscan. Requires driver/hardware
support to display (upscale) only a sub-area of teh source buffer.
VOCTRL_SET_WINDOW:
Used by X11/Win32 drivers to receive the window handle. May be called
multiple times, to move the drawable to other window (2-window fullscreen
switching etc)
VOCTRL_PAUSE:
Tell the vo driver tat we paused the playback. Usefull for drivers/hw
with timer.
VOCTRL_RESET:
Tell the vo driver that we did reset/seek, so there is a discontinuity of
the timestamps. Usefull for drivers/hw with timer.
VOCTRL_GET_EQUALIZER & VOCTRL_SET_EQUALIZER:
read/Write the video equalizer (brightness/contrast/saturation/hue)
attributes.
Rendering:
~~~~~~~~~~
There are 4 optional functions to cover the rendering process:
1. frame_start: tells the vo driver that we start rendering to the given buffer.
Also can be used to lock buffer handle (SDL requies it).
2. draw_slice: asks teh driver to copy/blit the given image area.
Note: even if VO_BUFFER_FLAG_INDIRECT is not set, you may implement
draw_slice() to get _notified_ when a area of the image is ready, so you
can do partial blit or whatever you want. Note, that in this case
(VO_BUFFER_FLAG_INDIRECT not set) the image is already copied to the buffer
you exported, you don't need to copy it, and src[] points into your buffer!
3. frame_done: tells the vo driver that we finished rendering to the given buffer.
the driver may do blitting of its backbuffer to video ram, or upload buffer
as texture (opengl) etc. Do NOT SHOW the frame yet!
Also can be used to unlock buffer handle (SDL requies it).
4. show_frame: asks the vo driver to show the given buffer/frame.
NOTE: it may be different to the buffer passed to last frame_done() !!!
(in case of out-of-order decoding, the above functions 1.-3. are called in
decoding order, and 4. is called in display order)
Event handling:
~~~~~~~~~~~~~~~
vo drivers may implement check_events(), it will be called by the (G)UI to
poll input events (mouse/keyboard/etc activity). Events should be passed
via the (optional) event_callback() callback function set by (G)UI or vo2 core.
details: TODO.
A'rpi / Astral & ESP-team
--
Developer of MPlayer, the Movie Player for Linux - http://www.MPlayerHQ.hu
More information about the MPlayer-G2-dev
mailing list