OSDN Git Service

Add the common BRC API to avoid the duplicated code
authorZhao Yakui <yakui.zhao@intel.com>
Fri, 20 Jul 2012 01:16:04 +0000 (21:16 -0400)
committerXiang, Haihao <haihao.xiang@intel.com>
Tue, 23 Oct 2012 05:50:28 +0000 (13:50 +0800)
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
src/Makefile.am
src/gen6_mfc.c
src/gen6_mfc.h
src/gen6_mfc_common.c [new file with mode: 0644]
src/gen75_mfc.c
src/gen7_mfc.c

index 8fe8124..4091b5e 100755 (executable)
@@ -48,6 +48,7 @@ driver_libs = \
 source_c = \
        dso_utils.c             \
        gen6_mfc.c              \
+       gen6_mfc_common.c       \
        gen6_mfd.c              \
        gen6_vme.c              \
        gen7_mfc.c              \
index deeb381..59034be 100644 (file)
@@ -730,290 +730,8 @@ gen6_mfc_free_avc_surface(void **data)
     *data = NULL;
 }
 
-static void
-gen6_mfc_bit_rate_control_context_init(struct encode_state *encode_state, 
-                                       struct gen6_mfc_context *mfc_context)
-{
-    VAEncSequenceParameterBufferH264 *pSequenceParameter = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
-    int width_in_mbs = (mfc_context->surface_state.width + 15) / 16;
-    int height_in_mbs = (mfc_context->surface_state.height + 15) / 16;
-    float fps =  pSequenceParameter->time_scale * 0.5 / pSequenceParameter->num_units_in_tick ;
-    int inter_mb_size = pSequenceParameter->bits_per_second * 1.0 / (fps+4.0) / width_in_mbs / height_in_mbs;
-    int intra_mb_size = inter_mb_size * 5.0;
-    int i;
-
-    mfc_context->bit_rate_control_context[SLICE_TYPE_I].target_mb_size = intra_mb_size;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_I].target_frame_size = intra_mb_size * width_in_mbs * height_in_mbs;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_P].target_mb_size = inter_mb_size;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_P].target_frame_size = inter_mb_size * width_in_mbs * height_in_mbs;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_B].target_mb_size = inter_mb_size;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_B].target_frame_size = inter_mb_size * width_in_mbs * height_in_mbs;
-
-    for(i = 0 ; i < 3; i++) {
-        mfc_context->bit_rate_control_context[i].QpPrimeY = 26;
-        mfc_context->bit_rate_control_context[i].MaxQpNegModifier = 6;
-        mfc_context->bit_rate_control_context[i].MaxQpPosModifier = 6;
-        mfc_context->bit_rate_control_context[i].GrowInit = 6;
-        mfc_context->bit_rate_control_context[i].GrowResistance = 4;
-        mfc_context->bit_rate_control_context[i].ShrinkInit = 6;
-        mfc_context->bit_rate_control_context[i].ShrinkResistance = 4;
-        
-        mfc_context->bit_rate_control_context[i].Correct[0] = 8;
-        mfc_context->bit_rate_control_context[i].Correct[1] = 4;
-        mfc_context->bit_rate_control_context[i].Correct[2] = 2;
-        mfc_context->bit_rate_control_context[i].Correct[3] = 2;
-        mfc_context->bit_rate_control_context[i].Correct[4] = 4;
-        mfc_context->bit_rate_control_context[i].Correct[5] = 8;
-    }
-    
-    mfc_context->bit_rate_control_context[SLICE_TYPE_I].TargetSizeInWord = (intra_mb_size + 16)/ 16;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_P].TargetSizeInWord = (inter_mb_size + 16)/ 16;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_B].TargetSizeInWord = (inter_mb_size + 16)/ 16;
-
-    mfc_context->bit_rate_control_context[SLICE_TYPE_I].MaxSizeInWord = mfc_context->bit_rate_control_context[SLICE_TYPE_I].TargetSizeInWord * 1.5;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_P].MaxSizeInWord = mfc_context->bit_rate_control_context[SLICE_TYPE_P].TargetSizeInWord * 1.5;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_B].MaxSizeInWord = mfc_context->bit_rate_control_context[SLICE_TYPE_B].TargetSizeInWord * 1.5;
-}
 
-static void
-gen6_mfc_brc_init(struct encode_state *encode_state,
-                  struct intel_encoder_context* encoder_context)
-{
-    struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
-    VAEncSequenceParameterBufferH264 *pSequenceParameter = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
-    VAEncMiscParameterBuffer* pMiscParamHRD = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeHRD]->buffer;
-    VAEncMiscParameterHRD* pParameterHRD = (VAEncMiscParameterHRD*)pMiscParamHRD->data;
-    double bitrate = pSequenceParameter->bits_per_second;
-    double framerate = (double)pSequenceParameter->time_scale /(2 * (double)pSequenceParameter->num_units_in_tick);
-    int inum = 1, pnum = 0, bnum = 0; /* Gop structure: number of I, P, B frames in the Gop. */
-    int intra_period = pSequenceParameter->intra_period;
-    int ip_period = pSequenceParameter->ip_period;
-    double qp1_size = 0.1 * 8 * 3 * (pSequenceParameter->picture_width_in_mbs<<4) * (pSequenceParameter->picture_height_in_mbs<<4)/2;
-    double qp51_size = 0.001 * 8 * 3 * (pSequenceParameter->picture_width_in_mbs<<4) * (pSequenceParameter->picture_height_in_mbs<<4)/2;
-    double bpf;
-
-    if (pSequenceParameter->ip_period) {
-        pnum = (intra_period + ip_period - 1)/ip_period - 1;
-        bnum = intra_period - inum - pnum;
-    }
-
-    mfc_context->brc.mode = encoder_context->rate_control_mode;
 
-    mfc_context->brc.target_frame_size[SLICE_TYPE_I] = (int)((double)((bitrate * intra_period)/framerate) /
-                                                             (double)(inum + BRC_PWEIGHT * pnum + BRC_BWEIGHT * bnum));
-    mfc_context->brc.target_frame_size[SLICE_TYPE_P] = BRC_PWEIGHT * mfc_context->brc.target_frame_size[SLICE_TYPE_I];
-    mfc_context->brc.target_frame_size[SLICE_TYPE_B] = BRC_BWEIGHT * mfc_context->brc.target_frame_size[SLICE_TYPE_I];
-
-    mfc_context->brc.gop_nums[SLICE_TYPE_I] = inum;
-    mfc_context->brc.gop_nums[SLICE_TYPE_P] = pnum;
-    mfc_context->brc.gop_nums[SLICE_TYPE_B] = bnum;
-
-    bpf = mfc_context->brc.bits_per_frame = bitrate/framerate;
-
-    mfc_context->hrd.buffer_size = (double)pParameterHRD->buffer_size;
-    mfc_context->hrd.current_buffer_fullness =
-        (double)(pParameterHRD->initial_buffer_fullness < mfc_context->hrd.buffer_size)?
-            pParameterHRD->initial_buffer_fullness: mfc_context->hrd.buffer_size/2.;
-    mfc_context->hrd.target_buffer_fullness = (double)mfc_context->hrd.buffer_size/2.;
-    mfc_context->hrd.buffer_capacity = (double)mfc_context->hrd.buffer_size/qp1_size;
-    mfc_context->hrd.violation_noted = 0;
-
-    if ((bpf > qp51_size) && (bpf < qp1_size)) {
-        mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY = 51 - 50*(bpf - qp51_size)/(qp1_size - qp51_size);
-    }
-    else if (bpf >= qp1_size)
-        mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY = 1;
-    else if (bpf <= qp51_size)
-        mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY = 51;
-
-    mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY = mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY = mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY;
-
-    BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY, 1, 51);
-    BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY, 1, 51);
-    BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY, 1, 51);
-}
-
-static int gen6_mfc_update_hrd(struct encode_state *encode_state,
-                               struct gen6_mfc_context *mfc_context,
-                               int frame_bits)
-{
-    double prev_bf = mfc_context->hrd.current_buffer_fullness;
-
-    mfc_context->hrd.current_buffer_fullness -= frame_bits;
-
-    if (mfc_context->hrd.buffer_size > 0 && mfc_context->hrd.current_buffer_fullness <= 0.) {
-        mfc_context->hrd.current_buffer_fullness = prev_bf;
-        return BRC_UNDERFLOW;
-    }
-    
-    mfc_context->hrd.current_buffer_fullness += mfc_context->brc.bits_per_frame;
-    if (mfc_context->hrd.buffer_size > 0 && mfc_context->hrd.current_buffer_fullness > mfc_context->hrd.buffer_size) {
-        if (mfc_context->brc.mode == VA_RC_VBR)
-            mfc_context->hrd.current_buffer_fullness = mfc_context->hrd.buffer_size;
-        else {
-            mfc_context->hrd.current_buffer_fullness = prev_bf;
-            return BRC_OVERFLOW;
-        }
-    }
-    return BRC_NO_HRD_VIOLATION;
-}
-
-static int gen6_mfc_brc_postpack(struct encode_state *encode_state,
-                                 struct gen6_mfc_context *mfc_context,
-                                 int frame_bits)
-{
-    gen6_brc_status sts = BRC_NO_HRD_VIOLATION;
-    VAEncSliceParameterBufferH264 *pSliceParameter = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[0]->buffer; 
-    int slicetype = pSliceParameter->slice_type;
-    int qpi = mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY;
-    int qpp = mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY;
-    int qpb = mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY;
-    int qp; // quantizer of previously encoded slice of current type
-    int qpn; // predicted quantizer for next frame of current type in integer format
-    double qpf; // predicted quantizer for next frame of current type in float format
-    double delta_qp; // QP correction
-    int target_frame_size, frame_size_next;
-    /* Notes:
-     *  x - how far we are from HRD buffer borders
-     *  y - how far we are from target HRD buffer fullness
-     */
-    double x, y;
-    double frame_size_alpha;
-
-    if (slicetype == SLICE_TYPE_SP)
-        slicetype = SLICE_TYPE_P;
-    else if (slicetype == SLICE_TYPE_SI)
-        slicetype = SLICE_TYPE_I;
-
-    qp = mfc_context->bit_rate_control_context[slicetype].QpPrimeY;
-
-    target_frame_size = mfc_context->brc.target_frame_size[slicetype];
-    if (mfc_context->hrd.buffer_capacity < 5)
-        frame_size_alpha = 0;
-    else
-        frame_size_alpha = (double)mfc_context->brc.gop_nums[slicetype];
-    if (frame_size_alpha > 30) frame_size_alpha = 30;
-    frame_size_next = target_frame_size + (double)(target_frame_size - frame_bits) /
-                                          (double)(frame_size_alpha + 1.);
-
-    /* frame_size_next: avoiding negative number and too small value */
-    if ((double)frame_size_next < (double)(target_frame_size * 0.25))
-        frame_size_next = (int)((double)target_frame_size * 0.25);
-
-    qpf = (double)qp * target_frame_size / frame_size_next;
-    qpn = (int)(qpf + 0.5);
-
-    if (qpn == qp) {
-        /* setting qpn we round qpf making mistakes: now we are trying to compensate this */
-        mfc_context->brc.qpf_rounding_accumulator += qpf - qpn;
-        if (mfc_context->brc.qpf_rounding_accumulator > 1.0) {
-            qpn++;
-            mfc_context->brc.qpf_rounding_accumulator = 0.;
-        } else if (mfc_context->brc.qpf_rounding_accumulator < -1.0) {
-            qpn--;
-            mfc_context->brc.qpf_rounding_accumulator = 0.;
-        }
-    }
-    /* making sure that QP is not changing too fast */
-    if ((qpn - qp) > BRC_QP_MAX_CHANGE) qpn = qp + BRC_QP_MAX_CHANGE;
-    else if ((qpn - qp) < -BRC_QP_MAX_CHANGE) qpn = qp - BRC_QP_MAX_CHANGE;
-    /* making sure that with QP predictions we did do not leave QPs range */
-    BRC_CLIP(qpn, 1, 51);
-
-    /* checking wthether HRD compliance is still met */
-    sts = gen6_mfc_update_hrd(encode_state, mfc_context, frame_bits);
-
-    /* calculating QP delta as some function*/
-    x = mfc_context->hrd.target_buffer_fullness - mfc_context->hrd.current_buffer_fullness;
-    if (x > 0) {
-        x /= mfc_context->hrd.target_buffer_fullness;
-        y = mfc_context->hrd.current_buffer_fullness;
-    }
-    else {
-        x /= (mfc_context->hrd.buffer_size - mfc_context->hrd.target_buffer_fullness);
-        y = mfc_context->hrd.buffer_size - mfc_context->hrd.current_buffer_fullness;
-    }
-    if (y < 0.01) y = 0.01;
-    if (x > 1) x = 1;
-    else if (x < -1) x = -1;
-
-    delta_qp = BRC_QP_MAX_CHANGE*exp(-1/y)*sin(BRC_PI_0_5 * x);
-    qpn = (int)(qpn + delta_qp + 0.5);
-
-    /* making sure that with QP predictions we did do not leave QPs range */
-    BRC_CLIP(qpn, 1, 51);
-
-    if (sts == BRC_NO_HRD_VIOLATION) { // no HRD violation
-        /* correcting QPs of slices of other types */
-        if (slicetype == SLICE_TYPE_P) {
-            if (abs(qpn + BRC_P_B_QP_DIFF - qpb) > 2)
-                mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY += (qpn + BRC_P_B_QP_DIFF - qpb) >> 1;
-            if (abs(qpn - BRC_I_P_QP_DIFF - qpi) > 2)
-                mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY += (qpn - BRC_I_P_QP_DIFF - qpi) >> 1;
-        } else if (slicetype == SLICE_TYPE_I) {
-            if (abs(qpn + BRC_I_B_QP_DIFF - qpb) > 4)
-                mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY += (qpn + BRC_I_B_QP_DIFF - qpb) >> 2;
-            if (abs(qpn + BRC_I_P_QP_DIFF - qpp) > 2)
-                mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY += (qpn + BRC_I_P_QP_DIFF - qpp) >> 2;
-        } else { // SLICE_TYPE_B
-            if (abs(qpn - BRC_P_B_QP_DIFF - qpp) > 2)
-                mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY += (qpn - BRC_P_B_QP_DIFF - qpp) >> 1;
-            if (abs(qpn - BRC_I_B_QP_DIFF - qpi) > 4)
-                mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY += (qpn - BRC_I_B_QP_DIFF - qpi) >> 2;
-        }
-        BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY, 1, 51);
-        BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY, 1, 51);
-        BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY, 1, 51);
-    } else if (sts == BRC_UNDERFLOW) { // underflow
-        if (qpn <= qp) qpn = qp + 1;
-        if (qpn > 51) {
-            qpn = 51;
-            sts = BRC_UNDERFLOW_WITH_MAX_QP; //underflow with maxQP
-        }
-    } else if (sts == BRC_OVERFLOW) {
-        if (qpn >= qp) qpn = qp - 1;
-        if (qpn < 1) { // < 0 (?) overflow with minQP
-            qpn = 1;
-            sts = BRC_OVERFLOW_WITH_MIN_QP; // bit stuffing to be done
-        }
-    }
-
-    mfc_context->bit_rate_control_context[slicetype].QpPrimeY = qpn;
-
-    return sts;
-}
-
-static void 
-gen6_mfc_hrd_context_init(struct encode_state *encode_state,
-                          struct intel_encoder_context *encoder_context)
-{
-    struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
-    VAEncSequenceParameterBufferH264 *pSequenceParameter = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
-    unsigned int rate_control_mode = encoder_context->rate_control_mode;
-    int target_bit_rate = pSequenceParameter->bits_per_second;
-    
-    // current we only support CBR mode.
-    if (rate_control_mode == VA_RC_CBR) {
-        mfc_context->vui_hrd.i_bit_rate_value = target_bit_rate >> 10;
-        mfc_context->vui_hrd.i_cpb_size_value = (target_bit_rate * 8) >> 10;
-        mfc_context->vui_hrd.i_initial_cpb_removal_delay = mfc_context->vui_hrd.i_cpb_size_value * 0.5 * 1024 / target_bit_rate * 90000;
-        mfc_context->vui_hrd.i_cpb_removal_delay = 2;
-        mfc_context->vui_hrd.i_frame_number = 0;
-
-        mfc_context->vui_hrd.i_initial_cpb_removal_delay_length = 24; 
-        mfc_context->vui_hrd.i_cpb_removal_delay_length = 24;
-        mfc_context->vui_hrd.i_dpb_output_delay_length = 24;
-    }
-
-}
-
-static void 
-gen6_mfc_hrd_context_update(struct encode_state *encode_state, 
-                          struct gen6_mfc_context *mfc_context) 
-{
-    mfc_context->vui_hrd.i_frame_number++;
-}
 
 static VAStatus gen6_mfc_avc_prepare(VADriverContextP ctx, 
                                      struct encode_state *encode_state,
@@ -1813,27 +1531,6 @@ gen6_mfc_avc_hardware_batchbuffer(VADriverContextP ctx,
 
 #endif
 
-int interlace_check(VADriverContextP ctx,
-                   struct encode_state *encode_state,
-                   struct intel_encoder_context *encoder_context) {
-    struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
-    VAEncSliceParameterBufferH264 *pSliceParameter;
-    int i;
-    int mbCount = 0;
-    int width_in_mbs = (mfc_context->surface_state.width + 15) / 16;
-    int height_in_mbs = (mfc_context->surface_state.height + 15) / 16;
-  
-    for (i = 0; i < encode_state->num_slice_params_ext; i++) {
-        pSliceParameter = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[i]->buffer; 
-        mbCount += pSliceParameter->num_macroblocks; 
-    }
-    
-    if ( mbCount == ( width_in_mbs * height_in_mbs ) )
-        return 0;
-
-    return 1;
-}
-
 
 static void
 gen6_mfc_avc_pipeline_programing(VADriverContextP ctx,
@@ -1843,7 +1540,7 @@ gen6_mfc_avc_pipeline_programing(VADriverContextP ctx,
     struct intel_batchbuffer *batch = encoder_context->base.batch;
     dri_bo *slice_batch_bo;
 
-    if ( interlace_check(ctx, encode_state, encoder_context) ) {
+    if ( intel_mfc_interlace_check(ctx, encode_state, encoder_context) ) {
         fprintf(stderr, "Current VA driver don't support interlace mode!\n");
         assert(0);
         return; 
@@ -1894,9 +1591,9 @@ gen6_mfc_avc_encode_picture(VADriverContextP ctx,
         gen6_mfc_run(ctx, encode_state, encoder_context);
         if (rate_control_mode == VA_RC_CBR /*|| rate_control_mode == VA_RC_VBR*/) {
             gen6_mfc_stop(ctx, encode_state, encoder_context, &current_frame_bits_size);
-            sts = gen6_mfc_brc_postpack(encode_state, mfc_context, current_frame_bits_size);
+            sts = intel_mfc_brc_postpack(encode_state, mfc_context, current_frame_bits_size);
             if (sts == BRC_NO_HRD_VIOLATION) {
-                gen6_mfc_hrd_context_update(encode_state, mfc_context);
+                intel_mfc_hrd_context_update(encode_state, mfc_context);
                 break;
             }
             else if (sts == BRC_OVERFLOW_WITH_MIN_QP || sts == BRC_UNDERFLOW_WITH_MAX_QP) {
@@ -1995,25 +1692,6 @@ gen6_mfc_context_destroy(void *context)
     free(mfc_context);
 }
 
-void gen6_mfc_brc_prepare(struct encode_state *encode_state,
-                          struct intel_encoder_context *encoder_context)
-{
-    unsigned int rate_control_mode = encoder_context->rate_control_mode;
-    struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
-
-    if (rate_control_mode == VA_RC_CBR) {
-        /*Programing bit rate control */
-        if ( mfc_context->bit_rate_control_context[SLICE_TYPE_I].MaxSizeInWord == 0 ) {
-            gen6_mfc_bit_rate_control_context_init(encode_state, mfc_context);
-            gen6_mfc_brc_init(encode_state, encoder_context);
-        }
-
-        /*Programing HRD control */
-        if ( mfc_context->vui_hrd.i_cpb_size_value == 0 )
-            gen6_mfc_hrd_context_init(encode_state, encoder_context);    
-    }
-}
-
 Bool gen6_mfc_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context)
 {
     struct gen6_mfc_context *mfc_context = calloc(1, sizeof(struct gen6_mfc_context));
@@ -2048,7 +1726,7 @@ Bool gen6_mfc_context_init(VADriverContextP ctx, struct intel_encoder_context *e
     encoder_context->mfc_context = mfc_context;
     encoder_context->mfc_context_destroy = gen6_mfc_context_destroy;
     encoder_context->mfc_pipeline = gen6_mfc_pipeline;
-    encoder_context->mfc_brc_prepare = gen6_mfc_brc_prepare;
+    encoder_context->mfc_brc_prepare = intel_mfc_brc_prepare;
 
     return True;
 }
index ba72a9a..d458d10 100644 (file)
@@ -66,24 +66,6 @@ struct encode_state;
 
 #define CMD_LEN_IN_OWORD        4
 
-#define BRC_CLIP(x, min, max) \
-{ \
-    x = ((x > (max)) ? (max) : ((x < (min)) ? (min) : x)); \
-}
-
-#define BRC_P_B_QP_DIFF 4
-#define BRC_I_P_QP_DIFF 2
-#define BRC_I_B_QP_DIFF (BRC_I_P_QP_DIFF + BRC_P_B_QP_DIFF)
-
-#define BRC_PWEIGHT 0.6  /* weight if P slice with comparison to I slice */
-#define BRC_BWEIGHT 0.25 /* weight if B slice with comparison to I slice */
-
-#define BRC_QP_MAX_CHANGE 5 /* maximum qp modification */
-#define BRC_CY 0.1 /* weight for */
-#define BRC_CX_UNDERFLOW 5.
-#define BRC_CX_OVERFLOW -4.
-
-#define BRC_PI_0_5 1.5707963267948966192313216916398
 
 typedef enum _gen6_brc_status
 {
@@ -246,9 +228,26 @@ VAStatus gen6_mfc_pipeline(VADriverContextP ctx,
                            struct encode_state *encode_state,
                            struct intel_encoder_context *encoder_context);
 void gen6_mfc_context_destroy(void *context);
-void gen6_mfc_brc_prepare(struct encode_state *encode_state,
-                          struct intel_encoder_context *encoder_context);
 
 extern
 Bool gen75_mfc_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context);
+
+
+extern int intel_mfc_update_hrd(struct encode_state *encode_state,
+                               struct gen6_mfc_context *mfc_context,
+                               int frame_bits);
+
+extern int intel_mfc_brc_postpack(struct encode_state *encode_state,
+                                 struct gen6_mfc_context *mfc_context,
+                                 int frame_bits);
+
+extern void intel_mfc_hrd_context_update(struct encode_state *encode_state,
+                               struct gen6_mfc_context *mfc_context);
+
+extern int intel_mfc_interlace_check(VADriverContextP ctx,
+                   struct encode_state *encode_state,
+                   struct intel_encoder_context *encoder_context);
+
+extern void intel_mfc_brc_prepare(struct encode_state *encode_state,
+                          struct intel_encoder_context *encoder_context);
 #endif /* _GEN6_MFC_BCS_H_ */
diff --git a/src/gen6_mfc_common.c b/src/gen6_mfc_common.c
new file mode 100644 (file)
index 0000000..f0dabe1
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * Copyright Â© 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Xiang Haihao <haihao.xiang@intel.com>
+ *    Zhao Yakui <yakui.zhao@intel.com>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+
+#include "intel_batchbuffer.h"
+#include "i965_defines.h"
+#include "i965_structs.h"
+#include "i965_drv_video.h"
+#include "i965_encoder.h"
+#include "i965_encoder_utils.h"
+#include "gen6_mfc.h"
+#include "gen6_vme.h"
+
+
+#define BRC_CLIP(x, min, max) \
+{ \
+    x = ((x > (max)) ? (max) : ((x < (min)) ? (min) : x)); \
+}
+
+#define BRC_P_B_QP_DIFF 4
+#define BRC_I_P_QP_DIFF 2
+#define BRC_I_B_QP_DIFF (BRC_I_P_QP_DIFF + BRC_P_B_QP_DIFF)
+
+#define BRC_PWEIGHT 0.6  /* weight if P slice with comparison to I slice */
+#define BRC_BWEIGHT 0.25 /* weight if B slice with comparison to I slice */
+
+#define BRC_QP_MAX_CHANGE 5 /* maximum qp modification */
+#define BRC_CY 0.1 /* weight for */
+#define BRC_CX_UNDERFLOW 5.
+#define BRC_CX_OVERFLOW -4.
+
+#define BRC_PI_0_5 1.5707963267948966192313216916398
+
+static void
+intel_mfc_bit_rate_control_context_init(struct encode_state *encode_state, 
+                                       struct gen6_mfc_context *mfc_context)
+{
+    VAEncSequenceParameterBufferH264 *pSequenceParameter = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
+    int width_in_mbs = (mfc_context->surface_state.width + 15) / 16;
+    int height_in_mbs = (mfc_context->surface_state.height + 15) / 16;
+    float fps =  pSequenceParameter->time_scale * 0.5 / pSequenceParameter->num_units_in_tick ;
+    int inter_mb_size = pSequenceParameter->bits_per_second * 1.0 / (fps+4.0) / width_in_mbs / height_in_mbs;
+    int intra_mb_size = inter_mb_size * 5.0;
+    int i;
+
+    mfc_context->bit_rate_control_context[SLICE_TYPE_I].target_mb_size = intra_mb_size;
+    mfc_context->bit_rate_control_context[SLICE_TYPE_I].target_frame_size = intra_mb_size * width_in_mbs * height_in_mbs;
+    mfc_context->bit_rate_control_context[SLICE_TYPE_P].target_mb_size = inter_mb_size;
+    mfc_context->bit_rate_control_context[SLICE_TYPE_P].target_frame_size = inter_mb_size * width_in_mbs * height_in_mbs;
+    mfc_context->bit_rate_control_context[SLICE_TYPE_B].target_mb_size = inter_mb_size;
+    mfc_context->bit_rate_control_context[SLICE_TYPE_B].target_frame_size = inter_mb_size * width_in_mbs * height_in_mbs;
+
+    for(i = 0 ; i < 3; i++) {
+        mfc_context->bit_rate_control_context[i].QpPrimeY = 26;
+        mfc_context->bit_rate_control_context[i].MaxQpNegModifier = 6;
+        mfc_context->bit_rate_control_context[i].MaxQpPosModifier = 6;
+        mfc_context->bit_rate_control_context[i].GrowInit = 6;
+        mfc_context->bit_rate_control_context[i].GrowResistance = 4;
+        mfc_context->bit_rate_control_context[i].ShrinkInit = 6;
+        mfc_context->bit_rate_control_context[i].ShrinkResistance = 4;
+        
+        mfc_context->bit_rate_control_context[i].Correct[0] = 8;
+        mfc_context->bit_rate_control_context[i].Correct[1] = 4;
+        mfc_context->bit_rate_control_context[i].Correct[2] = 2;
+        mfc_context->bit_rate_control_context[i].Correct[3] = 2;
+        mfc_context->bit_rate_control_context[i].Correct[4] = 4;
+        mfc_context->bit_rate_control_context[i].Correct[5] = 8;
+    }
+    
+    mfc_context->bit_rate_control_context[SLICE_TYPE_I].TargetSizeInWord = (intra_mb_size + 16)/ 16;
+    mfc_context->bit_rate_control_context[SLICE_TYPE_P].TargetSizeInWord = (inter_mb_size + 16)/ 16;
+    mfc_context->bit_rate_control_context[SLICE_TYPE_B].TargetSizeInWord = (inter_mb_size + 16)/ 16;
+
+    mfc_context->bit_rate_control_context[SLICE_TYPE_I].MaxSizeInWord = mfc_context->bit_rate_control_context[SLICE_TYPE_I].TargetSizeInWord * 1.5;
+    mfc_context->bit_rate_control_context[SLICE_TYPE_P].MaxSizeInWord = mfc_context->bit_rate_control_context[SLICE_TYPE_P].TargetSizeInWord * 1.5;
+    mfc_context->bit_rate_control_context[SLICE_TYPE_B].MaxSizeInWord = mfc_context->bit_rate_control_context[SLICE_TYPE_B].TargetSizeInWord * 1.5;
+}
+
+static void intel_mfc_brc_init(struct encode_state *encode_state,
+                  struct intel_encoder_context* encoder_context)
+{
+    struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
+    VAEncSequenceParameterBufferH264 *pSequenceParameter = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
+    VAEncMiscParameterBuffer* pMiscParamHRD = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeHRD]->buffer;
+    VAEncMiscParameterHRD* pParameterHRD = (VAEncMiscParameterHRD*)pMiscParamHRD->data;
+    double bitrate = pSequenceParameter->bits_per_second;
+    double framerate = (double)pSequenceParameter->time_scale /(2 * (double)pSequenceParameter->num_units_in_tick);
+    int inum = 1, pnum = 0, bnum = 0; /* Gop structure: number of I, P, B frames in the Gop. */
+    int intra_period = pSequenceParameter->intra_period;
+    int ip_period = pSequenceParameter->ip_period;
+    double qp1_size = 0.1 * 8 * 3 * (pSequenceParameter->picture_width_in_mbs<<4) * (pSequenceParameter->picture_height_in_mbs<<4)/2;
+    double qp51_size = 0.001 * 8 * 3 * (pSequenceParameter->picture_width_in_mbs<<4) * (pSequenceParameter->picture_height_in_mbs<<4)/2;
+    double bpf;
+
+    if (pSequenceParameter->ip_period) {
+        pnum = (intra_period + ip_period - 1)/ip_period - 1;
+        bnum = intra_period - inum - pnum;
+    }
+
+    mfc_context->brc.mode = encoder_context->rate_control_mode;
+
+    mfc_context->brc.target_frame_size[SLICE_TYPE_I] = (int)((double)((bitrate * intra_period)/framerate) /
+                                                             (double)(inum + BRC_PWEIGHT * pnum + BRC_BWEIGHT * bnum));
+    mfc_context->brc.target_frame_size[SLICE_TYPE_P] = BRC_PWEIGHT * mfc_context->brc.target_frame_size[SLICE_TYPE_I];
+    mfc_context->brc.target_frame_size[SLICE_TYPE_B] = BRC_BWEIGHT * mfc_context->brc.target_frame_size[SLICE_TYPE_I];
+
+    mfc_context->brc.gop_nums[SLICE_TYPE_I] = inum;
+    mfc_context->brc.gop_nums[SLICE_TYPE_P] = pnum;
+    mfc_context->brc.gop_nums[SLICE_TYPE_B] = bnum;
+
+    bpf = mfc_context->brc.bits_per_frame = bitrate/framerate;
+
+    mfc_context->hrd.buffer_size = (double)pParameterHRD->buffer_size;
+    mfc_context->hrd.current_buffer_fullness =
+        (double)(pParameterHRD->initial_buffer_fullness < mfc_context->hrd.buffer_size)?
+            pParameterHRD->initial_buffer_fullness: mfc_context->hrd.buffer_size/2.;
+    mfc_context->hrd.target_buffer_fullness = (double)mfc_context->hrd.buffer_size/2.;
+    mfc_context->hrd.buffer_capacity = (double)mfc_context->hrd.buffer_size/qp1_size;
+    mfc_context->hrd.violation_noted = 0;
+
+    if ((bpf > qp51_size) && (bpf < qp1_size)) {
+        mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY = 51 - 50*(bpf - qp51_size)/(qp1_size - qp51_size);
+    }
+    else if (bpf >= qp1_size)
+        mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY = 1;
+    else if (bpf <= qp51_size)
+        mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY = 51;
+
+    mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY = mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY;
+    mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY = mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY;
+
+    BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY, 1, 51);
+    BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY, 1, 51);
+    BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY, 1, 51);
+}
+
+int intel_mfc_update_hrd(struct encode_state *encode_state,
+                               struct gen6_mfc_context *mfc_context,
+                               int frame_bits)
+{
+    double prev_bf = mfc_context->hrd.current_buffer_fullness;
+
+    mfc_context->hrd.current_buffer_fullness -= frame_bits;
+
+    if (mfc_context->hrd.buffer_size > 0 && mfc_context->hrd.current_buffer_fullness <= 0.) {
+        mfc_context->hrd.current_buffer_fullness = prev_bf;
+        return BRC_UNDERFLOW;
+    }
+    
+    mfc_context->hrd.current_buffer_fullness += mfc_context->brc.bits_per_frame;
+    if (mfc_context->hrd.buffer_size > 0 && mfc_context->hrd.current_buffer_fullness > mfc_context->hrd.buffer_size) {
+        if (mfc_context->brc.mode == VA_RC_VBR)
+            mfc_context->hrd.current_buffer_fullness = mfc_context->hrd.buffer_size;
+        else {
+            mfc_context->hrd.current_buffer_fullness = prev_bf;
+            return BRC_OVERFLOW;
+        }
+    }
+    return BRC_NO_HRD_VIOLATION;
+}
+
+int intel_mfc_brc_postpack(struct encode_state *encode_state,
+                                 struct gen6_mfc_context *mfc_context,
+                                 int frame_bits)
+{
+    gen6_brc_status sts = BRC_NO_HRD_VIOLATION;
+    VAEncSliceParameterBufferH264 *pSliceParameter = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[0]->buffer; 
+    int slicetype = pSliceParameter->slice_type;
+    int qpi = mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY;
+    int qpp = mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY;
+    int qpb = mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY;
+    int qp; // quantizer of previously encoded slice of current type
+    int qpn; // predicted quantizer for next frame of current type in integer format
+    double qpf; // predicted quantizer for next frame of current type in float format
+    double delta_qp; // QP correction
+    int target_frame_size, frame_size_next;
+    /* Notes:
+     *  x - how far we are from HRD buffer borders
+     *  y - how far we are from target HRD buffer fullness
+     */
+    double x, y;
+    double frame_size_alpha;
+
+    if (slicetype == SLICE_TYPE_SP)
+        slicetype = SLICE_TYPE_P;
+    else if (slicetype == SLICE_TYPE_SI)
+        slicetype = SLICE_TYPE_I;
+
+    qp = mfc_context->bit_rate_control_context[slicetype].QpPrimeY;
+
+    target_frame_size = mfc_context->brc.target_frame_size[slicetype];
+    if (mfc_context->hrd.buffer_capacity < 5)
+        frame_size_alpha = 0;
+    else
+        frame_size_alpha = (double)mfc_context->brc.gop_nums[slicetype];
+    if (frame_size_alpha > 30) frame_size_alpha = 30;
+    frame_size_next = target_frame_size + (double)(target_frame_size - frame_bits) /
+                                          (double)(frame_size_alpha + 1.);
+
+    /* frame_size_next: avoiding negative number and too small value */
+    if ((double)frame_size_next < (double)(target_frame_size * 0.25))
+        frame_size_next = (int)((double)target_frame_size * 0.25);
+
+    qpf = (double)qp * target_frame_size / frame_size_next;
+    qpn = (int)(qpf + 0.5);
+
+    if (qpn == qp) {
+        /* setting qpn we round qpf making mistakes: now we are trying to compensate this */
+        mfc_context->brc.qpf_rounding_accumulator += qpf - qpn;
+        if (mfc_context->brc.qpf_rounding_accumulator > 1.0) {
+            qpn++;
+            mfc_context->brc.qpf_rounding_accumulator = 0.;
+        } else if (mfc_context->brc.qpf_rounding_accumulator < -1.0) {
+            qpn--;
+            mfc_context->brc.qpf_rounding_accumulator = 0.;
+        }
+    }
+    /* making sure that QP is not changing too fast */
+    if ((qpn - qp) > BRC_QP_MAX_CHANGE) qpn = qp + BRC_QP_MAX_CHANGE;
+    else if ((qpn - qp) < -BRC_QP_MAX_CHANGE) qpn = qp - BRC_QP_MAX_CHANGE;
+    /* making sure that with QP predictions we did do not leave QPs range */
+    BRC_CLIP(qpn, 1, 51);
+
+    /* checking wthether HRD compliance is still met */
+    sts = intel_mfc_update_hrd(encode_state, mfc_context, frame_bits);
+
+    /* calculating QP delta as some function*/
+    x = mfc_context->hrd.target_buffer_fullness - mfc_context->hrd.current_buffer_fullness;
+    if (x > 0) {
+        x /= mfc_context->hrd.target_buffer_fullness;
+        y = mfc_context->hrd.current_buffer_fullness;
+    }
+    else {
+        x /= (mfc_context->hrd.buffer_size - mfc_context->hrd.target_buffer_fullness);
+        y = mfc_context->hrd.buffer_size - mfc_context->hrd.current_buffer_fullness;
+    }
+    if (y < 0.01) y = 0.01;
+    if (x > 1) x = 1;
+    else if (x < -1) x = -1;
+
+    delta_qp = BRC_QP_MAX_CHANGE*exp(-1/y)*sin(BRC_PI_0_5 * x);
+    qpn = (int)(qpn + delta_qp + 0.5);
+
+    /* making sure that with QP predictions we did do not leave QPs range */
+    BRC_CLIP(qpn, 1, 51);
+
+    if (sts == BRC_NO_HRD_VIOLATION) { // no HRD violation
+        /* correcting QPs of slices of other types */
+        if (slicetype == SLICE_TYPE_P) {
+            if (abs(qpn + BRC_P_B_QP_DIFF - qpb) > 2)
+                mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY += (qpn + BRC_P_B_QP_DIFF - qpb) >> 1;
+            if (abs(qpn - BRC_I_P_QP_DIFF - qpi) > 2)
+                mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY += (qpn - BRC_I_P_QP_DIFF - qpi) >> 1;
+        } else if (slicetype == SLICE_TYPE_I) {
+            if (abs(qpn + BRC_I_B_QP_DIFF - qpb) > 4)
+                mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY += (qpn + BRC_I_B_QP_DIFF - qpb) >> 2;
+            if (abs(qpn + BRC_I_P_QP_DIFF - qpp) > 2)
+                mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY += (qpn + BRC_I_P_QP_DIFF - qpp) >> 2;
+        } else { // SLICE_TYPE_B
+            if (abs(qpn - BRC_P_B_QP_DIFF - qpp) > 2)
+                mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY += (qpn - BRC_P_B_QP_DIFF - qpp) >> 1;
+            if (abs(qpn - BRC_I_B_QP_DIFF - qpi) > 4)
+                mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY += (qpn - BRC_I_B_QP_DIFF - qpi) >> 2;
+        }
+        BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY, 1, 51);
+        BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY, 1, 51);
+        BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY, 1, 51);
+    } else if (sts == BRC_UNDERFLOW) { // underflow
+        if (qpn <= qp) qpn = qp + 1;
+        if (qpn > 51) {
+            qpn = 51;
+            sts = BRC_UNDERFLOW_WITH_MAX_QP; //underflow with maxQP
+        }
+    } else if (sts == BRC_OVERFLOW) {
+        if (qpn >= qp) qpn = qp - 1;
+        if (qpn < 1) { // < 0 (?) overflow with minQP
+            qpn = 1;
+            sts = BRC_OVERFLOW_WITH_MIN_QP; // bit stuffing to be done
+        }
+    }
+
+    mfc_context->bit_rate_control_context[slicetype].QpPrimeY = qpn;
+
+    return sts;
+}
+
+static void intel_mfc_hrd_context_init(struct encode_state *encode_state,
+                          struct intel_encoder_context *encoder_context)
+{
+    struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
+    VAEncSequenceParameterBufferH264 *pSequenceParameter = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
+    unsigned int rate_control_mode = encoder_context->rate_control_mode;
+    int target_bit_rate = pSequenceParameter->bits_per_second;
+    
+    // current we only support CBR mode.
+    if (rate_control_mode == VA_RC_CBR) {
+        mfc_context->vui_hrd.i_bit_rate_value = target_bit_rate >> 10;
+        mfc_context->vui_hrd.i_cpb_size_value = (target_bit_rate * 8) >> 10;
+        mfc_context->vui_hrd.i_initial_cpb_removal_delay = mfc_context->vui_hrd.i_cpb_size_value * 0.5 * 1024 / target_bit_rate * 90000;
+        mfc_context->vui_hrd.i_cpb_removal_delay = 2;
+        mfc_context->vui_hrd.i_frame_number = 0;
+
+        mfc_context->vui_hrd.i_initial_cpb_removal_delay_length = 24; 
+        mfc_context->vui_hrd.i_cpb_removal_delay_length = 24;
+        mfc_context->vui_hrd.i_dpb_output_delay_length = 24;
+    }
+
+}
+
+void 
+intel_mfc_hrd_context_update(struct encode_state *encode_state, 
+                          struct gen6_mfc_context *mfc_context) 
+{
+    mfc_context->vui_hrd.i_frame_number++;
+}
+
+int intel_mfc_interlace_check(VADriverContextP ctx,
+                   struct encode_state *encode_state,
+                   struct intel_encoder_context *encoder_context) 
+{
+    struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
+    VAEncSliceParameterBufferH264 *pSliceParameter;
+    int i;
+    int mbCount = 0;
+    int width_in_mbs = (mfc_context->surface_state.width + 15) / 16;
+    int height_in_mbs = (mfc_context->surface_state.height + 15) / 16;
+  
+    for (i = 0; i < encode_state->num_slice_params_ext; i++) {
+        pSliceParameter = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[i]->buffer; 
+        mbCount += pSliceParameter->num_macroblocks; 
+    }
+    
+    if ( mbCount == ( width_in_mbs * height_in_mbs ) )
+        return 0;
+
+    return 1;
+}
+
+void intel_mfc_brc_prepare(struct encode_state *encode_state,
+                          struct intel_encoder_context *encoder_context)
+{
+    unsigned int rate_control_mode = encoder_context->rate_control_mode;
+    struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
+
+    if (rate_control_mode == VA_RC_CBR) {
+        /*Programing bit rate control */
+        if ( mfc_context->bit_rate_control_context[SLICE_TYPE_I].MaxSizeInWord == 0 ) {
+            intel_mfc_bit_rate_control_context_init(encode_state, mfc_context);
+            intel_mfc_brc_init(encode_state, encoder_context);
+        }
+
+        /*Programing HRD control */
+        if ( mfc_context->vui_hrd.i_cpb_size_value == 0 )
+            intel_mfc_hrd_context_init(encode_state, encoder_context);    
+    }
+}
+
index 0748584..b226a1b 100644 (file)
@@ -333,133 +333,6 @@ gen75_mfc_avc_insert_object(VADriverContextP ctx, struct intel_encoder_context *
 }
 
 
-static void
-gen75_mfc_bit_rate_control_context_init(struct encode_state *encode_state, 
-                                       struct gen6_mfc_context *mfc_context)
-{
-    VAEncSequenceParameterBufferH264 *pSequenceParameter = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
-    int width_in_mbs = (mfc_context->surface_state.width + 15) / 16;
-    int height_in_mbs = (mfc_context->surface_state.height + 15) / 16;
-    float fps =  pSequenceParameter->time_scale * 0.5 / pSequenceParameter->num_units_in_tick ;
-    int inter_mb_size = pSequenceParameter->bits_per_second * 1.0 / (fps+4.0) / width_in_mbs / height_in_mbs;
-    int intra_mb_size = inter_mb_size * 5.0;
-    int i;
-
-    mfc_context->bit_rate_control_context[SLICE_TYPE_I].target_mb_size = intra_mb_size;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_I].target_frame_size = intra_mb_size * width_in_mbs * height_in_mbs;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_P].target_mb_size = inter_mb_size;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_P].target_frame_size = inter_mb_size * width_in_mbs * height_in_mbs;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_B].target_mb_size = inter_mb_size;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_B].target_frame_size = inter_mb_size * width_in_mbs * height_in_mbs;
-
-    for(i = 0 ; i < 3; i++) {
-        mfc_context->bit_rate_control_context[i].QpPrimeY = 26;
-        mfc_context->bit_rate_control_context[i].MaxQpNegModifier = 6;
-        mfc_context->bit_rate_control_context[i].MaxQpPosModifier = 6;
-        mfc_context->bit_rate_control_context[i].GrowInit = 6;
-        mfc_context->bit_rate_control_context[i].GrowResistance = 4;
-        mfc_context->bit_rate_control_context[i].ShrinkInit = 6;
-        mfc_context->bit_rate_control_context[i].ShrinkResistance = 4;
-        
-        mfc_context->bit_rate_control_context[i].Correct[0] = 8;
-        mfc_context->bit_rate_control_context[i].Correct[1] = 4;
-        mfc_context->bit_rate_control_context[i].Correct[2] = 2;
-        mfc_context->bit_rate_control_context[i].Correct[3] = 2;
-        mfc_context->bit_rate_control_context[i].Correct[4] = 4;
-        mfc_context->bit_rate_control_context[i].Correct[5] = 8;
-    }
-    
-    mfc_context->bit_rate_control_context[SLICE_TYPE_I].TargetSizeInWord = (intra_mb_size + 16)/ 16;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_P].TargetSizeInWord = (inter_mb_size + 16)/ 16;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_B].TargetSizeInWord = (inter_mb_size + 16)/ 16;
-
-    mfc_context->bit_rate_control_context[SLICE_TYPE_I].MaxSizeInWord = mfc_context->bit_rate_control_context[SLICE_TYPE_I].TargetSizeInWord * 1.5;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_P].MaxSizeInWord = mfc_context->bit_rate_control_context[SLICE_TYPE_P].TargetSizeInWord * 1.5;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_B].MaxSizeInWord = mfc_context->bit_rate_control_context[SLICE_TYPE_B].TargetSizeInWord * 1.5;
-}
-
-static void
-gen75_mfc_brc_init(struct encode_state *encode_state,
-                  struct intel_encoder_context* encoder_context)
-{
-    struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
-    VAEncSequenceParameterBufferH264 *pSequenceParameter = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
-    VAEncMiscParameterBuffer* pMiscParamHRD = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeHRD]->buffer;
-    VAEncMiscParameterHRD* pParameterHRD = (VAEncMiscParameterHRD*)pMiscParamHRD->data;
-    double bitrate = pSequenceParameter->bits_per_second;
-    double framerate = (double)pSequenceParameter->time_scale /(2 * (double)pSequenceParameter->num_units_in_tick);
-    int inum = 1, pnum = 0, bnum = 0; /* Gop structure: number of I, P, B frames in the Gop. */
-    int intra_period = pSequenceParameter->intra_period;
-    int ip_period = pSequenceParameter->ip_period;
-    double qp1_size = 0.1 * 8 * 3 * (pSequenceParameter->picture_width_in_mbs<<4) * (pSequenceParameter->picture_height_in_mbs<<4)/2;
-    double qp51_size = 0.001 * 8 * 3 * (pSequenceParameter->picture_width_in_mbs<<4) * (pSequenceParameter->picture_height_in_mbs<<4)/2;
-    double bpf;
-
-    if (pSequenceParameter->ip_period) {
-        pnum = (intra_period + ip_period - 1)/ip_period - 1;
-        bnum = intra_period - inum - pnum;
-    }
-
-    mfc_context->brc.mode = encoder_context->rate_control_mode;
-
-    mfc_context->brc.target_frame_size[SLICE_TYPE_I] = (int)((double)((bitrate * intra_period)/framerate) /
-                                                             (double)(inum + BRC_PWEIGHT * pnum + BRC_BWEIGHT * bnum));
-    mfc_context->brc.target_frame_size[SLICE_TYPE_P] = BRC_PWEIGHT * mfc_context->brc.target_frame_size[SLICE_TYPE_I];
-    mfc_context->brc.target_frame_size[SLICE_TYPE_B] = BRC_BWEIGHT * mfc_context->brc.target_frame_size[SLICE_TYPE_I];
-
-    mfc_context->brc.gop_nums[SLICE_TYPE_I] = inum;
-    mfc_context->brc.gop_nums[SLICE_TYPE_P] = pnum;
-    mfc_context->brc.gop_nums[SLICE_TYPE_B] = bnum;
-
-    bpf = mfc_context->brc.bits_per_frame = bitrate/framerate;
-
-    mfc_context->hrd.buffer_size = (double)pParameterHRD->buffer_size;
-    mfc_context->hrd.current_buffer_fullness =
-        (double)(pParameterHRD->initial_buffer_fullness < mfc_context->hrd.buffer_size)?
-            pParameterHRD->initial_buffer_fullness: mfc_context->hrd.buffer_size/2.;
-    mfc_context->hrd.target_buffer_fullness = (double)mfc_context->hrd.buffer_size/2.;
-    mfc_context->hrd.buffer_capacity = (double)mfc_context->hrd.buffer_size/qp1_size;
-    mfc_context->hrd.violation_noted = 0;
-
-    if ((bpf > qp51_size) && (bpf < qp1_size)) {
-        mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY = 51 - 50*(bpf - qp51_size)/(qp1_size - qp51_size);
-    }
-    else if (bpf >= qp1_size)
-        mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY = 1;
-    else if (bpf <= qp51_size)
-        mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY = 51;
-
-    mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY = mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY;
-    mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY = mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY;
-
-    BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY, 1, 51);
-    BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY, 1, 51);
-    BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY, 1, 51);
-}
-
-static void 
-gen75_mfc_hrd_context_init(struct encode_state *encode_state,
-                          struct intel_encoder_context *encoder_context)
-{
-    struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
-    VAEncSequenceParameterBufferH264 *pSequenceParameter = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
-    unsigned int rate_control_mode = encoder_context->rate_control_mode;
-    int target_bit_rate = pSequenceParameter->bits_per_second;
-    
-    // current we only support CBR mode.
-    if (rate_control_mode == VA_RC_CBR) {
-        mfc_context->vui_hrd.i_bit_rate_value = target_bit_rate >> 10;
-        mfc_context->vui_hrd.i_cpb_size_value = (target_bit_rate * 8) >> 10;
-        mfc_context->vui_hrd.i_initial_cpb_removal_delay = mfc_context->vui_hrd.i_cpb_size_value * 0.5 * 1024 / target_bit_rate * 90000;
-        mfc_context->vui_hrd.i_cpb_removal_delay = 2;
-        mfc_context->vui_hrd.i_frame_number = 0;
-
-        mfc_context->vui_hrd.i_initial_cpb_removal_delay_length = 24; 
-        mfc_context->vui_hrd.i_cpb_removal_delay_length = 24;
-        mfc_context->vui_hrd.i_dpb_output_delay_length = 24;
-    }
-
-}
 
 static void 
 gen75_mfc_free_avc_surface(void **data)
@@ -885,187 +758,6 @@ gen75_mfc_stop(VADriverContextP ctx,
 }
 
 
-static int gen75_mfc_update_hrd(struct encode_state *encode_state,
-                               struct gen6_mfc_context *mfc_context,
-                               int frame_bits)
-{
-    double prev_bf = mfc_context->hrd.current_buffer_fullness;
-
-    mfc_context->hrd.current_buffer_fullness -= frame_bits;
-
-    if (mfc_context->hrd.buffer_size > 0 && mfc_context->hrd.current_buffer_fullness <= 0.) {
-        mfc_context->hrd.current_buffer_fullness = prev_bf;
-        return BRC_UNDERFLOW;
-    }
-    
-    mfc_context->hrd.current_buffer_fullness += mfc_context->brc.bits_per_frame;
-    if (mfc_context->hrd.buffer_size > 0 && mfc_context->hrd.current_buffer_fullness > mfc_context->hrd.buffer_size) {
-        if (mfc_context->brc.mode == VA_RC_VBR)
-            mfc_context->hrd.current_buffer_fullness = mfc_context->hrd.buffer_size;
-        else {
-            mfc_context->hrd.current_buffer_fullness = prev_bf;
-            return BRC_OVERFLOW;
-        }
-    }
-    return BRC_NO_HRD_VIOLATION;
-}
-
-
-static int gen75_mfc_brc_postpack(struct encode_state *encode_state,
-                                 struct gen6_mfc_context *mfc_context,
-                                 int frame_bits)
-{
-    gen6_brc_status sts = BRC_NO_HRD_VIOLATION;
-    VAEncSliceParameterBufferH264 *pSliceParameter = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[0]->buffer; 
-    int slicetype = pSliceParameter->slice_type;
-    int qpi = mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY;
-    int qpp = mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY;
-    int qpb = mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY;
-    int qp; // quantizer of previously encoded slice of current type
-    int qpn; // predicted quantizer for next frame of current type in integer format
-    double qpf; // predicted quantizer for next frame of current type in float format
-    double delta_qp; // QP correction
-    int target_frame_size, frame_size_next;
-    /* Notes:
-     *  x - how far we are from HRD buffer borders
-     *  y - how far we are from target HRD buffer fullness
-     */
-    double x, y;
-    double frame_size_alpha;
-
-    if (slicetype == SLICE_TYPE_SP)
-        slicetype = SLICE_TYPE_P;
-    else if (slicetype == SLICE_TYPE_SI)
-        slicetype = SLICE_TYPE_I;
-
-    qp = mfc_context->bit_rate_control_context[slicetype].QpPrimeY;
-
-    target_frame_size = mfc_context->brc.target_frame_size[slicetype];
-    if (mfc_context->hrd.buffer_capacity < 5)
-        frame_size_alpha = 0;
-    else
-        frame_size_alpha = (double)mfc_context->brc.gop_nums[slicetype];
-    if (frame_size_alpha > 30) frame_size_alpha = 30;
-    frame_size_next = target_frame_size + (double)(target_frame_size - frame_bits) /
-                                          (double)(frame_size_alpha + 1.);
-
-    /* frame_size_next: avoiding negative number and too small value */
-    if ((double)frame_size_next < (double)(target_frame_size * 0.25))
-        frame_size_next = (int)((double)target_frame_size * 0.25);
-
-    qpf = (double)qp * target_frame_size / frame_size_next;
-    qpn = (int)(qpf + 0.5);
-
-    if (qpn == qp) {
-        /* setting qpn we round qpf making mistakes: now we are trying to compensate this */
-        mfc_context->brc.qpf_rounding_accumulator += qpf - qpn;
-        if (mfc_context->brc.qpf_rounding_accumulator > 1.0) {
-            qpn++;
-            mfc_context->brc.qpf_rounding_accumulator = 0.;
-        } else if (mfc_context->brc.qpf_rounding_accumulator < -1.0) {
-            qpn--;
-            mfc_context->brc.qpf_rounding_accumulator = 0.;
-        }
-    }
-    /* making sure that QP is not changing too fast */
-    if ((qpn - qp) > BRC_QP_MAX_CHANGE) qpn = qp + BRC_QP_MAX_CHANGE;
-    else if ((qpn - qp) < -BRC_QP_MAX_CHANGE) qpn = qp - BRC_QP_MAX_CHANGE;
-    /* making sure that with QP predictions we did do not leave QPs range */
-    BRC_CLIP(qpn, 1, 51);
-
-    /* checking wthether HRD compliance is still met */
-    sts = gen75_mfc_update_hrd(encode_state, mfc_context, frame_bits);
-
-    /* calculating QP delta as some function*/
-    x = mfc_context->hrd.target_buffer_fullness - mfc_context->hrd.current_buffer_fullness;
-    if (x > 0) {
-        x /= mfc_context->hrd.target_buffer_fullness;
-        y = mfc_context->hrd.current_buffer_fullness;
-    }
-    else {
-        x /= (mfc_context->hrd.buffer_size - mfc_context->hrd.target_buffer_fullness);
-        y = mfc_context->hrd.buffer_size - mfc_context->hrd.current_buffer_fullness;
-    }
-    if (y < 0.01) y = 0.01;
-    if (x > 1) x = 1;
-    else if (x < -1) x = -1;
-
-    delta_qp = BRC_QP_MAX_CHANGE*exp(-1/y)*sin(BRC_PI_0_5 * x);
-    qpn = (int)(qpn + delta_qp + 0.5);
-
-    /* making sure that with QP predictions we did do not leave QPs range */
-    BRC_CLIP(qpn, 1, 51);
-
-    if (sts == BRC_NO_HRD_VIOLATION) { // no HRD violation
-        /* correcting QPs of slices of other types */
-        if (slicetype == SLICE_TYPE_P) {
-            if (abs(qpn + BRC_P_B_QP_DIFF - qpb) > 2)
-                mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY += (qpn + BRC_P_B_QP_DIFF - qpb) >> 1;
-            if (abs(qpn - BRC_I_P_QP_DIFF - qpi) > 2)
-                mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY += (qpn - BRC_I_P_QP_DIFF - qpi) >> 1;
-        } else if (slicetype == SLICE_TYPE_I) {
-            if (abs(qpn + BRC_I_B_QP_DIFF - qpb) > 4)
-                mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY += (qpn + BRC_I_B_QP_DIFF - qpb) >> 2;
-            if (abs(qpn + BRC_I_P_QP_DIFF - qpp) > 2)
-                mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY += (qpn + BRC_I_P_QP_DIFF - qpp) >> 2;
-        } else { // SLICE_TYPE_B
-            if (abs(qpn - BRC_P_B_QP_DIFF - qpp) > 2)
-                mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY += (qpn - BRC_P_B_QP_DIFF - qpp) >> 1;
-            if (abs(qpn - BRC_I_B_QP_DIFF - qpi) > 4)
-                mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY += (qpn - BRC_I_B_QP_DIFF - qpi) >> 2;
-        }
-        BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_I].QpPrimeY, 1, 51);
-        BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_P].QpPrimeY, 1, 51);
-        BRC_CLIP(mfc_context->bit_rate_control_context[SLICE_TYPE_B].QpPrimeY, 1, 51);
-    } else if (sts == BRC_UNDERFLOW) { // underflow
-        if (qpn <= qp) qpn = qp + 1;
-        if (qpn > 51) {
-            qpn = 51;
-            sts = BRC_UNDERFLOW_WITH_MAX_QP; //underflow with maxQP
-        }
-    } else if (sts == BRC_OVERFLOW) {
-        if (qpn >= qp) qpn = qp - 1;
-        if (qpn < 1) { // < 0 (?) overflow with minQP
-            qpn = 1;
-            sts = BRC_OVERFLOW_WITH_MIN_QP; // bit stuffing to be done
-        }
-    }
-
-    mfc_context->bit_rate_control_context[slicetype].QpPrimeY = qpn;
-
-    return sts;
-}
-
-static void 
-gen75_mfc_hrd_context_update(struct encode_state *encode_state, 
-                          struct gen6_mfc_context *mfc_context) 
-{
-    mfc_context->vui_hrd.i_frame_number++;
-}
-
-
-static int interlace_check(VADriverContextP ctx,
-                   struct encode_state *encode_state,
-                   struct intel_encoder_context *encoder_context)
-{
-    struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
-    VAEncSliceParameterBufferH264 *pSliceParameter;
-    int i;
-    int mbCount = 0;
-    int width_in_mbs = (mfc_context->surface_state.width + 15) / 16;
-    int height_in_mbs = (mfc_context->surface_state.height + 15) / 16;
-  
-    for (i = 0; i < encode_state->num_slice_params_ext; i++) {
-        pSliceParameter = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[i]->buffer; 
-        mbCount += pSliceParameter->num_macroblocks; 
-    }
-    
-    if ( mbCount == ( width_in_mbs * height_in_mbs ) )
-        return 0;
-
-    return 1;
-}
-
 static void
 gen75_mfc_avc_slice_state(VADriverContextP ctx,
                          VAEncPictureParameterBufferH264 *pic_param,
@@ -1900,7 +1592,7 @@ gen75_mfc_avc_pipeline_programing(VADriverContextP ctx,
     struct intel_batchbuffer *batch = encoder_context->base.batch;
     dri_bo *slice_batch_bo;
 
-    if ( interlace_check(ctx, encode_state, encoder_context) ) {
+    if ( intel_mfc_interlace_check(ctx, encode_state, encoder_context) ) {
         fprintf(stderr, "Current VA driver don't support interlace mode!\n");
         assert(0);
         return; 
@@ -1952,9 +1644,9 @@ gen75_mfc_avc_encode_picture(VADriverContextP ctx,
         gen75_mfc_run(ctx, encode_state, encoder_context);
         if (rate_control_mode == VA_RC_CBR /*|| rate_control_mode == VA_RC_VBR*/) {
             gen75_mfc_stop(ctx, encode_state, encoder_context, &current_frame_bits_size);
-            sts = gen75_mfc_brc_postpack(encode_state, mfc_context, current_frame_bits_size);
+            sts = intel_mfc_brc_postpack(encode_state, mfc_context, current_frame_bits_size);
             if (sts == BRC_NO_HRD_VIOLATION) {
-                gen75_mfc_hrd_context_update(encode_state, mfc_context);
+                intel_mfc_hrd_context_update(encode_state, mfc_context);
                 break;
             }
             else if (sts == BRC_OVERFLOW_WITH_MIN_QP || sts == BRC_UNDERFLOW_WITH_MAX_QP) {
@@ -1972,24 +1664,6 @@ gen75_mfc_avc_encode_picture(VADriverContextP ctx,
     return VA_STATUS_SUCCESS;
 }
 
-static void gen75_mfc_brc_prepare(struct encode_state *encode_state,
-                          struct intel_encoder_context *encoder_context)
-{
-    unsigned int rate_control_mode = encoder_context->rate_control_mode;
-    struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
-
-    if (rate_control_mode == VA_RC_CBR) {
-        /*Programing bit rate control */
-        if ( mfc_context->bit_rate_control_context[SLICE_TYPE_I].MaxSizeInWord == 0 ) {
-            gen75_mfc_bit_rate_control_context_init(encode_state, mfc_context);
-            gen75_mfc_brc_init(encode_state, encoder_context);
-        }
-
-        /*Programing HRD control */
-        if ( mfc_context->vui_hrd.i_cpb_size_value == 0 )
-            gen75_mfc_hrd_context_init(encode_state, encoder_context);    
-    }
-}
 
 static void
 gen75_mfc_context_destroy(void *context)
@@ -2105,7 +1779,7 @@ Bool gen75_mfc_context_init(VADriverContextP ctx, struct intel_encoder_context *
     encoder_context->mfc_context = mfc_context;
     encoder_context->mfc_context_destroy = gen75_mfc_context_destroy;
     encoder_context->mfc_pipeline = gen75_mfc_pipeline;
-    encoder_context->mfc_brc_prepare = gen75_mfc_brc_prepare;
+    encoder_context->mfc_brc_prepare = intel_mfc_brc_prepare;
 
     return True;
 }
index 98102c8..1b6f6a7 100644 (file)
@@ -366,7 +366,7 @@ gen7_mfc_context_init(VADriverContextP ctx, struct intel_encoder_context *encode
     encoder_context->mfc_context = mfc_context;
     encoder_context->mfc_context_destroy = gen6_mfc_context_destroy;
     encoder_context->mfc_pipeline = gen6_mfc_pipeline;
-    encoder_context->mfc_brc_prepare = gen6_mfc_brc_prepare;
+    encoder_context->mfc_brc_prepare = intel_mfc_brc_prepare;
 
     return True;
 }