vsp_vp8.c revision ac309081b871fae9abf0c2c6827979ec83b09cf3
1/*
2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 *    Zhangfei Zhang <zhangfei.zhang@intel.com>
26 *    Mingruo Sun <mingruo.sun@intel.com>
27 *
28 */
29#include "vsp_VPP.h"
30#include "vsp_vp8.h"
31#include "psb_buffer.h"
32#include "psb_surface.h"
33#include "vsp_cmdbuf.h"
34#include "psb_drv_debug.h"
35#include "va/va_enc_vp8.h"
36
37#define INIT_DRIVER_DATA    psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
38#define INIT_CONTEXT_VPP    context_VPP_p ctx = (context_VPP_p) obj_context->format_data;
39#define CONFIG(id)  ((object_config_p) object_heap_lookup( &driver_data->config_heap, id ))
40#define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id ))
41#define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id ))
42
43#define SURFACE(id)    ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id ))
44
45#define KB 1024
46#define MB (KB * KB)
47#define VSP_VP8ENC_STATE_SIZE (48*MB)
48
49#define ALIGN_TO_128(value) ((value + 128 - 1) & ~(128 - 1))
50
51#define REF_FRAME_WIDTH  1920
52#define REF_FRAME_HEIGHT 1088
53#define REF_FRAME_BORDER   32
54
55#define VP8_ENC_CBR 1
56#define VP8_ENC_CBR_HRD 0
57
58#define XMEM_FRAME_BUFFER_SIZE_IN_BYTE ((REF_FRAME_WIDTH + 2 * REF_FRAME_BORDER) * (REF_FRAME_HEIGHT + 2 * REF_FRAME_BORDER) + \
59        2 * ((REF_FRAME_WIDTH + 2 * REF_FRAME_BORDER) >> 1) * (REF_FRAME_HEIGHT / 2 + REF_FRAME_BORDER)) // Allocated for HD
60
61enum filter_status {
62    FILTER_DISABLED = 0,
63    FILTER_ENABLED
64};
65
66typedef struct _Ref_frame_surface {
67    struct VssProcPictureVP8 ref_frame_buffers[4];
68} ref_frame_surface;
69
70#define FUNCTION_NAME \
71    printf("ENTER %s.\n",__FUNCTION__);
72
73#define EXIT_FUNCTION_NAME \
74    printf("EXIT %s.\n",__FUNCTION__);
75
76
77typedef union{
78        struct {
79            /* force this frame to be a keyframe */
80            unsigned int force_kf                       : 1;
81	    /* don't reference the last frame */
82            unsigned int no_ref_last                    : 1;
83	    /* don't reference the golden frame */
84            unsigned int no_ref_gf                      : 1;
85	    /* don't reference the alternate reference frame */
86            unsigned int no_ref_arf                     : 1;
87
88         unsigned int upd_last                     : 1;
89         unsigned int upd_gf                     : 2;
90         unsigned int upd_arf                     : 2;
91         unsigned int no_upd_last                     : 1;
92         unsigned int no_upd_gf                     : 1;
93         unsigned int no_upd_arf                     : 1;
94         unsigned int no_upd_entropy                     : 1;
95        } bits;
96        unsigned int value;
97    } vp8_fw_pic_flags;
98
99
100static void vsp_VP8_DestroyContext(object_context_p obj_context);
101
102static VAStatus vsp__VP8_check_legal_picture(object_context_p obj_context, object_config_p obj_config);
103
104static void vsp_VP8_QueryConfigAttributes(
105    VAProfile profile,
106    VAEntrypoint entrypoint,
107    VAConfigAttrib *attrib_list,
108    int num_attribs)
109{
110    int i;
111    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s\n", __FUNCTION__);
112
113    for (i = 0; i < num_attribs; i++) {
114        switch (attrib_list[i].type) {
115	case VAConfigAttribRTFormat:
116	    break;
117	case VAConfigAttribRateControl:
118	    attrib_list[i].value = VA_RC_CBR | VA_RC_VBR;
119	    break;
120	case VAConfigAttribEncAutoReference:
121	    attrib_list[i].value = 1;
122	    break;
123	case VAConfigAttribEncMaxRefFrames:
124	    attrib_list[i].value = 4;
125	    break;
126
127	default:
128	    attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
129	    break;
130	}
131    }
132}
133
134static VAStatus vsp_VP8_ValidateConfig(
135    object_config_p obj_config)
136{
137    int i;
138    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s\n", __FUNCTION__);
139
140    /* Check all attributes */
141    for (i = 0; i < obj_config->attrib_count; i++) {
142        switch (obj_config->attrib_list[i].type) {
143            case VAConfigAttribRTFormat:
144                /* Ignore */
145                break;
146            case VAConfigAttribRateControl:
147		break;
148            case VAConfigAttribEncAutoReference:
149		break;
150            case VAConfigAttribEncMaxRefFrames:
151		break;
152
153            default:
154                return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
155        }
156    }
157
158    return VA_STATUS_SUCCESS;
159}
160
161static VAStatus vsp_VP8_CreateContext(
162    object_context_p obj_context,
163    object_config_p obj_config)
164{
165    VAStatus vaStatus = VA_STATUS_SUCCESS;
166    /* currently vp8 will use vpp's context since they will use the same cmdbuf */
167    context_VPP_p ctx;
168    int i;
169
170    ctx = (context_VPP_p) calloc(1, sizeof(struct context_VPP_s));
171    if (NULL == ctx) {
172        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
173        DEBUG_FAILURE;
174        return vaStatus;
175    }
176
177    for (i = 0; i < obj_config->attrib_count; i++) {
178	if (obj_config->attrib_list[i].type == VAConfigAttribRateControl) {
179            ctx->rc_mode = obj_config->attrib_list[i].value;
180	    break;
181	}
182    }
183
184    /* set size */
185    ctx->param_sz = 0;
186    ctx->pic_param_sz = ALIGN_TO_128(sizeof(struct VssVp8encPictureParameterBuffer));
187    ctx->param_sz += ctx->pic_param_sz;
188    ctx->seq_param_sz = ALIGN_TO_128(sizeof(struct VssVp8encSequenceParameterBuffer));
189    ctx->param_sz += ctx->seq_param_sz;
190    ctx->ref_param_sz = ALIGN_TO_128(sizeof(ref_frame_surface));
191    ctx->param_sz += ctx->ref_param_sz;
192
193    /* set offset */
194    ctx->pic_param_offset = 0;
195    ctx->seq_param_offset = ctx->pic_param_sz;
196    ctx->ref_param_offset = ctx->pic_param_sz + ctx->seq_param_sz;
197
198    ctx->min_qp = 4;
199    ctx->max_qp = 63;
200    ctx->rc_undershoot = 100;
201    ctx->buffer_size = 6000;
202    ctx->initial_buffer_fullness = 4000;
203    ctx->optimal_buffer_fullness = 5000;
204
205    ctx->context_buf = (psb_buffer_p) calloc(1, sizeof(struct psb_buffer_s));
206    if (NULL == ctx->context_buf) {
207        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
208        DEBUG_FAILURE;
209        goto out;
210    }
211
212    vaStatus = psb_buffer_create(obj_context->driver_data, VSP_VP8ENC_STATE_SIZE, psb_bt_vpu_only, ctx->context_buf);
213
214    if (VA_STATUS_SUCCESS != vaStatus) {
215        goto out;
216    }
217
218    obj_context->format_data = (void*) ctx;
219    ctx->obj_context = obj_context;
220
221    return vaStatus;
222
223out:
224    vsp_VP8_DestroyContext(obj_context);
225
226    if (ctx)
227        free(ctx);
228
229    return vaStatus;
230}
231
232static void vsp_VP8_DestroyContext(
233    object_context_p obj_context)
234{
235    INIT_CONTEXT_VPP;
236
237    if (ctx->context_buf) {
238        psb_buffer_destroy(ctx->context_buf);
239        free(ctx->context_buf);
240        ctx->context_buf = NULL;
241    }
242
243    if (ctx->filters) {
244        free(ctx->filters);
245        ctx->num_filters = 0;
246    }
247
248    free(obj_context->format_data);
249    obj_context->format_data = NULL;
250}
251
252static VAStatus vsp_vp8_process_seqence_param(
253    context_VPP_p ctx,
254    object_buffer_p obj_buffer)
255{
256
257    VAStatus vaStatus = VA_STATUS_SUCCESS;
258    vsp_cmdbuf_p cmdbuf = ctx->obj_context->vsp_cmdbuf;
259    int i;
260    int ref_frame_width, ref_frame_height;
261
262    VAEncSequenceParameterBufferVP8 *va_seq =
263            (VAEncSequenceParameterBufferVP8 *) obj_buffer->buffer_data;
264    struct VssVp8encSequenceParameterBuffer *seq =
265            (struct VssVp8encSequenceParameterBuffer *)cmdbuf->seq_param_p;
266
267    ref_frame_surface *ref =
268	    (struct ref_frame_surface*)cmdbuf->ref_param_p;
269
270    ctx->frame_width = va_seq->frame_width;
271    ctx->frame_height = va_seq->frame_height;
272
273    /*cmd structures initializations*/
274    seq->frame_width       = va_seq->frame_width;
275    seq->frame_height      = va_seq->frame_height;
276    seq->rc_target_bitrate = va_seq->bits_per_second / 1000;
277    seq->max_intra_rate    = 0;
278    seq->rc_undershoot_pct = ctx->rc_undershoot;
279    seq->rc_overshoot_pct  = 100;
280    /* FIXME: API doc says max 5000, but for current default test vector we still use 6000 */
281    seq->rc_buf_sz         = ctx->buffer_size;
282    seq->rc_buf_initial_sz = ctx->initial_buffer_fullness;
283    seq->rc_buf_optimal_sz = ctx->optimal_buffer_fullness;
284    seq->rc_min_quantizer  = ctx->min_qp;
285    seq->rc_max_quantizer  = ctx->max_qp;
286    seq->kf_max_dist       = va_seq->kf_max_dist;
287    seq->kf_min_dist       = va_seq->kf_min_dist;
288    seq->frame_rate        = ctx->frame_rate;
289    seq->error_resilient   = va_seq->error_resilient;
290    seq->num_token_partitions = 2; // (log2: 2^2 = 4)
291    seq->rc_end_usage         = (ctx->rc_mode == VA_RC_CBR) ? VP8_ENC_CBR_HRD : VP8_ENC_CBR;  /* CBR */
292    seq->kf_mode              = va_seq->kf_auto;   /* AUTO */
293    seq->cyclic_intra_refresh = 0;
294
295    seq->concatenate_partitions = 1; //Make 0 not to concatenate partitions
296
297    ref_frame_width = (ctx->frame_width + 2 * 32 + 63) & (~63);
298    ref_frame_height = (ctx->frame_height + 2 * 32 + 63) & (~63);
299
300    ctx->frame_rate = seq->frame_rate;
301    ctx->bits_per_second = va_seq->bits_per_second;
302
303    ctx->vp8_seq_param = * seq;
304
305    vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VP8_ID, &cmdbuf->param_mem,
306                              VssVp8encSetSequenceParametersCommand,
307                              ctx->seq_param_offset,
308                              sizeof(struct VssVp8encSequenceParameterBuffer));
309    ctx->vp8_seq_cmd_send = 1;
310
311    /* pass 4 ref frame surface to kernel driver */
312    for (i = 0; i < 4; i++) {
313        ref->ref_frame_buffers[i].surface_id = va_seq->reference_frames[i];
314        ref->ref_frame_buffers[i].width = ref_frame_width;
315        ref->ref_frame_buffers[i].height = ref_frame_height;
316    }
317
318    for (i = 0; i < 4; i++) {
319	object_surface_p ref_surf = SURFACE(va_seq->reference_frames[i]);
320	if (!ref_surf)
321	    return VA_STATUS_ERROR_UNKNOWN;
322	ref_surf->is_ref_surface = 2;
323
324	vsp_cmdbuf_reloc_pic_param(&(ref->ref_frame_buffers[i].base),
325			           ctx->ref_param_offset,
326				   &(ref_surf->psb_surface->buf),
327				   cmdbuf->param_mem_loc, ref);
328    }
329
330    vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VP8_ID,
331                              &cmdbuf->param_mem, Vss_Sys_Ref_Frame_COMMAND,
332                              ctx->ref_param_offset,
333                              sizeof(ref_frame_surface));
334
335    return vaStatus;
336}
337
338static VAStatus vsp_vp8_process_dynamic_seqence_param(
339    context_VPP_p ctx)
340{
341
342    VAStatus vaStatus = VA_STATUS_SUCCESS;
343    vsp_cmdbuf_p cmdbuf = ctx->obj_context->vsp_cmdbuf;
344    int i;
345    int ref_frame_width, ref_frame_height;
346
347    struct VssVp8encSequenceParameterBuffer *seq =
348            (struct VssVp8encSequenceParameterBuffer *)cmdbuf->seq_param_p;
349
350    if( ctx->vp8_seq_cmd_send )
351    {  //just change the command buffer
352       seq->frame_rate = ctx->frame_rate;
353	seq->rc_min_quantizer = ctx->min_qp;
354	seq->cyclic_intra_refresh = ctx->cyclic_intra_refresh;
355	seq->rc_target_bitrate = ctx->bits_per_second / 1000 ;
356	seq->max_intra_rate = ctx->max_frame_size *30 * 1000 / ctx->bits_per_second;
357	return vaStatus;
358    }
359
360    *seq = ctx->vp8_seq_param ;
361     seq->frame_rate = ctx->frame_rate;
362     seq->rc_min_quantizer = ctx->min_qp;
363     seq->cyclic_intra_refresh = ctx->cyclic_intra_refresh;
364     seq->rc_target_bitrate = ctx->bits_per_second / 1000 ;
365     seq->max_intra_rate = ctx->max_frame_size *30 * 1000 / ctx->bits_per_second;
366
367
368    vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VP8_ID, &cmdbuf->param_mem,
369                              VssVp8encSetSequenceParametersCommand,
370                              ctx->seq_param_offset,
371                              sizeof(struct VssVp8encSequenceParameterBuffer));
372
373    return vaStatus;
374}
375
376
377static VAStatus vsp_vp8_process_picture_param(
378    psb_driver_data_p driver_data,
379    context_VPP_p ctx,
380    object_buffer_p obj_buffer,
381    VASurfaceID surface_id)
382
383{
384    VAStatus vaStatus = VA_STATUS_SUCCESS;
385    vsp_cmdbuf_p cmdbuf = ctx->obj_context->vsp_cmdbuf;
386
387    VAEncSequenceParameterBufferVP8 *va_seq =
388            (VAEncSequenceParameterBufferVP8 *) obj_buffer->buffer_data;
389    VAEncPictureParameterBufferVP8 *va_pic =
390            (VAProcPipelineParameterBuffer *) obj_buffer->buffer_data;
391    struct VssVp8encPictureParameterBuffer *pic = cmdbuf->pic_param_p;
392    struct VssVp8encSequenceParameterBuffer *seq =
393           (struct VssVp8encSequenceParameterBuffer *)cmdbuf->seq_param_p;
394    VACodedBufferSegment *p = &obj_buffer->codedbuf_mapinfo[0];
395    int ref_frame_width, ref_frame_height;
396
397    ref_frame_width = (ctx->frame_width + 2 * 32 + 63) & (~63);
398    ref_frame_height = (ctx->frame_height + 2 * 32 + 63) & (~63);
399
400    //map parameters
401    object_buffer_p pObj = BUFFER(va_pic->coded_buf); //tobe modified
402    if (!pObj)
403		return VA_STATUS_ERROR_UNKNOWN;
404
405    object_surface_p src_surface = SURFACE(surface_id);
406
407    pic->input_frame.surface_id = surface_id;
408    pic->input_frame.irq        = 1;
409    pic->input_frame.height     = ctx->frame_height;
410    pic->input_frame.width      = ctx->frame_width;
411    /* NOTE: In VIED API doc, stride must be the nearest integer multiple of 32 */
412    /* use vaCreateSurfaceWithAttribute with VAExternalMemoryNULL to create surface*/
413    //pic->input_frame.stride     = (ctx->frame_width + 31) & (~31);
414    pic->input_frame.stride     = ctx->obj_context->current_render_target->psb_surface->stride;
415    pic->input_frame.format     = 0; /* TODO: Specify NV12 = 0 */
416
417    pic->recon_frame.irq = 0;
418    pic->recon_frame.width = ref_frame_width;
419    pic->recon_frame.height = ref_frame_height;
420
421    pic->version = 0;
422#if 0
423    pic->pic_flags = (1<< 2) |  /* corresponds to  VP8_EFLAG_NO_REF_GF      */
424                     (1<< 3) |  /* corresponds to  VP8_EFLAG_NO_REF_ARF     */
425                     (1<< 12);   /* corresponds to ~VP8_EFLAG_NO_UPD_ENTROPY */
426#else
427   vp8_fw_pic_flags flags;
428   flags.value =0;
429
430   flags.bits.force_kf = va_pic->ref_flags.bits.force_kf;
431   flags.bits.no_ref_last = va_pic->ref_flags.bits.no_ref_last;
432   flags.bits.no_ref_gf = va_pic->ref_flags.bits.no_ref_gf;
433   flags.bits.no_ref_arf = va_pic->ref_flags.bits.no_ref_arf;
434   flags.bits.upd_last  = va_pic->pic_flags.bits.refresh_last;
435   flags.bits.upd_gf  =0;//= va_pic->pic_flags.bits.refresh_golden_frame;
436   flags.bits.upd_arf  =0;//= va_pic->pic_flags.bits.refresh_alternate_frame;
437   flags.bits.no_upd_last  = !va_pic->pic_flags.bits.refresh_last;
438   flags.bits.no_upd_gf  = !va_pic->pic_flags.bits.refresh_golden_frame;
439   flags.bits.no_upd_arf  = !va_pic->pic_flags.bits.refresh_alternate_frame;
440   flags.bits.no_upd_entropy  = !va_pic->pic_flags.bits.refresh_entropy_probs;
441
442   pic->pic_flags = flags.value;
443#endif
444    pic->prev_frame_dropped = 0; /* Not yet used */
445    pic->cpuused            = 5;
446    pic->sharpness          = va_pic->sharpness_level;
447    pic->num_token_partitions = va_pic->pic_flags.bits.num_token_partitions; /* 2^2 = 4 partitions */
448    pic->encoded_frame_size = pObj->size & ~31;
449    pic->encoded_frame_base = pObj->buffer_data  ;//tobe modified
450
451    {
452        vsp_cmdbuf_reloc_pic_param(&(pic->encoded_frame_base),
453                                   ctx->pic_param_offset, pObj->psb_buffer,
454                                   cmdbuf->param_mem_loc, pic);
455    }
456
457    {
458        object_surface_p cur_surf = SURFACE(surface_id);
459	if(!cur_surf)
460		return VA_STATUS_ERROR_UNKNOWN;
461
462        vsp_cmdbuf_reloc_pic_param(&(pic->input_frame.base),
463                                   ctx->pic_param_offset, &(cur_surf->psb_surface->buf),
464                                   cmdbuf->param_mem_loc, pic);
465    }
466
467    //vsp_cmdbuf_insert_command(cmdbuf, &cmdbuf->param_mem,
468    //                        VssVp8encEncodeFrameCommand,
469    //                        ctx->pic_param_offset,
470    //                        sizeof(VssVp8encPictureParameterBuffer));
471    //vsp_cmdbuf_fence_pic_param(cmdbuf, wsbmKBufHandle(wsbmKBuf(cmdbuf->param_mem.drm_buf)));
472
473    do { *cmdbuf->cmd_idx++ = CONTEXT_VP8_ID;\
474         *cmdbuf->cmd_idx++ = VssVp8encEncodeFrameCommand;\
475         VSP_RELOC_CMDBUF(cmdbuf->cmd_idx++, ctx->pic_param_offset, &cmdbuf->param_mem);\
476         *cmdbuf->cmd_idx++ = sizeof(struct VssVp8encPictureParameterBuffer);\
477         *cmdbuf->cmd_idx++ = 0; *cmdbuf->cmd_idx++ = 0;\
478         *cmdbuf->cmd_idx++ = wsbmKBufHandle(wsbmKBuf(pObj->psb_buffer->drm_buf)) ; \
479         *cmdbuf->cmd_idx++ = wsbmKBufHandle(wsbmKBuf((&cmdbuf->param_mem)->drm_buf)); } while(0);
480
481    return vaStatus;
482}
483
484static VAStatus vsp_vp8_process_misc_param(context_VPP_p ctx, object_buffer_p obj_buffer)
485{
486    VAEncMiscParameterBuffer *pBuffer;
487    VAEncMiscParameterAIR *air_param;
488    VAEncMiscParameterBufferMaxFrameSize *max_frame_size_param;
489    VAEncMiscParameterFrameRate *frame_rate_param;
490    VAEncMiscParameterRateControl *rate_control_param;
491    VAEncMiscParameterHRD *hrd_param;
492    VAStatus vaStatus = VA_STATUS_SUCCESS;
493    ASSERT(obj_buffer->type == VAEncMiscParameterBufferType);
494    pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data;
495    obj_buffer->size = 0;
496    switch (pBuffer->type) {
497    case VAEncMiscParameterTypeFrameRate:
498        frame_rate_param = (VAEncMiscParameterFrameRate *)pBuffer->data;
499        if (frame_rate_param->framerate < 1 || frame_rate_param->framerate > 65535) {
500            vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
501            break;
502        }
503        if (ctx->frame_rate == frame_rate_param->framerate)
504            break;
505        drv_debug_msg(VIDEO_DEBUG_GENERAL, "frame rate changed from %d to %d\n",
506                      ctx->frame_rate,
507                      frame_rate_param->framerate);
508        ctx->frame_rate = frame_rate_param->framerate;
509        ctx->re_send_seq_params = 1 ;
510        break;
511    case VAEncMiscParameterTypeRateControl:
512        rate_control_param = (VAEncMiscParameterRateControl *)pBuffer->data;
513        if (rate_control_param->initial_qp > 63 ||
514            rate_control_param->min_qp > 63) {
515            drv_debug_msg(VIDEO_DEBUG_ERROR, "Initial_qp(%d) and min_qpinitial_qp(%d) "
516                          "are invalid.\nQP shouldn't be larger than 63 for VP8\n",
517                          rate_control_param->initial_qp, rate_control_param->min_qp);
518            vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
519            break;
520        }
521        if (rate_control_param->min_qp == ctx->min_qp
522            && rate_control_param->bits_per_second  == ctx->bits_per_second) {
523            break;
524        }
525        if (rate_control_param->min_qp != ctx->min_qp) {
526            drv_debug_msg(VIDEO_DEBUG_ERROR, "min_qp was changed from %d to %d\n",
527                          ctx->min_qp, rate_control_param->min_qp);
528            ctx->min_qp = rate_control_param->min_qp;
529        }
530        if (rate_control_param->max_qp != ctx->max_qp) {
531            drv_debug_msg(VIDEO_DEBUG_ERROR, "max_qp was changed from %d to %d\n",
532                          ctx->max_qp, rate_control_param->max_qp);
533            ctx->max_qp = rate_control_param->max_qp;
534        }
535        if (rate_control_param->initial_qp != ctx->initial_qp) {
536            drv_debug_msg(VIDEO_DEBUG_ERROR, "Initial_qp was changed from %d to %d\n",
537                          ctx->initial_qp, rate_control_param->initial_qp);
538            ctx->initial_qp = rate_control_param->initial_qp;
539        }
540        if (rate_control_param->bits_per_second != ctx->bits_per_second) {
541            drv_debug_msg(VIDEO_DEBUG_ERROR, "Initial_qp was changed from %d to %d\n",
542                          ctx->bits_per_second, rate_control_param->bits_per_second);
543            ctx->bits_per_second = rate_control_param->bits_per_second;
544        }
545        if (rate_control_param->target_percentage != ctx->rc_undershoot) {
546            drv_debug_msg(VIDEO_DEBUG_ERROR, "rc_undershoot was changed from %d to %d\n",
547                          ctx->rc_undershoot, rate_control_param->target_percentage);
548            ctx->rc_undershoot = rate_control_param->target_percentage;
549        }
550
551        ctx->re_send_seq_params = 1 ;
552        break;
553    case VAEncMiscParameterTypeMaxFrameSize:
554        max_frame_size_param = (VAEncMiscParameterBufferMaxFrameSize *)pBuffer->data;
555        if (ctx->max_frame_size == max_frame_size_param->max_frame_size)
556            break;
557        drv_debug_msg(VIDEO_DEBUG_GENERAL, "max frame size changed from %d to %d\n",
558                      ctx->max_frame_size, max_frame_size_param->max_frame_size);
559        ctx->max_frame_size = max_frame_size_param->max_frame_size ;
560        ctx->re_send_seq_params = 1 ;
561        break;
562    case VAEncMiscParameterTypeAIR:
563        air_param = (VAEncMiscParameterAIR *)pBuffer->data;
564        if (air_param->air_num_mbs > 65535 ||
565            air_param->air_threshold > 65535) {
566            vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
567            break;
568        }
569        drv_debug_msg(VIDEO_DEBUG_GENERAL, "air slice size changed to num_air_mbs %d "
570                      "air_threshold %d, air_auto %d\n",
571                      air_param->air_num_mbs, air_param->air_threshold,
572                      air_param->air_auto);
573        ctx->cyclic_intra_refresh = air_param->air_threshold;
574        break;
575    case VAEncMiscParameterTypeHRD:
576	hrd_param = (VAEncMiscParameterHRD *)pBuffer->data;
577	ctx->buffer_size = hrd_param->buffer_size;
578	ctx->initial_buffer_fullness = hrd_param->initial_buffer_fullness;
579	ctx->optimal_buffer_fullness = hrd_param->optimal_buffer_fullness;
580	break;
581    case VAEncMiscParameterTypeQualityLevel:
582	break;
583    default:
584        vaStatus = VA_STATUS_ERROR_UNKNOWN;
585        DEBUG_FAILURE;
586        break;
587    }
588    free(obj_buffer->buffer_data);
589    obj_buffer->buffer_data = NULL;
590    return vaStatus;
591}
592static VAStatus vsp_VP8_RenderPicture(
593    object_context_p obj_context,
594    object_buffer_p *buffers,
595    int num_buffers)
596{
597
598    int i;
599    psb_driver_data_p driver_data = obj_context->driver_data;
600    INIT_CONTEXT_VPP;
601    VASurfaceID surface_id;
602    VAStatus vaStatus = VA_STATUS_SUCCESS;
603
604    for (i = 0; i < num_buffers; i++)
605    {
606
607        object_buffer_p obj_buffer = buffers[i];
608        switch (obj_buffer->type) {
609        case VAEncSequenceParameterBufferType:
610            vaStatus = vsp_vp8_process_seqence_param(ctx, obj_buffer);
611            break;
612        case VAEncPictureParameterBufferType:
613            surface_id = obj_context->current_render_surface_id;
614            vaStatus = vsp_vp8_process_picture_param(driver_data,ctx, obj_buffer,surface_id);
615            break;
616        case VAEncMiscParameterBufferType:
617            vaStatus = vsp_vp8_process_misc_param(ctx, obj_buffer);
618            break;
619        default:
620            vaStatus = VA_STATUS_SUCCESS;//VA_STATUS_ERROR_UNKNOWN;
621            DEBUG_FAILURE;
622        }
623        if (vaStatus != VA_STATUS_SUCCESS) {
624            break;
625        }
626    }
627
628    return vaStatus;
629}
630
631static VAStatus vsp_VP8_BeginPicture(
632    object_context_p obj_context)
633{
634    int ret;
635    VAStatus vaStatus = VA_STATUS_SUCCESS;
636    INIT_CONTEXT_VPP;
637    vsp_cmdbuf_p cmdbuf;
638
639    /* Initialise the command buffer */
640    ret = vsp_context_get_next_cmdbuf(ctx->obj_context);
641    if (ret) {
642        drv_debug_msg(VIDEO_DEBUG_GENERAL, "get next cmdbuf fail\n");
643            vaStatus = VA_STATUS_ERROR_UNKNOWN;
644            return vaStatus;
645     }
646
647    cmdbuf = obj_context->vsp_cmdbuf;
648
649    if (ctx->obj_context->frame_count == 0) /* first picture */
650    {
651        vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VP8_ID, ctx->context_buf, Vss_Sys_STATE_BUF_COMMAND,
652                                  0, VSP_VP8ENC_STATE_SIZE);
653    }
654
655    /* map param mem */
656    vaStatus = psb_buffer_map(&cmdbuf->param_mem, &cmdbuf->param_mem_p);
657    if (vaStatus) {
658        return vaStatus;
659    }
660
661    cmdbuf->pic_param_p = cmdbuf->param_mem_p;
662    cmdbuf->seq_param_p = cmdbuf->param_mem_p + ctx->seq_param_offset;
663    cmdbuf->ref_param_p = cmdbuf->param_mem_p + ctx->ref_param_offset;
664    ctx->vp8_seq_cmd_send = 0;
665    ctx->re_send_seq_params = 0;
666    return VA_STATUS_SUCCESS;
667}
668
669static VAStatus vsp_VP8_EndPicture(
670    object_context_p obj_context)
671{
672    INIT_CONTEXT_VPP;
673    psb_driver_data_p driver_data = obj_context->driver_data;
674    vsp_cmdbuf_p cmdbuf = obj_context->vsp_cmdbuf;
675
676    if(ctx->re_send_seq_params)
677    {
678        vsp_vp8_process_dynamic_seqence_param(ctx);
679    }
680
681    if (cmdbuf->param_mem_p != NULL) {
682        psb_buffer_unmap(&cmdbuf->param_mem);
683        cmdbuf->param_mem_p = NULL;
684        cmdbuf->pic_param_p = NULL;
685        cmdbuf->end_param_p = NULL;
686        cmdbuf->pipeline_param_p = NULL;
687        cmdbuf->denoise_param_p = NULL;
688        cmdbuf->enhancer_param_p = NULL;
689        cmdbuf->sharpen_param_p = NULL;
690        cmdbuf->frc_param_p = NULL;
691        cmdbuf->ref_param_p = NULL;
692     }
693
694//    ctx->obj_context->frame_count++;
695
696
697    if (vsp_context_flush_cmdbuf(ctx->obj_context))
698        drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_VPP: flush deblock cmdbuf error\n");
699
700    return VA_STATUS_SUCCESS;
701}
702
703struct format_vtable_s vsp_VP8_vtable = {
704queryConfigAttributes:
705    vsp_VP8_QueryConfigAttributes,
706validateConfig:
707    vsp_VP8_ValidateConfig,
708createContext:
709    vsp_VP8_CreateContext,
710destroyContext:
711    vsp_VP8_DestroyContext,
712beginPicture:
713    vsp_VP8_BeginPicture,
714renderPicture:
715    vsp_VP8_RenderPicture,
716endPicture:
717    vsp_VP8_EndPicture
718};
719
720