1 /*****************************************************************************
2 * video_decoder.c : video decoder thread
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: decoder.c,v 1.4 2002/08/29 23:53:22 massiot 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() */
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,
75 VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
77 msg_Err( p_vdec, "cannot spawn video decoder thread" );
78 vlc_object_destroy( p_vdec );
85 /*****************************************************************************
86 * vdec_DestroyThread: destroy a video decoder thread
87 *****************************************************************************/
88 void vdec_DestroyThread( vdec_thread_t *p_vdec )
90 /* Ask thread to kill itself */
93 /* Make sure the decoder thread leaves the vpar_GetMacroblock() function */
94 vlc_mutex_lock( &p_vdec->p_pool->lock );
95 vlc_cond_broadcast( &p_vdec->p_pool->wait_undecoded );
96 vlc_mutex_unlock( &p_vdec->p_pool->lock );
98 /* Waiting for the decoder thread to exit */
99 vlc_thread_join( p_vdec );
101 /* Free the object */
102 vlc_object_destroy( p_vdec );
105 /* following functions are local */
107 /*****************************************************************************
108 * vdec_InitThread: initialize video decoder thread
109 *****************************************************************************
110 * This function is called from RunThread and performs the second step of the
112 *****************************************************************************/
113 void vdec_InitThread( vdec_thread_t * p_vdec )
115 /* Re-nice ourself - otherwise we would steal CPU time from the video
116 * output, which would make a poor display. */
117 #if defined( HAVE_NICE )
118 if( nice(VDEC_NICE) == -1 )
119 #elif defined( WIN32 )
120 if( !SetThreadPriority( GetCurrentThread(),
121 THREAD_PRIORITY_BELOW_NORMAL ) )
126 msg_Warn( p_vdec, "couldn't nice() (%s)", strerror(errno) );
129 p_vdec->p_idct_data = NULL;
131 p_vdec->p_pool->pf_idct_init( &p_vdec->p_idct_data );
133 /* Mark thread as running and return */
136 /*****************************************************************************
137 * vdec_EndThread: thread destruction
138 *****************************************************************************
139 * This function is called when the thread ends after a sucessful
141 *****************************************************************************/
142 void vdec_EndThread( vdec_thread_t * p_vdec )
144 if( p_vdec->p_idct_data != NULL )
146 free( p_vdec->p_idct_data );
150 /*****************************************************************************
151 * MotionBlock: does one component of the motion compensation
152 *****************************************************************************/
153 static inline void MotionBlock( vdec_pool_t * p_pool, vlc_bool_t b_average,
154 int i_x_pred, int i_y_pred,
155 yuv_data_t * pp_dest[3], int i_dest_offset,
156 yuv_data_t * pp_src[3], int i_src_offset,
157 int i_stride, int i_height,
158 vlc_bool_t b_second_half, int i_chroma_format )
164 i_xy_half = ((i_y_pred & 1) << 1) | (i_x_pred & 1);
166 p_src1 = pp_src[0] + i_src_offset
167 + (i_x_pred >> 1) + (i_y_pred >> 1) * i_stride
168 + b_second_half * (i_stride << 3);
170 p_pool->ppppf_motion[b_average][0][i_xy_half]
171 ( pp_dest[0] + i_dest_offset + b_second_half * (i_stride << 3),
172 p_src1, i_stride, i_height );
174 if( i_chroma_format != CHROMA_NONE )
176 /* Expanded at compile-time. */
177 if( i_chroma_format != CHROMA_444 )
184 if( i_chroma_format == CHROMA_420 )
190 i_xy_half = ((i_y_pred & 1) << 1) | (i_x_pred & 1);
192 i_src_offset += b_second_half * (i_stride << 3);
193 i_dest_offset += b_second_half * (i_stride << 3);
195 p_src1 = pp_src[1] + i_src_offset
196 + (i_x_pred >> 1) + (i_y_pred >> 1) * i_stride;
197 p_src2 = pp_src[2] + i_src_offset
198 + (i_x_pred >> 1) + (i_y_pred >> 1) * i_stride;
200 p_pool->ppppf_motion[b_average][(i_chroma_format != CHROMA_444)]
202 ( pp_dest[1] + i_dest_offset, p_src1, i_stride, i_height );
203 p_pool->ppppf_motion[b_average][(i_chroma_format != CHROMA_444)]
205 ( pp_dest[2] + i_dest_offset, p_src2, i_stride, i_height );
210 /*****************************************************************************
211 * DecodeMacroblock: decode a macroblock
212 *****************************************************************************/
213 #define DECODE_INTRA_BLOCK( i_b, p_dest ) \
214 p_idct = &p_mb->p_idcts[i_b]; \
215 p_idct->pf_idct( p_idct->pi_block, p_dest, \
216 i_b < 4 ? i_lum_dct_stride : i_chrom_dct_stride, \
217 p_vdec->p_idct_data, p_idct->i_sparse_pos );
219 #define DECODE_NONINTRA_BLOCK( i_b, p_dest ) \
220 if( p_mb->i_coded_block_pattern & (1 << (11 - (i_b))) ) \
222 DECODE_INTRA_BLOCK( i_b, p_dest ) \
225 #define DECLARE_DECODEMB( PSZ_NAME, I_CHROMA ) \
226 void PSZ_NAME ( vdec_thread_t *p_vdec, macroblock_t * p_mb ) \
228 int i, i_lum_dct_offset, i_lum_dct_stride; \
229 int i_chrom_dct_offset, i_chrom_dct_stride; \
230 idct_inner_t * p_idct; \
231 vdec_pool_t * p_pool = p_vdec->p_pool; \
232 vpar_thread_t * p_vpar = p_pool->p_vpar; \
234 if( p_mb->i_mb_modes & DCT_TYPE_INTERLACED ) \
236 i_lum_dct_offset = p_vpar->picture.i_lum_stride; \
237 i_lum_dct_stride = p_vpar->picture.i_lum_stride * 2; \
241 i_lum_dct_offset = p_vpar->picture.i_lum_stride * 8; \
242 i_lum_dct_stride = p_vpar->picture.i_lum_stride; \
245 i_chrom_dct_offset = p_vpar->picture.i_chrom_stride * 8; \
246 i_chrom_dct_stride = p_vpar->picture.i_chrom_stride; \
248 if( !(p_mb->i_mb_modes & MB_INTRA) ) \
251 * Motion Compensation (ISO/IEC 13818-2 section 7.6) \
253 for( i = 0; i < p_mb->i_nb_motions; i++ ) \
255 motion_inner_t * p_motion = &p_mb->p_motions[i]; \
256 MotionBlock( p_pool, p_motion->b_average, \
257 p_motion->i_x_pred, p_motion->i_y_pred, \
258 p_mb->pp_dest, p_motion->i_dest_offset, \
259 p_motion->pp_source, p_motion->i_src_offset, \
260 p_motion->i_stride, p_motion->i_height, \
261 p_motion->b_second_half, I_CHROMA ); \
265 * Inverse DCT (ISO/IEC 13818-2 section Annex A) and \
266 * adding prediction and coefficient data (ISO/IEC \
267 * 13818-2 section 7.6.8) \
269 DECODE_NONINTRA_BLOCK( 0, p_mb->p_y_data ) \
270 DECODE_NONINTRA_BLOCK( 1, p_mb->p_y_data + 8 ) \
271 DECODE_NONINTRA_BLOCK( 2, p_mb->p_y_data + i_lum_dct_offset ) \
272 DECODE_NONINTRA_BLOCK( 3, p_mb->p_y_data + i_lum_dct_offset + 8 ) \
273 if( I_CHROMA != CHROMA_NONE ) \
275 DECODE_NONINTRA_BLOCK( 4, p_mb->p_u_data ) \
276 DECODE_NONINTRA_BLOCK( 5, p_mb->p_v_data ) \
277 if( I_CHROMA != CHROMA_420 ) \
279 DECODE_NONINTRA_BLOCK( 6, p_mb->p_u_data \
280 + i_chrom_dct_offset ) \
281 DECODE_NONINTRA_BLOCK( 7, p_mb->p_v_data \
282 + i_chrom_dct_offset ) \
283 if( I_CHROMA == CHROMA_444 ) \
285 DECODE_NONINTRA_BLOCK( 8, p_mb->p_u_data + 8 ) \
286 DECODE_NONINTRA_BLOCK( 9, p_mb->p_v_data + 8 ) \
287 DECODE_NONINTRA_BLOCK( 10, p_mb->p_u_data + 8 \
288 + i_chrom_dct_offset ) \
289 DECODE_NONINTRA_BLOCK( 11, p_mb->p_v_data + 8 \
290 + i_chrom_dct_offset ) \
297 /* Intra macroblock */ \
298 DECODE_INTRA_BLOCK( 0, p_mb->p_y_data ) \
299 DECODE_INTRA_BLOCK( 1, p_mb->p_y_data + 8 ) \
300 DECODE_INTRA_BLOCK( 2, p_mb->p_y_data + i_lum_dct_offset ) \
301 DECODE_INTRA_BLOCK( 3, p_mb->p_y_data + i_lum_dct_offset + 8 ) \
302 if( I_CHROMA != CHROMA_NONE ) \
304 DECODE_INTRA_BLOCK( 4, p_mb->p_u_data ) \
305 DECODE_INTRA_BLOCK( 5, p_mb->p_v_data ) \
306 if( I_CHROMA != CHROMA_420 ) \
308 DECODE_INTRA_BLOCK( 6, p_mb->p_u_data \
309 + i_chrom_dct_offset ) \
310 DECODE_INTRA_BLOCK( 7, p_mb->p_v_data \
311 + i_chrom_dct_offset ) \
312 if( I_CHROMA == CHROMA_444 ) \
314 DECODE_INTRA_BLOCK( 8, p_mb->p_u_data + 8 ) \
315 DECODE_INTRA_BLOCK( 9, p_mb->p_v_data + 8 ) \
316 DECODE_INTRA_BLOCK( 10, p_mb->p_u_data + 8 \
317 + i_chrom_dct_offset ) \
318 DECODE_INTRA_BLOCK( 11, p_mb->p_v_data + 8 \
319 + i_chrom_dct_offset ) \
326 DECLARE_DECODEMB( vdec_DecodeMacroblockBW, CHROMA_NONE )
327 DECLARE_DECODEMB( vdec_DecodeMacroblock420, CHROMA_420 )
328 DECLARE_DECODEMB( vdec_DecodeMacroblock422, CHROMA_422 )
329 DECLARE_DECODEMB( vdec_DecodeMacroblock444, CHROMA_444 )
331 #undef DECLARE_DECODEMB
333 /*****************************************************************************
334 * RunThread: video decoder thread
335 *****************************************************************************
336 * Video decoder thread. This function does only return when the thread is
338 *****************************************************************************/
339 static void RunThread( vdec_thread_t *p_vdec )
341 vdec_InitThread( p_vdec );
346 while( !p_vdec->b_die )
350 if( (p_mb = vpar_GetMacroblock( p_vdec->p_pool, &p_vdec->b_die )) != NULL )
352 p_vdec->p_pool->pf_vdec_decode( p_vdec, p_mb );
354 /* Decoding is finished, release the macroblock and free
355 * unneeded memory. */
356 p_vdec->p_pool->pf_free_mb( p_vdec->p_pool, p_mb );
361 vdec_EndThread( p_vdec );