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 
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 
vsp_VP8_QueryConfigAttributes(VAProfile __maybe_unused profile,VAEntrypoint __maybe_unused entrypoint,VAConfigAttrib * attrib_list,int num_attribs)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 
vsp_VP8_ValidateConfig(object_config_p obj_config)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 
vsp_VP8_set_default_params(struct VssVp8encSequenceParameterBuffer * vp8_seq)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 
vsp_VP8_CreateContext(object_context_p obj_context,object_config_p obj_config)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         free(ctx);
264 
265     return vaStatus;
266 }
267 
vsp_VP8_DestroyContext(object_context_p obj_context)268 static 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 
vsp_vp8_process_seqence_param(psb_driver_data_p driver_data,context_VPP_p ctx,object_buffer_p obj_buffer)288 static 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 
vsp_vp8_process_dynamic_seqence_param(context_VPP_p ctx)363 static 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 
vsp_vp8_process_picture_param(psb_driver_data_p driver_data,context_VPP_p ctx,object_buffer_p obj_buffer,VASurfaceID surface_id)389 static 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 
vsp_vp8_process_misc_param(context_VPP_p ctx,object_buffer_p obj_buffer)489 static 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 }
vsp_VP8_RenderPicture(object_context_p obj_context,object_buffer_p * buffers,int num_buffers)698 static 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 
vsp_VP8_BeginPicture(object_context_p obj_context)737 static 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 
dump_vssporcPicture(struct VssProcPictureVP8 * frame)775 static 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 
vsp_vp8_dump_commands(vsp_cmdbuf_p cmdbuf)787 static 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 
vsp_VP8_EndPicture(object_context_p obj_context)863 static 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 
898 struct format_vtable_s vsp_VP8_vtable = {
899 queryConfigAttributes:
900     vsp_VP8_QueryConfigAttributes,
901 validateConfig:
902     vsp_VP8_ValidateConfig,
903 createContext:
904     vsp_VP8_CreateContext,
905 destroyContext:
906     vsp_VP8_DestroyContext,
907 beginPicture:
908     vsp_VP8_BeginPicture,
909 renderPicture:
910     vsp_VP8_RenderPicture,
911 endPicture:
912     vsp_VP8_EndPicture
913 };
914