Skip to content

Commit 5a38897

Browse files
committed
Updates
1 parent 39b5ba9 commit 5a38897

18 files changed

+720
-43
lines changed

manager.go

+28-23
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ package media
1616
// }
1717
//
1818
// Various options are available to control the manager, for
19-
// logging and affecting decoding.
19+
// logging and affecting decoding, that can be applied when
20+
// creating the manager by passing them as arguments.
2021
//
2122
// Only one manager can be created. If NewManager is called
2223
// a second time, the previously created manager is returned,
@@ -46,33 +47,11 @@ type Manager interface {
4647
// of the caller to also close the writer when done.
4748
//Write(io.Writer, Format, []Metadata, ...Parameters) (Media, error)
4849

49-
// Return supported input formats which match any filter, which can be
50-
// a name, extension (with preceeding period) or mimetype. The MediaType
51-
// can be NONE (for any) or combinations of DEVICE and STREAM.
52-
//InputFormats(Type, ...string) []Format
53-
54-
// Return supported output formats which match any filter, which can be
55-
// a name, extension (with preceeding period) or mimetype. The MediaType
56-
// can be NONE (for any) or combinations of DEVICE and STREAM.
57-
//OutputFormats(Type, ...string) []Format
58-
5950
// Return supported devices for a given format.
6051
// Not all devices may be supported on all platforms or listed
6152
// if the device does not support enumeration.
6253
//Devices(Format) []Device
6354

64-
// Return all supported channel layouts
65-
//ChannelLayouts() []Metadata
66-
67-
// Return all supported sample formats
68-
//SampleFormats() []Metadata
69-
70-
// Return all supported pixel formats
71-
//PixelFormats() []Metadata
72-
73-
// Return all supported codecs
74-
//Codecs() []Metadata
75-
7655
// Return audio parameters for encoding
7756
// ChannelLayout, SampleFormat, Samplerate
7857
//AudioParameters(string, string, int) (Parameters, error)
@@ -89,6 +68,32 @@ type Manager interface {
8968
// Codec name, Profile name, Framerate (fps) and VideoParameters
9069
//VideoCodecParameters(string, string, float64, VideoParameters) (Parameters, error)
9170

71+
// Return supported input formats which match any filter, which can be
72+
// a name, extension (with preceeding period) or mimetype. The MediaType
73+
// can be NONE (for any) or combinations of DEVICE and STREAM.
74+
//InputFormats(Type, ...string) []Format
75+
76+
// Return supported output formats which match any filter, which can be
77+
// a name, extension (with preceeding period) or mimetype. The MediaType
78+
// can be NONE (for any) or combinations of DEVICE and STREAM.
79+
//OutputFormats(Type, ...string) []Format
80+
81+
// Return all supported sample formats
82+
SampleFormats() []Metadata
83+
84+
// Return all supported pixel formats
85+
PixelFormats() []Metadata
86+
87+
// Return standard channel layouts which can be used for audio,
88+
// with the number of channels provided. If no channels are provided,
89+
// then all standard channel layouts are returned.
90+
ChannelLayouts() []Metadata
91+
92+
// Return all supported codecs, of a specific type or all
93+
// if ANY is used. If any names is provided, then only the codecs
94+
// with those names are returned.
95+
Codecs(Type, ...string) []Metadata
96+
9297
// Return version information for the media manager as a set of
9398
// metadata
9499
Version() []Metadata

metadata.go

+3
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,7 @@ type Metadata interface {
2525

2626
// Returns the value as an image
2727
Image() image.Image
28+
29+
// Returns the value as an interface
30+
Any() any
2831
}

pkg/ffmpeg/channellayout.go

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package ffmpeg
2+
3+
import (
4+
"encoding/json"
5+
6+
// Packages
7+
ff "github.com/mutablelogic/go-media/sys/ffmpeg61"
8+
)
9+
10+
///////////////////////////////////////////////////////////////////////////////
11+
// TYPES
12+
13+
type (
14+
ChannelLayout ff.AVChannelLayout
15+
Channel ff.AVChannel
16+
)
17+
18+
type jsonChannelLayout struct {
19+
Name string `json:"name"`
20+
NumChannels int `json:"num_channels"`
21+
Order string `json:"order"`
22+
Channels []*Channel `json:"channels"`
23+
}
24+
25+
type jsonChannel struct {
26+
Index int `json:"index"`
27+
Name string `json:"name"`
28+
Description string `json:"description,omitempty"`
29+
}
30+
31+
///////////////////////////////////////////////////////////////////////////////
32+
// LIFECYCLE
33+
34+
func newChannelLayout(channellayout *ff.AVChannelLayout) *ChannelLayout {
35+
if !ff.AVUtil_channel_layout_check(channellayout) {
36+
return nil
37+
}
38+
return (*ChannelLayout)(channellayout)
39+
}
40+
41+
func newChannel(channel ff.AVChannel) *Channel {
42+
if channel == ff.AV_CHAN_NONE {
43+
return nil
44+
}
45+
return (*Channel)(&channel)
46+
}
47+
48+
///////////////////////////////////////////////////////////////////////////////
49+
// STRINGIFY
50+
51+
func (ch *ChannelLayout) MarshalJSON() ([]byte, error) {
52+
return json.Marshal(&jsonChannelLayout{
53+
Name: ch.Name(),
54+
NumChannels: ch.NumChannels(),
55+
Order: ch.Order(),
56+
Channels: ch.Channels(),
57+
})
58+
}
59+
60+
func (ch *Channel) MarshalJSON() ([]byte, error) {
61+
return json.Marshal(&jsonChannel{
62+
Name: ch.Name(),
63+
Description: ch.Description(),
64+
})
65+
}
66+
67+
func (ch *ChannelLayout) String() string {
68+
data, _ := json.MarshalIndent(ch, "", " ")
69+
return string(data)
70+
}
71+
72+
func (ch *Channel) String() string {
73+
data, _ := json.MarshalIndent(ch, "", " ")
74+
return string(data)
75+
}
76+
77+
///////////////////////////////////////////////////////////////////////////////
78+
// PROPERTIES - CHANNEL LAYOUT
79+
80+
func (ch *ChannelLayout) Name() string {
81+
if desc, err := ff.AVUtil_channel_layout_describe((*ff.AVChannelLayout)(ch)); err != nil {
82+
return ""
83+
} else {
84+
return desc
85+
}
86+
}
87+
88+
func (ch *ChannelLayout) NumChannels() int {
89+
return ff.AVUtil_get_channel_layout_nb_channels((*ff.AVChannelLayout)(ch))
90+
}
91+
92+
func (ch *ChannelLayout) Channels() []*Channel {
93+
var result []*Channel
94+
for i := 0; i < ch.NumChannels(); i++ {
95+
channel := ff.AVUtil_channel_layout_channel_from_index((*ff.AVChannelLayout)(ch), i)
96+
if channel != ff.AV_CHAN_NONE {
97+
result = append(result, newChannel(channel))
98+
}
99+
}
100+
return result
101+
}
102+
103+
func (ch *ChannelLayout) Order() string {
104+
order := (*ff.AVChannelLayout)(ch).Order()
105+
switch order {
106+
case ff.AV_CHANNEL_ORDER_UNSPEC:
107+
return "unspecified"
108+
case ff.AV_CHANNEL_ORDER_NATIVE:
109+
return "native"
110+
case ff.AV_CHANNEL_ORDER_CUSTOM:
111+
return "custom"
112+
case ff.AV_CHANNEL_ORDER_AMBISONIC:
113+
return "ambisonic"
114+
}
115+
return order.String()
116+
}
117+
118+
///////////////////////////////////////////////////////////////////////////////
119+
// PROPERTIES - CHANNEL
120+
121+
func (ch *Channel) Name() string {
122+
if desc, err := ff.AVUtil_channel_name((ff.AVChannel)(*ch)); err != nil {
123+
return "unknown"
124+
} else {
125+
return desc
126+
}
127+
}
128+
129+
func (ch *Channel) Description() string {
130+
if desc, err := ff.AVUtil_channel_description((ff.AVChannel)(*ch)); err != nil {
131+
return ""
132+
} else {
133+
return desc
134+
}
135+
}

pkg/ffmpeg/channellayout_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package ffmpeg_test
2+
3+
import (
4+
"testing"
5+
6+
ffmpeg "github.com/mutablelogic/go-media/pkg/ffmpeg"
7+
assert "github.com/stretchr/testify/assert"
8+
)
9+
10+
func Test_channellayout_001(t *testing.T) {
11+
assert := assert.New(t)
12+
13+
manager, err := ffmpeg.NewManager()
14+
if !assert.NoError(err) {
15+
t.FailNow()
16+
}
17+
18+
for _, format := range manager.ChannelLayouts() {
19+
t.Logf("%v", format)
20+
}
21+
}

pkg/ffmpeg/codec.go

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package ffmpeg
2+
3+
import (
4+
"encoding/json"
5+
"sort"
6+
7+
// Packages
8+
media "github.com/mutablelogic/go-media"
9+
ff "github.com/mutablelogic/go-media/sys/ffmpeg61"
10+
)
11+
12+
///////////////////////////////////////////////////////////////////////////////
13+
// TYPES
14+
15+
type Codec ff.AVCodec
16+
17+
///////////////////////////////////////////////////////////////////////////////
18+
// LIFECYCLE
19+
20+
func newCodec(codec *ff.AVCodec) *Codec {
21+
return (*Codec)(codec)
22+
}
23+
24+
///////////////////////////////////////////////////////////////////////////////
25+
// STRINGIFY
26+
27+
func (codec *Codec) MarshalJSON() ([]byte, error) {
28+
return (*ff.AVCodec)(codec).MarshalJSON()
29+
}
30+
31+
func (codec *Codec) String() string {
32+
data, _ := json.MarshalIndent((*ff.AVCodec)(codec), "", " ")
33+
return string(data)
34+
}
35+
36+
///////////////////////////////////////////////////////////////////////////////
37+
// PUBLIC METHODS
38+
39+
// Return the type of codec
40+
func (codec *Codec) Type() media.Type {
41+
switch (*ff.AVCodec)(codec).Type() {
42+
case ff.AVMEDIA_TYPE_AUDIO:
43+
return media.AUDIO
44+
case ff.AVMEDIA_TYPE_VIDEO:
45+
return media.VIDEO
46+
case ff.AVMEDIA_TYPE_SUBTITLE:
47+
return media.SUBTITLE
48+
}
49+
return media.NONE
50+
}
51+
52+
// The name the codec is referred to by
53+
func (codec *Codec) Name() string {
54+
return (*ff.AVCodec)(codec).Name()
55+
}
56+
57+
// The description of the codec
58+
func (codec *Codec) Description() string {
59+
return (*ff.AVCodec)(codec).LongName()
60+
}
61+
62+
// Pixel formats supported by the codec. This is only valid for video codecs.
63+
// The first pixel format is the default.
64+
func (codec *Codec) PixelFormats() []string {
65+
pixfmts := (*ff.AVCodec)(codec).PixelFormats()
66+
result := make([]string, len(pixfmts))
67+
for i, pixfmt := range pixfmts {
68+
result[i] = ff.AVUtil_get_pix_fmt_name(pixfmt)
69+
}
70+
return result
71+
}
72+
73+
// Sample formats supported by the codec. This is only valid for audio codecs.
74+
// The first sample format is the default.
75+
func (codec *Codec) SampleFormats() []string {
76+
samplefmts := (*ff.AVCodec)(codec).SampleFormats()
77+
result := make([]string, len(samplefmts))
78+
for i, samplefmt := range samplefmts {
79+
result[i] = ff.AVUtil_get_sample_fmt_name(samplefmt)
80+
}
81+
return result
82+
}
83+
84+
// Sample rates supported by the codec. This is only valid for audio codecs.
85+
// The first sample rate is the highest, sort the list in reverse order.
86+
func (codec *Codec) SampleRates() []int {
87+
samplerates := (*ff.AVCodec)(codec).SupportedSamplerates()
88+
sort.Sort(sort.Reverse(sort.IntSlice(samplerates)))
89+
return samplerates
90+
}
91+
92+
// Channel layouts supported by the codec. This is only valid for audio codecs.
93+
func (codec *Codec) ChannelLayouts() []string {
94+
chlayouts := (*ff.AVCodec)(codec).ChannelLayouts()
95+
result := make([]string, 0, len(chlayouts))
96+
for _, chlayout := range chlayouts {
97+
name, err := ff.AVUtil_channel_layout_describe(&chlayout)
98+
if err != nil {
99+
continue
100+
}
101+
result = append(result, name)
102+
}
103+
return result
104+
}
105+
106+
// Profiles supported by the codec. This is only valid for video codecs.
107+
func (codec *Codec) Profiles() []string {
108+
profiles := (*ff.AVCodec)(codec).Profiles()
109+
result := make([]string, len(profiles))
110+
for i, profile := range profiles {
111+
result[i] = profile.Name()
112+
}
113+
return result
114+
}

0 commit comments

Comments
 (0)