libcle266mpegdec libcle266mpegdec
Status: Beta
Brought to you by:
rofafor
libcle266mpegdec
================
This is a library which performs decoding of an MPEG-2 video elementary
stream using the hardware MPEG-2 decoder found in the VIA CLE266 chipset
on various motherboards including some of the VIA Epia series.
The library is based on the Andreas Robinson's mtest-0.1.1, that's propably
based on the work of Ivor Hewitt who reverse-engineered libddmpeg released
by VIA. The code looks quite similar to the XVMC portion of the Openchrome
driver for Xorg.
Prerequisites
-------------
This library accesses the CLE266 video hardware by memory maping the framebuffer
device. Only the linux-viafb driver from DirectFB CVS has been tested.
The DirectFB and DFB++ libraries should be patched with GetFBOffset and
GetFBOffsetDFB++ patches to enable the framebuffer offsets to be retrieved
for the surfaces used as buffers, recompiled and installed.
NOTE: The both patches have been merged into DirectFB CVS since 2006-10-08!
Installation
------------
Building and installing is straightforward. Simply run:
./configure
make
make install
License
-------
The license in source code headers has been changed from MIT to LGPL as Andreas
Robinson states in his email on DirectFB-dev mailing list:
"Hi, I just realized I have completely forgotten to mention the hardware decoder
test program on this mailinglist. Doh!
So, look here: http://cle266dfb.sourceforge.net/mtest-0.1.1.tar.gz
It is not really finished yet, and the license headers are wrong (should be
LGPL, but are not.) but it works.
Regards, Andreas"
Internals
---------
The structure of library is fairly simple. The API calls decoder.c which
in turn calls parser.c which calls scanner.c.
Scanner.c reads the mpeg file, locates block start codes and unpacks header
blocks into C structures.
Parser.c implements the mpeg2 state machine described in the standard.
Decoder.c takes data from the scanner and parser and gives it to the hardware
interface in hwdec.c.
The application code must set up 4 buffers for the decoder to work with and
tell to the library where these buffers are. After that the MPEG-2 data can
be send to the library. When a frame has been decoded, it will be in one of
the four buffers, and it can then be copied back from there for display.
There is no A-V synchronization or display capability in this library, so
feed it a video elementary stream and get back frames!
Library HOWTO
-------------
Here's an example code to show howto interface the library. See cle266mpegdec.h
for function prototypes. This example uses DirectFB for creating the buffers
as DirectFB surfaces with a YV12 pixel format. No DirectFB initialisation code
or error checking is included:
*** Setting up buffers ***
#include <directfb.h>
IDirectFB *dfb;
IDirectFBSurface *mpegfb[4];
DFBSurfaceDescription dsc;
int *mpegfb_ptr[4];
int mpegfb_ofs[4];
int mpegfb_stride;
uint8_t *buf;
int i;
/* The first step is to call CLE266MPEGInitialise()
* which mmaps /dev/fb0 and initialises the decoder
*/
fprintf(stderr, "Initialising CLE266 decoder:");
if (!CLE266MPEGInitialise("/dev/fb0")) {
fprintf(stderr, "failed!\n");
return false;
} else {
fprintf(stderr, "success!\n");
}
dsc.flags = (DFBSurfaceDescriptionFlags)(DSDESC_WIDTH |
DSDESC_HEIGHT |
DSDESC_PIXELFORMAT |
DSDESC_CAPS);
dsc.caps = DSCAPS_VIDEOONLY;
dsc.pixelformat = DSPF_YV12;
/* Set width and height as appropriate! e.g. 720 x 576 */
dsc.width = width;
dsc.height = height;
/* Create the MPEG buffers */
for ( i = 0; i < 4; i++) {
dfb->CreateSurface(dfb, &dsc, &mpegfb[i]);
mpegfb[i]->Clear(mpegfb[i], 0, 0, 0, 0);
mpegfb[i]->Lock(mpegfb[i], DSLF_WRITE,
(void**) &buf, &mpegfb_stride);
/* This is the step which requires the DirectFB / DFB++ patches */
mpegfb[i]->GetFramebufferOffset(mpegfb[i], &mpegfb_ofs[i]);
mpegfb_ptr[i] = buf;
}
/* Inform the decoder of the line length and locations of the buffers: */
CLE266MPEGSetStride(mpegfb_stride, mpegfb_stride >> 1);
for (i = 0; i < 4; i++) {
int y_offset = mpegfb_ofs[i];
int u_offset = y_offset + (mpegfb_stride * height);
int v_offset = u_offset + (mpegfb_stride >> 1) * (height >> 1);
CLE266MPEGSetFrameBuffer(i, y_offset, u_offset, v_offset);
}
*** Sending data to the decoder ***
Now that the decoder is initialised, we can start sending data to it,
that should be an MPEG-2 video elementary stream. The MPEG-2 data is
in the buffer 'data' and has length 'len'. The function returns the
number of bytes decoded in 'len' and the index of the framebuffer
containing any decoded frame or -1 if no frame has yet been decoded.
This will need to be in a loop with the buffer being incremented
for each call.
/* repeat while cle266FB is -1 */
cle266FB = CLE266MPEGDecodeData(data, &len, &pts);
On successful decoding, the decoded frame will be in the buffer
"mpegfb[i]" from where it can be blitted to another surface for
display or copied elsewhere as needed.
*** Clearing up ***
The application code should call CLE266MPEGClose() on exit.
References
----------
This library is based on the Andreas Robinson's mtest-0.1.1:
http://www.directfb.org/mailinglists/directfb-dev/2004/01-2004/msg00131.html
http://cle266dfb.sourceforge.net/mtest-0.1.1.tar.gz
Colin Paton's libsoftmpeg-cle266 that's based on mentioned mtest:
http://www.linuxtv.org/mailinglists/linuxtv-softmpeg/2004/03-2004/msg00031.html
http://crp.pwp.blueyonder.co.uk/MPEG/libsoftmpeg-cle266-0.01.tgz
Laurence Abbott's libcle266decode-0.1 that's based on mentioned libsoftmpeg-cle266:
http://lists.berlios.de/pipermail/softdevice-devel/2006q2/001943.html
http://vdr.club-burniston.co.uk/softdevice_cle266.diff
http://vdr.club-burniston.co.uk/libcle266decode-0.1.tar.gz