Skip to content

Commit 358ffdf

Browse files
committed
Updates
1 parent 3d49cbf commit 358ffdf

File tree

12 files changed

+406
-127
lines changed

12 files changed

+406
-127
lines changed

cmd/cli/decode.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package main
22

33
import (
4-
5-
// Packages
6-
74
"encoding/json"
85
"fmt"
96

7+
// Packages
108
"github.com/mutablelogic/go-media"
119
)
1210

cmd/cli/demuxers.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
// Packages
8+
"github.com/djthorpe/go-tablewriter"
9+
"github.com/mutablelogic/go-media"
10+
)
11+
12+
type DemuxersCmd struct {
13+
Filter string `arg:"" optional:"" help:"Filter by mimetype, name or .ext" type:"string"`
14+
}
15+
16+
func (cmd *DemuxersCmd) Run(globals *Globals) error {
17+
manager := media.NewManager()
18+
formats := manager.InputFormats(cmd.Filter)
19+
writer := tablewriter.New(os.Stdout, tablewriter.OptHeader(), tablewriter.OptOutputText())
20+
if len(formats) == 0 {
21+
fmt.Printf("No demuxers found for %q\n", cmd.Filter)
22+
return nil
23+
} else {
24+
return writer.Write(formats)
25+
}
26+
}

cmd/cli/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ type Globals struct {
1515
type CLI struct {
1616
Globals
1717
Version VersionCmd `cmd:"version" help:"Print version information"`
18+
Demuxers DemuxersCmd `cmd:"demuxers" help:"List media demultiplex (input) formats"`
19+
Muxers MuxersCmd `cmd:"muxers" help:"List media multiplex (output) formats"`
1820
Metadata MetadataCmd `cmd:"metadata" help:"Display media metadata information"`
1921
Decode DecodeCmd `cmd:"decode" help:"Decode media"`
2022
}

cmd/cli/muxers.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
// Packages
8+
"github.com/djthorpe/go-tablewriter"
9+
"github.com/mutablelogic/go-media"
10+
)
11+
12+
type MuxersCmd struct {
13+
Filter string `arg:"" optional:"" help:"Filter by mimetype, name or .ext" type:"string"`
14+
}
15+
16+
func (cmd *MuxersCmd) Run(globals *Globals) error {
17+
manager := media.NewManager()
18+
formats := manager.OutputFormats(cmd.Filter)
19+
writer := tablewriter.New(os.Stdout, tablewriter.OptHeader(), tablewriter.OptOutputText())
20+
if len(formats) == 0 {
21+
fmt.Printf("No muxers found for %q\n", cmd.Filter)
22+
return nil
23+
} else {
24+
return writer.Write(formats)
25+
}
26+
}

go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,19 @@ toolchain go1.22.4
77
require (
88
github.com/alecthomas/kong v0.9.0
99
github.com/djthorpe/go-errors v1.0.3
10-
github.com/djthorpe/go-tablewriter v0.0.7
10+
github.com/djthorpe/go-tablewriter v0.0.8
1111
github.com/hashicorp/go-multierror v1.1.1
1212
github.com/mutablelogic/go-client v1.0.8
1313
github.com/stretchr/testify v1.9.0
1414
)
1515

1616
require (
1717
github.com/davecgh/go-spew v1.1.1 // indirect
18-
github.com/hashicorp/errwrap v1.0.0 // indirect
18+
github.com/hashicorp/errwrap v1.1.0 // indirect
1919
github.com/mattn/go-runewidth v0.0.15 // indirect
2020
github.com/pmezard/go-difflib v1.0.0 // indirect
2121
github.com/rivo/uniseg v0.4.7 // indirect
22-
golang.org/x/sys v0.20.0 // indirect
23-
golang.org/x/term v0.20.0 // indirect
22+
golang.org/x/sys v0.21.0 // indirect
23+
golang.org/x/term v0.21.0 // indirect
2424
gopkg.in/yaml.v3 v3.0.1 // indirect
2525
)

manager.go

Lines changed: 148 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,184 @@
11
package media
22

3-
import ffmpeg "github.com/mutablelogic/go-media/sys/ffmpeg61"
3+
import (
4+
"encoding/json"
5+
"slices"
6+
"strings"
7+
8+
// Package imports
9+
ff "github.com/mutablelogic/go-media/sys/ffmpeg61"
10+
)
411

512
////////////////////////////////////////////////////////////////////////////
613
// TYPES
714

815
type manager struct {
916
}
1017

18+
type inputformat struct {
19+
ctx *ff.AVInputFormat
20+
Name string `json:"name"`
21+
Description string `json:"description" writer:",wrap,width:40"`
22+
Extensions string `json:"extensions,omitempty"`
23+
MimeTypes string `json:"mimetypes,omitempty"`
24+
}
25+
26+
type outputformat struct {
27+
ctx *ff.AVOutputFormat
28+
Name string `json:"name"`
29+
Description string `json:"description" writer:",wrap,width:40"`
30+
Extensions string `json:"extensions,omitempty"`
31+
MimeTypes string `json:"mimetypes,omitempty"`
32+
}
33+
1134
////////////////////////////////////////////////////////////////////////////
1235
// LIFECYCLE
1336

1437
func NewManager() *manager {
1538
return new(manager)
1639
}
1740

41+
func newInputFormat(ctx *ff.AVInputFormat) *inputformat {
42+
return &inputformat{
43+
ctx: ctx,
44+
Name: ctx.Name(),
45+
Description: ctx.LongName(),
46+
Extensions: ctx.Extensions(),
47+
MimeTypes: ctx.MimeTypes(),
48+
}
49+
}
50+
51+
func newOutputFormat(ctx *ff.AVOutputFormat) *outputformat {
52+
return &outputformat{
53+
ctx: ctx,
54+
Name: ctx.Name(),
55+
Description: ctx.LongName(),
56+
Extensions: ctx.Extensions(),
57+
MimeTypes: ctx.MimeTypes(),
58+
}
59+
}
60+
61+
////////////////////////////////////////////////////////////////////////////
62+
// STRINGIFY
63+
64+
func (v inputformat) MarshalJSON() ([]byte, error) {
65+
return json.Marshal(v.ctx)
66+
}
67+
68+
func (v outputformat) MarshalJSON() ([]byte, error) {
69+
return json.Marshal(v.ctx)
70+
}
71+
72+
func (v inputformat) String() string {
73+
data, _ := json.MarshalIndent(v, "", " ")
74+
return string(data)
75+
}
76+
77+
func (v outputformat) String() string {
78+
data, _ := json.MarshalIndent(v, "", " ")
79+
return string(data)
80+
}
81+
1882
////////////////////////////////////////////////////////////////////////////
1983
// PUBLIC METHODS
2084

21-
// Return the list of input formats, filtering by name or mimetype
22-
func (this *manager) InputFormats(mimetype string) []InputFormat {
85+
// Return the list of matching input formats, optionally filtering by name,
86+
// extension or mimetype File extensions should be prefixed with a dot,
87+
// e.g. ".mp4"
88+
func (manager *manager) InputFormats(filter ...string) []InputFormat {
2389
var result []InputFormat
90+
91+
// Iterate over all input formats
2492
var opaque uintptr
2593
for {
26-
demuxer := ffmpeg.AVFormat_demuxer_iterate(&opaque)
94+
demuxer := ff.AVFormat_demuxer_iterate(&opaque)
2795
if demuxer == nil {
2896
break
2997
}
30-
if this.matchesInput(demuxer, mimetype) {
31-
result = append(result, demuxer)
98+
if len(filter) == 0 {
99+
result = append(result, newInputFormat(demuxer))
100+
} else if manager.matchesInput(demuxer, filter...) {
101+
result = append(result, newInputFormat(demuxer))
32102
}
33103
}
34-
return result
35104

105+
// Return success
106+
return result
36107
}
37108

38-
// Return the list of output formats, filtering by name or mimetype
39-
func (this *manager) OutputFormats(name string) []OutputFormat {
40-
return nil
109+
// Return the list of matching output formats, optionally filtering by name,
110+
// extension or mimetype File extensions should be prefixed with a dot,
111+
// e.g. ".mp4"
112+
func (manager *manager) OutputFormats(filter ...string) []OutputFormat {
113+
var result []OutputFormat
114+
115+
// Iterate over all output formats
116+
var opaque uintptr
117+
for {
118+
muxer := ff.AVFormat_muxer_iterate(&opaque)
119+
if muxer == nil {
120+
break
121+
}
122+
if len(filter) == 0 {
123+
result = append(result, newOutputFormat(muxer))
124+
} else if manager.matchesOutput(muxer, filter...) {
125+
result = append(result, newOutputFormat(muxer))
126+
}
127+
}
128+
129+
// Return success
130+
return result
41131
}
42132

43133
////////////////////////////////////////////////////////////////////////////
44134
// PRIVATE METHODS
45135

46-
func (this *manager) matchesInput(demuxer *ffmpeg.AVInputFormat, mimetype string) bool {
47-
return true
136+
func (this *manager) matchesInput(demuxer *ff.AVInputFormat, mimetype ...string) bool {
137+
// Match any
138+
if len(mimetype) == 0 {
139+
return true
140+
}
141+
// Match mimetype
142+
for _, mimetype := range mimetype {
143+
mimetype = strings.ToLower(strings.TrimSpace(mimetype))
144+
if slices.Contains(strings.Split(demuxer.Name(), ","), mimetype) {
145+
return true
146+
}
147+
if strings.HasPrefix(mimetype, ".") {
148+
ext := strings.TrimPrefix(mimetype, ".")
149+
if slices.Contains(strings.Split(demuxer.Extensions(), ","), ext) {
150+
return true
151+
}
152+
}
153+
if slices.Contains(strings.Split(demuxer.MimeTypes(), ","), mimetype) {
154+
return true
155+
}
156+
}
157+
// No match
158+
return false
159+
}
160+
161+
func (this *manager) matchesOutput(muxer *ff.AVOutputFormat, mimetype ...string) bool {
162+
// Match any
163+
if len(mimetype) == 0 {
164+
return true
165+
}
166+
// Match mimetype
167+
for _, mimetype := range mimetype {
168+
mimetype = strings.ToLower(strings.TrimSpace(mimetype))
169+
if slices.Contains(strings.Split(muxer.Name(), ","), mimetype) {
170+
return true
171+
}
172+
if strings.HasPrefix(mimetype, ".") {
173+
ext := strings.TrimPrefix(mimetype, ".")
174+
if slices.Contains(strings.Split(muxer.Extensions(), ","), ext) {
175+
return true
176+
}
177+
}
178+
if slices.Contains(strings.Split(muxer.MimeTypes(), ","), mimetype) {
179+
return true
180+
}
181+
}
182+
// No match
183+
return false
48184
}

manager_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package media_test
2+
3+
import (
4+
// Import namespaces
5+
"testing"
6+
7+
// Package imports
8+
"github.com/stretchr/testify/assert"
9+
10+
// Namespace imports
11+
. "github.com/mutablelogic/go-media"
12+
)
13+
14+
func Test_manager_001(t *testing.T) {
15+
assert := assert.New(t)
16+
17+
manager := NewManager()
18+
assert.NotNil(manager)
19+
20+
formats := manager.InputFormats()
21+
assert.NotNil(formats)
22+
t.Log(formats)
23+
}
24+
25+
func Test_manager_002(t *testing.T) {
26+
assert := assert.New(t)
27+
28+
manager := NewManager()
29+
assert.NotNil(manager)
30+
31+
formats := manager.OutputFormats()
32+
assert.NotNil(formats)
33+
t.Log(formats)
34+
}

0 commit comments

Comments
 (0)