Skip to content

Commit e9c3ba9

Browse files
committed
Updated manager
1 parent 7128226 commit e9c3ba9

File tree

11 files changed

+493
-23
lines changed

11 files changed

+493
-23
lines changed
File renamed without changes.

manager.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
This is a package for reading, writing and inspecting media files. In
3+
order to operate on media, call NewManager() and then use the manager
4+
functions to determine capabilities and manage media files and devices.
5+
*/
6+
package media
7+
8+
// Manager represents a manager for media formats and devices.
9+
// Create a new manager object using the NewManager function.
10+
//
11+
// import "github.com/mutablelogic/go-media/pkg/ffmpeg"
12+
//
13+
// manager, err := ffmpeg.NewManager()
14+
// if err != nil {
15+
// ...
16+
// }
17+
//
18+
// Various options are available to control the manager, for
19+
// logging and affecting decoding.
20+
//
21+
// Only one manager can be created. If NewManager is called
22+
// a second time, the previously created manager is returned,
23+
// but any new options are applied.
24+
type Manager interface {
25+
// Open a media file or device for reading, from a path or url.
26+
// If a format is specified, then the format will be used to open
27+
// the file. Close the media object when done.
28+
//Open(string, Format, ...string) (Media, error)
29+
30+
// Open a media stream for reading. If a format is
31+
// specified, then the format will be used to open the file. Close the
32+
// media object when done. It is the responsibility of the caller to
33+
// also close the reader when done.
34+
//Read(io.Reader, Format, ...string) (Media, error)
35+
36+
// Create a media file or device for writing, from a path. If a format is
37+
// specified, then the format will be used to create the file or else
38+
// the format is guessed from the path. If no parameters are provided,
39+
// then the default parameters for the format are used.
40+
//Create(string, Format, []Metadata, ...Parameters) (Media, error)
41+
42+
// Create a media stream for writing. The format will be used to
43+
// determine the format and one or more CodecParameters used to
44+
// create the streams. If no parameters are provided, then the
45+
// default parameters for the format are used. It is the responsibility
46+
// of the caller to also close the writer when done.
47+
//Write(io.Writer, Format, []Metadata, ...Parameters) (Media, error)
48+
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+
59+
// Return supported devices for a given format.
60+
// Not all devices may be supported on all platforms or listed
61+
// if the device does not support enumeration.
62+
//Devices(Format) []Device
63+
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+
76+
// Return audio parameters for encoding
77+
// ChannelLayout, SampleFormat, Samplerate
78+
//AudioParameters(string, string, int) (Parameters, error)
79+
80+
// Return video parameters for encoding
81+
// Width, Height, PixelFormat
82+
//VideoParameters(int, int, string) (Parameters, error)
83+
84+
// Return codec parameters for audio encoding
85+
// Codec name and AudioParameters
86+
//AudioCodecParameters(string, AudioParameters) (Parameters, error)
87+
88+
// Return codec parameters for video encoding
89+
// Codec name, Profile name, Framerate (fps) and VideoParameters
90+
//VideoCodecParameters(string, string, float64, VideoParameters) (Parameters, error)
91+
92+
// Return version information for the media manager as a set of
93+
// metadata
94+
Version() []Metadata
95+
96+
// Log error messages with arguments
97+
Errorf(string, ...any)
98+
99+
// Log warning messages with arguments
100+
Warningf(string, ...any)
101+
102+
// Log info messages with arguments
103+
Infof(string, ...any)
104+
}

metadata.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
This is a package for reading, writing and inspecting media files. In
3+
order to operate on media, call NewManager() and then use the manager
4+
functions to determine capabilities and manage media files and devices.
5+
*/
6+
package media
7+
8+
import "image"
9+
10+
// Metadata is a key/value pair which can be used to describe a media object
11+
// or other metadata. The value can be retrieved as a string value,
12+
// data, or other type. If the value is a byte slice, then it can also
13+
// be retrieved as an image (for artwork)
14+
type Metadata interface {
15+
// Return the metadata key
16+
Key() string
17+
18+
// Return the value as a string. Returns the mimetype
19+
// if the value is a byte slice, and the mimetype can be
20+
// detected.
21+
Value() string
22+
23+
// Returns the value as a byte slice
24+
Bytes() []byte
25+
26+
// Returns the value as an image
27+
Image() image.Image
28+
}

pkg/ffmpeg/manager.go

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package ffmpeg
2+
3+
import (
4+
5+
// Packages
6+
media "github.com/mutablelogic/go-media"
7+
"github.com/mutablelogic/go-media/pkg/version"
8+
ff "github.com/mutablelogic/go-media/sys/ffmpeg61"
9+
)
10+
11+
///////////////////////////////////////////////////////////////////////////////
12+
// TYPES
13+
14+
type Manager struct {
15+
opts []Opt
16+
}
17+
18+
var _ media.Manager = (*Manager)(nil)
19+
20+
///////////////////////////////////////////////////////////////////////////////
21+
// GLOBALS
22+
23+
var (
24+
manager *Manager
25+
)
26+
27+
///////////////////////////////////////////////////////////////////////////////
28+
// LIFECYCLE
29+
30+
// Create a new media manager which enumerates the available codecs, formats
31+
// and devices
32+
func NewManager(opt ...Opt) (*Manager, error) {
33+
var options opts
34+
35+
// Return existing manager if it exists
36+
if manager == nil {
37+
manager = new(Manager)
38+
}
39+
40+
// Set default options
41+
options.level = ff.AV_LOG_WARNING
42+
43+
// Apply options
44+
for _, opt := range opt {
45+
if err := opt(&options); err != nil {
46+
return nil, err
47+
}
48+
}
49+
50+
// Set logging
51+
ff.AVUtil_log_set_level(options.level)
52+
if options.callback != nil {
53+
ff.AVUtil_log_set_callback(func(level ff.AVLog, message string, userInfo any) {
54+
options.callback(message)
55+
})
56+
}
57+
58+
// Initialise network
59+
ff.AVFormat_network_init()
60+
61+
// Set force flag - this is used to resample or resize decoded
62+
// frames even if the target format is the same as the source format
63+
if options.force {
64+
manager.opts = append(manager.opts, OptForce())
65+
}
66+
67+
// Retyrn success
68+
return manager, nil
69+
}
70+
71+
///////////////////////////////////////////////////////////////////////////////
72+
// PUBLIC METHODS
73+
74+
// Open a media file or device for reading, from a path or url.
75+
// If a format is specified, then the format will be used to open
76+
// the file. You can add additional options to the open call as
77+
// key=value pairs
78+
/*
79+
func (manager *Manager) Open(url string, format media.Format, opts ...string) (media.Media, error) {
80+
opt := append([]Opt{OptInputOpt(opts...)}, manager.opts...)
81+
if format != nil {
82+
opt = append(opt, OptInputFormat(format.Name()))
83+
}
84+
return Open(url, opt...)
85+
}
86+
87+
// Open an io.Reader for reading. If a format is specified, then the
88+
// format will be used to open the file. You can add additional options
89+
// to the open call as key=value pairs
90+
func (manager *Manager) NewReader(r io.Reader, format media.Format, opts ...string) (media.Media, error) {
91+
opt := append([]Opt{OptInputOpt(opts...)}, manager.opts...)
92+
if format != nil {
93+
opt = append(opt, OptInputFormat(format.Name()))
94+
}
95+
return NewReader(r, opt...)
96+
}
97+
*/
98+
99+
///////////////////////////////////////////////////////////////////////////////
100+
// PUBLIC METHODS - VERSION
101+
102+
// Return version information
103+
func (manager *Manager) Version() []media.Metadata {
104+
var result []media.Metadata
105+
for _, v := range version.Version() {
106+
result = append(result, NewMetadata(v.Key, v.Value))
107+
}
108+
return result
109+
}
110+
111+
///////////////////////////////////////////////////////////////////////////////
112+
// PUBLIC METHODS - LOGGING
113+
114+
// Log error messages
115+
func (manager *Manager) Errorf(v string, args ...any) {
116+
ff.AVUtil_log(nil, ff.AV_LOG_ERROR, v, args...)
117+
}
118+
119+
// Log warning messages
120+
func (manager *Manager) Warningf(v string, args ...any) {
121+
ff.AVUtil_log(nil, ff.AV_LOG_WARNING, v)
122+
}
123+
124+
// Log info messages
125+
func (manager *Manager) Infof(v string, args ...any) {
126+
ff.AVUtil_log(nil, ff.AV_LOG_INFO, v, args...)
127+
}

pkg/ffmpeg/manager_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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_manager_001(t *testing.T) {
11+
assert := assert.New(t)
12+
13+
// Create a manager
14+
manager, err := ffmpeg.NewManager(ffmpeg.OptLog(true, func(v string) {
15+
t.Log(v)
16+
}))
17+
if !assert.NoError(err) {
18+
t.FailNow()
19+
}
20+
21+
manager.Infof("INFO test")
22+
manager.Warningf("WARNING test")
23+
manager.Errorf("ERROR test")
24+
}
25+
26+
func Test_manager_002(t *testing.T) {
27+
assert := assert.New(t)
28+
29+
// Create a manager
30+
manager, err := ffmpeg.NewManager(ffmpeg.OptLog(true, func(v string) {
31+
t.Log(v)
32+
}))
33+
if !assert.NoError(err) {
34+
t.FailNow()
35+
}
36+
37+
for _, v := range manager.Version() {
38+
t.Log(v)
39+
}
40+
}

0 commit comments

Comments
 (0)