Skip to content

Commit 4a4d201

Browse files
authored
Add resampler functionality (#89)
* Added resampler * Updates after PR comments * Updated
1 parent 8a376ff commit 4a4d201

9 files changed

Lines changed: 1640 additions & 15 deletions

File tree

sys/ffmpeg80/avutil_frame.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,16 @@ func AVUtil_frame_get_num_planes(frame *AVFrame) int {
162162
return 0
163163
}
164164

165+
// Set up dst as a new reference to the same data described by src, sharing
166+
// its underlying buffer(s) (bumping their refcount) rather than copying -
167+
// dst must already be allocated but not yet hold any buffers of its own.
168+
func AVUtil_frame_ref(dst, src *AVFrame) error {
169+
if ret := AVError(C.av_frame_ref((*C.struct_AVFrame)(dst), (*C.struct_AVFrame)(src))); ret != 0 {
170+
return ret
171+
}
172+
return nil
173+
}
174+
165175
// Copy frame data
166176
func AVUtil_frame_copy(dst, src *AVFrame) error {
167177
if ret := AVError(C.av_frame_copy((*C.struct_AVFrame)(dst), (*C.struct_AVFrame)(src))); ret < 0 {

task/manager/manager.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ type Manager struct {
3737
////////////////////////////////////////////////////////////////////////////////
3838
// LIFECYCLE
3939

40-
// New creates a new media object
40+
// New creates a new task manager
4141
func New(ctx context.Context, opts ...Opt) (_ *Manager, err error) {
4242
self := new(Manager)
4343
if err := self.apply(opts); err != nil {
@@ -302,9 +302,10 @@ func (m *Manager) Remove(ctx context.Context, id uuid.UUID) (err error) {
302302

303303
// Wait blocks until the task registered under id finishes, or until ctx is
304304
// done, whichever comes first, then returns its final status. It returns an
305-
// error if the task hasn't been started (there's nothing to wait for), or if
306-
// the task itself returned an error (joined into err, alongside a context
307-
// error if ctx is what ended the wait).
305+
// error if the task hasn't been started (there's nothing to wait for), if
306+
// ctx ends the wait first (no status is returned in that case, since the
307+
// task may still be running), or if the task itself returned an error (its
308+
// status is still returned alongside that error).
308309
func (m *Manager) Wait(ctx context.Context, id uuid.UUID) (_ *schema.Status, err error) {
309310
ctx, endSpan := otel.StartSpan(m.tracer, ctx, "Wait",
310311
attribute.String("uuid", id.String()),

task/manager/opt.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
////////////////////////////////////////////////////////////////////////////////
99
// TYPES
1010

11-
// Opt is a functional option for filer manager configuration.
11+
// Opt is a functional option for task manager configuration.
1212
type Opt func(*opt) error
1313

1414
type opt struct {

writer/encoder.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,11 @@ func (e *Encoder) Encode(f frame.Frame) error {
178178

179179
// Flush signals end-of-stream to the codec registered for streamID and
180180
// passes any remaining buffered packets to the Encoder's callback. This is
181-
// a no-op for a subtitle stream: subtitles use a legacy API with no
182-
// buffering, so there is nothing to flush.
181+
// a no-op for a subtitle stream (subtitles use a legacy API with no
182+
// buffering, so there is nothing to flush) and for a stream whose codec
183+
// isn't actually an encoder (e.g. a StreamProfile fed to Add purely to copy
184+
// a demuxed stream's parameters/extradata onto the muxed output for a
185+
// remux - avcodec_send_frame is only valid against a real encoder context).
183186
func (e *Encoder) Flush(streamID int) error {
184187
ctx, err := e.contextFor(streamID)
185188
if err != nil {
@@ -188,6 +191,9 @@ func (e *Encoder) Flush(streamID int) error {
188191
if ctx.CodecType() == ff.AVMEDIA_TYPE_SUBTITLE {
189192
return nil
190193
}
194+
if codec := ctx.Codec(); codec == nil || !codec.IsEncoder() {
195+
return nil
196+
}
191197
return e.encode(ctx, streamID, nil)
192198
}
193199

writer/encoder_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,42 @@ func silentFrame(t *testing.T, streamID, numSamples int) *frame.AudioFrame {
5151
return frame
5252
}
5353

54+
// mismatchedFrame builds an audio frame in a deliberately different format
55+
// (s16 mono @ 8kHz) from silentFrame's (fltp stereo @ 44.1kHz) - the format
56+
// audioStream's aac profile expects. Used to force Writer.Encode's resampler
57+
// into a real conversion rather than the fast pass-through path.
58+
func mismatchedFrame(t *testing.T, streamID, numSamples int) *frame.AudioFrame {
59+
t.Helper()
60+
61+
frame, err := frame.NewAudioFrame(streamID)
62+
if err != nil {
63+
t.Fatalf("NewFrame: %v", err)
64+
}
65+
66+
frame.SetSampleFormat(ff.AVUtil_get_sample_fmt("s16"))
67+
frame.SetSampleRate(8000)
68+
69+
var ch ff.AVChannelLayout
70+
if err := ff.AVUtil_channel_layout_from_string(&ch, "mono"); err != nil {
71+
t.Fatalf("AVUtil_channel_layout_from_string: %v", err)
72+
}
73+
if err := frame.SetChannelLayout(ch); err != nil {
74+
t.Fatalf("SetChannelLayout: %v", err)
75+
}
76+
frame.SetNumSamples(numSamples)
77+
78+
if err := frame.AllocateBuffers(); err != nil {
79+
t.Fatalf("AllocateBuffers: %v", err)
80+
}
81+
82+
samples := frame.Int16(0)
83+
for i := range samples {
84+
samples[i] = 0
85+
}
86+
87+
return frame
88+
}
89+
5490
func newTestEncoder(t *testing.T, fn writer.PacketFn) *writer.Encoder {
5591
t.Helper()
5692
if fn == nil {

0 commit comments

Comments
 (0)