From 4fc00ce5947427d85a808685d10bde314334ec94 Mon Sep 17 00:00:00 2001 From: David Thorpe Date: Mon, 29 Jul 2024 19:37:41 +0200 Subject: [PATCH 1/2] Skip nil frames in decoder --- pkg/ffmpeg/decoder.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pkg/ffmpeg/decoder.go b/pkg/ffmpeg/decoder.go index 40e2bb7..ae8599b 100644 --- a/pkg/ffmpeg/decoder.go +++ b/pkg/ffmpeg/decoder.go @@ -155,12 +155,17 @@ func (d *Decoder) decode(packet *ff.AVPacket, fn DecoderFrameFn) error { dest = (*Frame)(d.frame) } + // If we have a nil frame here, then don't pass back to the caller + if dest == nil { + ff.AVUtil_frame_unref(d.frame) + continue + } + // Copy across the timebase and pts - // TODO if dest != nil { + // TODO // fmt.Println("pts=", d.frame.Pts()) - // (*ff.AVFrame)(dest).SetPts(d.frame.Pts()) - // (*ff.AVFrame)(dest).SetTimeBase(d.timeBase) - //} + // (*ff.AVFrame)(dest).SetPts(d.frame.Pts()) + // (*ff.AVFrame)(dest).SetTimeBase(d.timeBase) // Pass back to the caller if err := fn(d.stream, dest); errors.Is(err, io.EOF) { From a30a3666ff72023695b9c7878d213859ee13db43 Mon Sep 17 00:00:00 2001 From: David Thorpe Date: Mon, 29 Jul 2024 20:32:38 +0200 Subject: [PATCH 2/2] Fixed some resampler issues --- pkg/ffmpeg/resampler.go | 14 +++++++++++++- sys/ffmpeg61/avutil_samples.go | 14 +++++++++++++- sys/ffmpeg61/swresample_convert.go | 17 ++++++++--------- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/pkg/ffmpeg/resampler.go b/pkg/ffmpeg/resampler.go index b88ac47..9beb134 100644 --- a/pkg/ffmpeg/resampler.go +++ b/pkg/ffmpeg/resampler.go @@ -128,7 +128,7 @@ func (r *resampler) Frame(src *Frame) (*Frame, error) { } // Perform resampling - if err := ff.SWResample_convert_frame(r.ctx, (*ff.AVFrame)(src), (*ff.AVFrame)(r.dest)); err != nil { + if err := swrConvertFrame(r.ctx, (*ff.AVFrame)(src), (*ff.AVFrame)(r.dest)); err != nil { return nil, fmt.Errorf("SWResample_convert_frame: %w", err) } else if r.dest.NumSamples() == 0 { return nil, nil @@ -146,6 +146,18 @@ func (r *resampler) Frame(src *Frame) (*Frame, error) { //////////////////////////////////////////////////////////////////////////////// // PRIVATE METHODS +//func swrConvertFrame_(ctx *ff.SWRContext, src, dest *ff.AVFrame) error { +// return ff.SWResample_convert_frame(ctx, src, dest) +//} + +func swrConvertFrame(ctx *ff.SWRContext, src, dest *ff.AVFrame) error { + _, err := ff.SWResample_convert(ctx, ff.AVUtil_samples_frame(dest), ff.AVUtil_samples_frame(src)) + if err != nil { + return err + } + return nil +} + func newResampler(dest, src *Frame) (*ff.SWRContext, error) { // Create a new resampler ctx := ff.SWResample_alloc() diff --git a/sys/ffmpeg61/avutil_samples.go b/sys/ffmpeg61/avutil_samples.go index 26b34b0..cdaa993 100644 --- a/sys/ffmpeg61/avutil_samples.go +++ b/sys/ffmpeg61/avutil_samples.go @@ -16,7 +16,7 @@ import ( import "C" const ( - AV_NUM_PLANES = 48 + AV_NUM_PLANES = 8 ) type AVSamples struct { @@ -83,6 +83,18 @@ func (data *AVSamples) NumSamples() int { //////////////////////////////////////////////////////////////////////////////// // BINDINGS +// Get AVSamples from an AVFrame +func AVUtil_samples_frame(frame *AVFrame) *AVSamples { + return &AVSamples{ + nb_samples: frame.nb_samples, + nb_channels: frame.channels, + sample_fmt: C.enum_AVSampleFormat(frame.format), + plane_size: frame.linesize[0], + buffer_size: frame.linesize[0] * frame.nb_samples, + planes: frame.data, + } +} + // Allocate a samples buffer for nb_samples samples. Return allocated data for each plane, and the stride. func AVUtil_samples_alloc(nb_samples, nb_channels int, sample_fmt AVSampleFormat, align bool) (*AVSamples, error) { if nb_channels < 1 { diff --git a/sys/ffmpeg61/swresample_convert.go b/sys/ffmpeg61/swresample_convert.go index ee49901..47df74d 100644 --- a/sys/ffmpeg61/swresample_convert.go +++ b/sys/ffmpeg61/swresample_convert.go @@ -13,15 +13,14 @@ import "C" // PUBLIC METHODS // Core conversion function. Returns number of samples output per channel. -// in and in_count can be set to 0 to flush the last few samples out at the end. -func SWResample_convert(ctx *SWRContext, dst *AVSamples, dst_nb_samples int, src *AVSamples, src_nb_samples int) (int, error) { - n := int(C.swr_convert( - (*C.struct_SwrContext)(ctx), - &dst.planes[0], - C.int(dst_nb_samples), - &src.planes[0], - C.int(src_nb_samples), - )) +// src can be set to nil to flush the last few samples out at the end. +func SWResample_convert(ctx *SWRContext, dest, src *AVSamples) (int, error) { + var n int + if src != nil { + n = int(C.swr_convert((*C.struct_SwrContext)(ctx), &dest.planes[0], dest.nb_samples, &src.planes[0], src.nb_samples)) + } else { + n = int(C.swr_convert((*C.struct_SwrContext)(ctx), &dest.planes[0], dest.nb_samples, nil, 0)) + } if n < 0 { return 0, AVError(n) } else {