Fix reading multiple decoded frames

This commit is contained in:
Atsushi Watanabe
2025-09-16 13:33:45 +09:00
committed by Leo (Lei) Kang
parent 0710906fc7
commit e9f3dc20b6

View File

@@ -41,6 +41,11 @@ vpx_image_t* getFrame(vpx_codec_ctx_t* ctx, vpx_codec_iter_t* iter) {
return vpx_codec_get_frame(ctx, iter); return vpx_codec_get_frame(ctx, iter);
} }
// Frees a decoded frane
void freeFrame(vpx_image_t* f) {
vpx_img_free(f);
}
// Frees a decoder context // Frees a decoder context
void freeDecoderCtx(vpx_codec_ctx_t* ctx) { void freeDecoderCtx(vpx_codec_ctx_t* ctx) {
vpx_codec_destroy(ctx); vpx_codec_destroy(ctx);
@@ -65,6 +70,7 @@ type decoder struct {
codec *C.vpx_codec_ctx_t codec *C.vpx_codec_ctx_t
raw *C.vpx_image_t raw *C.vpx_image_t
cfg *C.vpx_codec_dec_cfg_t cfg *C.vpx_codec_dec_cfg_t
iter C.vpx_codec_iter_t
frameIndex int frameIndex int
tStart time.Time tStart time.Time
tLastFrame time.Time tLastFrame time.Time
@@ -93,28 +99,30 @@ func NewDecoder(r io.Reader, p prop.Media) (codec.VideoDecoder, error) {
return &decoder{ return &decoder{
codec: codec, codec: codec,
cfg: cfg, cfg: cfg,
iter: nil, // initialize to NULL to start iteration
reader: r, reader: r,
buf: make([]byte, 1024*1024), buf: make([]byte, 1024*1024),
}, nil }, nil
} }
func (d *decoder) Read() (image.Image, func(), error) { func (d *decoder) Read() (image.Image, func(), error) {
n, err := d.reader.Read(d.buf) var input *C.vpx_image_t
if err != nil { for {
return nil, nil, err input = C.getFrame(d.codec, &d.iter)
} if input != nil {
if n > 0 { break
}
d.iter = nil
// Read if there are no remained frames in the decoder
n, err := d.reader.Read(d.buf)
if err != nil {
return nil, nil, err
}
status := C.decodeFrame(d.codec, (*C.uint8_t)(&d.buf[0]), C.uint(n)) status := C.decodeFrame(d.codec, (*C.uint8_t)(&d.buf[0]), C.uint(n))
if status != C.VPX_CODEC_OK { if status != C.VPX_CODEC_OK {
return nil, nil, fmt.Errorf("decode failed: %v", status) return nil, nil, fmt.Errorf("decode failed: %v", status)
} }
} }
var iter C.vpx_codec_iter_t = nil // initialize to NULL to start iteration
input := C.getFrame(d.codec, &iter)
if input == nil {
return nil, nil, io.EOF
}
w := int(input.d_w) w := int(input.d_w)
h := int(input.d_h) h := int(input.d_h)
yStride := int(input.stride[0]) yStride := int(input.stride[0])
@@ -136,6 +144,7 @@ func (d *decoder) Read() (image.Image, func(), error) {
copy(dst.Cb[r*dst.CStride:r*dst.CStride+w/2], uSrc[r*uStride:r*uStride+w/2]) copy(dst.Cb[r*dst.CStride:r*dst.CStride+w/2], uSrc[r*uStride:r*uStride+w/2])
copy(dst.Cr[r*dst.CStride:r*dst.CStride+w/2], vSrc[r*vStride:r*vStride+w/2]) copy(dst.Cr[r*dst.CStride:r*dst.CStride+w/2], vSrc[r*vStride:r*vStride+w/2])
} }
C.freeFrame(input)
return dst, func() {}, nil return dst, func() {}, nil
} }