mirror of
https://github.com/pion/mediadevices.git
synced 2025-12-24 13:18:11 +08:00
Add context with timeout to darwin Read() calls (#674)
* Add timeout * Clean
This commit is contained in:
@@ -136,11 +136,26 @@ func (rc *ReadCloser) dataCb(data []byte) {
|
||||
// - For video, each call will return a frame.
|
||||
// - For audio, each call will return a chunk which its size configured by Latency
|
||||
func (rc *ReadCloser) Read() ([]byte, func(), error) {
|
||||
data, ok := <-rc.dataChan
|
||||
if !ok {
|
||||
return nil, func() {}, io.EOF
|
||||
data, release, err := rc.ReadContext(context.Background())
|
||||
if err != nil {
|
||||
return nil, release, err
|
||||
}
|
||||
return data, release, nil
|
||||
}
|
||||
|
||||
// ReadContext is Read but with a context for better error handling e.g. timeout, cancellation, etc.
|
||||
func (rc *ReadCloser) ReadContext(ctx context.Context) ([]byte, func(), error) {
|
||||
release := func() {} // no-op to satisfy Reader interface
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, release, ctx.Err()
|
||||
case data, ok := <-rc.dataChan:
|
||||
if !ok {
|
||||
return nil, release, io.EOF
|
||||
}
|
||||
return data, release, nil
|
||||
}
|
||||
return data, func() {}, nil
|
||||
}
|
||||
|
||||
// Close closes the capturing session, and no data will flow anymore
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package camera
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"image"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/pion/mediadevices/pkg/avfoundation"
|
||||
"github.com/pion/mediadevices/pkg/driver"
|
||||
@@ -14,8 +18,11 @@ type camera struct {
|
||||
device avfoundation.Device
|
||||
session *avfoundation.Session
|
||||
rcClose func()
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
const readTimeout = 3 * time.Second
|
||||
|
||||
func init() {
|
||||
Initialize()
|
||||
}
|
||||
@@ -53,6 +60,11 @@ func (cam *camera) Close() error {
|
||||
if cam.rcClose != nil {
|
||||
cam.rcClose()
|
||||
}
|
||||
|
||||
if cam.cancel != nil {
|
||||
cam.cancel()
|
||||
}
|
||||
|
||||
return cam.session.Close()
|
||||
}
|
||||
|
||||
@@ -66,10 +78,24 @@ func (cam *camera) VideoRecord(property prop.Media) (video.Reader, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cam.cancel = cancel
|
||||
cam.rcClose = rc.Close
|
||||
r := video.ReaderFunc(func() (image.Image, func(), error) {
|
||||
frame, _, err := rc.Read()
|
||||
if ctx.Err() != nil {
|
||||
// Return EOF if the camera is already closed.
|
||||
return nil, func() {}, io.EOF
|
||||
}
|
||||
|
||||
readCtx, cancel := context.WithTimeout(ctx, readTimeout)
|
||||
defer cancel()
|
||||
|
||||
frame, _, err := rc.ReadContext(readCtx)
|
||||
if err != nil {
|
||||
if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {
|
||||
return nil, func() {}, io.EOF
|
||||
}
|
||||
return nil, func() {}, err
|
||||
}
|
||||
return decoder.Decode(frame, property.Width, property.Height)
|
||||
|
||||
Reference in New Issue
Block a user