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