audio: Bug fix: players' buffer can be empty when seeking before proceeding (#366)

This commit is contained in:
Hajime Hoshi 2017-06-11 19:13:45 +09:00
parent 989aef8e2b
commit d8f425962c

View File

@ -287,12 +287,18 @@ func BytesReadSeekCloser(b []uint8) ReadSeekCloser {
return &bytesReadSeekCloser{reader: bytes.NewReader(b)} return &bytesReadSeekCloser{reader: bytes.NewReader(b)}
} }
type readingResult struct {
data []uint8
err error
}
// Player is an audio player which has one stream. // Player is an audio player which has one stream.
type Player struct { type Player struct {
players *players players *players
src ReadSeekCloser src ReadSeekCloser
sampleRate int sampleRate int
readingCh chan error readingCh chan readingResult
seekCh chan int64
buf []uint8 buf []uint8
pos int64 pos int64
@ -320,6 +326,7 @@ func NewPlayer(context *Context, src ReadSeekCloser) (*Player, error) {
players: context.players, players: context.players,
src: src, src: src,
sampleRate: context.sampleRate, sampleRate: context.sampleRate,
seekCh: make(chan int64, 1),
buf: []uint8{}, buf: []uint8{},
volume: 1, volume: 1,
} }
@ -369,28 +376,38 @@ func (p *Player) Close() error {
func (p *Player) readToBuffer(length int) (int, error) { func (p *Player) readToBuffer(length int) (int, error) {
if p.readingCh == nil { if p.readingCh == nil {
p.readingCh = make(chan error) p.readingCh = make(chan readingResult)
go func() { go func() {
defer close(p.readingCh) defer close(p.readingCh)
bb := make([]uint8, length) b := make([]uint8, length)
p.srcM.Lock() p.srcM.Lock()
n, err := p.src.Read(bb) n, err := p.src.Read(b)
p.srcM.Unlock() p.srcM.Unlock()
if err != nil { if err != nil {
p.readingCh <- err p.readingCh <- readingResult{
err: err,
}
return return
} }
if 0 < n { p.readingCh <- readingResult{
p.m.Lock() data: b[:n],
p.buf = append(p.buf, bb[:n]...)
p.m.Unlock()
} }
}() }()
} }
select { select {
case err := <-p.readingCh: case pos := <-p.seekCh:
p.buf = []uint8{}
p.pos = pos
return 0, nil
case r := <-p.readingCh:
if r.err != nil {
return 0, r.err
}
if len(r.data) > 0 {
p.buf = append(p.buf, r.data...)
}
p.readingCh = nil p.readingCh = nil
return len(p.buf), err return len(p.buf), nil
case <-time.After(15 * time.Millisecond): case <-time.After(15 * time.Millisecond):
return length, nil return length, nil
} }
@ -416,10 +433,8 @@ func (p *Player) proceed(length int) {
if p.readingCh != nil { if p.readingCh != nil {
return return
} }
p.m.Lock()
p.buf = p.buf[length:] p.buf = p.buf[length:]
p.pos += int64(length) p.pos += int64(length)
p.m.Unlock()
} }
// Play plays the stream. // Play plays the stream.
@ -462,10 +477,7 @@ func (p *Player) Seek(offset time.Duration) error {
if err != nil { if err != nil {
return err return err
} }
p.m.Lock() p.seekCh <- pos
p.buf = []uint8{}
p.pos = pos
p.m.Unlock()
return nil return nil
} }