]> git.sesse.net Git - vlc/blob - modules/codec/xvmc/decode.c
Various compile fixes for modules/codec/xvmc
[vlc] / modules / codec / xvmc / decode.c
1 /* $Id$
2  * decode.c
3  * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
4  * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
5  *
6  * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
7  * See http://libmpeg2.sourceforge.net/ for updates.
8  *
9  * mpeg2dec 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  * mpeg2dec 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-1307  USA
22  */
23
24 #include <vlc/vlc.h>
25 #include <vlc_vout.h>
26
27 #include "xxmc-config.h"
28
29 #include <string.h>     /* memcmp/memset, try to remove */
30 #include <stdlib.h>
31 #include <inttypes.h>
32
33 #include "mpeg2.h"
34 #include "attributes.h"
35 #include "mpeg2_internal.h"
36 #include "xvmc_vld.h"
37
38 static int mpeg2_accels = 0;
39
40 #define BUFFER_SIZE (1194 * 1024)
41
42 const mpeg2_info_t *mpeg2_info( mpeg2dec_t * mpeg2dec )
43 {
44     return &(mpeg2dec->info);
45 }
46
47 static inline int skip_chunk( mpeg2dec_t * mpeg2dec, int bytes )
48 {
49     uint8_t *current = NULL;
50     uint32_t shift;
51     uint8_t *limit = NULL;
52     uint8_t byte;
53
54     if (!bytes)
55         return 0;
56
57     current = mpeg2dec->buf_start;
58     shift = mpeg2dec->shift;
59     limit = current + bytes;
60
61     do {
62         byte = *current++;
63         if (shift == 0x00000100)
64         {
65             int skipped;
66
67             mpeg2dec->shift = 0xffffff00;
68             skipped = current - mpeg2dec->buf_start;
69             mpeg2dec->buf_start = current;
70             return skipped;
71         }
72         shift = (shift | byte) << 8;
73     } while (current < limit);
74
75     mpeg2dec->shift = shift;
76     mpeg2dec->buf_start = current;
77     return 0;
78 }
79
80 static inline int copy_chunk( mpeg2dec_t * mpeg2dec, int bytes )
81 {
82     uint8_t *current = NULL;
83     uint32_t shift;
84     uint8_t *chunk_ptr = NULL;
85     uint8_t *limit = NULL;
86     uint8_t byte;
87
88     if (!bytes)
89         return 0;
90
91     current = mpeg2dec->buf_start;
92     shift = mpeg2dec->shift;
93     chunk_ptr = mpeg2dec->chunk_ptr;
94     limit = current + bytes;
95
96     do {
97         byte = *current++;
98         if (shift == 0x00000100)
99         {
100             int copied;
101
102             mpeg2dec->shift = 0xffffff00;
103             mpeg2dec->chunk_size = chunk_ptr - mpeg2dec->chunk_start - 3;
104             mpeg2dec->chunk_ptr = chunk_ptr + 1;   
105             copied = current - mpeg2dec->buf_start;
106             mpeg2dec->buf_start = current;
107             return copied;
108         }
109         shift = (shift | byte) << 8;
110         *chunk_ptr++ = byte;
111     } while (current < limit);
112
113     mpeg2dec->shift = shift;
114     mpeg2dec->buf_start = current;
115     return 0;
116 }
117
118 void mpeg2_buffer( mpeg2dec_t * mpeg2dec, uint8_t * start, uint8_t * end )
119 {
120     mpeg2dec->buf_start = start;
121     mpeg2dec->buf_end = end;
122 }
123
124 int mpeg2_getpos( mpeg2dec_t * mpeg2dec )
125 {
126     return mpeg2dec->buf_end - mpeg2dec->buf_start;
127 }
128
129 static inline mpeg2_state_t seek_chunk( mpeg2dec_t * mpeg2dec )
130 {
131     int size, skipped;
132
133     size = mpeg2dec->buf_end - mpeg2dec->buf_start;
134     skipped = skip_chunk (mpeg2dec, size);
135     if (!skipped)
136     {
137         mpeg2dec->bytes_since_tag += size;
138         return STATE_BUFFER;
139     }
140     mpeg2dec->bytes_since_tag += skipped;
141     mpeg2dec->code = mpeg2dec->buf_start[-1];
142     return (mpeg2_state_t)-1;
143 }
144
145 mpeg2_state_t mpeg2_seek_header( mpeg2dec_t * mpeg2dec )
146 {
147     while( (mpeg2dec->code != 0xb3) &&
148            (((mpeg2dec->code != 0xb7) &&
149              (mpeg2dec->code != 0xb8) &&
150              mpeg2dec->code ) ||
151              (mpeg2dec->sequence.width == (unsigned)-1)) )
152     {
153         if (seek_chunk (mpeg2dec) == STATE_BUFFER)
154             return STATE_BUFFER;
155     }
156
157     mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
158     mpeg2dec->user_data_len = 0;
159     return (mpeg2dec->code ? mpeg2_parse_header (mpeg2dec) :
160                              mpeg2_header_picture_start (mpeg2dec));
161 }
162
163 #define RECEIVED(code,state) (((state) << 8) + (code))
164
165 mpeg2_state_t mpeg2_parse( mpeg2dec_t * mpeg2dec )
166 {
167     int size_buffer, size_chunk, copied;
168
169     if (mpeg2dec->action)
170     {
171         mpeg2_state_t state;
172
173         state = mpeg2dec->action (mpeg2dec);
174         if ((int)state >= 0)
175             return state;
176     }
177
178     while(1)
179     {
180         while( (unsigned int) (mpeg2dec->code - mpeg2dec->first_decode_slice)
181                  < mpeg2dec->nb_decode_slices )
182         {
183             size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start;
184             size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE -
185                           mpeg2dec->chunk_ptr);
186
187             if (size_buffer <= size_chunk)
188             {
189                 copied = copy_chunk (mpeg2dec, size_buffer);
190                 if (!copied)
191                 {
192                     mpeg2dec->bytes_since_tag += size_buffer;
193                     mpeg2dec->chunk_ptr += size_buffer;
194                     return STATE_BUFFER;
195                 }
196             }
197             else
198             {
199                 copied = copy_chunk (mpeg2dec, size_chunk);
200
201                 if( !copied )
202                 {
203                     /* filled the chunk buffer without finding a start code */
204                     mpeg2dec->bytes_since_tag += size_chunk;
205                     mpeg2dec->action = seek_chunk;
206                     return STATE_INVALID;
207                 }
208             }
209             mpeg2dec->bytes_since_tag += copied;
210             mpeg2_xxmc_slice( mpeg2dec, NULL,
211                               mpeg2dec->code,mpeg2dec->chunk_start,
212                               mpeg2dec->chunk_size);
213             mpeg2dec->prev_code = mpeg2dec->code;
214             mpeg2dec->code = mpeg2dec->buf_start[-1];
215             mpeg2dec->chunk_ptr = mpeg2dec->chunk_start;
216         }
217
218         if( (unsigned int) (mpeg2dec->code - 1) >= (0xb0 - 1) )
219               break;
220         if( seek_chunk (mpeg2dec) == STATE_BUFFER )
221             return STATE_BUFFER;
222     }
223
224     switch( mpeg2dec->code )
225     {
226         case 0x00:
227             mpeg2dec->action = mpeg2_header_picture_start;
228             return mpeg2dec->state;
229         case 0xb7:
230             mpeg2dec->action = mpeg2_header_end;
231             break;
232         case 0xb3:
233         case 0xb8:
234             mpeg2dec->action = mpeg2_parse_header;
235             break;
236         default:
237             mpeg2dec->action = seek_chunk;
238             return STATE_INVALID;
239     }
240     return (mpeg2dec->state == STATE_SLICE) ? STATE_SLICE : STATE_INVALID;
241 }
242
243 mpeg2_state_t mpeg2_parse_header( mpeg2dec_t * mpeg2dec )
244 {
245     static int (* process_header[]) (mpeg2dec_t * mpeg2dec) =
246     {
247         mpeg2_header_picture,
248         mpeg2_header_extension,
249         mpeg2_header_user_data,
250         mpeg2_header_sequence,
251         NULL,
252         NULL,
253         NULL,
254         NULL,
255         mpeg2_header_gop
256     };
257     int size_buffer, size_chunk, copied;
258
259     mpeg2dec->action = mpeg2_parse_header;
260     mpeg2dec->info.user_data = NULL;
261     mpeg2dec->info.user_data_len = 0;
262
263     while( 1 )
264     {
265         size_buffer = mpeg2dec->buf_end - mpeg2dec->buf_start;
266         size_chunk = (mpeg2dec->chunk_buffer + BUFFER_SIZE -
267                       mpeg2dec->chunk_ptr);
268         if( size_buffer <= size_chunk )
269         {
270             copied = copy_chunk (mpeg2dec, size_buffer);
271             if( !copied )
272             {
273                 mpeg2dec->bytes_since_tag += size_buffer;
274                 mpeg2dec->chunk_ptr += size_buffer;
275                 return STATE_BUFFER;
276             }
277         }
278         else
279         {
280             copied = copy_chunk (mpeg2dec, size_chunk);
281             if( !copied )
282             {
283                 /* filled the chunk buffer without finding a start code */
284                 mpeg2dec->bytes_since_tag += size_chunk;
285                 mpeg2dec->code = 0xb4;
286                 mpeg2dec->action = mpeg2_seek_header;
287                 return STATE_INVALID;
288             }
289         }
290         mpeg2dec->bytes_since_tag += copied;
291
292         if( process_header[mpeg2dec->code & 0x0b](mpeg2dec) )
293         {
294             mpeg2dec->code = mpeg2dec->buf_start[-1];
295             mpeg2dec->action = mpeg2_seek_header;
296             return STATE_INVALID;
297         }
298         mpeg2dec->code = mpeg2dec->buf_start[-1];
299
300         switch( RECEIVED(mpeg2dec->code, mpeg2dec->state) )
301         {
302             /* state transition after a sequence header */
303             case RECEIVED (0x00, STATE_SEQUENCE):
304                 mpeg2dec->action = mpeg2_header_picture_start;
305             case RECEIVED (0xb8, STATE_SEQUENCE):
306                 mpeg2_header_sequence_finalize( mpeg2dec );
307                 break;
308             /* other legal state transitions */
309             case RECEIVED (0x00, STATE_GOP):
310                 mpeg2_header_gop_finalize( mpeg2dec );
311                 mpeg2dec->action = mpeg2_header_picture_start;
312                 break;
313             case RECEIVED (0x01, STATE_PICTURE):
314             case RECEIVED (0x01, STATE_PICTURE_2ND):
315                 mpeg2_header_picture_finalize( mpeg2dec, mpeg2_accels );
316                 mpeg2dec->action = mpeg2_header_slice_start;
317                 break;
318             /* legal headers within a given state */
319             case RECEIVED (0xb2, STATE_SEQUENCE):
320             case RECEIVED (0xb2, STATE_GOP):
321             case RECEIVED (0xb2, STATE_PICTURE):
322             case RECEIVED (0xb2, STATE_PICTURE_2ND):
323             case RECEIVED (0xb5, STATE_SEQUENCE):
324             case RECEIVED (0xb5, STATE_PICTURE):
325             case RECEIVED (0xb5, STATE_PICTURE_2ND):
326                 mpeg2dec->chunk_ptr = mpeg2dec->chunk_start;
327                 continue;
328             default:
329                 mpeg2dec->action = mpeg2_seek_header;
330                 return STATE_INVALID;
331         }
332         mpeg2dec->chunk_start = mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
333         mpeg2dec->user_data_len = 0;
334         return mpeg2dec->state;
335     }
336 }
337
338 int mpeg2_convert( mpeg2dec_t * mpeg2dec, mpeg2_convert_t convert, void * arg )
339 {
340     mpeg2_convert_init_t convert_init;
341     int error;
342
343     error = convert( MPEG2_CONVERT_SET, NULL, &(mpeg2dec->sequence), 0,
344                 mpeg2_accels, arg, &convert_init );
345     if (!error)
346     {
347         mpeg2dec->convert = convert;
348         mpeg2dec->convert_arg = arg;
349         mpeg2dec->convert_id_size = convert_init.id_size;
350         mpeg2dec->convert_stride = 0;
351     }
352     return error;
353 }
354
355 int mpeg2_stride( mpeg2dec_t * mpeg2dec, int stride )
356 {
357     if (!mpeg2dec->convert)
358     {
359         if (stride < (int) mpeg2dec->sequence.width)
360             stride = mpeg2dec->sequence.width;
361         mpeg2dec->decoder.stride_frame = stride;
362     }
363     else
364     {
365         mpeg2_convert_init_t convert_init;
366
367         stride = mpeg2dec->convert( MPEG2_CONVERT_STRIDE, NULL,
368                                     &(mpeg2dec->sequence), stride,
369                                     mpeg2_accels, mpeg2dec->convert_arg,
370                                     &convert_init );
371         mpeg2dec->convert_id_size = convert_init.id_size;
372         mpeg2dec->convert_stride = stride;
373     }
374     return stride;
375 }
376
377 void mpeg2_set_buf( mpeg2dec_t * mpeg2dec, uint8_t * buf[3], void * id )
378 {
379     mpeg2_fbuf_t * fbuf;
380
381     if (mpeg2dec->custom_fbuf)
382     {
383         if (mpeg2dec->state == STATE_SEQUENCE)
384         {
385             mpeg2dec->fbuf[2] = mpeg2dec->fbuf[1];
386             mpeg2dec->fbuf[1] = mpeg2dec->fbuf[0];
387         }
388         mpeg2_set_fbuf( mpeg2dec,
389                 (mpeg2dec->decoder.coding_type == PIC_FLAG_CODING_TYPE_B) );
390         fbuf = mpeg2dec->fbuf[0];
391     }
392     else
393     {
394         fbuf = &(mpeg2dec->fbuf_alloc[mpeg2dec->alloc_index].fbuf);
395         mpeg2dec->alloc_index_user = ++mpeg2dec->alloc_index;
396     }
397     fbuf->buf[0] = buf[0];
398     fbuf->buf[1] = buf[1];
399     fbuf->buf[2] = buf[2];
400     fbuf->id = id;
401 }
402
403 void mpeg2_custom_fbuf( mpeg2dec_t * mpeg2dec, int custom_fbuf )
404 {
405     mpeg2dec->custom_fbuf = custom_fbuf;
406 }
407
408 void mpeg2_skip( mpeg2dec_t * mpeg2dec, int skip )
409 {
410     mpeg2dec->first_decode_slice = 1;
411     mpeg2dec->nb_decode_slices = skip ? 0 : (0xb0 - 1);
412 }
413
414 void mpeg2_slice_region( mpeg2dec_t * mpeg2dec, int start, int end )
415 {
416     start = (start < 1) ? 1 : (start > 0xb0) ? 0xb0 : start;
417     end = (end < start) ? start : (end > 0xb0) ? 0xb0 : end;
418     mpeg2dec->first_decode_slice = start;
419     mpeg2dec->nb_decode_slices = end - start;
420 }
421
422 void mpeg2_tag_picture( mpeg2dec_t * mpeg2dec, uint32_t tag, uint32_t tag2 )
423 {
424     mpeg2dec->tag_previous = mpeg2dec->tag_current;
425     mpeg2dec->tag2_previous = mpeg2dec->tag2_current;
426     mpeg2dec->tag_current = tag;
427     mpeg2dec->tag2_current = tag2;
428     mpeg2dec->num_tags++;
429     mpeg2dec->bytes_since_tag = 0;
430 }
431
432 uint32_t mpeg2_accel( uint32_t accel )
433 {
434     if( !mpeg2_accels )
435     {
436         if( accel & MPEG2_ACCEL_DETECT )
437             accel |= mpeg2_detect_accel ();
438         mpeg2_accels = accel |= MPEG2_ACCEL_DETECT;
439         mpeg2_cpu_state_init (accel);
440         /* mpeg2_idct_init (accel); */
441         mpeg2_mc_init (accel);
442     }
443     return mpeg2_accels & ~MPEG2_ACCEL_DETECT;
444 }
445
446 void mpeg2_reset( mpeg2dec_t * mpeg2dec, int full_reset )
447 {
448     mpeg2dec->buf_start = mpeg2dec->buf_end = NULL;
449     mpeg2dec->num_tags = 0;
450     mpeg2dec->shift = 0xffffff00;
451     mpeg2dec->code = 0xb4;
452     mpeg2dec->action = mpeg2_seek_header;
453     mpeg2dec->state = STATE_INVALID;
454     mpeg2dec->first = 1;
455     mpeg2dec->ptr_forward_ref_picture = NULL;
456     mpeg2dec->ptr_backward_ref_picture = NULL;
457
458     mpeg2_reset_info(&(mpeg2dec->info));
459     mpeg2dec->info.gop = NULL;
460     mpeg2dec->info.user_data = NULL;
461     mpeg2dec->info.user_data_len = 0;
462     if( full_reset )
463     {
464         mpeg2dec->info.sequence = NULL;
465         mpeg2_header_state_init (mpeg2dec);
466     }
467 }
468
469 mpeg2dec_t *mpeg2_init( void )
470 {
471     mpeg2dec_t *mpeg2dec = NULL;
472
473     mpeg2_accel( MPEG2_ACCEL_DETECT );
474     mpeg2dec = (mpeg2dec_t *) mpeg2_malloc( sizeof (mpeg2dec_t),
475                                             MPEG2_ALLOC_MPEG2DEC );
476     if( mpeg2dec == NULL )
477         return NULL;
478
479     memset( mpeg2dec->decoder.DCTblock, 0, 64 * sizeof (int16_t) );
480     memset( mpeg2dec->quantizer_matrix, 0, 4 * 64 * sizeof (uint8_t) );
481
482     mpeg2dec->chunk_buffer = (uint8_t *) mpeg2_malloc( BUFFER_SIZE + 4,
483                                                        MPEG2_ALLOC_CHUNK );
484     mpeg2dec->sequence.width = (unsigned int)-1;
485     mpeg2_reset (mpeg2dec, 1);
486     return mpeg2dec;
487 }
488
489 void mpeg2_close( mpeg2dec_t * mpeg2dec )
490 {
491     mpeg2_header_state_init( mpeg2dec );
492     mpeg2_free( mpeg2dec->chunk_buffer );
493     mpeg2_free( mpeg2dec );
494 }