Files

248 lines
5.5 KiB
Go
Raw Permalink Normal View History

2016-07-30 14:36:47 +08:00
// Package transcoder implements Transcoder based on Muxer/Demuxer and AudioEncoder/AudioDecoder interface.
2016-06-06 22:15:51 +08:00
package transcode
import (
2016-06-07 18:14:05 +08:00
"fmt"
2016-06-22 19:19:48 +08:00
"time"
2016-07-01 21:45:15 +08:00
"github.com/nareix/joy4/av"
"github.com/nareix/joy4/av/pktque"
2016-06-06 22:15:51 +08:00
)
2016-07-12 13:14:08 +08:00
var Debug bool
2016-06-07 18:14:05 +08:00
2016-06-22 19:19:48 +08:00
type tStream struct {
codec av.CodecData
timeline *pktque.Timeline
aencodec, adecodec av.AudioCodecData
2016-06-06 22:15:51 +08:00
aenc av.AudioEncoder
adec av.AudioDecoder
}
2016-07-12 12:23:16 +08:00
type Options struct {
2016-07-30 13:32:43 +08:00
// 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,
)
2016-07-12 12:23:16 +08:00
}
type Transcoder struct {
2016-06-22 19:19:48 +08:00
streams []*tStream
2016-06-06 22:15:51 +08:00
}
2016-07-12 12:23:16 +08:00
func NewTranscoder(streams []av.CodecData, options Options) (_self *Transcoder, err error) {
self := &Transcoder{}
2016-06-22 19:19:48 +08:00
self.streams = []*tStream{}
2016-06-07 18:14:05 +08:00
for i, stream := range streams {
2016-06-22 19:19:48 +08:00
ts := &tStream{codec: stream}
if stream.Type().IsAudio() {
2016-07-12 12:23:16 +08:00
if options.FindAudioDecoderEncoder != nil {
2016-06-06 22:15:51 +08:00
var ok bool
var enc av.AudioEncoder
var dec av.AudioDecoder
2016-07-16 12:38:09 +08:00
ok, dec, enc, err = options.FindAudioDecoderEncoder(stream.(av.AudioCodecData), i)
2016-06-06 22:15:51 +08:00
if ok {
if err != nil {
return
}
2016-06-22 19:19:48 +08:00
ts.timeline = &pktque.Timeline{}
if ts.codec, err = enc.CodecData(); err != nil {
return
}
2016-06-22 19:19:48 +08:00
ts.aencodec = ts.codec.(av.AudioCodecData)
ts.adecodec = stream.(av.AudioCodecData)
2016-06-06 22:15:51 +08:00
ts.aenc = enc
ts.adec = dec
}
}
}
self.streams = append(self.streams, ts)
}
2016-07-12 12:23:16 +08:00
_self = self
2016-06-06 22:15:51 +08:00
return
}
2016-06-22 19:19:48 +08:00
func (self *tStream) audioDecodeAndEncode(inpkt av.Packet) (outpkts []av.Packet, err error) {
var dur time.Duration
2016-06-07 18:14:05 +08:00
var frame av.AudioFrame
var ok bool
2016-06-22 19:19:48 +08:00
if ok, frame, err = self.adec.Decode(inpkt.Data); err != nil {
2016-06-07 18:14:05 +08:00
return
}
2016-06-22 19:19:48 +08:00
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
}
2016-07-12 13:14:08 +08:00
if Debug {
2016-06-22 19:19:48 +08:00
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)
2016-06-06 22:15:51 +08:00
return
}
2016-06-22 19:19:48 +08:00
outpkt := av.Packet{Idx: inpkt.Idx, Data: _outpkt}
outpkt.Time = self.timeline.Pop(dur)
2016-07-12 13:14:08 +08:00
if Debug {
2016-06-30 22:51:35 +08:00
fmt.Println("transcode: pop", outpkt.Time, dur)
2016-06-06 22:15:51 +08:00
}
2016-06-22 19:19:48 +08:00
outpkts = append(outpkts, outpkt)
2016-06-06 22:15:51 +08:00
}
2016-06-22 19:19:48 +08:00
2016-06-06 22:15:51 +08:00
return
}
2016-07-30 13:08:26 +08:00
// Do the transcode.
//
2016-07-30 13:32:43 +08:00
// In audio transcoding one Packet may transcode into many Packets
// packet time will be adjusted automatically.
2016-06-22 19:19:48 +08:00
func (self *Transcoder) Do(pkt av.Packet) (out []av.Packet, err error) {
stream := self.streams[pkt.Idx]
2016-06-07 18:14:05 +08:00
if stream.aenc != nil && stream.adec != nil {
2016-06-22 19:19:48 +08:00
if out, err = stream.audioDecodeAndEncode(pkt); err != nil {
return
2016-06-07 18:14:05 +08:00
}
} else {
2016-06-22 19:19:48 +08:00
out = append(out, pkt)
2016-06-07 18:14:05 +08:00
}
return
}
2016-07-30 13:32:43 +08:00
// Get CodecDatas after transcoding.
2016-06-12 08:53:06 +08:00
func (self *Transcoder) Streams() (streams []av.CodecData, err error) {
2016-06-06 22:15:51 +08:00
for _, stream := range self.streams {
2016-06-22 19:19:48 +08:00
streams = append(streams, stream.codec)
2016-06-06 22:15:51 +08:00
}
return
}
2016-07-30 13:32:43 +08:00
// Close transcoder, close related encoder and decoders.
2016-07-12 12:23:16 +08:00
func (self *Transcoder) Close() (err error) {
2016-06-06 22:15:51 +08:00
for _, stream := range self.streams {
if stream.aenc != nil {
stream.aenc.Close()
2016-06-22 19:19:48 +08:00
stream.aenc = nil
2016-06-06 22:15:51 +08:00
}
if stream.adec != nil {
stream.adec.Close()
2016-06-22 19:19:48 +08:00
stream.adec = nil
2016-06-06 22:15:51 +08:00
}
}
2016-07-12 12:23:16 +08:00
self.streams = nil
return
2016-06-06 22:15:51 +08:00
}
2016-07-30 13:08:26 +08:00
// Wrap transcoder and origin Muxer into new Muxer.
2016-07-30 13:32:43 +08:00
// Write to new Muxer will do transcoding automatically.
2016-06-06 22:15:51 +08:00
type Muxer struct {
2016-07-30 13:08:26 +08:00
av.Muxer // origin Muxer
Options // transcode options
2016-07-30 13:32:43 +08:00
transcoder *Transcoder
2016-06-06 22:15:51 +08:00
}
func (self *Muxer) WriteHeader(streams []av.CodecData) (err error) {
2016-07-12 12:23:16 +08:00
if self.transcoder, err = NewTranscoder(streams, self.Options); err != nil {
2016-06-06 22:15:51 +08:00
return
}
2016-06-12 08:53:06 +08:00
var newstreams []av.CodecData
2016-07-12 12:23:16 +08:00
if newstreams, err = self.transcoder.Streams(); err != nil {
2016-06-12 08:53:06 +08:00
return
}
if err = self.Muxer.WriteHeader(newstreams); err != nil {
2016-06-06 22:15:51 +08:00
return
}
return
}
2016-06-22 19:19:48 +08:00
func (self *Muxer) WritePacket(pkt av.Packet) (err error) {
var outpkts []av.Packet
2016-07-12 12:23:16 +08:00
if outpkts, err = self.transcoder.Do(pkt); err != nil {
2016-06-22 19:19:48 +08:00
return
}
for _, pkt := range outpkts {
if err = self.Muxer.WritePacket(pkt); err != nil {
2016-06-06 22:15:51 +08:00
return
}
}
return
}
2016-07-12 12:23:16 +08:00
func (self *Muxer) Close() (err error) {
if self.transcoder != nil {
return self.transcoder.Close()
}
return
2016-06-06 22:15:51 +08:00
}
2016-07-30 13:08:26 +08:00
// Wrap transcoder and origin Demuxer into new Demuxer.
2016-07-30 13:32:43 +08:00
// Read this Demuxer will do transcoding automatically.
2016-06-06 22:15:51 +08:00
type Demuxer struct {
2016-07-12 12:23:16 +08:00
av.Demuxer
2016-07-30 13:32:43 +08:00
Options
2016-07-12 12:23:16 +08:00
transcoder *Transcoder
2016-06-22 19:19:48 +08:00
outpkts []av.Packet
2016-06-06 22:15:51 +08:00
}
2016-07-12 12:23:16 +08:00
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
}
2016-06-06 22:15:51 +08:00
}
return
}
2016-06-22 19:19:48 +08:00
func (self *Demuxer) ReadPacket() (pkt av.Packet, err error) {
2016-07-12 12:23:16 +08:00
if err = self.prepare(); err != nil {
return
}
2016-06-06 22:15:51 +08:00
for {
2016-06-22 19:19:48 +08:00
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
}
2016-07-12 12:23:16 +08:00
if self.outpkts, err = self.transcoder.Do(rpkt); err != nil {
2016-06-07 18:14:05 +08:00
return
2016-06-06 22:15:51 +08:00
}
}
2016-06-22 19:19:48 +08:00
return
2016-06-06 22:15:51 +08:00
}
2016-07-12 12:23:16 +08:00
func (self *Demuxer) Streams() (streams []av.CodecData, err error) {
if err = self.prepare(); err != nil {
return
}
return self.transcoder.Streams()
2016-06-06 22:15:51 +08:00
}
2016-07-12 12:23:16 +08:00
func (self *Demuxer) Close() (err error) {
if self.transcoder != nil {
return self.transcoder.Close()
}
return
2016-06-06 22:15:51 +08:00
}