* video_decoder.c : video decoder thread
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
+ * $Id: video_decoder.c,v 1.45 2001/01/18 05:13:23 sam Exp $
*
- * Authors:
+ * Authors: Christophe Massiot <massiot@via.ecp.fr>
+ * Gaël Hendryckx <jimmy@via.ecp.fr>
*
* 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.
+ * 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-1307, USA.
+ * 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.
*****************************************************************************/
-/* FIXME: passer en terminate/destroy avec les signaux supplémentaires ?? */
-
/*****************************************************************************
* Preamble
*****************************************************************************/
+#include "defs.h"
+
#include <stdlib.h> /* free() */
#include <unistd.h> /* getpid() */
-#include <sys/types.h> /* on BSD, uio.h needs types.h */
-#include <sys/uio.h> /* for input.h */
+#include <errno.h> /* errno */
-#include "threads.h"
#include "config.h"
#include "common.h"
+#include "threads.h"
#include "mtime.h"
#include "plugins.h"
#include "intf_msg.h"
-#include "input.h"
-#include "decoder_fifo.h"
+#include "stream_control.h"
+#include "input_ext-dec.h"
+
#include "video.h"
#include "video_output.h"
+#include "vdec_motion.h"
#include "vdec_idct.h"
#include "video_decoder.h"
-#include "vdec_motion.h"
#include "vpar_blocks.h"
#include "vpar_headers.h"
*/
#ifdef VDEC_SMP
static int vdec_InitThread ( vdec_thread_t *p_vdec );
-static void vdec_DecodeMacroblock( vdec_thread_t *p_vdec,
- macroblock_t * p_mb );
#endif
static void RunThread ( vdec_thread_t *p_vdec );
static void ErrorThread ( vdec_thread_t *p_vdec );
{
vdec_thread_t * p_vdec;
- intf_DbgMsg("vdec debug: creating video decoder thread\n");
+ intf_DbgMsg("vdec debug: creating video decoder thread");
/* Allocate the memory needed to store the thread's structure */
if ( (p_vdec = (vdec_thread_t *)malloc( sizeof(vdec_thread_t) )) == NULL )
{
- intf_ErrMsg("vdec error: not enough memory for vdec_CreateThread() to create the new thread\n");
+ intf_ErrMsg("vdec error: not enough memory for vdec_CreateThread() to create the new thread");
return( NULL );
}
if ( vlc_thread_create(&p_vdec->thread_id, "video decoder",
(vlc_thread_func_t)RunThread, (void *)p_vdec) )
{
- intf_ErrMsg("vdec error: can't spawn video decoder thread\n");
+ intf_ErrMsg("vdec error: can't spawn video decoder thread");
free( p_vdec );
return( NULL );
}
- intf_DbgMsg("vdec debug: video decoder thread (%p) created\n", p_vdec);
+ intf_DbgMsg("vdec debug: video decoder thread (%p) created", p_vdec);
return( p_vdec );
}
*****************************************************************************/
void vdec_DestroyThread( vdec_thread_t *p_vdec /*, int *pi_status */ )
{
- intf_DbgMsg("vdec debug: requesting termination of video decoder thread %p\n", p_vdec);
+ intf_DbgMsg("vdec debug: requesting termination of video decoder thread %p", p_vdec);
/* Ask thread to kill itself */
p_vdec->b_die = 1;
int vdec_InitThread( vdec_thread_t *p_vdec )
#endif
{
+#ifndef HAVE_MMX
int i_dummy;
-
- intf_DbgMsg("vdec debug: initializing video decoder thread %p\n", p_vdec);
-
- /* Initialize other properties */
-#ifdef STATS
- p_vdec->c_loops = 0;
- p_vdec->c_idle_loops = 0;
- p_vdec->c_decoded_pictures = 0;
- p_vdec->c_decoded_i_pictures = 0;
- p_vdec->c_decoded_p_pictures = 0;
- p_vdec->c_decoded_b_pictures = 0;
#endif
+ intf_DbgMsg("vdec debug: initializing video decoder thread %p", p_vdec);
+
+#ifndef HAVE_MMX
/* Init crop table */
p_vdec->pi_crop = p_vdec->pi_crop_buf + (VDEC_CROPRANGE >> 1);
for( i_dummy = -(VDEC_CROPRANGE >> 1); i_dummy < 0; i_dummy++ )
{
p_vdec->pi_crop[i_dummy] = 255;
}
+#endif
+
+#ifdef VDEC_SMP
+ /* Re-nice ourself */
+ if( nice(VDEC_NICE) == -1 )
+ {
+ intf_WarnMsg( 2, "vdec warning : couldn't nice() (%s)",
+ strerror(errno) );
+ }
+#endif
/* Mark thread as running and return */
- intf_DbgMsg("vdec debug: InitThread(%p) succeeded\n", p_vdec);
+ intf_DbgMsg("vdec debug: InitThread(%p) succeeded", p_vdec);
return( 0 );
}
/*****************************************************************************
* EndThread: thread destruction
*****************************************************************************
- * This function is called when the thread ends after a sucessfull
+ * This function is called when the thread ends after a sucessful
* initialization.
*****************************************************************************/
static void EndThread( vdec_thread_t *p_vdec )
{
- intf_DbgMsg("vdec debug: EndThread(%p)\n", p_vdec);
+ intf_DbgMsg("vdec debug: EndThread(%p)", p_vdec);
}
/*****************************************************************************
"packuswb %%mm1,%%mm2\n\t"
"movq %%mm2,(%0)\n\t"
- "emms"
- :"+r" (p_data): "r" (p_block),"r" (i_incr+8));
+ //"emms"
+ :"+r" (p_data): "r" (p_block),"r" (i_incr+8));
}
#endif
"movq 112(%1),%%mm0\n\t"
"packuswb 120(%1),%%mm0\n\t"
"movq %%mm0,(%0)\n\t"
- "emms"
+ //"emms"
:"+r" (p_data): "r" (p_block),"r" (i_incr+8));
}
#endif
/*****************************************************************************
* vdec_DecodeMacroblock : decode a macroblock of a picture
*****************************************************************************/
-#define DECODEBLOCKS( OPBLOCK ) \
+#define DECODEBLOCKSC( OPBLOCK ) \
{ \
int i_b, i_mask; \
\
} \
}
-#ifdef VDEC_SMP
-static __inline__ void vdec_DecodeMacroblock( vdec_thread_t *p_vdec, macroblock_t * p_mb )
-#else
-void vdec_DecodeMacroblock( vdec_thread_t *p_vdec, macroblock_t * p_mb )
-#endif
+#define DECODEBLOCKSBW( OPBLOCK ) \
+{ \
+ int i_b, i_mask; \
+ \
+ i_mask = 1 << (3 + p_mb->i_chroma_nb_blocks); \
+ \
+ /* luminance */ \
+ for( i_b = 0; i_b < 4; i_b++, i_mask >>= 1 ) \
+ { \
+ if( p_mb->i_coded_block_pattern & i_mask ) \
+ { \
+ /* \
+ * Inverse DCT (ISO/IEC 13818-2 section Annex A) \
+ */ \
+ (p_mb->pf_idct[i_b])( p_vdec, p_mb->ppi_blocks[i_b], \
+ p_mb->pi_sparse_pos[i_b] ); \
+ \
+ /* \
+ * Adding prediction and coefficient data (ISO/IEC 13818-2 \
+ * section 7.6.8) \
+ */ \
+ OPBLOCK( p_vdec, p_mb->ppi_blocks[i_b], \
+ p_mb->p_data[i_b], p_mb->i_addb_l_stride ); \
+ } \
+ } \
+}
+
+void vdec_DecodeMacroblockC ( vdec_thread_t *p_vdec, macroblock_t * p_mb )
+{
+ if( !(p_mb->i_mb_type & MB_INTRA) )
+ {
+ /*
+ * Motion Compensation (ISO/IEC 13818-2 section 7.6)
+ */
+ if( p_mb->pf_motion == 0 )
+ {
+ intf_ErrMsg( "vdec error: pf_motion set to NULL" );
+ }
+ else
+ {
+ p_mb->pf_motion( p_mb );
+ }
+
+ DECODEBLOCKSC( AddBlock )
+ }
+ else
+ {
+ DECODEBLOCKSC( CopyBlock )
+ }
+
+ /*
+ * Decoding is finished, release the macroblock and free
+ * unneeded memory.
+ */
+ vpar_ReleaseMacroblock( &p_vdec->p_vpar->vfifo, p_mb );
+}
+
+void vdec_DecodeMacroblockBW ( vdec_thread_t *p_vdec, macroblock_t * p_mb )
{
if( !(p_mb->i_mb_type & MB_INTRA) )
{
*/
if( p_mb->pf_motion == 0 )
{
- intf_ErrMsg( "vdec error: pf_motion set to NULL\n" );
+ intf_ErrMsg( "vdec error: pf_motion set to NULL" );
}
else
{
p_mb->pf_motion( p_mb );
}
- DECODEBLOCKS( AddBlock )
+ DECODEBLOCKSBW( AddBlock )
}
else
{
- DECODEBLOCKS( CopyBlock )
+ DECODEBLOCKSBW( CopyBlock )
}
/*
}
+
/*****************************************************************************
* RunThread: video decoder thread
*****************************************************************************
*****************************************************************************/
static void RunThread( vdec_thread_t *p_vdec )
{
- intf_DbgMsg("vdec debug: running video decoder thread (%p) (pid == %i)\n",
+ intf_DbgMsg("vdec debug: running video decoder thread (%p) (pid == %i)",
p_vdec, getpid());
/*
if( (p_mb = vpar_GetMacroblock( &p_vdec->p_vpar->vfifo )) != NULL )
{
- vdec_DecodeMacroblock( p_vdec, p_mb );
+ vdec_DecodeMacroblockC ( p_vdec, p_mb );
}
}