1 /**************************************************************************
3 * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian.
4 * Copyright 2014 Advanced Micro Devices, Inc.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 **************************************************************************/
29 #include "pipe/p_video_codec.h"
31 #include "util/u_handle_table.h"
32 #include "util/u_video.h"
34 #include "vl/vl_vlc.h"
35 #include "vl/vl_winsys.h"
37 #include "va_private.h"
40 vlVaBeginPicture(VADriverContextP ctx
, VAContextID context_id
, VASurfaceID render_target
)
47 return VA_STATUS_ERROR_INVALID_CONTEXT
;
49 drv
= VL_VA_DRIVER(ctx
);
51 return VA_STATUS_ERROR_INVALID_CONTEXT
;
53 context
= handle_table_get(drv
->htab
, context_id
);
55 return VA_STATUS_ERROR_INVALID_CONTEXT
;
57 surf
= handle_table_get(drv
->htab
, render_target
);
58 if (!surf
|| !surf
->buffer
)
59 return VA_STATUS_ERROR_INVALID_SURFACE
;
61 context
->target
= surf
->buffer
;
62 if (!context
->decoder
) {
64 if ((context
->target
->buffer_format
!= PIPE_FORMAT_B8G8R8A8_UNORM
&&
65 context
->target
->buffer_format
!= PIPE_FORMAT_R8G8B8A8_UNORM
&&
66 context
->target
->buffer_format
!= PIPE_FORMAT_B8G8R8X8_UNORM
&&
67 context
->target
->buffer_format
!= PIPE_FORMAT_R8G8B8X8_UNORM
) ||
68 context
->target
->interlaced
)
69 return VA_STATUS_ERROR_UNIMPLEMENTED
;
70 return VA_STATUS_SUCCESS
;
73 context
->decoder
->begin_frame(context
->decoder
, context
->target
, &context
->desc
.base
);
75 return VA_STATUS_SUCCESS
;
79 vlVaGetReferenceFrame(vlVaDriver
*drv
, VASurfaceID surface_id
,
80 struct pipe_video_buffer
**ref_frame
)
82 vlVaSurface
*surf
= handle_table_get(drv
->htab
, surface_id
);
84 *ref_frame
= surf
->buffer
;
90 handlePictureParameterBuffer(vlVaDriver
*drv
, vlVaContext
*context
, vlVaBuffer
*buf
)
92 VAPictureParameterBufferHEVC
*hevc
;
95 switch (u_reduce_video_profile(context
->decoder
->profile
)) {
96 case PIPE_VIDEO_FORMAT_MPEG12
:
97 vlVaHandlePictureParameterBufferMPEG12(drv
, context
, buf
);
100 case PIPE_VIDEO_FORMAT_MPEG4_AVC
:
101 vlVaHandlePictureParameterBufferH264(drv
, context
, buf
);
104 case PIPE_VIDEO_FORMAT_VC1
:
105 vlVaHandlePictureParameterBufferVC1(drv
, context
, buf
);
108 case PIPE_VIDEO_FORMAT_MPEG4
:
109 vlVaHandlePictureParameterBufferMPEG4(drv
, context
, buf
);
112 case PIPE_VIDEO_FORMAT_HEVC
:
113 assert(buf
->size
>= sizeof(VAPictureParameterBufferHEVC
) && buf
->num_elements
== 1);
115 context
->desc
.h265
.pps
->sps
->chroma_format_idc
= hevc
->pic_fields
.bits
.chroma_format_idc
;
116 context
->desc
.h265
.pps
->sps
->separate_colour_plane_flag
=
117 hevc
->pic_fields
.bits
.separate_colour_plane_flag
;
118 context
->desc
.h265
.pps
->sps
->pic_width_in_luma_samples
= hevc
->pic_width_in_luma_samples
;
119 context
->desc
.h265
.pps
->sps
->pic_height_in_luma_samples
= hevc
->pic_height_in_luma_samples
;
120 context
->desc
.h265
.pps
->sps
->bit_depth_luma_minus8
= hevc
->bit_depth_luma_minus8
;
121 context
->desc
.h265
.pps
->sps
->bit_depth_chroma_minus8
= hevc
->bit_depth_chroma_minus8
;
122 context
->desc
.h265
.pps
->sps
->log2_max_pic_order_cnt_lsb_minus4
=
123 hevc
->log2_max_pic_order_cnt_lsb_minus4
;
124 context
->desc
.h265
.pps
->sps
->sps_max_dec_pic_buffering_minus1
=
125 hevc
->sps_max_dec_pic_buffering_minus1
;
126 context
->desc
.h265
.pps
->sps
->log2_min_luma_coding_block_size_minus3
=
127 hevc
->log2_min_luma_coding_block_size_minus3
;
128 context
->desc
.h265
.pps
->sps
->log2_diff_max_min_luma_coding_block_size
=
129 hevc
->log2_diff_max_min_luma_coding_block_size
;
130 context
->desc
.h265
.pps
->sps
->log2_min_transform_block_size_minus2
=
131 hevc
->log2_min_transform_block_size_minus2
;
132 context
->desc
.h265
.pps
->sps
->log2_diff_max_min_transform_block_size
=
133 hevc
->log2_diff_max_min_transform_block_size
;
134 context
->desc
.h265
.pps
->sps
->max_transform_hierarchy_depth_inter
=
135 hevc
->max_transform_hierarchy_depth_inter
;
136 context
->desc
.h265
.pps
->sps
->max_transform_hierarchy_depth_intra
=
137 hevc
->max_transform_hierarchy_depth_intra
;
138 context
->desc
.h265
.pps
->sps
->scaling_list_enabled_flag
=
139 hevc
->pic_fields
.bits
.scaling_list_enabled_flag
;
140 context
->desc
.h265
.pps
->sps
->amp_enabled_flag
= hevc
->pic_fields
.bits
.amp_enabled_flag
;
141 context
->desc
.h265
.pps
->sps
->sample_adaptive_offset_enabled_flag
=
142 hevc
->slice_parsing_fields
.bits
.sample_adaptive_offset_enabled_flag
;
143 context
->desc
.h265
.pps
->sps
->pcm_enabled_flag
= hevc
->pic_fields
.bits
.pcm_enabled_flag
;
144 if (hevc
->pic_fields
.bits
.pcm_enabled_flag
== 1) {
145 context
->desc
.h265
.pps
->sps
->pcm_sample_bit_depth_luma_minus1
=
146 hevc
->pcm_sample_bit_depth_luma_minus1
;
147 context
->desc
.h265
.pps
->sps
->pcm_sample_bit_depth_chroma_minus1
=
148 hevc
->pcm_sample_bit_depth_chroma_minus1
;
149 context
->desc
.h265
.pps
->sps
->log2_min_pcm_luma_coding_block_size_minus3
=
150 hevc
->log2_min_pcm_luma_coding_block_size_minus3
;
151 context
->desc
.h265
.pps
->sps
->log2_diff_max_min_pcm_luma_coding_block_size
=
152 hevc
->log2_diff_max_min_pcm_luma_coding_block_size
;
153 context
->desc
.h265
.pps
->sps
->pcm_loop_filter_disabled_flag
=
154 hevc
->pic_fields
.bits
.pcm_loop_filter_disabled_flag
;
156 context
->desc
.h265
.pps
->sps
->num_short_term_ref_pic_sets
= hevc
->num_short_term_ref_pic_sets
;
157 context
->desc
.h265
.pps
->sps
->long_term_ref_pics_present_flag
=
158 hevc
->slice_parsing_fields
.bits
.long_term_ref_pics_present_flag
;
159 context
->desc
.h265
.pps
->sps
->num_long_term_ref_pics_sps
= hevc
->num_long_term_ref_pic_sps
;
160 context
->desc
.h265
.pps
->sps
->sps_temporal_mvp_enabled_flag
=
161 hevc
->slice_parsing_fields
.bits
.sps_temporal_mvp_enabled_flag
;
162 context
->desc
.h265
.pps
->sps
->strong_intra_smoothing_enabled_flag
=
163 hevc
->pic_fields
.bits
.strong_intra_smoothing_enabled_flag
;
165 context
->desc
.h265
.pps
->dependent_slice_segments_enabled_flag
=
166 hevc
->slice_parsing_fields
.bits
.dependent_slice_segments_enabled_flag
;
167 context
->desc
.h265
.pps
->output_flag_present_flag
=
168 hevc
->slice_parsing_fields
.bits
.output_flag_present_flag
;
169 context
->desc
.h265
.pps
->num_extra_slice_header_bits
= hevc
->num_extra_slice_header_bits
;
170 context
->desc
.h265
.pps
->sign_data_hiding_enabled_flag
=
171 hevc
->pic_fields
.bits
.sign_data_hiding_enabled_flag
;
172 context
->desc
.h265
.pps
->cabac_init_present_flag
=
173 hevc
->slice_parsing_fields
.bits
.cabac_init_present_flag
;
174 context
->desc
.h265
.pps
->num_ref_idx_l0_default_active_minus1
=
175 hevc
->num_ref_idx_l0_default_active_minus1
;
176 context
->desc
.h265
.pps
->num_ref_idx_l1_default_active_minus1
=
177 hevc
->num_ref_idx_l1_default_active_minus1
;
178 context
->desc
.h265
.pps
->init_qp_minus26
= hevc
->init_qp_minus26
;
179 context
->desc
.h265
.pps
->constrained_intra_pred_flag
=
180 hevc
->pic_fields
.bits
.constrained_intra_pred_flag
;
181 context
->desc
.h265
.pps
->transform_skip_enabled_flag
=
182 hevc
->pic_fields
.bits
.transform_skip_enabled_flag
;
183 context
->desc
.h265
.pps
->cu_qp_delta_enabled_flag
=
184 hevc
->pic_fields
.bits
.cu_qp_delta_enabled_flag
;
185 context
->desc
.h265
.pps
->diff_cu_qp_delta_depth
= hevc
->diff_cu_qp_delta_depth
;
186 context
->desc
.h265
.pps
->pps_cb_qp_offset
= hevc
->pps_cb_qp_offset
;
187 context
->desc
.h265
.pps
->pps_cr_qp_offset
= hevc
->pps_cr_qp_offset
;
188 context
->desc
.h265
.pps
->pps_slice_chroma_qp_offsets_present_flag
=
189 hevc
->slice_parsing_fields
.bits
.pps_slice_chroma_qp_offsets_present_flag
;
190 context
->desc
.h265
.pps
->weighted_pred_flag
= hevc
->pic_fields
.bits
.weighted_pred_flag
;
191 context
->desc
.h265
.pps
->weighted_bipred_flag
= hevc
->pic_fields
.bits
.weighted_bipred_flag
;
192 context
->desc
.h265
.pps
->transquant_bypass_enabled_flag
=
193 hevc
->pic_fields
.bits
.transquant_bypass_enabled_flag
;
194 context
->desc
.h265
.pps
->tiles_enabled_flag
= hevc
->pic_fields
.bits
.tiles_enabled_flag
;
195 context
->desc
.h265
.pps
->entropy_coding_sync_enabled_flag
=
196 hevc
->pic_fields
.bits
.entropy_coding_sync_enabled_flag
;
197 if (hevc
->pic_fields
.bits
.tiles_enabled_flag
== 1) {
198 context
->desc
.h265
.pps
->num_tile_columns_minus1
= hevc
->num_tile_columns_minus1
;
199 context
->desc
.h265
.pps
->num_tile_rows_minus1
= hevc
->num_tile_rows_minus1
;
200 for (i
= 0 ; i
< 19 ; i
++)
201 context
->desc
.h265
.pps
->column_width_minus1
[i
] = hevc
->column_width_minus1
[i
];
202 for (i
= 0 ; i
< 21 ; i
++)
203 context
->desc
.h265
.pps
->row_height_minus1
[i
] = hevc
->row_height_minus1
[i
];
204 context
->desc
.h265
.pps
->loop_filter_across_tiles_enabled_flag
=
205 hevc
->pic_fields
.bits
.loop_filter_across_tiles_enabled_flag
;
207 context
->desc
.h265
.pps
->pps_loop_filter_across_slices_enabled_flag
=
208 hevc
->pic_fields
.bits
.pps_loop_filter_across_slices_enabled_flag
;
209 context
->desc
.h265
.pps
->deblocking_filter_override_enabled_flag
=
210 hevc
->slice_parsing_fields
.bits
.deblocking_filter_override_enabled_flag
;
211 context
->desc
.h265
.pps
->pps_deblocking_filter_disabled_flag
=
212 hevc
->slice_parsing_fields
.bits
.pps_disable_deblocking_filter_flag
;
213 context
->desc
.h265
.pps
->pps_beta_offset_div2
= hevc
->pps_beta_offset_div2
;
214 context
->desc
.h265
.pps
->pps_tc_offset_div2
= hevc
->pps_tc_offset_div2
;
215 context
->desc
.h265
.pps
->lists_modification_present_flag
=
216 hevc
->slice_parsing_fields
.bits
.lists_modification_present_flag
;
217 context
->desc
.h265
.pps
->log2_parallel_merge_level_minus2
=
218 hevc
->log2_parallel_merge_level_minus2
;
219 context
->desc
.h265
.pps
->slice_segment_header_extension_present_flag
=
220 hevc
->slice_parsing_fields
.bits
.slice_segment_header_extension_present_flag
;
222 context
->desc
.h265
.IDRPicFlag
= hevc
->slice_parsing_fields
.bits
.IdrPicFlag
;
223 context
->desc
.h265
.RAPPicFlag
= hevc
->slice_parsing_fields
.bits
.RapPicFlag
;
225 context
->desc
.h265
.CurrPicOrderCntVal
= hevc
->CurrPic
.pic_order_cnt
;
227 for (i
= 0 ; i
< 8 ; i
++) {
228 context
->desc
.h265
.RefPicSetStCurrBefore
[i
] = 0xFF;
229 context
->desc
.h265
.RefPicSetStCurrAfter
[i
] = 0xFF;
230 context
->desc
.h265
.RefPicSetLtCurr
[i
] = 0xFF;
232 context
->desc
.h265
.NumPocStCurrBefore
= 0;
233 context
->desc
.h265
.NumPocStCurrAfter
= 0;
234 context
->desc
.h265
.NumPocLtCurr
= 0;
235 unsigned int iBefore
= 0;
236 unsigned int iAfter
= 0;
237 unsigned int iCurr
= 0;
238 for (i
= 0 ; i
< 15 ; i
++) {
239 context
->desc
.h265
.PicOrderCntVal
[i
] = hevc
->ReferenceFrames
[i
].pic_order_cnt
;
241 unsigned int index
= hevc
->ReferenceFrames
[i
].picture_id
& 0x7F;
246 vlVaGetReferenceFrame(drv
, hevc
->ReferenceFrames
[i
].picture_id
, &context
->desc
.h265
.ref
[i
]);
248 if ((hevc
->ReferenceFrames
[i
].flags
& VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE
) && (iBefore
< 8)) {
249 context
->desc
.h265
.RefPicSetStCurrBefore
[iBefore
++] = i
;
250 context
->desc
.h265
.NumPocStCurrBefore
++;
252 if ((hevc
->ReferenceFrames
[i
].flags
& VA_PICTURE_HEVC_RPS_ST_CURR_AFTER
) && (iAfter
< 8)) {
253 context
->desc
.h265
.RefPicSetStCurrAfter
[iAfter
++] = i
;
254 context
->desc
.h265
.NumPocStCurrAfter
++;
256 if ((hevc
->ReferenceFrames
[i
].flags
& VA_PICTURE_HEVC_RPS_LT_CURR
) && (iCurr
< 8)) {
257 context
->desc
.h265
.RefPicSetLtCurr
[iCurr
++] = i
;
258 context
->desc
.h265
.NumPocLtCurr
++;
269 handleIQMatrixBuffer(vlVaContext
*context
, vlVaBuffer
*buf
)
271 VAIQMatrixBufferHEVC
*h265
;
273 switch (u_reduce_video_profile(context
->decoder
->profile
)) {
274 case PIPE_VIDEO_FORMAT_MPEG12
:
275 vlVaHandleIQMatrixBufferMPEG12(context
, buf
);
278 case PIPE_VIDEO_FORMAT_MPEG4_AVC
:
279 vlVaHandleIQMatrixBufferH264(context
, buf
);
282 case PIPE_VIDEO_FORMAT_MPEG4
:
283 vlVaHandleIQMatrixBufferMPEG4(context
, buf
);
286 case PIPE_VIDEO_FORMAT_HEVC
:
287 assert(buf
->size
>= sizeof(VAIQMatrixBufferH264
) && buf
->num_elements
== 1);
289 memcpy(&context
->desc
.h265
.pps
->sps
->ScalingList4x4
, h265
->ScalingList4x4
, 6 * 16);
290 memcpy(&context
->desc
.h265
.pps
->sps
->ScalingList8x8
, h265
->ScalingList8x8
, 6 * 64);
291 memcpy(&context
->desc
.h265
.pps
->sps
->ScalingList16x16
, h265
->ScalingList16x16
, 6 * 64);
292 memcpy(&context
->desc
.h265
.pps
->sps
->ScalingList32x32
, h265
->ScalingList32x32
, 2 * 64);
293 memcpy(&context
->desc
.h265
.pps
->sps
->ScalingListDCCoeff16x16
, h265
->ScalingListDC16x16
, 6);
294 memcpy(&context
->desc
.h265
.pps
->sps
->ScalingListDCCoeff32x32
, h265
->ScalingListDC32x32
, 2);
303 handleSliceParameterBuffer(vlVaContext
*context
, vlVaBuffer
*buf
)
305 VASliceParameterBufferHEVC
*h265
;
307 switch (u_reduce_video_profile(context
->decoder
->profile
)) {
308 case PIPE_VIDEO_FORMAT_MPEG4_AVC
:
309 vlVaHandleSliceParameterBufferH264(context
, buf
);
312 case PIPE_VIDEO_FORMAT_MPEG4
:
313 vlVaHandleSliceParameterBufferMPEG4(context
, buf
);
316 case PIPE_VIDEO_FORMAT_HEVC
:
317 assert(buf
->size
>= sizeof(VASliceParameterBufferHEVC
) && buf
->num_elements
== 1);
319 for (int i
= 0 ; i
< 2 ; i
++) {
320 for (int j
= 0 ; j
< 15 ; j
++)
321 context
->desc
.h265
.RefPicList
[i
][j
] = h265
->RefPicList
[i
][j
];
323 context
->desc
.h265
.UseRefPicList
= true;
331 bufHasStartcode(vlVaBuffer
*buf
, unsigned int code
, unsigned int bits
)
333 struct vl_vlc vlc
= {0};
336 /* search the first 64 bytes for a startcode */
337 vl_vlc_init(&vlc
, 1, (const void * const*)&buf
->data
, &buf
->size
);
338 for (i
= 0; i
< 64 && vl_vlc_bits_left(&vlc
) >= bits
; ++i
) {
339 if (vl_vlc_peekbits(&vlc
, bits
) == code
)
341 vl_vlc_eatbits(&vlc
, 8);
342 vl_vlc_fillbits(&vlc
);
349 handleVASliceDataBufferType(vlVaContext
*context
, vlVaBuffer
*buf
)
351 enum pipe_video_format format
;
352 unsigned num_buffers
= 0;
353 void * const *buffers
[2];
355 static const uint8_t start_code_h264
[] = { 0x00, 0x00, 0x01 };
356 static const uint8_t start_code_h265
[] = { 0x00, 0x00, 0x01 };
357 static const uint8_t start_code_vc1
[] = { 0x00, 0x00, 0x01, 0x0d };
359 format
= u_reduce_video_profile(context
->decoder
->profile
);
361 case PIPE_VIDEO_FORMAT_MPEG4_AVC
:
362 if (bufHasStartcode(buf
, 0x000001, 24))
365 buffers
[num_buffers
] = (void *const)&start_code_h264
;
366 sizes
[num_buffers
++] = sizeof(start_code_h264
);
368 case PIPE_VIDEO_FORMAT_HEVC
:
369 if (bufHasStartcode(buf
, 0x000001, 24))
372 buffers
[num_buffers
] = (void *const)&start_code_h265
;
373 sizes
[num_buffers
++] = sizeof(start_code_h265
);
375 case PIPE_VIDEO_FORMAT_VC1
:
376 if (bufHasStartcode(buf
, 0x0000010d, 32) ||
377 bufHasStartcode(buf
, 0x0000010c, 32) ||
378 bufHasStartcode(buf
, 0x0000010b, 32))
381 if (context
->decoder
->profile
== PIPE_VIDEO_PROFILE_VC1_ADVANCED
) {
382 buffers
[num_buffers
] = (void *const)&start_code_vc1
;
383 sizes
[num_buffers
++] = sizeof(start_code_vc1
);
386 case PIPE_VIDEO_FORMAT_MPEG4
:
387 if (bufHasStartcode(buf
, 0x000001, 24))
390 vlVaDecoderFixMPEG4Startcode(context
);
391 buffers
[num_buffers
] = (void *)context
->mpeg4
.start_code
;
392 sizes
[num_buffers
++] = context
->mpeg4
.start_code_size
;
397 buffers
[num_buffers
] = buf
->data
;
398 sizes
[num_buffers
] = buf
->size
;
400 context
->decoder
->decode_bitstream(context
->decoder
, context
->target
, &context
->desc
.base
,
401 num_buffers
, (const void * const*)buffers
, sizes
);
405 vlVaRenderPicture(VADriverContextP ctx
, VAContextID context_id
, VABufferID
*buffers
, int num_buffers
)
408 vlVaContext
*context
;
409 VAStatus vaStatus
= VA_STATUS_SUCCESS
;
414 return VA_STATUS_ERROR_INVALID_CONTEXT
;
416 drv
= VL_VA_DRIVER(ctx
);
418 return VA_STATUS_ERROR_INVALID_CONTEXT
;
420 context
= handle_table_get(drv
->htab
, context_id
);
422 return VA_STATUS_ERROR_INVALID_CONTEXT
;
424 for (i
= 0; i
< num_buffers
; ++i
) {
425 vlVaBuffer
*buf
= handle_table_get(drv
->htab
, buffers
[i
]);
427 return VA_STATUS_ERROR_INVALID_BUFFER
;
430 case VAPictureParameterBufferType
:
431 handlePictureParameterBuffer(drv
, context
, buf
);
434 case VAIQMatrixBufferType
:
435 handleIQMatrixBuffer(context
, buf
);
438 case VASliceParameterBufferType
:
439 handleSliceParameterBuffer(context
, buf
);
442 case VASliceDataBufferType
:
443 handleVASliceDataBufferType(context
, buf
);
445 case VAProcPipelineParameterBufferType
:
446 vaStatus
= vlVaHandleVAProcPipelineParameterBufferType(drv
, context
, buf
);
458 vlVaEndPicture(VADriverContextP ctx
, VAContextID context_id
)
461 vlVaContext
*context
;
464 return VA_STATUS_ERROR_INVALID_CONTEXT
;
466 drv
= VL_VA_DRIVER(ctx
);
468 return VA_STATUS_ERROR_INVALID_CONTEXT
;
470 context
= handle_table_get(drv
->htab
, context_id
);
472 return VA_STATUS_ERROR_INVALID_CONTEXT
;
474 if (!context
->decoder
) {
476 return VA_STATUS_SUCCESS
;
479 context
->mpeg4
.frame_num
++;
480 context
->decoder
->end_frame(context
->decoder
, context
->target
, &context
->desc
.base
);
482 return VA_STATUS_SUCCESS
;