]> git.sesse.net Git - vlc/blob - modules/codec/cinepak.c
28ef9351f27a271f6a2eec59ecb12beeedbaa331
[vlc] / modules / codec / cinepak.c
1 /*****************************************************************************
2  * cinepak.c: cinepak video decoder 
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: cinepak.c,v 1.1 2003/10/02 21:12:45 gbazin 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 #include <string.h>
29
30 #include <vlc/vlc.h>
31 #include <vlc/vout.h>
32 #include <vlc/decoder.h>
33 #include <vlc/input.h>
34
35 #define CINEPAK_MAXSTRIP 32
36
37 typedef struct cinepak_codebook_s
38 {
39     u8 i_y[4];
40     u8 i_u, i_v;
41     
42 } cinepak_codebook_t;
43
44 typedef struct cinepak_context_s
45 {
46     int b_grayscale; /* force to grayscale */
47     
48     int i_width;
49     int i_height;
50
51     int i_stride_x;
52     int i_stride_y;
53      
54     u8  *p_y, *p_u, *p_v;
55
56     int i_stride[3]; /* our 3 planes */
57     int i_lines[3];
58     u8  *p_pix[3];
59     
60     cinepak_codebook_t codebook_v1[CINEPAK_MAXSTRIP][256];
61     cinepak_codebook_t codebook_v4[CINEPAK_MAXSTRIP][256];
62     
63 } cinepak_context_t;
64
65 /*****************************************************************************
66  * decoder_sys_t : decoder descriptor
67  *****************************************************************************/
68 struct decoder_sys_t
69 {
70     /*
71      * Cinepak properties
72      */
73     cinepak_context_t *p_context;
74
75     /*
76      * Output properties
77      */
78     vout_thread_t *p_vout;
79 };
80
81 /*****************************************************************************
82  * Local prototypes
83  *****************************************************************************/
84 static int OpenDecoder( vlc_object_t * );
85 static int InitDecoder( decoder_t * );
86 static int RunDecoder ( decoder_t *, block_t * );
87 static int EndDecoder ( decoder_t * );
88
89 static int cinepak_decode_frame( cinepak_context_t *, int, u8 * );
90
91 /*****************************************************************************
92  * Module descriptor
93  *****************************************************************************/
94 vlc_module_begin();
95     set_description( _("Cinepak video decoder") );
96     set_capability( "decoder", 70 );
97     set_callbacks( OpenDecoder, NULL );
98 vlc_module_end();
99
100 /*****************************************************************************
101  * OpenDecoder: probe the decoder and return score
102  *****************************************************************************
103  * Tries to launch a decoder and return score so that the interface is able 
104  * to chose.
105  *****************************************************************************/
106 static int OpenDecoder( vlc_object_t *p_this )
107 {
108     decoder_t *p_dec = (decoder_t*)p_this;
109     
110     switch( p_dec->p_fifo->i_fourcc )
111     {
112         case VLC_FOURCC('c','v','i','d'):
113         case VLC_FOURCC('C','V','I','D'):
114             break;
115
116         default:
117             return VLC_EGENERIC;
118     }
119
120     /* Allocate the memory needed to store the decoder's structure */
121     if( ( p_dec->p_sys =
122           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
123     {
124         msg_Err( p_dec, "out of memory" );
125         return VLC_EGENERIC;
126     }
127
128     p_dec->pf_init = InitDecoder;
129     p_dec->pf_decode = RunDecoder;
130     p_dec->pf_end = EndDecoder;
131
132     return VLC_SUCCESS;
133 }
134
135 /*****************************************************************************
136  * InitDecoder: Initalize the decoder
137  *****************************************************************************/
138 static int InitDecoder( decoder_t *p_dec )
139 {
140     decoder_sys_t *p_sys = p_dec->p_sys;
141     vlc_value_t val;
142
143     p_sys->p_vout = NULL;
144
145     if( !(p_sys->p_context = malloc( sizeof( cinepak_context_t ) ) ) )
146     {
147         msg_Err( p_dec, "out of memory" );
148     }
149     memset( p_sys->p_context, 0, sizeof( cinepak_context_t ) );
150
151     var_Create( p_dec, "grayscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
152     var_Get( p_dec, "grayscale", &val );
153     p_sys->p_context->b_grayscale = val.b_bool;
154
155     msg_Dbg( p_dec, "cinepak decoder started" );
156
157     return VLC_SUCCESS;
158 }
159
160 /****************************************************************************
161  * RunDecoder: the whole thing
162  ****************************************************************************
163  * This function must be fed with whole frames.
164  ****************************************************************************/
165 static int RunDecoder( decoder_t *p_dec, block_t *p_block )
166 {
167     decoder_sys_t *p_sys = p_dec->p_sys;
168     int i_status, i_plane;
169     u8 *p_dst, *p_src;
170     picture_t *p_pic;
171
172     i_status = cinepak_decode_frame( p_sys->p_context,
173                                      p_block->i_buffer, p_block->p_buffer );
174     if( i_status < 0 )
175     {
176         msg_Warn( p_dec, "cannot decode one frame (%d bytes)",
177                   p_block->i_buffer );
178         block_Release( p_block );
179         return VLC_SUCCESS;
180     }
181
182     /* Check our vout */
183     p_sys->p_vout = vout_Request( p_dec, p_sys->p_vout,
184                                   p_sys->p_context->i_width,
185                                   p_sys->p_context->i_height,
186                                   VLC_FOURCC('I','4','2','0'),
187                                   p_sys->p_context->i_width
188                                     * VOUT_ASPECT_FACTOR
189                                     / p_sys->p_context->i_height );
190     if( !p_sys->p_vout )
191     {
192         msg_Err( p_dec, "cannot create vout" );
193         block_Release( p_block );
194         return VLC_EGENERIC;
195     }
196
197     /* Send decoded frame to vout */
198     while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) )
199     {
200         if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )
201         {
202             block_Release( p_block );
203             return VLC_EGENERIC;
204         }
205         msleep( VOUT_OUTMEM_SLEEP );
206     }
207
208     for( i_plane = 0; i_plane < 3; i_plane++ )
209     {
210         int i_line, i_lines;
211
212         p_dst = p_pic->p[i_plane].p_pixels;
213         p_src = p_sys->p_context->p_pix[i_plane];
214
215         i_lines = __MIN( p_sys->p_context->i_lines[i_plane],
216                          p_pic->p[i_plane].i_lines );
217         for( i_line = 0; i_line < i_lines; i_line++ )
218         {
219             memcpy( p_dst, p_src,
220                     __MIN( p_pic->p[i_plane].i_pitch,
221                            p_sys->p_context->i_stride[i_plane] ) );
222             p_dst += p_pic->p[i_plane].i_pitch;
223             p_src += p_sys->p_context->i_stride[i_plane];
224         }
225     }
226
227     vout_DatePicture( p_sys->p_vout, p_pic, p_block->i_pts);
228     vout_DisplayPicture( p_sys->p_vout, p_pic );
229
230     block_Release( p_block );
231     return VLC_SUCCESS;
232 }
233
234 /*****************************************************************************
235  * EndDecoder: theora decoder destruction
236  *****************************************************************************/
237 static int EndDecoder( decoder_t *p_dec )
238 {
239     decoder_sys_t *p_sys = p_dec->p_sys;
240     int i;
241
242     msg_Dbg( p_dec, "cinepak decoder stopped" );
243
244     vout_Request( p_dec, p_sys->p_vout, 0, 0, 0, 0 );
245
246     for( i = 0; i < 3; i++ )
247     {
248         if( p_sys->p_context->p_pix[i] ) free( p_sys->p_context->p_pix[i] );
249     }
250
251     free( p_sys->p_context );
252
253     free( p_sys );
254
255     return VLC_SUCCESS;
256 }
257
258 /*****************************************************************************
259  * local Functions
260  *****************************************************************************/
261
262 #define GET2BYTES( p ) \
263     GetWBE( p ); p+= 2;
264 /* FIXME */
265 #define GET3BYTES( p ) \
266     (GetDWBE( p ) >> 8); p+= 3;
267
268 #define GET4BYTES( p ) \
269     GetDWBE( p ); p+= 4;
270
271 #define FREE( p ) \
272     if( p ) free( p )
273
274 static void cinepak_LoadCodebook( cinepak_codebook_t *p_codebook,
275                                   u8 *p_data, int b_grayscale )
276 {
277     int i, i_y[4], i_u, i_v, i_Cb, i_Cr;
278     int i_uv;
279 #define SCALEBITS 12
280 #define FIX( x ) ( (int)( (x) * ( 1L << SCALEBITS ) + 0.5 ) )
281     
282     for( i = 0; i < 4; i++ )
283     {
284         i_y[i] = (u8)( *(p_data++) );
285     }
286     if( b_grayscale )
287     {
288         i_u  = (s8)( *(p_data++) );
289         i_v  = (s8)( *(p_data++) );
290     }
291     else
292     {
293         i_u  = 0;
294         i_v  = 0;
295     }
296
297     /*
298           | Y  |   | 1 -0.0655  0.0110 | | CY |
299           | Cb | = | 0  1.1656 -0.0062 | | CU |
300           | Cr |   | 0  0.0467  1.4187 | | CV |
301      */
302     i_uv = ( FIX( -0.0655 ) * i_u + FIX( 0.0110 ) * i_v ) >> SCALEBITS;
303     for( i = 0; i < 4; i++ )
304     {
305         i_y[i] += i_uv;
306     }
307     i_Cb  = ( FIX( 1.1656 ) * i_u + FIX( -0.0062 ) * i_v ) >> SCALEBITS;
308     i_Cr  = ( FIX( 0.0467 ) * i_u + FIX(  1.4187 ) * i_v ) >> SCALEBITS;
309
310     for( i = 0; i < 4; i++ )
311     {
312         p_codebook->i_y[i] = __MIN( __MAX( 0, i_y[i] ), 255 );
313     }
314     p_codebook->i_u  = __MIN( __MAX( 0, i_Cb + 128 ), 255 );
315     p_codebook->i_v  = __MIN( __MAX( 0, i_Cr + 128 ), 255 );
316
317 #undef FIX
318 #undef SCALEBITS
319 }
320
321 static void cinepak_Getv4( cinepak_context_t *p_context,
322                            int i_strip, int i_x, int i_y,
323                            int i_x2, int i_y2, u8 *p_data )
324 {
325     u8 i_index[4];
326     int i,j;
327
328     u8 *p_dst_y, *p_dst_u, *p_dst_v;
329 #define PIX_SET_Y( x, y, v ) \
330     p_dst_y[(x) + (y)* p_context->i_stride[0]] = (v);
331
332 #define PIX_SET_UV( i, p, x, y, v ) \
333     p[(x) + (y)* (p_context->i_stride[i])] = (v);
334
335     for( i = 0; i < 4; i++ )
336     {
337         i_index[i] = *(p_data++);
338     }
339
340     /* y plane */
341     p_dst_y = p_context->p_pix[0] + p_context->i_stride[0] * i_y + i_x;
342     p_dst_u = p_context->p_pix[1] + p_context->i_stride[1] * (i_y/2) + (i_x/2);
343     p_dst_v = p_context->p_pix[2] + p_context->i_stride[2] * (i_y/2) + (i_x/2);
344
345     for( i = 0; i < 2; i++ )
346     {
347         for( j = 0; j < 2; j ++ )
348         {
349             PIX_SET_Y( 2*j + 0, 2*i + 0, 
350                        p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[0]);
351             PIX_SET_Y( 2*j + 1, 2*i + 0, 
352                        p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[1]);
353             PIX_SET_Y( 2*j + 0, 2*i + 1, 
354                        p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[2]);
355             PIX_SET_Y( 2*j + 1, 2*i + 1, 
356                        p_context->codebook_v4[i_strip][i_index[j+2*i]].i_y[3]);
357
358             PIX_SET_UV( 1, p_dst_u, j, i, 
359                         p_context->codebook_v4[i_strip][i_index[j+2*i]].i_u );
360             PIX_SET_UV( 2, p_dst_v, j, i, 
361                         p_context->codebook_v4[i_strip][i_index[j+2*i]].i_v );
362         }
363     }
364 #undef PIX_SET_Y
365 #undef PIX_SET_UV
366 }
367
368 static void cinepak_Getv1( cinepak_context_t *p_context,
369                            int i_strip, int i_x,  int i_y,
370                            int i_x2, int i_y2, u8 *p_data )
371 {
372     u8 i_index;
373     int i,j;
374
375     u8 *p_dst_y, *p_dst_u, *p_dst_v;
376 #define PIX_SET_Y( x, y, v ) \
377     p_dst_y[(x) + (y)* p_context->i_stride[0]] = (v);
378
379 #define PIX_SET_UV( i,p, x, y, v ) \
380     p[(x) + (y)* (p_context->i_stride[i])] = (v);
381
382     i_index = *(p_data++);
383
384     /* y plane */
385     p_dst_y = p_context->p_pix[0] + p_context->i_stride[0] * i_y + i_x;
386     p_dst_u = p_context->p_pix[1] + p_context->i_stride[1] * (i_y/2) + (i_x/2);
387     p_dst_v = p_context->p_pix[2] + p_context->i_stride[2] * (i_y/2) + (i_x/2);
388
389     for( i = 0; i < 2; i++ )
390     {
391         for( j = 0; j < 2; j ++ )
392         {
393             PIX_SET_Y( 2*j + 0, 2*i + 0, 
394                        p_context->codebook_v1[i_strip][i_index].i_y[2*i+j] );
395             PIX_SET_Y( 2*j + 1, 2*i + 0, 
396                        p_context->codebook_v1[i_strip][i_index].i_y[2*i+j] );
397             PIX_SET_Y( 2*j + 0, 2*i + 1, 
398                        p_context->codebook_v1[i_strip][i_index].i_y[2*i+j] );
399             PIX_SET_Y( 2*j + 1, 2*i + 1, 
400                        p_context->codebook_v1[i_strip][i_index].i_y[2*i+j] );
401
402             PIX_SET_UV( 1,p_dst_u, j, i, 
403                         p_context->codebook_v1[i_strip][i_index].i_u );
404             PIX_SET_UV( 2,p_dst_v, j, i, 
405                         p_context->codebook_v1[i_strip][i_index].i_v );
406         }
407     }
408
409 #undef PIX_SET_Y
410 #undef PIX_SET_UV
411 }
412
413 /*****************************************************************************
414  * The function that decode one frame
415  *****************************************************************************/
416 static int cinepak_decode_frame( cinepak_context_t *p_context, 
417                                  int i_length, u8 *p_data )
418 {
419     int i_strip;
420
421     int i_frame_flags;
422     int i_frame_size;
423     int i_width, i_height;
424     int i_frame_strips;
425     int i_index;
426     int i_strip_x1 =0, i_strip_y1=0;
427     int i_strip_x2 =0, i_strip_y2=0;
428
429     if( i_length <= 10 )
430     {
431         /* Broken header or no data */
432         return( -1 );
433     }
434
435     /* get header */
436     i_frame_flags  = *(p_data++);
437     i_frame_size = GET3BYTES( p_data );
438     i_width  = GET2BYTES( p_data );
439     i_height = GET2BYTES( p_data );
440     i_frame_strips = GET2BYTES( p_data );
441
442     if( !i_frame_size || !i_width || !i_height )
443     {
444         /* Broken header */
445         return( -1 );
446     }
447
448     /* Check if we have a picture buffer with good size */
449     if( ( p_context->i_width != i_width ) ||
450         ( p_context->i_height != i_height ) )
451     {
452         int i;
453         for( i = 0; i < 3; i++ )
454         {
455             FREE( p_context->p_pix[i] );
456         }
457
458         p_context->i_width = i_width;
459         p_context->i_height = i_height;
460
461         p_context->i_stride[0] = ( i_width + 3 ) & 0xfffc;
462         p_context->i_stride[1] = p_context->i_stride[2] = 
463                 p_context->i_stride[0] / 2;
464
465         p_context->i_lines[0] = ( i_height + 3 ) & 0xfffc;
466         p_context->i_lines[1] = p_context->i_lines[2] =
467                 p_context->i_lines[0] /2;
468
469         for( i = 0; i < 3; i++ )
470         {
471             p_context->p_pix[i] = malloc( p_context->i_stride[i] * 
472                                           p_context->i_lines[i] );
473             /* Set it to all black */
474             memset( p_context->p_pix[i], ( i == 0 ) ? 0 : 128 ,
475                     p_context->i_stride[i] * p_context->i_lines[i] );
476         }
477     }
478
479     if( i_frame_size != i_length )
480     {
481         i_length = __MIN( i_length, i_frame_size );
482     }
483     i_length -= 10;
484
485     if( i_frame_strips >= CINEPAK_MAXSTRIP )
486     {
487         i_frame_strips = CINEPAK_MAXSTRIP;
488     }
489
490     /* Now decode each strip */
491     for( i_strip = 0; i_strip < i_frame_strips; i_strip++ )
492     {
493         int i_strip_id;
494         int i_strip_size;
495
496         if( i_length <= 12 )
497         {
498             break;
499         }
500
501         i_strip_id   = GET2BYTES( p_data );
502         i_strip_size = GET2BYTES( p_data );
503         i_strip_size = __MIN( i_strip_size, i_length );
504         /* FIXME I don't really understand how it's work; */
505         i_strip_y1  = i_strip_y2 + GET2BYTES( p_data );
506         i_strip_x1  = GET2BYTES( p_data );
507         i_strip_y2  = i_strip_y2 + GET2BYTES( p_data );
508         i_strip_x2  = GET2BYTES( p_data );
509
510         i_length -= i_strip_size;
511
512         i_strip_size -= 12;
513         /* init codebook , if needed */
514         if( ( i_strip > 0 )&&( !(i_frame_flags&0x01) ) )
515         {
516             memcpy( &p_context->codebook_v1[i_strip], 
517                     &p_context->codebook_v1[i_strip-1],
518                     sizeof(cinepak_codebook_t[256] ) );
519
520             memcpy( &p_context->codebook_v4[i_strip], 
521                     &p_context->codebook_v4[i_strip-1],
522                     sizeof(cinepak_codebook_t[256] ) );
523         }
524
525         /* Now parse all chunk in this strip */
526         while( i_strip_size > 0 )
527         {
528             cinepak_codebook_t (*p_codebook)[CINEPAK_MAXSTRIP][256];
529             int i_mode;
530
531             int i_chunk_id;
532             int i_chunk_size;
533             u32 i_vector_flags;
534             int i_count;
535             int i;
536             int i_x, i_y; /* (0,0) begin in fact at (x1,y1) ... */
537
538             i_chunk_id   = GET2BYTES( p_data );
539             i_chunk_size = GET2BYTES( p_data );
540             i_chunk_size  = __MIN( i_chunk_size, i_strip_size ); 
541             i_strip_size -= i_chunk_size;
542
543             i_chunk_size -= 4;
544
545             i_x = 0; 
546             i_y = 0;
547             if( i_chunk_size < 0 )
548             {
549                 break;
550             }
551
552             switch( i_chunk_id )
553             {
554             case( 0x2000 ): /* 12bits v4 Intra*/
555             case( 0x2200 ): /* 12bits v1 Intra*/
556             case( 0x2400 ): /* 8bits v4 Intra*/
557             case( 0x2600 ): /* 8bits v1 Intra */
558                 i_mode = ( ( i_chunk_id&0x0400 ) == 0 );
559                 p_codebook = ( i_chunk_id&0x0200 ) ?
560                                &p_context->codebook_v1 :
561                                &p_context->codebook_v4;
562
563                 i_count = __MIN( i_chunk_size / ( i_mode ? 6 : 4 ), 256 );
564
565                 for( i = 0; i < i_count; i++ )
566                 {
567                     cinepak_LoadCodebook( &((*p_codebook)[i_strip][i]), 
568                                           p_data, 
569                                           i_mode&~p_context->b_grayscale );
570                     p_data += i_mode ? 6 : 4;
571                     i_chunk_size -= i_mode ? 6 : 4;
572                 }
573                 break;
574
575             case( 0x2100 ): /* selective 12bits v4 Inter*/
576             case( 0x2300 ): /* selective 12bits v1 Inter*/
577             case( 0x2500 ): /* selective 8bits v4 Inter*/
578             case( 0x2700 ): /* selective 8bits v1 Inter*/
579                 i_mode = ( ( i_chunk_id&0x0400 ) == 0 );
580                 p_codebook = ( i_chunk_id&0x0200 ) ?
581                                &p_context->codebook_v1 :
582                                &p_context->codebook_v4;
583
584                 i_index = 0;
585                 while( (i_chunk_size > 4)&&(i_index<256))
586                 {
587                     i_vector_flags = GET4BYTES( p_data );
588                     i_chunk_size -= 4;
589                     for( i = 0; i < 32; i++ )
590                     {
591                         if( ( i_chunk_size < ( i_mode ? 6 : 4 ) )
592                             || (i_index >= 256 ) )
593                         {
594                             break;
595                         }
596                         if( i_vector_flags&0x80000000UL )
597                         {
598                             cinepak_LoadCodebook(
599                                 &((*p_codebook)[i_strip][i_index]),
600                                 p_data, i_mode&~p_context->b_grayscale );
601
602                             p_data += i_mode ? 6 : 4;
603                             i_chunk_size -= i_mode ? 6 : 4;
604                         }
605                         i_index++;
606                         i_vector_flags <<= 1;
607                     }
608                 }
609                 break;
610
611             case( 0x3000 ): /* load image Intra */
612                 while( (i_chunk_size >= 4 )&&(i_y<i_strip_y2-i_strip_y1) )
613                 {
614                     i_vector_flags = GET4BYTES( p_data );
615                     i_chunk_size -= 4;
616                     i_strip_size -= 4;
617                     i_length     -= 4;
618
619                     for( i = 0; i < 32; i++ )
620                     {
621                         if( ( i_y >= i_strip_y2 - i_strip_y1) ||
622                             ( i_chunk_size<=0 ) )
623                         {
624                             break;
625                         }
626                         if( i_vector_flags&0x80000000UL )
627                         {
628                             cinepak_Getv4( p_context,
629                                            i_strip,
630                                            i_strip_x1 + i_x, 
631                                            i_strip_y1 + i_y,
632                                            i_strip_x2, i_strip_y2,
633                                            p_data );
634                             p_data += 4;
635                             i_chunk_size -= 4;
636                         }
637                         else
638                         {
639                             cinepak_Getv1( p_context,
640                                            i_strip,
641                                            i_strip_x1 + i_x, 
642                                            i_strip_y1 + i_y,
643                                            i_strip_x2, i_strip_y2,
644                                            p_data );
645                             p_data++;
646                             i_chunk_size--;
647                         }
648
649                         i_x += 4;
650                         if( i_x >= i_strip_x2 - i_strip_x1 )
651                         {
652                             i_x = 0;
653                             i_y += 4;
654                         }
655                         i_vector_flags <<= 1;
656                     }
657                 } 
658                 break;
659
660             case( 0x3100 ): /* load image Inter */
661                 while( ( i_chunk_size > 4 )&&( i_y < i_strip_y2 - i_strip_y1) )
662                 {
663                     u32 i_mask;
664                     i_vector_flags = GET4BYTES( p_data );
665                     i_chunk_size -= 4;
666                     i_mask = 0x80000000UL;
667
668                     while( (i_chunk_size > 0 ) && ( i_mask )
669                            && ( i_y < i_strip_y2 - i_strip_y1 ) )
670                     {
671                         if( i_vector_flags&i_mask )
672                         {
673                             i_mask >>= 1;
674                             if( !i_mask )
675                             {
676                                 if( i_chunk_size < 4 )
677                                 {
678                                     break;
679                                 } 
680                                 i_vector_flags = GET4BYTES( p_data );
681                                 i_chunk_size -= 4;
682                                 i_mask = 0x80000000UL;
683                             }
684                             if( i_vector_flags&i_mask )
685                             {
686                                 if( i_chunk_size < 4 ) break;
687                                 cinepak_Getv4( p_context,
688                                                i_strip,
689                                                i_strip_x1 + i_x, 
690                                                i_strip_y1 + i_y,
691                                                i_strip_x2, i_strip_y2,
692                                                p_data );
693                                 p_data += 4;
694                                 i_chunk_size -= 4;
695                             }
696                             else
697                             {
698                                 if( i_chunk_size < 1 ) break;
699                                 cinepak_Getv1( p_context,
700                                                i_strip,
701                                                i_strip_x1 + i_x, 
702                                                i_strip_y1 + i_y,
703                                                i_strip_x2, i_strip_y2,
704                                                p_data );
705                                 p_data++;
706                                 i_chunk_size--;
707                             }
708                         }
709                         i_mask >>= 1;
710
711                         i_x += 4;
712                         if( i_x >= i_strip_x2 - i_strip_x1 )
713                         {
714                             i_x = 0;
715                             i_y += 4;
716                         }
717                     }
718                 } 
719                 break;
720
721             case( 0x3200 ): /* load intra picture but all v1*/
722                 while( ( i_chunk_size > 0 ) &&
723                        ( i_y < i_strip_y2 - i_strip_y1 ) )
724                 {
725                     cinepak_Getv1( p_context,
726                                    i_strip,
727                                    i_strip_x1 + i_x, 
728                                    i_strip_y1 + i_y,
729                                    i_strip_x2, i_strip_y2,
730                                    p_data );
731                     p_data++;
732                     i_chunk_size--;
733
734                     i_x += 4;
735                     if( i_x >= i_strip_x2 - i_strip_x1 )
736                     {
737                         i_x = 0;
738                         i_y += 4;
739                     }
740                 } 
741                 break;
742
743             default:
744                 break;
745
746             }
747             p_data += i_chunk_size ; /* skip remains bytes */
748         }
749     }
750
751     return( 0 );
752 }