forked from nareix/joy4
-
Notifications
You must be signed in to change notification settings - Fork 2
/
transcode.go
247 lines (219 loc) · 5.49 KB
/
transcode.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
// Package transcoder implements Transcoder based on Muxer/Demuxer and AudioEncoder/AudioDecoder interface.
package transcode
import (
"fmt"
"time"
"github.com/Danile71/joy4/av"
"github.com/Danile71/joy4/av/pktque"
)
var Debug bool
type tStream struct {
codec av.CodecData
timeline *pktque.Timeline
aencodec, adecodec av.AudioCodecData
aenc av.AudioEncoder
adec av.AudioDecoder
}
type Options struct {
// check if transcode is needed, and create the AudioDecoder and AudioEncoder.
FindAudioDecoderEncoder func(codec av.AudioCodecData, i int) (
need bool, dec av.AudioDecoder, enc av.AudioEncoder, err error,
)
}
type Transcoder struct {
streams []*tStream
}
func NewTranscoder(streams []av.CodecData, options Options) (_self *Transcoder, err error) {
self := &Transcoder{}
self.streams = []*tStream{}
for i, stream := range streams {
ts := &tStream{codec: stream}
if stream.Type().IsAudio() {
if options.FindAudioDecoderEncoder != nil {
var ok bool
var enc av.AudioEncoder
var dec av.AudioDecoder
ok, dec, enc, err = options.FindAudioDecoderEncoder(stream.(av.AudioCodecData), i)
if ok {
if err != nil {
return
}
ts.timeline = &pktque.Timeline{}
if ts.codec, err = enc.CodecData(); err != nil {
return
}
ts.aencodec = ts.codec.(av.AudioCodecData)
ts.adecodec = stream.(av.AudioCodecData)
ts.aenc = enc
ts.adec = dec
}
}
}
self.streams = append(self.streams, ts)
}
_self = self
return
}
func (self *tStream) audioDecodeAndEncode(inpkt av.Packet) (outpkts []av.Packet, err error) {
var dur time.Duration
var frame av.AudioFrame
var ok bool
if ok, frame, err = self.adec.Decode(inpkt.Data); err != nil {
return
}
if !ok {
return
}
if dur, err = self.adecodec.PacketDuration(inpkt.Data); err != nil {
err = fmt.Errorf("transcode: PacketDuration() failed for input stream #%d", inpkt.Idx)
return
}
if Debug {
fmt.Println("transcode: push", inpkt.Time, dur)
}
self.timeline.Push(inpkt.Time, dur)
var _outpkts [][]byte
if _outpkts, err = self.aenc.Encode(frame); err != nil {
return
}
for _, _outpkt := range _outpkts {
if dur, err = self.aencodec.PacketDuration(_outpkt); err != nil {
err = fmt.Errorf("transcode: PacketDuration() failed for output stream #%d", inpkt.Idx)
return
}
outpkt := av.Packet{Idx: inpkt.Idx, Data: _outpkt}
outpkt.Time = self.timeline.Pop(dur)
if Debug {
fmt.Println("transcode: pop", outpkt.Time, dur)
}
outpkts = append(outpkts, outpkt)
}
return
}
// Do the transcode.
//
// In audio transcoding one Packet may transcode into many Packets
// packet time will be adjusted automatically.
func (self *Transcoder) Do(pkt av.Packet) (out []av.Packet, err error) {
stream := self.streams[pkt.Idx]
if stream.aenc != nil && stream.adec != nil {
if out, err = stream.audioDecodeAndEncode(pkt); err != nil {
return
}
} else {
out = append(out, pkt)
}
return
}
// Get CodecDatas after transcoding.
func (self *Transcoder) Streams() (streams []av.CodecData, err error) {
for _, stream := range self.streams {
streams = append(streams, stream.codec)
}
return
}
// Close transcoder, close related encoder and decoders.
func (self *Transcoder) Close() (err error) {
for _, stream := range self.streams {
if stream.aenc != nil {
stream.aenc.Close()
stream.aenc = nil
}
if stream.adec != nil {
stream.adec.Close()
stream.adec = nil
}
}
self.streams = nil
return
}
// Wrap transcoder and origin Muxer into new Muxer.
// Write to new Muxer will do transcoding automatically.
type Muxer struct {
av.Muxer // origin Muxer
Options // transcode options
transcoder *Transcoder
}
func (self *Muxer) WriteHeader(streams []av.CodecData) (err error) {
if self.transcoder, err = NewTranscoder(streams, self.Options); err != nil {
return
}
var newstreams []av.CodecData
if newstreams, err = self.transcoder.Streams(); err != nil {
return
}
if err = self.Muxer.WriteHeader(newstreams); err != nil {
return
}
return
}
func (self *Muxer) WritePacket(pkt av.Packet) (err error) {
var outpkts []av.Packet
if outpkts, err = self.transcoder.Do(pkt); err != nil {
return
}
for _, pkt := range outpkts {
if err = self.Muxer.WritePacket(pkt); err != nil {
return
}
}
return
}
func (self *Muxer) Close() (err error) {
if self.transcoder != nil {
return self.transcoder.Close()
}
return
}
// Wrap transcoder and origin Demuxer into new Demuxer.
// Read this Demuxer will do transcoding automatically.
type Demuxer struct {
av.Demuxer
Options
transcoder *Transcoder
outpkts []av.Packet
}
func (self *Demuxer) prepare() (err error) {
if self.transcoder == nil {
var streams []av.CodecData
if streams, err = self.Demuxer.Streams(); err != nil {
return
}
if self.transcoder, err = NewTranscoder(streams, self.Options); err != nil {
return
}
}
return
}
func (self *Demuxer) ReadPacket() (pkt av.Packet, err error) {
if err = self.prepare(); err != nil {
return
}
for {
if len(self.outpkts) > 0 {
pkt = self.outpkts[0]
self.outpkts = self.outpkts[1:]
return
}
var rpkt av.Packet
if rpkt, err = self.Demuxer.ReadPacket(); err != nil {
return
}
if self.outpkts, err = self.transcoder.Do(rpkt); err != nil {
return
}
}
return
}
func (self *Demuxer) Streams() (streams []av.CodecData, err error) {
if err = self.prepare(); err != nil {
return
}
return self.transcoder.Streams()
}
func (self *Demuxer) Close() (err error) {
if self.transcoder != nil {
return self.transcoder.Close()
}
return
}