I've got a simple program that reads frames off a webcam and puts pointers to them on a channel in a goroutine. Another portion reads the frame pointers from the channel and pops them onto another queue. This other queue then does some additional processing to them, and when this additional processing is done, a bunch of memory gets allocated that apparently never gets garbage collected. I'm in over my head trying to figure out why:
This function reads the frames off the channel in a loop:
func (mr *OpenCVMotionRunner) Run() error {
log.Println("Starting motion detection... ")
// inMotion := false
win := opencv.NewWindow("GoOpenCV: VideoPlayer")
defer win.Destroy()
test := mr.md.(*CV2FrameDiffMotionDetector)
for {
f := mr.imageChan.PopFrame()
mr.frame = nil
switch f := f.(type) {
default:
return fmt.Errorf("Unknown frame type")
case *BSFrame:
mr.frame = f.ToOpenCVFrame()
case *OpenCVFrame:
mr.frame = f
}
f = nil
test.SetCurrent(mr.frame)
delta := test.Delta()
// win.ShowImage(mr.frame.image)
if delta != nil {
win.ShowImage(delta)
opencv.WaitKey(1)
} else {
fmt.Println("wtf")
}
}
return nil
}
It appears that the problematic part is this specifically:
mr.frame = f.ToOpenCVFrame()
This is the type and the method:
// Frame with byte slice image
type BSFrame struct {
image []byte
Time time.Time
Width uint32
Height uint32
}
func (f *BSFrame) ToOpenCVFrame() *OpenCVFrame {
img := opencv.DecodeImageMem(f.image)
return &OpenCVFrame{
image: img,
Time: f.Time,
Width: f.Width,
Height: f.Height,
}
}
This is the destination type:
type OpenCVFrame struct {
image *opencv.IplImage
Time time.Time
Width uint32
Height uint32
}
PopFrame, FYI, is just a method on an type that aliases a channel:
type BSFrameChan chan *BSFrame
func (fc BSFrameChan) PopFrame() (frame Frame) {
frame = <-fc
return
}
Hopefully this is enough code for the problem to present itself. The rest is here if needed.