Fix race condition when closing encoders (#215)

* Fix race condition when closing encoders

* Apply PR feedback
This commit is contained in:
88hcsif 2020-07-02 09:53:49 +01:00 committed by GitHub
parent 3a8bf7ba7e
commit e7162d2085
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 16 additions and 17 deletions

View file

@ -15,6 +15,7 @@ const chanSize = 2
type H264Encoder struct {
Output chan encoder.OutFrame
Input chan encoder.InFrame
done chan struct{}
buf *bytes.Buffer
enc *x264.Encoder
@ -30,6 +31,7 @@ func NewH264Encoder(width, height, fps int) (encoder.Encoder, error) {
v := &H264Encoder{
Output: make(chan encoder.OutFrame, 5*chanSize),
Input: make(chan encoder.InFrame, chanSize),
done: make(chan struct{}),
buf: bytes.NewBuffer(make([]byte, 0)),
width: width,
@ -81,13 +83,16 @@ func (v *H264Encoder) startLooping() {
v.Output <- encoder.OutFrame{ Data: v.buf.Bytes(), Timestamp: img.Timestamp }
v.buf.Reset()
}
close(v.Output)
close(v.done)
}
// Release release memory and stop loop
func (v *H264Encoder) release() {
close(v.Input)
// Wait for loop to stop
<-v.done
log.Println("Releasing encoder")
// TODO: Bug here, after close it will signal
close(v.Output)
err := v.enc.Close()
if err != nil {
log.Println("Failed to close H264 encoder")

View file

@ -47,6 +47,7 @@ const chanSize = 2
type VpxEncoder struct {
Output chan encoder.OutFrame
Input chan encoder.InFrame
done chan struct{}
width int
height int
@ -65,6 +66,7 @@ func NewVpxEncoder(w, h, fps, bitrate, keyframe int) (encoder.Encoder, error) {
v := &VpxEncoder{
Output: make(chan encoder.OutFrame, 5*chanSize),
Input: make(chan encoder.InFrame, chanSize),
done: make(chan struct{}),
// C
width: w,
@ -152,18 +154,18 @@ func (v *VpxEncoder) startLooping() {
}
v.Output <- encoder.OutFrame{ Data: bs, Timestamp: img.Timestamp }
}
close(v.Output)
close(v.done)
}
// Release release memory and stop loop
func (v *VpxEncoder) release() {
close(v.Input)
// Wait for loop to stop
<-v.done
log.Println("Releasing encoder")
C.vpx_img_free(&v.vpxImage)
C.vpx_codec_destroy(&v.vpxCodexCtx)
// TODO: Bug here, after close it will signal
close(v.Output)
if v.Input != nil {
close(v.Input)
}
}
// GetInputChan returns input channel

View file

@ -89,13 +89,7 @@ func (r *Room) startAudio(sampleRate int) {
idx := 0
// fanout Audio
fmt.Println("listening audio channel", r.IsRunning)
for sample := range r.audioChannel {
if !r.IsRunning {
log.Println("Room ", r.ID, " audio channel closed")
return
}
for i := 0; i < len(sample); {
rem := util.MinInt(len(sample)-i, len(pcm)-idx)
copy(pcm[idx:idx+rem], sample[i:i+rem])
@ -129,6 +123,7 @@ func (r *Room) startAudio(sampleRate int) {
}
}
log.Println("Room ", r.ID, " audio channel closed")
}
// startVideo listen from imageChannel and push to Encoder. The output of encoder will be pushed to webRTC
@ -177,12 +172,9 @@ func (r *Room) startVideo(width, height int, videoEncoderType string) {
}()
for image := range r.imageChannel {
if !r.IsRunning {
log.Println("Room ", r.ID, " video channel closed")
return
}
if len(einput) < cap(einput) {
einput <- encoder.InFrame{ Image: image.Image, Timestamp: image.Timestamp }
}
}
log.Println("Room ", r.ID, " video channel closed")
}