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