@@ -25,6 +25,8 @@ type demuxer struct {
25
25
type decoder struct {
26
26
stream int
27
27
codec * ff.AVCodecContext
28
+ dest * par // Destination parameters
29
+ timeBase ff.AVRational // Timebase for the stream
28
30
frame * ff.AVFrame // Destination frame
29
31
reframe * ff.AVFrame // Destination frame after resample or resize
30
32
resampler * ff.SWRContext // Resampler for audio
@@ -36,7 +38,7 @@ var _ Decoder = (*demuxer)(nil)
36
38
////////////////////////////////////////////////////////////////////////////
37
39
// LIFECYCLE
38
40
39
- func newDemuxer (input * ff.AVFormatContext , mapfn DecoderMapFunc ) (* demuxer , error ) {
41
+ func newDemuxer (input * ff.AVFormatContext , mapfn DecoderMapFunc , force bool ) (* demuxer , error ) {
40
42
demuxer := new (demuxer )
41
43
demuxer .input = input
42
44
demuxer .decoders = make (map [int ]* decoder )
@@ -62,7 +64,7 @@ func newDemuxer(input *ff.AVFormatContext, mapfn DecoderMapFunc) (*demuxer, erro
62
64
result = errors .Join (result , err )
63
65
} else if parameters == nil {
64
66
continue
65
- } else if decoder , err := demuxer .newDecoder (stream , parameters ); err != nil {
67
+ } else if decoder , err := demuxer .newDecoder (stream , parameters .( * par ), force ); err != nil {
66
68
result = errors .Join (result , err )
67
69
} else {
68
70
streamNum := stream .Index ()
@@ -86,15 +88,21 @@ func newDemuxer(input *ff.AVFormatContext, mapfn DecoderMapFunc) (*demuxer, erro
86
88
return demuxer , nil
87
89
}
88
90
89
- func (d * demuxer ) newDecoder (stream * ff.AVStream , dest Parameters ) (* decoder , error ) {
91
+ func (d * demuxer ) newDecoder (stream * ff.AVStream , dest * par , force bool ) (* decoder , error ) {
90
92
decoder := new (decoder )
91
93
decoder .stream = stream .Id ()
94
+ decoder .dest = dest
95
+ decoder .timeBase = stream .TimeBase ()
92
96
93
97
// Use parameters to create the decoder resampler or resizer
94
98
src := stream .CodecPar ()
95
- if equals , err := equalsStream (dest , src ); err != nil {
99
+ equals , err := equalsStream (dest , src )
100
+ if err != nil {
96
101
return nil , err
97
- } else if ! equals {
102
+ }
103
+
104
+ // We resample or rescale if the parameters don't match, or if we're forced
105
+ if ! equals || force {
98
106
switch src .CodecType () {
99
107
case ff .AVMEDIA_TYPE_AUDIO :
100
108
if resampler , frame , err := newResampler (dest , src ); err != nil {
@@ -135,7 +143,7 @@ func (d *demuxer) newDecoder(stream *ff.AVStream, dest Parameters) (*decoder, er
135
143
return nil , errors .Join (decoder .close (), err )
136
144
}
137
145
138
- // Create a frame for decoder output - after resize/resample
146
+ // Create a frame for decoder output - before resize/resample
139
147
if frame := ff .AVUtil_frame_alloc (); frame == nil {
140
148
return nil , errors .Join (decoder .close (), errors .New ("failed to allocate frame" ))
141
149
} else {
@@ -146,38 +154,28 @@ func (d *demuxer) newDecoder(stream *ff.AVStream, dest Parameters) (*decoder, er
146
154
return decoder , nil
147
155
}
148
156
149
- func newResizer (dest Parameters , src * ff.AVCodecParameters ) (* ff.SWSContext , * ff.AVFrame , error ) {
150
- // Get native pixel format
151
- dest_pixel_format := ff .AVUtil_get_pix_fmt (dest .PixelFormat ())
152
-
157
+ func newResizer (dest * par , src * ff.AVCodecParameters ) (* ff.SWSContext , * ff.AVFrame , error ) {
153
158
// Create scaling context and destination frame
154
- if ctx := ff .SWScale_get_context (
159
+ ctx := ff .SWScale_get_context (
155
160
src .Width (), src .Height (), src .PixelFormat (), // source
156
- dest .Width (), dest .Height (), dest_pixel_format , // destination
157
- ff .SWS_BILINEAR , nil , nil , nil ); ctx == nil {
161
+ dest .videopar .Width , dest .videopar .Height , dest .videopar .PixelFormat , // destination
162
+ ff .SWS_BILINEAR , nil , nil , nil )
163
+ if ctx == nil {
158
164
return nil , nil , errors .New ("failed to allocate swscale context" )
159
- } else if frame := ff .AVUtil_frame_alloc (); frame == nil {
165
+ }
166
+
167
+ // Create a new frame for the resizing video
168
+ frame := ff .AVUtil_frame_alloc ()
169
+ if frame == nil {
160
170
ff .SWScale_free_context (ctx )
161
171
return nil , nil , errors .New ("failed to allocate frame" )
162
- } else {
163
- // Set frame parameters
164
- frame .SetPixFmt (dest_pixel_format )
165
- frame .SetWidth (dest .Width ())
166
- frame .SetHeight (dest .Height ())
167
-
168
- // Return success
169
- return ctx , frame , nil
170
172
}
171
- }
172
173
173
- func newResampler (dest Parameters , src * ff.AVCodecParameters ) (* ff.SWRContext , * ff.AVFrame , error ) {
174
- // Get native sample format and channel layout
175
- var dest_channel_layout ff.AVChannelLayout
176
- dest_sample_format := ff .AVUtil_get_sample_fmt (dest .SampleFormat ())
177
- if err := ff .AVUtil_channel_layout_from_string (& dest_channel_layout , dest .ChannelLayout ()); err != nil {
178
- return nil , nil , fmt .Errorf ("failed to get channel layout: %w" , err )
179
- }
174
+ // Return success
175
+ return ctx , frame , nil
176
+ }
180
177
178
+ func newResampler (dest * par , src * ff.AVCodecParameters ) (* ff.SWRContext , * ff.AVFrame , error ) {
181
179
// Create a new resampler
182
180
ctx := ff .SWResample_alloc ()
183
181
if ctx == nil {
@@ -186,7 +184,7 @@ func newResampler(dest Parameters, src *ff.AVCodecParameters) (*ff.SWRContext, *
186
184
187
185
// Set options to covert from the codec frame to the decoder frame
188
186
if err := ff .SWResample_set_opts (ctx ,
189
- dest_channel_layout , dest_sample_format , dest .Samplerate () , // destination
187
+ dest . audiopar . Ch , dest . audiopar . SampleFormat , dest .audiopar . Samplerate , // destination
190
188
src .ChannelLayout (), src .SampleFormat (), src .Samplerate (), // source
191
189
); err != nil {
192
190
ff .SWResample_free (ctx )
@@ -206,19 +204,14 @@ func newResampler(dest Parameters, src *ff.AVCodecParameters) (*ff.SWRContext, *
206
204
return nil , nil , errors .New ("failed to allocate frame" )
207
205
}
208
206
209
- // Set frame parameters
210
- frame .SetSampleRate (dest .Samplerate ())
211
- frame .SetSampleFormat (dest_sample_format )
212
- frame .SetChannelLayout (dest_channel_layout )
213
-
214
207
// Return success
215
208
return ctx , frame , nil
216
209
}
217
210
218
211
func (d * demuxer ) close () error {
219
212
var result error
220
213
221
- // Free decoded frame
214
+ // Free source frame
222
215
if d .frame != nil {
223
216
ff .AVUtil_frame_free (d .frame )
224
217
}
@@ -251,16 +244,16 @@ func (d *decoder) close() error {
251
244
ff .SWScale_free_context (d .rescaler )
252
245
}
253
246
254
- // Free rescaler frame
255
- if d .reframe != nil {
256
- ff .AVUtil_frame_free (d .reframe )
257
- }
258
-
259
247
// Free destination frame
260
248
if d .frame != nil {
261
249
ff .AVUtil_frame_free (d .frame )
262
250
}
263
251
252
+ // Free rescaled/resized frame
253
+ if d .reframe != nil {
254
+ ff .AVUtil_frame_free (d .reframe )
255
+ }
256
+
264
257
// Return any errors
265
258
return result
266
259
}
@@ -313,9 +306,10 @@ FOR_LOOP:
313
306
return err
314
307
}
315
308
}
316
- // Unreference the packet
317
- ff .AVCodec_packet_unref (packet )
318
309
}
310
+
311
+ // Unreference the packet
312
+ ff .AVCodec_packet_unref (packet )
319
313
}
320
314
321
315
// Flush the decoders
@@ -332,7 +326,7 @@ FOR_LOOP:
332
326
333
327
func (d * decoder ) decode (packet * ff.AVPacket , demuxfn DecoderFunc , framefn FrameFunc ) error {
334
328
if demuxfn != nil {
335
- // Send the packet to the user defined packet function
329
+ // Send the packet (or a nil to flush) to the user defined packet function
336
330
return demuxfn (newPacket (packet ))
337
331
}
338
332
@@ -352,27 +346,49 @@ func (d *decoder) decode(packet *ff.AVPacket, demuxfn DecoderFunc, framefn Frame
352
346
}
353
347
354
348
// Resample or resize the frame, then pass to the frame function
355
- if frame , err := d .re (d .frame ); err != nil {
349
+ frame , err := d .re (d .frame )
350
+ if err != nil {
356
351
return err
357
- } else if err := framefn (newFrame (frame )); errors .Is (err , io .EOF ) {
352
+ }
353
+
354
+ // Copy over the timebase and ptr
355
+ frame .SetTimeBase (d .timeBase )
356
+ frame .SetPts (d .frame .Pts ())
357
+
358
+ // Pass back to the caller
359
+ if err := framefn (newFrame (frame )); errors .Is (err , io .EOF ) {
358
360
// End early, return EOF
359
361
result = io .EOF
360
362
break
361
363
} else if err != nil {
362
364
return err
363
365
}
366
+
367
+ // Re-allocate frames for next iteration
368
+ ff .AVUtil_frame_unref (d .frame )
369
+ ff .AVUtil_frame_unref (d .reframe )
364
370
}
365
371
366
372
// Flush the resizer or resampler if we haven't received an EOF
367
373
if result == nil {
368
- if frame , err := d .re (nil ); err != nil {
369
- return err
370
- } else if frame == nil {
371
- // NOOP
372
- } else if err := framefn (newFrame (d .frame )); errors .Is (err , io .EOF ) {
373
- // NOOP
374
- } else if err != nil {
375
- return err
374
+ finished := false
375
+ for {
376
+ if finished {
377
+ break
378
+ }
379
+ if frame , err := d .reflush (d .frame ); err != nil {
380
+ return err
381
+ } else if frame == nil {
382
+ finished = true
383
+ } else if err := framefn (newFrame (frame )); errors .Is (err , io .EOF ) {
384
+ finished = true
385
+ } else if err != nil {
386
+ return err
387
+ }
388
+
389
+ // Re-allocate frames for next iteration
390
+ ff .AVUtil_frame_unref (d .frame )
391
+ ff .AVUtil_frame_unref (d .reframe )
376
392
}
377
393
}
378
394
@@ -384,8 +400,8 @@ func (d *decoder) re(src *ff.AVFrame) (*ff.AVFrame, error) {
384
400
switch d .codec .Codec ().Type () {
385
401
case ff .AVMEDIA_TYPE_AUDIO :
386
402
if d .resampler != nil && src != nil {
387
- // Resample the audio
388
- if err := resample ( d . resampler , d .reframe , src ); err != nil {
403
+ // Resample the audio or flush if src is nil
404
+ if err := d . resample ( d .reframe , src ); err != nil {
389
405
return nil , err
390
406
} else {
391
407
return d .reframe , nil
@@ -394,7 +410,7 @@ func (d *decoder) re(src *ff.AVFrame) (*ff.AVFrame, error) {
394
410
case ff .AVMEDIA_TYPE_VIDEO :
395
411
if d .rescaler != nil && src != nil {
396
412
// Rescale the video
397
- if err := rescale ( d . rescaler , d .reframe , src ); err != nil {
413
+ if err := d . rescale ( d .reframe , src ); err != nil {
398
414
return nil , err
399
415
} else {
400
416
return d .reframe , nil
@@ -406,36 +422,58 @@ func (d *decoder) re(src *ff.AVFrame) (*ff.AVFrame, error) {
406
422
return src , nil
407
423
}
408
424
409
- func rescale (ctx * ff.SWSContext , dest , src * ff.AVFrame ) error {
410
- // Copy properties from source
411
- if err := ff .AVUtil_frame_copy_props (dest , src ); err != nil {
412
- return fmt .Errorf ("failed to copy props: %w" , err )
425
+ func (d * decoder ) reflush (src * ff.AVFrame ) (* ff.AVFrame , error ) {
426
+ switch d .codec .Codec ().Type () {
427
+ case ff .AVMEDIA_TYPE_AUDIO :
428
+ if d .resampler != nil {
429
+ if num_samples := ff .SWResample_get_delay (d .resampler , int64 (src .SampleRate ())); num_samples > 0 {
430
+ fmt .Println ("TODO there are" , num_samples , "samples left" )
431
+ }
432
+ }
433
+ }
434
+
435
+ // No flush necessary
436
+ return nil , nil
437
+ }
438
+
439
+ func (d * decoder ) rescale (dest , src * ff.AVFrame ) error {
440
+ dest .SetPixFmt (d .dest .videopar .PixelFormat )
441
+ dest .SetWidth (d .dest .videopar .Width )
442
+ dest .SetHeight (d .dest .videopar .Height )
443
+
444
+ // Allocate rescaled frame
445
+ if err := ff .AVUtil_frame_get_buffer (dest , false ); err != nil {
446
+ return fmt .Errorf ("AVUtil_frame_get_buffer: %w" , err )
413
447
}
448
+
414
449
// Perform rescale
415
- if err := ff .SWScale_scale_frame (ctx , dest , src , false ); err != nil {
450
+ if err := ff .SWScale_scale_frame (d . rescaler , dest , src , false ); err != nil {
416
451
return fmt .Errorf ("SWScale_scale_frame: %w" , err )
417
452
}
418
453
return nil
419
454
}
420
455
421
- func resample (ctx * ff.SWRContext , dest , src * ff.AVFrame ) error {
422
- // Copy properties from source
423
- //if err := ff.AVUtil_frame_copy_props(dest, src); err != nil {
424
- // return fmt.Errorf("failed to copy props: %w", err)
425
- //}
456
+ func (d * decoder ) resample (dest , src * ff.AVFrame ) error {
457
+ dest .SetChannelLayout (d .dest .audiopar .Ch )
458
+ dest .SetSampleFormat (d .dest .audiopar .SampleFormat )
459
+ dest .SetSampleRate (d .dest .audiopar .Samplerate )
426
460
427
- dest_samples , err := ff .SWResample_get_out_samples (ctx , src .NumSamples ())
428
- if err != nil {
461
+ if dest_samples , err := ff .SWResample_get_out_samples (d .resampler , src .NumSamples ()); err != nil {
429
462
return fmt .Errorf ("SWResample_get_out_samples: %w" , err )
463
+ } else {
464
+ dest .SetNumSamples (dest_samples )
465
+
466
+ }
467
+
468
+ // Allocate resampled frame
469
+ if err := ff .AVUtil_frame_get_buffer (dest , false ); err != nil {
470
+ return fmt .Errorf ("AVUtil_frame_get_buffer: %w" , err )
430
471
}
431
- dest .SetNumSamples (dest_samples )
432
- fmt .Println ("dest frame=" , dest )
433
472
434
473
// Perform resampling
435
- if err := ff .SWResample_convert_frame (ctx , src , dest ); err != nil {
474
+ if err := ff .SWResample_convert_frame (d . resampler , src , dest ); err != nil {
436
475
return fmt .Errorf ("SWResample_convert_frame: %w" , err )
437
476
}
438
-
439
477
return nil
440
478
}
441
479
0 commit comments