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         CHECK_ALLOCATION(dec_ctx);
77         obj_context->format_data = (void *)dec_ctx;
78         ctx->has_dec_ctx = 1;
79         vaStatus = vld_dec_CreateContext(dec_ctx, obj_context);
80         DEBUG_FAILURE;
81     }
82 
83     dec_ctx->yuv_ctx = ctx;
84     dec_ctx->process_buffer = tng_yuv_processor_process_buffer;
85 
86     return vaStatus;
87 }
88 
tng_yuv_processor_DestroyContext(object_context_p obj_context)89 static void tng_yuv_processor_DestroyContext(
90     object_context_p obj_context)
91 {
92     context_DEC_p dec_ctx = (context_DEC_p) obj_context->format_data;
93     context_yuv_processor_p yuv_ctx = NULL;
94     int has_dec_ctx = 0;
95 
96     if (dec_ctx == NULL)
97         return;
98 
99     yuv_ctx = dec_ctx->yuv_ctx;
100 
101     if (yuv_ctx) {
102         has_dec_ctx = yuv_ctx->has_dec_ctx;
103         free(yuv_ctx);
104         dec_ctx->yuv_ctx = NULL;
105     }
106 
107     if (has_dec_ctx) {
108         free(dec_ctx);
109         obj_context->format_data = NULL;
110     }
111 }
112 
tng_yuv_processor_BeginPicture(object_context_p __maybe_unused obj_context)113 static VAStatus tng_yuv_processor_BeginPicture(
114     object_context_p __maybe_unused obj_context)
115 {
116     return VA_STATUS_SUCCESS;
117 }
118 
tng__yuv_processor_process(context_DEC_p dec_ctx)119 static void tng__yuv_processor_process(context_DEC_p dec_ctx)
120 {
121     context_yuv_processor_p ctx = dec_ctx->yuv_ctx;
122     psb_cmdbuf_p cmdbuf = dec_ctx->obj_context->cmdbuf;
123     /* psb_surface_p target_surface = dec_ctx->obj_context->current_render_target->psb_surface; */
124     psb_surface_p src_surface = ctx->src_surface;
125     psb_buffer_p buffer;
126     uint32_t reg_value;
127 
128     psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, DISPLAY_PICTURE_SIZE));
129 
130     reg_value = 0;
131     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_HEIGHT, (ctx->display_height) - 1);
132     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_WIDTH, (ctx->display_width) - 1);
133     psb_cmdbuf_rendec_write(cmdbuf, reg_value);
134 
135     reg_value = 0;
136     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_HEIGHT, (ctx->coded_height) - 1);
137     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_WIDTH, (ctx->coded_width) - 1);
138     psb_cmdbuf_rendec_write(cmdbuf, reg_value);
139     psb_cmdbuf_rendec_end(cmdbuf);
140 
141 
142     /*TODO add stride and else there*/
143     reg_value = 0;
144     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, CODEC_MODE, 3);
145     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE, 1);
146     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, CODEC_PROFILE, 1);
147     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, CHROMA_FORMAT, 1);
148     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, OPERATING_MODE, ROW_STRIDE, src_surface->stride_mode);
149 
150     psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET( MSVDX_CMDS, OPERATING_MODE ));
151     psb_cmdbuf_rendec_write(cmdbuf, reg_value);
152     psb_cmdbuf_rendec_end(cmdbuf);
153 
154     psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES));
155     buffer = &src_surface->buf;
156     psb_cmdbuf_rendec_write_address(cmdbuf, buffer, buffer->buffer_ofs);
157     psb_cmdbuf_rendec_write_address(cmdbuf, buffer,
158                                     buffer->buffer_ofs +
159                                     src_surface->chroma_offset);
160     psb_cmdbuf_rendec_end(cmdbuf);
161 
162     reg_value = 0;
163     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, CONSTRAINED_INTRA_PRED, 0 );
164     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, MODE_CONFIG, 0 );
165     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, DISABLE_DEBLOCK_FILTER_IDC, 1 );
166     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_ALPHA_CO_OFFSET_DIV2, 0 );
167     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_BETA_OFFSET_DIV2, 0 );
168     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_FIELD_TYPE, 2 );
169     REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_CMDS, SLICE_PARAMS, SLICE_CODE_TYPE, 1 ); // P
170     *dec_ctx->p_slice_params = reg_value;
171 
172     psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET( MSVDX_CMDS, SLICE_PARAMS ) );
173     psb_cmdbuf_rendec_write(cmdbuf, reg_value);
174     psb_cmdbuf_rendec_end(cmdbuf);
175 
176     vld_dec_setup_alternative_frame(dec_ctx->obj_context);
177 
178     *cmdbuf->cmd_idx++ = CMD_DEBLOCK | CMD_DEBLOCK_TYPE_SKIP;
179     *cmdbuf->cmd_idx++ = 0;
180     *cmdbuf->cmd_idx++ = ctx->coded_width / 16;
181     *cmdbuf->cmd_idx++ = ctx->coded_height / 16;
182     *cmdbuf->cmd_idx++ = 0;
183     *cmdbuf->cmd_idx++ = 0;
184 
185 }
186 
tng__yuv_processor_execute(context_DEC_p dec_ctx,object_buffer_p obj_buffer)187 static VAStatus tng__yuv_processor_execute(context_DEC_p dec_ctx, object_buffer_p obj_buffer)
188 {
189     /* psb_surface_p target_surface = dec_ctx->obj_context->current_render_target->psb_surface; */
190     context_yuv_processor_p ctx = dec_ctx->yuv_ctx;
191     uint32_t reg_value;
192     VAStatus vaStatus;
193 
194     ASSERT(obj_buffer->type == YUVProcessorSurfaceType ||
195            obj_buffer->type == VAProcPipelineParameterBufferType);
196     ASSERT(obj_buffer->num_elements == 1);
197     ASSERT(obj_buffer->size == sizeof(struct surface_param_s));
198 
199     if ((obj_buffer->num_elements != 1) ||
200         ((obj_buffer->size != sizeof(struct surface_param_s)) &&
201         (obj_buffer->size != sizeof(VAProcPipelineParameterBuffer)))) {
202         return VA_STATUS_ERROR_UNKNOWN;
203     }
204 
205     /* yuv rotation issued from dec driver, TODO removed later */
206     if (obj_buffer->type == YUVProcessorSurfaceType) {
207         surface_param_p surface_params = (surface_param_p) obj_buffer->buffer_data;
208         psb_surface_p rotate_surface = dec_ctx->obj_context->current_render_target->out_loop_surface;
209         object_context_p obj_context = dec_ctx->obj_context;
210         psb_driver_data_p driver_data = obj_context->driver_data;
211 
212         ctx->display_width = (surface_params->display_width + 0xf) & ~0xf;
213         ctx->display_height = (surface_params->display_height + 0xf) & ~0xf;
214         ctx->coded_width = (surface_params->coded_width + 0xf) & ~0xf;
215         ctx->coded_height = (surface_params->coded_height + 0xf) & ~0xf;
216         ctx->src_surface = surface_params->src_surface;
217 
218         ctx->proc_param = NULL;
219         dec_ctx->obj_context->msvdx_rotate = obj_context->msvdx_rotate;
220         SET_SURFACE_INFO_rotate(rotate_surface, dec_ctx->obj_context->msvdx_rotate);
221 
222         obj_buffer->buffer_data = NULL;
223         obj_buffer->size = 0;
224 
225 #ifdef PSBVIDEO_MSVDX_DEC_TILING
226         if (GET_SURFACE_INFO_tiling(ctx->src_surface)) {
227             unsigned long msvdx_tile = psb__tile_stride_log2_256(rotate_surface->stride);
228             obj_context->msvdx_tile &= 0xf; /* clear rotate tile */
229             obj_context->msvdx_tile |= (msvdx_tile << 4);
230             obj_context->ctp_type &= (~PSB_CTX_TILING_MASK); /* clear tile context */
231             obj_context->ctp_type |= ((obj_context->msvdx_tile & 0xff) << 16);
232             psb_update_context(driver_data, obj_context->ctp_type);
233             drv_debug_msg(VIDEO_DEBUG_GENERAL, "update tile context, msvdx_tiled is 0x%08x \n", obj_context->msvdx_tile);
234         }
235 #endif
236     } else if (obj_buffer->type == VAProcPipelineParameterBufferType) {
237         VAProcPipelineParameterBuffer *vpp_params = (VAProcPipelineParameterBuffer *) obj_buffer->buffer_data;
238         object_surface_p obj_surface = SURFACE(vpp_params->surface);
239         psb_surface_p rotate_surface = dec_ctx->obj_context->current_render_target->psb_surface;
240 
241         if (obj_surface == NULL){
242             vaStatus = VA_STATUS_ERROR_UNKNOWN;
243             return vaStatus;
244         }
245 
246         //ctx->display_width = ((vpp_params->surface_region->width + 0xf) & ~0xf);
247         //ctx->display_height = ((vpp_params->surface_region->height + 0x1f) & ~0x1f);
248         ctx->display_width = ((obj_surface->width + 0xf) & ~0xf);
249         ctx->display_height = ((obj_surface->height + 0xf) & ~0xf);
250         ctx->coded_width = ctx->display_width;
251         ctx->coded_height = ctx->display_height;
252 
253         ctx->src_surface = obj_surface->psb_surface;
254         dec_ctx->obj_context->msvdx_rotate = vpp_params->rotation_state;
255         SET_SURFACE_INFO_rotate(rotate_surface, dec_ctx->obj_context->msvdx_rotate);
256 
257         ctx->proc_param = vpp_params;
258         obj_buffer->buffer_data = NULL;
259         obj_buffer->size = 0;
260 
261 #ifdef PSBVIDEO_MSVDX_DEC_TILING
262         object_context_p obj_context = dec_ctx->obj_context;
263 	psb_driver_data_p driver_data = obj_context->driver_data;
264         drv_debug_msg(VIDEO_DEBUG_GENERAL, "attempt to update tile context\n");
265         if (GET_SURFACE_INFO_tiling(ctx->src_surface)) {
266             drv_debug_msg(VIDEO_DEBUG_GENERAL, "update tile context\n");
267 
268             unsigned long msvdx_tile = psb__tile_stride_log2_256(rotate_surface->stride);
269             obj_context->msvdx_tile &= 0xf; /* clear rotate tile */
270             obj_context->msvdx_tile |= (msvdx_tile << 4);
271             obj_context->ctp_type &= (~PSB_CTX_TILING_MASK); /* clear tile context */
272             obj_context->ctp_type |= ((obj_context->msvdx_tile & 0xff) << 16);
273             psb_update_context(driver_data, obj_context->ctp_type);
274             drv_debug_msg(VIDEO_DEBUG_GENERAL, "update tile context, msvdx_tiled is 0x%08x \n", obj_context->msvdx_tile);
275         }
276 #endif
277     }
278 
279 #ifdef ADNROID
280         LOGV("%s, %d %d %d %d***************************************************\n",
281                   __func__, ctx->display_width, ctx->display_height, ctx->coded_width, ctx->coded_height);
282 #endif
283 
284     vaStatus = VA_STATUS_SUCCESS;
285 
286     if (psb_context_get_next_cmdbuf(dec_ctx->obj_context)) {
287         vaStatus = VA_STATUS_ERROR_UNKNOWN;
288         DEBUG_FAILURE;
289         return vaStatus;
290     }
291     /* ctx->begin_slice(ctx, slice_param); */
292     vld_dec_FE_state(dec_ctx->obj_context, NULL);
293 
294     tng__yuv_processor_process(dec_ctx);
295     /* ctx->process_slice(ctx, slice_param); */
296     vld_dec_write_kick(dec_ctx->obj_context);
297 
298     dec_ctx->obj_context->video_op = psb_video_vld;
299     dec_ctx->obj_context->flags = 0;
300 
301     /* ctx->end_slice(ctx); */
302     dec_ctx->obj_context->flags = FW_VA_RENDER_IS_FIRST_SLICE | FW_VA_RENDER_IS_LAST_SLICE | FW_INTERNAL_CONTEXT_SWITCH;
303 
304     if (psb_context_submit_cmdbuf(dec_ctx->obj_context)) {
305         vaStatus = VA_STATUS_ERROR_UNKNOWN;
306     }
307     return vaStatus;
308 }
309 
tng_yuv_processor_process_buffer(context_DEC_p dec_ctx,object_buffer_p buffer)310 static VAStatus tng_yuv_processor_process_buffer(
311     context_DEC_p dec_ctx,
312     object_buffer_p buffer)
313 {
314     VAStatus vaStatus = VA_STATUS_SUCCESS;
315     object_buffer_p obj_buffer = buffer;
316     unsigned int type = obj_buffer->type;
317     {
318         switch (type) {
319         case YUVProcessorSurfaceType:
320         case VAProcPipelineParameterBufferType:
321             vaStatus = tng__yuv_processor_execute(dec_ctx, obj_buffer);
322             DEBUG_FAILURE;
323             break;
324 
325         default:
326             vaStatus = VA_STATUS_ERROR_UNKNOWN;
327             DEBUG_FAILURE;
328         }
329     }
330 
331     return vaStatus;
332 }
333 
tng_yuv_processor_EndPicture(object_context_p obj_context)334 static VAStatus tng_yuv_processor_EndPicture(
335     object_context_p obj_context)
336 {
337     context_DEC_p dec_ctx = (context_DEC_p) obj_context->format_data;
338     context_yuv_processor_p ctx = dec_ctx->yuv_ctx;
339 
340     if (psb_context_flush_cmdbuf(obj_context)) {
341         return VA_STATUS_ERROR_UNKNOWN;
342     }
343 
344     if (ctx->proc_param) {
345         free(ctx->proc_param);
346         ctx->proc_param = NULL;
347     }
348 
349     return VA_STATUS_SUCCESS;
350 }
351 
352 struct format_vtable_s tng_yuv_processor_vtable = {
353 queryConfigAttributes:
354     tng_yuv_processor_QueryConfigAttributes,
355 validateConfig:
356     tng_yuv_processor_ValidateConfig,
357 createContext:
358     tng_yuv_processor_CreateContext,
359 destroyContext:
360     tng_yuv_processor_DestroyContext,
361 beginPicture:
362     tng_yuv_processor_BeginPicture,
363 renderPicture:
364     vld_dec_RenderPicture,
365 endPicture:
366     tng_yuv_processor_EndPicture
367 };
368 
369 #define VED_SUPPORTED_FILTERS_NUM 1
370 #define INIT_DRIVER_DATA    psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
371 #define CONFIG(id)  ((object_config_p) object_heap_lookup( &driver_data->config_heap, id ))
372 #define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id ))
373 #define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id ))
374 
ved_QueryVideoProcFilters(VADriverContextP ctx,VAContextID context,VAProcFilterType * filters,unsigned int * num_filters)375 VAStatus ved_QueryVideoProcFilters(
376     VADriverContextP    ctx,
377     VAContextID         context,
378     VAProcFilterType   *filters,
379     unsigned int       *num_filters)
380 {
381     INIT_DRIVER_DATA;
382     VAStatus vaStatus = VA_STATUS_SUCCESS;
383     object_context_p obj_context;
384     object_config_p obj_config;
385     VAEntrypoint tmp;
386     int count;
387 
388     /* check if ctx is right */
389     obj_context = CONTEXT(context);
390     if (NULL == obj_context) {
391         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find context\n");
392         vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
393         goto err;
394     }
395 
396     obj_config = CONFIG(obj_context->config_id);
397     if (NULL == obj_config) {
398         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find config\n");
399         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
400         goto err;
401     }
402 
403     tmp = obj_config->entrypoint;
404     if (tmp != VAEntrypointVideoProc) {
405         drv_debug_msg(VIDEO_DEBUG_ERROR, "current entrypoint is %d, not VAEntrypointVideoProc\n", tmp);
406         vaStatus = VA_STATUS_ERROR_UNKNOWN;
407         goto err;
408     }
409 
410     /* check if filters and num_filters is valid */
411     if (NULL == num_filters || NULL == filters) {
412         drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide input parameter num_filters %p, filters %p\n", num_filters, filters);
413         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
414         goto err;
415     }
416 
417     /* check if the filter array size is valid */
418     if (*num_filters < VED_SUPPORTED_FILTERS_NUM) {
419         drv_debug_msg(VIDEO_DEBUG_ERROR, "The filters array size(%d) is NOT valid! Supported filters num is %d\n",
420                 *num_filters, VED_SUPPORTED_FILTERS_NUM);
421         vaStatus = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
422         *num_filters = VED_SUPPORTED_FILTERS_NUM;
423         goto err;
424     }
425 
426     count = 0;
427     filters[count++] = VAProcFilterNone;
428     *num_filters = count;
429 
430 err:
431     return vaStatus;
432 }
433 
ved_QueryVideoProcFilterCaps(VADriverContextP ctx,VAContextID context,VAProcFilterType type,void * filter_caps,unsigned int * num_filter_caps)434 VAStatus ved_QueryVideoProcFilterCaps(
435         VADriverContextP    ctx,
436         VAContextID         context,
437         VAProcFilterType    type,
438         void               *filter_caps,
439         unsigned int       *num_filter_caps)
440 {
441     INIT_DRIVER_DATA;
442     VAStatus vaStatus = VA_STATUS_SUCCESS;
443     object_context_p obj_context;
444     object_config_p obj_config;
445     VAProcFilterCap *no_cap;
446 
447     /* check if context is right */
448     obj_context = CONTEXT(context);
449     if (NULL == obj_context) {
450         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find context\n");
451         vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
452         goto err;
453     }
454 
455     obj_config = CONFIG(obj_context->config_id);
456     if (NULL == obj_config) {
457         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find config\n");
458         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
459         goto err;
460     }
461 
462     /* check if filter_caps and num_filter_caps is right */
463     if (NULL == num_filter_caps || NULL == filter_caps){
464         drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide input parameter num_filters %p, filters %p\n", num_filter_caps, filter_caps);
465         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
466         goto err;
467     }
468 
469     if (*num_filter_caps < 1) {
470         drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide input parameter num_filters == %d (> 1)\n", *num_filter_caps);
471         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
472         goto err;
473     }
474 
475     /* check if curent HW support and return corresponding caps */
476         /* FIXME: we should use a constant table to return caps */
477     switch (type) {
478     case VAProcFilterNone:
479         no_cap = filter_caps;
480         no_cap->range.min_value = 0;
481         no_cap->range.max_value = 0;
482         no_cap->range.default_value = 0;
483         no_cap->range.step = 0;
484         *num_filter_caps = 1;
485         break;
486     default:
487         drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide filter type %d\n", type);
488         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_FILTER;
489         *num_filter_caps = 0;
490         goto err;
491     }
492 
493 err:
494     return vaStatus;
495 }
496 
ved_QueryVideoProcPipelineCaps(VADriverContextP ctx,VAContextID context,VABufferID * filters,unsigned int num_filters,VAProcPipelineCaps * pipeline_caps)497 VAStatus ved_QueryVideoProcPipelineCaps(
498         VADriverContextP    ctx,
499         VAContextID         context,
500         VABufferID         *filters,
501         unsigned int        num_filters,
502         VAProcPipelineCaps *pipeline_caps)
503 {
504     INIT_DRIVER_DATA;
505     VAStatus vaStatus = VA_STATUS_SUCCESS;
506     object_context_p obj_context;
507     object_config_p obj_config;
508     VAProcFilterParameterBufferBase *base;
509     object_buffer_p buf;
510 
511     /* check if ctx is right */
512     obj_context = CONTEXT(context);
513     if (NULL == obj_context) {
514         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find context\n");
515         vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
516         goto err;
517     }
518 
519     obj_config = CONFIG(obj_context->config_id);
520     if (NULL == obj_config) {
521         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find config\n");
522         vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
523         goto err;
524     }
525 
526     /* check if filters and num_filters and pipeline-caps are right */
527     if (num_filters != 1) {
528         drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid num_filters %d\n", num_filters);
529         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
530         goto err;
531     }
532 
533     if (NULL == filters || pipeline_caps == NULL) {
534         drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid filters %p or pipeline_caps %p\n", filters, pipeline_caps);
535         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
536         goto err;
537     }
538 
539     memset(pipeline_caps, 0, sizeof(*pipeline_caps));
540 
541     buf = BUFFER(*(filters));
542 
543     if (buf == NULL){
544         drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid filter buffer: NULL \n");
545         vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
546         goto err;
547     }
548 
549     base = (VAProcFilterParameterBufferBase *)buf->buffer_data;
550     /* check filter buffer setting */
551     switch (base->type) {
552     case VAProcFilterNone:
553         pipeline_caps->rotation_flags = (1 << VA_ROTATION_NONE);
554         pipeline_caps->rotation_flags |= (1 << VA_ROTATION_90);
555         pipeline_caps->rotation_flags |= (1 << VA_ROTATION_180);
556         pipeline_caps->rotation_flags |= (1 << VA_ROTATION_270);
557         break;
558 
559     default:
560         drv_debug_msg(VIDEO_DEBUG_ERROR, "Do NOT support the filter type %d\n", base->type);
561         vaStatus = VA_STATUS_ERROR_UNKNOWN;
562         goto err;
563     }
564 err:
565     return vaStatus;
566 }
567