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