Properly close dav1d decoder, clone settings map on aom
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
DataHoarder 2023-10-26 07:07:23 +02:00
parent b08b662354
commit c54e961aee
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
3 changed files with 100 additions and 24 deletions

View file

@ -8,7 +8,7 @@
void set_threading(Dav1dSettings* s, int threads) {
#if DAV1D_VERSION_AT_LEAST(6,0)
s->n_threads = threads;
#else
s->n_tile_threads = MIN(floor(sqrt(threads)), DAV1D_MAX_TILE_THREADS);
s->n_frame_threads = MIN(ceil(threads / s->n_tile_threads), DAV1D_MAX_FRAME_THREADS);

View file

@ -15,8 +15,10 @@ import (
"git.gammaspectra.live/S.O.N.G/Ignite/frame"
"git.gammaspectra.live/S.O.N.G/Ignite/utilities"
"git.gammaspectra.live/S.O.N.G/Ignite/utilities/ivfreader"
"golang.org/x/exp/constraints"
"io"
"runtime"
"strconv"
"sync"
"sync/atomic"
"unsafe"
@ -35,6 +37,8 @@ type Decoder struct {
picture C.Dav1dPicture
data C.Dav1dData
closer sync.Once
bufPool sync.Pool
}
@ -57,12 +61,20 @@ func NewDecoder(r io.Reader, settings map[string]any) (d *Decoder, err error) {
return nil, err
}
maxThreads := int(getSettingUnsigned[uint64](settings, "threads", 0))
if maxThreads == 0 {
maxThreads = runtime.NumCPU()
}
//TODO settings: apply_grain, output_invisible_frames, decode_frame_type, inloop_filters
C.dav1d_default_settings(&d.settings)
C.set_threading(&d.settings, C.int(runtime.NumCPU()))
C.set_threading(&d.settings, C.int(maxThreads))
if ret := C.dav1d_open(&d.ctx, &d.settings); ret != 0 {
return nil, fmt.Errorf("error %d", ret)
}
if d.firstFrame, err = d.Decode(); err != nil {
d.Close()
return nil, err
}
@ -146,11 +158,14 @@ func (d *Decoder) flushPicture() C.int {
}
func (d *Decoder) Close() {
if d.data.sz > 0 {
C.dav1d_data_unref(&d.data)
}
//TODO: close other context
d.closer.Do(func() {
if d.data.sz > 0 {
C.dav1d_data_unref(&d.data)
}
if d.ctx != nil {
C.dav1d_close(&d.ctx)
}
})
}
const (
@ -196,12 +211,8 @@ func (d *Decoder) pictureToFrame() (frame.Frame, error) {
}
properties.ColorSpace.BitDepth = byte(bitDepth)
properties.FullColorRange = false
if d.picture.seq_hdr.color_range == 1 {
//TODO check
properties.FullColorRange = true
}
//TODO check
properties.FullColorRange = d.picture.seq_hdr.color_range == 1
properties.ColorSpace.ChromaSamplePosition = color.ChromaSamplePositionUnspecified
if d.picture.seq_hdr.chr == C.DAV1D_CHR_UNKNOWN {
@ -316,3 +327,65 @@ func (d *Decoder) Decode() (frame.Frame, error) {
func (d *Decoder) Version() string {
return Version()
}
func getSettingUnsigned[T constraints.Unsigned](m map[string]any, name string, fallback T) T {
if v, ok := m[name]; ok {
if val, ok := v.(string); ok {
if intVal, err := strconv.ParseUint(val, 10, 0); err != nil {
delete(m, name)
return T(intVal)
} else {
return fallback
}
}
if val, ok := v.(int); ok {
return T(val)
}
if val, ok := v.(int64); ok {
return T(val)
}
if val, ok := v.(uint); ok {
return T(val)
}
if val, ok := v.(uint64); ok {
return T(val)
}
if val, ok := v.(C.int); ok {
return T(val)
}
if val, ok := v.(C.uint); ok {
return T(val)
}
if val, ok := v.(bool); ok {
if val {
return 1
} else {
return 0
}
}
}
return fallback
}
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
}
if val, ok := v.(uint); ok {
return val != 0
}
if val, ok := v.(uint64); ok {
return val != 0
}
return true
}
return fallback
}

View file

@ -14,6 +14,7 @@ import (
"git.gammaspectra.live/S.O.N.G/Ignite/utilities/obuwriter"
"golang.org/x/exp/constraints"
"io"
"maps"
"runtime"
"strconv"
"sync/atomic"
@ -45,6 +46,8 @@ const (
func NewEncoder(w io.Writer, properties frame.StreamProperties, settings map[string]any) (*Encoder, error) {
e := &Encoder{}
clonedSettings := maps.Clone(settings)
var aomErr C.aom_codec_err_t
encoder := C.aom_codec_av1_cx()
@ -52,15 +55,15 @@ func NewEncoder(w io.Writer, properties frame.StreamProperties, settings map[str
return nil, errors.New("unsupported codec")
}
e.cfg.g_usage = C.uint(getSettingUnsigned(settings, "usage", uint(UsageGoodQuality)))
e.cfg.g_usage = C.uint(getSettingUnsigned(clonedSettings, "usage", uint(UsageGoodQuality)))
if getSettingBool(settings, "good", false) {
if getSettingBool(clonedSettings, "good", false) {
e.cfg.g_usage = UsageGoodQuality
}
if getSettingBool(settings, "rt", false) {
if getSettingBool(clonedSettings, "rt", false) {
e.cfg.g_usage = UsageRealtime
}
if getSettingBool(settings, "allintra", false) {
if getSettingBool(clonedSettings, "allintra", false) {
e.cfg.g_usage = UsageAllIntra
}
@ -138,17 +141,17 @@ func NewEncoder(w io.Writer, properties frame.StreamProperties, settings map[str
// boolean settings
if getSettingBool(settings, "large-scale-tile", e.cfg.large_scale_tile != 0) {
if getSettingBool(clonedSettings, "large-scale-tile", e.cfg.large_scale_tile != 0) {
e.cfg.large_scale_tile = 1
}
if getSettingBool(settings, "monochrome", e.cfg.monochrome != 0) {
if getSettingBool(clonedSettings, "monochrome", e.cfg.monochrome != 0) {
e.cfg.monochrome = 1
}
if getSettingBool(settings, "enable-fwd-kf", e.cfg.fwd_kf_enabled != 0) {
if getSettingBool(clonedSettings, "enable-fwd-kf", e.cfg.fwd_kf_enabled != 0) {
e.cfg.fwd_kf_enabled = 1
}
if getSettingBool(settings, "kf-disabled", false) {
if getSettingBool(clonedSettings, "kf-disabled", false) {
e.cfg.kf_mode = C.AOM_KF_DISABLED
}
@ -198,12 +201,12 @@ func NewEncoder(w io.Writer, properties frame.StreamProperties, settings map[str
{&e.cfg.sframe_mode, "sframe-mode"},
} {
//todo: unset setting from map
*s.p = C.uint(getSettingUnsigned(settings, s.n, uint(*s.p)))
*s.p = C.uint(getSettingUnsigned(clonedSettings, s.n, uint(*s.p)))
}
// string/enum settings
endUsage := getSettingString(settings, "end-usage", "vbr")
endUsage := getSettingString(clonedSettings, "end-usage", "vbr")
switch endUsage {
case "vbr":
@ -234,7 +237,7 @@ func NewEncoder(w io.Writer, properties frame.StreamProperties, settings map[str
}
}
for k, v := range settings {
for k, v := range clonedSettings {
if err := func() error {
var strVal *C.char
if val, ok := v.(string); ok {