1 /*****************************************************************************
2 * video_decoder.c : video decoder thread
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: decoder.c,v 1.5 2002/11/20 13:37:35 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() */
33 #include <vlc/decoder.h>
36 # include <errno.h> /* errno */
39 # include <unistd.h> /* getpid() */
50 static void RunThread ( vdec_thread_t *p_vdec );
52 /*****************************************************************************
53 * vdec_CreateThread: create a video decoder thread
54 *****************************************************************************
55 * This function creates a new video decoder thread, and returns a pointer
56 * to its description. On error, it returns NULL.
57 *****************************************************************************/
58 vdec_thread_t * vdec_CreateThread( vdec_pool_t * p_pool )
60 vdec_thread_t * p_vdec;
62 /* Allocate the memory needed to store the thread's structure */
63 p_vdec = vlc_object_create( p_pool->p_vpar->p_fifo, sizeof(vdec_thread_t) );
66 msg_Err( p_pool->p_vpar->p_fifo, "out of memory" );
71 * Initialize the parser properties
73 p_vdec->p_pool = p_pool;
75 /* Spawn the video decoder thread */
76 if( vlc_thread_create( p_vdec, "video decoder", RunThread,
77 VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
79 msg_Err( p_vdec, "cannot spawn video decoder thread" );
80 vlc_object_destroy( p_vdec );
87 /*****************************************************************************
88 * vdec_DestroyThread: destroy a video decoder thread
89 *****************************************************************************/
90 void vdec_DestroyThread( vdec_thread_t *p_vdec )
92 /* Ask thread to kill itself */
95 /* Make sure the decoder thread leaves the vpar_GetMacroblock() function */
96 vlc_mutex_lock( &p_vdec->p_pool->lock );
97 vlc_cond_broadcast( &p_vdec->p_pool->wait_undecoded );
98 vlc_mutex_unlock( &p_vdec->p_pool->lock );
100 /* Waiting for the decoder thread to exit */
101 vlc_thread_join( p_vdec );
103 /* Free the object */
104 vlc_object_destroy( p_vdec );
107 /* following functions are local */
109 /*****************************************************************************
110 * vdec_InitThread: initialize video decoder thread
111 *****************************************************************************
112 * This function is called from RunThread and performs the second step of the
114 *****************************************************************************/
115 void vdec_InitThread( vdec_thread_t * p_vdec )
117 /* Re-nice ourself - otherwise we would steal CPU time from the video
118 * output, which would make a poor display. */
119 #if defined( HAVE_NICE )
120 if( nice(VDEC_NICE) == -1 )
121 #elif defined( WIN32 )
122 if( !SetThreadPriority( GetCurrentThread(),
123 THREAD_PRIORITY_BELOW_NORMAL ) )
129 msg_Warn( p_vdec, "couldn't nice() (%s)", strerror(errno) );
131 msg_Warn( p_vdec, "couldn't nice()" );
135 p_vdec->p_idct_data = NULL;
137 p_vdec->p_pool->pf_idct_init( &p_vdec->p_idct_data );
139 /* Mark thread as running and return */
142 /*****************************************************************************
143 * vdec_EndThread: thread destruction
144 *****************************************************************************
145 * This function is called when the thread ends after a sucessful
147 *****************************************************************************/
148 void vdec_EndThread( vdec_thread_t * p_vdec )
150 if( p_vdec->p_idct_data != NULL )
152 free( p_vdec->p_idct_data );
156 /*****************************************************************************
157 * MotionBlock: does one component of the motion compensation
158 *****************************************************************************/
159 static inline void MotionBlock( vdec_pool_t * p_pool, vlc_bool_t b_average,
160 int i_x_pred, int i_y_pred,
161 yuv_data_t * pp_dest[3], int i_dest_offset,
162 yuv_data_t * pp_src[3], int i_src_offset,
163 int i_stride, int i_height,
164 vlc_bool_t b_second_half, int i_chroma_format )
170 i_xy_half = ((i_y_pred & 1) << 1) | (i_x_pred & 1);
172 p_src1 = pp_src[0] + i_src_offset
173 + (i_x_pred >> 1) + (i_y_pred >> 1) * i_stride
174 + b_second_half * (i_stride << 3);
176 p_pool->ppppf_motion[b_average][0][i_xy_half]
177 ( pp_dest[0] + i_dest_offset + b_second_half * (i_stride << 3),
178 p_src1, i_stride, i_height );
180 if( i_chroma_format != CHROMA_NONE )
182 /* Expanded at compile-time. */
183 if( i_chroma_format != CHROMA_444 )
190 if( i_chroma_format == CHROMA_420 )
196 i_xy_half = ((i_y_pred & 1) << 1) | (i_x_pred & 1);
198 i_src_offset += b_second_half * (i_stride << 3);
199 i_dest_offset += b_second_half * (i_stride << 3);
201 p_src1 = pp_src[1] + i_src_offset
202 + (i_x_pred >> 1) + (i_y_pred >> 1) * i_stride;
203 p_src2 = pp_src[2] + i_src_offset
204 + (i_x_pred >> 1) + (i_y_pred >> 1) * i_stride;
206 p_pool->ppppf_motion[b_average][(i_chroma_format != CHROMA_444)]
208 ( pp_dest[1] + i_dest_offset, p_src1, i_stride, i_height );
209 p_pool->ppppf_motion[b_average][(i_chroma_format != CHROMA_444)]
211 ( pp_dest[2] + i_dest_offset, p_src2, i_stride, i_height );
216 /*****************************************************************************
217 * DecodeMacroblock: decode a macroblock
218 *****************************************************************************/
219 #define DECODE_INTRA_BLOCK( i_b, p_dest ) \
220 p_idct = &p_mb->p_idcts[i_b]; \
221 p_idct->pf_idct( p_idct->pi_block, p_dest, \
222 i_b < 4 ? i_lum_dct_stride : i_chrom_dct_stride, \
223 p_vdec->p_idct_data, p_idct->i_sparse_pos );
225 #define DECODE_NONINTRA_BLOCK( i_b, p_dest ) \
226 if( p_mb->i_coded_block_pattern & (1 << (11 - (i_b))) ) \
228 DECODE_INTRA_BLOCK( i_b, p_dest ) \
231 #define DECLARE_DECODEMB( PSZ_NAME, I_CHROMA ) \
232 void PSZ_NAME ( vdec_thread_t *p_vdec, macroblock_t * p_mb ) \
234 int i, i_lum_dct_offset, i_lum_dct_stride; \
235 int i_chrom_dct_offset, i_chrom_dct_stride; \
236 idct_inner_t * p_idct; \
237 vdec_pool_t * p_pool = p_vdec->p_pool; \
238 vpar_thread_t * p_vpar = p_pool->p_vpar; \
240 if( p_mb->i_mb_modes & DCT_TYPE_INTERLACED ) \
242 i_lum_dct_offset = p_vpar->picture.i_lum_stride; \
243 i_lum_dct_stride = p_vpar->picture.i_lum_stride * 2; \
247 i_lum_dct_offset = p_vpar->picture.i_lum_stride * 8; \
248 i_lum_dct_stride = p_vpar->picture.i_lum_stride; \
251 i_chrom_dct_offset = p_vpar->picture.i_chrom_stride * 8; \
252 i_chrom_dct_stride = p_vpar->picture.i_chrom_stride; \
254 if( !(p_mb->i_mb_modes & MB_INTRA) ) \
257 * Motion Compensation (ISO/IEC 13818-2 section 7.6) \
259 for( i = 0; i < p_mb->i_nb_motions; i++ ) \
261 motion_inner_t * p_motion = &p_mb->p_motions[i]; \
262 MotionBlock( p_pool, p_motion->b_average, \
263 p_motion->i_x_pred, p_motion->i_y_pred, \
264 p_mb->pp_dest, p_motion->i_dest_offset, \
265 p_motion->pp_source, p_motion->i_src_offset, \
266 p_motion->i_stride, p_motion->i_height, \
267 p_motion->b_second_half, I_CHROMA ); \
271 * Inverse DCT (ISO/IEC 13818-2 section Annex A) and \
272 * adding prediction and coefficient data (ISO/IEC \
273 * 13818-2 section 7.6.8) \
275 DECODE_NONINTRA_BLOCK( 0, p_mb->p_y_data ) \
276 DECODE_NONINTRA_BLOCK( 1, p_mb->p_y_data + 8 ) \
277 DECODE_NONINTRA_BLOCK( 2, p_mb->p_y_data + i_lum_dct_offset ) \
278 DECODE_NONINTRA_BLOCK( 3, p_mb->p_y_data + i_lum_dct_offset + 8 ) \
279 if( I_CHROMA != CHROMA_NONE ) \
281 DECODE_NONINTRA_BLOCK( 4, p_mb->p_u_data ) \
282 DECODE_NONINTRA_BLOCK( 5, p_mb->p_v_data ) \
283 if( I_CHROMA != CHROMA_420 ) \
285 DECODE_NONINTRA_BLOCK( 6, p_mb->p_u_data \
286 + i_chrom_dct_offset ) \
287 DECODE_NONINTRA_BLOCK( 7, p_mb->p_v_data \
288 + i_chrom_dct_offset ) \
289 if( I_CHROMA == CHROMA_444 ) \
291 DECODE_NONINTRA_BLOCK( 8, p_mb->p_u_data + 8 ) \
292 DECODE_NONINTRA_BLOCK( 9, p_mb->p_v_data + 8 ) \
293 DECODE_NONINTRA_BLOCK( 10, p_mb->p_u_data + 8 \
294 + i_chrom_dct_offset ) \
295 DECODE_NONINTRA_BLOCK( 11, p_mb->p_v_data + 8 \
296 + i_chrom_dct_offset ) \
303 /* Intra macroblock */ \
304 DECODE_INTRA_BLOCK( 0, p_mb->p_y_data ) \
305 DECODE_INTRA_BLOCK( 1, p_mb->p_y_data + 8 ) \
306 DECODE_INTRA_BLOCK( 2, p_mb->p_y_data + i_lum_dct_offset ) \
307 DECODE_INTRA_BLOCK( 3, p_mb->p_y_data + i_lum_dct_offset + 8 ) \
308 if( I_CHROMA != CHROMA_NONE ) \
310 DECODE_INTRA_BLOCK( 4, p_mb->p_u_data ) \
311 DECODE_INTRA_BLOCK( 5, p_mb->p_v_data ) \
312 if( I_CHROMA != CHROMA_420 ) \
314 DECODE_INTRA_BLOCK( 6, p_mb->p_u_data \
315 + i_chrom_dct_offset ) \
316 DECODE_INTRA_BLOCK( 7, p_mb->p_v_data \
317 + i_chrom_dct_offset ) \
318 if( I_CHROMA == CHROMA_444 ) \
320 DECODE_INTRA_BLOCK( 8, p_mb->p_u_data + 8 ) \
321 DECODE_INTRA_BLOCK( 9, p_mb->p_v_data + 8 ) \
322 DECODE_INTRA_BLOCK( 10, p_mb->p_u_data + 8 \
323 + i_chrom_dct_offset ) \
324 DECODE_INTRA_BLOCK( 11, p_mb->p_v_data + 8 \
325 + i_chrom_dct_offset ) \
332 DECLARE_DECODEMB( vdec_DecodeMacroblockBW, CHROMA_NONE )
333 DECLARE_DECODEMB( vdec_DecodeMacroblock420, CHROMA_420 )
334 DECLARE_DECODEMB( vdec_DecodeMacroblock422, CHROMA_422 )
335 DECLARE_DECODEMB( vdec_DecodeMacroblock444, CHROMA_444 )
337 #undef DECLARE_DECODEMB
339 /*****************************************************************************
340 * RunThread: video decoder thread
341 *****************************************************************************
342 * Video decoder thread. This function does only return when the thread is
344 *****************************************************************************/
345 static void RunThread( vdec_thread_t *p_vdec )
347 vdec_InitThread( p_vdec );
352 while( !p_vdec->b_die )
356 if( (p_mb = vpar_GetMacroblock( p_vdec->p_pool, &p_vdec->b_die )) != NULL )
358 p_vdec->p_pool->pf_vdec_decode( p_vdec, p_mb );
360 /* Decoding is finished, release the macroblock and free
361 * unneeded memory. */
362 p_vdec->p_pool->pf_free_mb( p_vdec->p_pool, p_mb );
367 vdec_EndThread( p_vdec );