Discussion:
[PATCH 4/4] VP9 encoder: use generic rate control parameters
(too old to reply)
Mark Thompson
2016-12-23 01:11:38 UTC
Permalink
Also adds support for fractional framerate.

Signed-off-by: Mark Thompson <***@jkqxz.net>
---
src/gen9_vp9_encoder.c | 232 +++++++------------------------------------------
src/gen9_vp9_encoder.h | 12 +--
src/i965_drv_video.c | 10 +--
src/i965_encoder.c | 36 ++++++++
src/i965_encoder.h | 1 +
5 files changed, 69 insertions(+), 222 deletions(-)

diff --git a/src/gen9_vp9_encoder.c b/src/gen9_vp9_encoder.c
index 3ea1537..05d86da 100644
--- a/src/gen9_vp9_encoder.c
+++ b/src/gen9_vp9_encoder.c
@@ -1201,8 +1201,8 @@ void gen9_vp9_set_curbe_brc(VADriverContextP ctx,
VP9_BRC_KBPS;
cmd->dw9.min_bit_rate = (vp9_state->min_bit_rate + VP9_BRC_KBPS - 1) / VP9_BRC_KBPS *
VP9_BRC_KBPS;
- cmd->dw10.frame_ratem = vp9_state->frame_rate;
- cmd->dw11.frame_rated = 1;
+ cmd->dw10.frame_ratem = vp9_state->framerate.num;
+ cmd->dw11.frame_rated = vp9_state->framerate.den;

cmd->dw14.avbr_accuracy = 30;
cmd->dw14.avbr_convergence = 150;
@@ -1235,8 +1235,8 @@ void gen9_vp9_set_curbe_brc(VADriverContextP ctx,
cmd->dw17.enable_dynamic_scaling = vp9_state->dys_in_use;
cmd->dw17.brc_overshoot_cbr_pct = 150;

- dInputBitsPerFrame = (double)(cmd->dw8.max_bit_rate) / (vp9_state->frame_rate);
- dbps_ratio = dInputBitsPerFrame / ((double)(vp9_state->vbv_buffer_size_in_bit) / 30);
+ dInputBitsPerFrame = (double)cmd->dw8.max_bit_rate * (double)vp9_state->framerate.den / (double)vp9_state->framerate.num;
+ dbps_ratio = dInputBitsPerFrame / ((double)vp9_state->vbv_buffer_size_in_bit / 30.0);
if (dbps_ratio < 0.1)
dbps_ratio = 0.1;
if (dbps_ratio > 3.5)
@@ -1423,7 +1423,6 @@ gen9_vp9_brc_init_reset_kernel(VADriverContextP ctx,
brc_initreset_curbe.initbrc = !vp9_state->brc_inited;
brc_initreset_curbe.mbbrc_enabled = 0;
brc_initreset_curbe.ref_frame_flag = vp9_state->ref_frame_flag;
- brc_initreset_curbe.frame_rate = vp9_state->frame_rate;

vme_context->pfn_set_curbe_brc(ctx, encode_state,
gpe_context,
@@ -1523,7 +1522,6 @@ gen9_vp9_brc_intra_dist_kernel(VADriverContextP ctx,
brc_intra_dist_curbe.initbrc = !vp9_state->brc_inited;
brc_intra_dist_curbe.mbbrc_enabled = 0;
brc_intra_dist_curbe.ref_frame_flag = vp9_state->ref_frame_flag;
- brc_intra_dist_curbe.frame_rate = vp9_state->frame_rate;

vme_context->pfn_set_curbe_brc(ctx, encode_state,
gpe_context,
@@ -3926,169 +3924,40 @@ gen9_encode_vp9_check_parameter(VADriverContextP ctx,
return VA_STATUS_ERROR_UNIMPLEMENTED;

if (vp9_state->brc_enabled) {
- if (vp9_state->brc_flag_check & VP9_BRC_FAILURE) {
- WARN_ONCE("Rate control misc_parameter is required for BRC\n");
- return VA_STATUS_ERROR_INVALID_PARAMETER;
- }
+ if (vp9_state->first_frame || vp9_state->picture_coding_type == KEY_FRAME) {
+ vp9_state->brc_reset = encoder_context->brc.need_reset || vp9_state->first_frame;

- if (vp9_state->first_frame) {
- unsigned int brc_flag;
- VAEncMiscParameterBuffer *misc_param;
-
- brc_flag = VP9_BRC_SEQ | VP9_BRC_RC;
- if ((vp9_state->brc_flag_check & brc_flag) != brc_flag) {
- WARN_ONCE("SPS/RC misc is required for BRC\n");
+ if (!encoder_context->brc.framerate[0].num || !encoder_context->brc.framerate[0].den ||
+ !encoder_context->brc.bits_per_second[0])
return VA_STATUS_ERROR_INVALID_PARAMETER;
- }

- /* check the corresponding BRC parameter for CBR and VBR */
- if (encoder_context->rate_control_mode == VA_RC_CBR) {
- vp9_state->target_bit_rate = seq_param->bits_per_second;
- vp9_state->gop_size = seq_param->intra_period;
-
- if (vp9_state->brc_flag_check & VP9_BRC_HRD) {
- VAEncMiscParameterHRD *misc_param_hrd;
-
- misc_param = (VAEncMiscParameterBuffer *)
- encode_state->misc_param[VAEncMiscParameterTypeHRD][0]->buffer;
- misc_param_hrd = (VAEncMiscParameterHRD *)misc_param->data;
-
- vp9_state->init_vbv_buffer_fullness_in_bit = misc_param_hrd->initial_buffer_fullness;
- vp9_state->vbv_buffer_size_in_bit = misc_param_hrd->buffer_size;
- }
-
- if (vp9_state->brc_flag_check & VP9_BRC_FR) {
- VAEncMiscParameterFrameRate *misc_param_fr;
-
- misc_param = (VAEncMiscParameterBuffer *)
- encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
- misc_param_fr = (VAEncMiscParameterFrameRate *)misc_param->data;
-
- vp9_state->frame_rate = misc_param_fr->framerate;
- } else {
- /* Assign the default frame rate */
- vp9_state->frame_rate = 30;
- }
-
- /* RC misc will override HRD parameter */
- if (vp9_state->brc_flag_check & VP9_BRC_RC) {
- VAEncMiscParameterRateControl *misc_param_rc;
-
- misc_param = (VAEncMiscParameterBuffer *)
- encode_state->misc_param[VAEncMiscParameterTypeRateControl][0]->buffer;
- misc_param_rc = (VAEncMiscParameterRateControl *)misc_param->data;
-
- vp9_state->target_bit_rate = misc_param_rc->bits_per_second;
- vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
- misc_param_rc->window_size;
- vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
- vp9_state->window_size = misc_param_rc->window_size;
- }
+ vp9_state->gop_size = encoder_context->brc.gop_size;
+ vp9_state->framerate = encoder_context->brc.framerate[0];
+
+ if (encoder_context->rate_control_mode == VA_RC_CBR ||
+ !encoder_context->brc.target_percentage[0]) {
+ vp9_state->target_bit_rate = encoder_context->brc.bits_per_second[0];
vp9_state->max_bit_rate = vp9_state->target_bit_rate;
vp9_state->min_bit_rate = vp9_state->target_bit_rate;
} else {
- /* VBR mode */
- brc_flag = VP9_BRC_SEQ | VP9_BRC_RC;
- vp9_state->target_bit_rate = seq_param->bits_per_second;
- vp9_state->gop_size = seq_param->intra_period;
-
- if (vp9_state->brc_flag_check & VP9_BRC_FR) {
- VAEncMiscParameterFrameRate *misc_param_fr;
-
- misc_param = (VAEncMiscParameterBuffer *)
- encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
- misc_param_fr = (VAEncMiscParameterFrameRate *)misc_param->data;
-
- vp9_state->frame_rate = misc_param_fr->framerate;
- } else {
- /* Assign the default frame rate */
- vp9_state->frame_rate = 30;
- }
-
- if (vp9_state->brc_flag_check & VP9_BRC_RC) {
- VAEncMiscParameterRateControl *misc_param_rc;
-
- misc_param = (VAEncMiscParameterBuffer *)
- encode_state->misc_param[VAEncMiscParameterTypeRateControl][0]->buffer;
- misc_param_rc = (VAEncMiscParameterRateControl *)misc_param->data;
-
- vp9_state->max_bit_rate = misc_param_rc->bits_per_second;
- vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
- misc_param_rc->window_size;
- vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
- vp9_state->target_bit_rate = (misc_param_rc->bits_per_second / 100) *
- misc_param_rc->target_percentage;
- vp9_state->min_bit_rate = (misc_param_rc->bits_per_second / 100) *
- (2 * misc_param_rc->target_percentage - 100);
- vp9_state->target_percentage = misc_param_rc->target_percentage;
- vp9_state->window_size = misc_param_rc->window_size;
- }
- }
- }
- else if (vp9_state->picture_coding_type == KEY_FRAME){
- VAEncMiscParameterBuffer *misc_param;
- /* update the BRC parameter only when it is key-frame */
- /* If the parameter related with RC is changed. Reset BRC */
- if (vp9_state->brc_flag_check & VP9_BRC_FR) {
- VAEncMiscParameterFrameRate *misc_param_fr;
-
- misc_param = (VAEncMiscParameterBuffer *)
- encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
- misc_param_fr = (VAEncMiscParameterFrameRate *)misc_param->data;
-
- if (vp9_state->frame_rate != misc_param_fr->framerate) {
- vp9_state->brc_reset = 1;
- vp9_state->frame_rate = misc_param_fr->framerate;
- }
- }
-
- /* check the GOP size. And bit_per_second in SPS is ignored */
- if (vp9_state->brc_flag_check & VP9_BRC_SEQ) {
- if (vp9_state->gop_size != seq_param->intra_period) {
- vp9_state->brc_reset = 1;
- vp9_state->gop_size = seq_param->intra_period;
- }
+ vp9_state->max_bit_rate = encoder_context->brc.bits_per_second[0];
+ vp9_state->target_bit_rate = vp9_state->max_bit_rate * encoder_context->brc.target_percentage[0] / 100;
+ if (2 * vp9_state->target_bit_rate < vp9_state->max_bit_rate)
+ vp9_state->min_bit_rate = 0;
+ else
+ vp9_state->min_bit_rate = 2 * vp9_state->target_bit_rate - vp9_state->max_bit_rate;
}

- /* update the bit_per_second */
- if (vp9_state->brc_flag_check & VP9_BRC_RC) {
- VAEncMiscParameterRateControl *misc_param_rc;
-
- misc_param = (VAEncMiscParameterBuffer *)
- encode_state->misc_param[VAEncMiscParameterTypeRateControl][0]->buffer;
- misc_param_rc = (VAEncMiscParameterRateControl *)misc_param->data;
-
- if (encoder_context->rate_control_mode == VA_RC_CBR) {
- if (vp9_state->target_bit_rate != misc_param_rc->bits_per_second ||
- vp9_state->window_size != misc_param_rc->window_size) {
- vp9_state->target_bit_rate = misc_param_rc->bits_per_second;
- vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
- misc_param_rc->window_size;
- vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit * 2;
- vp9_state->window_size = misc_param_rc->window_size;
- vp9_state->max_bit_rate = vp9_state->target_bit_rate;
- vp9_state->min_bit_rate = vp9_state->target_bit_rate;
- vp9_state->brc_reset = 1;
- }
- } else {
- /* VBR mode */
- if (vp9_state->max_bit_rate != misc_param_rc->bits_per_second ||
- vp9_state->target_percentage != misc_param_rc->target_percentage) {
-
- vp9_state->target_bit_rate = (misc_param_rc->bits_per_second / 100) *
- misc_param_rc->target_percentage;
- vp9_state->min_bit_rate = (misc_param_rc->bits_per_second / 100) *
- (2 * misc_param_rc->target_percentage - 100);
- vp9_state->max_bit_rate = misc_param_rc->bits_per_second;
- vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
- misc_param_rc->window_size;
- vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
- vp9_state->target_percentage = misc_param_rc->target_percentage;
- vp9_state->window_size = misc_param_rc->window_size;
- vp9_state->brc_reset = 1;
- }
- }
- }
+ if (encoder_context->brc.hrd_buffer_size)
+ vp9_state->vbv_buffer_size_in_bit = encoder_context->brc.hrd_buffer_size;
+ else if (encoder_context->brc.window_size)
+ vp9_state->vbv_buffer_size_in_bit = (uint64_t)vp9_state->max_bit_rate * encoder_context->brc.window_size / 1000;
+ else
+ vp9_state->vbv_buffer_size_in_bit = vp9_state->max_bit_rate;
+ if (encoder_context->brc.hrd_initial_buffer_fullness)
+ vp9_state->init_vbv_buffer_fullness_in_bit = encoder_context->brc.hrd_initial_buffer_fullness;
+ else
+ vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
}
}

@@ -5805,47 +5674,6 @@ static void
gen9_vp9_pak_brc_prepare(struct encode_state *encode_state,
struct intel_encoder_context *encoder_context)
{
- struct gen9_encoder_context_vp9 *pak_context = encoder_context->mfc_context;
- struct gen9_vp9_state *vp9_state;
-
- vp9_state = (struct gen9_vp9_state *)(encoder_context->enc_priv_state);
-
- if (!vp9_state || !pak_context)
- return;
-
- if (vp9_state->brc_enabled) {
- /* check the buffer related with BRC */
- vp9_state->brc_flag_check = 0;
- if (encode_state->seq_param_ext && encode_state->seq_param_ext->buffer) {
- vp9_state->brc_flag_check |= VP9_BRC_SEQ;
- }
-
- /* Frame_rate */
- if (encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0] &&
- encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer) {
- vp9_state->brc_flag_check |= VP9_BRC_FR;
- }
-
- /* HRD */
- if (encode_state->misc_param[VAEncMiscParameterTypeRateControl][0] &&
- encode_state->misc_param[VAEncMiscParameterTypeRateControl][0]->buffer) {
- vp9_state->brc_flag_check |= VP9_BRC_RC;
- }
-
- if (encode_state->misc_param[VAEncMiscParameterTypeHRD][0] &&
- encode_state->misc_param[VAEncMiscParameterTypeHRD][0]->buffer) {
- vp9_state->brc_flag_check |= VP9_BRC_HRD;
- }
-
- /*
- * If user-app doesn't pass the buffer related with BRC for the first
- * frame, the error flag is returned.
- */
- if (vp9_state->brc_flag_check == 0 && vp9_state->first_frame) {
- vp9_state->brc_flag_check |= VP9_BRC_FAILURE;
- }
- }
- return;
}

static void
diff --git a/src/gen9_vp9_encoder.h b/src/gen9_vp9_encoder.h
index ad2d875..972e2ad 100644
--- a/src/gen9_vp9_encoder.h
+++ b/src/gen9_vp9_encoder.h
@@ -1552,7 +1552,6 @@ struct gen9_vp9_brc_curbe_param
int32_t brc_num_pak_passes;
bool multi_ref_qp_check;
int16_t frame_number;
- int32_t frame_rate;
VP9_MEDIA_STATE_TYPE media_state_type;
};

@@ -1649,12 +1648,6 @@ typedef struct _vp9_frame_status_
uint8_t intra_only;
} vp9_frame_status;

-#define VP9_BRC_SEQ 0x01
-#define VP9_BRC_HRD 0x02
-#define VP9_BRC_RC 0x04
-#define VP9_BRC_FR 0x08
-#define VP9_BRC_FAILURE (1 << 31)
-
struct gen9_hcpe_pipe_mode_select_param
{
uint32_t codec_mode;
@@ -1925,18 +1918,15 @@ struct gen9_vp9_state {
unsigned long init_vbv_buffer_fullness_in_bit;
unsigned long vbv_buffer_size_in_bit;
int frame_number;
- uint32_t frame_rate;
+ struct intel_fraction framerate;
uint8_t ref_frame_flag;
uint8_t dys_ref_frame_flag;
uint8_t picture_coding_type;
unsigned int adaptive_transform_decision_enabled;
int curr_mode_decision_index;
int target_usage;
- int window_size;
- int target_percentage;
unsigned int mb_data_offset;
int curr_pak_pass;
- unsigned int brc_flag_check;
bool first_frame;
bool dys_enabled;
bool dys_in_use;
diff --git a/src/i965_drv_video.c b/src/i965_drv_video.c
index e602b4e..15920f5 100644
--- a/src/i965_drv_video.c
+++ b/src/i965_drv_video.c
@@ -2794,7 +2794,7 @@ i965_BeginPicture(VADriverContextP ctx,
struct object_surface *obj_surface = SURFACE(render_target);
struct object_config *obj_config;
VAStatus vaStatus = VA_STATUS_SUCCESS;
- int i, j;
+ int i;

ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
ASSERT_RET(obj_surface, VA_STATUS_ERROR_INVALID_SURFACE);
@@ -2848,14 +2848,6 @@ i965_BeginPicture(VADriverContextP ctx,
i965_release_buffer_store(&obj_context->codec_state.encode.misc_param[VAEncMiscParameterTypeROI][0]);

i965_release_buffer_store(&obj_context->codec_state.encode.encmb_map);
-
- if (obj_config->profile == VAProfileVP9Profile0) {
- for (i = 0; i < ARRAY_ELEMS(obj_context->codec_state.encode.misc_param); i++)
- for (j = 0; j < ARRAY_ELEMS(obj_context->codec_state.encode.misc_param[0]); j++)
- i965_release_buffer_store(&obj_context->codec_state.encode.misc_param[i][j]);
-
- i965_release_buffer_store(&obj_context->codec_state.encode.seq_param_ext);
- }
} else {
obj_context->codec_state.decode.current_render_target = render_target;
i965_release_buffer_store(&obj_context->codec_state.decode.pic_param);
diff --git a/src/i965_encoder.c b/src/i965_encoder.c
index 76789f3..be37b84 100644
--- a/src/i965_encoder.c
+++ b/src/i965_encoder.c
@@ -490,6 +490,34 @@ intel_encoder_check_brc_hevc_sequence_parameter(VADriverContextP ctx,
}

static VAStatus
+intel_encoder_check_brc_vp9_sequence_parameter(VADriverContextP ctx,
+ struct encode_state *encode_state,
+ struct intel_encoder_context *encoder_context)
+{
+ VAEncSequenceParameterBufferVP9 *seq_param = (VAEncSequenceParameterBufferVP9*)encode_state->seq_param_ext->buffer;
+ unsigned int gop_size;
+
+ if (!encoder_context->is_new_sequence)
+ return VA_STATUS_SUCCESS;
+ if (!seq_param)
+ return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+ if (seq_param->intra_period == 0)
+ gop_size = -1; // Dummy value (infinity).
+ else
+ gop_size = seq_param->intra_period;
+
+ if (encoder_context->brc.bits_per_second[0] != seq_param->bits_per_second ||
+ encoder_context->brc.gop_size != gop_size) {
+ encoder_context->brc.bits_per_second[0] = seq_param->bits_per_second;
+ encoder_context->brc.gop_size = gop_size;
+ encoder_context->brc.need_reset = 1;
+ }
+
+ return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
intel_encoder_check_brc_sequence_parameter(VADriverContextP ctx,
struct encode_state *encode_state,
struct intel_encoder_context *encoder_context)
@@ -505,6 +533,9 @@ intel_encoder_check_brc_sequence_parameter(VADriverContextP ctx,
case CODEC_HEVC:
return intel_encoder_check_brc_hevc_sequence_parameter(ctx, encode_state, encoder_context);

+ case CODEC_VP9:
+ return intel_encoder_check_brc_vp9_sequence_parameter(ctx, encode_state, encoder_context);
+
default:
// TODO: other codecs
return VA_STATUS_SUCCESS;
@@ -541,6 +572,11 @@ intel_encoder_check_rate_control_parameter(VADriverContextP ctx,
encoder_context->brc.target_percentage[temporal_id] = misc->target_percentage;
encoder_context->brc.need_reset = 1;
}
+
+ if (encoder_context->brc.window_size != misc->window_size) {
+ encoder_context->brc.window_size = misc->window_size;
+ encoder_context->brc.need_reset = 1;
+ }
}

static void
diff --git a/src/i965_encoder.h b/src/i965_encoder.h
index 7016975..be19ce6 100644
--- a/src/i965_encoder.h
+++ b/src/i965_encoder.h
@@ -91,6 +91,7 @@ struct intel_encoder_context
unsigned int target_percentage[MAX_TEMPORAL_LAYERS];
unsigned int hrd_buffer_size;
unsigned int hrd_initial_buffer_fullness;
+ unsigned int window_size;
unsigned int need_reset;

unsigned int num_roi;
--
2.11.0
Xiang, Haihao
2016-12-21 04:46:04 UTC
Permalink
Post by Mark Thompson
Also adds support for fractional framerate.
---
 src/gen9_vp9_encoder.c | 240 ++++++++-----------------------------------------
 src/gen9_vp9_encoder.h |  10 +--
 src/i965_drv_video.c   |  10 +--
 src/i965_encoder.c     |  36 ++++++++
 src/i965_encoder.h     |   1 +
 5 files changed, 77 insertions(+), 220 deletions(-)
diff --git a/src/gen9_vp9_encoder.c b/src/gen9_vp9_encoder.c
index 3ea1537..2e884e2 100644
--- a/src/gen9_vp9_encoder.c
+++ b/src/gen9_vp9_encoder.c
@@ -1201,8 +1201,8 @@ void gen9_vp9_set_curbe_brc(VADriverContextP ctx,
                                                   VP9_BRC_KBPS;
             cmd->dw9.min_bit_rate           = (vp9_state->min_bit_rate  + VP9_BRC_KBPS - 1) / VP9_BRC_KBPS *
                                                   VP9_BRC_KBPS;
-            cmd->dw10.frame_ratem           = vp9_state->frame_rate;
-            cmd->dw11.frame_rated           = 1;
+            cmd->dw10.frame_ratem           = vp9_state->framerate.num;
+            cmd->dw11.frame_rated           = vp9_state->framerate.den;
 
             cmd->dw14.avbr_accuracy         = 30;
             cmd->dw14.avbr_convergence      = 150;
@@ -1235,8 +1235,8 @@ void gen9_vp9_set_curbe_brc(VADriverContextP ctx,
             cmd->dw17.enable_dynamic_scaling = vp9_state->dys_in_use;
             cmd->dw17.brc_overshoot_cbr_pct = 150;
 
-            dInputBitsPerFrame = (double)(cmd->dw8.max_bit_rate) / (vp9_state->frame_rate);
-            dbps_ratio         = dInputBitsPerFrame / ((double)(vp9_state->vbv_buffer_size_in_bit) / 30);
+            dInputBitsPerFrame = (double)cmd->dw8.max_bit_rate * (double)vp9_state->framerate.den / (double)vp9_state->framerate.num;
+            dbps_ratio         = dInputBitsPerFrame / (double)vp9_state->vbv_buffer_size_in_bit / 30.0;
             if (dbps_ratio < 0.1)
                 dbps_ratio = 0.1;
             if (dbps_ratio > 3.5)
@@ -1423,7 +1423,6 @@ gen9_vp9_brc_init_reset_kernel(VADriverContextP ctx,
     brc_initreset_curbe.initbrc            = !vp9_state->brc_inited;
     brc_initreset_curbe.mbbrc_enabled      = 0;
     brc_initreset_curbe.ref_frame_flag      = vp9_state->ref_frame_flag;
-    brc_initreset_curbe.frame_rate           = vp9_state->frame_rate;
 
     vme_context->pfn_set_curbe_brc(ctx, encode_state,
                                    gpe_context,
@@ -1523,7 +1522,6 @@ gen9_vp9_brc_intra_dist_kernel(VADriverContextP ctx,
     brc_intra_dist_curbe.initbrc            = !vp9_state->brc_inited;
     brc_intra_dist_curbe.mbbrc_enabled      = 0;
     brc_intra_dist_curbe.ref_frame_flag      = vp9_state->ref_frame_flag;
-    brc_intra_dist_curbe.frame_rate           = vp9_state->frame_rate;
 
     vme_context->pfn_set_curbe_brc(ctx, encode_state,
                                    gpe_context,
@@ -3926,168 +3924,47 @@ gen9_encode_vp9_check_parameter(VADriverContextP ctx,
         return VA_STATUS_ERROR_UNIMPLEMENTED;
 
     if (vp9_state->brc_enabled) {
-        if (vp9_state->brc_flag_check & VP9_BRC_FAILURE) {
-            WARN_ONCE("Rate control misc_parameter is required for BRC\n");
-            return VA_STATUS_ERROR_INVALID_PARAMETER;
-        }
-
-        if (vp9_state->first_frame) {
-            unsigned int brc_flag;
-            VAEncMiscParameterBuffer *misc_param;
-
-            brc_flag = VP9_BRC_SEQ | VP9_BRC_RC;
-            if ((vp9_state->brc_flag_check & brc_flag) != brc_flag) {
-                WARN_ONCE("SPS/RC misc is required for BRC\n");
-                return VA_STATUS_ERROR_INVALID_PARAMETER;
-            }
+        if (vp9_state->first_frame || vp9_state->picture_coding_type == KEY_FRAME) {
+            vp9_state->brc_reset = encoder_context->brc.need_reset || vp9_state->first_frame;
 
             /* check the corresponding BRC parameter for CBR and VBR */
             if (encoder_context->rate_control_mode == VA_RC_CBR) {
-                vp9_state->target_bit_rate = seq_param->bits_per_second;
-                vp9_state->gop_size = seq_param->intra_period;
-
-                if (vp9_state->brc_flag_check & VP9_BRC_HRD) {
-                    VAEncMiscParameterHRD *misc_param_hrd;
-
-                    misc_param = (VAEncMiscParameterBuffer *)
-                        encode_state->misc_param[VAEncMiscParameterTypeHRD][0]->buffer;
-                    misc_param_hrd = (VAEncMiscParameterHRD *)misc_param->data;
-
-                    vp9_state->init_vbv_buffer_fullness_in_bit = misc_param_hrd->initial_buffer_fullness;
-                    vp9_state->vbv_buffer_size_in_bit = misc_param_hrd->buffer_size;
-                }
-
-                if (vp9_state->brc_flag_check & VP9_BRC_FR) {
-                    VAEncMiscParameterFrameRate *misc_param_fr;
-
-                    misc_param = (VAEncMiscParameterBuffer *)
-                        encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
-                    misc_param_fr = (VAEncMiscParameterFrameRate *)misc_param->data;
-
-                    vp9_state->frame_rate = misc_param_fr->framerate;
-                } else {
-                    /* Assign the default frame rate */
-                    vp9_state->frame_rate = 30;
-                }
-
-                /* RC misc will override HRD parameter */
-                if (vp9_state->brc_flag_check & VP9_BRC_RC) {
-                    VAEncMiscParameterRateControl *misc_param_rc;
-
-                    misc_param = (VAEncMiscParameterBuffer *)
-                        encode_state->misc_param[VAEncMiscParameterTypeRateControl][0]->buffer;
-                    misc_param_rc = (VAEncMiscParameterRateControl *)misc_param->data;
-
-                    vp9_state->target_bit_rate = misc_param_rc->bits_per_second;
-                    vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
-                                                 misc_param_rc->window_size;
-                    vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
-                    vp9_state->window_size = misc_param_rc->window_size;
-                }
+                if (!encoder_context->brc.framerate[0].num || !encoder_context->brc.framerate[0].den ||
+                    !encoder_context->brc.bits_per_second[0])
+                    return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+                vp9_state->gop_size = encoder_context->brc.gop_size;
+
+                vp9_state->framerate = encoder_context->brc.framerate[0];
+                vp9_state->target_bit_rate = encoder_context->brc.bits_per_second[0];
                 vp9_state->max_bit_rate = vp9_state->target_bit_rate;
                 vp9_state->min_bit_rate = vp9_state->target_bit_rate;
-            } else {
-                /* VBR mode */
-                brc_flag = VP9_BRC_SEQ | VP9_BRC_RC;
-                vp9_state->target_bit_rate = seq_param->bits_per_second;
-                vp9_state->gop_size = seq_param->intra_period;
-
-                if (vp9_state->brc_flag_check & VP9_BRC_FR) {
-                    VAEncMiscParameterFrameRate *misc_param_fr;
-
-                    misc_param = (VAEncMiscParameterBuffer *)
-                        encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
-                    misc_param_fr = (VAEncMiscParameterFrameRate *)misc_param->data;
-
-                    vp9_state->frame_rate = misc_param_fr->framerate;
-                } else {
-                    /* Assign the default frame rate */
-                    vp9_state->frame_rate = 30;
-                }
-
-                if (vp9_state->brc_flag_check & VP9_BRC_RC) {
-                    VAEncMiscParameterRateControl *misc_param_rc;
-
-                    misc_param = (VAEncMiscParameterBuffer *)
-                        encode_state->misc_param[VAEncMiscParameterTypeRateControl][0]->buffer;
-                    misc_param_rc = (VAEncMiscParameterRateControl *)misc_param->data;
-
-                    vp9_state->max_bit_rate = misc_param_rc->bits_per_second;
-                    vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
-                                                 misc_param_rc->window_size;
-                    vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
-                    vp9_state->target_bit_rate = (misc_param_rc->bits_per_second / 100) *
-                                misc_param_rc->target_percentage;
-                    vp9_state->min_bit_rate = (misc_param_rc->bits_per_second / 100) *
-                         (2 * misc_param_rc->target_percentage - 100);
-                    vp9_state->target_percentage = misc_param_rc->target_percentage;
-                    vp9_state->window_size = misc_param_rc->window_size;
-                }
-            }
-        }
-        else if (vp9_state->picture_coding_type == KEY_FRAME){
-            VAEncMiscParameterBuffer *misc_param;
-            /* update the BRC parameter only when it is key-frame */
-            /* If the parameter related with RC is changed. Reset BRC */
-            if (vp9_state->brc_flag_check & VP9_BRC_FR) {
-               VAEncMiscParameterFrameRate *misc_param_fr;
-
-               misc_param = (VAEncMiscParameterBuffer *)
-                   encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
-               misc_param_fr = (VAEncMiscParameterFrameRate *)misc_param->data;
-
-               if (vp9_state->frame_rate != misc_param_fr->framerate) {
-                   vp9_state->brc_reset = 1;
-                   vp9_state->frame_rate = misc_param_fr->framerate;
-               }
-            }
 
-            /* check the GOP size. And bit_per_second in SPS is ignored */
-            if (vp9_state->brc_flag_check & VP9_BRC_SEQ) {
-                if (vp9_state->gop_size != seq_param->intra_period) {
-                    vp9_state->brc_reset = 1;
-                    vp9_state->gop_size = seq_param->intra_period;
-                }
-            }
+                vp9_state->vbv_buffer_size_in_bit = encoder_context->brc.hrd_buffer_size;
+                vp9_state->init_vbv_buffer_fullness_in_bit = encoder_context->brc.hrd_initial_buffer_fullness;
vp9_state->init_vbv_buffer_fullness_in_bit may be overrode by the misc
RC parameters (vp9_state->window_size) in the current code.
Post by Mark Thompson
 
-            /* update the bit_per_second */
-            if (vp9_state->brc_flag_check & VP9_BRC_RC) {
-                VAEncMiscParameterRateControl *misc_param_rc;
-
-                misc_param = (VAEncMiscParameterBuffer *)
-                    encode_state->misc_param[VAEncMiscParameterTypeRateControl][0]->buffer;
-                misc_param_rc = (VAEncMiscParameterRateControl *)misc_param->data;
-
-                if (encoder_context->rate_control_mode == VA_RC_CBR) {
-                    if (vp9_state->target_bit_rate != misc_param_rc->bits_per_second ||
-                        vp9_state->window_size != misc_param_rc->window_size) {
-                        vp9_state->target_bit_rate = misc_param_rc->bits_per_second;
-                        vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
-                                                 misc_param_rc->window_size;
-                        vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit * 2;
-                        vp9_state->window_size = misc_param_rc->window_size;
-                        vp9_state->max_bit_rate = vp9_state->target_bit_rate;
-                        vp9_state->min_bit_rate = vp9_state->target_bit_rate;
-                        vp9_state->brc_reset = 1;
-                    }
-                } else {
-                    /* VBR mode */
-                    if (vp9_state->max_bit_rate != misc_param_rc->bits_per_second ||
-                        vp9_state->target_percentage != misc_param_rc->target_percentage) {
-
-                        vp9_state->target_bit_rate = (misc_param_rc->bits_per_second / 100) *
-                                misc_param_rc->target_percentage;
-                        vp9_state->min_bit_rate = (misc_param_rc->bits_per_second / 100) *
-                             (2 * misc_param_rc->target_percentage - 100);
-                        vp9_state->max_bit_rate = misc_param_rc->bits_per_second;
-                        vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
-                                                 misc_param_rc->window_size;
-                        vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
-                        vp9_state->target_percentage = misc_param_rc->target_percentage;
-                        vp9_state->window_size = misc_param_rc->window_size;
-                        vp9_state->brc_reset = 1;
-                    }
-                }
+            } else {
+                /* VBR mode */
+                if (!encoder_context->brc.framerate[0].num || !encoder_context->brc.framerate[0].den ||
+                    !encoder_context->brc.bits_per_second[0] || !encoder_context->brc.target_percentage[0] ||
+                    !encoder_context->brc.window_size)
+                    return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+                vp9_state->gop_size = encoder_context->brc.gop_size;
+
+                vp9_state->framerate = encoder_context->brc.framerate[0];
+                vp9_state->max_bit_rate = encoder_context->brc.bits_per_second[0];
+                vp9_state->target_percentage = encoder_context->brc.target_percentage[0];
+                vp9_state->window_size = encoder_context->brc.window_size;
+
+                vp9_state->target_bit_rate = vp9_state->max_bit_rate * encoder_context->brc.target_percentage[0] / 100;
+                if (2 * vp9_state->target_bit_rate < vp9_state->max_bit_rate)
+                    vp9_state->min_bit_rate = 0;
+                else
+                    vp9_state->min_bit_rate = 2 * vp9_state->target_bit_rate - vp9_state->max_bit_rate;
+
+                vp9_state->vbv_buffer_size_in_bit = (vp9_state->max_bit_rate / 1000) * vp9_state->window_size;
+                vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
This patch uses two different ways to get vp9_state->vbv_buffer_size_in_bit for CBR and VBR. 
I think we should use the same way. I prefer the way used for CBR in your patch although it is not the same of the current code.
Post by Mark Thompson
             }
         }
     }
@@ -5805,47 +5682,6 @@ static void
 gen9_vp9_pak_brc_prepare(struct encode_state *encode_state,
                           struct intel_encoder_context *encoder_context)
 {
-    struct gen9_encoder_context_vp9 *pak_context = encoder_context->mfc_context;
-    struct gen9_vp9_state *vp9_state;
-
-    vp9_state = (struct gen9_vp9_state *)(encoder_context->enc_priv_state);
-
-    if (!vp9_state || !pak_context)
-        return;
-
-    if (vp9_state->brc_enabled) {
-        /* check the buffer related with BRC */
-        vp9_state->brc_flag_check = 0;
-        if (encode_state->seq_param_ext && encode_state->seq_param_ext->buffer) {
-            vp9_state->brc_flag_check |= VP9_BRC_SEQ;
-        }
-
-        /* Frame_rate */
-        if (encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0] &&
-            encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer) {
-            vp9_state->brc_flag_check |= VP9_BRC_FR;
-        }
-
-        /* HRD */
-        if (encode_state->misc_param[VAEncMiscParameterTypeRateControl][0] &&
-            encode_state->misc_param[VAEncMiscParameterTypeRateControl][0]->buffer) {
-            vp9_state->brc_flag_check |= VP9_BRC_RC;
-        }
-
-        if (encode_state->misc_param[VAEncMiscParameterTypeHRD][0] &&
-            encode_state->misc_param[VAEncMiscParameterTypeHRD][0]->buffer) {
-            vp9_state->brc_flag_check |= VP9_BRC_HRD;
-        }
-
-        /*
-         * If user-app doesn't pass the buffer related with BRC for the first
-         * frame, the error flag is returned.
-         */
-        if (vp9_state->brc_flag_check == 0 && vp9_state->first_frame) {
-            vp9_state->brc_flag_check |= VP9_BRC_FAILURE;
-        }
-    }
-    return;
 }
 
 static void
diff --git a/src/gen9_vp9_encoder.h b/src/gen9_vp9_encoder.h
index ad2d875..76f58a6 100644
--- a/src/gen9_vp9_encoder.h
+++ b/src/gen9_vp9_encoder.h
@@ -1552,7 +1552,6 @@ struct gen9_vp9_brc_curbe_param
     int32_t   brc_num_pak_passes;
     bool      multi_ref_qp_check;
     int16_t   frame_number;
-    int32_t   frame_rate;
     VP9_MEDIA_STATE_TYPE                       media_state_type;
 };
 
@@ -1649,12 +1648,6 @@ typedef struct _vp9_frame_status_
     uint8_t intra_only;
 } vp9_frame_status;
 
-#define VP9_BRC_SEQ         0x01
-#define VP9_BRC_HRD         0x02
-#define VP9_BRC_RC          0x04
-#define VP9_BRC_FR          0x08
-#define VP9_BRC_FAILURE     (1 << 31)
-
 struct gen9_hcpe_pipe_mode_select_param
 {
     uint32_t                    codec_mode;
@@ -1925,7 +1918,7 @@ struct gen9_vp9_state {
     unsigned long init_vbv_buffer_fullness_in_bit;
     unsigned long vbv_buffer_size_in_bit;
     int      frame_number;
-    uint32_t frame_rate;
+    struct intel_fraction framerate;
     uint8_t  ref_frame_flag;
     uint8_t  dys_ref_frame_flag;
     uint8_t  picture_coding_type;
@@ -1936,7 +1929,6 @@ struct gen9_vp9_state {
     int      target_percentage;
     unsigned int mb_data_offset;
     int      curr_pak_pass;
-    unsigned int brc_flag_check;
     bool     first_frame;
     bool     dys_enabled;
     bool     dys_in_use;
diff --git a/src/i965_drv_video.c b/src/i965_drv_video.c
index e602b4e..15920f5 100644
--- a/src/i965_drv_video.c
+++ b/src/i965_drv_video.c
@@ -2794,7 +2794,7 @@ i965_BeginPicture(VADriverContextP ctx,
     struct object_surface *obj_surface = SURFACE(render_target);
     struct object_config *obj_config;
     VAStatus vaStatus = VA_STATUS_SUCCESS;
-    int i, j;
+    int i;
 
     ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
     ASSERT_RET(obj_surface, VA_STATUS_ERROR_INVALID_SURFACE);
@@ -2848,14 +2848,6 @@ i965_BeginPicture(VADriverContextP ctx,
         i965_release_buffer_store(&obj_context->codec_state.encode.misc_param[VAEncMiscParameterTypeROI][0]);
 
         i965_release_buffer_store(&obj_context->codec_state.encode.encmb_map);
-
-        if (obj_config->profile == VAProfileVP9Profile0) {
-            for (i = 0; i < ARRAY_ELEMS(obj_context->codec_state.encode.misc_param); i++)
-                for (j = 0; j < ARRAY_ELEMS(obj_context->codec_state.encode.misc_param[0]); j++)
-                    i965_release_buffer_store(&obj_context->codec_state.encode.misc_param[i][j]);
-
-            i965_release_buffer_store(&obj_context->codec_state.encode.seq_param_ext);
-        }
     } else {
         obj_context->codec_state.decode.current_render_target = render_target;
         i965_release_buffer_store(&obj_context->codec_state.decode.pic_param);
diff --git a/src/i965_encoder.c b/src/i965_encoder.c
index 20ae554..192c8b8 100644
--- a/src/i965_encoder.c
+++ b/src/i965_encoder.c
@@ -490,6 +490,34 @@ intel_encoder_check_brc_hevc_sequence_parameter(VADriverContextP ctx,
 }
 
 static VAStatus
+intel_encoder_check_brc_vp9_sequence_parameter(VADriverContextP ctx,
+                                               struct encode_state *encode_state,
+                                               struct intel_encoder_context *encoder_context)
+{
+    VAEncSequenceParameterBufferVP9 *seq_param = (VAEncSequenceParameterBufferVP9*)encode_state->seq_param_ext->buffer;
+    unsigned int gop_size;
+
+    if (!encoder_context->is_new_sequence)
+        return VA_STATUS_SUCCESS;
+    if (!seq_param)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    if (seq_param->intra_period == 0)
+        gop_size = -1; // Dummy value (infinity).
+    else
+        gop_size = seq_param->intra_period;
+
+    if (encoder_context->brc.bits_per_second[0] != seq_param->bits_per_second ||
+        encoder_context->brc.gop_size != gop_size) {
+        encoder_context->brc.bits_per_second[0] = seq_param->bits_per_second;
+        encoder_context->brc.gop_size = gop_size;
+        encoder_context->brc.need_reset = 1;
+    }
+
+    return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
 intel_encoder_check_brc_sequence_parameter(VADriverContextP ctx,
                                            struct encode_state *encode_state,
                                            struct intel_encoder_context *encoder_context)
@@ -505,6 +533,9 @@ intel_encoder_check_brc_sequence_parameter(VADriverContextP ctx,
         return intel_encoder_check_brc_hevc_sequence_parameter(ctx, encode_state, encoder_context);
 
+        return intel_encoder_check_brc_vp9_sequence_parameter(ctx, encode_state, encoder_context);
+
         // TODO: other codecs
         return VA_STATUS_SUCCESS;
@@ -541,6 +572,11 @@ intel_encoder_check_rate_control_parameter(VADriverContextP ctx,
         encoder_context->brc.target_percentage[temporal_id] = misc->target_percentage;
         encoder_context->brc.need_reset = 1;
     }
+
+    if (encoder_context->brc.window_size != misc->window_size) {
+        encoder_context->brc.window_size = misc->window_size;
+        encoder_context->brc.need_reset = 1;
+    }
 }
 
 static void
diff --git a/src/i965_encoder.h b/src/i965_encoder.h
index 7016975..be19ce6 100644
--- a/src/i965_encoder.h
+++ b/src/i965_encoder.h
@@ -91,6 +91,7 @@ struct intel_encoder_context
         unsigned int target_percentage[MAX_TEMPORAL_LAYERS];
         unsigned int hrd_buffer_size;
         unsigned int hrd_initial_buffer_fullness;
+        unsigned int window_size;
         unsigned int need_reset;
 
         unsigned int num_roi;
Mark Thompson
2016-12-21 12:28:48 UTC
Permalink
Post by Xiang, Haihao
Post by Mark Thompson
Also adds support for fractional framerate.
---
src/gen9_vp9_encoder.c | 240 ++++++++-----------------------------------------
src/gen9_vp9_encoder.h | 10 +--
src/i965_drv_video.c | 10 +--
src/i965_encoder.c | 36 ++++++++
src/i965_encoder.h | 1 +
5 files changed, 77 insertions(+), 220 deletions(-)
...
/* check the corresponding BRC parameter for CBR and VBR */
if (encoder_context->rate_control_mode == VA_RC_CBR) {
- vp9_state->target_bit_rate = seq_param->bits_per_second;
- vp9_state->gop_size = seq_param->intra_period;
-
- if (vp9_state->brc_flag_check & VP9_BRC_HRD) {
- VAEncMiscParameterHRD *misc_param_hrd;
-
- misc_param = (VAEncMiscParameterBuffer *)
- encode_state->misc_param[VAEncMiscParameterTypeHRD][0]->buffer;
- misc_param_hrd = (VAEncMiscParameterHRD *)misc_param->data;
-
- vp9_state->init_vbv_buffer_fullness_in_bit = misc_param_hrd->initial_buffer_fullness;
- vp9_state->vbv_buffer_size_in_bit = misc_param_hrd->buffer_size;
- }
-
- if (vp9_state->brc_flag_check & VP9_BRC_FR) {
- VAEncMiscParameterFrameRate *misc_param_fr;
-
- misc_param = (VAEncMiscParameterBuffer *)
- encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
- misc_param_fr = (VAEncMiscParameterFrameRate *)misc_param->data;
-
- vp9_state->frame_rate = misc_param_fr->framerate;
- } else {
- /* Assign the default frame rate */
- vp9_state->frame_rate = 30;
- }
-
- /* RC misc will override HRD parameter */
- if (vp9_state->brc_flag_check & VP9_BRC_RC) {
- VAEncMiscParameterRateControl *misc_param_rc;
-
- misc_param = (VAEncMiscParameterBuffer *)
- encode_state->misc_param[VAEncMiscParameterTypeRateControl][0]->buffer;
- misc_param_rc = (VAEncMiscParameterRateControl *)misc_param->data;
-
- vp9_state->target_bit_rate = misc_param_rc->bits_per_second;
- vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
- misc_param_rc->window_size;
- vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
- vp9_state->window_size = misc_param_rc->window_size;
- }
+ if (!encoder_context->brc.framerate[0].num || !encoder_context->brc.framerate[0].den ||
+ !encoder_context->brc.bits_per_second[0])
+ return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+ vp9_state->gop_size = encoder_context->brc.gop_size;
+
+ vp9_state->framerate = encoder_context->brc.framerate[0];
+ vp9_state->target_bit_rate = encoder_context->brc.bits_per_second[0];
vp9_state->max_bit_rate = vp9_state->target_bit_rate;
vp9_state->min_bit_rate = vp9_state->target_bit_rate;
- } else {
- /* VBR mode */
- brc_flag = VP9_BRC_SEQ | VP9_BRC_RC;
- vp9_state->target_bit_rate = seq_param->bits_per_second;
- vp9_state->gop_size = seq_param->intra_period;
-
- if (vp9_state->brc_flag_check & VP9_BRC_FR) {
- VAEncMiscParameterFrameRate *misc_param_fr;
-
- misc_param = (VAEncMiscParameterBuffer *)
- encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
- misc_param_fr = (VAEncMiscParameterFrameRate *)misc_param->data;
-
- vp9_state->frame_rate = misc_param_fr->framerate;
- } else {
- /* Assign the default frame rate */
- vp9_state->frame_rate = 30;
- }
-
- if (vp9_state->brc_flag_check & VP9_BRC_RC) {
- VAEncMiscParameterRateControl *misc_param_rc;
-
- misc_param = (VAEncMiscParameterBuffer *)
- encode_state->misc_param[VAEncMiscParameterTypeRateControl][0]->buffer;
- misc_param_rc = (VAEncMiscParameterRateControl *)misc_param->data;
-
- vp9_state->max_bit_rate = misc_param_rc->bits_per_second;
- vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
- misc_param_rc->window_size;
- vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
- vp9_state->target_bit_rate = (misc_param_rc->bits_per_second / 100) *
- misc_param_rc->target_percentage;
- vp9_state->min_bit_rate = (misc_param_rc->bits_per_second / 100) *
- (2 * misc_param_rc->target_percentage - 100);
- vp9_state->target_percentage = misc_param_rc->target_percentage;
- vp9_state->window_size = misc_param_rc->window_size;
- }
- }
- }
- else if (vp9_state->picture_coding_type == KEY_FRAME){
- VAEncMiscParameterBuffer *misc_param;
- /* update the BRC parameter only when it is key-frame */
- /* If the parameter related with RC is changed. Reset BRC */
- if (vp9_state->brc_flag_check & VP9_BRC_FR) {
- VAEncMiscParameterFrameRate *misc_param_fr;
-
- misc_param = (VAEncMiscParameterBuffer *)
- encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
- misc_param_fr = (VAEncMiscParameterFrameRate *)misc_param->data;
-
- if (vp9_state->frame_rate != misc_param_fr->framerate) {
- vp9_state->brc_reset = 1;
- vp9_state->frame_rate = misc_param_fr->framerate;
- }
- }
- /* check the GOP size. And bit_per_second in SPS is ignored */
- if (vp9_state->brc_flag_check & VP9_BRC_SEQ) {
- if (vp9_state->gop_size != seq_param->intra_period) {
- vp9_state->brc_reset = 1;
- vp9_state->gop_size = seq_param->intra_period;
- }
- }
+ vp9_state->vbv_buffer_size_in_bit = encoder_context->brc.hrd_buffer_size;
+ vp9_state->init_vbv_buffer_fullness_in_bit = encoder_context->brc.hrd_initial_buffer_fullness;
vp9_state->init_vbv_buffer_fullness_in_bit may be overrode by the misc
RC parameters (vp9_state->window_size) in the current code.
I think we want to ignore window_size in CBR mode? The bitrate is intended to be constant, so the window to average over is necessarily zero. The relevant parts (to my mind) of the RC parameter structure (really just bits_per_second) are already reflected in the generic code.

I'm happy to change it if you feel the window_size should be used there. Though, I would ask which one "wins" if both HRD parameters and window_size are set?
Post by Xiang, Haihao
Post by Mark Thompson
- /* update the bit_per_second */
- if (vp9_state->brc_flag_check & VP9_BRC_RC) {
- VAEncMiscParameterRateControl *misc_param_rc;
-
- misc_param = (VAEncMiscParameterBuffer *)
- encode_state->misc_param[VAEncMiscParameterTypeRateControl][0]->buffer;
- misc_param_rc = (VAEncMiscParameterRateControl *)misc_param->data;
-
- if (encoder_context->rate_control_mode == VA_RC_CBR) {
- if (vp9_state->target_bit_rate != misc_param_rc->bits_per_second ||
- vp9_state->window_size != misc_param_rc->window_size) {
- vp9_state->target_bit_rate = misc_param_rc->bits_per_second;
- vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
- misc_param_rc->window_size;
- vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit * 2;
- vp9_state->window_size = misc_param_rc->window_size;
- vp9_state->max_bit_rate = vp9_state->target_bit_rate;
- vp9_state->min_bit_rate = vp9_state->target_bit_rate;
- vp9_state->brc_reset = 1;
- }
- } else {
- /* VBR mode */
- if (vp9_state->max_bit_rate != misc_param_rc->bits_per_second ||
- vp9_state->target_percentage != misc_param_rc->target_percentage) {
-
- vp9_state->target_bit_rate = (misc_param_rc->bits_per_second / 100) *
- misc_param_rc->target_percentage;
- vp9_state->min_bit_rate = (misc_param_rc->bits_per_second / 100) *
- (2 * misc_param_rc->target_percentage - 100);
- vp9_state->max_bit_rate = misc_param_rc->bits_per_second;
- vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
- misc_param_rc->window_size;
- vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
- vp9_state->target_percentage = misc_param_rc->target_percentage;
- vp9_state->window_size = misc_param_rc->window_size;
- vp9_state->brc_reset = 1;
- }
- }
+ } else {
+ /* VBR mode */
+ if (!encoder_context->brc.framerate[0].num || !encoder_context->brc.framerate[0].den ||
+ !encoder_context->brc.bits_per_second[0] || !encoder_context->brc.target_percentage[0] ||
+ !encoder_context->brc.window_size)
+ return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+ vp9_state->gop_size = encoder_context->brc.gop_size;
+
+ vp9_state->framerate = encoder_context->brc.framerate[0];
+ vp9_state->max_bit_rate = encoder_context->brc.bits_per_second[0];
+ vp9_state->target_percentage = encoder_context->brc.target_percentage[0];
+ vp9_state->window_size = encoder_context->brc.window_size;
+
+ vp9_state->target_bit_rate = vp9_state->max_bit_rate * encoder_context->brc.target_percentage[0] / 100;
+ if (2 * vp9_state->target_bit_rate < vp9_state->max_bit_rate)
+ vp9_state->min_bit_rate = 0;
+ else
+ vp9_state->min_bit_rate = 2 * vp9_state->target_bit_rate - vp9_state->max_bit_rate;
+
+ vp9_state->vbv_buffer_size_in_bit = (vp9_state->max_bit_rate / 1000) * vp9_state->window_size;
+ vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
This patch uses two different ways to get vp9_state->vbv_buffer_size_in_bit for CBR and VBR.
I think we should use the same way. I prefer the way used for CBR in your patch although it is not the same of the current code.
The VBR mode behaviour was intended to be the same as what is there currently, mainly because it is harder for me to verify the result than with CBR. The current code for VBR ignores the HRD parameters and instead generates VBV values from the RC parameters, and I have preserved that behaviour.

I can change it to use the HRD parameters if they are set? Or would you prefer that the two code paths are merged, with a branch on CBR vs. VBR only around the setting of min|max_bit_rate?

Thanks,

- Mark
Xiang, Haihao
2016-12-22 02:11:23 UTC
Permalink
Post by Xiang, Haihao
Post by Mark Thompson
Also adds support for fractional framerate.
---
 src/gen9_vp9_encoder.c | 240 ++++++++---------------------------
--------------
 src/gen9_vp9_encoder.h |  10 +--
 src/i965_drv_video.c   |  10 +--
 src/i965_encoder.c     |  36 ++++++++
 src/i965_encoder.h     |   1 +
 5 files changed, 77 insertions(+), 220 deletions(-)
...
             /* check the corresponding BRC parameter for CBR and
VBR */
             if (encoder_context->rate_control_mode == VA_RC_CBR) {
-                vp9_state->target_bit_rate = seq_param-
Post by Mark Thompson
bits_per_second;
-                vp9_state->gop_size = seq_param->intra_period;
-
-                if (vp9_state->brc_flag_check & VP9_BRC_HRD) {
-                    VAEncMiscParameterHRD *misc_param_hrd;
-
-                    misc_param = (VAEncMiscParameterBuffer *)
-                        encode_state-
Post by Mark Thompson
misc_param[VAEncMiscParameterTypeHRD][0]->buffer;
-                    misc_param_hrd = (VAEncMiscParameterHRD
*)misc_param->data;
-
-                    vp9_state->init_vbv_buffer_fullness_in_bit =
misc_param_hrd->initial_buffer_fullness;
-                    vp9_state->vbv_buffer_size_in_bit =
misc_param_hrd->buffer_size;
-                }
-
-                if (vp9_state->brc_flag_check & VP9_BRC_FR) {
-                    VAEncMiscParameterFrameRate *misc_param_fr;
-
-                    misc_param = (VAEncMiscParameterBuffer *)
-                        encode_state-
Post by Mark Thompson
misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
-                    misc_param_fr = (VAEncMiscParameterFrameRate
*)misc_param->data;
-
-                    vp9_state->frame_rate = misc_param_fr-
Post by Mark Thompson
framerate;
-                } else {
-                    /* Assign the default frame rate */
-                    vp9_state->frame_rate = 30;
-                }
-
-                /* RC misc will override HRD parameter */
-                if (vp9_state->brc_flag_check & VP9_BRC_RC) {
-                    VAEncMiscParameterRateControl
*misc_param_rc;
-
-                    misc_param = (VAEncMiscParameterBuffer *)
-                        encode_state-
Post by Mark Thompson
misc_param[VAEncMiscParameterTypeRateControl][0]->buffer;
-                    misc_param_rc =
(VAEncMiscParameterRateControl *)misc_param->data;
-
-                    vp9_state->target_bit_rate = misc_param_rc-
Post by Mark Thompson
bits_per_second;
-                    vp9_state->vbv_buffer_size_in_bit =
(misc_param_rc->bits_per_second / 1000) *
-                                                 misc_param_rc-
Post by Mark Thompson
window_size;
-                    vp9_state->init_vbv_buffer_fullness_in_bit =
vp9_state->vbv_buffer_size_in_bit / 2;
-                    vp9_state->window_size = misc_param_rc-
Post by Mark Thompson
window_size;
-                }
+                if (!encoder_context->brc.framerate[0].num ||
!encoder_context->brc.framerate[0].den ||
+                    !encoder_context->brc.bits_per_second[0])
+                    return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+                vp9_state->gop_size = encoder_context-
Post by Mark Thompson
brc.gop_size;
+
+                vp9_state->framerate = encoder_context-
Post by Mark Thompson
brc.framerate[0];
+                vp9_state->target_bit_rate = encoder_context-
Post by Mark Thompson
brc.bits_per_second[0];
                 vp9_state->max_bit_rate = vp9_state-
Post by Mark Thompson
target_bit_rate;
                 vp9_state->min_bit_rate = vp9_state-
Post by Mark Thompson
target_bit_rate;
-            } else {
-                /* VBR mode */
-                brc_flag = VP9_BRC_SEQ | VP9_BRC_RC;
-                vp9_state->target_bit_rate = seq_param-
Post by Mark Thompson
bits_per_second;
-                vp9_state->gop_size = seq_param->intra_period;
-
-                if (vp9_state->brc_flag_check & VP9_BRC_FR) {
-                    VAEncMiscParameterFrameRate *misc_param_fr;
-
-                    misc_param = (VAEncMiscParameterBuffer *)
-                        encode_state-
Post by Mark Thompson
misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
-                    misc_param_fr = (VAEncMiscParameterFrameRate
*)misc_param->data;
-
-                    vp9_state->frame_rate = misc_param_fr-
Post by Mark Thompson
framerate;
-                } else {
-                    /* Assign the default frame rate */
-                    vp9_state->frame_rate = 30;
-                }
-
-                if (vp9_state->brc_flag_check & VP9_BRC_RC) {
-                    VAEncMiscParameterRateControl
*misc_param_rc;
-
-                    misc_param = (VAEncMiscParameterBuffer *)
-                        encode_state-
Post by Mark Thompson
misc_param[VAEncMiscParameterTypeRateControl][0]->buffer;
-                    misc_param_rc =
(VAEncMiscParameterRateControl *)misc_param->data;
-
-                    vp9_state->max_bit_rate = misc_param_rc-
Post by Mark Thompson
bits_per_second;
-                    vp9_state->vbv_buffer_size_in_bit =
(misc_param_rc->bits_per_second / 1000) *
-                                                 misc_param_rc-
Post by Mark Thompson
window_size;
-                    vp9_state->init_vbv_buffer_fullness_in_bit =
vp9_state->vbv_buffer_size_in_bit / 2;
-                    vp9_state->target_bit_rate = (misc_param_rc-
Post by Mark Thompson
bits_per_second / 100) *
-                                misc_param_rc-
Post by Mark Thompson
target_percentage;
-                    vp9_state->min_bit_rate = (misc_param_rc-
Post by Mark Thompson
bits_per_second / 100) *
-                         (2 * misc_param_rc->target_percentage -
100);
-                    vp9_state->target_percentage =
misc_param_rc->target_percentage;
-                    vp9_state->window_size = misc_param_rc-
Post by Mark Thompson
window_size;
-                }
-            }
-        }
-        else if (vp9_state->picture_coding_type == KEY_FRAME){
-            VAEncMiscParameterBuffer *misc_param;
-            /* update the BRC parameter only when it is key-
frame */
-            /* If the parameter related with RC is changed.
Reset BRC */
-            if (vp9_state->brc_flag_check & VP9_BRC_FR) {
-               VAEncMiscParameterFrameRate *misc_param_fr;
-
-               misc_param = (VAEncMiscParameterBuffer *)
-                   encode_state-
Post by Mark Thompson
misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
-               misc_param_fr = (VAEncMiscParameterFrameRate
*)misc_param->data;
-
-               if (vp9_state->frame_rate != misc_param_fr-
Post by Mark Thompson
framerate) {
-                   vp9_state->brc_reset = 1;
-                   vp9_state->frame_rate = misc_param_fr-
Post by Mark Thompson
framerate;
-               }
-            }
 
-            /* check the GOP size. And bit_per_second in SPS is
ignored */
-            if (vp9_state->brc_flag_check & VP9_BRC_SEQ) {
-                if (vp9_state->gop_size != seq_param-
Post by Mark Thompson
intra_period) {
-                    vp9_state->brc_reset = 1;
-                    vp9_state->gop_size = seq_param-
Post by Mark Thompson
intra_period;
-                }
-            }
+                vp9_state->vbv_buffer_size_in_bit =
encoder_context->brc.hrd_buffer_size;
+                vp9_state->init_vbv_buffer_fullness_in_bit =
encoder_context->brc.hrd_initial_buffer_fullness;
vp9_state->init_vbv_buffer_fullness_in_bit may be overrode by the misc
RC parameters (vp9_state->window_size) in the current code.
I think we want to ignore window_size in CBR mode?  The bitrate is
intended to be constant, so the window to average over is necessarily
zero.  The relevant parts (to my mind) of the RC parameter structure
(really just bits_per_second) are already reflected in the generic
code.
I'm happy to change it if you feel the window_size should be used
there.  Though, I would ask which one "wins" if both HRD parameters
and window_size are set?
Agree, we should use the HRD parameters.
Post by Xiang, Haihao
Post by Mark Thompson
 
-            /* update the bit_per_second */
-            if (vp9_state->brc_flag_check & VP9_BRC_RC) {
-                VAEncMiscParameterRateControl *misc_param_rc;
-
-                misc_param = (VAEncMiscParameterBuffer *)
-                    encode_state-
Post by Mark Thompson
misc_param[VAEncMiscParameterTypeRateControl][0]->buffer;
-                misc_param_rc = (VAEncMiscParameterRateControl
*)misc_param->data;
-
-                if (encoder_context->rate_control_mode ==
VA_RC_CBR) {
-                    if (vp9_state->target_bit_rate !=
misc_param_rc->bits_per_second ||
-                        vp9_state->window_size != misc_param_rc-
Post by Mark Thompson
window_size) {
-                        vp9_state->target_bit_rate =
misc_param_rc->bits_per_second;
-                        vp9_state->vbv_buffer_size_in_bit =
(misc_param_rc->bits_per_second / 1000) *
-                                                 misc_param_rc-
Post by Mark Thompson
window_size;
-                        vp9_state-
Post by Mark Thompson
init_vbv_buffer_fullness_in_bit = vp9_state-
vbv_buffer_size_in_bit * 2;
-                        vp9_state->window_size = misc_param_rc-
Post by Mark Thompson
window_size;
-                        vp9_state->max_bit_rate = vp9_state-
Post by Mark Thompson
target_bit_rate;
-                        vp9_state->min_bit_rate = vp9_state-
Post by Mark Thompson
target_bit_rate;
-                        vp9_state->brc_reset = 1;
-                    }
-                } else {
-                    /* VBR mode */
-                    if (vp9_state->max_bit_rate !=
misc_param_rc->bits_per_second ||
-                        vp9_state->target_percentage !=
misc_param_rc->target_percentage) {
-
-                        vp9_state->target_bit_rate =
(misc_param_rc->bits_per_second / 100) *
-                                misc_param_rc-
Post by Mark Thompson
target_percentage;
-                        vp9_state->min_bit_rate =
(misc_param_rc->bits_per_second / 100) *
-                             (2 * misc_param_rc-
Post by Mark Thompson
target_percentage - 100);
-                        vp9_state->max_bit_rate = misc_param_rc-
Post by Mark Thompson
bits_per_second;
-                        vp9_state->vbv_buffer_size_in_bit =
(misc_param_rc->bits_per_second / 1000) *
-                                                 misc_param_rc-
Post by Mark Thompson
window_size;
-                        vp9_state-
Post by Mark Thompson
init_vbv_buffer_fullness_in_bit = vp9_state-
vbv_buffer_size_in_bit / 2;
-                        vp9_state->target_percentage =
misc_param_rc->target_percentage;
-                        vp9_state->window_size = misc_param_rc-
Post by Mark Thompson
window_size;
-                        vp9_state->brc_reset = 1;
-                    }
-                }
+            } else {
+                /* VBR mode */
+                if (!encoder_context->brc.framerate[0].num ||
!encoder_context->brc.framerate[0].den ||
+                    !encoder_context->brc.bits_per_second[0] ||
!encoder_context->brc.target_percentage[0] ||
+                    !encoder_context->brc.window_size)
+                    return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+                vp9_state->gop_size = encoder_context-
Post by Mark Thompson
brc.gop_size;
+
+                vp9_state->framerate = encoder_context-
Post by Mark Thompson
brc.framerate[0];
+                vp9_state->max_bit_rate = encoder_context-
Post by Mark Thompson
brc.bits_per_second[0];
+                vp9_state->target_percentage = encoder_context-
Post by Mark Thompson
brc.target_percentage[0];
+                vp9_state->window_size = encoder_context-
Post by Mark Thompson
brc.window_size;
+
+                vp9_state->target_bit_rate = vp9_state-
Post by Mark Thompson
max_bit_rate * encoder_context->brc.target_percentage[0] / 100;
+                if (2 * vp9_state->target_bit_rate < vp9_state-
Post by Mark Thompson
max_bit_rate)
+                    vp9_state->min_bit_rate = 0;
+                else
+                    vp9_state->min_bit_rate = 2 * vp9_state-
Post by Mark Thompson
target_bit_rate - vp9_state->max_bit_rate;
+
+                vp9_state->vbv_buffer_size_in_bit = (vp9_state-
Post by Mark Thompson
max_bit_rate / 1000) * vp9_state->window_size;
+                vp9_state->init_vbv_buffer_fullness_in_bit =
vp9_state->vbv_buffer_size_in_bit / 2;
This patch uses two different ways to get vp9_state-
Post by Mark Thompson
vbv_buffer_size_in_bit for CBR and VBR.
I think we should use the same way. I prefer the way used for CBR
in your patch although it is not the same of the current code.
The VBR mode behaviour was intended to be the same as what is there
currently, mainly because it is harder for me to verify the result
than with CBR.  The current code for VBR ignores the HRD parameters
and instead generates VBV values from the RC parameters, and I have
preserved that behaviour.
I can change it to use the HRD parameters if they are set?  Or would
you prefer that the two code paths are merged, with a branch on CBR
vs. VBR only around the setting of min|max_bit_rate?
User should provide the HRD parameters to the driver. The problem with
the current implementation for VP9 is user can't change the buffer
fullness any more if the misc RC parameters are provided
Thanks,
- Mark
Mark Thompson
2016-12-19 23:01:12 UTC
Permalink
Signed-off-by: Mark Thompson <***@jkqxz.net>
---
src/gen6_mfc.h | 6 ------
src/gen8_mfc.c | 68 +++++++++++++---------------------------------------------
2 files changed, 15 insertions(+), 59 deletions(-)

diff --git a/src/gen6_mfc.h b/src/gen6_mfc.h
index 290922b..7a5d940 100644
--- a/src/gen6_mfc.h
+++ b/src/gen6_mfc.h
@@ -235,12 +235,6 @@ struct gen6_mfc_context
double qpf_rounding_accumulator[MAX_TEMPORAL_LAYERS];
int bits_prev_frame[MAX_TEMPORAL_LAYERS];
int prev_slice_type[MAX_TEMPORAL_LAYERS];
-
- double saved_bps;
- double saved_fps;
- int saved_intra_period;
- int saved_ip_period;
- int saved_idr_period;
} brc;

struct {
diff --git a/src/gen8_mfc.c b/src/gen8_mfc.c
index d1de92c..7811cd0 100644
--- a/src/gen8_mfc.c
+++ b/src/gen8_mfc.c
@@ -3324,12 +3324,8 @@ static void gen8_mfc_vp8_brc_init(struct encode_state *encode_state,
{
struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
VAEncSequenceParameterBufferVP8 *seq_param = (VAEncSequenceParameterBufferVP8 *)encode_state->seq_param_ext->buffer;
- VAEncMiscParameterBuffer* misc_param_hrd = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeHRD][0]->buffer;
- VAEncMiscParameterHRD* param_hrd = (VAEncMiscParameterHRD*)misc_param_hrd->data;
- VAEncMiscParameterBuffer* misc_param_frame_rate_buffer = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
- VAEncMiscParameterFrameRate* param_frame_rate = (VAEncMiscParameterFrameRate*)misc_param_frame_rate_buffer->data;
- double bitrate = seq_param->bits_per_second;
- unsigned int frame_rate = param_frame_rate->framerate;
+ double bitrate = encoder_context->brc.bits_per_second[0];
+ double framerate = (double)encoder_context->brc.framerate[0].num / (double)encoder_context->brc.framerate[0].den;
int inum = 1, pnum = 0;
int intra_period = seq_param->intra_period;
int width_in_mbs = ALIGN(seq_param->frame_width, 16) / 16;
@@ -3340,14 +3336,14 @@ static void gen8_mfc_vp8_brc_init(struct encode_state *encode_state,

mfc_context->brc.mode = encoder_context->rate_control_mode;

- mfc_context->brc.target_frame_size[0][SLICE_TYPE_I] = (int)((double)((bitrate * intra_period)/frame_rate) /
+ mfc_context->brc.target_frame_size[0][SLICE_TYPE_I] = (int)((double)((bitrate * intra_period) / framerate) /
(double)(inum + BRC_PWEIGHT * pnum ));
mfc_context->brc.target_frame_size[0][SLICE_TYPE_P] = BRC_PWEIGHT * mfc_context->brc.target_frame_size[0][SLICE_TYPE_I];

mfc_context->brc.gop_nums[0][SLICE_TYPE_I] = inum;
mfc_context->brc.gop_nums[0][SLICE_TYPE_P] = pnum;

- mfc_context->brc.bits_per_frame[0] = bitrate/frame_rate;
+ mfc_context->brc.bits_per_frame[0] = bitrate / framerate;

mfc_context->brc.qp_prime_y[0][SLICE_TYPE_I] = gen8_mfc_vp8_qindex_estimate(encode_state,
mfc_context,
@@ -3358,10 +3354,15 @@ static void gen8_mfc_vp8_brc_init(struct encode_state *encode_state,
mfc_context->brc.target_frame_size[0][SLICE_TYPE_P],
0);

- mfc_context->hrd.buffer_size[0] = (double)param_hrd->buffer_size;
- mfc_context->hrd.current_buffer_fullness[0] =
- (double)(param_hrd->initial_buffer_fullness < mfc_context->hrd.buffer_size[0])?
- param_hrd->initial_buffer_fullness: mfc_context->hrd.buffer_size[0]/2.;
+ if (encoder_context->brc.hrd_buffer_size)
+ mfc_context->hrd.buffer_size[0] = (double)encoder_context->brc.hrd_buffer_size;
+ else
+ mfc_context->hrd.buffer_size[0] = 2.0 * bitrate;
+ if (encoder_context->brc.hrd_initial_buffer_fullness &&
+ encoder_context->brc.hrd_initial_buffer_fullness < mfc_context->hrd.buffer_size[0])
+ mfc_context->hrd.current_buffer_fullness[0] = (double)encoder_context->brc.hrd_initial_buffer_fullness;
+ else
+ mfc_context->hrd.current_buffer_fullness[0] = mfc_context->hrd.buffer_size[0] / 2.0;
mfc_context->hrd.target_buffer_fullness[0] = (double)mfc_context->hrd.buffer_size[0]/2.;
mfc_context->hrd.buffer_capacity[0] = (double)mfc_context->hrd.buffer_size[0]/max_frame_size;
mfc_context->hrd.violation_noted = 0;
@@ -3487,7 +3488,7 @@ static void gen8_mfc_vp8_hrd_context_init(struct encode_state *encode_state,
struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
VAEncSequenceParameterBufferVP8 *seq_param = (VAEncSequenceParameterBufferVP8 *)encode_state->seq_param_ext->buffer;
unsigned int rate_control_mode = encoder_context->rate_control_mode;
- int target_bit_rate = seq_param->bits_per_second;
+ int target_bit_rate = encoder_context->brc.bits_per_second[0];

// current we only support CBR mode.
if (rate_control_mode == VA_RC_CBR) {
@@ -3509,45 +3510,6 @@ static void gen8_mfc_vp8_hrd_context_update(struct encode_state *encode_state,
mfc_context->vui_hrd.i_frame_number++;
}

-/*
- * Check whether the parameters related with CBR are updated and decide whether
- * it needs to reinitialize the configuration related with CBR.
- * Currently it will check the following parameters:
- * bits_per_second
- * frame_rate
- * gop_configuration(intra_period, ip_period, intra_idr_period)
- */
-static bool gen8_mfc_vp8_brc_updated_check(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;
- double cur_fps, cur_bitrate;
- VAEncSequenceParameterBufferVP8 *seq_param = (VAEncSequenceParameterBufferVP8 *)encode_state->seq_param_ext->buffer;
- VAEncMiscParameterBuffer *misc_param_frame_rate_buf = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
- VAEncMiscParameterFrameRate *param_frame_rate = (VAEncMiscParameterFrameRate*)misc_param_frame_rate_buf->data;
- unsigned int frame_rate = param_frame_rate->framerate;
-
- if (rate_control_mode != VA_RC_CBR) {
- return false;
- }
-
- cur_bitrate = seq_param->bits_per_second;
- cur_fps = frame_rate;
-
- if ((cur_bitrate == mfc_context->brc.saved_bps) &&
- (cur_fps == mfc_context->brc.saved_fps) &&
- (seq_param->intra_period == mfc_context->brc.saved_intra_period)) {
- /* the parameters related with CBR are not updaetd */
- return false;
- }
-
- mfc_context->brc.saved_intra_period = seq_param->intra_period;
- mfc_context->brc.saved_fps = cur_fps;
- mfc_context->brc.saved_bps = cur_bitrate;
- return true;
-}
-
static void gen8_mfc_vp8_brc_prepare(struct encode_state *encode_state,
struct intel_encoder_context *encoder_context)
{
@@ -3557,7 +3519,7 @@ static void gen8_mfc_vp8_brc_prepare(struct encode_state *encode_state,
bool brc_updated;
assert(encoder_context->codec != CODEC_MPEG2);

- brc_updated = gen8_mfc_vp8_brc_updated_check(encode_state, encoder_context);
+ brc_updated = encoder_context->brc.need_reset;

/*Programing bit rate control */
if (brc_updated) {
--
2.10.2
Mark Thompson
2016-12-21 12:27:29 UTC
Permalink
Update references in both H.264 encoders (gen6_mfc and gen9_vdenc).
---
New version.
* Use a single field for framerate (adding a new struct to represent
it), as recommended by Haihao.
* Fix some missed cases where bitrate was read from the initial
sequence parameters rather than the most recent RC parameters.
The new struct is called "struct intel_fraction" to be consistent
with the namespacing in the rest of that file, it could go somewhere
else if that is preferred. Relatedly, the code might be nicer with
some more convenience functions around it (notably comparison and
fraction -> double, which are both used in a number of places), but
I'm not sure where they would go or what they would be called so I
have not done this.
Thanks,
- Mark
src/gen6_mfc_common.c | 11 +++++++----
src/gen9_vdenc.c | 28 ++++++++++++++++------------
src/gen9_vdenc.h | 2 +-
src/i965_encoder.c | 49 ++++++++++++++++++++++++++++++++++-------
--------
src/i965_encoder.h | 8 +++++++-
5 files changed, 65 insertions(+), 33 deletions(-)
...
@@ -480,7 +497,7 @@
intel_encoder_check_framerate_parameter(VADriverContextP ctx,
struct intel_encoder_context
*encoder_context,
VAEncMiscParameterFrameRate
*misc)
{
- int framerate_per_100s;
+ struct intel_fraction framerate;
int temporal_id = 0;
if (encoder_context->layer.num_layers >= 2)
@@ -490,12 +507,14 @@
intel_encoder_check_framerate_parameter(VADriverContextP ctx,
return;
if (misc->framerate & 0xffff0000)
- framerate_per_100s = (misc->framerate & 0xffff) * 100 /
((misc->framerate >> 16) & 0xffff);
+ framerate = (struct intel_fraction) { misc->framerate >> 16
& 0xffff, misc->framerate & 0xffff };
'misc->framerate >> 16 & 0xffff' is denominator, not numerator.
Hmm. Reading the comment in va/va.h again:

/*
* fps = numerator / denominator
* The high 2 bytes (bits 16 to 31) of framerate specifies the numerator, and
* the low 2 bytes (bits 0 to 15) of framerate specifies the denominator. For
* example, ((100 < 16 ) | 750) is 7.5 fps
*
* If the high 2 btyes is 0, the frame rate is specified by the low 2 bytes.
*/
unsigned int framerate;

the example and the text do not agree (I was following the text and didn't read the example carefully). Looking at the previous code there, apparently the example is the one which should be followed? If you could confirm that this is the intention and will not break any other drivers, I will send a new patch to libva to fix the text of the comment (and also change my code to match).
BTW could you refine your patch series to avoid compiler warning?
Looking at these with gcc (5 or 6), I have:

CC libi965_drv_video_la-i965_encoder.lo
../../src/i965_encoder.c: In function ‘reduce_fraction’:
../../src/i965_encoder.c:49:5: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
while (c = a % b) {
^

-> add redundant parentheses to suppress the warning, in patch 1.

CC libi965_drv_video_la-gen8_mfc.lo
../../src/gen8_mfc.c: In function ‘gen8_mfc_vp8_hrd_context_init’:
../../src/gen8_mfc.c:3489:38: warning: unused variable ‘seq_param’ [-Wunused-variable]
VAEncSequenceParameterBufferVP8 *seq_param = (VAEncSequenceParameterBufferVP8 *)encode_state->seq_param_ext->buffer;
^

-> remove the now-unused variable, in patch 3.

Do you have any other warnings? (I'll send a new series correcting these once the other questions are resolved.)

Thanks,

- Mark
Mark Thompson
2016-12-22 18:22:00 UTC
Permalink
Signed-off-by: Mark Thompson <***@jkqxz.net>
---
Post by Mark Thompson
/*
* fps = numerator / denominator
* The high 2 bytes (bits 16 to 31) of framerate specifies the numerator, and
* the low 2 bytes (bits 0 to 15) of framerate specifies the denominator. For
* example, ((100 < 16 ) | 750) is 7.5 fps
*
* If the high 2 btyes is 0, the frame rate is specified by the low 2 bytes.
*/
unsigned int framerate;
the example and the text do not agree (I was following the text and
didn't read the example carefully). Looking at the previous code
there, apparently the example is the one which should be followed?
It was my fault when I added the comment. Yes, we should follow the
example, some applications have already uses the form of the example.
BTW the example should be ((100 << 16) | 750) :(
Post by Mark Thompson
If you could confirm that this is the intention and will not break
any other drivers, I will send a new patch to libva to fix the text
of the comment (and also change my code to match).
Yes, please.
Enclosing patch fixes the incorrect comment, and also adds a bit more explanation to hopefully make the use clearer.

Thanks,

- Mark


va/va.h | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/va/va.h b/va/va.h
index 8791906..a1ab4a8 100644
--- a/va/va.h
+++ b/va/va.h
@@ -1277,12 +1277,22 @@ typedef struct _VAEncMiscParameterRateControl
typedef struct _VAEncMiscParameterFrameRate
{
/*
- * fps = numerator / denominator
- * The high 2 bytes (bits 16 to 31) of framerate specifies the numerator, and
- * the low 2 bytes (bits 0 to 15) of framerate specifies the denominator. For
- * example, ((100 < 16 ) | 750) is 7.5 fps
+ * The framerate is specified as a number of frames per second, as a
+ * fraction. The denominator of the fraction is given in the top half
+ * (the high two bytes) of the framerate field, and the numerator is
+ * given in the bottom half (the low two bytes).
*
- * If the high 2 btyes is 0, the frame rate is specified by the low 2 bytes.
+ * That is:
+ * denominator = framerate >> 16 & 0xffff;
+ * numerator = framerate & 0xffff;
+ * fps = numerator / denominator;
+ *
+ * For example, if framerate is set to (100 << 16 | 750), this is
+ * 750 / 100, hence 7.5fps.
+ *
+ * If the denominator is zero (the high two bytes are both zero) then
+ * it takes the value one instead, so the framerate is just the integer
+ * in the low 2 bytes.
*/
unsigned int framerate;
union
--
2.11.0
Xiang, Haihao
2016-12-23 15:11:41 UTC
Permalink
Applied, Thanks.
-----Original Message-----
Sent: Friday, December 23, 2016 2:22 AM
Subject: [PATCH] va.h: Improve the comment on the encode framerate
parameter
---
Post by Mark Thompson
/*
* fps = numerator / denominator
* The high 2 bytes (bits 16 to 31) of framerate specifies the numerator, and
* the low 2 bytes (bits 0 to 15) of framerate specifies the denominator. For
* example, ((100 < 16 ) | 750) is 7.5 fps
*
* If the high 2 btyes is 0, the frame rate is specified by the low 2 bytes.
*/
unsigned int framerate;
the example and the text do not agree (I was following the text and
didn't read the example carefully). Looking at the previous code
there, apparently the example is the one which should be followed?
It was my fault when I added the comment. Yes, we should follow the
example, some applications have already uses the form of the example.
BTW the example should be ((100 << 16) | 750) :(
Post by Mark Thompson
If you could confirm that this is the intention and will not break
any other drivers, I will send a new patch to libva to fix the text
of the comment (and also change my code to match).
Yes, please.
Enclosing patch fixes the incorrect comment, and also adds a bit more
explanation to hopefully make the use clearer.
Thanks,
- Mark
va/va.h | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/va/va.h b/va/va.h
index 8791906..a1ab4a8 100644
--- a/va/va.h
+++ b/va/va.h
@@ -1277,12 +1277,22 @@ typedef struct _VAEncMiscParameterRateControl
typedef struct _VAEncMiscParameterFrameRate {
/*
- * fps = numerator / denominator
- * The high 2 bytes (bits 16 to 31) of framerate specifies the numerator, and
- * the low 2 bytes (bits 0 to 15) of framerate specifies the denominator. For
- * example, ((100 < 16 ) | 750) is 7.5 fps
+ * The framerate is specified as a number of frames per second, as a
+ * fraction. The denominator of the fraction is given in the top half
+ * (the high two bytes) of the framerate field, and the numerator is
+ * given in the bottom half (the low two bytes).
*
- * If the high 2 btyes is 0, the frame rate is specified by the low 2 bytes.
+ * denominator = framerate >> 16 & 0xffff;
+ * numerator = framerate & 0xffff;
+ * fps = numerator / denominator;
+ *
+ * For example, if framerate is set to (100 << 16 | 750), this is
+ * 750 / 100, hence 7.5fps.
+ *
+ * If the denominator is zero (the high two bytes are both zero) then
+ * it takes the value one instead, so the framerate is just the integer
+ * in the low 2 bytes.
*/
unsigned int framerate;
union
--
2.11.0
Mark Thompson
2016-12-23 01:10:49 UTC
Permalink
Signed-off-by: Mark Thompson <***@jkqxz.net>
---
src/gen6_mfc.h | 6 -----
src/gen8_mfc.c | 73 ++++++++++++++--------------------------------------------
2 files changed, 17 insertions(+), 62 deletions(-)

diff --git a/src/gen6_mfc.h b/src/gen6_mfc.h
index 290922b..7a5d940 100644
--- a/src/gen6_mfc.h
+++ b/src/gen6_mfc.h
@@ -235,12 +235,6 @@ struct gen6_mfc_context
double qpf_rounding_accumulator[MAX_TEMPORAL_LAYERS];
int bits_prev_frame[MAX_TEMPORAL_LAYERS];
int prev_slice_type[MAX_TEMPORAL_LAYERS];
-
- double saved_bps;
- double saved_fps;
- int saved_intra_period;
- int saved_ip_period;
- int saved_idr_period;
} brc;

struct {
diff --git a/src/gen8_mfc.c b/src/gen8_mfc.c
index d1de92c..90119d7 100644
--- a/src/gen8_mfc.c
+++ b/src/gen8_mfc.c
@@ -3324,12 +3324,8 @@ static void gen8_mfc_vp8_brc_init(struct encode_state *encode_state,
{
struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
VAEncSequenceParameterBufferVP8 *seq_param = (VAEncSequenceParameterBufferVP8 *)encode_state->seq_param_ext->buffer;
- VAEncMiscParameterBuffer* misc_param_hrd = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeHRD][0]->buffer;
- VAEncMiscParameterHRD* param_hrd = (VAEncMiscParameterHRD*)misc_param_hrd->data;
- VAEncMiscParameterBuffer* misc_param_frame_rate_buffer = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
- VAEncMiscParameterFrameRate* param_frame_rate = (VAEncMiscParameterFrameRate*)misc_param_frame_rate_buffer->data;
- double bitrate = seq_param->bits_per_second;
- unsigned int frame_rate = param_frame_rate->framerate;
+ double bitrate = encoder_context->brc.bits_per_second[0];
+ double framerate = (double)encoder_context->brc.framerate[0].num / (double)encoder_context->brc.framerate[0].den;
int inum = 1, pnum = 0;
int intra_period = seq_param->intra_period;
int width_in_mbs = ALIGN(seq_param->frame_width, 16) / 16;
@@ -3340,14 +3336,14 @@ static void gen8_mfc_vp8_brc_init(struct encode_state *encode_state,

mfc_context->brc.mode = encoder_context->rate_control_mode;

- mfc_context->brc.target_frame_size[0][SLICE_TYPE_I] = (int)((double)((bitrate * intra_period)/frame_rate) /
+ mfc_context->brc.target_frame_size[0][SLICE_TYPE_I] = (int)((double)((bitrate * intra_period) / framerate) /
(double)(inum + BRC_PWEIGHT * pnum ));
mfc_context->brc.target_frame_size[0][SLICE_TYPE_P] = BRC_PWEIGHT * mfc_context->brc.target_frame_size[0][SLICE_TYPE_I];

mfc_context->brc.gop_nums[0][SLICE_TYPE_I] = inum;
mfc_context->brc.gop_nums[0][SLICE_TYPE_P] = pnum;

- mfc_context->brc.bits_per_frame[0] = bitrate/frame_rate;
+ mfc_context->brc.bits_per_frame[0] = bitrate / framerate;

mfc_context->brc.qp_prime_y[0][SLICE_TYPE_I] = gen8_mfc_vp8_qindex_estimate(encode_state,
mfc_context,
@@ -3358,12 +3354,17 @@ static void gen8_mfc_vp8_brc_init(struct encode_state *encode_state,
mfc_context->brc.target_frame_size[0][SLICE_TYPE_P],
0);

- mfc_context->hrd.buffer_size[0] = (double)param_hrd->buffer_size;
- mfc_context->hrd.current_buffer_fullness[0] =
- (double)(param_hrd->initial_buffer_fullness < mfc_context->hrd.buffer_size[0])?
- param_hrd->initial_buffer_fullness: mfc_context->hrd.buffer_size[0]/2.;
- mfc_context->hrd.target_buffer_fullness[0] = (double)mfc_context->hrd.buffer_size[0]/2.;
- mfc_context->hrd.buffer_capacity[0] = (double)mfc_context->hrd.buffer_size[0]/max_frame_size;
+ if (encoder_context->brc.hrd_buffer_size)
+ mfc_context->hrd.buffer_size[0] = (double)encoder_context->brc.hrd_buffer_size;
+ else
+ mfc_context->hrd.buffer_size[0] = bitrate;
+ if (encoder_context->brc.hrd_initial_buffer_fullness &&
+ encoder_context->brc.hrd_initial_buffer_fullness < mfc_context->hrd.buffer_size[0])
+ mfc_context->hrd.current_buffer_fullness[0] = (double)encoder_context->brc.hrd_initial_buffer_fullness;
+ else
+ mfc_context->hrd.current_buffer_fullness[0] = mfc_context->hrd.buffer_size[0] / 2.0;
+ mfc_context->hrd.target_buffer_fullness[0] = (double)mfc_context->hrd.buffer_size[0] / 2.0;
+ mfc_context->hrd.buffer_capacity[0] = (double)mfc_context->hrd.buffer_size[0] / max_frame_size;
mfc_context->hrd.violation_noted = 0;
}

@@ -3485,9 +3486,8 @@ static void gen8_mfc_vp8_hrd_context_init(struct encode_state *encode_state,
struct intel_encoder_context *encoder_context)
{
struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
- VAEncSequenceParameterBufferVP8 *seq_param = (VAEncSequenceParameterBufferVP8 *)encode_state->seq_param_ext->buffer;
unsigned int rate_control_mode = encoder_context->rate_control_mode;
- int target_bit_rate = seq_param->bits_per_second;
+ int target_bit_rate = encoder_context->brc.bits_per_second[0];

// current we only support CBR mode.
if (rate_control_mode == VA_RC_CBR) {
@@ -3509,45 +3509,6 @@ static void gen8_mfc_vp8_hrd_context_update(struct encode_state *encode_state,
mfc_context->vui_hrd.i_frame_number++;
}

-/*
- * Check whether the parameters related with CBR are updated and decide whether
- * it needs to reinitialize the configuration related with CBR.
- * Currently it will check the following parameters:
- * bits_per_second
- * frame_rate
- * gop_configuration(intra_period, ip_period, intra_idr_period)
- */
-static bool gen8_mfc_vp8_brc_updated_check(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;
- double cur_fps, cur_bitrate;
- VAEncSequenceParameterBufferVP8 *seq_param = (VAEncSequenceParameterBufferVP8 *)encode_state->seq_param_ext->buffer;
- VAEncMiscParameterBuffer *misc_param_frame_rate_buf = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
- VAEncMiscParameterFrameRate *param_frame_rate = (VAEncMiscParameterFrameRate*)misc_param_frame_rate_buf->data;
- unsigned int frame_rate = param_frame_rate->framerate;
-
- if (rate_control_mode != VA_RC_CBR) {
- return false;
- }
-
- cur_bitrate = seq_param->bits_per_second;
- cur_fps = frame_rate;
-
- if ((cur_bitrate == mfc_context->brc.saved_bps) &&
- (cur_fps == mfc_context->brc.saved_fps) &&
- (seq_param->intra_period == mfc_context->brc.saved_intra_period)) {
- /* the parameters related with CBR are not updaetd */
- return false;
- }
-
- mfc_context->brc.saved_intra_period = seq_param->intra_period;
- mfc_context->brc.saved_fps = cur_fps;
- mfc_context->brc.saved_bps = cur_bitrate;
- return true;
-}
-
static void gen8_mfc_vp8_brc_prepare(struct encode_state *encode_state,
struct intel_encoder_context *encoder_context)
{
@@ -3557,7 +3518,7 @@ static void gen8_mfc_vp8_brc_prepare(struct encode_state *encode_state,
bool brc_updated;
assert(encoder_context->codec != CODEC_MPEG2);

- brc_updated = gen8_mfc_vp8_brc_updated_check(encode_state, encoder_context);
+ brc_updated = encoder_context->brc.need_reset;

/*Programing bit rate control */
if (brc_updated) {
--
2.11.0
Mark Thompson
2016-12-19 23:00:24 UTC
Permalink
Signed-off-by: Mark Thompson <***@jkqxz.net>
---
src/gen9_mfc.h | 6 ----
src/gen9_mfc_hevc.c | 83 ++++++++++-------------------------------------------
src/i965_encoder.c | 74 +++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 84 insertions(+), 79 deletions(-)

diff --git a/src/gen9_mfc.h b/src/gen9_mfc.h
index f7dc572..8e7d5ad 100644
--- a/src/gen9_mfc.h
+++ b/src/gen9_mfc.h
@@ -153,12 +153,6 @@ struct gen9_hcpe_context {
int target_frame_size[3]; // I,P,B
double bits_per_frame;
double qpf_rounding_accumulator;
-
- double saved_bps;
- double saved_fps;
- int saved_intra_period;
- int saved_ip_period;
- int saved_idr_period;
} brc;

struct {
diff --git a/src/gen9_mfc_hevc.c b/src/gen9_mfc_hevc.c
index be5666c..8a84c1c 100644
--- a/src/gen9_mfc_hevc.c
+++ b/src/gen9_mfc_hevc.c
@@ -524,7 +524,7 @@ gen9_hcpe_hevc_pic_state(VADriverContextP ctx, struct encode_state *encode_state
int ctb_size = 1 << log2_ctb_size;
double rawctubits = 8 * 3 * ctb_size * ctb_size / 2.0;
int maxctubits = (int)(5 * rawctubits / 3) ;
- double bitrate = seq_param->bits_per_second * 1.0;
+ double bitrate = (double)encoder_context->brc.bits_per_second[0];
double framebitrate = bitrate / 32 / 8; //32 byte unit
int minframebitrate = 0;//(int) (framebitrate * 3 / 10);
int maxframebitrate = (int)(framebitrate * 10 / 10);
@@ -2163,15 +2163,16 @@ VAStatus intel_hcpe_hevc_prepare(VADriverContextP ctx,

static void
intel_hcpe_bit_rate_control_context_init(struct encode_state *encode_state,
- struct gen9_hcpe_context *mfc_context)
+ struct intel_encoder_context *encoder_context)
{
+ struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
int ctb_size = 16;
int width_in_mbs = (pSequenceParameter->pic_width_in_luma_samples + ctb_size - 1) / ctb_size;
int height_in_mbs = (pSequenceParameter->pic_height_in_luma_samples + ctb_size - 1) / ctb_size;

- float fps = pSequenceParameter->vui_time_scale / pSequenceParameter->vui_num_units_in_tick ;
- double bitrate = pSequenceParameter->bits_per_second * 1.0;
+ double fps = (double)encoder_context->brc.framerate[0].num / (double)encoder_context->brc.framerate[0].den;
+ double bitrate = encoder_context->brc.bits_per_second[0];
int inter_mb_size = bitrate * 1.0 / (fps + 4.0) / width_in_mbs / height_in_mbs;
int intra_mb_size = inter_mb_size * 5.0;
int i;
@@ -2214,11 +2215,9 @@ static void intel_hcpe_brc_init(struct encode_state *encode_state,
{
struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
- VAEncMiscParameterHRD* pParameterHRD = NULL;
- VAEncMiscParameterBuffer* pMiscParamHRD = NULL;

- double bitrate = pSequenceParameter->bits_per_second * 1.0;
- double framerate = (double)pSequenceParameter->vui_time_scale / (double)pSequenceParameter->vui_num_units_in_tick;
+ double bitrate = (double)encoder_context->brc.bits_per_second[0];
+ double framerate = (double)encoder_context->brc.framerate[0].num / (double)encoder_context->brc.framerate[0].den;
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;
@@ -2238,12 +2237,6 @@ static void intel_hcpe_brc_init(struct encode_state *encode_state,
qp1_size = qp1_size * bpp;
qp51_size = qp51_size * bpp;

- if (!encode_state->misc_param[VAEncMiscParameterTypeHRD][0] || !encode_state->misc_param[VAEncMiscParameterTypeHRD][0]->buffer)
- return;
-
- pMiscParamHRD = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeHRD][0]->buffer;
- pParameterHRD = (VAEncMiscParameterHRD*)pMiscParamHRD->data;
-
if (pSequenceParameter->ip_period) {
pnum = (intra_period + ip_period - 1) / ip_period - 1;
bnum = intra_period - inum - pnum;
@@ -2262,7 +2255,7 @@ static void intel_hcpe_brc_init(struct encode_state *encode_state,

bpf = mfc_context->brc.bits_per_frame = bitrate / framerate;

- if (!pParameterHRD || pParameterHRD->buffer_size <= 0)
+ if (!encoder_context->brc.hrd_buffer_size)
{
mfc_context->hrd.buffer_size = bitrate * ratio;
mfc_context->hrd.current_buffer_fullness =
@@ -2270,7 +2263,7 @@ static void intel_hcpe_brc_init(struct encode_state *encode_state,
bitrate * ratio/2 : mfc_context->hrd.buffer_size / 2.;
}else
{
- buffer_size = (double)pParameterHRD->buffer_size ;
+ buffer_size = (double)encoder_context->brc.hrd_buffer_size;
if(buffer_size < bitrate * ratio_min)
{
buffer_size = bitrate * ratio_min;
@@ -2279,11 +2272,11 @@ static void intel_hcpe_brc_init(struct encode_state *encode_state,
buffer_size = bitrate * ratio_max ;
}
mfc_context->hrd.buffer_size =buffer_size;
- if(pParameterHRD->initial_buffer_fullness > 0)
+ if(encoder_context->brc.hrd_initial_buffer_fullness)
{
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.;
+ (double)(encoder_context->brc.hrd_initial_buffer_fullness < mfc_context->hrd.buffer_size) ?
+ encoder_context->brc.hrd_initial_buffer_fullness : mfc_context->hrd.buffer_size / 2.;
}else
{
mfc_context->hrd.current_buffer_fullness = mfc_context->hrd.buffer_size / 2.;
@@ -2468,9 +2461,8 @@ static void intel_hcpe_hrd_context_init(struct encode_state *encode_state,
struct intel_encoder_context *encoder_context)
{
struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
- VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
unsigned int rate_control_mode = encoder_context->rate_control_mode;
- int target_bit_rate = pSequenceParameter->bits_per_second;
+ unsigned int target_bit_rate = encoder_context->brc.bits_per_second[0];

// current we only support CBR mode.
if (rate_control_mode == VA_RC_CBR) {
@@ -2519,51 +2511,6 @@ int intel_hcpe_interlace_check(VADriverContextP ctx,
return 1;
}

-/*
- * Check whether the parameters related with CBR are updated and decide whether
- * it needs to reinitialize the configuration related with CBR.
- * Currently it will check the following parameters:
- * bits_per_second
- * frame_rate
- * gop_configuration(intra_period, ip_period, intra_idr_period)
- */
-static bool intel_hcpe_brc_updated_check(struct encode_state *encode_state,
- struct intel_encoder_context *encoder_context)
-{
- /* to do */
- unsigned int rate_control_mode = encoder_context->rate_control_mode;
- struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
- double cur_fps, cur_bitrate;
- VAEncSequenceParameterBufferHEVC *pSequenceParameter;
-
-
- if (rate_control_mode != VA_RC_CBR) {
- return false;
- }
-
- pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
-
- cur_bitrate = pSequenceParameter->bits_per_second;
- cur_fps = (double)pSequenceParameter->vui_time_scale /
- (double)pSequenceParameter->vui_num_units_in_tick;
-
- if ((cur_bitrate == mfc_context->brc.saved_bps) &&
- (cur_fps == mfc_context->brc.saved_fps) &&
- (pSequenceParameter->intra_period == mfc_context->brc.saved_intra_period) &&
- (pSequenceParameter->intra_idr_period == mfc_context->brc.saved_idr_period) &&
- (pSequenceParameter->intra_period == mfc_context->brc.saved_intra_period)) {
- /* the parameters related with CBR are not updaetd */
- return false;
- }
-
- mfc_context->brc.saved_ip_period = pSequenceParameter->ip_period;
- mfc_context->brc.saved_intra_period = pSequenceParameter->intra_period;
- mfc_context->brc.saved_idr_period = pSequenceParameter->intra_idr_period;
- mfc_context->brc.saved_fps = cur_fps;
- mfc_context->brc.saved_bps = cur_bitrate;
- return true;
-}
-
void intel_hcpe_brc_prepare(struct encode_state *encode_state,
struct intel_encoder_context *encoder_context)
{
@@ -2574,12 +2521,12 @@ void intel_hcpe_brc_prepare(struct encode_state *encode_state,
bool brc_updated;
assert(encoder_context->codec != CODEC_MPEG2);

- brc_updated = intel_hcpe_brc_updated_check(encode_state, encoder_context);
+ brc_updated = encoder_context->brc.need_reset;

/*Programing bit rate control */
if ((mfc_context->bit_rate_control_context[HEVC_SLICE_I].MaxSizeInWord == 0) ||
brc_updated) {
- intel_hcpe_bit_rate_control_context_init(encode_state, mfc_context);
+ intel_hcpe_bit_rate_control_context_init(encode_state, encoder_context);
intel_hcpe_brc_init(encode_state, encoder_context);
}

diff --git a/src/i965_encoder.c b/src/i965_encoder.c
index e5aff72..20ae554 100644
--- a/src/i965_encoder.c
+++ b/src/i965_encoder.c
@@ -432,19 +432,83 @@ intel_encoder_check_brc_vp8_sequence_parameter(VADriverContextP ctx,
}

static VAStatus
+intel_encoder_check_brc_hevc_sequence_parameter(VADriverContextP ctx,
+ struct encode_state *encode_state,
+ struct intel_encoder_context *encoder_context)
+{
+ VAEncSequenceParameterBufferHEVC *seq_param = (VAEncSequenceParameterBufferHEVC*)encode_state->seq_param_ext->buffer;
+ struct intel_fraction framerate;
+ unsigned int gop_size, num_iframes_in_gop, num_pframes_in_gop, num_bframes_in_gop;
+
+ if (!encoder_context->is_new_sequence)
+ return VA_STATUS_SUCCESS;
+ if (!seq_param)
+ return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+ if (!seq_param->vui_time_scale || !seq_param->vui_num_units_in_tick)
+ framerate = (struct intel_fraction) { 30, 1 };
+ else
+ framerate = (struct intel_fraction) { seq_param->vui_time_scale, seq_param->vui_num_units_in_tick };
+ framerate = reduce_fraction(framerate);
+
+ num_iframes_in_gop = 1;
+ if (seq_param->intra_period == 0) {
+ gop_size = -1;
+ num_pframes_in_gop = -1;
+ } else if (seq_param->intra_period == 1) {
+ gop_size = 1;
+ num_pframes_in_gop = 0;
+ } else {
+ gop_size = seq_param->intra_period;
+ num_pframes_in_gop = (seq_param->intra_period + seq_param->ip_period - 1) / seq_param->ip_period - 1;
+ }
+ num_bframes_in_gop = gop_size - num_iframes_in_gop - num_pframes_in_gop;
+
+ if (encoder_context->brc.framerate[0].num != framerate.num ||
+ encoder_context->brc.framerate[0].den != framerate.den) {
+ encoder_context->brc.framerate[0] = framerate;
+ encoder_context->brc.need_reset = 1;
+ }
+
+ if (encoder_context->brc.gop_size != gop_size ||
+ encoder_context->brc.num_iframes_in_gop != num_iframes_in_gop ||
+ encoder_context->brc.num_pframes_in_gop != num_pframes_in_gop ||
+ encoder_context->brc.num_bframes_in_gop != num_bframes_in_gop) {
+ encoder_context->brc.gop_size = gop_size;
+ encoder_context->brc.num_iframes_in_gop = num_iframes_in_gop;
+ encoder_context->brc.num_pframes_in_gop = num_pframes_in_gop;
+ encoder_context->brc.num_bframes_in_gop = num_bframes_in_gop;
+ encoder_context->brc.need_reset = 1;
+ }
+
+ if (encoder_context->brc.bits_per_second[0] != seq_param->bits_per_second) {
+ encoder_context->brc.bits_per_second[0] = seq_param->bits_per_second;
+ encoder_context->brc.need_reset = 1;
+ }
+
+ return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
intel_encoder_check_brc_sequence_parameter(VADriverContextP ctx,
struct encode_state *encode_state,
struct intel_encoder_context *encoder_context)
{
- if (encoder_context->codec == CODEC_H264 ||
- encoder_context->codec == CODEC_H264_MVC)
+ switch (encoder_context->codec) {
+ case CODEC_H264:
+ case CODEC_H264_MVC:
return intel_encoder_check_brc_h264_sequence_parameter(ctx, encode_state, encoder_context);

- if (encoder_context->codec == CODEC_VP8)
+ case CODEC_VP8:
return intel_encoder_check_brc_vp8_sequence_parameter(ctx, encode_state, encoder_context);

- // TODO: other codecs
- return VA_STATUS_SUCCESS;
+ case CODEC_HEVC:
+ return intel_encoder_check_brc_hevc_sequence_parameter(ctx, encode_state, encoder_context);
+
+ default:
+ // TODO: other codecs
+ return VA_STATUS_SUCCESS;
+ }
}

static void
--
2.10.2
Mark Thompson
2016-12-23 01:10:04 UTC
Permalink
Signed-off-by: Mark Thompson <***@jkqxz.net>
---
src/gen9_mfc.h | 6 ----
src/gen9_mfc_hevc.c | 83 ++++++++++-------------------------------------------
src/i965_encoder.c | 74 +++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 84 insertions(+), 79 deletions(-)

diff --git a/src/gen9_mfc.h b/src/gen9_mfc.h
index f7dc572..8e7d5ad 100644
--- a/src/gen9_mfc.h
+++ b/src/gen9_mfc.h
@@ -153,12 +153,6 @@ struct gen9_hcpe_context {
int target_frame_size[3]; // I,P,B
double bits_per_frame;
double qpf_rounding_accumulator;
-
- double saved_bps;
- double saved_fps;
- int saved_intra_period;
- int saved_ip_period;
- int saved_idr_period;
} brc;

struct {
diff --git a/src/gen9_mfc_hevc.c b/src/gen9_mfc_hevc.c
index be5666c..8a84c1c 100644
--- a/src/gen9_mfc_hevc.c
+++ b/src/gen9_mfc_hevc.c
@@ -524,7 +524,7 @@ gen9_hcpe_hevc_pic_state(VADriverContextP ctx, struct encode_state *encode_state
int ctb_size = 1 << log2_ctb_size;
double rawctubits = 8 * 3 * ctb_size * ctb_size / 2.0;
int maxctubits = (int)(5 * rawctubits / 3) ;
- double bitrate = seq_param->bits_per_second * 1.0;
+ double bitrate = (double)encoder_context->brc.bits_per_second[0];
double framebitrate = bitrate / 32 / 8; //32 byte unit
int minframebitrate = 0;//(int) (framebitrate * 3 / 10);
int maxframebitrate = (int)(framebitrate * 10 / 10);
@@ -2163,15 +2163,16 @@ VAStatus intel_hcpe_hevc_prepare(VADriverContextP ctx,

static void
intel_hcpe_bit_rate_control_context_init(struct encode_state *encode_state,
- struct gen9_hcpe_context *mfc_context)
+ struct intel_encoder_context *encoder_context)
{
+ struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
int ctb_size = 16;
int width_in_mbs = (pSequenceParameter->pic_width_in_luma_samples + ctb_size - 1) / ctb_size;
int height_in_mbs = (pSequenceParameter->pic_height_in_luma_samples + ctb_size - 1) / ctb_size;

- float fps = pSequenceParameter->vui_time_scale / pSequenceParameter->vui_num_units_in_tick ;
- double bitrate = pSequenceParameter->bits_per_second * 1.0;
+ double fps = (double)encoder_context->brc.framerate[0].num / (double)encoder_context->brc.framerate[0].den;
+ double bitrate = encoder_context->brc.bits_per_second[0];
int inter_mb_size = bitrate * 1.0 / (fps + 4.0) / width_in_mbs / height_in_mbs;
int intra_mb_size = inter_mb_size * 5.0;
int i;
@@ -2214,11 +2215,9 @@ static void intel_hcpe_brc_init(struct encode_state *encode_state,
{
struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
- VAEncMiscParameterHRD* pParameterHRD = NULL;
- VAEncMiscParameterBuffer* pMiscParamHRD = NULL;

- double bitrate = pSequenceParameter->bits_per_second * 1.0;
- double framerate = (double)pSequenceParameter->vui_time_scale / (double)pSequenceParameter->vui_num_units_in_tick;
+ double bitrate = (double)encoder_context->brc.bits_per_second[0];
+ double framerate = (double)encoder_context->brc.framerate[0].num / (double)encoder_context->brc.framerate[0].den;
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;
@@ -2238,12 +2237,6 @@ static void intel_hcpe_brc_init(struct encode_state *encode_state,
qp1_size = qp1_size * bpp;
qp51_size = qp51_size * bpp;

- if (!encode_state->misc_param[VAEncMiscParameterTypeHRD][0] || !encode_state->misc_param[VAEncMiscParameterTypeHRD][0]->buffer)
- return;
-
- pMiscParamHRD = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeHRD][0]->buffer;
- pParameterHRD = (VAEncMiscParameterHRD*)pMiscParamHRD->data;
-
if (pSequenceParameter->ip_period) {
pnum = (intra_period + ip_period - 1) / ip_period - 1;
bnum = intra_period - inum - pnum;
@@ -2262,7 +2255,7 @@ static void intel_hcpe_brc_init(struct encode_state *encode_state,

bpf = mfc_context->brc.bits_per_frame = bitrate / framerate;

- if (!pParameterHRD || pParameterHRD->buffer_size <= 0)
+ if (!encoder_context->brc.hrd_buffer_size)
{
mfc_context->hrd.buffer_size = bitrate * ratio;
mfc_context->hrd.current_buffer_fullness =
@@ -2270,7 +2263,7 @@ static void intel_hcpe_brc_init(struct encode_state *encode_state,
bitrate * ratio/2 : mfc_context->hrd.buffer_size / 2.;
}else
{
- buffer_size = (double)pParameterHRD->buffer_size ;
+ buffer_size = (double)encoder_context->brc.hrd_buffer_size;
if(buffer_size < bitrate * ratio_min)
{
buffer_size = bitrate * ratio_min;
@@ -2279,11 +2272,11 @@ static void intel_hcpe_brc_init(struct encode_state *encode_state,
buffer_size = bitrate * ratio_max ;
}
mfc_context->hrd.buffer_size =buffer_size;
- if(pParameterHRD->initial_buffer_fullness > 0)
+ if(encoder_context->brc.hrd_initial_buffer_fullness)
{
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.;
+ (double)(encoder_context->brc.hrd_initial_buffer_fullness < mfc_context->hrd.buffer_size) ?
+ encoder_context->brc.hrd_initial_buffer_fullness : mfc_context->hrd.buffer_size / 2.;
}else
{
mfc_context->hrd.current_buffer_fullness = mfc_context->hrd.buffer_size / 2.;
@@ -2468,9 +2461,8 @@ static void intel_hcpe_hrd_context_init(struct encode_state *encode_state,
struct intel_encoder_context *encoder_context)
{
struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
- VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
unsigned int rate_control_mode = encoder_context->rate_control_mode;
- int target_bit_rate = pSequenceParameter->bits_per_second;
+ unsigned int target_bit_rate = encoder_context->brc.bits_per_second[0];

// current we only support CBR mode.
if (rate_control_mode == VA_RC_CBR) {
@@ -2519,51 +2511,6 @@ int intel_hcpe_interlace_check(VADriverContextP ctx,
return 1;
}

-/*
- * Check whether the parameters related with CBR are updated and decide whether
- * it needs to reinitialize the configuration related with CBR.
- * Currently it will check the following parameters:
- * bits_per_second
- * frame_rate
- * gop_configuration(intra_period, ip_period, intra_idr_period)
- */
-static bool intel_hcpe_brc_updated_check(struct encode_state *encode_state,
- struct intel_encoder_context *encoder_context)
-{
- /* to do */
- unsigned int rate_control_mode = encoder_context->rate_control_mode;
- struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
- double cur_fps, cur_bitrate;
- VAEncSequenceParameterBufferHEVC *pSequenceParameter;
-
-
- if (rate_control_mode != VA_RC_CBR) {
- return false;
- }
-
- pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
-
- cur_bitrate = pSequenceParameter->bits_per_second;
- cur_fps = (double)pSequenceParameter->vui_time_scale /
- (double)pSequenceParameter->vui_num_units_in_tick;
-
- if ((cur_bitrate == mfc_context->brc.saved_bps) &&
- (cur_fps == mfc_context->brc.saved_fps) &&
- (pSequenceParameter->intra_period == mfc_context->brc.saved_intra_period) &&
- (pSequenceParameter->intra_idr_period == mfc_context->brc.saved_idr_period) &&
- (pSequenceParameter->intra_period == mfc_context->brc.saved_intra_period)) {
- /* the parameters related with CBR are not updaetd */
- return false;
- }
-
- mfc_context->brc.saved_ip_period = pSequenceParameter->ip_period;
- mfc_context->brc.saved_intra_period = pSequenceParameter->intra_period;
- mfc_context->brc.saved_idr_period = pSequenceParameter->intra_idr_period;
- mfc_context->brc.saved_fps = cur_fps;
- mfc_context->brc.saved_bps = cur_bitrate;
- return true;
-}
-
void intel_hcpe_brc_prepare(struct encode_state *encode_state,
struct intel_encoder_context *encoder_context)
{
@@ -2574,12 +2521,12 @@ void intel_hcpe_brc_prepare(struct encode_state *encode_state,
bool brc_updated;
assert(encoder_context->codec != CODEC_MPEG2);

- brc_updated = intel_hcpe_brc_updated_check(encode_state, encoder_context);
+ brc_updated = encoder_context->brc.need_reset;

/*Programing bit rate control */
if ((mfc_context->bit_rate_control_context[HEVC_SLICE_I].MaxSizeInWord == 0) ||
brc_updated) {
- intel_hcpe_bit_rate_control_context_init(encode_state, mfc_context);
+ intel_hcpe_bit_rate_control_context_init(encode_state, encoder_context);
intel_hcpe_brc_init(encode_state, encoder_context);
}

diff --git a/src/i965_encoder.c b/src/i965_encoder.c
index 3aaac34..76789f3 100644
--- a/src/i965_encoder.c
+++ b/src/i965_encoder.c
@@ -432,19 +432,83 @@ intel_encoder_check_brc_vp8_sequence_parameter(VADriverContextP ctx,
}

static VAStatus
+intel_encoder_check_brc_hevc_sequence_parameter(VADriverContextP ctx,
+ struct encode_state *encode_state,
+ struct intel_encoder_context *encoder_context)
+{
+ VAEncSequenceParameterBufferHEVC *seq_param = (VAEncSequenceParameterBufferHEVC*)encode_state->seq_param_ext->buffer;
+ struct intel_fraction framerate;
+ unsigned int gop_size, num_iframes_in_gop, num_pframes_in_gop, num_bframes_in_gop;
+
+ if (!encoder_context->is_new_sequence)
+ return VA_STATUS_SUCCESS;
+ if (!seq_param)
+ return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+ if (!seq_param->vui_time_scale || !seq_param->vui_num_units_in_tick)
+ framerate = (struct intel_fraction) { 30, 1 };
+ else
+ framerate = (struct intel_fraction) { seq_param->vui_time_scale, seq_param->vui_num_units_in_tick };
+ framerate = reduce_fraction(framerate);
+
+ num_iframes_in_gop = 1;
+ if (seq_param->intra_period == 0) {
+ gop_size = -1;
+ num_pframes_in_gop = -1;
+ } else if (seq_param->intra_period == 1) {
+ gop_size = 1;
+ num_pframes_in_gop = 0;
+ } else {
+ gop_size = seq_param->intra_period;
+ num_pframes_in_gop = (seq_param->intra_period + seq_param->ip_period - 1) / seq_param->ip_period - 1;
+ }
+ num_bframes_in_gop = gop_size - num_iframes_in_gop - num_pframes_in_gop;
+
+ if (encoder_context->brc.framerate[0].num != framerate.num ||
+ encoder_context->brc.framerate[0].den != framerate.den) {
+ encoder_context->brc.framerate[0] = framerate;
+ encoder_context->brc.need_reset = 1;
+ }
+
+ if (encoder_context->brc.gop_size != gop_size ||
+ encoder_context->brc.num_iframes_in_gop != num_iframes_in_gop ||
+ encoder_context->brc.num_pframes_in_gop != num_pframes_in_gop ||
+ encoder_context->brc.num_bframes_in_gop != num_bframes_in_gop) {
+ encoder_context->brc.gop_size = gop_size;
+ encoder_context->brc.num_iframes_in_gop = num_iframes_in_gop;
+ encoder_context->brc.num_pframes_in_gop = num_pframes_in_gop;
+ encoder_context->brc.num_bframes_in_gop = num_bframes_in_gop;
+ encoder_context->brc.need_reset = 1;
+ }
+
+ if (encoder_context->brc.bits_per_second[0] != seq_param->bits_per_second) {
+ encoder_context->brc.bits_per_second[0] = seq_param->bits_per_second;
+ encoder_context->brc.need_reset = 1;
+ }
+
+ return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
intel_encoder_check_brc_sequence_parameter(VADriverContextP ctx,
struct encode_state *encode_state,
struct intel_encoder_context *encoder_context)
{
- if (encoder_context->codec == CODEC_H264 ||
- encoder_context->codec == CODEC_H264_MVC)
+ switch (encoder_context->codec) {
+ case CODEC_H264:
+ case CODEC_H264_MVC:
return intel_encoder_check_brc_h264_sequence_parameter(ctx, encode_state, encoder_context);

- if (encoder_context->codec == CODEC_VP8)
+ case CODEC_VP8:
return intel_encoder_check_brc_vp8_sequence_parameter(ctx, encode_state, encoder_context);

- // TODO: other codecs
- return VA_STATUS_SUCCESS;
+ case CODEC_HEVC:
+ return intel_encoder_check_brc_hevc_sequence_parameter(ctx, encode_state, encoder_context);
+
+ default:
+ // TODO: other codecs
+ return VA_STATUS_SUCCESS;
+ }
}

static void
--
2.11.0
Xiang, Haihao
2016-12-23 15:24:36 UTC
Permalink
The patch series looks good to me and I also tested with VDEnc.

Thanks
Haihao
-----Original Message-----
Thompson
Sent: Friday, December 23, 2016 9:08 AM
Subject: [Libva] [PATCH 1/4] i965_encoder: consistently represent framerate
as a fraction
Update references in both H.264 encoders (gen6_mfc and gen9_vdenc).
---
* Derive numerator and denominator from the correct parts of the framerate
parameter (see also earlier patch fixing the comment in va.h).
* Make VP8 HRD buffer size derivation the same as other codecs.
* Make the VP9 rate control setup behave more consistently (use window
size if needed for VBR, always use HRD parameters if present).
* Fix warnings.
Thanks,
- Mark
src/gen6_mfc_common.c | 11 +++++++----
src/gen9_vdenc.c | 28 ++++++++++++++++------------
src/gen9_vdenc.h | 2 +-
src/i965_encoder.c | 49 ++++++++++++++++++++++++++++++++++---------
------
src/i965_encoder.h | 8 +++++++-
5 files changed, 65 insertions(+), 33 deletions(-)
diff --git a/src/gen6_mfc_common.c b/src/gen6_mfc_common.c index
68d030e..15c0637 100644
--- a/src/gen6_mfc_common.c
+++ b/src/gen6_mfc_common.c
@@ -119,16 +119,19 @@ static void intel_mfc_brc_init(struct encode_state
*encode_state,
if (i == 0) {
bitrate = encoder_context->brc.bits_per_second[0];
- framerate = (double)encoder_context->brc.framerate_per_100s[0] /
100.0;
+ framerate = (double)encoder_context->brc.framerate[0].num /
+ (double)encoder_context->brc.framerate[0].den;
} else {
bitrate = (encoder_context->brc.bits_per_second[i] -
encoder_context->brc.bits_per_second[i - 1]);
- framerate = (double)(encoder_context->brc.framerate_per_100s[i] -
encoder_context->brc.framerate_per_100s[i - 1]) / 100.0;
+ framerate = ((double)encoder_context->brc.framerate[i].num /
(double)encoder_context->brc.framerate[i].den) -
+ ((double)encoder_context->brc.framerate[i - 1].num /
+ (double)encoder_context->brc.framerate[i - 1].den);
}
if (i == encoder_context->layer.num_layers - 1)
factor = 1.0;
- else
- factor = (double)encoder_context->brc.framerate_per_100s[i] /
encoder_context->brc.framerate_per_100s[encoder_context-
layer.num_layers - 1];
+ else {
+ factor = ((double)encoder_context->brc.framerate[i].num /
(double)encoder_context->brc.framerate[i].den) /
+ ((double)encoder_context->brc.framerate[i - 1].num /
(double)encoder_context->brc.framerate[i - 1].den);
+ }
hrd_factor = (double)bitrate / encoder_context-
brc.bits_per_second[encoder_context->layer.num_layers - 1];
diff --git a/src/gen9_vdenc.c b/src/gen9_vdenc.c index 8009b31..691faec
100644
--- a/src/gen9_vdenc.c
+++ b/src/gen9_vdenc.c
@@ -851,7 +851,7 @@
gen9_vdenc_update_misc_parameters(VADriverContextP ctx,
if (vdenc_context->internal_rate_mode != I965_BRC_CQP &&
encoder_context->brc.need_reset) {
/* So far, vdenc doesn't support temporal layer */
- vdenc_context->frames_per_100s = encoder_context-
brc.framerate_per_100s[0];
+ vdenc_context->framerate = encoder_context->brc.framerate[0];
vdenc_context->vbv_buffer_size_in_bit = encoder_context-
brc.hrd_buffer_size;
vdenc_context->init_vbv_buffer_fullness_in_bit = encoder_context-
brc.hrd_initial_buffer_fullness;
@@ -927,7 +927,8 @@ gen9_vdenc_update_parameters(VADriverContextP
ctx,
!vdenc_context->vbv_buffer_size_in_bit ||
!vdenc_context->max_bit_rate ||
!vdenc_context->target_bit_rate ||
- !vdenc_context->frames_per_100s))
+ !vdenc_context->framerate.num ||
+ !vdenc_context->framerate.den))
vdenc_context->brc_enabled = 0;
if (!vdenc_context->brc_enabled) {
@@ -1565,7 +1566,8 @@
gen9_vdenc_get_profile_level_max_frame(VADriverContextP ctx,
tmpf = max_mbps / 172.0;
max_byte_per_frame0 = (uint64_t)(tmpf * bits_per_mb);
- max_byte_per_frame1 = (uint64_t)(((double)max_mbps * 100) /
vdenc_context->frames_per_100s *bits_per_mb);
+ max_byte_per_frame1 = (uint64_t)(((double)max_mbps *
vdenc_context->framerate.den) /
+
+ (double)vdenc_context->framerate.num * bits_per_mb);
/* TODO: check VAEncMiscParameterTypeMaxFrameSize */
ret = (unsigned int)MIN(max_byte_per_frame0, max_byte_per_frame1);
@@ -1586,12 +1588,12 @@
gen9_vdenc_calculate_initial_qp(VADriverContextP ctx,
frame_size = (vdenc_context->frame_width * vdenc_context-
frame_height * 3 / 2);
qp = (int)(1.0 / 1.2 * pow(10.0,
- (log10(frame_size * 2.0 / 3.0 * ((float)vdenc_context-
frames_per_100s) /
- ((float)(vdenc_context->target_bit_rate * 1000) * 100)) -
x0) *
+ (log10(frame_size * 2.0 / 3.0 * vdenc_context-
framerate.num /
+
+ ((double)vdenc_context->target_bit_rate * 1000.0 *
+ vdenc_context->framerate.den)) - x0) *
(y1 - y0) / (x1 - x0) + y0) + 0.5);
qp += 2;
- delat_qp = (int)(9 - (vdenc_context->vbv_buffer_size_in_bit *
((float)vdenc_context->frames_per_100s) /
- ((float)(vdenc_context->target_bit_rate * 1000) * 100)));
+ delat_qp = (int)(9 - (vdenc_context->vbv_buffer_size_in_bit *
((double)vdenc_context->framerate.num) /
+ ((double)vdenc_context->target_bit_rate *
+ 1000.0 * vdenc_context->framerate.den)));
if (delat_qp > 0)
qp += delat_qp;
@@ -1615,7 +1617,8 @@
gen9_vdenc_update_huc_brc_init_dmem(VADriverContextP ctx,
double input_bits_per_frame, bps_ratio;
int i;
- vdenc_context->brc_init_reset_input_bits_per_frame =
((double)(vdenc_context->max_bit_rate * 1000) * 100) / vdenc_context-
frames_per_100s;
+ vdenc_context->brc_init_reset_input_bits_per_frame =
+ ((double)vdenc_context->max_bit_rate * 1000.0 *
+ vdenc_context->framerate.den) / vdenc_context->framerate.num;
vdenc_context->brc_init_current_target_buf_full_in_bits =
vdenc_context->brc_init_reset_input_bits_per_frame;
vdenc_context->brc_target_size = vdenc_context-
init_vbv_buffer_fullness_in_bit;
@@ -1645,8 +1648,8 @@
gen9_vdenc_update_huc_brc_init_dmem(VADriverContextP ctx,
else if (vdenc_context->internal_rate_mode == I965_BRC_VBR)
dmem->brc_flag |= 0x20;
- dmem->frame_rate_m = vdenc_context->frames_per_100s;
- dmem->frame_rate_d = 100;
+ dmem->frame_rate_m = vdenc_context->framerate.num;
+ dmem->frame_rate_d = vdenc_context->framerate.den;
dmem->profile_level_max_frame =
gen9_vdenc_get_profile_level_max_frame(ctx, encoder_context,
seq_param->level_idc);
@@ -1656,8 +1659,9 @@
gen9_vdenc_update_huc_brc_init_dmem(VADriverContextP ctx,
dmem->min_qp = 10;
dmem->max_qp = 51;
- input_bits_per_frame = ((double)vdenc_context->max_bit_rate * 1000 *
100) / vdenc_context->frames_per_100s;
- bps_ratio = input_bits_per_frame / ((double)vdenc_context-
vbv_buffer_size_in_bit * 100 / vdenc_context->frames_per_100s);
+ input_bits_per_frame = ((double)vdenc_context->max_bit_rate * 1000.0
* vdenc_context->framerate.den) / vdenc_context->framerate.num;
+ bps_ratio = input_bits_per_frame /
+ ((double)vdenc_context->vbv_buffer_size_in_bit *
+ vdenc_context->framerate.den / vdenc_context->framerate.num);
if (bps_ratio < 0.1)
bps_ratio = 0.1;
diff --git a/src/gen9_vdenc.h b/src/gen9_vdenc.h index e790497..41e4362
100644
--- a/src/gen9_vdenc.h
+++ b/src/gen9_vdenc.h
@@ -741,7 +741,7 @@ struct gen9_vdenc_context
uint32_t min_bit_rate; /* in kbps */
uint64_t init_vbv_buffer_fullness_in_bit;
uint64_t vbv_buffer_size_in_bit;
- uint32_t frames_per_100s;
+ struct intel_fraction framerate;
uint32_t gop_size;
uint32_t ref_dist;
uint32_t brc_target_size;
diff --git a/src/i965_encoder.c b/src/i965_encoder.c index d874322..3aaac34
100644
--- a/src/i965_encoder.c
+++ b/src/i965_encoder.c
@@ -42,6 +42,17 @@
#include "i965_post_processing.h"
+static struct intel_fraction
+reduce_fraction(struct intel_fraction f) {
+ unsigned int a = f.num, b = f.den, c;
+ while ((c = a % b)) {
+ a = b;
+ b = c;
+ }
+ return (struct intel_fraction) { f.num / b, f.den / b }; }
+
static VAStatus
intel_encoder_check_brc_h264_sequence_parameter(VADriverContextP ctx,
struct intel_encoder_context *encoder_context) {
VAEncSequenceParameterBufferH264 *seq_param =
(VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext-
buffer;
+ struct intel_fraction framerate;
+ unsigned int bits_per_second;
unsigned short num_pframes_in_gop, num_bframes_in_gop;
- unsigned int bits_per_second, framerate_per_100s;
if (!encoder_context->is_new_sequence)
return VA_STATUS_SUCCESS;
@@ -315,10 +327,13 @@
intel_encoder_check_brc_h264_sequence_parameter(VADriverContextP ctx,
assert(seq_param);
bits_per_second = seq_param->bits_per_second; // for the highest layer
- if (!seq_param->num_units_in_tick || !seq_param->time_scale)
- framerate_per_100s = 3000;
- else
- framerate_per_100s = seq_param->time_scale * 100 / (2 * seq_param-
num_units_in_tick); // for the highest layer
+ if (!seq_param->num_units_in_tick || !seq_param->time_scale) {
+ framerate = (struct intel_fraction) { 30, 1 };
+ } else {
+ // for the highest layer
+ framerate = (struct intel_fraction) { seq_param->time_scale, 2 *
seq_param->num_units_in_tick };
+ }
+ framerate = reduce_fraction(framerate);
encoder_context->brc.num_iframes_in_gop = 1; // Always 1
@@ -326,7 +341,7 @@
intel_encoder_check_brc_h264_sequence_parameter(VADriverContextP ctx,
if (seq_param->ip_period == 0)
goto error;
- encoder_context->brc.gop_size = (unsigned int)(framerate_per_100s /
100.0 + 0.5); // fake
+ encoder_context->brc.gop_size = (framerate.num + framerate.den
+ - 1) / framerate.den; // fake
num_pframes_in_gop = (encoder_context->brc.gop_size +
seq_param->ip_period - 1) / seq_param->ip_period - 1;
} else if (seq_param->intra_period == 1) { // E.g. IDRIII...
@@ -347,11 +362,12 @@
intel_encoder_check_brc_h264_sequence_parameter(VADriverContextP ctx,
if (num_pframes_in_gop != encoder_context->brc.num_pframes_in_gop
||
num_bframes_in_gop != encoder_context->brc.num_bframes_in_gop
||
bits_per_second != encoder_context-
brc.bits_per_second[encoder_context->layer.num_layers - 1] ||
- framerate_per_100s != encoder_context-
brc.framerate_per_100s[encoder_context->layer.num_layers - 1]) {
+ framerate.num != encoder_context->brc.framerate[encoder_context-
layer.num_layers - 1].num ||
+ framerate.den !=
+ encoder_context->brc.framerate[encoder_context->layer.num_layers -
+ 1].den) {
encoder_context->brc.num_pframes_in_gop = num_pframes_in_gop;
encoder_context->brc.num_bframes_in_gop = num_bframes_in_gop;
encoder_context->brc.bits_per_second[encoder_context-
layer.num_layers - 1] = bits_per_second;
- encoder_context->brc.framerate_per_100s[encoder_context-
layer.num_layers - 1] = framerate_per_100s;
+
+ encoder_context->brc.framerate[encoder_context->layer.num_layers - 1]
+ = framerate;
encoder_context->brc.need_reset = 1;
}
@@ -392,8 +408,9 @@
intel_encoder_check_brc_vp8_sequence_parameter(VADriverContextP ctx,
num_pframes_in_gop = encoder_context->brc.gop_size - 1;
bits_per_second = seq_param->bits_per_second; // for the highest
layer
- if (!encoder_context->brc.framerate_per_100s[encoder_context-
layer.num_layers - 1]) {
- encoder_context->brc.framerate_per_100s[encoder_context-
layer.num_layers - 1] = 3000; // for the highest layer
+ if (!encoder_context->brc.framerate[encoder_context->layer.num_layers
- 1].num) {
+ // for the highest layer
+
+ encoder_context->brc.framerate[encoder_context->layer.num_layers - 1]
+ = (struct intel_fraction) { 30, 1 };
encoder_context->brc.need_reset = 1;
}
@@ -480,7 +497,7 @@
intel_encoder_check_framerate_parameter(VADriverContextP ctx,
struct intel_encoder_context *encoder_context,
VAEncMiscParameterFrameRate *misc) {
- int framerate_per_100s;
+ struct intel_fraction framerate;
int temporal_id = 0;
intel_encoder_check_framerate_parameter(VADriverContextP ctx,
return;
if (misc->framerate & 0xffff0000)
- framerate_per_100s = (misc->framerate & 0xffff) * 100 / ((misc-
framerate >> 16) & 0xffff);
+ framerate = (struct intel_fraction) { misc->framerate & 0xffff,
+ misc->framerate >> 16 & 0xffff };
else
- framerate_per_100s = misc->framerate * 100;
+ framerate = (struct intel_fraction) { misc->framerate, 1 };
+ framerate = reduce_fraction(framerate);
- if (encoder_context->brc.framerate_per_100s[temporal_id] !=
framerate_per_100s) {
- encoder_context->brc.framerate_per_100s[temporal_id] =
framerate_per_100s;
+ if (encoder_context->brc.framerate[temporal_id].num != framerate.num
||
+ encoder_context->brc.framerate[temporal_id].den != framerate.den) {
+ encoder_context->brc.framerate[temporal_id] = framerate;
encoder_context->brc.need_reset = 1;
}
}
diff --git a/src/i965_encoder.h b/src/i965_encoder.h index 0b636d6..7016975
100644
--- a/src/i965_encoder.h
+++ b/src/i965_encoder.h
@@ -55,6 +55,12 @@ struct intel_roi
char value;
};
+struct intel_fraction
+{
+ unsigned int num;
+ unsigned int den;
+};
+
struct intel_encoder_context
{
struct hw_context base;
@@ -80,7 +86,7 @@ struct intel_encoder_context
unsigned short num_pframes_in_gop;
unsigned short num_bframes_in_gop;
unsigned int bits_per_second[MAX_TEMPORAL_LAYERS];
- unsigned int framerate_per_100s[MAX_TEMPORAL_LAYERS];
+ struct intel_fraction framerate[MAX_TEMPORAL_LAYERS];
unsigned int mb_rate_control[MAX_TEMPORAL_LAYERS];
unsigned int target_percentage[MAX_TEMPORAL_LAYERS];
unsigned int hrd_buffer_size;
--
2.11.0
_______________________________________________
Libva mailing list
https://lists.freedesktop.org/mailman/listinfo/libva
Kelley, Sean V
2016-12-27 17:23:42 UTC
Permalink
On 12/22/16, 5:08 PM, "Libva on behalf of Mark Thompson" <libva-***@lists.freedesktop.org on behalf of ***@jkqxz.net> wrote:

Update references in both H.264 encoders (gen6_mfc and gen9_vdenc).


Lgtm,

Sean

Signed-off-by: Mark Thompson <***@jkqxz.net>
---
Changes for the series:
* Derive numerator and denominator from the correct parts of the framerate parameter (see also earlier patch fixing the comment in va.h).
* Make VP8 HRD buffer size derivation the same as other codecs.
* Make the VP9 rate control setup behave more consistently (use window size if needed for VBR, always use HRD parameters if present).
* Fix warnings.

Thanks,

- Mark


src/gen6_mfc_common.c | 11 +++++++----
src/gen9_vdenc.c | 28 ++++++++++++++++------------
src/gen9_vdenc.h | 2 +-
src/i965_encoder.c | 49 ++++++++++++++++++++++++++++++++++---------------
src/i965_encoder.h | 8 +++++++-
5 files changed, 65 insertions(+), 33 deletions(-)

diff --git a/src/gen6_mfc_common.c b/src/gen6_mfc_common.c
index 68d030e..15c0637 100644
--- a/src/gen6_mfc_common.c
+++ b/src/gen6_mfc_common.c
@@ -119,16 +119,19 @@ static void intel_mfc_brc_init(struct encode_state *encode_state,

if (i == 0) {
bitrate = encoder_context->brc.bits_per_second[0];
- framerate = (double)encoder_context->brc.framerate_per_100s[0] / 100.0;
+ framerate = (double)encoder_context->brc.framerate[0].num / (double)encoder_context->brc.framerate[0].den;
} else {
bitrate = (encoder_context->brc.bits_per_second[i] - encoder_context->brc.bits_per_second[i - 1]);
- framerate = (double)(encoder_context->brc.framerate_per_100s[i] - encoder_context->brc.framerate_per_100s[i - 1]) / 100.0;
+ framerate = ((double)encoder_context->brc.framerate[i].num / (double)encoder_context->brc.framerate[i].den) -
+ ((double)encoder_context->brc.framerate[i - 1].num / (double)encoder_context->brc.framerate[i - 1].den);
}

if (i == encoder_context->layer.num_layers - 1)
factor = 1.0;
- else
- factor = (double)encoder_context->brc.framerate_per_100s[i] / encoder_context->brc.framerate_per_100s[encoder_context->layer.num_layers - 1];
+ else {
+ factor = ((double)encoder_context->brc.framerate[i].num / (double)encoder_context->brc.framerate[i].den) /
+ ((double)encoder_context->brc.framerate[i - 1].num / (double)encoder_context->brc.framerate[i - 1].den);
+ }

hrd_factor = (double)bitrate / encoder_context->brc.bits_per_second[encoder_context->layer.num_layers - 1];

diff --git a/src/gen9_vdenc.c b/src/gen9_vdenc.c
index 8009b31..691faec 100644
--- a/src/gen9_vdenc.c
+++ b/src/gen9_vdenc.c
@@ -851,7 +851,7 @@ gen9_vdenc_update_misc_parameters(VADriverContextP ctx,
if (vdenc_context->internal_rate_mode != I965_BRC_CQP &&
encoder_context->brc.need_reset) {
/* So far, vdenc doesn't support temporal layer */
- vdenc_context->frames_per_100s = encoder_context->brc.framerate_per_100s[0];
+ vdenc_context->framerate = encoder_context->brc.framerate[0];

vdenc_context->vbv_buffer_size_in_bit = encoder_context->brc.hrd_buffer_size;
vdenc_context->init_vbv_buffer_fullness_in_bit = encoder_context->brc.hrd_initial_buffer_fullness;
@@ -927,7 +927,8 @@ gen9_vdenc_update_parameters(VADriverContextP ctx,
!vdenc_context->vbv_buffer_size_in_bit ||
!vdenc_context->max_bit_rate ||
!vdenc_context->target_bit_rate ||
- !vdenc_context->frames_per_100s))
+ !vdenc_context->framerate.num ||
+ !vdenc_context->framerate.den))
vdenc_context->brc_enabled = 0;

if (!vdenc_context->brc_enabled) {
@@ -1565,7 +1566,8 @@ gen9_vdenc_get_profile_level_max_frame(VADriverContextP ctx,
tmpf = max_mbps / 172.0;

max_byte_per_frame0 = (uint64_t)(tmpf * bits_per_mb);
- max_byte_per_frame1 = (uint64_t)(((double)max_mbps * 100) / vdenc_context->frames_per_100s *bits_per_mb);
+ max_byte_per_frame1 = (uint64_t)(((double)max_mbps * vdenc_context->framerate.den) /
+ (double)vdenc_context->framerate.num * bits_per_mb);

/* TODO: check VAEncMiscParameterTypeMaxFrameSize */
ret = (unsigned int)MIN(max_byte_per_frame0, max_byte_per_frame1);
@@ -1586,12 +1588,12 @@ gen9_vdenc_calculate_initial_qp(VADriverContextP ctx,

frame_size = (vdenc_context->frame_width * vdenc_context->frame_height * 3 / 2);
qp = (int)(1.0 / 1.2 * pow(10.0,
- (log10(frame_size * 2.0 / 3.0 * ((float)vdenc_context->frames_per_100s) /
- ((float)(vdenc_context->target_bit_rate * 1000) * 100)) - x0) *
+ (log10(frame_size * 2.0 / 3.0 * vdenc_context->framerate.num /
+ ((double)vdenc_context->target_bit_rate * 1000.0 * vdenc_context->framerate.den)) - x0) *
(y1 - y0) / (x1 - x0) + y0) + 0.5);
qp += 2;
- delat_qp = (int)(9 - (vdenc_context->vbv_buffer_size_in_bit * ((float)vdenc_context->frames_per_100s) /
- ((float)(vdenc_context->target_bit_rate * 1000) * 100)));
+ delat_qp = (int)(9 - (vdenc_context->vbv_buffer_size_in_bit * ((double)vdenc_context->framerate.num) /
+ ((double)vdenc_context->target_bit_rate * 1000.0 * vdenc_context->framerate.den)));
if (delat_qp > 0)
qp += delat_qp;

@@ -1615,7 +1617,8 @@ gen9_vdenc_update_huc_brc_init_dmem(VADriverContextP ctx,
double input_bits_per_frame, bps_ratio;
int i;

- vdenc_context->brc_init_reset_input_bits_per_frame = ((double)(vdenc_context->max_bit_rate * 1000) * 100) / vdenc_context->frames_per_100s;
+ vdenc_context->brc_init_reset_input_bits_per_frame =
+ ((double)vdenc_context->max_bit_rate * 1000.0 * vdenc_context->framerate.den) / vdenc_context->framerate.num;
vdenc_context->brc_init_current_target_buf_full_in_bits = vdenc_context->brc_init_reset_input_bits_per_frame;
vdenc_context->brc_target_size = vdenc_context->init_vbv_buffer_fullness_in_bit;

@@ -1645,8 +1648,8 @@ gen9_vdenc_update_huc_brc_init_dmem(VADriverContextP ctx,
else if (vdenc_context->internal_rate_mode == I965_BRC_VBR)
dmem->brc_flag |= 0x20;

- dmem->frame_rate_m = vdenc_context->frames_per_100s;
- dmem->frame_rate_d = 100;
+ dmem->frame_rate_m = vdenc_context->framerate.num;
+ dmem->frame_rate_d = vdenc_context->framerate.den;

dmem->profile_level_max_frame = gen9_vdenc_get_profile_level_max_frame(ctx, encoder_context, seq_param->level_idc);

@@ -1656,8 +1659,9 @@ gen9_vdenc_update_huc_brc_init_dmem(VADriverContextP ctx,
dmem->min_qp = 10;
dmem->max_qp = 51;

- input_bits_per_frame = ((double)vdenc_context->max_bit_rate * 1000 * 100) / vdenc_context->frames_per_100s;
- bps_ratio = input_bits_per_frame / ((double)vdenc_context->vbv_buffer_size_in_bit * 100 / vdenc_context->frames_per_100s);
+ input_bits_per_frame = ((double)vdenc_context->max_bit_rate * 1000.0 * vdenc_context->framerate.den) / vdenc_context->framerate.num;
+ bps_ratio = input_bits_per_frame /
+ ((double)vdenc_context->vbv_buffer_size_in_bit * vdenc_context->framerate.den / vdenc_context->framerate.num);

if (bps_ratio < 0.1)
bps_ratio = 0.1;
diff --git a/src/gen9_vdenc.h b/src/gen9_vdenc.h
index e790497..41e4362 100644
--- a/src/gen9_vdenc.h
+++ b/src/gen9_vdenc.h
@@ -741,7 +741,7 @@ struct gen9_vdenc_context
uint32_t min_bit_rate; /* in kbps */
uint64_t init_vbv_buffer_fullness_in_bit;
uint64_t vbv_buffer_size_in_bit;
- uint32_t frames_per_100s;
+ struct intel_fraction framerate;
uint32_t gop_size;
uint32_t ref_dist;
uint32_t brc_target_size;
diff --git a/src/i965_encoder.c b/src/i965_encoder.c
index d874322..3aaac34 100644
--- a/src/i965_encoder.c
+++ b/src/i965_encoder.c
@@ -42,6 +42,17 @@

#include "i965_post_processing.h"

+static struct intel_fraction
+reduce_fraction(struct intel_fraction f)
+{
+ unsigned int a = f.num, b = f.den, c;
+ while ((c = a % b)) {
+ a = b;
+ b = c;
+ }
+ return (struct intel_fraction) { f.num / b, f.den / b };
+}
+
static VAStatus
clear_border(struct object_surface *obj_surface)
{
@@ -306,8 +317,9 @@ intel_encoder_check_brc_h264_sequence_parameter(VADriverContextP ctx,
struct intel_encoder_context *encoder_context)
{
VAEncSequenceParameterBufferH264 *seq_param = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
+ struct intel_fraction framerate;
+ unsigned int bits_per_second;
unsigned short num_pframes_in_gop, num_bframes_in_gop;
- unsigned int bits_per_second, framerate_per_100s;

if (!encoder_context->is_new_sequence)
return VA_STATUS_SUCCESS;
@@ -315,10 +327,13 @@ intel_encoder_check_brc_h264_sequence_parameter(VADriverContextP ctx,
assert(seq_param);
bits_per_second = seq_param->bits_per_second; // for the highest layer

- if (!seq_param->num_units_in_tick || !seq_param->time_scale)
- framerate_per_100s = 3000;
- else
- framerate_per_100s = seq_param->time_scale * 100 / (2 * seq_param->num_units_in_tick); // for the highest layer
+ if (!seq_param->num_units_in_tick || !seq_param->time_scale) {
+ framerate = (struct intel_fraction) { 30, 1 };
+ } else {
+ // for the highest layer
+ framerate = (struct intel_fraction) { seq_param->time_scale, 2 * seq_param->num_units_in_tick };
+ }
+ framerate = reduce_fraction(framerate);

encoder_context->brc.num_iframes_in_gop = 1; // Always 1

@@ -326,7 +341,7 @@ intel_encoder_check_brc_h264_sequence_parameter(VADriverContextP ctx,
if (seq_param->ip_period == 0)
goto error;

- encoder_context->brc.gop_size = (unsigned int)(framerate_per_100s / 100.0 + 0.5); // fake
+ encoder_context->brc.gop_size = (framerate.num + framerate.den - 1) / framerate.den; // fake
num_pframes_in_gop = (encoder_context->brc.gop_size +
seq_param->ip_period - 1) / seq_param->ip_period - 1;
} else if (seq_param->intra_period == 1) { // E.g. IDRIII...
@@ -347,11 +362,12 @@ intel_encoder_check_brc_h264_sequence_parameter(VADriverContextP ctx,
if (num_pframes_in_gop != encoder_context->brc.num_pframes_in_gop ||
num_bframes_in_gop != encoder_context->brc.num_bframes_in_gop ||
bits_per_second != encoder_context->brc.bits_per_second[encoder_context->layer.num_layers - 1] ||
- framerate_per_100s != encoder_context->brc.framerate_per_100s[encoder_context->layer.num_layers - 1]) {
+ framerate.num != encoder_context->brc.framerate[encoder_context->layer.num_layers - 1].num ||
+ framerate.den != encoder_context->brc.framerate[encoder_context->layer.num_layers - 1].den) {
encoder_context->brc.num_pframes_in_gop = num_pframes_in_gop;
encoder_context->brc.num_bframes_in_gop = num_bframes_in_gop;
encoder_context->brc.bits_per_second[encoder_context->layer.num_layers - 1] = bits_per_second;
- encoder_context->brc.framerate_per_100s[encoder_context->layer.num_layers - 1] = framerate_per_100s;
+ encoder_context->brc.framerate[encoder_context->layer.num_layers - 1] = framerate;
encoder_context->brc.need_reset = 1;
}

@@ -392,8 +408,9 @@ intel_encoder_check_brc_vp8_sequence_parameter(VADriverContextP ctx,
num_pframes_in_gop = encoder_context->brc.gop_size - 1;
bits_per_second = seq_param->bits_per_second; // for the highest layer

- if (!encoder_context->brc.framerate_per_100s[encoder_context->layer.num_layers - 1]) {
- encoder_context->brc.framerate_per_100s[encoder_context->layer.num_layers - 1] = 3000; // for the highest layer
+ if (!encoder_context->brc.framerate[encoder_context->layer.num_layers - 1].num) {
+ // for the highest layer
+ encoder_context->brc.framerate[encoder_context->layer.num_layers - 1] = (struct intel_fraction) { 30, 1 };
encoder_context->brc.need_reset = 1;
}

@@ -480,7 +497,7 @@ intel_encoder_check_framerate_parameter(VADriverContextP ctx,
struct intel_encoder_context *encoder_context,
VAEncMiscParameterFrameRate *misc)
{
- int framerate_per_100s;
+ struct intel_fraction framerate;
int temporal_id = 0;

if (encoder_context->layer.num_layers >= 2)
@@ -490,12 +507,14 @@ intel_encoder_check_framerate_parameter(VADriverContextP ctx,
return;

if (misc->framerate & 0xffff0000)
- framerate_per_100s = (misc->framerate & 0xffff) * 100 / ((misc->framerate >> 16) & 0xffff);
+ framerate = (struct intel_fraction) { misc->framerate & 0xffff, misc->framerate >> 16 & 0xffff };
else
- framerate_per_100s = misc->framerate * 100;
+ framerate = (struct intel_fraction) { misc->framerate, 1 };
+ framerate = reduce_fraction(framerate);

- if (encoder_context->brc.framerate_per_100s[temporal_id] != framerate_per_100s) {
- encoder_context->brc.framerate_per_100s[temporal_id] = framerate_per_100s;
+ if (encoder_context->brc.framerate[temporal_id].num != framerate.num ||
+ encoder_context->brc.framerate[temporal_id].den != framerate.den) {
+ encoder_context->brc.framerate[temporal_id] = framerate;
encoder_context->brc.need_reset = 1;
}
}
diff --git a/src/i965_encoder.h b/src/i965_encoder.h
index 0b636d6..7016975 100644
--- a/src/i965_encoder.h
+++ b/src/i965_encoder.h
@@ -55,6 +55,12 @@ struct intel_roi
char value;
};

+struct intel_fraction
+{
+ unsigned int num;
+ unsigned int den;
+};
+
struct intel_encoder_context
{
struct hw_context base;
@@ -80,7 +86,7 @@ struct intel_encoder_context
unsigned short num_pframes_in_gop;
unsigned short num_bframes_in_gop;
unsigned int bits_per_second[MAX_TEMPORAL_LAYERS];
- unsigned int framerate_per_100s[MAX_TEMPORAL_LAYERS];
+ struct intel_fraction framerate[MAX_TEMPORAL_LAYERS];
unsigned int mb_rate_control[MAX_TEMPORAL_LAYERS];
unsigned int target_percentage[MAX_TEMPORAL_LAYERS];
unsigned int hrd_buffer_size;
--
2.11.0

_______________________________________________
Libva mailing list
***@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libva

Loading...