Update codec.Reader interface to return byte slice

This commit is contained in:
Lukas Herman
2020-10-28 07:34:43 -07:00
parent c8547c4597
commit f4a4edcabd
12 changed files with 80 additions and 228 deletions
+22 -33
View File
@@ -80,7 +80,6 @@ const (
type encoderVP8 struct {
r video.Reader
buf []byte
frame []byte
fdDRI C.int
@@ -297,25 +296,17 @@ func newVP8Encoder(r video.Reader, p prop.Media, params ParamsVP8) (codec.ReadCl
return e, nil
}
func (e *encoderVP8) Read(p []byte) (int, error) {
func (e *encoderVP8) Read() ([]byte, error) {
e.mu.Lock()
defer e.mu.Unlock()
if e.closed {
return 0, io.EOF
}
if e.buf != nil {
n, err := mio.Copy(p, e.buf)
if err == nil {
e.buf = nil
}
return n, err
return nil, io.EOF
}
img, err := e.r.Read()
if err != nil {
return 0, err
return nil, err
}
yuvImg := img.(*image.YCbCr)
@@ -357,7 +348,7 @@ func (e *encoderVP8) Read(p []byte) (int, error) {
}
}
if e.picParam.reconstructed_frame == C.VA_INVALID_SURFACE {
return 0, errors.New("no available surface")
return nil, errors.New("no available surface")
}
C.setForceKFFlagVP8(&e.picParam, 0)
@@ -425,7 +416,7 @@ func (e *encoderVP8) Read(p []byte) (int, error) {
C.size_t(uintptr(p.src)),
&id,
); s != C.VA_STATUS_SUCCESS {
return 0, fmt.Errorf("failed to create buffer: %s", C.GoString(C.vaErrorStr(s)))
return nil, fmt.Errorf("failed to create buffer: %s", C.GoString(C.vaErrorStr(s)))
}
buffs = append(buffs, id)
}
@@ -435,17 +426,17 @@ func (e *encoderVP8) Read(p []byte) (int, error) {
e.display, e.ctxID,
e.surfs[surfaceVP8Input],
); s != C.VA_STATUS_SUCCESS {
return 0, fmt.Errorf("failed to begin picture: %s", C.GoString(C.vaErrorStr(s)))
return nil, fmt.Errorf("failed to begin picture: %s", C.GoString(C.vaErrorStr(s)))
}
// Upload image
var vaImg C.VAImage
var rawBuf unsafe.Pointer
if s := C.vaDeriveImage(e.display, e.surfs[surfaceVP8Input], &vaImg); s != C.VA_STATUS_SUCCESS {
return 0, fmt.Errorf("failed to derive image: %s", C.GoString(C.vaErrorStr(s)))
return nil, fmt.Errorf("failed to derive image: %s", C.GoString(C.vaErrorStr(s)))
}
if s := C.vaMapBuffer(e.display, vaImg.buf, &rawBuf); s != C.VA_STATUS_SUCCESS {
return 0, fmt.Errorf("failed to map buffer: %s", C.GoString(C.vaErrorStr(s)))
return nil, fmt.Errorf("failed to map buffer: %s", C.GoString(C.vaErrorStr(s)))
}
// TODO: use vaImg.pitches to support padding
C.memcpy(
@@ -461,10 +452,10 @@ func (e *encoderVP8) Read(p []byte) (int, error) {
unsafe.Pointer(&yuvImg.Cr[0]), C.size_t(len(yuvImg.Cr)),
)
if s := C.vaUnmapBuffer(e.display, vaImg.buf); s != C.VA_STATUS_SUCCESS {
return 0, fmt.Errorf("failed to unmap buffer: %s", C.GoString(C.vaErrorStr(s)))
return nil, fmt.Errorf("failed to unmap buffer: %s", C.GoString(C.vaErrorStr(s)))
}
if s := C.vaDestroyImage(e.display, vaImg.image_id); s != C.VA_STATUS_SUCCESS {
return 0, fmt.Errorf("failed to destroy image: %s", C.GoString(C.vaErrorStr(s)))
return nil, fmt.Errorf("failed to destroy image: %s", C.GoString(C.vaErrorStr(s)))
}
if s := C.vaRenderPicture(
@@ -472,38 +463,38 @@ func (e *encoderVP8) Read(p []byte) (int, error) {
&buffs[1], // 0 is for ouput
C.int(len(buffs)-1),
); s != C.VA_STATUS_SUCCESS {
return 0, fmt.Errorf("failed to render picture: %s", C.GoString(C.vaErrorStr(s)))
return nil, fmt.Errorf("failed to render picture: %s", C.GoString(C.vaErrorStr(s)))
}
if s := C.vaEndPicture(
e.display, e.ctxID,
); s != C.VA_STATUS_SUCCESS {
return 0, fmt.Errorf("failed to end picture: %s", C.GoString(C.vaErrorStr(s)))
return nil, fmt.Errorf("failed to end picture: %s", C.GoString(C.vaErrorStr(s)))
}
// Load encoded data
for retry := 3; retry >= 0; retry-- {
if s := C.vaSyncSurface(e.display, e.picParam.reconstructed_frame); s != C.VA_STATUS_SUCCESS {
return 0, fmt.Errorf("failed to sync surface: %s", C.GoString(C.vaErrorStr(s)))
return nil, fmt.Errorf("failed to sync surface: %s", C.GoString(C.vaErrorStr(s)))
}
var surfStat C.VASurfaceStatus
if s := C.vaQuerySurfaceStatus(
e.display, e.picParam.reconstructed_frame, &surfStat,
); s != C.VA_STATUS_SUCCESS {
return 0, fmt.Errorf("failed to query surface status: %s", C.GoString(C.vaErrorStr(s)))
return nil, fmt.Errorf("failed to query surface status: %s", C.GoString(C.vaErrorStr(s)))
}
if surfStat == C.VASurfaceReady {
break
}
if retry == 0 {
return 0, fmt.Errorf("failed to sync surface: %d", surfStat)
return nil, fmt.Errorf("failed to sync surface: %d", surfStat)
}
}
var seg *C.VACodedBufferSegment
if s := C.vaMapBufferSeg(e.display, buffs[0], &seg); s != C.VA_STATUS_SUCCESS {
return 0, fmt.Errorf("failed to map buffer: %s", C.GoString(C.vaErrorStr(s)))
return nil, fmt.Errorf("failed to map buffer: %s", C.GoString(C.vaErrorStr(s)))
}
if seg.status&C.VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK != 0 {
return 0, errors.New("buffer size too small")
return nil, errors.New("buffer size too small")
}
if cap(e.frame) < int(seg.size) {
@@ -516,13 +507,13 @@ func (e *encoderVP8) Read(p []byte) (int, error) {
)
if s := C.vaUnmapBuffer(e.display, buffs[0]); s != C.VA_STATUS_SUCCESS {
return 0, fmt.Errorf("failed to unmap buffer: %s", C.GoString(C.vaErrorStr(s)))
return nil, fmt.Errorf("failed to unmap buffer: %s", C.GoString(C.vaErrorStr(s)))
}
// Destroy buffers
for _, b := range buffs {
if s := C.vaDestroyBuffer(e.display, b); s != C.VA_STATUS_SUCCESS {
return 0, fmt.Errorf("failed to destroy buffer: %s", C.GoString(C.vaErrorStr(s)))
return nil, fmt.Errorf("failed to destroy buffer: %s", C.GoString(C.vaErrorStr(s)))
}
}
@@ -545,11 +536,9 @@ func (e *encoderVP8) Read(p []byte) (int, error) {
e.picParam.ref_last_frame = e.picParam.reconstructed_frame
C.setRefreshLastFlagVP8(&e.picParam, 1)
n, err := mio.Copy(p, e.frame)
if err != nil {
e.buf = e.frame
}
return n, err
encoded := make([]byte, len(e.frame))
copy(encoded, e.frame)
return encoded, err
}
func (e *encoderVP8) SetBitRate(b int) error {