]> git.sesse.net Git - vlc/blob - modules/codec/xvmc/slice_xvmc_vld.c
b9a0d136545db279a1ac70c81a73cf691a2963f3
[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 void mpeg2_xxmc_choose_coding(decoder_t *p_dec,
51         mpeg2_decoder_t * const decoder, picture_t *picture,
52         double aspect_ratio, int flags)
53 {
54     if (picture)
55     {
56         //vlc_fourcc_t decoder_format = picture->format.i_chroma;
57         //if (decoder_format == VLC_FOURCC('X','x','M','C')) {
58         vlc_xxmc_t *xxmc = (vlc_xxmc_t *) picture->p_data;
59
60         /*
61          * Make a request for acceleration type and mpeg coding from
62          * the output plugin.
63          */
64
65         xxmc->fallback_format = VLC_FOURCC('Y','V','1','2');
66         xxmc->acceleration = VLC_XVMC_ACCEL_VLD;//| VLC_XVMC_ACCEL_IDCT| VLC_XVMC_ACCEL_MOCOMP ;
67
68         //msg_Dbg(p_dec, "mpeg2_xxmc_choose_coding 2");
69         /*
70          * Standard MOCOMP / IDCT XvMC implementation for interlaced streams
71          * is buggy. The bug is inherited from the old XvMC driver. Don't use it until
72          * it has been fixed. (A volunteer ?)
73          */
74
75         //if ( decoder->picture_structure != 3 ) {
76         //xxmc->acceleration &= ~( VLC_XVMC_ACCEL_IDCT | VLC_XVMC_ACCEL_MOCOMP );
77         //}
78
79         xxmc->mpeg = (decoder->mpeg1) ? VLC_XVMC_MPEG_1:VLC_XVMC_MPEG_2;
80         xxmc->proc_xxmc_update_frame( picture,
81                                       decoder->width,
82                                       decoder->height,
83                                       aspect_ratio,
84                                       VLC_IMGFMT_XXMC, flags );
85         //}
86   }
87 }
88
89 void mpeg2_xxmc_slice( mpeg2dec_t *mpeg2dec, picture_t *picture,
90                         int code, uint8_t *buffer, int size)
91 {
92     mpeg2_decoder_t * const decoder = &(mpeg2dec->decoder);
93     picture = (picture_t *)mpeg2dec->fbuf[0]->id;
94     vlc_xxmc_t *xxmc = (vlc_xxmc_t *) picture->p_data;
95     vlc_vld_frame_t *vft = &xxmc->vld_frame;
96     unsigned mb_frame_height;
97     int i;
98     const uint8_t *scan_pattern;
99
100     if (1 == code)
101     {
102         //mpeg2_skip(mpeg2dec, 1);
103         //frame->bad_frame = 1;
104
105         /*
106          * Check that first field went through OK. Otherwise,
107          * indicate bad frame.
108          */ 
109         if (decoder->second_field)
110         {
111             mpeg2dec->xvmc_last_slice_code = (xxmc->decoded) ? 0 : -1;
112             xxmc->decoded = 0;
113         }
114         else
115         {
116             mpeg2dec->xvmc_last_slice_code = 0;
117         }
118
119         mb_frame_height =
120                 //(!(decoder->mpeg1) && (decoder->progressive_sequence)) ?
121                 //2*((decoder->height+31) >> 5) :
122                 (decoder->height+15) >> 4;
123         mpeg2dec->xxmc_mb_pic_height = (decoder->picture_structure == FRAME_PICTURE ) ?
124                                         mb_frame_height : mb_frame_height >> 1;
125
126         if (decoder->mpeg1)
127         {
128             vft->mv_ranges[0][0] = decoder->b_motion.f_code[0];
129             vft->mv_ranges[0][1] = decoder->b_motion.f_code[0];
130             vft->mv_ranges[1][0] = decoder->f_motion.f_code[0];
131             vft->mv_ranges[1][1] = decoder->f_motion.f_code[0];
132         }
133         else
134         {
135             vft->mv_ranges[0][0] = decoder->b_motion.f_code[0];
136             vft->mv_ranges[0][1] = decoder->b_motion.f_code[1];
137             vft->mv_ranges[1][0] = decoder->f_motion.f_code[0];
138             vft->mv_ranges[1][1] = decoder->f_motion.f_code[1];
139         }
140
141         vft->picture_structure = decoder->picture_structure;
142         vft->picture_coding_type = decoder->coding_type;
143         vft->mpeg_coding = (decoder->mpeg1) ? 0 : 1;
144         vft->progressive_sequence = decoder->progressive_sequence;
145         vft->scan = (decoder->scan == mpeg2_scan_alt);
146         vft->pred_dct_frame = decoder->frame_pred_frame_dct;
147         vft->concealment_motion_vectors =
148         decoder->concealment_motion_vectors;
149         vft->q_scale_type = decoder->q_scale_type;
150         vft->intra_vlc_format = decoder->intra_vlc_format;
151         vft->intra_dc_precision = 7 - decoder->intra_dc_precision;
152         vft->second_field = decoder->second_field;
153
154         /*
155          * Translation of libmpeg2's Q-matrix layout to VLD XvMC's.
156          * Errors here will give
157          * blocky artifacts and sometimes wrong colors.
158          */
159
160         scan_pattern = (vft->scan) ? alternate_scan : zig_zag_scan;
161         if( (vft->load_intra_quantizer_matrix = decoder->load_intra_quantizer_matrix) )
162         {
163             for (i=0; i<64; ++i)
164             {
165                 vft->intra_quantizer_matrix[scan_pattern[i]] =
166                 mpeg2dec->quantizer_matrix[0][decoder->scan[i]];
167             }
168         }
169
170         if( (vft->load_non_intra_quantizer_matrix = decoder->load_non_intra_quantizer_matrix) )
171         {
172             for (i=0; i<64; ++i)
173             {
174                 vft->non_intra_quantizer_matrix[scan_pattern[i]] =
175                                         mpeg2dec->quantizer_matrix[1][decoder->scan[i]];
176             }
177         }
178         decoder->load_intra_quantizer_matrix = 0;
179         decoder->load_non_intra_quantizer_matrix = 0;
180
181         vft->forward_reference_picture = (picture_t *)mpeg2dec->ptr_forward_ref_picture;
182         vft->backward_reference_picture = (picture_t *)mpeg2dec->ptr_backward_ref_picture;
183
184 #if 0
185     printf("\nSLICE DATA !!!! size=%d", size-4);
186     int i=0;
187     if ( vft->forward_reference_picture != NULL && ((vlc_xxmc_t *)
188          vft->forward_reference_picture->p_data)->slice_data_size > 10)
189     {
190         printf("\nFORWARD SLICE DATA !!!! size=%d\n", ((vlc_xxmc_t *)
191                vft->forward_reference_picture->p_data)->slice_data_size);
192         for (i=0;i<10;i++)
193         {
194             printf("%d ", *(((vlc_xxmc_t *) vft->forward_reference_picture->p_data)->slice_data+i));
195         }
196         printf("\nFORWARD SLICE DATA END!!!!\n");
197     }
198     if ( vft->backward_reference_picture != NULL && ((vlc_xxmc_t *)
199          vft->backward_reference_picture->p_data)->slice_data_size > 10)
200     {
201         printf("\nBACKWARD SLICE DATA !!!! size=%d\n", ((vlc_xxmc_t *)
202                vft->backward_reference_picture->p_data)->slice_data_size);
203         for (i=0;i<10;i++)
204         {
205             printf("%d ", *(((vlc_xxmc_t *) vft->backward_reference_picture->p_data)->slice_data+i));
206         }
207         printf("\nBACKWARD SLICE DATA END!!!!\n");
208     }
209 #endif
210
211         xxmc->proc_xxmc_begin( picture );
212         if (xxmc->result != 0)
213         {
214             /* "mpeg2_xxmc_slice begin failed" */
215             /* xmc->proc_xxmc_flushsync( picture ); */
216             xxmc->proc_xxmc_flush( picture );
217             mpeg2dec->xvmc_last_slice_code=-1;
218         }
219     }
220
221     if( ((code == mpeg2dec->xvmc_last_slice_code + 1 ||
222         code == mpeg2dec->xvmc_last_slice_code)) &&
223         code <= mpeg2dec->xxmc_mb_pic_height )
224     {
225         /*
226          * Send this slice to the output plugin. May stall for a long
227          * time in proc_slice;
228          */
229         //mpeg2_skip(mpeg2dec, 1);
230
231         //frame->bad_frame = 1;
232         //size = mpeg2dec->chunk_ptr-mpeg2dec->chunk_start;
233         xxmc->slice_data_size = size;//mpeg2dec->buf_end - mpeg2dec->buf_start;
234         xxmc->slice_data = mpeg2dec->chunk_start;//buffer;
235         xxmc->slice_code = code;
236         xxmc->proc_xxmc_slice( picture );
237
238         if (xxmc->result != 0)
239         {
240             //xxmc->proc_xxmc_flushsync( picture );
241             xxmc->proc_xxmc_flush( picture );   
242             mpeg2dec->xvmc_last_slice_code=-1;
243             return;
244         }
245         if (code == mpeg2dec->xxmc_mb_pic_height)
246         {
247             /*
248              * We've encountered the last slice of this frame.
249              * Release the decoder for a new frame and, if all
250              * went well, tell libmpeg2 that we are ready.
251              */
252
253             mpeg2_xxmc_vld_frame_complete(mpeg2dec,picture,code);
254             return;
255         }
256         else if (code == mpeg2dec->xvmc_last_slice_code + 1)
257         {
258             //xxmc->proc_xxmc_flush( picture );
259
260             /*
261              * Keep track of slices.
262              */
263             mpeg2dec->xvmc_last_slice_code++;
264         }
265     }
266     else
267     {
268         /*
269          * An error has occured.
270          */
271
272         //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);
273         mpeg2dec->xvmc_last_slice_code = -1;
274         xxmc->proc_xxmc_flush( picture );
275         return;
276     }
277 }
278
279 void mpeg2_xxmc_vld_frame_complete(mpeg2dec_t *mpeg2dec, picture_t *picture, int code) 
280 {
281     vlc_xxmc_t *xxmc = (vlc_xxmc_t *) picture->p_data;
282     vlc_vld_frame_t *vft = &xxmc->vld_frame;
283
284     if (xxmc->decoded)
285         return;
286
287     if (mpeg2dec->xvmc_last_slice_code >= 1)
288     {
289         xxmc->proc_xxmc_flush( picture );
290         if (xxmc->result)
291         {
292             mpeg2dec->xvmc_last_slice_code=-1;
293             return;
294         }
295         xxmc->decoded = 1;
296         mpeg2dec->xvmc_last_slice_code++;
297         if (vft->picture_structure == 3 || vft->second_field)
298         {
299             if (xxmc->result == 0)
300                 mpeg2_skip(mpeg2dec, 0);
301             //frame->bad_frame = 0;
302         }
303     }
304 }
305