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