@@ -17,6 +17,7 @@ type Decoder struct {
17
17
stream int
18
18
codec * ff.AVCodecContext
19
19
dest * Par // Destination parameters
20
+ re * Re // Resample/resize
20
21
timeBase ff.AVRational // Timebase for the stream
21
22
frame * ff.AVFrame // Destination frame
22
23
}
@@ -25,21 +26,38 @@ type Decoder struct {
25
26
// LIFECYCLE
26
27
27
28
// Create a stream decoder which can decode packets from the input stream
28
- // TODO: resample and resize frames to the destination parameters
29
29
func NewDecoder (stream * ff.AVStream , dest * Par , force bool ) (* Decoder , error ) {
30
30
decoder := new (Decoder )
31
31
decoder .stream = stream .Id ()
32
32
decoder .dest = dest
33
33
decoder .timeBase = stream .TimeBase ()
34
34
35
+ // Create a frame for decoder output - before resize/resample
36
+ frame := ff .AVUtil_frame_alloc ()
37
+ if frame == nil {
38
+ return nil , errors .New ("failed to allocate frame" )
39
+ }
40
+
35
41
// Create a codec context for the decoder
36
42
codec := ff .AVCodec_find_decoder (stream .CodecPar ().CodecID ())
37
43
if codec == nil {
44
+ ff .AVUtil_frame_free (frame )
38
45
return nil , fmt .Errorf ("failed to find decoder for codec %q" , stream .CodecPar ().CodecID ())
39
46
} else if ctx := ff .AVCodec_alloc_context (codec ); ctx == nil {
47
+ ff .AVUtil_frame_free (frame )
40
48
return nil , fmt .Errorf ("failed to allocate codec context for codec %q" , codec .Name ())
41
49
} else {
42
50
decoder .codec = ctx
51
+ decoder .frame = frame
52
+ }
53
+
54
+ // If the destination codec parameters are not nil, then create a resample/resizer
55
+ if dest != nil {
56
+ if re , err := NewRe (dest , force ); err != nil {
57
+ return nil , errors .Join (err , decoder .Close ())
58
+ } else {
59
+ decoder .re = re
60
+ }
43
61
}
44
62
45
63
// Copy codec parameters from input stream to output codec context
@@ -52,13 +70,6 @@ func NewDecoder(stream *ff.AVStream, dest *Par, force bool) (*Decoder, error) {
52
70
return nil , errors .Join (decoder .Close (), err )
53
71
}
54
72
55
- // Create a frame for decoder output - before resize/resample
56
- if frame := ff .AVUtil_frame_alloc (); frame == nil {
57
- return nil , errors .Join (decoder .Close (), errors .New ("failed to allocate frame" ))
58
- } else {
59
- decoder .frame = frame
60
- }
61
-
62
73
// Return success
63
74
return decoder , nil
64
75
}
@@ -67,6 +78,11 @@ func NewDecoder(stream *ff.AVStream, dest *Par, force bool) (*Decoder, error) {
67
78
func (d * Decoder ) Close () error {
68
79
var result error
69
80
81
+ // Free resampler/resizer
82
+ if d .re != nil {
83
+ result = errors .Join (result , d .re .Close ())
84
+ }
85
+
70
86
// Free the codec context
71
87
if d .codec != nil {
72
88
ff .AVCodec_free_context (d .codec )
@@ -77,30 +93,38 @@ func (d *Decoder) Close() error {
77
93
ff .AVUtil_frame_free (d .frame )
78
94
}
79
95
96
+ // Reset fields
97
+ d .re = nil
98
+ d .codec = nil
99
+ d .frame = nil
100
+
80
101
// Return any errors
81
102
return result
82
103
}
83
104
84
105
////////////////////////////////////////////////////////////////////////////////
85
106
// PUBLIC METHODS
86
107
108
+ // Decode a packet into a set of frames to pass back to the
109
+ // DecoderFrameFn. If the packet is nil, then the decoder will
110
+ // flush any remaining frames.
111
+ // TODO: Optionally use the user defined packet function
112
+ // if they want to use AVParser
113
+ // TODO: The frame sent to DecoderFrameFn needs to have the
114
+ // correct timebase, etc set
87
115
func (d * Decoder ) decode (packet * ff.AVPacket , fn DecoderFrameFn ) error {
88
116
if fn == nil {
89
117
return errors .New ("DecoderFrameFn is nil" )
90
118
}
91
119
92
- //if demuxfn != nil {
93
- // Send the packet (or a nil to flush) to the user defined packet function
94
- // return demuxfn(newPacket(packet, d.stream, d.codec.Codec().Type(), d.timeBase))
95
- //}
96
-
97
120
// Submit the packet to the decoder (nil packet will flush the decoder)
98
121
if err := ff .AVCodec_send_packet (d .codec , packet ); err != nil {
99
122
return err
100
123
}
101
124
102
125
// get all the available frames from the decoder
103
126
var result error
127
+ var dest * Frame
104
128
for {
105
129
// End early if we've received an EOF
106
130
if result != nil {
@@ -115,25 +139,38 @@ func (d *Decoder) decode(packet *ff.AVPacket, fn DecoderFrameFn) error {
115
139
return err
116
140
}
117
141
142
+ // Obtain the output frame. If a new frame is returned, it is
143
+ // managed by the rescaler/resizer and no need to unreference it
144
+ // later.
145
+ if d .re != nil {
146
+ if frame , err := d .re .Frame ((* Frame )(d .frame )); err != nil {
147
+ result = errors .Join (result , err )
148
+ } else {
149
+ dest = frame
150
+ }
151
+ } else {
152
+ dest = (* Frame )(d .frame )
153
+ }
154
+
118
155
// TODO: Modify Pts?
156
+ // What else do we need to copy across?
157
+ fmt .Println ("TODO" , d .timeBase , dest .TimeBase (), ff .AVTimestamp (dest .Pts ()))
158
+ if dest .Pts () == PTS_UNDEFINED {
159
+ (* ff .AVFrame )(dest ).SetPts (d .frame .Pts ())
160
+ }
119
161
120
162
// Pass back to the caller
121
- if err := fn (d .stream , ( * Frame )( d . frame ) ); errors .Is (err , io .EOF ) {
163
+ if err := fn (d .stream , dest ); errors .Is (err , io .EOF ) {
122
164
// End early, return EOF
123
165
result = io .EOF
124
166
} else if err != nil {
125
167
return err
126
168
}
127
169
128
- // Re-allocate frames for next iteration
170
+ // Re-allocate frame for next iteration
129
171
ff .AVUtil_frame_unref (d .frame )
130
172
}
131
173
132
- // Flush
133
- if err := fn (d .stream , nil ); err != nil && ! errors .Is (err , io .EOF ) {
134
- result = errors .Join (result , err )
135
- }
136
-
137
174
// Return success or EOF
138
175
return result
139
176
}
0 commit comments