]> git.sesse.net Git - vlc/blob - plugins/cinepak/cinepak.c
d15fc3aff5aadb48aa58747cf0c735a71c90ae97
[vlc] / plugins / cinepak / cinepak.c
1 /*****************************************************************************
2  * cinepak.c: cinepak video decoder 
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: cinepak.c,v 1.4 2002/07/23 17:19:02 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28
29 #include <vlc/vlc.h>
30 #include <vlc/vout.h>
31 #include <vlc/decoder.h>
32 #include <vlc/input.h>
33
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>                                              /* getpid() */
36 #endif
37
38 #include <errno.h>
39 #include <string.h>
40
41 #ifdef HAVE_SYS_TIMES_H
42 #   include <sys/times.h>
43 #endif
44
45 #include "vdec_ext-plugins.h"
46 #include "cinepak.h"
47
48 /*
49  * Local prototypes
50  */
51 static int      decoder_Probe   ( vlc_fourcc_t * );
52 static int      decoder_Run     ( decoder_fifo_t * );
53 static int      InitThread      ( videodec_thread_t * );
54 static void     EndThread       ( videodec_thread_t * );
55 static void     DecodeThread    ( videodec_thread_t * );
56
57
58 /*****************************************************************************
59  * Capabilities
60  *****************************************************************************/
61 void _M( vdec_getfunctions )( function_list_t * p_function_list )
62 {
63     p_function_list->functions.dec.pf_probe = decoder_Probe;
64     p_function_list->functions.dec.pf_run   = decoder_Run;
65 }
66
67 /*****************************************************************************
68  * Build configuration tree.
69  *****************************************************************************/
70
71 MODULE_CONFIG_START
72 MODULE_CONFIG_STOP
73
74 MODULE_INIT_START
75     SET_DESCRIPTION( "Cinepak Video Decoder" )
76     ADD_CAPABILITY( DECODER, 70 )
77 MODULE_INIT_STOP
78
79 MODULE_ACTIVATE_START
80     _M( vdec_getfunctions )( &p_module->p_functions->dec );
81 MODULE_ACTIVATE_STOP
82
83 MODULE_DEACTIVATE_START
84 MODULE_DEACTIVATE_STOP
85
86
87 /*****************************************************************************
88  * decoder_Probe: probe the decoder and return score
89  *****************************************************************************
90  * Tries to launch a decoder and return score so that the interface is able 
91  * to chose.
92  *****************************************************************************/
93 static int decoder_Probe( vlc_fourcc_t *pi_type )
94 {
95     switch(  *pi_type )
96     {
97         case( VLC_FOURCC('c','v','i','d') ):
98         case( VLC_FOURCC('C','V','I','D') ):
99             return( 0);
100         default:
101             return( -1 );
102     }
103 }
104
105 /*****************************************************************************
106  * decoder_Run: this function is called just after the thread is created
107  *****************************************************************************/
108 static int decoder_Run ( decoder_fifo_t * p_fifo )
109 {
110     videodec_thread_t   *p_vdec;
111     int b_error;
112     
113     if ( !(p_vdec = (videodec_thread_t*)malloc( sizeof(videodec_thread_t))) )
114     {
115         msg_Err( p_fifo, "out of memory" );
116         DecoderError( p_fifo );
117         return( -1 );
118     }
119     memset( p_vdec, 0, sizeof( videodec_thread_t ) );
120
121     p_vdec->p_fifo = p_fifo;
122
123     if( InitThread( p_vdec ) != 0 )
124     {
125         DecoderError( p_fifo );
126         return( -1 );
127     }
128      
129     while( (!p_vdec->p_fifo->b_die) && (!p_vdec->p_fifo->b_error) )
130     {
131         DecodeThread( p_vdec );
132     }
133
134     if( ( b_error = p_vdec->p_fifo->b_error ) )
135     {
136         DecoderError( p_vdec->p_fifo );
137     }
138
139     EndThread( p_vdec );
140
141     if( b_error )
142     {
143         return( -1 );
144     }
145    
146     return( 0 );
147
148
149
150 /*****************************************************************************
151  * locales Functions
152  *****************************************************************************/
153
154 static inline u16 GetWBE( u8 *p_buff )
155 {
156     return( (p_buff[0]<<8) + p_buff[1] );
157 }
158
159 static inline u32 GetDWBE( u8 *p_buff )
160 {
161     return( (p_buff[0] << 24) + ( p_buff[1] <<16 ) +
162             ( p_buff[2] <<8 ) + p_buff[3] );
163 }
164
165 #define GET2BYTES( p ) \
166     GetWBE( p ); p+= 2;
167 /* FIXME */
168 #define GET3BYTES( p ) \
169     (GetDWBE( p ) >> 8); p+= 3;
170
171 #define GET4BYTES( p ) \
172     GetDWBE( p ); p+= 4;
173
174 #define FREE( p ) \
175     if( p ) free( p )
176
177 /* get the first pes from fifo */
178 static pes_packet_t *__PES_GET( decoder_fifo_t *p_fifo )
179 {
180     pes_packet_t *p_pes;
181
182     vlc_mutex_lock( &p_fifo->data_lock );
183
184     /* if fifo is emty wait */
185     while( !p_fifo->p_first )
186     {
187         if( p_fifo->b_die )
188         {
189             vlc_mutex_unlock( &p_fifo->data_lock );
190             return( NULL );
191         }
192         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
193     }
194     p_pes = p_fifo->p_first;
195
196     vlc_mutex_unlock( &p_fifo->data_lock );
197
198     return( p_pes );
199 }
200
201 /* free the first pes and go to next */
202 static void __PES_NEXT( decoder_fifo_t *p_fifo )
203 {
204     pes_packet_t *p_next;
205
206     vlc_mutex_lock( &p_fifo->data_lock );
207     
208     p_next = p_fifo->p_first->p_next;
209     p_fifo->p_first->p_next = NULL;
210     input_DeletePES( p_fifo->p_packets_mgt, p_fifo->p_first );
211     p_fifo->p_first = p_next;
212     p_fifo->i_depth--;
213
214     if( !p_fifo->p_first )
215     {
216         /* No PES in the fifo */
217         /* pp_last no longer valid */
218         p_fifo->pp_last = &p_fifo->p_first;
219         while( !p_fifo->p_first )
220         {
221             vlc_cond_signal( &p_fifo->data_wait );
222             vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
223         }
224     }
225     vlc_mutex_unlock( &p_fifo->data_lock );
226 }
227
228 static inline void __GetFrame( videodec_thread_t *p_vdec )
229 {
230     pes_packet_t  *p_pes;
231     data_packet_t *p_data;
232     byte_t        *p_buffer;
233
234     p_pes = __PES_GET( p_vdec->p_fifo );
235     p_vdec->i_pts = p_pes->i_pts;
236
237     while( ( !p_pes->i_nb_data )||( !p_pes->i_pes_size ) )
238     {
239         __PES_NEXT( p_vdec->p_fifo );
240         p_pes = __PES_GET( p_vdec->p_fifo );
241     }
242     p_vdec->i_framesize = p_pes->i_pes_size;
243     if( p_pes->i_nb_data == 1 )
244     {
245         p_vdec->p_framedata = p_pes->p_first->p_payload_start;
246         return;    
247     }
248     /* get a buffer and gather all data packet */
249     p_vdec->p_framedata = p_buffer = malloc( p_pes->i_pes_size );
250     p_data = p_pes->p_first;
251     do
252     {
253         p_vdec->p_fifo->p_vlc->pf_memcpy( p_buffer, p_data->p_payload_start, 
254                      p_data->p_payload_end - p_data->p_payload_start );
255         p_buffer += p_data->p_payload_end - p_data->p_payload_start;
256         p_data = p_data->p_next;
257     } while( p_data );
258 }
259
260 static inline void __NextFrame( videodec_thread_t *p_vdec )
261 {
262     pes_packet_t  *p_pes;
263
264     p_pes = __PES_GET( p_vdec->p_fifo );
265     if( p_pes->i_nb_data != 1 )
266     {
267         free( p_vdec->p_framedata ); /* FIXME keep this buffer */
268     }
269     __PES_NEXT( p_vdec->p_fifo );
270 }
271
272 static int cinepak_CheckVout( vout_thread_t *p_vout,
273                               int i_width,
274                               int i_height )
275 {
276     if( !p_vout )
277     {
278         return( 0 );
279     }
280     
281     if( ( p_vout->render.i_width != i_width )||
282         ( p_vout->render.i_height != i_height )||
283         ( p_vout->render.i_chroma != VLC_FOURCC('I','4','2','0') )||
284         ( p_vout->render.i_aspect != VOUT_ASPECT_FACTOR * i_width / i_height) )
285     {
286         return( 0 );
287     }
288     else
289     {
290         return( 1 );
291     }
292 }
293
294 /* Return a Vout */
295
296 static vout_thread_t *cinepak_CreateVout( videodec_thread_t *p_vdec,
297                                          int i_width,
298                                          int i_height )
299 {
300     vout_thread_t *p_vout;
301
302     if( (!i_width)||(!i_height) )
303     {
304         return( NULL ); /* Can't create a new vout without display size */
305     }
306
307     /* Spawn a video output if there is none. First we look for our children,
308      * then we look for any other vout that might be available. */
309     p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
310                                               FIND_CHILD );
311     if( !p_vout )
312     {
313         p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
314                                                   FIND_ANYWHERE );
315     }
316
317     if( p_vout )
318     {
319         if( !cinepak_CheckVout( p_vout, i_width, i_height ) )
320         {
321             /* We are not interested in this format, close this vout */
322             vlc_object_detach_all( p_vout );
323             vlc_object_release( p_vout );
324             vout_DestroyThread( p_vout );
325             p_vout = NULL;
326         }
327         else
328         {
329             /* This video output is cool! Hijack it. */
330             vlc_object_detach_all( p_vout );
331             vlc_object_attach( p_vout, p_vdec->p_fifo );
332             vlc_object_release( p_vout );
333         }
334     }
335
336     if( p_vout == NULL )
337     {
338         msg_Dbg( p_vdec->p_fifo, "no vout present, spawning one" );
339     
340         p_vout = vout_CreateThread( p_vdec->p_fifo,
341                                     i_width,
342                                     i_height,
343                                     VLC_FOURCC('I','4','2','0'),
344                                     VOUT_ASPECT_FACTOR * i_width / i_height );
345     }
346
347     return( p_vout );
348 }
349
350 void cinepak_LoadCodebook( cinepak_codebook_t *p_codebook,
351                            u8 *p_data,
352                            int b_grayscale )
353 {
354     int i, i_y[4], i_u, i_v, i_Cb, i_Cr;
355     int i_uv;
356 #define SCALEBITS 12
357 #define FIX( x ) ( (int)( (x) * ( 1L << SCALEBITS ) + 0.5 ) )
358     
359     for( i = 0; i < 4; i++ )
360     {
361         i_y[i] = (u8)( *(p_data++) );
362     }
363     if( b_grayscale )
364     {
365         i_u  = (s8)( *(p_data++) );
366         i_v  = (s8)( *(p_data++) );
367     }
368     else
369     {
370         i_u  = 0;
371         i_v  = 0;
372     }
373     
374     /*
375           | Y  |   | 1 -0.0655  0.0110 | | CY |
376           | Cb | = | 0  1.1656 -0.0062 | | CU |
377           | Cr |   | 0  0.0467  1.4187 | | CV |
378      */
379     i_uv = ( FIX( -0.0655 ) * i_u + FIX( 0.0110 ) * i_v ) >> SCALEBITS;
380     for( i = 0; i < 4; i++ )
381     {
382         i_y[i] += i_uv;
383     }
384     i_Cb  = ( FIX( 1.1656 ) * i_u + FIX( -0.0062 ) * i_v ) >> SCALEBITS;
385     i_Cr  = ( FIX( 0.0467 ) * i_u + FIX(  1.4187 ) * i_v ) >> SCALEBITS;
386     
387     for( i = 0; i < 4; i++ )
388     {
389         p_codebook->i_y[i] = __MIN( __MAX( 0, i_y[i] ), 255 );
390     }
391     p_codebook->i_u  = __MIN( __MAX( 0, i_Cb + 128 ), 255 );
392     p_codebook->i_v  = __MIN( __MAX( 0, i_Cr + 128 ), 255 );
393    
394 #undef FIX
395 #undef SCALEBITS
396 }
397
398 void cinepak_Getv4( cinepak_context_t *p_context,
399                     int i_strip,
400                     int i_x,  int i_y,
401                     int i_x2, int i_y2,
402                     u8 *p_data )
403 {
404     u8 i_index[4];
405     int i,j;
406     
407     u8 *p_dst_y, *p_dst_u, *p_dst_v;
408 #define PIX_SET_Y( x, y, v ) \
409     p_dst_y[(x) + (y)* p_context->i_stride[0]] = (v);
410     
411 #define PIX_SET_UV( i, p, x, y, v ) \
412     p[(x) + (y)* (p_context->i_stride[i])] = (v);
413    
414     for( i = 0; i < 4; i++ )
415     {
416         i_index[i] = *(p_data++);
417     }
418
419     /* y plane */
420     p_dst_y = p_context->p_pix[0] + p_context->i_stride[0] * i_y + i_x;
421     p_dst_u = p_context->p_pix[1] + p_context->i_stride[1] * (i_y/2) + (i_x/2);
422     p_dst_v = p_context->p_pix[2] + p_context->i_stride[2] * (i_y/2) + (i_x/2);
423     
424     for( i = 0; i < 2; i++ )
425     {
426         for( j = 0; j < 2; j ++ )
427         {
428             PIX_SET_Y( 2*j + 0, 2*i + 0, 
429                        p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[0]);
430             PIX_SET_Y( 2*j + 1, 2*i + 0, 
431                        p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[1]);
432             PIX_SET_Y( 2*j + 0, 2*i + 1, 
433                        p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[2]);
434             PIX_SET_Y( 2*j + 1, 2*i + 1, 
435                        p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[3]);
436
437             PIX_SET_UV( 1, p_dst_u, j, i, 
438                         p_context->codebook_v4[i_strip][i_index[j+2*i]].i_u );
439             PIX_SET_UV( 2, p_dst_v, j, i, 
440                         p_context->codebook_v4[i_strip][i_index[j+2*i]].i_v );
441         }
442     }
443 #undef PIX_SET_Y
444 #undef PIX_SET_UV
445 }
446
447 void cinepak_Getv1( cinepak_context_t *p_context,
448                     int i_strip,
449                     int i_x,  int i_y,
450                     int i_x2, int i_y2,
451                     u8 *p_data )
452 {
453     u8 i_index;
454     int i,j;
455     
456     u8 *p_dst_y, *p_dst_u, *p_dst_v;
457 #define PIX_SET_Y( x, y, v ) \
458     p_dst_y[(x) + (y)* p_context->i_stride[0]] = (v);
459     
460 #define PIX_SET_UV( i,p, x, y, v ) \
461     p[(x) + (y)* (p_context->i_stride[i])] = (v);
462    
463     i_index = *(p_data++);
464
465     /* y plane */
466     p_dst_y = p_context->p_pix[0] + p_context->i_stride[0] * i_y + i_x;
467     p_dst_u = p_context->p_pix[1] + p_context->i_stride[1] * (i_y/2) + (i_x/2);
468     p_dst_v = p_context->p_pix[2] + p_context->i_stride[2] * (i_y/2) + (i_x/2);
469
470     for( i = 0; i < 2; i++ )
471     {
472         for( j = 0; j < 2; j ++ )
473         {
474             PIX_SET_Y( 2*j + 0, 2*i + 0, 
475                        p_context->codebook_v1[i_strip][i_index].i_y[0] );
476             PIX_SET_Y( 2*j + 1, 2*i + 0, 
477                        p_context->codebook_v1[i_strip][i_index].i_y[1] );
478             PIX_SET_Y( 2*j + 0, 2*i + 1, 
479                        p_context->codebook_v1[i_strip][i_index].i_y[2] );
480             PIX_SET_Y( 2*j + 1, 2*i + 1, 
481                        p_context->codebook_v1[i_strip][i_index].i_y[3] );
482
483             PIX_SET_UV( 1,p_dst_u, j, i, 
484                         p_context->codebook_v1[i_strip][i_index].i_u );
485             PIX_SET_UV( 2,p_dst_v, j, i, 
486                         p_context->codebook_v1[i_strip][i_index].i_v );
487         }
488     }
489
490 #undef PIX_SET_Y
491 #undef PIX_SET_UV
492 }
493
494 /*****************************************************************************
495  * The function that decode one frame
496  *****************************************************************************/
497 int cinepak_decode_frame( cinepak_context_t *p_context, 
498                           int i_length, u8 *p_data )
499 {
500     int i_strip;
501
502     int i_frame_flags;
503     int i_frame_size;
504     int i_width, i_height;
505     int i_frame_strips;
506     int i_index;
507     int i_strip_x1 =0, i_strip_y1=0;
508     int i_strip_x2 =0, i_strip_y2=0;
509    
510     if( i_length <= 10 )
511     {
512         /* Broken header or no data */
513         return( -1 );
514     }
515   
516     /* get header */
517     i_frame_flags  = *(p_data++);
518     i_frame_size = GET3BYTES( p_data );
519     i_width  = GET2BYTES( p_data );
520     i_height = GET2BYTES( p_data );
521     i_frame_strips = GET2BYTES( p_data );
522     
523     /* Check if we have a picture buffer with good size */
524     if( ( p_context->i_width != i_width )||
525         ( p_context->i_height != i_height ) )
526     {
527         int i;
528         for( i = 0; i < 3; i++ )
529         {
530             FREE( p_context->p_pix[i] );
531         }
532
533         p_context->i_width = i_width;
534         p_context->i_height = i_height;
535
536         p_context->i_stride[0] = ( i_width + 3)&0xfffc;
537         p_context->i_stride[1] = p_context->i_stride[2] = 
538                 p_context->i_stride[0] / 2;
539
540         p_context->i_lines[0] = ( i_height + 3 )&0xfffc;
541         p_context->i_lines[1] = p_context->i_lines[2] =
542                 p_context->i_lines[0] /2;
543         
544         for( i = 0; i < 3; i++ )
545         {
546             p_context->p_pix[i] = malloc( p_context->i_stride[i] * 
547                                           p_context->i_lines[i] );
548         }
549     }
550
551     if( i_frame_size != i_length )
552     {
553         i_length = __MIN( i_length, i_frame_size );
554     }
555     i_length -= 10;
556
557     if( i_frame_strips >= CINEPAK_MAXSTRIP )
558     {
559         i_frame_strips = CINEPAK_MAXSTRIP;
560     }
561
562     /* Now decode each strip */
563
564     for( i_strip = 0; i_strip < i_frame_strips; i_strip++ )
565     {
566         int i_strip_id;
567         int i_strip_size;
568
569         if( i_length <= 12 )
570         {
571             break;
572         }
573         
574            
575         i_strip_id   = GET2BYTES( p_data );
576         i_strip_size = GET2BYTES( p_data );
577         i_strip_size = __MIN( i_strip_size, i_length );
578         /* FIXME I don't really understand how it's work; */
579         i_strip_y1  = i_strip_y2 + GET2BYTES( p_data );
580         i_strip_x1  = GET2BYTES( p_data );
581         i_strip_y2  = i_strip_y2 + GET2BYTES( p_data );
582         i_strip_x2  = GET2BYTES( p_data );
583
584         i_length -= i_strip_size;
585
586         i_strip_size -= 12;
587         /* init codebook , if needed */
588         if( ( i_strip > 0 )&&( !(i_frame_flags&0x01) ) )
589         {
590             memcpy( &p_context->codebook_v1[i_strip], 
591                     &p_context->codebook_v1[i_strip-1],
592                     sizeof(cinepak_codebook_t[256] ) );
593
594             memcpy( &p_context->codebook_v4[i_strip], 
595                     &p_context->codebook_v4[i_strip-1],
596                     sizeof(cinepak_codebook_t[256] ) );
597         }
598
599         /* Now parse all chunk in this strip */
600         while( i_strip_size > 0 )
601         {
602             cinepak_codebook_t (*p_codebook)[CINEPAK_MAXSTRIP][256];
603             int i_mode;
604
605             int i_chunk_id;
606             int i_chunk_size;
607             u32 i_vector_flags;
608             int i_count;
609             int i;
610             int i_x, i_y; /* (0,0) begin in fact at (x1,y1) ... */
611
612             i_chunk_id   = GET2BYTES( p_data );
613             i_chunk_size = GET2BYTES( p_data );
614             i_chunk_size  = __MIN( i_chunk_size, i_strip_size ); 
615             i_strip_size -= i_chunk_size;
616             
617             i_chunk_size -= 4;
618
619             i_x = 0; 
620             i_y = 0;
621             if( i_chunk_size < 0 )
622             {
623                 break;
624             }
625             
626             switch( i_chunk_id )
627             {
628                 case( 0x2000 ): /* 12bits v4 Intra*/
629                 case( 0x2200 ): /* 12bits v1 Intra*/
630                 case( 0x2400 ): /* 8bits v4 Intra*/
631                 case( 0x2600 ): /* 8bits v1 Intra */
632                     i_mode = ( ( i_chunk_id&0x0400 ) == 0 );
633                     p_codebook = ( i_chunk_id&0x0200 ) ?
634                                     &p_context->codebook_v1 :
635                                     &p_context->codebook_v4;
636                     
637                     i_count = __MIN( i_chunk_size / ( i_mode ? 6 : 4 ), 256 );
638
639                     for( i = 0; i < i_count; i++ )
640                     {
641                         cinepak_LoadCodebook( &((*p_codebook)[i_strip][i]), 
642                                               p_data, 
643                                        i_mode&~p_context->b_grayscale );
644                         p_data += i_mode ? 6 : 4;
645                         i_chunk_size -= i_mode ? 6 : 4;
646                     }
647                     break;
648
649                 case( 0x2100 ): /* selective 12bits v4 Inter*/
650                 case( 0x2300 ): /* selective 12bits v1 Inter*/
651                 case( 0x2500 ): /* selective 8bits v4 Inter*/
652                 case( 0x2700 ): /* selective 8bits v1 Inter*/
653                     i_mode = ( ( i_chunk_id&0x0400 ) == 0 );
654                     p_codebook = ( i_chunk_id&0x0200 ) ?
655                                     &p_context->codebook_v1 :
656                                     &p_context->codebook_v4;
657                     
658                     i_index = 0;
659                     while( (i_chunk_size > 4)&&(i_index<256))
660                     {
661                         i_vector_flags = GET4BYTES( p_data );
662                         i_chunk_size -= 4;
663                         for( i = 0; i < 32; i++ )
664                         {
665                             if( ( i_chunk_size < ( i_mode ? 6 : 4 ) )||(i_index >= 256 ))
666                             {
667                                 break;
668                             }
669                             if( i_vector_flags&0x80000000UL )
670                             {
671                                 cinepak_LoadCodebook( &((*p_codebook)[i_strip][i_index]),
672                                                       p_data, 
673                                             i_mode&~p_context->b_grayscale );
674
675                                 p_data += i_mode ? 6 : 4;
676                                 i_chunk_size -= i_mode ? 6 : 4;
677                             }
678                             i_index++;
679                             i_vector_flags <<= 1;
680                         }
681                     }
682                     break;
683
684                 case( 0x3000 ): /* load image Intra */
685                     while( (i_chunk_size >= 4 )&&(i_y<i_strip_y2-i_strip_y1) )
686                     {
687                         i_vector_flags = GET4BYTES( p_data );
688                         i_chunk_size -= 4;
689                         i_strip_size -= 4;
690                         i_length     -= 4;
691
692                         for( i = 0; i < 32; i++ )
693                         {
694                             if( ( i_y >= i_strip_y2 - i_strip_y1)||
695                                     ( i_chunk_size<=0) )
696                             {
697                                 break;
698                             }
699                             if( i_vector_flags&0x80000000UL )
700                             {
701                                 cinepak_Getv4( p_context,
702                                                i_strip,
703                                                i_strip_x1 + i_x, 
704                                                i_strip_y1 + i_y,
705                                                i_strip_x2, i_strip_y2,
706                                                p_data );
707                                 p_data += 4;
708                                 i_chunk_size -= 4;
709                             }
710                             else
711                             {
712                                 cinepak_Getv1( p_context,
713                                                i_strip,
714                                                i_strip_x1 + i_x, 
715                                                i_strip_y1 + i_y,
716                                                i_strip_x2, i_strip_y2,
717                                                p_data );
718                                 p_data++;
719                                 i_chunk_size--;
720                             }
721
722                             i_x += 4;
723                             if( i_x >= i_strip_x2 - i_strip_x1 )
724                             {
725                                 i_x = 0;
726                                 i_y += 4;
727                             }
728                             i_vector_flags <<= 1;
729                         }
730                     } 
731                     break;
732
733                 case( 0x3100 ): /* load image Inter */
734                     while( ( i_chunk_size > 4 )&&( i_y < i_strip_y2 - i_strip_y1) )
735                     {
736                         u32 i_mask;
737                         i_vector_flags = GET4BYTES( p_data );
738                         i_chunk_size -= 4;
739                         i_mask = 0x80000000UL;
740
741                         while((i_chunk_size > 0 )&&( i_mask )&&( i_y < i_strip_y2 - i_strip_y1 ))
742                         {
743                             if( i_vector_flags&i_mask)
744                             {
745                                 i_mask >>= 1;
746                                 if( !i_mask )
747                                 {
748                                     if( i_chunk_size < 4 )
749                                     {
750                                         break;
751                                     } 
752                                     i_vector_flags = GET4BYTES( p_data );
753                                     i_chunk_size -= 4;
754                                     i_mask = 0x80000000UL;
755                                 }
756                                 if( i_vector_flags&i_mask )
757                                 {
758                                     if( i_chunk_size < 4 ) break;
759                                     cinepak_Getv4( p_context,
760                                                    i_strip,
761                                                    i_strip_x1 + i_x, 
762                                                    i_strip_y1 + i_y,
763                                                    i_strip_x2, i_strip_y2,
764                                                    p_data );
765                                     p_data += 4;
766                                     i_chunk_size -= 4;
767                                 }
768                                 else
769                                 {
770                                     if( i_chunk_size < 1 ) break;
771                                     cinepak_Getv1( p_context,
772                                                    i_strip,
773                                                    i_strip_x1 + i_x, 
774                                                    i_strip_y1 + i_y,
775                                                    i_strip_x2, i_strip_y2,
776                                                    p_data );
777                                     p_data++;
778                                     i_chunk_size--;
779                                 }
780                             }
781                             i_mask >>= 1;
782
783                             i_x += 4;
784                             if( i_x >= i_strip_x2 - i_strip_x1 )
785                             {
786                                 i_x = 0;
787                                 i_y += 4;
788                             }
789                         }
790                     } 
791                     break;
792
793                 case( 0x3200 ): /* load intra picture but all v1*/
794                     while( ( i_chunk_size > 0 )&&
795                            ( i_y < i_strip_y2 - i_strip_y1) )
796                     {
797                         cinepak_Getv1( p_context,
798                                        i_strip,
799                                        i_strip_x1 + i_x, 
800                                        i_strip_y1 + i_y,
801                                        i_strip_x2, i_strip_y2,
802                                        p_data );
803                         p_data++;
804                         i_chunk_size--;
805
806                         i_x += 4;
807                         if( i_x >= i_strip_x2 - i_strip_x1 )
808                         {
809                             i_x = 0;
810                             i_y += 4;
811                         }
812                         
813                     } 
814                     break;
815                     
816
817
818                 default:
819                     break;
820
821             }
822             p_data += i_chunk_size ; /* skip remains bytes */
823             
824         }
825     }
826
827     
828     return( 0 );
829 }
830
831
832 /*****************************************************************************
833  *
834  * Functions that initialize, decode and end the decoding process
835  *
836  *****************************************************************************/
837
838 /*****************************************************************************
839  * InitThread: initialize vdec output thread
840  *****************************************************************************
841  * This function is called from decoder_Run and performs the second step 
842  * of the initialization. It returns 0 on success. Note that the thread's 
843  * flag are not modified inside this function.
844  *****************************************************************************/
845
846 static int InitThread( videodec_thread_t *p_vdec )
847 {
848
849     /* This will be created after the first decoded frame */
850     if( !(p_vdec->p_context = malloc( sizeof( cinepak_context_t ) ) ) )
851     {
852         msg_Err( p_vdec->p_fifo, "out of memory" );
853     }
854     memset( p_vdec->p_context, 0, sizeof( cinepak_context_t ) );
855
856     if( config_GetInt( p_vdec->p_fifo, "grayscale" ) )
857     {
858         p_vdec->p_context->b_grayscale = 1;
859     }
860     else
861     {
862         p_vdec->p_context->b_grayscale = 0;
863     }
864     
865     p_vdec->p_vout = NULL;
866     msg_Dbg( p_vdec->p_fifo, "cinepak decoder started" );
867     return( 0 );
868 }
869
870
871 /*****************************************************************************
872  * DecodeThread: Called for decode one frame
873  *****************************************************************************/
874 static void  DecodeThread( videodec_thread_t *p_vdec )
875 {
876     int     i_status;
877     
878     int i_plane;
879     u8 *p_dst, *p_src;
880     picture_t *p_pic; /* videolan picture */
881
882     __GetFrame( p_vdec );
883
884     i_status = cinepak_decode_frame( p_vdec->p_context,
885                                      p_vdec->i_framesize,
886                                      p_vdec->p_framedata );
887     __NextFrame( p_vdec );
888                                          
889     if( i_status < 0 )
890     {
891         msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
892                                   p_vdec->i_framesize );
893         return;
894     }
895     
896     /* Check our vout */
897     if( !cinepak_CheckVout( p_vdec->p_vout,
898                             p_vdec->p_context->i_width,
899                             p_vdec->p_context->i_height ) )
900     {
901         p_vdec->p_vout = 
902           cinepak_CreateVout( p_vdec,
903                               p_vdec->p_context->i_width,
904                               p_vdec->p_context->i_height );
905
906         if( !p_vdec->p_vout )
907         {
908             msg_Err( p_vdec->p_fifo, "cannot create vout" );
909             p_vdec->p_fifo->b_error = 1; /* abort */
910             return;
911         }
912     }
913
914     /* Send decoded frame to vout */
915     while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
916     {
917         if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
918         {
919             return;
920         }
921         msleep( VOUT_OUTMEM_SLEEP );
922     }
923     
924     for( i_plane = 0; i_plane < 3; i_plane++ )
925     {
926         int i_line, i_lines;
927
928         p_dst = p_pic->p[i_plane].p_pixels;
929         p_src = p_vdec->p_context->p_pix[i_plane];
930
931         i_lines = __MIN( p_vdec->p_context->i_lines[i_plane],
932                          p_pic->p[i_plane].i_lines );
933         for( i_line = 0; i_line < i_lines; i_line++ )
934         {
935             memcpy( p_dst, 
936                     p_src, 
937                     __MIN( p_pic->p[i_plane].i_pitch,
938                            p_vdec->p_context->i_stride[i_plane] ) );
939             p_dst += p_pic->p[i_plane].i_pitch;
940             p_src += p_vdec->p_context->i_stride[i_plane];
941         }
942     }
943
944     vout_DatePicture( p_vdec->p_vout, p_pic, p_vdec->i_pts);
945     vout_DisplayPicture( p_vdec->p_vout, p_pic );
946     
947     return;
948 }
949
950
951 /*****************************************************************************
952  * EndThread: thread destruction
953  *****************************************************************************
954  * This function is called when the thread ends after a sucessful
955  * initialization.
956  *****************************************************************************/
957 static void EndThread( videodec_thread_t *p_vdec )
958 {
959     int i;
960     
961     if( !p_vdec )
962     {
963         return;
964     }
965     msg_Dbg( p_vdec->p_fifo, "cinepak decoder stopped" );
966
967     for( i = 0; i < 3; i++ )
968     {
969         FREE( p_vdec->p_context->p_pix[i] );
970     }
971     
972     free( p_vdec->p_context );
973     
974     if( p_vdec->p_vout != NULL )
975     {
976         /* We are about to die. Reattach video output to p_vlc. */
977         vlc_object_detach( p_vdec->p_vout, p_vdec->p_fifo );
978         vlc_object_attach( p_vdec->p_vout, p_vdec->p_fifo->p_vlc );
979     }
980     
981     free( p_vdec );
982 }
983
984