fate: add more tests for hue video filter
[ffmpeg.git] / libavcodec / vaapi_vc1.c
1 /*
2  * VC-1 HW decode acceleration through VA API
3  *
4  * Copyright (C) 2008-2009 Splitted-Desktop Systems
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 #include "hwaccel.h"
24 #include "internal.h"
25 #include "vaapi_decode.h"
26 #include "vc1.h"
27 #include "vc1data.h"
28
29 /** Translate FFmpeg MV modes to VA API */
30 static int get_VAMvModeVC1(enum MVModes mv_mode)
31 {
32     switch (mv_mode) {
33     case MV_PMODE_1MV_HPEL_BILIN: return VAMvMode1MvHalfPelBilinear;
34     case MV_PMODE_1MV:            return VAMvMode1Mv;
35     case MV_PMODE_1MV_HPEL:       return VAMvMode1MvHalfPel;
36     case MV_PMODE_MIXED_MV:       return VAMvModeMixedMv;
37     case MV_PMODE_INTENSITY_COMP: return VAMvModeIntensityCompensation;
38     }
39     return 0;
40 }
41
42 /** Check whether the MVTYPEMB bitplane is present */
43 static inline int vc1_has_MVTYPEMB_bitplane(const VC1Context *v)
44 {
45     if (v->mv_type_is_raw)
46         return 0;
47     return v->fcm == PROGRESSIVE &&
48            (v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) &&
49            (v->mv_mode == MV_PMODE_MIXED_MV ||
50             (v->mv_mode == MV_PMODE_INTENSITY_COMP &&
51              v->mv_mode2 == MV_PMODE_MIXED_MV));
52 }
53
54 /** Check whether the SKIPMB bitplane is present */
55 static inline int vc1_has_SKIPMB_bitplane(const VC1Context *v)
56 {
57     if (v->skip_is_raw)
58         return 0;
59     return (v->fcm == PROGRESSIVE || v->fcm == ILACE_FRAME) &&
60            ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) ||
61             (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type));
62 }
63
64 /** Check whether the DIRECTMB bitplane is present */
65 static inline int vc1_has_DIRECTMB_bitplane(const VC1Context *v)
66 {
67     if (v->dmb_is_raw)
68         return 0;
69     return (v->fcm == PROGRESSIVE || v->fcm == ILACE_FRAME) &&
70            (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type);
71 }
72
73 /** Check whether the ACPRED bitplane is present */
74 static inline int vc1_has_ACPRED_bitplane(const VC1Context *v)
75 {
76     if (v->acpred_is_raw)
77         return 0;
78     return v->profile == PROFILE_ADVANCED &&
79            (v->s.pict_type == AV_PICTURE_TYPE_I ||
80             (v->s.pict_type == AV_PICTURE_TYPE_B && v->bi_type));
81 }
82
83 /** Check whether the OVERFLAGS bitplane is present */
84 static inline int vc1_has_OVERFLAGS_bitplane(const VC1Context *v)
85 {
86     if (v->overflg_is_raw)
87         return 0;
88     return v->profile == PROFILE_ADVANCED &&
89            (v->s.pict_type == AV_PICTURE_TYPE_I ||
90             (v->s.pict_type == AV_PICTURE_TYPE_B && v->bi_type)) &&
91            (v->overlap && v->pq <= 8) &&
92            v->condover == CONDOVER_SELECT;
93 }
94
95 /** Check whether the FIELDTX bitplane is present */
96 static inline int vc1_has_FIELDTX_bitplane(const VC1Context *v)
97 {
98     if (v->fieldtx_is_raw)
99         return 0;
100     return v->fcm == ILACE_FRAME &&
101            (v->s.pict_type == AV_PICTURE_TYPE_I ||
102             (v->s.pict_type == AV_PICTURE_TYPE_B && v->bi_type));
103 }
104
105 /** Check whether the FORWARDMB bitplane is present */
106 static inline int vc1_has_FORWARDMB_bitplane(const VC1Context *v)
107 {
108     if (v->fmb_is_raw)
109         return 0;
110     return v->fcm == ILACE_FIELD &&
111            (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type);
112 }
113
114 /** Reconstruct bitstream PTYPE (7.1.1.4, index into Table-35) */
115 static int vc1_get_PTYPE(const VC1Context *v)
116 {
117     const MpegEncContext *s = &v->s;
118     switch (s->pict_type) {
119     case AV_PICTURE_TYPE_I: return 0;
120     case AV_PICTURE_TYPE_P: return v->p_frame_skipped ? 4 : 1;
121     case AV_PICTURE_TYPE_B: return v->bi_type         ? 3 : 2;
122     }
123     return 0;
124 }
125
126 /** Reconstruct bitstream FPTYPE (9.1.1.42, index into Table-105) */
127 static int vc1_get_FPTYPE(const VC1Context *v)
128 {
129     const MpegEncContext *s = &v->s;
130     switch (s->pict_type) {
131     case AV_PICTURE_TYPE_I: return 0;
132     case AV_PICTURE_TYPE_P: return 3;
133     case AV_PICTURE_TYPE_B: return v->bi_type ? 7 : 4;
134     }
135     return 0;
136 }
137
138 /** Reconstruct bitstream MVMODE (7.1.1.32) */
139 static inline VAMvModeVC1 vc1_get_MVMODE(const VC1Context *v)
140 {
141     if ((v->fcm == PROGRESSIVE || v->fcm == ILACE_FIELD) &&
142         ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) ||
143          (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type)))
144         return get_VAMvModeVC1(v->mv_mode);
145     return 0;
146 }
147
148 /** Reconstruct bitstream MVMODE2 (7.1.1.33) */
149 static inline VAMvModeVC1 vc1_get_MVMODE2(const VC1Context *v)
150 {
151     if ((v->fcm == PROGRESSIVE || v->fcm == ILACE_FIELD) &&
152         (v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) &&
153         v->mv_mode == MV_PMODE_INTENSITY_COMP)
154         return get_VAMvModeVC1(v->mv_mode2);
155     return 0;
156 }
157
158 av_unused static inline int vc1_get_INTCOMPFIELD(const VC1Context *v)
159 {
160     if ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) &&
161         v->fcm == ILACE_FIELD &&
162         v->mv_mode == MV_PMODE_INTENSITY_COMP)
163         switch (v->intcompfield) {
164         case 1: return 1;
165         case 2: return 2;
166         case 3: return 0;
167         }
168     return 0;
169 }
170
171 static inline int vc1_get_LUMSCALE(const VC1Context *v)
172 {
173     if (v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) {
174         if ((v->fcm == PROGRESSIVE && v->mv_mode == MV_PMODE_INTENSITY_COMP) ||
175             (v->fcm == ILACE_FRAME && v->intcomp))
176             return v->lumscale;
177         else if (v->fcm == ILACE_FIELD && v->mv_mode == MV_PMODE_INTENSITY_COMP)
178             switch (v->intcompfield) {
179             case 1: return v->lumscale;
180             case 2: return v->lumscale2;
181             case 3: return v->lumscale;
182         }
183     }
184     return 0;
185 }
186
187 static inline int vc1_get_LUMSHIFT(const VC1Context *v)
188 {
189     if (v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) {
190         if ((v->fcm == PROGRESSIVE && v->mv_mode == MV_PMODE_INTENSITY_COMP) ||
191             (v->fcm == ILACE_FRAME && v->intcomp))
192             return v->lumshift;
193         else if (v->fcm == ILACE_FIELD && v->mv_mode == MV_PMODE_INTENSITY_COMP)
194             switch (v->intcompfield) {
195             case 1: return v->lumshift;
196             case 2: return v->lumshift2;
197             case 3: return v->lumshift;
198         }
199     }
200     return 0;
201 }
202
203 av_unused static inline int vc1_get_LUMSCALE2(const VC1Context *v)
204 {
205     if ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) &&
206         v->fcm == ILACE_FIELD &&
207         v->mv_mode == MV_PMODE_INTENSITY_COMP &&
208         v->intcompfield == 3)
209         return v->lumscale2;
210     return 0;
211 }
212
213 av_unused static inline int vc1_get_LUMSHIFT2(const VC1Context *v)
214 {
215     if ((v->s.pict_type == AV_PICTURE_TYPE_P && !v->p_frame_skipped) &&
216         v->fcm == ILACE_FIELD &&
217         v->mv_mode == MV_PMODE_INTENSITY_COMP &&
218         v->intcompfield == 3)
219         return v->lumshift2;
220     return 0;
221 }
222
223 /** Reconstruct bitstream TTFRM (7.1.1.41, Table-53) */
224 static inline int vc1_get_TTFRM(const VC1Context *v)
225 {
226     switch (v->ttfrm) {
227     case TT_8X8: return 0;
228     case TT_8X4: return 1;
229     case TT_4X8: return 2;
230     case TT_4X4: return 3;
231     }
232     return 0;
233 }
234
235 /** Pack FFmpeg bitplanes into a VABitPlaneBuffer element */
236 static inline void vc1_pack_bitplanes(uint8_t *bitplane, int n, const uint8_t *ff_bp[3], int x, int y, int stride)
237 {
238     const int bitplane_index = n / 2;
239     const int ff_bp_index = y * stride + x;
240     uint8_t v = 0;
241     if (ff_bp[0])
242         v = ff_bp[0][ff_bp_index];
243     if (ff_bp[1])
244         v |= ff_bp[1][ff_bp_index] << 1;
245     if (ff_bp[2])
246         v |= ff_bp[2][ff_bp_index] << 2;
247     bitplane[bitplane_index] = (bitplane[bitplane_index] << 4) | v;
248 }
249
250 static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size)
251 {
252     const VC1Context *v = avctx->priv_data;
253     const MpegEncContext *s = &v->s;
254     VAAPIDecodePicture *pic = s->current_picture_ptr->hwaccel_picture_private;
255     VAPictureParameterBufferVC1 pic_param;
256     int err;
257
258     pic->output_surface = ff_vaapi_get_surface_id(s->current_picture_ptr->f);
259
260     pic_param = (VAPictureParameterBufferVC1) {
261         .forward_reference_picture         = VA_INVALID_ID,
262         .backward_reference_picture        = VA_INVALID_ID,
263         .inloop_decoded_picture            = VA_INVALID_ID,
264         .sequence_fields.bits = {
265             .pulldown                      = v->broadcast,
266             .interlace                     = v->interlace,
267             .tfcntrflag                    = v->tfcntrflag,
268             .finterpflag                   = v->finterpflag,
269             .psf                           = v->psf,
270             .multires                      = v->multires,
271             .overlap                       = v->overlap,
272             .syncmarker                    = v->resync_marker,
273             .rangered                      = v->rangered,
274             .max_b_frames                  = s->avctx->max_b_frames,
275             .profile                       = v->profile,
276         },
277         .coded_width                       = s->avctx->coded_width,
278         .coded_height                      = s->avctx->coded_height,
279         .entrypoint_fields.bits = {
280             .broken_link                   = v->broken_link,
281             .closed_entry                  = v->closed_entry,
282             .panscan_flag                  = v->panscanflag,
283             .loopfilter                    = s->loop_filter,
284         },
285         .conditional_overlap_flag          = v->condover,
286         .fast_uvmc_flag                    = v->fastuvmc,
287         .range_mapping_fields.bits = {
288             .luma_flag                     = v->range_mapy_flag,
289             .luma                          = v->range_mapy,
290             .chroma_flag                   = v->range_mapuv_flag,
291             .chroma                        = v->range_mapuv,
292         },
293         .b_picture_fraction                = v->bfraction_lut_index,
294         .cbp_table                         = (v->fcm == PROGRESSIVE ? v->cbptab : v->icbptab),
295         .mb_mode_table                     = v->mbmodetab,
296         .range_reduction_frame             = v->rangeredfrm,
297         .rounding_control                  = v->rnd,
298         .post_processing                   = v->postproc,
299         .picture_resolution_index          = v->respic,
300         .picture_fields.bits = {
301             .picture_type                  = (v->fcm == ILACE_FIELD ? vc1_get_FPTYPE(v) : vc1_get_PTYPE(v)),
302             .frame_coding_mode             = v->fcm,
303             .top_field_first               = v->tff,
304             .is_first_field                = !v->second_field,
305             .intensity_compensation        = v->intcomp,
306         },
307         .luma_scale                        = vc1_get_LUMSCALE(v),
308         .luma_shift                        = vc1_get_LUMSHIFT(v),
309 #if VA_CHECK_VERSION(1, 1, 0)
310         .luma_scale2                       = vc1_get_LUMSCALE2(v),
311         .luma_shift2                       = vc1_get_LUMSHIFT2(v),
312         .intensity_compensation_field      = vc1_get_INTCOMPFIELD(v),
313 #endif
314         .raw_coding.flags = {
315             .mv_type_mb                    = v->mv_type_is_raw,
316             .direct_mb                     = v->dmb_is_raw,
317             .skip_mb                       = v->skip_is_raw,
318             .field_tx                      = v->fieldtx_is_raw,
319             .forward_mb                    = v->fmb_is_raw,
320             .ac_pred                       = v->acpred_is_raw,
321             .overflags                     = v->overflg_is_raw,
322         },
323         .bitplane_present.flags = {
324             .bp_mv_type_mb                 = vc1_has_MVTYPEMB_bitplane(v),
325             .bp_direct_mb                  = vc1_has_DIRECTMB_bitplane(v),
326             .bp_skip_mb                    = vc1_has_SKIPMB_bitplane(v),
327             .bp_field_tx                   = vc1_has_FIELDTX_bitplane(v),
328             .bp_forward_mb                 = vc1_has_FORWARDMB_bitplane(v),
329             .bp_ac_pred                    = vc1_has_ACPRED_bitplane(v),
330             .bp_overflags                  = vc1_has_OVERFLAGS_bitplane(v),
331         },
332         .reference_fields.bits = {
333             .reference_distance_flag       = v->refdist_flag,
334             .reference_distance            = v->refdist,
335             .num_reference_pictures        = v->numref,
336             .reference_field_pic_indicator = v->reffield,
337         },
338         .mv_fields.bits = {
339             .mv_mode                       = vc1_get_MVMODE(v),
340             .mv_mode2                      = vc1_get_MVMODE2(v),
341             .mv_table                      = (v->fcm == PROGRESSIVE ? s->mv_table_index : v->imvtab),
342             .two_mv_block_pattern_table    = v->twomvbptab,
343             .four_mv_switch                = v->fourmvswitch,
344             .four_mv_block_pattern_table   = v->fourmvbptab,
345             .extended_mv_flag              = v->extended_mv,
346             .extended_mv_range             = v->mvrange,
347             .extended_dmv_flag             = v->extended_dmv,
348             .extended_dmv_range            = v->dmvrange,
349         },
350         .pic_quantizer_fields.bits = {
351             .dquant                        = v->dquant,
352             .quantizer                     = v->quantizer_mode,
353             .half_qp                       = v->halfpq,
354             .pic_quantizer_scale           = v->pq,
355             .pic_quantizer_type            = v->pquantizer,
356             .dq_frame                      = v->dquantfrm,
357             .dq_profile                    = v->dqprofile,
358             .dq_sb_edge                    = v->dqprofile == DQPROFILE_SINGLE_EDGE  ? v->dqsbedge : 0,
359             .dq_db_edge                    = v->dqprofile == DQPROFILE_DOUBLE_EDGES ? v->dqsbedge : 0,
360             .dq_binary_level               = v->dqbilevel,
361             .alt_pic_quantizer             = v->altpq,
362         },
363         .transform_fields.bits = {
364             .variable_sized_transform_flag = v->vstransform,
365             .mb_level_transform_type_flag  = v->ttmbf,
366             .frame_level_transform_type    = vc1_get_TTFRM(v),
367             .transform_ac_codingset_idx1   = v->c_ac_table_index,
368             .transform_ac_codingset_idx2   = v->y_ac_table_index,
369             .intra_transform_dc_table      = v->s.dc_table_index,
370         },
371     };
372
373     switch (s->pict_type) {
374     case AV_PICTURE_TYPE_B:
375         pic_param.backward_reference_picture = ff_vaapi_get_surface_id(s->next_picture.f);
376         // fall-through
377     case AV_PICTURE_TYPE_P:
378         pic_param.forward_reference_picture = ff_vaapi_get_surface_id(s->last_picture.f);
379         break;
380     }
381
382     err = ff_vaapi_decode_make_param_buffer(avctx, pic,
383                                             VAPictureParameterBufferType,
384                                             &pic_param, sizeof(pic_param));
385     if (err)
386         goto fail;
387
388     if (pic_param.bitplane_present.value & 0x7f) {
389         uint8_t *bitplane;
390         const uint8_t *ff_bp[3];
391         int x, y, n;
392         size_t size = (s->mb_width * s->mb_height + 1) / 2;
393
394         bitplane = av_mallocz(size);
395         if (!bitplane) {
396             err = AVERROR(ENOMEM);
397             goto fail;
398         }
399
400         switch (s->pict_type) {
401         case AV_PICTURE_TYPE_P:
402             ff_bp[0] = pic_param.bitplane_present.flags.bp_direct_mb  ? v->direct_mb_plane    : NULL;
403             ff_bp[1] = pic_param.bitplane_present.flags.bp_skip_mb    ? s->mbskip_table       : NULL;
404             ff_bp[2] = pic_param.bitplane_present.flags.bp_mv_type_mb ? v->mv_type_mb_plane   : NULL;
405             break;
406         case AV_PICTURE_TYPE_B:
407             if (!v->bi_type) {
408                 ff_bp[0] = pic_param.bitplane_present.flags.bp_direct_mb  ? v->direct_mb_plane  : NULL;
409                 ff_bp[1] = pic_param.bitplane_present.flags.bp_skip_mb    ? s->mbskip_table     : NULL;
410                 ff_bp[2] = pic_param.bitplane_present.flags.bp_forward_mb ? v->forward_mb_plane : NULL;
411                 break;
412             }
413             /* fall-through (BI-type) */
414         case AV_PICTURE_TYPE_I:
415             ff_bp[0] = pic_param.bitplane_present.flags.bp_field_tx   ? v->fieldtx_plane      : NULL;
416             ff_bp[1] = pic_param.bitplane_present.flags.bp_ac_pred    ? v->acpred_plane       : NULL;
417             ff_bp[2] = pic_param.bitplane_present.flags.bp_overflags  ? v->over_flags_plane   : NULL;
418             break;
419         default:
420             ff_bp[0] = NULL;
421             ff_bp[1] = NULL;
422             ff_bp[2] = NULL;
423             break;
424         }
425
426         n = 0;
427         for (y = 0; y < s->mb_height; y++)
428             for (x = 0; x < s->mb_width; x++, n++)
429                 vc1_pack_bitplanes(bitplane, n, ff_bp, x, y, s->mb_stride);
430         if (n & 1) /* move last nibble to the high order */
431             bitplane[n/2] <<= 4;
432
433         err = ff_vaapi_decode_make_param_buffer(avctx, pic,
434                                                 VABitPlaneBufferType,
435                                                 bitplane, size);
436         av_free(bitplane);
437         if (err)
438             goto fail;
439     }
440     return 0;
441
442 fail:
443     ff_vaapi_decode_cancel(avctx, pic);
444     return err;
445 }
446
447 static int vaapi_vc1_end_frame(AVCodecContext *avctx)
448 {
449     VC1Context *v = avctx->priv_data;
450     MpegEncContext *s = &v->s;
451     VAAPIDecodePicture *pic = s->current_picture_ptr->hwaccel_picture_private;
452     int ret;
453
454     ret = ff_vaapi_decode_issue(avctx, pic);
455     if (ret < 0)
456         goto fail;
457
458     ff_mpeg_draw_horiz_band(s, 0, s->avctx->height);
459
460 fail:
461     return ret;
462 }
463
464 static int vaapi_vc1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size)
465 {
466     const VC1Context *v = avctx->priv_data;
467     const MpegEncContext *s = &v->s;
468     VAAPIDecodePicture *pic = s->current_picture_ptr->hwaccel_picture_private;
469     VASliceParameterBufferVC1 slice_param;
470     int err;
471
472     /* Current bit buffer is beyond any marker for VC-1, so skip it */
473     if (avctx->codec_id == AV_CODEC_ID_VC1 && IS_MARKER(AV_RB32(buffer))) {
474         buffer += 4;
475         size -= 4;
476     }
477
478     slice_param = (VASliceParameterBufferVC1) {
479         .slice_data_size         = size,
480         .slice_data_offset       = 0,
481         .slice_data_flag         = VA_SLICE_DATA_FLAG_ALL,
482         .macroblock_offset       = get_bits_count(&s->gb),
483         .slice_vertical_position = s->mb_y,
484     };
485
486     err = ff_vaapi_decode_make_slice_buffer(avctx, pic,
487                                             &slice_param, sizeof(slice_param),
488                                             buffer, size);
489     if (err < 0) {
490         ff_vaapi_decode_cancel(avctx, pic);
491         return err;
492     }
493
494     return 0;
495 }
496
497 #if CONFIG_WMV3_VAAPI_HWACCEL
498 const AVHWAccel ff_wmv3_vaapi_hwaccel = {
499     .name                 = "wmv3_vaapi",
500     .type                 = AVMEDIA_TYPE_VIDEO,
501     .id                   = AV_CODEC_ID_WMV3,
502     .pix_fmt              = AV_PIX_FMT_VAAPI,
503     .start_frame          = &vaapi_vc1_start_frame,
504     .end_frame            = &vaapi_vc1_end_frame,
505     .decode_slice         = &vaapi_vc1_decode_slice,
506     .frame_priv_data_size = sizeof(VAAPIDecodePicture),
507     .init                 = &ff_vaapi_decode_init,
508     .uninit               = &ff_vaapi_decode_uninit,
509     .frame_params         = &ff_vaapi_common_frame_params,
510     .priv_data_size       = sizeof(VAAPIDecodeContext),
511     .caps_internal        = HWACCEL_CAP_ASYNC_SAFE,
512 };
513 #endif
514
515 const AVHWAccel ff_vc1_vaapi_hwaccel = {
516     .name                 = "vc1_vaapi",
517     .type                 = AVMEDIA_TYPE_VIDEO,
518     .id                   = AV_CODEC_ID_VC1,
519     .pix_fmt              = AV_PIX_FMT_VAAPI,
520     .start_frame          = &vaapi_vc1_start_frame,
521     .end_frame            = &vaapi_vc1_end_frame,
522     .decode_slice         = &vaapi_vc1_decode_slice,
523     .frame_priv_data_size = sizeof(VAAPIDecodePicture),
524     .init                 = &ff_vaapi_decode_init,
525     .uninit               = &ff_vaapi_decode_uninit,
526     .frame_params         = &ff_vaapi_common_frame_params,
527     .priv_data_size       = sizeof(VAAPIDecodeContext),
528     .caps_internal        = HWACCEL_CAP_ASYNC_SAFE,
529 };