1 /*
2  * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3  * Copyright (c) Imagination Technologies Limited, UK
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sub license, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial portions
15  * of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
21  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 /*
27  * Authors:
28  *    Li Zeng <li.zeng@intel.com>
29  */
30 
31 #include "tng_vld_dec.h"
32 #include "psb_drv_debug.h"
33 #include "hwdefs/dxva_fw_ctrl.h"
34 #include "hwdefs/reg_io2.h"
35 #include "hwdefs/msvdx_offsets.h"
36 #include "hwdefs/msvdx_cmds_io2.h"
37 
38 #include <malloc.h>
39 
40 #define SURFACE(id)   ((object_surface_p) object_heap_lookup( &dec_ctx->obj_context->driver_data->surface_heap, id ))
41 
tng_yuv_processor_QueryConfigAttributes(VAProfile __maybe_unused rofile,VAEntrypoint __maybe_unused entrypoint,VAConfigAttrib __maybe_unused * attrib_list,int __maybe_unused num_attribs)42 static void tng_yuv_processor_QueryConfigAttributes(
43     VAProfile __maybe_unused rofile,
44     VAEntrypoint __maybe_unused entrypoint,
45     VAConfigAttrib __maybe_unused * attrib_list,
46     int __maybe_unused num_attribs)
47 {
48     /* No specific attributes */
49 }
50 
tng_yuv_processor_ValidateConfig(object_config_p __maybe_unused obj_config)51 static VAStatus tng_yuv_processor_ValidateConfig(
52     object_config_p __maybe_unused obj_config)
53 {
54     return VA_STATUS_SUCCESS;
55 }
56 
57 static VAStatus tng_yuv_processor_process_buffer( context_DEC_p, object_buffer_p);
58 
tng_yuv_processor_CreateContext(object_context_p obj_context,object_config_p __maybe_unused obj_config)59 static VAStatus tng_yuv_processor_CreateContext(
60     object_context_p obj_context,
61     object_config_p __maybe_unused obj_config)
62 {
63     VAStatus vaStatus = VA_STATUS_SUCCESS;
64     context_DEC_p dec_ctx = (context_DEC_p) obj_context->format_data;
65     context_yuv_processor_p ctx;
66 
67     ctx = (context_yuv_processor_p) malloc(sizeof(struct context_yuv_processor_s));
68     CHECK_ALLOCATION(ctx);
69 
70     /* ctx could be create in/out another dec context */
71     ctx->has_dec_ctx = 0;
72     ctx->src_surface = NULL;
73 
74     if (!dec_ctx) {
75         dec_ctx = (context_DEC_p) malloc(sizeof(struct context_DEC_s));
76         if(dec_ctx == NULL) {
77             free(ctx);
78             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
79             drv_debug_msg(VIDEO_DEBUG_ERROR, "%s fails with '%d' at %s:%d\n", __FUNCTION__, vaStatus, __FILE__, __LINE__);
80             return vaStatus;
81         }
82         obj_context->format_data = (void *)dec_ctx;
83         ctx->has_dec_ctx = 1;
84         vaStatus = vld_dec_CreateContext(dec_ctx, obj_context);
85         DEBUG_FAILURE;
86     }
87 
88     dec_ctx->yuv_ctx = ctx;
89     dec_ctx->process_buffer = tng_yuv_processor_process_buffer;
90 
91     return vaStatus;
92 }
93 
tng_yuv_processor_DestroyContext(object_context_p obj_context)94 static void tng_yuv_processor_DestroyContext(
95     object_context_p obj_context)
96 {
97     context_DEC_p dec_ctx = (context_DEC_p) obj_context->format_data;
98     context_yuv_processor_p yuv_ctx = NULL;
99     int has_dec_ctx = 0;
100 
101     if (dec_ctx == NULL)
102         return;
103 
104     yuv_ctx = dec_ctx->yuv_ctx;
105 
106     if (yuv_ctx) {
107         has_dec_ctx = yuv_ctx->has_dec_ctx;
108         free(yuv_ctx);
109         dec_ctx->yuv_ctx = NULL;
110     }
111 
112     if (has_dec_ctx) {
113         free(dec_ctx);
114         obj_context->format_data = NULL;
115     }
116 }
117 
tng_yuv_processor_BeginPicture(object_context_p __maybe_unused obj_context)118 static VAStatus tng_yuv_processor_BeginPicture(
119     object_context_p __maybe_unused obj_context)
120 {
121     return VA_STATUS_SUCCESS;
122 }
123 
tng__yuv_processor_process(context_DEC_p dec_ctx)124 static void tng__yuv_processor_process(context_DEC_p dec_ctx)
125 {
126     context_yuv_processor_p ctx = dec_ctx->yuv_ctx;
127     psb_cmdbuf_p cmdbuf = dec_ctx->obj_context->cmdbuf;
128     /* psb_surface_p target_surface = dec_ctx->obj_context->current_render_target->psb_surface; */
129     psb_surface_p src_surface = ctx->src_surface;
130     psb_buffer_p buffer;
131     uint32_t reg_value;
132 
133     psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, DISPLAY_PICTURE_SIZE));
134 
135     reg_value = 0;
136     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_HEIGHT, (ctx->display_height) - 1);
137     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_WIDTH, (ctx->display_width) - 1);
138     psb_cmdbuf_rendec_write(cmdbuf, reg_value);
139 
140     reg_value = 0;
141     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_HEIGHT, (ctx->coded_height) - 1);
142     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_WIDTH, (ctx->coded_width) - 1);
143     psb_cmdbuf_rendec_write(cmdbuf, reg_value);
144     psb_cmdbuf_rendec_end(cmdbuf);
145 
146 
147     /*TODO add stride and else there*/
148     reg_value = 0;
149     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, CODEC_MODE, 3);
150     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE, 1);
151     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, CODEC_PROFILE, 1);
152     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, CHROMA_FORMAT, 1);
153     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, ROW_STRIDE, src_surface->stride_mode);
154 
155     psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET( MSVDX_CMDS, OPERATING_MODE ));
156     psb_cmdbuf_rendec_write(cmdbuf, reg_value);
157     psb_cmdbuf_rendec_end(cmdbuf);
158 
159     psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES));
160     buffer = &src_surface->buf;
161     psb_cmdbuf_rendec_write_address(cmdbuf, buffer, buffer->buffer_ofs);
162     psb_cmdbuf_rendec_write_address(cmdbuf, buffer,
163                                     buffer->buffer_ofs +
164                                     src_surface->chroma_offset);
165     psb_cmdbuf_rendec_end(cmdbuf);
166 
167     reg_value = 0;
168     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, CONSTRAINED_INTRA_PRED, 0 );
169     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, MODE_CONFIG, 0 );
170     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, DISABLE_DEBLOCK_FILTER_IDC, 1 );
171     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_ALPHA_CO_OFFSET_DIV2, 0 );
172     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_BETA_OFFSET_DIV2, 0 );
173     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_FIELD_TYPE, 2 );
174     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_CODE_TYPE, 1 ); // P
175     *dec_ctx->p_slice_params = reg_value;
176 
177     psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET( MSVDX_CMDS, SLICE_PARAMS ) );
178     psb_cmdbuf_rendec_write(cmdbuf, reg_value);
179     psb_cmdbuf_rendec_end(cmdbuf);
180 
181     vld_dec_setup_alternative_frame(dec_ctx->obj_context);
182 
183     *cmdbuf->cmd_idx++ = CMD_DEBLOCK | CMD_DEBLOCK_TYPE_SKIP;
184     *cmdbuf->cmd_idx++ = 0;
185     *cmdbuf->cmd_idx++ = ctx->coded_width / 16;
186     *cmdbuf->cmd_idx++ = ctx->coded_height / 16;
187     *cmdbuf->cmd_idx++ = 0;
188     *cmdbuf->cmd_idx++ = 0;
189 
190 }
191 
tng__yuv_processor_execute(context_DEC_p dec_ctx,object_buffer_p obj_buffer)192 static VAStatus tng__yuv_processor_execute(context_DEC_p dec_ctx, object_buffer_p obj_buffer)
193 {
194     /* psb_surface_p target_surface = dec_ctx->obj_context->current_render_target->psb_surface; */
195     context_yuv_processor_p ctx = dec_ctx->yuv_ctx;
196     uint32_t reg_value;
197     VAStatus vaStatus;
198 
199     ASSERT(obj_buffer->type == YUVProcessorSurfaceType ||
200            obj_buffer->type == VAProcPipelineParameterBufferType);
201     ASSERT(obj_buffer->num_elements == 1);
202     ASSERT(obj_buffer->size == sizeof(struct surface_param_s));
203 
204     if ((obj_buffer->num_elements != 1) ||
205         ((obj_buffer->size != sizeof(struct surface_param_s)) &&
206         (obj_buffer->size != sizeof(VAProcPipelineParameterBuffer)))) {
207         return VA_STATUS_ERROR_UNKNOWN;
208     }
209 
210     /* yuv rotation issued from dec driver, TODO removed later */
211     if (obj_buffer->type == YUVProcessorSurfaceType) {
212         surface_param_p surface_params = (surface_param_p) obj_buffer->buffer_data;
213         psb_surface_p rotate_surface = dec_ctx->obj_context->current_render_target->out_loop_surface;
214         object_context_p obj_context = dec_ctx->obj_context;
215         psb_driver_data_p driver_data = obj_context->driver_data;
216 
217         ctx->display_width = (surface_params->display_width + 0xf) & ~0xf;
218         ctx->display_height = (surface_params->display_height + 0xf) & ~0xf;
219         ctx->coded_width = (surface_params->coded_width + 0xf) & ~0xf;
220         ctx->coded_height = (surface_params->coded_height + 0xf) & ~0xf;
221         ctx->src_surface = surface_params->src_surface;
222 
223         ctx->proc_param = NULL;
224         dec_ctx->obj_context->msvdx_rotate = obj_context->msvdx_rotate;
225         SET_SURFACE_INFO_rotate(rotate_surface, dec_ctx->obj_context->msvdx_rotate);
226 
227         obj_buffer->buffer_data = NULL;
228         obj_buffer->size = 0;
229 
230 #ifdef PSBVIDEO_MSVDX_DEC_TILING
231         if (GET_SURFACE_INFO_tiling(ctx->src_surface)) {
232             unsigned long msvdx_tile = psb__tile_stride_log2_256(rotate_surface->stride);
233             obj_context->msvdx_tile &= 0xf; /* clear rotate tile */
234             obj_context->msvdx_tile |= (msvdx_tile << 4);
235             obj_context->ctp_type &= (~PSB_CTX_TILING_MASK); /* clear tile context */
236             obj_context->ctp_type |= ((obj_context->msvdx_tile & 0xff) << 16);
237             psb_update_context(driver_data, obj_context->ctp_type);
238             drv_debug_msg(VIDEO_DEBUG_GENERAL, "update tile context, msvdx_tiled is 0x%08x \n", obj_context->msvdx_tile);
239         }
240 #endif
241     } else if (obj_buffer->type == VAProcPipelineParameterBufferType) {
242         VAProcPipelineParameterBuffer *vpp_params = (VAProcPipelineParameterBuffer *) obj_buffer->buffer_data;
243         object_surface_p obj_surface = SURFACE(vpp_params->surface);
244         psb_surface_p rotate_surface = dec_ctx->obj_context->current_render_target->psb_surface;
245 
246         if (obj_surface == NULL){
247             vaStatus = VA_STATUS_ERROR_UNKNOWN;
248             return vaStatus;
249         }
250 
251         //ctx->display_width = ((vpp_params->surface_region->width + 0xf) & ~0xf);
252         //ctx->display_height = ((vpp_params->surface_region->height + 0x1f) & ~0x1f);
253         ctx->display_width = ((obj_surface->width + 0xf) & ~0xf);
254         ctx->display_height = ((obj_surface->height + 0xf) & ~0xf);
255         ctx->coded_width = ctx->display_width;
256         ctx->coded_height = ctx->display_height;
257 
258         ctx->src_surface = obj_surface->psb_surface;
259         dec_ctx->obj_context->msvdx_rotate = vpp_params->rotation_state;
260         SET_SURFACE_INFO_rotate(rotate_surface, dec_ctx->obj_context->msvdx_rotate);
261 
262         ctx->proc_param = vpp_params;
263         obj_buffer->buffer_data = NULL;
264         obj_buffer->size = 0;
265 
266 #ifdef PSBVIDEO_MSVDX_DEC_TILING
267         object_context_p obj_context = dec_ctx->obj_context;
268 	psb_driver_data_p driver_data = obj_context->driver_data;
269         drv_debug_msg(VIDEO_DEBUG_GENERAL, "attempt to update tile context\n");
270         if (GET_SURFACE_INFO_tiling(ctx->src_surface)) {
271             drv_debug_msg(VIDEO_DEBUG_GENERAL, "update tile context\n");
272 
273             unsigned long msvdx_tile = psb__tile_stride_log2_256(rotate_surface->stride);
274             obj_context->msvdx_tile &= 0xf; /* clear rotate tile */
275             obj_context->msvdx_tile |= (msvdx_tile << 4);
276             obj_context->ctp_type &= (~PSB_CTX_TILING_MASK); /* clear tile context */
277             obj_context->ctp_type |= ((obj_context->msvdx_tile & 0xff) << 16);
278             psb_update_context(driver_data, obj_context->ctp_type);
279             drv_debug_msg(VIDEO_DEBUG_GENERAL, "update tile context, msvdx_tiled is 0x%08x \n", obj_context->msvdx_tile);
280         }
281 #endif
282     }
283 
284 #ifdef ADNROID
285         LOGV("%s, %d %d %d %d***************************************************\n",
286                   __func__, ctx->display_width, ctx->display_height, ctx->coded_width, ctx->coded_height);
287 #endif
288 
289     vaStatus = VA_STATUS_SUCCESS;
290 
291     if (psb_context_get_next_cmdbuf(dec_ctx->obj_context)) {
292         vaStatus = VA_STATUS_ERROR_UNKNOWN;
293         DEBUG_FAILURE;
294         return vaStatus;
295     }
296     /* ctx->begin_slice(ctx, slice_param); */
297     vld_dec_FE_state(dec_ctx->obj_context, NULL);
298 
299     tng__yuv_processor_process(dec_ctx);
300     /* ctx->process_slice(ctx, slice_param); */
301     vld_dec_write_kick(dec_ctx->obj_context);
302 
303     dec_ctx->obj_context->video_op = psb_video_vld;
304     dec_ctx->obj_context->flags = 0;
305 
306     /* ctx->end_slice(ctx); */
307     dec_ctx->obj_context->flags = FW_VA_RENDER_IS_FIRST_SLICE | FW_VA_RENDER_IS_LAST_SLICE | FW_INTERNAL_CONTEXT_SWITCH;
308 
309     if (psb_context_submit_cmdbuf(dec_ctx->obj_context)) {
310         vaStatus = VA_STATUS_ERROR_UNKNOWN;
311     }
312     return vaStatus;
313 }
314 
tng_yuv_processor_process_buffer(context_DEC_p dec_ctx,object_buffer_p buffer)315 static VAStatus tng_yuv_processor_process_buffer(
316     context_DEC_p dec_ctx,
317     object_buffer_p buffer)
318 {
319     VAStatus vaStatus = VA_STATUS_SUCCESS;
320     object_buffer_p obj_buffer = buffer;
321     unsigned int type = obj_buffer->type;
322     {
323         switch (type) {
324         case YUVProcessorSurfaceType:
325         case VAProcPipelineParameterBufferType:
326             vaStatus = tng__yuv_processor_execute(dec_ctx, obj_buffer);
327             DEBUG_FAILURE;
328             break;
329 
330         default:
331             vaStatus = VA_STATUS_ERROR_UNKNOWN;
332             DEBUG_FAILURE;
333         }
334     }
335 
336     return vaStatus;
337 }
338 
tng_yuv_processor_EndPicture(object_context_p obj_context)339 static VAStatus tng_yuv_processor_EndPicture(
340     object_context_p obj_context)
341 {
342     context_DEC_p dec_ctx = (context_DEC_p) obj_context->format_data;
343     context_yuv_processor_p ctx = dec_ctx->yuv_ctx;
344 
345     if (psb_context_flush_cmdbuf(obj_context)) {
346         return VA_STATUS_ERROR_UNKNOWN;
347     }
348 
349     if (ctx->proc_param) {
350         free(ctx->proc_param);
351         ctx->proc_param = NULL;
352     }
353 
354     return VA_STATUS_SUCCESS;
355 }
356 
357 struct format_vtable_s tng_yuv_processor_vtable = {
358 queryConfigAttributes:
359     tng_yuv_processor_QueryConfigAttributes,
360 validateConfig:
361     tng_yuv_processor_ValidateConfig,
362 createContext:
363     tng_yuv_processor_CreateContext,
364 destroyContext:
365     tng_yuv_processor_DestroyContext,
366 beginPicture:
367     tng_yuv_processor_BeginPicture,
368 renderPicture:
369     vld_dec_RenderPicture,
370 endPicture:
371     tng_yuv_processor_EndPicture
372 };
373 
374 #define VED_SUPPORTED_FILTERS_NUM 1
375 #define INIT_DRIVER_DATA    psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
376 #define CONFIG(id)  ((object_config_p) object_heap_lookup( &driver_data->config_heap, id ))
377 #define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id ))
378 #define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id ))
379 
ved_QueryVideoProcFilters(VADriverContextP ctx,VAContextID context,VAProcFilterType * filters,unsigned int * num_filters)380 VAStatus ved_QueryVideoProcFilters(
381     VADriverContextP    ctx,
382     VAContextID         context,
383     VAProcFilterType   *filters,
384     unsigned int       *num_filters)
385 {
386     INIT_DRIVER_DATA;
387     VAStatus vaStatus = VA_STATUS_SUCCESS;
388     object_context_p obj_context;
389     object_config_p obj_config;
390     VAEntrypoint tmp;
391     int count;
392 
393     /* check if ctx is right */
394     obj_context = CONTEXT(context);
395     if (NULL == obj_context) {
396         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find context\n");
397         vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
398         goto err;
399     }
400 
401     obj_config = CONFIG(obj_context->config_id);
402     if (NULL == obj_config) {
403         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find config\n");
404         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
405         goto err;
406     }
407 
408     tmp = obj_config->entrypoint;
409     if (tmp != VAEntrypointVideoProc) {
410         drv_debug_msg(VIDEO_DEBUG_ERROR, "current entrypoint is %d, not VAEntrypointVideoProc\n", tmp);
411         vaStatus = VA_STATUS_ERROR_UNKNOWN;
412         goto err;
413     }
414 
415     /* check if filters and num_filters is valid */
416     if (NULL == num_filters || NULL == filters) {
417         drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide input parameter num_filters %p, filters %p\n", num_filters, filters);
418         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
419         goto err;
420     }
421 
422     /* check if the filter array size is valid */
423     if (*num_filters < VED_SUPPORTED_FILTERS_NUM) {
424         drv_debug_msg(VIDEO_DEBUG_ERROR, "The filters array size(%d) is NOT valid! Supported filters num is %d\n",
425                 *num_filters, VED_SUPPORTED_FILTERS_NUM);
426         vaStatus = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
427         *num_filters = VED_SUPPORTED_FILTERS_NUM;
428         goto err;
429     }
430 
431     count = 0;
432     filters[count++] = VAProcFilterNone;
433     *num_filters = count;
434 
435 err:
436     return vaStatus;
437 }
438 
ved_QueryVideoProcFilterCaps(VADriverContextP ctx,VAContextID context,VAProcFilterType type,void * filter_caps,unsigned int * num_filter_caps)439 VAStatus ved_QueryVideoProcFilterCaps(
440         VADriverContextP    ctx,
441         VAContextID         context,
442         VAProcFilterType    type,
443         void               *filter_caps,
444         unsigned int       *num_filter_caps)
445 {
446     INIT_DRIVER_DATA;
447     VAStatus vaStatus = VA_STATUS_SUCCESS;
448     object_context_p obj_context;
449     object_config_p obj_config;
450     VAProcFilterCap *no_cap;
451 
452     /* check if context is right */
453     obj_context = CONTEXT(context);
454     if (NULL == obj_context) {
455         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find context\n");
456         vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
457         goto err;
458     }
459 
460     obj_config = CONFIG(obj_context->config_id);
461     if (NULL == obj_config) {
462         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find config\n");
463         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
464         goto err;
465     }
466 
467     /* check if filter_caps and num_filter_caps is right */
468     if (NULL == num_filter_caps || NULL == filter_caps){
469         drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide input parameter num_filters %p, filters %p\n", num_filter_caps, filter_caps);
470         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
471         goto err;
472     }
473 
474     if (*num_filter_caps < 1) {
475         drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide input parameter num_filters == %d (> 1)\n", *num_filter_caps);
476         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
477         goto err;
478     }
479 
480     /* check if curent HW support and return corresponding caps */
481         /* FIXME: we should use a constant table to return caps */
482     switch (type) {
483     case VAProcFilterNone:
484         no_cap = filter_caps;
485         no_cap->range.min_value = 0;
486         no_cap->range.max_value = 0;
487         no_cap->range.default_value = 0;
488         no_cap->range.step = 0;
489         *num_filter_caps = 1;
490         break;
491     default:
492         drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide filter type %d\n", type);
493         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_FILTER;
494         *num_filter_caps = 0;
495         goto err;
496     }
497 
498 err:
499     return vaStatus;
500 }
501 
ved_QueryVideoProcPipelineCaps(VADriverContextP ctx,VAContextID context,VABufferID * filters,unsigned int num_filters,VAProcPipelineCaps * pipeline_caps)502 VAStatus ved_QueryVideoProcPipelineCaps(
503         VADriverContextP    ctx,
504         VAContextID         context,
505         VABufferID         *filters,
506         unsigned int        num_filters,
507         VAProcPipelineCaps *pipeline_caps)
508 {
509     INIT_DRIVER_DATA;
510     VAStatus vaStatus = VA_STATUS_SUCCESS;
511     object_context_p obj_context;
512     object_config_p obj_config;
513     VAProcFilterParameterBufferBase *base;
514     object_buffer_p buf;
515 
516     /* check if ctx is right */
517     obj_context = CONTEXT(context);
518     if (NULL == obj_context) {
519         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find context\n");
520         vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
521         goto err;
522     }
523 
524     obj_config = CONFIG(obj_context->config_id);
525     if (NULL == obj_config) {
526         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find config\n");
527         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
528         goto err;
529     }
530 
531     /* check if filters and num_filters and pipeline-caps are right */
532     if (num_filters != 1) {
533         drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid num_filters %d\n", num_filters);
534         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
535         goto err;
536     }
537 
538     if (NULL == filters || pipeline_caps == NULL) {
539         drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid filters %p or pipeline_caps %p\n", filters, pipeline_caps);
540         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
541         goto err;
542     }
543 
544     memset(pipeline_caps, 0, sizeof(*pipeline_caps));
545 
546     buf = BUFFER(*(filters));
547 
548     if (buf == NULL){
549         drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid filter buffer: NULL \n");
550         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
551         goto err;
552     }
553 
554     base = (VAProcFilterParameterBufferBase *)buf->buffer_data;
555     /* check filter buffer setting */
556     switch (base->type) {
557     case VAProcFilterNone:
558         pipeline_caps->rotation_flags = (1 << VA_ROTATION_NONE);
559         pipeline_caps->rotation_flags |= (1 << VA_ROTATION_90);
560         pipeline_caps->rotation_flags |= (1 << VA_ROTATION_180);
561         pipeline_caps->rotation_flags |= (1 << VA_ROTATION_270);
562         break;
563 
564     default:
565         drv_debug_msg(VIDEO_DEBUG_ERROR, "Do NOT support the filter type %d\n", base->type);
566         vaStatus = VA_STATUS_ERROR_UNKNOWN;
567         goto err;
568     }
569 err:
570     return vaStatus;
571 }
572