mirror of
https://github.com/pion/mediadevices.git
synced 2025-10-04 00:06:32 +08:00
215 lines
4.6 KiB
Go
215 lines
4.6 KiB
Go
package video
|
|
|
|
import (
|
|
"image"
|
|
)
|
|
|
|
// FrameBuffer is a buffer that can store any image format.
|
|
type FrameBuffer struct {
|
|
buffer []uint8
|
|
tmp image.Image
|
|
}
|
|
|
|
// NewFrameBuffer creates a new FrameBuffer instance and initialize internal buffer
|
|
// with initialSize
|
|
func NewFrameBuffer(initialSize int) *FrameBuffer {
|
|
return &FrameBuffer{
|
|
buffer: make([]uint8, initialSize),
|
|
}
|
|
}
|
|
|
|
func (buff *FrameBuffer) storeInOrder(srcs ...[]uint8) {
|
|
var neededSize int
|
|
|
|
for _, src := range srcs {
|
|
neededSize += len(src)
|
|
}
|
|
|
|
if len(buff.buffer) < neededSize {
|
|
if cap(buff.buffer) >= neededSize {
|
|
buff.buffer = buff.buffer[:neededSize]
|
|
} else {
|
|
buff.buffer = make([]uint8, neededSize)
|
|
}
|
|
}
|
|
|
|
var currentLen int
|
|
for _, src := range srcs {
|
|
copy(buff.buffer[currentLen:], src)
|
|
currentLen += len(src)
|
|
}
|
|
}
|
|
|
|
// Load loads the current owned image
|
|
func (buff *FrameBuffer) Load() image.Image {
|
|
return buff.tmp
|
|
}
|
|
|
|
// StoreCopy makes a copy of src and store its copy. StoreCopy will reuse as much memory as it can
|
|
// from the previous copies. For example, if StoreCopy is given an image that has the same resolution
|
|
// and format from the previous call, StoreCopy will not allocate extra memory and only copy the content
|
|
// from src to the previous buffer.
|
|
func (buff *FrameBuffer) StoreCopy(src image.Image) {
|
|
switch src := src.(type) {
|
|
case *image.Alpha:
|
|
clone, ok := buff.tmp.(*image.Alpha)
|
|
if ok {
|
|
*clone = *src
|
|
} else {
|
|
copied := *src
|
|
clone = &copied
|
|
}
|
|
|
|
buff.storeInOrder(src.Pix)
|
|
clone.Pix = buff.buffer[:len(src.Pix)]
|
|
|
|
buff.tmp = clone
|
|
case *image.Alpha16:
|
|
clone, ok := buff.tmp.(*image.Alpha16)
|
|
if ok {
|
|
*clone = *src
|
|
} else {
|
|
copied := *src
|
|
clone = &copied
|
|
}
|
|
|
|
buff.storeInOrder(src.Pix)
|
|
clone.Pix = buff.buffer[:len(src.Pix)]
|
|
|
|
buff.tmp = clone
|
|
case *image.CMYK:
|
|
clone, ok := buff.tmp.(*image.CMYK)
|
|
if ok {
|
|
*clone = *src
|
|
} else {
|
|
copied := *src
|
|
clone = &copied
|
|
}
|
|
|
|
buff.storeInOrder(src.Pix)
|
|
clone.Pix = buff.buffer[:len(src.Pix)]
|
|
|
|
buff.tmp = clone
|
|
case *image.Gray:
|
|
clone, ok := buff.tmp.(*image.Gray)
|
|
if ok {
|
|
*clone = *src
|
|
} else {
|
|
copied := *src
|
|
clone = &copied
|
|
}
|
|
|
|
buff.storeInOrder(src.Pix)
|
|
clone.Pix = buff.buffer[:len(src.Pix)]
|
|
|
|
buff.tmp = clone
|
|
case *image.Gray16:
|
|
clone, ok := buff.tmp.(*image.Gray16)
|
|
if ok {
|
|
*clone = *src
|
|
} else {
|
|
copied := *src
|
|
clone = &copied
|
|
}
|
|
|
|
buff.storeInOrder(src.Pix)
|
|
clone.Pix = buff.buffer[:len(src.Pix)]
|
|
|
|
buff.tmp = clone
|
|
case *image.NRGBA:
|
|
clone, ok := buff.tmp.(*image.NRGBA)
|
|
if ok {
|
|
*clone = *src
|
|
} else {
|
|
copied := *src
|
|
clone = &copied
|
|
}
|
|
|
|
buff.storeInOrder(src.Pix)
|
|
clone.Pix = buff.buffer[:len(src.Pix)]
|
|
|
|
buff.tmp = clone
|
|
case *image.NRGBA64:
|
|
clone, ok := buff.tmp.(*image.NRGBA64)
|
|
if ok {
|
|
*clone = *src
|
|
} else {
|
|
copied := *src
|
|
clone = &copied
|
|
}
|
|
|
|
buff.storeInOrder(src.Pix)
|
|
clone.Pix = buff.buffer[:len(src.Pix)]
|
|
|
|
buff.tmp = clone
|
|
case *image.RGBA:
|
|
clone, ok := buff.tmp.(*image.RGBA)
|
|
if ok {
|
|
*clone = *src
|
|
} else {
|
|
copied := *src
|
|
clone = &copied
|
|
}
|
|
|
|
buff.storeInOrder(src.Pix)
|
|
clone.Pix = buff.buffer[:len(src.Pix)]
|
|
|
|
buff.tmp = clone
|
|
case *image.RGBA64:
|
|
clone, ok := buff.tmp.(*image.RGBA64)
|
|
if ok {
|
|
*clone = *src
|
|
} else {
|
|
copied := *src
|
|
clone = &copied
|
|
}
|
|
|
|
buff.storeInOrder(src.Pix)
|
|
clone.Pix = buff.buffer[:len(src.Pix)]
|
|
|
|
buff.tmp = clone
|
|
case *image.NYCbCrA:
|
|
clone, ok := buff.tmp.(*image.NYCbCrA)
|
|
if ok {
|
|
*clone = *src
|
|
} else {
|
|
copied := *src
|
|
clone = &copied
|
|
}
|
|
|
|
var currentLen int
|
|
buff.storeInOrder(src.Y, src.Cb, src.Cr, src.A)
|
|
clone.Y = buff.buffer[currentLen : currentLen+len(src.Y) : currentLen+len(src.Y)]
|
|
currentLen += len(src.Y)
|
|
clone.Cb = buff.buffer[currentLen : currentLen+len(src.Cb) : currentLen+len(src.Cb)]
|
|
currentLen += len(src.Cb)
|
|
clone.Cr = buff.buffer[currentLen : currentLen+len(src.Cr) : currentLen+len(src.Cr)]
|
|
currentLen += len(src.Cr)
|
|
clone.A = buff.buffer[currentLen : currentLen+len(src.A) : currentLen+len(src.A)]
|
|
|
|
buff.tmp = clone
|
|
case *image.YCbCr:
|
|
clone, ok := buff.tmp.(*image.YCbCr)
|
|
if ok {
|
|
*clone = *src
|
|
} else {
|
|
copied := *src
|
|
clone = &copied
|
|
}
|
|
|
|
var currentLen int
|
|
buff.storeInOrder(src.Y, src.Cb, src.Cr)
|
|
clone.Y = buff.buffer[currentLen : currentLen+len(src.Y) : currentLen+len(src.Y)]
|
|
currentLen += len(src.Y)
|
|
clone.Cb = buff.buffer[currentLen : currentLen+len(src.Cb) : currentLen+len(src.Cb)]
|
|
currentLen += len(src.Cb)
|
|
clone.Cr = buff.buffer[currentLen : currentLen+len(src.Cr) : currentLen+len(src.Cr)]
|
|
|
|
buff.tmp = clone
|
|
default:
|
|
var converted image.RGBA
|
|
imageToRGBA(&converted, src)
|
|
buff.StoreCopy(&converted)
|
|
}
|
|
}
|