1
mirror of https://code.videolan.org/videolan/vlc synced 2024-09-28 23:09:59 +02:00

* ./modules/codec/xvid.c: beginning of a video decoder using the Xvid codec

from xvid.org; compile with --enable-xvid --with-xvid-tree=..., run with
    --codec xvid,any (the priority is lower than ffmpeg's for the now).

    todo list: direct rendering, better buffer handling, see why only I frames
               are rendered OK here... probably more.
This commit is contained in:
Sam Hocevar 2002-11-05 22:53:21 +00:00
parent be822ed642
commit 281b9bb481
3 changed files with 342 additions and 1 deletions

View File

@ -1274,6 +1274,61 @@ then
fi
dnl
dnl xvid decoder plugin
dnl
AC_ARG_ENABLE(xvid,
[ --enable-xvid xvid codec (default disabled)])
if test "x${enable_xvid}" = "xyes"
then
AC_ARG_WITH(xvid,
[ --with-xvid=PATH path to xvid installation],[],[])
if test "x${with_xvid}" != "xno" -a "x${with_xvid}" != "x"
then
CPPFLAGS_xvid="${CPPFLAGS_xvid} -I${with_xvid}/include"
LDFLAGS_xvid="${LDFLAGS_xvid} -L${with_xvid}/lib"
fi
LDFLAGS_xvid="${LDFLAGS_xvid}"
AC_ARG_WITH(xvid-tree,
[ --with-xvid-tree=PATH xvid tree for static linking])
if test "x${with_xvid_tree}" != "x"
then
AC_MSG_CHECKING(for libxvidcore.a in ${with_xvid_tree})
real_xvid_tree="`cd ${with_xvid_tree} 2>/dev/null && pwd`"
if test "x${real_xvid_tree}" = x
then
dnl The given directory can't be found
AC_MSG_RESULT(no)
AC_MSG_ERROR([cannot cd to ${with_xvid_tree}])
fi
if test -f "${real_xvid_tree}/build/generic/libxvidcore.a"
then
dnl Use a custom xvid
AC_MSG_RESULT(${real_xvid_tree}/build/generic/libxvidcore.a)
BUILTINS="${BUILTINS} xvid"
LDFLAGS_xvid="${LDFLAGS_xvid} ${real_xvid_tree}/build/generic/libxvidcore.a"
CPPFLAGS_xvid="${CPPFLAGS_xvid} -I${real_xvid_tree}/src"
else
dnl The given libxvidcore wasn't built
AC_MSG_RESULT(no)
AC_MSG_ERROR([cannot find ${real_xvid_tree}/build/generic/libxvidcore.a, make sure you compiled libxvidcore in ${with_xvid_tree}])
fi
else
CPPFLAGS="${CPPFLAGS_save} ${CPPFLAGS_xvid}"
LDFLAGS="${LDFLAGS_save} ${LDFLAGS_xvid}"
AC_CHECK_HEADERS(xvid.h, ,
[ AC_MSG_ERROR([Cannot find development headers for libxvidcore...]) ])
AC_CHECK_LIB(xvid, xvid_init, [
PLUGINS="${PLUGINS} xvid"
LDFLAGS_xvid="${LDFLAGS_xvid} -lxvid" ],
[ AC_MSG_ERROR([Cannot find libxvidcore library...]) ])
LDFLAGS="${LDFLAGS_save}"
CPPFLAGS="${CPPFLAGS_save}"
fi
fi
dnl
dnl MP4 module

View File

@ -3,4 +3,4 @@ SOURCES_lpcm = modules/codec/lpcm.c
SOURCES_araw = modules/codec/araw.c
SOURCES_vorbis = modules/codec/vorbis.c
SOURCES_dv = modules/codec/dv.c
#SOURCES_xvid = modules/codec/xvid.c
SOURCES_xvid = modules/codec/xvid.c

286
modules/codec/xvid.c Normal file
View File

@ -0,0 +1,286 @@
/*****************************************************************************
* xvid.c: a decoder for libxvidcore, the Xvid video codec
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: xvid.c,v 1.1 2002/11/05 22:53:21 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/input.h>
#include <vlc/decoder.h>
#include <stdlib.h>
#include "codecs.h"
#include <xvid.h>
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int RunDecoder ( decoder_fifo_t * );
static int OpenDecoder ( vlc_object_t * );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
set_description( _("Xvid video decoder") );
set_capability( "decoder", 50 );
set_callbacks( OpenDecoder, NULL );
vlc_module_end();
/*****************************************************************************
* OpenDecoder: probe the decoder and return score
*****************************************************************************
* The fourcc format for DV is "dvsd"
*****************************************************************************/
static int OpenDecoder ( vlc_object_t *p_this )
{
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
if( p_fifo->i_fourcc != VLC_FOURCC('x','v','i','d')
&& p_fifo->i_fourcc != VLC_FOURCC('X','V','I','D')
&& p_fifo->i_fourcc != VLC_FOURCC('D','I','V','X') )
{
return VLC_EGENERIC;
}
p_fifo->pf_run = RunDecoder;
return VLC_SUCCESS;
}
/*****************************************************************************
* RunDecoder: this function is called just after the thread is created
*****************************************************************************/
static int RunDecoder ( decoder_fifo_t *p_fifo )
{
XVID_INIT_PARAM xinit;
XVID_DEC_PARAM xparam;
BITMAPINFOHEADER * p_format;
void * p_xvid;
pes_packet_t * p_pes = NULL;
bit_stream_t bit_stream;
vout_thread_t * p_vout;
uint8_t * p_buffer, * p_image;
int i_ret;
int i_width, i_height, i_chroma, i_aspect;
int i_size, i_offset;
if( InitBitstream( &bit_stream, p_fifo, NULL, NULL ) != VLC_SUCCESS )
{
msg_Err( p_fifo, "cannot initialise bitstream" );
p_fifo->b_error = VLC_TRUE;
DecoderError( p_fifo );
return VLC_EGENERIC;
}
p_format = (BITMAPINFOHEADER *)p_fifo->p_demux_data;
/* Guess picture properties from the BIH */
i_width = p_format->biWidth;
i_height = p_format->biHeight;
i_chroma = VLC_FOURCC('Y','V','1','2');
i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
/* XXX: Completely arbitrary buffer size */
i_size = i_width * i_height / 4;
i_offset = 0;
p_buffer = malloc( i_size + 4 * i_width * i_height );
p_image = p_buffer + 4 * i_width * i_height;
if( !p_buffer )
{
msg_Err( p_fifo, "out of memory" );
p_fifo->b_error = VLC_TRUE;
CloseBitstream( &bit_stream );
DecoderError( p_fifo );
return VLC_EGENERIC;
}
xinit.cpu_flags = 0;
xvid_init( NULL, 0, &xinit, NULL );
xparam.width = i_width;
xparam.height = i_height;
i_ret = xvid_decore( NULL, XVID_DEC_CREATE, &xparam, NULL );
if( i_ret )
{
msg_Err( p_fifo, "cannot create xvid decoder" );
p_fifo->b_error = VLC_TRUE;
free( p_buffer );
CloseBitstream( &bit_stream );
DecoderError( p_fifo );
return VLC_EGENERIC;
}
p_xvid = xparam.handle;
/* Spawn a video output if there is none. First we look amongst our
* children, then we look for any other vout that might be available */
p_vout = vlc_object_find( p_fifo, VLC_OBJECT_VOUT, FIND_CHILD );
if( !p_vout )
{
p_vout = vlc_object_find( p_fifo, VLC_OBJECT_VOUT, FIND_ANYWHERE );
}
if( p_vout )
{
if( p_vout->render.i_width != i_width
|| p_vout->render.i_height != i_height
|| p_vout->render.i_chroma != i_chroma
|| p_vout->render.i_aspect != i_aspect )
{
/* We are not interested in this format, close this vout */
vlc_object_detach( p_vout );
vlc_object_release( p_vout );
vout_DestroyThread( p_vout );
p_vout = NULL;
}
else
{
/* This video output is cool! Hijack it. */
vlc_object_detach( p_vout );
vlc_object_attach( p_vout, p_fifo );
vlc_object_release( p_vout );
}
}
if( !p_vout )
{
msg_Dbg( p_fifo, "no vout present, spawning one" );
p_vout = vout_CreateThread( p_fifo,
i_width, i_height,
i_chroma, i_aspect );
if( !p_vout )
{
msg_Err( p_fifo, "could not spawn vout" );
p_fifo->b_error = VLC_TRUE;
xvid_decore( p_xvid, XVID_DEC_DESTROY, NULL, NULL );
free( p_buffer );
CloseBitstream( &bit_stream );
DecoderError( p_fifo );
return VLC_EGENERIC;
}
}
/* Main loop */
while( !p_fifo->b_die && !p_fifo->b_error )
{
XVID_DEC_FRAME xframe;
mtime_t i_pts = 0;
GetChunk( &bit_stream, p_buffer + i_offset, i_size - i_offset );
if( p_pes )
{
input_DeletePES( p_fifo->p_packets_mgt, p_pes );
}
input_ExtractPES( p_fifo, &p_pes );
if( p_pes )
{
/* Don't trust the sucker */
//i_pts = p_pes->i_pts + DEFAULT_PTS_DELAY;
i_pts = mdate() + DEFAULT_PTS_DELAY;
}
if( p_fifo->b_die || p_fifo->b_error )
{
break;
}
/* Decode the stuff */
xframe.bitstream = p_buffer;
xframe.length = i_size;
xframe.image = p_image;
xframe.stride = i_width;
xframe.colorspace = XVID_CSP_YV12;
i_ret = xvid_decore( p_xvid, XVID_DEC_DECODE, &xframe, NULL );
/* FIXME: check i_ret */
if( p_vout )
{
picture_t *p_pic;
while( !(p_pic = vout_CreatePicture( p_vout, 0, 0, 0 ) ) )
{
if( p_fifo->b_die || p_fifo->b_error )
{
break;
}
msleep( VOUT_OUTMEM_SLEEP );
}
if( !p_pic )
{
break;
}
/* TODO: use pf_memcpy when this is stable. */
memcpy( p_pic->p[0].p_pixels,
p_image,
i_width * i_height );
memcpy( p_pic->p[2].p_pixels,
p_image + i_width * i_height,
i_width * i_height / 4 );
memcpy( p_pic->p[1].p_pixels,
p_image + i_width * i_height + i_width * i_height / 4,
i_width * i_height / 4 );
vout_DatePicture( p_vout, p_pic, i_pts );
vout_DisplayPicture( p_vout, p_pic );
}
/* Move the remaining data. TODO: only do this when necessary. */
memmove( p_buffer, p_buffer + xframe.length, i_size - xframe.length );
i_offset = i_size - xframe.length;
}
/* Clean up everything */
vlc_object_detach( p_vout );
vout_DestroyThread( p_vout );
xvid_decore( p_xvid, XVID_DEC_DESTROY, NULL, NULL );
if( p_pes )
{
input_DeletePES( p_fifo->p_packets_mgt, p_pes );
}
free( p_buffer );
CloseBitstream( &bit_stream );
if( p_fifo->b_error )
{
DecoderError( p_fifo );
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}