~ubuntu-branches/debian/wheezy/vlc/wheezy

« back to all changes in this revision

Viewing changes to modules/codec/cinepak.c

Tags: upstream-0.7.2.final
ImportĀ upstreamĀ versionĀ 0.7.2.final

Show diffs side-by-side

added added

removed removed

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