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
42static 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
51static VAStatus tng_yuv_processor_ValidateConfig(
52    object_config_p __maybe_unused obj_config)
53{
54    return VA_STATUS_SUCCESS;
55}
56
57static VAStatus tng_yuv_processor_process_buffer( context_DEC_p, object_buffer_p);
58
59static 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
94static 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
118static VAStatus tng_yuv_processor_BeginPicture(
119    object_context_p __maybe_unused obj_context)
120{
121    return VA_STATUS_SUCCESS;
122}
123
124static 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
192static 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
315static 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
339static 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
357struct format_vtable_s tng_yuv_processor_vtable = {
358queryConfigAttributes:
359    tng_yuv_processor_QueryConfigAttributes,
360validateConfig:
361    tng_yuv_processor_ValidateConfig,
362createContext:
363    tng_yuv_processor_CreateContext,
364destroyContext:
365    tng_yuv_processor_DestroyContext,
366beginPicture:
367    tng_yuv_processor_BeginPicture,
368renderPicture:
369    vld_dec_RenderPicture,
370endPicture:
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
380VAStatus 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
435err:
436    return vaStatus;
437}
438
439VAStatus 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
498err:
499    return vaStatus;
500}
501
502VAStatus 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    }
569err:
570    return vaStatus;
571}
572