* 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 $
+ * $Id: xvid.c,v 1.5 2003/02/20 01:52:45 sigmunau 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
set_description( _("Xvid video decoder") );
set_capability( "decoder", 50 );
set_callbacks( OpenDecoder, NULL );
+ add_bool( "xvid-direct-render", 0, NULL, "direct rendering",
+ "Use libxvidcore's direct rendering feature.", VLC_TRUE );
vlc_module_end();
/*****************************************************************************
* OpenDecoder: probe the decoder and return score
*****************************************************************************
- * The fourcc format for DV is "dvsd"
+ * FIXME: find fourcc formats supported by xvid
*****************************************************************************/
static int OpenDecoder ( vlc_object_t *p_this )
{
uint8_t * p_buffer, * p_image;
int i_ret;
int i_width, i_height, i_chroma, i_aspect;
- int i_size, i_offset;
+ int i_size, i_offset, i_image_size;
+
+ vlc_bool_t b_direct = config_GetInt( p_fifo, "xvid-direct-render" );
if( InitBitstream( &bit_stream, p_fifo, NULL, NULL ) != VLC_SUCCESS )
{
DecoderError( p_fifo );
return VLC_EGENERIC;
}
+ if( ( p_format = (BITMAPINFOHEADER *)p_fifo->p_bitmapinfoheader ) == NULL )
+ {
+ i_width = 1;
+ i_height = 1; // avoid segfault anyway it's wrong
+ }
+ else
+ {
+ /* Guess picture properties from the BIH */
+ i_width = p_format->biWidth;
+ i_height = p_format->biHeight;
+ }
- 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_image_size = b_direct ? 0 : 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;
+
+ p_buffer = malloc( i_size + i_image_size );
+ p_image = p_buffer + i_size;
if( !p_buffer )
{
/* 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 );
- }
- }
+ p_vout = vout_Request( p_fifo, NULL,
+ i_width, i_height, i_chroma, i_aspect );
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;
- }
+ 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;
+ XVID_DEC_PICTURE xpic;
mtime_t i_pts = 0;
+ picture_t *p_pic;
GetChunk( &bit_stream, p_buffer + i_offset, i_size - i_offset );
break;
}
+ 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;
+ }
+
+ if( b_direct )
+ {
+ xpic.y = p_pic->p[0].p_pixels;
+ xpic.u = p_pic->p[1].p_pixels;
+ xpic.v = p_pic->p[2].p_pixels;
+ xpic.stride_y = p_pic->p[0].i_pitch;
+ xpic.stride_u = p_pic->p[1].i_pitch;
+ xpic.stride_v = p_pic->p[2].i_pitch;
+ }
+
/* Decode the stuff */
xframe.bitstream = p_buffer;
xframe.length = i_size;
- xframe.image = p_image;
+ xframe.image = b_direct ? (void*)&xpic : p_image;
xframe.stride = i_width;
- xframe.colorspace = XVID_CSP_YV12;
+ xframe.colorspace = b_direct ? XVID_CSP_EXTERN : XVID_CSP_YV12;
i_ret = xvid_decore( p_xvid, XVID_DEC_DECODE, &xframe, NULL );
/* FIXME: check i_ret */
- if( p_vout )
+ if( !b_direct )
{
- 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,
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 );
}
+ 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 );
+ vout_Request( p_fifo, p_vout, 0, 0, 0, 0 );
xvid_decore( p_xvid, XVID_DEC_DESTROY, NULL, NULL );