Compare commits
19 Commits
Author | SHA1 | Date |
---|---|---|
|
3bad711693 | |
|
f5a86e9282 | |
|
4dc3a544f7 | |
|
f9c5b5e0c6 | |
|
426c26c613 | |
|
4187d0dfda | |
|
a4e70df617 | |
|
994c0995e0 | |
|
a99fa94072 | |
|
331286f9d0 | |
|
c0774e8ba6 | |
|
0d8ecc64ad | |
|
6481884b73 | |
|
f8dce5ce9d | |
|
7f13d014b9 | |
|
78f280e743 | |
|
69147a81b3 | |
|
ae6b69d40d | |
|
50e7125bce |
|
@ -22,8 +22,11 @@ _testmain.go
|
||||||
# built binaries
|
# built binaries
|
||||||
uplink
|
uplink
|
||||||
*.exe
|
*.exe
|
||||||
|
*.dll
|
||||||
*.test
|
*.test
|
||||||
|
|
||||||
|
*.orig
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
# Windows image file caches
|
# Windows image file caches
|
||||||
|
|
|
@ -17,6 +17,8 @@ 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 {
|
||||||
|
@ -50,12 +52,17 @@ 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 {
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package genericapi
|
||||||
|
|
||||||
|
type DynamicallyConfigurable interface {
|
||||||
|
MakeConfigurationObject() interface{}
|
||||||
|
ValidateConfiguration(config interface{}) bool
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
package codecs
|
||||||
|
|
||||||
|
//go:generate go run ./internal/generator/main.go
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,83 @@
|
||||||
|
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)
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
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,6 +4,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -13,7 +14,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("mpthreetest.mp3")
|
reader, _ := os.Open(filepath.Join("testassets", "mpthreetest.mp3"))
|
||||||
defer reader.Close()
|
defer reader.Close()
|
||||||
|
|
||||||
demuxer := Demux(reader)
|
demuxer := Demux(reader)
|
||||||
|
@ -28,7 +29,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, ShouldEqual, "mp3")
|
So(stream.CodecInfo.CodecName, ShouldBeIn, []string{"mp3", "mp3float"})
|
||||||
So(stream.CodecInfo.Type, ShouldEqual, Audio)
|
So(stream.CodecInfo.Type, ShouldEqual, Audio)
|
||||||
audioStream = stream
|
audioStream = stream
|
||||||
}
|
}
|
||||||
|
@ -43,7 +44,7 @@ func Test_Demux(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("video and audio", func() {
|
Convey("video and audio", func() {
|
||||||
reader, _ := os.Open("small.ogv")
|
reader, _ := os.Open(filepath.Join("testassets", "small.ogv"))
|
||||||
defer reader.Close()
|
defer reader.Close()
|
||||||
|
|
||||||
demuxer := Demux(reader)
|
demuxer := Demux(reader)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
package formats
|
||||||
|
|
||||||
|
//go:generate go run ./internal/generator/main.go
|
|
@ -0,0 +1,839 @@
|
||||||
|
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
|
||||||
|
)
|
|
@ -0,0 +1,86 @@
|
||||||
|
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)
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
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,6 +4,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
@ -12,7 +13,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("mpthreetest.mp3")
|
reader, _ := os.Open(filepath.Join("testassets", "mpthreetest.mp3"))
|
||||||
defer reader.Close()
|
defer reader.Close()
|
||||||
|
|
||||||
demuxer := Demux(reader)
|
demuxer := Demux(reader)
|
||||||
|
@ -27,7 +28,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, ShouldEqual, "mp3")
|
So(stream.CodecInfo.CodecName, ShouldBeIn, []string{"mp3", "mp3float"})
|
||||||
So(stream.CodecInfo.Type, ShouldEqual, Audio)
|
So(stream.CodecInfo.Type, ShouldEqual, Audio)
|
||||||
audioStream = stream
|
audioStream = stream
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package transcode
|
||||||
|
|
||||||
|
import "git.icedream.tech/icedream/uplink/app/genericapi"
|
||||||
|
|
||||||
|
type Transcoder interface {
|
||||||
|
genericapi.DynamicallyConfigurable
|
||||||
|
|
||||||
|
AcceptedInputCodecs() []string
|
||||||
|
AcceptedOutputCodecs() []string
|
||||||
|
|
||||||
|
NewInstance(config interface{}) <-TranscoderInstance
|
||||||
|
}
|
|
@ -9,12 +9,17 @@ 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 []plugins.PluginInstance
|
plugins []registeredPlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() *App {
|
func New() *App {
|
||||||
|
@ -23,7 +28,7 @@ func New() *App {
|
||||||
Authenticator: new(authentication.DummyAuthenticator),
|
Authenticator: new(authentication.DummyAuthenticator),
|
||||||
ChannelManager: channels.NewChannelManager(),
|
ChannelManager: channels.NewChannelManager(),
|
||||||
|
|
||||||
plugins: []plugins.PluginInstance{},
|
plugins: []registeredPlugin{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,14 +45,18 @@ func (app *App) UsePlugin(plugin *plugins.Plugin) {
|
||||||
p.SetAuthenticator(app.Authenticator)
|
p.SetAuthenticator(app.Authenticator)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("Plugin initialized:", plugin.Descriptor.Name)
|
log.Println("Plugin registered:", plugin.Descriptor.Name)
|
||||||
|
|
||||||
app.plugins = append(app.plugins, pluginInstance)
|
app.plugins = append(app.plugins, registeredPlugin{
|
||||||
|
Instance: pluginInstance,
|
||||||
|
Descriptor: plugin.Descriptor,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *App) Init() {
|
func (app *App) Init() {
|
||||||
for _, plugin := range app.plugins {
|
for _, plugin := range app.plugins {
|
||||||
plugin.Init()
|
plugin.Instance.Init()
|
||||||
|
log.Println("Plugin initialized:", plugin.Descriptor.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,9 @@ 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,22 +39,23 @@ 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 {
|
||||||
_, cerr := mi.writeMetadata()
|
_, err = mi.writeMetadata()
|
||||||
//n += cn
|
if err != nil {
|
||||||
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[mi.offset:mi.offset+toWrite])
|
copy(outBytes, data[n:n+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,6 +4,7 @@ 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"
|
||||||
)
|
)
|
||||||
|
@ -16,7 +17,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,13 +2,24 @@ 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
|
||||||
|
@ -25,7 +36,9 @@ 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) {
|
||||||
|
@ -43,6 +56,36 @@ func (instance *pluginInstance) SetServer(server *httpserver.Server) {
|
||||||
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,27 +1,21 @@
|
||||||
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) {
|
||||||
|
@ -31,33 +25,6 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,8 +33,6 @@ 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) {
|
||||||
|
@ -95,6 +60,13 @@ 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
|
||||||
|
@ -103,32 +75,26 @@ 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
|
||||||
}
|
|
||||||
|
|
||||||
if channelRbuf, ok := instance.ringBuffers[channelId]; ok {
|
metadataChan := channel.Metadata()
|
||||||
if containerRbuf, ok := channelRbuf[containerId]; ok {
|
defer func() { metadataChan <- nil }()
|
||||||
burst := containerRbuf.Bytes()
|
go func() {
|
||||||
log.Println("Sending", humanize.Bytes(uint64(len(burst))), "burst")
|
for metadata := range metadataChan {
|
||||||
_, err := io.Copy(nw, bytes.NewReader(burst))
|
metadataToWrite := streams.Metadata{}
|
||||||
if err != nil {
|
if value, ok := metadata["StreamTitle"]; ok {
|
||||||
log.Println(err)
|
metadataToWrite["StreamTitle"] = value
|
||||||
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(err)
|
log.Println("copying stream to output failed:", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,6 @@ 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,16 +43,11 @@ 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 f158770a793e28c093dc22c2a9ef0af20bdd804f
|
Subproject commit d481e19a7c9f8d849bb3f6a69854ec711dc894e8
|
Loading…
Reference in New Issue