Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
|
f16bc99590 |
|
@ -22,11 +22,8 @@ _testmain.go
|
||||||
# built binaries
|
# built binaries
|
||||||
uplink
|
uplink
|
||||||
*.exe
|
*.exe
|
||||||
*.dll
|
|
||||||
*.test
|
*.test
|
||||||
|
|
||||||
*.orig
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
# Windows image file caches
|
# Windows image file caches
|
||||||
|
|
|
@ -17,8 +17,6 @@ type Channel struct {
|
||||||
OutputStreams map[string]*media.MediaStream
|
OutputStreams map[string]*media.MediaStream
|
||||||
|
|
||||||
Events *pubsub.PubSub
|
Events *pubsub.PubSub
|
||||||
|
|
||||||
lastMetadata map[string]string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) AddInputStream(id string) *media.MediaStream {
|
func (channel *Channel) AddInputStream(id string) *media.MediaStream {
|
||||||
|
@ -52,17 +50,12 @@ func (channel *Channel) AddOutputContainer(id string) *media.MediaStreamContaine
|
||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) SetMetadata(data map[string]string) {
|
func (channel *Channel) SetMetadata(data map[string]string) {
|
||||||
channel.lastMetadata = data
|
|
||||||
channel.Events.Pub(data, "metadata")
|
channel.Events.Pub(data, "metadata")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) Metadata() chan map[string]string {
|
func (channel *Channel) Metadata() chan map[string]string {
|
||||||
outC := make(chan map[string]string)
|
outC := make(chan map[string]string)
|
||||||
go func() {
|
go func() {
|
||||||
defer close(outC)
|
|
||||||
if channel.lastMetadata != nil {
|
|
||||||
outC <- channel.lastMetadata
|
|
||||||
}
|
|
||||||
c := channel.Events.Sub("metadata")
|
c := channel.Events.Sub("metadata")
|
||||||
forloop:
|
forloop:
|
||||||
for event := range c {
|
for event := range c {
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
package genericapi
|
|
||||||
|
|
||||||
type DynamicallyConfigurable interface {
|
|
||||||
MakeConfigurationObject() interface{}
|
|
||||||
ValidateConfiguration(config interface{}) bool
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
package codecs
|
|
||||||
|
|
||||||
//go:generate go run ./internal/generator/main.go
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,83 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func must(err error) {
|
|
||||||
if err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cmd := exec.Command("ffmpeg", "-codecs")
|
|
||||||
outputBytes, err := cmd.Output()
|
|
||||||
must(err)
|
|
||||||
|
|
||||||
code := `package codecs
|
|
||||||
|
|
||||||
var (
|
|
||||||
`
|
|
||||||
|
|
||||||
bufreader := bufio.NewScanner(bytes.NewReader(outputBytes))
|
|
||||||
|
|
||||||
/*Encoders:
|
|
||||||
V..... = Video
|
|
||||||
A..... = Audio
|
|
||||||
S..... = Subtitle
|
|
||||||
.F.... = Frame-level multithreading
|
|
||||||
..S... = Slice-level multithreading
|
|
||||||
...X.. = Codec is experimental
|
|
||||||
....B. = Supports draw_horiz_band
|
|
||||||
.....D = Supports direct rendering method 1
|
|
||||||
------
|
|
||||||
V..... a64multi Multicolor charset for Commodore 64 (codec a64_multi)
|
|
||||||
V..... a64multi5 Multicolor charset for Commodore 64, extended with 5th color (colram) (codec a64_multi5)*/
|
|
||||||
|
|
||||||
waitingForList := true
|
|
||||||
for bufreader.Scan() && waitingForList {
|
|
||||||
text := bufreader.Text()
|
|
||||||
if text == " -------" {
|
|
||||||
waitingForList = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for bufreader.Scan() {
|
|
||||||
text := bufreader.Text()
|
|
||||||
//isVideo := text[1] == 'V'
|
|
||||||
//isAudio := text[1] == 'A'
|
|
||||||
//isSubtitle := text[1] == 'S'
|
|
||||||
|
|
||||||
text = text[8:]
|
|
||||||
cols := strings.Fields(text)
|
|
||||||
|
|
||||||
id := cols[0]
|
|
||||||
name := strings.Join(cols[1:], " ")
|
|
||||||
code += fmt.Sprintf(`
|
|
||||||
// %s
|
|
||||||
Codec_%s = %q
|
|
||||||
`, name, strings.ToUpper(id), id)
|
|
||||||
}
|
|
||||||
|
|
||||||
code += `
|
|
||||||
)
|
|
||||||
`
|
|
||||||
|
|
||||||
codeBytes, err := format.Source([]byte(code))
|
|
||||||
must(err)
|
|
||||||
|
|
||||||
f, err := os.Create("gen_codecs.go")
|
|
||||||
must(err)
|
|
||||||
defer f.Close()
|
|
||||||
_, err = f.Write(codeBytes)
|
|
||||||
must(err)
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
package demux
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"git.icedream.tech/icedream/uplink/app/media"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Demuxer interface {
|
|
||||||
NewInstance(r io.Reader) <-DemuxerInstance
|
|
||||||
}
|
|
||||||
|
|
||||||
type DemuxerInstance interface {
|
|
||||||
Error() error
|
|
||||||
Reader() io.Reader
|
|
||||||
ContainerInfo() *media.MediaStreamContainerInfo
|
|
||||||
}
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -14,7 +13,7 @@ import (
|
||||||
func Test_Demux(t *testing.T) {
|
func Test_Demux(t *testing.T) {
|
||||||
Convey("Demuxer", t, func() {
|
Convey("Demuxer", t, func() {
|
||||||
Convey("audio-only", func() {
|
Convey("audio-only", func() {
|
||||||
reader, _ := os.Open(filepath.Join("testassets", "mpthreetest.mp3"))
|
reader, _ := os.Open("mpthreetest.mp3")
|
||||||
defer reader.Close()
|
defer reader.Close()
|
||||||
|
|
||||||
demuxer := Demux(reader)
|
demuxer := Demux(reader)
|
||||||
|
@ -29,7 +28,7 @@ func Test_Demux(t *testing.T) {
|
||||||
So(audioStream, ShouldBeNil)
|
So(audioStream, ShouldBeNil)
|
||||||
So(stream.StreamId, ShouldEqual, 0)
|
So(stream.StreamId, ShouldEqual, 0)
|
||||||
So(stream.Pts, ShouldEqual, 0)
|
So(stream.Pts, ShouldEqual, 0)
|
||||||
So(stream.CodecInfo.CodecName, ShouldBeIn, []string{"mp3", "mp3float"})
|
So(stream.CodecInfo.CodecName, ShouldEqual, "mp3")
|
||||||
So(stream.CodecInfo.Type, ShouldEqual, Audio)
|
So(stream.CodecInfo.Type, ShouldEqual, Audio)
|
||||||
audioStream = stream
|
audioStream = stream
|
||||||
}
|
}
|
||||||
|
@ -44,7 +43,7 @@ func Test_Demux(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("video and audio", func() {
|
Convey("video and audio", func() {
|
||||||
reader, _ := os.Open(filepath.Join("testassets", "small.ogv"))
|
reader, _ := os.Open("small.ogv")
|
||||||
defer reader.Close()
|
defer reader.Close()
|
||||||
|
|
||||||
demuxer := Demux(reader)
|
demuxer := Demux(reader)
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
package formats
|
|
||||||
|
|
||||||
//go:generate go run ./internal/generator/main.go
|
|
|
@ -1,839 +0,0 @@
|
||||||
package formats
|
|
||||||
|
|
||||||
var (
|
|
||||||
|
|
||||||
// 3GP (3GPP file format)
|
|
||||||
Format_3GP = "3gp"
|
|
||||||
// 3GP (3GPP file format)
|
|
||||||
Mux_Format_3GP = Format_3GP
|
|
||||||
|
|
||||||
// a64 - video for Commodore 64
|
|
||||||
Format_A64 = "a64"
|
|
||||||
// a64 - video for Commodore 64
|
|
||||||
Mux_Format_A64 = Format_A64
|
|
||||||
|
|
||||||
// raw AC-3
|
|
||||||
Format_AC3 = "ac3"
|
|
||||||
// raw AC-3
|
|
||||||
Mux_Format_AC3 = Format_AC3
|
|
||||||
|
|
||||||
// ADTS AAC (Advanced Audio Coding)
|
|
||||||
Format_ADTS = "adts"
|
|
||||||
// ADTS AAC (Advanced Audio Coding)
|
|
||||||
Mux_Format_ADTS = Format_ADTS
|
|
||||||
|
|
||||||
// CRI ADX
|
|
||||||
Format_ADX = "adx"
|
|
||||||
// CRI ADX
|
|
||||||
Mux_Format_ADX = Format_ADX
|
|
||||||
|
|
||||||
// Audio IFF
|
|
||||||
Format_AIFF = "aiff"
|
|
||||||
// Audio IFF
|
|
||||||
Mux_Format_AIFF = Format_AIFF
|
|
||||||
|
|
||||||
// PCM A-law
|
|
||||||
Format_ALAW = "alaw"
|
|
||||||
// PCM A-law
|
|
||||||
Mux_Format_ALAW = Format_ALAW
|
|
||||||
|
|
||||||
// ALSA audio output
|
|
||||||
Format_ALSA = "alsa"
|
|
||||||
// ALSA audio output
|
|
||||||
Mux_Format_ALSA = Format_ALSA
|
|
||||||
|
|
||||||
// 3GPP AMR
|
|
||||||
Format_AMR = "amr"
|
|
||||||
// 3GPP AMR
|
|
||||||
Mux_Format_AMR = Format_AMR
|
|
||||||
|
|
||||||
// Animated Portable Network Graphics
|
|
||||||
Format_APNG = "apng"
|
|
||||||
// Animated Portable Network Graphics
|
|
||||||
Mux_Format_APNG = Format_APNG
|
|
||||||
|
|
||||||
// raw aptX (Audio Processing Technology for Bluetooth)
|
|
||||||
Format_APTX = "aptx"
|
|
||||||
// raw aptX (Audio Processing Technology for Bluetooth)
|
|
||||||
Mux_Format_APTX = Format_APTX
|
|
||||||
|
|
||||||
// raw aptX HD (Audio Processing Technology for Bluetooth)
|
|
||||||
Format_APTX_HD = "aptx_hd"
|
|
||||||
// raw aptX HD (Audio Processing Technology for Bluetooth)
|
|
||||||
Mux_Format_APTX_HD = Format_APTX_HD
|
|
||||||
|
|
||||||
// ASF (Advanced / Active Streaming Format)
|
|
||||||
Format_ASF = "asf"
|
|
||||||
// ASF (Advanced / Active Streaming Format)
|
|
||||||
Mux_Format_ASF = Format_ASF
|
|
||||||
|
|
||||||
// ASF (Advanced / Active Streaming Format)
|
|
||||||
Format_ASF_STREAM = "asf_stream"
|
|
||||||
// ASF (Advanced / Active Streaming Format)
|
|
||||||
Mux_Format_ASF_STREAM = Format_ASF_STREAM
|
|
||||||
|
|
||||||
// SSA (SubStation Alpha) subtitle
|
|
||||||
Format_ASS = "ass"
|
|
||||||
// SSA (SubStation Alpha) subtitle
|
|
||||||
Mux_Format_ASS = Format_ASS
|
|
||||||
|
|
||||||
// AST (Audio Stream)
|
|
||||||
Format_AST = "ast"
|
|
||||||
// AST (Audio Stream)
|
|
||||||
Mux_Format_AST = Format_AST
|
|
||||||
|
|
||||||
// Sun AU
|
|
||||||
Format_AU = "au"
|
|
||||||
// Sun AU
|
|
||||||
Mux_Format_AU = Format_AU
|
|
||||||
|
|
||||||
// AVI (Audio Video Interleaved)
|
|
||||||
Format_AVI = "avi"
|
|
||||||
// AVI (Audio Video Interleaved)
|
|
||||||
Mux_Format_AVI = Format_AVI
|
|
||||||
|
|
||||||
// SWF (ShockWave Flash) (AVM2)
|
|
||||||
Format_AVM2 = "avm2"
|
|
||||||
// SWF (ShockWave Flash) (AVM2)
|
|
||||||
Mux_Format_AVM2 = Format_AVM2
|
|
||||||
|
|
||||||
// G.729 BIT file format
|
|
||||||
Format_BIT = "bit"
|
|
||||||
// G.729 BIT file format
|
|
||||||
Mux_Format_BIT = Format_BIT
|
|
||||||
|
|
||||||
// Apple CAF (Core Audio Format)
|
|
||||||
Format_CAF = "caf"
|
|
||||||
// Apple CAF (Core Audio Format)
|
|
||||||
Mux_Format_CAF = Format_CAF
|
|
||||||
|
|
||||||
// raw Chinese AVS (Audio Video Standard) video
|
|
||||||
Format_CAVSVIDEO = "cavsvideo"
|
|
||||||
// raw Chinese AVS (Audio Video Standard) video
|
|
||||||
Mux_Format_CAVSVIDEO = Format_CAVSVIDEO
|
|
||||||
|
|
||||||
// codec2 .c2 muxer
|
|
||||||
Format_CODEC2 = "codec2"
|
|
||||||
// codec2 .c2 muxer
|
|
||||||
Mux_Format_CODEC2 = Format_CODEC2
|
|
||||||
|
|
||||||
// raw codec2 muxer
|
|
||||||
Format_CODEC2RAW = "codec2raw"
|
|
||||||
// raw codec2 muxer
|
|
||||||
Mux_Format_CODEC2RAW = Format_CODEC2RAW
|
|
||||||
|
|
||||||
// CRC testing
|
|
||||||
Format_CRC = "crc"
|
|
||||||
// CRC testing
|
|
||||||
Mux_Format_CRC = Format_CRC
|
|
||||||
|
|
||||||
// DASH Muxer
|
|
||||||
Format_DASH = "dash"
|
|
||||||
// DASH Muxer
|
|
||||||
Mux_Format_DASH = Format_DASH
|
|
||||||
|
|
||||||
// raw data
|
|
||||||
Format_DATA = "data"
|
|
||||||
// raw data
|
|
||||||
Mux_Format_DATA = Format_DATA
|
|
||||||
|
|
||||||
// D-Cinema audio
|
|
||||||
Format_DAUD = "daud"
|
|
||||||
// D-Cinema audio
|
|
||||||
Mux_Format_DAUD = Format_DAUD
|
|
||||||
|
|
||||||
// raw Dirac
|
|
||||||
Format_DIRAC = "dirac"
|
|
||||||
// raw Dirac
|
|
||||||
Mux_Format_DIRAC = Format_DIRAC
|
|
||||||
|
|
||||||
// raw DNxHD (SMPTE VC-3)
|
|
||||||
Format_DNXHD = "dnxhd"
|
|
||||||
// raw DNxHD (SMPTE VC-3)
|
|
||||||
Mux_Format_DNXHD = Format_DNXHD
|
|
||||||
|
|
||||||
// raw DTS
|
|
||||||
Format_DTS = "dts"
|
|
||||||
// raw DTS
|
|
||||||
Mux_Format_DTS = Format_DTS
|
|
||||||
|
|
||||||
// DV (Digital Video)
|
|
||||||
Format_DV = "dv"
|
|
||||||
// DV (Digital Video)
|
|
||||||
Mux_Format_DV = Format_DV
|
|
||||||
|
|
||||||
// MPEG-2 PS (DVD VOB)
|
|
||||||
Format_DVD = "dvd"
|
|
||||||
// MPEG-2 PS (DVD VOB)
|
|
||||||
Mux_Format_DVD = Format_DVD
|
|
||||||
|
|
||||||
// raw E-AC-3
|
|
||||||
Format_EAC3 = "eac3"
|
|
||||||
// raw E-AC-3
|
|
||||||
Mux_Format_EAC3 = Format_EAC3
|
|
||||||
|
|
||||||
// PCM 32-bit floating-point big-endian
|
|
||||||
Format_F32BE = "f32be"
|
|
||||||
// PCM 32-bit floating-point big-endian
|
|
||||||
Mux_Format_F32BE = Format_F32BE
|
|
||||||
|
|
||||||
// PCM 32-bit floating-point little-endian
|
|
||||||
Format_F32LE = "f32le"
|
|
||||||
// PCM 32-bit floating-point little-endian
|
|
||||||
Mux_Format_F32LE = Format_F32LE
|
|
||||||
|
|
||||||
// F4V Adobe Flash Video
|
|
||||||
Format_F4V = "f4v"
|
|
||||||
// F4V Adobe Flash Video
|
|
||||||
Mux_Format_F4V = Format_F4V
|
|
||||||
|
|
||||||
// PCM 64-bit floating-point big-endian
|
|
||||||
Format_F64BE = "f64be"
|
|
||||||
// PCM 64-bit floating-point big-endian
|
|
||||||
Mux_Format_F64BE = Format_F64BE
|
|
||||||
|
|
||||||
// PCM 64-bit floating-point little-endian
|
|
||||||
Format_F64LE = "f64le"
|
|
||||||
// PCM 64-bit floating-point little-endian
|
|
||||||
Mux_Format_F64LE = Format_F64LE
|
|
||||||
|
|
||||||
// Linux framebuffer
|
|
||||||
Format_FBDEV = "fbdev"
|
|
||||||
// Linux framebuffer
|
|
||||||
Mux_Format_FBDEV = Format_FBDEV
|
|
||||||
|
|
||||||
// FFmpeg metadata in text
|
|
||||||
Format_FFMETADATA = "ffmetadata"
|
|
||||||
// FFmpeg metadata in text
|
|
||||||
Mux_Format_FFMETADATA = Format_FFMETADATA
|
|
||||||
|
|
||||||
// FIFO queue pseudo-muxer
|
|
||||||
Format_FIFO = "fifo"
|
|
||||||
// FIFO queue pseudo-muxer
|
|
||||||
Mux_Format_FIFO = Format_FIFO
|
|
||||||
|
|
||||||
// Fifo test muxer
|
|
||||||
Format_FIFO_TEST = "fifo_test"
|
|
||||||
// Fifo test muxer
|
|
||||||
Mux_Format_FIFO_TEST = Format_FIFO_TEST
|
|
||||||
|
|
||||||
// Sega FILM / CPK
|
|
||||||
Format_FILM_CPK = "film_cpk"
|
|
||||||
// Sega FILM / CPK
|
|
||||||
Mux_Format_FILM_CPK = Format_FILM_CPK
|
|
||||||
|
|
||||||
// Adobe Filmstrip
|
|
||||||
Format_FILMSTRIP = "filmstrip"
|
|
||||||
// Adobe Filmstrip
|
|
||||||
Mux_Format_FILMSTRIP = Format_FILMSTRIP
|
|
||||||
|
|
||||||
// Flexible Image Transport System
|
|
||||||
Format_FITS = "fits"
|
|
||||||
// Flexible Image Transport System
|
|
||||||
Mux_Format_FITS = Format_FITS
|
|
||||||
|
|
||||||
// raw FLAC
|
|
||||||
Format_FLAC = "flac"
|
|
||||||
// raw FLAC
|
|
||||||
Mux_Format_FLAC = Format_FLAC
|
|
||||||
|
|
||||||
// FLV (Flash Video)
|
|
||||||
Format_FLV = "flv"
|
|
||||||
// FLV (Flash Video)
|
|
||||||
Mux_Format_FLV = Format_FLV
|
|
||||||
|
|
||||||
// framecrc testing
|
|
||||||
Format_FRAMECRC = "framecrc"
|
|
||||||
// framecrc testing
|
|
||||||
Mux_Format_FRAMECRC = Format_FRAMECRC
|
|
||||||
|
|
||||||
// Per-frame hash testing
|
|
||||||
Format_FRAMEHASH = "framehash"
|
|
||||||
// Per-frame hash testing
|
|
||||||
Mux_Format_FRAMEHASH = Format_FRAMEHASH
|
|
||||||
|
|
||||||
// Per-frame MD5 testing
|
|
||||||
Format_FRAMEMD5 = "framemd5"
|
|
||||||
// Per-frame MD5 testing
|
|
||||||
Mux_Format_FRAMEMD5 = Format_FRAMEMD5
|
|
||||||
|
|
||||||
// raw G.722
|
|
||||||
Format_G722 = "g722"
|
|
||||||
// raw G.722
|
|
||||||
Mux_Format_G722 = Format_G722
|
|
||||||
|
|
||||||
// raw G.723.1
|
|
||||||
Format_G723_1 = "g723_1"
|
|
||||||
// raw G.723.1
|
|
||||||
Mux_Format_G723_1 = Format_G723_1
|
|
||||||
|
|
||||||
// raw big-endian G.726 ("left-justified")
|
|
||||||
Format_G726 = "g726"
|
|
||||||
// raw big-endian G.726 ("left-justified")
|
|
||||||
Mux_Format_G726 = Format_G726
|
|
||||||
|
|
||||||
// raw little-endian G.726 ("right-justified")
|
|
||||||
Format_G726LE = "g726le"
|
|
||||||
// raw little-endian G.726 ("right-justified")
|
|
||||||
Mux_Format_G726LE = Format_G726LE
|
|
||||||
|
|
||||||
// GIF Animation
|
|
||||||
Format_GIF = "gif"
|
|
||||||
// GIF Animation
|
|
||||||
Mux_Format_GIF = Format_GIF
|
|
||||||
|
|
||||||
// raw GSM
|
|
||||||
Format_GSM = "gsm"
|
|
||||||
// raw GSM
|
|
||||||
Mux_Format_GSM = Format_GSM
|
|
||||||
|
|
||||||
// GXF (General eXchange Format)
|
|
||||||
Format_GXF = "gxf"
|
|
||||||
// GXF (General eXchange Format)
|
|
||||||
Mux_Format_GXF = Format_GXF
|
|
||||||
|
|
||||||
// raw H.261
|
|
||||||
Format_H261 = "h261"
|
|
||||||
// raw H.261
|
|
||||||
Mux_Format_H261 = Format_H261
|
|
||||||
|
|
||||||
// raw H.263
|
|
||||||
Format_H263 = "h263"
|
|
||||||
// raw H.263
|
|
||||||
Mux_Format_H263 = Format_H263
|
|
||||||
|
|
||||||
// raw H.264 video
|
|
||||||
Format_H264 = "h264"
|
|
||||||
// raw H.264 video
|
|
||||||
Mux_Format_H264 = Format_H264
|
|
||||||
|
|
||||||
// Hash testing
|
|
||||||
Format_HASH = "hash"
|
|
||||||
// Hash testing
|
|
||||||
Mux_Format_HASH = Format_HASH
|
|
||||||
|
|
||||||
// HDS Muxer
|
|
||||||
Format_HDS = "hds"
|
|
||||||
// HDS Muxer
|
|
||||||
Mux_Format_HDS = Format_HDS
|
|
||||||
|
|
||||||
// raw HEVC video
|
|
||||||
Format_HEVC = "hevc"
|
|
||||||
// raw HEVC video
|
|
||||||
Mux_Format_HEVC = Format_HEVC
|
|
||||||
|
|
||||||
// Apple HTTP Live Streaming
|
|
||||||
Format_HLS = "hls"
|
|
||||||
// Apple HTTP Live Streaming
|
|
||||||
Mux_Format_HLS = Format_HLS
|
|
||||||
|
|
||||||
// Microsoft Windows ICO
|
|
||||||
Format_ICO = "ico"
|
|
||||||
// Microsoft Windows ICO
|
|
||||||
Mux_Format_ICO = Format_ICO
|
|
||||||
|
|
||||||
// iLBC storage
|
|
||||||
Format_ILBC = "ilbc"
|
|
||||||
// iLBC storage
|
|
||||||
Mux_Format_ILBC = Format_ILBC
|
|
||||||
|
|
||||||
// image2 sequence
|
|
||||||
Format_IMAGE2 = "image2"
|
|
||||||
// image2 sequence
|
|
||||||
Mux_Format_IMAGE2 = Format_IMAGE2
|
|
||||||
|
|
||||||
// piped image2 sequence
|
|
||||||
Format_IMAGE2PIPE = "image2pipe"
|
|
||||||
// piped image2 sequence
|
|
||||||
Mux_Format_IMAGE2PIPE = Format_IMAGE2PIPE
|
|
||||||
|
|
||||||
// iPod H.264 MP4 (MPEG-4 Part 14)
|
|
||||||
Format_IPOD = "ipod"
|
|
||||||
// iPod H.264 MP4 (MPEG-4 Part 14)
|
|
||||||
Mux_Format_IPOD = Format_IPOD
|
|
||||||
|
|
||||||
// Berkeley/IRCAM/CARL Sound Format
|
|
||||||
Format_IRCAM = "ircam"
|
|
||||||
// Berkeley/IRCAM/CARL Sound Format
|
|
||||||
Mux_Format_IRCAM = Format_IRCAM
|
|
||||||
|
|
||||||
// ISMV/ISMA (Smooth Streaming)
|
|
||||||
Format_ISMV = "ismv"
|
|
||||||
// ISMV/ISMA (Smooth Streaming)
|
|
||||||
Mux_Format_ISMV = Format_ISMV
|
|
||||||
|
|
||||||
// On2 IVF
|
|
||||||
Format_IVF = "ivf"
|
|
||||||
// On2 IVF
|
|
||||||
Mux_Format_IVF = Format_IVF
|
|
||||||
|
|
||||||
// JACOsub subtitle format
|
|
||||||
Format_JACOSUB = "jacosub"
|
|
||||||
// JACOsub subtitle format
|
|
||||||
Mux_Format_JACOSUB = Format_JACOSUB
|
|
||||||
|
|
||||||
// LOAS/LATM
|
|
||||||
Format_LATM = "latm"
|
|
||||||
// LOAS/LATM
|
|
||||||
Mux_Format_LATM = Format_LATM
|
|
||||||
|
|
||||||
// LRC lyrics
|
|
||||||
Format_LRC = "lrc"
|
|
||||||
// LRC lyrics
|
|
||||||
Mux_Format_LRC = Format_LRC
|
|
||||||
|
|
||||||
// raw MPEG-4 video
|
|
||||||
Format_M4V = "m4v"
|
|
||||||
// raw MPEG-4 video
|
|
||||||
Mux_Format_M4V = Format_M4V
|
|
||||||
|
|
||||||
// Matroska
|
|
||||||
Format_MATROSKA = "matroska"
|
|
||||||
// Matroska
|
|
||||||
Mux_Format_MATROSKA = Format_MATROSKA
|
|
||||||
|
|
||||||
// MD5 testing
|
|
||||||
Format_MD5 = "md5"
|
|
||||||
// MD5 testing
|
|
||||||
Mux_Format_MD5 = Format_MD5
|
|
||||||
|
|
||||||
// MicroDVD subtitle format
|
|
||||||
Format_MICRODVD = "microdvd"
|
|
||||||
// MicroDVD subtitle format
|
|
||||||
Mux_Format_MICRODVD = Format_MICRODVD
|
|
||||||
|
|
||||||
// raw MJPEG video
|
|
||||||
Format_MJPEG = "mjpeg"
|
|
||||||
// raw MJPEG video
|
|
||||||
Mux_Format_MJPEG = Format_MJPEG
|
|
||||||
|
|
||||||
// extract pts as timecode v2 format, as defined by mkvtoolnix
|
|
||||||
Format_MKVTIMESTAMP_V2 = "mkvtimestamp_v2"
|
|
||||||
// extract pts as timecode v2 format, as defined by mkvtoolnix
|
|
||||||
Mux_Format_MKVTIMESTAMP_V2 = Format_MKVTIMESTAMP_V2
|
|
||||||
|
|
||||||
// raw MLP
|
|
||||||
Format_MLP = "mlp"
|
|
||||||
// raw MLP
|
|
||||||
Mux_Format_MLP = Format_MLP
|
|
||||||
|
|
||||||
// Yamaha SMAF
|
|
||||||
Format_MMF = "mmf"
|
|
||||||
// Yamaha SMAF
|
|
||||||
Mux_Format_MMF = Format_MMF
|
|
||||||
|
|
||||||
// QuickTime / MOV
|
|
||||||
Format_MOV = "mov"
|
|
||||||
// QuickTime / MOV
|
|
||||||
Mux_Format_MOV = Format_MOV
|
|
||||||
|
|
||||||
// MP2 (MPEG audio layer 2)
|
|
||||||
Format_MP2 = "mp2"
|
|
||||||
// MP2 (MPEG audio layer 2)
|
|
||||||
Mux_Format_MP2 = Format_MP2
|
|
||||||
|
|
||||||
// MP3 (MPEG audio layer 3)
|
|
||||||
Format_MP3 = "mp3"
|
|
||||||
// MP3 (MPEG audio layer 3)
|
|
||||||
Mux_Format_MP3 = Format_MP3
|
|
||||||
|
|
||||||
// MP4 (MPEG-4 Part 14)
|
|
||||||
Format_MP4 = "mp4"
|
|
||||||
// MP4 (MPEG-4 Part 14)
|
|
||||||
Mux_Format_MP4 = Format_MP4
|
|
||||||
|
|
||||||
// MPEG-1 Systems / MPEG program stream
|
|
||||||
Format_MPEG = "mpeg"
|
|
||||||
// MPEG-1 Systems / MPEG program stream
|
|
||||||
Mux_Format_MPEG = Format_MPEG
|
|
||||||
|
|
||||||
// raw MPEG-1 video
|
|
||||||
Format_MPEG1VIDEO = "mpeg1video"
|
|
||||||
// raw MPEG-1 video
|
|
||||||
Mux_Format_MPEG1VIDEO = Format_MPEG1VIDEO
|
|
||||||
|
|
||||||
// raw MPEG-2 video
|
|
||||||
Format_MPEG2VIDEO = "mpeg2video"
|
|
||||||
// raw MPEG-2 video
|
|
||||||
Mux_Format_MPEG2VIDEO = Format_MPEG2VIDEO
|
|
||||||
|
|
||||||
// MPEG-TS (MPEG-2 Transport Stream)
|
|
||||||
Format_MPEGTS = "mpegts"
|
|
||||||
// MPEG-TS (MPEG-2 Transport Stream)
|
|
||||||
Mux_Format_MPEGTS = Format_MPEGTS
|
|
||||||
|
|
||||||
// MIME multipart JPEG
|
|
||||||
Format_MPJPEG = "mpjpeg"
|
|
||||||
// MIME multipart JPEG
|
|
||||||
Mux_Format_MPJPEG = Format_MPJPEG
|
|
||||||
|
|
||||||
// PCM mu-law
|
|
||||||
Format_MULAW = "mulaw"
|
|
||||||
// PCM mu-law
|
|
||||||
Mux_Format_MULAW = Format_MULAW
|
|
||||||
|
|
||||||
// MXF (Material eXchange Format)
|
|
||||||
Format_MXF = "mxf"
|
|
||||||
// MXF (Material eXchange Format)
|
|
||||||
Mux_Format_MXF = Format_MXF
|
|
||||||
|
|
||||||
// MXF (Material eXchange Format) D-10 Mapping
|
|
||||||
Format_MXF_D10 = "mxf_d10"
|
|
||||||
// MXF (Material eXchange Format) D-10 Mapping
|
|
||||||
Mux_Format_MXF_D10 = Format_MXF_D10
|
|
||||||
|
|
||||||
// MXF (Material eXchange Format) Operational Pattern Atom
|
|
||||||
Format_MXF_OPATOM = "mxf_opatom"
|
|
||||||
// MXF (Material eXchange Format) Operational Pattern Atom
|
|
||||||
Mux_Format_MXF_OPATOM = Format_MXF_OPATOM
|
|
||||||
|
|
||||||
// raw null video
|
|
||||||
Format_NULL = "null"
|
|
||||||
// raw null video
|
|
||||||
Mux_Format_NULL = Format_NULL
|
|
||||||
|
|
||||||
// NUT
|
|
||||||
Format_NUT = "nut"
|
|
||||||
// NUT
|
|
||||||
Mux_Format_NUT = Format_NUT
|
|
||||||
|
|
||||||
// Ogg Audio
|
|
||||||
Format_OGA = "oga"
|
|
||||||
// Ogg Audio
|
|
||||||
Mux_Format_OGA = Format_OGA
|
|
||||||
|
|
||||||
// Ogg
|
|
||||||
Format_OGG = "ogg"
|
|
||||||
// Ogg
|
|
||||||
Mux_Format_OGG = Format_OGG
|
|
||||||
|
|
||||||
// Ogg Video
|
|
||||||
Format_OGV = "ogv"
|
|
||||||
// Ogg Video
|
|
||||||
Mux_Format_OGV = Format_OGV
|
|
||||||
|
|
||||||
// Sony OpenMG audio
|
|
||||||
Format_OMA = "oma"
|
|
||||||
// Sony OpenMG audio
|
|
||||||
Mux_Format_OMA = Format_OMA
|
|
||||||
|
|
||||||
// Ogg Opus
|
|
||||||
Format_OPUS = "opus"
|
|
||||||
// Ogg Opus
|
|
||||||
Mux_Format_OPUS = Format_OPUS
|
|
||||||
|
|
||||||
// OSS (Open Sound System) playback
|
|
||||||
Format_OSS = "oss"
|
|
||||||
// OSS (Open Sound System) playback
|
|
||||||
Mux_Format_OSS = Format_OSS
|
|
||||||
|
|
||||||
// PSP MP4 (MPEG-4 Part 14)
|
|
||||||
Format_PSP = "psp"
|
|
||||||
// PSP MP4 (MPEG-4 Part 14)
|
|
||||||
Mux_Format_PSP = Format_PSP
|
|
||||||
|
|
||||||
// Pulse audio output
|
|
||||||
Format_PULSE = "pulse"
|
|
||||||
// Pulse audio output
|
|
||||||
Mux_Format_PULSE = Format_PULSE
|
|
||||||
|
|
||||||
// raw video
|
|
||||||
Format_RAWVIDEO = "rawvideo"
|
|
||||||
// raw video
|
|
||||||
Mux_Format_RAWVIDEO = Format_RAWVIDEO
|
|
||||||
|
|
||||||
// RealMedia
|
|
||||||
Format_RM = "rm"
|
|
||||||
// RealMedia
|
|
||||||
Mux_Format_RM = Format_RM
|
|
||||||
|
|
||||||
// raw id RoQ
|
|
||||||
Format_ROQ = "roq"
|
|
||||||
// raw id RoQ
|
|
||||||
Mux_Format_ROQ = Format_ROQ
|
|
||||||
|
|
||||||
// Lego Mindstorms RSO
|
|
||||||
Format_RSO = "rso"
|
|
||||||
// Lego Mindstorms RSO
|
|
||||||
Mux_Format_RSO = Format_RSO
|
|
||||||
|
|
||||||
// RTP output
|
|
||||||
Format_RTP = "rtp"
|
|
||||||
// RTP output
|
|
||||||
Mux_Format_RTP = Format_RTP
|
|
||||||
|
|
||||||
// RTP/mpegts output format
|
|
||||||
Format_RTP_MPEGTS = "rtp_mpegts"
|
|
||||||
// RTP/mpegts output format
|
|
||||||
Mux_Format_RTP_MPEGTS = Format_RTP_MPEGTS
|
|
||||||
|
|
||||||
// RTSP output
|
|
||||||
Format_RTSP = "rtsp"
|
|
||||||
// RTSP output
|
|
||||||
Mux_Format_RTSP = Format_RTSP
|
|
||||||
|
|
||||||
// PCM signed 16-bit big-endian
|
|
||||||
Format_S16BE = "s16be"
|
|
||||||
// PCM signed 16-bit big-endian
|
|
||||||
Mux_Format_S16BE = Format_S16BE
|
|
||||||
|
|
||||||
// PCM signed 16-bit little-endian
|
|
||||||
Format_S16LE = "s16le"
|
|
||||||
// PCM signed 16-bit little-endian
|
|
||||||
Mux_Format_S16LE = Format_S16LE
|
|
||||||
|
|
||||||
// PCM signed 24-bit big-endian
|
|
||||||
Format_S24BE = "s24be"
|
|
||||||
// PCM signed 24-bit big-endian
|
|
||||||
Mux_Format_S24BE = Format_S24BE
|
|
||||||
|
|
||||||
// PCM signed 24-bit little-endian
|
|
||||||
Format_S24LE = "s24le"
|
|
||||||
// PCM signed 24-bit little-endian
|
|
||||||
Mux_Format_S24LE = Format_S24LE
|
|
||||||
|
|
||||||
// PCM signed 32-bit big-endian
|
|
||||||
Format_S32BE = "s32be"
|
|
||||||
// PCM signed 32-bit big-endian
|
|
||||||
Mux_Format_S32BE = Format_S32BE
|
|
||||||
|
|
||||||
// PCM signed 32-bit little-endian
|
|
||||||
Format_S32LE = "s32le"
|
|
||||||
// PCM signed 32-bit little-endian
|
|
||||||
Mux_Format_S32LE = Format_S32LE
|
|
||||||
|
|
||||||
// PCM signed 8-bit
|
|
||||||
Format_S8 = "s8"
|
|
||||||
// PCM signed 8-bit
|
|
||||||
Mux_Format_S8 = Format_S8
|
|
||||||
|
|
||||||
// SAP output
|
|
||||||
Format_SAP = "sap"
|
|
||||||
// SAP output
|
|
||||||
Mux_Format_SAP = Format_SAP
|
|
||||||
|
|
||||||
// raw SBC
|
|
||||||
Format_SBC = "sbc"
|
|
||||||
// raw SBC
|
|
||||||
Mux_Format_SBC = Format_SBC
|
|
||||||
|
|
||||||
// Scenarist Closed Captions
|
|
||||||
Format_SCC = "scc"
|
|
||||||
// Scenarist Closed Captions
|
|
||||||
Mux_Format_SCC = Format_SCC
|
|
||||||
|
|
||||||
// SDL2 output device
|
|
||||||
Format_SDL = "sdl"
|
|
||||||
// SDL2 output device
|
|
||||||
Mux_Format_SDL = Format_SDL
|
|
||||||
|
|
||||||
// SDL2 output device
|
|
||||||
Format_SDL2 = "sdl2"
|
|
||||||
// SDL2 output device
|
|
||||||
Mux_Format_SDL2 = Format_SDL2
|
|
||||||
|
|
||||||
// segment
|
|
||||||
Format_SEGMENT = "segment"
|
|
||||||
// segment
|
|
||||||
Mux_Format_SEGMENT = Format_SEGMENT
|
|
||||||
|
|
||||||
// JPEG single image
|
|
||||||
Format_SINGLEJPEG = "singlejpeg"
|
|
||||||
// JPEG single image
|
|
||||||
Mux_Format_SINGLEJPEG = Format_SINGLEJPEG
|
|
||||||
|
|
||||||
// Loki SDL MJPEG
|
|
||||||
Format_SMJPEG = "smjpeg"
|
|
||||||
// Loki SDL MJPEG
|
|
||||||
Mux_Format_SMJPEG = Format_SMJPEG
|
|
||||||
|
|
||||||
// Smooth Streaming Muxer
|
|
||||||
Format_SMOOTHSTREAMING = "smoothstreaming"
|
|
||||||
// Smooth Streaming Muxer
|
|
||||||
Mux_Format_SMOOTHSTREAMING = Format_SMOOTHSTREAMING
|
|
||||||
|
|
||||||
// SoX native
|
|
||||||
Format_SOX = "sox"
|
|
||||||
// SoX native
|
|
||||||
Mux_Format_SOX = Format_SOX
|
|
||||||
|
|
||||||
// IEC 61937 (used on S/PDIF - IEC958)
|
|
||||||
Format_SPDIF = "spdif"
|
|
||||||
// IEC 61937 (used on S/PDIF - IEC958)
|
|
||||||
Mux_Format_SPDIF = Format_SPDIF
|
|
||||||
|
|
||||||
// Ogg Speex
|
|
||||||
Format_SPX = "spx"
|
|
||||||
// Ogg Speex
|
|
||||||
Mux_Format_SPX = Format_SPX
|
|
||||||
|
|
||||||
// SubRip subtitle
|
|
||||||
Format_SRT = "srt"
|
|
||||||
// SubRip subtitle
|
|
||||||
Mux_Format_SRT = Format_SRT
|
|
||||||
|
|
||||||
// streaming segment muxer
|
|
||||||
Format_STREAM_SEGMENT = "stream_segment"
|
|
||||||
// streaming segment muxer
|
|
||||||
Mux_Format_STREAM_SEGMENT = Format_STREAM_SEGMENT
|
|
||||||
|
|
||||||
// streaming segment muxer
|
|
||||||
Format_SSEGMENT = "ssegment"
|
|
||||||
// streaming segment muxer
|
|
||||||
Mux_Format_SSEGMENT = Format_SSEGMENT
|
|
||||||
|
|
||||||
// raw HDMV Presentation Graphic Stream subtitles
|
|
||||||
Format_SUP = "sup"
|
|
||||||
// raw HDMV Presentation Graphic Stream subtitles
|
|
||||||
Mux_Format_SUP = Format_SUP
|
|
||||||
|
|
||||||
// MPEG-2 PS (SVCD)
|
|
||||||
Format_SVCD = "svcd"
|
|
||||||
// MPEG-2 PS (SVCD)
|
|
||||||
Mux_Format_SVCD = Format_SVCD
|
|
||||||
|
|
||||||
// SWF (ShockWave Flash)
|
|
||||||
Format_SWF = "swf"
|
|
||||||
// SWF (ShockWave Flash)
|
|
||||||
Mux_Format_SWF = Format_SWF
|
|
||||||
|
|
||||||
// Multiple muxer tee
|
|
||||||
Format_TEE = "tee"
|
|
||||||
// Multiple muxer tee
|
|
||||||
Mux_Format_TEE = Format_TEE
|
|
||||||
|
|
||||||
// raw TrueHD
|
|
||||||
Format_TRUEHD = "truehd"
|
|
||||||
// raw TrueHD
|
|
||||||
Mux_Format_TRUEHD = Format_TRUEHD
|
|
||||||
|
|
||||||
// TTA (True Audio)
|
|
||||||
Format_TTA = "tta"
|
|
||||||
// TTA (True Audio)
|
|
||||||
Mux_Format_TTA = Format_TTA
|
|
||||||
|
|
||||||
// PCM unsigned 16-bit big-endian
|
|
||||||
Format_U16BE = "u16be"
|
|
||||||
// PCM unsigned 16-bit big-endian
|
|
||||||
Mux_Format_U16BE = Format_U16BE
|
|
||||||
|
|
||||||
// PCM unsigned 16-bit little-endian
|
|
||||||
Format_U16LE = "u16le"
|
|
||||||
// PCM unsigned 16-bit little-endian
|
|
||||||
Mux_Format_U16LE = Format_U16LE
|
|
||||||
|
|
||||||
// PCM unsigned 24-bit big-endian
|
|
||||||
Format_U24BE = "u24be"
|
|
||||||
// PCM unsigned 24-bit big-endian
|
|
||||||
Mux_Format_U24BE = Format_U24BE
|
|
||||||
|
|
||||||
// PCM unsigned 24-bit little-endian
|
|
||||||
Format_U24LE = "u24le"
|
|
||||||
// PCM unsigned 24-bit little-endian
|
|
||||||
Mux_Format_U24LE = Format_U24LE
|
|
||||||
|
|
||||||
// PCM unsigned 32-bit big-endian
|
|
||||||
Format_U32BE = "u32be"
|
|
||||||
// PCM unsigned 32-bit big-endian
|
|
||||||
Mux_Format_U32BE = Format_U32BE
|
|
||||||
|
|
||||||
// PCM unsigned 32-bit little-endian
|
|
||||||
Format_U32LE = "u32le"
|
|
||||||
// PCM unsigned 32-bit little-endian
|
|
||||||
Mux_Format_U32LE = Format_U32LE
|
|
||||||
|
|
||||||
// PCM unsigned 8-bit
|
|
||||||
Format_U8 = "u8"
|
|
||||||
// PCM unsigned 8-bit
|
|
||||||
Mux_Format_U8 = Format_U8
|
|
||||||
|
|
||||||
// uncoded framecrc testing
|
|
||||||
Format_UNCODEDFRAMECRC = "uncodedframecrc"
|
|
||||||
// uncoded framecrc testing
|
|
||||||
Mux_Format_UNCODEDFRAMECRC = Format_UNCODEDFRAMECRC
|
|
||||||
|
|
||||||
// Video4Linux2 output device
|
|
||||||
Format_V4L2 = "v4l2"
|
|
||||||
// Video4Linux2 output device
|
|
||||||
Mux_Format_V4L2 = Format_V4L2
|
|
||||||
|
|
||||||
// raw VC-1 video
|
|
||||||
Format_VC1 = "vc1"
|
|
||||||
// raw VC-1 video
|
|
||||||
Mux_Format_VC1 = Format_VC1
|
|
||||||
|
|
||||||
// VC-1 test bitstream
|
|
||||||
Format_VC1TEST = "vc1test"
|
|
||||||
// VC-1 test bitstream
|
|
||||||
Mux_Format_VC1TEST = Format_VC1TEST
|
|
||||||
|
|
||||||
// MPEG-1 Systems / MPEG program stream (VCD)
|
|
||||||
Format_VCD = "vcd"
|
|
||||||
// MPEG-1 Systems / MPEG program stream (VCD)
|
|
||||||
Mux_Format_VCD = Format_VCD
|
|
||||||
|
|
||||||
// MPEG-2 PS (VOB)
|
|
||||||
Format_VOB = "vob"
|
|
||||||
// MPEG-2 PS (VOB)
|
|
||||||
Mux_Format_VOB = Format_VOB
|
|
||||||
|
|
||||||
// Creative Voice
|
|
||||||
Format_VOC = "voc"
|
|
||||||
// Creative Voice
|
|
||||||
Mux_Format_VOC = Format_VOC
|
|
||||||
|
|
||||||
// Sony Wave64
|
|
||||||
Format_W64 = "w64"
|
|
||||||
// Sony Wave64
|
|
||||||
Mux_Format_W64 = Format_W64
|
|
||||||
|
|
||||||
// WAV / WAVE (Waveform Audio)
|
|
||||||
Format_WAV = "wav"
|
|
||||||
// WAV / WAVE (Waveform Audio)
|
|
||||||
Mux_Format_WAV = Format_WAV
|
|
||||||
|
|
||||||
// WebM
|
|
||||||
Format_WEBM = "webm"
|
|
||||||
// WebM
|
|
||||||
Mux_Format_WEBM = Format_WEBM
|
|
||||||
|
|
||||||
// WebM Chunk Muxer
|
|
||||||
Format_WEBM_CHUNK = "webm_chunk"
|
|
||||||
// WebM Chunk Muxer
|
|
||||||
Mux_Format_WEBM_CHUNK = Format_WEBM_CHUNK
|
|
||||||
|
|
||||||
// WebM DASH Manifest
|
|
||||||
Format_WEBM_DASH_MANIFEST = "webm_dash_manifest"
|
|
||||||
// WebM DASH Manifest
|
|
||||||
Mux_Format_WEBM_DASH_MANIFEST = Format_WEBM_DASH_MANIFEST
|
|
||||||
|
|
||||||
// WebP
|
|
||||||
Format_WEBP = "webp"
|
|
||||||
// WebP
|
|
||||||
Mux_Format_WEBP = Format_WEBP
|
|
||||||
|
|
||||||
// WebVTT subtitle
|
|
||||||
Format_WEBVTT = "webvtt"
|
|
||||||
// WebVTT subtitle
|
|
||||||
Mux_Format_WEBVTT = Format_WEBVTT
|
|
||||||
|
|
||||||
// Windows Television (WTV)
|
|
||||||
Format_WTV = "wtv"
|
|
||||||
// Windows Television (WTV)
|
|
||||||
Mux_Format_WTV = Format_WTV
|
|
||||||
|
|
||||||
// raw WavPack
|
|
||||||
Format_WV = "wv"
|
|
||||||
// raw WavPack
|
|
||||||
Mux_Format_WV = Format_WV
|
|
||||||
|
|
||||||
// XV (XVideo) output device
|
|
||||||
Format_XV = "xv"
|
|
||||||
// XV (XVideo) output device
|
|
||||||
Mux_Format_XV = Format_XV
|
|
||||||
|
|
||||||
// YUV4MPEG pipe
|
|
||||||
Format_YUV4MPEGPIPE = "yuv4mpegpipe"
|
|
||||||
// YUV4MPEG pipe
|
|
||||||
Mux_Format_YUV4MPEGPIPE = Format_YUV4MPEGPIPE
|
|
||||||
)
|
|
|
@ -1,86 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func must(err error) {
|
|
||||||
if err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cmd := exec.Command("ffmpeg", "-muxers")
|
|
||||||
outputBytes, err := cmd.Output()
|
|
||||||
must(err)
|
|
||||||
|
|
||||||
code := `package formats
|
|
||||||
|
|
||||||
var (
|
|
||||||
`
|
|
||||||
|
|
||||||
bufreader := bufio.NewScanner(bytes.NewReader(outputBytes))
|
|
||||||
|
|
||||||
/*File formats:
|
|
||||||
D. = Demuxing supported
|
|
||||||
.E = Muxing supported
|
|
||||||
--
|
|
||||||
E 3g2 3GP2 (3GPP2 file format)
|
|
||||||
E 3gp 3GP (3GPP file format)*/
|
|
||||||
|
|
||||||
waitingForList := true
|
|
||||||
for bufreader.Scan() && waitingForList {
|
|
||||||
text := bufreader.Text()
|
|
||||||
if text == " --" {
|
|
||||||
waitingForList = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for bufreader.Scan() {
|
|
||||||
text := bufreader.Text()
|
|
||||||
demuxingSupported := text[1] == 'D'
|
|
||||||
muxingSupported := text[2] == 'E'
|
|
||||||
text = text[4:]
|
|
||||||
cols := strings.Fields(text)
|
|
||||||
ids := strings.Split(cols[0], ",")
|
|
||||||
name := strings.Join(cols[1:], " ")
|
|
||||||
for _, id := range ids {
|
|
||||||
code += fmt.Sprintf(`
|
|
||||||
// %s
|
|
||||||
Format_%s = %q
|
|
||||||
`, name, strings.ToUpper(id), id)
|
|
||||||
if demuxingSupported {
|
|
||||||
code += fmt.Sprintf(` // %s
|
|
||||||
Demux_Format_%s = Format_%s
|
|
||||||
`, name, strings.ToUpper(id), strings.ToUpper(id))
|
|
||||||
}
|
|
||||||
if muxingSupported {
|
|
||||||
code += fmt.Sprintf(` // %s
|
|
||||||
Mux_Format_%s = Format_%s
|
|
||||||
`, name, strings.ToUpper(id), strings.ToUpper(id))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
code += `
|
|
||||||
)
|
|
||||||
`
|
|
||||||
|
|
||||||
codeBytes, err := format.Source([]byte(code))
|
|
||||||
must(err)
|
|
||||||
|
|
||||||
f, err := os.Create("gen_formats.go")
|
|
||||||
must(err)
|
|
||||||
defer f.Close()
|
|
||||||
_, err = f.Write(codeBytes)
|
|
||||||
must(err)
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
package mux
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"git.icedream.tech/icedream/uplink/app/media"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Muxer interface {
|
|
||||||
AcceptsCodec(info media.MediaStreamCodecInfo) bool
|
|
||||||
GeneratesFormat(info media.MediaStreamContainerInfo) bool
|
|
||||||
|
|
||||||
NewInstance(streams ...*media.MediaStream) <-MuxerInstance
|
|
||||||
}
|
|
||||||
|
|
||||||
type MuxerInstance interface {
|
|
||||||
Error() error
|
|
||||||
Container() *media.MediaStreamContainerInfo
|
|
||||||
}
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
@ -13,7 +12,7 @@ import (
|
||||||
func Test_Muxer(t *testing.T) {
|
func Test_Muxer(t *testing.T) {
|
||||||
Convey("Muxer", t, func() {
|
Convey("Muxer", t, func() {
|
||||||
Convey("audio-only", func() {
|
Convey("audio-only", func() {
|
||||||
reader, _ := os.Open(filepath.Join("testassets", "mpthreetest.mp3"))
|
reader, _ := os.Open("mpthreetest.mp3")
|
||||||
defer reader.Close()
|
defer reader.Close()
|
||||||
|
|
||||||
demuxer := Demux(reader)
|
demuxer := Demux(reader)
|
||||||
|
@ -28,7 +27,7 @@ func Test_Muxer(t *testing.T) {
|
||||||
So(audioStream, ShouldBeNil)
|
So(audioStream, ShouldBeNil)
|
||||||
So(stream.StreamId, ShouldEqual, 0)
|
So(stream.StreamId, ShouldEqual, 0)
|
||||||
So(stream.Pts, ShouldEqual, 0)
|
So(stream.Pts, ShouldEqual, 0)
|
||||||
So(stream.CodecInfo.CodecName, ShouldBeIn, []string{"mp3", "mp3float"})
|
So(stream.CodecInfo.CodecName, ShouldEqual, "mp3")
|
||||||
So(stream.CodecInfo.Type, ShouldEqual, Audio)
|
So(stream.CodecInfo.Type, ShouldEqual, Audio)
|
||||||
audioStream = stream
|
audioStream = stream
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
package transcode
|
|
||||||
|
|
||||||
import "git.icedream.tech/icedream/uplink/app/genericapi"
|
|
||||||
|
|
||||||
type Transcoder interface {
|
|
||||||
genericapi.DynamicallyConfigurable
|
|
||||||
|
|
||||||
AcceptedInputCodecs() []string
|
|
||||||
AcceptedOutputCodecs() []string
|
|
||||||
|
|
||||||
NewInstance(config interface{}) <-TranscoderInstance
|
|
||||||
}
|
|
|
@ -9,17 +9,12 @@ import (
|
||||||
"git.icedream.tech/icedream/uplink/plugins"
|
"git.icedream.tech/icedream/uplink/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
type registeredPlugin struct {
|
|
||||||
Instance plugins.PluginInstance
|
|
||||||
Descriptor plugins.PluginDescriptor
|
|
||||||
}
|
|
||||||
|
|
||||||
type App struct {
|
type App struct {
|
||||||
Server *httpserver.Server
|
Server *httpserver.Server
|
||||||
Authenticator authentication.Authenticator
|
Authenticator authentication.Authenticator
|
||||||
ChannelManager *channels.ChannelManager
|
ChannelManager *channels.ChannelManager
|
||||||
|
|
||||||
plugins []registeredPlugin
|
plugins []plugins.PluginInstance
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() *App {
|
func New() *App {
|
||||||
|
@ -28,7 +23,7 @@ func New() *App {
|
||||||
Authenticator: new(authentication.DummyAuthenticator),
|
Authenticator: new(authentication.DummyAuthenticator),
|
||||||
ChannelManager: channels.NewChannelManager(),
|
ChannelManager: channels.NewChannelManager(),
|
||||||
|
|
||||||
plugins: []registeredPlugin{},
|
plugins: []plugins.PluginInstance{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,18 +40,14 @@ func (app *App) UsePlugin(plugin *plugins.Plugin) {
|
||||||
p.SetAuthenticator(app.Authenticator)
|
p.SetAuthenticator(app.Authenticator)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("Plugin registered:", plugin.Descriptor.Name)
|
log.Println("Plugin initialized:", plugin.Descriptor.Name)
|
||||||
|
|
||||||
app.plugins = append(app.plugins, registeredPlugin{
|
app.plugins = append(app.plugins, pluginInstance)
|
||||||
Instance: pluginInstance,
|
|
||||||
Descriptor: plugin.Descriptor,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *App) Init() {
|
func (app *App) Init() {
|
||||||
for _, plugin := range app.plugins {
|
for _, plugin := range app.plugins {
|
||||||
plugin.Instance.Init()
|
plugin.Init()
|
||||||
log.Println("Plugin initialized:", plugin.Descriptor.Name)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,6 @@ func NewServer() *Server {
|
||||||
Router: gin.New(),
|
Router: gin.New(),
|
||||||
}
|
}
|
||||||
|
|
||||||
server.Router.Use(gin.Logger())
|
|
||||||
server.Router.Use(gin.Recovery())
|
|
||||||
|
|
||||||
server.Http.Handler = server.Router
|
server.Http.Handler = server.Router
|
||||||
server.Http.Addr = ":8000"
|
server.Http.Addr = ":8000"
|
||||||
|
|
||||||
|
|
|
@ -39,23 +39,22 @@ func (mi *MetadataInjector) writeMetadata() (n int, err error) {
|
||||||
|
|
||||||
func (mi *MetadataInjector) Write(data []byte) (n int, err error) {
|
func (mi *MetadataInjector) Write(data []byte) (n int, err error) {
|
||||||
for n < len(data) {
|
for n < len(data) {
|
||||||
restLen := len(data) - n
|
|
||||||
toWrite := mi.MetadataInterval - mi.offset
|
toWrite := mi.MetadataInterval - mi.offset
|
||||||
if toWrite > restLen {
|
|
||||||
toWrite = restLen
|
|
||||||
}
|
|
||||||
|
|
||||||
if toWrite <= 0 {
|
if toWrite <= 0 {
|
||||||
_, err = mi.writeMetadata()
|
_, cerr := mi.writeMetadata()
|
||||||
if err != nil {
|
//n += cn
|
||||||
|
if cerr != nil {
|
||||||
|
err = cerr
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mi.offset = 0
|
mi.offset = 0
|
||||||
|
// toWrite = mi.MetadataInterval
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
outBytes := make([]byte, toWrite)
|
outBytes := make([]byte, toWrite)
|
||||||
copy(outBytes, data[n:n+toWrite])
|
copy(outBytes, data[mi.offset:mi.offset+toWrite])
|
||||||
cn, cerr := mi.Writer.Write(outBytes)
|
cn, cerr := mi.Writer.Write(outBytes)
|
||||||
n += cn
|
n += cn
|
||||||
mi.offset += cn
|
mi.offset += cn
|
||||||
|
|
3
main.go
3
main.go
|
@ -4,7 +4,6 @@ import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"git.icedream.tech/icedream/uplink/app"
|
"git.icedream.tech/icedream/uplink/app"
|
||||||
"git.icedream.tech/icedream/uplink/plugins/icecast/input"
|
|
||||||
"git.icedream.tech/icedream/uplink/plugins/icecast/output"
|
"git.icedream.tech/icedream/uplink/plugins/icecast/output"
|
||||||
"git.icedream.tech/icedream/uplink/plugins/test/sine"
|
"git.icedream.tech/icedream/uplink/plugins/test/sine"
|
||||||
)
|
)
|
||||||
|
@ -17,7 +16,7 @@ func main() {
|
||||||
|
|
||||||
func run() (err error) {
|
func run() (err error) {
|
||||||
backend := app.New()
|
backend := app.New()
|
||||||
backend.UsePlugin(icecast_input.Plugin)
|
// backend.UsePlugin(icecast_input.Plugin)
|
||||||
backend.UsePlugin(icecast_output.Plugin)
|
backend.UsePlugin(icecast_output.Plugin)
|
||||||
backend.UsePlugin(sine.Plugin)
|
backend.UsePlugin(sine.Plugin)
|
||||||
backend.Init()
|
backend.Init()
|
||||||
|
|
|
@ -2,24 +2,13 @@ package icecast_input
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"git.icedream.tech/icedream/uplink/app/authentication"
|
"git.icedream.tech/icedream/uplink/app/authentication"
|
||||||
"git.icedream.tech/icedream/uplink/app/channels"
|
"git.icedream.tech/icedream/uplink/app/channels"
|
||||||
"git.icedream.tech/icedream/uplink/app/servers/http"
|
"git.icedream.tech/icedream/uplink/app/servers/http"
|
||||||
"git.icedream.tech/icedream/uplink/app/streams"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
var allowedCopyHeaders = []string{
|
|
||||||
"icy-br",
|
|
||||||
"icy-name",
|
|
||||||
"icy-description",
|
|
||||||
"icy-pub",
|
|
||||||
"icy-url",
|
|
||||||
"icy-genre",
|
|
||||||
}
|
|
||||||
|
|
||||||
type pluginInstance struct {
|
type pluginInstance struct {
|
||||||
server *httpserver.Server
|
server *httpserver.Server
|
||||||
authenticator authentication.Authenticator
|
authenticator authentication.Authenticator
|
||||||
|
@ -36,9 +25,7 @@ func (instance *pluginInstance) SetChannelManager(channelManager *channels.Chann
|
||||||
|
|
||||||
func (instance *pluginInstance) SetServer(server *httpserver.Server) {
|
func (instance *pluginInstance) SetServer(server *httpserver.Server) {
|
||||||
instance.server = server
|
instance.server = server
|
||||||
}
|
|
||||||
|
|
||||||
func (instance *pluginInstance) Init() {
|
|
||||||
router := instance.server.Router
|
router := instance.server.Router
|
||||||
|
|
||||||
router.PUT("/:channel", func(ctx *gin.Context) {
|
router.PUT("/:channel", func(ctx *gin.Context) {
|
||||||
|
@ -56,36 +43,6 @@ func (instance *pluginInstance) Init() {
|
||||||
ctx.Status(401)
|
ctx.Status(401)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
io.Copy(channel.InputStream, ctx.Request.Body)
|
||||||
var sr io.Reader = ctx.Request.Body
|
|
||||||
defer ctx.Request.Body.Close()
|
|
||||||
if ctx.GetHeader("icy-metadata") == "1" {
|
|
||||||
metaInt64, err := strconv.ParseInt(ctx.GetHeader("icy-metaint"), 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
ctx.Status(400)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
metaInt := int(metaInt64)
|
|
||||||
|
|
||||||
// Client is sending metadata!
|
|
||||||
mr := streams.NewMetadataExtractor(sr, metaInt)
|
|
||||||
sr = mr
|
|
||||||
|
|
||||||
metadataChan := channel.Metadata()
|
|
||||||
defer func() { metadataChan <- nil }()
|
|
||||||
go func() {
|
|
||||||
for metadata := range metadataChan {
|
|
||||||
metadataToWrite := streams.Metadata{}
|
|
||||||
if value, ok := metadata["StreamTitle"]; ok {
|
|
||||||
metadataToWrite["StreamTitle"] = value
|
|
||||||
}
|
|
||||||
channel.SetMetadata(metadataToWrite)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
input := channel.AddInputStream("icecast")
|
|
||||||
|
|
||||||
io.Copy(input, sr)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,27 @@
|
||||||
package icecast_output
|
package icecast_output
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
"git.icedream.tech/icedream/uplink/app/authentication"
|
"git.icedream.tech/icedream/uplink/app/authentication"
|
||||||
"git.icedream.tech/icedream/uplink/app/channels"
|
"git.icedream.tech/icedream/uplink/app/channels"
|
||||||
|
"git.icedream.tech/icedream/uplink/app/media"
|
||||||
"git.icedream.tech/icedream/uplink/app/servers/http"
|
"git.icedream.tech/icedream/uplink/app/servers/http"
|
||||||
"git.icedream.tech/icedream/uplink/app/streams"
|
"git.icedream.tech/icedream/uplink/app/streams"
|
||||||
|
humanize "github.com/dustin/go-humanize"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/glycerine/rbuf"
|
||||||
)
|
)
|
||||||
|
|
||||||
type pluginInstance struct {
|
type pluginInstance struct {
|
||||||
server *httpserver.Server
|
server *httpserver.Server
|
||||||
authenticator authentication.Authenticator
|
authenticator authentication.Authenticator
|
||||||
channelManager *channels.ChannelManager
|
channelManager *channels.ChannelManager
|
||||||
|
ringBuffers map[string]map[string]*rbuf.FixedSizeRingBuf
|
||||||
}
|
}
|
||||||
|
|
||||||
func (instance *pluginInstance) SetAuthenticator(authenticator authentication.Authenticator) {
|
func (instance *pluginInstance) SetAuthenticator(authenticator authentication.Authenticator) {
|
||||||
|
@ -25,6 +31,33 @@ func (instance *pluginInstance) SetAuthenticator(authenticator authentication.Au
|
||||||
func (instance *pluginInstance) SetChannelManager(channelManager *channels.ChannelManager) {
|
func (instance *pluginInstance) SetChannelManager(channelManager *channels.ChannelManager) {
|
||||||
instance.channelManager = channelManager
|
instance.channelManager = channelManager
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
channelC := channelManager.Events().Sub("open")
|
||||||
|
log.Println("Burst cache: Now watching")
|
||||||
|
for c := range channelC {
|
||||||
|
channelId := c.(string)
|
||||||
|
go func(channel *channels.Channel) {
|
||||||
|
streamRbufMap := map[string]*rbuf.FixedSizeRingBuf{}
|
||||||
|
instance.ringBuffers[channelId] = streamRbufMap
|
||||||
|
outputContainerC := channel.Events.Sub("output_container")
|
||||||
|
log.Println("Burst cache: Now watching channel", channelId)
|
||||||
|
for c := range outputContainerC {
|
||||||
|
containerId := c.(string)
|
||||||
|
burstCache := rbuf.NewFixedSizeRingBuf(64 * 1024)
|
||||||
|
streamRbufMap[containerId] = burstCache
|
||||||
|
go func(container *media.MediaStreamContainer) {
|
||||||
|
r := container.Sub()
|
||||||
|
log.Println("Burst cache: Now watching container", containerId, "in channel", channelId)
|
||||||
|
io.Copy(burstCache, r)
|
||||||
|
}(channel.OutputContainers[containerId])
|
||||||
|
runtime.Gosched()
|
||||||
|
}
|
||||||
|
}(channelManager.Channel(channelId))
|
||||||
|
runtime.Gosched()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
runtime.Gosched()
|
||||||
|
|
||||||
// TODO - handle channel and container closure
|
// TODO - handle channel and container closure
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +66,8 @@ func (instance *pluginInstance) SetServer(server *httpserver.Server) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (instance *pluginInstance) Init() {
|
func (instance *pluginInstance) Init() {
|
||||||
|
instance.ringBuffers = map[string]map[string]*rbuf.FixedSizeRingBuf{}
|
||||||
|
|
||||||
router := instance.server.Router
|
router := instance.server.Router
|
||||||
|
|
||||||
router.GET("/:channel/:container", func(ctx *gin.Context) {
|
router.GET("/:channel/:container", func(ctx *gin.Context) {
|
||||||
|
@ -60,13 +95,6 @@ func (instance *pluginInstance) Init() {
|
||||||
ctx.Writer.Header().Set("icy-metadata", "1")
|
ctx.Writer.Header().Set("icy-metadata", "1")
|
||||||
ctx.Writer.Header().Set("icy-metaint", fmt.Sprintf("%d", metaInt))
|
ctx.Writer.Header().Set("icy-metaint", fmt.Sprintf("%d", metaInt))
|
||||||
}
|
}
|
||||||
ctx.Writer.Header().Set("icy-name", "Channel name") // TODO
|
|
||||||
ctx.Writer.Header().Set("icy-pub", "0") // TODO
|
|
||||||
ctx.Writer.Header().Set("Server", "Uplink/0.0.0; Icecast 2.4.0 compatible")
|
|
||||||
ctx.Writer.Header().Set("Cache-Control", "no-cache, no-store")
|
|
||||||
ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
|
||||||
ctx.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type")
|
|
||||||
ctx.Writer.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS, HEAD")
|
|
||||||
ctx.Writer.WriteHeader(200)
|
ctx.Writer.WriteHeader(200)
|
||||||
|
|
||||||
w := ctx.Writer
|
w := ctx.Writer
|
||||||
|
@ -75,26 +103,32 @@ func (instance *pluginInstance) Init() {
|
||||||
sr := container.Sub()
|
sr := container.Sub()
|
||||||
defer sr.Close()
|
defer sr.Close()
|
||||||
|
|
||||||
|
log.Println("Someone tuned in to", channelId, channel)
|
||||||
|
|
||||||
if sendMetadata {
|
if sendMetadata {
|
||||||
mw = streams.NewMetadataInjector(w, metaInt)
|
mw = streams.NewMetadataInjector(w, metaInt)
|
||||||
nw = mw
|
nw = mw
|
||||||
|
}
|
||||||
|
|
||||||
metadataChan := channel.Metadata()
|
if channelRbuf, ok := instance.ringBuffers[channelId]; ok {
|
||||||
defer func() { metadataChan <- nil }()
|
if containerRbuf, ok := channelRbuf[containerId]; ok {
|
||||||
go func() {
|
burst := containerRbuf.Bytes()
|
||||||
for metadata := range metadataChan {
|
log.Println("Sending", humanize.Bytes(uint64(len(burst))), "burst")
|
||||||
metadataToWrite := streams.Metadata{}
|
_, err := io.Copy(nw, bytes.NewReader(burst))
|
||||||
if value, ok := metadata["StreamTitle"]; ok {
|
if err != nil {
|
||||||
metadataToWrite["StreamTitle"] = value
|
log.Println(err)
|
||||||
}
|
return
|
||||||
mw.SetMetadata(metadataToWrite)
|
|
||||||
}
|
}
|
||||||
}()
|
} else {
|
||||||
|
log.Println("No burst cache for", channelId, "/", containerId)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Println("No burst cache for", channelId)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := io.Copy(nw, sr)
|
_, err := io.Copy(nw, sr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("copying stream to output failed:", err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@ func (instance *pluginInstance) Init() {
|
||||||
channelManager := instance.channelManager
|
channelManager := instance.channelManager
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
time.Sleep(2 * time.Second) // give burst cache a chance to realize
|
||||||
|
|
||||||
c, err := channelManager.Open("sine")
|
c, err := channelManager.Open("sine")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("ERROR: sine channel could not be opened:", err)
|
log.Println("ERROR: sine channel could not be opened:", err)
|
||||||
|
|
|
@ -43,11 +43,16 @@ func (stream *SineStream) Read(data []byte) (n int, err error) {
|
||||||
targetTime := stream.Timestamp.
|
targetTime := stream.Timestamp.
|
||||||
Add(time.Duration(float64(time.Second) * float64(stream.State) / float64(stream.Samplerate)))
|
Add(time.Duration(float64(time.Second) * float64(stream.State) / float64(stream.Samplerate)))
|
||||||
delay := targetTime.Sub(time.Now())
|
delay := targetTime.Sub(time.Now())
|
||||||
|
/*log.Println("state", stream.State, "value", sampleValue, "time", targetTime, "delay", delay)
|
||||||
|
time.Sleep(time.Second)*/
|
||||||
if delay > 0 {
|
if delay > 0 {
|
||||||
<-time.After(delay)
|
<-time.After(delay)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*if stream.State%uint64(stream.Samplerate) == 0 {
|
||||||
|
log.Println("state", stream.State, "value", sampleValue, "time", targetTime, "delay", delay)
|
||||||
|
}*/
|
||||||
|
|
||||||
stream.State++
|
stream.State++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit d481e19a7c9f8d849bb3f6a69854ec711dc894e8
|
Subproject commit f158770a793e28c093dc22c2a9ef0af20bdd804f
|
Loading…
Reference in New Issue