Release AVFoundation ReadCloser on camera close (#375)

This commit is contained in:
Eric Daniels
2022-03-28 06:57:15 -04:00
committed by GitHub
parent 548cdac668
commit 70261260cb
2 changed files with 23 additions and 5 deletions

View File

@@ -11,6 +11,7 @@ package avfoundation
// }
import "C"
import (
"context"
"fmt"
"io"
"unsafe"
@@ -93,9 +94,11 @@ func Devices(mediaType MediaType) ([]Device, error) {
// ReadCloser is a wrapper around the data callback from AVFoundation. The data received from the
// the underlying callback can be retrieved by calling Read.
type ReadCloser struct {
dataChan chan []byte
id handleID
onClose func()
dataChan chan []byte
id handleID
onClose func()
cancelCtx context.Context
cancelFunc func()
}
func newReadCloser(onClose func()) *ReadCloser {
@@ -103,12 +106,22 @@ func newReadCloser(onClose func()) *ReadCloser {
rc.dataChan = make(chan []byte, 1)
rc.onClose = onClose
rc.id = register(rc.dataCb)
cancelCtx, cancelFunc := context.WithCancel(context.Background())
rc.cancelCtx = cancelCtx
rc.cancelFunc = cancelFunc
return &rc
}
func (rc *ReadCloser) dataCb(data []byte) {
// TODO: add a policy for slow reader
rc.dataChan <- data
if rc.cancelCtx.Err() != nil {
return
}
select {
case <-rc.cancelCtx.Done():
close(rc.dataChan)
case rc.dataChan <- data:
}
}
// Read reads raw data, the format is determined by the media type and property:
@@ -127,7 +140,7 @@ func (rc *ReadCloser) Close() {
if rc.onClose != nil {
rc.onClose()
}
close(rc.dataChan)
rc.cancelFunc()
unregister(rc.id)
}

View File

@@ -13,6 +13,7 @@ import (
type camera struct {
device avfoundation.Device
session *avfoundation.Session
rcClose func()
}
func init() {
@@ -43,6 +44,9 @@ func (cam *camera) Open() error {
}
func (cam *camera) Close() error {
if cam.rcClose != nil {
cam.rcClose()
}
return cam.session.Close()
}
@@ -56,6 +60,7 @@ func (cam *camera) VideoRecord(property prop.Media) (video.Reader, error) {
if err != nil {
return nil, err
}
cam.rcClose = rc.Close
r := video.ReaderFunc(func() (image.Image, func(), error) {
frame, _, err := rc.Read()
if err != nil {