1 /*****************************************************************************
2 * video_decoder.c : video decoder thread
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: video_decoder.c,v 1.10 2002/06/01 12:32:00 sam Exp $
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * Michel Lespinasse <walken@zoy.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
28 #include <stdlib.h> /* free() */
29 #include <string.h> /* memcpy(), memset() */
30 #include <errno.h> /* errno */
34 #include <vlc/decoder.h>
37 # include <unistd.h> /* getpid() */
40 #include "vdec_ext-plugins.h"
41 #include "video_decoder.h"
42 #include "vpar_pool.h"
43 #include "video_parser.h"
48 static void RunThread ( vdec_thread_t *p_vdec );
50 /*****************************************************************************
51 * vdec_CreateThread: create a video decoder thread
52 *****************************************************************************
53 * This function creates a new video decoder thread, and returns a pointer
54 * to its description. On error, it returns NULL.
55 *****************************************************************************/
56 vdec_thread_t * vdec_CreateThread( vdec_pool_t * p_pool )
58 vdec_thread_t * p_vdec;
60 /* Allocate the memory needed to store the thread's structure */
61 p_vdec = vlc_object_create( p_pool->p_vpar->p_fifo, sizeof(vdec_thread_t) );
64 msg_Err( p_pool->p_vpar->p_fifo, "out of memory" );
69 * Initialize the parser properties
71 p_vdec->p_pool = p_pool;
73 /* Spawn the video decoder thread */
74 if( vlc_thread_create( p_vdec, "video decoder", RunThread, 0 ) )
76 msg_Err( p_vdec, "cannot spawn video decoder thread" );
77 vlc_object_destroy( p_vdec );
84 /*****************************************************************************
85 * vdec_DestroyThread: destroy a video decoder thread
86 *****************************************************************************/
87 void vdec_DestroyThread( vdec_thread_t *p_vdec )
89 /* Ask thread to kill itself */
92 /* Make sure the decoder thread leaves the vpar_GetMacroblock() function */
93 vlc_mutex_lock( &p_vdec->p_pool->lock );
94 vlc_cond_broadcast( &p_vdec->p_pool->wait_undecoded );
95 vlc_mutex_unlock( &p_vdec->p_pool->lock );
97 /* Waiting for the decoder thread to exit */
98 vlc_thread_join( p_vdec );
100 /* Free the object */
101 vlc_object_destroy( p_vdec );
104 /* following functions are local */
106 /*****************************************************************************
107 * vdec_InitThread: initialize video decoder thread
108 *****************************************************************************
109 * This function is called from RunThread and performs the second step of the
111 *****************************************************************************/
112 void vdec_InitThread( vdec_thread_t * p_vdec )
114 /* Re-nice ourself - otherwise we would steal CPU time from the video
115 * output, which would make a poor display. */
116 #if defined( HAVE_NICE )
117 if( nice(VDEC_NICE) == -1 )
118 #elif defined( WIN32 )
119 if( !SetThreadPriority( GetCurrentThread(),
120 THREAD_PRIORITY_BELOW_NORMAL ) )
125 msg_Warn( p_vdec, "couldn't nice() (%s)", strerror(errno) );
128 p_vdec->p_idct_data = NULL;
130 p_vdec->p_pool->pf_idct_init( &p_vdec->p_idct_data );
132 /* Mark thread as running and return */
135 /*****************************************************************************
136 * vdec_EndThread: thread destruction
137 *****************************************************************************
138 * This function is called when the thread ends after a sucessful
140 *****************************************************************************/
141 void vdec_EndThread( vdec_thread_t * p_vdec )
143 if( p_vdec->p_idct_data != NULL )
145 free( p_vdec->p_idct_data );
149 /*****************************************************************************
150 * MotionBlock: does one component of the motion compensation
151 *****************************************************************************/
152 static inline void MotionBlock( vdec_pool_t * p_pool, vlc_bool_t b_average,
153 int i_x_pred, int i_y_pred,
154 yuv_data_t * pp_dest[3], int i_dest_offset,
155 yuv_data_t * pp_src[3], int i_src_offset,
156 int i_stride, int i_height,
157 vlc_bool_t b_second_half, int i_chroma_format )
163 i_xy_half = ((i_y_pred & 1) << 1) | (i_x_pred & 1);
165 p_src1 = pp_src[0] + i_src_offset
166 + (i_x_pred >> 1) + (i_y_pred >> 1) * i_stride
167 + b_second_half * (i_stride << 3);
169 p_pool->ppppf_motion[b_average][0][i_xy_half]
170 ( pp_dest[0] + i_dest_offset + b_second_half * (i_stride << 3),
171 p_src1, i_stride, i_height );
173 if( i_chroma_format != CHROMA_NONE )
175 /* Expanded at compile-time. */
176 if( i_chroma_format != CHROMA_444 )
183 if( i_chroma_format == CHROMA_420 )
189 i_xy_half = ((i_y_pred & 1) << 1) | (i_x_pred & 1);
191 i_src_offset += b_second_half * (i_stride << 3);
192 i_dest_offset += b_second_half * (i_stride << 3);
194 p_src1 = pp_src[1] + i_src_offset
195 + (i_x_pred >> 1) + (i_y_pred >> 1) * i_stride;
196 p_src2 = pp_src[2] + i_src_offset
197 + (i_x_pred >> 1) + (i_y_pred >> 1) * i_stride;
199 p_pool->ppppf_motion[b_average][(i_chroma_format != CHROMA_444)]
201 ( pp_dest[1] + i_dest_offset, p_src1, i_stride, i_height );
202 p_pool->ppppf_motion[b_average][(i_chroma_format != CHROMA_444)]
204 ( pp_dest[2] + i_dest_offset, p_src2, i_stride, i_height );
209 /*****************************************************************************
210 * DecodeMacroblock: decode a macroblock
211 *****************************************************************************/
212 #define DECODE_INTRA_BLOCK( i_b, p_dest ) \
213 p_idct = &p_mb->p_idcts[i_b]; \
214 p_idct->pf_idct( p_idct->pi_block, p_dest, \
215 i_b < 4 ? i_lum_dct_stride : i_chrom_dct_stride, \
216 p_vdec->p_idct_data, p_idct->i_sparse_pos );
218 #define DECODE_NONINTRA_BLOCK( i_b, p_dest ) \
219 if( p_mb->i_coded_block_pattern & (1 << (11 - (i_b))) ) \
221 DECODE_INTRA_BLOCK( i_b, p_dest ); \
224 #define DECLARE_DECODEMB( PSZ_NAME, I_CHROMA ) \
225 void PSZ_NAME ( vdec_thread_t *p_vdec, macroblock_t * p_mb ) \
227 int i, i_lum_dct_offset, i_lum_dct_stride; \
228 int i_chrom_dct_offset, i_chrom_dct_stride; \
229 idct_inner_t * p_idct; \
230 vdec_pool_t * p_pool = p_vdec->p_pool; \
231 vpar_thread_t * p_vpar = p_pool->p_vpar; \
233 if( p_mb->i_mb_modes & DCT_TYPE_INTERLACED ) \
235 i_lum_dct_offset = p_vpar->picture.i_lum_stride; \
236 i_lum_dct_stride = p_vpar->picture.i_lum_stride * 2; \
240 i_lum_dct_offset = p_vpar->picture.i_lum_stride * 8; \
241 i_lum_dct_stride = p_vpar->picture.i_lum_stride; \
244 i_chrom_dct_offset = p_vpar->picture.i_chrom_stride * 8; \
245 i_chrom_dct_stride = p_vpar->picture.i_chrom_stride; \
247 if( !(p_mb->i_mb_modes & MB_INTRA) ) \
250 * Motion Compensation (ISO/IEC 13818-2 section 7.6) \
252 for( i = 0; i < p_mb->i_nb_motions; i++ ) \
254 motion_inner_t * p_motion = &p_mb->p_motions[i]; \
255 MotionBlock( p_pool, p_motion->b_average, \
256 p_motion->i_x_pred, p_motion->i_y_pred, \
257 p_mb->pp_dest, p_motion->i_dest_offset, \
258 p_motion->pp_source, p_motion->i_src_offset, \
259 p_motion->i_stride, p_motion->i_height, \
260 p_motion->b_second_half, I_CHROMA ); \
264 * Inverse DCT (ISO/IEC 13818-2 section Annex A) and \
265 * adding prediction and coefficient data (ISO/IEC \
266 * 13818-2 section 7.6.8) \
268 DECODE_NONINTRA_BLOCK( 0, p_mb->p_y_data ); \
269 DECODE_NONINTRA_BLOCK( 1, p_mb->p_y_data + 8 ); \
270 DECODE_NONINTRA_BLOCK( 2, p_mb->p_y_data + i_lum_dct_offset ); \
271 DECODE_NONINTRA_BLOCK( 3, p_mb->p_y_data + i_lum_dct_offset + 8 ); \
272 if( I_CHROMA != CHROMA_NONE ) \
274 DECODE_NONINTRA_BLOCK( 4, p_mb->p_u_data ); \
275 DECODE_NONINTRA_BLOCK( 5, p_mb->p_v_data ); \
276 if( I_CHROMA != CHROMA_420 ) \
278 DECODE_NONINTRA_BLOCK( 6, p_mb->p_u_data \
279 + i_chrom_dct_offset ); \
280 DECODE_NONINTRA_BLOCK( 7, p_mb->p_v_data \
281 + i_chrom_dct_offset ); \
282 if( I_CHROMA == CHROMA_444 ) \
284 DECODE_NONINTRA_BLOCK( 8, p_mb->p_u_data + 8 ); \
285 DECODE_NONINTRA_BLOCK( 9, p_mb->p_v_data + 8 ); \
286 DECODE_NONINTRA_BLOCK( 10, p_mb->p_u_data + 8 \
287 + i_chrom_dct_offset ); \
288 DECODE_NONINTRA_BLOCK( 11, p_mb->p_v_data + 8 \
289 + i_chrom_dct_offset ); \
296 /* Intra macroblock */ \
297 DECODE_INTRA_BLOCK( 0, p_mb->p_y_data ); \
298 DECODE_INTRA_BLOCK( 1, p_mb->p_y_data + 8 ); \
299 DECODE_INTRA_BLOCK( 2, p_mb->p_y_data + i_lum_dct_offset ); \
300 DECODE_INTRA_BLOCK( 3, p_mb->p_y_data + i_lum_dct_offset + 8 ); \
301 if( I_CHROMA != CHROMA_NONE ) \
303 DECODE_INTRA_BLOCK( 4, p_mb->p_u_data ); \
304 DECODE_INTRA_BLOCK( 5, p_mb->p_v_data ); \
305 if( I_CHROMA != CHROMA_420 ) \
307 DECODE_INTRA_BLOCK( 6, p_mb->p_u_data \
308 + i_chrom_dct_offset ); \
309 DECODE_INTRA_BLOCK( 7, p_mb->p_v_data \
310 + i_chrom_dct_offset ); \
311 if( I_CHROMA == CHROMA_444 ) \
313 DECODE_INTRA_BLOCK( 8, p_mb->p_u_data + 8 ); \
314 DECODE_INTRA_BLOCK( 9, p_mb->p_v_data + 8 ); \
315 DECODE_INTRA_BLOCK( 10, p_mb->p_u_data + 8 \
316 + i_chrom_dct_offset ); \
317 DECODE_INTRA_BLOCK( 11, p_mb->p_v_data + 8 \
318 + i_chrom_dct_offset ); \
325 DECLARE_DECODEMB( vdec_DecodeMacroblockBW, CHROMA_NONE );
326 DECLARE_DECODEMB( vdec_DecodeMacroblock420, CHROMA_420 );
327 DECLARE_DECODEMB( vdec_DecodeMacroblock422, CHROMA_422 );
328 DECLARE_DECODEMB( vdec_DecodeMacroblock444, CHROMA_444 );
330 #undef DECLARE_DECODEMB
332 /*****************************************************************************
333 * RunThread: video decoder thread
334 *****************************************************************************
335 * Video decoder thread. This function does only return when the thread is
337 *****************************************************************************/
338 static void RunThread( vdec_thread_t *p_vdec )
340 vdec_InitThread( p_vdec );
345 while( !p_vdec->b_die )
349 if( (p_mb = vpar_GetMacroblock( p_vdec->p_pool, &p_vdec->b_die )) != NULL )
351 p_vdec->p_pool->pf_vdec_decode( p_vdec, p_mb );
353 /* Decoding is finished, release the macroblock and free
354 * unneeded memory. */
355 p_vdec->p_pool->pf_free_mb( p_vdec->p_pool, p_mb );
360 vdec_EndThread( p_vdec );