X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fvideo_decoder%2Fvideo_decoder.c;h=769aaa21169785d60d7b04d63c6e08cad47a4a4f;hb=440f9992ee947ea5fd0debbf35fdd1011c6404b3;hp=b8d4bb4bdd9afffa8e766e27871f6f400cf8b9c6;hpb=b9dc0c52b5a34aff07f588bf89f520cff6713ca7;p=vlc diff --git a/src/video_decoder/video_decoder.c b/src/video_decoder/video_decoder.c index b8d4bb4bdd..769aaa2116 100644 --- a/src/video_decoder/video_decoder.c +++ b/src/video_decoder/video_decoder.c @@ -1,76 +1,88 @@ -/******************************************************************************* +/***************************************************************************** * video_decoder.c : video decoder thread - * (c)1999 VideoLAN - *******************************************************************************/ + ***************************************************************************** + * Copyright (C) 1999, 2000 VideoLAN + * $Id: video_decoder.c,v 1.50 2001/05/30 17:03:12 sam Exp $ + * + * Authors: Christophe Massiot + * Gaël Hendryckx + * + * 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 "defs.h" -/* ?? passer en terminate/destroy avec les signaux supplémentaires */ +#include /* getpid() */ -/******************************************************************************* - * Preamble - *******************************************************************************/ -//#include "vlc.h" - -#include -#include -#include -#include -#include -#include -#include -#include +#include /* free() */ +#include /* memcpy(), memset() */ +#include /* errno */ #include "config.h" #include "common.h" +#include "threads.h" #include "mtime.h" -#include "vlc_thread.h" #include "intf_msg.h" -#include "debug.h" /* ?? temporaire, requis par netlist.h */ -#include "input.h" -#include "input_netlist.h" -#include "decoder_fifo.h" +#include "stream_control.h" +#include "input_ext-dec.h" + #include "video.h" #include "video_output.h" -#include "vdec_idct.h" -#include "video_decoder.h" #include "vdec_motion.h" +#include "video_decoder.h" #include "vpar_blocks.h" #include "vpar_headers.h" -#include "video_fifo.h" #include "vpar_synchro.h" #include "video_parser.h" +#include "video_fifo.h" /* * Local prototypes */ -static int InitThread ( vdec_thread_t *p_vdec ); +#ifdef VDEC_SMP +static int vdec_InitThread ( vdec_thread_t *p_vdec ); +#endif static void RunThread ( vdec_thread_t *p_vdec ); static void ErrorThread ( vdec_thread_t *p_vdec ); static void EndThread ( vdec_thread_t *p_vdec ); -static void DecodeMacroblock ( vdec_thread_t *p_vdec, - macroblock_t * p_mb ); -/******************************************************************************* +/***************************************************************************** * vdec_CreateThread: create a video decoder thread - ******************************************************************************* + ***************************************************************************** * This function creates a new video decoder thread, and returns a pointer * to its description. On error, it returns NULL. * Following configuration properties are used: - * ?? - *******************************************************************************/ + * XXX?? + *****************************************************************************/ vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ ) { 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 ); } @@ -89,33 +101,35 @@ vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ ) 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 ); } -/******************************************************************************* +/***************************************************************************** * vdec_DestroyThread: destroy a video decoder thread - ******************************************************************************* + ***************************************************************************** * Destroy and terminate thread. This function will return 0 if the thread could * be destroyed, and non 0 else. The last case probably means that the thread * was still active, and another try may succeed. - *******************************************************************************/ + *****************************************************************************/ 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; - /* Make sure the parser thread leaves the GetByte() function */ + +#ifdef VDEC_SMP + /* Make sure the decoder thread leaves the vpar_GetMacroblock() function */ vlc_mutex_lock( &(p_vdec->p_vpar->vfifo.lock) ); vlc_cond_signal( &(p_vdec->p_vpar->vfifo.wait) ); vlc_mutex_unlock( &(p_vdec->p_vpar->vfifo.lock) ); - +#endif /* Waiting for the decoder thread to exit */ /* Remove this as soon as the "status" flag is implemented */ @@ -124,104 +138,48 @@ void vdec_DestroyThread( vdec_thread_t *p_vdec /*, int *pi_status */ ) /* following functions are local */ -/******************************************************************************* - * InitThread: initialize video decoder thread - ******************************************************************************* +/***************************************************************************** + * vdec_InitThread: initialize video decoder thread + ***************************************************************************** * This function is called from RunThread and performs the second step of the * initialization. It returns 0 on success. Note that the thread's flag are not * modified inside this function. - *******************************************************************************/ -static int InitThread( vdec_thread_t *p_vdec ) -{ - 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; + *****************************************************************************/ +#ifdef VDEC_SMP +static int vdec_InitThread( vdec_thread_t *p_vdec ) +#else +int vdec_InitThread( vdec_thread_t *p_vdec ) #endif - - /* 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] = 0; - } - for( ; i_dummy < 255; i_dummy ++ ) - { - p_vdec->pi_crop[i_dummy] = i_dummy; - } - for( ; i_dummy < (VDEC_CROPRANGE >> 1) -1; i_dummy++ ) - { - p_vdec->pi_crop[i_dummy] = 255; - } - - /* Mark thread as running and return */ - intf_DbgMsg("vdec debug: InitThread(%p) succeeded\n", p_vdec); - return( 0 ); -} - -/******************************************************************************* - * RunThread: video decoder thread - ******************************************************************************* - * Video decoder thread. This function does only return when the thread is - * terminated. - *******************************************************************************/ -static void RunThread( vdec_thread_t *p_vdec ) { - intf_DbgMsg("vdec debug: running video decoder thread (%p) (pid == %i)\n", - p_vdec, getpid()); + intf_DbgMsg("vdec debug: initializing video decoder thread %p", p_vdec); - /* - * Initialize thread and free configuration - */ - p_vdec->b_error = InitThread( p_vdec ); - if( p_vdec->b_error ) - { - return; - } - p_vdec->b_run = 1; + p_vdec->pf_decode_init = p_vdec->p_vpar->pf_decode_init; + p_vdec->pf_decode_mb_c = p_vdec->p_vpar->pf_decode_mb_c; + p_vdec->pf_decode_mb_bw = p_vdec->p_vpar->pf_decode_mb_bw; - /* - * Main loop - it is not executed if an error occured during - * initialization - */ - while( (!p_vdec->b_die) && (!p_vdec->b_error) ) - { - macroblock_t * p_mb; + p_vdec->pf_decode_init( p_vdec ); - if( (p_mb = vpar_GetMacroblock( &p_vdec->p_vpar->vfifo )) != NULL ) - { - DecodeMacroblock( p_vdec, p_mb ); - } - } - - /* - * Error loop - */ - if( p_vdec->b_error ) +#ifdef VDEC_SMP + /* Re-nice ourself */ + if( nice(VDEC_NICE) == -1 ) { - ErrorThread( p_vdec ); + intf_WarnMsg( 2, "vdec warning : couldn't nice() (%s)", + strerror(errno) ); } +#endif - /* End of thread */ - EndThread( p_vdec ); - p_vdec->b_run = 0; + /* Mark thread as running and return */ + intf_DbgMsg("vdec debug: InitThread(%p) succeeded", p_vdec); + return( 0 ); } -/******************************************************************************* +/***************************************************************************** * ErrorThread: RunThread() error loop - ******************************************************************************* + ***************************************************************************** * This function is called when an error occured during thread main's loop. The * thread can still receive feed, but must be ready to terminate as soon as * possible. - *******************************************************************************/ + *****************************************************************************/ static void ErrorThread( vdec_thread_t *p_vdec ) { macroblock_t * p_mb; @@ -234,118 +192,62 @@ static void ErrorThread( vdec_thread_t *p_vdec ) } } -/******************************************************************************* +/***************************************************************************** * 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); } -/******************************************************************************* - * DecodeMacroblock : decode a macroblock of a picture - *******************************************************************************/ -static void DecodeMacroblock( vdec_thread_t *p_vdec, macroblock_t * p_mb ) +/***************************************************************************** + * RunThread: video decoder thread + ***************************************************************************** + * Video decoder thread. This function does only return when the thread is + * terminated. + *****************************************************************************/ +static void RunThread( vdec_thread_t *p_vdec ) { - int i_b; + intf_DbgMsg("vdec debug: running video decoder thread (%p) (pid == %i)", + p_vdec, getpid()); /* - * Motion Compensation (ISO/IEC 13818-2 section 7.6) + * Initialize thread and free configuration */ - (*p_mb->pf_motion)( p_mb ); - - /* luminance */ - for( i_b = 0; i_b < 4; i_b++ ) - { - /* - * 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) - */ - (p_mb->pf_addb[i_b])( p_vdec, p_mb->ppi_blocks[i_b], - p_mb->p_data[i_b], p_mb->i_addb_l_stride ); - } - - /* chrominance */ - for( i_b = 4; i_b < 4 + p_mb->i_chroma_nb_blocks; i_b++ ) + p_vdec->b_error = vdec_InitThread( p_vdec ); + if( p_vdec->b_error ) { - /* - * 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) - */ - (p_mb->pf_addb[i_b])( p_vdec, p_mb->ppi_blocks[i_b], - p_mb->p_data[i_b], p_mb->i_addb_c_stride ); + return; } + p_vdec->b_run = 1; /* - * Decoding is finished, release the macroblock and free - * unneeded memory. + * Main loop - it is not executed if an error occured during + * initialization */ - vpar_ReleaseMacroblock( &p_vdec->p_vpar->vfifo, p_mb ); -} - -/******************************************************************************* - * vdec_AddBlock : add a block - *******************************************************************************/ -void vdec_AddBlock( vdec_thread_t * p_vdec, dctelem_t * p_block, yuv_data_t * p_data, int i_incr ) -{ - int i_x, i_y; - - for( i_y = 0; i_y < 8; i_y++ ) + while( (!p_vdec->b_die) && (!p_vdec->b_error) ) { - for( i_x = 0; i_x < 8; i_x++ ) + macroblock_t * p_mb; + + if( (p_mb = vpar_GetMacroblock( &p_vdec->p_vpar->vfifo )) != NULL ) { - *p_data = p_vdec->pi_crop[*p_data + *p_block++]; - p_data++; + p_vdec->pf_decode_mb_c( p_vdec, p_mb ); } - p_data += i_incr; } -} -/******************************************************************************* - * vdec_CopyBlock : copy a block - *******************************************************************************/ -void vdec_CopyBlock( vdec_thread_t * p_vdec, dctelem_t * p_block, yuv_data_t * p_data, int i_incr ) -{ - int i_y; -//fprintf(stderr, "%d ", i_incr ); - - for( i_y = 0; i_y < 8; i_y++ ) + /* + * Error loop + */ + if( p_vdec->b_error ) { -#if 0 - /* dctelem_t and yuv_data_t are the same */ - memcpy( p_data, p_block, 8*sizeof(yuv_data_t) ); - p_data += i_incr+8; - p_block += 8; -#else - int i_x; - - for( i_x = 0; i_x < 8; i_x++ ) - { - /* ??? Need clip to be MPEG-2 compliant */ - /* ??? Why does the reference decoder add 128 ??? */ - *p_data++ = p_vdec->pi_crop[*p_block++]; - } - p_data += i_incr; -#endif + ErrorThread( p_vdec ); } -} -/******************************************************************************* - * vdec_DummyBlock : dummy function that does nothing - *******************************************************************************/ -void vdec_DummyBlock( vdec_thread_t * p_vdec, dctelem_t * p_block, yuv_data_t * p_data, int i_incr ) -{ + /* End of thread */ + EndThread( p_vdec ); + p_vdec->b_run = 0; } +