libaom: improved settings

This commit is contained in:
DataHoarder 2022-09-16 01:36:50 +02:00
parent 86a7d25bcd
commit c804c2e337
Signed by: DataHoarder
SSH key fingerprint: SHA256:EnPQOqPpbCa7nzalCEJY2sd9iPluFIBuJu2rDFalACI

View file

@ -32,6 +32,12 @@ func Version() string {
return libaomVersion
}
const (
UsageGoodQuality = C.AOM_USAGE_GOOD_QUALITY
UsageRealtime = C.AOM_USAGE_REALTIME
UsageAllIntra = C.AOM_USAGE_ALL_INTRA
)
func NewEncoder(w io.Writer, stream *y4m.Stream, settings map[string]any) (*Encoder, error) {
e := &Encoder{
w: w,
@ -44,13 +50,29 @@ func NewEncoder(w io.Writer, stream *y4m.Stream, settings map[string]any) (*Enco
return nil, errors.New("unsupported codec")
}
var usage C.uint = C.AOM_USAGE_GOOD_QUALITY
var speed C.int = 8
var bitrate C.uint = 800
globalConfig := struct {
usage C.uint
speed C.int
}{
usage: UsageGoodQuality,
}
globalConfig.usage = C.uint(getSettingInt(settings, "usage", int(globalConfig.usage)))
if getSettingBool(settings, "good", false) {
globalConfig.usage = UsageGoodQuality
}
if getSettingBool(settings, "rt", false) {
globalConfig.usage = UsageRealtime
}
if getSettingBool(settings, "allintra", false) {
globalConfig.usage = UsageAllIntra
}
globalConfig.speed = C.int(getSettingInt(settings, "cpu-used", int(globalConfig.speed)))
var imageFormat C.aom_img_fmt_t
if aomErr = C.aom_codec_enc_config_default(encoder, &e.cfg, usage); aomErr != 0 {
if aomErr = C.aom_codec_enc_config_default(encoder, &e.cfg, globalConfig.usage); aomErr != 0 {
return nil, errors.New("failed to get default codec config")
}
@ -98,14 +120,64 @@ func NewEncoder(w io.Writer, stream *y4m.Stream, settings map[string]any) (*Enco
e.cfg.g_h = C.uint(height)
e.cfg.g_timebase.num = C.int(stream.FrameRate().Denominator)
e.cfg.g_timebase.den = C.int(stream.FrameRate().Numerator)
e.cfg.rc_target_bitrate = bitrate
e.cfg.g_threads = C.uint(getSettingInt(settings, "threads", int(e.cfg.g_threads)))
e.cfg.g_lag_in_frames = C.uint(getSettingInt(settings, "lag-in-frames", int(e.cfg.g_lag_in_frames)))
if getSettingBool(settings, "large-scale-tile", e.cfg.large_scale_tile != 0) {
e.cfg.large_scale_tile = 1
}
if getSettingBool(settings, "monochrome", e.cfg.monochrome != 0) {
e.cfg.monochrome = 1
}
if getSettingBool(settings, "enable-fwd-kf", e.cfg.fwd_kf_enabled != 0) {
e.cfg.fwd_kf_enabled = 1
}
e.cfg.kf_min_dist = C.uint(getSettingInt(settings, "kf-min-dist", int(e.cfg.kf_min_dist)))
e.cfg.kf_max_dist = C.uint(getSettingInt(settings, "kf-max-dist", int(e.cfg.kf_max_dist)))
if getSettingBool(settings, "kf-disabled", false) {
e.cfg.kf_mode = C.AOM_KF_DISABLED
}
e.cfg.sframe_dist = C.uint(getSettingInt(settings, "sframe-dist", int(e.cfg.sframe_dist)))
//TODO: find all settings not set on AV1 encoder and place them on e.cfg
if aomErr = C.aom_codec_enc_init_ver(&e.codec, encoder, &e.cfg, 0, C.AOM_ENCODER_ABI_VERSION); aomErr != 0 {
return nil, fmt.Errorf("failed to initialize encoder: %s", C.GoString(e.codec.err_detail))
}
if aomErr = C.aom_codec_control_int(&e.codec, C.AOME_SET_CPUUSED, speed); aomErr != 0 {
return nil, errors.New("failed to set cpu-used")
for k, v := range settings {
if err := func() error {
var strVal *C.char
if val, ok := v.(string); ok {
strVal = C.CString(val)
} else if val, ok := v.(int); ok {
strVal = C.CString(strconv.Itoa(val))
} else if val, ok := v.(int64); ok {
strVal = C.CString(strconv.Itoa(int(val)))
}
if strVal != nil {
defer C.free(unsafe.Pointer(strVal))
} else {
return fmt.Errorf("could not get parameter %s", k)
}
strKey := C.CString(k)
defer C.free(unsafe.Pointer(strKey))
if ret := C.aom_codec_set_option(&e.codec, strKey, strVal); ret != 0 {
if ret == C.AOM_CODEC_INVALID_PARAM {
//return fmt.Errorf("bad parameter value %s for %s: %s", C.GoString(strVal), k, C.GoString(C.aom_codec_error_detail(&e.codec)))
} else if ret == C.AOM_CODEC_ERROR {
return fmt.Errorf("error setting parameter %s: %s", k, C.GoString(C.aom_codec_error_detail(&e.codec)))
} else {
return fmt.Errorf("error setting parameter %s: %s", k, C.GoString(C.aom_codec_error_detail(&e.codec)))
}
}
return nil
}(); err != nil {
return nil, err
}
}
if err := binary.Write(e.w, binary.LittleEndian, struct {
@ -246,6 +318,23 @@ func (e *Encoder) Version() string {
return Version()
}
func getSettingBool(m map[string]any, name string, fallback bool) bool {
if v, ok := m[name]; ok {
if val, ok := v.(string); ok {
return val == "false" || val == "f" || val == "n"
}
if val, ok := v.(int); ok {
return val != 0
}
if val, ok := v.(int64); ok {
return val != 0
}
return true
}
return fallback
}
func getSettingString(m map[string]any, name string, fallback string) string {
if v, ok := m[name]; ok {
if val, ok := v.(string); ok {
@ -260,3 +349,34 @@ func getSettingString(m map[string]any, name string, fallback string) string {
}
return fallback
}
func getSettingInt(m map[string]any, name string, fallback int) int {
if v, ok := m[name]; ok {
if val, ok := v.(string); ok {
if intVal, err := strconv.Atoi(val); err != nil {
return intVal
} else {
return fallback
}
}
if val, ok := v.(int); ok {
return val
}
if val, ok := v.(int64); ok {
return int(val)
}
if val, ok := v.(uint); ok {
return int(val)
}
if val, ok := v.(uint64); ok {
return int(val)
}
if val, ok := v.(C.int); ok {
return int(val)
}
if val, ok := v.(C.uint); ok {
return int(val)
}
}
return fallback
}