diff --git a/examples/codecparam/main.go b/examples/codecparam/main.go index 98ce75e..dfe40f0 100644 --- a/examples/codecparam/main.go +++ b/examples/codecparam/main.go @@ -67,7 +67,7 @@ func main() { // This example is using libva's hardware accelerated codec. // Set encoder parameters to prohibit bitrate overshoot as possible. cp.RateControlMode = vaapi.RateControlVBR - cp.RateControl.BitsPerSecond = 400000 + cp.BitRate = 400000 cp.RateControl.TargetPercentage = 95 c.VideoEncoderBuilders = []codec.VideoEncoderBuilder{&cp} }, diff --git a/pkg/codec/vaapi/params.go b/pkg/codec/vaapi/params.go index d8425a8..9659f98 100644 --- a/pkg/codec/vaapi/params.go +++ b/pkg/codec/vaapi/params.go @@ -27,13 +27,16 @@ type SequenceParamVP8 struct { // NewVP8Param returns default parameters of VP8 codec. func NewVP8Param() (ParamVP8, error) { return ParamVP8{ + BaseParams: codec.BaseParams{ + BitRate: 320000, + KeyFrameInterval: 30, + }, Sequence: SequenceParamVP8{ ClampQindexLow: 9, ClampQindexHigh: 127, }, RateControlMode: RateControlVBR, RateControl: RateControlParam{ - BitsPerSecond: 400000, TargetPercentage: 80, WindowSize: 1500, InitialQP: 60, @@ -62,10 +65,11 @@ type ParamVP9 struct { // RateControlParam represents VAEncMiscParameterRateControl. type RateControlParam struct { - // BitsPerSecond is a maximum bit-rate. - // This parameter overwrites prop.Codec.BitRate. - BitsPerSecond uint - // TargetPercentage is a target bit-rate relative to BitsPerSecond. + // bitsPerSecond is a maximum bit-rate. + // This parameter is calculated from BaseParams.BitRate. + bitsPerSecond uint + // TargetPercentage is a target bit-rate relative to the maximum bit-rate. + // BaseParams.BitRate / (TargetPercentage * 0.01) will be the maximum bit-rate. TargetPercentage uint // WindowSize is a rate control window size in milliseconds. WindowSize uint @@ -96,9 +100,12 @@ const ( // NewVP9Param returns default parameters of VP9 codec. func NewVP9Param() (ParamVP9, error) { return ParamVP9{ + BaseParams: codec.BaseParams{ + BitRate: 320000, + KeyFrameInterval: 30, + }, RateControlMode: RateControlVBR, RateControl: RateControlParam{ - BitsPerSecond: 400000, TargetPercentage: 80, WindowSize: 1500, InitialQP: 60, diff --git a/pkg/codec/vaapi/vp8.go b/pkg/codec/vaapi/vp8.go index 76d4c9b..b82cf0c 100644 --- a/pkg/codec/vaapi/vp8.go +++ b/pkg/codec/vaapi/vp8.go @@ -106,9 +106,8 @@ func newVP8Encoder(r video.Reader, p prop.Media, params ParamVP8) (io.ReadCloser p.FrameRate = 30 } - if params.RateControl.BitsPerSecond == 0 { - params.RateControl.BitsPerSecond = uint(float32(params.BitRate) * 1.5) - } + params.RateControl.bitsPerSecond = + uint(float32(params.BitRate) / (0.01 * float32(params.RateControl.TargetPercentage))) // Parameters are from https://github.com/intel/libva-utils/blob/master/encode/vp8enc.c e := &encoderVP8{ @@ -119,7 +118,7 @@ func newVP8Encoder(r video.Reader, p prop.Media, params ParamVP8) (io.ReadCloser seqParam: C.VAEncSequenceParameterBufferVP8{ frame_width: C.uint(p.Width), frame_height: C.uint(p.Height), - bits_per_second: C.uint(params.RateControl.BitsPerSecond), + bits_per_second: C.uint(params.RateControl.bitsPerSecond), intra_period: C.uint(params.KeyFrameInterval), kf_max_dist: C.uint(params.KeyFrameInterval), reference_frames: [4]C.VASurfaceID{ @@ -153,9 +152,9 @@ func newVP8Encoder(r video.Reader, p prop.Media, params ParamVP8) (io.ReadCloser _type: C.VAEncMiscParameterTypeHRD, }, data: C.VAEncMiscParameterHRD{ - initial_buffer_fullness: C.uint(params.RateControl.BitsPerSecond * + initial_buffer_fullness: C.uint(params.RateControl.bitsPerSecond * params.RateControl.WindowSize / 2000), - buffer_size: C.uint(params.RateControl.BitsPerSecond * + buffer_size: C.uint(params.RateControl.bitsPerSecond * params.RateControl.WindowSize / 1000), }, }, @@ -176,7 +175,7 @@ func newVP8Encoder(r video.Reader, p prop.Media, params ParamVP8) (io.ReadCloser initial_qp: C.uint(params.RateControl.InitialQP), min_qp: C.uint(params.RateControl.MinQP), max_qp: C.uint(params.RateControl.MaxQP), - bits_per_second: C.uint(params.RateControl.BitsPerSecond), + bits_per_second: C.uint(params.RateControl.bitsPerSecond), target_percentage: C.uint(params.RateControl.TargetPercentage), }, }, diff --git a/pkg/codec/vaapi/vp9.go b/pkg/codec/vaapi/vp9.go index 1362bd3..88707f4 100644 --- a/pkg/codec/vaapi/vp9.go +++ b/pkg/codec/vaapi/vp9.go @@ -110,9 +110,8 @@ func newVP9Encoder(r video.Reader, p prop.Media, params ParamVP9) (io.ReadCloser p.FrameRate = 30 } - if params.RateControl.BitsPerSecond == 0 { - params.RateControl.BitsPerSecond = uint(float32(params.BitRate) * 1.5) - } + params.RateControl.bitsPerSecond = + uint(float32(params.BitRate) / (0.01 * float32(params.RateControl.TargetPercentage))) // Parameters are from https://github.com/intel/libva-utils/blob/master/encode/vp9enc.c e := &encoderVP9{ @@ -123,7 +122,7 @@ func newVP9Encoder(r video.Reader, p prop.Media, params ParamVP9) (io.ReadCloser seqParam: C.VAEncSequenceParameterBufferVP9{ max_frame_width: 8192, max_frame_height: 8192, - bits_per_second: C.uint(params.RateControl.BitsPerSecond), + bits_per_second: C.uint(params.RateControl.bitsPerSecond), intra_period: C.uint(params.KeyFrameInterval), kf_min_dist: 1, kf_max_dist: C.uint(params.KeyFrameInterval), @@ -161,9 +160,9 @@ func newVP9Encoder(r video.Reader, p prop.Media, params ParamVP9) (io.ReadCloser _type: C.VAEncMiscParameterTypeHRD, }, data: C.VAEncMiscParameterHRD{ - initial_buffer_fullness: C.uint(params.RateControl.BitsPerSecond * + initial_buffer_fullness: C.uint(params.RateControl.bitsPerSecond * params.RateControl.WindowSize / 2000), - buffer_size: C.uint(params.RateControl.BitsPerSecond * + buffer_size: C.uint(params.RateControl.bitsPerSecond * params.RateControl.WindowSize / 1000), }, }, @@ -184,7 +183,7 @@ func newVP9Encoder(r video.Reader, p prop.Media, params ParamVP9) (io.ReadCloser initial_qp: C.uint(params.RateControl.InitialQP), min_qp: C.uint(params.RateControl.MinQP), max_qp: C.uint(params.RateControl.MaxQP), - bits_per_second: C.uint(params.RateControl.BitsPerSecond), + bits_per_second: C.uint(params.RateControl.bitsPerSecond), target_percentage: C.uint(params.RateControl.TargetPercentage), }, },