1/*
2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3 * Copyright (c) Imagination Technologies Limited, UK
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 *    Elaine Wang <elaine.wang@intel.com>
27 *    Zeng Li <zeng.li@intel.com>
28 *    Edward Lin <edward.lin@intel.com>
29 *
30 */
31
32#include <errno.h>
33#include <stdlib.h>
34#include <unistd.h>
35#include <stdint.h>
36#include <string.h>
37#include <limits.h>
38
39#include "hwdefs/coreflags.h"
40#include "hwdefs/topaz_vlc_regs.h"
41#include "hwdefs/topaz_db_regs.h"
42
43#include "va/va_enc_h264.h"
44
45#include "psb_def.h"
46#include "psb_drv_debug.h"
47#include "psb_surface.h"
48#include "tng_cmdbuf.h"
49#include "tng_hostcode.h"
50#include "tng_hostheader.h"
51#include "tng_picmgmt.h"
52#include "tng_slotorder.h"
53#include "tng_hostair.h"
54#include "tng_H264ES.h"
55#ifdef _TOPAZHP_PDUMP_
56#include "tng_trace.h"
57#endif
58
59#define TOPAZ_H264_MAX_BITRATE 135000000
60
61#define INIT_CONTEXT_H264ES     context_ENC_p ctx = (context_ENC_p) obj_context->format_data
62#define SURFACE(id)    ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id ))
63#define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &ctx->obj_context->driver_data->buffer_heap, id ))
64
65static VAStatus tng__H264ES_init_profile(
66    object_context_p obj_context,
67    object_config_p obj_config)
68{
69    VAStatus vaStatus = VA_STATUS_SUCCESS;
70    context_ENC_p ctx;
71    ctx = (context_ENC_p) obj_context->format_data;
72    switch (obj_config->profile) {
73        case VAProfileH264Baseline:
74        case VAProfileH264ConstrainedBaseline:
75            ctx->ui8ProfileIdc = H264ES_PROFILE_BASELINE;
76            break;
77        case VAProfileH264Main:
78            ctx->ui8ProfileIdc = H264ES_PROFILE_MAIN;
79            break;
80        case VAProfileH264High:
81            ctx->ui8ProfileIdc = H264ES_PROFILE_HIGH;
82            break;
83        case VAProfileH264StereoHigh:
84            ctx->ui8ProfileIdc = H264ES_PROFILE_HIGH;
85            ctx->bEnableMVC = 1;
86            ctx->ui16MVCViewIdx = 0;
87            break;
88        default:
89            ctx->ui8ProfileIdc = H264ES_PROFILE_BASELINE;
90            vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
91            break;
92    }
93    drv_debug_msg(VIDEO_DEBUG_GENERAL,
94        "%s: obj_config->profile = %dctx->eStandard = %d, ctx->bEnableMVC = %d\n",
95        __FUNCTION__, obj_config->profile, ctx->eStandard, ctx->bEnableMVC);
96    return vaStatus;
97}
98
99static VAStatus tng__H264ES_get_codec_type(
100    object_context_p obj_context,
101    object_config_p __maybe_unused obj_config)
102{
103    VAStatus vaStatus = VA_STATUS_SUCCESS;
104    context_ENC_p ctx = (context_ENC_p) obj_context->format_data;
105    IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams);
106
107    ctx->eCodec = IMG_CODEC_NUM;
108
109    if (ctx->bEnableMVC) {
110        switch (psRCParams->eRCMode) {
111            case IMG_RCMODE_NONE:
112                ctx->eCodec = IMG_CODEC_H264MVC_NO_RC;
113                break;
114            case IMG_RCMODE_CBR:
115                ctx->eCodec = IMG_CODEC_H264MVC_CBR;
116                break;
117            case IMG_RCMODE_VBR:
118                ctx->eCodec = IMG_CODEC_H264MVC_VBR;
119                break;
120            default:
121                drv_debug_msg(VIDEO_DEBUG_ERROR, "RC mode MVC\n");
122                break;
123        }
124    } else {
125        switch (psRCParams->eRCMode) {
126            case IMG_RCMODE_NONE:
127                ctx->eCodec = IMG_CODEC_H264_NO_RC;
128                break;
129            case IMG_RCMODE_CBR:
130                ctx->eCodec = IMG_CODEC_H264_CBR;
131                break;
132            case IMG_RCMODE_VBR:
133                ctx->eCodec = IMG_CODEC_H264_VBR;
134                break;
135            case IMG_RCMODE_VCM:
136                ctx->eCodec = IMG_CODEC_H264_VCM;
137                break;
138            default:
139                drv_debug_msg(VIDEO_DEBUG_ERROR, "RC mode\n");
140                break;
141        }
142    }
143    return vaStatus;
144}
145
146static VAStatus tng__H264ES_init_format_mode(
147    object_context_p obj_context,
148    object_config_p __maybe_unused obj_config)
149{
150    VAStatus vaStatus = VA_STATUS_SUCCESS;
151    context_ENC_p ctx = (context_ENC_p) obj_context->format_data;
152
153    ctx->bIsInterlaced = IMG_FALSE;
154    ctx->bIsInterleaved = IMG_FALSE;
155    ctx->ui16PictureHeight = ctx->ui16FrameHeight;
156    ctx->eCodec = IMG_CODEC_H264_NO_RC;
157    return vaStatus;
158}
159
160static void tng__H264ES_init_context(object_context_p obj_context,
161    object_config_p __maybe_unused obj_config)
162{
163    context_ENC_p ctx = (context_ENC_p) obj_context->format_data;
164    //This parameter need not be exposed
165    ctx->ui8InterIntraIndex = 3;
166    ctx->ui8CodedSkippedIndex = 3;
167    ctx->bEnableHostQP = IMG_FALSE;
168    ctx->uMaxChunks = 0xA0;
169    ctx->uChunksPerMb = 0x40;
170    ctx->uPriorityChunks = (0xA0 - 0x60);
171    ctx->ui32FCode = 4;
172    ctx->iFineYSearchSize = 2;
173
174    //This parameter need not be exposed
175    //host to control the encoding process
176    ctx->bEnableInpCtrl = IMG_FALSE;
177    ctx->bEnableHostBias = IMG_FALSE;
178    //By default false Newly Added
179    ctx->bEnableCumulativeBiases = IMG_FALSE;
180
181    //Weighted Prediction is not supported in TopazHP Version 3.0
182    ctx->bWeightedPrediction = IMG_FALSE;
183    ctx->ui8VPWeightedImplicitBiPred = 0;
184    ctx->bInsertHRDParams = IMG_FALSE;
185    ctx->bArbitrarySO = IMG_FALSE;
186    ctx->ui32BasicUnit = 0;
187    ctx->idr_force_flag = 0;
188    ctx->bVPAdaptiveRoundingDisable = IMG_FALSE;
189}
190
191static VAStatus tng__H264ES_process_misc_framerate_param(context_ENC_p ctx, object_buffer_p obj_buffer)
192{
193    VAEncMiscParameterBuffer *pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data;
194    VAEncMiscParameterFrameRate *psMiscFrameRateParam;
195    IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams);
196
197    ASSERT(obj_buffer->type == VAEncMiscParameterTypeFrameRate);
198    ASSERT(obj_buffer->size == sizeof(VAEncMiscParameterFrameRate));
199
200    psMiscFrameRateParam = (VAEncMiscParameterFrameRate *)(pBuffer->data);
201
202    if (psMiscFrameRateParam == NULL)
203        return VA_STATUS_ERROR_INVALID_BUFFER;
204
205    if (psMiscFrameRateParam->framerate < 1 || psMiscFrameRateParam->framerate > 65535)
206        return VA_STATUS_ERROR_INVALID_PARAMETER;
207
208
209    if (psRCParams->ui32FrameRate == 0)
210        psRCParams->ui32FrameRate = psMiscFrameRateParam->framerate;
211    else {
212        if(psMiscFrameRateParam->framerate != psRCParams->ui32FrameRate){
213	    if (psMiscFrameRateParam->framerate > psRCParams->ui32FrameRate)
214		psRCParams->ui32BitsPerSecond /= (float)psMiscFrameRateParam->framerate / psRCParams->ui32FrameRate;
215	    else
216		psRCParams->ui32BitsPerSecond *= (float)psRCParams->ui32FrameRate / psMiscFrameRateParam->framerate;
217            psRCParams->ui32FrameRate = psMiscFrameRateParam->framerate;
218            ctx->rc_update_flag |= RC_MASK_frame_rate;
219        }
220    }
221
222    return VA_STATUS_SUCCESS;
223}
224
225static VAStatus tng__H264ES_process_misc_ratecontrol_param(context_ENC_p ctx, object_buffer_p obj_buffer)
226{
227    IMG_INT32 ui32BitsPerFrame;
228    VAEncMiscParameterRateControl *psMiscRcParams;
229    IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams);
230    VAEncMiscParameterBuffer *pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data;
231    unsigned int max_bps;
232
233    ASSERT(obj_buffer->type == VAEncMiscParameterTypeRateControl);
234    ASSERT(obj_buffer->size == sizeof(VAEncMiscParameterRateControl));
235    psMiscRcParams = (VAEncMiscParameterRateControl *)pBuffer->data;
236
237#ifdef _TOPAZHP_PDUMP_
238    tng_H264ES_trace_misc_rc_params(psMiscRcParams);
239#endif
240
241    drv_debug_msg(VIDEO_DEBUG_GENERAL,
242        "%s psRCParams->ui32BitsPerSecond = %d, psMiscRcParams->bits_per_second = %d \n",
243        __FUNCTION__, psRCParams->ui32BitsPerSecond, psMiscRcParams->bits_per_second);
244
245    if (psMiscRcParams->bits_per_second > TOPAZ_H264_MAX_BITRATE) {
246        drv_debug_msg(VIDEO_DEBUG_GENERAL,
247            "%s: bits_per_second(%d) exceeds the maximum bitrate, set it with %d\n",
248            __FUNCTION__, psMiscRcParams->bits_per_second, TOPAZ_H264_MAX_BITRATE);
249        psMiscRcParams->bits_per_second = TOPAZ_H264_MAX_BITRATE;
250    }
251
252    if ((psRCParams->ui32BitsPerSecond != psMiscRcParams->bits_per_second) &&
253        psMiscRcParams->bits_per_second != 0) {
254        psRCParams->ui32BitsPerSecond = psMiscRcParams->bits_per_second;
255	ctx->rc_update_flag |= RC_MASK_bits_per_second;
256    }
257
258    drv_debug_msg(VIDEO_DEBUG_GENERAL,
259        "%s: rate control changed from %d to %d\n", __FUNCTION__,
260        psRCParams->ui32BitsPerSecond, psMiscRcParams->bits_per_second);
261
262    if (psMiscRcParams->rc_flags.value != 0) {
263       if (psMiscRcParams->rc_flags.bits.disable_bit_stuffing)
264           ctx->sRCParams.bDisableBitStuffing = IMG_TRUE;
265       drv_debug_msg(VIDEO_DEBUG_GENERAL, "bDisableBitStuffing is %d\n",
266           ctx->sRCParams.bDisableBitStuffing);
267    }
268
269    if (psMiscRcParams->window_size > 2000) {
270	drv_debug_msg(VIDEO_DEBUG_ERROR, "window_size is too much!\n");
271	return VA_STATUS_ERROR_INVALID_PARAMETER;
272    }
273
274    if (psMiscRcParams->window_size != 0)
275        ctx->uiCbrBufferTenths = psMiscRcParams->window_size / 100;
276
277    if (psRCParams->ui32FrameRate == 0)
278        psRCParams->ui32FrameRate = 30;
279
280    /* According to Table A-1 Level limits, if resolution is bigger than 625SD,
281       min compression ratio is 4, otherwise min compression ratio is 2 */
282    if (psRCParams->ui32BitsPerSecond == 0) {
283	max_bps =  (ctx->obj_context->picture_width * ctx->obj_context->picture_height * 3 / 2 ) * 8 * psRCParams->ui32FrameRate;
284	if (ctx->ui16SourceWidth > 720)
285	    max_bps /= 4;
286	else
287	    max_bps /= 2;
288	psRCParams->ui32BitsPerSecond = max_bps;
289    }
290
291    if (ctx->uiCbrBufferTenths) {
292        psRCParams->ui32BufferSize = (IMG_UINT32)(psRCParams->ui32BitsPerSecond * ctx->uiCbrBufferTenths / 10.0);
293    } else {
294        if (psRCParams->ui32BitsPerSecond < 256000)
295            psRCParams->ui32BufferSize = ((9 * psRCParams->ui32BitsPerSecond) >> 1);
296        else
297            psRCParams->ui32BufferSize = ((5 * psRCParams->ui32BitsPerSecond) >> 1);
298    }
299
300    drv_debug_msg(VIDEO_DEBUG_GENERAL,
301        "%s ctx->uiCbrBufferTenths = %d, psRCParams->ui32BufferSize = %d\n",
302        __FUNCTION__, ctx->uiCbrBufferTenths, psRCParams->ui32BufferSize);
303    drv_debug_msg(VIDEO_DEBUG_GENERAL,
304        "%s psRCParams->ui32BitsPerSecond = %d, psMiscRcParams->bits_per_second = %d\n",
305        __FUNCTION__, psRCParams->ui32BitsPerSecond, psMiscRcParams->bits_per_second);
306
307    //psRCParams->ui32BUSize = psMiscRcParams->basic_unit_size;
308    psRCParams->i32InitialDelay = (13 * psRCParams->ui32BufferSize) >> 4;
309    psRCParams->i32InitialLevel = (3 * psRCParams->ui32BufferSize) >> 4;
310
311    ui32BitsPerFrame = psRCParams->ui32BitsPerSecond / psRCParams->ui32FrameRate;
312    /* in order to minimise mismatches between firmware and external world InitialLevel should be a multiple of ui32BitsPerFrame */
313    psRCParams->i32InitialLevel = ((psRCParams->i32InitialLevel + ui32BitsPerFrame / 2) / ui32BitsPerFrame) * ui32BitsPerFrame;
314    psRCParams->i32InitialLevel = tng__max(psRCParams->i32InitialLevel, ui32BitsPerFrame);
315    psRCParams->i32InitialDelay = psRCParams->ui32BufferSize - psRCParams->i32InitialLevel;
316
317    //free(psMiscRcParams);
318    if (psMiscRcParams->initial_qp > 51 ||
319	psMiscRcParams->min_qp > 51 ||
320	psMiscRcParams->max_qp > 51) {
321        drv_debug_msg(VIDEO_DEBUG_ERROR,
322            "%s: Initial_qp(%d) min_qp(%d) max_qp(%d) invalid.\nQP shouldn't be larger than 51 for H264\n",
323            __FUNCTION__, psMiscRcParams->initial_qp, psMiscRcParams->min_qp, psMiscRcParams->max_qp);
324        return VA_STATUS_ERROR_INVALID_PARAMETER;
325    }
326
327    if ((psRCParams->ui32InitialQp != psMiscRcParams->initial_qp) &&
328	(psMiscRcParams->initial_qp != 0)) {
329	drv_debug_msg(VIDEO_DEBUG_GENERAL,
330	    "%s: initial_qp updated from %d to %d\n",
331	    __FUNCTION__, psRCParams->ui32InitialQp, psMiscRcParams->initial_qp);
332	ctx->rc_update_flag |= RC_MASK_initial_qp;
333	psRCParams->ui32InitialQp = psMiscRcParams->initial_qp;
334    }
335
336    if ((psRCParams->iMinQP != psMiscRcParams->min_qp) &&
337	(psMiscRcParams->min_qp != 0)) {
338	drv_debug_msg(VIDEO_DEBUG_GENERAL,
339	    "%s: min_qp updated from %d to %d\n",
340	    __FUNCTION__, psRCParams->iMinQP, psMiscRcParams->min_qp);
341	ctx->rc_update_flag |= RC_MASK_min_qp;
342	psRCParams->iMinQP = psMiscRcParams->min_qp;
343    }
344
345    if ((ctx->max_qp != psMiscRcParams->max_qp) &&
346	(psMiscRcParams->max_qp != 0)) {
347	drv_debug_msg(VIDEO_DEBUG_GENERAL,
348	    "%s: max_qp updated from %d to %d\n",
349	    __FUNCTION__, ctx->max_qp, psMiscRcParams->max_qp);
350	ctx->rc_update_flag |= RC_MASK_max_qp;
351	ctx->max_qp = psMiscRcParams->max_qp;
352    }
353
354    return VA_STATUS_SUCCESS;
355}
356
357static VAStatus tng__H264ES_process_misc_hrd_param(context_ENC_p ctx, object_buffer_p obj_buffer)
358{
359    VAStatus vaStatus = VA_STATUS_SUCCESS;
360    VAEncMiscParameterBuffer *pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data;
361    VAEncMiscParameterHRD *psMiscHrdParams = NULL;
362    IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams);
363    ASSERT(obj_buffer->type == VAEncMiscParameterTypeHRD);
364    ASSERT(obj_buffer->size == sizeof(VAEncMiscParameterHRD));
365    psMiscHrdParams = (VAEncMiscParameterHRD *)pBuffer->data;
366
367    if (psMiscHrdParams->buffer_size == 0
368	|| psMiscHrdParams->initial_buffer_fullness == 0) {
369	drv_debug_msg(VIDEO_DEBUG_ERROR, "Find zero value for buffer_size "
370		"and initial_buffer_fullness.\n");
371	vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
372	return vaStatus;
373    }
374
375    if (ctx->initial_buffer_fullness > ctx->buffer_size) {
376	drv_debug_msg(VIDEO_DEBUG_ERROR, "initial_buffer_fullnessi(%d) shouldn't be"
377		" larger that buffer_size(%d)!\n",
378		psMiscHrdParams->initial_buffer_fullness,
379		psMiscHrdParams->buffer_size);
380	vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
381	return vaStatus;
382    }
383
384    if (!psRCParams->bRCEnable) {
385	drv_debug_msg(VIDEO_DEBUG_ERROR, "Only when rate control is enabled,"
386		" VAEncMiscParameterTypeHRD will take effect.\n");
387	vaStatus = VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
388	return vaStatus;
389    }
390
391    ctx->buffer_size = psMiscHrdParams->buffer_size;
392    ctx->initial_buffer_fullness = psMiscHrdParams->initial_buffer_fullness;
393    ctx->bInsertHRDParams = IMG_TRUE;
394    drv_debug_msg(VIDEO_DEBUG_GENERAL, "hrd param buffer_size set to %d "
395	"initial buffer fullness set to %d\n",
396	ctx->buffer_size, ctx->initial_buffer_fullness);
397
398    return VA_STATUS_SUCCESS;
399}
400
401//APP_SetVideoParams
402static VAStatus tng__H264ES_process_misc_air_param(context_ENC_p ctx, object_buffer_p obj_buffer)
403{
404    VAEncMiscParameterBuffer *pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data;
405    VAEncMiscParameterAIR *psMiscAirParams = NULL;
406    ADAPTIVE_INTRA_REFRESH_INFO_TYPE *psAIRInfo = &(ctx->sAirInfo);
407    IMG_UINT32 ui32MbNum;
408    ASSERT(obj_buffer->type == VAEncMiscParameterTypeAIR);
409    ASSERT(obj_buffer->size == sizeof(VAEncMiscParameterAIR));
410
411    psMiscAirParams = (VAEncMiscParameterAIR*)pBuffer->data;
412    ui32MbNum = (ctx->ui16PictureHeight * ctx->ui16Width) >> 8;
413
414    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: enable_AIR = %d, mb_num = %d, thresh_hold = %d, air_auto = %d\n", __FUNCTION__,
415        ctx->bEnableAIR, psMiscAirParams->air_num_mbs, psMiscAirParams->air_threshold, psMiscAirParams->air_auto);
416
417    ctx->bEnableAIR = 1;
418    ctx->bEnableInpCtrl = 1;
419    ctx->bEnableHostBias = 1;
420    ctx->ui8EnableSelStatsFlags |= ESF_FIRST_STAGE_STATS;
421    ctx->ui8EnableSelStatsFlags |= ESF_MP_BEST_MB_DECISION_STATS;
422
423    /*FIXME
424    if (psMiscAirParams->air_threshold == -1 && psMiscAirParams->air_num_mbs == 0) {
425        drv_debug_msg(VIDEO_DEBUG_ERROR,
426            "%s: ERROR: Cannot have both -AIRMBperFrame set to zero"
427            "AND and -AIRSADThreshold set to -1 (APP_SetVideoParams)\n",
428            __FUNCTION__);
429        return VA_STATUS_ERROR_INVALID_PARAMETER;
430    }*/
431
432    if (psMiscAirParams->air_num_mbs > 65535) {
433        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: ERROR: air_num_mbs = %d should not bigger than 65536\n",
434            __FUNCTION__, psMiscAirParams->air_num_mbs);
435        return VA_STATUS_ERROR_INVALID_PARAMETER;
436    }
437
438    if (psMiscAirParams->air_num_mbs > ui32MbNum)
439        psMiscAirParams->air_num_mbs = ui32MbNum;
440
441    if (psMiscAirParams->air_threshold > 65535) {
442        drv_debug_msg(VIDEO_DEBUG_ERROR,
443            "%s: ERROR: air_threshold = %d should not bigger than 65536\n",
444            __FUNCTION__, psMiscAirParams->air_threshold);
445        return VA_STATUS_ERROR_INVALID_PARAMETER;
446    }
447
448    if (psMiscAirParams->air_auto) {
449	psAIRInfo->i32NumAIRSPerFrame = -1;
450	psAIRInfo->i32SAD_Threshold = -1;
451	psAIRInfo->i16AIRSkipCnt = -1;
452    } else {
453	psAIRInfo->i32NumAIRSPerFrame = psMiscAirParams->air_num_mbs;
454	psAIRInfo->i32SAD_Threshold = psMiscAirParams->air_threshold;
455	psAIRInfo->i16AIRSkipCnt = -1;
456    }
457
458    psAIRInfo->ui16AIRScanPos = 0;
459
460    drv_debug_msg(VIDEO_DEBUG_GENERAL,
461        "%s: air slice size changed to num_air_mbs %d "
462        "air_threshold %d, air_auto %d\n", __FUNCTION__,
463        psMiscAirParams->air_num_mbs, psMiscAirParams->air_threshold,
464        psMiscAirParams->air_auto);
465
466    if (psAIRInfo->pi8AIR_Table != NULL)
467        free(psAIRInfo->pi8AIR_Table);
468    tng_air_buf_create(ctx);
469
470    return VA_STATUS_SUCCESS;
471}
472
473static VAStatus tng__H264ES_process_misc_cir_param(context_ENC_p ctx, object_buffer_p obj_buffer)
474{
475    VAEncMiscParameterBuffer *pBuffer = (VAEncMiscParameterBuffer *)obj_buffer->buffer_data;
476    VAEncMiscParameterCIR *psMiscCirParams = NULL;
477
478    ASSERT(obj_buffer->type == VAEncMiscParameterTypeCIR);
479    ASSERT(obj_buffer->size == sizeof(VAEncMiscParameterCIR));
480
481    psMiscCirParams = (VAEncMiscParameterCIR*)pBuffer->data;
482
483    if (psMiscCirParams->cir_num_mbs > 0) {
484	drv_debug_msg(VIDEO_DEBUG_GENERAL,
485	    "CIR enabled with MB count %d\n", ctx->ui16IntraRefresh);
486	ctx->ui16IntraRefresh = psMiscCirParams->cir_num_mbs;
487	ctx->bEnableCIR = 1;
488	ctx->bEnableInpCtrl = 1;
489	ctx->bEnableHostBias = 1;
490    } else {
491        drv_debug_msg(VIDEO_DEBUG_ERROR,
492            "%s: ERROR: invalid cir num mbs(%d), should bigger than 0\n",
493            __FUNCTION__, ctx->ui16IntraRefresh);
494        return VA_STATUS_ERROR_INVALID_PARAMETER;
495    }
496
497    return VA_STATUS_SUCCESS;
498}
499
500static IMG_UINT8 tng__H264ES_calculate_level(context_ENC_p ctx)
501{
502    IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams);
503    IMG_UINT32 ui32MBf=0;
504    IMG_UINT32 ui32MBs;
505    IMG_UINT32 ui32Level=0;
506    IMG_UINT32 ui32TempLevel=0;
507    IMG_UINT32 ui32DpbMbs;
508    // We need to calculate the level based on a few constraints these are
509    // Macroblocks per second
510    // picture size
511    // decoded picture buffer size, and bitrate
512    ui32MBf = (ctx->ui16Width)*(ctx->ui16FrameHeight) >> 8;
513    ui32MBs = ui32MBf * psRCParams->ui32FrameRate;
514
515
516    // could do these in nice tables, but this is clearer
517    if      (ui32MBf > 22080) ui32Level = SH_LEVEL_51;
518    else if (ui32MBf >  8704) ui32Level = SH_LEVEL_50;
519    else if (ui32MBf >  8192) ui32Level = SH_LEVEL_42;
520    else if (ui32MBf >  5120) ui32Level = SH_LEVEL_40;
521    else if (ui32MBf >  3600) ui32Level = SH_LEVEL_32;
522    else if (ui32MBf >  1620) ui32Level = SH_LEVEL_31;
523    else if (ui32MBf >   792) ui32Level = SH_LEVEL_22;
524    else if (ui32MBf >   396) ui32Level = SH_LEVEL_21;
525    else if (ui32MBf >    99) ui32Level = SH_LEVEL_11;
526    else ui32Level = SH_LEVEL_10;
527
528    drv_debug_msg(VIDEO_DEBUG_GENERAL,
529        "%s: ui32MBf = %d, ui32MBs = %d, ui32Level = %d\n",
530        __FUNCTION__, ui32MBf, ui32MBs, ui32Level);
531
532    //ui32DpbMbs = ui32MBf * (psContext->ui32MaxNumRefFrames + 1);
533    ui32DpbMbs = ui32MBf * (ctx->ui8MaxNumRefFrames + 1);
534
535    if      (ui32DpbMbs > 110400) ui32TempLevel = SH_LEVEL_51;
536    else if (ui32DpbMbs >  34816) ui32TempLevel = SH_LEVEL_50;
537    else if (ui32DpbMbs >  32768) ui32TempLevel = SH_LEVEL_42;
538    else if (ui32DpbMbs >  20480) ui32TempLevel = SH_LEVEL_40;
539    else if (ui32DpbMbs >  18000) ui32TempLevel = SH_LEVEL_32;
540    else if (ui32DpbMbs >   8100) ui32TempLevel = SH_LEVEL_31;
541    else if (ui32DpbMbs >   4752) ui32TempLevel = SH_LEVEL_22;
542    else if (ui32DpbMbs >   2376) ui32TempLevel = SH_LEVEL_21;
543    else if (ui32DpbMbs >    900) ui32TempLevel = SH_LEVEL_12;
544    else if (ui32DpbMbs >    396) ui32TempLevel = SH_LEVEL_11;
545    else ui32TempLevel = SH_LEVEL_10;
546    ui32Level = tng__max(ui32Level, ui32TempLevel);
547
548    drv_debug_msg(VIDEO_DEBUG_GENERAL,
549        "%s: ui32DpbMbs = %d, ui32Level = %d\n",
550        __FUNCTION__, ui32DpbMbs, ui32Level);
551
552    // now restrict based on the number of macroblocks per second
553    if      (ui32MBs > 589824) ui32TempLevel = SH_LEVEL_51;
554    else if (ui32MBs > 522240) ui32TempLevel = SH_LEVEL_50;
555    else if (ui32MBs > 245760) ui32TempLevel = SH_LEVEL_42;
556    else if (ui32MBs > 216000) ui32TempLevel = SH_LEVEL_40;
557    else if (ui32MBs > 108000) ui32TempLevel = SH_LEVEL_32;
558    else if (ui32MBs >  40500) ui32TempLevel = SH_LEVEL_31;
559    else if (ui32MBs >  20250) ui32TempLevel = SH_LEVEL_30;
560    else if (ui32MBs >  19800) ui32TempLevel = SH_LEVEL_22;
561    else if (ui32MBs >  11880) ui32TempLevel = SH_LEVEL_21;
562    else if (ui32MBs >   6000) ui32TempLevel = SH_LEVEL_13;
563    else if (ui32MBs >   3000) ui32TempLevel = SH_LEVEL_12;
564    else if (ui32MBs >   1485) ui32TempLevel = SH_LEVEL_11;
565    else ui32TempLevel = SH_LEVEL_10;
566    ui32Level = tng__max(ui32Level, ui32TempLevel);
567
568    drv_debug_msg(VIDEO_DEBUG_GENERAL,
569        "%s: ui32TempLevel = %d, ui32Level = %d\n",
570        __FUNCTION__, ui32TempLevel, ui32Level);
571
572    if (psRCParams->bRCEnable) {
573        // now restrict based on the requested bitrate
574        if      (psRCParams->ui32FrameRate > 135000000) ui32TempLevel = SH_LEVEL_51;
575        else if (psRCParams->ui32FrameRate >  50000000) ui32TempLevel = SH_LEVEL_50;
576        else if (psRCParams->ui32FrameRate >  20000000) ui32TempLevel = SH_LEVEL_41;
577        else if (psRCParams->ui32FrameRate >  14000000) ui32TempLevel = SH_LEVEL_32;
578        else if (psRCParams->ui32FrameRate >  10000000) ui32TempLevel = SH_LEVEL_31;
579        else if (psRCParams->ui32FrameRate >   4000000) ui32TempLevel = SH_LEVEL_30;
580        else if (psRCParams->ui32FrameRate >   2000000) ui32TempLevel = SH_LEVEL_21;
581        else if (psRCParams->ui32FrameRate >    768000) ui32TempLevel = SH_LEVEL_20;
582        else if (psRCParams->ui32FrameRate >    384000) ui32TempLevel = SH_LEVEL_13;
583        else if (psRCParams->ui32FrameRate >    192000) ui32TempLevel = SH_LEVEL_12;
584        else if (psRCParams->ui32FrameRate >    128000) ui32TempLevel = SH_LEVEL_11;
585        else if (psRCParams->ui32FrameRate >     64000) ui32TempLevel = SH_LEVEL_1B;
586        else ui32TempLevel = SH_LEVEL_10;
587
588        ui32Level = tng__max(ui32Level, ui32TempLevel);
589    }
590/*
591    if (pParams->bLossless) {
592        ui32Level = tng__max(ui32Level, 320);
593    }
594*/
595    drv_debug_msg(VIDEO_DEBUG_GENERAL,
596        "%s: target level is %d, input level is %d\n",
597        __FUNCTION__, ui32Level, ctx->ui8LevelIdc);
598    return (IMG_UINT8)ui32Level;
599}
600
601static VAStatus tng__H264ES_process_sequence_param(context_ENC_p ctx, object_buffer_p obj_buffer)
602{
603    VAStatus vaStatus = VA_STATUS_SUCCESS;
604    VAEncSequenceParameterBufferH264 *psSeqParams;
605    H264_CROP_PARAMS* psCropParams = &(ctx->sCropParams);
606    IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams);
607    FRAME_ORDER_INFO *psFrameInfo = &(ctx->sFrameOrderInfo);
608    H264_VUI_PARAMS *psVuiParams = &(ctx->sVuiParams);
609    IMG_UINT32 ui32MaxUnit32 = (IMG_UINT32)0x7ffa;
610    IMG_UINT32 ui32IPCount = 0;
611    IMG_UINT64 ui64Temp = 0;
612
613    ASSERT(obj_buffer->type == VAEncSequenceParameterBufferType);
614    ASSERT(obj_buffer->size == sizeof(VAEncSequenceParameterBufferH264));
615
616    if (obj_buffer->size != sizeof(VAEncSequenceParameterBufferH264)) {
617        vaStatus = VA_STATUS_ERROR_UNKNOWN;
618        goto out1;
619    }
620
621    ctx->obj_context->frame_count = 0;
622    psSeqParams = (VAEncSequenceParameterBufferH264 *) obj_buffer->buffer_data;
623    obj_buffer->buffer_data = NULL;
624    obj_buffer->size = 0;
625
626#ifdef _TOPAZHP_PDUMP_
627    tng_H264ES_trace_seq_params(psSeqParams);
628#endif
629
630    ctx->ui8LevelIdc = psSeqParams->level_idc;
631    ctx->ui8MaxNumRefFrames = psSeqParams->max_num_ref_frames;
632
633    ctx->ui32IdrPeriod = psSeqParams->intra_idr_period;
634    ctx->ui32IntraCnt = psSeqParams->intra_period;
635    ui32IPCount = (IMG_UINT32)(psSeqParams->ip_period);
636
637    if ((ui32IPCount > 4) || (ui32IPCount == 0)) {
638        drv_debug_msg(VIDEO_DEBUG_ERROR,
639            "%s: ip_period %d, it should be in [1, 4]\n",
640            __FUNCTION__, psSeqParams->ip_period);
641        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
642        goto out1;
643    }
644
645    if (ctx->ui32IntraCnt == 0) {
646        if (ui32IPCount == 1)
647            ctx->ui32IntraCnt = INT_MAX;
648        else
649            ctx->ui32IntraCnt = INT_MAX - (INT_MAX % ui32IPCount);
650        ctx->ui32IdrPeriod = 1;
651    } else if (ctx->ui32IntraCnt == 1) {
652        //only I frame or IDR frames;
653        ui32IPCount = 1;
654        if (ctx->ui32IdrPeriod == 0)
655            ctx->ui32IdrPeriod = INT_MAX;
656    } else {
657        if (ctx->ui32IdrPeriod == 0) {
658            ctx->ui32IdrPeriod = INT_MAX / ctx->ui32IntraCnt;
659        } else if (ctx->ui32IdrPeriod > 1) {
660            ui64Temp = (IMG_UINT64)(ctx->ui32IdrPeriod) * (IMG_UINT64)(ctx->ui32IntraCnt);
661            if (ui64Temp >= (IMG_UINT64)INT_MAX) {
662                ctx->ui32IdrPeriod = INT_MAX / ctx->ui32IntraCnt;
663            }
664        }
665
666        if ((ctx->ui32IntraCnt % ui32IPCount) != 0) {
667            if (ctx->ui32IntraCnt > INT_MAX - ui32IPCount + (ctx->ui32IntraCnt % ui32IPCount))
668                ctx->ui32IntraCnt = INT_MAX - ui32IPCount + (ctx->ui32IntraCnt % ui32IPCount);
669            else
670                ctx->ui32IntraCnt += ui32IPCount - (ctx->ui32IntraCnt % ui32IPCount);
671        }
672    }
673
674    if (ctx->ui32FrameCount[ctx->ui32StreamID] > 0) {
675        ctx->idr_force_flag = 1;
676	if (ctx->ui32IntraCntSave != ctx->ui32IntraCnt) {
677	    drv_debug_msg(VIDEO_DEBUG_GENERAL,
678		"%s: intra_period updated from %d to %d\n",
679		__FUNCTION__, ctx->ui32IntraCntSave, ctx->ui32IntraCnt);
680	    ctx->rc_update_flag |= RC_MASK_intra_period;
681	}
682    }
683
684    ctx->ui32IntraCntSave = ctx->ui32IntraCnt;
685
686    ctx->ui8SlotsInUse = ui32IPCount + 1; //Bframes + 2
687
688    //bits per second
689    if (!psSeqParams->bits_per_second) {
690        psSeqParams->bits_per_second = ctx->ui16Width * ctx->ui16PictureHeight * 30 * 12;
691    }
692
693    if (psSeqParams->bits_per_second > TOPAZ_H264_MAX_BITRATE) {
694        psSeqParams->bits_per_second = TOPAZ_H264_MAX_BITRATE;
695        drv_debug_msg(VIDEO_DEBUG_ERROR,
696            "%s: bits_per_second(%d) exceeds the maximum bitrate, set it with %d\n",
697            __FUNCTION__, psSeqParams->bits_per_second,
698            TOPAZ_H264_MAX_BITRATE);
699    }
700
701    if (psRCParams->ui32BitsPerSecond == 0)
702        psRCParams->ui32BitsPerSecond = psSeqParams->bits_per_second;
703
704    if (psSeqParams->bits_per_second != psRCParams->ui32BitsPerSecond) {
705        psRCParams->ui32BitsPerSecond = psSeqParams->bits_per_second;
706	ctx->rc_update_flag |= RC_MASK_bits_per_second;
707    }
708
709    psRCParams->ui32IntraFreq = ctx->ui32IntraCnt;
710    psRCParams->ui32TransferBitsPerSecond = psRCParams->ui32BitsPerSecond;
711    psRCParams->ui16BFrames = ui32IPCount - 1;
712
713    if (psRCParams->ui32FrameRate == 0)
714        psRCParams->ui32FrameRate = 30;
715
716    //set the B frames
717    if (psRCParams->eRCMode == IMG_RCMODE_VCM)
718        psRCParams->ui16BFrames = 0;
719
720    if ((psRCParams->ui16BFrames > 0) && (ctx->ui8ProfileIdc == H264ES_PROFILE_BASELINE)) {
721        ctx->ui8ProfileIdc = H264ES_PROFILE_MAIN;
722    }
723
724    if (psFrameInfo->slot_consume_dpy_order != NULL)
725        free(psFrameInfo->slot_consume_dpy_order);
726    if (psFrameInfo->slot_consume_enc_order != NULL)
727        free(psFrameInfo->slot_consume_enc_order);
728
729    if (psRCParams->ui16BFrames != 0) {
730        memset(psFrameInfo, 0, sizeof(FRAME_ORDER_INFO));
731        psFrameInfo->slot_consume_dpy_order = (int *)malloc(ctx->ui8SlotsInUse * sizeof(int));
732        psFrameInfo->slot_consume_enc_order = (int *)malloc(ctx->ui8SlotsInUse * sizeof(int));
733
734        if ((psFrameInfo->slot_consume_dpy_order == NULL) ||
735            (psFrameInfo->slot_consume_enc_order == NULL)) {
736            drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: error malloc slot order array\n", __FUNCTION__);
737        }
738    }
739
740    //set the crop parameters
741    psCropParams->bClip = psSeqParams->frame_cropping_flag;
742    psCropParams->ui16LeftCropOffset = psSeqParams->frame_crop_left_offset;
743    psCropParams->ui16RightCropOffset = psSeqParams->frame_crop_right_offset;
744    psCropParams->ui16TopCropOffset = psSeqParams->frame_crop_top_offset;
745    psCropParams->ui16BottomCropOffset = psSeqParams->frame_crop_bottom_offset;
746
747    //set level idc parameter
748    ctx->ui32VertMVLimit = 255 ;//(63.75 in qpel increments)
749    ctx->bLimitNumVectors = IMG_FALSE;
750
751    if (ctx->ui8LevelIdc == 111)
752        ctx->ui8LevelIdc = SH_LEVEL_1B;
753
754    ctx->ui8LevelIdc = tng__H264ES_calculate_level(ctx);
755
756    /*Setting VertMVLimit and LimitNumVectors only for H264*/
757    if (ctx->ui8LevelIdc >= SH_LEVEL_30)
758        ctx->bLimitNumVectors = IMG_TRUE;
759    else
760        ctx->bLimitNumVectors = IMG_FALSE;
761
762    if (ctx->ui8LevelIdc >= SH_LEVEL_31)
763        ctx->ui32VertMVLimit = 2047 ;//(511.75 in qpel increments)
764    else if (ctx->ui8LevelIdc >= SH_LEVEL_21)
765        ctx->ui32VertMVLimit = 1023 ;//(255.75 in qpel increments)
766    else if (ctx->ui8LevelIdc >= SH_LEVEL_11)
767        ctx->ui32VertMVLimit = 511 ;//(127.75 in qpel increments)
768
769    //set VUI info
770    memset(psVuiParams, 0, sizeof(H264_VUI_PARAMS));
771    if (psSeqParams->time_scale != 0 && psSeqParams->num_units_in_tick != 0
772		&& (psSeqParams->time_scale > psSeqParams->num_units_in_tick)) {
773        psVuiParams->Time_Scale = psSeqParams->time_scale;
774        psVuiParams->num_units_in_tick = psSeqParams->num_units_in_tick;
775    }
776
777out1:
778    free(obj_buffer->buffer_data);
779    obj_buffer->buffer_data = NULL;
780    obj_buffer->size = 0;
781
782    return vaStatus;
783}
784
785#if 0
786static VAStatus tng__H264ES_process_picture_param(context_ENC_p ctx, object_buffer_p obj_buffer)
787{
788    VAStatus vaStatus = VA_STATUS_SUCCESS;
789    context_ENC_mem *ps_mem = &(ctx->ctx_mem[ctx->ui32StreamID]);
790    context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf[ctx->ui32StreamID]);
791    IMG_RC_PARAMS * psRCParams = &(ctx->sRCParams);
792    VAEncPictureParameterBufferH264 *psPicParams;
793    IMG_BOOL bDepViewPPS = IMG_FALSE;
794
795    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: start\n",__FUNCTION__);
796    ASSERT(obj_buffer->type == VAEncPictureParameterBufferType);
797    if (obj_buffer->size != sizeof(VAEncPictureParameterBufferH264)) {
798        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s L%d Invalid coded buffer handle\n", __FUNCTION__, __LINE__);
799        return VA_STATUS_ERROR_UNKNOWN;
800    }
801
802    /* Transfer ownership of VAEncPictureParameterBufferH264 data */
803    psPicParams = (VAEncPictureParameterBufferH264 *) obj_buffer->buffer_data;
804
805    obj_buffer->buffer_data = NULL;
806    obj_buffer->size = 0;
807
808    ASSERT(ctx->ui16Width == psPicParams->picture_width);
809    ASSERT(ctx->ui16PictureHeight == psPicParams->picture_height);
810
811#ifdef _TOPAZHP_OLD_LIBVA_
812    ps_buf->ref_surface = SURFACE(psPicParams->ReferenceFrames[0].picture_id);
813    ps_buf->coded_buf = BUFFER(psPicParams->coded_buf);
814#else
815    {
816        IMG_INT32 i;
817        ps_buf->rec_surface = SURFACE(psPicParams->CurrPic.picture_id);
818        for (i = 0; i < 16; i++)
819            ps_buf->ref_surface[i] = SURFACE(psPicParams->ReferenceFrames[i].picture_id);
820        ps_buf->coded_buf = BUFFER(psPicParams->coded_buf);
821    }
822#endif
823
824    if (NULL == ps_buf->coded_buf) {
825        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s L%d Invalid coded buffer handle\n", __FUNCTION__, __LINE__);
826        free(psPicParams);
827        return VA_STATUS_ERROR_INVALID_BUFFER;
828    }
829
830    if ((ctx->bEnableMvc) && (ctx->ui16MVCViewIdx != 0) &&
831        (ctx->ui16MVCViewIdx != (IMG_UINT16)(NON_MVC_VIEW))) {
832        bDepViewPPS = IMG_TRUE;
833    }
834
835    /************* init ****************
836    ctx->bCabacEnabled = psPicParams->pic_fields.bits.entropy_coding_mode_flag;
837    ctx->bH2648x8Transform = psPicParams->pic_fields.bits.transform_8x8_mode_flag;
838    ctx->bH264IntraConstrained = psPicParams->pic_fields.bits.constrained_intra_pred_flag;
839    ctx->bWeightedPrediction = psPicParams->pic_fields.bits.weighted_pred_flag;
840    ctx->ui8VPWeightedImplicitBiPred = psPicParams->pic_fields.bits.weighted_bipred_idc;
841    ctx->bCustomScaling = psPicParams->pic_fields.bits.pic_scaling_matrix_present_flag;
842    ************* set rc params *************/
843//    ctx->sRCParams.ui32InitialQp = psPicParams->pic_init_qp;
844//    ctx->sRCParams.i8QCPOffset = psPicParams->chroma_qp_index_offset;
845    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s psRCParams->ui32InitialQp = %d, psRCParams->iMinQP = %d\n", __FUNCTION__, psPicParams->pic_init_qp, psPicParams->chroma_qp_index_offset);
846    tng__H264ES_prepare_picture_header(
847        ps_mem->bufs_pic_template.virtual_addr,
848        0, //IMG_BOOL    bCabacEnabled,
849        ctx->bH2648x8Transform, //IMG_BOOL    b_8x8transform,
850        0, //IMG_BOOL    bIntraConstrained,
851        0, //IMG_INT8    i8CQPOffset,
852        0, //IMG_BOOL    bWeightedPrediction,
853        0, //IMG_UINT8   ui8WeightedBiPred,
854        0, //IMG_BOOL    bMvcPPS,
855        0, //IMG_BOOL    bScalingMatrix,
856        0  //IMG_BOOL    bScalingLists
857    );
858    free(psPicParams);
859/*
860    if (psRCParams->ui16BFrames == 0) {
861        tng_send_codedbuf(ctx, (ctx->obj_context->frame_count&1));
862        tng_send_source_frame(ctx, (ctx->obj_context->frame_count&1), ctx->obj_context->frame_count);
863    } else
864        tng__H264ES_provide_buffer_for_BFrames(ctx);
865*/
866    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: end\n",__FUNCTION__);
867
868    return vaStatus;
869}
870#endif
871
872static VAStatus tng__H264ES_process_picture_param_base(context_ENC_p ctx, unsigned char *buf)
873{
874    VAStatus vaStatus = VA_STATUS_SUCCESS;
875    context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf);
876    VAEncPictureParameterBufferH264 *psPicParams;
877#ifndef _TNG_FRAMES_
878    IMG_INT32 i;
879#endif
880    psPicParams = (VAEncPictureParameterBufferH264 *) buf;
881
882#ifdef _TOPAZHP_PDUMP_
883    tng_H264ES_trace_pic_params(psPicParams);
884#endif
885
886#ifdef _TNG_FRAMES_
887    ps_buf->rec_surface  = SURFACE(psPicParams->CurrPic.picture_id);
888    ps_buf->ref_surface  = SURFACE(psPicParams->ReferenceFrames[0].picture_id);
889    ps_buf->ref_surface1 = SURFACE(psPicParams->ReferenceFrames[1].picture_id);
890    drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: psPicParams->coded_buf = 0x%08x, ps_buf->coded_buf = 0x%08x\n",
891        __FUNCTION__, psPicParams->coded_buf, ps_buf->coded_buf);
892#else
893    {
894        ps_buf->rec_surface = SURFACE(psPicParams->CurrPic.picture_id);
895        for (i = 0; i < 4; i++) {
896            ps_buf->ref_surface[i] = SURFACE(psPicParams->ReferenceFrames[i].picture_id);
897	    ps_buf->ref_surface[i]->is_ref_surface = 1;
898	}
899    }
900#endif
901
902    ps_buf->coded_buf = BUFFER(psPicParams->coded_buf);
903
904    if (NULL == ps_buf->coded_buf) {
905        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s L%d Invalid coded buffer handle\n", __FUNCTION__, __LINE__);
906        free(psPicParams);
907        return VA_STATUS_ERROR_INVALID_BUFFER;
908    }
909
910    ctx->bH2648x8Transform = psPicParams->pic_fields.bits.transform_8x8_mode_flag;
911    if ((ctx->bH2648x8Transform == 1) && (ctx->ui8ProfileIdc != H264ES_PROFILE_HIGH)) {
912        drv_debug_msg(VIDEO_DEBUG_ERROR,
913        "%s L%d only high profile could set bH2648x8Transform TRUE\n",
914        __FUNCTION__, __LINE__);
915        ctx->bH2648x8Transform = 0;
916    }
917
918    ctx->bH264IntraConstrained = psPicParams->pic_fields.bits.constrained_intra_pred_flag;
919    if (ctx->bEnableMVC == 1) {
920        drv_debug_msg(VIDEO_DEBUG_ERROR,
921            "%s L%d MVC could not set bH264IntraConstrained TRUE\n",
922            __FUNCTION__, __LINE__);
923        ctx->bH264IntraConstrained = 0;
924    }
925
926    ctx->bCabacEnabled = psPicParams->pic_fields.bits.entropy_coding_mode_flag;
927    ctx->bWeightedPrediction = psPicParams->pic_fields.bits.weighted_pred_flag;
928    ctx->ui8VPWeightedImplicitBiPred = psPicParams->pic_fields.bits.weighted_bipred_idc;
929
930    /************* init ****************
931    ctx->bCustomScaling = psPicParams->pic_fields.bits.pic_scaling_matrix_present_flag;
932    ************* set rc params *************/
933    if (ctx->sRCParams.ui32InitialQp == 0)
934        ctx->sRCParams.ui32InitialQp = psPicParams->pic_init_qp;
935
936    ctx->ui32LastPicture = psPicParams->last_picture;
937
938    return vaStatus;
939}
940
941static VAStatus tng__H264ES_process_picture_param_mvc(context_ENC_p ctx, unsigned char *buf)
942{
943    VAStatus vaStatus = VA_STATUS_SUCCESS;
944    VAEncPictureParameterBufferH264_MVC *psPicMvcParams;
945
946    psPicMvcParams = (VAEncPictureParameterBufferH264_MVC *) buf;
947    ctx->ui16MVCViewIdx = ctx->ui32StreamID = psPicMvcParams->view_id;
948    //vaStatus = tng__H264ES_process_picture_param_base(ctx, (unsigned char*)&(psPicMvcParams->base_picture_param));
949
950    return vaStatus;
951}
952
953static VAStatus tng__H264ES_process_picture_param(context_ENC_p ctx, object_buffer_p obj_buffer)
954{
955    VAStatus vaStatus = VA_STATUS_SUCCESS;
956
957    ASSERT(obj_buffer->type == VAEncPictureParameterBufferType);
958
959    drv_debug_msg(VIDEO_DEBUG_GENERAL,
960        "%s: ctx->bEnableMVC = %d\n", __FUNCTION__, ctx->bEnableMVC);
961
962    if (ctx->bEnableMVC) {
963        if (obj_buffer->size != sizeof(VAEncPictureParameterBufferH264_MVC)) {
964            drv_debug_msg(VIDEO_DEBUG_ERROR,
965                "%s L%d Invalid picture parameter H264 mvc buffer handle\n",
966                __FUNCTION__, __LINE__);
967            return VA_STATUS_ERROR_UNKNOWN;
968        }
969        vaStatus = tng__H264ES_process_picture_param_mvc(ctx, obj_buffer->buffer_data);
970    } else {
971        if (obj_buffer->size != sizeof(VAEncPictureParameterBufferH264)) {
972            drv_debug_msg(VIDEO_DEBUG_ERROR,
973                "%s L%d Invalid picture parameter H264 buffer handle\n",
974                __FUNCTION__, __LINE__);
975            return VA_STATUS_ERROR_UNKNOWN;
976        }
977        vaStatus = tng__H264ES_process_picture_param_base(ctx, obj_buffer->buffer_data);
978    }
979    free(obj_buffer->buffer_data);
980    obj_buffer->buffer_data = NULL;
981    obj_buffer->size = 0;
982    return vaStatus;
983}
984
985static VAStatus tng__H264ES_process_slice_param_mrfld(context_ENC_p ctx, object_buffer_p obj_buffer)
986{
987    VAStatus vaStatus = VA_STATUS_SUCCESS;
988    VAEncSliceParameterBufferH264 *psSliceParamsH264;
989    unsigned int i;
990    unsigned int uiPreMBAddress = 0;
991    unsigned int uiCurMBAddress = 0;
992    unsigned int uiPreMBNumbers = 0;
993    unsigned int uiCurMBNumbers = 0;
994    unsigned int uiAllMBNumbers = 0;
995    unsigned char ucPreDeblockIdc = 0;
996    unsigned char ucCurDeblockIdc = 0;
997
998    /* Transfer ownership of VAEncPictureParameterBufferH264 data */
999    psSliceParamsH264 = (VAEncSliceParameterBufferH264*) obj_buffer->buffer_data;
1000
1001#ifdef _TOPAZHP_PDUMP_
1002    tng_H264ES_trace_slice_params(psSliceParamsH264);
1003#endif
1004
1005    ucPreDeblockIdc = psSliceParamsH264->disable_deblocking_filter_idc;
1006
1007    for (i = 0; i < obj_buffer->num_elements; i++) {
1008        uiCurMBAddress = psSliceParamsH264->macroblock_address;
1009        uiCurMBNumbers = psSliceParamsH264->num_macroblocks;
1010        if (uiCurMBAddress != uiPreMBAddress + uiPreMBNumbers) {
1011            drv_debug_msg(VIDEO_DEBUG_ERROR,
1012                "%s L%d Error Macroblock Address (%d), address (%d), number (%d)\n",
1013                __FUNCTION__, __LINE__, i, psSliceParamsH264->macroblock_address,
1014                psSliceParamsH264->num_macroblocks);
1015            return VA_STATUS_ERROR_INVALID_PARAMETER;
1016        }
1017        uiPreMBNumbers = uiCurMBNumbers;
1018        uiPreMBAddress = uiCurMBAddress;
1019        uiAllMBNumbers += uiCurMBNumbers;
1020
1021        ucCurDeblockIdc = psSliceParamsH264->disable_deblocking_filter_idc;
1022        if (ucPreDeblockIdc != ucCurDeblockIdc) {
1023            drv_debug_msg(VIDEO_DEBUG_ERROR,
1024                "%s L%d Error Macroblock Address (%d), deblock idc pre (%d), cur (%d)\n",
1025                __FUNCTION__, __LINE__, i, ucPreDeblockIdc, ucCurDeblockIdc);
1026            return VA_STATUS_ERROR_INVALID_PARAMETER;
1027        }
1028        psSliceParamsH264++;
1029    }
1030
1031    if (uiAllMBNumbers != (unsigned int)(((IMG_UINT16)(ctx->ui16Width) * (IMG_UINT16)(ctx->ui16PictureHeight)) >> 8)) {
1032        drv_debug_msg(VIDEO_DEBUG_ERROR,
1033            "%s L%d Error Macroblock all number (%d), (%d)\n",
1034            __FUNCTION__, __LINE__, i, uiAllMBNumbers,
1035            ((ctx->ui16Width * ctx->ui16PictureHeight) >> 8));
1036        return VA_STATUS_ERROR_INVALID_PARAMETER;
1037    }
1038
1039    //deblocking behaviour
1040    ctx->bArbitrarySO = IMG_FALSE;
1041    ctx->ui8DeblockIDC = ucCurDeblockIdc;
1042    ctx->ui8SlicesPerPicture = obj_buffer->num_elements;
1043
1044    return vaStatus;
1045}
1046
1047static VAStatus tng__H264ES_process_slice_param_mdfld(context_ENC_p ctx, object_buffer_p obj_buffer)
1048{
1049    VAStatus vaStatus = VA_STATUS_SUCCESS;
1050    VAEncSliceParameterBuffer *psSliceParams = NULL;
1051    psSliceParams = (VAEncSliceParameterBuffer*) obj_buffer->buffer_data;
1052
1053    //deblocking behaviour
1054    ctx->bArbitrarySO = IMG_FALSE;
1055    ctx->ui8DeblockIDC = psSliceParams->slice_flags.bits.disable_deblocking_filter_idc;
1056    ctx->ui8SlicesPerPicture = obj_buffer->num_elements;
1057    return vaStatus;
1058}
1059
1060static VAStatus tng__H264ES_process_misc_max_slice_size_param(context_ENC_p ctx, object_buffer_p obj_buffer)
1061{
1062    VAEncMiscParameterBuffer *pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data;
1063    VAEncMiscParameterMaxSliceSize *psMiscMaxSliceSizeParams = NULL;
1064    IMG_RC_PARAMS *psRCParams = &(ctx->sRCParams);
1065
1066    ASSERT(obj_buffer->type == VAEncMiscParameterTypeMaxSliceSize);
1067    ASSERT(obj_buffer->size == sizeof(VAEncMiscParameterMaxSliceSize));
1068
1069    psMiscMaxSliceSizeParams = (VAEncMiscParameterMaxSliceSize*)pBuffer->data;
1070
1071    if (psMiscMaxSliceSizeParams->max_slice_size > 0) {
1072	psRCParams->ui32SliceByteLimit = psMiscMaxSliceSizeParams->max_slice_size;
1073	drv_debug_msg(VIDEO_DEBUG_GENERAL,
1074	    "Max slice size is %d\n", psRCParams->ui32SliceByteLimit);
1075    } else {
1076        drv_debug_msg(VIDEO_DEBUG_ERROR,
1077            "%s: ERROR: invalid max slice size(%d), should bigger than 0\n",
1078            __FUNCTION__, psMiscMaxSliceSizeParams->max_slice_size);
1079	psRCParams->ui32SliceByteLimit = 0;
1080        return VA_STATUS_ERROR_INVALID_PARAMETER;
1081    }
1082
1083    return VA_STATUS_SUCCESS;
1084}
1085
1086static VAStatus tng__H264ES_process_slice_param(context_ENC_p ctx, object_buffer_p obj_buffer)
1087{
1088    VAStatus vaStatus = VA_STATUS_SUCCESS;
1089    ASSERT(obj_buffer->type == VAEncSliceParameterBufferType);
1090    /* Prepare InParams for macros of current slice, insert slice header, insert do slice command */
1091
1092    if (obj_buffer->size == sizeof(VAEncSliceParameterBufferH264)) {
1093        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Receive VAEncSliceParameterBufferH264 buffer\n");
1094        vaStatus = tng__H264ES_process_slice_param_mrfld(ctx, obj_buffer);
1095    } else if (obj_buffer->size == sizeof(VAEncSliceParameterBuffer)) {
1096        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Receive VAEncSliceParameterBuffer buffer\n");
1097        vaStatus = tng__H264ES_process_slice_param_mdfld(ctx, obj_buffer);
1098    } else {
1099        drv_debug_msg(VIDEO_DEBUG_ERROR, "Buffer size(%d) is wrong. It should be %d or %d\n",
1100            obj_buffer->size, sizeof(VAEncSliceParameterBuffer),
1101            sizeof(VAEncSliceParameterBufferH264));
1102        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1103    }
1104
1105    free(obj_buffer->buffer_data);
1106    obj_buffer->size = 0;
1107    obj_buffer->buffer_data = NULL;
1108    return vaStatus;
1109}
1110
1111static VAStatus tng__H264ES_process_misc_param(context_ENC_p ctx, object_buffer_p obj_buffer)
1112{
1113    VAStatus vaStatus = VA_STATUS_SUCCESS;
1114    VAEncMiscParameterBuffer *pBuffer;
1115
1116    ASSERT(obj_buffer->type == VAEncMiscParameterBufferType);
1117    ASSERT(ctx != NULL);
1118    /* Transfer ownership of VAEncMiscParameterBuffer data */
1119    pBuffer = (VAEncMiscParameterBuffer *) obj_buffer->buffer_data;
1120    obj_buffer->size = 0;
1121
1122    switch (pBuffer->type) {
1123        case VAEncMiscParameterTypeFrameRate:
1124            vaStatus = tng__H264ES_process_misc_framerate_param(ctx, obj_buffer);
1125            break;
1126        case VAEncMiscParameterTypeRateControl:
1127            vaStatus = tng__H264ES_process_misc_ratecontrol_param(ctx, obj_buffer);
1128            break;
1129        case VAEncMiscParameterTypeHRD:
1130            vaStatus = tng__H264ES_process_misc_hrd_param(ctx, obj_buffer);
1131            break;
1132        case VAEncMiscParameterTypeAIR:
1133            vaStatus = tng__H264ES_process_misc_air_param(ctx, obj_buffer);
1134            break;
1135	case VAEncMiscParameterTypeCIR:
1136            vaStatus = tng__H264ES_process_misc_cir_param(ctx, obj_buffer);
1137            break;
1138	case VAEncMiscParameterTypeMaxSliceSize:
1139	    vaStatus = tng__H264ES_process_misc_max_slice_size_param(ctx, obj_buffer);
1140            break;
1141        default:
1142            break;
1143    }
1144    free(obj_buffer->buffer_data);
1145    obj_buffer->buffer_data = NULL;
1146
1147    return vaStatus;
1148}
1149
1150static void tng_H264ES_QueryConfigAttributes(
1151    VAProfile __maybe_unused profile,
1152    VAEntrypoint __maybe_unused entrypoint,
1153    VAConfigAttrib *attrib_list,
1154    int num_attribs)
1155{
1156    int i;
1157
1158    /* RateControl attributes */
1159    for (i = 0; i < num_attribs; i++) {
1160        switch (attrib_list[i].type) {
1161        case VAConfigAttribRTFormat:
1162            break;
1163
1164        case VAConfigAttribRateControl:
1165            attrib_list[i].value = VA_RC_NONE | VA_RC_CBR | VA_RC_VBR | VA_RC_VCM;
1166            break;
1167
1168        case VAConfigAttribEncAutoReference:
1169            attrib_list[i].value = 1;
1170            break;
1171
1172        case VAConfigAttribEncMaxRefFrames:
1173            attrib_list[i].value = 4;
1174            break;
1175
1176        default:
1177            attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
1178            break;
1179        }
1180    }
1181}
1182
1183static VAStatus tng_H264ES_ValidateConfig(
1184    object_config_p obj_config)
1185{
1186    int i;
1187
1188    /* Check all attributes */
1189    for (i = 0; i < obj_config->attrib_count; i++) {
1190        switch (obj_config->attrib_list[i].type) {
1191            case VAConfigAttribRTFormat:
1192                /* Ignore */
1193                break;
1194            case VAConfigAttribRateControl:
1195                break;
1196            case VAConfigAttribEncAutoReference:
1197                break;
1198            case VAConfigAttribEncMaxRefFrames:
1199                break;
1200            default:
1201                return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
1202        }
1203    }
1204
1205    return VA_STATUS_SUCCESS;
1206}
1207
1208static VAStatus tng_H264ES_setup_profile_features(context_ENC_p ctx)
1209{
1210    VAStatus vaStatus = VA_STATUS_SUCCESS;
1211
1212    IMG_ENCODE_FEATURES * pEncFeatures = &ctx->sEncFeatures;
1213    pEncFeatures->bEnable8x16MVDetect = IMG_TRUE;
1214    pEncFeatures->bEnable16x8MVDetect = IMG_TRUE;
1215
1216    return vaStatus;
1217}
1218
1219
1220static VAStatus tng_H264ES_CreateContext(
1221    object_context_p obj_context,
1222    object_config_p obj_config)
1223{
1224    VAStatus vaStatus = VA_STATUS_SUCCESS;
1225    context_ENC_p ctx;
1226
1227    vaStatus = tng_CreateContext(obj_context, obj_config, 0);
1228
1229    if (VA_STATUS_SUCCESS != vaStatus)
1230        return VA_STATUS_ERROR_ALLOCATION_FAILED;
1231
1232    ctx = (context_ENC_p) obj_context->format_data;
1233    ctx->eStandard = IMG_STANDARD_H264;
1234
1235    tng__H264ES_init_context(obj_context, obj_config);
1236
1237    vaStatus = tng__H264ES_init_profile(obj_context, obj_config);
1238    if (vaStatus != VA_STATUS_SUCCESS) {
1239        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: tng__H264ES_init_profile\n", __FUNCTION__);
1240    }
1241
1242    vaStatus = tng__H264ES_init_format_mode(obj_context, obj_config);
1243    if (vaStatus != VA_STATUS_SUCCESS) {
1244        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: tng__H264ES_init_format_mode\n", __FUNCTION__);
1245    }
1246
1247    vaStatus = tng__H264ES_get_codec_type(obj_context, obj_config);
1248    if (vaStatus != VA_STATUS_SUCCESS) {
1249        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: tng__H264ES_init_rc_mode\n", __FUNCTION__);
1250    }
1251
1252    vaStatus = tng_H264ES_setup_profile_features(ctx);
1253    if (vaStatus != VA_STATUS_SUCCESS) {
1254        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: tng__profile_features\n", __FUNCTION__);
1255    }
1256
1257    vaStatus = tng__patch_hw_profile(ctx);
1258    if (vaStatus != VA_STATUS_SUCCESS) {
1259        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: tng__patch_hw_profile\n", __FUNCTION__);
1260    }
1261
1262    return vaStatus;
1263}
1264
1265static void tng_H264ES_DestroyContext(
1266    object_context_p obj_context)
1267{
1268    tng_DestroyContext(obj_context, 0);
1269}
1270
1271static VAStatus tng_H264ES_BeginPicture(
1272    object_context_p obj_context)
1273{
1274    INIT_CONTEXT_H264ES;
1275    VAStatus vaStatus = VA_STATUS_SUCCESS;
1276    vaStatus = tng_BeginPicture(ctx);
1277    return vaStatus;
1278}
1279
1280static VAStatus tng_H264ES_RenderPicture(
1281    object_context_p obj_context,
1282    object_buffer_p *buffers,
1283    int num_buffers)
1284{
1285    INIT_CONTEXT_H264ES;
1286    VAStatus vaStatus = VA_STATUS_SUCCESS;
1287    int i;
1288
1289    for (i = 0; i < num_buffers; i++) {
1290        object_buffer_p obj_buffer = buffers[i];
1291        drv_debug_msg(VIDEO_DEBUG_GENERAL,
1292            "%s: type = %d, num = %d\n",
1293            __FUNCTION__, obj_buffer->type, num_buffers);
1294
1295        switch (obj_buffer->type) {
1296            case VAEncSequenceParameterBufferType:
1297                drv_debug_msg(VIDEO_DEBUG_GENERAL,
1298                    "tng_H264_RenderPicture got VAEncSequenceParameterBufferType\n");
1299                vaStatus = tng__H264ES_process_sequence_param(ctx, obj_buffer);
1300                DEBUG_FAILURE;
1301                break;
1302            case VAEncPictureParameterBufferType:
1303                drv_debug_msg(VIDEO_DEBUG_GENERAL,
1304                    "tng_H264_RenderPicture got VAEncPictureParameterBuffer\n");
1305                vaStatus = tng__H264ES_process_picture_param(ctx, obj_buffer);
1306                DEBUG_FAILURE;
1307                break;
1308
1309            case VAEncSliceParameterBufferType:
1310                drv_debug_msg(VIDEO_DEBUG_GENERAL,
1311                    "tng_H264_RenderPicture got VAEncSliceParameterBufferType\n");
1312                vaStatus = tng__H264ES_process_slice_param(ctx, obj_buffer);
1313                DEBUG_FAILURE;
1314                break;
1315
1316            case VAEncMiscParameterBufferType:
1317                drv_debug_msg(VIDEO_DEBUG_GENERAL,
1318                    "tng_H264_RenderPicture got VAEncMiscParameterBufferType\n");
1319                vaStatus = tng__H264ES_process_misc_param(ctx, obj_buffer);
1320                DEBUG_FAILURE;
1321                break;
1322            default:
1323                vaStatus = VA_STATUS_ERROR_UNKNOWN;
1324                DEBUG_FAILURE;
1325        }
1326        if (vaStatus != VA_STATUS_SUCCESS) {
1327            break;
1328        }
1329    }
1330    return vaStatus;
1331}
1332
1333static VAStatus tng_H264ES_EndPicture(
1334    object_context_p obj_context)
1335{
1336    INIT_CONTEXT_H264ES;
1337    VAStatus vaStatus = VA_STATUS_SUCCESS;
1338    vaStatus = tng_EndPicture(ctx);
1339    return vaStatus;
1340}
1341
1342struct format_vtable_s tng_H264ES_vtable = {
1343queryConfigAttributes:
1344    tng_H264ES_QueryConfigAttributes,
1345validateConfig:
1346    tng_H264ES_ValidateConfig,
1347createContext:
1348    tng_H264ES_CreateContext,
1349destroyContext:
1350    tng_H264ES_DestroyContext,
1351beginPicture:
1352    tng_H264ES_BeginPicture,
1353renderPicture:
1354    tng_H264ES_RenderPicture,
1355endPicture:
1356    tng_H264ES_EndPicture
1357};
1358
1359/*EOF*/
1360