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