package generator import "fmt" // V210AGenerator combines a v210 fill generator with a packed 10-bit alpha // plane. It owns the fill generator and closes it from Close. type V210AGenerator struct { fill FrameGenerator width int height int fillSize int alphaBase []byte } var _ FrameGenerator = (*V210AGenerator)(nil) func NewV210AGenerator( fill FrameGenerator, width, height uint, ) (*V210AGenerator, error) { if fill == nil { return nil, fmt.Errorf("v210a: fill generator is nil") } if width == 0 || height == 0 { return nil, fmt.Errorf("v210a: width and height must be greater than zero, got %dx%d", width, height) } if width%2 != 0 { return nil, fmt.Errorf("v210a: width must be even for 4:2:2 video, got %d", width) } g := &V210AGenerator{ fill: fill, width: int(width), height: int(height), fillSize: V210FrameSize(int(width), int(height)), alphaBase: make([]byte, AlphaFrameSize(int(width), int(height))), } if err := fillAlphaPlane(g.alphaBase, g.width, g.height, alphaOpaque); err != nil { return nil, fmt.Errorf("v210a: initialize alpha plane: %w", err) } return g, nil } func (g *V210AGenerator) GenerateFrame(dst []byte, frameIndex int) error { need := V210AFrameSize(g.width, g.height) if len(dst) < need { return fmt.Errorf("v210a: destination is too small: got %d bytes, need %d", len(dst), need) } if err := g.fill.GenerateFrame(dst[:g.fillSize], frameIndex); err != nil { return fmt.Errorf("v210a: generate fill frame %d: %w", frameIndex, err) } alpha := dst[g.fillSize:need] copy(alpha, g.alphaBase) if err := patchAlphaMovingSquare(alpha, g.width, g.height, frameIndex); err != nil { return fmt.Errorf("v210a: patch alpha frame %d: %w", frameIndex, err) } return nil } func (g *V210AGenerator) Close() error { return g.fill.Close() }