-
Notifications
You must be signed in to change notification settings - Fork 16
/
buffer.go
142 lines (130 loc) · 3.61 KB
/
buffer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Package v4l, a facade to the Video4Linux video capture interface
// Copyright (C) 2016 Zoltán Korándi <[email protected]>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//go:build linux
// +build linux
package v4l
import "io"
// A Buffer holds the raw image data of a frame captured from a Device. It
// implements io.Reader, io.ByteReader, io.ReaderAt, and io.Seeker. A call to
// Capture, Close, or TurnOff on the corresponding Device may cause the contents
// of the buffer to go away.
type Buffer struct {
d *device
n uint64
pos int
seq uint32
}
// Size returns the total number of bytes in the buffer. As long as the data is
// available, the return value is constant and unaffected by calls to the
// methods of Buffer. If the data is no longer available, it returns 0.
func (b *Buffer) Size() int64 {
return int64(len(b.source()))
}
// Len returns the number of unread bytes in the buffer. If the data is no
// longer available, it returns 0.
func (b *Buffer) Len() int {
src := b.source()
if src == nil {
return 0
}
return len(src) - b.pos
}
// SeqNum returns the sequence number of the frame in the buffer as reported by
// the kernel.
func (b *Buffer) SeqNum() uint32 {
return b.seq
}
// Read reads up to len(dst) bytes into dst, and returns the number of bytes
// read, along with any error encountered.
func (b *Buffer) Read(dst []byte) (int, error) {
src := b.source()
if src == nil {
return 0, ErrBufferGone
}
if b.pos == len(src) {
return 0, io.EOF
}
n := copy(dst, src[b.pos:])
b.pos += n
return n, nil
}
// ReadAt reads up to len(dst) bytes into dst starting at the specified offset,
// and returns the number of bytes read, along with any error encountered.
// The seek offset is unaffected by ReadAt.
func (b *Buffer) ReadAt(dst []byte, offset int64) (int, error) {
src := b.source()
if src == nil {
return 0, ErrBufferGone
}
if offset < 0 {
return 0, Error("negative offset")
}
if offset >= int64(len(src)) {
return 0, io.EOF
}
n := copy(dst, src[offset:])
if n < len(dst) {
return n, io.EOF
}
return n, nil
}
// ReadByte returns the next byte in the buffer.
func (b *Buffer) ReadByte() (byte, error) {
src := b.source()
if src == nil {
return 0, ErrBufferGone
}
if b.pos == len(src) {
return 0, io.EOF
}
x := src[b.pos]
b.pos++
return x, nil
}
// Seek sets the seek offset.
func (b *Buffer) Seek(offset int64, whence int) (int64, error) {
src := b.source()
if src == nil {
return 0, ErrBufferGone
}
var i int64
switch whence {
case io.SeekStart:
i = offset
case io.SeekCurrent:
i = int64(b.pos) + offset
case io.SeekEnd:
i = int64(len(src)) + offset
default:
return 0, Error("invalid whence")
}
if i < 0 {
return 0, Error("negative offset")
}
if i > int64(len(src)) {
i = int64(len(src))
}
b.pos = int(i)
return i, nil
}
// source returns the underlying byte slice of the buffer, or nil, if it's no
// longer available.
func (b *Buffer) source() []byte {
if b.d.nCaptures != b.n || b.d.bufIndex == noBuffer {
return nil
}
return b.d.buffers[b.d.bufIndex]
}