]> git.sesse.net Git - vlc/blob - modules/codec/xvmc/slice_xvmc_vld.c
Nicer commits, faster breaking time and better-looking headers
[vlc] / modules / codec / xvmc / slice_xvmc_vld.c
1 /* $Id$
2  * Copyright (c) 2004 The Unichrome project. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU General Public License as published by the Free Software
6  * Foundation; either version 2, or (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTIES OR REPRESENTATIONS; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  * See the GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along with
14  * this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16  *
17  *
18  */
19  
20 #include <vlc/vlc.h>
21 #include <vlc_vout.h>
22 #include <vlc_codec.h>
23
24 #include "mpeg2.h"
25 #include "mpeg2_internal.h"
26 #include "xvmc_vld.h"
27
28 static uint8_t zig_zag_scan[64] ATTR_ALIGN(16) =
29 {
30     /* Zig-Zag scan pattern */
31      0, 1, 8,16, 9, 2, 3,10,
32     17,24,32,25,18,11, 4, 5,
33     12,19,26,33,40,48,41,34,
34     27,20,13, 6, 7,14,21,28,
35     35,42,49,56,57,50,43,36,
36     29,22,15,23,30,37,44,51,
37     58,59,52,45,38,31,39,46,
38     53,60,61,54,47,55,62,63
39 };
40
41 static uint8_t alternate_scan [64] ATTR_ALIGN(16) =
42 {
43     /* Alternate scan pattern */
44     0,8,16,24,1,9,2,10,17,25,32,40,48,56,57,49,
45     41,33,26,18,3,11,4,12,19,27,34,42,50,58,35,43,
46     51,59,20,28,5,13,6,14,21,29,36,44,52,60,37,45,
47     53,61,22,30,7,15,23,31,38,46,54,62,39,47,55,63
48 };
49
50
51
52
53 void mpeg2_xxmc_choose_coding(decoder_t *p_dec, mpeg2_decoder_t * const decoder, picture_t *picture,
54                               double aspect_ratio, int flags) 
55 {
56     if (picture)
57     {
58         //vlc_fourcc_t decoder_format = picture->format.i_chroma;
59         //if (decoder_format == VLC_FOURCC('X','x','M','C')) {
60         vlc_xxmc_t *xxmc = (vlc_xxmc_t *) picture->p_accel_data;
61
62         /*
63          * Make a request for acceleration type and mpeg coding from
64          * the output plugin.
65          */
66
67         xxmc->fallback_format = VLC_FOURCC('Y','V','1','2');
68         xxmc->acceleration = VLC_XVMC_ACCEL_VLD;//| VLC_XVMC_ACCEL_IDCT| VLC_XVMC_ACCEL_MOCOMP ;
69
70         //msg_Dbg(p_dec, "mpeg2_xxmc_choose_coding 2");
71         /*
72          * Standard MOCOMP / IDCT XvMC implementation for interlaced streams
73          * is buggy. The bug is inherited from the old XvMC driver. Don't use it until
74          * it has been fixed. (A volunteer ?)
75          */
76
77         //if ( decoder->picture_structure != 3 ) {
78         //xxmc->acceleration &= ~( VLC_XVMC_ACCEL_IDCT | VLC_XVMC_ACCEL_MOCOMP );
79         //}
80
81         xxmc->mpeg = (decoder->mpeg1) ? VLC_XVMC_MPEG_1:VLC_XVMC_MPEG_2;
82         xxmc->proc_xxmc_update_frame( picture,
83                                       decoder->width,
84                                       decoder->height,
85                                       aspect_ratio,
86                                       VLC_IMGFMT_XXMC, flags );
87         //}
88   }
89 }
90
91 void mpeg2_xxmc_slice( mpeg2dec_t *mpeg2dec, picture_t *picture, int code,
92                        uint8_t *buffer, int size) 
93 {
94     mpeg2_decoder_t * const decoder = &(mpeg2dec->decoder);
95     picture = (picture_t *)mpeg2dec->fbuf[0]->id;
96     vlc_xxmc_t *xxmc = (vlc_xxmc_t *) picture->p_accel_data;
97     vlc_vld_frame_t *vft = &xxmc->vld_frame;
98     unsigned mb_frame_height;
99     int i;
100     const uint8_t *scan_pattern;
101
102     if (1 == code)
103     {
104         //mpeg2_skip(mpeg2dec, 1);
105         //frame->bad_frame = 1;
106
107         /*
108          * Check that first field went through OK. Otherwise,
109          * indicate bad frame.
110          */ 
111         if (decoder->second_field)
112         {
113             mpeg2dec->xvmc_last_slice_code = (xxmc->decoded) ? 0 : -1;
114             xxmc->decoded = 0;
115         }
116         else
117         {
118             mpeg2dec->xvmc_last_slice_code = 0;
119         }
120
121         mb_frame_height =
122                 //(!(decoder->mpeg1) && (decoder->progressive_sequence)) ?
123                 //2*((decoder->height+31) >> 5) :
124                 (decoder->height+15) >> 4;
125         mpeg2dec->xxmc_mb_pic_height = (decoder->picture_structure == FRAME_PICTURE ) ?
126                                         mb_frame_height : mb_frame_height >> 1;
127
128         if (decoder->mpeg1)
129         {
130             vft->mv_ranges[0][0] = decoder->b_motion.f_code[0];
131             vft->mv_ranges[0][1] = decoder->b_motion.f_code[0];
132             vft->mv_ranges[1][0] = decoder->f_motion.f_code[0];
133             vft->mv_ranges[1][1] = decoder->f_motion.f_code[0];
134         }
135         else
136         {
137             vft->mv_ranges[0][0] = decoder->b_motion.f_code[0];
138             vft->mv_ranges[0][1] = decoder->b_motion.f_code[1];
139             vft->mv_ranges[1][0] = decoder->f_motion.f_code[0];
140             vft->mv_ranges[1][1] = decoder->f_motion.f_code[1];
141         }
142
143         vft->picture_structure = decoder->picture_structure;
144         vft->picture_coding_type = decoder->coding_type;
145         vft->mpeg_coding = (decoder->mpeg1) ? 0 : 1;
146         vft->progressive_sequence = decoder->progressive_sequence;
147         vft->scan = (decoder->scan == mpeg2_scan_alt);
148         vft->pred_dct_frame = decoder->frame_pred_frame_dct;
149         vft->concealment_motion_vectors =
150         decoder->concealment_motion_vectors;
151         vft->q_scale_type = decoder->q_scale_type;
152         vft->intra_vlc_format = decoder->intra_vlc_format;
153         vft->intra_dc_precision = 7 - decoder->intra_dc_precision;
154         vft->second_field = decoder->second_field;
155
156         /*
157          * Translation of libmpeg2's Q-matrix layout to VLD XvMC's.
158          * Errors here will give
159          * blocky artifacts and sometimes wrong colors.
160          */
161
162         scan_pattern = (vft->scan) ? alternate_scan : zig_zag_scan;
163         if( (vft->load_intra_quantizer_matrix = decoder->load_intra_quantizer_matrix) )
164         {
165             for (i=0; i<64; ++i)
166             {
167                 vft->intra_quantizer_matrix[scan_pattern[i]] =
168                 mpeg2dec->quantizer_matrix[0][decoder->scan[i]];
169             }
170         }
171
172         if( (vft->load_non_intra_quantizer_matrix = decoder->load_non_intra_quantizer_matrix) )
173         {
174             for (i=0; i<64; ++i)
175             {
176                 vft->non_intra_quantizer_matrix[scan_pattern[i]] =
177                                         mpeg2dec->quantizer_matrix[1][decoder->scan[i]];
178             }
179         }
180         decoder->load_intra_quantizer_matrix = 0;
181         decoder->load_non_intra_quantizer_matrix = 0;
182
183         vft->forward_reference_picture = (picture_t *)mpeg2dec->ptr_forward_ref_picture;
184         vft->backward_reference_picture = (picture_t *)mpeg2dec->ptr_backward_ref_picture;
185
186 #if 0
187     printf("\nSLICE DATA !!!! size=%d", size-4);
188     int i=0;
189     if ( vft->forward_reference_picture != NULL && ((vlc_xxmc_t *)
190          vft->forward_reference_picture->p_accel_data)->slice_data_size > 10)
191     {
192         printf("\nFORWARD SLICE DATA !!!! size=%d\n", ((vlc_xxmc_t *)
193                vft->forward_reference_picture->p_accel_data)->slice_data_size);
194         for (i=0;i<10;i++)
195         {
196             printf("%d ", *(((vlc_xxmc_t *) vft->forward_reference_picture->p_accel_data)->slice_data+i));
197         }
198         printf("\nFORWARD SLICE DATA END!!!!\n");
199     }
200     if ( vft->backward_reference_picture != NULL && ((vlc_xxmc_t *)
201          vft->backward_reference_picture->p_accel_data)->slice_data_size > 10)
202     {
203         printf("\nBACKWARD SLICE DATA !!!! size=%d\n", ((vlc_xxmc_t *)
204                vft->backward_reference_picture->p_accel_data)->slice_data_size);
205         for (i=0;i<10;i++)
206         {
207             printf("%d ", *(((vlc_xxmc_t *) vft->backward_reference_picture->p_accel_data)->slice_data+i));
208         }
209         printf("\nBACKWARD SLICE DATA END!!!!\n");
210     }
211 #endif
212
213         xxmc->proc_xxmc_begin( picture );
214         if (xxmc->result != 0)
215         {
216             /* "mpeg2_xxmc_slice begin failed" */
217             /* xmc->proc_xxmc_flushsync( picture ); */
218             xxmc->proc_xxmc_flush( picture );
219             mpeg2dec->xvmc_last_slice_code=-1;
220         }
221     }
222
223     if( ((code == mpeg2dec->xvmc_last_slice_code + 1 ||
224         code == mpeg2dec->xvmc_last_slice_code)) &&
225         code <= mpeg2dec->xxmc_mb_pic_height )
226     {
227         /*
228          * Send this slice to the output plugin. May stall for a long
229          * time in proc_slice;
230          */
231         //mpeg2_skip(mpeg2dec, 1);
232
233         //frame->bad_frame = 1;
234         //size = mpeg2dec->chunk_ptr-mpeg2dec->chunk_start;
235         xxmc->slice_data_size = size;//mpeg2dec->buf_end - mpeg2dec->buf_start;
236         xxmc->slice_data = mpeg2dec->chunk_start;//buffer;
237         xxmc->slice_code = code;
238         xxmc->proc_xxmc_slice( picture );
239
240         if (xxmc->result != 0)
241         {
242             //xxmc->proc_xxmc_flushsync( picture );
243             xxmc->proc_xxmc_flush( picture );   
244             mpeg2dec->xvmc_last_slice_code=-1;
245             return;
246         }
247         if (code == mpeg2dec->xxmc_mb_pic_height)
248         {
249             /*
250              * We've encountered the last slice of this frame.
251              * Release the decoder for a new frame and, if all
252              * went well, tell libmpeg2 that we are ready.
253              */
254
255             mpeg2_xxmc_vld_frame_complete(mpeg2dec,picture,code);
256             return;
257         }
258         else if (code == mpeg2dec->xvmc_last_slice_code + 1)
259         {
260             //xxmc->proc_xxmc_flush( picture );
261
262             /*
263              * Keep track of slices.
264              */
265             mpeg2dec->xvmc_last_slice_code++;
266         }
267     }
268     else
269     {
270         /*
271          * An error has occured.
272          */
273
274         //printf("VLD XvMC: Slice error: code=%d\tlast slice code=%d\tmb_pic_height=%d\n", code, mpeg2dec->xvmc_last_slice_code,mpeg2dec->xxmc_mb_pic_height);
275         mpeg2dec->xvmc_last_slice_code = -1;
276         xxmc->proc_xxmc_flush( picture );
277         return;
278     }
279 }
280
281 void mpeg2_xxmc_vld_frame_complete(mpeg2dec_t *mpeg2dec, picture_t *picture, int code) 
282 {
283     vlc_xxmc_t *xxmc = (vlc_xxmc_t *) picture->p_accel_data;
284     vlc_vld_frame_t *vft = &xxmc->vld_frame;
285
286     if (xxmc->decoded)
287         return;
288
289     if (mpeg2dec->xvmc_last_slice_code >= 1)
290     {
291         xxmc->proc_xxmc_flush( picture );
292         if (xxmc->result)
293         {
294             mpeg2dec->xvmc_last_slice_code=-1;
295             return;
296         }
297         xxmc->decoded = 1;
298         mpeg2dec->xvmc_last_slice_code++;
299         if (vft->picture_structure == 3 || vft->second_field)
300         {
301             if (xxmc->result == 0)
302                 mpeg2_skip(mpeg2dec, 0);
303             //frame->bad_frame = 0;
304         }
305     }
306 }
307