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:
parent
be822ed642
commit
281b9bb481
@ -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
|
||||
|
@ -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
286
modules/codec/xvid.c
Normal 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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user