video_decoder.c 10.8 KB
Newer Older
Michel Kaempf's avatar
Michel Kaempf committed
1
2
3
4
5
6
7
8
9
10
11
12
13
/*******************************************************************************
 * video_decoder.c : video decoder thread
 * (c)1999 VideoLAN
 *******************************************************************************/

/* ?? passer en terminate/destroy avec les signaux supplmentaires */

/*******************************************************************************
 * Preamble
 *******************************************************************************/
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
14
#include <unistd.h>
Michel Kaempf's avatar
Michel Kaempf committed
15
16
17
18
19
20
21
22
#include <string.h>
#include <sys/uio.h>
#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>

#include "config.h"
#include "common.h"
#include "mtime.h"
23
#include "vlc_thread.h"
Michel Kaempf's avatar
Michel Kaempf committed
24
25
26
27
28
29
30
31
32

#include "intf_msg.h"
#include "debug.h"                      /* ?? temporaire, requis par netlist.h */

#include "input.h"
#include "input_netlist.h"
#include "decoder_fifo.h"
#include "video.h"
#include "video_output.h"
33
34
35
36
#include "video_parser.h"

#include "undec_picture.h"
#include "video_fifo.h"
Michel Kaempf's avatar
Michel Kaempf committed
37
38
39
40
41
42
43
44
45
#include "video_decoder.h"

/*
 * Local prototypes
 */
static int      InitThread          ( vdec_thread_t *p_vdec );
static void     RunThread           ( vdec_thread_t *p_vdec );
static void     ErrorThread         ( vdec_thread_t *p_vdec );
static void     EndThread           ( vdec_thread_t *p_vdec );
46
47
static void     DecodePicture       ( vdec_thread_t *p_vdec,
                                      undec_picture_t * p_undec_p );
Michel Kaempf's avatar
Michel Kaempf committed
48
49

/*******************************************************************************
50
 * vdec_CreateThread: create a video decoder thread
Michel Kaempf's avatar
Michel Kaempf committed
51
52
53
54
55
56
 *******************************************************************************
 * 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:
 * ??
 *******************************************************************************/
57
vdec_thread_t * vdec_CreateThread( vpar_thread_t *p_vpar /*, int *pi_status */ )
Michel Kaempf's avatar
Michel Kaempf committed
58
{
59
60
61
62
63
64
65
    vdec_thread_t *     p_vdec;

    intf_DbgMsg("vdec debug: creating video decoder thread\n");

    /* Allocate the memory needed to store the thread's structure */
    if ( (p_vdec = (vdec_thread_t *)malloc( sizeof(vdec_thread_t) )) == NULL )
    {
66
        intf_ErrMsg("vdec error: not enough memory for vdec_CreateThread() to create the new thread\n");
67
68
69
70
71
72
73
74
75
76
        return( NULL );
    }

    /*
     * Initialize the thread properties
     */
    p_vdec->b_die = 0;
    p_vdec->b_error = 0;

    /*
77
     * Initialize the parser properties
78
     */
79
    p_vdec->p_vpar = p_vpar;
80
81

    /* Spawn the video decoder thread */
82
83
    if ( vlc_thread_create(&p_vdec->thread_id, "video decoder",
         (vlc_thread_func)RunThread, (void *)p_vdec) )
84
85
86
87
88
89
90
91
    {
        intf_ErrMsg("vdec error: can't spawn video decoder thread\n");
        free( p_vdec );
        return( NULL );
    }

    intf_DbgMsg("vdec debug: video decoder thread (%p) created\n", p_vdec);
    return( p_vdec );
Michel Kaempf's avatar
Michel Kaempf committed
92
93
94
}

/*******************************************************************************
95
 * vdec_DestroyThread: destroy a video decoder thread
Michel Kaempf's avatar
Michel Kaempf committed
96
 *******************************************************************************
97
 * Destroy and terminate thread. This function will return 0 if the thread could
Michel Kaempf's avatar
Michel Kaempf committed
98
99
100
 * be destroyed, and non 0 else. The last case probably means that the thread
 * was still active, and another try may succeed.
 *******************************************************************************/
101
void vdec_DestroyThread( vdec_thread_t *p_vdec /*, int *pi_status */ )
Michel Kaempf's avatar
Michel Kaempf committed
102
{
103
104
105
106
107
    intf_DbgMsg("vdec debug: requesting termination of video decoder thread %p\n", p_vdec);

    /* Ask thread to kill itself */
    p_vdec->b_die = 1;

Michel Kaempf's avatar
Michel Kaempf committed
108
    /* Waiting for the decoder thread to exit */
109
    /* Remove this as soon as the "status" flag is implemented */
110
    vlc_thread_join( p_vdec->thread_id );
Michel Kaempf's avatar
Michel Kaempf committed
111
112
113
114
115
}

/* following functions are local */

/*******************************************************************************
116
 * InitThread: initialize video decoder thread
Michel Kaempf's avatar
Michel Kaempf committed
117
118
119
120
121
122
123
 *******************************************************************************
 * 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 )
{
124
125
    intf_DbgMsg("vdec debug: initializing video decoder thread %p\n", p_vdec);

Michel Kaempf's avatar
Michel Kaempf committed
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
    /* 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

    /* Mark thread as running and return */
    intf_DbgMsg("vdec debug: InitThread(%p) succeeded\n", p_vdec);    
    return( 0 );    
}

/*******************************************************************************
142
 * RunThread: video decoder thread
Michel Kaempf's avatar
Michel Kaempf committed
143
 *******************************************************************************
144
 * Video decoder thread. This function does only return when the thread is
Michel Kaempf's avatar
Michel Kaempf committed
145
146
147
148
 * terminated. 
 *******************************************************************************/
static void RunThread( vdec_thread_t *p_vdec )
{
149
150
    intf_DbgMsg("vdec debug: running video decoder thread (%p) (pid == %i)\n",
                p_vdec, getpid());
151

Michel Kaempf's avatar
Michel Kaempf committed
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
    /* 
     * Initialize thread and free configuration 
     */
    p_vdec->b_error = InitThread( p_vdec );
    if( p_vdec->b_error )
    {
        return;
    }
    p_vdec->b_run = 1;

    /*
     * Main loop - it is not executed if an error occured during
     * initialization
     */
    while( (!p_vdec->b_die) && (!p_vdec->b_error) )
    {
168
169
170
171
172
173
        undec_picture_t *       p_undec_p;
        
        if( (p_undec_p = GetPicture( p_vdec->p_vpar->p_fifo )) != NULL )
        {
            DecodePicture( p_vdec, p_undec_p );
        }
Michel Kaempf's avatar
Michel Kaempf committed
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
    } 

    /*
     * Error loop
     */
    if( p_vdec->b_error )
    {
        ErrorThread( p_vdec );        
    }

    /* End of thread */
    EndThread( p_vdec );
    p_vdec->b_run = 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 )
{
198
199
    undec_picture_t *       p_undec_p;

Michel Kaempf's avatar
Michel Kaempf committed
200
201
202
    /* Wait until a `die' order */
    while( !p_vdec->b_die )
    {
203
204
        p_undec_p = GetPicture( p_vdec->p_vpar.vfifo );
        DestroyPicture( p_vdec->p_vpar.vfifo, p_undec_p );
205

Michel Kaempf's avatar
Michel Kaempf committed
206
207
208
209
210
211
212
213
214
215
216
217
218
        /* Sleep a while */
        msleep( VDEC_IDLE_SLEEP );                
    }
}

/*******************************************************************************
 * EndThread: thread destruction
 *******************************************************************************
 * This function is called when the thread ends after a sucessfull 
 * initialization.
 *******************************************************************************/
static void EndThread( vdec_thread_t *p_vdec )
{
219
220
    intf_DbgMsg("vdec debug: EndThread(%p)\n", p_vdec);
}
221

222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/*******************************************************************************
 * DecodePicture : decode a picture
 *******************************************************************************/
static void DecodePicture( vdec_thread_t *p_vdec, undec_picture_t * p_undec_p )
{
    static int              pi_chroma_nb_blocks[4] = {0, 1, 2, 4};
    static int              pi_chroma_nb_coeffs[4] = {0, 64, 128, 256};
    static f_motion_mb_t    ppf_chroma_motion[4] = { NULL,
                                                     &vdec_MotionMacroBlock420,
                                                     &vdec_MotionMacroBlock422,
                                                     &vdec_MotionMacroBlock444 };
    static f_motion_t       pppf_motion_forward[4][2] = {
                                {NULL, NULL} /* I picture */
                                {&vdec_MotionForward, &vdec_MotionForward} /* P */
                                {NULL, &vdec_MotionForward} /* B */
                                {NULL, NULL} /* D */ };
    static f_motion_t       pppf_motion_backward[4][2] = {
                                {NULL, NULL} /* I picture */
                                {NULL, NULL} /* P */
                                {NULL, &vdec_MotionBackward} /* B */
                                {NULL, NULL} /* D */ };
    static f_motion_t       ppf_motion[4] = { NULL,
                                              &vdec_MotionTopFirst,
                                              &vdec_MotionBottomFirst,
                                              &vdec_MotionFrame };

    int             i_mb, i_b, i_totb;
    coeff_t *       p_y, p_u, p_v;
    f_motion_mb_t   pf_chroma_motion;
    f_motion_t      pf_motion_forward, pf_motion_backward;
    int             i_chroma_nb_blocks, i_chroma_nb_coeffs;
    
    p_y = (coeff_t *)p_undec_p->p_picture->p_y;
    p_u = (coeff_t *)p_undec_p->p_picture->p_u;
    p_v = (coeff_t *)p_undec_p->p_picture->p_v;
Michel Kaempf's avatar
Michel Kaempf committed
257

258
259
260
261
#define I_chroma_format     p_undec_p->p_picture->i_chroma_format
    pf_chroma_motion = ppf_chroma_motion[I_chroma_format];
    pf_motion_forward
    pf_motion = ppf_motion[p_undec_p->i_structure];
Michel Kaempf's avatar
Michel Kaempf committed
262

263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
    i_chroma_nb_blocks = pi_chroma_nb_blocks[I_chroma_format];
    i_chroma_nb_coeffs = pi_chroma_nb_coeffs[I_chroma_format];
#undef I_chroma_format

    for( i_mb = 0; i_mb < p_undec_p->i_mb_height*p_undec_p->i_mb_width; i_mb++ )
    {
#define P_mb_info           p_undec_p->p_mb_info[i_ref]

        /*
         * Inverse DCT (ISO/IEC 13818-2 section Annex A)
         */
        
        /* Luminance : always 4 blocks */
        for( i_b = 0; i_b < 4; i_b++ )
        {
            (*P_mb_info.p_idct_function[i_b])( p_y + i_b*64 );
        }
        i_totb = 4;
        
        /* Chrominance Cr */
        for( i_b = 0; i_b < i_chroma_nb_blocks; i_b++ )
        {
            (*P_mb_info.p_idct_function[i_totb + i_b])( p_u + i_b*64 );
        }
        i_totb += i_chroma_nb_blocks;
        
        /* Chrominance Cb */
        for( i_b = 0; i_b < i_chroma_nb_blocks; i_b++ )
        {
            (*P_mb_info.p_idct_function[i_totb + i_b])( p_v + i_b*64 );
        }

        /*
         * Motion Compensation (ISO/IEC 13818-2 section 7.6)
         */
        (*pf_motion)( p_vdec, p_undec_p, i_mb, pf_chroma_motion );

        p_y += 256;
        p_u += i_chroma_nb_coeffs;
        p_v += i_chroma_nb_coeffs;
#undef P_mb_info
    }

    /*
     * Decoding is finished, mark the picture ready for displaying and free
     * unneeded memory
     */
    vpar_ReleasePicture( p_vdec->p_vpar->p_fifo, p_undec_p );
Michel Kaempf's avatar
Michel Kaempf committed
311
}