Skip to content

Commit e5846d7

Browse files
committed
Added new manager
1 parent 3152c10 commit e5846d7

File tree

6 files changed

+70
-13
lines changed

6 files changed

+70
-13
lines changed

manager.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ functions to determine capabilities and manage media files and devices.
55
*/
66
package media
77

8+
import "io"
9+
810
// Manager represents a manager for media formats and devices.
911
// Create a new manager object using the NewManager function.
1012
//
@@ -26,7 +28,7 @@ type Manager interface {
2628
// Open a media file or device for reading, from a path or url.
2729
// If a format is specified, then the format will be used to open
2830
// the file. Close the media object when done.
29-
//Open(string, Format, ...string) (Media, error)
31+
Open(string, Format, ...string) (Media, error)
3032

3133
// Open a media stream for reading. If a format is
3234
// specified, then the format will be used to open the file. Close the
@@ -47,11 +49,6 @@ type Manager interface {
4749
// of the caller to also close the writer when done.
4850
//Write(io.Writer, Format, []Metadata, ...Parameters) (Media, error)
4951

50-
// Return supported devices for a given format.
51-
// Not all devices may be supported on all platforms or listed
52-
// if the device does not support enumeration.
53-
//Devices(Format) []Device
54-
5552
// Return audio parameters for encoding
5653
// ChannelLayout, SampleFormat, Samplerate
5754
//AudioParameters(string, string, int) (Parameters, error)
@@ -113,3 +110,13 @@ type Format interface {
113110
// The unique name that the format can be referenced as
114111
Name() string
115112
}
113+
114+
// A container format for a media file, reader, device or
115+
// network stream
116+
type Media interface {
117+
io.Closer
118+
119+
// The type of the format, which can be combinations of
120+
// INPUT, OUTPUT, DEVICE
121+
Type() Type
122+
}

pkg/ffmpeg/decoder.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import (
88

99
// Packages
1010
ff "github.com/mutablelogic/go-media/sys/ffmpeg61"
11+
12+
// Namespace imports
13+
. "github.com/djthorpe/go-errors"
1114
)
1215

1316
////////////////////////////////////////////////////////////////////////////////
@@ -35,7 +38,7 @@ func NewDecoder(stream *ff.AVStream, dest *Par, force bool) (*Decoder, error) {
3538
// Create a frame for decoder output - before resize/resample
3639
frame := ff.AVUtil_frame_alloc()
3740
if frame == nil {
38-
return nil, errors.New("failed to allocate frame")
41+
return nil, ErrInternalAppError.With("failed to allocate frame")
3942
}
4043

4144
// Create a codec context for the decoder
@@ -114,12 +117,12 @@ func (d *Decoder) Close() error {
114117
// correct timebase, etc set
115118
func (d *Decoder) decode(packet *ff.AVPacket, fn DecoderFrameFn) error {
116119
if fn == nil {
117-
return errors.New("DecoderFrameFn is nil")
120+
return ErrBadParameter.With("DecoderFrameFn is nil")
118121
}
119122

120123
// Submit the packet to the decoder (nil packet will flush the decoder)
121124
if err := ff.AVCodec_send_packet(d.codec, packet); err != nil {
122-
return err
125+
return ErrInternalAppError.With("AVCodec_send_packet:", err)
123126
}
124127

125128
// get all the available frames from the decoder
@@ -136,7 +139,7 @@ func (d *Decoder) decode(packet *ff.AVPacket, fn DecoderFrameFn) error {
136139
// Finished decoding packet or EOF
137140
break
138141
} else if err != nil {
139-
return err
142+
return ErrInternalAppError.With("AVCodec_receive_frame:", err)
140143
}
141144

142145
// Obtain the output frame. If a new frame is returned, it is

pkg/ffmpeg/manager.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import (
88
media "github.com/mutablelogic/go-media"
99
version "github.com/mutablelogic/go-media/pkg/version"
1010
ff "github.com/mutablelogic/go-media/sys/ffmpeg61"
11+
12+
// Namespace imports
13+
. "github.com/djthorpe/go-errors"
1114
)
1215

1316
///////////////////////////////////////////////////////////////////////////////
@@ -95,6 +98,24 @@ func (manager *Manager) NewReader(r io.Reader, format media.Format, opts ...stri
9598
}
9699
*/
97100

101+
///////////////////////////////////////////////////////////////////////////////
102+
// PUBLIC METHODS - READER
103+
104+
func (manager *Manager) Open(url string, format media.Format, opts ...string) (media.Media, error) {
105+
o := append([]Opt{}, manager.opts[:]...)
106+
if format != nil {
107+
if format_, ok := format.(*Format); ok && format_.Input != nil {
108+
o = append(o, optInputFormat(format_))
109+
} else {
110+
return nil, ErrBadParameter.With("invalid input format")
111+
}
112+
}
113+
if len(opts) > 0 {
114+
o = append(o, OptInputOpt(opts...))
115+
}
116+
return Open(url, o...)
117+
}
118+
98119
///////////////////////////////////////////////////////////////////////////////
99120
// PUBLIC METHODS - FORMATS
100121

pkg/ffmpeg/opts.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package ffmpeg
22

33
import (
44
// Package imports
5-
5+
media "github.com/mutablelogic/go-media"
66
ffmpeg "github.com/mutablelogic/go-media/sys/ffmpeg61"
77

88
// Namespace imports
@@ -32,6 +32,7 @@ type opts struct {
3232
metadata []*Metadata
3333

3434
// Reader options
35+
t media.Type
3536
iformat *ffmpeg.AVInputFormat
3637
opts []string // These are key=value pairs
3738
}
@@ -87,6 +88,19 @@ func OptInputFormat(name string) Opt {
8788
}
8889
}
8990

91+
// Input format from ff.AVInputFormat
92+
func optInputFormat(format *Format) Opt {
93+
return func(o *opts) error {
94+
if format != nil && format.Input != nil {
95+
o.iformat = format.Input
96+
o.t = format.Type()
97+
} else {
98+
return ErrBadParameter.With("invalid input format")
99+
}
100+
return nil
101+
}
102+
}
103+
90104
// Input format options
91105
func OptInputOpt(opt ...string) Opt {
92106
return func(o *opts) error {

pkg/ffmpeg/reader.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"io"
88
"slices"
99
"strings"
10+
"syscall"
1011
"time"
1112

1213
// Packages
@@ -22,6 +23,7 @@ import (
2223

2324
// Media reader which reads from a URL, file path or device
2425
type Reader struct {
26+
t media.Type
2527
input *ff.AVFormatContext
2628
avio *ff.AVIOContextEx
2729
force bool
@@ -122,8 +124,9 @@ func (r *Reader) open(options *opts) (*Reader, error) {
122124
return nil, err
123125
}
124126

125-
// Set force flag
127+
// Set force flag and type
126128
r.force = options.force
129+
r.t = options.t | media.INPUT
127130

128131
// Return success
129132
return r, nil
@@ -164,6 +167,11 @@ func (r *Reader) String() string {
164167
////////////////////////////////////////////////////////////////////////////////
165168
// PUBLIC METHODS
166169

170+
// Return the media type
171+
func (r *Reader) Type() media.Type {
172+
return r.t
173+
}
174+
167175
// Return the duration of the media stream, returns zero if unknown
168176
func (r *Reader) Duration() time.Duration {
169177
duration := r.input.Duration()
@@ -391,8 +399,10 @@ FOR_LOOP:
391399
default:
392400
if err := ff.AVFormat_read_frame(r.input, packet); errors.Is(err, io.EOF) {
393401
break FOR_LOOP
402+
} else if errors.Is(err, syscall.EAGAIN) {
403+
continue FOR_LOOP
394404
} else if err != nil {
395-
return err
405+
return ErrInternalAppError.With("AVFormat_read_frame: ", err)
396406
}
397407
stream_index := packet.StreamIndex()
398408
if decoder := decoders[stream_index]; decoder != nil {

sys/ffmpeg61/avformat_demux.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ func AVFormat_read_frame(ctx *AVFormatContext, packet *AVPacket) error {
112112
if err := AVError(C.av_read_frame((*C.struct_AVFormatContext)(ctx), (*C.struct_AVPacket)(packet))); err < 0 {
113113
if err == AVERROR_EOF {
114114
return io.EOF
115+
} else if err.IsErrno(syscall.EAGAIN) {
116+
return syscall.EAGAIN
115117
} else {
116118
return err
117119
}

0 commit comments

Comments
 (0)