From 4724734870d86e2242e19619b5948f14b5b3220e Mon Sep 17 00:00:00 2001 From: Cacsjep Date: Sat, 27 Jan 2024 20:38:43 +0100 Subject: [PATCH] Review changes Reorder flags, and update them # Update Example Use renaming function to create sws context Clean up Use new framdata image funcs # Sws scale context New way to update the context Use sws_scale_frame instead of sws_scale Reordering funcs for get and set # Sws sclate context flag Add "Flag" for algo name # Update sws test --- examples/scaling/main.go | 58 ++++++---- flags.go | 64 +++++------ flags_test.go | 36 +++--- internal/cmd/flags/main.go | 4 +- software_scale_context.go | 194 ++++++++++++++++++++------------- software_scale_context_flag.go | 22 ++-- software_scale_context_test.go | 83 ++++++-------- 7 files changed, 249 insertions(+), 212 deletions(-) diff --git a/examples/scaling/main.go b/examples/scaling/main.go index ba4614a..f76045f 100644 --- a/examples/scaling/main.go +++ b/examples/scaling/main.go @@ -6,17 +6,23 @@ import ( "image/png" "log" "os" + "strings" "github.com/asticode/go-astiav" ) -func main() { +var ( + output = flag.String("o", "", "the png output path") + dstWidth = flag.Int("w", 50, "destination width") + dstHeight = flag.Int("h", 50, "destination height") +) - var ( - output = flag.String("o", "", "the png output path") - dstWidth = flag.Int("w", 50, "destination width") - dstHeight = flag.Int("h", 50, "destination height") - ) +func main() { + // Handle ffmpeg logs + astiav.SetLogLevel(astiav.LogLevelDebug) + astiav.SetLogCallback(func(l astiav.LogLevel, fmt, msg, parent string) { + log.Printf("ffmpeg log: %s (level: %d)\n", strings.TrimSpace(msg), l) + }) // Parse flags flag.Parse() @@ -51,30 +57,35 @@ func main() { dstFrame := astiav.AllocFrame() defer dstFrame.Free() - // Create software scale context flags - swscf := astiav.NewSoftwareScaleContextFlags(astiav.SoftwareScaleContextBilinear) - // Create software scale context - swsCtx := astiav.NewSoftwareScaleContext(srcFrame.Width(), srcFrame.Height(), srcFrame.PixelFormat(), *dstWidth, *dstHeight, astiav.PixelFormatRgba, swscf) - if swsCtx == nil { - log.Fatal("main: creating software scale context failed") + swsCtx, err := astiav.CreateSoftwareScaleContext( + srcFrame.Width(), + srcFrame.Height(), + srcFrame.PixelFormat(), + *dstWidth, + *dstHeight, + astiav.PixelFormatRgba, + astiav.NewSoftwareScaleContextFlags(astiav.SoftwareScaleContextFlagBilinear), + ) + if err != nil { + log.Fatal(fmt.Errorf("main: creating software scale context failed: %w"), err) } defer swsCtx.Free() - // Prepare destination frame (Width, Height and Buffer for correct scaling would be set) - if err = swsCtx.PrepareDestinationFrameForScaling(dstFrame); err != nil { - log.Fatal(fmt.Errorf("main: prepare destination image failed: %w", err)) - } - // Scale frame - if output_slice_height := swsCtx.ScaleFrame(srcFrame, dstFrame); output_slice_height != *dstHeight { - log.Fatal(fmt.Errorf("main: scale error, expected output slice height %d, but got %d", *dstHeight, output_slice_height)) + if err := swsCtx.ScaleFrame(srcFrame, dstFrame); err != nil { + log.Fatal(fmt.Errorf("main: scale frame failed: %w"), err) } - // Get image - img, err := dstFrame.Data().Image() + // Guess destination image format + img, err := dstFrame.Data().GuessImageFormat() if err != nil { - log.Fatal(fmt.Errorf("main: getting destination image failed: %w", err)) + log.Fatal(fmt.Errorf("main: guessing destination image format failed: %w", err)) + } + + // Copy frame data to destination image + if err = dstFrame.Data().ToImage(img); err != nil { + log.Fatal(fmt.Errorf("main: copying frame data to destination image failed: %w", err)) } // Encode to png @@ -82,5 +93,6 @@ func main() { log.Fatal(fmt.Errorf("main: encoding to png failed: %w", err)) } - log.Println("done") + // Success + log.Println("success") } diff --git a/flags.go b/flags.go index 339deec..6007100 100644 --- a/flags.go +++ b/flags.go @@ -145,45 +145,45 @@ func (fs FilterCommandFlags) Del(f FilterCommandFlag) FilterCommandFlags { func (fs FilterCommandFlags) Has(f FilterCommandFlag) bool { return astikit.BitFlags(fs).Has(uint64(f)) } -type FormatContextCtxFlags astikit.BitFlags +type FormatContextFlags astikit.BitFlags -func NewFormatContextCtxFlags(fs ...FormatContextCtxFlag) FormatContextCtxFlags { - o := FormatContextCtxFlags(0) +func NewFormatContextFlags(fs ...FormatContextFlag) FormatContextFlags { + o := FormatContextFlags(0) for _, f := range fs { o = o.Add(f) } return o } -func (fs FormatContextCtxFlags) Add(f FormatContextCtxFlag) FormatContextCtxFlags { - return FormatContextCtxFlags(astikit.BitFlags(fs).Add(uint64(f))) +func (fs FormatContextFlags) Add(f FormatContextFlag) FormatContextFlags { + return FormatContextFlags(astikit.BitFlags(fs).Add(uint64(f))) } -func (fs FormatContextCtxFlags) Del(f FormatContextCtxFlag) FormatContextCtxFlags { - return FormatContextCtxFlags(astikit.BitFlags(fs).Del(uint64(f))) +func (fs FormatContextFlags) Del(f FormatContextFlag) FormatContextFlags { + return FormatContextFlags(astikit.BitFlags(fs).Del(uint64(f))) } -func (fs FormatContextCtxFlags) Has(f FormatContextCtxFlag) bool { return astikit.BitFlags(fs).Has(uint64(f)) } +func (fs FormatContextFlags) Has(f FormatContextFlag) bool { return astikit.BitFlags(fs).Has(uint64(f)) } -type FormatContextFlags astikit.BitFlags +type FormatContextCtxFlags astikit.BitFlags -func NewFormatContextFlags(fs ...FormatContextFlag) FormatContextFlags { - o := FormatContextFlags(0) +func NewFormatContextCtxFlags(fs ...FormatContextCtxFlag) FormatContextCtxFlags { + o := FormatContextCtxFlags(0) for _, f := range fs { o = o.Add(f) } return o } -func (fs FormatContextFlags) Add(f FormatContextFlag) FormatContextFlags { - return FormatContextFlags(astikit.BitFlags(fs).Add(uint64(f))) +func (fs FormatContextCtxFlags) Add(f FormatContextCtxFlag) FormatContextCtxFlags { + return FormatContextCtxFlags(astikit.BitFlags(fs).Add(uint64(f))) } -func (fs FormatContextFlags) Del(f FormatContextFlag) FormatContextFlags { - return FormatContextFlags(astikit.BitFlags(fs).Del(uint64(f))) +func (fs FormatContextCtxFlags) Del(f FormatContextCtxFlag) FormatContextCtxFlags { + return FormatContextCtxFlags(astikit.BitFlags(fs).Del(uint64(f))) } -func (fs FormatContextFlags) Has(f FormatContextFlag) bool { return astikit.BitFlags(fs).Has(uint64(f)) } +func (fs FormatContextCtxFlags) Has(f FormatContextCtxFlag) bool { return astikit.BitFlags(fs).Has(uint64(f)) } type FormatEventFlags astikit.BitFlags @@ -285,42 +285,42 @@ func (fs SeekFlags) Del(f SeekFlag) SeekFlags { func (fs SeekFlags) Has(f SeekFlag) bool { return astikit.BitFlags(fs).Has(uint64(f)) } -type StreamEventFlags astikit.BitFlags +type SoftwareScaleContextFlags astikit.BitFlags -func NewStreamEventFlags(fs ...StreamEventFlag) StreamEventFlags { - o := StreamEventFlags(0) +func NewSoftwareScaleContextFlags(fs ...SoftwareScaleContextFlag) SoftwareScaleContextFlags { + o := SoftwareScaleContextFlags(0) for _, f := range fs { o = o.Add(f) } return o } -func (fs StreamEventFlags) Add(f StreamEventFlag) StreamEventFlags { - return StreamEventFlags(astikit.BitFlags(fs).Add(uint64(f))) +func (fs SoftwareScaleContextFlags) Add(f SoftwareScaleContextFlag) SoftwareScaleContextFlags { + return SoftwareScaleContextFlags(astikit.BitFlags(fs).Add(uint64(f))) } -func (fs StreamEventFlags) Del(f StreamEventFlag) StreamEventFlags { - return StreamEventFlags(astikit.BitFlags(fs).Del(uint64(f))) +func (fs SoftwareScaleContextFlags) Del(f SoftwareScaleContextFlag) SoftwareScaleContextFlags { + return SoftwareScaleContextFlags(astikit.BitFlags(fs).Del(uint64(f))) } -func (fs StreamEventFlags) Has(f StreamEventFlag) bool { return astikit.BitFlags(fs).Has(uint64(f)) } +func (fs SoftwareScaleContextFlags) Has(f SoftwareScaleContextFlag) bool { return astikit.BitFlags(fs).Has(uint64(f)) } -type SoftwareScaleContextFlags astikit.BitFlags +type StreamEventFlags astikit.BitFlags -func NewSoftwareScaleContextFlags(fs ...SoftwareScaleContextFlag) SoftwareScaleContextFlags { - o := SoftwareScaleContextFlags(0) +func NewStreamEventFlags(fs ...StreamEventFlag) StreamEventFlags { + o := StreamEventFlags(0) for _, f := range fs { o = o.Add(f) } return o } -func (fs SoftwareScaleContextFlags) Add(f SoftwareScaleContextFlag) SoftwareScaleContextFlags { - return SoftwareScaleContextFlags(astikit.BitFlags(fs).Add(uint64(f))) +func (fs StreamEventFlags) Add(f StreamEventFlag) StreamEventFlags { + return StreamEventFlags(astikit.BitFlags(fs).Add(uint64(f))) } -func (fs SoftwareScaleContextFlags) Del(f SoftwareScaleContextFlag) SoftwareScaleContextFlags { - return SoftwareScaleContextFlags(astikit.BitFlags(fs).Del(uint64(f))) +func (fs StreamEventFlags) Del(f StreamEventFlag) StreamEventFlags { + return StreamEventFlags(astikit.BitFlags(fs).Del(uint64(f))) } -func (fs SoftwareScaleContextFlags) Has(f SoftwareScaleContextFlag) bool { return astikit.BitFlags(fs).Has(uint64(f)) } +func (fs StreamEventFlags) Has(f StreamEventFlag) bool { return astikit.BitFlags(fs).Has(uint64(f)) } diff --git a/flags_test.go b/flags_test.go index e1a07f6..d6189cf 100644 --- a/flags_test.go +++ b/flags_test.go @@ -70,15 +70,6 @@ func TestFilterCommandFlags(t *testing.T) { require.False(t, fs.Has(astiav.FilterCommandFlag(2))) } -func TestFormatContextCtxFlags(t *testing.T) { - fs := astiav.NewFormatContextCtxFlags(astiav.FormatContextCtxFlag(1)) - require.True(t, fs.Has(astiav.FormatContextCtxFlag(1))) - fs = fs.Add(astiav.FormatContextCtxFlag(2)) - require.True(t, fs.Has(astiav.FormatContextCtxFlag(2))) - fs = fs.Del(astiav.FormatContextCtxFlag(2)) - require.False(t, fs.Has(astiav.FormatContextCtxFlag(2))) -} - func TestFormatContextFlags(t *testing.T) { fs := astiav.NewFormatContextFlags(astiav.FormatContextFlag(1)) require.True(t, fs.Has(astiav.FormatContextFlag(1))) @@ -88,6 +79,15 @@ func TestFormatContextFlags(t *testing.T) { require.False(t, fs.Has(astiav.FormatContextFlag(2))) } +func TestFormatContextCtxFlags(t *testing.T) { + fs := astiav.NewFormatContextCtxFlags(astiav.FormatContextCtxFlag(1)) + require.True(t, fs.Has(astiav.FormatContextCtxFlag(1))) + fs = fs.Add(astiav.FormatContextCtxFlag(2)) + require.True(t, fs.Has(astiav.FormatContextCtxFlag(2))) + fs = fs.Del(astiav.FormatContextCtxFlag(2)) + require.False(t, fs.Has(astiav.FormatContextCtxFlag(2))) +} + func TestFormatEventFlags(t *testing.T) { fs := astiav.NewFormatEventFlags(astiav.FormatEventFlag(1)) require.True(t, fs.Has(astiav.FormatEventFlag(1))) @@ -133,15 +133,6 @@ func TestSeekFlags(t *testing.T) { require.False(t, fs.Has(astiav.SeekFlag(2))) } -func TestStreamEventFlags(t *testing.T) { - fs := astiav.NewStreamEventFlags(astiav.StreamEventFlag(1)) - require.True(t, fs.Has(astiav.StreamEventFlag(1))) - fs = fs.Add(astiav.StreamEventFlag(2)) - require.True(t, fs.Has(astiav.StreamEventFlag(2))) - fs = fs.Del(astiav.StreamEventFlag(2)) - require.False(t, fs.Has(astiav.StreamEventFlag(2))) -} - func TestSoftwareScaleContextFlags(t *testing.T) { fs := astiav.NewSoftwareScaleContextFlags(astiav.SoftwareScaleContextFlag(1)) require.True(t, fs.Has(astiav.SoftwareScaleContextFlag(1))) @@ -150,3 +141,12 @@ func TestSoftwareScaleContextFlags(t *testing.T) { fs = fs.Del(astiav.SoftwareScaleContextFlag(2)) require.False(t, fs.Has(astiav.SoftwareScaleContextFlag(2))) } + +func TestStreamEventFlags(t *testing.T) { + fs := astiav.NewStreamEventFlags(astiav.StreamEventFlag(1)) + require.True(t, fs.Has(astiav.StreamEventFlag(1))) + fs = fs.Add(astiav.StreamEventFlag(2)) + require.True(t, fs.Has(astiav.StreamEventFlag(2))) + fs = fs.Del(astiav.StreamEventFlag(2)) + require.False(t, fs.Has(astiav.StreamEventFlag(2))) +} diff --git a/internal/cmd/flags/main.go b/internal/cmd/flags/main.go index dfca6df..c5f05bf 100644 --- a/internal/cmd/flags/main.go +++ b/internal/cmd/flags/main.go @@ -21,15 +21,15 @@ var list = []listItem{ {Name: "CodecHardwareConfigMethod"}, {Name: "Dictionary"}, {Name: "FilterCommand"}, - {Name: "FormatContextCtx"}, {Name: "FormatContext"}, + {Name: "FormatContextCtx"}, {Name: "FormatEvent"}, {Name: "IOContext"}, {Name: "IOFormat"}, {Name: "Packet"}, {Name: "Seek"}, - {Name: "StreamEvent"}, {Name: "SoftwareScaleContext"}, + {Name: "StreamEvent"}, } var tmpl = `// Code generated by astiav. DO NOT EDIT. diff --git a/software_scale_context.go b/software_scale_context.go index e1622e0..e9e1ffd 100644 --- a/software_scale_context.go +++ b/software_scale_context.go @@ -4,7 +4,7 @@ package astiav //#include import "C" import ( - "fmt" + "errors" ) // https://github.com/FFmpeg/FFmpeg/blob/n5.0/libswscale/swscale_internal.h#L300 @@ -20,7 +20,17 @@ type SoftwareScaleContext struct { srcW C.int } -func NewSoftwareScaleContext(srcW, srcH int, srcFormat PixelFormat, dstW, dstH int, dstFormat PixelFormat, flags SoftwareScaleContextFlags) *SoftwareScaleContext { +type softwareScaleContextUpdate struct { + dstFormat *PixelFormat + dstH *int + dstW *int + flags *SoftwareScaleContextFlags + srcFormat *PixelFormat + srcH *int + srcW *int +} + +func CreateSoftwareScaleContext(srcW, srcH int, srcFormat PixelFormat, dstW, dstH int, dstFormat PixelFormat, flags SoftwareScaleContextFlags) (*SoftwareScaleContext, error) { ssc := SoftwareScaleContext{ dstFormat: C.enum_AVPixelFormat(dstFormat), dstH: C.int(dstH), @@ -42,130 +52,166 @@ func NewSoftwareScaleContext(srcW, srcH int, srcFormat PixelFormat, dstW, dstH i nil, nil, nil, ) if ssc.c == nil { - return nil + return nil, errors.New("astiav: empty new context") } - return &ssc + return &ssc, nil } -func (ssc *SoftwareScaleContext) ScaleFrame(src, dst *Frame) (height int) { - height = int( - C.sws_scale( - ssc.c, - &src.c.data[0], - &src.c.linesize[0], - 0, - C.int(src.Height()), - &dst.c.data[0], &dst.c.linesize[0])) - return +func (ssc *SoftwareScaleContext) ScaleFrame(src, dst *Frame) error { + return newError(C.sws_scale_frame(ssc.c, dst.c, src.c)) } -func (ssc *SoftwareScaleContext) updateContext() error { - ssc.c = C.sws_getCachedContext( +func (ssc *SoftwareScaleContext) update(u softwareScaleContextUpdate) error { + dstW := ssc.dstW + if u.dstW != nil { + dstW = C.int(*u.dstW) + } + + dstH := ssc.dstH + if u.dstH != nil { + dstH = C.int(*u.dstH) + } + + dstFormat := ssc.dstFormat + if u.dstFormat != nil { + dstFormat = C.enum_AVPixelFormat(*u.dstFormat) + } + + srcW := ssc.srcW + if u.srcW != nil { + srcW = C.int(*u.srcW) + } + + srcH := ssc.srcH + if u.srcH != nil { + srcH = C.int(*u.srcH) + } + + srcFormat := ssc.srcFormat + if u.srcFormat != nil { + srcFormat = C.enum_AVPixelFormat(*u.srcFormat) + } + + flags := ssc.flags + if u.flags != nil { + flags = SoftwareScaleContextFlags(*u.flags) + } + + c := C.sws_getCachedContext( ssc.c, - ssc.srcW, - ssc.srcH, - ssc.srcFormat, - ssc.dstW, - ssc.dstH, - ssc.dstFormat, - C.int(ssc.flags), + srcW, + srcH, + srcFormat, + dstW, + dstH, + dstFormat, + C.int(flags), nil, nil, nil, ) - if ssc.c == nil { - return fmt.Errorf("failed to update sws context") + if c == nil { + return errors.New("astiav: empty new context") } - return nil -} -func (ssc *SoftwareScaleContext) PrepareDestinationFrameForScaling(dstFrame *Frame) error { - dstFrame.SetPixelFormat(PixelFormat(ssc.dstFormat)) - dstFrame.SetWidth(int(ssc.dstW)) - dstFrame.SetHeight(int(ssc.dstH)) - return dstFrame.AllocBuffer(1) -} + ssc.c = c + if u.dstW != nil { + ssc.dstW = dstW + } + if u.dstH != nil { + ssc.dstH = dstH + } + if u.dstFormat != nil { + ssc.dstFormat = dstFormat + } + if u.srcW != nil { + ssc.srcW = srcW + } + if u.srcH != nil { + ssc.srcH = srcH + } + if u.srcFormat != nil { + ssc.srcFormat = srcFormat + } + if u.flags != nil { + ssc.flags = flags + } -func (ssc *SoftwareScaleContext) DestinationHeight() int { - return int(ssc.dstH) + return nil } -func (ssc *SoftwareScaleContext) DestinationPixelFormat() PixelFormat { - return PixelFormat(ssc.dstFormat) +func (ssc *SoftwareScaleContext) Flags() SoftwareScaleContextFlags { + return ssc.flags } -func (ssc *SoftwareScaleContext) DestinationResolution() (int, int) { - return int(ssc.dstW), int(ssc.dstH) +func (ssc *SoftwareScaleContext) SetFlags(swscf SoftwareScaleContextFlags) error { + return ssc.update(softwareScaleContextUpdate{flags: &swscf}) } func (ssc *SoftwareScaleContext) DestinationWidth() int { return int(ssc.dstW) } -func (ssc *SoftwareScaleContext) Flags() SoftwareScaleContextFlags { - return ssc.flags -} - -func (ssc *SoftwareScaleContext) SetDestinationHeight(i int) error { - ssc.dstH = C.int(i) - return ssc.updateContext() +func (ssc *SoftwareScaleContext) SetDestinationWidth(i int) error { + return ssc.update(softwareScaleContextUpdate{dstW: &i}) } -func (ssc *SoftwareScaleContext) SetDestinationPixelFormat(p PixelFormat) error { - ssc.dstFormat = C.enum_AVPixelFormat(p) - return ssc.updateContext() +func (ssc *SoftwareScaleContext) DestinationHeight() int { + return int(ssc.dstH) } -func (ssc *SoftwareScaleContext) SetDestinationResolution(w int, h int) error { - ssc.dstW = C.int(w) - ssc.dstH = C.int(h) - return ssc.updateContext() +func (ssc *SoftwareScaleContext) SetDestinationHeight(i int) error { + return ssc.update(softwareScaleContextUpdate{dstH: &i}) } -func (ssc *SoftwareScaleContext) SetDestinationWidth(i int) error { - ssc.dstW = C.int(i) - return ssc.updateContext() +func (ssc *SoftwareScaleContext) DestinationPixelFormat() PixelFormat { + return PixelFormat(ssc.dstFormat) } -func (ssc *SoftwareScaleContext) SetFlags(swscf SoftwareScaleContextFlags) { - ssc.flags = swscf +func (ssc *SoftwareScaleContext) SetDestinationPixelFormat(p PixelFormat) error { + return ssc.update(softwareScaleContextUpdate{dstFormat: &p}) } -func (ssc *SoftwareScaleContext) SetSourceHeight(i int) error { - ssc.srcH = C.int(i) - return ssc.updateContext() +func (ssc *SoftwareScaleContext) DestinationResolution() (width int, height int) { + return int(ssc.dstW), int(ssc.dstH) } -func (ssc *SoftwareScaleContext) SetSourcePixelFormat(p PixelFormat) error { - ssc.srcFormat = C.enum_AVPixelFormat(p) - return ssc.updateContext() +func (ssc *SoftwareScaleContext) SetDestinationResolution(w int, h int) error { + return ssc.update(softwareScaleContextUpdate{dstW: &w, dstH: &h}) } -func (ssc *SoftwareScaleContext) SetSourceResolution(w int, h int) error { - ssc.srcW = C.int(w) - ssc.srcH = C.int(h) - return ssc.updateContext() +func (ssc *SoftwareScaleContext) SourceWidth() int { + return int(ssc.srcW) } func (ssc *SoftwareScaleContext) SetSourceWidth(i int) error { - ssc.srcW = C.int(i) - return ssc.updateContext() + return ssc.update(softwareScaleContextUpdate{srcW: &i}) } func (ssc *SoftwareScaleContext) SourceHeight() int { return int(ssc.srcH) } +func (ssc *SoftwareScaleContext) SetSourceHeight(i int) error { + return ssc.update(softwareScaleContextUpdate{srcH: &i}) +} + func (ssc *SoftwareScaleContext) SourcePixelFormat() PixelFormat { return PixelFormat(ssc.srcFormat) } +func (ssc *SoftwareScaleContext) SetSourcePixelFormat(p PixelFormat) error { + return ssc.update(softwareScaleContextUpdate{srcFormat: &p}) +} + func (ssc *SoftwareScaleContext) SourceResolution() (int, int) { return int(ssc.srcW), int(ssc.srcH) } -func (ssc *SoftwareScaleContext) SourceWidth() int { - return int(ssc.srcW) +func (ssc *SoftwareScaleContext) SetSourceResolution(w int, h int) error { + return ssc.update(softwareScaleContextUpdate{srcW: &w, srcH: &h}) } -func (sc *SoftwareScaleContext) Free() { - C.sws_freeContext(sc.c) +func (ssc *SoftwareScaleContext) Free() { + if ssc.c != nil { + C.sws_freeContext(ssc.c) + } } diff --git a/software_scale_context_flag.go b/software_scale_context_flag.go index 9e08788..079b403 100644 --- a/software_scale_context_flag.go +++ b/software_scale_context_flag.go @@ -8,15 +8,15 @@ type SoftwareScaleContextFlag int // https://github.com/FFmpeg/FFmpeg/blob/n5.0/libswscale/swscale.h#L59 const ( - SoftwareScaleContextArea = SoftwareScaleContextFlag(C.SWS_AREA) - SoftwareScaleContextBicubic = SoftwareScaleContextFlag(C.SWS_BICUBIC) - SoftwareScaleContextBicublin = SoftwareScaleContextFlag(C.SWS_BICUBLIN) - SoftwareScaleContextBilinear = SoftwareScaleContextFlag(C.SWS_BILINEAR) - SoftwareScaleContextFastBilinear = SoftwareScaleContextFlag(C.SWS_FAST_BILINEAR) - SoftwareScaleContextGauss = SoftwareScaleContextFlag(C.SWS_GAUSS) - SoftwareScaleContextLanczos = SoftwareScaleContextFlag(C.SWS_LANCZOS) - SoftwareScaleContextPoint = SoftwareScaleContextFlag(C.SWS_POINT) - SoftwareScaleContextSinc = SoftwareScaleContextFlag(C.SWS_SINC) - SoftwareScaleContextSpline = SoftwareScaleContextFlag(C.SWS_SPLINE) - SoftwareScaleContextX = SoftwareScaleContextFlag(C.SWS_X) + SoftwareScaleContextFlagArea = SoftwareScaleContextFlag(C.SWS_AREA) + SoftwareScaleContextFlagBicubic = SoftwareScaleContextFlag(C.SWS_BICUBIC) + SoftwareScaleContextFlagBicublin = SoftwareScaleContextFlag(C.SWS_BICUBLIN) + SoftwareScaleContextFlagBilinear = SoftwareScaleContextFlag(C.SWS_BILINEAR) + SoftwareScaleContextFlagFastBilinear = SoftwareScaleContextFlag(C.SWS_FAST_BILINEAR) + SoftwareScaleContextFlagGauss = SoftwareScaleContextFlag(C.SWS_GAUSS) + SoftwareScaleContextFlagLanczos = SoftwareScaleContextFlag(C.SWS_LANCZOS) + SoftwareScaleContextFlagPoint = SoftwareScaleContextFlag(C.SWS_POINT) + SoftwareScaleContextFlagSinc = SoftwareScaleContextFlag(C.SWS_SINC) + SoftwareScaleContextFlagSpline = SoftwareScaleContextFlag(C.SWS_SPLINE) + SoftwareScaleContextFlagX = SoftwareScaleContextFlag(C.SWS_X) ) diff --git a/software_scale_context_test.go b/software_scale_context_test.go index d25d592..37d7e74 100644 --- a/software_scale_context_test.go +++ b/software_scale_context_test.go @@ -1,7 +1,6 @@ package astiav_test import ( - "image" "testing" "github.com/asticode/go-astiav" @@ -21,49 +20,46 @@ func TestSoftwareScaleContext(t *testing.T) { require.NotNil(t, f3) defer f3.Free() - srcW := 100 - srcH := 100 + srcW := 320 + srcH := 280 srcPixelFormat := astiav.PixelFormatYuv420P - dstW := 200 - dstH := 200 + dstW := 640 + dstH := 480 dstPixelFormat := astiav.PixelFormatRgba + swscf1 := astiav.SoftwareScaleContextFlags(astiav.SoftwareScaleContextFlagBilinear) f1.SetHeight(srcH) f1.SetWidth(srcW) f1.SetPixelFormat(srcPixelFormat) require.NoError(t, f1.AllocBuffer(1)) - swscf_1 := astiav.NewSoftwareScaleContextFlags(astiav.SoftwareScaleContextBilinear) - swsc := astiav.NewSoftwareScaleContext(srcW, srcH, srcPixelFormat, dstW, dstH, dstPixelFormat, swscf_1) - require.NotNil(t, swsc) - require.Equal(t, swsc.Flags(), swscf_1) - - swscf_2 := astiav.NewSoftwareScaleContextFlags(astiav.SoftwareScaleContextPoint) - swsc.SetFlags(swscf_2) - require.Equal(t, swsc.Flags(), swscf_2) - - require.NoError(t, swsc.PrepareDestinationFrameForScaling(f2)) - require.Equal(t, dstH, swsc.ScaleFrame(f1, f2)) + swsc, err := astiav.CreateSoftwareScaleContext(srcW, srcH, srcPixelFormat, dstW, dstH, dstPixelFormat, swscf1) + require.NoError(t, err) + defer swsc.Free() - require.Equal(t, dstW, f2.Height()) - require.Equal(t, dstH, f2.Width()) + require.NoError(t, swsc.ScaleFrame(f1, f2)) + require.Equal(t, dstH, f2.Height()) + require.Equal(t, dstW, f2.Width()) require.Equal(t, dstPixelFormat, f2.PixelFormat()) - i1, err := f2.Data().Image() - require.NoError(t, err) - require.Equal(t, dstW, i1.Bounds().Dx()) - require.Equal(t, dstH, i1.Bounds().Dy()) - _, nrgbaOk := i1.(*image.NRGBA) - require.True(t, nrgbaOk) - - dstW = 50 - dstH = 50 + dstW = 1024 + dstH = 576 dstPixelFormat = astiav.PixelFormatYuv420P + swscf2 := astiav.SoftwareScaleContextFlags(astiav.SoftwareScaleContextFlagPoint) + + require.Equal(t, swsc.Flags(), swscf1) + swsc.SetFlags(swscf2) + require.Equal(t, swsc.Flags(), swscf2) require.NoError(t, swsc.SetSourceWidth(f2.Width())) require.Equal(t, swsc.SourceWidth(), f2.Width()) require.NoError(t, swsc.SetSourceHeight(f2.Height())) require.Equal(t, swsc.SourceHeight(), f2.Height()) + require.NoError(t, swsc.SetSourceResolution(1280, 720)) + w, h := swsc.SourceResolution() + require.Equal(t, w, 1280) + require.Equal(t, h, 720) + require.NoError(t, swsc.SetSourceResolution(f2.Width(), f2.Height())) require.NoError(t, swsc.SetSourcePixelFormat(f2.PixelFormat())) require.Equal(t, swsc.SourcePixelFormat(), f2.PixelFormat()) @@ -71,34 +67,17 @@ func TestSoftwareScaleContext(t *testing.T) { require.Equal(t, swsc.DestinationWidth(), dstW) require.NoError(t, swsc.SetDestinationHeight(dstH)) require.Equal(t, swsc.DestinationHeight(), dstH) + require.NoError(t, swsc.SetDestinationResolution(800, 600)) + w, h = swsc.DestinationResolution() + require.Equal(t, w, 800) + require.Equal(t, h, 600) + require.NoError(t, swsc.SetDestinationResolution(dstW, dstH)) require.NoError(t, swsc.SetDestinationPixelFormat(dstPixelFormat)) require.Equal(t, swsc.DestinationPixelFormat(), dstPixelFormat) - require.NoError(t, swsc.PrepareDestinationFrameForScaling(f3)) - require.Equal(t, f3.Height(), dstH) - require.Equal(t, f3.Width(), dstW) - require.Equal(t, f3.PixelFormat(), dstPixelFormat) - require.Equal(t, dstH, swsc.ScaleFrame(f2, f3)) - require.Equal(t, dstW, f3.Height()) - require.Equal(t, dstH, f3.Width()) + require.NoError(t, swsc.ScaleFrame(f2, f3)) + require.Equal(t, dstW, f3.Width()) + require.Equal(t, dstH, f3.Height()) require.Equal(t, dstPixelFormat, f3.PixelFormat()) - i2, err := f3.Data().Image() - require.NoError(t, err) - require.Equal(t, dstW, i2.Bounds().Dx()) - require.Equal(t, dstH, i2.Bounds().Dy()) - _, ycbcrOk := i2.(*image.YCbCr) - require.True(t, ycbcrOk) - - require.NoError(t, swsc.SetDestinationResolution(640, 480)) - w, h := swsc.DestinationResolution() - require.Equal(t, w, 640) - require.Equal(t, h, 480) - - require.NoError(t, swsc.SetSourceResolution(480, 270)) - w, h = swsc.SourceResolution() - require.Equal(t, w, 480) - require.Equal(t, h, 270) - - defer swsc.Free() }