mirror of
https://github.com/datarhei/core.git
synced 2025-09-27 20:32:35 +08:00
379 lines
9.9 KiB
Go
379 lines
9.9 KiB
Go
package api
|
|
|
|
import (
|
|
"github.com/datarhei/core/v16/encoding/json"
|
|
"github.com/datarhei/core/v16/restream/app"
|
|
)
|
|
|
|
type ProgressIOFramerate struct {
|
|
Min json.Number `json:"min" swaggertype:"number" jsonschema:"type=number"`
|
|
Max json.Number `json:"max" swaggertype:"number" jsonschema:"type=number"`
|
|
Average json.Number `json:"avg" swaggertype:"number" jsonschema:"type=number"`
|
|
}
|
|
|
|
// ProgressIO represents the progress of an ffmpeg input or output
|
|
type ProgressIO struct {
|
|
ID string `json:"id" jsonschema:"minLength=1"`
|
|
Address string `json:"address" jsonschema:"minLength=1"`
|
|
|
|
// General
|
|
Index uint64 `json:"index" format:"uint64"`
|
|
Stream uint64 `json:"stream" format:"uint64"`
|
|
Format string `json:"format"`
|
|
Type string `json:"type"`
|
|
Codec string `json:"codec"`
|
|
Coder string `json:"coder"`
|
|
Profile int `json:"profile"`
|
|
Level int `json:"level"`
|
|
Frame uint64 `json:"frame" format:"uint64"`
|
|
Keyframe uint64 `json:"keyframe" format:"uint64"`
|
|
Framerate ProgressIOFramerate `json:"framerate"`
|
|
FPS json.Number `json:"fps" swaggertype:"number" jsonschema:"type=number"`
|
|
Packet uint64 `json:"packet" format:"uint64"`
|
|
PPS json.Number `json:"pps" swaggertype:"number" jsonschema:"type=number"`
|
|
Size uint64 `json:"size_kb" format:"uint64"` // kbytes
|
|
Bitrate json.Number `json:"bitrate_kbit" swaggertype:"number" jsonschema:"type=number"` // kbit/s
|
|
Extradata uint64 `json:"extradata_size_bytes" format:"uint64"` // bytes
|
|
|
|
// Video
|
|
Pixfmt string `json:"pix_fmt,omitempty"`
|
|
Quantizer json.Number `json:"q,omitempty" swaggertype:"number" jsonschema:"type=number"`
|
|
Width uint64 `json:"width,omitempty" format:"uint64"`
|
|
Height uint64 `json:"height,omitempty" format:"uint64"`
|
|
|
|
// Audio
|
|
Samplefmt string `json:"sample_fmt,omitempty"`
|
|
Sampling uint64 `json:"sampling_hz,omitempty" format:"uint64"`
|
|
Layout string `json:"layout,omitempty"`
|
|
Channels uint64 `json:"channels,omitempty" format:"uint64"`
|
|
|
|
// avstream
|
|
AVstream *AVstream `json:"avstream" jsonschema:"anyof_type=null;object"`
|
|
}
|
|
|
|
// Unmarshal converts a core ProgressIO to a ProgressIO in API representation
|
|
func (i *ProgressIO) Unmarshal(io *app.ProgressIO) {
|
|
if io == nil {
|
|
return
|
|
}
|
|
|
|
i.ID = io.ID
|
|
i.Address = io.Address
|
|
i.Index = io.Index
|
|
i.Stream = io.Stream
|
|
i.Format = io.Format
|
|
i.Type = io.Type
|
|
i.Codec = io.Codec
|
|
i.Coder = io.Coder
|
|
i.Profile = io.Profile
|
|
i.Level = io.Level
|
|
i.Frame = io.Frame
|
|
i.Keyframe = io.Keyframe
|
|
i.Framerate.Min = json.ToNumber(io.Framerate.Min)
|
|
i.Framerate.Max = json.ToNumber(io.Framerate.Max)
|
|
i.Framerate.Average = json.ToNumber(io.Framerate.Average)
|
|
i.FPS = json.ToNumber(io.FPS)
|
|
i.Packet = io.Packet
|
|
i.PPS = json.ToNumber(io.PPS)
|
|
i.Size = io.Size / 1024
|
|
i.Bitrate = json.ToNumber(io.Bitrate / 1024)
|
|
i.Extradata = io.Extradata
|
|
i.Pixfmt = io.Pixfmt
|
|
i.Quantizer = json.ToNumber(io.Quantizer)
|
|
i.Width = io.Width
|
|
i.Height = io.Height
|
|
i.Samplefmt = io.Samplefmt
|
|
i.Sampling = io.Sampling
|
|
i.Layout = io.Layout
|
|
i.Channels = io.Channels
|
|
|
|
if io.AVstream != nil {
|
|
i.AVstream = &AVstream{}
|
|
i.AVstream.Unmarshal(io.AVstream)
|
|
}
|
|
}
|
|
|
|
func (i *ProgressIO) Marshal() app.ProgressIO {
|
|
p := app.ProgressIO{
|
|
ID: i.ID,
|
|
Address: i.Address,
|
|
Index: i.Index,
|
|
Stream: i.Stream,
|
|
Format: i.Format,
|
|
Type: i.Type,
|
|
Codec: i.Codec,
|
|
Coder: i.Coder,
|
|
Profile: i.Profile,
|
|
Level: i.Level,
|
|
Frame: i.Frame,
|
|
Keyframe: i.Keyframe,
|
|
Packet: i.Packet,
|
|
Size: i.Size * 1024,
|
|
Extradata: i.Extradata,
|
|
Pixfmt: i.Pixfmt,
|
|
Width: i.Width,
|
|
Height: i.Height,
|
|
Samplefmt: i.Samplefmt,
|
|
Sampling: i.Sampling,
|
|
Layout: i.Layout,
|
|
Channels: i.Channels,
|
|
}
|
|
|
|
if x, err := i.Framerate.Min.Float64(); err == nil {
|
|
p.Framerate.Min = x
|
|
}
|
|
|
|
if x, err := i.Framerate.Max.Float64(); err == nil {
|
|
p.Framerate.Max = x
|
|
}
|
|
|
|
if x, err := i.Framerate.Average.Float64(); err == nil {
|
|
p.Framerate.Average = x
|
|
}
|
|
|
|
if x, err := i.FPS.Float64(); err == nil {
|
|
p.FPS = x
|
|
}
|
|
|
|
if x, err := i.PPS.Float64(); err == nil {
|
|
p.PPS = x
|
|
}
|
|
|
|
if x, err := i.Bitrate.Float64(); err == nil {
|
|
p.Bitrate = x * 1024
|
|
}
|
|
|
|
if x, err := i.Quantizer.Float64(); err == nil {
|
|
p.Quantizer = x
|
|
}
|
|
|
|
if i.AVstream != nil {
|
|
p.AVstream = i.AVstream.Marshal()
|
|
}
|
|
|
|
return p
|
|
}
|
|
|
|
// Progress represents the progress of an ffmpeg process
|
|
type Progress struct {
|
|
Started bool `json:"started"`
|
|
Input []ProgressIO `json:"inputs"`
|
|
Output []ProgressIO `json:"outputs"`
|
|
Mapping StreamMapping `json:"mapping"`
|
|
Frame uint64 `json:"frame" format:"uint64"`
|
|
Packet uint64 `json:"packet" format:"uint64"`
|
|
FPS json.Number `json:"fps" swaggertype:"number" jsonschema:"type=number"`
|
|
Quantizer json.Number `json:"q" swaggertype:"number" jsonschema:"type=number"`
|
|
Size uint64 `json:"size_kb" format:"uint64"` // kbytes
|
|
Time json.Number `json:"time" swaggertype:"number" jsonschema:"type=number"`
|
|
Bitrate json.Number `json:"bitrate_kbit" swaggertype:"number" jsonschema:"type=number"` // kbit/s
|
|
Speed json.Number `json:"speed" swaggertype:"number" jsonschema:"type=number"`
|
|
Drop uint64 `json:"drop" format:"uint64"`
|
|
Dup uint64 `json:"dup" format:"uint64"`
|
|
}
|
|
|
|
// Unmarshal converts a core Progress to a Progress in API representation
|
|
func (p *Progress) Unmarshal(pp *app.Progress) {
|
|
p.Input = []ProgressIO{}
|
|
p.Output = []ProgressIO{}
|
|
|
|
if pp == nil {
|
|
return
|
|
}
|
|
|
|
p.Started = pp.Started
|
|
p.Input = make([]ProgressIO, len(pp.Input))
|
|
p.Output = make([]ProgressIO, len(pp.Output))
|
|
p.Frame = pp.Frame
|
|
p.Packet = pp.Packet
|
|
p.FPS = json.ToNumber(pp.FPS)
|
|
p.Quantizer = json.ToNumber(pp.Quantizer)
|
|
p.Size = pp.Size / 1024
|
|
p.Time = json.ToNumber(pp.Time)
|
|
p.Bitrate = json.ToNumber(pp.Bitrate / 1024)
|
|
p.Speed = json.ToNumber(pp.Speed)
|
|
p.Drop = pp.Drop
|
|
p.Dup = pp.Dup
|
|
|
|
for i, io := range pp.Input {
|
|
p.Input[i].Unmarshal(&io)
|
|
}
|
|
|
|
for i, io := range pp.Output {
|
|
p.Output[i].Unmarshal(&io)
|
|
}
|
|
|
|
p.Mapping.Unmarshal(&pp.Mapping)
|
|
}
|
|
|
|
func (p *Progress) Marshal() app.Progress {
|
|
pp := app.Progress{
|
|
Started: p.Started,
|
|
Input: make([]app.ProgressIO, 0, len(p.Input)),
|
|
Output: make([]app.ProgressIO, 0, len(p.Output)),
|
|
Mapping: p.Mapping.Marshal(),
|
|
Frame: p.Frame,
|
|
Packet: p.Packet,
|
|
Size: p.Size * 1024,
|
|
Drop: p.Drop,
|
|
Dup: p.Dup,
|
|
}
|
|
|
|
if x, err := p.FPS.Float64(); err == nil {
|
|
pp.FPS = x
|
|
}
|
|
|
|
if x, err := p.Quantizer.Float64(); err == nil {
|
|
pp.Quantizer = x
|
|
}
|
|
|
|
if x, err := p.Time.Float64(); err == nil {
|
|
pp.Time = x
|
|
}
|
|
|
|
if x, err := p.Bitrate.Float64(); err == nil {
|
|
pp.Bitrate = x * 1024
|
|
}
|
|
|
|
if x, err := p.Speed.Float64(); err == nil {
|
|
pp.Speed = x
|
|
}
|
|
|
|
for _, io := range p.Input {
|
|
pp.Input = append(pp.Input, io.Marshal())
|
|
}
|
|
|
|
for _, io := range p.Output {
|
|
pp.Output = append(pp.Output, io.Marshal())
|
|
}
|
|
|
|
return pp
|
|
}
|
|
|
|
type GraphElement struct {
|
|
Index int `json:"index"`
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Filter string `json:"filter"`
|
|
DstID string `json:"dst_id"`
|
|
DstName string `json:"dst_name"`
|
|
DstFilter string `json:"dst_filter"`
|
|
Inpad string `json:"inpad"`
|
|
Outpad string `json:"outpad"`
|
|
Timebase string `json:"timebase"`
|
|
Type string `json:"type"` // audio or video
|
|
Format string `json:"format"`
|
|
Sampling uint64 `json:"sampling"` // Hz
|
|
Layout string `json:"layout"`
|
|
Width uint64 `json:"width"`
|
|
Height uint64 `json:"height"`
|
|
}
|
|
|
|
func (g *GraphElement) Unmarshal(a *app.GraphElement) {
|
|
g.Index = a.Index
|
|
g.ID = a.ID
|
|
g.Name = a.Name
|
|
g.Filter = a.Filter
|
|
g.DstID = a.DstID
|
|
g.DstName = a.DstName
|
|
g.DstFilter = a.DstFilter
|
|
g.Inpad = a.Inpad
|
|
g.Outpad = a.Outpad
|
|
g.Timebase = a.Timebase
|
|
g.Type = a.Type
|
|
g.Format = a.Format
|
|
g.Sampling = a.Sampling
|
|
g.Layout = a.Layout
|
|
g.Width = a.Width
|
|
g.Height = a.Height
|
|
}
|
|
|
|
func (g *GraphElement) Marshal() app.GraphElement {
|
|
a := app.GraphElement{
|
|
Index: g.Index,
|
|
ID: g.ID,
|
|
Name: g.Name,
|
|
Filter: g.Filter,
|
|
DstID: g.DstID,
|
|
DstName: g.DstName,
|
|
DstFilter: g.DstFilter,
|
|
Inpad: g.Inpad,
|
|
Outpad: g.Outpad,
|
|
Timebase: g.Timebase,
|
|
Type: g.Type,
|
|
Format: g.Format,
|
|
Sampling: g.Sampling,
|
|
Layout: g.Layout,
|
|
Width: g.Width,
|
|
Height: g.Height,
|
|
}
|
|
|
|
return a
|
|
}
|
|
|
|
type GraphMapping struct {
|
|
Input int `json:"input"`
|
|
Output int `json:"output"`
|
|
Index int `json:"index"`
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Copy bool `json:"copy"`
|
|
}
|
|
|
|
func (g *GraphMapping) Unmarshal(a *app.GraphMapping) {
|
|
g.Input = a.Input
|
|
g.Output = a.Output
|
|
g.Index = a.Index
|
|
g.ID = a.ID
|
|
g.Name = a.Name
|
|
g.Copy = a.Copy
|
|
}
|
|
|
|
func (g *GraphMapping) Marshal() app.GraphMapping {
|
|
a := app.GraphMapping{
|
|
Input: g.Input,
|
|
Output: g.Output,
|
|
Index: g.Index,
|
|
ID: g.ID,
|
|
Name: g.Name,
|
|
Copy: g.Copy,
|
|
}
|
|
|
|
return a
|
|
}
|
|
|
|
type StreamMapping struct {
|
|
Graphs []GraphElement `json:"graphs"`
|
|
Mapping []GraphMapping `json:"mapping"`
|
|
}
|
|
|
|
// Unmarshal converts a core StreamMapping to a StreamMapping in API representation
|
|
func (s *StreamMapping) Unmarshal(m *app.StreamMapping) {
|
|
s.Graphs = make([]GraphElement, len(m.Graphs))
|
|
for i, graph := range m.Graphs {
|
|
s.Graphs[i].Unmarshal(&graph)
|
|
}
|
|
|
|
s.Mapping = make([]GraphMapping, len(m.Mapping))
|
|
for i, mapping := range m.Mapping {
|
|
s.Mapping[i].Unmarshal(&mapping)
|
|
}
|
|
}
|
|
|
|
func (s *StreamMapping) Marshal() app.StreamMapping {
|
|
m := app.StreamMapping{
|
|
Graphs: make([]app.GraphElement, 0, len(s.Graphs)),
|
|
Mapping: make([]app.GraphMapping, 0, len(s.Mapping)),
|
|
}
|
|
|
|
for _, graph := range s.Graphs {
|
|
m.Graphs = append(m.Graphs, graph.Marshal())
|
|
}
|
|
|
|
for _, mapping := range s.Mapping {
|
|
m.Mapping = append(m.Mapping, mapping.Marshal())
|
|
}
|
|
|
|
return m
|
|
}
|