Home | History | Annotate | Download | only in src
      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 (at) intel.com>
     26  *    Mingruo Sun <mingruo.sun (at) 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 (1*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 0
     56 #define VP8_ENC_CBR_HRD 1
     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 
     61 enum filter_status {
     62     FILTER_DISABLED = 0,
     63     FILTER_ENABLED
     64 };
     65 
     66 typedef 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 
     77 typedef 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 upd_entropy                     : 1;
     95     } bits;
     96     unsigned int value;
     97 } vp8_fw_pic_flags;
     98 
     99 
    100 static void vsp_VP8_DestroyContext(object_context_p obj_context);
    101 
    102 static VAStatus vsp__VP8_check_legal_picture(object_context_p obj_context, object_config_p obj_config);
    103 
    104 static void vsp_VP8_QueryConfigAttributes(
    105     VAProfile __maybe_unused profile,
    106     VAEntrypoint __maybe_unused 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_VCM | 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         case VAConfigAttribEncRateControlExt:
    127             attrib_list[i].value = 3;
    128             break;
    129 
    130         default:
    131             attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
    132             break;
    133         }
    134     }
    135 }
    136 
    137 static VAStatus vsp_VP8_ValidateConfig(
    138     object_config_p obj_config)
    139 {
    140     int i;
    141     drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s\n", __FUNCTION__);
    142 
    143     /* Check all attributes */
    144     for (i = 0; i < obj_config->attrib_count; i++) {
    145         switch (obj_config->attrib_list[i].type) {
    146         case VAConfigAttribRTFormat:
    147             /* Ignore */
    148             break;
    149         case VAConfigAttribRateControl:
    150             break;
    151         case VAConfigAttribEncAutoReference:
    152             break;
    153         case VAConfigAttribEncMaxRefFrames:
    154             break;
    155         case VAConfigAttribEncRateControlExt:
    156             break;
    157 
    158         default:
    159             return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
    160         }
    161     }
    162 
    163     return VA_STATUS_SUCCESS;
    164 }
    165 
    166 void vsp_VP8_set_default_params(struct VssVp8encSequenceParameterBuffer *vp8_seq)
    167 {
    168 
    169     vp8_seq->frame_width = 1280;
    170     vp8_seq->frame_height = 720;
    171     vp8_seq->frame_rate = 30;
    172     vp8_seq->error_resilient = 0;
    173     vp8_seq->num_token_partitions = 2;
    174     vp8_seq->kf_mode = 1;
    175     vp8_seq->kf_min_dist = 0;
    176     vp8_seq->kf_max_dist = 30;
    177     vp8_seq->rc_target_bitrate = 2000;
    178     vp8_seq->rc_min_quantizer = 4;
    179     vp8_seq->rc_max_quantizer = 63;
    180     vp8_seq->rc_undershoot_pct = 100;
    181     vp8_seq->rc_overshoot_pct = 100;
    182     vp8_seq->rc_end_usage = VP8_ENC_CBR;
    183     vp8_seq->rc_buf_sz = 6000;
    184     vp8_seq->rc_buf_initial_sz = 4000;
    185     vp8_seq->rc_buf_optimal_sz = 5000;
    186     vp8_seq->max_intra_rate = 0;
    187     vp8_seq->cyclic_intra_refresh = 0;
    188     vp8_seq->concatenate_partitions = 1;
    189     vp8_seq->recon_buffer_mode = vss_vp8enc_seq_param_recon_buffer_mode_per_seq;
    190     vp8_seq->ts_number_layers = 1;
    191     vp8_seq->ts_layer_id[0] = 0;
    192     vp8_seq->ts_rate_decimator[0] = 0;
    193     vp8_seq->ts_periodicity = 0;
    194     vp8_seq->ts_target_bitrate[0] = 0;
    195 }
    196 
    197 static VAStatus vsp_VP8_CreateContext(
    198     object_context_p obj_context,
    199     object_config_p obj_config)
    200 {
    201     VAStatus vaStatus = VA_STATUS_SUCCESS;
    202     /* currently vp8 will use vpp's context since they will use the same cmdbuf */
    203     context_VPP_p ctx;
    204     int i;
    205 
    206     ctx = (context_VPP_p) calloc(1, sizeof(struct context_VPP_s));
    207     if (NULL == ctx) {
    208         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    209         DEBUG_FAILURE;
    210         return vaStatus;
    211     }
    212 
    213     //set default VP8 sequence params
    214     vsp_VP8_set_default_params(&ctx->vp8_seq_param);
    215     ctx->temporal_layer_number = 1;
    216 
    217     for (i = 0; i < obj_config->attrib_count; i++) {
    218         if (obj_config->attrib_list[i].type == VAConfigAttribRateControl) {
    219             if (obj_config->attrib_list[i].value == VA_RC_VCM)
    220                ctx->vp8_seq_param.rc_end_usage = VP8_ENC_CBR_HRD;
    221             else
    222                ctx->vp8_seq_param.rc_end_usage = VP8_ENC_CBR;
    223         }
    224     }
    225 
    226     /* set size */
    227     ctx->param_sz = 0;
    228     ctx->pic_param_sz = ALIGN_TO_128(sizeof(struct VssVp8encPictureParameterBuffer));
    229     ctx->param_sz += ctx->pic_param_sz;
    230     ctx->seq_param_sz = ALIGN_TO_128(sizeof(struct VssVp8encSequenceParameterBuffer));
    231     ctx->param_sz += ctx->seq_param_sz;
    232     ctx->ref_param_sz = ALIGN_TO_128(sizeof(ref_frame_surface));
    233     ctx->param_sz += ctx->ref_param_sz;
    234 
    235     /* set offset */
    236     ctx->pic_param_offset = 0;
    237     ctx->seq_param_offset = ctx->pic_param_sz;
    238     ctx->ref_param_offset = ctx->pic_param_sz + ctx->seq_param_sz;
    239 
    240 
    241     ctx->context_buf = (psb_buffer_p) calloc(1, sizeof(struct psb_buffer_s));
    242     if (NULL == ctx->context_buf) {
    243         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    244         DEBUG_FAILURE;
    245         goto out;
    246     }
    247 
    248     vaStatus = psb_buffer_create(obj_context->driver_data, VSP_VP8ENC_STATE_SIZE, psb_bt_vpu_only, ctx->context_buf);
    249 
    250     if (VA_STATUS_SUCCESS != vaStatus) {
    251         goto out;
    252     }
    253 
    254     obj_context->format_data = (void*) ctx;
    255     ctx->obj_context = obj_context;
    256 
    257     return vaStatus;
    258 
    259 out:
    260     vsp_VP8_DestroyContext(obj_context);
    261 
    262     if (ctx) {
    263         if(ctx->context_buf != NULL)
    264             free(ctx->context_buf);
    265         free(ctx);
    266         ctx = NULL;
    267     }
    268 
    269     return vaStatus;
    270 }
    271 
    272 static void vsp_VP8_DestroyContext(
    273     object_context_p obj_context)
    274 {
    275     INIT_CONTEXT_VPP;
    276 
    277     if (ctx->context_buf) {
    278         psb_buffer_destroy(ctx->context_buf);
    279         free(ctx->context_buf);
    280         ctx->context_buf = NULL;
    281     }
    282 
    283     if (ctx->filters) {
    284         free(ctx->filters);
    285         ctx->num_filters = 0;
    286     }
    287 
    288     free(obj_context->format_data);
    289     obj_context->format_data = NULL;
    290 }
    291 
    292 static VAStatus vsp_vp8_process_seqence_param(
    293     psb_driver_data_p driver_data,
    294     context_VPP_p ctx,
    295     object_buffer_p obj_buffer)
    296 {
    297 
    298     VAStatus vaStatus = VA_STATUS_SUCCESS;
    299     vsp_cmdbuf_p cmdbuf = ctx->obj_context->vsp_cmdbuf;
    300     int i;
    301     int ref_frame_width, ref_frame_height, ref_chroma_height, ref_size;
    302 
    303     VAEncSequenceParameterBufferVP8 *va_seq =
    304         (VAEncSequenceParameterBufferVP8 *) obj_buffer->buffer_data;
    305     struct VssVp8encSequenceParameterBuffer *seq = &ctx->vp8_seq_param;
    306     struct VssVp8encSequenceParameterBuffer *seq_to_firmware =
    307         (struct VssVp8encSequenceParameterBuffer *)cmdbuf->seq_param_p;
    308 
    309     struct ref_frame_surface *ref =
    310         (struct ref_frame_surface*)cmdbuf->ref_param_p;
    311 
    312     seq->frame_width       = va_seq->frame_width;
    313     seq->frame_height      = va_seq->frame_height;
    314     seq->rc_target_bitrate = va_seq->bits_per_second / 1000;
    315     seq->max_intra_rate    = 100 * ctx->max_frame_size /
    316                              (va_seq->bits_per_second / seq->frame_rate);
    317     /* FIXME: API doc says max 5000, but for current default test vector we still use 6000 */
    318     seq->kf_mode           = va_seq->kf_auto;   /* AUTO */
    319     seq->kf_max_dist       = va_seq->kf_max_dist;
    320     seq->kf_min_dist       = va_seq->kf_min_dist;
    321     seq->error_resilient   = va_seq->error_resilient;
    322 
    323     ref_frame_width = (seq->frame_width + 2 * 32 + 63) & (~63);
    324     ref_frame_height = (seq->frame_height + 2 * 32 + 63) & (~63);
    325     ref_chroma_height = (ref_frame_height / 2 + 63) & (~63);
    326     ref_size = ref_frame_width * (ref_frame_height + ref_chroma_height);
    327 
    328     for (i = 0; i < 4; i++) {
    329         seq->ref_frame_buffers[i].surface_id = va_seq->reference_frames[i];
    330         seq->ref_frame_buffers[i].width = ref_frame_width;
    331         seq->ref_frame_buffers[i].height = ref_frame_height;
    332     }
    333 
    334     for (i = 0; i < 4; i++) {
    335         object_surface_p ref_surf = SURFACE(va_seq->reference_frames[i]);
    336         if (!ref_surf)
    337             return VA_STATUS_ERROR_UNKNOWN;
    338 
    339         ref_surf->is_ref_surface = 2;
    340 
    341         if (ref_surf->psb_surface->size < ref_size) {
    342             /* re-alloc buffer */
    343             ref_surf->psb_surface->size = ref_size;
    344             psb_buffer_destroy(&ref_surf->psb_surface->buf);
    345             vaStatus = psb_buffer_create(driver_data, ref_surf->psb_surface->size, psb_bt_surface, &ref_surf->psb_surface->buf);
    346             if (VA_STATUS_SUCCESS != vaStatus)
    347                 return VA_STATUS_ERROR_ALLOCATION_FAILED;
    348         }
    349 
    350         vsp_cmdbuf_reloc_pic_param(&(seq->ref_frame_buffers[i].base),
    351                                    0,
    352                                    &(ref_surf->psb_surface->buf),
    353                                    cmdbuf->param_mem_loc, seq);
    354     }
    355 
    356     *seq_to_firmware = *seq;
    357 
    358     vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VP8_ID, &cmdbuf->param_mem,
    359                               VssVp8encSetSequenceParametersCommand,
    360                               ctx->seq_param_offset,
    361                               sizeof(struct VssVp8encSequenceParameterBuffer));
    362     ctx->vp8_seq_cmd_send = 1;
    363 
    364     return vaStatus;
    365 }
    366 
    367 static VAStatus vsp_vp8_process_dynamic_seqence_param(
    368     context_VPP_p ctx)
    369 {
    370 
    371     VAStatus vaStatus = VA_STATUS_SUCCESS;
    372     vsp_cmdbuf_p cmdbuf = ctx->obj_context->vsp_cmdbuf;
    373     int ref_frame_width, ref_frame_height;
    374 
    375     struct VssVp8encSequenceParameterBuffer *seq =
    376         (struct VssVp8encSequenceParameterBuffer *)cmdbuf->seq_param_p;
    377 
    378     *seq = ctx->vp8_seq_param ;
    379     seq->max_intra_rate    = 100 * ctx->max_frame_size /
    380                              (seq->rc_target_bitrate * 1000 / seq->frame_rate);
    381 
    382     if (!ctx->vp8_seq_cmd_send) {
    383         vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VP8_ID, &cmdbuf->param_mem,
    384                                   VssVp8encSetSequenceParametersCommand,
    385                                   ctx->seq_param_offset,
    386                                   sizeof(struct VssVp8encSequenceParameterBuffer));
    387     }
    388 
    389     return vaStatus;
    390 }
    391 
    392 
    393 static VAStatus vsp_vp8_process_picture_param(
    394     psb_driver_data_p driver_data,
    395     context_VPP_p ctx,
    396     object_buffer_p obj_buffer,
    397     VASurfaceID surface_id)
    398 
    399 {
    400     VAStatus vaStatus = VA_STATUS_SUCCESS;
    401     vsp_cmdbuf_p cmdbuf = ctx->obj_context->vsp_cmdbuf;
    402 
    403     VAEncPictureParameterBufferVP8 *va_pic =
    404         (VAEncPictureParameterBufferVP8 *) obj_buffer->buffer_data;
    405     struct VssVp8encPictureParameterBuffer *pic =
    406         (struct VssVp8encPictureParameterBuffer *)cmdbuf->pic_param_p;
    407     struct VssVp8encSequenceParameterBuffer *seq =
    408         (struct VssVp8encSequenceParameterBuffer *)cmdbuf->seq_param_p;
    409     int ref_frame_width, ref_frame_height;
    410     vp8_fw_pic_flags flags;
    411 
    412     ref_frame_width = (ctx->vp8_seq_param.frame_width + 2 * 32 + 63) & (~63);
    413     ref_frame_height = (ctx->vp8_seq_param.frame_height + 2 * 32 + 63) & (~63);
    414 
    415     //map parameters
    416     object_buffer_p pObj = BUFFER(va_pic->coded_buf); //tobe modified
    417     if (!pObj)
    418         return VA_STATUS_ERROR_UNKNOWN;
    419 
    420     object_surface_p src_surface = SURFACE(surface_id);
    421 
    422     pic->input_frame.surface_id = surface_id;
    423     pic->input_frame.irq        = 1;
    424     pic->input_frame.height     = ctx->vp8_seq_param.frame_height;
    425     pic->input_frame.width      = ctx->vp8_seq_param.frame_width;
    426     /* NOTE: In VIED API doc, stride must be the nearest integer multiple of 32 */
    427     /* use vaCreateSurfaceWithAttribute with VAExternalMemoryNULL to create surface*/
    428     //pic->input_frame.stride     = (ctx->frame_width + 31) & (~31);
    429     pic->input_frame.stride     = ctx->obj_context->current_render_target->psb_surface->stride;
    430     pic->input_frame.format     = 0; /* TODO: Specify NV12 = 0 */
    431 
    432     pic->recon_frame.irq = 0;
    433     pic->recon_frame.width = ref_frame_width;
    434     pic->recon_frame.height = ref_frame_height;
    435 
    436     pic->version = 0;
    437 
    438     flags.value = 0;
    439     flags.bits.force_kf = va_pic->ref_flags.bits.force_kf;
    440     flags.bits.no_ref_last = va_pic->ref_flags.bits.no_ref_last;
    441     flags.bits.no_ref_gf = va_pic->ref_flags.bits.no_ref_gf;
    442     flags.bits.no_ref_arf = va_pic->ref_flags.bits.no_ref_arf;
    443     flags.bits.upd_last  = va_pic->pic_flags.bits.refresh_last;
    444     flags.bits.upd_gf  = va_pic->pic_flags.bits.copy_buffer_to_golden;
    445     flags.bits.upd_arf  = va_pic->pic_flags.bits.copy_buffer_to_alternate;
    446     flags.bits.no_upd_last  = !va_pic->pic_flags.bits.refresh_last;
    447     flags.bits.no_upd_gf  = !va_pic->pic_flags.bits.refresh_golden_frame;
    448     flags.bits.no_upd_arf  = !va_pic->pic_flags.bits.refresh_alternate_frame;
    449     flags.bits.upd_entropy  = va_pic->pic_flags.bits.refresh_entropy_probs;
    450     if (ctx->temporal_layer_number > 1)
    451         flags.bits.upd_entropy = 0;
    452     pic->pic_flags = flags.value;
    453 
    454     pic->prev_frame_dropped = 0; /* Not yet used */
    455     pic->cpuused            = 5;
    456     pic->sharpness          = va_pic->sharpness_level;
    457     pic->num_token_partitions = va_pic->pic_flags.bits.num_token_partitions; /* 2^2 = 4 partitions */
    458     pic->encoded_frame_size = pObj->size & ~31;
    459     pic->encoded_frame_base = (uint32_t)pObj->buffer_data;
    460 
    461     {
    462         vsp_cmdbuf_reloc_pic_param(&(pic->encoded_frame_base),
    463                                    ctx->pic_param_offset, pObj->psb_buffer,
    464                                    cmdbuf->param_mem_loc, pic);
    465     }
    466 
    467     {
    468         object_surface_p cur_surf = SURFACE(surface_id);
    469         if (!cur_surf)
    470             return VA_STATUS_ERROR_UNKNOWN;
    471 
    472         vsp_cmdbuf_reloc_pic_param(&(pic->input_frame.base),
    473                                    0, &(cur_surf->psb_surface->buf),
    474                                    cmdbuf->param_mem_loc, pic);
    475         vsp_cmdbuf_reloc_pic_param(&(pic->input_frame.base_uv),
    476                                    pic->input_frame.stride * ctx->obj_context->current_render_target->height,
    477                                    &(cur_surf->psb_surface->buf),
    478                                    cmdbuf->param_mem_loc, pic);
    479     }
    480 
    481     *cmdbuf->cmd_idx++ = CONTEXT_VP8_ID;
    482     *cmdbuf->cmd_idx++ = VssVp8encEncodeFrameCommand;
    483     VSP_RELOC_CMDBUF(cmdbuf->cmd_idx++, ctx->pic_param_offset, &cmdbuf->param_mem);
    484     *cmdbuf->cmd_idx++ = sizeof(struct VssVp8encPictureParameterBuffer);
    485     *cmdbuf->cmd_idx++ = 0;
    486     *cmdbuf->cmd_idx++ = 0;
    487     *cmdbuf->cmd_idx++ = wsbmKBufHandle(wsbmKBuf(pObj->psb_buffer->drm_buf)) ;
    488     *cmdbuf->cmd_idx++ = wsbmKBufHandle(wsbmKBuf((&cmdbuf->param_mem)->drm_buf));
    489 
    490     return vaStatus;
    491 }
    492 
    493 static VAStatus vsp_vp8_process_misc_param(context_VPP_p ctx, object_buffer_p obj_buffer)
    494 {
    495     VAEncMiscParameterBuffer *pBuffer;
    496     VAEncMiscParameterAIR *air_param;
    497     VAEncMiscParameterBufferMaxFrameSize *max_frame_size_param;
    498     VAEncMiscParameterFrameRate *frame_rate_param;
    499     VAEncMiscParameterRateControl *rate_control_param;
    500     VAEncMiscParameterHRD *hrd_param;
    501     VAEncMiscParameterTemporalLayerStructure* tslayer_param;
    502     struct VssVp8encSequenceParameterBuffer *seq = &ctx->vp8_seq_param;
    503     VAStatus vaStatus = VA_STATUS_SUCCESS;
    504     uint32_t layer_id, i;
    505 
    506     ASSERT(obj_buffer->type == VAEncMiscParameterBufferType);
    507     pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data;
    508     obj_buffer->size = 0;
    509 
    510     switch (pBuffer->type) {
    511     case VAEncMiscParameterTypeTemporalLayerStructure:
    512         tslayer_param = (VAEncMiscParameterTemporalLayerStructure *)pBuffer->data;
    513         //verify parameter
    514         if (tslayer_param->number_of_layers < 2 && tslayer_param->number_of_layers > 3) {
    515             drv_debug_msg(VIDEO_DEBUG_ERROR, "Temporal Layer Number should be 2 or 3\n");
    516             vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
    517             break;
    518         }
    519 
    520         if (tslayer_param->periodicity > 32 || tslayer_param->periodicity < 1) {
    521             drv_debug_msg(VIDEO_DEBUG_ERROR, "ts_periodicity shoulde be 1 - 32\n");
    522             vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
    523             break;
    524         }
    525 
    526         for (i = 0; i < tslayer_param->periodicity; i++) {
    527             layer_id = tslayer_param->layer_id[i];
    528             if (layer_id > (tslayer_param->number_of_layers - 1)) {
    529                 drv_debug_msg(VIDEO_DEBUG_ERROR, "layer_id shoulde be 0 - %d\n",
    530                               tslayer_param->number_of_layers - 1);
    531                 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
    532                 break;
    533             }
    534         }
    535 
    536         if (vaStatus == VA_STATUS_ERROR_INVALID_PARAMETER)
    537             break;
    538 
    539         seq->ts_number_layers = tslayer_param->number_of_layers;
    540         ctx->temporal_layer_number = tslayer_param->number_of_layers;
    541         seq->ts_periodicity = tslayer_param->periodicity;
    542 
    543         for (i = 0; i < seq->ts_periodicity; i++)
    544             seq->ts_layer_id[i] = tslayer_param->layer_id[i];
    545 
    546         //set default bitrate and framerate
    547         if (seq->ts_number_layers == 2) {
    548             seq->ts_target_bitrate[0] = seq->rc_target_bitrate * 6 / 10;
    549             seq->ts_target_bitrate[1] = seq->rc_target_bitrate ;
    550             seq->ts_rate_decimator[0] = 2;
    551             seq->ts_rate_decimator[1] = 1;
    552         }
    553         if (seq->ts_number_layers == 3) {
    554             seq->ts_target_bitrate[0] = seq->rc_target_bitrate * 4 / 10;
    555             seq->ts_target_bitrate[1] = seq->rc_target_bitrate * 6 / 10;
    556             seq->ts_target_bitrate[2] = seq->rc_target_bitrate ;
    557             seq->ts_rate_decimator[0] = 4;
    558             seq->ts_rate_decimator[1] = 2;
    559             seq->ts_rate_decimator[2] = 1;
    560         }
    561 
    562         ctx->re_send_seq_params = 1;
    563         break;
    564     case VAEncMiscParameterTypeFrameRate:
    565         frame_rate_param = (VAEncMiscParameterFrameRate *)pBuffer->data;
    566         if (frame_rate_param->framerate > 120) {
    567             drv_debug_msg(VIDEO_DEBUG_ERROR, "%d is invalid."
    568                           "framerate could not be larger than 120\n",
    569                           frame_rate_param->framerate);
    570             frame_rate_param->framerate = 120;
    571         }
    572         if (frame_rate_param->framerate < 1) {
    573             drv_debug_msg(VIDEO_DEBUG_ERROR, "%d is invalid."
    574                           "framerate could not be smaller than 1\n",
    575                           frame_rate_param->framerate);
    576             frame_rate_param->framerate = 1;
    577         }
    578 
    579         if (ctx->temporal_layer_number == 1) {
    580             if (seq->frame_rate != frame_rate_param->framerate) {
    581                 drv_debug_msg(VIDEO_DEBUG_GENERAL, "frame rate changed from %d to %d\n",
    582                               seq->frame_rate,
    583                               frame_rate_param->framerate);
    584                 seq->frame_rate = frame_rate_param->framerate;
    585                 ctx->re_send_seq_params = 1;
    586             }
    587         } else {
    588             layer_id = frame_rate_param->framerate_flags.bits.temporal_id % 3;
    589             if (ctx->frame_rate[layer_id] != frame_rate_param->framerate) {
    590                 drv_debug_msg(VIDEO_DEBUG_GENERAL, "frame rate of layer %d will be changed from %d to %d\n",
    591                               layer_id, ctx->frame_rate[layer_id], frame_rate_param->framerate);
    592                 ctx->frame_rate[layer_id] = frame_rate_param->framerate;
    593                 if (layer_id == ctx->temporal_layer_number - 1) { //top layer
    594                     seq->frame_rate = ctx->frame_rate[layer_id];
    595                 }
    596                 ctx->re_send_seq_params = 1 ;
    597             }
    598         }
    599         break;
    600     case VAEncMiscParameterTypeRateControl:
    601         rate_control_param = (VAEncMiscParameterRateControl *)pBuffer->data;
    602         if (rate_control_param->max_qp > 63 ||
    603             rate_control_param->min_qp > 63) {
    604             drv_debug_msg(VIDEO_DEBUG_ERROR, "max_qp(%d) and min_qp(%d) "
    605                           "are invalid.\nQP shouldn't be larger than 63 for VP8\n",
    606                           rate_control_param->max_qp, rate_control_param->min_qp);
    607             rate_control_param->max_qp = 63;
    608             rate_control_param->min_qp = rate_control_param->max_qp;
    609         }
    610 
    611         if (rate_control_param->min_qp != seq->rc_min_quantizer) {
    612             drv_debug_msg(VIDEO_DEBUG_ERROR, "min_qp was changed from %d to %d\n",
    613                           seq->rc_min_quantizer, rate_control_param->min_qp);
    614             seq->rc_min_quantizer = rate_control_param->min_qp;
    615         }
    616 
    617         if (rate_control_param->max_qp != seq->rc_max_quantizer) {
    618             drv_debug_msg(VIDEO_DEBUG_ERROR, "max_qp was changed from %d to %d\n",
    619                           seq->rc_max_quantizer, rate_control_param->max_qp);
    620             seq->rc_max_quantizer = rate_control_param->max_qp;
    621         }
    622 
    623         // no initial qp for vp8
    624 
    625         if (rate_control_param->target_percentage != seq->rc_undershoot_pct) {
    626             drv_debug_msg(VIDEO_DEBUG_ERROR, "rc_undershoot was changed from %d to %d\n",
    627                           seq->rc_undershoot_pct, rate_control_param->target_percentage);
    628             seq->rc_undershoot_pct = rate_control_param->target_percentage;
    629         }
    630 
    631         if (rate_control_param->bits_per_second / 1000 > 20000) {
    632             drv_debug_msg(VIDEO_DEBUG_ERROR, "%d is invalid."
    633                           "bitrate could not be larger than 20000\n",
    634                           rate_control_param->bits_per_second / 1000);
    635             rate_control_param->bits_per_second = 20000000;
    636         }
    637 
    638         if (ctx->temporal_layer_number == 1) {
    639             if (rate_control_param->bits_per_second / 1000 != seq->rc_target_bitrate) {
    640                 drv_debug_msg(VIDEO_DEBUG_ERROR, "bitrate was changed from %dkbps to %dkbps\n",
    641                               seq->rc_target_bitrate, rate_control_param->bits_per_second / 1000);
    642                 seq->rc_target_bitrate = rate_control_param->bits_per_second / 1000;
    643                 seq->ts_target_bitrate[0] = rate_control_param->bits_per_second / 1000;
    644 
    645             }
    646         } else {
    647             layer_id = rate_control_param->rc_flags.bits.temporal_id % 3;
    648             if (rate_control_param->bits_per_second / 1000 != seq->ts_target_bitrate[layer_id]) {
    649                 drv_debug_msg(VIDEO_DEBUG_ERROR, "bitrate was changed from %dkbps to %dkbps\n",
    650                               seq->ts_target_bitrate[layer_id], rate_control_param->bits_per_second / 1000);
    651                 seq->ts_target_bitrate[layer_id] = rate_control_param->bits_per_second / 1000;
    652             }
    653         }
    654 
    655         ctx->re_send_seq_params = 1;
    656         break;
    657     case VAEncMiscParameterTypeMaxFrameSize:
    658         max_frame_size_param = (VAEncMiscParameterBufferMaxFrameSize *)pBuffer->data;
    659         if (ctx->max_frame_size == max_frame_size_param->max_frame_size)
    660             break;
    661 
    662         drv_debug_msg(VIDEO_DEBUG_ERROR, "max frame size changed from %d to %d\n",
    663                       ctx->max_frame_size, max_frame_size_param->max_frame_size);
    664         ctx->max_frame_size = max_frame_size_param->max_frame_size ;
    665         ctx->re_send_seq_params = 1 ;
    666         break;
    667     case VAEncMiscParameterTypeAIR:
    668         air_param = (VAEncMiscParameterAIR *)pBuffer->data;
    669         if (air_param->air_num_mbs > 65535 ||
    670             air_param->air_threshold > 65535) {
    671             vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
    672             break;
    673         }
    674 
    675         drv_debug_msg(VIDEO_DEBUG_GENERAL, "air slice size changed to num_air_mbs %d "
    676                       "air_threshold %d, air_auto %d\n",
    677                       air_param->air_num_mbs, air_param->air_threshold,
    678                       air_param->air_auto);
    679         seq->cyclic_intra_refresh = air_param->air_threshold;
    680         break;
    681     case VAEncMiscParameterTypeHRD:
    682         hrd_param = (VAEncMiscParameterHRD *)pBuffer->data;
    683         seq->rc_buf_sz = hrd_param->buffer_size;
    684         seq->rc_buf_initial_sz = hrd_param->initial_buffer_fullness;
    685         seq->rc_buf_optimal_sz = hrd_param->optimal_buffer_fullness;
    686         ctx->re_send_seq_params = 1;
    687         break;
    688     case VAEncMiscParameterTypeQualityLevel:
    689         break;
    690 
    691     default:
    692         vaStatus = VA_STATUS_ERROR_UNKNOWN;
    693         DEBUG_FAILURE;
    694         break;
    695     }
    696 
    697     free(obj_buffer->buffer_data);
    698     obj_buffer->buffer_data = NULL;
    699 
    700     return vaStatus;
    701 }
    702 static VAStatus vsp_VP8_RenderPicture(
    703     object_context_p obj_context,
    704     object_buffer_p *buffers,
    705     int num_buffers)
    706 {
    707 
    708     int i;
    709     psb_driver_data_p driver_data = obj_context->driver_data;
    710     INIT_CONTEXT_VPP;
    711     VASurfaceID surface_id;
    712     VAStatus vaStatus = VA_STATUS_SUCCESS;
    713 
    714     for (i = 0; i < num_buffers; i++) {
    715 
    716         object_buffer_p obj_buffer = buffers[i];
    717         switch (obj_buffer->type) {
    718         case VAEncSequenceParameterBufferType:
    719             vaStatus = vsp_vp8_process_seqence_param(driver_data, ctx, obj_buffer);
    720             break;
    721         case VAEncPictureParameterBufferType:
    722             surface_id = obj_context->current_render_surface_id;
    723             vaStatus = vsp_vp8_process_picture_param(driver_data, ctx, obj_buffer, surface_id);
    724             break;
    725         case VAEncMiscParameterBufferType:
    726             vaStatus = vsp_vp8_process_misc_param(ctx, obj_buffer);
    727             break;
    728         default:
    729             vaStatus = VA_STATUS_SUCCESS;//VA_STATUS_ERROR_UNKNOWN;
    730             DEBUG_FAILURE;
    731         }
    732 
    733         if (vaStatus != VA_STATUS_SUCCESS) {
    734             break;
    735         }
    736     }
    737 
    738     return vaStatus;
    739 }
    740 
    741 static VAStatus vsp_VP8_BeginPicture(
    742     object_context_p obj_context)
    743 {
    744     int ret;
    745     VAStatus vaStatus = VA_STATUS_SUCCESS;
    746     INIT_CONTEXT_VPP;
    747     vsp_cmdbuf_p cmdbuf;
    748 
    749     /* Initialise the command buffer */
    750     ret = vsp_context_get_next_cmdbuf(ctx->obj_context);
    751     if (ret) {
    752         drv_debug_msg(VIDEO_DEBUG_GENERAL, "get next cmdbuf fail\n");
    753         vaStatus = VA_STATUS_ERROR_UNKNOWN;
    754         return vaStatus;
    755     }
    756 
    757     cmdbuf = obj_context->vsp_cmdbuf;
    758 
    759     if (ctx->obj_context->frame_count == 0) { /* first picture */
    760         vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VP8_ID, ctx->context_buf, Vss_Sys_STATE_BUF_COMMAND,
    761                                   0, VSP_VP8ENC_STATE_SIZE);
    762     }
    763 
    764     /* map param mem */
    765     vaStatus = psb_buffer_map(&cmdbuf->param_mem, &cmdbuf->param_mem_p);
    766     if (vaStatus) {
    767         return vaStatus;
    768     }
    769 
    770     cmdbuf->pic_param_p = cmdbuf->param_mem_p;
    771     cmdbuf->seq_param_p = cmdbuf->param_mem_p + ctx->seq_param_offset;
    772     cmdbuf->ref_param_p = cmdbuf->param_mem_p + ctx->ref_param_offset;
    773     ctx->vp8_seq_cmd_send = 0;
    774     ctx->re_send_seq_params = 0;
    775 
    776     return VA_STATUS_SUCCESS;
    777 }
    778 
    779 static inline void  dump_vssporcPicture(struct VssProcPictureVP8 * frame)
    780 {
    781     drv_debug_msg(VIDEO_ENCODE_DEBUG, "surface_id 0x%08x\n", frame->surface_id);
    782     drv_debug_msg(VIDEO_ENCODE_DEBUG, "irq %d\n", frame->irq);
    783     drv_debug_msg(VIDEO_ENCODE_DEBUG, "base 0x%08x\n", frame->base);
    784     drv_debug_msg(VIDEO_ENCODE_DEBUG, "base_uv 0x%08x\n", frame->base_uv);
    785     drv_debug_msg(VIDEO_ENCODE_DEBUG, "height %d\n", frame->height);
    786     drv_debug_msg(VIDEO_ENCODE_DEBUG, "width %d\n", frame->width);
    787     drv_debug_msg(VIDEO_ENCODE_DEBUG, "stride %d\n", frame->stride);
    788     drv_debug_msg(VIDEO_ENCODE_DEBUG, "format %d\n", frame->format);
    789 }
    790 
    791 static void vsp_vp8_dump_commands(vsp_cmdbuf_p cmdbuf)
    792 {
    793     unsigned int i, cmd_idx;
    794     unsigned int cmdbuffer_size = (unsigned char *)cmdbuf->cmd_idx - cmdbuf->cmd_start; /* In bytes */
    795     unsigned int cmd_number = cmdbuffer_size / sizeof(struct vss_command_t);
    796     struct vss_command_t *cmd = (struct vss_command_t *)cmdbuf->cmd_start;
    797     struct VssVp8encPictureParameterBuffer *pic =
    798         (struct VssVp8encPictureParameterBuffer *)cmdbuf->pic_param_p;
    799     struct VssVp8encSequenceParameterBuffer *seq =
    800         (struct VssVp8encSequenceParameterBuffer *)cmdbuf->seq_param_p;
    801 
    802     for (cmd_idx = 0; cmd_idx < cmd_number; cmd_idx++) {
    803         drv_debug_msg(VIDEO_ENCODE_DEBUG, "\n============command start============\ncontext %d\ntype%d\n",
    804                       cmd[cmd_idx].context, cmd[cmd_idx].type);
    805         if (cmd[cmd_idx].type == VssVp8encEncodeFrameCommand) {
    806             drv_debug_msg(VIDEO_ENCODE_DEBUG, "input frame\n");
    807             dump_vssporcPicture(&pic->input_frame);
    808 
    809             drv_debug_msg(VIDEO_ENCODE_DEBUG, "recon frame\n");
    810             dump_vssporcPicture(&pic->recon_frame);
    811 
    812             drv_debug_msg(VIDEO_ENCODE_DEBUG, "version %d\n", pic->version);
    813             drv_debug_msg(VIDEO_ENCODE_DEBUG, "pic_flags 0x%08x\n", pic->pic_flags);
    814             drv_debug_msg(VIDEO_ENCODE_DEBUG, "prev_frame_dropped %d\n", pic->prev_frame_dropped);
    815             drv_debug_msg(VIDEO_ENCODE_DEBUG, "cpuused %d\n", pic->cpuused);
    816             drv_debug_msg(VIDEO_ENCODE_DEBUG, "sharpness %d\n", pic->sharpness);
    817             drv_debug_msg(VIDEO_ENCODE_DEBUG, "num_token_partitions %d\n", pic->num_token_partitions);
    818             drv_debug_msg(VIDEO_ENCODE_DEBUG, "encoded_frame_size %d\n", pic->encoded_frame_size);
    819             drv_debug_msg(VIDEO_ENCODE_DEBUG, "encoded_frame_base 0x%08x\n", pic->encoded_frame_base);
    820         }
    821 
    822         if (cmd[cmd_idx].type == VssVp8encSetSequenceParametersCommand) {
    823             drv_debug_msg(VIDEO_ENCODE_DEBUG, "frame_width %d\n", seq->frame_width);
    824             drv_debug_msg(VIDEO_ENCODE_DEBUG, "frame_height %d\n", seq->frame_height);
    825             drv_debug_msg(VIDEO_ENCODE_DEBUG, "frame_rate %d\n", seq->frame_rate);
    826             drv_debug_msg(VIDEO_ENCODE_DEBUG, "error_resilient %d\n", seq->error_resilient);
    827             drv_debug_msg(VIDEO_ENCODE_DEBUG, "num_token_partitions %d\n", seq->num_token_partitions);
    828             drv_debug_msg(VIDEO_ENCODE_DEBUG, "kf_mode %d\n", seq->kf_mode);
    829             drv_debug_msg(VIDEO_ENCODE_DEBUG, "kf_min_dist %d\n", seq->kf_min_dist);
    830             drv_debug_msg(VIDEO_ENCODE_DEBUG, "kf_max_dist %d\n", seq->kf_max_dist);
    831             drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_target_bitrate %d\n", seq->rc_target_bitrate);
    832             drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_min_quantizer %d\n", seq->rc_min_quantizer);
    833             drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_max_quantizer %d\n", seq->rc_max_quantizer);
    834             drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_undershoot_pct %d\n", seq->rc_undershoot_pct);
    835             drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_overshoot_pct %d\n", seq->rc_overshoot_pct);
    836             drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_end_usage %d\n", seq->rc_end_usage);
    837             drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_buf_sz %d\n", seq->rc_buf_sz);
    838             drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_buf_initial_sz %d\n", seq->rc_buf_initial_sz);
    839             drv_debug_msg(VIDEO_ENCODE_DEBUG, "rc_buf_optimal_sz %d\n", seq->rc_buf_optimal_sz);
    840             drv_debug_msg(VIDEO_ENCODE_DEBUG, "max_intra_rate %d\n", seq->max_intra_rate);
    841             drv_debug_msg(VIDEO_ENCODE_DEBUG, "cyclic_intra_refresh %d\n", seq->cyclic_intra_refresh);
    842             drv_debug_msg(VIDEO_ENCODE_DEBUG, "concatenate_partitions %d\n", seq->concatenate_partitions);
    843             drv_debug_msg(VIDEO_ENCODE_DEBUG, "recon_buffer_mode %d\n", seq->recon_buffer_mode);
    844             drv_debug_msg(VIDEO_ENCODE_DEBUG, "ts_number_layers %d\n", seq->ts_number_layers);
    845 
    846             for (i = 0; i < 3; i++)
    847                 drv_debug_msg(VIDEO_ENCODE_DEBUG, "ts_target_bitrate[%d] %d\n", i, seq->ts_target_bitrate[i]);
    848 
    849             for (i = 0; i < 3; i++)
    850                 drv_debug_msg(VIDEO_ENCODE_DEBUG, "ts_rate_decimator[%d] %d\n", i, seq->ts_rate_decimator[i]);
    851             drv_debug_msg(VIDEO_ENCODE_DEBUG, "ts_periodicity %d\n", seq->ts_periodicity);
    852 
    853             for (i = 0; i < seq->ts_periodicity; i++)
    854                 drv_debug_msg(VIDEO_ENCODE_DEBUG, "ts_layer_id[%d] %d\n", i, seq->ts_layer_id[i]);
    855 
    856             for (i = 0; i < 4; i++) {
    857                 drv_debug_msg(VIDEO_ENCODE_DEBUG, "ref_frame_buffer %d\n", i);
    858                 dump_vssporcPicture(&seq->ref_frame_buffers[i]);
    859             }
    860         }
    861 
    862         drv_debug_msg(VIDEO_ENCODE_DEBUG, "============command end============\n");
    863     }
    864 }
    865 
    866 
    867 static VAStatus vsp_VP8_EndPicture(
    868     object_context_p obj_context)
    869 {
    870     INIT_CONTEXT_VPP;
    871     psb_driver_data_p driver_data = obj_context->driver_data;
    872     vsp_cmdbuf_p cmdbuf = obj_context->vsp_cmdbuf;
    873 
    874     if (ctx->re_send_seq_params) {
    875         vsp_vp8_process_dynamic_seqence_param(ctx);
    876     }
    877 
    878     drv_debug_msg(VIDEO_ENCODE_DEBUG, "ctx->obj_context->frame_count=%d\n", ctx->obj_context->frame_count + 1);
    879     vsp_vp8_dump_commands(cmdbuf);
    880 
    881     if (cmdbuf->param_mem_p != NULL) {
    882         psb_buffer_unmap(&cmdbuf->param_mem);
    883         cmdbuf->param_mem_p = NULL;
    884         cmdbuf->pic_param_p = NULL;
    885         cmdbuf->end_param_p = NULL;
    886         cmdbuf->pipeline_param_p = NULL;
    887         cmdbuf->denoise_param_p = NULL;
    888         cmdbuf->enhancer_param_p = NULL;
    889         cmdbuf->sharpen_param_p = NULL;
    890         cmdbuf->frc_param_p = NULL;
    891         cmdbuf->ref_param_p = NULL;
    892     }
    893 
    894     if (vsp_context_flush_cmdbuf(ctx->obj_context)) {
    895         drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_VP8: flush deblock cmdbuf error\n");
    896         return VA_STATUS_ERROR_UNKNOWN;
    897     }
    898 
    899     return VA_STATUS_SUCCESS;
    900 }
    901 
    902 struct format_vtable_s vsp_VP8_vtable = {
    903 queryConfigAttributes:
    904     vsp_VP8_QueryConfigAttributes,
    905 validateConfig:
    906     vsp_VP8_ValidateConfig,
    907 createContext:
    908     vsp_VP8_CreateContext,
    909 destroyContext:
    910     vsp_VP8_DestroyContext,
    911 beginPicture:
    912     vsp_VP8_BeginPicture,
    913 renderPicture:
    914     vsp_VP8_RenderPicture,
    915 endPicture:
    916     vsp_VP8_EndPicture
    917 };
    918